Example #1
0
def split_ast(ast):
    """
    split the ast into header and initializer headers.
    initializers cannot be included in more than one translation unit (c file)
    """
    init_decls = []

    def extern_inits(decl):
        # c_ast.ID is used for directives. pass them straight through to both files
        if isinstance(decl, c_ast.ID):
            init_decls.append(decl)
            return decl
        elif decl.init:
            init_decls.append(
                c_ast.Decl(decl.name, decl.quals, decl.storage, decl.funcspec,
                           decl.type, decl.init, decl.bitsize))
            decl.storage = ['extern']
            decl.init = None
            return decl
        else:
            return decl

    out_ast = c_ast.FileAST([extern_inits(e) for e in ast.ext])
    init_ast = c_ast.FileAST(init_decls)
    return (out_ast, init_ast)
Example #2
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
Example #3
0
def global_log(ast_tree):
    global_log = c_ast.Decl(
        'global_log', [], [], [],
        c_ast.TypeDecl('global_log', [], c_ast.Struct('Global_Log', None)),
        None, None)
    temp_ls1 = []
    temp_ls1.append(global_log)
    temp_ls2 = []
    temp_ls2 = copy.deepcopy(ast_tree.ext)
    global_log = c_ast.FileAST(temp_ls1 + temp_ls2)
    return global_log
Example #4
0
    def parse(self, text, filename='', debuglevel=0,
            initial_type_symbols=set()):
        self.clex.filename = filename
        self.clex.reset_lineno()

        # _scope_stack[-1] is the current (topmost) scope.

        initial_scope = dict((tpsym, 1) for tpsym in initial_type_symbols)
        initial_scope.update(
                dict((tpsym, 1) for tpsym in self.initial_type_symbols))
        self._scope_stack = [initial_scope]

        if not text or text.isspace():
            return c_ast.FileAST([])
        else:
            return self.cparser.parse(text, lexer=self.clex, debug=debuglevel)
Example #5
0
def run(externs, our_fns, cpp_filter, cpp_all, decompile=True):
    '''frozenset(str) -> frozenset(str) -> str -> str -> opt:bool -> [c_ast]'''
    global OUR_FNS, EXTERN_REG_MAP, STKVAR_MAP  # for repl convenience
    OUR_FNS = our_fns

    fn_segs = data.get_segs(['extern', '.text'])
    rodata_segs = data.get_segs(['.rodata', '.srdata'])
    data_segs = data.get_segs(['.data', '.bss'])
    lit_segs = data.get_segs(['.lit4', '.lit8'])

    num_lits = data.get_num_literals(lit_segs)
    str_lits = data.get_str_literals(rodata_segs)
    data_txt = data.get_data(data_segs, cpp_filter)

    # XXX FIXME this will be going away once we've added emitting numeric and
    # string constants directly at their site of use
    if decompile is True:
        for (k, v) in num_lits.iteritems():
            ty = type(v)
            if ty is ep_ct.cfloat:
                print 'float %s = %s;' % (k, v)
            elif ty is ep_ct.cdouble:
                print 'double %s = %s;' % (k, v)
            else:
                raise Exception('o no')
        for (k, v) in str_lits.iteritems():
            print 'const char *%s = %s;' % (k, data.c_stringify(v))

    protos = map(cdecl.make_internal_fn_decl, our_fns)

    (lib_fns, tds) = data.get_fns_and_types(fn_segs, externs, cpp_all)
    all_tds = {x.name: x for x in tds}
    typedefs = cdecl.resolve_typedefs(all_tds)
    EXTERN_REG_MAP = data.get_fn_arg_map(lib_fns, typedefs)
    STKVAR_MAP = data.get_stkvars(our_fns)
    stkvar_decls = data.make_stkvar_txt(our_fns, STKVAR_MAP, cpp_filter)

    if decompile is True:
        print XXX_INTRO_HACK
        return gen_from_node(
            c_ast.FileAST(data_txt + protos + list(
                generate(ida.loc_by_name(decl.name), decl, our_fns,
                         EXTERN_REG_MAP, STKVAR_MAP, stkvar_decls)
                for decl in protos)))
    else:
        return
