AST_t AST_t::get_enclosing_class_specifier(bool jump_templates) const { AST node = _ast; while (node != NULL && ASTType(node) != AST_CLASS_SPECIFIER) { node = ASTParent(node); } while (node != NULL && ASTType(node) != AST_SIMPLE_DECLARATION) { node = ASTParent(node); } if (jump_templates) { while (node != NULL && ASTParent(node) != NULL && ASTType(ASTParent(node)) == AST_TEMPLATE_DECLARATION) { node = ASTParent(node); } } AST_t result(node); return node; }
void AST_t::remove_in_list() { AST list = this->_ast; // Look for the enclosing list while (list != NULL && ASTType(list) != AST_NODE_LIST) { list = ASTParent(list); } if (list == NULL) { std::cerr << "A suitable list has not been found" << std::endl; return; } AST parent = ASTParent(list); AST previous = ASTSon0(list); if (previous != NULL) { ast_set_parent(previous, parent); } int i; for (i = 0; i < ASTNumChildren(parent); i++) { if (ASTChild(parent, i) == list) { ast_set_child(parent, i, previous); break; } } }
void AST_t::replace_with(AST_t ast) { if (ast._ast == NULL) { internal_error("Trying to replace a tree with an empty tree.", 0); } if (this->_ast == NULL) { internal_error("Trying to replace an empty tree with another tree", 0); } AST previous_parent = ASTParent(this->_ast); ast_replace(this->_ast, ast._ast); ast_set_parent(this->_ast, previous_parent); // Relink sons for (int i = 0; i < ASTNumChildren(this->_ast); i++) { if (ASTChild(this->_ast, i) != NULL) { ast_set_parent(ASTChild(this->_ast, i), this->_ast); } } }
AST_t AST_t::get_enclosing_block() const { AST node = _ast; while (!is_extensible_block(node)) { node = ASTParent(node); } AST_t result(node); return result; }
void ASTIterator::next() { if (!is_last()) { _current = ASTParent(_current); } else { _current = NULL; } }
// XXX - Fixme, implement it using ast_list_concat void AST_t::prepend_list(AST orig_list, AST prepended_list) { if (ASTType(orig_list) != AST_NODE_LIST || ASTType(prepended_list) != AST_NODE_LIST) { std::cerr << "You tried to prepend two lists that are not " << "orig_list=" << ast_print_node_type(ASTType(orig_list)) << " " << "prepend_list=" << ast_print_node_type(ASTType(prepended_list)) << std::endl; return; } // Relink the parent, first remove pointer to the prepended_list if (ASTParent(prepended_list) != NULL) { AST parent = ASTParent(prepended_list); for (int i = 0; i < ASTNumChildren(parent); i++) { if (ASTChild(parent, i) == prepended_list) { ast_set_child(parent, i, NULL); break; } } } // Now make the prepended_list as the son AST original_previous = ASTSon0(orig_list); ast_set_child(orig_list, 0, prepended_list); // Go to the deeper node of prepended_list AST iter = prepended_list; while (ASTSon0(iter) != NULL) { iter = ASTSon0(iter); } ast_set_child(iter, 0, original_previous); }
AST AST_t::get_translation_unit(AST node) { if (node == NULL) return NULL; while (node != NULL && ASTType(node) != AST_TRANSLATION_UNIT) { node = ASTParent(node); } return node; }
AST_t AST_t::get_enclosing_namespace_definition() const { AST node = _ast; while (node != NULL && ASTType(node) != AST_NAMESPACE_DEFINITION && ASTType(node) != AST_GCC_NAMESPACE_DEFINITION) { node = ASTParent(node); } AST_t result(node); return node; }
AST_t ASTIterator::get_parent_of_list() { // This is similar to a rewind, actually, but without modifying // _current AST it = _ast; while (it != NULL && ASTType(it) == AST_NODE_LIST) { it = ASTParent(it); } return AST_t(it); }
void AST_t::relink_parent(AST previous_child, AST new_child) { AST parent = ASTParent(previous_child); int i; for (i = 0; i < ASTNumChildren(parent); i++) { if (ASTChild(parent, i) == previous_child) break; } if (i == ASTNumChildren(parent)) { std::cerr << "Claimed parent does not have the node as a child" << std::endl; return; } AST parent_new_child = ASTParent(new_child); if (parent_new_child != NULL) { int j; for (j = 0; j < ASTNumChildren(parent_new_child); j++) { if (ASTChild(parent_new_child, j) == new_child) break; } if (j == ASTNumChildren(parent)) { std::cerr << "Claimed parent of new child does not have the node as a child" << std::endl; return; } // Disable for sanity this son now ast_set_child(parent, j, NULL); } // Relink ast_set_child(parent, i, new_child); }
void AST_t::prepend_sibling_function(AST_t t) { // Do nothing if (t._ast == NULL) { return; } AST_t enclosing_function = this-> get_enclosing_function_definition(/*jump_templates*/true, /*jump_external_decl*/true); AST list = ASTParent(enclosing_function._ast); AST prepended_list = get_list_of_extensible_block(t._ast); prepend_list(list, prepended_list); }
AST AST_t::get_enclosing_list(AST ast) { if (ast == NULL) { return NULL; } AST list = ast; // Look for the enclosing list while (list != NULL && ASTType(list) != AST_NODE_LIST) { list = ASTParent(list); } return list; }
bool ASTIterator::is_last() { if (_current == NULL) return true; AST _possible_next = ASTParent(_current); if (_possible_next == NULL || ASTType(_possible_next) != AST_NODE_LIST) { return true; } else if (ASTType(_possible_next) == AST_NODE_LIST && ASTSon0(_possible_next) != _current) { return true; } return false; }
AST_t AST_t::get_enclosing_function_definition(bool jump_templates, bool jump_external_decl) const { AST node = _ast; while (node != NULL && ASTType(node) != AST_FUNCTION_DEFINITION) { node = ASTParent(node); } // Jump over template declarations if (jump_templates) { // Now the node is an AST_FUNCTION_DEFINITION while (node != NULL && ASTParent(node) != NULL && ASTType(ASTParent(node)) == AST_TEMPLATE_DECLARATION) { node = ASTParent(node); } } // Extern declarations pose a problem, let's jump them as well if (jump_external_decl) { while (node != NULL && ASTParent(node) != NULL && ASTType(ASTParent(node)) == AST_LINKAGE_SPEC_DECL) { node = ASTParent(node); } } AST_t result(node); return result; }
static void ast_dump_graphviz_rec(AST a, FILE* f, size_t parent_node, int position, char is_extended UNUSED_PARAMETER) { // static char* octagon = "octagon"; // static char* doubleoctagon = "doubleoctagon"; static char* ellipse = "ellipse"; static char* mdiamond = "Mdiamond"; static char* box = "box"; char* shape; // I know this is not exact, but there is a %z qualifier in printf // while there is not such thing for intptr_t size_t current_node = (size_t)a; if (a != NULL) { // Select shape shape = box; if (ASTType(a) == AST_AMBIGUITY) shape = ellipse; if (ASTType(a) == AST_NODE_LIST) shape = mdiamond; // if (a->construct_type == CT_SPECIFICATION) shape = ellipse; // else if (a->construct_type == CT_OMP_SPECIFICATION) shape = mdiamond; // else if (a->construct_type == CT_EXECUTABLE) shape = octagon; // else if (a->construct_type == CT_OMP_EXECUTABLE) shape = doubleoctagon; if (ASTText(a)) { char *quoted = quote_protect(ASTText(a)); fprintf(f, "n%zd[shape=%s,label=\"%s\\nNode=%p\\nParent=%p\\n%s\\nText: \\\"%s\\\"\"]\n", current_node, shape, ast_print_node_type(ASTType(a)), a, ASTParent(a), ast_location(a), quoted); free(quoted); } else { fprintf(f, "n%zd[shape=%s,label=\"%s\\nNode=%p\\nParent=%p\\n%s\"]\n", current_node, shape, ast_print_node_type(ASTType(a)), a, ASTParent(a), ast_location(a)); } // Print this only for non extended referenced nodes if (parent_node != 0) { fprintf(f, "n%zd -> n%zd [label=\"%d\"]\n", parent_node, current_node, position); } if (ASTType(a) != AST_AMBIGUITY) { int i; if (!is_extended) { for(i = 0; i < ASTNumChildren(a); i++) { if (ASTChild(a, i) != NULL) { ast_dump_graphviz_rec(ASTChild(a, i), f, current_node, i, /* is_extended */ is_extended); } } } // Now print all extended trees referenced here // First get all TL_AST in 'orig' that point to its childrens extensible_struct_t* extended_data = ast_get_extensible_struct(a); if (extended_data != NULL && !is_extended) { int num_fields = 0; const char** keys = NULL; const void** values = NULL; extensible_struct_get_all_data(extended_data, &num_fields, &keys, &values); for (i = 0; i < num_fields; i++) { const char* field_name = keys[i]; tl_type_t* tl_data = (tl_type_t*)values[i]; if (tl_data->kind == TL_AST) { if (tl_data->data._ast != a) { ast_dump_graphviz_rec(tl_data->data._ast, f, /* parent_node */ 0, /* position */ 0, /* is_extended */ 1); } // Add an edge fprintf(f, "n%zd -> n%zd [label=\"%s\",style=dashed]\n", current_node, (size_t)(tl_data->data._ast), field_name); } } } } else if (ASTType(a) == AST_AMBIGUITY) { int i; for(i = 0; i < ast_get_num_ambiguities(a); i++) { ast_dump_graphviz_rec(ast_get_ambiguity(a, i), f, current_node, i, /* is_extended */ 0); } } } else { fprintf(f, "n%zd[shape=circle,label=\"\",fixedsize=true,style=filled,fillcolor=black,height=0.1,width=0.1]\n", current_node); if (parent_node != 0) { fprintf(f, "n%zd -> n%zd [label=\"%d\"]\n", parent_node, current_node, position); } } }
AST_t AST_t::get_parent() const { return ASTParent(this->_ast); }
static void ast_dump_graphviz_rec(AST a, FILE* f, int parent_node, int position) { // static char* octagon = "octagon"; // static char* doubleoctagon = "doubleoctagon"; static char* ellipse = "ellipse"; static char* mdiamond = "Mdiamond"; static char* box = "box"; char* shape; int node_actual = nodes_counter++; if (a != NULL) { // Select shape shape = box; if (ASTType(a) == AST_AMBIGUITY) shape = ellipse; if (ASTType(a) == AST_NODE_LIST) shape = mdiamond; // if (a->construct_type == CT_SPECIFICATION) shape = ellipse; // else if (a->construct_type == CT_OMP_SPECIFICATION) shape = mdiamond; // else if (a->construct_type == CT_EXECUTABLE) shape = octagon; // else if (a->construct_type == CT_OMP_EXECUTABLE) shape = doubleoctagon; if (ASTText(a)) { fprintf(f, "n%d[shape=%s,label=\"%s\\nNode=%p\\nParent=%p\\n%s\\nText: -%s-\"]\n", node_actual, shape, ast_print_node_type(ASTType(a)), a, ASTParent(a), ast_location(a), ASTText(a)); } else { fprintf(f, "n%d[shape=%s,label=\"%s\\nNode=%p\\nParent=%p\\n%s\"]\n", node_actual, shape, ast_print_node_type(ASTType(a)), a, ASTParent(a), ast_location(a)); } if (parent_node != 0) { fprintf(f, "n%d -> n%d [label=\"%d\"]\n", parent_node, node_actual, position); } if (ASTType(a) != AST_AMBIGUITY) { int i; for(i = 0; i < ASTNumChildren(a); i++) { ast_dump_graphviz_rec(ASTChild(a, i),f, node_actual, i); } } else if (ASTType(a) == AST_AMBIGUITY) { int i; for(i = 0; i < ast_get_num_ambiguities(a); i++) { ast_dump_graphviz_rec(ast_get_ambiguity(a, i), f, node_actual, i); } } } else { fprintf(f, "n%d[shape=circle,label=\"\",fixedsize=true,style=filled,fillcolor=black,height=0.1,width=0.1]\n", node_actual); if (parent_node != 0) { fprintf(f, "n%d -> n%d [label=\"%d\"]\n", parent_node, node_actual, position); } } }