static void addcan(int tok, Node *n, Miscellaneous *miscell) { Node *m, *prev = ZN; Node **ptr; Node *N; Symbol *s, *t; int cmp; static char dumpbuf[BUFF_LEN]; static Node *can = ZN; if (!n) return; if (n->ntyp == tok) { addcan(tok, n->rgt, miscell); addcan(tok, n->lft, miscell); return; } #if 0 if ((tok == AND && n->ntyp == TRUE) || (tok == OR && n->ntyp == FALSE)) return; #endif N = dupnode(n); if (!can) { can = N; return; } s = DoDump(N,dumpbuf, miscell); if (can->ntyp != tok) /* only one element in list so far */ { ptr = &can; goto insert; } /* there are at least 2 elements in list */ prev = ZN; for (m = can; m->ntyp == tok && m->rgt; prev = m, m = m->rgt) { t = DoDump(m->lft,dumpbuf, miscell); cmp = strcmp(s->name, t->name); if (cmp == 0) /* duplicate */ return; if (cmp < 0) { if (!prev) { can = tl_nn(tok, N, can, miscell); return; } else { ptr = &(prev->rgt); goto insert; } } } /* new entry goes at the end of the list */ ptr = &(prev->rgt); insert: t = DoDump(*ptr,dumpbuf, miscell); cmp = strcmp(s->name, t->name); if (cmp == 0) /* duplicate */ return; if (cmp < 0) *ptr = tl_nn(tok, N, *ptr, miscell); else *ptr = tl_nn(tok, *ptr, N, miscell); }
static void addcan(int tok, Node *n) { Node *m, *prev = ZN; Node **ptr; Node *N; Symbol *s, *t; int cmp; if (!n) return; if (n->ntyp == tok) { addcan(tok, n->rgt); addcan(tok, n->lft); return; } N = dupnode(n); if (!can) { can = N; return; } s = DoDump(N); if (can->ntyp != tok) /* only one element in list so far */ { ptr = &can; goto insert; } /* there are at least 2 elements in list */ prev = ZN; for (m = can; m->ntyp == tok && m->rgt; prev = m, m = m->rgt) { t = DoDump(m->lft); if (t != ZS) cmp = strcmp(s->name, t->name); else cmp = 0; if (cmp == 0) /* duplicate */ return; if (cmp < 0) { if (!prev) { can = tl_nn(tok, N, can); return; } else { ptr = &(prev->rgt); goto insert; } } } /* new entry goes at the end of the list */ ptr = &(prev->rgt); insert: t = DoDump(*ptr); cmp = strcmp(s->name, t->name); if (cmp == 0) /* duplicate */ return; if (cmp < 0) *ptr = tl_nn(tok, N, *ptr); else *ptr = tl_nn(tok, *ptr, N); }
Node * Canonical(Node *n) { Node *m, *p, *k1, *k2, *prev, *dflt = ZN; int tok; if (!n) return n; tok = n->ntyp; if (tok != AND && tok != OR) return n; can = ZN; addcan(tok, n); #if 0 Debug("\nA0: "); Dump(can); Debug("\nA1: "); Dump(n); Debug("\n"); #endif releasenode(1, n); /* mark redundant nodes */ if (tok == AND) { for (m = can; m; m = (m->ntyp == AND) ? m->rgt : ZN) { k1 = (m->ntyp == AND) ? m->lft : m; if (k1->ntyp == TRUE) { marknode(AND, m); dflt = True; continue; } if (k1->ntyp == FALSE) { releasenode(1, can); can = False; goto out; } } for (m = can; m; m = (m->ntyp == AND) ? m->rgt : ZN) for (p = can; p; p = (p->ntyp == AND) ? p->rgt : ZN) { if (p == m || p->ntyp == -1 || m->ntyp == -1) continue; k1 = (m->ntyp == AND) ? m->lft : m; k2 = (p->ntyp == AND) ? p->lft : p; if (isequal(k1, k2)) { marknode(AND, p); continue; } if (anywhere(OR, k1, k2)) { marknode(AND, p); continue; } } } if (tok == OR) { for (m = can; m; m = (m->ntyp == OR) ? m->rgt : ZN) { k1 = (m->ntyp == OR) ? m->lft : m; if (k1->ntyp == FALSE) { marknode(OR, m); dflt = False; continue; } if (k1->ntyp == TRUE) { releasenode(1, can); can = True; goto out; } } for (m = can; m; m = (m->ntyp == OR) ? m->rgt : ZN) for (p = can; p; p = (p->ntyp == OR) ? p->rgt : ZN) { if (p == m || p->ntyp == -1 || m->ntyp == -1) continue; k1 = (m->ntyp == OR) ? m->lft : m; k2 = (p->ntyp == OR) ? p->lft : p; if (isequal(k1, k2)) { marknode(OR, p); continue; } if (anywhere(AND, k1, k2)) { marknode(OR, p); continue; } } } for (m = can, prev = ZN; m; ) /* remove marked nodes */ { if (m->ntyp == -1) { k2 = m->rgt; releasenode(0, m); if (!prev) { m = can = can->rgt; } else { m = prev->rgt = k2; /* if deleted the last node in a chain */ if (!prev->rgt && prev->lft && (prev->ntyp == AND || prev->ntyp == OR)) { k1 = prev->lft; prev->ntyp = prev->lft->ntyp; prev->sym = prev->lft->sym; prev->rgt = prev->lft->rgt; prev->lft = prev->lft->lft; releasenode(0, k1); } } continue; } prev = m; m = m->rgt; } out: #if 0 Debug("A2: "); Dump(can); Debug("\n"); #endif if (!can) { if (!dflt) fatal("cannot happen, Canonical", (char *) 0); return dflt; } return can; }