Example #6
0
def generate_code(request, response):
    for proto_file in request.proto_file:
        output = []

        ast = c_ast.FileAST([])
        generator = c_generator.CGenerator()

        ast.ext += [c_ast.EmptyStatement()]

        # Parse request
        for item, package in traverse(proto_file):
            data = {
                'package': proto_file.package or '&lt;root&gt;',
                'filename': proto_file.name,
                'name': item.name,
            }

            if isinstance(item, DescriptorProto):
                data.update({
                    'type': 'Message',
                    'properties': [{'name': f.name, 'type': int(f.type)}
                                   for f in item.field]
                })

            elif isinstance(item, EnumDescriptorProto):
                data.update({
                    'type': 'Enum',
                    'values': [{'name': v.name, 'value': v.number}
                               for v in item.value]
                })

            output.append(data)

        # Fill response
        f = response.file.add()
        f.name = proto_file.name + '.c'
        f.content = generator.visit(ast)
Example #7
0
def generate_sai_api_tbl_h(apis):
    def createDecl(api):
        apitype = 'sai_' + api + '_api_t'
        apivar = 'sai_' + api + '_api_tbl'
        return c_ast.Decl(
            apivar, list(), list(), list(),
            c_ast.PtrDecl(
                list(),
                c_ast.TypeDecl(apivar, list(), c_ast.IdentifierType([
                    apitype,
                ]))), None, None)

    tdecls = [createDecl(api) for api in apis]
    tstruct = c_ast.Struct('_sai_api_tbl_t', tdecls)
    tdec = c_ast.TypeDecl('sai_api_tbl_t', list(), tstruct)
    tdef = c_ast.Typedef('sai_api_tbl_t', list(), ['typedef'], tdec)
    externdec = c_ast.Decl(
        'sai_api_tbl', list(), ['extern'], list(),
        c_ast.TypeDecl('sai_api_tbl', list(),
                       c_ast.IdentifierType(['sai_api_tbl_t'])), None, None)
    api_t = c_ast.FileAST([tdef, externdec])
    generator = c_generator.CGenerator()
    sai_api_tbl_h_str = r'''#include "sai.h"
#ifndef SAI_API_TBL
#define SAI_API_TBL

'''
    sai_api_tbl_h_str += generator.visit(api_t)
    sai_api_tbl_h_str += r'''
extern sai_status_t sai_api_tbl_init();

#endif
'''
    # print(api_t)
    print(sai_api_tbl_h_str)
    with open('adaptor/gen-inc/sai_api_tbl.h', 'w') as f:
        f.write(sai_api_tbl_h_str)
Example #8
0
def to_func_ast(ast):
    return c_ast.FileAST(ast)
Example #9
0
 def createProgram(self):
     self.prog = c_ast.FileAST([self.ast, self.main])
