blob: 074a808ef2379a2adcfe0070cc4aff62945321c2 [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):
35 str = string.replace(str, "'", ' ')
36 str = string.replace(str, '"', ' ')
37 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 tokens = string.split(str)
51 for token in tokens:
52 try:
53 c = token[0]
54 if string.find(string.letters, c) < 0:
55 pass
56 elif len(token) < 3:
57 pass
58 else:
59 lower = string.lower(token)
60 # TODO: generalize this a bit
61 if lower == 'and' or lower == 'the':
62 pass
63 elif index.has_key(token):
64 index[token].append(id)
65 else:
66 index[token] = [id]
67 except:
68 pass
69
70
71
72##################################################################
73#
Daniel Veillard2d1464f2002-01-21 23:16:56 +000074# Parsing: libxml-decl.txt
75#
76##################################################################
Daniel Veillard61006472002-01-21 17:31:47 +000077def mormalizeTypeSpaces(raw, function):
78 global types
79
80 tokens = string.split(raw)
81 type = ''
82 for token in tokens:
83 if type != '':
84 type = type + ' ' + token
85 else:
86 type = token
87 if types.has_key(type):
88 types[type].append(function)
89 else:
90 types[type] = [function]
91 return type
92
93def removeComments(raw):
94 while string.find(raw, '/*') > 0:
95 e = string.find(raw, '/*')
96 tmp = raw[0:e]
97 raw = raw[e:]
98 e = string.find(raw, '*/')
99 if e > 0:
100 raw = tmp + raw[e + 2:]
101 else:
102 raw = tmp
103 return raw
104
105def extractArgs(raw, function):
106 raw = removeComments(raw)
Daniel Veillard9d06d302002-01-22 18:15:52 +0000107 raw = string.replace(raw, '\n', ' ')
108 raw = string.replace(raw, '\r', ' ')
Daniel Veillard61006472002-01-21 17:31:47 +0000109 list = string.split(raw, ",")
110 ret = []
111 for arg in list:
112 i = len(arg)
113 if i == 0:
114 continue
115 i = i - 1
116 c = arg[i]
117 while string.find(string.letters, c) >= 0 or \
Daniel Veillard9d06d302002-01-22 18:15:52 +0000118 string.find(string.digits, c) >= 0 or c == '_':
Daniel Veillard61006472002-01-21 17:31:47 +0000119 i = i - 1
120 if i < 0:
121 break
122 c = arg[i]
123 name = arg[i+1:]
124 while string.find(string.whitespace, c) >= 0:
125 i = i - 1
126 if i < 0:
127 break
128 c = arg[i]
129 type = mormalizeTypeSpaces(arg[0:i+1], function)
Daniel Veillard9d06d302002-01-22 18:15:52 +0000130 if name == 'void' and type == '':
131 pass
132 else:
133 ret.append([type, name, ''])
134
Daniel Veillard61006472002-01-21 17:31:47 +0000135 return ret
136
137def extractTypes(raw, function):
138 global ret_types
139
140 tokens = string.split(raw)
141 type = ''
142 for token in tokens:
143 if type != '':
144 type = type + ' ' + token
145 else:
146 type = token
147 if ret_types.has_key(type):
148 ret_types[type].append(function)
149 else:
150 ret_types[type] = [function]
Daniel Veillard9d06d302002-01-22 18:15:52 +0000151
Daniel Veillard61006472002-01-21 17:31:47 +0000152 return type
153
154def parseMacro():
155 global input
156 global macros
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000157 global variables
Daniel Veillard61006472002-01-21 17:31:47 +0000158
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000159 var = 1
Daniel Veillard61006472002-01-21 17:31:47 +0000160 line = input.readline()[:-1]
161 while line != "</MACRO>":
162 if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
163 name = line[6:-7]
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000164 elif string.find(line, "#define") >= 0:
165 var = 0
Daniel Veillard61006472002-01-21 17:31:47 +0000166 line = input.readline()[:-1]
167
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000168 if var == 1:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000169 variables[name] = ['', ''] # type, info
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000170 identifiers_type[name] = "variable"
171 else:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000172 macros[name] = [[], ''] # args, info
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000173 identifiers_type[name] = "macro"
Daniel Veillard61006472002-01-21 17:31:47 +0000174
175def parseStruct():
176 global input
177 global structs
178
179 line = input.readline()[:-1]
180 while line != "</STRUCT>":
181 if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
182 name = line[6:-7]
183 line = input.readline()[:-1]
184
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000185 structs[name] = ''
Daniel Veillard61006472002-01-21 17:31:47 +0000186 identifiers_type[name] = "struct"
187
188def parseTypedef():
189 global input
190 global typedefs
191
192 line = input.readline()[:-1]
193 while line != "</TYPEDEF>":
194 if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
195 name = line[6:-7]
196 line = input.readline()[:-1]
197
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000198 typedefs[name] = ''
Daniel Veillard61006472002-01-21 17:31:47 +0000199 identifiers_type[name] = "typedef"
200
201def parseEnum():
202 global input
203 global enums
204
205 line = input.readline()[:-1]
206 consts = []
207 while line != "</ENUM>":
208 if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
209 name = line[6:-7]
210 elif string.find(line, 'enum') >= 0:
211 pass
212 elif string.find(line, '{') >= 0:
213 pass
214 elif string.find(line, '}') >= 0:
215 pass
216 elif string.find(line, ';') >= 0:
217 pass
218 else:
219 comment = string.find(line, '/*')
220 if comment >= 0:
221 line = line[0:comment]
222 decls = string.split(line, ",")
223 for decl in decls:
224 val = string.split(decl, "=")[0]
225 tokens = string.split(val)
226 if len(tokens) >= 1:
227 token = tokens[0]
228 if string.find(string.letters, token[0]) >= 0:
229 consts.append(token)
230 identifiers_type[token] = "const"
231 line = input.readline()[:-1]
232
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000233 enums[name] = [consts, '']
Daniel Veillard61006472002-01-21 17:31:47 +0000234 identifiers_type[name] = "enum"
235
236def parseStaticFunction():
237 global input
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000238 global user_functions
Daniel Veillard61006472002-01-21 17:31:47 +0000239
240 line = input.readline()[:-1]
241 type = None
Daniel Veillard9d06d302002-01-22 18:15:52 +0000242 signature = ""
Daniel Veillard61006472002-01-21 17:31:47 +0000243 while line != "</USER_FUNCTION>":
244 if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
245 name = line[6:-7]
246 elif line[0:9] == "<RETURNS>" and line[-10:] == "</RETURNS>":
247 type = extractTypes(line[9:-10], name)
248 else:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000249 signature = signature + line
Daniel Veillard61006472002-01-21 17:31:47 +0000250 line = input.readline()[:-1]
251
252 args = extractArgs(signature, name)
Daniel Veillard9d06d302002-01-22 18:15:52 +0000253 user_functions[name] = [[type, ''] , args, '']
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000254 identifiers_type[name] = "functype"
Daniel Veillard61006472002-01-21 17:31:47 +0000255
256def parseFunction():
257 global input
258 global functions
259
260 line = input.readline()[:-1]
261 type = None
Daniel Veillard9d06d302002-01-22 18:15:52 +0000262 signature = ""
Daniel Veillard61006472002-01-21 17:31:47 +0000263 while line != "</FUNCTION>":
264 if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
265 name = line[6:-7]
266 elif line[0:9] == "<RETURNS>" and line[-10:] == "</RETURNS>":
267 type = extractTypes(line[9:-10], name)
268 else:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000269 signature = signature + line
Daniel Veillard61006472002-01-21 17:31:47 +0000270 line = input.readline()[:-1]
271
272 args = extractArgs(signature, name)
Daniel Veillard9d06d302002-01-22 18:15:52 +0000273 functions[name] = [[type, ''] , args, '']
Daniel Veillard61006472002-01-21 17:31:47 +0000274 identifiers_type[name] = "function"
275
Daniel Veillard61006472002-01-21 17:31:47 +0000276print "Parsing: libxml-decl.txt"
277input = open('libxml-decl.txt')
278while 1:
279 line = input.readline()
280 if not line:
281 break
282 line = line[:-1]
283 if line == "<MACRO>":
284 parseMacro()
285 elif line == "<ENUM>":
286 parseEnum()
287 elif line == "<FUNCTION>":
288 parseFunction()
289 elif line == "<STRUCT>":
290 parseStruct()
291 elif line == "<TYPEDEF>":
292 parseTypedef()
293 elif line == "<USER_FUNCTION>":
294 parseStaticFunction()
295 elif len(line) >= 1 and line[0] == "<":
296 print "unhandled %s" % (line)
297
298print "Parsed: %d macros. %d structs, %d typedefs, %d enums" % (
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000299 len(macros.keys()), len(structs.keys()), len(typedefs.keys()),
300 len(enums))
Daniel Veillard61006472002-01-21 17:31:47 +0000301c = 0
302for enum in enums.keys():
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000303 consts = enums[enum][0]
Daniel Veillard61006472002-01-21 17:31:47 +0000304 c = c + len(consts)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000305print " %d variables, %d constants, %d functions and %d functypes" % (
306 len(variables.keys()), c, len(functions.keys()),
307 len(user_functions.keys()))
Daniel Veillard61006472002-01-21 17:31:47 +0000308print "The functions manipulates %d different types" % (len(types.keys()))
309print "The functions returns %d different types" % (len(ret_types.keys()))
310
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000311##################################################################
312#
313# Parsing: libxml-decl-list.txt
314#
315##################################################################
316def parseSection():
317 global input
318 global sections
319 global files
320 global identifiers_file
321
322 tokens = []
323 line = input.readline()[:-1]
324 while line != "</SECTION>":
325 if line[0:6] == "<FILE>" and line[-7:] == "</FILE>":
326 name = line[6:-7]
327 elif len(line) > 0:
328 tokens.append(line)
329 line = input.readline()[:-1]
330
331 sections.append(name)
332 files[name] = tokens
333 for token in tokens:
334 identifiers_file[token] = name
335 #
336 # Small transitivity for enum values
337 #
338 if enums.has_key(token):
339 for const in enums[token][0]:
340 identifiers_file[const] = name
341
Daniel Veillard61006472002-01-21 17:31:47 +0000342print "Parsing: libxml-decl-list.txt"
343input = open('libxml-decl-list.txt')
344while 1:
345 line = input.readline()
346 if not line:
347 break
348 line = line[:-1]
349 if line == "<SECTION>":
350 parseSection()
351 elif len(line) >= 1 and line[0] == "<":
352 print "unhandled %s" % (line)
353
354print "Parsed: %d files %d identifiers" % (len(files), len(identifiers_file.keys()))
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000355##################################################################
356#
357# Parsing: xml/*.xml
358# To enrich the existing info with extracted comments
359#
360##################################################################
361
362nbcomments = 0
363
Daniel Veillard9d06d302002-01-22 18:15:52 +0000364def insertParameterComment(id, name, value, is_param):
365 global nbcomments
366
Daniel Veillardf8592562002-01-23 17:58:17 +0000367 indexString(id, value)
Daniel Veillard9d06d302002-01-22 18:15:52 +0000368 if functions.has_key(id):
369 if is_param == 1:
370 args = functions[id][1]
371 found = 0
372 for arg in args:
373 if arg[1] == name:
374 arg[2] = value
375 found = 1
376 break
377 if found == 0 and name != '...':
378 print "Arg %s not found on function %s description" % (name, id)
379 return
380 else:
381 ret = functions[id][0]
382 ret[1] = value
383 elif user_functions.has_key(id):
384 if is_param == 1:
385 args = user_functions[id][1]
386 found = 0
387 for arg in args:
388 if arg[1] == name:
389 arg[2] = value
390 found = 1
391 break
392 if found == 0 and name != '...':
393 print "Arg %s not found on functype %s description" % (name, id)
394 print args
395 return
396 else:
397 ret = user_functions[id][0]
398 ret[1] = value
399 elif macros.has_key(id):
400 if is_param == 1:
401 args = macros[id][0]
402 found = 0
403 for arg in args:
404 if arg[0] == name:
405 arg[1] = value
406 found = 1
407 break
408 if found == 0:
409 args.append([name, value])
410 else:
411 print "Return info for macro %s: %s" % (id, value)
412# ret = macros[id][0]
413# ret[1] = value
414 else:
415 print "lost specific comment %s: %s: %s" % (id, name, value)
416 return
417 nbcomments = nbcomments + 1
418
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000419def insertComment(name, title, value, id):
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000420 global nbcomments
421
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000422 ids[name] = id
Daniel Veillardf8592562002-01-23 17:58:17 +0000423 indexString(name, value)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000424 if functions.has_key(name):
425 functions[name][2] = value
Daniel Veillard9d06d302002-01-22 18:15:52 +0000426 return "function"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000427 elif typedefs.has_key(name):
428 typedefs[name] = value
Daniel Veillard9d06d302002-01-22 18:15:52 +0000429 return "typedef"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000430 elif macros.has_key(name):
Daniel Veillard9d06d302002-01-22 18:15:52 +0000431 macros[name][1] = value
432 return "macro"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000433 elif variables.has_key(name):
Daniel Veillard9d06d302002-01-22 18:15:52 +0000434 variables[name][1] = value
435 return "variable"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000436 elif structs.has_key(name):
437 structs[name] = value
Daniel Veillard9d06d302002-01-22 18:15:52 +0000438 return "struct"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000439 elif enums.has_key(name):
440 enums[name][1] = value
Daniel Veillard9d06d302002-01-22 18:15:52 +0000441 return "enum"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000442 elif user_functions.has_key(name):
Daniel Veillard9d06d302002-01-22 18:15:52 +0000443 user_functions[name][2] = value
444 return "user_function"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000445 else:
446 print "lost comment %s: %s" % (name, value)
Daniel Veillard9d06d302002-01-22 18:15:52 +0000447 return "unknown"
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000448 nbcomments = nbcomments + 1
449
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000450
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000451import os
452import xmllib
453try:
454 import sgmlop
455except ImportError:
456 sgmlop = None # accelerator not available
457
458debug = 0
459
460if sgmlop:
461 class FastParser:
462 """sgmlop based XML parser. this is typically 15x faster
463 than SlowParser..."""
464
465 def __init__(self, target):
466
467 # setup callbacks
468 self.finish_starttag = target.start
469 self.finish_endtag = target.end
470 self.handle_data = target.data
471
472 # activate parser
473 self.parser = sgmlop.XMLParser()
474 self.parser.register(self)
475 self.feed = self.parser.feed
476 self.entity = {
477 "amp": "&", "gt": ">", "lt": "<",
478 "apos": "'", "quot": '"'
479 }
480
481 def close(self):
482 try:
483 self.parser.close()
484 finally:
485 self.parser = self.feed = None # nuke circular reference
486
487 def handle_entityref(self, entity):
488 # <string> entity
489 try:
490 self.handle_data(self.entity[entity])
491 except KeyError:
492 self.handle_data("&%s;" % entity)
493
494else:
495 FastParser = None
496
497
498class SlowParser(xmllib.XMLParser):
499 """slow but safe standard parser, based on the XML parser in
500 Python's standard library."""
501
502 def __init__(self, target):
503 self.unknown_starttag = target.start
504 self.handle_data = target.data
505 self.unknown_endtag = target.end
506 xmllib.XMLParser.__init__(self)
507
508def getparser(target = None):
509 # get the fastest available parser, and attach it to an
510 # unmarshalling object. return both objects.
511 if target == None:
512 target = docParser()
513 if FastParser:
514 return FastParser(target), target
515 return SlowParser(target), target
516
517class docParser:
518 def __init__(self):
519 self._methodname = None
520 self._data = []
521 self.id = None
522 self.title = None
523 self.descr = None
524 self.string = None
525
526 def close(self):
527 if debug:
528 print "close"
529
530 def getmethodname(self):
531 return self._methodname
532
533 def data(self, text):
534 if debug:
535 print "data %s" % text
536 self._data.append(text)
537
538 def start(self, tag, attrs):
539 if debug:
540 print "start %s, %s" % (tag, attrs)
541 if tag == 'refsect2':
542 self.id = None
543 self.title = None
544 self.descr = None
545 self.string = None
Daniel Veillard9d06d302002-01-22 18:15:52 +0000546 self.type = None
547 self.in_parameter = 0
548 self.is_parameter = 0
549 self.parameter = None
550 self.parameter_info = None
551 self.entry = 0
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000552 elif tag == 'para':
553 self._data = []
554 elif tag == 'title':
555 self._data = []
Daniel Veillard9d06d302002-01-22 18:15:52 +0000556 elif tag == 'tgroup':
557 self.in_parameter = 1
558 elif tag == 'row':
559 self._data = []
560 self.entry = 0
561 elif tag == 'entry':
562 self.entry = self.entry + 1
563 elif tag == 'parameter' and self.in_parameter == 1:
564 self._data = []
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000565 elif tag == 'anchor' and self.id == None:
566 if attrs.has_key('id'):
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000567 self.orig_id = attrs['id']
568 self.id = string.replace(self.orig_id, '-CAPS', '')
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000569 self.id = string.replace(self.id, '-', '_')
570
571 def end(self, tag):
572 if debug:
573 print "end %s" % tag
574 if tag == 'refsect2':
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000575 self.type = insertComment(self.id, self.title, self.string,
576 self.orig_id)
Daniel Veillard9d06d302002-01-22 18:15:52 +0000577 self.string = None
578 elif tag == 'row':
579 if self.parameter_info != None and self.parameter_info != '':
580 insertParameterComment(self.id, self.parameter,
581 self.parameter_info, self.is_parameter)
582 self.parameter_info = None
583 self.parameter = 0
584 self.is_parameter = 0
585 elif tag == 'parameter' and self.in_parameter == 1 and self.entry == 1:
586 str = ''
587 for c in self._data:
588 str = str + c
589 str = string.replace(str, '\n', ' ')
590 str = string.replace(str, '\r', ' ')
591 str = string.replace(str, ' ', ' ')
592 str = string.replace(str, ' ', ' ')
593 str = string.replace(str, ' ', ' ')
594 while len(str) >= 1 and str[0] == ' ':
595 str=str[1:]
596 self.parameter = str
597 self.is_parameter = 1
598 self._data = []
599 elif tag == 'para' or tag == 'entry':
600 str = ''
601 for c in self._data:
602 str = str + c
603 str = string.replace(str, '\n', ' ')
604 str = string.replace(str, '\r', ' ')
605 str = string.replace(str, ' ', ' ')
606 str = string.replace(str, ' ', ' ')
607 str = string.replace(str, ' ', ' ')
608 while len(str) >= 1 and str[0] == ' ':
609 str=str[1:]
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000610 if self.string == None:
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000611 self.string = str
Daniel Veillard9d06d302002-01-22 18:15:52 +0000612 elif self.in_parameter == 1:
613 self.parameter_info = str
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000614 self._data = []
615 elif tag == 'title':
616 str = ''
617 for c in self._data:
618 str = str + c
619 str = string.replace(str, '\n', ' ')
620 str = string.replace(str, '\r', ' ')
621 str = string.replace(str, ' ', ' ')
622 str = string.replace(str, ' ', ' ')
623 str = string.replace(str, ' ', ' ')
624 while len(str) >= 1 and str[0] == ' ':
625 str=str[1:]
626 self.title = str
627
628xmlfiles = 0
629filenames = os.listdir("xml")
630for filename in filenames:
631 try:
632 f = open("xml/" + filename, 'r')
633 except IOError, msg:
634 print file, ":", msg
635 continue
636 data = f.read()
637 (parser, target) = getparser()
638 parser.feed(data)
639 parser.close()
640 xmlfiles = xmlfiles + 1
641
642print "Parsed: %d XML files collexting %d comments" % (xmlfiles, nbcomments)
643
644##################################################################
645#
646# Saving: libxml2-api.xml
647#
648##################################################################
649
650def escape(raw):
Daniel Veillard9d06d302002-01-22 18:15:52 +0000651 raw = string.replace(raw, '&', '&amp;')
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000652 raw = string.replace(raw, '<', '&lt;')
653 raw = string.replace(raw, '>', '&gt;')
Daniel Veillard9d06d302002-01-22 18:15:52 +0000654 raw = string.replace(raw, "'", '&apos;')
655 raw = string.replace(raw, '"', '&quot;')
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000656 return raw
Daniel Veillard61006472002-01-21 17:31:47 +0000657
658print "Saving XML description libxml2-api.xml"
659output = open("libxml2-api.xml", "w")
Daniel Veillardf8592562002-01-23 17:58:17 +0000660output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
Daniel Veillard61006472002-01-21 17:31:47 +0000661output.write("<api name='libxml2'>\n")
662output.write(" <files>\n")
663for file in files.keys():
664 output.write(" <file name='%s'>\n" % file)
665 for symbol in files[file]:
666 output.write(" <exports symbol='%s'/>\n" % (symbol))
667 output.write(" </file>\n")
668output.write(" </files>\n")
669
670output.write(" <symbols>\n")
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000671symbols=macros.keys()
672for i in structs.keys(): symbols.append(i)
673for i in variables.keys(): variables.append(i)
674for i in typedefs.keys(): symbols.append(i)
Daniel Veillard61006472002-01-21 17:31:47 +0000675for i in enums.keys():
676 symbols.append(i)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000677 for j in enums[i][0]:
Daniel Veillard61006472002-01-21 17:31:47 +0000678 symbols.append(j)
679for i in functions.keys(): symbols.append(i)
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000680for i in user_functions.keys(): symbols.append(i)
Daniel Veillard61006472002-01-21 17:31:47 +0000681symbols.sort()
682prev = None
683for i in symbols:
684 if i == prev:
685# print "Symbol %s redefined" % (i)
686 continue
687 else:
688 prev = i
689 if identifiers_type.has_key(i):
690 type = identifiers_type[i]
691
692 if identifiers_file.has_key(i):
693 file = identifiers_file[i]
694 else:
695 file = None
696
697 output.write(" <%s name='%s'" % (type, i))
698 if file != None:
699 output.write(" file='%s'" % (file))
700 if type == "function":
701 output.write(">\n");
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000702 (ret, args, doc) = functions[i]
703 if doc != None and doc != '':
704 output.write(" <info>%s</info>\n" % (escape(doc)))
Daniel Veillard9d06d302002-01-22 18:15:52 +0000705 if ret[1] != None and ret[1] != '':
706 output.write(" <return type='%s' info='%s'/>\n" % (
707 ret[0], escape(ret[1])))
708 else:
709 if ret[0] != 'void' and\
710 ret[0][0:4] != 'void': # This one is actually a bug in GTK Doc
711 print "Description for return on %s is missing" % (i)
712 output.write(" <return type='%s'/>\n" % (ret[0]))
Daniel Veillard61006472002-01-21 17:31:47 +0000713 for arg in args:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000714 if arg[2] != None and arg[2] != '':
715 output.write(" <arg name='%s' type='%s' info='%s'/>\n" %
716 (arg[1], arg[0], escape(arg[2])))
717 else:
718 if arg[0] != '...':
719 print "Description for %s on %s is missing" % (arg[1], i)
720 output.write(" <arg name='%s' type='%s'/>\n" % (
721 arg[1], arg[0]))
722 output.write(" </%s>\n" % (type));
723 elif type == 'functype':
724 output.write(">\n");
725 (ret, args, doc) = user_functions[i]
726 if doc != None and doc != '':
727 output.write(" <info>%s</info>\n" % (escape(doc)))
728 if ret[1] != None and ret[1] != '':
729 output.write(" <return type='%s' info='%s'/>\n" % (
730 ret[0], escape(ret[1])))
731 else:
732 if ret[0] != 'void' and\
733 ret[0][0:4] != 'void': # This one is actually a bug in GTK Doc
734 print "Description for return on %s is missing" % (i)
735 output.write(" <return type='%s'/>\n" % (ret[0]))
736 for arg in args:
737 if arg[2] != None and arg[2] != '':
738 output.write(" <arg name='%s' type='%s' info='%s'/>\n" %
739 (arg[1], arg[0], escape(arg[2])))
740 else:
741 if arg[0] != '...':
742 print "Description for %s on %s is missing" % (arg[1], i)
743 output.write(" <arg name='%s' type='%s'/>\n" % (
744 arg[1], arg[0]))
Daniel Veillard61006472002-01-21 17:31:47 +0000745 output.write(" </%s>\n" % (type));
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000746 elif type == 'macro':
Daniel Veillard9d06d302002-01-22 18:15:52 +0000747 output.write(">\n");
748 if macros[i][1] != None and macros[i][1] != '':
749 output.write(" <info>%s</info>\n" % (escape(macros[i][1])))
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000750 else:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000751 print "Description for %s is missing" % (i)
752 args = macros[i][0]
753 for arg in args:
754 if arg[1] != None and arg[1] != '':
755 output.write(" <arg name='%s' info='%s'/>\n" %
756 (arg[0], escape(arg[1])))
757 else:
758 print "Description for %s on %s is missing" % (arg[1], i)
759 output.write(" <arg name='%s'/>\n" % (arg[0]))
760 output.write(" </%s>\n" % (type));
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000761 elif type == 'struct':
762 if structs[i] != None and structs[i] != '':
763 output.write(" info='%s'/>\n" % (escape(structs[i])))
764 else:
765 output.write("/>\n");
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000766 elif type == 'variable':
Daniel Veillard9d06d302002-01-22 18:15:52 +0000767 if variables[i][1] != None and variables[i][1] != '':
Daniel Veillard2d1464f2002-01-21 23:16:56 +0000768 output.write(" info='%s'/>\n" % (escape(variables[i])))
769 else:
770 output.write("/>\n");
771 elif type == 'typedef':
772 if typedefs[i] != None and typedefs[i] != '':
773 output.write(" info='%s'/>\n" % (escape(typedefs[i])))
774 else:
775 output.write("/>\n");
Daniel Veillard61006472002-01-21 17:31:47 +0000776 else:
777 output.write("/>\n");
778 else:
779 print "Symbol %s not found in identifiers list" % (i)
780output.write(" </symbols>\n")
781output.write("</api>\n")
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000782output.close()
Daniel Veillard61006472002-01-21 17:31:47 +0000783print "generated XML for %d symbols" % (len(symbols))
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000784
785##################################################################
786#
787# Saving: libxml2-api.xml
788#
789##################################################################
790
791hash = {}
792for file in files.keys():
793 for symbol in files[file]:
794 hash[symbol] = file
795
796def link(id):
797 if ids.has_key(id):
798 target = string.upper(ids[id])
799 else:
800 target = string.upper(id)
801 file = 'html/libxml-' + string.lower(hash[id]) + '.html';
802 return file + '#' + target
803
804print "Saving XML crossreferences libxml2-refs.xml"
805output = open("libxml2-refs.xml", "w")
Daniel Veillardf8592562002-01-23 17:58:17 +0000806output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000807output.write("<apirefs name='libxml2'>\n")
808output.write(" <references>\n")
809typ = ids.keys()
810typ.sort()
811for id in typ:
812 output.write(" <reference name='%s' href='%s'/>\n" % (id, link(id)))
813output.write(" </references>\n")
814output.write(" <alpha>\n")
815letter = None
816ids = ids.keys()
817ids.sort()
818for id in ids:
819 if id[0] != letter:
820 if letter != None:
821 output.write(" </letter>\n")
822 letter = id[0]
823 output.write(" <letter name='%s'>\n" % (letter))
824 output.write(" <ref name='%s'/>\n" % (id))
825if letter != None:
826 output.write(" </letter>\n")
827output.write(" </alpha>\n")
828output.write(" <constructors>\n")
829typ = ret_types.keys()
830typ.sort()
831for type in typ:
832 if type == '' or type == 'void' or type == "int" or type == "char *" or \
833 type == "const char *" :
834 continue
835 output.write(" <type name='%s'>\n" % (type))
836 ids = ret_types[type]
837 for id in ids:
838 output.write(" <ref name='%s'/>\n" % (id))
839 output.write(" </type>\n")
840output.write(" </constructors>\n")
841output.write(" <functions>\n")
842typ = types.keys()
843typ.sort()
844for type in typ:
845 if type == '' or type == 'void' or type == "int" or type == "char *" or \
846 type == "const char *" :
847 continue
848 output.write(" <type name='%s'>\n" % (type))
849 ids = types[type]
850 for id in ids:
851 output.write(" <ref name='%s'/>\n" % (id))
852 output.write(" </type>\n")
853output.write(" </functions>\n")
854
855output.write(" <files>\n")
856typ = files.keys()
857typ.sort()
858for file in typ:
859 output.write(" <file name='%s'>\n" % (file))
860 for id in files[file]:
861 output.write(" <ref name='%s'/>\n" % (id))
862 output.write(" </file>\n")
863output.write(" </files>\n")
Daniel Veillardf8592562002-01-23 17:58:17 +0000864
865output.write(" <index>\n")
866typ = index.keys()
867typ.sort()
868letter = None
869count = 0
870chunk = 0
871chunks = []
872for id in typ:
873 if len(index[id]) > 30:
874 continue
875 if id[0] != letter:
876 if letter == None or count > 200:
877 if letter != None:
878 output.write(" </letter>\n")
879 output.write(" </chunk>\n")
880 count = 0
881 chunks.append(["chunk%s" % (chunk -1), first_letter, letter])
882 output.write(" <chunk name='chunk%s'>\n" % (chunk))
883 first_letter = id[0]
884 chunk = chunk + 1
885 elif letter != None:
886 output.write(" </letter>\n")
887 letter = id[0]
888 output.write(" <letter name='%s'>\n" % (letter))
889 output.write(" <word name='%s'>\n" % (id))
890 tokens = index[id];
891 tokens.sort()
892 tok = None
893 for token in index[id]:
894 if tok == token:
895 continue
896 tok = token
897 output.write(" <ref name='%s'/>\n" % (token))
898 count = count + 1
899 output.write(" </word>\n")
900if letter != None:
901 output.write(" </letter>\n")
902 output.write(" </chunk>\n")
903 output.write(" <chunks>\n")
904 for ch in chunks:
905 output.write(" <chunk name='%s' start='%s' end='%s'/>\n" % (
906 ch[0], ch[1], ch[2]))
907 output.write(" </chunks>\n")
908output.write(" </index>\n")
909
Daniel Veillard3bf65be2002-01-23 12:36:34 +0000910output.write("</apirefs>\n")
911output.close()