Store source file and dependency paths relative to the target's directory, not relati...
[scons.git] / bin / scons-proc.py
1 #!/usr/bin/env python
2 #
3 # Process a list of Python and/or XML files containing SCons documentation.
4 #
5 # Depending on the options, this script creates DocBook-formatted lists
6 # of the Builders, Tools or construction variables in generated SGML
7 # files containing the summary text and/or .mod files contining the
8 # ENTITY definitions for each item.
9 #
10 import getopt
11 import os.path
12 import re
13 import string
14 import StringIO
15 import sys
16 import xml.sax
17
18 import SConsDoc
19
20 base_sys_path = [os.getcwd() + '/build/test-tar-gz/lib/scons'] + sys.path
21
22 helpstr = """\
23 Usage: scons-varlist.py [-b .gen,.mod] [-t .gen,.mod] [-v .gen,.mod] [infile]
24 Options:
25   -m, --modfile               .mod file to hold Builder entities
26 """
27
28 opts, args = getopt.getopt(sys.argv[1:],
29                            "b:t:v:",
30                            ['builders=', 'tools=', 'variables='])
31
32 buildersfiles = None
33 toolsfiles = None
34 variablesfiles = None
35
36 for o, a in opts:
37     if o == '-b' or o == '--builders':
38         buildersfiles = a
39     elif o == '-t' or o == '--tools':
40         toolsfiles = a
41     elif o == '-v' or o == '--variables':
42         variablesfiles = a
43
44 h = SConsDoc.SConsDocHandler()
45 saxparser = xml.sax.make_parser()
46 saxparser.setContentHandler(h)
47 saxparser.setErrorHandler(h)
48
49 preamble = """\
50 <?xml version="1.0"?>
51 <scons_doc>
52 """
53
54 postamble = """\
55 </scons_doc>
56 """
57
58 for f in args:
59     _, ext = os.path.splitext(f)
60     if ext == '.py':
61         dir, _ = os.path.split(f)
62         if dir:
63             sys.path = [dir] + base_sys_path
64         module = SConsDoc.importfile(f)
65         h.set_file_info(f, len(preamble.split('\n')))
66         try:
67             content = module.__scons_doc__
68         except AttributeError:
69             content = None
70         else:
71             del module.__scons_doc__
72     else:
73         h.set_file_info(f, len(preamble.split('\n')))
74         content = open(f).read()
75     if content:
76         content = content.replace('&', '&amp;')
77         input = preamble + content + postamble
78         try:
79             saxparser.parse(StringIO.StringIO(input))
80         except:
81             sys.stderr.write("error in %s\n" % f)
82             raise
83
84 Warning = """\
85 <!--
86 THIS IS AN AUTOMATICALLY-GENERATED FILE.  DO NOT EDIT.
87 -->
88 """
89
90 Regular_Entities_Header = """\
91 <!--
92
93   Regular %s entities.
94
95 -->
96 """
97
98 Link_Entities_Header = """\
99 <!--
100
101   Entities that are links to the %s entries in the appendix.
102
103 -->
104 """
105
106 class XXX:
107     def __init__(self, entries, **kw):
108         values = entries.values()
109         values.sort()
110         self.values = values
111         for k, v in kw.items():
112             setattr(self, k, v)
113     def write_gen(self, filename):
114         if not filename:
115             return
116         f = open(filename, 'w')
117         for v in self.values:
118             f.write('\n<varlistentry id="%s%s">\n' %
119                         (self.prefix, self.idfunc(v.name)))
120             for term in self.termfunc(v.name):
121                 f.write('<term><%s>%s</%s></term>\n' %
122                         (self.tag, term, self.tag))
123             f.write('<listitem>\n')
124             for chunk in v.summary.body:
125                 f.write(str(chunk))
126             #if v.uses:
127             #    u = map(lambda x, s: '&%slink-%s;' % (s.prefix, x), v.uses)
128             #    f.write('<para>\n')
129             #    f.write('Uses:  ' + ', '.join(u) + '.\n')
130             #    f.write('</para>\n')
131             f.write('</listitem>\n')
132             f.write('</varlistentry>\n')
133     def write_mod(self, filename):
134         if not filename:
135             return
136         f = open(filename, 'w')
137         f.write(Warning)
138         f.write('\n')
139         f.write(Regular_Entities_Header % self.description)
140         f.write('\n')
141         for v in self.values:
142             f.write('<!ENTITY %s%s "<%s>%s</%s>">\n' %
143                         (self.prefix, self.idfunc(v.name),
144                          self.tag, self.entityfunc(v.name), self.tag))
145         f.write('\n')
146         f.write(Warning)
147         f.write('\n')
148         f.write(Link_Entities_Header % self.description)
149         f.write('\n')
150         for v in self.values:
151             f.write('<!ENTITY %slink-%s \'<link linkend="%s%s"><%s>%s</%s></link>\'>\n' %
152                         (self.prefix, self.idfunc(v.name),
153                          self.prefix, self.idfunc(v.name),
154                          self.tag, self.entityfunc(v.name), self.tag))
155         f.write('\n')
156         f.write(Warning)
157
158 if buildersfiles:
159     g = XXX(h.builders,
160             description = 'builder',
161             prefix = 'b-',
162             tag = 'function',
163             idfunc = lambda x: x,
164             termfunc = lambda x: [x+'()', 'env.'+x+'()'],
165             entityfunc = lambda x: x)
166
167     gen, mod = string.split(buildersfiles, ',')
168     g.write_gen(gen)
169     g.write_mod(mod)
170
171 if toolsfiles:
172     g = XXX(h.tools,
173             description = 'tool',
174             prefix = 't-',
175             tag = 'literal',
176             idfunc = lambda x: string.replace(x, '+', 'X'),
177             termfunc = lambda x: [x],
178             entityfunc = lambda x: x)
179
180     gen, mod = string.split(toolsfiles, ',')
181     g.write_gen(gen)
182     g.write_mod(mod)
183
184 if variablesfiles:
185     g = XXX(h.cvars,
186             description = 'construction variable',
187             prefix = 'cv-',
188             tag = 'envar',
189             idfunc = lambda x: x,
190             termfunc = lambda x: [x],
191             entityfunc = lambda x: '$'+x)
192
193     gen, mod = string.split(variablesfiles, ',')
194     g.write_gen(gen)
195     g.write_mod(mod)