Imported Upstream version 2.9.1
[platform/upstream/libxml2.git] / doc / examples / index.py
1 #!/usr/bin/python -u
2 #
3 # Indexes the examples and build an XML description
4 #
5 import string
6 import glob
7 import sys
8 try:
9     import libxml2
10 except:
11     sys.exit(1)
12 sys.path.insert(0, "..")
13 from apibuild import CParser, escape
14
15 examples = []
16 extras = ['examples.xsl', 'index.html', 'index.py']
17 tests = []
18 sections = {}
19 symbols = {}
20 api_dict = None
21 api_doc = None
22
23 def load_api():
24     global api_dict
25     global api_doc
26
27     if api_dict != None:
28         return
29     api_dict = {}
30     try:
31         print "loading ../libxml2-api.xml"
32         api_doc = libxml2.parseFile("../libxml2-api.xml")
33     except:
34         print "failed to parse ../libxml2-api.xml"
35         sys.exit(1)
36
37 def find_symbol(name):
38     global api_dict
39     global api_doc
40
41     if api_doc == None:
42         load_api()
43
44     if name == None:
45         return
46     if api_dict.has_key(name):
47         return api_dict[name]
48     ctxt = api_doc.xpathNewContext()
49     res = ctxt.xpathEval("/api/symbols/*[@name = '%s']" % (name))
50     if type(res) == type([]) and len(res) >= 1:
51         if len(res) > 1:
52             print "Found %d references to %s in the API" % (len(res), name)
53         node = res[0]
54         typ = node.name
55         file = node.xpathEval("string(@file)")
56         info = node.xpathEval("string(info)")
57     else:
58         print "Reference %s not found in the API" % (name)
59         return None
60     ret = (typ, file, info)
61     api_dict[name] = ret
62     return ret
63
64 def parse_top_comment(filename, comment):
65     res = {}
66     lines = string.split(comment, "\n")
67     item = None
68     for line in lines:
69         while line != "" and (line[0] == ' ' or line[0] == '\t'):
70             line = line[1:]
71         while line != "" and line[0] == '*':
72             line = line[1:]
73         while line != "" and (line[0] == ' ' or line[0] == '\t'):
74             line = line[1:]
75         try:
76             (it, line) = string.split(line, ":", 1)
77             item = it
78             while line != "" and (line[0] == ' ' or line[0] == '\t'):
79                 line = line[1:]
80             if res.has_key(item):
81                 res[item] = res[item] + " " + line
82             else:
83                 res[item] = line
84         except:
85             if item != None:
86                 if res.has_key(item):
87                     res[item] = res[item] + " " + line
88                 else:
89                     res[item] = line
90     return res
91
92 def parse(filename, output):
93     global symbols
94     global sections
95
96     parser = CParser(filename)
97     parser.collect_references()
98     idx = parser.parse()
99     info = parse_top_comment(filename, parser.top_comment)
100     output.write("  <example filename='%s'>\n" % filename)
101     try:
102         synopsis = info['synopsis']
103         output.write("    <synopsis>%s</synopsis>\n" % escape(synopsis));
104     except:
105         print "Example %s lacks a synopsis description" % (filename)
106     try:
107         purpose = info['purpose']
108         output.write("    <purpose>%s</purpose>\n" % escape(purpose));
109     except:
110         print "Example %s lacks a purpose description" % (filename)
111     try:
112         usage = info['usage']
113         output.write("    <usage>%s</usage>\n" % escape(usage));
114     except:
115         print "Example %s lacks an usage description" % (filename)
116     try:
117         test = info['test']
118         output.write("    <test>%s</test>\n" % escape(test));
119         progname=filename[0:-2]
120         command=string.replace(test, progname, './' + progname, 1)
121         tests.append(command)
122     except:
123         pass
124     try:
125         author = info['author']
126         output.write("    <author>%s</author>\n" % escape(author));
127     except:
128         print "Example %s lacks an author description" % (filename)
129     try:
130         copy = info['copy']
131         output.write("    <copy>%s</copy>\n" % escape(copy));
132     except:
133         print "Example %s lacks a copyright description" % (filename)
134     try:
135         section = info['section']
136         output.write("    <section>%s</section>\n" % escape(section));
137         if sections.has_key(section):
138             sections[section].append(filename)
139         else:
140             sections[section] = [filename]
141     except:
142         print "Example %s lacks a section description" % (filename)
143     for topic in info.keys():
144         if topic != "purpose" and topic != "usage" and \
145            topic != "author" and topic != "copy" and \
146            topic != "section" and topic != "synopsis" and topic != "test":
147             str = info[topic]
148             output.write("    <extra topic='%s'>%s</extra>\n" % (
149                          escape(topic), escape(str)))
150     output.write("    <includes>\n")
151     for include in idx.includes.keys():
152         if include.find("libxml") != -1:
153             output.write("      <include>%s</include>\n" % (escape(include)))
154     output.write("    </includes>\n")
155     output.write("    <uses>\n")
156     for ref in idx.references.keys():
157         id = idx.references[ref]
158         name = id.get_name()
159         line = id.get_lineno()
160         if symbols.has_key(name):
161             sinfo = symbols[name]
162             refs = sinfo[0]
163             # gather at most 5 references per symbols
164             if refs > 5:
165                 continue
166             sinfo.append(filename)
167             sinfo[0] = refs + 1
168         else:
169             symbols[name] = [1, filename]
170         info = find_symbol(name)
171         if info != None:
172             type = info[0]
173             file = info[1]
174             output.write("      <%s line='%d' file='%s' name='%s'/>\n" % (type,
175                          line, file, name))
176         else:
177             type = id.get_type()
178             output.write("      <%s line='%d' name='%s'/>\n" % (type,
179                          line, name))
180
181     output.write("    </uses>\n")
182     output.write("  </example>\n")
183
184     return idx
185
186 def dump_symbols(output):
187     global symbols
188
189     output.write("  <symbols>\n")
190     keys = symbols.keys()
191     keys.sort()
192     for symbol in keys:
193         output.write("    <symbol name='%s'>\n" % (symbol))
194         info = symbols[symbol]
195         i = 1
196         while i < len(info):
197             output.write("      <ref filename='%s'/>\n" % (info[i]))
198             i = i + 1
199         output.write("    </symbol>\n")
200     output.write("  </symbols>\n")
201
202 def dump_sections(output):
203     global sections
204
205     output.write("  <sections>\n")
206     keys = sections.keys()
207     keys.sort()
208     for section in keys:
209         output.write("    <section name='%s'>\n" % (section))
210         info = sections[section]
211         i = 0
212         while i < len(info):
213             output.write("      <example filename='%s'/>\n" % (info[i]))
214             i = i + 1
215         output.write("    </section>\n")
216     output.write("  </sections>\n")
217
218 def dump_Makefile():
219     for file in glob.glob('*.xml'):
220         extras.append(file)
221     for file in glob.glob('*.res'):
222         extras.append(file)
223     Makefile="""##
224 ## This file is auto-generated by index.py
225 ## DO NOT EDIT !!!
226 ##
227
228 AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include -I$(srcdir)/include
229 AM_CFLAGS = $(THREAD_CFLAGS) $(Z_CFLAGS)
230 LDADD = $(RDL_LIBS) $(STATIC_BINARIES) $(top_builddir)/libxml2.la $(THREAD_LIBS) $(Z_LIBS) $(ICONV_LIBS) -lm $(WIN32_EXTRA_LIBADD)
231
232 CLEANFILES = *.tmp
233
234 if REBUILD_DOCS
235 rebuild: examples.xml index.html
236 .PHONY: rebuild
237
238 examples.xml: index.py $(noinst_PROGRAMS:=.c)
239         cd $(srcdir) && $(PYTHON) index.py
240         $(MAKE) Makefile
241
242 index.html: examples.xml examples.xsl
243         cd $(srcdir) && xsltproc examples.xsl examples.xml && echo "Rebuilt web page"
244         -cd $(srcdir) && xmllint --valid --noout index.html
245 endif
246
247 install-data-local: 
248         $(MKDIR_P) $(DESTDIR)$(HTML_DIR)
249         -$(INSTALL) -m 0644 $(srcdir)/*.html $(srcdir)/*.c $(srcdir)/*.xml $(srcdir)/*.xsl $(srcdir)/*.res $(DESTDIR)$(HTML_DIR)
250
251 clean-local:
252         test -f Makefile.am || rm -f test?.xml
253
254 """
255     examples.sort()
256     extras.sort()
257     tests.sort()
258     EXTRA_DIST=""
259     for extra in extras:
260         EXTRA_DIST = EXTRA_DIST + " \\\n\t" + extra
261     Makefile = Makefile + "EXTRA_DIST =%s\n\n" % (EXTRA_DIST)
262     noinst_PROGRAMS=""
263     for example in examples:
264         noinst_PROGRAMS = noinst_PROGRAMS + " \\\n\t" + example
265     Makefile = Makefile + "noinst_PROGRAMS =%s\n\n" % (noinst_PROGRAMS)
266     for example in examples:
267         Makefile = Makefile + "%s_SOURCES = %s.c\n\n" % (example, example)
268     Makefile = Makefile + "valgrind: \n\t$(MAKE) CHECKER='valgrind' tests\n\n"
269     Makefile = Makefile + "tests: $(noinst_PROGRAMS)\n"
270     Makefile = Makefile + "\ttest -f Makefile.am || test -f test1.xml || $(LN_S) $(srcdir)/test?.xml .\n"
271     Makefile = Makefile + "\t@(echo '## examples regression tests')\n"
272     Makefile = Makefile + "\t@(echo > .memdump)\n"
273     for test in tests:
274         Makefile = Makefile + "\t$(CHECKER) %s\n" % (test)
275         Makefile = Makefile + '\t@grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0\n'
276     try:
277         old = open("Makefile.am", "r").read()
278         if old != Makefile:
279             n = open("Makefile.am", "w").write(Makefile)
280             print "Updated Makefile.am"
281     except:
282         print "Failed to read or save Makefile.am"
283 #    #
284 #    # Autogenerate the .cvsignore too ... DEPRECATED
285 #    #
286 #    ignore = """.memdump
287 #Makefile.in
288 #Makefile
289 #"""
290 #    for example in examples:
291 #        ignore = ignore + "%s\n" % (example)
292 #    try:
293 #       old = open(".cvsignore", "r").read()
294 #       if old != ignore:
295 #           n = open(".cvsignore", "w").write(ignore)
296 #           print "Updated .cvsignore"
297 #    except:
298 #        print "Failed to read or save .cvsignore"
299
300 if __name__ == "__main__":
301     load_api()
302     output = open("examples.xml", "w")
303     output.write("<examples>\n")
304
305     for file in glob.glob('*.c'):
306         parse(file, output)
307         examples.append(file[:-2])
308
309     dump_symbols(output)
310     dump_sections(output)
311     output.write("</examples>\n")
312     output.close()
313     dump_Makefile()
314