1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-07-13 09:01:53 +03:00
Files
libxml2/doc/parsedecl.py
Daniel Veillard 610064716f added an XML description of the API, moved the script generating it here.
* Makefile.am doc/Makefile.am doc/libxml2-api.xml doc/parsedecl.py:
  added an XML description of the API, moved the script generating
  it here. Added a "make api" target
Daniel
2002-01-21 17:31:47 +00:00

337 lines
8.2 KiB
Python
Executable File

#!/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 != "</MACRO>":
if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
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 != "</STRUCT>":
if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
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 != "</TYPEDEF>":
if line[0:6] == "<NAME>" and line[-7:] == "</NAME>":
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 != "</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 private_functions
line = input.readline()[:-1]
type = None
signature = None
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 = 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 != "</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 = 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 != "</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]:
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 == "<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), 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 == "<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()))
print "Saving XML description libxml2-api.xml"
output = open("libxml2-api.xml", "w")
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
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(" <return type='%s'/>\n" % (ret))
for arg in args:
output.write(" <arg name='%s' type='%s'/>\n" % (
arg[1], arg[0]))
output.write(" </%s>\n" % (type));
else:
output.write("/>\n");
else:
print "Symbol %s not found in identifiers list" % (i)
output.write(" </symbols>\n")
output.write("</api>\n")
print "generated XML for %d symbols" % (len(symbols))