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
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
def instrument_input(self): logger.info('instrumenting input') init_code = '' input_nodes = annotation.get_input_nodes(self.doc) if not input_nodes: return for input_node in input_nodes: # input_nodes should be 'decl_stmt' type_name, var_name, _ = syntaxutil.parse_decl_stmt(input_node) if config.get('handle_array') == 'true': if '[' in type_name: text = domutil.get_text_content(input_node) self.code = self.code.replace(text, '') # We need to do the simplify self.struct_limit = 30 init_code += self.generate_input(type_name, var_name) self.code = self.code.replace('//@HeliumInputEnd', init_code, 1)
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
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