def createMain(self): #Main Function #Declaration z1 = c_ast.TypeDecl('args',[],c_ast.IdentifierType(['int'])) args = c_ast.Decl('args',[],[],[],z1,None,None) z2= c_ast.PtrDecl([],c_ast.TypeDecl('argv',[],c_ast.IdentifierType(['char']))) z3=c_ast.ArrayDecl(z2,None,[]) argv = c_ast.Decl('argv',[],[],[],z3,None,None) params=c_ast.ParamList([args,argv]) mainDec=c_ast.FuncDecl(params,c_ast.TypeDecl('main',[],c_ast.IdentifierType(['int']))) # insertTest(functionName,varVals,varTypes) #Body ##Signal sigalrm=c_ast.ID(name="14") funcCast=c_ast.TypeDecl(declname = None,quals=[],type=c_ast.IdentifierType(['void'])) paramCast=c_ast.ParamList([c_ast.Typename(name=None,quals=[],type=c_ast.TypeDecl(declname = None,quals=[],type=c_ast.IdentifierType(['int'])))]) typeFunc=c_ast.PtrDecl(type=c_ast.FuncDecl(paramCast,funcCast),quals=[]) kchild=c_ast.Cast(to_type=c_ast.Typename(name=None, quals=[],type=typeFunc),expr=c_ast.ID(name="kill_child")) expressList = [sigalrm,kchild] signalStmt=c_ast.FuncCall(c_ast.ID(name="signal"),c_ast.ExprList(expressList)) ##Return returnStmt=c_ast.Return(c_ast.Constant(type="int",value="0")) comp=c_ast.Compound([signalStmt,returnStmt]) return c_ast.FuncDef(mainDec,None,comp)
def define_sizeof_modifier_type(t): # setup the toplevel call if t.get_typename(): argument_ast = t.get_reference()("storage") else: argument_ast = t.define("storage") prefix = "fffc_get_sizeof_" desired_name = CGenerator().visit(argument_ast) suffix = encode_hash(desired_name) function_name = prefix + suffix # build the underlying function call underlying_call = get_sizeof_pointer_to_type(t.underlying_type, c_ast.ID("storage")) # build this just as above, except with the call in place of the sizeof storage_tdecl = c_ast.Decl("storage", [], [], [], c_ast.PtrDecl([], argument_ast), None, None) func_tdecl = c_ast.TypeDecl( function_name, [], c_ast.IdentifierType(["long", "long", "unsigned"])) funcdecl = c_ast.FuncDecl(c_ast.ParamList([storage_tdecl]), func_tdecl) funcdef = c_ast.FuncDef( c_ast.Decl(function_name, [], [], [], funcdecl, None, None), None, c_ast.Compound([c_ast.Return(underlying_call)]), ) comment = "/* " + desired_name + "*/\n" kr_funcdecl = c_ast.FuncDecl(c_ast.ParamList([]), func_tdecl) return comment, kr_funcdecl, funcdef
def merge_ast_tree(ast_tree, ext_index, bock_item_index, new_node, mode): ext_after = [] block_items_after = [] block_items_before = [] ext_before = ast_tree.ext[:ext_index] if (len(ast_tree.ext) > 1): ext_after = ast_tree.ext[ext_index + 1:] func_def_decl = ast_tree.ext[ext_index].decl para_decl = ast_tree.ext[ext_index].param_decls if (bock_item_index + 1 <= len(ast_tree.ext[ext_index].body.block_items)): if (mode == "insert_after"): block_items_before = ast_tree.ext[ ext_index].body.block_items[:bock_item_index + 1] if (mode == "insert_before"): block_items_before = ast_tree.ext[ ext_index].body.block_items[:bock_item_index] if (len(ast_tree.ext[ext_index].body.block_items) > 1): if (mode == "insert_after"): block_items_after = ast_tree.ext[ext_index].body.block_items[ bock_item_index + 1:] if (mode == "insert_before"): block_items_after = ast_tree.ext[ext_index].body.block_items[ bock_item_index:] block_items_before.append(new_node) changed_body = c_ast.Compound(block_items_before + block_items_after) changed_ext = c_ast.FuncDef(func_def_decl, para_decl, changed_body) ext_before.append(changed_ext) ast_tree = c_ast.FileAST(ext_before + ext_after) return ast_tree
def _build_handle_function(functions): """ Wraps the switch statement in a function definition """ case_statement = _build_case(functions) available_check = c_ast.If( c_ast.BinaryOp( '<', c_ast.FuncCall( c_ast.ID('mailbox_available'), c_ast.ExprList([c_ast.Constant('int', '2')]) ), c_ast.Constant('int', '4') ), c_ast.Return(None), None ) handle_decl = c_ast.FuncDecl( None, c_ast.TypeDecl('_handle_events', [], c_ast.IdentifierType(['void'])), ) command_decl = c_ast.Decl('command', [], [], [], c_ast.TypeDecl('command', [], c_ast.IdentifierType(['int'])), [], []) command_read = _generate_read('command') body = c_ast.Compound([available_check, command_decl, command_read, case_statement]) return c_ast.FuncDef(handle_decl, [], body)
def eliminateParams(self): self.params=c_ast.ParamList([]) mainDec=c_ast.Decl(name='mainFake',quals=[],init=None,bitsize=None,storage=[],funcspec=[],type=c_ast.FuncDecl(self.params,c_ast.TypeDecl('mainFake',[],c_ast.IdentifierType(['int'])))) self.main = c_ast.FuncDef(mainDec,None,self.main.body) for i,func in enumerate(self.ast.ext): if(isinstance(func,c_ast.FuncDef)): if func.decl.name == 'main': self.ast.ext[i]=self.main
def createTest(block,functionName,varVals,varTypes): #Main Function #Declaration z1 = c_ast.TypeDecl('args',[],c_ast.IdentifierType(['int'])) args = c_ast.Decl('args',[],[],[],z1,None,None) z2= c_ast.PtrDecl([],c_ast.TypeDecl('argv',[],c_ast.IdentifierType(['char']))) z3=c_ast.ArrayDecl(z2,None,[]) argv = c_ast.Decl('argv',[],[],[],z3,None,None) params=c_ast.ParamList([args,argv]) mainDec=c_ast.FuncDecl(params,c_ast.TypeDecl('main',[],c_ast.IdentifierType(['int']))) insertTest(functionName,varVals,varTypes) #Body returnStmt=c_ast.Return(c_ast.Constant(type="int",value="0")) comp=c_ast.Compound([returnStmt]) main= c_ast.FuncDef(mainDec,None,comp) insertTest(main,"func",['1','2'],['int','int'])
def generate(ea, decl, our_fns, extern_reg_map, stkvar_map, stkvar_decls): '''ea_t -> c_ast() -> frozenset(str) -> {str : reg_sig} -> {str : {int : tinfo_t}} {str : [c_ast]} -> c_ast''' try: stkvars = stkvar_map[decl.name] var_decls = stkvar_decls[decl.name] except KeyError: stkvars = {} var_decls = [] start_ea = ida.get_func(ea).startEA body = [XXX_STACKVAR_HACK()] + [var_decls] + [ x for x in c_for_insn(start_ea, our_fns, extern_reg_map, stkvars) ] funcdef = c_ast.FuncDef(decl, None, c_ast.Compound(flatten(body))) return funcdef
def addTestFunction(ast, expectedOutput, testFxn, initVars, initList): varList = [] exprList = [] fxnName = '' inFxn = False listi = 0 for i in range(len(initVars)): v = initVars[i] if inFxn: exprList.append(c_ast.Constant('int', initList[listi])) listi += 1 if (')' in v): inFxn = False newVar = c_ast.FuncCall(c_ast.ID(fxnName), c_ast.ExprList(exprList)) varList.append(newVar) exprList = [] else: if ('(' in v): fxnName = v[:v.index('(')] if (v[v.index('(')+1] != ')'): inFxn = True exprList.append(c_ast.Constant('int', initList[listi])) listi += 1 else: newVar = c_ast.FuncCall(c_ast.ID(fxnName), c_ast.ExprList([])) varList.append(newVar) else: newVar = c_ast.Assignment('=', c_ast.ID(v), c_ast.Constant('int', initList[listi])) listi += 1 varList.append(newVar) fxnDecl = c_ast.FuncDecl(None, c_ast.TypeDecl('klee_test_entry', [], c_ast.IdentifierType(['void']))) fxnCall = c_ast.FuncCall(c_ast.ID(testFxn), c_ast.ExprList([])) binaryOp = c_ast.BinaryOp('==', fxnCall, c_ast.Constant('int', expectedOutput)) ifFalse = c_ast.Compound([c_ast.FuncCall(c_ast.ID('klee_silent_exit'), c_ast.ExprList([c_ast.Constant('int', '0')]))]) ifTrue = c_ast.Compound([]) blockItems = [] for v in varList: blockItems.append(v) blockItems.append(c_ast.If(binaryOp, ifTrue, ifFalse)) fxnBody = c_ast.Compound(blockItems) fxnNode = c_ast.FuncDef(fxnDecl, None, fxnBody) ast.ext.append(fxnNode)
def fndecl(name, inargs, outargs, code): ptroutargs = [deepcopy(arg) for arg in outargs] rename = RenameVisitor("out") for arg in ptroutargs: rename.visit(arg) arg.type = c_ast.PtrDecl([], arg.type) arg.init = None fdecl = c_ast.FuncDecl( c_ast.ParamList(inargs + ptroutargs), c_ast.TypeDecl(name, [], c_ast.IdentifierType(['void']))) decl = c_ast.Decl(name, [], [], [], fdecl, None, None) assign = [] for ptr, var in zip(ptroutargs, outargs): assign.append( c_ast.Assignment('=', c_ast.UnaryOp('*', c_ast.ID(ptr.name)), c_ast.ID(var.name))) comp = c_ast.Compound(code + assign) return c_ast.FuncDef(decl, None, comp)
def _get_assume_definition(self): param_name = '__cond' int_type = a.TypeDecl(param_name, [], a.IdentifierType(['int'])) param_list = a.ParamList( [a.Decl(param_name, [], [], [], int_type, None, None)]) assume_type = a.TypeDecl('__VERIFIER_assume', [], a.IdentifierType(['void'])) assume_func_decl = a.FuncDecl(param_list, assume_type) assume_decl = a.Decl('__VERIFIER_assume', list(), list(), list(), assume_func_decl, None, None) exit_code = a.ExprList([a.Constant('int', '0')]) true_branch = a.Compound([a.FuncCall(a.ID('exit'), exit_code)]) false_branch = None if_statement = a.If(a.UnaryOp('!', a.ID(param_name)), true_branch, false_branch) return_statement = a.Return(None) body_items = [if_statement, return_statement] assume_body = a.Compound(body_items) return a.FuncDef(assume_decl, None, assume_body)
def define_sizeof_type_from_ast(argument_ast): prefix = "fffc_get_sizeof_" desired_name = CGenerator().visit(argument_ast) suffix = encode_hash(desired_name) function_name = prefix + suffix storage_tdecl = c_ast.Decl("storage", [], [], [], c_ast.PtrDecl([], argument_ast), None, None) func_tdecl = c_ast.TypeDecl( function_name, [], c_ast.IdentifierType(["long", "long", "unsigned"])) funcdecl = c_ast.FuncDecl(c_ast.ParamList([storage_tdecl]), func_tdecl) funcdef = c_ast.FuncDef( c_ast.Decl(function_name, [], [], [], funcdecl, None, None), None, c_ast.Compound([ c_ast.Return( c_ast.UnaryOp("sizeof", c_ast.UnaryOp("*", c_ast.ID("storage")))) ]), ) comment = "/* " + desired_name + "*/\n" kr_funcdecl = c_ast.FuncDecl(c_ast.ParamList([]), func_tdecl) return comment, kr_funcdecl, funcdef
def cfg_path_to_ast(cfg): """Generates a AST from a CFG path (No FileAST support, it handles FuncDecl, If, While and no compound objects). Parameters ---------- cfg : ControlFlowGraph """ current_compound = c_ast.Compound([]) ast = current_compound previous_compound = None nodes = list(nx.topological_sort(cfg)) for n in nodes: if type(n) in {c_ast.FuncDef, c_ast.While, c_ast.If}: previous_compound = current_compound current_compound = c_ast.Compound([]) if type(n) == c_ast.FuncDef: inner_ast = c_ast.FuncDef(n.decl, n.param_decls, current_compound) elif type(n) == c_ast.While: inner_ast = c_ast.While(n.cond, current_compound) elif type(n) == c_ast.If: inner_ast = c_ast.If(n.cond, current_compound, None) previous_compound.block_items.append(inner_ast) elif type(n) not in { ControlFlowGraph.FuncDefEnd, ControlFlowGraph.IfEnd, ControlFlowGraph.IfStart, ControlFlowGraph.WhileEnd }: current_compound.block_items.append(n) return ast
def simisrt(ast, isrdict): isrnum = len(isrdict) identi = c_ast.IdentifierType(['void']) fundetyde = c_ast.TypeDecl('simulate', [], identi) simdecl = c_ast.Decl('simulate', [], [], [], c_ast.FuncDecl(None, fundetyde), None, None, None) simu = c_ast.FuncDef(simdecl, None, c_ast.Compound([])) for i in range(0, isrnum): #isr[0] = &isr_1; simassiisr = astAssiIsr(i) simu.body.block_items.append(simassiisr) for isr in isrdict: #deferral[0] = &deferral_1; if isrdict[isr] == isr: simdef = astAssiDef(isr) simu.body.block_items.append(simdef) #int rand = __VERIFIER_nondet() % N; simveri = astVeriNon() simu.body.block_items.append(simveri) simpri = astAssiPri() simu.body.block_items.append(simpri) simfuncisr = astFuncIsr() simu.body.block_items.append(simfuncisr) simu.show() ast.ext.append(simu)
def ast_to_cfg(self, ast: c_ast.Node) -> (c_ast.Node, c_ast.Node): """Recursively compute the CFG from a AST. Given a AST node (can be any complex structure) the function will return the first and last nodes of the CFG in a tuple and will modify `cfg` adding the corresponding nodes and edges representing the final CFG. Parameters ---------- ast : pycparser.c_ast.Node to be translated into a CFG Returns ------- A tuple with references to the first and last element of the CFG """ typ = type(ast) entrynode = ControlFlowGraph.EntryNode() exitnode = ControlFlowGraph.ExitNode() self.add_node(entrynode) self.add_node(exitnode) # A c_ast.If in CFG is: # cfg(body.true) # / \ # if(cond) endif* # \ / # ---------------------- # # returns (if(c), endif) if typ == c_ast.If: astif = c_ast.If(ast.cond, None, None, coord=ast.coord) if_start = ControlFlowGraph.IfNode(astif) self.add_node(if_start) self.add_edge(entrynode, if_start) true_branch_body_entry, true_branch_body_exit = self.ast_to_cfg(ast.iftrue) asserttrue = ControlFlowGraph.AssertNode(ast.cond) self.add_node(asserttrue) self.add_edge(if_start, asserttrue) self.add_edge(asserttrue, true_branch_body_entry) self.join_adjacents_and_merge(asserttrue, removed_node=true_branch_body_entry) self.join_adjacents_and_merge(exitnode, removed_node=true_branch_body_exit) if ast.iffalse is not None: false_branch_body_start, false_branch_body_last = self.ast_to_cfg(ast.iffalse) if self.iffalse: assertfalse = ControlFlowGraph.AssertNode(c_ast.UnaryOp("!", ast.cond)) self.add_node(assertfalse) self.add_edge(if_start, assertfalse) self.add_edge(assertfalse, false_branch_body_start) else: self.add_edge(if_start, false_branch_body_start) self.join_adjacents_and_merge(assertfalse, removed_node=false_branch_body_start) self.join_adjacents_and_merge(exitnode, removed_node=false_branch_body_last) else: if self.iffalse: assertfalse = ControlFlowGraph.AssertNode(c_ast.UnaryOp("!", ast.cond)) self.add_node(assertfalse) self.add_edge(if_start, assertfalse) self.add_edge(assertfalse, exitnode) else: self.add_edge(if_start, exitnode) # A c_ast.While in CFG is: # cfg(body) # / \ # while(c) endwhile* -->--+ # ^ \ / | # | ---->---- | # +----------------------------+ # # returns (while(c), endwhile*) elif typ == c_ast.While: while_body_entry, while_body_exit = self.ast_to_cfg(ast.stmt) astwhile = c_ast.While(ast.cond, None, coord=ast.coord) whilenode = ControlFlowGraph.Node(astwhile) self.add_node(whilenode) self.add_edge(whilenode, exitnode) self.add_edge(entrynode, whilenode) asserttrue = ControlFlowGraph.AssertNode(ast.cond) self.add_node(asserttrue) self.add_edge(whilenode, asserttrue) self.add_edge(asserttrue, while_body_entry) self.join_adjacents_and_merge(asserttrue, removed_node=while_body_entry) # In a while the last statement return to the while condition if self.loop: self.join_adjacents_and_merge(whilenode, removed_node=while_body_exit) else: self.join_adjacents_and_merge(exitnode, removed_node=while_body_exit) # A c_ast.Compound in CFG is: # # cfg(block(1)) --> cfg(block(2)) --> ... --> cfg(block(n)) # # return (cfg(block(1)).first, cfg(block(n)).last) elif typ == c_ast.Compound: items = ast.block_items if items is not None: first_node = items[0] first_node_entry, prev_node_exit = self.ast_to_cfg(first_node) self.join_adjacents_and_merge(entrynode, removed_node=first_node_entry) if len(items) > 1: for i in items[1:-1]: i_node_entry, i_node_exit = self.ast_to_cfg(i) self.join_adjacents_and_remove(prev_node_exit, i_node_entry) prev_node_exit = i_node_exit last_node = items[-1] last_node_entry, last_node_exit = self.ast_to_cfg(last_node) self.join_adjacents_and_remove(prev_node_exit, last_node_entry) else: last_node = first_node last_node_exit = prev_node_exit self.join_adjacents_and_merge(exitnode, removed_node=last_node_exit) else: noopnode = ControlFlowGraph.Node(c_ast.EmptyStatement(coord=ast.coord)) self.add_node(noopnode) self.add_edge(entrynode, noopnode) self.add_edge(noopnode, exitnode) # A c_ast.Compound in CFG is: # # function.name --> cfg(function.body).first # # return (function.name, cfg(function.body).last) elif typ == c_ast.FuncDef: (first_body, last_body) = self.ast_to_cfg(ast.body) astfuncdef = c_ast.FuncDef(ast.decl, ast.param_decls, None, coord=ast.coord) funcdefnode = ControlFlowGraph.Node(astfuncdef) self.add_node(funcdefnode) self.add_edge(entrynode, funcdefnode) self.add_edge(last_body, exitnode) # we insert the FuncDef body CFG discarding its entry and exit nodes self.join_adjacents_and_merge(funcdefnode, removed_node=first_body) self.join_adjacents_and_merge(exitnode, removed_node=last_body) else: basicnode = ControlFlowGraph.Node(ast) self.add_node(basicnode) self.add_edge(entrynode, basicnode) self.add_edge(basicnode, exitnode) return entrynode, exitnode
def visit_FuncDecl(self, node): try: mfun = node.type.declname fun = self.sname + mfun node.type.declname = fun rett = ' '.join(node.type.type.names) except AttributeError: # This means the function returns a pointer mfun = node.type.type.declname fun = self.sname + mfun node.type.type.declname = fun rett = None param = c_ast.Constant("string", '"' + fun + '() called"') elist = c_ast.ExprList([param]) call = c_ast.FuncCall(c_ast.ID('DEBUG_ONCE'), elist) compound = c_ast.Compound([call]) rval = { 'int': c_ast.Constant("int", "0"), 'int32': c_ast.Constant("int", "0"), 'int64': c_ast.Constant("int", "0"), 'uint32': c_ast.Constant("int", "0"), 'size_t': c_ast.Constant("int", "0"), 'double': c_ast.Constant("int", "0"), 'unsigned long': c_ast.Constant("int", "0"), # Enums... 'cef_color_model_t': c_ast.Constant("int", "0"), 'cef_context_menu_media_state_flags_t': c_ast.Constant("int", "0"), 'cef_context_menu_media_type_t': c_ast.Constant("int", "0"), 'cef_context_menu_type_flags_t': c_ast.Constant("int", "0"), 'cef_context_menu_edit_state_flags_t': c_ast.Constant("int", "0"), 'cef_dom_document_type_t': c_ast.Constant("int", "0"), 'cef_dom_node_type_t': c_ast.Constant("int", "0"), 'cef_duplex_mode_t': c_ast.Constant("int", "0"), 'cef_errorcode_t': c_ast.Constant("int", "0"), 'cef_menu_item_type_t': c_ast.Constant("int", "0"), 'cef_postdataelement_type_t': c_ast.Constant("int", "0"), 'cef_resource_type_t': c_ast.Constant("int", "0"), 'cef_transition_type_t': c_ast.Constant("int", "0"), 'cef_urlrequest_status_t': c_ast.Constant("int", "0"), 'cef_value_type_t': c_ast.Constant("int", "0"), 'cef_xml_node_type_t': c_ast.Constant("int", "0"), # special cases... 'time_t': c_ast.Constant("int", "0"), 'cef_time_t': c_ast.Constant("Struct", "(cef_time_t){}"), 'cef_string_userfree_t': c_ast.Constant("Ptr", "NULL"), None: c_ast.Constant("Ptr", "NULL"), }.get(rett, None) if not rval is None: ret = c_ast.Return(rval) compound.block_items.append(ret) elif rett != 'void': print('Return type not handled: ' + rett) sys.exit(1) decl = c_ast.Decl(fun, None, None, ["CEF_CALLBACK"], node, None, None) fdef = c_ast.FuncDef(decl, None, compound) self.funs[mfun] = fun # fix const double pointer: https://github.com/eliben/pycparser/issues/68 self.ret.append(self.gen.visit(fdef).replace('* const ', ' const* '))
def gen_c_func_adaptor(astperfile): adaptorH = r'''//Automatically generated by goSAIadapterBuilder. #include "sai_api_tbl.h" ''' adaptorC = r'''//Automatically generated by goSAIadapterBuilder. #include "sai_api_tbl_init.c" ''' adaptorFuncdefs = [] for file_ast_fn in astperfile.keys(): # for file_ast_fn in ['/home/johnnie/Documents/gitprojects/SAI/inc/sairouterinterface.h', ]: # for file_ast_fn in ['/home/johnnie/Documents/gitprojects/SAI/inc/sairoute.h', ]: file_ast = astperfile[file_ast_fn] fn_core = file_ast_fn.split('/')[-1] fileC = r'''//Automatically generated by goSAIadapterBuilder. #include "sai_api_tbl.h" ''' fileH = r'''//Automatically generated by goSAIadapterBuilder. #include "sai.h" ''' api_ast = [ inst for inst in file_ast if 'api' in inst.name and not "sai_common_api_t" == inst.name and not "sai_api" in inst.name ] api = dict([(apidecl.type.type.names[0], apidecl.name) for apitypedef in api_ast for apidecl in apitypedef.type.type.decls]) # print(api) for functypedef in file_ast: if not 'fn' in functypedef.name: continue funcdecl = functypedef.type.type if type(funcdecl.type) is c_ast.TypeDecl: funcdecl.type.declname = funcdecl.type.declname[:-3] funcdeclreturntype = funcdecl.type.type.names[0] else: funcdecl.type.type.declname = funcdecl.type.type.declname[:-3] funcdeclreturntype = funcdecl.type.type.type.names[0] if funcdeclreturntype != 'sai_status_t': print("Ret", funcdeclreturntype) continue tblname = file_ast[-1].name + 'bl' if 'api' not in tblname: tblname = None for td in file_ast: if 'table' in td.name: tblname = td.name if tblname == None: break fdecl = c_ast.Decl(functypedef.name[:-3], list(), list(), list(), type=funcdecl, init=None, bitsize=None) fbody = c_ast.Compound(block_items=[ c_ast.Return(expr=c_ast.FuncCall( name=c_ast.StructRef( name=c_ast.StructRef(name=c_ast.ID(name='sai_api_tbl'), type='.', field=c_ast.ID(name=tblname)), # type='->',field=c_ast.ID(name=functypedef.name[4:-3])), type='->', field=c_ast.ID(name=api[functypedef.name])), args=c_ast.ExprList( exprs=[c_ast.ID(p.name) for p in funcdecl.args.params]))) ]) funcdef = c_ast.FuncDef(decl=fdecl, param_decls=None, body=fbody) # print(funcdef) adaptorFuncdefs.append(fdecl) funcH = generator.visit(c_ast.FileAST(fdecl)) fileH += funcH funcC = generator.visit(funcdef) fileC += funcC # print(file_ast) if fileC[-2:] != '"\n': hname = 'adaptor/gen-inc/' + fn_core[:-2] + "_adaptor.h" with open(hname, 'w') as f: f.write(fileH) print("written to", hname) cname = 'adaptor/gen-src/' + fn_core[:-2] + "_adaptor.c" with open(cname, 'w') as f: f.write(fileC) print("written to", cname) adaptorH += '#include "' + hname + '"\n' adaptorC += '#include "' + cname + '"\n' with open("adaptor/gen-inc/sai_adaptor.h", 'w') as f: f.write(adaptorH) with open("adaptor/sai_adaptor_all.c", 'w') as f: f.write(adaptorC) return adaptorFuncdefs
def parse_sources(self, path): ''' Parse all lvgl sources which are required for generating the bindings returns: ParseResult (collections.namedtuple) with the following fields: enums: dict of enum name -> pycparser.c_ast.FuncDef object functions: dict of enum name -> value objects: dict of object name -> LvglObject object defines: dict of name -> string representation of evaluated #define ''' enums = collections.OrderedDict() functions = collections.OrderedDict() declarations = collections.OrderedDict() structs = collections.OrderedDict() typedefs = collections.OrderedDict() ast = self.parse_file(os.path.join(path, 'lvgl.h')) previous_item = None # TODO: this whole filtering of items could be done in the bindings generator to allow for extending bindings generator without changing the sourceparser for item in ast.ext: if isinstance(item, c_ast.Decl) and isinstance(item.type, c_ast.FuncDecl): # C function if item.name not in functions: # If it is already in there, it might be a FuncDef and we want to keep that one functions[item.name] = c_ast.FuncDef(item, None, None) elif isinstance(item, c_ast.FuncDef): functions[item.decl.name] = item elif isinstance(item, c_ast.Typedef) and not item.name in self.TYPEDEFS: # Do not register typedefs which are defined in self.TYPEDEFS, these are # to be treated as basic types by the bindings generators typedefs[item.name] = item if isinstance(item.type, c_ast.TypeDecl) and (isinstance(item.type.type, c_ast.Struct) or isinstance(item.type.type, c_ast.Union)): # typedef struct { ... } lv_struct_name_t; try: structs[stripstart(item.type.declname,'lv_')] = item.type.type except ValueError: # If name does not start with lv_ pass elif (isinstance(item.type, c_ast.TypeDecl) and isinstance(item.type.type, c_ast.IdentifierType) and isinstance(previous_item, c_ast.Decl) and isinstance(previous_item.type, c_ast.Enum)): # typedef lv_enum_t ...; directly after an enum definition # newer lvgl uses this to define enum variables as uint8_t enumname, enum = self.enum_to_dict(previous_item.type) enums[enumname] = enum elif isinstance(item, c_ast.Decl) and isinstance(item.type, c_ast.TypeDecl): declarations[stripstart(item.type.declname, 'lv_')] = item.type previous_item = item objects, global_functions = self.determine_objects(functions, typedefs) # Find defines in color.h and symbol_def.h defines = collections.OrderedDict() # There is not OrderedSet in Python, so let's use OrderedDict with None values for filename in 'lv_misc/lv_color.h', 'lv_misc/lv_symbol_def.h': with open(os.path.join(path, filename), 'rt', encoding='utf-8') as file: code = file.read() for define in re.findall('^\s*#define\s+(\w+)', code,flags = re.MULTILINE): if not define.startswith('_'): defines[define] = None return ParseResult(enums, functions, declarations, typedefs, structs, objects, global_functions, defines)
def ast_to_cfg(digraph, ast: c_ast.Node) -> (c_ast.Node, c_ast.Node): """Recursively compute the CFG from a AST. Given a AST node (can be any complex structure) the function will return the first and last nodes of the CFG in a tuple and will modify `cfg` adding the corresponding nodes and edges representing the final CFG. Parameters ---------- digraph : networkx.DiGraph ast : pycparser.c_ast.Node to be translated into a CFG Returns ------- A tuple with references to the first and last element of the CFG Notes ----- Depending on the node type, we need to build a DiGraph and return its starting/ending nodes. Nodes marqued with * in figures are adhoc nodes to have only one end in the graph. """ typ = type(ast) # A c_ast.If in CFG is: # if(c)(cfg(body.true)) # / \ # ifstart(c) endif* # \ / # ---------------------- # # returns (if(c), endif) if typ == c_ast.If: first = ControlFlowGraph.IfStart(coord=str(ast.coord) + ":END") last = ControlFlowGraph.IfEnd(coord=str(ast.coord) + ":END") digraph.add_node(last) true_branch_first = c_ast.If(ast.cond, None, None, coord=ast.coord) true_branch_body_first, true_branch_body_last = ast_to_cfg( digraph, ast.iftrue) digraph.add_node(first) digraph.add_node(true_branch_first) digraph.add_node(true_branch_body_first) digraph.add_node(true_branch_body_last) digraph.add_edge(first, true_branch_first) digraph.add_edge(true_branch_first, true_branch_body_first) digraph.add_edge(true_branch_body_last, last) if ast.iffalse is not None: false_branch_first = c_ast.If(c_ast.UnaryOp("!", ast.cond), None, None, coord=ast.coord) digraph.add_node(false_branch_first) digraph.add_edge(first, false_branch_first) false_branch_body_start, false_branch_body_last = ast_to_cfg( digraph, ast.iffalse) digraph.add_node(false_branch_body_start) digraph.add_node(false_branch_body_last) digraph.add_edge(false_branch_first, false_branch_body_start) digraph.add_edge(false_branch_body_last, last) digraph.add_edge(first, last) return (first, last) # A c_ast.While in CFG is: # cfg(body) # / \ # while(c) endwhile* -->--+ # ^ \ / | # | ---->---- | # +----------------------------+ # # returns (while(c), endwhile*) elif typ == c_ast.While: body_first, body_last = ast_to_cfg(digraph, ast.stmt) first = c_ast.While(ast.cond, None, coord=ast.coord) last = ControlFlowGraph.WhileEnd(coord=str(ast.coord) + ":END") digraph.add_node(first) digraph.add_edge(first, body_first) digraph.add_edge(body_last, last) digraph.add_edge(first, last) return first, last # A c_ast.Compound in CFG is: # # cfg(block(1)) --> cfg(block(2)) --> ... --> cfg(block(n)) # # return (cfg(block(1)).first, cfg(block(n)).last) elif typ == c_ast.Compound: items = ast.block_items (first, last) = (None, None) old_i_last = None for i in items: i_first, i_last = ast_to_cfg(digraph, i) if old_i_last is not None: digraph.add_edge(old_i_last, i_first) if first is None: first = i_first old_i_last = i_last last = old_i_last return first, last # A c_ast.Compound in CFG is: # # function.name --> cfg(function.body).first # # return (function.name, cfg(function.body).last) elif typ == c_ast.FuncDef: (first_body, last_body) = ast_to_cfg(digraph, ast.body) first = c_ast.FuncDef(ast.decl, ast.param_decls, None, coord=ast.coord) last = ControlFlowGraph.FuncDefEnd(coord=str(ast.coord) + ":END") digraph.add_node(first) digraph.add_edge(first, first_body) digraph.add_edge(last_body, last) return first, last else: digraph.add_node(ast) return ast, ast