int epcmp( /* compare two expressions for equivalence */ EPNODE *ep1, EPNODE *ep2 ) { double d; if (ep1->type != ep2->type) return(1); switch (ep1->type) { case VAR: return(ep1->v.ln != ep2->v.ln); case NUM: if (ep2->v.num == 0) return(ep1->v.num != 0); d = ep1->v.num / ep2->v.num; return((d > 1.000000000001) | (d < 0.999999999999)); case CHAN: case ARG: return(ep1->v.chan != ep2->v.chan); case '=': case ':': return(epcmp(ep1->v.kid->sibling, ep2->v.kid->sibling)); case CLKT: case SYM: /* should never get this one */ return(0); default: ep1 = ep1->v.kid; ep2 = ep2->v.kid; while (ep1 != NULL) { if (ep2 == NULL) return(1); if (epcmp(ep1, ep2)) return(1); ep1 = ep1->sibling; ep2 = ep2->sibling; } return(ep2 != NULL); } }
void getstatement(void) /* get next statement */ { EPNODE *ep; char *qname; VARDEF *vdef; if (nextc == ';') { /* empty statement */ scan(); return; } if (esupport&E_OUTCHAN && nextc == '$') { /* channel assignment */ ep = getchan(); addchan(ep); } else { /* ordinary definition */ ep = getdefn(); qname = qualname(dname(ep), 0); if (esupport&E_REDEFW && (vdef = varlookup(qname)) != NULL) { if (vdef->def != NULL && epcmp(ep, vdef->def)) { wputs(qname); if (vdef->def->type == ':') wputs(": redefined constant expression\n"); else wputs(": redefined\n"); } else if (ep->v.kid->type == FUNC && vdef->lib != NULL) { wputs(qname); wputs(": definition hides library function\n"); } } if (ep->type == ':') dremove(qname); else dclear(qname); dpush(qname, ep); } if (nextc != EOF) { if (nextc != ';') syntax("';' expected"); scan(); } }