blob: 4e000e3034e02bb76363bbdab8974cc40856e94e [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#
6# TODO: try to extracts comments from the DocBook output of
7
8import sys
9import string
10
Daniel Veillard3bf65be2002-01-23 12:36:34 +000011ids = {}
12
Daniel Veillard2d1464f2002-01-21 23:16:56 +000013macros = {}
14variables = {}
15structs = {}
16typedefs = {}
Daniel Veillard61006472002-01-21 17:31:47 +000017enums = {}
18functions = {}
Daniel Veillard2d1464f2002-01-21 23:16:56 +000019user_functions = {}
Daniel Veillard61006472002-01-21 17:31:47 +000020ret_types = {}
21types = {}
22
23sections = []
24files = {}
25identifiers_file = {}
26identifiers_type = {}
27
Daniel Veillard2d1464f2002-01-21 23:16:56 +000028##################################################################
29#
30# Parsing: libxml-decl.txt
31#
32##################################################################
Daniel Veillard61006472002-01-21 17:31:47 +000033def mormalizeTypeSpaces(raw, function):
34 global types
35
36 tokens = string.split(raw)
37 type = ''
38 for token in tokens:
39 if type != '':
40 type = type + ' ' + token
41 else:
42 type = token
43 if types.has_key(type):
44 types[type].append(function)
45 else:
46 types[type] = [function]
47 return type
48
49def removeComments(raw):
50 while string.find(raw, '/*') > 0:
51 e = string.find(raw, '/*')
52 tmp = raw[0:e]
53 raw = raw[e:]
54 e = string.find(raw, '*/')
55 if e > 0:
56 raw = tmp + raw[e + 2:]
57 else:
58 raw = tmp
59 return raw
60
61def extractArgs(raw, function):
62 raw = removeComments(raw)
Daniel Veillard9d06d302002-01-22 18:15:52 +000063 raw = string.replace(raw, '\n', ' ')
64 raw = string.replace(raw, '\r', ' ')
Daniel Veillard61006472002-01-21 17:31:47 +000065 list = string.split(raw, ",")
66 ret = []
67 for arg in list:
68 i = len(arg)
69 if i == 0:
70 continue
71 i = i - 1
72 c = arg[i]
73 while string.find(string.letters, c) >= 0 or \
Daniel Veillard9d06d302002-01-22 18:15:52 +000074 string.find(string.digits, c) >= 0 or c == '_':
Daniel Veillard61006472002-01-21 17:31:47 +000075 i = i - 1
76 if i < 0:
77 break
78 c = arg[i]
79 name = arg[i+1:]
80 while string.find(string.whitespace, c) >= 0:
81 i = i - 1
82 if i < 0:
83 break
84 c = arg[i]
85 type = mormalizeTypeSpaces(arg[0:i+1], function)
Daniel Veillard9d06d302002-01-22 18:15:52 +000086 if name == 'void' and type == '':
87 pass
88 else:
89 ret.append([type, name, ''])
90
Daniel Veillard61006472002-01-21 17:31:47 +000091 return ret
92
93def extractTypes(raw, function):
94 global ret_types
95
96 tokens = string.split(raw)
97 type = ''
98 for token in tokens:
99 if type != '':
100 type = type + ' ' + token
101 else:
102 type = token
103 if ret_types.has_key(type):
104 ret_types[type].append(function)
105 else:
106 ret_types[type] = [function]
Daniel Veillard9d06d302002-01-22 18:15:52 +0000107
Daniel Veillard61006472002-01-21 17:31:47 +0000108 return type
109
110def parseMacro():
111 global input
112 global macros
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000113 global variables
Daniel Veillard61006472002-01-21 17:31:47 +0000114
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000115 var = 1
Daniel Veillard61006472002-01-21 17:31:47 +0000116 line = input.readline()[:-1]
117 while line != "</MACRO>":
118 if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
119 name = line[6:-7]
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000120 elif string.find(line, "#define") >= 0:
121 var = 0
Daniel Veillard61006472002-01-21 17:31:47 +0000122 line = input.readline()[:-1]
123
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000124 if var == 1:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000125 variables[name] = ['', ''] # type, info
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000126 identifiers_type[name] = "variable"
127 else:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000128 macros[name] = [[], ''] # args, info
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000129 identifiers_type[name] = "macro"
Daniel Veillard61006472002-01-21 17:31:47 +0000130
131def parseStruct():
132 global input
133 global structs
134
135 line = input.readline()[:-1]
136 while line != "</STRUCT>":
137 if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
138 name = line[6:-7]
139 line = input.readline()[:-1]
140
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000141 structs[name] = ''
Daniel Veillard61006472002-01-21 17:31:47 +0000142 identifiers_type[name] = "struct"
143
144def parseTypedef():
145 global input
146 global typedefs
147
148 line = input.readline()[:-1]
149 while line != "</TYPEDEF>":
150 if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
151 name = line[6:-7]
152 line = input.readline()[:-1]
153
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000154 typedefs[name] = ''
Daniel Veillard61006472002-01-21 17:31:47 +0000155 identifiers_type[name] = "typedef"
156
157def parseEnum():
158 global input
159 global enums
160
161 line = input.readline()[:-1]
162 consts = []
163 while line != "</ENUM>":
164 if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
165 name = line[6:-7]
166 elif string.find(line, 'enum') >= 0:
167 pass
168 elif string.find(line, '{') >= 0:
169 pass
170 elif string.find(line, '}') >= 0:
171 pass
172 elif string.find(line, ';') >= 0:
173 pass
174 else:
175 comment = string.find(line, '/*')
176 if comment >= 0:
177 line = line[0:comment]
178 decls = string.split(line, ",")
179 for decl in decls:
180 val = string.split(decl, "=")[0]
181 tokens = string.split(val)
182 if len(tokens) >= 1:
183 token = tokens[0]
184 if string.find(string.letters, token[0]) >= 0:
185 consts.append(token)
186 identifiers_type[token] = "const"
187 line = input.readline()[:-1]
188
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000189 enums[name] = [consts, '']
Daniel Veillard61006472002-01-21 17:31:47 +0000190 identifiers_type[name] = "enum"
191
192def parseStaticFunction():
193 global input
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000194 global user_functions
Daniel Veillard61006472002-01-21 17:31:47 +0000195
196 line = input.readline()[:-1]
197 type = None
Daniel Veillard9d06d302002-01-22 18:15:52 +0000198 signature = ""
Daniel Veillard61006472002-01-21 17:31:47 +0000199 while line != "</USER_FUNCTION>":
200 if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
201 name = line[6:-7]
202 elif line[0:9] == "<RETURNS>" and line[-10:] == "</RETURNS>":
203 type = extractTypes(line[9:-10], name)
204 else:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000205 signature = signature + line
Daniel Veillard61006472002-01-21 17:31:47 +0000206 line = input.readline()[:-1]
207
208 args = extractArgs(signature, name)
Daniel Veillard9d06d302002-01-22 18:15:52 +0000209 user_functions[name] = [[type, ''] , args, '']
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000210 identifiers_type[name] = "functype"
Daniel Veillard61006472002-01-21 17:31:47 +0000211
212def parseFunction():
213 global input
214 global functions
215
216 line = input.readline()[:-1]
217 type = None
Daniel Veillard9d06d302002-01-22 18:15:52 +0000218 signature = ""
Daniel Veillard61006472002-01-21 17:31:47 +0000219 while line != "</FUNCTION>":
220 if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
221 name = line[6:-7]
222 elif line[0:9] == "<RETURNS>" and line[-10:] == "</RETURNS>":
223 type = extractTypes(line[9:-10], name)
224 else:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000225 signature = signature + line
Daniel Veillard61006472002-01-21 17:31:47 +0000226 line = input.readline()[:-1]
227
228 args = extractArgs(signature, name)
Daniel Veillard9d06d302002-01-22 18:15:52 +0000229 functions[name] = [[type, ''] , args, '']
Daniel Veillard61006472002-01-21 17:31:47 +0000230 identifiers_type[name] = "function"
231
Daniel Veillard61006472002-01-21 17:31:47 +0000232print "Parsing: libxml-decl.txt"
233input = open('libxml-decl.txt')
234while 1:
235 line = input.readline()
236 if not line:
237 break
238 line = line[:-1]
239 if line == "<MACRO>":
240 parseMacro()
241 elif line == "<ENUM>":
242 parseEnum()
243 elif line == "<FUNCTION>":
244 parseFunction()
245 elif line == "<STRUCT>":
246 parseStruct()
247 elif line == "<TYPEDEF>":
248 parseTypedef()
249 elif line == "<USER_FUNCTION>":
250 parseStaticFunction()
251 elif len(line) >= 1 and line[0] == "<":
252 print "unhandled %s" % (line)
253
254print "Parsed: %d macros. %d structs, %d typedefs, %d enums" % (
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000255 len(macros.keys()), len(structs.keys()), len(typedefs.keys()),
256 len(enums))
Daniel Veillard61006472002-01-21 17:31:47 +0000257c = 0
258for enum in enums.keys():
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000259 consts = enums[enum][0]
Daniel Veillard61006472002-01-21 17:31:47 +0000260 c = c + len(consts)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000261print " %d variables, %d constants, %d functions and %d functypes" % (
262 len(variables.keys()), c, len(functions.keys()),
263 len(user_functions.keys()))
Daniel Veillard61006472002-01-21 17:31:47 +0000264print "The functions manipulates %d different types" % (len(types.keys()))
265print "The functions returns %d different types" % (len(ret_types.keys()))
266
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000267##################################################################
268#
269# Parsing: libxml-decl-list.txt
270#
271##################################################################
272def parseSection():
273 global input
274 global sections
275 global files
276 global identifiers_file
277
278 tokens = []
279 line = input.readline()[:-1]
280 while line != "</SECTION>":
281 if line[0:6] == "<FILE>" and line[-7:] == "</FILE>":
282 name = line[6:-7]
283 elif len(line) > 0:
284 tokens.append(line)
285 line = input.readline()[:-1]
286
287 sections.append(name)
288 files[name] = tokens
289 for token in tokens:
290 identifiers_file[token] = name
291 #
292 # Small transitivity for enum values
293 #
294 if enums.has_key(token):
295 for const in enums[token][0]:
296 identifiers_file[const] = name
297
Daniel Veillard61006472002-01-21 17:31:47 +0000298print "Parsing: libxml-decl-list.txt"
299input = open('libxml-decl-list.txt')
300while 1:
301 line = input.readline()
302 if not line:
303 break
304 line = line[:-1]
305 if line == "<SECTION>":
306 parseSection()
307 elif len(line) >= 1 and line[0] == "<":
308 print "unhandled %s" % (line)
309
310print "Parsed: %d files %d identifiers" % (len(files), len(identifiers_file.keys()))
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000311##################################################################
312#
313# Parsing: xml/*.xml
314# To enrich the existing info with extracted comments
315#
316##################################################################
317
318nbcomments = 0
319
Daniel Veillard9d06d302002-01-22 18:15:52 +0000320def insertParameterComment(id, name, value, is_param):
321 global nbcomments
322
323 if functions.has_key(id):
324 if is_param == 1:
325 args = functions[id][1]
326 found = 0
327 for arg in args:
328 if arg[1] == name:
329 arg[2] = value
330 found = 1
331 break
332 if found == 0 and name != '...':
333 print "Arg %s not found on function %s description" % (name, id)
334 return
335 else:
336 ret = functions[id][0]
337 ret[1] = value
338 elif user_functions.has_key(id):
339 if is_param == 1:
340 args = user_functions[id][1]
341 found = 0
342 for arg in args:
343 if arg[1] == name:
344 arg[2] = value
345 found = 1
346 break
347 if found == 0 and name != '...':
348 print "Arg %s not found on functype %s description" % (name, id)
349 print args
350 return
351 else:
352 ret = user_functions[id][0]
353 ret[1] = value
354 elif macros.has_key(id):
355 if is_param == 1:
356 args = macros[id][0]
357 found = 0
358 for arg in args:
359 if arg[0] == name:
360 arg[1] = value
361 found = 1
362 break
363 if found == 0:
364 args.append([name, value])
365 else:
366 print "Return info for macro %s: %s" % (id, value)
367# ret = macros[id][0]
368# ret[1] = value
369 else:
370 print "lost specific comment %s: %s: %s" % (id, name, value)
371 return
372 nbcomments = nbcomments + 1
373
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000374def insertComment(name, title, value, id):
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000375 global nbcomments
376
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000377 ids[name] = id
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000378 if functions.has_key(name):
379 functions[name][2] = value
Daniel Veillard9d06d302002-01-22 18:15:52 +0000380 return "function"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000381 elif typedefs.has_key(name):
382 typedefs[name] = value
Daniel Veillard9d06d302002-01-22 18:15:52 +0000383 return "typedef"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000384 elif macros.has_key(name):
Daniel Veillard9d06d302002-01-22 18:15:52 +0000385 macros[name][1] = value
386 return "macro"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000387 elif variables.has_key(name):
Daniel Veillard9d06d302002-01-22 18:15:52 +0000388 variables[name][1] = value
389 return "variable"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000390 elif structs.has_key(name):
391 structs[name] = value
Daniel Veillard9d06d302002-01-22 18:15:52 +0000392 return "struct"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000393 elif enums.has_key(name):
394 enums[name][1] = value
Daniel Veillard9d06d302002-01-22 18:15:52 +0000395 return "enum"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000396 elif user_functions.has_key(name):
Daniel Veillard9d06d302002-01-22 18:15:52 +0000397 user_functions[name][2] = value
398 return "user_function"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000399 else:
400 print "lost comment %s: %s" % (name, value)
Daniel Veillard9d06d302002-01-22 18:15:52 +0000401 return "unknown"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000402 nbcomments = nbcomments + 1
403
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000404
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000405import os
406import xmllib
407try:
408 import sgmlop
409except ImportError:
410 sgmlop = None # accelerator not available
411
412debug = 0
413
414if sgmlop:
415 class FastParser:
416 """sgmlop based XML parser. this is typically 15x faster
417 than SlowParser..."""
418
419 def __init__(self, target):
420
421 # setup callbacks
422 self.finish_starttag = target.start
423 self.finish_endtag = target.end
424 self.handle_data = target.data
425
426 # activate parser
427 self.parser = sgmlop.XMLParser()
428 self.parser.register(self)
429 self.feed = self.parser.feed
430 self.entity = {
431 "amp": "&", "gt": ">", "lt": "<",
432 "apos": "'", "quot": '"'
433 }
434
435 def close(self):
436 try:
437 self.parser.close()
438 finally:
439 self.parser = self.feed = None # nuke circular reference
440
441 def handle_entityref(self, entity):
442 # <string> entity
443 try:
444 self.handle_data(self.entity[entity])
445 except KeyError:
446 self.handle_data("&%s;" % entity)
447
448else:
449 FastParser = None
450
451
452class SlowParser(xmllib.XMLParser):
453 """slow but safe standard parser, based on the XML parser in
454 Python's standard library."""
455
456 def __init__(self, target):
457 self.unknown_starttag = target.start
458 self.handle_data = target.data
459 self.unknown_endtag = target.end
460 xmllib.XMLParser.__init__(self)
461
462def getparser(target = None):
463 # get the fastest available parser, and attach it to an
464 # unmarshalling object. return both objects.
465 if target == None:
466 target = docParser()
467 if FastParser:
468 return FastParser(target), target
469 return SlowParser(target), target
470
471class docParser:
472 def __init__(self):
473 self._methodname = None
474 self._data = []
475 self.id = None
476 self.title = None
477 self.descr = None
478 self.string = None
479
480 def close(self):
481 if debug:
482 print "close"
483
484 def getmethodname(self):
485 return self._methodname
486
487 def data(self, text):
488 if debug:
489 print "data %s" % text
490 self._data.append(text)
491
492 def start(self, tag, attrs):
493 if debug:
494 print "start %s, %s" % (tag, attrs)
495 if tag == 'refsect2':
496 self.id = None
497 self.title = None
498 self.descr = None
499 self.string = None
Daniel Veillard9d06d302002-01-22 18:15:52 +0000500 self.type = None
501 self.in_parameter = 0
502 self.is_parameter = 0
503 self.parameter = None
504 self.parameter_info = None
505 self.entry = 0
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000506 elif tag == 'para':
507 self._data = []
508 elif tag == 'title':
509 self._data = []
Daniel Veillard9d06d302002-01-22 18:15:52 +0000510 elif tag == 'tgroup':
511 self.in_parameter = 1
512 elif tag == 'row':
513 self._data = []
514 self.entry = 0
515 elif tag == 'entry':
516 self.entry = self.entry + 1
517 elif tag == 'parameter' and self.in_parameter == 1:
518 self._data = []
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000519 elif tag == 'anchor' and self.id == None:
520 if attrs.has_key('id'):
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000521 self.orig_id = attrs['id']
522 self.id = string.replace(self.orig_id, '-CAPS', '')
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000523 self.id = string.replace(self.id, '-', '_')
524
525 def end(self, tag):
526 if debug:
527 print "end %s" % tag
528 if tag == 'refsect2':
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000529 self.type = insertComment(self.id, self.title, self.string,
530 self.orig_id)
Daniel Veillard9d06d302002-01-22 18:15:52 +0000531 self.string = None
532 elif tag == 'row':
533 if self.parameter_info != None and self.parameter_info != '':
534 insertParameterComment(self.id, self.parameter,
535 self.parameter_info, self.is_parameter)
536 self.parameter_info = None
537 self.parameter = 0
538 self.is_parameter = 0
539 elif tag == 'parameter' and self.in_parameter == 1 and self.entry == 1:
540 str = ''
541 for c in self._data:
542 str = str + c
543 str = string.replace(str, '\n', ' ')
544 str = string.replace(str, '\r', ' ')
545 str = string.replace(str, ' ', ' ')
546 str = string.replace(str, ' ', ' ')
547 str = string.replace(str, ' ', ' ')
548 while len(str) >= 1 and str[0] == ' ':
549 str=str[1:]
550 self.parameter = str
551 self.is_parameter = 1
552 self._data = []
553 elif tag == 'para' or tag == 'entry':
554 str = ''
555 for c in self._data:
556 str = str + c
557 str = string.replace(str, '\n', ' ')
558 str = string.replace(str, '\r', ' ')
559 str = string.replace(str, ' ', ' ')
560 str = string.replace(str, ' ', ' ')
561 str = string.replace(str, ' ', ' ')
562 while len(str) >= 1 and str[0] == ' ':
563 str=str[1:]
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000564 if self.string == None:
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000565 self.string = str
Daniel Veillard9d06d302002-01-22 18:15:52 +0000566 elif self.in_parameter == 1:
567 self.parameter_info = str
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000568 self._data = []
569 elif tag == 'title':
570 str = ''
571 for c in self._data:
572 str = str + c
573 str = string.replace(str, '\n', ' ')
574 str = string.replace(str, '\r', ' ')
575 str = string.replace(str, ' ', ' ')
576 str = string.replace(str, ' ', ' ')
577 str = string.replace(str, ' ', ' ')
578 while len(str) >= 1 and str[0] == ' ':
579 str=str[1:]
580 self.title = str
581
582xmlfiles = 0
583filenames = os.listdir("xml")
584for filename in filenames:
585 try:
586 f = open("xml/" + filename, 'r')
587 except IOError, msg:
588 print file, ":", msg
589 continue
590 data = f.read()
591 (parser, target) = getparser()
592 parser.feed(data)
593 parser.close()
594 xmlfiles = xmlfiles + 1
595
596print "Parsed: %d XML files collexting %d comments" % (xmlfiles, nbcomments)
597
598##################################################################
599#
600# Saving: libxml2-api.xml
601#
602##################################################################
603
604def escape(raw):
Daniel Veillard9d06d302002-01-22 18:15:52 +0000605 raw = string.replace(raw, '&', '&amp;')
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000606 raw = string.replace(raw, '<', '&lt;')
607 raw = string.replace(raw, '>', '&gt;')
Daniel Veillard9d06d302002-01-22 18:15:52 +0000608 raw = string.replace(raw, "'", '&apos;')
609 raw = string.replace(raw, '"', '&quot;')
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000610 return raw
Daniel Veillard61006472002-01-21 17:31:47 +0000611
612print "Saving XML description libxml2-api.xml"
613output = open("libxml2-api.xml", "w")
614output.write("<api name='libxml2'>\n")
615output.write(" <files>\n")
616for file in files.keys():
617 output.write(" <file name='%s'>\n" % file)
618 for symbol in files[file]:
619 output.write(" <exports symbol='%s'/>\n" % (symbol))
620 output.write(" </file>\n")
621output.write(" </files>\n")
622
623output.write(" <symbols>\n")
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000624symbols=macros.keys()
625for i in structs.keys(): symbols.append(i)
626for i in variables.keys(): variables.append(i)
627for i in typedefs.keys(): symbols.append(i)
Daniel Veillard61006472002-01-21 17:31:47 +0000628for i in enums.keys():
629 symbols.append(i)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000630 for j in enums[i][0]:
Daniel Veillard61006472002-01-21 17:31:47 +0000631 symbols.append(j)
632for i in functions.keys(): symbols.append(i)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000633for i in user_functions.keys(): symbols.append(i)
Daniel Veillard61006472002-01-21 17:31:47 +0000634symbols.sort()
635prev = None
636for i in symbols:
637 if i == prev:
638# print "Symbol %s redefined" % (i)
639 continue
640 else:
641 prev = i
642 if identifiers_type.has_key(i):
643 type = identifiers_type[i]
644
645 if identifiers_file.has_key(i):
646 file = identifiers_file[i]
647 else:
648 file = None
649
650 output.write(" <%s name='%s'" % (type, i))
651 if file != None:
652 output.write(" file='%s'" % (file))
653 if type == "function":
654 output.write(">\n");
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000655 (ret, args, doc) = functions[i]
656 if doc != None and doc != '':
657 output.write(" <info>%s</info>\n" % (escape(doc)))
Daniel Veillard9d06d302002-01-22 18:15:52 +0000658 if ret[1] != None and ret[1] != '':
659 output.write(" <return type='%s' info='%s'/>\n" % (
660 ret[0], escape(ret[1])))
661 else:
662 if ret[0] != 'void' and\
663 ret[0][0:4] != 'void': # This one is actually a bug in GTK Doc
664 print "Description for return on %s is missing" % (i)
665 output.write(" <return type='%s'/>\n" % (ret[0]))
Daniel Veillard61006472002-01-21 17:31:47 +0000666 for arg in args:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000667 if arg[2] != None and arg[2] != '':
668 output.write(" <arg name='%s' type='%s' info='%s'/>\n" %
669 (arg[1], arg[0], escape(arg[2])))
670 else:
671 if arg[0] != '...':
672 print "Description for %s on %s is missing" % (arg[1], i)
673 output.write(" <arg name='%s' type='%s'/>\n" % (
674 arg[1], arg[0]))
675 output.write(" </%s>\n" % (type));
676 elif type == 'functype':
677 output.write(">\n");
678 (ret, args, doc) = user_functions[i]
679 if doc != None and doc != '':
680 output.write(" <info>%s</info>\n" % (escape(doc)))
681 if ret[1] != None and ret[1] != '':
682 output.write(" <return type='%s' info='%s'/>\n" % (
683 ret[0], escape(ret[1])))
684 else:
685 if ret[0] != 'void' and\
686 ret[0][0:4] != 'void': # This one is actually a bug in GTK Doc
687 print "Description for return on %s is missing" % (i)
688 output.write(" <return type='%s'/>\n" % (ret[0]))
689 for arg in args:
690 if arg[2] != None and arg[2] != '':
691 output.write(" <arg name='%s' type='%s' info='%s'/>\n" %
692 (arg[1], arg[0], escape(arg[2])))
693 else:
694 if arg[0] != '...':
695 print "Description for %s on %s is missing" % (arg[1], i)
696 output.write(" <arg name='%s' type='%s'/>\n" % (
697 arg[1], arg[0]))
Daniel Veillard61006472002-01-21 17:31:47 +0000698 output.write(" </%s>\n" % (type));
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000699 elif type == 'macro':
Daniel Veillard9d06d302002-01-22 18:15:52 +0000700 output.write(">\n");
701 if macros[i][1] != None and macros[i][1] != '':
702 output.write(" <info>%s</info>\n" % (escape(macros[i][1])))
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000703 else:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000704 print "Description for %s is missing" % (i)
705 args = macros[i][0]
706 for arg in args:
707 if arg[1] != None and arg[1] != '':
708 output.write(" <arg name='%s' info='%s'/>\n" %
709 (arg[0], escape(arg[1])))
710 else:
711 print "Description for %s on %s is missing" % (arg[1], i)
712 output.write(" <arg name='%s'/>\n" % (arg[0]))
713 output.write(" </%s>\n" % (type));
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000714 elif type == 'struct':
715 if structs[i] != None and structs[i] != '':
716 output.write(" info='%s'/>\n" % (escape(structs[i])))
717 else:
718 output.write("/>\n");
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000719 elif type == 'variable':
Daniel Veillard9d06d302002-01-22 18:15:52 +0000720 if variables[i][1] != None and variables[i][1] != '':
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000721 output.write(" info='%s'/>\n" % (escape(variables[i])))
722 else:
723 output.write("/>\n");
724 elif type == 'typedef':
725 if typedefs[i] != None and typedefs[i] != '':
726 output.write(" info='%s'/>\n" % (escape(typedefs[i])))
727 else:
728 output.write("/>\n");
Daniel Veillard61006472002-01-21 17:31:47 +0000729 else:
730 output.write("/>\n");
731 else:
732 print "Symbol %s not found in identifiers list" % (i)
733output.write(" </symbols>\n")
734output.write("</api>\n")
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000735output.close()
Daniel Veillard61006472002-01-21 17:31:47 +0000736print "generated XML for %d symbols" % (len(symbols))
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000737
738##################################################################
739#
740# Saving: libxml2-api.xml
741#
742##################################################################
743
744hash = {}
745for file in files.keys():
746 for symbol in files[file]:
747 hash[symbol] = file
748
749def link(id):
750 if ids.has_key(id):
751 target = string.upper(ids[id])
752 else:
753 target = string.upper(id)
754 file = 'html/libxml-' + string.lower(hash[id]) + '.html';
755 return file + '#' + target
756
757print "Saving XML crossreferences libxml2-refs.xml"
758output = open("libxml2-refs.xml", "w")
759output.write("<apirefs name='libxml2'>\n")
760output.write(" <references>\n")
761typ = ids.keys()
762typ.sort()
763for id in typ:
764 output.write(" <reference name='%s' href='%s'/>\n" % (id, link(id)))
765output.write(" </references>\n")
766output.write(" <alpha>\n")
767letter = None
768ids = ids.keys()
769ids.sort()
770for id in ids:
771 if id[0] != letter:
772 if letter != None:
773 output.write(" </letter>\n")
774 letter = id[0]
775 output.write(" <letter name='%s'>\n" % (letter))
776 output.write(" <ref name='%s'/>\n" % (id))
777if letter != None:
778 output.write(" </letter>\n")
779output.write(" </alpha>\n")
780output.write(" <constructors>\n")
781typ = ret_types.keys()
782typ.sort()
783for type in typ:
784 if type == '' or type == 'void' or type == "int" or type == "char *" or \
785 type == "const char *" :
786 continue
787 output.write(" <type name='%s'>\n" % (type))
788 ids = ret_types[type]
789 for id in ids:
790 output.write(" <ref name='%s'/>\n" % (id))
791 output.write(" </type>\n")
792output.write(" </constructors>\n")
793output.write(" <functions>\n")
794typ = types.keys()
795typ.sort()
796for type in typ:
797 if type == '' or type == 'void' or type == "int" or type == "char *" or \
798 type == "const char *" :
799 continue
800 output.write(" <type name='%s'>\n" % (type))
801 ids = types[type]
802 for id in ids:
803 output.write(" <ref name='%s'/>\n" % (id))
804 output.write(" </type>\n")
805output.write(" </functions>\n")
806
807output.write(" <files>\n")
808typ = files.keys()
809typ.sort()
810for file in typ:
811 output.write(" <file name='%s'>\n" % (file))
812 for id in files[file]:
813 output.write(" <ref name='%s'/>\n" % (id))
814 output.write(" </file>\n")
815output.write(" </files>\n")
816output.write("</apirefs>\n")
817output.close()
818print "generated %d XML references" % (len(ids))