Example #10
0
def async_to_sync(async_ast: c_ast.Node, config):
    """ Given a c99 code in a AST form, returns the corresponding code of its
    synchronous equivalent program.

    Notes
    -----
    First step is calculate all code between round variables assigments, then
    we add all the context needed to reach that piece of code.

    Entry point     if  ... if ...      Current round            Next round
    * --------------------------------> *----------------------> *
                    A                               B
    
    The code we want to extract is in path B, but we need to collect all the
    conditions to reach this path, this is obtained collection all c_ast.If
    in path A.

    Path A and B can't contain c_ast.Continue nodes. Path B can't contain other
    round assigments in the middle.
    """
    phase_variable = config['phase']
    round_variable = config['round']
    labels = config['labels']

    # we discard what we won't use
    main_ast = cast_lib.find_funcdef_node(async_ast, 'main')
    cast_lib.map_dfs(main_ast, cast_lib.replace_while_with_body, [])
    cast_lib.filter_nodes(main_ast, remove_declarations)

    codecfg = cfg.ControlFlowGraph(main_ast)

    # we search paths between every (monotonically increasing) assigment of round variables
    paths_between_rounds = paths_between_round_assignments(
        codecfg, labels, round_variable, phase_variable)

    # for every protocol's round we calculate all possible paths including its previous context (e.g., ifs conditions)
    start_node = list(nx.topological_sort(codecfg))[0]
    complete_paths_by_round = {}

    for round_label, suffix_paths in paths_between_rounds.items():
        complete_paths_by_round[round_label] = []

        for suffix_path in suffix_paths:
            suffix_first_node = list(nx.topological_sort(suffix_path))[0]
            prefix_paths = get_cfg_paths_between_nodes(codecfg, start_node,
                                                       suffix_first_node)

            cp = complete_paths(suffix_path, prefix_paths)
            complete_paths_by_round[round_label].extend(cp)

    # the code of a round is the (graph) union of all the complete paths found to belong to that round
    # the easiest approach is to remove the nodes not included in those paths from the original code using the coord property
    sync_code = {}

    for round_label, paths in complete_paths_by_round.items():

        round_code_cfg = cfg.ControlFlowGraph()
        nodes_to_keep = set()

        for p in paths:
            for n in p.nodes():
                nodes_to_keep.add(str(n.coord))

        round_sync_code = copy.deepcopy(main_ast)
        cast_lib.filter_nodes(round_sync_code, node_coord_not_in_set,
                              nodes_to_keep)
        sync_code[round_label] = round_sync_code

    # translate to CompHO
    compho = {}

    for round_label, ast_code in sync_code.items():
        compho[round_label] = {}
        ast_send = c_ast.FileAST([copy.deepcopy(ast_code)])
        get_compho_send(ast_send)
        ast_update = c_ast.FileAST([copy.deepcopy(ast_code)])
        get_compho_update(ast_update, round_variable, round_label)
        compho[round_label]['send'] = ast_send
        compho[round_label]['update'] = ast_update

    return compho
Example #11
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
Example #12
0
def remove_defs(headers,
                base_dir,
                blacklist,
                take_typedefs=True,
                take_funcs=True,
                take_decls=True,
                **kwargs):
    """
    Keeps only type definitions and function declarations.
    :param headers:
    :param base_dir:
    :param blacklist:
    :return:
    """
    parser = c_parser.CParser()

    def take_coord(coord):
        pth = coord_path(coord)
        return pth is not None and pth.startswith(base_dir)

    class FuncDefVisitor(c_ast.NodeVisitor):
        def __init__(self):
            self.defs = []
            self.ar = ArrayEval()

        def visit_FuncDef(self, node):
            return

        def visit_Typedef(self, node):
            if not take_coord(
                    node.coord) or node.name in blacklist or not take_typedefs:
                return
            self.ar.visit(node)
            self.defs.append(node)

        def visit_FunDecl(self, node):
            if not take_coord(
                    node.coord
            ) or node.decl.name in blacklist or not take_funcs:
                return
            self.ar.visit(node)
            self.defs.append(node)

        def visit_Decl(self, node):
            if not take_coord(
                    node.coord) or node.name in blacklist or not take_decls:
                return
            if 'static' in node.storage: return
            self.ar.visit(node)
            self.defs.append(node)

    to_parse = headers.decode('utf8')

    # quick hack for sizeof
    to_parse = replace_sizeofs(to_parse)

    ast = parser.parse(to_parse, debuglevel=0)

    v = FuncDefVisitor()
    v.visit(ast)
    nast = c_ast.FileAST(v.defs)

    generator = c_generator.CGenerator()
    genc = generator.visit(nast)

    return genc