static void expand_g(Graph *g) { Node *now, *n1, *n2, *nx; int can_release; if (!g->New) { Debug2("\nDone with %s", g->name->name); if (tl_verbose) dump_graph(g); if (not_new(g)) { if (tl_verbose) printf("\tIs Not New\n"); return; } if (g->Next) { Debug(" Has Next ["); for (n1 = g->Next; n1; n1 = n1->nxt) { Dump(n1); Debug(", "); } Debug("]\n"); ng(ZS, getsym(g->name), g->Next, ZN, ZN); } return; } if (tl_verbose) { Symbol *z; printf("\nExpand %s, from ", g->name->name); for (z = g->incoming; z; z = z->next) printf("%s, ", z->name); printf("\n\thandle:\t"); Explain(g->New->ntyp); dump_graph(g); } if (g->New->ntyp == AND) { if (g->New->nxt) { n2 = g->New->rgt; while (n2->nxt) n2 = n2->nxt; n2->nxt = g->New->nxt; } n1 = n2 = g->New->lft; while (n2->nxt) n2 = n2->nxt; n2->nxt = g->New->rgt; releasenode(0, g->New); g->New = n1; push_stack(g); return; } can_release = 0; /* unless it need not go into Old */ now = g->New; g->New = g->New->nxt; now->nxt = ZN; if (now->ntyp != TRUE) { if (g->Old) { for (n1 = g->Old; n1->nxt; n1 = n1->nxt) if (isequal(now, n1)) { can_release = 1; goto out; } n1->nxt = now; } else g->Old = now; } out: switch (now->ntyp) { case FALSE: push_stack(g); break; case TRUE: releasenode(1, now); push_stack(g); break; case PREDICATE: case NOT: if (can_release) releasenode(1, now); push_stack(g); break; case V_OPER: Assert(now->rgt != ZN, now->ntyp); Assert(now->lft != ZN, now->ntyp); Assert(now->rgt->nxt == ZN, now->ntyp); Assert(now->lft->nxt == ZN, now->ntyp); n1 = now->rgt; n1->nxt = g->New; if (can_release) nx = now; else nx = getnode(now); /* now also appears in Old */ nx->nxt = g->Next; n2 = now->lft; n2->nxt = getnode(now->rgt); n2->nxt->nxt = g->New; g->New = flatten(n2); push_stack(g); ng(ZS, g->incoming, n1, g->Old, nx); break; case U_OPER: Assert(now->rgt->nxt == ZN, now->ntyp); Assert(now->lft->nxt == ZN, now->ntyp); n1 = now->lft; if (can_release) nx = now; else nx = getnode(now); /* now also appears in Old */ nx->nxt = g->Next; n2 = now->rgt; n2->nxt = g->New; goto common; #ifdef NXT case NEXT: Assert(now->lft != ZN, now->ntyp); nx = dupnode(now->lft); nx->nxt = g->Next; g->Next = nx; if (can_release) releasenode(0, now); push_stack(g); break; #endif case OR: Assert(now->rgt->nxt == ZN, now->ntyp); Assert(now->lft->nxt == ZN, now->ntyp); n1 = now->lft; nx = g->Next; n2 = now->rgt; n2->nxt = g->New; common: n1->nxt = g->New; ng(ZS, g->incoming, n1, g->Old, nx); g->New = flatten(n2); if (can_release) releasenode(1, now); push_stack(g); break; } }
// Apply DeMorgan's law to push the NOT node if it is found above an AND or an OR node. // Return TRUE when a NOT node is pushed down else return FALSE. int push_down_NOT(syntree *arg, List *del_node_list) { syntree *NOT_A_node, *NOT_B_node, *A_node, *B_node; syntree *node_to_be_del; ASSERT(arg); ASSERT(arg->type == NOT_TYPE); ASSERT(arg->left_tree); ASSERT(arg->right_tree == NULL); if (arg->left_tree->type == AND_TYPE) { // NOT above AND. Apply DeMorgan's Law // NOT(A AND B) -> NOT(A) OR NOT(B) A_node = arg->left_tree->left_tree; B_node = arg->left_tree->right_tree; // Add the unwanted AND node to the list of nodes to be deleted. node_to_be_del = arg->left_tree; List_insertElement(del_node_list, node_to_be_del); // Create the NOT(A) subtree. NOT_A_node = not_new(A_node); // Create the NOT(B) subtree. NOT_B_node = not_new(B_node); // Convert the root NOT node to an OR node and create the (NOT(A) OR NOT(B)) tree. arg->type = OR_TYPE; arg->left_tree = NOT_A_node; arg->right_tree = NOT_B_node; return TRUE; } else if (arg->left_tree->type == OR_TYPE) { // NOT above OR. Apply DeMorgan's Law // NOT(A OR B) -> NOT(A) AND NOT(B) A_node = arg->left_tree->left_tree; B_node = arg->left_tree->right_tree; // Add the unwanted OR node to the list of nodes to be deleted. node_to_be_del = arg->left_tree; List_insertElement(del_node_list, node_to_be_del); // Create the NOT(A) subtree. NOT_A_node = not_new(A_node); // Create the NOT(B) subtree. NOT_B_node = not_new(B_node); // Convert the root NOT node to an AND node and create the (NOT(A) AND NOT(B)) tree. arg->type = AND_TYPE; arg->left_tree = NOT_A_node; arg->right_tree = NOT_B_node; return TRUE; } else { // No need to push down the NOT node return FALSE; } }