Пример #1
0
def resolve_local_type(var, node):
    """Resolve the var in any nodes before `node`
    Will search for `decl_stmt` or `params`
    Return type name if found.
    """
    while node and node.previousSibling:
        node = node.previousSibling
        if domutil.is_element(node):
            # won't search beyond function. That will resolved as global variable
            if node.tagName == 'function':
                return None
            if node.tagName == 'decl_stmt':
                type_name,var_name,_ = syntaxutil.parse_decl_stmt(node)
                if var == var_name:
                    return type_name
            elif node.tagName == 'parameter_list':
                # if reach function's parameter list, search params, if fail, then stop
                params = syntaxutil.parse_parameter_list(node)
                for type_name,var_name in params:
                    if var == var_name:
                        return type_name
    if node and node.parentNode:
        return resolve_local_type(var, node.parentNode)
    else:
        return None
Пример #2
0
def resolve_alive_vars(node, resolved):
    """Resolve all alive vars at this node.
    :return {var: type}
    """
    result = {}
    if node.previousSibling:
        node = node.previousSibling
        if domutil.is_element(node):
            if node.tagName == 'decl_stmt':
                type_name,var_name,_ = syntaxutil.parse_decl_stmt(node)
                if var_name not in result:
                    result[var_name] = type_name
            elif node.tagName == 'parameter_list':
                params = syntaxutil.parse_parameter_list(node)
                for type_name,var_name in params:
                    if var_name not in result:
                        result[var_name] = type_name
    elif node.parentNode:
        node = node.parentNode
    else:
        return {}
    more = resolve_alive_vars(node, resolved | result.keys())
    for key in more:
        if key not in result:
            result[key] = more[key]
    return result
Пример #3
0
def func(directory):
    for root,_,files in os.walk(directory):
        for f in files:
            if f.endswith('.c'):
                filename = os.path.join(root, f)
                print(filename)
                with tempfile.TemporaryFile() as fp:
                    with open(filename) as f:
                        change_count = 0
                        for line in f:
                            if line.strip().endswith(';') and ',' in line:
                                if line.count('(') == line.count(')'):
                                    doc = domutil.get_doc_from_code(line)
                                    unit_nodes = doc.getElementsByTagName('unit')
                                    unit_node = unit_nodes.item(0)
                                    decl_stmt_node = domutil.get_first_child_by_tagname(unit_node, 'decl_stmt')
                                    if domutil.is_element(decl_stmt_node) and decl_stmt_node.tagName == 'decl_stmt':
                                        decl_nodes = domutil.get_children_by_tagname(decl_stmt_node, 'decl')
                                        if len(decl_nodes) > 1:
                                            change_count+=1
                                            # result = syntaxutil.parse_decl_stmt_code(line)
                                            full_type = get_type(line)
                                            # FIXME job *job, *sj = deserializeJob(nextjob,remlen,&nextjob,SER_MESSAGE);
                                            if full_type and '(' not in line:
                                                variables = line.split(',')[:]
                                                var1 = variables[0]
                                                line = var1 + ';\n' + ';\n'.join([full_type + ' ' + var for var in variables[1:]])
                            fp.write(line.encode('utf8'))
                        print('made '+str(change_count)+' changes to file: ' + filename)
                    fp.seek(0)
                    content = fp.read().decode('utf8')
                    with open(filename, 'w') as f:
                        f.write(content)
Пример #4
0
def parse_decl_stmt(node):
    """Parse a <decl_stmt> node.
    Assume only one variable can be in the statement(guranteed by decl spliter preprocessor).
    :return (type, name, init)
    """
    assert(domutil.is_element(node) and node.tagName == 'decl_stmt')
    decl_node = domutil.get_first_child_by_tagname(node, 'decl')
    return parse_decl(decl_node)
Пример #5
0
def get_annotation_segment(node):
    """from HeliumStart to HeliumStop
    """
    node_list = [node]
    while node.nextSibling:
        node = node.nextSibling
        node_list.append(node)
        if domutil.is_element(node) and node.tagName == 'comment':
            comment_text = domutil.get_text_content(node)
            if '@HeliumStop' in comment_text: break
    return node_list
Пример #6
0
def parse_parameter_list(node):
    """Parse a <parameter_list> of a function.
    :return ((type1,var1), (type2,var2), ...)
    """
    assert(domutil.is_element(node) and node.tagName == 'parameter_list')
    result = []
    for param_node in domutil.get_children_by_tagname(node, 'param'):
        decl_node = domutil.get_first_child_by_tagname(param_node, 'decl')
        if decl_node:
            type_name,var_name,_ = parse_decl(decl_node)
            result.append((type_name, var_name))
    return result
