blob: dfbbba233dfc1332f013448095088d33f58acb49 [file] [log] [blame]
Daniel Veillard61006472002-01-21 17:31:47 +00001#!/usr/bin/python -u
2#
3# tries to parse the output of gtk-doc declaration files and make
4# an XML reusable description from them
5#
Daniel Veillard61006472002-01-21 17:31:47 +00006import sys
7import string
8
Daniel Veillard3bf65be2002-01-23 12:36:34 +00009ids = {}
10
Daniel Veillard2d1464f2002-01-21 23:16:56 +000011macros = {}
12variables = {}
13structs = {}
14typedefs = {}
Daniel Veillard61006472002-01-21 17:31:47 +000015enums = {}
16functions = {}
Daniel Veillard2d1464f2002-01-21 23:16:56 +000017user_functions = {}
Daniel Veillard61006472002-01-21 17:31:47 +000018ret_types = {}
19types = {}
20
21sections = []
22files = {}
23identifiers_file = {}
24identifiers_type = {}
25
Daniel Veillard2d1464f2002-01-21 23:16:56 +000026##################################################################
27#
Daniel Veillardf8592562002-01-23 17:58:17 +000028# Indexer to generate the word index
29#
30##################################################################
31index = {}
32
33
34def indexString(id, str):
Daniel Veillard5f4b5992002-02-20 10:22:49 +000035 if str == None:
36 return
Daniel Veillardf8592562002-01-23 17:58:17 +000037 str = string.replace(str, "'", ' ')
38 str = string.replace(str, '"', ' ')
39 str = string.replace(str, "/", ' ')
40 str = string.replace(str, '*', ' ')
41 str = string.replace(str, "[", ' ')
42 str = string.replace(str, "]", ' ')
43 str = string.replace(str, "(", ' ')
44 str = string.replace(str, ")", ' ')
45 str = string.replace(str, "<", ' ')
46 str = string.replace(str, '>', ' ')
47 str = string.replace(str, "&", ' ')
48 str = string.replace(str, '#', ' ')
49 str = string.replace(str, ",", ' ')
50 str = string.replace(str, '.', ' ')
51 str = string.replace(str, ';', ' ')
52 tokens = string.split(str)
53 for token in tokens:
54 try:
55 c = token[0]
56 if string.find(string.letters, c) < 0:
57 pass
58 elif len(token) < 3:
59 pass
60 else:
61 lower = string.lower(token)
62 # TODO: generalize this a bit
63 if lower == 'and' or lower == 'the':
64 pass
65 elif index.has_key(token):
66 index[token].append(id)
67 else:
68 index[token] = [id]
69 except:
70 pass
71
72
73
74##################################################################
75#
Daniel Veillard2d1464f2002-01-21 23:16:56 +000076# Parsing: libxml-decl.txt
77#
78##################################################################
Daniel Veillard61006472002-01-21 17:31:47 +000079def mormalizeTypeSpaces(raw, function):
80 global types
81
82 tokens = string.split(raw)
83 type = ''
84 for token in tokens:
85 if type != '':
86 type = type + ' ' + token
87 else:
88 type = token
89 if types.has_key(type):
90 types[type].append(function)
91 else:
92 types[type] = [function]
93 return type
94
95def removeComments(raw):
96 while string.find(raw, '/*') > 0:
97 e = string.find(raw, '/*')
98 tmp = raw[0:e]
99 raw = raw[e:]
100 e = string.find(raw, '*/')
101 if e > 0:
102 raw = tmp + raw[e + 2:]
103 else:
104 raw = tmp
105 return raw
106
107def extractArgs(raw, function):
108 raw = removeComments(raw)
Daniel Veillard9d06d302002-01-22 18:15:52 +0000109 raw = string.replace(raw, '\n', ' ')
110 raw = string.replace(raw, '\r', ' ')
Daniel Veillard61006472002-01-21 17:31:47 +0000111 list = string.split(raw, ",")
112 ret = []
113 for arg in list:
114 i = len(arg)
115 if i == 0:
116 continue
117 i = i - 1
118 c = arg[i]
119 while string.find(string.letters, c) >= 0 or \
Daniel Veillard9d06d302002-01-22 18:15:52 +0000120 string.find(string.digits, c) >= 0 or c == '_':
Daniel Veillard61006472002-01-21 17:31:47 +0000121 i = i - 1
122 if i < 0:
123 break
124 c = arg[i]
125 name = arg[i+1:]
126 while string.find(string.whitespace, c) >= 0:
127 i = i - 1
128 if i < 0:
129 break
130 c = arg[i]
131 type = mormalizeTypeSpaces(arg[0:i+1], function)
Daniel Veillard9d06d302002-01-22 18:15:52 +0000132 if name == 'void' and type == '':
133 pass
134 else:
135 ret.append([type, name, ''])
136
Daniel Veillard61006472002-01-21 17:31:47 +0000137 return ret
138
139def extractTypes(raw, function):
140 global ret_types
141
142 tokens = string.split(raw)
143 type = ''
144 for token in tokens:
145 if type != '':
146 type = type + ' ' + token
147 else:
148 type = token
149 if ret_types.has_key(type):
150 ret_types[type].append(function)
151 else:
152 ret_types[type] = [function]
Daniel Veillard9d06d302002-01-22 18:15:52 +0000153
Daniel Veillard61006472002-01-21 17:31:47 +0000154 return type
155
156def parseMacro():
157 global input
158 global macros
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000159 global variables
Daniel Veillard61006472002-01-21 17:31:47 +0000160
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000161 var = 1
Daniel Veillard61006472002-01-21 17:31:47 +0000162 line = input.readline()[:-1]
163 while line != "</MACRO>":
164 if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
165 name = line[6:-7]
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000166 elif string.find(line, "#define") >= 0:
167 var = 0
Daniel Veillard61006472002-01-21 17:31:47 +0000168 line = input.readline()[:-1]
169
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000170 if var == 1:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000171 variables[name] = ['', ''] # type, info
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000172 identifiers_type[name] = "variable"
173 else:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000174 macros[name] = [[], ''] # args, info
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000175 identifiers_type[name] = "macro"
Daniel Veillard61006472002-01-21 17:31:47 +0000176
177def parseStruct():
178 global input
179 global structs
180
181 line = input.readline()[:-1]
182 while line != "</STRUCT>":
183 if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
184 name = line[6:-7]
185 line = input.readline()[:-1]
186
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000187 structs[name] = ''
Daniel Veillard61006472002-01-21 17:31:47 +0000188 identifiers_type[name] = "struct"
189
190def parseTypedef():
191 global input
192 global typedefs
193
194 line = input.readline()[:-1]
195 while line != "</TYPEDEF>":
196 if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
197 name = line[6:-7]
198 line = input.readline()[:-1]
199
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000200 typedefs[name] = ''
Daniel Veillard61006472002-01-21 17:31:47 +0000201 identifiers_type[name] = "typedef"
202
203def parseEnum():
204 global input
205 global enums
206
207 line = input.readline()[:-1]
208 consts = []
209 while line != "</ENUM>":
210 if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
211 name = line[6:-7]
212 elif string.find(line, 'enum') >= 0:
213 pass
214 elif string.find(line, '{') >= 0:
215 pass
216 elif string.find(line, '}') >= 0:
217 pass
218 elif string.find(line, ';') >= 0:
219 pass
220 else:
221 comment = string.find(line, '/*')
222 if comment >= 0:
223 line = line[0:comment]
224 decls = string.split(line, ",")
225 for decl in decls:
226 val = string.split(decl, "=")[0]
227 tokens = string.split(val)
228 if len(tokens) >= 1:
229 token = tokens[0]
230 if string.find(string.letters, token[0]) >= 0:
231 consts.append(token)
232 identifiers_type[token] = "const"
233 line = input.readline()[:-1]
234
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000235 enums[name] = [consts, '']
Daniel Veillard61006472002-01-21 17:31:47 +0000236 identifiers_type[name] = "enum"
237
238def parseStaticFunction():
239 global input
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000240 global user_functions
Daniel Veillard61006472002-01-21 17:31:47 +0000241
242 line = input.readline()[:-1]
243 type = None
Daniel Veillard9d06d302002-01-22 18:15:52 +0000244 signature = ""
Daniel Veillard61006472002-01-21 17:31:47 +0000245 while line != "</USER_FUNCTION>":
246 if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
247 name = line[6:-7]
248 elif line[0:9] == "<RETURNS>" and line[-10:] == "</RETURNS>":
249 type = extractTypes(line[9:-10], name)
250 else:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000251 signature = signature + line
Daniel Veillard61006472002-01-21 17:31:47 +0000252 line = input.readline()[:-1]
253
254 args = extractArgs(signature, name)
Daniel Veillard9d06d302002-01-22 18:15:52 +0000255 user_functions[name] = [[type, ''] , args, '']
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000256 identifiers_type[name] = "functype"
Daniel Veillard61006472002-01-21 17:31:47 +0000257
258def parseFunction():
259 global input
260 global functions
261
262 line = input.readline()[:-1]
263 type = None
Daniel Veillard9d06d302002-01-22 18:15:52 +0000264 signature = ""
Daniel Veillard61006472002-01-21 17:31:47 +0000265 while line != "</FUNCTION>":
266 if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
267 name = line[6:-7]
268 elif line[0:9] == "<RETURNS>" and line[-10:] == "</RETURNS>":
269 type = extractTypes(line[9:-10], name)
270 else:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000271 signature = signature + line
Daniel Veillard61006472002-01-21 17:31:47 +0000272 line = input.readline()[:-1]
273
274 args = extractArgs(signature, name)
Daniel Veillard9d06d302002-01-22 18:15:52 +0000275 functions[name] = [[type, ''] , args, '']
Daniel Veillard61006472002-01-21 17:31:47 +0000276 identifiers_type[name] = "function"
277
Daniel Veillard61006472002-01-21 17:31:47 +0000278print "Parsing: libxml-decl.txt"
279input = open('libxml-decl.txt')
280while 1:
281 line = input.readline()
282 if not line:
283 break
284 line = line[:-1]
285 if line == "<MACRO>":
286 parseMacro()
287 elif line == "<ENUM>":
288 parseEnum()
289 elif line == "<FUNCTION>":
290 parseFunction()
291 elif line == "<STRUCT>":
292 parseStruct()
293 elif line == "<TYPEDEF>":
294 parseTypedef()
295 elif line == "<USER_FUNCTION>":
296 parseStaticFunction()
297 elif len(line) >= 1 and line[0] == "<":
298 print "unhandled %s" % (line)
299
300print "Parsed: %d macros. %d structs, %d typedefs, %d enums" % (
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000301 len(macros.keys()), len(structs.keys()), len(typedefs.keys()),
302 len(enums))
Daniel Veillard61006472002-01-21 17:31:47 +0000303c = 0
304for enum in enums.keys():
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000305 consts = enums[enum][0]
Daniel Veillard61006472002-01-21 17:31:47 +0000306 c = c + len(consts)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000307print " %d variables, %d constants, %d functions and %d functypes" % (
308 len(variables.keys()), c, len(functions.keys()),
309 len(user_functions.keys()))
Daniel Veillard61006472002-01-21 17:31:47 +0000310print "The functions manipulates %d different types" % (len(types.keys()))
311print "The functions returns %d different types" % (len(ret_types.keys()))
312
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000313##################################################################
314#
315# Parsing: libxml-decl-list.txt
316#
317##################################################################
318def parseSection():
319 global input
320 global sections
321 global files
322 global identifiers_file
323
324 tokens = []
325 line = input.readline()[:-1]
326 while line != "</SECTION>":
327 if line[0:6] == "<FILE>" and line[-7:] == "</FILE>":
328 name = line[6:-7]
329 elif len(line) > 0:
330 tokens.append(line)
331 line = input.readline()[:-1]
332
333 sections.append(name)
334 files[name] = tokens
335 for token in tokens:
336 identifiers_file[token] = name
337 #
338 # Small transitivity for enum values
339 #
340 if enums.has_key(token):
341 for const in enums[token][0]:
342 identifiers_file[const] = name
343
Daniel Veillard61006472002-01-21 17:31:47 +0000344print "Parsing: libxml-decl-list.txt"
345input = open('libxml-decl-list.txt')
346while 1:
347 line = input.readline()
348 if not line:
349 break
350 line = line[:-1]
351 if line == "<SECTION>":
352 parseSection()
353 elif len(line) >= 1 and line[0] == "<":
354 print "unhandled %s" % (line)
355
356print "Parsed: %d files %d identifiers" % (len(files), len(identifiers_file.keys()))
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000357##################################################################
358#
359# Parsing: xml/*.xml
360# To enrich the existing info with extracted comments
361#
362##################################################################
363
364nbcomments = 0
365
Daniel Veillard9d06d302002-01-22 18:15:52 +0000366def insertParameterComment(id, name, value, is_param):
367 global nbcomments
368
Daniel Veillardf8592562002-01-23 17:58:17 +0000369 indexString(id, value)
Daniel Veillard9d06d302002-01-22 18:15:52 +0000370 if functions.has_key(id):
371 if is_param == 1:
372 args = functions[id][1]
373 found = 0
374 for arg in args:
375 if arg[1] == name:
376 arg[2] = value
377 found = 1
378 break
379 if found == 0 and name != '...':
380 print "Arg %s not found on function %s description" % (name, id)
381 return
382 else:
383 ret = functions[id][0]
384 ret[1] = value
385 elif user_functions.has_key(id):
386 if is_param == 1:
387 args = user_functions[id][1]
388 found = 0
389 for arg in args:
390 if arg[1] == name:
391 arg[2] = value
392 found = 1
393 break
394 if found == 0 and name != '...':
395 print "Arg %s not found on functype %s description" % (name, id)
396 print args
397 return
398 else:
399 ret = user_functions[id][0]
400 ret[1] = value
401 elif macros.has_key(id):
402 if is_param == 1:
403 args = macros[id][0]
404 found = 0
405 for arg in args:
406 if arg[0] == name:
407 arg[1] = value
408 found = 1
409 break
410 if found == 0:
411 args.append([name, value])
412 else:
413 print "Return info for macro %s: %s" % (id, value)
414# ret = macros[id][0]
415# ret[1] = value
416 else:
417 print "lost specific comment %s: %s: %s" % (id, name, value)
418 return
419 nbcomments = nbcomments + 1
420
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000421def insertComment(name, title, value, id):
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000422 global nbcomments
423
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000424 ids[name] = id
Daniel Veillardf8592562002-01-23 17:58:17 +0000425 indexString(name, value)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000426 if functions.has_key(name):
427 functions[name][2] = value
Daniel Veillard9d06d302002-01-22 18:15:52 +0000428 return "function"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000429 elif typedefs.has_key(name):
430 typedefs[name] = value
Daniel Veillard9d06d302002-01-22 18:15:52 +0000431 return "typedef"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000432 elif macros.has_key(name):
Daniel Veillard9d06d302002-01-22 18:15:52 +0000433 macros[name][1] = value
434 return "macro"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000435 elif variables.has_key(name):
Daniel Veillard9d06d302002-01-22 18:15:52 +0000436 variables[name][1] = value
437 return "variable"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000438 elif structs.has_key(name):
439 structs[name] = value
Daniel Veillard9d06d302002-01-22 18:15:52 +0000440 return "struct"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000441 elif enums.has_key(name):
442 enums[name][1] = value
Daniel Veillard9d06d302002-01-22 18:15:52 +0000443 return "enum"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000444 elif user_functions.has_key(name):
Daniel Veillard9d06d302002-01-22 18:15:52 +0000445 user_functions[name][2] = value
446 return "user_function"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000447 else:
448 print "lost comment %s: %s" % (name, value)
Daniel Veillard9d06d302002-01-22 18:15:52 +0000449 return "unknown"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000450 nbcomments = nbcomments + 1
451
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000452
Daniel Veillard817e70b2002-11-19 22:28:48 +0000453import libxml2
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000454import os
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000455
456
Daniel Veillard817e70b2002-11-19 22:28:48 +0000457def analyzeXMLDescriptionRow(doc, desc, id, row):
458 if doc == None or desc == None or id == None or row == None:
459 return
460 ctxt = doc.xpathNewContext()
461 ctxt.setContextNode(row)
462 param = ctxt.xpathEval("entry[1]/parameter")
463 entries = ctxt.xpathEval("entry")
464 if param == []:
465 is_param = 0
466 name = None
467 else:
468 name = param[0].content
469 is_param = 1
470 str = entries[1].content
471 str = string.replace(str, '\n', ' ')
472 str = string.replace(str, '\r', ' ')
473 str = string.replace(str, ' ', ' ')
474 str = string.replace(str, ' ', ' ')
475 str = string.replace(str, ' ', ' ')
476 while len(str) >= 1 and str[0] == ' ':
477 str=str[1:]
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000478
Daniel Veillard817e70b2002-11-19 22:28:48 +0000479 insertParameterComment(id, name, str, is_param)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000480
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000481
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000482
Daniel Veillard817e70b2002-11-19 22:28:48 +0000483def analyzeXMLDescription(doc, desc):
484 if doc == None or desc == None:
485 return
486 ctxt = doc.xpathNewContext()
487 ctxt.setContextNode(desc)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000488
Daniel Veillard817e70b2002-11-19 22:28:48 +0000489 #
490 # get the function name
491 #
492 try:
493 title = ctxt.xpathEval("title")[0].content
494 except:
495 return
496 old_id = ctxt.xpathEval("string(title/anchor/@id)")
497 id = string.replace(title, '(', ' ');
498 id = string.replace(id, ')', ' ');
499 id = string.split(id) [0]
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000500
Daniel Veillard817e70b2002-11-19 22:28:48 +0000501 #
502 # get the function comments
503 #
504 comment = ""
505 paras = ctxt.xpathEval("para")
506 for para in paras:
507 str = para.content
508 str = string.replace(str, '\n', ' ')
509 str = string.replace(str, '\r', ' ')
510 str = string.replace(str, ' ', ' ')
511 str = string.replace(str, ' ', ' ')
512 str = string.replace(str, ' ', ' ')
513 while len(str) >= 1 and str[0] == ' ':
514 str=str[1:]
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000515
Daniel Veillard817e70b2002-11-19 22:28:48 +0000516 comment = comment + str
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000517
Daniel Veillard817e70b2002-11-19 22:28:48 +0000518 insertComment(id, title, comment, old_id)
519
520 rows = ctxt.xpathEval("informaltable/tgroup/tbody/row")
521 for row in rows:
522 analyzeXMLDescriptionRow(doc, desc, id, row)
523
524def analyzeXMLDoc(doc):
525 if doc == None:
526 return
527 ctxt = doc.xpathNewContext()
528 descriptions = ctxt.xpathEval("//refsect2")
529 print len(descriptions)
530 for description in descriptions:
531 analyzeXMLDescription(doc, description)
532
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000533xmlfiles = 0
534filenames = os.listdir("xml")
535for filename in filenames:
Daniel Veillard817e70b2002-11-19 22:28:48 +0000536 print filename
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000537 try:
Daniel Veillard817e70b2002-11-19 22:28:48 +0000538 doc = libxml2.parseFile("xml/" + filename)
539 analyzeXMLDoc(doc)
540 doc.freeDoc()
541 xmlfiles = xmlfiles + 1
542 except:
543 print "failed to parse XML description %s" % ("xml/" + filename)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000544 continue
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000545
546print "Parsed: %d XML files collexting %d comments" % (xmlfiles, nbcomments)
547
548##################################################################
549#
550# Saving: libxml2-api.xml
551#
552##################################################################
553
554def escape(raw):
Daniel Veillard9d06d302002-01-22 18:15:52 +0000555 raw = string.replace(raw, '&', '&amp;')
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000556 raw = string.replace(raw, '<', '&lt;')
557 raw = string.replace(raw, '>', '&gt;')
Daniel Veillard9d06d302002-01-22 18:15:52 +0000558 raw = string.replace(raw, "'", '&apos;')
559 raw = string.replace(raw, '"', '&quot;')
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000560 return raw
Daniel Veillard61006472002-01-21 17:31:47 +0000561
562print "Saving XML description libxml2-api.xml"
563output = open("libxml2-api.xml", "w")
Daniel Veillardf8592562002-01-23 17:58:17 +0000564output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
Daniel Veillard61006472002-01-21 17:31:47 +0000565output.write("<api name='libxml2'>\n")
566output.write(" <files>\n")
567for file in files.keys():
568 output.write(" <file name='%s'>\n" % file)
569 for symbol in files[file]:
570 output.write(" <exports symbol='%s'/>\n" % (symbol))
571 output.write(" </file>\n")
572output.write(" </files>\n")
573
574output.write(" <symbols>\n")
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000575symbols=macros.keys()
576for i in structs.keys(): symbols.append(i)
577for i in variables.keys(): variables.append(i)
578for i in typedefs.keys(): symbols.append(i)
Daniel Veillard61006472002-01-21 17:31:47 +0000579for i in enums.keys():
580 symbols.append(i)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000581 for j in enums[i][0]:
Daniel Veillard61006472002-01-21 17:31:47 +0000582 symbols.append(j)
583for i in functions.keys(): symbols.append(i)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000584for i in user_functions.keys(): symbols.append(i)
Daniel Veillard61006472002-01-21 17:31:47 +0000585symbols.sort()
586prev = None
587for i in symbols:
588 if i == prev:
589# print "Symbol %s redefined" % (i)
590 continue
591 else:
592 prev = i
593 if identifiers_type.has_key(i):
594 type = identifiers_type[i]
595
596 if identifiers_file.has_key(i):
597 file = identifiers_file[i]
598 else:
599 file = None
600
601 output.write(" <%s name='%s'" % (type, i))
602 if file != None:
603 output.write(" file='%s'" % (file))
604 if type == "function":
605 output.write(">\n");
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000606 (ret, args, doc) = functions[i]
607 if doc != None and doc != '':
608 output.write(" <info>%s</info>\n" % (escape(doc)))
Daniel Veillard9d06d302002-01-22 18:15:52 +0000609 if ret[1] != None and ret[1] != '':
610 output.write(" <return type='%s' info='%s'/>\n" % (
611 ret[0], escape(ret[1])))
612 else:
613 if ret[0] != 'void' and\
614 ret[0][0:4] != 'void': # This one is actually a bug in GTK Doc
615 print "Description for return on %s is missing" % (i)
616 output.write(" <return type='%s'/>\n" % (ret[0]))
Daniel Veillard61006472002-01-21 17:31:47 +0000617 for arg in args:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000618 if arg[2] != None and arg[2] != '':
619 output.write(" <arg name='%s' type='%s' info='%s'/>\n" %
620 (arg[1], arg[0], escape(arg[2])))
621 else:
622 if arg[0] != '...':
623 print "Description for %s on %s is missing" % (arg[1], i)
624 output.write(" <arg name='%s' type='%s'/>\n" % (
625 arg[1], arg[0]))
626 output.write(" </%s>\n" % (type));
627 elif type == 'functype':
628 output.write(">\n");
629 (ret, args, doc) = user_functions[i]
630 if doc != None and doc != '':
631 output.write(" <info>%s</info>\n" % (escape(doc)))
632 if ret[1] != None and ret[1] != '':
633 output.write(" <return type='%s' info='%s'/>\n" % (
634 ret[0], escape(ret[1])))
635 else:
636 if ret[0] != 'void' and\
637 ret[0][0:4] != 'void': # This one is actually a bug in GTK Doc
638 print "Description for return on %s is missing" % (i)
639 output.write(" <return type='%s'/>\n" % (ret[0]))
640 for arg in args:
641 if arg[2] != None and arg[2] != '':
642 output.write(" <arg name='%s' type='%s' info='%s'/>\n" %
643 (arg[1], arg[0], escape(arg[2])))
644 else:
645 if arg[0] != '...':
646 print "Description for %s on %s is missing" % (arg[1], i)
647 output.write(" <arg name='%s' type='%s'/>\n" % (
648 arg[1], arg[0]))
Daniel Veillard61006472002-01-21 17:31:47 +0000649 output.write(" </%s>\n" % (type));
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000650 elif type == 'macro':
Daniel Veillard9d06d302002-01-22 18:15:52 +0000651 output.write(">\n");
652 if macros[i][1] != None and macros[i][1] != '':
653 output.write(" <info>%s</info>\n" % (escape(macros[i][1])))
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000654 else:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000655 print "Description for %s is missing" % (i)
656 args = macros[i][0]
657 for arg in args:
658 if arg[1] != None and arg[1] != '':
659 output.write(" <arg name='%s' info='%s'/>\n" %
660 (arg[0], escape(arg[1])))
661 else:
662 print "Description for %s on %s is missing" % (arg[1], i)
663 output.write(" <arg name='%s'/>\n" % (arg[0]))
664 output.write(" </%s>\n" % (type));
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000665 elif type == 'struct':
666 if structs[i] != None and structs[i] != '':
667 output.write(" info='%s'/>\n" % (escape(structs[i])))
668 else:
669 output.write("/>\n");
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000670 elif type == 'variable':
Daniel Veillard9d06d302002-01-22 18:15:52 +0000671 if variables[i][1] != None and variables[i][1] != '':
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000672 output.write(" info='%s'/>\n" % (escape(variables[i])))
673 else:
674 output.write("/>\n");
675 elif type == 'typedef':
676 if typedefs[i] != None and typedefs[i] != '':
677 output.write(" info='%s'/>\n" % (escape(typedefs[i])))
678 else:
679 output.write("/>\n");
Daniel Veillard61006472002-01-21 17:31:47 +0000680 else:
681 output.write("/>\n");
682 else:
683 print "Symbol %s not found in identifiers list" % (i)
684output.write(" </symbols>\n")
685output.write("</api>\n")
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000686output.close()
Daniel Veillard61006472002-01-21 17:31:47 +0000687print "generated XML for %d symbols" % (len(symbols))
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000688
689##################################################################
690#
691# Saving: libxml2-api.xml
692#
693##################################################################
694
695hash = {}
696for file in files.keys():
697 for symbol in files[file]:
698 hash[symbol] = file
699
700def link(id):
701 if ids.has_key(id):
702 target = string.upper(ids[id])
703 else:
704 target = string.upper(id)
Daniel Veillard5f4b5992002-02-20 10:22:49 +0000705 if hash.has_key(id):
William M. Bracka716ff12003-08-16 14:58:33 +0000706 module = hash[id]
Daniel Veillard5f4b5992002-02-20 10:22:49 +0000707 else:
708 module = 'index'
709 file = 'html/libxml-' + module + '.html';
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000710 return file + '#' + target
711
712print "Saving XML crossreferences libxml2-refs.xml"
713output = open("libxml2-refs.xml", "w")
Daniel Veillardf8592562002-01-23 17:58:17 +0000714output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000715output.write("<apirefs name='libxml2'>\n")
716output.write(" <references>\n")
717typ = ids.keys()
718typ.sort()
719for id in typ:
720 output.write(" <reference name='%s' href='%s'/>\n" % (id, link(id)))
721output.write(" </references>\n")
722output.write(" <alpha>\n")
723letter = None
724ids = ids.keys()
725ids.sort()
726for id in ids:
727 if id[0] != letter:
728 if letter != None:
729 output.write(" </letter>\n")
730 letter = id[0]
731 output.write(" <letter name='%s'>\n" % (letter))
732 output.write(" <ref name='%s'/>\n" % (id))
733if letter != None:
734 output.write(" </letter>\n")
735output.write(" </alpha>\n")
736output.write(" <constructors>\n")
737typ = ret_types.keys()
738typ.sort()
739for type in typ:
740 if type == '' or type == 'void' or type == "int" or type == "char *" or \
741 type == "const char *" :
742 continue
743 output.write(" <type name='%s'>\n" % (type))
744 ids = ret_types[type]
745 for id in ids:
746 output.write(" <ref name='%s'/>\n" % (id))
747 output.write(" </type>\n")
748output.write(" </constructors>\n")
749output.write(" <functions>\n")
750typ = types.keys()
751typ.sort()
752for type in typ:
753 if type == '' or type == 'void' or type == "int" or type == "char *" or \
754 type == "const char *" :
755 continue
756 output.write(" <type name='%s'>\n" % (type))
757 ids = types[type]
758 for id in ids:
759 output.write(" <ref name='%s'/>\n" % (id))
760 output.write(" </type>\n")
761output.write(" </functions>\n")
762
763output.write(" <files>\n")
764typ = files.keys()
765typ.sort()
766for file in typ:
767 output.write(" <file name='%s'>\n" % (file))
768 for id in files[file]:
769 output.write(" <ref name='%s'/>\n" % (id))
770 output.write(" </file>\n")
771output.write(" </files>\n")
Daniel Veillardf8592562002-01-23 17:58:17 +0000772
773output.write(" <index>\n")
774typ = index.keys()
775typ.sort()
776letter = None
777count = 0
778chunk = 0
779chunks = []
780for id in typ:
781 if len(index[id]) > 30:
782 continue
783 if id[0] != letter:
784 if letter == None or count > 200:
785 if letter != None:
786 output.write(" </letter>\n")
787 output.write(" </chunk>\n")
788 count = 0
789 chunks.append(["chunk%s" % (chunk -1), first_letter, letter])
790 output.write(" <chunk name='chunk%s'>\n" % (chunk))
791 first_letter = id[0]
792 chunk = chunk + 1
793 elif letter != None:
794 output.write(" </letter>\n")
795 letter = id[0]
796 output.write(" <letter name='%s'>\n" % (letter))
797 output.write(" <word name='%s'>\n" % (id))
798 tokens = index[id];
799 tokens.sort()
800 tok = None
801 for token in index[id]:
802 if tok == token:
803 continue
804 tok = token
805 output.write(" <ref name='%s'/>\n" % (token))
806 count = count + 1
807 output.write(" </word>\n")
808if letter != None:
809 output.write(" </letter>\n")
810 output.write(" </chunk>\n")
811 output.write(" <chunks>\n")
812 for ch in chunks:
813 output.write(" <chunk name='%s' start='%s' end='%s'/>\n" % (
814 ch[0], ch[1], ch[2]))
815 output.write(" </chunks>\n")
816output.write(" </index>\n")
817
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000818output.write("</apirefs>\n")
819output.close()