blob: 56305c8ddcbccda4e64f7bd6e70c5da9e7edfecb [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
533doc = libxml2.parseFile("xml/c14n.xml");
534analyzeXMLDoc(doc)
535doc.freeDoc()
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000536
537xmlfiles = 0
538filenames = os.listdir("xml")
539for filename in filenames:
Daniel Veillard817e70b2002-11-19 22:28:48 +0000540 print filename
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000541 try:
Daniel Veillard817e70b2002-11-19 22:28:48 +0000542 doc = libxml2.parseFile("xml/" + filename)
543 analyzeXMLDoc(doc)
544 doc.freeDoc()
545 xmlfiles = xmlfiles + 1
546 except:
547 print "failed to parse XML description %s" % ("xml/" + filename)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000548 continue
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000549
550print "Parsed: %d XML files collexting %d comments" % (xmlfiles, nbcomments)
551
552##################################################################
553#
554# Saving: libxml2-api.xml
555#
556##################################################################
557
558def escape(raw):
Daniel Veillard9d06d302002-01-22 18:15:52 +0000559 raw = string.replace(raw, '&', '&amp;')
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000560 raw = string.replace(raw, '<', '&lt;')
561 raw = string.replace(raw, '>', '&gt;')
Daniel Veillard9d06d302002-01-22 18:15:52 +0000562 raw = string.replace(raw, "'", '&apos;')
563 raw = string.replace(raw, '"', '&quot;')
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000564 return raw
Daniel Veillard61006472002-01-21 17:31:47 +0000565
566print "Saving XML description libxml2-api.xml"
567output = open("libxml2-api.xml", "w")
Daniel Veillardf8592562002-01-23 17:58:17 +0000568output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
Daniel Veillard61006472002-01-21 17:31:47 +0000569output.write("<api name='libxml2'>\n")
570output.write(" <files>\n")
571for file in files.keys():
572 output.write(" <file name='%s'>\n" % file)
573 for symbol in files[file]:
574 output.write(" <exports symbol='%s'/>\n" % (symbol))
575 output.write(" </file>\n")
576output.write(" </files>\n")
577
578output.write(" <symbols>\n")
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000579symbols=macros.keys()
580for i in structs.keys(): symbols.append(i)
581for i in variables.keys(): variables.append(i)
582for i in typedefs.keys(): symbols.append(i)
Daniel Veillard61006472002-01-21 17:31:47 +0000583for i in enums.keys():
584 symbols.append(i)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000585 for j in enums[i][0]:
Daniel Veillard61006472002-01-21 17:31:47 +0000586 symbols.append(j)
587for i in functions.keys(): symbols.append(i)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000588for i in user_functions.keys(): symbols.append(i)
Daniel Veillard61006472002-01-21 17:31:47 +0000589symbols.sort()
590prev = None
591for i in symbols:
592 if i == prev:
593# print "Symbol %s redefined" % (i)
594 continue
595 else:
596 prev = i
597 if identifiers_type.has_key(i):
598 type = identifiers_type[i]
599
600 if identifiers_file.has_key(i):
601 file = identifiers_file[i]
602 else:
603 file = None
604
605 output.write(" <%s name='%s'" % (type, i))
606 if file != None:
607 output.write(" file='%s'" % (file))
608 if type == "function":
609 output.write(">\n");
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000610 (ret, args, doc) = functions[i]
611 if doc != None and doc != '':
612 output.write(" <info>%s</info>\n" % (escape(doc)))
Daniel Veillard9d06d302002-01-22 18:15:52 +0000613 if ret[1] != None and ret[1] != '':
614 output.write(" <return type='%s' info='%s'/>\n" % (
615 ret[0], escape(ret[1])))
616 else:
617 if ret[0] != 'void' and\
618 ret[0][0:4] != 'void': # This one is actually a bug in GTK Doc
619 print "Description for return on %s is missing" % (i)
620 output.write(" <return type='%s'/>\n" % (ret[0]))
Daniel Veillard61006472002-01-21 17:31:47 +0000621 for arg in args:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000622 if arg[2] != None and arg[2] != '':
623 output.write(" <arg name='%s' type='%s' info='%s'/>\n" %
624 (arg[1], arg[0], escape(arg[2])))
625 else:
626 if arg[0] != '...':
627 print "Description for %s on %s is missing" % (arg[1], i)
628 output.write(" <arg name='%s' type='%s'/>\n" % (
629 arg[1], arg[0]))
630 output.write(" </%s>\n" % (type));
631 elif type == 'functype':
632 output.write(">\n");
633 (ret, args, doc) = user_functions[i]
634 if doc != None and doc != '':
635 output.write(" <info>%s</info>\n" % (escape(doc)))
636 if ret[1] != None and ret[1] != '':
637 output.write(" <return type='%s' info='%s'/>\n" % (
638 ret[0], escape(ret[1])))
639 else:
640 if ret[0] != 'void' and\
641 ret[0][0:4] != 'void': # This one is actually a bug in GTK Doc
642 print "Description for return on %s is missing" % (i)
643 output.write(" <return type='%s'/>\n" % (ret[0]))
644 for arg in args:
645 if arg[2] != None and arg[2] != '':
646 output.write(" <arg name='%s' type='%s' info='%s'/>\n" %
647 (arg[1], arg[0], escape(arg[2])))
648 else:
649 if arg[0] != '...':
650 print "Description for %s on %s is missing" % (arg[1], i)
651 output.write(" <arg name='%s' type='%s'/>\n" % (
652 arg[1], arg[0]))
Daniel Veillard61006472002-01-21 17:31:47 +0000653 output.write(" </%s>\n" % (type));
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000654 elif type == 'macro':
Daniel Veillard9d06d302002-01-22 18:15:52 +0000655 output.write(">\n");
656 if macros[i][1] != None and macros[i][1] != '':
657 output.write(" <info>%s</info>\n" % (escape(macros[i][1])))
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000658 else:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000659 print "Description for %s is missing" % (i)
660 args = macros[i][0]
661 for arg in args:
662 if arg[1] != None and arg[1] != '':
663 output.write(" <arg name='%s' info='%s'/>\n" %
664 (arg[0], escape(arg[1])))
665 else:
666 print "Description for %s on %s is missing" % (arg[1], i)
667 output.write(" <arg name='%s'/>\n" % (arg[0]))
668 output.write(" </%s>\n" % (type));
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000669 elif type == 'struct':
670 if structs[i] != None and structs[i] != '':
671 output.write(" info='%s'/>\n" % (escape(structs[i])))
672 else:
673 output.write("/>\n");
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000674 elif type == 'variable':
Daniel Veillard9d06d302002-01-22 18:15:52 +0000675 if variables[i][1] != None and variables[i][1] != '':
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000676 output.write(" info='%s'/>\n" % (escape(variables[i])))
677 else:
678 output.write("/>\n");
679 elif type == 'typedef':
680 if typedefs[i] != None and typedefs[i] != '':
681 output.write(" info='%s'/>\n" % (escape(typedefs[i])))
682 else:
683 output.write("/>\n");
Daniel Veillard61006472002-01-21 17:31:47 +0000684 else:
685 output.write("/>\n");
686 else:
687 print "Symbol %s not found in identifiers list" % (i)
688output.write(" </symbols>\n")
689output.write("</api>\n")
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000690output.close()
Daniel Veillard61006472002-01-21 17:31:47 +0000691print "generated XML for %d symbols" % (len(symbols))
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000692
693##################################################################
694#
695# Saving: libxml2-api.xml
696#
697##################################################################
698
699hash = {}
700for file in files.keys():
701 for symbol in files[file]:
702 hash[symbol] = file
703
704def link(id):
705 if ids.has_key(id):
706 target = string.upper(ids[id])
707 else:
708 target = string.upper(id)
Daniel Veillard5f4b5992002-02-20 10:22:49 +0000709 if hash.has_key(id):
710 module = string.lower(hash[id])
711 else:
712 module = 'index'
713 file = 'html/libxml-' + module + '.html';
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000714 return file + '#' + target
715
716print "Saving XML crossreferences libxml2-refs.xml"
717output = open("libxml2-refs.xml", "w")
Daniel Veillardf8592562002-01-23 17:58:17 +0000718output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000719output.write("<apirefs name='libxml2'>\n")
720output.write(" <references>\n")
721typ = ids.keys()
722typ.sort()
723for id in typ:
724 output.write(" <reference name='%s' href='%s'/>\n" % (id, link(id)))
725output.write(" </references>\n")
726output.write(" <alpha>\n")
727letter = None
728ids = ids.keys()
729ids.sort()
730for id in ids:
731 if id[0] != letter:
732 if letter != None:
733 output.write(" </letter>\n")
734 letter = id[0]
735 output.write(" <letter name='%s'>\n" % (letter))
736 output.write(" <ref name='%s'/>\n" % (id))
737if letter != None:
738 output.write(" </letter>\n")
739output.write(" </alpha>\n")
740output.write(" <constructors>\n")
741typ = ret_types.keys()
742typ.sort()
743for type in typ:
744 if type == '' or type == 'void' or type == "int" or type == "char *" or \
745 type == "const char *" :
746 continue
747 output.write(" <type name='%s'>\n" % (type))
748 ids = ret_types[type]
749 for id in ids:
750 output.write(" <ref name='%s'/>\n" % (id))
751 output.write(" </type>\n")
752output.write(" </constructors>\n")
753output.write(" <functions>\n")
754typ = types.keys()
755typ.sort()
756for type in typ:
757 if type == '' or type == 'void' or type == "int" or type == "char *" or \
758 type == "const char *" :
759 continue
760 output.write(" <type name='%s'>\n" % (type))
761 ids = types[type]
762 for id in ids:
763 output.write(" <ref name='%s'/>\n" % (id))
764 output.write(" </type>\n")
765output.write(" </functions>\n")
766
767output.write(" <files>\n")
768typ = files.keys()
769typ.sort()
770for file in typ:
771 output.write(" <file name='%s'>\n" % (file))
772 for id in files[file]:
773 output.write(" <ref name='%s'/>\n" % (id))
774 output.write(" </file>\n")
775output.write(" </files>\n")
Daniel Veillardf8592562002-01-23 17:58:17 +0000776
777output.write(" <index>\n")
778typ = index.keys()
779typ.sort()
780letter = None
781count = 0
782chunk = 0
783chunks = []
784for id in typ:
785 if len(index[id]) > 30:
786 continue
787 if id[0] != letter:
788 if letter == None or count > 200:
789 if letter != None:
790 output.write(" </letter>\n")
791 output.write(" </chunk>\n")
792 count = 0
793 chunks.append(["chunk%s" % (chunk -1), first_letter, letter])
794 output.write(" <chunk name='chunk%s'>\n" % (chunk))
795 first_letter = id[0]
796 chunk = chunk + 1
797 elif letter != None:
798 output.write(" </letter>\n")
799 letter = id[0]
800 output.write(" <letter name='%s'>\n" % (letter))
801 output.write(" <word name='%s'>\n" % (id))
802 tokens = index[id];
803 tokens.sort()
804 tok = None
805 for token in index[id]:
806 if tok == token:
807 continue
808 tok = token
809 output.write(" <ref name='%s'/>\n" % (token))
810 count = count + 1
811 output.write(" </word>\n")
812if letter != None:
813 output.write(" </letter>\n")
814 output.write(" </chunk>\n")
815 output.write(" <chunks>\n")
816 for ch in chunks:
817 output.write(" <chunk name='%s' start='%s' end='%s'/>\n" % (
818 ch[0], ch[1], ch[2]))
819 output.write(" </chunks>\n")
820output.write(" </index>\n")
821
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000822output.write("</apirefs>\n")
823output.close()