Пример #7
0
def parse_for_init(node):
    """Parse init statement in for.
    Assume only one variable in decl.
    :return (type1,var1)
    """
    assert(domutil.is_element(node) and node.tagName == 'init')
    decl_node = domutil.get_first_child_by_tagname(node, 'decl')
    if decl_node:
        type_name, var_name, _ = parse_decl(decl_node)
        return (type_name, var_name)
    else:
        return (None, None)
Пример #8
0
def parse_function(node):
    """parse a <function> node.
    :return (type_name, function_name, ((type1, param1), (type2, param2), ...))
    """
    assert(domutil.is_element(node) and node.tagName == 'function')
    type_node = domutil.get_first_child_by_tagname(node, 'type')
    name_node = domutil.get_first_child_by_tagname(node, 'name')
    parameter_list_node = domutil.get_first_child_by_tagname(node, 'parameter_list')
    type_name = domutil.get_text_content(type_node)
    name = domutil.get_text_content(name_node)
    params = parse_parameter_list(parameter_list_node)
    return (type_name, name, params)
Пример #9
0
def get_segment_nodes(doc):
    """Get nodes between //@HeliumStart and //@HeliumStop
    :return a list of nodes
    """
    comment_node = get_comment_node_by_annotation(doc, '@HelumStart')
    if not comment_node: return []
    results = []
    node = comment_node
    while node.nextSibling:
        node = node.nextSibling
        if domutil.is_element(node):
            results.append(node)
            if '@HeliumStop' in domutil.get_text_content(node):
                return results
    return None
Пример #10
0
def get_input_nodes(doc):
    """Get nodes between //@HeliumInput and //@HeliumInputEnd
    :return a list of nodes
    """
    comment_node = get_comment_node_by_annotation(doc, '@HeliumInput')
    if not comment_node: return []
    results = []
    node = comment_node
    while node.nextSibling:
        node = node.nextSibling
        if domutil.is_element(node):
            if node.tagName == 'decl_stmt':
                results.append(node)
            elif '@HeliumInputEnd' in domutil.get_text_content(node):
                return results
    return None
Пример #11
0
def parse_struct(node):
    """Parse a <struct> node
    Do not anonymous inner enum, union or structs.
    :return (name, [(type1, field1), (type1, field1), ...])
    """
    assert(domutil.is_element(node) and node.tagName == 'struct')
    name_node = domutil.get_first_child_by_tagname(node, 'name')
    block_node = domutil.get_first_child_by_tagname(node, 'block')
    if name_node:
        name = domutil.get_text_content(name_node)
    else:
        name = ''
    fields = []
    for decl_stmt_node in domutil.get_children_by_tagname(block_node, 'decl_stmt'):
        decl = parse_decl_stmt(decl_stmt_node)
        fields.append(decl[0:2])
    return (name, fields)
Пример #12
0
def get_undefined_vars(nodes, resolved):
    """Get undefined variable.
    :param nodes: a list of dom nodes
    :param resolved: a set of names as strings that is assumed to be defined
    :return a set of names
    """
    result = set()
    for node in nodes:
        if domutil.is_element(node):
            if node.tagName == 'decl_stmt':
                _,var_name,_ = syntaxutil.parse_decl_stmt(node)
                resolved.add(var_name)
            elif node.tagName == 'expr':
                # in #ifdef, there may be `#elif defined(__sun)`
                if domutil.in_node(node, 'cpp:ifdef', level=2) or\
                    domutil.in_node(node, 'cpp:elif', level=2) or\
                    domutil.in_node(node, 'cpp:ifndef', level=2):
                    continue
                name_set = syntaxutil.parse_expr(node)
                for name in name_set:
                    # uint8_t, false, true, NULL
                    if sys.resolve_single(name):
                        continue
                    # here we find the undefined variable
                    if name not in resolved and name not in result:
                        result.add(name)
            elif node.tagName == 'for':
                init_node = domutil.get_first_child_by_tagname(node, 'init')
                if init_node:
                    _, var = syntaxutil.parse_for_init(init_node)
                    if var:
                        resolved.add(var)
            elif node.tagName == 'parameter_list':
                params = syntaxutil.parse_parameter_list(node)
                for _,name in params:
                    resolved.add(name)
            elif node.tagName == 'cpp:define':
                value_node = domutil.get_first_child_by_tagname(node, 'cpp:value')
                text = domutil.get_text_content(value_node)
                match = re.findall(r'([A-Z_]{2,})', text)
                for m in match:
                    if m not in resolved:
                        result.add(m)
            new_result = get_undefined_vars(node.childNodes, resolved | result)
            result.update(new_result)
    return result
Пример #13
0
def parse_decl(node):
    """Parse a <decl> node.
    Assume only one variable can be in the statement(guranteed by decl spliter preprocessor).
    :return (type,name,init)
    """
    assert(domutil.is_element(node) and node.tagName == 'decl')
    type_node = domutil.get_first_child_by_tagname(node, 'type')
    name_node = domutil.get_first_child_by_tagname(node, 'name')
    type_name = domutil.get_text_content(type_node)
    var_name = domutil.get_text_content(name_node)
    if '[' in var_name:
        new_var_name = var_name[:var_name.find('[')]
        new_type_name = type_name + var_name[var_name.find('['):]
        var_name = new_var_name
        type_name = new_type_name
    # TODO init
    return (type_name, var_name, None)
