Esempio n. 1
0
    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)
Esempio n. 2
0
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
Esempio n. 3
0
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
Esempio n. 4
0
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)
Esempio n. 5
0
 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
Esempio n. 6
0
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'])
Esempio n. 7
0
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)
Esempio n. 9
0
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)
Esempio n. 10
0
    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)
Esempio n. 11
0
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
Esempio n. 12
0
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
Esempio n. 13
0
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)
Esempio n. 14
0
    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   
        
Esempio n. 15
0
    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* '))
Esempio n. 16
0
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
Esempio n. 17
0
    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)
Esempio n. 18
0
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