static void print_graph_node(NODE *node) { int i; GRAPH *graph = CAST_TO_GRAPH(node); printf("\n"); for (i = 0; i < tree_num_children(node); i++) { HASH_ENTRY *he; printf("%d ->", i); he = find_in_hash(graph->forward, tree_get_child(node, i), sizeof(void *)); if (he) { HASH *subhash = he->data; HASH_ITERATOR iter; for (hash_iterator(subhash, &iter); hash_iterator_valid(&iter); hash_iterator_next(&iter)) { NODE *n = iter.entry->key; HASH_ENTRY *he2 = find_in_hash(graph->labels, n, sizeof(void *)); if (he2) printf(" %d", (int) he2->data); } } printf("\n"); tree_print(tree_get_child(node, i), 2); } }
void replace_backward(GRAPH *graph, NODE *old, NODE *vertex, EDGE_TYPE type) { HASH *subhash = get_from_hash(graph->backward, old, sizeof(void *)); HASH_ITERATOR iter; for (hash_iterator(subhash, &iter); hash_iterator_valid(&iter); hash_iterator_next(&iter)) { NODE *pred = iter.entry->key; EDGE_TYPE type2 = (EDGE_TYPE) iter.entry->data; remove_edge(graph, pred, old); if (vertex != NULL) add_edge(graph, pred, vertex, type | type2); } }
static NODE *get_successor(GRAPH *graph, NODE *vertex, EDGE_TYPE type) { HASH *subhash = get_from_hash(graph->forward, vertex, sizeof(void *)); HASH_ITERATOR iter; for (hash_iterator(subhash, &iter); hash_iterator_valid(&iter); hash_iterator_next(&iter)) { NODE *succ = iter.entry->key; EDGE_TYPE succ_type = (EDGE_TYPE) iter.entry->data; if (succ_type & type) return succ; } return NULL; }
void inject_before(GRAPH *graph, NODE *vertex, NODE *before, EDGE_TYPE type) { HASH *subhash = get_from_hash(graph->backward, before, sizeof(void *)); HASH_ITERATOR iter; for (hash_iterator(subhash, &iter); hash_iterator_valid(&iter); hash_iterator_next(&iter)) { NODE *pred = iter.entry->key; EDGE_TYPE type = (EDGE_TYPE) iter.entry->data; remove_edge(graph, pred, before); add_edge(graph, pred, vertex, type); } add_edge(graph, vertex, before, EDGE_NORMAL | type); }
void hash_remove_by_value(struct hash *hash, void *value) { struct hash_iterator hi; struct hash_element *he; hash_iterator_init(hash, &hi); while ((he = hash_iterator_next(&hi))) { if (he->value == value) { hash_iterator_delete_element(&hi); } } hash_iterator_free(&hi); }
static void pf_cn_set_print(const struct pf_cn_set *s, const int lev) { if (s) { struct hash_iterator hi; struct hash_element *he; msg(lev, " ----- struct pf_cn_set -----"); msg(lev, " default_allow=%s", drop_accept(s->default_allow)); if (s->hash_table) { hash_iterator_init(s->hash_table, &hi); while ((he = hash_iterator_next(&hi))) { struct pf_cn *e = (struct pf_cn *)he->value; msg(lev, " %s %s", e->cn, drop_accept(!e->exclude)); } msg(lev, " ----------"); { struct pf_cn_elem *ce; for (ce = s->list; ce != NULL; ce = ce->next) { struct pf_cn *e = lookup_cn_rule(s->hash_table, ce->rule.cn, cn_hash_function(ce->rule.cn, 0)); if (e) { msg(lev, " %s %s", e->cn, drop_accept(!e->exclude)); } else { msg(lev, " %s LOOKUP FAILED", ce->rule.cn); } } } } } }
static void print_nhash(struct hash *hash) { struct hash_iterator hi; struct hash_element *he; int count = 0; hash_iterator_init(hash, &hi, true); while ((he = hash_iterator_next(&hi))) { printf("%d ", (int) he->value); ++count; } printf("\n"); hash_iterator_free(&hi); ASSERT(count == hash_n_elements(hash)); }
static void edge_printer(NODE *from, NODE *to, void *data) { if (data) { DFA *dfa = data; LIST *output = get_from_hash(dfa->outputs, to, sizeof(void *)); DAA_SET *set = output->size ? output->items[0] : NULL; if (set) { printf("{"); HASH_ITERATOR iter; for (hash_iterator(set->set, &iter); hash_iterator_valid(&iter); hash_iterator_next(&iter)) { DECLARATION *decl = CAST_TO_DECLARATION(iter.entry->data); printf("<font color=\"%s\">%s</font>", get_colour(decl->colour), (char *) iter.entry->key); printf(","); } printf("}"); } } }
static EXPRESSION *simplify_expression(MODULE *module, FUNCTION *func, BLOCK *block, EXPRESSION *expr, STATEMENT *before) { int i; int source_line = CAST_TO_AST(expr)->source_line; if (!has_graph(func) && is_short_circuit(expr)) { TYPE *new_temp_type = CAST_TO_EXPRESSION(tree_get_child(expr, 0))->type; EXPRESSION *new_temp = make_new_temp(module, func, new_temp_type, source_line); STATEMENT *new_assign = make_assignment(new_temp, tree_get_child(expr, 0), source_line); tree_add_before(CAST_TO_NODE(block), CAST_TO_NODE(new_assign), CAST_TO_NODE(before)); STATEMENT *new_assign2 = make_assignment(new_temp, tree_get_child(expr, 1), source_line); EXPRESSION *new_cond = new_temp; if (tree_is_type(expr, EXPR_OR)) new_cond = make_unary_expression(EXPR_NOT, new_cond, source_line); STATEMENT *new_if = make_if(new_cond, make_block(NULL, new_assign2, 0), NULL, 0); tree_add_before(CAST_TO_NODE(block), CAST_TO_NODE(new_if), CAST_TO_NODE(before)); return new_temp; } if (has_graph(func) && is_short_circuit(expr)) { GRAPH *graph = func->graph; EXPRESSION *sub0 = tree_get_child(expr, 0); EXPRESSION *sub1 = tree_get_child(expr, 1); STATEMENT *new_test = make_test(sub0, source_line); EDGE_TYPE inner_type = tree_is_type(expr, EXPR_OR) ? EDGE_NO : EDGE_YES; EDGE_TYPE outer_type = tree_is_type(expr, EXPR_OR) ? EDGE_YES : EDGE_NO; add_vertex(graph, CAST_TO_NODE(new_test)); HASH *subhash = get_from_hash(graph->forward, before, sizeof(void *)); HASH_ITERATOR iter; for (hash_iterator(subhash, &iter); hash_iterator_valid(&iter); hash_iterator_next(&iter)) { EDGE_TYPE type = (EDGE_TYPE) iter.entry->data; if (outer_type & type) add_edge(graph, CAST_TO_NODE(new_test), iter.entry->key, type); if (inner_type & type) inner_type = type; } inject_before(graph, CAST_TO_NODE(new_test), CAST_TO_NODE(before), inner_type); return sub1; } if (is_simple(expr)) return expr; if (tree_is_type(expr, EXPR_CALL)) { EXPRESSION *args = CAST_TO_EXPRESSION(tree_get_child(expr, 1)); args = atomise_expression(module, func, block, args, before); tree_get_child(expr, 1) = args; return expr; } for (i = 0; i < tree_num_children(expr); i++) { EXPRESSION *child = tree_get_child(expr, i); if (!is_atomic(child)) { TYPE *new_temp_type = CAST_TO_EXPRESSION(child)->type; EXPRESSION *new_temp = make_new_temp(module, func, new_temp_type, CAST_TO_AST(child)->source_line); STATEMENT *new_assign = make_assignment(new_temp, child, CAST_TO_AST(child)->source_line); if (has_graph(func)) { GRAPH *graph = func->graph; add_vertex(graph, CAST_TO_NODE(new_assign)); inject_before(graph, CAST_TO_NODE(new_assign), CAST_TO_NODE(before), 0); } else tree_add_before(CAST_TO_NODE(block), CAST_TO_NODE(new_assign), CAST_TO_NODE(before)); tree_get_child(expr, i) = new_temp; } } return expr; }
void list_test(void) { openvpn_thread_init(); { struct gc_arena gc = gc_new(); struct hash *hash = hash_init(10000, get_random(), word_hash_function, word_compare_function); struct hash *nhash = hash_init(256, get_random(), word_hash_function, word_compare_function); printf("hash_init n_buckets=%d mask=0x%08x\n", hash->n_buckets, hash->mask); /* parse words from stdin */ while (true) { char buf[256]; char wordbuf[256]; int wbi; int bi; char c; if (!fgets(buf, sizeof(buf), stdin)) { break; } bi = wbi = 0; do { c = buf[bi++]; if (isalnum(c) || c == '_') { ASSERT(wbi < (int) sizeof(wordbuf)); wordbuf[wbi++] = c; } else { if (wbi) { struct word *w; ASSERT(wbi < (int) sizeof(wordbuf)); wordbuf[wbi++] = '\0'; /* word is parsed from stdin */ /* does it already exist in table? */ w = (struct word *) hash_lookup(hash, wordbuf); if (w) { /* yes, increment count */ ++w->n; } else { /* no, make a new object */ ALLOC_OBJ_GC(w, struct word, &gc); w->word = string_alloc(wordbuf, &gc); w->n = 1; ASSERT(hash_add(hash, w->word, w, false)); ASSERT(hash_add(nhash, w->word, (void *) ((random() & 0x0F) + 1), false)); } } wbi = 0; } } while (c); } #if 1 /* remove some words from the table */ { rmhash(hash, "true"); rmhash(hash, "false"); } #endif /* output contents of hash table */ { int base; int inc = 0; int count = 0; for (base = 0; base < hash_n_buckets(hash); base += inc) { struct hash_iterator hi; struct hash_element *he; inc = (get_random() % 3) + 1; hash_iterator_init_range(hash, &hi, true, base, base + inc); while ((he = hash_iterator_next(&hi))) { struct word *w = (struct word *) he->value; printf("%6d '%s'\n", w->n, w->word); ++count; } hash_iterator_free(&hi); } ASSERT(count == hash_n_elements(hash)); } #if 1 /* test hash_remove_by_value function */ { int i; for (i = 1; i <= 16; ++i) { printf("[%d] ***********************************\n", i); print_nhash(nhash); hash_remove_by_value(nhash, (void *) i, true); } printf("FINAL **************************\n"); print_nhash(nhash); } #endif hash_free(hash); hash_free(nhash); gc_free(&gc); } openvpn_thread_cleanup(); }
int emit_function(FUNCTION *func, EMIT_FUNCTIONS *functions, void *data) { GRAPH *graph = func->graph; QUEUE *queue = create_queue(); HASH *done = create_hash(10, key_type_direct); queue_push(queue, tree_get_child(graph, 0)); NODE *last = NULL; while (!queue_is_empty(queue)) { NODE *vertex = queue_pop(queue); if (find_in_hash(done, vertex, sizeof(void *))) continue; do_next: add_to_hash(done, vertex, sizeof(void *), (void *) 1); int label = (int) get_from_hash(graph->labels, vertex, sizeof(void *)); HASH *predecessor_hash = get_from_hash(graph->backward, vertex, sizeof(void *)); HASH_ITERATOR iter; hash_iterator(predecessor_hash, &iter); if (predecessor_hash && (predecessor_hash->num > 1 || (predecessor_hash->num == 1 && last != iter.entry->key))) { functions->emit_label(label, data); } functions->emit_comment(vertex, data); HASH *successor_hash = get_from_hash(graph->forward, vertex, sizeof(void *)); NODE *successor; int successor_label; if (successor_hash) { hash_iterator(successor_hash, &iter); successor = iter.entry->key; successor_label = (int) get_from_hash(graph->labels, successor, sizeof(void *)); } else successor = NULL; if (tree_is_type(vertex, STMT_ENTER)) { functions->emit_enter(vertex, data); } else if (tree_is_type(vertex, STMT_EXIT)) { functions->emit_exit(vertex, data); last = vertex; continue; } else if (tree_is_type(vertex, STMT_ASSIGN)) functions->emit_assign(vertex, data); else if (tree_is_type(vertex, STMT_RETURN)) functions->emit_return(vertex, data); else if (tree_is_type(vertex, STMT_TEST)) { hash_iterator_next(&iter); NODE *branch = iter.entry->key; EDGE_TYPE branch_type = (EDGE_TYPE) iter.entry->data; int branch_label = (int) get_from_hash(graph->labels, branch, sizeof(void *)); functions->emit_test(vertex, branch_type, branch_label, data); if (!find_in_hash(done, branch, sizeof(void *))) queue_push(queue, branch); /* Force label on next vertex, in case we jumped to it in the test's branch. Fixes a bug where the label is omitted just because the test was before it, by neglecting to notice that the test reaches it by a jump. */ vertex = NULL; } last = vertex; if (find_in_hash(done, successor, sizeof(void *))) { functions->emit_jump(successor_label, data); continue; } vertex = successor; if (vertex) goto do_next; } functions->emit_end(data); destroy_queue(queue); destroy_hash(done); return 1; }
void print_graph(GRAPH *graph, char *name, void *data) { int i; graph_sequence++; printf("subgraph cluster_%s_%d {\n", name, graph_sequence); printf(" label=\"%s\"; labelloc=\"t\";\n", name); printf(" ranksep=0.1\n"); printf(" node [shape=\"box\", style=\"filled\"];\n"); /* Vertices. */ for (i = 0; i < tree_num_children(graph); i++) { NODE *vertex = tree_get_child(graph, i); if (vertex == NULL) continue; if (combine_bb && !tree_is_type(vertex, DEF_VARIABLE) && get_bb_next(graph, vertex, 2)) continue; printf(" %s_%d_%d [label=<<table border=\"0\">\n", name, graph_sequence, i); printf("<tr><td>%d. ", i); vertex_printer(vertex, data); printf("</td></tr>\n"); if (combine_bb && !tree_is_type(vertex, DEF_VARIABLE)) { NODE *next_vertex = get_bb_next(graph, vertex, 1); while (next_vertex) { vertex = next_vertex; int pos = (int) get_from_hash(graph->labels, vertex, sizeof(void *)); printf("<tr><td>%d. ", pos); vertex_printer(vertex, data); printf("</td></tr>\n"); next_vertex = get_bb_next(graph, vertex, 1); } } printf("</table>>"); if (tree_is_type(vertex, DEF_VARIABLE)) { DECLARATION *decl = CAST_TO_DECLARATION(vertex); printf(", fillcolor=%s", get_colour(decl->colour)); } printf("];\n"); HASH_ENTRY *he; NODE *from = vertex; he = find_in_hash(graph->forward, from, sizeof(void *)); if (he) { HASH *subhash = he->data; HASH_ITERATOR iter; for (hash_iterator(subhash, &iter); hash_iterator_valid(&iter); hash_iterator_next(&iter)) { NODE *to = iter.entry->key; HASH_ENTRY *he2 = find_in_hash(graph->labels, to, sizeof(void *)); if (he2) { EDGE_TYPE type = (EDGE_TYPE) iter.entry->data; if (type == EDGE_SYMMETRICAL) continue; printf(" %s_%d_%d -> %s_%d_%d [label=<", name, graph_sequence, i, name, graph_sequence, (int) he2->data); if (type & EDGE_YES) printf("Y"); if (type & EDGE_NO) printf("N"); if (type & EDGE_BACK) printf("B"); if (type & EDGE_LOOP) printf("L"); edge_printer(from, to, data); printf(">];\n"); } } } } printf("}\n"); }