Пример #14
0
def parse_expr(node):
    """Parse a <expr>
    :retrn a set of variable names used.
    :bug it=(item*)ptr; the type cast will be recognized as name
    :bug there may be <expr> inside <expr>
    """
    assert(domutil.is_element(node) and node.tagName == 'expr')
    name_nodes = domutil.get_children_by_tagname(node, 'name')
    names = set()
    for name_node in name_nodes:
        name = domutil.get_text_content(name_node)
        # TODO move array related code into util
        names.add(simplify_variable_name(name))
    # for a->b
    double_name_node = domutil.get_first_child_by_tagnames(node, 'name', 'name')
    if double_name_node:
        name = domutil.get_text_content(double_name_node)
        names.add(simplify_variable_name(name))
    return names
Пример #15
0
def parse_typedef(node):
    """Parse a <typedef> node
    <typedef>typedef <type>struct <name>A</name> *</type> <name>hello_t</name>;</typedef>
    <typedef>typedef <type><struct>struct <name>_stritem</name> <block> ... </struct></type> <name>item</name>;</typedef>
    :return (alias, original)
    """
    assert(domutil.is_element(node) and node.tagName == 'typedef')
    type_node = domutil.get_first_child_by_tagname(node, 'type')
    # support <function_decl> in <typedef>, i.e. typdef void *func(int a, int b)
    # return: (func, '')
    if not type_node:
        function_decl_node = domutil.get_first_child_by_tagname(node, 'function_decl')
        name_node = domutil.get_first_child_by_tagname(function_decl_node, 'name')
        alias = domutil.get_text_content(name_node)
        return (alias.strip(), '')
    name_node = domutil.get_first_child_by_tagname(node, 'name')
    original = domutil.get_text_content_except(type_node, 'block')
    alias = domutil.get_text_content(name_node)
    return (alias.strip(), original.strip())
Пример #16
0
def resolve_undefined_vars(nodes, resolved):
    """Get undefined variable. Resolve its type.
    :param nodes: a list of dom nodes
    :param resolved: a set of names as strings that is assumed to be defined
    :return {var: type, ...}
    """
    result = {}
    for node in nodes:
        if domutil.is_element(node):
            if node.tagName == 'decl_stmt':
                _,var_name,_ = syntaxutil.parse_decl_stmt(node)
                resolved.add(var_name)
            elif node.tagName == 'expr':
                # in #ifdef, there may be `#elif defined(__sun)`
                if domutil.in_node(node, 'cpp:ifdef', level=2) or\
                    domutil.in_node(node, 'cpp:elif', level=2) or\
                    domutil.in_node(node, 'cpp:ifndef', level=2):
                    continue
                name_set = syntaxutil.parse_expr(node)
                for name in name_set:
                    # uint8_t, false, true, NULL
                    if sys.resolve_single(name):
                        continue
                    # here we find the undefined variable
                    if name not in resolved and name not in result:
                        type_name = resolve_local_type(name, node)
                        if type_name:
                            result[name] = type_name
                        # if it is a global variable, do not print warning
                        elif not local.check_global_variable(name):
                            logger.warning('undefind variable ' + name + ' not resovled for local type.')
            elif node.tagName == 'for':
                init_node = domutil.get_first_child_by_tagname(node, 'init')
                if init_node:
                    _, var = syntaxutil.parse_for_init(init_node)
                    if var:
                        resolved.add(var)
            new_result = resolve_undefined_vars(node.childNodes, resolved | result.keys())
            result.update(new_result)
    return result
Пример #17
0
def instrument_segment(doc, segment):
    first_node = segment[0]
    last_node = segment[-1]
    parent = first_node.parentNode
    pre = doc.createElement('comment')
    pre.appendChild(doc.createTextNode('\n//@Pre\n'))
    parent.insertBefore(pre, first_node)
    post = doc.createElement('comment')
    post.appendChild(doc.createTextNode('\n//@Post\n'))
    parent.insertBefore(post, last_node.nextSibling)
    segment.insert(0, pre)
    segment.append(post)
    # loop invariant
    if config.get('instrument_loop') == 'true':
        for node in segment:
            if domutil.is_element(node) and node.tagName == 'for' or node.tagName == 'while':
                block_node = domutil.get_first_child_by_tagname(node, 'block')
                if not block_node: continue
                inner = doc.createElement('comment')
                inner.appendChild(doc.createTextNode('\n//@Inner\n'))
                block_node.insertBefore(inner, block_node.lastChild)
    return segment