--- ray/src/common/calexpr.c 1990/06/26 09:15:11 1.5 +++ ray/src/common/calexpr.c 1991/08/14 08:18:14 1.15 @@ -1,4 +1,4 @@ -/* Copyright (c) 1986 Regents of the University of California */ +/* Copyright (c) 1991 Regents of the University of California */ #ifndef lint static char SCCSid[] = "$SunId$ LBL"; @@ -27,12 +27,9 @@ static char SCCSid[] = "$SunId$ LBL"; #include "calcomp.h" #define MAXLINE 256 /* maximum line length */ -#define MAXWORD 64 /* maximum word length */ #define newnode() (EPNODE *)ecalloc(1, sizeof(EPNODE)) -#define isid(c) (isalnum(c) || (c) == '_' || (c) == '.') - #define isdecimal(c) (isdigit(c) || (c) == '.') extern double atof(), pow(); @@ -78,16 +75,19 @@ double (*eoper[])() = { /* expression operations */ esubtr, 0, edivi, - 0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0, ebotch, + 0,0, + ebotch, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, epow, }; -static char *infile; /* input file name */ static FILE *infp; /* input file pointer */ static char *linbuf; /* line buffer */ +static char *infile; /* input file name */ +static int lineno; /* input line number */ static int linepos; /* position in buffer */ @@ -97,7 +97,7 @@ char *expr; { EPNODE *ep; - initstr(NULL, expr); + initstr(expr, NULL, 0); #if defined(VARIABLE) && defined(FUNCTION) curfunc = NULL; #endif @@ -292,45 +292,68 @@ register EPNODE *ep; } -initfile(file, fp) /* prepare input file */ -char *file; +initfile(fp, fn, ln) /* prepare input file */ FILE *fp; +char *fn; +int ln; { static char inpbuf[MAXLINE]; - infile = file; infp = fp; linbuf = inpbuf; + infile = fn; + lineno = ln; linepos = 0; inpbuf[0] = '\0'; scan(); } -initstr(file, s) /* prepare input string */ -char *file; +initstr(s, fn, ln) /* prepare input string */ char *s; +char *fn; +int ln; { - infile = file; infp = NULL; + infile = fn; + lineno = ln; linbuf = s; linepos = 0; scan(); } -scan() /* scan next character */ +getscanpos(fnp, lnp, spp, fpp) /* return current scan position */ +char **fnp; +int *lnp; +char **spp; +FILE **fpp; { + if (fnp != NULL) *fnp = infile; + if (lnp != NULL) *lnp = lineno; + if (spp != NULL) *spp = linbuf+linepos; + if (fpp != NULL) *fpp = infp; +} + + +int +scan() /* scan next character, return literal next */ +{ + register int lnext = 0; + do { if (linbuf[linepos] == '\0') if (infp == NULL || fgets(linbuf, MAXLINE, infp) == NULL) nextc = EOF; else { nextc = linbuf[0]; + lineno++; linepos = 1; } else nextc = linbuf[linepos++]; + if (!lnext) + lnext = nextc; if (nextc == '{') { scan(); while (nextc != '}') @@ -341,24 +364,55 @@ scan() /* scan next character */ scan(); } } while (isspace(nextc)); + return(lnext); } +char * +ltoa(l) /* convert long to ascii */ +long l; +{ + static char buf[16]; + register char *cp; + int neg = 0; + + if (l == 0) + return("0"); + if (l < 0) { + l = -l; + neg++; + } + cp = buf + sizeof(buf); + *--cp = '\0'; + while (l) { + *--cp = l % 10 + '0'; + l /= 10; + } + if (neg) + *--cp = '-'; + return(cp); +} + + syntax(err) /* report syntax error and quit */ char *err; { register int i; + if (infile != NULL || lineno != 0) { + if (infile != NULL) eputs(infile); + if (lineno != 0) { + eputs(infile != NULL ? ", line " : "line "); + eputs(ltoa((long)lineno)); + } + eputs(": syntax error:\n"); + } eputs(linbuf); if (linbuf[strlen(linbuf)-1] != '\n') eputs("\n"); for (i = 0; i < linepos-1; i++) eputs(linbuf[i] == '\t' ? "\t" : " "); eputs("^ "); - if (infile != NULL) { - eputs(infile); - eputs(": "); - } eputs(err); eputs("\n"); quit(1); @@ -384,11 +438,14 @@ char * getname() /* scan an identifier */ { static char str[MAXWORD+1]; - register int i; + register int i, lnext; - for (i = 0; i < MAXWORD && isid(nextc); i++, scan()) - str[i] = nextc; + lnext = nextc; + for (i = 0; i < MAXWORD && isid(lnext); i++, lnext = scan()) + str[i] = lnext; str[i] = '\0'; + while (isid(lnext)) /* skip rest of name */ + lnext = scan(); return(str); } @@ -397,12 +454,13 @@ getname() /* scan an identifier */ int getinum() /* scan a positive integer */ { - register int n; + register int n, lnext; n = 0; - while (isdigit(nextc)) { - n = n * 10 + nextc - '0'; - scan(); + lnext = nextc; + while (isdigit(lnext)) { + n = n * 10 + lnext - '0'; + lnext = scan(); } return(n); } @@ -411,32 +469,33 @@ getinum() /* scan a positive integer */ double getnum() /* scan a positive float */ { - register int i; + register int i, lnext; char str[MAXWORD+1]; i = 0; - while (isdigit(nextc) && i < MAXWORD) { - str[i++] = nextc; - scan(); + lnext = nextc; + while (isdigit(lnext) && i < MAXWORD) { + str[i++] = lnext; + lnext = scan(); } - if (nextc == '.' && i < MAXWORD) { - str[i++] = nextc; - scan(); - while (isdigit(nextc) && i < MAXWORD) { - str[i++] = nextc; - scan(); + if (lnext == '.' && i < MAXWORD) { + str[i++] = lnext; + lnext = scan(); + while (isdigit(lnext) && i < MAXWORD) { + str[i++] = lnext; + lnext = scan(); } } - if ((nextc == 'e' || nextc == 'E') && i < MAXWORD) { - str[i++] = nextc; - scan(); - if ((nextc == '-' || nextc == '+') && i < MAXWORD) { - str[i++] = nextc; - scan(); + if ((lnext == 'e' || lnext == 'E') && i < MAXWORD) { + str[i++] = lnext; + lnext = scan(); + if ((lnext == '-' || lnext == '+') && i < MAXWORD) { + str[i++] = lnext; + lnext = scan(); } - while (isdigit(nextc) && i < MAXWORD) { - str[i++] = nextc; - scan(); + while (isdigit(lnext) && i < MAXWORD) { + str[i++] = lnext; + lnext = scan(); } } str[i] = '\0'; @@ -492,23 +551,23 @@ getE2() /* E2 -> E2 MULOP E3 */ EPNODE * -getE3() /* E3 -> E3 ^ E4 */ +getE3() /* E3 -> E4 ^ E3 */ /* E4 */ { register EPNODE *ep1, *ep2; ep1 = getE4(); - while (nextc == '^') { + if (nextc == '^') { ep2 = newnode(); ep2->type = nextc; scan(); addekid(ep2, ep1); - addekid(ep2, getE4()); + addekid(ep2, getE3()); #ifdef RCONST if (ep1->type == NUM && ep1->sibling->type == NUM) ep2 = rconst(ep2); #endif - ep1 = ep2; + return(ep2); } return(ep1); } @@ -547,6 +606,7 @@ getE5() /* E5 -> (E1) */ /* ARG */ { int i; + char *nam; register EPNODE *ep1, *ep2; if (nextc == '(') { @@ -569,23 +629,26 @@ getE5() /* E5 -> (E1) */ #endif #if defined(VARIABLE) || defined(FUNCTION) - if (isalpha(nextc)) { - ep1 = newnode(); - ep1->type = VAR; - ep1->v.ln = varinsert(getname()); - + if (isalpha(nextc) || nextc == CNTXMARK) { + nam = getname(); #if defined(VARIABLE) && defined(FUNCTION) + ep1 = NULL; if (curfunc != NULL) for (i = 1, ep2 = curfunc->v.kid->sibling; ep2 != NULL; i++, ep2 = ep2->sibling) - if (!strcmp(ep2->v.name, ep1->v.ln->name)) { - epfree(ep1); + if (!strcmp(ep2->v.name, nam)) { ep1 = newnode(); ep1->type = ARG; ep1->v.chan = i; break; } + if (ep1 == NULL) #endif + { + ep1 = newnode(); + ep1->type = VAR; + ep1->v.ln = varinsert(nam); + } #ifdef FUNCTION if (nextc == '(') { ep2 = newnode(); @@ -605,6 +668,10 @@ getE5() /* E5 -> (E1) */ syntax("'(' expected"); #endif #endif +#ifdef RCONST + if (isconstvar(ep1)) + ep1 = rconst(ep1); +#endif return(ep1); } #endif @@ -636,4 +703,57 @@ register EPNODE *epar; return(ep); } + + +isconstvar(ep) /* is ep linked to a constant expression? */ +register EPNODE *ep; +{ +#ifdef VARIABLE + register EPNODE *ep1; +#ifdef FUNCTION + + if (ep->type == FUNC) { + if (!isconstfun(ep->v.kid)) + return(0); + for (ep1 = ep->v.kid->sibling; ep1 != NULL; ep1 = ep1->sibling) + if (ep1->type != NUM && !isconstfun(ep1)) + return(0); + return(1); + } +#endif + if (ep->type != VAR) + return(0); + ep1 = ep->v.ln->def; + if (ep1 == NULL || ep1->type != ':') + return(0); +#ifdef FUNCTION + if (ep1->v.kid->type != SYM) + return(0); +#endif + return(1); +#else + return(ep->type == FUNC); +#endif +} + + +#if defined(FUNCTION) && defined(VARIABLE) +isconstfun(ep) /* is ep linked to a constant function? */ +register EPNODE *ep; +{ + register EPNODE *dp; + register LIBR *lp; + + if (ep->type != VAR) + return(0); + dp = ep->v.ln->def; + if (dp != NULL && dp->type != ':') + return(0); + if ((dp == NULL || dp->v.kid->type != FUNC) + && ((lp = liblookup(ep->v.ln->name)) == NULL + || lp->atyp != ':')) + return(0); + return(1); +} +#endif #endif