blob: 31457011b0f69e805666c83ac79b16ec6c29f1e4 [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 Veillard2d1464f2002-01-21 23:16:56 +0000453import os
454import xmllib
455try:
456 import sgmlop
457except ImportError:
458 sgmlop = None # accelerator not available
459
460debug = 0
461
462if sgmlop:
463 class FastParser:
464 """sgmlop based XML parser. this is typically 15x faster
465 than SlowParser..."""
466
467 def __init__(self, target):
468
469 # setup callbacks
470 self.finish_starttag = target.start
471 self.finish_endtag = target.end
472 self.handle_data = target.data
473
474 # activate parser
475 self.parser = sgmlop.XMLParser()
476 self.parser.register(self)
477 self.feed = self.parser.feed
478 self.entity = {
479 "amp": "&", "gt": ">", "lt": "<",
480 "apos": "'", "quot": '"'
481 }
482
483 def close(self):
484 try:
485 self.parser.close()
486 finally:
487 self.parser = self.feed = None # nuke circular reference
488
489 def handle_entityref(self, entity):
490 # <string> entity
491 try:
492 self.handle_data(self.entity[entity])
493 except KeyError:
494 self.handle_data("&%s;" % entity)
495
496else:
497 FastParser = None
498
499
500class SlowParser(xmllib.XMLParser):
501 """slow but safe standard parser, based on the XML parser in
502 Python's standard library."""
503
504 def __init__(self, target):
505 self.unknown_starttag = target.start
506 self.handle_data = target.data
507 self.unknown_endtag = target.end
508 xmllib.XMLParser.__init__(self)
509
510def getparser(target = None):
511 # get the fastest available parser, and attach it to an
512 # unmarshalling object. return both objects.
513 if target == None:
514 target = docParser()
515 if FastParser:
516 return FastParser(target), target
517 return SlowParser(target), target
518
519class docParser:
520 def __init__(self):
521 self._methodname = None
522 self._data = []
523 self.id = None
524 self.title = None
525 self.descr = None
526 self.string = None
527
528 def close(self):
529 if debug:
530 print "close"
531
532 def getmethodname(self):
533 return self._methodname
534
535 def data(self, text):
536 if debug:
537 print "data %s" % text
538 self._data.append(text)
539
540 def start(self, tag, attrs):
541 if debug:
542 print "start %s, %s" % (tag, attrs)
543 if tag == 'refsect2':
544 self.id = None
545 self.title = None
546 self.descr = None
547 self.string = None
Daniel Veillard9d06d302002-01-22 18:15:52 +0000548 self.type = None
549 self.in_parameter = 0
550 self.is_parameter = 0
551 self.parameter = None
552 self.parameter_info = None
553 self.entry = 0
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000554 elif tag == 'para':
555 self._data = []
556 elif tag == 'title':
557 self._data = []
Daniel Veillard9d06d302002-01-22 18:15:52 +0000558 elif tag == 'tgroup':
559 self.in_parameter = 1
560 elif tag == 'row':
561 self._data = []
562 self.entry = 0
563 elif tag == 'entry':
564 self.entry = self.entry + 1
565 elif tag == 'parameter' and self.in_parameter == 1:
566 self._data = []
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000567 elif tag == 'anchor' and self.id == None:
568 if attrs.has_key('id'):
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000569 self.orig_id = attrs['id']
570 self.id = string.replace(self.orig_id, '-CAPS', '')
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000571 self.id = string.replace(self.id, '-', '_')
572
573 def end(self, tag):
574 if debug:
575 print "end %s" % tag
576 if tag == 'refsect2':
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000577 self.type = insertComment(self.id, self.title, self.string,
578 self.orig_id)
Daniel Veillard9d06d302002-01-22 18:15:52 +0000579 self.string = None
580 elif tag == 'row':
581 if self.parameter_info != None and self.parameter_info != '':
582 insertParameterComment(self.id, self.parameter,
583 self.parameter_info, self.is_parameter)
584 self.parameter_info = None
585 self.parameter = 0
586 self.is_parameter = 0
587 elif tag == 'parameter' and self.in_parameter == 1 and self.entry == 1:
588 str = ''
589 for c in self._data:
590 str = str + c
591 str = string.replace(str, '\n', ' ')
592 str = string.replace(str, '\r', ' ')
593 str = string.replace(str, ' ', ' ')
594 str = string.replace(str, ' ', ' ')
595 str = string.replace(str, ' ', ' ')
596 while len(str) >= 1 and str[0] == ' ':
597 str=str[1:]
598 self.parameter = str
599 self.is_parameter = 1
600 self._data = []
601 elif tag == 'para' or tag == 'entry':
602 str = ''
603 for c in self._data:
604 str = str + c
605 str = string.replace(str, '\n', ' ')
606 str = string.replace(str, '\r', ' ')
607 str = string.replace(str, ' ', ' ')
608 str = string.replace(str, ' ', ' ')
609 str = string.replace(str, ' ', ' ')
610 while len(str) >= 1 and str[0] == ' ':
611 str=str[1:]
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000612 if self.string == None:
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000613 self.string = str
Daniel Veillard9d06d302002-01-22 18:15:52 +0000614 elif self.in_parameter == 1:
615 self.parameter_info = str
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000616 self._data = []
617 elif tag == 'title':
618 str = ''
619 for c in self._data:
620 str = str + c
621 str = string.replace(str, '\n', ' ')
622 str = string.replace(str, '\r', ' ')
623 str = string.replace(str, ' ', ' ')
624 str = string.replace(str, ' ', ' ')
625 str = string.replace(str, ' ', ' ')
626 while len(str) >= 1 and str[0] == ' ':
627 str=str[1:]
628 self.title = str
629
630xmlfiles = 0
631filenames = os.listdir("xml")
632for filename in filenames:
633 try:
634 f = open("xml/" + filename, 'r')
635 except IOError, msg:
636 print file, ":", msg
637 continue
638 data = f.read()
639 (parser, target) = getparser()
640 parser.feed(data)
641 parser.close()
642 xmlfiles = xmlfiles + 1
643
644print "Parsed: %d XML files collexting %d comments" % (xmlfiles, nbcomments)
645
646##################################################################
647#
648# Saving: libxml2-api.xml
649#
650##################################################################
651
652def escape(raw):
Daniel Veillard9d06d302002-01-22 18:15:52 +0000653 raw = string.replace(raw, '&', '&amp;')
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000654 raw = string.replace(raw, '<', '&lt;')
655 raw = string.replace(raw, '>', '&gt;')
Daniel Veillard9d06d302002-01-22 18:15:52 +0000656 raw = string.replace(raw, "'", '&apos;')
657 raw = string.replace(raw, '"', '&quot;')
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000658 return raw
Daniel Veillard61006472002-01-21 17:31:47 +0000659
660print "Saving XML description libxml2-api.xml"
661output = open("libxml2-api.xml", "w")
Daniel Veillardf8592562002-01-23 17:58:17 +0000662output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
Daniel Veillard61006472002-01-21 17:31:47 +0000663output.write("<api name='libxml2'>\n")
664output.write(" <files>\n")
665for file in files.keys():
666 output.write(" <file name='%s'>\n" % file)
667 for symbol in files[file]:
668 output.write(" <exports symbol='%s'/>\n" % (symbol))
669 output.write(" </file>\n")
670output.write(" </files>\n")
671
672output.write(" <symbols>\n")
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000673symbols=macros.keys()
674for i in structs.keys(): symbols.append(i)
675for i in variables.keys(): variables.append(i)
676for i in typedefs.keys(): symbols.append(i)
Daniel Veillard61006472002-01-21 17:31:47 +0000677for i in enums.keys():
678 symbols.append(i)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000679 for j in enums[i][0]:
Daniel Veillard61006472002-01-21 17:31:47 +0000680 symbols.append(j)
681for i in functions.keys(): symbols.append(i)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000682for i in user_functions.keys(): symbols.append(i)
Daniel Veillard61006472002-01-21 17:31:47 +0000683symbols.sort()
684prev = None
685for i in symbols:
686 if i == prev:
687# print "Symbol %s redefined" % (i)
688 continue
689 else:
690 prev = i
691 if identifiers_type.has_key(i):
692 type = identifiers_type[i]
693
694 if identifiers_file.has_key(i):
695 file = identifiers_file[i]
696 else:
697 file = None
698
699 output.write(" <%s name='%s'" % (type, i))
700 if file != None:
701 output.write(" file='%s'" % (file))
702 if type == "function":
703 output.write(">\n");
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000704 (ret, args, doc) = functions[i]
705 if doc != None and doc != '':
706 output.write(" <info>%s</info>\n" % (escape(doc)))
Daniel Veillard9d06d302002-01-22 18:15:52 +0000707 if ret[1] != None and ret[1] != '':
708 output.write(" <return type='%s' info='%s'/>\n" % (
709 ret[0], escape(ret[1])))
710 else:
711 if ret[0] != 'void' and\
712 ret[0][0:4] != 'void': # This one is actually a bug in GTK Doc
713 print "Description for return on %s is missing" % (i)
714 output.write(" <return type='%s'/>\n" % (ret[0]))
Daniel Veillard61006472002-01-21 17:31:47 +0000715 for arg in args:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000716 if arg[2] != None and arg[2] != '':
717 output.write(" <arg name='%s' type='%s' info='%s'/>\n" %
718 (arg[1], arg[0], escape(arg[2])))
719 else:
720 if arg[0] != '...':
721 print "Description for %s on %s is missing" % (arg[1], i)
722 output.write(" <arg name='%s' type='%s'/>\n" % (
723 arg[1], arg[0]))
724 output.write(" </%s>\n" % (type));
725 elif type == 'functype':
726 output.write(">\n");
727 (ret, args, doc) = user_functions[i]
728 if doc != None and doc != '':
729 output.write(" <info>%s</info>\n" % (escape(doc)))
730 if ret[1] != None and ret[1] != '':
731 output.write(" <return type='%s' info='%s'/>\n" % (
732 ret[0], escape(ret[1])))
733 else:
734 if ret[0] != 'void' and\
735 ret[0][0:4] != 'void': # This one is actually a bug in GTK Doc
736 print "Description for return on %s is missing" % (i)
737 output.write(" <return type='%s'/>\n" % (ret[0]))
738 for arg in args:
739 if arg[2] != None and arg[2] != '':
740 output.write(" <arg name='%s' type='%s' info='%s'/>\n" %
741 (arg[1], arg[0], escape(arg[2])))
742 else:
743 if arg[0] != '...':
744 print "Description for %s on %s is missing" % (arg[1], i)
745 output.write(" <arg name='%s' type='%s'/>\n" % (
746 arg[1], arg[0]))
Daniel Veillard61006472002-01-21 17:31:47 +0000747 output.write(" </%s>\n" % (type));
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000748 elif type == 'macro':
Daniel Veillard9d06d302002-01-22 18:15:52 +0000749 output.write(">\n");
750 if macros[i][1] != None and macros[i][1] != '':
751 output.write(" <info>%s</info>\n" % (escape(macros[i][1])))
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000752 else:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000753 print "Description for %s is missing" % (i)
754 args = macros[i][0]
755 for arg in args:
756 if arg[1] != None and arg[1] != '':
757 output.write(" <arg name='%s' info='%s'/>\n" %
758 (arg[0], escape(arg[1])))
759 else:
760 print "Description for %s on %s is missing" % (arg[1], i)
761 output.write(" <arg name='%s'/>\n" % (arg[0]))
762 output.write(" </%s>\n" % (type));
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000763 elif type == 'struct':
764 if structs[i] != None and structs[i] != '':
765 output.write(" info='%s'/>\n" % (escape(structs[i])))
766 else:
767 output.write("/>\n");
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000768 elif type == 'variable':
Daniel Veillard9d06d302002-01-22 18:15:52 +0000769 if variables[i][1] != None and variables[i][1] != '':
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000770 output.write(" info='%s'/>\n" % (escape(variables[i])))
771 else:
772 output.write("/>\n");
773 elif type == 'typedef':
774 if typedefs[i] != None and typedefs[i] != '':
775 output.write(" info='%s'/>\n" % (escape(typedefs[i])))
776 else:
777 output.write("/>\n");
Daniel Veillard61006472002-01-21 17:31:47 +0000778 else:
779 output.write("/>\n");
780 else:
781 print "Symbol %s not found in identifiers list" % (i)
782output.write(" </symbols>\n")
783output.write("</api>\n")
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000784output.close()
Daniel Veillard61006472002-01-21 17:31:47 +0000785print "generated XML for %d symbols" % (len(symbols))
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000786
787##################################################################
788#
789# Saving: libxml2-api.xml
790#
791##################################################################
792
793hash = {}
794for file in files.keys():
795 for symbol in files[file]:
796 hash[symbol] = file
797
798def link(id):
799 if ids.has_key(id):
800 target = string.upper(ids[id])
801 else:
802 target = string.upper(id)
Daniel Veillard5f4b5992002-02-20 10:22:49 +0000803 if hash.has_key(id):
804 module = string.lower(hash[id])
805 else:
806 module = 'index'
807 file = 'html/libxml-' + module + '.html';
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000808 return file + '#' + target
809
810print "Saving XML crossreferences libxml2-refs.xml"
811output = open("libxml2-refs.xml", "w")
Daniel Veillardf8592562002-01-23 17:58:17 +0000812output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000813output.write("<apirefs name='libxml2'>\n")
814output.write(" <references>\n")
815typ = ids.keys()
816typ.sort()
817for id in typ:
818 output.write(" <reference name='%s' href='%s'/>\n" % (id, link(id)))
819output.write(" </references>\n")
820output.write(" <alpha>\n")
821letter = None
822ids = ids.keys()
823ids.sort()
824for id in ids:
825 if id[0] != letter:
826 if letter != None:
827 output.write(" </letter>\n")
828 letter = id[0]
829 output.write(" <letter name='%s'>\n" % (letter))
830 output.write(" <ref name='%s'/>\n" % (id))
831if letter != None:
832 output.write(" </letter>\n")
833output.write(" </alpha>\n")
834output.write(" <constructors>\n")
835typ = ret_types.keys()
836typ.sort()
837for type in typ:
838 if type == '' or type == 'void' or type == "int" or type == "char *" or \
839 type == "const char *" :
840 continue
841 output.write(" <type name='%s'>\n" % (type))
842 ids = ret_types[type]
843 for id in ids:
844 output.write(" <ref name='%s'/>\n" % (id))
845 output.write(" </type>\n")
846output.write(" </constructors>\n")
847output.write(" <functions>\n")
848typ = types.keys()
849typ.sort()
850for type in typ:
851 if type == '' or type == 'void' or type == "int" or type == "char *" or \
852 type == "const char *" :
853 continue
854 output.write(" <type name='%s'>\n" % (type))
855 ids = types[type]
856 for id in ids:
857 output.write(" <ref name='%s'/>\n" % (id))
858 output.write(" </type>\n")
859output.write(" </functions>\n")
860
861output.write(" <files>\n")
862typ = files.keys()
863typ.sort()
864for file in typ:
865 output.write(" <file name='%s'>\n" % (file))
866 for id in files[file]:
867 output.write(" <ref name='%s'/>\n" % (id))
868 output.write(" </file>\n")
869output.write(" </files>\n")
Daniel Veillardf8592562002-01-23 17:58:17 +0000870
871output.write(" <index>\n")
872typ = index.keys()
873typ.sort()
874letter = None
875count = 0
876chunk = 0
877chunks = []
878for id in typ:
879 if len(index[id]) > 30:
880 continue
881 if id[0] != letter:
882 if letter == None or count > 200:
883 if letter != None:
884 output.write(" </letter>\n")
885 output.write(" </chunk>\n")
886 count = 0
887 chunks.append(["chunk%s" % (chunk -1), first_letter, letter])
888 output.write(" <chunk name='chunk%s'>\n" % (chunk))
889 first_letter = id[0]
890 chunk = chunk + 1
891 elif letter != None:
892 output.write(" </letter>\n")
893 letter = id[0]
894 output.write(" <letter name='%s'>\n" % (letter))
895 output.write(" <word name='%s'>\n" % (id))
896 tokens = index[id];
897 tokens.sort()
898 tok = None
899 for token in index[id]:
900 if tok == token:
901 continue
902 tok = token
903 output.write(" <ref name='%s'/>\n" % (token))
904 count = count + 1
905 output.write(" </word>\n")
906if letter != None:
907 output.write(" </letter>\n")
908 output.write(" </chunk>\n")
909 output.write(" <chunks>\n")
910 for ch in chunks:
911 output.write(" <chunk name='%s' start='%s' end='%s'/>\n" % (
912 ch[0], ch[1], ch[2]))
913 output.write(" </chunks>\n")
914output.write(" </index>\n")
915
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000916output.write("</apirefs>\n")
917output.close()