def parse(testcode, **kwargs): state = newState(testcode, **kwargs) cparser.parse("test.c", state) if state._errors: print "parsing errors:" pprint(state._errors) assert False, "there are parsing errors" return state
def create_ast(): """Parse a C headerfile with C preprocessor, and create an AST.""" cpp_h = os.path.join(os.path.dirname(__file__), 'cpp.h') inc_h = os.path.join(os.path.dirname(__file__), 'include.h') assert os.path.isfile(cpp_h) and os.path.isfile(inc_h) text = cpp.parse_file(cpp_h) yield cparser.parse(text)
def create_dissector(filename, platform, folders=None, includes=None): """Parse 'filename' to create a Wireshark protocol dissector. 'filename' is the C header/code file to parse. 'platform' is the platform we should simulate. 'folders' is a set of all folders to -Include. 'includes' is a set of filenames to #include. Returns the error if parsing failed, None if succeeded. """ try: text = cpp.parse_file(filename, platform, folders, includes) ast = cparser.parse(text, filename) cparser.find_structs(ast, platform) except OSError: raise except Exception as err: # Clean up a bit try: del cparser.StructVisitor._last_proto.dissectors[platform] del cparser.StructVisitor._last_visitor del cparser.StructVisitor._last_diss del cparser.StructVisitor._last_proto except Exception: pass if Options.verbose: print('Failed "%s":%s which raised %s' % (filename, platform.name, repr(err))) if Options.debug: sys.excepthook(*sys.exc_info()) return err if Options.verbose: print("Parsed header file '%s':%s successfully." % (filename, platform.name))
def parse_error(): """Test that two structs with the same name raises an error.""" code = 'struct a {int c;}; \nstruct b { int d; \nstruct a {int d;}; };' ast = cparser.parse(code, 'test') with contexts.raises(cparser.ParseError) as error: cparser.find_structs(ast) assert str(error).startswith('Two structs with same name a')
def create_ast(): """Parse a C headerfile with C preprocessor, and create an AST.""" # Find the header files and cpp if we are run from a different folder cpp_h = os.path.join(os.path.dirname(__file__), 'cpp.h') inc_h = os.path.join(os.path.dirname(__file__), 'include.h') assert os.path.isfile(cpp_h) and os.path.isfile(inc_h) text = cpp.parse_file(cpp_h) yield cparser.parse(text)
def req_1f(): """Test requirement FR1-F: Detect same name structs.""" cparser.StructVisitor.all_protocols = {} code = 'struct a {int c;};\nstruct b { int d;\nstruct a {int d;}; };' ast = cparser.parse(code, 'test') with contexts.raises(cparser.ParseError) as error: cparser.find_structs(ast) assert str(error).startswith('Two structs with same name a') cparser.StructVisitor.all_protocols = {}
def parse_array_type(): """Test arrays as struct members.""" ast = cparser.parse('struct arr { int a[10]; char b[20]; };') struct = _child(ast, 2) a, b = struct.children() assert struct.name == 'arr' assert isinstance(_child(a, 1), c_ast.ArrayDecl) assert _child(b, 2).declname == 'b' assert _child(b, 3).names[0] == 'char'
def get_5genes1(self) : """ Returns a list of ss_5gene ssystems with or w/o modifications""" fname = 'allProblems/ss_5genes1' self.logger.info('Creating canonical instance of ss_5genes1') self.logger.debug('Calling cparser on 5genes1') ss = SSystem(cparser.parse(fname)) ss_list = self._list_modifications(ss,Modifier5genes1()) self.logger.debug('Returning list of mods of 5genes1') return ss_list
def req_1a(): """Test requirement FR1-A: Support for int, floa, char and bool.""" ast = cparser.parse(''' struct basic { int a; float b; char c; _Bool d; }; ''') a, b, c, d = _child(ast, 2).children() assert _child(a, 2).names[0] == 'int' assert _child(b, 2).names[0] == 'float' assert _child(c, 2).names[0] == 'char' assert _child(d, 2).names[0] == '_Bool'
def req_1b(): """Test requirement FR1-B: Support enums.""" cparser.StructVisitor.all_protocols = {} ast = cparser.parse('enum c {a, b=3}; struct req { enum c test; };') assert isinstance(_child(ast.children()[1], 4), c_ast.Enum) enum = list(cparser.find_structs(ast)[0].dissectors.values())[0].children[0] assert enum assert enum.name == 'test' assert enum._valuestring_values == '{[0]="a", [3]="b"}' assert enum.type == 'uint32' and enum.size == 4
def parse_basic_types(): """Test that our parser support structs with basic types.""" ast = cparser.parse('struct simple { int a; float b; char c;};') struct = _child(ast, 2) a, b, c = struct.children() assert struct.name == 'simple' assert a.name == 'a' and b.name == 'b' and c.name == 'c' assert _child(a, 2).names[0] == 'int' assert _child(b, 2).names[0] == 'float' assert _child(c, 2).names[0] == 'char'
def get_5genes1(self): """ Returns a list of ss_5gene ssystems with or w/o modifications""" fname = 'allProblems/ss_5genes1' self.logger.info('Creating canonical instance of ss_5genes1') self.logger.debug('Calling cparser on 5genes1') ss = SSystem(cparser.parse(fname)) ss_list = self._list_modifications(ss, Modifier5genes1()) self.logger.debug('Returning list of mods of 5genes1') return ss_list
def req_1b(): """Test requirement FR1-B: Support enums.""" cparser.StructVisitor.all_protocols = {} ast = cparser.parse('enum c {a, b=3}; struct req { enum c test; };') assert isinstance(_child(ast.children()[1], 4), c_ast.Enum) enum = list( cparser.find_structs(ast)[0].dissectors.values())[0].children[0] assert enum assert enum.name == 'test' assert enum._valuestring_values == '{[0]="a", [3]="b"}' assert enum.type == 'uint32' and enum.size == 4
def parse_enum_type(): """Test enums as struct members.""" ast = cparser.parse(''' enum color { RED=1, BLUE, GREEN=5 }; struct arr { enum color which; int tmp; }; ''') struct = ast.children()[1].children()[0] a, b = struct.children() assert struct.name == 'arr' assert isinstance(_child(a, 2), c_ast.Enum) assert _child(a, 1).declname == 'which' assert _child(a, 2).name == 'color'
def req_1e(): """Test requirement FR1-E: Support arrays.""" cparser.StructVisitor.all_protocols = {} ast = cparser.parse('struct req1e {int a[8][7]; char b[9]; float c[5];};') a, b, c = [_child(i, 1) for i in _child(ast, 2).children()] assert isinstance(b, c_ast.ArrayDecl) and isinstance(c, c_ast.ArrayDecl) assert isinstance(_child(a, 1), c_ast.ArrayDecl) assert _child(a, 2).declname == 'a' assert _child(a, 3).names[0] == 'int' a, b, c = list(cparser.find_structs(ast)[0].dissectors.values())[0].children assert isinstance(b, dissector.Field) assert a.type == 'bytes' and b.type == 'string' and c.type == 'bytes' assert a.size == 4*56 and b.size == 9 and c.size == 20
def req_1e(): """Test requirement FR1-E: Support arrays.""" cparser.StructVisitor.all_protocols = {} ast = cparser.parse('struct req1e {int a[8][7]; char b[9]; float c[5];};') a, b, c = [_child(i, 1) for i in _child(ast, 2).children()] assert isinstance(b, c_ast.ArrayDecl) and isinstance(c, c_ast.ArrayDecl) assert isinstance(_child(a, 1), c_ast.ArrayDecl) assert _child(a, 2).declname == 'a' assert _child(a, 3).names[0] == 'int' a, b, c = list( cparser.find_structs(ast)[0].dissectors.values())[0].children assert isinstance(b, dissector.Field) assert a.type == 'bytes' and b.type == 'string' and c.type == 'bytes' assert a.size == 4 * 56 and b.size == 9 and c.size == 20
def parse_union_type(): """Test enums as struct members.""" ast = cparser.parse(''' union test_union { short a; long long b; float c; }; struct struct_with_union { union test_union union_member; int d; }; ''') union = ast.children()[0].children()[0] a, b, c = union.children() assert union.name == 'test_union' struct = ast.children()[1].children()[0] a, b = struct.children() assert struct.name == 'struct_with_union' assert isinstance(_child(a, 2), c_ast.Union) assert _child(a, 1).declname == 'union_member' assert _child(a, 2).name == 'test_union'
def main(): # excluding this programs name (argv[0]) and all arguments up to and # and excluding the first "--" are c files to include try: c_code_files = argv[1:argv.index("--")] except ValueError: # there might be no "--" c_code_files = argv[1:] if len(c_code_files) == 0: raise Exception("You must provide at least one C source file") state = State() state.autoSetupSystemMacros() state.autoSetupGlobalIncludeWrappers() interpreter = Interpreter() interpreter.register(state) for cfile in c_code_files: state = parse(cfile, state) main_func = interpreter.getFunc("main") if len(main_func.C_argTypes) == 0: return_code = interpreter.runFunc("main", return_as_ctype=False) else: # if the main() function doesn't have zero arguments, it # should have the standard two, (int argc0, char **argv0) assert (len(main_func.C_argTypes) == 2) # first c file is program name and first argument arguments_to_c_prog = [c_code_files[0]] try: # append everything after the "--" as c program arguments arguments_to_c_prog += argv[argv.index("--") + 1:] except: ValueError # return_as_ctype=False as we're expecting a simple int or None for void return_code = interpreter.runFunc("main", len(arguments_to_c_prog), arguments_to_c_prog, return_as_ctype=False) if isinstance(return_code, int): exit(return_code)
def main(): # excluding this programs name (argv[0]) and all arguments up to and # and excluding the first "--" are c files to include try: c_code_files = argv[1:argv.index("--")] except ValueError: # there might be no "--" c_code_files = argv[1:] if len(c_code_files) == 0: raise Exception("You must provide at least one C source file") state = State() state.autoSetupSystemMacros() state.autoSetupGlobalIncludeWrappers() interpreter = Interpreter() interpreter.register(state) for cfile in c_code_files: state = parse(cfile, state) main_func = interpreter.getFunc("main") if len(main_func.C_argTypes) == 0: return_code = interpreter.runFunc("main", return_as_ctype=False) else: # if the main() function doesn't have zero arguments, it # should have the standard two, (int argc0, char **argv0) assert(len(main_func.C_argTypes) == 2) # first c file is program name and first argument arguments_to_c_prog = [c_code_files[0]] try: # append everything after the "--" as c program arguments arguments_to_c_prog += argv[argv.index("--")+1:] except: ValueError # return_as_ctype=False as we're expecting a simple int or None for void return_code = interpreter.runFunc( "main", len(arguments_to_c_prog), arguments_to_c_prog, return_as_ctype=False) if isinstance(return_code, int): exit(return_code)
def create_structs(): """Creates an AST and finds all structs within it.""" code = ''' struct inner { int a1; int a2; int a3; }; enum color { RED, GREEN=3, YELLOW, RED=10 }; typedef enum weekday { MON, TUE, WED, FRI=5 } weekday_t; struct find { int a; float b; char c; enum color enumtest; char str[30]; float d[3]; struct inner inner_struct; unsigned short oprs[+2][9-7][((5 * 3) + (-5)) / 5]; weekday_t day; long double bytes; }; ''' ast = cparser.parse(code, 'test') structs = {i.name: i for i in cparser.find_structs(ast)} yield list(structs['find'].dissectors.values())[0].children cparser.StructVisitor.all_protocols = {}
def parse_cpython(self): # We keep all in the same state, i.e. the same static space. # This also means that we don't reset macro definitions. This speeds up header includes. # Usually this is not a problem. cparser.parse(CPythonDir + "/Modules/main.c", self) # Py_Main self.macros["FAST_LOOPS"] = cparser.Macro( rightside="0") # not sure where this would come from cparser.parse(CPythonDir + "/Python/ceval.c", self) # PyEval_EvalFrameEx etc del self.macros["EMPTY"] # will be redefined later cparser.parse(CPythonDir + "/Python/getopt.c", self) # _PyOS_GetOpt cparser.parse(CPythonDir + "/Python/pythonrun.c", self) # Py_Initialize cparser.parse(CPythonDir + "/Python/pystate.c", self) # PyInterpreterState_New cparser.parse(CPythonDir + "/Python/sysmodule.c", self) # PySys_ResetWarnOptions cparser.parse(CPythonDir + "/Python/random.c", self) # _PyRandom_Init cparser.parse(CPythonDir + "/Objects/object.c", self) # _Py_ReadyTypes etc cparser.parse(CPythonDir + "/Objects/typeobject.c", self) # PyType_Ready cparser.parse(CPythonDir + "/Objects/tupleobject.c", self) # PyTuple_New del self.macros["Return"] # will be used differently # We need these macro hacks because dictobject.c will use the same vars. self.macros["length_hint_doc"] = cparser.Macro( rightside="length_hint_doc__dict") self.macros["numfree"] = cparser.Macro(rightside="numfree__dict") self.macros["free_list"] = cparser.Macro(rightside="free_list__dict") cparser.parse(CPythonDir + "/Objects/dictobject.c", self) # PyDict_New # We need this macro hack because stringobject.c will use the same var. self.macros["sizeof__doc__"] = cparser.Macro( rightside="sizeof__doc__str") cparser.parse(CPythonDir + "/Objects/stringobject.c", self) # PyString_FromString cparser.parse(CPythonDir + "/Objects/obmalloc.c", self) # PyObject_Free cparser.parse(CPythonDir + "/Modules/gcmodule.c", self) # _PyObject_GC_NewVar cparser.parse(CPythonDir + "/Objects/descrobject.c", self) # PyDescr_NewWrapper # We need these macro hacks because methodobject.c will use the same vars. self.macros["numfree"] = cparser.Macro(rightside="numfree__methodobj") self.macros["free_list"] = cparser.Macro( rightside="free_list__methodobj") cparser.parse(CPythonDir + "/Objects/methodobject.c", self) # PyCFunction_NewEx # We need these macro hacks because methodobject.c will use the same vars. self.macros["numfree"] = cparser.Macro(rightside="numfree__list") self.macros["free_list"] = cparser.Macro(rightside="free_list__list") self.macros["sizeof_doc"] = cparser.Macro(rightside="sizeof_doc__list") self.macros["length_hint_doc"] = cparser.Macro( rightside="length_hint_doc__list") self.macros["index_doc"] = cparser.Macro(rightside="index_doc__list") self.macros["count_doc"] = cparser.Macro(rightside="count__list") cparser.parse(CPythonDir + "/Objects/listobject.c", self) # PyList_New cparser.parse(CPythonDir + "/Objects/abstract.c", self) # PySequence_List cparser.parse(CPythonDir + "/Python/modsupport.c", self) # Py_BuildValue
def loop(self): cparser.parse("<input>", self.state)
if len(c) == 0: break if c == "\n": for m in state._errors[oldErrNum:]: print("Error:", m) oldErrNum = len(state._errors) for m in state.contentlist[oldContentListNum:]: print("Parsed:", m) oldContentListNum = len(state.contentlist) yield c def prepareState(): state = cparser.State() state.autoSetupSystemMacros() state.autoSetupGlobalIncludeWrappers() def readInclude(fn): if fn == "<input>": reader = input_reader_handler(state) return reader, None return cparser.State.readLocalInclude(state, fn) state.readLocalInclude = readInclude return state state = prepareState() if __name__ == '__main__': cparser.parse("<input>", state)
def req_1d(): """Test requirement FR1-D: Support unions.""" ast = cparser.parse('struct req { union type { int a; char b; }; };') assert isinstance(_child(ast, 4), c_ast.Union) assert _child(ast, 4).name == 'type'
def req_1c(): """Test requirement FR1-C: Support member of type struct.""" a = cparser.parse('struct outside { struct inside { int a; char b; }; };') assert isinstance(_child(a, 4), c_ast.Struct) assert _child(a, 2).name == 'outside' and _child(a, 4).name == 'inside' assert _child(a, 7).names[0] == 'int'
def parse_cpython(self): # We keep all in the same state, i.e. the same static space. # This also means that we don't reset macro definitions. This speeds up header includes. # Usually this is not a problem. cparser.parse(CPythonDir + "/Modules/main.c", self) # Py_Main self.macros["FAST_LOOPS"] = cparser.Macro(rightside="0") # not sure where this would come from cparser.parse(CPythonDir + "/Python/ceval.c", self) # PyEval_EvalFrameEx etc del self.macros["EMPTY"] # will be redefined later cparser.parse(CPythonDir + "/Python/getopt.c", self) # _PyOS_GetOpt cparser.parse(CPythonDir + "/Python/pythonrun.c", self) # Py_Initialize cparser.parse(CPythonDir + "/Python/pystate.c", self) # PyInterpreterState_New cparser.parse(CPythonDir + "/Python/sysmodule.c", self) # PySys_ResetWarnOptions cparser.parse(CPythonDir + "/Python/random.c", self) # _PyRandom_Init cparser.parse(CPythonDir + "/Objects/object.c", self) # _Py_ReadyTypes etc cparser.parse(CPythonDir + "/Objects/typeobject.c", self) # PyType_Ready cparser.parse(CPythonDir + "/Objects/tupleobject.c", self) # PyTuple_New del self.macros["Return"] # will be used differently # We need these macro hacks because dictobject.c will use the same vars. self.macros["length_hint_doc"] = cparser.Macro(rightside="length_hint_doc__dict") self.macros["numfree"] = cparser.Macro(rightside="numfree__dict") self.macros["free_list"] = cparser.Macro(rightside="free_list__dict") cparser.parse(CPythonDir + "/Objects/dictobject.c", self) # PyDict_New # We need this macro hack because stringobject.c will use the same var. self.macros["sizeof__doc__"] = cparser.Macro(rightside="sizeof__doc__str") cparser.parse(CPythonDir + "/Objects/stringobject.c", self) # PyString_FromString cparser.parse(CPythonDir + "/Objects/obmalloc.c", self) # PyObject_Free cparser.parse(CPythonDir + "/Modules/gcmodule.c", self) # _PyObject_GC_NewVar cparser.parse(CPythonDir + "/Objects/descrobject.c", self) # PyDescr_NewWrapper # We need these macro hacks because methodobject.c will use the same vars. self.macros["numfree"] = cparser.Macro(rightside="numfree__methodobj") self.macros["free_list"] = cparser.Macro(rightside="free_list__methodobj") cparser.parse(CPythonDir + "/Objects/methodobject.c", self) # PyCFunction_NewEx # We need these macro hacks because methodobject.c will use the same vars. self.macros["numfree"] = cparser.Macro(rightside="numfree__list") self.macros["free_list"] = cparser.Macro(rightside="free_list__list") self.macros["sizeof_doc"] = cparser.Macro(rightside="sizeof_doc__list") self.macros["length_hint_doc"] = cparser.Macro(rightside="length_hint_doc__list") self.macros["index_doc"] = cparser.Macro(rightside="index_doc__list") self.macros["count_doc"] = cparser.Macro(rightside="count__list") cparser.parse(CPythonDir + "/Objects/listobject.c", self) # PyList_New cparser.parse(CPythonDir + "/Objects/abstract.c", self) # PySequence_List cparser.parse(CPythonDir + "/Python/modsupport.c", self) # Py_BuildValue
if args.to_test and i >= args.to_test: break if i < args.from_test - 1: i += 1 continue test_case_dir = os.path.join(test_dir, test_case) output_dir = os.path.join(script_dir, "output") test_files = list(os.listdir(test_case_dir)) input_file = os.path.join(test_case_dir, test_files.pop(test_files.index("input.txt"))) try: if test_case.startswith("TS"): scan(input_file) else: parse(input_file) except Exception as e: # raise e print("Execution failed:", str(e)) fail = True else: fail = False if not fail: if test_case.startswith("TXX"): if os.name == "nt": tester_file = os.path.join(script_dir, "interpreter", "tester_Windows.exe") elif os.name == "posix": tester_file = os.path.join(script_dir, "interpreter", "tester_Linux.out")
while True: c = input.read(1) if len(c) == 0: break if c == "\n": for m in state._errors[oldErrNum:]: print "Error:", m oldErrNum = len(state._errors) for m in state.contentlist[oldContentListNum:]: print "Parsed:", m oldContentListNum = len(state.contentlist) yield c def prepareState(): state = cparser.State() state.autoSetupSystemMacros() state.autoSetupGlobalIncludeWrappers() def readInclude(fn): if fn == "<input>": reader = input_reader_hanlder(state) return reader, None return cparser.State.readLocalInclude(state, fn) state.readLocalInclude = readInclude return state state = prepareState() if __name__ == '__main__': cparser.parse("<input>", state)
better_exchook.install() import cparser def prepareState(): state = cparser.State() state.autoSetupSystemMacros() state.autoSetupGlobalIncludeWrappers() return state MyDir = os.path.dirname(__file__) state = prepareState() cparser.parse(MyDir + "/test_interpreter.c", state) from cparser import interpreter interpreter = interpreter.Interpreter() interpreter.register(state) if __name__ == '__main__': print("errors so far:") for m in state._errors: print(m) for f in state.contentlist: if not isinstance(f, cparser.CFunc): continue if not f.body: continue
sys.path.append(MyDir + "/../..") # so that 'import cparser' works as expected sys.path.append(MyDir + "/..") # so that 'import better_exchook' works import better_exchook better_exchook.install() import cparser def prepareState(): state = cparser.State() state.autoSetupSystemMacros() state.autoSetupGlobalIncludeWrappers() return state state = prepareState() cparser.parse(MyDir + "/test_interpreter.c", state) import cparser.interpreter interpreter = cparser.interpreter.Interpreter() interpreter.register(state) if __name__ == '__main__': print "erros so far:" for m in state._errors: print m for f in state.contentlist: if not isinstance(f, cparser.CFunc): continue if not f.body: continue
git_tag = '' if args.git: git_tag = subprocess.check_output( ['git', 'describe', '--always', '--abbrev=0'], cwd=input_dir).strip() git_tag = codecs.decode(git_tag) print('GIT:') print(git_tag) file_masks = config['masks'] filenames = [] for mask in file_masks: filenames += glob.glob(input_dir + mask, recursive=True) print('Found', len(filenames), 'files') macros = {k: '' for k in macros} index = cparser.parse(input_dir, filenames, clang_args, macros) index = { 'index': index, 'git_tag': git_tag, 'repository': config['repository'].replace('{TAG}', git_tag), 'groups': config['groups'] } json.dump(index, open(args.output_path, 'w', encoding='utf-8'), indent=4)
yield None # make it a generator return reader(), None return cparser.State.readLocalInclude(state, filename) state.readLocalInclude = lambda fn: readLocalInclude(state, fn) state.autoSetupGlobalIncludeWrappers() return state state = prepareState() from glob import glob for fn in glob(LuaDir + "/src/*.c"): print "parse", fn, "..." cparser.parse(fn, state) import cparser.interpreter interpreter = cparser.interpreter.Interpreter() interpreter.register(state) interpreter.registerFinalize() if __name__ == '__main__': print "erros so far:" for m in state._errors: print m print print "PyAST of main:" interpreter.dumpFunc("main")
state.macros["SIZEOF_TIME_T"] = state.macros["SIZEOF_LONG"] state.macros["SIZEOF__BOOL"] = cparser.Macro(rightside="1") state.macros["HAVE_SIGNAL_H"] = cparser.Macro(rightside="1") return yield None # make it a generator return reader(), None return cparser.State.readLocalInclude(state, filename) state.readLocalInclude = lambda fn: readLocalInclude(state, fn) state.autoSetupGlobalIncludeWrappers() return state state = prepareState() cparser.parse(CPythonDir + "/Modules/main.c", state) # Py_Main cparser.parse(CPythonDir + "/Python/getopt.c", state) # _PyOS_GetOpt cparser.parse(CPythonDir + "/Python/pythonrun.c", state) # Py_Initialize cparser.parse(CPythonDir + "/Python/pystate.c", state) # PyInterpreterState_New cparser.parse(CPythonDir + "/Python/sysmodule.c", state) # PySys_ResetWarnOptions cparser.parse(CPythonDir + "/Include/structmember.h", state) # struct PyMemberDef. just for now to avoid errors :) import cparser.interpreter interpreter = cparser.interpreter.Interpreter() interpreter.register(state) interpreter.registerFinalize() if __name__ == '__main__': print "erros so far:" for m in state._errors: