#!/usr/bin/python -u # # tries to parse the output of gtk-doc declaration files and make # an XML reusable description from them # # TODO: try to extracts comments from the DocBook output of import sys import string macros = [] structs = [] typedefs = [] enums = {} functions = {} private_functions = {} ret_types = {} types = {} sections = [] files = {} identifiers_file = {} identifiers_type = {} 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) 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: 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) # print "list: %s -> %s, %s" % (list, type, name) 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 line = input.readline()[:-1] while line != "": if line[0:6] == "" and line[-7:] == "": name = line[6:-7] line = input.readline()[:-1] macros.append(name) identifiers_type[name] = "macro" def parseStruct(): global input global structs line = input.readline()[:-1] while line != "": if line[0:6] == "" and line[-7:] == "": name = line[6:-7] line = input.readline()[:-1] structs.append(name) identifiers_type[name] = "struct" def parseTypedef(): global input global typedefs line = input.readline()[:-1] while line != "": if line[0:6] == "" and line[-7:] == "": name = line[6:-7] line = input.readline()[:-1] typedefs.append(name) identifiers_type[name] = "typedef" def parseEnum(): global input global enums line = input.readline()[:-1] consts = [] while line != "": if line[0:6] == "" and line[-7:] == "": 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 private_functions line = input.readline()[:-1] type = None signature = None while line != "": if line[0:6] == "" and line[-7:] == "": name = line[6:-7] elif line[0:9] == "" and line[-10:] == "": type = extractTypes(line[9:-10], name) else: signature = line line = input.readline()[:-1] args = extractArgs(signature, name) private_functions[name] = (type , args) identifiers_type[name] = "private_func" def parseFunction(): global input global functions line = input.readline()[:-1] type = None signature = None while line != "": if line[0:6] == "" and line[-7:] == "": name = line[6:-7] elif line[0:9] == "" and line[-10:] == "": type = extractTypes(line[9:-10], name) else: signature = line line = input.readline()[:-1] args = extractArgs(signature, name) functions[name] = (type , args) identifiers_type[name] = "function" def parseSection(): global input global sections global files global identifiers_file tokens = [] line = input.readline()[:-1] while line != "": if line[0:6] == "" and line[-7:] == "": 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]: identifiers_file[const] = name print "Parsing: libxml-decl.txt" input = open('libxml-decl.txt') while 1: line = input.readline() if not line: break line = line[:-1] if line == "": parseMacro() elif line == "": parseEnum() elif line == "": parseFunction() elif line == "": parseStruct() elif line == "": parseTypedef() elif line == "": parseStaticFunction() elif len(line) >= 1 and line[0] == "<": print "unhandled %s" % (line) print "Parsed: %d macros. %d structs, %d typedefs, %d enums" % ( len(macros), len(structs), len(typedefs), len(enums)) c = 0 for enum in enums.keys(): consts = enums[enum] c = c + len(consts) print " %d constants, %d functions and %d private functions" % ( c, len(functions.keys()), len(private_functions.keys())) print "The functions manipulates %d different types" % (len(types.keys())) print "The functions returns %d different types" % (len(ret_types.keys())) 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 == "
": parseSection() elif len(line) >= 1 and line[0] == "<": print "unhandled %s" % (line) print "Parsed: %d files %d identifiers" % (len(files), len(identifiers_file.keys())) print "Saving XML description libxml2-api.xml" output = open("libxml2-api.xml", "w") output.write("\n") output.write(" \n") for file in files.keys(): output.write(" \n" % file) for symbol in files[file]: output.write(" \n" % (symbol)) output.write(" \n") output.write(" \n") output.write(" \n") symbols=macros for i in structs: symbols.append(i) for i in typedefs: symbols.append(i) for i in enums.keys(): symbols.append(i) for j in enums[i]: symbols.append(j) for i in 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) = functions[i] output.write(" \n" % (ret)) for arg in args: output.write(" \n" % ( arg[1], arg[0])) output.write(" \n" % (type)); else: output.write("/>\n"); else: print "Symbol %s not found in identifiers list" % (i) output.write(" \n") output.write("\n") print "generated XML for %d symbols" % (len(symbols))