| 1 |
< |
/* Copyright (c) 1986 Regents of the University of California */ |
| 1 |
> |
/* Copyright (c) 1991 Regents of the University of California */ |
| 2 |
|
|
| 3 |
|
#ifndef lint |
| 4 |
|
static char SCCSid[] = "$SunId$ LBL"; |
| 16 |
|
* 1/15/88 Added clock for caching of variable values. |
| 17 |
|
* |
| 18 |
|
* 11/16/88 Added VARDEF structure for hard linking. |
| 19 |
+ |
* |
| 20 |
+ |
* 5/31/90 Added conditional compile (REDEFW) for redefinition warning. |
| 21 |
+ |
* |
| 22 |
+ |
* 4/23/91 Added ':' assignment for constant expressions |
| 23 |
|
*/ |
| 24 |
|
|
| 25 |
|
#include <stdio.h> |
| 36 |
|
|
| 37 |
|
extern char *ecalloc(), *savestr(); |
| 38 |
|
|
| 39 |
< |
extern double dvalue(); |
| 39 |
> |
static double dvalue(); |
| 40 |
|
|
| 41 |
|
long eclock = -1; /* value storage timer */ |
| 42 |
|
|
| 70 |
|
eputs(": cannot open\n"); |
| 71 |
|
quit(1); |
| 72 |
|
} |
| 73 |
< |
initfile(fname, fp); |
| 73 |
> |
initfile(fp, fname, 0); |
| 74 |
|
while (nextc != EOF) |
| 75 |
|
loaddefn(); |
| 76 |
|
if (fname != NULL) |
| 78 |
|
} |
| 79 |
|
|
| 80 |
|
|
| 81 |
< |
scompile(file, str) /* get definitions from a string */ |
| 78 |
< |
char *file; |
| 81 |
> |
scompile(str, fn, ln) /* get definitions from a string */ |
| 82 |
|
char *str; |
| 83 |
+ |
char *fn; |
| 84 |
+ |
int ln; |
| 85 |
|
{ |
| 86 |
< |
initstr(file, str); |
| 86 |
> |
initstr(str, fn, ln); |
| 87 |
|
while (nextc != EOF) |
| 88 |
|
loaddefn(); |
| 89 |
|
} |
| 107 |
|
} |
| 108 |
|
|
| 109 |
|
|
| 110 |
< |
varset(vname, val) /* set a variable's value */ |
| 110 |
> |
varset(vname, assign, val) /* set a variable's value */ |
| 111 |
|
char *vname; |
| 112 |
+ |
int assign; |
| 113 |
|
double val; |
| 114 |
|
{ |
| 115 |
|
register EPNODE *ep1, *ep2; |
| 118 |
|
ep2 = ep1->v.kid->sibling; |
| 119 |
|
if (ep2->type == NUM) { |
| 120 |
|
ep2->v.num = val; |
| 121 |
< |
ep2->sibling->v.tick = -1; |
| 121 |
> |
ep1->type = assign; |
| 122 |
|
return; |
| 123 |
|
} |
| 124 |
|
} |
| 125 |
|
/* hand build definition */ |
| 126 |
|
ep1 = newnode(); |
| 127 |
< |
ep1->type = '='; |
| 127 |
> |
ep1->type = assign; |
| 128 |
|
ep2 = newnode(); |
| 129 |
|
ep2->type = SYM; |
| 130 |
|
ep2->v.name = savestr(vname); |
| 133 |
|
ep2->type = NUM; |
| 134 |
|
ep2->v.num = val; |
| 135 |
|
addekid(ep1, ep2); |
| 136 |
< |
ep2 = newnode(); |
| 131 |
< |
ep2->type = TICK; |
| 132 |
< |
ep2->v.tick = -1; |
| 133 |
< |
addekid(ep1, ep2); |
| 134 |
< |
ep2 = newnode(); |
| 135 |
< |
ep2->type = NUM; |
| 136 |
< |
addekid(ep1, ep2); |
| 137 |
< |
dclear(vname); |
| 136 |
> |
dremove(vname); |
| 137 |
|
dpush(ep1); |
| 138 |
|
} |
| 139 |
|
|
| 140 |
|
|
| 141 |
< |
dclear(name) /* delete all definitions of name */ |
| 141 |
> |
dclear(name) /* delete variable definitions of name */ |
| 142 |
|
char *name; |
| 143 |
|
{ |
| 144 |
|
register EPNODE *ep; |
| 145 |
|
|
| 146 |
+ |
while ((ep = dpop(name)) != NULL) { |
| 147 |
+ |
if (ep->type == ':') { |
| 148 |
+ |
dpush(ep); /* don't clear constants */ |
| 149 |
+ |
return; |
| 150 |
+ |
} |
| 151 |
+ |
epfree(ep); |
| 152 |
+ |
} |
| 153 |
+ |
} |
| 154 |
+ |
|
| 155 |
+ |
|
| 156 |
+ |
dremove(name) /* delete all definitions of name */ |
| 157 |
+ |
char *name; |
| 158 |
+ |
{ |
| 159 |
+ |
register EPNODE *ep; |
| 160 |
+ |
|
| 161 |
|
while ((ep = dpop(name)) != NULL) |
| 162 |
|
epfree(ep); |
| 163 |
|
} |
| 173 |
|
|
| 174 |
|
|
| 175 |
|
#ifdef OUTCHAN |
| 176 |
< |
chanout() /* set output channels */ |
| 176 |
> |
chanout(cs) /* set output channels */ |
| 177 |
> |
int (*cs)(); |
| 178 |
|
{ |
| 179 |
|
register EPNODE *ep; |
| 180 |
|
|
| 181 |
|
for (ep = outchan; ep != NULL; ep = ep->sibling) |
| 182 |
< |
chanset(ep->v.kid->v.chan, evalue(ep->v.kid->sibling)); |
| 182 |
> |
(*cs)(ep->v.kid->v.chan, evalue(ep->v.kid->sibling)); |
| 183 |
|
|
| 184 |
|
} |
| 185 |
|
#endif |
| 186 |
|
|
| 187 |
|
|
| 188 |
< |
dclearall() /* clear all definitions */ |
| 188 |
> |
dcleanup(lvl) /* clear definitions (0->vars,1->output,2->consts) */ |
| 189 |
> |
int lvl; |
| 190 |
|
{ |
| 191 |
|
register int i; |
| 192 |
|
register VARDEF *vp; |
| 194 |
|
|
| 195 |
|
for (i = 0; i < NHASH; i++) |
| 196 |
|
for (vp = hashtbl[i]; vp != NULL; vp = vp->next) |
| 197 |
< |
dclear(vp->name); |
| 197 |
> |
if (lvl >= 2) |
| 198 |
> |
dremove(vp->name); |
| 199 |
> |
else |
| 200 |
> |
dclear(vp->name); |
| 201 |
|
#ifdef OUTCHAN |
| 202 |
< |
for (ep = outchan; ep != NULL; ep = ep->sibling) |
| 203 |
< |
epfree(ep); |
| 204 |
< |
outchan = NULL; |
| 202 |
> |
if (lvl >= 1) { |
| 203 |
> |
for (ep = outchan; ep != NULL; ep = ep->sibling) |
| 204 |
> |
epfree(ep); |
| 205 |
> |
outchan = NULL; |
| 206 |
> |
} |
| 207 |
|
#endif |
| 208 |
|
} |
| 209 |
|
|
| 378 |
|
loaddefn() /* load next definition */ |
| 379 |
|
{ |
| 380 |
|
register EPNODE *ep; |
| 381 |
+ |
EPNODE *lastdef; |
| 382 |
|
|
| 383 |
|
if (nextc == ';') { /* empty statement */ |
| 384 |
|
scan(); |
| 392 |
|
#endif |
| 393 |
|
{ /* ordinary definition */ |
| 394 |
|
ep = getdefn(); |
| 395 |
< |
dclear(dname(ep)); |
| 395 |
> |
#ifdef REDEFW |
| 396 |
> |
if ((lastdef = dlookup(dname(ep))) != NULL) { |
| 397 |
> |
wputs(dname(ep)); |
| 398 |
> |
if (lastdef->type == ':') |
| 399 |
> |
wputs(": redefined constant expression\n"); |
| 400 |
> |
else |
| 401 |
> |
wputs(": redefined\n"); |
| 402 |
> |
} |
| 403 |
> |
#ifdef FUNCTION |
| 404 |
> |
else if (ep->v.kid->type == FUNC && |
| 405 |
> |
liblookup(ep->v.kid->v.kid->v.name) != NULL) { |
| 406 |
> |
wputs(ep->v.kid->v.kid->v.name); |
| 407 |
> |
wputs(": definition hides library function\n"); |
| 408 |
> |
} |
| 409 |
> |
#endif |
| 410 |
> |
#endif |
| 411 |
> |
if (ep->type == ':') |
| 412 |
> |
dremove(dname(ep)); |
| 413 |
> |
else |
| 414 |
> |
dclear(dname(ep)); |
| 415 |
|
dpush(ep); |
| 416 |
|
} |
| 417 |
|
if (nextc != EOF) { |
| 424 |
|
|
| 425 |
|
EPNODE * |
| 426 |
|
getdefn() /* A -> SYM = E1 */ |
| 427 |
+ |
/* SYM : E1 */ |
| 428 |
|
/* FUNC(SYM,..) = E1 */ |
| 429 |
+ |
/* FUNC(SYM,..) : E1 */ |
| 430 |
|
{ |
| 431 |
|
register EPNODE *ep1, *ep2; |
| 432 |
|
|
| 460 |
|
curfunc = NULL; |
| 461 |
|
#endif |
| 462 |
|
|
| 463 |
< |
if (nextc != '=') |
| 464 |
< |
syntax("'=' expected"); |
| 422 |
< |
scan(); |
| 463 |
> |
if (nextc != '=' && nextc != ':') |
| 464 |
> |
syntax("'=' or ':' expected"); |
| 465 |
|
|
| 466 |
|
ep2 = newnode(); |
| 467 |
< |
ep2->type = '='; |
| 467 |
> |
ep2->type = nextc; |
| 468 |
> |
scan(); |
| 469 |
|
addekid(ep2, ep1); |
| 470 |
|
addekid(ep2, getE1()); |
| 471 |
|
|
| 472 |
+ |
if ( |
| 473 |
|
#ifdef FUNCTION |
| 474 |
< |
if (ep1->type == SYM) |
| 474 |
> |
ep1->type == SYM && |
| 475 |
|
#endif |
| 476 |
< |
{ |
| 476 |
> |
ep1->sibling->type != NUM) { |
| 477 |
|
ep1 = newnode(); |
| 478 |
|
ep1->type = TICK; |
| 479 |
|
ep1->v.tick = -1; |
| 534 |
|
quit(1); |
| 535 |
|
} |
| 536 |
|
ep1 = d->v.kid->sibling; /* get expression */ |
| 537 |
+ |
if (ep1->type == NUM) |
| 538 |
+ |
return(ep1->v.num); /* return if number */ |
| 539 |
|
ep2 = ep1->sibling; /* check time */ |
| 540 |
|
if (ep2->v.tick < 0 || ep2->v.tick < eclock) { |
| 541 |
< |
ep2->v.tick = eclock; |
| 541 |
> |
ep2->v.tick = d->type == ':' ? 1L<<30 : eclock; |
| 542 |
|
ep2 = ep2->sibling; |
| 543 |
< |
ep2->v.num = evalue(ep1); /* compute new value */ |
| 543 |
> |
ep2->v.num = evalue(ep1); /* needs new value */ |
| 544 |
|
} else |
| 545 |
< |
ep2 = ep2->sibling; /* reuse old value */ |
| 545 |
> |
ep2 = ep2->sibling; /* else reuse old value */ |
| 546 |
|
|
| 547 |
|
return(ep2->v.num); |
| 548 |
|
} |