def test_format_C(configfile, c_header): c = conf.Config(configfile) conf.config = c defs = list(parse(c_header, tag="test")) x = ccore.from_db(defs[0]) assert x._is_macro assert x.show(form="C") == "#define MYCONST 0x10;" x = ccore.from_db(defs[5]) assert x._is_typedef assert x.show( form="C") == "typedef int (*foo)(int, char, unsigned int, void *);" x = ccore.from_db(defs[8]) assert x._is_typedef assert x.show(form="C") == "typedef void *(*(*foo2[2])(int, void **))[3];" x = ccore.from_db(defs[10]) assert x._is_struct assert (x.show(form="C") == """struct _mystruct { myinteger I; int tab[12]; unsigned char p[16]; short *s; struct _mystruct *next; foo func; struct _bar bar[2]; };""")
def test_format_ctypes(configfile, c_header): c = conf.Config(configfile) conf.config = c defs = list(parse(c_header, tag="test")) x = ccore.from_db(defs[0]) assert x._is_macro assert x.show(form="ctypes") == "MYCONST = 16" x = ccore.from_db(defs[5]) assert x._is_typedef assert (x.show(form="ctypes") == "foo = POINTER(CFUNCTYPE(c_int, c_int, c_byte, c_uint, c_void_p))") x = ccore.from_db(defs[8]) assert x._is_typedef assert (x.show( form="ctypes" ) == "foo2 = POINTER(CFUNCTYPE(POINTER(c_void_p*3), c_int, c_void_p))*2") x = ccore.from_db(defs[10]) assert x._is_struct assert (x.show(form="ctypes") == """struct__mystruct = type('struct__mystruct',(Structure,),{}) struct__mystruct._fields_ = [("I", myinteger), ("tab", c_int*12), ("p", c_ubyte*16), ("s", POINTER(c_short)), ("next", POINTER(struct__mystruct)), ("func", foo), ("bar", struct__bar*2)]""")
def test_format_amoco(configfile,c_header): c = conf.Config(configfile) conf.config = c defs = list(parse(c_header,tag='test')) x = ccore.from_db(defs[0]) assert x._is_macro assert x.show(form='amoco') == 'MYCONST = 0x10' x = ccore.from_db(defs[5]) assert x._is_typedef assert x.show(form='amoco') == "TypeDefine('foo','P')" x = ccore.from_db(defs[8]) assert x._is_typedef assert x.show(form='amoco') == "TypeDefine('foo2','P * 2')" x = ccore.from_db(defs[10]) assert x._is_struct assert x.show(form='amoco') == '@StructDefine("""\nmyinteger : I ;comment for field I\ni * 12 : tab ;modern comment for tab\ns * 16 : p ;\nP : s ;\nP : next ;\nfoo : func ;\nstruct__bar * 2 : bar ;\n""")\nclass struct__mystruct(StructFormatter):\n def __init__(self,data="",offset=0):\n if data: self.unpack(data,offset)\n '
def test_format_C(configfile,c_header): c = conf.Config(configfile) conf.config = c defs = list(parse(c_header,tag='test')) x = ccore.from_db(defs[0]) assert x._is_macro assert x.show(form='C') == '#define MYCONST 0x10;' x = ccore.from_db(defs[5]) assert x._is_typedef assert x.show(form='C') == 'typedef int (*foo)(int, char, unsigned int, void *);' x = ccore.from_db(defs[8]) assert x._is_typedef assert x.show(form='C') == 'typedef void *(*(*foo2[2])(int, void **))[3];' x = ccore.from_db(defs[10]) assert x._is_struct assert x.show(form='C') == """struct _mystruct {
def test_format_ctypes(configfile,c_header): c = conf.Config(configfile) conf.config = c defs = list(parse(c_header,tag='test')) x = ccore.from_db(defs[0]) assert x._is_macro assert x.show(form='ctypes') == 'MYCONST = 16' x = ccore.from_db(defs[5]) assert x._is_typedef assert x.show(form='ctypes') == 'foo = POINTER(CFUNCTYPE(c_int, c_int, c_byte, c_uint, c_void_p))' x = ccore.from_db(defs[8]) assert x._is_typedef assert x.show(form='ctypes') == 'foo2 = POINTER(CFUNCTYPE(POINTER(c_void_p*3), c_int, c_void_p))*2' x = ccore.from_db(defs[10]) assert x._is_struct assert x.show(form='ctypes') == """struct__mystruct = type('struct__mystruct',(Structure,),{})
def collect(ctx, allc, types, functions, macros, strict, xclang, src): """Collects types (struct,union,class,...) definitions, functions prototypes and/or macro definitions from SRC files/directory. Collected definitions are stored in a local database, tagged with the global 'tag' option if present or with a timestamp. The extraction is performed using libclang parser which can receive specific parameters through the --clang option. By default, only header files are parsed (the --all option allows to collect from all input files) and all implemented collectors are used. In strict mode, the clang options need to conform to the makefile that lead to the compilation of all input source (i.e. clang diagnostics errors are not bypassed with fake types). """ c = conf.config cxx = c.Collect.cxx F = lambda f: f.endswith('.h') or (cxx and f.endswith('.hpp')) K = None c.Collect.strict |= strict if allc is True: F = lambda f: (f.endswith('.c') or (cxx and f.endswith('.cpp')) or F(f)) if types or functions or macros: K = [] if types: K += [TYPEDEF_DECL, STRUCT_DECL, UNION_DECL] if functions: K += [FUNCTION_DECL] if macros: K += [MACRO_DEF] tag = ctx.obj['db'].tag._hash or None if tag is None: tag = str(time.time()) # filters: ctx.obj['F'] = F # selected kinds of cursors to collect: ctx.obj['K'] = K # temporary database cache: dbo = {} # if no clang params is provided, use defaults: if xclang is None: # keep comments in parser output: args = [ '-ferror-limit=0', '-fparse-all-comments', ] # add header directories: for i in (D for D in src if os.path.isdir(D)): args.append('-I%s' % i) else: args = xclang.split(' ') # count source files: FILES = set() for D in src: if os.path.isdir(D): for dirname, subdirs, files in os.walk(D.rstrip('/')): for f in filter(F, files): filename = '%s/%s' % (dirname, f) FILES.add(filename) elif os.path.isfile(D) and F(D): FILES.add(D) total = len(FILES) W = c.Terminal.width - 12 # parse and collect all sources: while len(FILES) > 0: t0 = time.time() filename = FILES.pop() if not c.Terminal.quiet: p = (((total - len(FILES)) * 100.) / total) click.echo(('[%3d%%] %s ' % (p, filename)).ljust(W), nl=False) l = parse(filename, args, kind=K, tag=tag[-1]) t1 = time.time() if c.Terminal.timer: click.secho('(%.2f+' % (t1 - t0), nl=False, fg='cyan') if l is None: return -1 if len(l) > 0: # remove already processed/included files FILES.difference_update([el['src'] for el in l]) # remove duplicates into dbo: for x in l: dbo[x['id'] + x['src']] = x t2 = time.time() if c.Terminal.timer: click.secho('%.2f)' % (t2 - t1), fg='cyan') db = ctx.obj['db'] if not c.Terminal.quiet: click.echo('-' * (c.Terminal.width)) click.echo('saving database...'.ljust(W), nl=False) N = len(dbo) db.insert_multiple(dbo.values()) db.close() if not c.Terminal.quiet: click.secho(('[%4d]' % N).rjust(12), fg='green') return 0