Annotation of embedaddon/libxml2/doc/examples/index.py, revision 1.1.1.1
1.1 misho 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.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="""# Beware this is autogenerated by index.py
224: INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -I@srcdir@/include @THREAD_CFLAGS@ @Z_CFLAGS@
225: DEPS = $(top_builddir)/libxml2.la
226: LDADDS = @STATIC_BINARIES@ $(top_builddir)/libxml2.la @THREAD_LIBS@ @Z_LIBS@ $(ICONV_LIBS) -lm @WIN32_EXTRA_LIBADD@
227:
228: rebuild: examples.xml index.html
229:
230: examples.xml: index.py *.c
231: -@($(srcdir)/index.py)
232:
233: index.html: examples.xml examples.xsl
234: -@(xsltproc examples.xsl examples.xml && echo "Rebuilt web page" && xmllint --valid --noout index.html)
235:
236: install-data-local:
237: $(mkinstalldirs) $(DESTDIR)$(HTML_DIR)
238: -@INSTALL@ -m 0644 $(srcdir)/*.html $(srcdir)/*.c $(srcdir)/*.xml $(srcdir)/*.xsl $(srcdir)/*.res $(DESTDIR)$(HTML_DIR)
239:
240: """
241: EXTRA_DIST=""
242: for extra in extras:
243: EXTRA_DIST = EXTRA_DIST + extra + " "
244: Makefile = Makefile + "EXTRA_DIST=%s\n\n" % (EXTRA_DIST)
245: noinst_PROGRAMS=""
246: for example in examples:
247: noinst_PROGRAMS = noinst_PROGRAMS + example + " "
248: Makefile = Makefile + "noinst_PROGRAMS=%s\n\n" % (noinst_PROGRAMS)
249: for example in examples:
250: Makefile = Makefile + "%s_SOURCES=%s.c\n%s_LDFLAGS=\n%s_DEPENDENCIES= $(DEPS)\n%s_LDADD= @RDL_LIBS@ $(LDADDS)\n\n" % (example, example, example,
251: example, example)
252: Makefile = Makefile + "valgrind: \n\t$(MAKE) CHECKER='valgrind' tests\n\n"
253: Makefile = Makefile + "tests: $(noinst_PROGRAMS)\n"
254: Makefile = Makefile + "\t@(echo '## examples regression tests')\n"
255: Makefile = Makefile + "\t@(echo > .memdump)\n"
256: for test in tests:
257: Makefile = Makefile + "\t@($(CHECKER) %s)\n" % (test)
258: Makefile = Makefile + '\t@(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0)\n'
259: Makefile = Makefile + "\n\n"
260: try:
261: old = open("Makefile.am", "r").read()
262: if old != Makefile:
263: n = open("Makefile.am", "w").write(Makefile)
264: print "Updated Makefile.am"
265: except:
266: print "Failed to read or save Makefile.am"
267: #
268: # Autogenerate the .cvsignore too ...
269: #
270: ignore = """.memdump
271: Makefile.in
272: Makefile
273: """
274: for example in examples:
275: ignore = ignore + "%s\n" % (example)
276: try:
277: old = open(".cvsignore", "r").read()
278: if old != ignore:
279: n = open(".cvsignore", "w").write(ignore)
280: print "Updated .cvsignore"
281: except:
282: print "Failed to read or save .cvsignore"
283:
284: if __name__ == "__main__":
285: load_api()
286: output = open("examples.xml", "w")
287: output.write("<examples>\n")
288:
289: for file in glob.glob('*.c'):
290: parse(file, output)
291: examples.append(file[:-2])
292:
293: dump_symbols(output)
294: dump_sections(output)
295: output.write("</examples>\n")
296: output.close()
297: dump_Makefile()
298:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>