|
Packit |
423ecb |
#!/usr/bin/python -u
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# This is the API builder, it parses the C sources and build the
|
|
Packit |
423ecb |
# API formal description in XML.
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# See Copyright for the status of this software.
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# daniel@veillard.com
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
import os, sys
|
|
Packit |
423ecb |
import string
|
|
Packit |
423ecb |
import glob
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
debug=0
|
|
Packit |
423ecb |
#debugsym='ignorableWhitespaceSAXFunc'
|
|
Packit |
423ecb |
debugsym=None
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# C parser analysis code
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
ignored_files = {
|
|
Packit |
423ecb |
"trio": "too many non standard macros",
|
|
Packit |
423ecb |
"trio.c": "too many non standard macros",
|
|
Packit |
423ecb |
"trionan.c": "too many non standard macros",
|
|
Packit |
423ecb |
"triostr.c": "too many non standard macros",
|
|
Packit |
423ecb |
"acconfig.h": "generated portability layer",
|
|
Packit |
423ecb |
"config.h": "generated portability layer",
|
|
Packit |
423ecb |
"libxml.h": "internal only",
|
|
Packit |
423ecb |
"testOOM.c": "out of memory tester",
|
|
Packit |
423ecb |
"testOOMlib.h": "out of memory tester",
|
|
Packit |
423ecb |
"testOOMlib.c": "out of memory tester",
|
|
Packit |
423ecb |
"rngparser.c": "not yet integrated",
|
|
Packit |
423ecb |
"rngparser.h": "not yet integrated",
|
|
Packit |
423ecb |
"elfgcchack.h": "not a normal header",
|
|
Packit |
423ecb |
"testHTML.c": "test tool",
|
|
Packit |
423ecb |
"testReader.c": "test tool",
|
|
Packit |
423ecb |
"testSchemas.c": "test tool",
|
|
Packit |
423ecb |
"testXPath.c": "test tool",
|
|
Packit |
423ecb |
"testAutomata.c": "test tool",
|
|
Packit |
423ecb |
"testModule.c": "test tool",
|
|
Packit |
423ecb |
"testRegexp.c": "test tool",
|
|
Packit |
423ecb |
"testThreads.c": "test tool",
|
|
Packit |
423ecb |
"testC14N.c": "test tool",
|
|
Packit |
423ecb |
"testRelax.c": "test tool",
|
|
Packit |
423ecb |
"testThreadsWin32.c": "test tool",
|
|
Packit |
423ecb |
"testSAX.c": "test tool",
|
|
Packit |
423ecb |
"testURI.c": "test tool",
|
|
Packit |
423ecb |
"testapi.c": "generated regression tests",
|
|
Packit |
423ecb |
"runtest.c": "regression tests program",
|
|
Packit |
423ecb |
"runsuite.c": "regression tests program",
|
|
Packit |
423ecb |
"tst.c": "not part of the library",
|
|
Packit |
423ecb |
"test.c": "not part of the library",
|
|
Packit |
423ecb |
"testdso.c": "test for dynamid shared libraries",
|
|
Packit |
423ecb |
"testrecurse.c": "test for entities recursions",
|
|
Packit |
423ecb |
"xzlib.h": "Internal API only 2.8.0",
|
|
Packit |
423ecb |
"buf.h": "Internal API only 2.9.0",
|
|
Packit |
423ecb |
"enc.h": "Internal API only 2.9.0",
|
|
Packit |
423ecb |
"/save.h": "Internal API only 2.9.0",
|
|
Packit |
423ecb |
"timsort.h": "Internal header only for xpath.c 2.9.0",
|
|
Packit |
423ecb |
}
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
ignored_words = {
|
|
Packit |
423ecb |
"WINAPI": (0, "Windows keyword"),
|
|
Packit |
423ecb |
"LIBXML_DLL_IMPORT": (0, "Special macro to flag external keywords"),
|
|
Packit |
423ecb |
"XMLPUBVAR": (0, "Special macro for extern vars for win32"),
|
|
Packit |
423ecb |
"XSLTPUBVAR": (0, "Special macro for extern vars for win32"),
|
|
Packit |
423ecb |
"EXSLTPUBVAR": (0, "Special macro for extern vars for win32"),
|
|
Packit |
423ecb |
"XMLPUBFUN": (0, "Special macro for extern funcs for win32"),
|
|
Packit |
423ecb |
"XSLTPUBFUN": (0, "Special macro for extern funcs for win32"),
|
|
Packit |
423ecb |
"EXSLTPUBFUN": (0, "Special macro for extern funcs for win32"),
|
|
Packit |
423ecb |
"XMLCALL": (0, "Special macro for win32 calls"),
|
|
Packit |
423ecb |
"XSLTCALL": (0, "Special macro for win32 calls"),
|
|
Packit |
423ecb |
"XMLCDECL": (0, "Special macro for win32 calls"),
|
|
Packit |
423ecb |
"EXSLTCALL": (0, "Special macro for win32 calls"),
|
|
Packit |
423ecb |
"__declspec": (3, "Windows keyword"),
|
|
Packit |
423ecb |
"__stdcall": (0, "Windows keyword"),
|
|
Packit |
423ecb |
"ATTRIBUTE_UNUSED": (0, "macro keyword"),
|
|
Packit |
423ecb |
"LIBEXSLT_PUBLIC": (0, "macro keyword"),
|
|
Packit |
423ecb |
"X_IN_Y": (5, "macro function builder"),
|
|
Packit |
423ecb |
"ATTRIBUTE_ALLOC_SIZE": (3, "macro for gcc checking extension"),
|
|
Packit |
423ecb |
"ATTRIBUTE_PRINTF": (5, "macro for gcc printf args checking extension"),
|
|
Packit |
423ecb |
"LIBXML_ATTR_FORMAT": (5, "macro for gcc printf args checking extension"),
|
|
Packit |
423ecb |
"LIBXML_ATTR_ALLOC_SIZE": (3, "macro for gcc checking extension"),
|
|
Packit |
423ecb |
"__XML_EXTERNC": (0, "Special macro added for os400"),
|
|
Packit |
423ecb |
}
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def escape(raw):
|
|
Packit |
423ecb |
raw = raw.replace('&', '&')
|
|
Packit |
423ecb |
raw = raw.replace('<', '<')
|
|
Packit |
423ecb |
raw = raw.replace('>', '>')
|
|
Packit |
423ecb |
raw = raw.replace("'", ''')
|
|
Packit |
423ecb |
raw = raw.replace('"', '"')
|
|
Packit |
423ecb |
return raw
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def uniq(items):
|
|
Packit |
423ecb |
d = {}
|
|
Packit |
423ecb |
for item in items:
|
|
Packit |
423ecb |
d[item]=1
|
|
Packit |
423ecb |
return list(d.keys())
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
class identifier:
|
|
Packit |
423ecb |
def __init__(self, name, header=None, module=None, type=None, lineno = 0,
|
|
Packit |
423ecb |
info=None, extra=None, conditionals = None):
|
|
Packit |
423ecb |
self.name = name
|
|
Packit |
423ecb |
self.header = header
|
|
Packit |
423ecb |
self.module = module
|
|
Packit |
423ecb |
self.type = type
|
|
Packit |
423ecb |
self.info = info
|
|
Packit |
423ecb |
self.extra = extra
|
|
Packit |
423ecb |
self.lineno = lineno
|
|
Packit |
423ecb |
self.static = 0
|
|
Packit |
423ecb |
if conditionals == None or len(conditionals) == 0:
|
|
Packit |
423ecb |
self.conditionals = None
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.conditionals = conditionals[:]
|
|
Packit |
423ecb |
if self.name == debugsym:
|
|
Packit |
423ecb |
print("=> define %s : %s" % (debugsym, (module, type, info,
|
|
Packit |
423ecb |
extra, conditionals)))
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def __repr__(self):
|
|
Packit |
423ecb |
r = "%s %s:" % (self.type, self.name)
|
|
Packit |
423ecb |
if self.static:
|
|
Packit |
423ecb |
r = r + " static"
|
|
Packit |
423ecb |
if self.module != None:
|
|
Packit |
423ecb |
r = r + " from %s" % (self.module)
|
|
Packit |
423ecb |
if self.info != None:
|
|
Packit |
423ecb |
r = r + " " + repr(self.info)
|
|
Packit |
423ecb |
if self.extra != None:
|
|
Packit |
423ecb |
r = r + " " + repr(self.extra)
|
|
Packit |
423ecb |
if self.conditionals != None:
|
|
Packit |
423ecb |
r = r + " " + repr(self.conditionals)
|
|
Packit |
423ecb |
return r
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def set_header(self, header):
|
|
Packit |
423ecb |
self.header = header
|
|
Packit |
423ecb |
def set_module(self, module):
|
|
Packit |
423ecb |
self.module = module
|
|
Packit |
423ecb |
def set_type(self, type):
|
|
Packit |
423ecb |
self.type = type
|
|
Packit |
423ecb |
def set_info(self, info):
|
|
Packit |
423ecb |
self.info = info
|
|
Packit |
423ecb |
def set_extra(self, extra):
|
|
Packit |
423ecb |
self.extra = extra
|
|
Packit |
423ecb |
def set_lineno(self, lineno):
|
|
Packit |
423ecb |
self.lineno = lineno
|
|
Packit |
423ecb |
def set_static(self, static):
|
|
Packit |
423ecb |
self.static = static
|
|
Packit |
423ecb |
def set_conditionals(self, conditionals):
|
|
Packit |
423ecb |
if conditionals == None or len(conditionals) == 0:
|
|
Packit |
423ecb |
self.conditionals = None
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.conditionals = conditionals[:]
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def get_name(self):
|
|
Packit |
423ecb |
return self.name
|
|
Packit |
423ecb |
def get_header(self):
|
|
Packit |
423ecb |
return self.module
|
|
Packit |
423ecb |
def get_module(self):
|
|
Packit |
423ecb |
return self.module
|
|
Packit |
423ecb |
def get_type(self):
|
|
Packit |
423ecb |
return self.type
|
|
Packit |
423ecb |
def get_info(self):
|
|
Packit |
423ecb |
return self.info
|
|
Packit |
423ecb |
def get_lineno(self):
|
|
Packit |
423ecb |
return self.lineno
|
|
Packit |
423ecb |
def get_extra(self):
|
|
Packit |
423ecb |
return self.extra
|
|
Packit |
423ecb |
def get_static(self):
|
|
Packit |
423ecb |
return self.static
|
|
Packit |
423ecb |
def get_conditionals(self):
|
|
Packit |
423ecb |
return self.conditionals
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def update(self, header, module, type = None, info = None, extra=None,
|
|
Packit |
423ecb |
conditionals=None):
|
|
Packit |
423ecb |
if self.name == debugsym:
|
|
Packit |
423ecb |
print("=> update %s : %s" % (debugsym, (module, type, info,
|
|
Packit |
423ecb |
extra, conditionals)))
|
|
Packit |
423ecb |
if header != None and self.header == None:
|
|
Packit |
423ecb |
self.set_header(module)
|
|
Packit |
423ecb |
if module != None and (self.module == None or self.header == self.module):
|
|
Packit |
423ecb |
self.set_module(module)
|
|
Packit |
423ecb |
if type != None and self.type == None:
|
|
Packit |
423ecb |
self.set_type(type)
|
|
Packit |
423ecb |
if info != None:
|
|
Packit |
423ecb |
self.set_info(info)
|
|
Packit |
423ecb |
if extra != None:
|
|
Packit |
423ecb |
self.set_extra(extra)
|
|
Packit |
423ecb |
if conditionals != None:
|
|
Packit |
423ecb |
self.set_conditionals(conditionals)
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
class index:
|
|
Packit |
423ecb |
def __init__(self, name = "noname"):
|
|
Packit |
423ecb |
self.name = name
|
|
Packit |
423ecb |
self.identifiers = {}
|
|
Packit |
423ecb |
self.functions = {}
|
|
Packit |
423ecb |
self.variables = {}
|
|
Packit |
423ecb |
self.includes = {}
|
|
Packit |
423ecb |
self.structs = {}
|
|
Packit |
423ecb |
self.enums = {}
|
|
Packit |
423ecb |
self.typedefs = {}
|
|
Packit |
423ecb |
self.macros = {}
|
|
Packit |
423ecb |
self.references = {}
|
|
Packit |
423ecb |
self.info = {}
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def add_ref(self, name, header, module, static, type, lineno, info=None, extra=None, conditionals = None):
|
|
Packit |
423ecb |
if name[0:2] == '__':
|
|
Packit |
423ecb |
return None
|
|
Packit |
423ecb |
d = None
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
d = self.identifiers[name]
|
|
Packit |
423ecb |
d.update(header, module, type, lineno, info, extra, conditionals)
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
d = identifier(name, header, module, type, lineno, info, extra, conditionals)
|
|
Packit |
423ecb |
self.identifiers[name] = d
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if d != None and static == 1:
|
|
Packit |
423ecb |
d.set_static(1)
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if d != None and name != None and type != None:
|
|
Packit |
423ecb |
self.references[name] = d
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if name == debugsym:
|
|
Packit |
423ecb |
print("New ref: %s" % (d))
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
return d
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def add(self, name, header, module, static, type, lineno, info=None, extra=None, conditionals = None):
|
|
Packit |
423ecb |
if name[0:2] == '__':
|
|
Packit |
423ecb |
return None
|
|
Packit |
423ecb |
d = None
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
d = self.identifiers[name]
|
|
Packit |
423ecb |
d.update(header, module, type, lineno, info, extra, conditionals)
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
d = identifier(name, header, module, type, lineno, info, extra, conditionals)
|
|
Packit |
423ecb |
self.identifiers[name] = d
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if d != None and static == 1:
|
|
Packit |
423ecb |
d.set_static(1)
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if d != None and name != None and type != None:
|
|
Packit |
423ecb |
if type == "function":
|
|
Packit |
423ecb |
self.functions[name] = d
|
|
Packit |
423ecb |
elif type == "functype":
|
|
Packit |
423ecb |
self.functions[name] = d
|
|
Packit |
423ecb |
elif type == "variable":
|
|
Packit |
423ecb |
self.variables[name] = d
|
|
Packit |
423ecb |
elif type == "include":
|
|
Packit |
423ecb |
self.includes[name] = d
|
|
Packit |
423ecb |
elif type == "struct":
|
|
Packit |
423ecb |
self.structs[name] = d
|
|
Packit |
423ecb |
elif type == "enum":
|
|
Packit |
423ecb |
self.enums[name] = d
|
|
Packit |
423ecb |
elif type == "typedef":
|
|
Packit |
423ecb |
self.typedefs[name] = d
|
|
Packit |
423ecb |
elif type == "macro":
|
|
Packit |
423ecb |
self.macros[name] = d
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
print("Unable to register type ", type)
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if name == debugsym:
|
|
Packit |
423ecb |
print("New symbol: %s" % (d))
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
return d
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def merge(self, idx):
|
|
Packit |
423ecb |
for id in list(idx.functions.keys()):
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# macro might be used to override functions or variables
|
|
Packit |
423ecb |
# definitions
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
if id in self.macros:
|
|
Packit |
423ecb |
del self.macros[id]
|
|
Packit |
423ecb |
if id in self.functions:
|
|
Packit |
423ecb |
print("function %s from %s redeclared in %s" % (
|
|
Packit |
423ecb |
id, self.functions[id].header, idx.functions[id].header))
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.functions[id] = idx.functions[id]
|
|
Packit |
423ecb |
self.identifiers[id] = idx.functions[id]
|
|
Packit |
423ecb |
for id in list(idx.variables.keys()):
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# macro might be used to override functions or variables
|
|
Packit |
423ecb |
# definitions
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
if id in self.macros:
|
|
Packit |
423ecb |
del self.macros[id]
|
|
Packit |
423ecb |
if id in self.variables:
|
|
Packit |
423ecb |
print("variable %s from %s redeclared in %s" % (
|
|
Packit |
423ecb |
id, self.variables[id].header, idx.variables[id].header))
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.variables[id] = idx.variables[id]
|
|
Packit |
423ecb |
self.identifiers[id] = idx.variables[id]
|
|
Packit |
423ecb |
for id in list(idx.structs.keys()):
|
|
Packit |
423ecb |
if id in self.structs:
|
|
Packit |
423ecb |
print("struct %s from %s redeclared in %s" % (
|
|
Packit |
423ecb |
id, self.structs[id].header, idx.structs[id].header))
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.structs[id] = idx.structs[id]
|
|
Packit |
423ecb |
self.identifiers[id] = idx.structs[id]
|
|
Packit |
423ecb |
for id in list(idx.typedefs.keys()):
|
|
Packit |
423ecb |
if id in self.typedefs:
|
|
Packit |
423ecb |
print("typedef %s from %s redeclared in %s" % (
|
|
Packit |
423ecb |
id, self.typedefs[id].header, idx.typedefs[id].header))
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.typedefs[id] = idx.typedefs[id]
|
|
Packit |
423ecb |
self.identifiers[id] = idx.typedefs[id]
|
|
Packit |
423ecb |
for id in list(idx.macros.keys()):
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# macro might be used to override functions or variables
|
|
Packit |
423ecb |
# definitions
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
if id in self.variables:
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
if id in self.functions:
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
if id in self.enums:
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
if id in self.macros:
|
|
Packit |
423ecb |
print("macro %s from %s redeclared in %s" % (
|
|
Packit |
423ecb |
id, self.macros[id].header, idx.macros[id].header))
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.macros[id] = idx.macros[id]
|
|
Packit |
423ecb |
self.identifiers[id] = idx.macros[id]
|
|
Packit |
423ecb |
for id in list(idx.enums.keys()):
|
|
Packit |
423ecb |
if id in self.enums:
|
|
Packit |
423ecb |
print("enum %s from %s redeclared in %s" % (
|
|
Packit |
423ecb |
id, self.enums[id].header, idx.enums[id].header))
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.enums[id] = idx.enums[id]
|
|
Packit |
423ecb |
self.identifiers[id] = idx.enums[id]
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def merge_public(self, idx):
|
|
Packit |
423ecb |
for id in list(idx.functions.keys()):
|
|
Packit |
423ecb |
if id in self.functions:
|
|
Packit |
423ecb |
# check that function condition agrees with header
|
|
Packit |
423ecb |
if idx.functions[id].conditionals != \
|
|
Packit |
423ecb |
self.functions[id].conditionals:
|
|
Packit |
423ecb |
print("Header condition differs from Function for %s:" \
|
|
Packit |
423ecb |
% id)
|
|
Packit |
423ecb |
print(" H: %s" % self.functions[id].conditionals)
|
|
Packit |
423ecb |
print(" C: %s" % idx.functions[id].conditionals)
|
|
Packit |
423ecb |
up = idx.functions[id]
|
|
Packit |
423ecb |
self.functions[id].update(None, up.module, up.type, up.info, up.extra)
|
|
Packit |
423ecb |
# else:
|
|
Packit |
423ecb |
# print "Function %s from %s is not declared in headers" % (
|
|
Packit |
423ecb |
# id, idx.functions[id].module)
|
|
Packit |
423ecb |
# TODO: do the same for variables.
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def analyze_dict(self, type, dict):
|
|
Packit |
423ecb |
count = 0
|
|
Packit |
423ecb |
public = 0
|
|
Packit |
423ecb |
for name in list(dict.keys()):
|
|
Packit |
423ecb |
id = dict[name]
|
|
Packit |
423ecb |
count = count + 1
|
|
Packit |
423ecb |
if id.static == 0:
|
|
Packit |
423ecb |
public = public + 1
|
|
Packit |
423ecb |
if count != public:
|
|
Packit |
423ecb |
print(" %d %s , %d public" % (count, type, public))
|
|
Packit |
423ecb |
elif count != 0:
|
|
Packit |
423ecb |
print(" %d public %s" % (count, type))
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def analyze(self):
|
|
Packit |
423ecb |
self.analyze_dict("functions", self.functions)
|
|
Packit |
423ecb |
self.analyze_dict("variables", self.variables)
|
|
Packit |
423ecb |
self.analyze_dict("structs", self.structs)
|
|
Packit |
423ecb |
self.analyze_dict("typedefs", self.typedefs)
|
|
Packit |
423ecb |
self.analyze_dict("macros", self.macros)
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
class CLexer:
|
|
Packit |
423ecb |
"""A lexer for the C language, tokenize the input by reading and
|
|
Packit |
423ecb |
analyzing it line by line"""
|
|
Packit |
423ecb |
def __init__(self, input):
|
|
Packit |
423ecb |
self.input = input
|
|
Packit |
423ecb |
self.tokens = []
|
|
Packit |
423ecb |
self.line = ""
|
|
Packit |
423ecb |
self.lineno = 0
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def getline(self):
|
|
Packit |
423ecb |
line = ''
|
|
Packit |
423ecb |
while line == '':
|
|
Packit |
423ecb |
line = self.input.readline()
|
|
Packit |
423ecb |
if not line:
|
|
Packit |
423ecb |
return None
|
|
Packit |
423ecb |
self.lineno = self.lineno + 1
|
|
Packit |
423ecb |
line = line.lstrip()
|
|
Packit |
423ecb |
line = line.rstrip()
|
|
Packit |
423ecb |
if line == '':
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
while line[-1] == '\\':
|
|
Packit |
423ecb |
line = line[:-1]
|
|
Packit |
423ecb |
n = self.input.readline()
|
|
Packit |
423ecb |
self.lineno = self.lineno + 1
|
|
Packit |
423ecb |
n = n.lstrip()
|
|
Packit |
423ecb |
n = n.rstrip()
|
|
Packit |
423ecb |
if not n:
|
|
Packit |
423ecb |
break
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
line = line + n
|
|
Packit |
423ecb |
return line
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def getlineno(self):
|
|
Packit |
423ecb |
return self.lineno
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def push(self, token):
|
|
Packit |
423ecb |
self.tokens.insert(0, token);
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def debug(self):
|
|
Packit |
423ecb |
print("Last token: ", self.last)
|
|
Packit |
423ecb |
print("Token queue: ", self.tokens)
|
|
Packit |
423ecb |
print("Line %d end: " % (self.lineno), self.line)
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def token(self):
|
|
Packit |
423ecb |
while self.tokens == []:
|
|
Packit |
423ecb |
if self.line == "":
|
|
Packit |
423ecb |
line = self.getline()
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
line = self.line
|
|
Packit |
423ecb |
self.line = ""
|
|
Packit |
423ecb |
if line == None:
|
|
Packit |
423ecb |
return None
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if line[0] == '#':
|
|
Packit |
423ecb |
self.tokens = list(map((lambda x: ('preproc', x)),
|
|
Packit |
423ecb |
line.split()))
|
|
Packit |
423ecb |
break;
|
|
Packit |
423ecb |
l = len(line)
|
|
Packit |
423ecb |
if line[0] == '"' or line[0] == "'":
|
|
Packit |
423ecb |
end = line[0]
|
|
Packit |
423ecb |
line = line[1:]
|
|
Packit |
423ecb |
found = 0
|
|
Packit |
423ecb |
tok = ""
|
|
Packit |
423ecb |
while found == 0:
|
|
Packit |
423ecb |
i = 0
|
|
Packit |
423ecb |
l = len(line)
|
|
Packit |
423ecb |
while i < l:
|
|
Packit |
423ecb |
if line[i] == end:
|
|
Packit |
423ecb |
self.line = line[i+1:]
|
|
Packit |
423ecb |
line = line[:i]
|
|
Packit |
423ecb |
l = i
|
|
Packit |
423ecb |
found = 1
|
|
Packit |
423ecb |
break
|
|
Packit |
423ecb |
if line[i] == '\\':
|
|
Packit |
423ecb |
i = i + 1
|
|
Packit |
423ecb |
i = i + 1
|
|
Packit |
423ecb |
tok = tok + line
|
|
Packit |
423ecb |
if found == 0:
|
|
Packit |
423ecb |
line = self.getline()
|
|
Packit |
423ecb |
if line == None:
|
|
Packit |
423ecb |
return None
|
|
Packit |
423ecb |
self.last = ('string', tok)
|
|
Packit |
423ecb |
return self.last
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if l >= 2 and line[0] == '/' and line[1] == '*':
|
|
Packit |
423ecb |
line = line[2:]
|
|
Packit |
423ecb |
found = 0
|
|
Packit |
423ecb |
tok = ""
|
|
Packit |
423ecb |
while found == 0:
|
|
Packit |
423ecb |
i = 0
|
|
Packit |
423ecb |
l = len(line)
|
|
Packit |
423ecb |
while i < l:
|
|
Packit |
423ecb |
if line[i] == '*' and i+1 < l and line[i+1] == '/':
|
|
Packit |
423ecb |
self.line = line[i+2:]
|
|
Packit |
423ecb |
line = line[:i-1]
|
|
Packit |
423ecb |
l = i
|
|
Packit |
423ecb |
found = 1
|
|
Packit |
423ecb |
break
|
|
Packit |
423ecb |
i = i + 1
|
|
Packit |
423ecb |
if tok != "":
|
|
Packit |
423ecb |
tok = tok + "\n"
|
|
Packit |
423ecb |
tok = tok + line
|
|
Packit |
423ecb |
if found == 0:
|
|
Packit |
423ecb |
line = self.getline()
|
|
Packit |
423ecb |
if line == None:
|
|
Packit |
423ecb |
return None
|
|
Packit |
423ecb |
self.last = ('comment', tok)
|
|
Packit |
423ecb |
return self.last
|
|
Packit |
423ecb |
if l >= 2 and line[0] == '/' and line[1] == '/':
|
|
Packit |
423ecb |
line = line[2:]
|
|
Packit |
423ecb |
self.last = ('comment', line)
|
|
Packit |
423ecb |
return self.last
|
|
Packit |
423ecb |
i = 0
|
|
Packit |
423ecb |
while i < l:
|
|
Packit |
423ecb |
if line[i] == '/' and i+1 < l and line[i+1] == '/':
|
|
Packit |
423ecb |
self.line = line[i:]
|
|
Packit |
423ecb |
line = line[:i]
|
|
Packit |
423ecb |
break
|
|
Packit |
423ecb |
if line[i] == '/' and i+1 < l and line[i+1] == '*':
|
|
Packit |
423ecb |
self.line = line[i:]
|
|
Packit |
423ecb |
line = line[:i]
|
|
Packit |
423ecb |
break
|
|
Packit |
423ecb |
if line[i] == '"' or line[i] == "'":
|
|
Packit |
423ecb |
self.line = line[i:]
|
|
Packit |
423ecb |
line = line[:i]
|
|
Packit |
423ecb |
break
|
|
Packit |
423ecb |
i = i + 1
|
|
Packit |
423ecb |
l = len(line)
|
|
Packit |
423ecb |
i = 0
|
|
Packit |
423ecb |
while i < l:
|
|
Packit |
423ecb |
if line[i] == ' ' or line[i] == '\t':
|
|
Packit |
423ecb |
i = i + 1
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
o = ord(line[i])
|
|
Packit |
423ecb |
if (o >= 97 and o <= 122) or (o >= 65 and o <= 90) or \
|
|
Packit |
423ecb |
(o >= 48 and o <= 57):
|
|
Packit |
423ecb |
s = i
|
|
Packit |
423ecb |
while i < l:
|
|
Packit |
423ecb |
o = ord(line[i])
|
|
Packit |
423ecb |
if (o >= 97 and o <= 122) or (o >= 65 and o <= 90) or \
|
|
Packit |
423ecb |
(o >= 48 and o <= 57) or \
|
|
Packit |
423ecb |
(" \t(){}:;,+-*/%&!|[]=><".find(line[i])) == -1:
|
|
Packit |
423ecb |
i = i + 1
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
break
|
|
Packit |
423ecb |
self.tokens.append(('name', line[s:i]))
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
if "(){}:;,[]".find(line[i]) != -1:
|
|
Packit |
423ecb |
# if line[i] == '(' or line[i] == ')' or line[i] == '{' or \
|
|
Packit |
423ecb |
# line[i] == '}' or line[i] == ':' or line[i] == ';' or \
|
|
Packit |
423ecb |
# line[i] == ',' or line[i] == '[' or line[i] == ']':
|
|
Packit |
423ecb |
self.tokens.append(('sep', line[i]))
|
|
Packit |
423ecb |
i = i + 1
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
if "+-*><=/%&!|.".find(line[i]) != -1:
|
|
Packit |
423ecb |
# if line[i] == '+' or line[i] == '-' or line[i] == '*' or \
|
|
Packit |
423ecb |
# line[i] == '>' or line[i] == '<' or line[i] == '=' or \
|
|
Packit |
423ecb |
# line[i] == '/' or line[i] == '%' or line[i] == '&' or \
|
|
Packit |
423ecb |
# line[i] == '!' or line[i] == '|' or line[i] == '.':
|
|
Packit |
423ecb |
if line[i] == '.' and i + 2 < l and \
|
|
Packit |
423ecb |
line[i+1] == '.' and line[i+2] == '.':
|
|
Packit |
423ecb |
self.tokens.append(('name', '...'))
|
|
Packit |
423ecb |
i = i + 3
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
j = i + 1
|
|
Packit |
423ecb |
if j < l and (
|
|
Packit |
423ecb |
"+-*><=/%&!|".find(line[j]) != -1):
|
|
Packit |
423ecb |
# line[j] == '+' or line[j] == '-' or line[j] == '*' or \
|
|
Packit |
423ecb |
# line[j] == '>' or line[j] == '<' or line[j] == '=' or \
|
|
Packit |
423ecb |
# line[j] == '/' or line[j] == '%' or line[j] == '&' or \
|
|
Packit |
423ecb |
# line[j] == '!' or line[j] == '|'):
|
|
Packit |
423ecb |
self.tokens.append(('op', line[i:j+1]))
|
|
Packit |
423ecb |
i = j + 1
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.tokens.append(('op', line[i]))
|
|
Packit |
423ecb |
i = i + 1
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
s = i
|
|
Packit |
423ecb |
while i < l:
|
|
Packit |
423ecb |
o = ord(line[i])
|
|
Packit |
423ecb |
if (o >= 97 and o <= 122) or (o >= 65 and o <= 90) or \
|
|
Packit |
423ecb |
(o >= 48 and o <= 57) or (
|
|
Packit |
423ecb |
" \t(){}:;,+-*/%&!|[]=><".find(line[i]) == -1):
|
|
Packit |
423ecb |
# line[i] != ' ' and line[i] != '\t' and
|
|
Packit |
423ecb |
# line[i] != '(' and line[i] != ')' and
|
|
Packit |
423ecb |
# line[i] != '{' and line[i] != '}' and
|
|
Packit |
423ecb |
# line[i] != ':' and line[i] != ';' and
|
|
Packit |
423ecb |
# line[i] != ',' and line[i] != '+' and
|
|
Packit |
423ecb |
# line[i] != '-' and line[i] != '*' and
|
|
Packit |
423ecb |
# line[i] != '/' and line[i] != '%' and
|
|
Packit |
423ecb |
# line[i] != '&' and line[i] != '!' and
|
|
Packit |
423ecb |
# line[i] != '|' and line[i] != '[' and
|
|
Packit |
423ecb |
# line[i] != ']' and line[i] != '=' and
|
|
Packit |
423ecb |
# line[i] != '*' and line[i] != '>' and
|
|
Packit |
423ecb |
# line[i] != '<'):
|
|
Packit |
423ecb |
i = i + 1
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
break
|
|
Packit |
423ecb |
self.tokens.append(('name', line[s:i]))
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
tok = self.tokens[0]
|
|
Packit |
423ecb |
self.tokens = self.tokens[1:]
|
|
Packit |
423ecb |
self.last = tok
|
|
Packit |
423ecb |
return tok
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
class CParser:
|
|
Packit |
423ecb |
"""The C module parser"""
|
|
Packit |
423ecb |
def __init__(self, filename, idx = None):
|
|
Packit |
423ecb |
self.filename = filename
|
|
Packit |
423ecb |
if len(filename) > 2 and filename[-2:] == '.h':
|
|
Packit |
423ecb |
self.is_header = 1
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.is_header = 0
|
|
Packit |
423ecb |
self.input = open(filename)
|
|
Packit |
423ecb |
self.lexer = CLexer(self.input)
|
|
Packit |
423ecb |
if idx == None:
|
|
Packit |
423ecb |
self.index = index()
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.index = idx
|
|
Packit |
423ecb |
self.top_comment = ""
|
|
Packit |
423ecb |
self.last_comment = ""
|
|
Packit |
423ecb |
self.comment = None
|
|
Packit |
423ecb |
self.collect_ref = 0
|
|
Packit |
423ecb |
self.no_error = 0
|
|
Packit |
423ecb |
self.conditionals = []
|
|
Packit |
423ecb |
self.defines = []
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def collect_references(self):
|
|
Packit |
423ecb |
self.collect_ref = 1
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def stop_error(self):
|
|
Packit |
423ecb |
self.no_error = 1
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def start_error(self):
|
|
Packit |
423ecb |
self.no_error = 0
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def lineno(self):
|
|
Packit |
423ecb |
return self.lexer.getlineno()
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def index_add(self, name, module, static, type, info=None, extra = None):
|
|
Packit |
423ecb |
if self.is_header == 1:
|
|
Packit |
423ecb |
self.index.add(name, module, module, static, type, self.lineno(),
|
|
Packit |
423ecb |
info, extra, self.conditionals)
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.index.add(name, None, module, static, type, self.lineno(),
|
|
Packit |
423ecb |
info, extra, self.conditionals)
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def index_add_ref(self, name, module, static, type, info=None,
|
|
Packit |
423ecb |
extra = None):
|
|
Packit |
423ecb |
if self.is_header == 1:
|
|
Packit |
423ecb |
self.index.add_ref(name, module, module, static, type,
|
|
Packit |
423ecb |
self.lineno(), info, extra, self.conditionals)
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.index.add_ref(name, None, module, static, type, self.lineno(),
|
|
Packit |
423ecb |
info, extra, self.conditionals)
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def warning(self, msg):
|
|
Packit |
423ecb |
if self.no_error:
|
|
Packit |
423ecb |
return
|
|
Packit |
423ecb |
print(msg)
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def error(self, msg, token=-1):
|
|
Packit |
423ecb |
if self.no_error:
|
|
Packit |
423ecb |
return
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
print("Parse Error: " + msg)
|
|
Packit |
423ecb |
if token != -1:
|
|
Packit |
423ecb |
print("Got token ", token)
|
|
Packit |
423ecb |
self.lexer.debug()
|
|
Packit |
423ecb |
sys.exit(1)
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def debug(self, msg, token=-1):
|
|
Packit |
423ecb |
print("Debug: " + msg)
|
|
Packit |
423ecb |
if token != -1:
|
|
Packit |
423ecb |
print("Got token ", token)
|
|
Packit |
423ecb |
self.lexer.debug()
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def parseTopComment(self, comment):
|
|
Packit |
423ecb |
res = {}
|
|
Packit |
423ecb |
lines = comment.split("\n")
|
|
Packit |
423ecb |
item = None
|
|
Packit |
423ecb |
for line in lines:
|
|
Packit |
423ecb |
while line != "" and (line[0] == ' ' or line[0] == '\t'):
|
|
Packit |
423ecb |
line = line[1:]
|
|
Packit |
423ecb |
while line != "" and line[0] == '*':
|
|
Packit |
423ecb |
line = line[1:]
|
|
Packit |
423ecb |
while line != "" and (line[0] == ' ' or line[0] == '\t'):
|
|
Packit |
423ecb |
line = line[1:]
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
(it, line) = line.split(":", 1)
|
|
Packit |
423ecb |
item = it
|
|
Packit |
423ecb |
while line != "" and (line[0] == ' ' or line[0] == '\t'):
|
|
Packit |
423ecb |
line = line[1:]
|
|
Packit |
423ecb |
if item in res:
|
|
Packit |
423ecb |
res[item] = res[item] + " " + line
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
res[item] = line
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
if item != None:
|
|
Packit |
423ecb |
if item in res:
|
|
Packit |
423ecb |
res[item] = res[item] + " " + line
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
res[item] = line
|
|
Packit |
423ecb |
self.index.info = res
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def parseComment(self, token):
|
|
Packit |
423ecb |
if self.top_comment == "":
|
|
Packit |
423ecb |
self.top_comment = token[1]
|
|
Packit |
423ecb |
if self.comment == None or token[1][0] == '*':
|
|
Packit |
423ecb |
self.comment = token[1];
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.comment = self.comment + token[1]
|
|
Packit |
423ecb |
token = self.lexer.token()
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if self.comment.find("DOC_DISABLE") != -1:
|
|
Packit |
423ecb |
self.stop_error()
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if self.comment.find("DOC_ENABLE") != -1:
|
|
Packit |
423ecb |
self.start_error()
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# Parse a comment block associate to a typedef
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
def parseTypeComment(self, name, quiet = 0):
|
|
Packit |
423ecb |
if name[0:2] == '__':
|
|
Packit |
423ecb |
quiet = 1
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
args = []
|
|
Packit |
423ecb |
desc = ""
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if self.comment == None:
|
|
Packit |
423ecb |
if not quiet:
|
|
Packit |
423ecb |
self.warning("Missing comment for type %s" % (name))
|
|
Packit |
423ecb |
return((args, desc))
|
|
Packit |
423ecb |
if self.comment[0] != '*':
|
|
Packit |
423ecb |
if not quiet:
|
|
Packit |
423ecb |
self.warning("Missing * in type comment for %s" % (name))
|
|
Packit |
423ecb |
return((args, desc))
|
|
Packit |
423ecb |
lines = self.comment.split('\n')
|
|
Packit |
423ecb |
if lines[0] == '*':
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
if lines[0] != "* %s:" % (name):
|
|
Packit |
423ecb |
if not quiet:
|
|
Packit |
423ecb |
self.warning("Misformatted type comment for %s" % (name))
|
|
Packit |
423ecb |
self.warning(" Expecting '* %s:' got '%s'" % (name, lines[0]))
|
|
Packit |
423ecb |
return((args, desc))
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
while len(lines) > 0 and lines[0] == '*':
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
desc = ""
|
|
Packit |
423ecb |
while len(lines) > 0:
|
|
Packit |
423ecb |
l = lines[0]
|
|
Packit |
423ecb |
while len(l) > 0 and l[0] == '*':
|
|
Packit |
423ecb |
l = l[1:]
|
|
Packit |
423ecb |
l = l.strip()
|
|
Packit |
423ecb |
desc = desc + " " + l
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
desc = desc.strip()
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if quiet == 0:
|
|
Packit |
423ecb |
if desc == "":
|
|
Packit |
423ecb |
self.warning("Type comment for %s lack description of the macro" % (name))
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
return(desc)
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# Parse a comment block associate to a macro
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
def parseMacroComment(self, name, quiet = 0):
|
|
Packit |
423ecb |
if name[0:2] == '__':
|
|
Packit |
423ecb |
quiet = 1
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
args = []
|
|
Packit |
423ecb |
desc = ""
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if self.comment == None:
|
|
Packit |
423ecb |
if not quiet:
|
|
Packit |
423ecb |
self.warning("Missing comment for macro %s" % (name))
|
|
Packit |
423ecb |
return((args, desc))
|
|
Packit |
423ecb |
if self.comment[0] != '*':
|
|
Packit |
423ecb |
if not quiet:
|
|
Packit |
423ecb |
self.warning("Missing * in macro comment for %s" % (name))
|
|
Packit |
423ecb |
return((args, desc))
|
|
Packit |
423ecb |
lines = self.comment.split('\n')
|
|
Packit |
423ecb |
if lines[0] == '*':
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
if lines[0] != "* %s:" % (name):
|
|
Packit |
423ecb |
if not quiet:
|
|
Packit |
423ecb |
self.warning("Misformatted macro comment for %s" % (name))
|
|
Packit |
423ecb |
self.warning(" Expecting '* %s:' got '%s'" % (name, lines[0]))
|
|
Packit |
423ecb |
return((args, desc))
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
while lines[0] == '*':
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
while len(lines) > 0 and lines[0][0:3] == '* @':
|
|
Packit |
423ecb |
l = lines[0][3:]
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
(arg, desc) = l.split(':', 1)
|
|
Packit |
423ecb |
desc=desc.strip()
|
|
Packit |
423ecb |
arg=arg.strip()
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
if not quiet:
|
|
Packit |
423ecb |
self.warning("Misformatted macro comment for %s" % (name))
|
|
Packit |
423ecb |
self.warning(" problem with '%s'" % (lines[0]))
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
l = lines[0].strip()
|
|
Packit |
423ecb |
while len(l) > 2 and l[0:3] != '* @':
|
|
Packit |
423ecb |
while l[0] == '*':
|
|
Packit |
423ecb |
l = l[1:]
|
|
Packit |
423ecb |
desc = desc + ' ' + l.strip()
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
if len(lines) == 0:
|
|
Packit |
423ecb |
break
|
|
Packit |
423ecb |
l = lines[0]
|
|
Packit |
423ecb |
args.append((arg, desc))
|
|
Packit |
423ecb |
while len(lines) > 0 and lines[0] == '*':
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
desc = ""
|
|
Packit |
423ecb |
while len(lines) > 0:
|
|
Packit |
423ecb |
l = lines[0]
|
|
Packit |
423ecb |
while len(l) > 0 and l[0] == '*':
|
|
Packit |
423ecb |
l = l[1:]
|
|
Packit |
423ecb |
l = l.strip()
|
|
Packit |
423ecb |
desc = desc + " " + l
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
desc = desc.strip()
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if quiet == 0:
|
|
Packit |
423ecb |
if desc == "":
|
|
Packit |
423ecb |
self.warning("Macro comment for %s lack description of the macro" % (name))
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
return((args, desc))
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# Parse a comment block and merge the informations found in the
|
|
Packit |
423ecb |
# parameters descriptions, finally returns a block as complete
|
|
Packit |
423ecb |
# as possible
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
def mergeFunctionComment(self, name, description, quiet = 0):
|
|
Packit |
423ecb |
if name == 'main':
|
|
Packit |
423ecb |
quiet = 1
|
|
Packit |
423ecb |
if name[0:2] == '__':
|
|
Packit |
423ecb |
quiet = 1
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
(ret, args) = description
|
|
Packit |
423ecb |
desc = ""
|
|
Packit |
423ecb |
retdesc = ""
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if self.comment == None:
|
|
Packit |
423ecb |
if not quiet:
|
|
Packit |
423ecb |
self.warning("Missing comment for function %s" % (name))
|
|
Packit |
423ecb |
return(((ret[0], retdesc), args, desc))
|
|
Packit |
423ecb |
if self.comment[0] != '*':
|
|
Packit |
423ecb |
if not quiet:
|
|
Packit |
423ecb |
self.warning("Missing * in function comment for %s" % (name))
|
|
Packit |
423ecb |
return(((ret[0], retdesc), args, desc))
|
|
Packit |
423ecb |
lines = self.comment.split('\n')
|
|
Packit |
423ecb |
if lines[0] == '*':
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
if lines[0] != "* %s:" % (name):
|
|
Packit |
423ecb |
if not quiet:
|
|
Packit |
423ecb |
self.warning("Misformatted function comment for %s" % (name))
|
|
Packit |
423ecb |
self.warning(" Expecting '* %s:' got '%s'" % (name, lines[0]))
|
|
Packit |
423ecb |
return(((ret[0], retdesc), args, desc))
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
while lines[0] == '*':
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
nbargs = len(args)
|
|
Packit |
423ecb |
while len(lines) > 0 and lines[0][0:3] == '* @':
|
|
Packit |
423ecb |
l = lines[0][3:]
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
(arg, desc) = l.split(':', 1)
|
|
Packit |
423ecb |
desc=desc.strip()
|
|
Packit |
423ecb |
arg=arg.strip()
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
if not quiet:
|
|
Packit |
423ecb |
self.warning("Misformatted function comment for %s" % (name))
|
|
Packit |
423ecb |
self.warning(" problem with '%s'" % (lines[0]))
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
l = lines[0].strip()
|
|
Packit |
423ecb |
while len(l) > 2 and l[0:3] != '* @':
|
|
Packit |
423ecb |
while l[0] == '*':
|
|
Packit |
423ecb |
l = l[1:]
|
|
Packit |
423ecb |
desc = desc + ' ' + l.strip()
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
if len(lines) == 0:
|
|
Packit |
423ecb |
break
|
|
Packit |
423ecb |
l = lines[0]
|
|
Packit |
423ecb |
i = 0
|
|
Packit |
423ecb |
while i < nbargs:
|
|
Packit |
423ecb |
if args[i][1] == arg:
|
|
Packit |
423ecb |
args[i] = (args[i][0], arg, desc)
|
|
Packit |
423ecb |
break;
|
|
Packit |
423ecb |
i = i + 1
|
|
Packit |
423ecb |
if i >= nbargs:
|
|
Packit |
423ecb |
if not quiet:
|
|
Packit |
423ecb |
self.warning("Unable to find arg %s from function comment for %s" % (
|
|
Packit |
423ecb |
arg, name))
|
|
Packit |
423ecb |
while len(lines) > 0 and lines[0] == '*':
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
desc = ""
|
|
Packit |
423ecb |
while len(lines) > 0:
|
|
Packit |
423ecb |
l = lines[0]
|
|
Packit |
423ecb |
while len(l) > 0 and l[0] == '*':
|
|
Packit |
423ecb |
l = l[1:]
|
|
Packit |
423ecb |
l = l.strip()
|
|
Packit |
423ecb |
if len(l) >= 6 and l[0:6] == "return" or l[0:6] == "Return":
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
l = l.split(' ', 1)[1]
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
l = ""
|
|
Packit |
423ecb |
retdesc = l.strip()
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
while len(lines) > 0:
|
|
Packit |
423ecb |
l = lines[0]
|
|
Packit |
423ecb |
while len(l) > 0 and l[0] == '*':
|
|
Packit |
423ecb |
l = l[1:]
|
|
Packit |
423ecb |
l = l.strip()
|
|
Packit |
423ecb |
retdesc = retdesc + " " + l
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
desc = desc + " " + l
|
|
Packit |
423ecb |
del lines[0]
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
retdesc = retdesc.strip()
|
|
Packit |
423ecb |
desc = desc.strip()
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if quiet == 0:
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# report missing comments
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
i = 0
|
|
Packit |
423ecb |
while i < nbargs:
|
|
Packit |
423ecb |
if args[i][2] == None and args[i][0] != "void" and \
|
|
Packit |
423ecb |
((args[i][1] != None) or (args[i][1] == '')):
|
|
Packit |
423ecb |
self.warning("Function comment for %s lacks description of arg %s" % (name, args[i][1]))
|
|
Packit |
423ecb |
i = i + 1
|
|
Packit |
423ecb |
if retdesc == "" and ret[0] != "void":
|
|
Packit |
423ecb |
self.warning("Function comment for %s lacks description of return value" % (name))
|
|
Packit |
423ecb |
if desc == "":
|
|
Packit |
423ecb |
self.warning("Function comment for %s lacks description of the function" % (name))
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
return(((ret[0], retdesc), args, desc))
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def parsePreproc(self, token):
|
|
Packit |
423ecb |
if debug:
|
|
Packit |
423ecb |
print("=> preproc ", token, self.lexer.tokens)
|
|
Packit |
423ecb |
name = token[1]
|
|
Packit |
423ecb |
if name == "#include":
|
|
Packit |
423ecb |
token = self.lexer.token()
|
|
Packit |
423ecb |
if token == None:
|
|
Packit |
423ecb |
return None
|
|
Packit |
423ecb |
if token[0] == 'preproc':
|
|
Packit |
423ecb |
self.index_add(token[1], self.filename, not self.is_header,
|
|
Packit |
423ecb |
"include")
|
|
Packit |
423ecb |
return self.lexer.token()
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
if name == "#define":
|
|
Packit |
423ecb |
token = self.lexer.token()
|
|
Packit |
423ecb |
if token == None:
|
|
Packit |
423ecb |
return None
|
|
Packit |
423ecb |
if token[0] == 'preproc':
|
|
Packit |
423ecb |
# TODO macros with arguments
|
|
Packit |
423ecb |
name = token[1]
|
|
Packit |
423ecb |
lst = []
|
|
Packit |
423ecb |
token = self.lexer.token()
|
|
Packit |
423ecb |
while token != None and token[0] == 'preproc' and \
|
|
Packit |
423ecb |
token[1][0] != '#':
|
|
Packit |
423ecb |
lst.append(token[1])
|
|
Packit |
423ecb |
token = self.lexer.token()
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
name = name.split('(') [0]
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
pass
|
|
Packit |
423ecb |
info = self.parseMacroComment(name, not self.is_header)
|
|
Packit |
423ecb |
self.index_add(name, self.filename, not self.is_header,
|
|
Packit |
423ecb |
"macro", info)
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# Processing of conditionals modified by Bill 1/1/05
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# We process conditionals (i.e. tokens from #ifdef, #ifndef,
|
|
Packit |
423ecb |
# #if, #else and #endif) for headers and mainline code,
|
|
Packit |
423ecb |
# store the ones from the header in libxml2-api.xml, and later
|
|
Packit |
423ecb |
# (in the routine merge_public) verify that the two (header and
|
|
Packit |
423ecb |
# mainline code) agree.
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# There is a small problem with processing the headers. Some of
|
|
Packit |
423ecb |
# the variables are not concerned with enabling / disabling of
|
|
Packit |
423ecb |
# library functions (e.g. '__XML_PARSER_H__'), and we don't want
|
|
Packit |
423ecb |
# them to be included in libxml2-api.xml, or involved in
|
|
Packit |
423ecb |
# the check between the header and the mainline code. To
|
|
Packit |
423ecb |
# accomplish this, we ignore any conditional which doesn't include
|
|
Packit |
423ecb |
# the string 'ENABLED'
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
if name == "#ifdef":
|
|
Packit |
423ecb |
apstr = self.lexer.tokens[0][1]
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
self.defines.append(apstr)
|
|
Packit |
423ecb |
if apstr.find('ENABLED') != -1:
|
|
Packit |
423ecb |
self.conditionals.append("defined(%s)" % apstr)
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
pass
|
|
Packit |
423ecb |
elif name == "#ifndef":
|
|
Packit |
423ecb |
apstr = self.lexer.tokens[0][1]
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
self.defines.append(apstr)
|
|
Packit |
423ecb |
if apstr.find('ENABLED') != -1:
|
|
Packit |
423ecb |
self.conditionals.append("!defined(%s)" % apstr)
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
pass
|
|
Packit |
423ecb |
elif name == "#if":
|
|
Packit |
423ecb |
apstr = ""
|
|
Packit |
423ecb |
for tok in self.lexer.tokens:
|
|
Packit |
423ecb |
if apstr != "":
|
|
Packit |
423ecb |
apstr = apstr + " "
|
|
Packit |
423ecb |
apstr = apstr + tok[1]
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
self.defines.append(apstr)
|
|
Packit |
423ecb |
if apstr.find('ENABLED') != -1:
|
|
Packit |
423ecb |
self.conditionals.append(apstr)
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
pass
|
|
Packit |
423ecb |
elif name == "#else":
|
|
Packit |
423ecb |
if self.conditionals != [] and \
|
|
Packit |
423ecb |
self.defines[-1].find('ENABLED') != -1:
|
|
Packit |
423ecb |
self.conditionals[-1] = "!(%s)" % self.conditionals[-1]
|
|
Packit |
423ecb |
elif name == "#endif":
|
|
Packit |
423ecb |
if self.conditionals != [] and \
|
|
Packit |
423ecb |
self.defines[-1].find('ENABLED') != -1:
|
|
Packit |
423ecb |
self.conditionals = self.conditionals[:-1]
|
|
Packit |
423ecb |
self.defines = self.defines[:-1]
|
|
Packit |
423ecb |
token = self.lexer.token()
|
|
Packit |
423ecb |
while token != None and token[0] == 'preproc' and \
|
|
Packit |
423ecb |
token[1][0] != '#':
|
|
Packit |
423ecb |
token = self.lexer.token()
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# token acquisition on top of the lexer, it handle internally
|
|
Packit |
423ecb |
# preprocessor and comments since they are logically not part of
|
|
Packit |
423ecb |
# the program structure.
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
def token(self):
|
|
Packit |
423ecb |
global ignored_words
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
token = self.lexer.token()
|
|
Packit |
423ecb |
while token != None:
|
|
Packit |
423ecb |
if token[0] == 'comment':
|
|
Packit |
423ecb |
token = self.parseComment(token)
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
elif token[0] == 'preproc':
|
|
Packit |
423ecb |
token = self.parsePreproc(token)
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
elif token[0] == "name" and token[1] == "__const":
|
|
Packit |
423ecb |
token = ("name", "const")
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
elif token[0] == "name" and token[1] == "__attribute":
|
|
Packit |
423ecb |
token = self.lexer.token()
|
|
Packit |
423ecb |
while token != None and token[1] != ";":
|
|
Packit |
423ecb |
token = self.lexer.token()
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
elif token[0] == "name" and token[1] in ignored_words:
|
|
Packit |
423ecb |
(n, info) = ignored_words[token[1]]
|
|
Packit |
423ecb |
i = 0
|
|
Packit |
423ecb |
while i < n:
|
|
Packit |
423ecb |
token = self.lexer.token()
|
|
Packit |
423ecb |
i = i + 1
|
|
Packit |
423ecb |
token = self.lexer.token()
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
if debug:
|
|
Packit |
423ecb |
print("=> ", token)
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
return None
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# Parse a typedef, it records the type and its name.
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
def parseTypedef(self, token):
|
|
Packit |
423ecb |
if token == None:
|
|
Packit |
423ecb |
return None
|
|
Packit |
423ecb |
token = self.parseType(token)
|
|
Packit |
423ecb |
if token == None:
|
|
Packit |
423ecb |
self.error("parsing typedef")
|
|
Packit |
423ecb |
return None
|
|
Packit |
423ecb |
base_type = self.type
|
|
Packit |
423ecb |
type = base_type
|
|
Packit |
423ecb |
#self.debug("end typedef type", token)
|
|
Packit |
423ecb |
while token != None:
|
|
Packit |
423ecb |
if token[0] == "name":
|
|
Packit |
423ecb |
name = token[1]
|
|
Packit |
423ecb |
signature = self.signature
|
|
Packit |
423ecb |
if signature != None:
|
|
Packit |
423ecb |
type = type.split('(')[0]
|
|
Packit |
423ecb |
d = self.mergeFunctionComment(name,
|
|
Packit |
423ecb |
((type, None), signature), 1)
|
|
Packit |
423ecb |
self.index_add(name, self.filename, not self.is_header,
|
|
Packit |
423ecb |
"functype", d)
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
if base_type == "struct":
|
|
Packit |
423ecb |
self.index_add(name, self.filename, not self.is_header,
|
|
Packit |
423ecb |
"struct", type)
|
|
Packit |
423ecb |
base_type = "struct " + name
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
# TODO report missing or misformatted comments
|
|
Packit |
423ecb |
info = self.parseTypeComment(name, 1)
|
|
Packit |
423ecb |
self.index_add(name, self.filename, not self.is_header,
|
|
Packit |
423ecb |
"typedef", type, info)
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.error("parsing typedef: expecting a name")
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
#self.debug("end typedef", token)
|
|
Packit |
423ecb |
if token != None and token[0] == 'sep' and token[1] == ',':
|
|
Packit |
423ecb |
type = base_type
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
while token != None and token[0] == "op":
|
|
Packit |
423ecb |
type = type + token[1]
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
elif token != None and token[0] == 'sep' and token[1] == ';':
|
|
Packit |
423ecb |
break;
|
|
Packit |
423ecb |
elif token != None and token[0] == 'name':
|
|
Packit |
423ecb |
type = base_type
|
|
Packit |
423ecb |
continue;
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.error("parsing typedef: expecting ';'", token)
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# Parse a C code block, used for functions it parse till
|
|
Packit |
423ecb |
# the balancing } included
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
def parseBlock(self, token):
|
|
Packit |
423ecb |
while token != None:
|
|
Packit |
423ecb |
if token[0] == "sep" and token[1] == "{":
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
token = self.parseBlock(token)
|
|
Packit |
423ecb |
elif token[0] == "sep" and token[1] == "}":
|
|
Packit |
423ecb |
self.comment = None
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
if self.collect_ref == 1:
|
|
Packit |
423ecb |
oldtok = token
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if oldtok[0] == "name" and oldtok[1][0:3] == "xml":
|
|
Packit |
423ecb |
if token[0] == "sep" and token[1] == "(":
|
|
Packit |
423ecb |
self.index_add_ref(oldtok[1], self.filename,
|
|
Packit |
423ecb |
0, "function")
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
elif token[0] == "name":
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if token[0] == "sep" and (token[1] == ";" or
|
|
Packit |
423ecb |
token[1] == "," or token[1] == "="):
|
|
Packit |
423ecb |
self.index_add_ref(oldtok[1], self.filename,
|
|
Packit |
423ecb |
0, "type")
|
|
Packit |
423ecb |
elif oldtok[0] == "name" and oldtok[1][0:4] == "XML_":
|
|
Packit |
423ecb |
self.index_add_ref(oldtok[1], self.filename,
|
|
Packit |
423ecb |
0, "typedef")
|
|
Packit |
423ecb |
elif oldtok[0] == "name" and oldtok[1][0:7] == "LIBXML_":
|
|
Packit |
423ecb |
self.index_add_ref(oldtok[1], self.filename,
|
|
Packit |
423ecb |
0, "typedef")
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# Parse a C struct definition till the balancing }
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
def parseStruct(self, token):
|
|
Packit |
423ecb |
fields = []
|
|
Packit |
423ecb |
#self.debug("start parseStruct", token)
|
|
Packit |
423ecb |
while token != None:
|
|
Packit |
423ecb |
if token[0] == "sep" and token[1] == "{":
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
token = self.parseTypeBlock(token)
|
|
Packit |
423ecb |
elif token[0] == "sep" and token[1] == "}":
|
|
Packit |
423ecb |
self.struct_fields = fields
|
|
Packit |
423ecb |
#self.debug("end parseStruct", token)
|
|
Packit |
423ecb |
#print fields
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
base_type = self.type
|
|
Packit |
423ecb |
#self.debug("before parseType", token)
|
|
Packit |
423ecb |
token = self.parseType(token)
|
|
Packit |
423ecb |
#self.debug("after parseType", token)
|
|
Packit |
423ecb |
if token != None and token[0] == "name":
|
|
Packit |
423ecb |
fname = token[1]
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if token[0] == "sep" and token[1] == ";":
|
|
Packit |
423ecb |
self.comment = None
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
fields.append((self.type, fname, self.comment))
|
|
Packit |
423ecb |
self.comment = None
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.error("parseStruct: expecting ;", token)
|
|
Packit |
423ecb |
elif token != None and token[0] == "sep" and token[1] == "{":
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
token = self.parseTypeBlock(token)
|
|
Packit |
423ecb |
if token != None and token[0] == "name":
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if token != None and token[0] == "sep" and token[1] == ";":
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.error("parseStruct: expecting ;", token)
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.error("parseStruct: name", token)
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
self.type = base_type;
|
|
Packit |
423ecb |
self.struct_fields = fields
|
|
Packit |
423ecb |
#self.debug("end parseStruct", token)
|
|
Packit |
423ecb |
#print fields
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# Parse a C enum block, parse till the balancing }
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
def parseEnumBlock(self, token):
|
|
Packit |
423ecb |
self.enums = []
|
|
Packit |
423ecb |
name = None
|
|
Packit |
423ecb |
self.comment = None
|
|
Packit |
423ecb |
comment = ""
|
|
Packit |
423ecb |
value = "0"
|
|
Packit |
423ecb |
while token != None:
|
|
Packit |
423ecb |
if token[0] == "sep" and token[1] == "{":
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
token = self.parseTypeBlock(token)
|
|
Packit |
423ecb |
elif token[0] == "sep" and token[1] == "}":
|
|
Packit |
423ecb |
if name != None:
|
|
Packit |
423ecb |
if self.comment != None:
|
|
Packit |
423ecb |
comment = self.comment
|
|
Packit |
423ecb |
self.comment = None
|
|
Packit |
423ecb |
self.enums.append((name, value, comment))
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
elif token[0] == "name":
|
|
Packit |
423ecb |
if name != None:
|
|
Packit |
423ecb |
if self.comment != None:
|
|
Packit |
423ecb |
comment = self.comment.strip()
|
|
Packit |
423ecb |
self.comment = None
|
|
Packit |
423ecb |
self.enums.append((name, value, comment))
|
|
Packit |
423ecb |
name = token[1]
|
|
Packit |
423ecb |
comment = ""
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if token[0] == "op" and token[1][0] == "=":
|
|
Packit |
423ecb |
value = ""
|
|
Packit |
423ecb |
if len(token[1]) > 1:
|
|
Packit |
423ecb |
value = token[1][1:]
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
while token[0] != "sep" or (token[1] != ',' and
|
|
Packit |
423ecb |
token[1] != '}'):
|
|
Packit |
423ecb |
value = value + token[1]
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
value = "%d" % (int(value) + 1)
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
self.warning("Failed to compute value of enum %s" % (name))
|
|
Packit |
423ecb |
value=""
|
|
Packit |
423ecb |
if token[0] == "sep" and token[1] == ",":
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# Parse a C definition block, used for structs it parse till
|
|
Packit |
423ecb |
# the balancing }
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
def parseTypeBlock(self, token):
|
|
Packit |
423ecb |
while token != None:
|
|
Packit |
423ecb |
if token[0] == "sep" and token[1] == "{":
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
token = self.parseTypeBlock(token)
|
|
Packit |
423ecb |
elif token[0] == "sep" and token[1] == "}":
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# Parse a type: the fact that the type name can either occur after
|
|
Packit |
423ecb |
# the definition or within the definition makes it a little harder
|
|
Packit |
423ecb |
# if inside, the name token is pushed back before returning
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
def parseType(self, token):
|
|
Packit |
423ecb |
self.type = ""
|
|
Packit |
423ecb |
self.struct_fields = []
|
|
Packit |
423ecb |
self.signature = None
|
|
Packit |
423ecb |
if token == None:
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
while token[0] == "name" and (
|
|
Packit |
423ecb |
token[1] == "const" or \
|
|
Packit |
423ecb |
token[1] == "unsigned" or \
|
|
Packit |
423ecb |
token[1] == "signed"):
|
|
Packit |
423ecb |
if self.type == "":
|
|
Packit |
423ecb |
self.type = token[1]
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.type = self.type + " " + token[1]
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if token[0] == "name" and (token[1] == "long" or token[1] == "short"):
|
|
Packit |
423ecb |
if self.type == "":
|
|
Packit |
423ecb |
self.type = token[1]
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.type = self.type + " " + token[1]
|
|
Packit |
423ecb |
if token[0] == "name" and token[1] == "int":
|
|
Packit |
423ecb |
if self.type == "":
|
|
Packit |
423ecb |
self.type = tmp[1]
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.type = self.type + " " + tmp[1]
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
elif token[0] == "name" and token[1] == "struct":
|
|
Packit |
423ecb |
if self.type == "":
|
|
Packit |
423ecb |
self.type = token[1]
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.type = self.type + " " + token[1]
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
nametok = None
|
|
Packit |
423ecb |
if token[0] == "name":
|
|
Packit |
423ecb |
nametok = token
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if token != None and token[0] == "sep" and token[1] == "{":
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
token = self.parseStruct(token)
|
|
Packit |
423ecb |
elif token != None and token[0] == "op" and token[1] == "*":
|
|
Packit |
423ecb |
self.type = self.type + " " + nametok[1] + " *"
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
while token != None and token[0] == "op" and token[1] == "*":
|
|
Packit |
423ecb |
self.type = self.type + " *"
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if token[0] == "name":
|
|
Packit |
423ecb |
nametok = token
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.error("struct : expecting name", token)
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
elif token != None and token[0] == "name" and nametok != None:
|
|
Packit |
423ecb |
self.type = self.type + " " + nametok[1]
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if nametok != None:
|
|
Packit |
423ecb |
self.lexer.push(token)
|
|
Packit |
423ecb |
token = nametok
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
elif token[0] == "name" and token[1] == "enum":
|
|
Packit |
423ecb |
if self.type == "":
|
|
Packit |
423ecb |
self.type = token[1]
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.type = self.type + " " + token[1]
|
|
Packit |
423ecb |
self.enums = []
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if token != None and token[0] == "sep" and token[1] == "{":
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
token = self.parseEnumBlock(token)
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.error("parsing enum: expecting '{'", token)
|
|
Packit |
423ecb |
enum_type = None
|
|
Packit |
423ecb |
if token != None and token[0] != "name":
|
|
Packit |
423ecb |
self.lexer.push(token)
|
|
Packit |
423ecb |
token = ("name", "enum")
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
enum_type = token[1]
|
|
Packit |
423ecb |
for enum in self.enums:
|
|
Packit |
423ecb |
self.index_add(enum[0], self.filename,
|
|
Packit |
423ecb |
not self.is_header, "enum",
|
|
Packit |
423ecb |
(enum[1], enum[2], enum_type))
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
elif token[0] == "name":
|
|
Packit |
423ecb |
if self.type == "":
|
|
Packit |
423ecb |
self.type = token[1]
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.type = self.type + " " + token[1]
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.error("parsing type %s: expecting a name" % (self.type),
|
|
Packit |
423ecb |
token)
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
while token != None and (token[0] == "op" or
|
|
Packit |
423ecb |
token[0] == "name" and token[1] == "const"):
|
|
Packit |
423ecb |
self.type = self.type + " " + token[1]
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# if there is a parenthesis here, this means a function type
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
if token != None and token[0] == "sep" and token[1] == '(':
|
|
Packit |
423ecb |
self.type = self.type + token[1]
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
while token != None and token[0] == "op" and token[1] == '*':
|
|
Packit |
423ecb |
self.type = self.type + token[1]
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if token == None or token[0] != "name" :
|
|
Packit |
423ecb |
self.error("parsing function type, name expected", token);
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
self.type = self.type + token[1]
|
|
Packit |
423ecb |
nametok = token
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if token != None and token[0] == "sep" and token[1] == ')':
|
|
Packit |
423ecb |
self.type = self.type + token[1]
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if token != None and token[0] == "sep" and token[1] == '(':
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
type = self.type;
|
|
Packit |
423ecb |
token = self.parseSignature(token);
|
|
Packit |
423ecb |
self.type = type;
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.error("parsing function type, '(' expected", token);
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.error("parsing function type, ')' expected", token);
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
self.lexer.push(token)
|
|
Packit |
423ecb |
token = nametok
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# do some lookahead for arrays
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
if token != None and token[0] == "name":
|
|
Packit |
423ecb |
nametok = token
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if token != None and token[0] == "sep" and token[1] == '[':
|
|
Packit |
423ecb |
self.type = self.type + nametok[1]
|
|
Packit |
423ecb |
while token != None and token[0] == "sep" and token[1] == '[':
|
|
Packit |
423ecb |
self.type = self.type + token[1]
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
while token != None and token[0] != 'sep' and \
|
|
Packit |
423ecb |
token[1] != ']' and token[1] != ';':
|
|
Packit |
423ecb |
self.type = self.type + token[1]
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if token != None and token[0] == 'sep' and token[1] == ']':
|
|
Packit |
423ecb |
self.type = self.type + token[1]
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.error("parsing array type, ']' expected", token);
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
elif token != None and token[0] == "sep" and token[1] == ':':
|
|
Packit |
423ecb |
# remove :12 in case it's a limited int size
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
self.lexer.push(token)
|
|
Packit |
423ecb |
token = nametok
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# Parse a signature: '(' has been parsed and we scan the type definition
|
|
Packit |
423ecb |
# up to the ')' included
|
|
Packit |
423ecb |
def parseSignature(self, token):
|
|
Packit |
423ecb |
signature = []
|
|
Packit |
423ecb |
if token != None and token[0] == "sep" and token[1] == ')':
|
|
Packit |
423ecb |
self.signature = []
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
while token != None:
|
|
Packit |
423ecb |
token = self.parseType(token)
|
|
Packit |
423ecb |
if token != None and token[0] == "name":
|
|
Packit |
423ecb |
signature.append((self.type, token[1], None))
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
elif token != None and token[0] == "sep" and token[1] == ',':
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
elif token != None and token[0] == "sep" and token[1] == ')':
|
|
Packit |
423ecb |
# only the type was provided
|
|
Packit |
423ecb |
if self.type == "...":
|
|
Packit |
423ecb |
signature.append((self.type, "...", None))
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
signature.append((self.type, None, None))
|
|
Packit |
423ecb |
if token != None and token[0] == "sep":
|
|
Packit |
423ecb |
if token[1] == ',':
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
elif token[1] == ')':
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
break
|
|
Packit |
423ecb |
self.signature = signature
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# Parse a global definition, be it a type, variable or function
|
|
Packit |
423ecb |
# the extern "C" blocks are a bit nasty and require it to recurse.
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
def parseGlobal(self, token):
|
|
Packit |
423ecb |
static = 0
|
|
Packit |
423ecb |
if token[1] == 'extern':
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if token == None:
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
if token[0] == 'string':
|
|
Packit |
423ecb |
if token[1] == 'C':
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if token == None:
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
if token[0] == 'sep' and token[1] == "{":
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
# print 'Entering extern "C line ', self.lineno()
|
|
Packit |
423ecb |
while token != None and (token[0] != 'sep' or
|
|
Packit |
423ecb |
token[1] != "}"):
|
|
Packit |
423ecb |
if token[0] == 'name':
|
|
Packit |
423ecb |
token = self.parseGlobal(token)
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.error(
|
|
Packit |
423ecb |
"token %s %s unexpected at the top level" % (
|
|
Packit |
423ecb |
token[0], token[1]))
|
|
Packit |
423ecb |
token = self.parseGlobal(token)
|
|
Packit |
423ecb |
# print 'Exiting extern "C" line', self.lineno()
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
elif token[1] == 'static':
|
|
Packit |
423ecb |
static = 1
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if token == None or token[0] != 'name':
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if token[1] == 'typedef':
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
return self.parseTypedef(token)
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
token = self.parseType(token)
|
|
Packit |
423ecb |
type_orig = self.type
|
|
Packit |
423ecb |
if token == None or token[0] != "name":
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
type = type_orig
|
|
Packit |
423ecb |
self.name = token[1]
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
while token != None and (token[0] == "sep" or token[0] == "op"):
|
|
Packit |
423ecb |
if token[0] == "sep":
|
|
Packit |
423ecb |
if token[1] == "[":
|
|
Packit |
423ecb |
type = type + token[1]
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
while token != None and (token[0] != "sep" or \
|
|
Packit |
423ecb |
token[1] != ";"):
|
|
Packit |
423ecb |
type = type + token[1]
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if token != None and token[0] == "op" and token[1] == "=":
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# Skip the initialization of the variable
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if token[0] == 'sep' and token[1] == '{':
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
token = self.parseBlock(token)
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.comment = None
|
|
Packit |
423ecb |
while token != None and (token[0] != "sep" or \
|
|
Packit |
423ecb |
(token[1] != ';' and token[1] != ',')):
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
self.comment = None
|
|
Packit |
423ecb |
if token == None or token[0] != "sep" or (token[1] != ';' and
|
|
Packit |
423ecb |
token[1] != ','):
|
|
Packit |
423ecb |
self.error("missing ';' or ',' after value")
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if token != None and token[0] == "sep":
|
|
Packit |
423ecb |
if token[1] == ";":
|
|
Packit |
423ecb |
self.comment = None
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if type == "struct":
|
|
Packit |
423ecb |
self.index_add(self.name, self.filename,
|
|
Packit |
423ecb |
not self.is_header, "struct", self.struct_fields)
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.index_add(self.name, self.filename,
|
|
Packit |
423ecb |
not self.is_header, "variable", type)
|
|
Packit |
423ecb |
break
|
|
Packit |
423ecb |
elif token[1] == "(":
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
token = self.parseSignature(token)
|
|
Packit |
423ecb |
if token == None:
|
|
Packit |
423ecb |
return None
|
|
Packit |
423ecb |
if token[0] == "sep" and token[1] == ";":
|
|
Packit |
423ecb |
d = self.mergeFunctionComment(self.name,
|
|
Packit |
423ecb |
((type, None), self.signature), 1)
|
|
Packit |
423ecb |
self.index_add(self.name, self.filename, static,
|
|
Packit |
423ecb |
"function", d)
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
elif token[0] == "sep" and token[1] == "{":
|
|
Packit |
423ecb |
d = self.mergeFunctionComment(self.name,
|
|
Packit |
423ecb |
((type, None), self.signature), static)
|
|
Packit |
423ecb |
self.index_add(self.name, self.filename, static,
|
|
Packit |
423ecb |
"function", d)
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
token = self.parseBlock(token);
|
|
Packit |
423ecb |
elif token[1] == ',':
|
|
Packit |
423ecb |
self.comment = None
|
|
Packit |
423ecb |
self.index_add(self.name, self.filename, static,
|
|
Packit |
423ecb |
"variable", type)
|
|
Packit |
423ecb |
type = type_orig
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
while token != None and token[0] == "sep":
|
|
Packit |
423ecb |
type = type + token[1]
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
if token != None and token[0] == "name":
|
|
Packit |
423ecb |
self.name = token[1]
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
break
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
return token
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def parse(self):
|
|
Packit |
423ecb |
self.warning("Parsing %s" % (self.filename))
|
|
Packit |
423ecb |
token = self.token()
|
|
Packit |
423ecb |
while token != None:
|
|
Packit |
423ecb |
if token[0] == 'name':
|
|
Packit |
423ecb |
token = self.parseGlobal(token)
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.error("token %s %s unexpected at the top level" % (
|
|
Packit |
423ecb |
token[0], token[1]))
|
|
Packit |
423ecb |
token = self.parseGlobal(token)
|
|
Packit |
423ecb |
return
|
|
Packit |
423ecb |
self.parseTopComment(self.top_comment)
|
|
Packit |
423ecb |
return self.index
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
class docBuilder:
|
|
Packit |
423ecb |
"""A documentation builder"""
|
|
Packit |
423ecb |
def __init__(self, name, directories=['.'], excludes=[]):
|
|
Packit |
423ecb |
self.name = name
|
|
Packit |
423ecb |
self.directories = directories
|
|
Packit |
423ecb |
self.excludes = excludes + list(ignored_files.keys())
|
|
Packit |
423ecb |
self.modules = {}
|
|
Packit |
423ecb |
self.headers = {}
|
|
Packit |
423ecb |
self.idx = index()
|
|
Packit |
423ecb |
self.xref = {}
|
|
Packit |
423ecb |
self.index = {}
|
|
Packit |
423ecb |
if name == 'libxml2':
|
|
Packit |
423ecb |
self.basename = 'libxml'
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.basename = name
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def indexString(self, id, str):
|
|
Packit |
423ecb |
if str == None:
|
|
Packit |
423ecb |
return
|
|
Packit |
423ecb |
str = str.replace("'", ' ')
|
|
Packit |
423ecb |
str = str.replace('"', ' ')
|
|
Packit |
423ecb |
str = str.replace("/", ' ')
|
|
Packit |
423ecb |
str = str.replace('*', ' ')
|
|
Packit |
423ecb |
str = str.replace("[", ' ')
|
|
Packit |
423ecb |
str = str.replace("]", ' ')
|
|
Packit |
423ecb |
str = str.replace("(", ' ')
|
|
Packit |
423ecb |
str = str.replace(")", ' ')
|
|
Packit |
423ecb |
str = str.replace("<", ' ')
|
|
Packit |
423ecb |
str = str.replace('>', ' ')
|
|
Packit |
423ecb |
str = str.replace("&", ' ')
|
|
Packit |
423ecb |
str = str.replace('#', ' ')
|
|
Packit |
423ecb |
str = str.replace(",", ' ')
|
|
Packit |
423ecb |
str = str.replace('.', ' ')
|
|
Packit |
423ecb |
str = str.replace(';', ' ')
|
|
Packit |
423ecb |
tokens = str.split()
|
|
Packit |
423ecb |
for token in tokens:
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
c = token[0]
|
|
Packit |
423ecb |
if string.ascii_letters.find(c) < 0:
|
|
Packit |
423ecb |
pass
|
|
Packit |
423ecb |
elif len(token) < 3:
|
|
Packit |
423ecb |
pass
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
lower = token.lower()
|
|
Packit |
423ecb |
# TODO: generalize this a bit
|
|
Packit |
423ecb |
if lower == 'and' or lower == 'the':
|
|
Packit |
423ecb |
pass
|
|
Packit |
423ecb |
elif token in self.xref:
|
|
Packit |
423ecb |
self.xref[token].append(id)
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
self.xref[token] = [id]
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
pass
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def analyze(self):
|
|
Packit |
423ecb |
print("Project %s : %d headers, %d modules" % (self.name, len(list(self.headers.keys())), len(list(self.modules.keys()))))
|
|
Packit |
423ecb |
self.idx.analyze()
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def scanHeaders(self):
|
|
Packit |
423ecb |
for header in list(self.headers.keys()):
|
|
Packit |
423ecb |
parser = CParser(header)
|
|
Packit |
423ecb |
idx = parser.parse()
|
|
Packit |
423ecb |
self.headers[header] = idx;
|
|
Packit |
423ecb |
self.idx.merge(idx)
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def scanModules(self):
|
|
Packit |
423ecb |
for module in list(self.modules.keys()):
|
|
Packit |
423ecb |
parser = CParser(module)
|
|
Packit |
423ecb |
idx = parser.parse()
|
|
Packit |
423ecb |
# idx.analyze()
|
|
Packit |
423ecb |
self.modules[module] = idx
|
|
Packit |
423ecb |
self.idx.merge_public(idx)
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def scan(self):
|
|
Packit |
423ecb |
for directory in self.directories:
|
|
Packit |
423ecb |
files = glob.glob(directory + "/*.c")
|
|
Packit |
423ecb |
for file in files:
|
|
Packit |
423ecb |
skip = 0
|
|
Packit |
423ecb |
for excl in self.excludes:
|
|
Packit |
423ecb |
if file.find(excl) != -1:
|
|
Packit |
423ecb |
print("Skipping %s" % file)
|
|
Packit |
423ecb |
skip = 1
|
|
Packit |
423ecb |
break
|
|
Packit |
423ecb |
if skip == 0:
|
|
Packit |
423ecb |
self.modules[file] = None;
|
|
Packit |
423ecb |
files = glob.glob(directory + "/*.h")
|
|
Packit |
423ecb |
for file in files:
|
|
Packit |
423ecb |
skip = 0
|
|
Packit |
423ecb |
for excl in self.excludes:
|
|
Packit |
423ecb |
if file.find(excl) != -1:
|
|
Packit |
423ecb |
print("Skipping %s" % file)
|
|
Packit |
423ecb |
skip = 1
|
|
Packit |
423ecb |
break
|
|
Packit |
423ecb |
if skip == 0:
|
|
Packit |
423ecb |
self.headers[file] = None;
|
|
Packit |
423ecb |
self.scanHeaders()
|
|
Packit |
423ecb |
self.scanModules()
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def modulename_file(self, file):
|
|
Packit |
423ecb |
module = os.path.basename(file)
|
|
Packit |
423ecb |
if module[-2:] == '.h':
|
|
Packit |
423ecb |
module = module[:-2]
|
|
Packit |
423ecb |
elif module[-2:] == '.c':
|
|
Packit |
423ecb |
module = module[:-2]
|
|
Packit |
423ecb |
return module
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def serialize_enum(self, output, name):
|
|
Packit |
423ecb |
id = self.idx.enums[name]
|
|
Packit |
423ecb |
output.write("
|
|
Packit |
423ecb |
self.modulename_file(id.header)))
|
|
Packit |
423ecb |
if id.info != None:
|
|
Packit |
423ecb |
info = id.info
|
|
Packit |
423ecb |
if info[0] != None and info[0] != '':
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
val = eval(info[0])
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
val = info[0]
|
|
Packit |
423ecb |
output.write(" value='%s'" % (val));
|
|
Packit |
423ecb |
if info[2] != None and info[2] != '':
|
|
Packit |
423ecb |
output.write(" type='%s'" % info[2]);
|
|
Packit |
423ecb |
if info[1] != None and info[1] != '':
|
|
Packit |
423ecb |
output.write(" info='%s'" % escape(info[1]));
|
|
Packit |
423ecb |
output.write("/>\n")
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def serialize_macro(self, output, name):
|
|
Packit |
423ecb |
id = self.idx.macros[name]
|
|
Packit |
423ecb |
output.write(" <macro name='%s' file='%s'>\n" % (name,
|
|
Packit |
423ecb |
self.modulename_file(id.header)))
|
|
Packit |
423ecb |
if id.info != None:
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
(args, desc) = id.info
|
|
Packit |
423ecb |
if desc != None and desc != "":
|
|
Packit |
423ecb |
output.write(" <info>%s</info>\n" % (escape(desc)))
|
|
Packit |
423ecb |
self.indexString(name, desc)
|
|
Packit |
423ecb |
for arg in args:
|
|
Packit |
423ecb |
(name, desc) = arg
|
|
Packit |
423ecb |
if desc != None and desc != "":
|
|
Packit |
423ecb |
output.write(" <arg name='%s' info='%s'/>\n" % (
|
|
Packit |
423ecb |
name, escape(desc)))
|
|
Packit |
423ecb |
self.indexString(name, desc)
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
output.write(" <arg name='%s'/>\n" % (name))
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
pass
|
|
Packit |
423ecb |
output.write(" </macro>\n")
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def serialize_typedef(self, output, name):
|
|
Packit |
423ecb |
id = self.idx.typedefs[name]
|
|
Packit |
423ecb |
if id.info[0:7] == 'struct ':
|
|
Packit |
423ecb |
output.write("
|
|
Packit |
423ecb |
name, self.modulename_file(id.header), id.info))
|
|
Packit |
423ecb |
name = id.info[7:]
|
|
Packit |
423ecb |
if name in self.idx.structs and ( \
|
|
Packit |
423ecb |
type(self.idx.structs[name].info) == type(()) or
|
|
Packit |
423ecb |
type(self.idx.structs[name].info) == type([])):
|
|
Packit |
423ecb |
output.write(">\n");
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
for field in self.idx.structs[name].info:
|
|
Packit |
423ecb |
desc = field[2]
|
|
Packit |
423ecb |
self.indexString(name, desc)
|
|
Packit |
423ecb |
if desc == None:
|
|
Packit |
423ecb |
desc = ''
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
desc = escape(desc)
|
|
Packit |
423ecb |
output.write(" <field name='%s' type='%s' info='%s'/>\n" % (field[1] , field[0], desc))
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
print("Failed to serialize struct %s" % (name))
|
|
Packit |
423ecb |
output.write(" </struct>\n")
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
output.write("/>\n");
|
|
Packit |
423ecb |
else :
|
|
Packit |
423ecb |
output.write("
|
|
Packit |
423ecb |
name, self.modulename_file(id.header), id.info))
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
desc = id.extra
|
|
Packit |
423ecb |
if desc != None and desc != "":
|
|
Packit |
423ecb |
output.write(">\n <info>%s</info>\n" % (escape(desc)))
|
|
Packit |
423ecb |
output.write(" </typedef>\n")
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
output.write("/>\n")
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
output.write("/>\n")
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def serialize_variable(self, output, name):
|
|
Packit |
423ecb |
id = self.idx.variables[name]
|
|
Packit |
423ecb |
if id.info != None:
|
|
Packit |
423ecb |
output.write(" <variable name='%s' file='%s' type='%s'/>\n" % (
|
|
Packit |
423ecb |
name, self.modulename_file(id.header), id.info))
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
output.write(" <variable name='%s' file='%s'/>\n" % (
|
|
Packit |
423ecb |
name, self.modulename_file(id.header)))
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def serialize_function(self, output, name):
|
|
Packit |
423ecb |
id = self.idx.functions[name]
|
|
Packit |
423ecb |
if name == debugsym:
|
|
Packit |
423ecb |
print("=>", id)
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
output.write(" <%s name='%s' file='%s' module='%s'>\n" % (id.type,
|
|
Packit |
423ecb |
name, self.modulename_file(id.header),
|
|
Packit |
423ecb |
self.modulename_file(id.module)))
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# Processing of conditionals modified by Bill 1/1/05
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
if id.conditionals != None:
|
|
Packit |
423ecb |
apstr = ""
|
|
Packit |
423ecb |
for cond in id.conditionals:
|
|
Packit |
423ecb |
if apstr != "":
|
|
Packit |
423ecb |
apstr = apstr + " && "
|
|
Packit |
423ecb |
apstr = apstr + cond
|
|
Packit |
423ecb |
output.write(" <cond>%s</cond>\n"% (apstr));
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
(ret, params, desc) = id.info
|
|
Packit |
423ecb |
if (desc == None or desc == '') and \
|
|
Packit |
423ecb |
name[0:9] != "xmlThrDef" and name != "xmlDllMain":
|
|
Packit |
423ecb |
print("%s %s from %s has no description" % (id.type, name,
|
|
Packit |
423ecb |
self.modulename_file(id.module)))
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
output.write(" <info>%s</info>\n" % (escape(desc)))
|
|
Packit |
423ecb |
self.indexString(name, desc)
|
|
Packit |
423ecb |
if ret[0] != None:
|
|
Packit |
423ecb |
if ret[0] == "void":
|
|
Packit |
423ecb |
output.write(" <return type='void'/>\n")
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
output.write(" <return type='%s' info='%s'/>\n" % (
|
|
Packit |
423ecb |
ret[0], escape(ret[1])))
|
|
Packit |
423ecb |
self.indexString(name, ret[1])
|
|
Packit |
423ecb |
for param in params:
|
|
Packit |
423ecb |
if param[0] == 'void':
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
if param[2] == None:
|
|
Packit |
423ecb |
output.write(" <arg name='%s' type='%s' info=''/>\n" % (param[1], param[0]))
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
output.write(" <arg name='%s' type='%s' info='%s'/>\n" % (param[1], param[0], escape(param[2])))
|
|
Packit |
423ecb |
self.indexString(name, param[2])
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
print("Failed to save function %s info: " % name, repr(id.info))
|
|
Packit |
423ecb |
output.write(" </%s>\n" % (id.type))
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def serialize_exports(self, output, file):
|
|
Packit |
423ecb |
module = self.modulename_file(file)
|
|
Packit |
423ecb |
output.write(" <file name='%s'>\n" % (module))
|
|
Packit |
423ecb |
dict = self.headers[file]
|
|
Packit |
423ecb |
if dict.info != None:
|
|
Packit |
423ecb |
for data in ('Summary', 'Description', 'Author'):
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
output.write(" <%s>%s</%s>\n" % (
|
|
Packit |
423ecb |
data.lower(),
|
|
Packit |
423ecb |
escape(dict.info[data]),
|
|
Packit |
423ecb |
data.lower()))
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
print("Header %s lacks a %s description" % (module, data))
|
|
Packit |
423ecb |
if 'Description' in dict.info:
|
|
Packit |
423ecb |
desc = dict.info['Description']
|
|
Packit |
423ecb |
if desc.find("DEPRECATED") != -1:
|
|
Packit |
423ecb |
output.write(" <deprecated/>\n")
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
ids = list(dict.macros.keys())
|
|
Packit |
423ecb |
ids.sort()
|
|
Packit |
423ecb |
for id in uniq(ids):
|
|
Packit |
423ecb |
# Macros are sometime used to masquerade other types.
|
|
Packit |
423ecb |
if id in dict.functions:
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
if id in dict.variables:
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
if id in dict.typedefs:
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
if id in dict.structs:
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
if id in dict.enums:
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
output.write(" <exports symbol='%s' type='macro'/>\n" % (id))
|
|
Packit |
423ecb |
ids = list(dict.enums.keys())
|
|
Packit |
423ecb |
ids.sort()
|
|
Packit |
423ecb |
for id in uniq(ids):
|
|
Packit |
423ecb |
output.write(" <exports symbol='%s' type='enum'/>\n" % (id))
|
|
Packit |
423ecb |
ids = list(dict.typedefs.keys())
|
|
Packit |
423ecb |
ids.sort()
|
|
Packit |
423ecb |
for id in uniq(ids):
|
|
Packit |
423ecb |
output.write(" <exports symbol='%s' type='typedef'/>\n" % (id))
|
|
Packit |
423ecb |
ids = list(dict.structs.keys())
|
|
Packit |
423ecb |
ids.sort()
|
|
Packit |
423ecb |
for id in uniq(ids):
|
|
Packit |
423ecb |
output.write(" <exports symbol='%s' type='struct'/>\n" % (id))
|
|
Packit |
423ecb |
ids = list(dict.variables.keys())
|
|
Packit |
423ecb |
ids.sort()
|
|
Packit |
423ecb |
for id in uniq(ids):
|
|
Packit |
423ecb |
output.write(" <exports symbol='%s' type='variable'/>\n" % (id))
|
|
Packit |
423ecb |
ids = list(dict.functions.keys())
|
|
Packit |
423ecb |
ids.sort()
|
|
Packit |
423ecb |
for id in uniq(ids):
|
|
Packit |
423ecb |
output.write(" <exports symbol='%s' type='function'/>\n" % (id))
|
|
Packit |
423ecb |
output.write(" </file>\n")
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def serialize_xrefs_files(self, output):
|
|
Packit |
423ecb |
headers = list(self.headers.keys())
|
|
Packit |
423ecb |
headers.sort()
|
|
Packit |
423ecb |
for file in headers:
|
|
Packit |
423ecb |
module = self.modulename_file(file)
|
|
Packit |
423ecb |
output.write(" <file name='%s'>\n" % (module))
|
|
Packit |
423ecb |
dict = self.headers[file]
|
|
Packit |
423ecb |
ids = uniq(list(dict.functions.keys()) + list(dict.variables.keys()) + \
|
|
Packit |
423ecb |
list(dict.macros.keys()) + list(dict.typedefs.keys()) + \
|
|
Packit |
423ecb |
list(dict.structs.keys()) + list(dict.enums.keys()))
|
|
Packit |
423ecb |
ids.sort()
|
|
Packit |
423ecb |
for id in ids:
|
|
Packit |
423ecb |
output.write(" <ref name='%s'/>\n" % (id))
|
|
Packit |
423ecb |
output.write(" </file>\n")
|
|
Packit |
423ecb |
pass
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def serialize_xrefs_functions(self, output):
|
|
Packit |
423ecb |
funcs = {}
|
|
Packit |
423ecb |
for name in list(self.idx.functions.keys()):
|
|
Packit |
423ecb |
id = self.idx.functions[name]
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
(ret, params, desc) = id.info
|
|
Packit |
423ecb |
for param in params:
|
|
Packit |
423ecb |
if param[0] == 'void':
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
if param[0] in funcs:
|
|
Packit |
423ecb |
funcs[param[0]].append(name)
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
funcs[param[0]] = [name]
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
pass
|
|
Packit |
423ecb |
typ = list(funcs.keys())
|
|
Packit |
423ecb |
typ.sort()
|
|
Packit |
423ecb |
for type in typ:
|
|
Packit |
423ecb |
if type == '' or type == 'void' or type == "int" or \
|
|
Packit |
423ecb |
type == "char *" or type == "const char *" :
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
output.write(" <type name='%s'>\n" % (type))
|
|
Packit |
423ecb |
ids = funcs[type]
|
|
Packit |
423ecb |
ids.sort()
|
|
Packit |
423ecb |
pid = '' # not sure why we have dups, but get rid of them!
|
|
Packit |
423ecb |
for id in ids:
|
|
Packit |
423ecb |
if id != pid:
|
|
Packit |
423ecb |
output.write(" <ref name='%s'/>\n" % (id))
|
|
Packit |
423ecb |
pid = id
|
|
Packit |
423ecb |
output.write(" </type>\n")
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def serialize_xrefs_constructors(self, output):
|
|
Packit |
423ecb |
funcs = {}
|
|
Packit |
423ecb |
for name in list(self.idx.functions.keys()):
|
|
Packit |
423ecb |
id = self.idx.functions[name]
|
|
Packit |
423ecb |
try:
|
|
Packit |
423ecb |
(ret, params, desc) = id.info
|
|
Packit |
423ecb |
if ret[0] == "void":
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
if ret[0] in funcs:
|
|
Packit |
423ecb |
funcs[ret[0]].append(name)
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
funcs[ret[0]] = [name]
|
|
Packit |
423ecb |
except:
|
|
Packit |
423ecb |
pass
|
|
Packit |
423ecb |
typ = list(funcs.keys())
|
|
Packit |
423ecb |
typ.sort()
|
|
Packit |
423ecb |
for type in typ:
|
|
Packit |
423ecb |
if type == '' or type == 'void' or type == "int" or \
|
|
Packit |
423ecb |
type == "char *" or type == "const char *" :
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
output.write(" <type name='%s'>\n" % (type))
|
|
Packit |
423ecb |
ids = funcs[type]
|
|
Packit |
423ecb |
ids.sort()
|
|
Packit |
423ecb |
for id in ids:
|
|
Packit |
423ecb |
output.write(" <ref name='%s'/>\n" % (id))
|
|
Packit |
423ecb |
output.write(" </type>\n")
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def serialize_xrefs_alpha(self, output):
|
|
Packit |
423ecb |
letter = None
|
|
Packit |
423ecb |
ids = list(self.idx.identifiers.keys())
|
|
Packit |
423ecb |
ids.sort()
|
|
Packit |
423ecb |
for id in ids:
|
|
Packit |
423ecb |
if id[0] != letter:
|
|
Packit |
423ecb |
if letter != None:
|
|
Packit |
423ecb |
output.write(" </letter>\n")
|
|
Packit |
423ecb |
letter = id[0]
|
|
Packit |
423ecb |
output.write(" <letter name='%s'>\n" % (letter))
|
|
Packit |
423ecb |
output.write(" <ref name='%s'/>\n" % (id))
|
|
Packit |
423ecb |
if letter != None:
|
|
Packit |
423ecb |
output.write(" </letter>\n")
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def serialize_xrefs_references(self, output):
|
|
Packit |
423ecb |
typ = list(self.idx.identifiers.keys())
|
|
Packit |
423ecb |
typ.sort()
|
|
Packit |
423ecb |
for id in typ:
|
|
Packit |
423ecb |
idf = self.idx.identifiers[id]
|
|
Packit |
423ecb |
module = idf.header
|
|
Packit |
423ecb |
output.write(" <reference name='%s' href='%s'/>\n" % (id,
|
|
Packit |
423ecb |
'html/' + self.basename + '-' +
|
|
Packit |
423ecb |
self.modulename_file(module) + '.html#' +
|
|
Packit |
423ecb |
id))
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def serialize_xrefs_index(self, output):
|
|
Packit |
423ecb |
index = self.xref
|
|
Packit |
423ecb |
typ = list(index.keys())
|
|
Packit |
423ecb |
typ.sort()
|
|
Packit |
423ecb |
letter = None
|
|
Packit |
423ecb |
count = 0
|
|
Packit |
423ecb |
chunk = 0
|
|
Packit |
423ecb |
chunks = []
|
|
Packit |
423ecb |
for id in typ:
|
|
Packit |
423ecb |
if len(index[id]) > 30:
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
if id[0] != letter:
|
|
Packit |
423ecb |
if letter == None or count > 200:
|
|
Packit |
423ecb |
if letter != None:
|
|
Packit |
423ecb |
output.write(" </letter>\n")
|
|
Packit |
423ecb |
output.write(" </chunk>\n")
|
|
Packit |
423ecb |
count = 0
|
|
Packit |
423ecb |
chunks.append(["chunk%s" % (chunk -1), first_letter, letter])
|
|
Packit |
423ecb |
output.write(" <chunk name='chunk%s'>\n" % (chunk))
|
|
Packit |
423ecb |
first_letter = id[0]
|
|
Packit |
423ecb |
chunk = chunk + 1
|
|
Packit |
423ecb |
elif letter != None:
|
|
Packit |
423ecb |
output.write(" </letter>\n")
|
|
Packit |
423ecb |
letter = id[0]
|
|
Packit |
423ecb |
output.write(" <letter name='%s'>\n" % (letter))
|
|
Packit |
423ecb |
output.write(" <word name='%s'>\n" % (id))
|
|
Packit |
423ecb |
tokens = index[id];
|
|
Packit |
423ecb |
tokens.sort()
|
|
Packit |
423ecb |
tok = None
|
|
Packit |
423ecb |
for token in tokens:
|
|
Packit |
423ecb |
if tok == token:
|
|
Packit |
423ecb |
continue
|
|
Packit |
423ecb |
tok = token
|
|
Packit |
423ecb |
output.write(" <ref name='%s'/>\n" % (token))
|
|
Packit |
423ecb |
count = count + 1
|
|
Packit |
423ecb |
output.write(" </word>\n")
|
|
Packit |
423ecb |
if letter != None:
|
|
Packit |
423ecb |
output.write(" </letter>\n")
|
|
Packit |
423ecb |
output.write(" </chunk>\n")
|
|
Packit |
423ecb |
if count != 0:
|
|
Packit |
423ecb |
chunks.append(["chunk%s" % (chunk -1), first_letter, letter])
|
|
Packit |
423ecb |
output.write(" <chunks>\n")
|
|
Packit |
423ecb |
for ch in chunks:
|
|
Packit |
423ecb |
output.write(" <chunk name='%s' start='%s' end='%s'/>\n" % (
|
|
Packit |
423ecb |
ch[0], ch[1], ch[2]))
|
|
Packit |
423ecb |
output.write(" </chunks>\n")
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def serialize_xrefs(self, output):
|
|
Packit |
423ecb |
output.write(" <references>\n")
|
|
Packit |
423ecb |
self.serialize_xrefs_references(output)
|
|
Packit |
423ecb |
output.write(" </references>\n")
|
|
Packit |
423ecb |
output.write(" <alpha>\n")
|
|
Packit |
423ecb |
self.serialize_xrefs_alpha(output)
|
|
Packit |
423ecb |
output.write(" </alpha>\n")
|
|
Packit |
423ecb |
output.write(" <constructors>\n")
|
|
Packit |
423ecb |
self.serialize_xrefs_constructors(output)
|
|
Packit |
423ecb |
output.write(" </constructors>\n")
|
|
Packit |
423ecb |
output.write(" <functions>\n")
|
|
Packit |
423ecb |
self.serialize_xrefs_functions(output)
|
|
Packit |
423ecb |
output.write(" </functions>\n")
|
|
Packit |
423ecb |
output.write(" <files>\n")
|
|
Packit |
423ecb |
self.serialize_xrefs_files(output)
|
|
Packit |
423ecb |
output.write(" </files>\n")
|
|
Packit |
423ecb |
output.write(" <index>\n")
|
|
Packit |
423ecb |
self.serialize_xrefs_index(output)
|
|
Packit |
423ecb |
output.write(" </index>\n")
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def serialize(self):
|
|
Packit |
423ecb |
filename = "%s-api.xml" % self.name
|
|
Packit |
423ecb |
print("Saving XML description %s" % (filename))
|
|
Packit |
423ecb |
output = open(filename, "w")
|
|
Packit |
423ecb |
output.write('\n')
|
|
Packit |
423ecb |
output.write("<api name='%s'>\n" % self.name)
|
|
Packit |
423ecb |
output.write(" <files>\n")
|
|
Packit |
423ecb |
headers = list(self.headers.keys())
|
|
Packit |
423ecb |
headers.sort()
|
|
Packit |
423ecb |
for file in headers:
|
|
Packit |
423ecb |
self.serialize_exports(output, file)
|
|
Packit |
423ecb |
output.write(" </files>\n")
|
|
Packit |
423ecb |
output.write(" <symbols>\n")
|
|
Packit |
423ecb |
macros = list(self.idx.macros.keys())
|
|
Packit |
423ecb |
macros.sort()
|
|
Packit |
423ecb |
for macro in macros:
|
|
Packit |
423ecb |
self.serialize_macro(output, macro)
|
|
Packit |
423ecb |
enums = list(self.idx.enums.keys())
|
|
Packit |
423ecb |
enums.sort()
|
|
Packit |
423ecb |
for enum in enums:
|
|
Packit |
423ecb |
self.serialize_enum(output, enum)
|
|
Packit |
423ecb |
typedefs = list(self.idx.typedefs.keys())
|
|
Packit |
423ecb |
typedefs.sort()
|
|
Packit |
423ecb |
for typedef in typedefs:
|
|
Packit |
423ecb |
self.serialize_typedef(output, typedef)
|
|
Packit |
423ecb |
variables = list(self.idx.variables.keys())
|
|
Packit |
423ecb |
variables.sort()
|
|
Packit |
423ecb |
for variable in variables:
|
|
Packit |
423ecb |
self.serialize_variable(output, variable)
|
|
Packit |
423ecb |
functions = list(self.idx.functions.keys())
|
|
Packit |
423ecb |
functions.sort()
|
|
Packit |
423ecb |
for function in functions:
|
|
Packit |
423ecb |
self.serialize_function(output, function)
|
|
Packit |
423ecb |
output.write(" </symbols>\n")
|
|
Packit |
423ecb |
output.write("</api>\n")
|
|
Packit |
423ecb |
output.close()
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
filename = "%s-refs.xml" % self.name
|
|
Packit |
423ecb |
print("Saving XML Cross References %s" % (filename))
|
|
Packit |
423ecb |
output = open(filename, "w")
|
|
Packit |
423ecb |
output.write('\n')
|
|
Packit |
423ecb |
output.write("<apirefs name='%s'>\n" % self.name)
|
|
Packit |
423ecb |
self.serialize_xrefs(output)
|
|
Packit |
423ecb |
output.write("</apirefs>\n")
|
|
Packit |
423ecb |
output.close()
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
def rebuild():
|
|
Packit |
423ecb |
builder = None
|
|
Packit |
423ecb |
if glob.glob("parser.c") != [] :
|
|
Packit |
423ecb |
print("Rebuilding API description for libxml2")
|
|
Packit |
423ecb |
builder = docBuilder("libxml2", [".", "."],
|
|
Packit |
423ecb |
["xmlwin32version.h", "tst.c"])
|
|
Packit |
423ecb |
elif glob.glob("../parser.c") != [] :
|
|
Packit |
423ecb |
print("Rebuilding API description for libxml2")
|
|
Packit |
423ecb |
builder = docBuilder("libxml2", ["..", "../include/libxml"],
|
|
Packit |
423ecb |
["xmlwin32version.h", "tst.c"])
|
|
Packit |
423ecb |
elif glob.glob("../libxslt/transform.c") != [] :
|
|
Packit |
423ecb |
print("Rebuilding API description for libxslt")
|
|
Packit |
423ecb |
builder = docBuilder("libxslt", ["../libxslt"],
|
|
Packit |
423ecb |
["win32config.h", "libxslt.h", "tst.c"])
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
print("rebuild() failed, unable to guess the module")
|
|
Packit |
423ecb |
return None
|
|
Packit |
423ecb |
builder.scan()
|
|
Packit |
423ecb |
builder.analyze()
|
|
Packit |
423ecb |
builder.serialize()
|
|
Packit |
423ecb |
if glob.glob("../libexslt/exslt.c") != [] :
|
|
Packit |
423ecb |
extra = docBuilder("libexslt", ["../libexslt"], ["libexslt.h"])
|
|
Packit |
423ecb |
extra.scan()
|
|
Packit |
423ecb |
extra.analyze()
|
|
Packit |
423ecb |
extra.serialize()
|
|
Packit |
423ecb |
return builder
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
# for debugging the parser
|
|
Packit |
423ecb |
#
|
|
Packit |
423ecb |
def parse(filename):
|
|
Packit |
423ecb |
parser = CParser(filename)
|
|
Packit |
423ecb |
idx = parser.parse()
|
|
Packit |
423ecb |
return idx
|
|
Packit |
423ecb |
|
|
Packit |
423ecb |
if __name__ == "__main__":
|
|
Packit |
423ecb |
if len(sys.argv) > 1:
|
|
Packit |
423ecb |
debug = 1
|
|
Packit |
423ecb |
parse(sys.argv[1])
|
|
Packit |
423ecb |
else:
|
|
Packit |
423ecb |
rebuild()
|