def getFuncs(headerFiles): """Read a list of header files or gccxml files, return a dictionary of function signatures. If the file extension is .h, it will be converted to a temporary XML file (requires gccxml) before parsing If the file extension is .xml, it will be parsed directly Returns a dictionary of signatures like: {funcName: (returnType, [(arg1Name, arg1Type), ...]), ...} Types are given as ctypes. """ if type(headerFiles) is not types.ListType: headerFiles = [headerFiles] functions = {} for hf in headerFiles: if os.path.splitext(hf)[1] == '.h': try: xmlf = tempfile.mkstemp(".xml")[1] os.system("gccxml %s -fxml=%s" % (hf, xmlf)) except: print "Can not generate XML from header file, aborting" raise else: xmlf = hf #print "Parsing", xmlf xmlfData = gccxmlparser.parse(xmlf) for d in xmlfData: if type(d) is typedesc.Function and d.name[:9] != '__builtin': args = [] for arg in d.arguments: typ, ptr = getCType(arg.atype) args.append((arg.name, typ, ptr)) functions[d.name] = (getCType(d.returns), args) return functions
def generate_code( xmlfile, outfile, expressions=None, symbols=None, verbose=False, generate_comments=False, known_symbols=None, searched_dlls=None, types=None, preloaded_dlls=[], generate_docstrings=False, ): # expressions is a sequence of compiled regular expressions, # symbols is a sequence of names from gccxmlparser import parse items = parse(xmlfile) # filter symbols to generate todo = [] if types: items = [i for i in items if isinstance(i, types)] if symbols: syms = set(symbols) for i in items: if i.name in syms: todo.append(i) syms.remove(i.name) if syms: print "symbols not found", list(syms) if expressions: for i in items: for s in expressions: if i.name is None: continue match = s.match(i.name) # we only want complete matches if match and match.group() == i.name: todo.append(i) break if symbols or expressions: items = todo ################ gen = Generator(outfile, generate_comments=generate_comments, generate_docstrings=generate_docstrings, known_symbols=known_symbols, searched_dlls=searched_dlls, preloaded_dlls=preloaded_dlls) loops = gen.generate_code(items) if verbose: gen.print_stats(sys.stderr) print >> sys.stderr, "needed %d loop(s)" % loops
def find_types(self, include_files, defines): for i in range(20): source = [] for fname in include_files: source.append('#include "%s"' % fname) source.append( "#define DECLARE(sym) template <typename T> T symbol_##sym(T) {}" ) source.append("#define DEFINE(sym) symbol_##sym(sym)") for name in defines: # create a function template for each value source.append("DECLARE(%s)" % name) source.append("int main() {") for name in defines: # instantiate a function template. # The return type of the function is the symbol's type. source.append(" DEFINE(%s);" % name) source.append("}") fd, fname = tempfile.mkstemp(".xml") os.close(fd) invalid_symbols = self.try_create_xml(source, fname) if not invalid_symbols: break if self.options.verbose: if i == 0: print >> sys.stderr, "compiler errors caused by '-c' flag.\n" \ "Trying to resolve them in multiple passes." print >> sys.stderr, "pass %d:" % (i + 1) for n in invalid_symbols: del defines[n] if self.options.verbose: print >> sys.stderr, "\t", n else: raise CompilerError() items = gccxmlparser.parse(fname) # make sure the temporary file is removed after using it if not self.options.keep_temporary_files: os.remove(fname) else: print >> sys.stderr, "Info: file '%s' not removed" % fname types = {} for i in items: name = getattr(i, "name", None) if name and name.startswith("symbol_"): name = name[len("symbol_"):] typ = i.returns try: typ = self.c_type_name(i.returns) except TypeError, detail: # XXX Warning? ## print >> sys.stderr, "skipped #define %s %s" % (name, defines[name]), detail pass else: types[name] = typ
def generate_code(xmlfile, outfile, expressions=None, symbols=None, verbose=False, generate_comments=False, known_symbols=None, searched_dlls=None, types=None, preloaded_dlls=[], generate_docstrings=False,): # expressions is a sequence of compiled regular expressions, # symbols is a sequence of names from gccxmlparser import parse items = parse(xmlfile) # filter symbols to generate todo = [] if types: items = [i for i in items if isinstance(i, types)] if symbols: syms = set(symbols) for i in items: if i.name in syms: todo.append(i) syms.remove(i.name) if syms: print "symbols not found", list(syms) if expressions: for i in items: for s in expressions: if i.name is None: continue match = s.match(i.name) # we only want complete matches if match and match.group() == i.name: todo.append(i) break if symbols or expressions: items = todo ################ gen = Generator(outfile, generate_comments=generate_comments, generate_docstrings=generate_docstrings, known_symbols=known_symbols, searched_dlls=searched_dlls, preloaded_dlls=preloaded_dlls) loops = gen.generate_code(items) if verbose: gen.print_stats(sys.stderr) print >> sys.stderr, "needed %d loop(s)" % loops
def find_types(self, include_files, defines): for i in range(20): source = [] for fname in include_files: source.append('#include "%s"' % fname) source.append("#define DECLARE(sym) template <typename T> T symbol_##sym(T) {}") source.append("#define DEFINE(sym) symbol_##sym(sym)") for name in defines: # create a function template for each value source.append("DECLARE(%s)" % name) source.append("int main() {") for name in defines: # instantiate a function template. # The return type of the function is the symbol's type. source.append(" DEFINE(%s);" % name) source.append("}") fd, fname = tempfile.mkstemp(".xml") os.close(fd) invalid_symbols = self.try_create_xml(source, fname) if not invalid_symbols: break if self.options.verbose: if i == 0: print >> sys.stderr, "compiler errors caused by '-c' flag.\n" \ "Trying to resolve them in multiple passes." print >> sys.stderr, "pass %d:" % (i + 1) for n in invalid_symbols: del defines[n] if self.options.verbose: print >> sys.stderr, "\t", n else: raise CompilerError() items = gccxmlparser.parse(fname) # make sure the temporary file is removed after using it if not self.options.keep_temporary_files: os.remove(fname) else: print >> sys.stderr, "Info: file '%s' not removed" % fname types = {} for i in items: name = getattr(i, "name", None) if name and name.startswith("symbol_"): name = name[len("symbol_"):] typ = i.returns try: typ = self.c_type_name(i.returns) except TypeError, detail: # XXX Warning? ## print >> sys.stderr, "skipped #define %s %s" % (name, defines[name]), detail pass else: types[name] = typ
def query_items(xml): # XXX: support filter xml_items = parse(xml) #items = {} keep = set() named = {} locations = {} for it in xml_items: #items[it] = it keep.add(it) if hasattr(it, 'name'): named[it] = it.name if hasattr(it, 'location'): locations[it] = it.location return keep, named, locations