Exemplo n.º 1
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
Exemplo n.º 2
0
def extract_to_resolve(node, resolved):
    """Extract functions, types, undefined global variables to resolve
    :param node: dom node that need to resolve
    :return a set
    """
    functions = set()
    types = set()
    unknown = set()
    for n in node.getElementsByTagName('call'):
        # in #ifdef, there may be `#elif defined(__sun)`
        if domutil.in_node(n, 'cpp:ifdef', level=2) or\
            domutil.in_node(n, 'cpp:elif', level=2) or\
            domutil.in_node(n, 'cpp:ifndef', level=2):
            continue
        call_name_node = domutil.get_first_child_by_tagname(n, 'name')
        call_name = domutil.get_text_content(call_name_node)
        functions.add(call_name)
    for n in node.getElementsByTagName('type'):
        if domutil.in_node(n, 'cpp:define', level=4): continue
        name_node = domutil.get_first_child_by_tagname(n, 'name')
        name = domutil.get_text_content(name_node)
        types.add(name)
    for n in node.getElementsByTagName('cpp:value'):
        value = domutil.get_text_content(n)
        types |= syntaxutil.parse_type_cast(value)
    for n in node.getElementsByTagName('cpp:define'):
        functions |= syntaxutil.parse_cpp_define(n)
    for n in node.getElementsByTagName('cpp:value'):
        # now lets resolve every word
        value = domutil.get_text_content(n)
        for word in re.findall(r'\b\w+\b', value):
            unknown.add(word)
    # if function return type if enum, the function is not marked as <function>
    # but what if the enum is trully enum? This is addressed in resolver/localfunc.py
    for n in node.getElementsByTagName('enum'):
        name_node = domutil.get_first_child_by_tagname(n, 'name')
        name = domutil.get_text_content(name_node)
        functions.add(name)
    variables = io.get_undefined_vars([node], resolved)
    if '' in functions: functions.remove('')
    if '' in types: types.remove('')
    if '' in variables: variables.remove('')
    # return functions-resolved, types-resolved, variables
    return (functions | types | variables | unknown) - resolved
Exemplo n.º 3
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