📄 apibuild.py
字号:
#!/usr/bin/python -u## This is the API builder, it parses the C sources and build the# API formal description in XML.## See Copyright for the status of this software.## daniel@veillard.com#import os, sysimport stringimport globdebug=0#debugsym='ignorableWhitespaceSAXFunc'debugsym=None## C parser analysis code#ignored_files = { "trio": "too many non standard macros", "trio.c": "too many non standard macros", "trionan.c": "too many non standard macros", "triostr.c": "too many non standard macros", "acconfig.h": "generated portability layer", "config.h": "generated portability layer", "libxml.h": "internal only", "testOOM.c": "out of memory tester", "testOOMlib.h": "out of memory tester", "testOOMlib.c": "out of memory tester", "rngparser.c": "not yet integrated", "rngparser.h": "not yet integrated", "elfgcchack.h": "not a normal header", "testapi.c": "generated regression tests", "tst.c": "not part of the library", "testdso.c": "test for dynamid shared libraries",}ignored_words = { "WINAPI": (0, "Windows keyword"), "LIBXML_DLL_IMPORT": (0, "Special macro to flag external keywords"), "XMLPUBVAR": (0, "Special macro for extern vars for win32"), "XSLTPUBVAR": (0, "Special macro for extern vars for win32"), "EXSLTPUBVAR": (0, "Special macro for extern vars for win32"), "XMLPUBFUN": (0, "Special macro for extern funcs for win32"), "XSLTPUBFUN": (0, "Special macro for extern funcs for win32"), "EXSLTPUBFUN": (0, "Special macro for extern funcs for win32"), "XMLCALL": (0, "Special macro for win32 calls"), "XSLTCALL": (0, "Special macro for win32 calls"), "EXSLTCALL": (0, "Special macro for win32 calls"), "__declspec": (3, "Windows keyword"), "__stdcall": (0, "Windows keyword"), "ATTRIBUTE_UNUSED": (0, "macro keyword"), "LIBEXSLT_PUBLIC": (0, "macro keyword"), "X_IN_Y": (5, "macro function builder"),}def escape(raw): raw = string.replace(raw, '&', '&') raw = string.replace(raw, '<', '<') raw = string.replace(raw, '>', '>') raw = string.replace(raw, "'", ''') raw = string.replace(raw, '"', '"') return rawdef uniq(items): d = {} for item in items: d[item]=1 return d.keys()class identifier: def __init__(self, name, header=None, module=None, type=None, lineno = 0, info=None, extra=None, conditionals = None): self.name = name self.header = header self.module = module self.type = type self.info = info self.extra = extra self.lineno = lineno self.static = 0 if conditionals == None or len(conditionals) == 0: self.conditionals = None else: self.conditionals = conditionals[:] if self.name == debugsym: print "=> define %s : %s" % (debugsym, (module, type, info, extra, conditionals)) def __repr__(self): r = "%s %s:" % (self.type, self.name) if self.static: r = r + " static" if self.module != None: r = r + " from %s" % (self.module) if self.info != None: r = r + " " + `self.info` if self.extra != None: r = r + " " + `self.extra` if self.conditionals != None: r = r + " " + `self.conditionals` return r def set_header(self, header): self.header = header def set_module(self, module): self.module = module def set_type(self, type): self.type = type def set_info(self, info): self.info = info def set_extra(self, extra): self.extra = extra def set_lineno(self, lineno): self.lineno = lineno def set_static(self, static): self.static = static def set_conditionals(self, conditionals): if conditionals == None or len(conditionals) == 0: self.conditionals = None else: self.conditionals = conditionals[:] def get_name(self): return self.name def get_header(self): return self.module def get_module(self): return self.module def get_type(self): return self.type def get_info(self): return self.info def get_lineno(self): return self.lineno def get_extra(self): return self.extra def get_static(self): return self.static def get_conditionals(self): return self.conditionals def update(self, header, module, type = None, info = None, extra=None, conditionals=None): if self.name == debugsym: print "=> update %s : %s" % (debugsym, (module, type, info, extra, conditionals)) if header != None and self.header == None: self.set_header(module) if module != None and (self.module == None or self.header == self.module): self.set_module(module) if type != None and self.type == None: self.set_type(type) if info != None: self.set_info(info) if extra != None: self.set_extra(extra) if conditionals != None: self.set_conditionals(conditionals)class index: def __init__(self, name = "noname"): self.name = name self.identifiers = {} self.functions = {} self.variables = {} self.includes = {} self.structs = {} self.enums = {} self.typedefs = {} self.macros = {} self.references = {} self.info = {} def add_ref(self, name, header, module, static, type, lineno, info=None, extra=None, conditionals = None): if name[0:2] == '__': return None d = None try: d = self.identifiers[name] d.update(header, module, type, lineno, info, extra, conditionals) except: d = identifier(name, header, module, type, lineno, info, extra, conditionals) self.identifiers[name] = d if d != None and static == 1: d.set_static(1) if d != None and name != None and type != None: self.references[name] = d if name == debugsym: print "New ref: %s" % (d) return d def add(self, name, header, module, static, type, lineno, info=None, extra=None, conditionals = None): if name[0:2] == '__': return None d = None try: d = self.identifiers[name] d.update(header, module, type, lineno, info, extra, conditionals) except: d = identifier(name, header, module, type, lineno, info, extra, conditionals) self.identifiers[name] = d if d != None and static == 1: d.set_static(1) if d != None and name != None and type != None: if type == "function": self.functions[name] = d elif type == "functype": self.functions[name] = d elif type == "variable": self.variables[name] = d elif type == "include": self.includes[name] = d elif type == "struct": self.structs[name] = d elif type == "enum": self.enums[name] = d elif type == "typedef": self.typedefs[name] = d elif type == "macro": self.macros[name] = d else: print "Unable to register type ", type if name == debugsym: print "New symbol: %s" % (d) return d def merge(self, idx): for id in idx.functions.keys(): # # macro might be used to override functions or variables # definitions # if self.macros.has_key(id): del self.macros[id] if self.functions.has_key(id): print "function %s from %s redeclared in %s" % ( id, self.functions[id].header, idx.functions[id].header) else: self.functions[id] = idx.functions[id] self.identifiers[id] = idx.functions[id] for id in idx.variables.keys(): # # macro might be used to override functions or variables # definitions # if self.macros.has_key(id): del self.macros[id] if self.variables.has_key(id): print "variable %s from %s redeclared in %s" % ( id, self.variables[id].header, idx.variables[id].header) else: self.variables[id] = idx.variables[id] self.identifiers[id] = idx.variables[id] for id in idx.structs.keys(): if self.structs.has_key(id): print "struct %s from %s redeclared in %s" % ( id, self.structs[id].header, idx.structs[id].header) else: self.structs[id] = idx.structs[id] self.identifiers[id] = idx.structs[id] for id in idx.typedefs.keys(): if self.typedefs.has_key(id): print "typedef %s from %s redeclared in %s" % ( id, self.typedefs[id].header, idx.typedefs[id].header) else: self.typedefs[id] = idx.typedefs[id] self.identifiers[id] = idx.typedefs[id] for id in idx.macros.keys(): # # macro might be used to override functions or variables # definitions # if self.variables.has_key(id): continue if self.functions.has_key(id): continue if self.enums.has_key(id): continue if self.macros.has_key(id): print "macro %s from %s redeclared in %s" % ( id, self.macros[id].header, idx.macros[id].header) else: self.macros[id] = idx.macros[id] self.identifiers[id] = idx.macros[id] for id in idx.enums.keys(): if self.enums.has_key(id): print "enum %s from %s redeclared in %s" % ( id, self.enums[id].header, idx.enums[id].header) else: self.enums[id] = idx.enums[id] self.identifiers[id] = idx.enums[id] def merge_public(self, idx): for id in idx.functions.keys(): if self.functions.has_key(id): # check that function condition agrees with header if idx.functions[id].conditionals != \ self.functions[id].conditionals: print "Header condition differs from Function for %s:" \ % id print " H: %s" % self.functions[id].conditionals print " C: %s" % idx.functions[id].conditionals up = idx.functions[id] self.functions[id].update(None, up.module, up.type, up.info, up.extra) # else: # print "Function %s from %s is not declared in headers" % ( # id, idx.functions[id].module) # TODO: do the same for variables. def analyze_dict(self, type, dict): count = 0 public = 0 for name in dict.keys(): id = dict[name] count = count + 1 if id.static == 0: public = public + 1 if count != public: print " %d %s , %d public" % (count, type, public) elif count != 0: print " %d public %s" % (count, type) def analyze(self): self.analyze_dict("functions", self.functions) self.analyze_dict("variables", self.variables) self.analyze_dict("structs", self.structs) self.analyze_dict("typedefs", self.typedefs) self.analyze_dict("macros", self.macros) class CLexer: """A lexer for the C language, tokenize the input by reading and analyzing it line by line""" def __init__(self, input): self.input = input self.tokens = [] self.line = "" self.lineno = 0 def getline(self): line = '' while line == '': line = self.input.readline() if not line: return None self.lineno = self.lineno + 1 line = string.lstrip(line) line = string.rstrip(line) if line == '': continue while line[-1] == '\\': line = line[:-1] n = self.input.readline() self.lineno = self.lineno + 1 n = string.lstrip(n) n = string.rstrip(n) if not n: break else: line = line + n return line def getlineno(self): return self.lineno def push(self, token): self.tokens.insert(0, token); def debug(self): print "Last token: ", self.last print "Token queue: ", self.tokens print "Line %d end: " % (self.lineno), self.line def token(self): while self.tokens == []: if self.line == "": line = self.getline() else: line = self.line self.line = "" if line == None: return None if line[0] == '#': self.tokens = map((lambda x: ('preproc', x)), string.split(line)) break; l = len(line) if line[0] == '"' or line[0] == "'": end = line[0] line = line[1:] found = 0 tok = "" while found == 0: i = 0 l = len(line) while i < l: if line[i] == end: self.line = line[i+1:]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -