| #!/usr/bin/python -u | 
 | # | 
 | # tries to parse the output of gtk-doc declaration files and make | 
 | # an XML reusable description from them | 
 | # | 
 | import sys | 
 | import string | 
 |  | 
 | ids = {} | 
 |  | 
 | macros = {} | 
 | variables = {} | 
 | structs = {} | 
 | typedefs = {} | 
 | enums = {} | 
 | functions = {} | 
 | user_functions = {} | 
 | ret_types = {} | 
 | types = {} | 
 |  | 
 | sections = [] | 
 | files = {} | 
 | identifiers_file = {} | 
 | identifiers_type = {} | 
 |  | 
 | ################################################################## | 
 | # | 
 | #          Indexer to generate the word index | 
 | # | 
 | ################################################################## | 
 | index = {} | 
 |  | 
 |  | 
 | def indexString(id, str): | 
 |     if str == None: | 
 |         return | 
 |     str = string.replace(str, "'", ' ') | 
 |     str = string.replace(str, '"', ' ') | 
 |     str = string.replace(str, "/", ' ') | 
 |     str = string.replace(str, '*', ' ') | 
 |     str = string.replace(str, "[", ' ') | 
 |     str = string.replace(str, "]", ' ') | 
 |     str = string.replace(str, "(", ' ') | 
 |     str = string.replace(str, ")", ' ') | 
 |     str = string.replace(str, "<", ' ') | 
 |     str = string.replace(str, '>', ' ') | 
 |     str = string.replace(str, "&", ' ') | 
 |     str = string.replace(str, '#', ' ') | 
 |     str = string.replace(str, ",", ' ') | 
 |     str = string.replace(str, '.', ' ') | 
 |     str = string.replace(str, ';', ' ') | 
 |     tokens = string.split(str) | 
 |     for token in tokens: | 
 |         try: | 
 | 	    c = token[0] | 
 | 	    if string.find(string.letters, c) < 0: | 
 | 	        pass | 
 | 	    elif len(token) < 3: | 
 | 		pass | 
 | 	    else: | 
 | 		lower = string.lower(token) | 
 | 		# TODO: generalize this a bit | 
 | 		if lower == 'and' or lower == 'the': | 
 | 		    pass | 
 | 		elif index.has_key(token): | 
 | 		    index[token].append(id) | 
 | 		else: | 
 | 		    index[token] = [id] | 
 | 	except: | 
 | 	    pass | 
 |         | 
 |  | 
 |  | 
 | ################################################################## | 
 | # | 
 | #          Parsing: libxml-decl.txt | 
 | # | 
 | ################################################################## | 
 | def mormalizeTypeSpaces(raw, function): | 
 |     global types | 
 |  | 
 |     tokens = string.split(raw) | 
 |     type = '' | 
 |     for token in tokens: | 
 | 	if type != '': | 
 | 	    type = type + ' ' + token | 
 | 	else: | 
 | 	    type = token | 
 |     if types.has_key(type): | 
 |         types[type].append(function) | 
 |     else: | 
 |         types[type] = [function] | 
 |     return type | 
 |  | 
 | def removeComments(raw): | 
 |     while string.find(raw, '/*') > 0: | 
 |         e = string.find(raw, '/*') | 
 | 	tmp = raw[0:e] | 
 | 	raw = raw[e:] | 
 | 	e = string.find(raw, '*/') | 
 | 	if e > 0: | 
 | 	    raw = tmp + raw[e + 2:] | 
 | 	else: | 
 | 	    raw = tmp | 
 |     return raw | 
 |  | 
 | def extractArgs(raw, function): | 
 |     raw = removeComments(raw) | 
 |     raw = string.replace(raw, '\n', ' ') | 
 |     raw = string.replace(raw, '\r', ' ') | 
 |     list = string.split(raw, ",") | 
 |     ret = [] | 
 |     for arg in list: | 
 |         i = len(arg) | 
 | 	if i == 0: | 
 | 	    continue | 
 | 	i = i - 1 | 
 | 	c = arg[i] | 
 | 	while string.find(string.letters, c) >= 0 or \ | 
 | 	      string.find(string.digits, c) >= 0 or c == '_': | 
 | 	    i = i - 1 | 
 | 	    if i < 0: | 
 | 	        break | 
 | 	    c = arg[i] | 
 | 	name = arg[i+1:] | 
 |         while string.find(string.whitespace, c) >= 0: | 
 | 	    i = i - 1 | 
 | 	    if i < 0: | 
 | 	        break | 
 | 	    c = arg[i] | 
 | 	type = mormalizeTypeSpaces(arg[0:i+1], function) | 
 | 	if name == 'void' and type == '': | 
 | 	    pass | 
 | 	else: | 
 | 	    ret.append([type, name, '']) | 
 |  | 
 |     return ret | 
 |  | 
 | def extractTypes(raw, function): | 
 |     global ret_types | 
 |  | 
 |     tokens = string.split(raw) | 
 |     type = '' | 
 |     for token in tokens: | 
 | 	if type != '': | 
 | 	    type = type + ' ' + token | 
 | 	else: | 
 | 	    type = token | 
 |     if ret_types.has_key(type): | 
 |         ret_types[type].append(function) | 
 |     else: | 
 |         ret_types[type] = [function] | 
 |  | 
 |     return type | 
 |  | 
 | def parseMacro(): | 
 |     global input | 
 |     global macros | 
 |     global variables | 
 |  | 
 |     var = 1 | 
 |     line = input.readline()[:-1] | 
 |     while line != "</MACRO>": | 
 |         if line[0:6] == "<NAME>" and line[-7:] == "</NAME>": | 
 | 	    name = line[6:-7] | 
 | 	elif string.find(line, "#define") >= 0: | 
 | 	    var = 0 | 
 | 	line = input.readline()[:-1] | 
 |  | 
 |     if var == 1: | 
 | 	variables[name] = ['', ''] # type, info | 
 | 	identifiers_type[name] = "variable" | 
 |     else: | 
 | 	macros[name] = [[], ''] # args, info | 
 | 	identifiers_type[name] = "macro" | 
 |  | 
 | def parseStruct(): | 
 |     global input | 
 |     global structs | 
 |  | 
 |     line = input.readline()[:-1] | 
 |     while line != "</STRUCT>": | 
 |         if line[0:6] == "<NAME>" and line[-7:] == "</NAME>": | 
 | 	    name = line[6:-7] | 
 | 	line = input.readline()[:-1] | 
 |  | 
 |     structs[name] = '' | 
 |     identifiers_type[name] = "struct" | 
 |  | 
 | def parseTypedef(): | 
 |     global input | 
 |     global typedefs | 
 |  | 
 |     line = input.readline()[:-1] | 
 |     while line != "</TYPEDEF>": | 
 |         if line[0:6] == "<NAME>" and line[-7:] == "</NAME>": | 
 | 	    name = line[6:-7] | 
 | 	line = input.readline()[:-1] | 
 |  | 
 |     typedefs[name] = '' | 
 |     identifiers_type[name] = "typedef" | 
 |  | 
 | def parseEnum(): | 
 |     global input | 
 |     global enums | 
 |  | 
 |     line = input.readline()[:-1] | 
 |     consts = [] | 
 |     while line != "</ENUM>": | 
 |         if line[0:6] == "<NAME>" and line[-7:] == "</NAME>": | 
 | 	    name = line[6:-7] | 
 | 	elif string.find(line, 'enum') >= 0: | 
 | 	    pass | 
 | 	elif string.find(line, '{') >= 0: | 
 | 	    pass | 
 | 	elif string.find(line, '}') >= 0: | 
 | 	    pass | 
 | 	elif string.find(line, ';') >= 0: | 
 | 	    pass | 
 | 	else: | 
 | 	    comment = string.find(line, '/*') | 
 | 	    if comment >= 0: | 
 | 	        line = line[0:comment] | 
 | 	    decls = string.split(line, ",") | 
 | 	    for decl in decls: | 
 | 		val = string.split(decl, "=")[0] | 
 | 		tokens = string.split(val) | 
 | 		if len(tokens) >= 1: | 
 | 		    token = tokens[0] | 
 | 		    if string.find(string.letters, token[0]) >= 0: | 
 | 			consts.append(token) | 
 | 			identifiers_type[token] = "const" | 
 | 	line = input.readline()[:-1] | 
 |          | 
 |     enums[name] = [consts, ''] | 
 |     identifiers_type[name] = "enum" | 
 |  | 
 | def parseStaticFunction(): | 
 |     global input | 
 |     global user_functions | 
 |  | 
 |     line = input.readline()[:-1] | 
 |     type = None | 
 |     signature = "" | 
 |     while line != "</USER_FUNCTION>": | 
 |         if line[0:6] == "<NAME>" and line[-7:] == "</NAME>": | 
 | 	    name = line[6:-7] | 
 |         elif line[0:9] == "<RETURNS>" and line[-10:] == "</RETURNS>": | 
 | 	    type = extractTypes(line[9:-10], name) | 
 | 	else: | 
 | 	    signature = signature + line | 
 | 	line = input.readline()[:-1] | 
 |  | 
 |     args = extractArgs(signature, name) | 
 |     user_functions[name] = [[type, ''] , args, ''] | 
 |     identifiers_type[name] = "functype" | 
 |  | 
 | def parseFunction(): | 
 |     global input | 
 |     global functions | 
 |  | 
 |     line = input.readline()[:-1] | 
 |     type = None | 
 |     signature = "" | 
 |     while line != "</FUNCTION>": | 
 |         if line[0:6] == "<NAME>" and line[-7:] == "</NAME>": | 
 | 	    name = line[6:-7] | 
 |         elif line[0:9] == "<RETURNS>" and line[-10:] == "</RETURNS>": | 
 | 	    type = extractTypes(line[9:-10], name) | 
 | 	else: | 
 | 	    signature = signature + line | 
 | 	line = input.readline()[:-1] | 
 |  | 
 |     args = extractArgs(signature, name) | 
 |     functions[name] = [[type, ''] , args, ''] | 
 |     identifiers_type[name] = "function" | 
 |  | 
 | print "Parsing: libxml-decl.txt" | 
 | input = open('libxml-decl.txt') | 
 | while 1: | 
 |     line = input.readline() | 
 |     if not line: | 
 |         break | 
 |     line = line[:-1] | 
 |     if line == "<MACRO>": | 
 |         parseMacro() | 
 |     elif line == "<ENUM>": | 
 |         parseEnum() | 
 |     elif line == "<FUNCTION>": | 
 |         parseFunction() | 
 |     elif line == "<STRUCT>": | 
 |         parseStruct() | 
 |     elif line == "<TYPEDEF>": | 
 |         parseTypedef() | 
 |     elif line == "<USER_FUNCTION>": | 
 |         parseStaticFunction() | 
 |     elif len(line) >= 1 and line[0] == "<": | 
 |         print "unhandled %s" % (line) | 
 |  | 
 | print "Parsed: %d macros. %d structs, %d typedefs, %d enums" % ( | 
 |           len(macros.keys()), len(structs.keys()), len(typedefs.keys()), | 
 | 	  len(enums)) | 
 | c = 0 | 
 | for enum in enums.keys(): | 
 |     consts = enums[enum][0] | 
 |     c = c + len(consts) | 
 | print "        %d variables, %d constants, %d functions and %d functypes" % ( | 
 |           len(variables.keys()), c, len(functions.keys()), | 
 | 	  len(user_functions.keys())) | 
 | print "The functions manipulates %d different types" % (len(types.keys())) | 
 | print "The functions returns %d different types" % (len(ret_types.keys())) | 
 |  | 
 | ################################################################## | 
 | # | 
 | #          Parsing: libxml-decl-list.txt | 
 | # | 
 | ################################################################## | 
 | def parseSection(): | 
 |     global input | 
 |     global sections | 
 |     global files | 
 |     global identifiers_file | 
 |  | 
 |     tokens = [] | 
 |     line = input.readline()[:-1] | 
 |     while line != "</SECTION>": | 
 |         if line[0:6] == "<FILE>" and line[-7:] == "</FILE>": | 
 | 	    name = line[6:-7] | 
 | 	elif len(line) > 0: | 
 | 	    tokens.append(line) | 
 | 	line = input.readline()[:-1] | 
 |  | 
 |     sections.append(name) | 
 |     files[name] = tokens | 
 |     for token in tokens: | 
 |         identifiers_file[token] = name | 
 | 	# | 
 | 	# Small transitivity for enum values | 
 | 	# | 
 | 	if enums.has_key(token): | 
 | 	    for const in enums[token][0]: | 
 | 	        identifiers_file[const] = name | 
 |  | 
 | print "Parsing: libxml-decl-list.txt" | 
 | input = open('libxml-decl-list.txt') | 
 | while 1: | 
 |     line = input.readline() | 
 |     if not line: | 
 |         break | 
 |     line = line[:-1] | 
 |     if line == "<SECTION>": | 
 |         parseSection() | 
 |     elif len(line) >= 1 and line[0] == "<": | 
 |         print "unhandled %s" % (line) | 
 |  | 
 | print "Parsed: %d files %d identifiers" % (len(files), len(identifiers_file.keys())) | 
 | ################################################################## | 
 | # | 
 | #          Parsing: xml/*.xml | 
 | #          To enrich the existing info with extracted comments | 
 | # | 
 | ################################################################## | 
 |  | 
 | nbcomments = 0 | 
 |  | 
 | def insertParameterComment(id, name, value, is_param): | 
 |     global nbcomments | 
 |  | 
 |     indexString(id, value) | 
 |     if functions.has_key(id): | 
 |         if is_param == 1: | 
 | 	    args = functions[id][1] | 
 | 	    found = 0 | 
 | 	    for arg in args: | 
 | 		if arg[1] == name: | 
 | 		    arg[2] = value | 
 | 		    found = 1 | 
 | 		    break | 
 | 	    if found == 0 and name != '...': | 
 | 		print "Arg %s not found on function %s description" % (name, id) | 
 | 		return | 
 | 	else: | 
 | 	    ret = functions[id][0] | 
 | 	    ret[1] = value | 
 |     elif user_functions.has_key(id): | 
 |         if is_param == 1: | 
 | 	    args = user_functions[id][1] | 
 | 	    found = 0 | 
 | 	    for arg in args: | 
 | 		if arg[1] == name: | 
 | 		    arg[2] = value | 
 | 		    found = 1 | 
 | 		    break | 
 | 	    if found == 0 and name != '...': | 
 | 		print "Arg %s not found on functype %s description" % (name, id) | 
 | 		print args | 
 | 		return | 
 | 	else: | 
 | 	    ret = user_functions[id][0] | 
 | 	    ret[1] = value | 
 |     elif macros.has_key(id): | 
 |         if is_param == 1: | 
 | 	    args = macros[id][0] | 
 | 	    found = 0 | 
 | 	    for arg in args: | 
 | 		if arg[0] == name: | 
 | 		    arg[1] = value | 
 | 		    found = 1 | 
 | 		    break | 
 | 	    if found == 0: | 
 | 	        args.append([name, value]) | 
 | 	else: | 
 | 	    print "Return info for macro %s: %s" % (id, value) | 
 | #	    ret = macros[id][0] | 
 | #	    ret[1] = value | 
 |     else: | 
 |         print "lost specific comment %s: %s: %s" % (id, name, value) | 
 | 	return | 
 |     nbcomments = nbcomments + 1 | 
 |  | 
 | def insertComment(name, title, value, id): | 
 |     global nbcomments | 
 |  | 
 |     ids[name] = id | 
 |     indexString(name, value) | 
 |     if functions.has_key(name): | 
 |         functions[name][2] = value | 
 | 	return "function" | 
 |     elif typedefs.has_key(name): | 
 |         typedefs[name] = value | 
 | 	return "typedef" | 
 |     elif macros.has_key(name): | 
 |         macros[name][1] = value | 
 | 	return "macro" | 
 |     elif variables.has_key(name): | 
 |         variables[name][1] = value | 
 | 	return "variable" | 
 |     elif structs.has_key(name): | 
 |         structs[name] = value | 
 | 	return "struct" | 
 |     elif enums.has_key(name): | 
 |         enums[name][1] = value | 
 | 	return "enum" | 
 |     elif user_functions.has_key(name): | 
 |         user_functions[name][2] = value | 
 | 	return "user_function" | 
 |     else: | 
 |         print "lost comment %s: %s" % (name, value) | 
 | 	return "unknown" | 
 |     nbcomments = nbcomments + 1 | 
 |  | 
 |  | 
 | import libxml2 | 
 | import os | 
 |  | 
 |  | 
 | def analyzeXMLDescriptionRow(doc, desc, id, row): | 
 |     if doc == None or desc == None or id == None or row == None: | 
 |         return | 
 |     ctxt = doc.xpathNewContext() | 
 |     ctxt.setContextNode(row) | 
 |     param = ctxt.xpathEval("entry[1]/parameter") | 
 |     entries = ctxt.xpathEval("entry") | 
 |     if param == []: | 
 |         is_param = 0 | 
 | 	name = None | 
 |     else: | 
 |         name = param[0].content | 
 | 	is_param = 1 | 
 |     str = entries[1].content | 
 |     str = string.replace(str, '\n', ' ') | 
 |     str = string.replace(str, '\r', ' ') | 
 |     str = string.replace(str, '    ', ' ') | 
 |     str = string.replace(str, '   ', ' ') | 
 |     str = string.replace(str, '  ', ' ') | 
 |     while len(str) >= 1 and str[0] == ' ': | 
 | 	str=str[1:] | 
 |  | 
 |     insertParameterComment(id, name, str, is_param) | 
 |  | 
 |  | 
 |  | 
 | def analyzeXMLDescription(doc, desc): | 
 |     if doc == None or desc == None: | 
 |         return | 
 |     ctxt = doc.xpathNewContext() | 
 |     ctxt.setContextNode(desc) | 
 |  | 
 |     # | 
 |     # get the function name | 
 |     # | 
 |     try: | 
 | 	title = ctxt.xpathEval("title")[0].content | 
 |     except: | 
 |         return | 
 |     old_id = ctxt.xpathEval("string(title/anchor/@id)") | 
 |     id = string.replace(title, '(', ' '); | 
 |     id = string.replace(id, ')', ' '); | 
 |     id = string.split(id) [0] | 
 |  | 
 |     # | 
 |     # get the function comments | 
 |     # | 
 |     comment = "" | 
 |     paras = ctxt.xpathEval("para") | 
 |     for para in paras: | 
 |         str = para.content | 
 | 	str = string.replace(str, '\n', ' ') | 
 | 	str = string.replace(str, '\r', ' ') | 
 | 	str = string.replace(str, '    ', ' ') | 
 | 	str = string.replace(str, '   ', ' ') | 
 | 	str = string.replace(str, '  ', ' ') | 
 | 	while len(str) >= 1 and str[0] == ' ': | 
 | 	    str=str[1:] | 
 |  | 
 |         comment = comment + str | 
 |  | 
 |     insertComment(id, title, comment, old_id) | 
 |  | 
 |     rows = ctxt.xpathEval("informaltable/tgroup/tbody/row") | 
 |     for row in rows: | 
 |         analyzeXMLDescriptionRow(doc, desc, id, row) | 
 |  | 
 | def analyzeXMLDoc(doc): | 
 |     if doc == None: | 
 |         return | 
 |     ctxt = doc.xpathNewContext() | 
 |     descriptions = ctxt.xpathEval("//refsect2") | 
 |     print len(descriptions) | 
 |     for description in descriptions: | 
 |         analyzeXMLDescription(doc, description) | 
 |  | 
 | xmlfiles = 0 | 
 | filenames = os.listdir("xml") | 
 | for filename in filenames: | 
 |     print filename | 
 |     try: | 
 |         doc = libxml2.parseFile("xml/" + filename) | 
 | 	analyzeXMLDoc(doc) | 
 | 	doc.freeDoc() | 
 | 	xmlfiles = xmlfiles + 1 | 
 |     except: | 
 |         print "failed to parse XML description %s" % ("xml/" + filename) | 
 | 	continue | 
 |  | 
 | print "Parsed: %d XML files collexting %d comments" % (xmlfiles, nbcomments) | 
 |  | 
 | ################################################################## | 
 | # | 
 | #          Saving: libxml2-api.xml | 
 | # | 
 | ################################################################## | 
 |  | 
 | def escape(raw): | 
 |     raw = string.replace(raw, '&', '&') | 
 |     raw = string.replace(raw, '<', '<') | 
 |     raw = string.replace(raw, '>', '>') | 
 |     raw = string.replace(raw, "'", ''') | 
 |     raw = string.replace(raw, '"', '"') | 
 |     return raw | 
 |  | 
 | print "Saving XML description libxml2-api.xml" | 
 | output = open("libxml2-api.xml", "w") | 
 | output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n') | 
 | output.write("<api name='libxml2'>\n") | 
 | output.write("  <files>\n") | 
 | for file in files.keys(): | 
 |     output.write("    <file name='%s'>\n" % file) | 
 |     for symbol in files[file]: | 
 |         output.write("     <exports symbol='%s'/>\n" % (symbol)) | 
 |     output.write("    </file>\n") | 
 | output.write("  </files>\n") | 
 |  | 
 | output.write("  <symbols>\n") | 
 | symbols=macros.keys() | 
 | for i in structs.keys(): symbols.append(i) | 
 | for i in variables.keys(): variables.append(i) | 
 | for i in typedefs.keys(): symbols.append(i) | 
 | for i in enums.keys(): | 
 |     symbols.append(i) | 
 |     for j in enums[i][0]: | 
 |         symbols.append(j) | 
 | for i in functions.keys(): symbols.append(i) | 
 | for i in user_functions.keys(): symbols.append(i) | 
 | symbols.sort() | 
 | prev = None | 
 | for i in symbols: | 
 |     if i == prev: | 
 | #        print "Symbol %s redefined" % (i) | 
 | 	continue | 
 |     else: | 
 |         prev = i | 
 |     if identifiers_type.has_key(i): | 
 |         type = identifiers_type[i] | 
 | 	 | 
 |         if identifiers_file.has_key(i): | 
 | 	    file = identifiers_file[i] | 
 | 	else: | 
 | 	    file = None | 
 |  | 
 | 	output.write("    <%s name='%s'" % (type, i)) | 
 | 	if file != None: | 
 | 	    output.write(" file='%s'" % (file)) | 
 | 	if type == "function": | 
 | 	   output.write(">\n"); | 
 | 	   (ret, args, doc) = functions[i] | 
 | 	   if doc != None and doc != '': | 
 | 	       output.write("      <info>%s</info>\n" % (escape(doc))) | 
 | 	   if ret[1] != None and ret[1] != '': | 
 | 	       output.write("      <return type='%s' info='%s'/>\n" % ( | 
 | 	                    ret[0], escape(ret[1]))) | 
 | 	   else: | 
 | 	       if ret[0] != 'void' and\ | 
 | 	          ret[0][0:4] != 'void': # This one is actually a bug in GTK Doc | 
 | 		   print "Description for return on %s is missing" % (i) | 
 | 	       output.write("      <return type='%s'/>\n" % (ret[0])) | 
 | 	   for arg in args: | 
 | 	       if arg[2] != None and arg[2] != '': | 
 | 		   output.write("      <arg name='%s' type='%s' info='%s'/>\n" % | 
 | 		                (arg[1], arg[0], escape(arg[2]))) | 
 | 	       else: | 
 | 	           if arg[0] != '...': | 
 | 		       print "Description for %s on %s is missing" % (arg[1], i) | 
 | 		   output.write("      <arg name='%s' type='%s'/>\n" % ( | 
 | 				arg[1], arg[0])) | 
 | 	   output.write("    </%s>\n" % (type)); | 
 | 	elif type == 'functype': | 
 | 	   output.write(">\n"); | 
 | 	   (ret, args, doc) = user_functions[i] | 
 | 	   if doc != None and doc != '': | 
 | 	       output.write("      <info>%s</info>\n" % (escape(doc))) | 
 | 	   if ret[1] != None and ret[1] != '': | 
 | 	       output.write("      <return type='%s' info='%s'/>\n" % ( | 
 | 	                    ret[0], escape(ret[1]))) | 
 | 	   else: | 
 | 	       if ret[0] != 'void' and\ | 
 | 	          ret[0][0:4] != 'void': # This one is actually a bug in GTK Doc | 
 | 		   print "Description for return on %s is missing" % (i) | 
 | 	       output.write("      <return type='%s'/>\n" % (ret[0])) | 
 | 	   for arg in args: | 
 | 	       if arg[2] != None and arg[2] != '': | 
 | 		   output.write("      <arg name='%s' type='%s' info='%s'/>\n" % | 
 | 		                (arg[1], arg[0], escape(arg[2]))) | 
 | 	       else: | 
 | 	           if arg[0] != '...': | 
 | 		       print "Description for %s on %s is missing" % (arg[1], i) | 
 | 		   output.write("      <arg name='%s' type='%s'/>\n" % ( | 
 | 				arg[1], arg[0])) | 
 | 	   output.write("    </%s>\n" % (type)); | 
 | 	elif type == 'macro': | 
 | 	   output.write(">\n"); | 
 | 	   if macros[i][1] != None and macros[i][1] != '': | 
 | 	       output.write("      <info>%s</info>\n" % (escape(macros[i][1]))) | 
 | 	   else: | 
 | 	       print "Description for %s is missing" % (i) | 
 | 	   args = macros[i][0] | 
 | 	   for arg in args: | 
 | 	       if arg[1] != None and arg[1] != '': | 
 | 		   output.write("      <arg name='%s' info='%s'/>\n" % | 
 | 		                (arg[0], escape(arg[1]))) | 
 | 	       else: | 
 | 	           print "Description for %s on %s is missing" % (arg[1], i) | 
 | 		   output.write("      <arg name='%s'/>\n" % (arg[0])) | 
 | 	   output.write("    </%s>\n" % (type)); | 
 | 	elif type == 'struct': | 
 | 	   if structs[i] != None and structs[i] != '': | 
 | 	       output.write(" info='%s'/>\n" % (escape(structs[i]))) | 
 | 	   else: | 
 | 	       output.write("/>\n"); | 
 | 	elif type == 'variable': | 
 | 	   if variables[i][1] != None and variables[i][1] != '': | 
 | 	       output.write(" info='%s'/>\n" % (escape(variables[i]))) | 
 | 	   else: | 
 | 	       output.write("/>\n"); | 
 | 	elif type == 'typedef': | 
 | 	   if typedefs[i] != None and typedefs[i] != '': | 
 | 	       output.write(" info='%s'/>\n" % (escape(typedefs[i]))) | 
 | 	   else: | 
 | 	       output.write("/>\n"); | 
 | 	else: | 
 | 	   output.write("/>\n"); | 
 |     else: | 
 |         print "Symbol %s not found in identifiers list" % (i) | 
 | output.write("  </symbols>\n") | 
 | output.write("</api>\n") | 
 | output.close() | 
 | print "generated XML for %d symbols" % (len(symbols)) | 
 |  | 
 | ################################################################## | 
 | # | 
 | #          Saving: libxml2-api.xml | 
 | # | 
 | ################################################################## | 
 |  | 
 | hash = {} | 
 | for file in files.keys(): | 
 |     for symbol in files[file]: | 
 |         hash[symbol] = file | 
 |  | 
 | def link(id): | 
 |     if ids.has_key(id): | 
 |         target = string.upper(ids[id]) | 
 |     else: | 
 | 	target = string.upper(id) | 
 |     if hash.has_key(id): | 
 |         module = string.lower(hash[id]) | 
 |     else: | 
 |         module = 'index' | 
 |     file = 'html/libxml-' + module + '.html'; | 
 |     return file + '#' + target | 
 |      | 
 | print "Saving XML crossreferences libxml2-refs.xml" | 
 | output = open("libxml2-refs.xml", "w") | 
 | output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n') | 
 | output.write("<apirefs name='libxml2'>\n") | 
 | output.write("  <references>\n") | 
 | typ = ids.keys() | 
 | typ.sort() | 
 | for id in typ: | 
 |     output.write("    <reference name='%s' href='%s'/>\n" % (id, link(id))) | 
 | output.write("  </references>\n") | 
 | output.write("  <alpha>\n") | 
 | letter = None | 
 | ids = ids.keys() | 
 | ids.sort() | 
 | for id in ids: | 
 |     if id[0] != letter: | 
 |         if letter != None: | 
 | 	    output.write("    </letter>\n") | 
 |         letter = id[0] | 
 | 	output.write("    <letter name='%s'>\n" % (letter)) | 
 |     output.write("    <ref name='%s'/>\n" % (id)) | 
 | if letter != None: | 
 |     output.write("    </letter>\n") | 
 | output.write("  </alpha>\n") | 
 | output.write("  <constructors>\n") | 
 | typ = ret_types.keys() | 
 | typ.sort() | 
 | for type in typ: | 
 |     if type == '' or type == 'void' or type == "int" or type == "char *" or \ | 
 |        type == "const char *" : | 
 |         continue | 
 |     output.write("    <type name='%s'>\n" % (type)) | 
 |     ids = ret_types[type] | 
 |     for id in ids: | 
 | 	output.write("      <ref name='%s'/>\n" % (id)) | 
 |     output.write("    </type>\n") | 
 | output.write("  </constructors>\n") | 
 | output.write("  <functions>\n") | 
 | typ = types.keys() | 
 | typ.sort() | 
 | for type in typ: | 
 |     if type == '' or type == 'void' or type == "int" or type == "char *" or \ | 
 |        type == "const char *" : | 
 |         continue | 
 |     output.write("    <type name='%s'>\n" % (type)) | 
 |     ids = types[type] | 
 |     for id in ids: | 
 | 	output.write("      <ref name='%s'/>\n" % (id)) | 
 |     output.write("    </type>\n") | 
 | output.write("  </functions>\n") | 
 |  | 
 | output.write("  <files>\n") | 
 | typ = files.keys() | 
 | typ.sort() | 
 | for file in typ: | 
 |     output.write("    <file name='%s'>\n" % (file)) | 
 |     for id in files[file]: | 
 | 	output.write("      <ref name='%s'/>\n" % (id)) | 
 |     output.write("    </file>\n") | 
 | output.write("  </files>\n") | 
 |  | 
 | output.write("  <index>\n") | 
 | typ = index.keys() | 
 | typ.sort() | 
 | letter = None | 
 | count = 0 | 
 | chunk = 0 | 
 | chunks = [] | 
 | for id in typ: | 
 |     if len(index[id]) > 30: | 
 |         continue | 
 |     if id[0] != letter: | 
 |         if letter == None or count > 200: | 
 | 	    if letter != None: | 
 | 		output.write("      </letter>\n") | 
 | 	        output.write("    </chunk>\n") | 
 | 		count = 0 | 
 | 		chunks.append(["chunk%s" % (chunk -1), first_letter, letter]) | 
 | 	    output.write("    <chunk name='chunk%s'>\n" % (chunk)) | 
 | 	    first_letter = id[0] | 
 | 	    chunk = chunk + 1 | 
 |         elif letter != None: | 
 | 	    output.write("      </letter>\n") | 
 |         letter = id[0] | 
 | 	output.write("      <letter name='%s'>\n" % (letter)) | 
 |     output.write("        <word name='%s'>\n" % (id)) | 
 |     tokens = index[id]; | 
 |     tokens.sort() | 
 |     tok = None | 
 |     for token in index[id]: | 
 |         if tok == token: | 
 | 	    continue | 
 | 	tok = token | 
 | 	output.write("          <ref name='%s'/>\n" % (token)) | 
 | 	count = count + 1 | 
 |     output.write("        </word>\n") | 
 | if letter != None: | 
 |     output.write("      </letter>\n") | 
 |     output.write("    </chunk>\n") | 
 |     output.write("    <chunks>\n") | 
 |     for ch in chunks: | 
 |         output.write("      <chunk name='%s' start='%s' end='%s'/>\n" % ( | 
 | 	             ch[0], ch[1], ch[2])) | 
 |     output.write("    </chunks>\n") | 
 | output.write("  </index>\n") | 
 |  | 
 | output.write("</apirefs>\n") | 
 | output.close() |