EPNODE * getE3(void) /* E3 -> E4 ^ E3 */ /* E4 */ { EPNODE *ep1, *ep2; ep1 = getE4(); if (nextc != '^') return(ep1); ep2 = newnode(); ep2->type = nextc; scan(); addekid(ep2, ep1); addekid(ep2, getE3()); if (esupport&E_RCONST) { EPNODE *ep3 = ep1->sibling; if (ep1->type == NUM && ep3->type == NUM) { ep2 = rconst(ep2); } else if (ep1->type == NUM && ep1->v.num == 0) { epfree(ep3); /* (0 ^ E3) */ ep1->sibling = NULL; efree((char *)ep2); ep2 = ep1; } else if ((ep3->type == NUM && ep3->v.num == 0) || (ep1->type == NUM && ep1->v.num == 1)) { epfree(ep2); /* (E4 ^ 0) or (1 ^ E3) */ ep2 = newnode(); ep2->type = NUM; ep2->v.num = 1; } } return(ep2); }
void epfree( /* free a parse tree */ EPNODE *epar ) { EPNODE *ep; switch (epar->type) { case VAR: varfree(epar->v.ln); break; case SYM: freestr(epar->v.name); break; case NUM: case CHAN: case ARG: case CLKT: break; default: while ((ep = epar->v.kid) != NULL) { epar->v.kid = ep->sibling; epfree(ep); } break; } efree((char *)epar); }
void addchan( /* add an output channel assignment */ EPNODE *sp ) { int ch = sp->v.kid->v.chan; EPNODE *ep, *epl; for (epl = NULL, ep = outchan; ep != NULL; epl = ep, ep = ep->sibling) if (ep->v.kid->v.chan >= ch) { if (epl != NULL) epl->sibling = sp; else outchan = sp; if (ep->v.kid->v.chan > ch) sp->sibling = ep; else { sp->sibling = ep->sibling; epfree(ep); } return; } if (epl != NULL) epl->sibling = sp; else outchan = sp; sp->sibling = NULL; }
void dremove( /* delete all definitions of name */ char *name ) { EPNODE *ep; while ((ep = dpop(name)) != NULL) epfree(ep); }
EPNODE * getE2(void) /* E2 -> E2 MULOP E3 */ /* E3 */ { EPNODE *ep1, *ep2; ep1 = getE3(); while (nextc == '*' || nextc == '/') { ep2 = newnode(); ep2->type = nextc; scan(); addekid(ep2, ep1); addekid(ep2, getE3()); if (esupport&E_RCONST) { EPNODE *ep3 = ep1->sibling; if (ep1->type == NUM && ep3->type == NUM) { ep2 = rconst(ep2); } else if (ep3->type == NUM) { if (ep2->type == '/') { if (ep3->v.num == 0) syntax("divide by zero constant"); ep2->type = '*'; /* for speed */ ep3->v.num = 1./ep3->v.num; } else if (ep3->v.num == 0) { ep1->sibling = NULL; /* (E2 * 0) */ epfree(ep2); ep2 = ep3; } } else if (ep1->type == NUM && ep1->v.num == 0) { epfree(ep3); /* (0 * E3) or (0 / E3) */ ep1->sibling = NULL; efree((char *)ep2); ep2 = ep1; } } ep1 = ep2; } return(ep1); }
double eval( /* evaluate an expression string */ char *expr ) { EPNODE *ep; double rval; ep = eparse(expr); rval = evalue(ep); epfree(ep); return(rval); }
void dclear( /* delete variable definitions of name */ char *name ) { EPNODE *ep; while ((ep = dpop(name)) != NULL) { if (ep->type == ':') { dpush(name, ep); /* don't clear constants */ return; } epfree(ep); } }
EPNODE * rconst( /* reduce a constant expression */ EPNODE *epar ) { EPNODE *ep; ep = newnode(); ep->type = NUM; errno = 0; ep->v.num = evalue(epar); if (errno == EDOM || errno == ERANGE) syntax("bad constant expression"); epfree(epar); return(ep); }
void dcleanup( /* clear definitions (0->vars,1->output,2->consts) */ int lvl ) { int i; VARDEF *vp; EPNODE *ep; /* if context is global, clear all */ for (i = 0; i < NHASH; i++) for (vp = hashtbl[i]; vp != NULL; vp = vp->next) if (incontext(vp->name)) { if (lvl >= 2) dremove(vp->name); else dclear(vp->name); } if (lvl >= 1) { for (ep = outchan; ep != NULL; ep = ep->sibling) epfree(ep); outchan = NULL; } }