ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/calexpr.c
(Generate patch)

Comparing ray/src/common/calexpr.c (file contents):
Revision 1.1 by greg, Thu Feb 2 10:34:27 1989 UTC vs.
Revision 2.16 by greg, Thu Feb 16 09:49:29 1995 UTC

# Line 1 | Line 1
1 < /* Copyright (c) 1986 Regents of the University of California */
1 > /* Copyright (c) 1992 Regents of the University of California */
2  
3   #ifndef lint
4   static char SCCSid[] = "$SunId$ LBL";
# Line 24 | Line 24 | static char SCCSid[] = "$SunId$ LBL";
24  
25   #include  <errno.h>
26  
27 + #include  <math.h>
28 +
29   #include  "calcomp.h"
30  
31 < #define  MAXLINE        256             /* maximum line length */
30 < #define  MAXWORD        64              /* maximum word length */
31 > #define  MAXLINE        256             /* maximum line length */
32  
33 < #define  newnode()      (EPNODE *)ecalloc(1, sizeof(EPNODE))
33 > #define  newnode()      (EPNODE *)ecalloc(1, sizeof(EPNODE))
34  
35 < #define  isid(c)        (isalnum(c) || (c) == '_' || (c) == '.')
35 > #define  isdecimal(c)   (isdigit(c) || (c) == '.')
36  
37 < #define  isdecimal(c)   (isdigit(c) || (c) == '.')
37 <
38 < extern double  atof(), pow();
39 < extern char  *fgets(), *savestr();
37 > extern char  *savestr();
38   extern char  *emalloc(), *ecalloc();
39   extern EPNODE  *curfunc;
40 < extern double  efunc(), evariable(), enumber(), euminus(), echannel();
41 < extern double  eargument(), eadd(), esubtr(), emult(), edivi(), epow();
42 < extern double  ebotch();
43 < extern int  errno;
40 > extern double  efunc(), evariable();
41 > static double  euminus(), eargument(), enumber();
42 > #ifdef  INCHAN
43 > static double  echannel();
44 > #endif
45 > static double  eadd(), esubtr(), emult(), edivi(), epow();
46 > static double  ebotch();
47  
48 + #ifdef  DCL_ATOF
49 + extern double  atof();
50 + #endif
51 +
52   int  nextc;                             /* lookahead character */
53  
54 < double  (*eoper[])() = {                /* expression operations */
54 > double  (*eoper[])() = {                /* expression operations */
55          ebotch,
56 < #ifdef  VARIABLE
56 > #ifdef  VARIABLE
57          evariable,
58   #else
59          ebotch,
60   #endif
61          enumber,
62          euminus,
63 < #ifdef  INCHAN
63 > #ifdef  INCHAN
64          echannel,
65   #else
66          ebotch,
67   #endif
68 < #ifdef  FUNCTION
68 > #ifdef  FUNCTION
69          efunc,
70          eargument,
71   #else
# Line 77 | Line 82 | double  (*eoper[])() = {               /* expression operations */
82          esubtr,
83          0,
84          edivi,
85 <        0,0,0,0,0,0,0,0,0,0,0,0,0,
85 >        0,0,0,0,0,0,0,0,0,0,
86          ebotch,
87 +        0,0,
88 +        ebotch,
89          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
90          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
91          epow,
92   };
93  
87 static char  *infile;                   /* input file name */
94   static FILE  *infp;                     /* input file pointer */
95   static char  *linbuf;                   /* line buffer */
96 + static char  *infile;                   /* input file name */
97 + static int  lineno;                     /* input line number */
98   static int  linepos;                    /* position in buffer */
99  
100  
# Line 96 | Line 104 | char  *expr;
104   {
105      EPNODE  *ep;
106  
107 <    initstr(NULL, expr);
107 >    initstr(expr, NULL, 0);
108   #if  defined(VARIABLE) && defined(FUNCTION)
109      curfunc = NULL;
110   #endif
# Line 121 | Line 129 | char  *expr;
129   }
130  
131  
132 + epcmp(ep1, ep2)                 /* compare two expressions for equivalence */
133 + register EPNODE  *ep1, *ep2;
134 + {
135 +        double  d;
136 +
137 +        if (ep1->type != ep2->type)
138 +                return(1);
139 +
140 +        switch (ep1->type) {
141 +
142 +        case VAR:
143 +                return(ep1->v.ln != ep2->v.ln);
144 +
145 +        case NUM:
146 +                if (ep2->v.num == 0)
147 +                        return(ep1->v.num != 0);
148 +                d = ep1->v.num / ep2->v.num;
149 +                return(d > 1.000000000001 | d < 0.999999999999);
150 +
151 +        case CHAN:
152 +        case ARG:
153 +                return(ep1->v.chan != ep2->v.chan);
154 +
155 +        case '=':
156 +        case ':':
157 +                return(epcmp(ep1->v.kid->sibling, ep2->v.kid->sibling));
158 +
159 +        case TICK:
160 +        case SYM:                       /* should never get this one */
161 +                return(0);
162 +
163 +        default:
164 +                ep1 = ep1->v.kid;
165 +                ep2 = ep2->v.kid;
166 +                while (ep1 != NULL) {
167 +                        if (ep2 == NULL)
168 +                                return(1);
169 +                        if (epcmp(ep1, ep2))
170 +                                return(1);
171 +                        ep1 = ep1->sibling;
172 +                        ep2 = ep2->sibling;
173 +                }
174 +                return(ep2 != NULL);
175 +        }
176 + }
177 +
178 +
179   epfree(epar)                    /* free a parse tree */
180 < register EPNODE  *epar;
180 > register EPNODE  *epar;
181   {
182      register EPNODE  *ep;
183  
184      switch (epar->type) {
185  
186 + #if  defined(VARIABLE) || defined(FUNCTION)
187          case VAR:
188              varfree(epar->v.ln);
189              break;
# Line 135 | Line 191 | register EPNODE  *epar;
191          case SYM:
192              freestr(epar->v.name);
193              break;
194 + #endif
195  
196          case NUM:
197          case CHAN:
# Line 143 | Line 200 | register EPNODE  *epar;
200              break;
201  
202          default:
203 <            for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
203 >            while ((ep = epar->v.kid) != NULL) {
204 >                epar->v.kid = ep->sibling;
205                  epfree(ep);
206 +            }
207              break;
208  
209      }
# Line 153 | Line 212 | register EPNODE  *epar;
212   }
213  
214                                  /* the following used to be a switch */
215 < #ifdef  FUNCTION
215 > #ifdef  FUNCTION
216   static double
217   eargument(ep)
218 < EPNODE  *ep;
218 > EPNODE  *ep;
219   {
220      return(argument(ep->v.chan));
221   }
# Line 164 | Line 223 | EPNODE  *ep;
223  
224   static double
225   enumber(ep)
226 < EPNODE  *ep;
226 > EPNODE  *ep;
227   {
228      return(ep->v.num);
229   }
230  
231   static double
232   euminus(ep)
233 < EPNODE  *ep;
233 > EPNODE  *ep;
234   {
235      register EPNODE  *ep1 = ep->v.kid;
236  
237      return(-evalue(ep1));
238   }
239  
240 < #ifdef  INCHAN
240 > #ifdef  INCHAN
241   static double
242   echannel(ep)
243 < EPNODE  *ep;
243 > EPNODE  *ep;
244   {
245      return(chanvalue(ep->v.chan));
246   }
# Line 189 | Line 248 | EPNODE  *ep;
248  
249   static double
250   eadd(ep)
251 < EPNODE  *ep;
251 > EPNODE  *ep;
252   {
253      register EPNODE  *ep1 = ep->v.kid;
254  
# Line 198 | Line 257 | EPNODE  *ep;
257  
258   static double
259   esubtr(ep)
260 < EPNODE  *ep;
260 > EPNODE  *ep;
261   {
262      register EPNODE  *ep1 = ep->v.kid;
263  
# Line 207 | Line 266 | EPNODE  *ep;
266  
267   static double
268   emult(ep)
269 < EPNODE  *ep;
269 > EPNODE  *ep;
270   {
271      register EPNODE  *ep1 = ep->v.kid;
272  
# Line 216 | Line 275 | EPNODE  *ep;
275  
276   static double
277   edivi(ep)
278 < EPNODE  *ep;
278 > EPNODE  *ep;
279   {
280      register EPNODE  *ep1 = ep->v.kid;
281      double  d;
# Line 232 | Line 291 | EPNODE  *ep;
291  
292   static double
293   epow(ep)
294 < EPNODE  *ep;
294 > EPNODE  *ep;
295   {
296      register EPNODE  *ep1 = ep->v.kid;
297      double  d;
298 <    int  lasterrno;
298 >    int  lasterrno;
299  
300      lasterrno = errno;
301      errno = 0;
302      d = pow(evalue(ep1), evalue(ep1->sibling));
303 < #ifdef  IEEE
303 > #ifdef  IEEE
304      if (!finite(d))
305          errno = EDOM;
306   #endif
# Line 255 | Line 314 | EPNODE  *ep;
314  
315   static double
316   ebotch(ep)
317 < EPNODE  *ep;
317 > EPNODE  *ep;
318   {
319      eputs("Bad expression!\n");
320      quit(1);
# Line 264 | Line 323 | EPNODE  *ep;
323  
324   EPNODE *
325   ekid(ep, n)                     /* return pointer to a node's nth kid */
326 < register EPNODE  *ep;
326 > register EPNODE  *ep;
327   register int  n;
328   {
329  
# Line 278 | Line 337 | register int  n;
337  
338   int
339   nekids(ep)                      /* return # of kids for node ep */
340 < register EPNODE  *ep;
340 > register EPNODE  *ep;
341   {
342      register int  n = 0;
343  
# Line 289 | Line 348 | register EPNODE  *ep;
348   }
349  
350  
351 < initfile(file, fp)              /* prepare input file */
293 < char  *file;
351 > initfile(fp, fn, ln)            /* prepare input file */
352   FILE  *fp;
353 + char  *fn;
354 + int  ln;
355   {
356 <    static char  inpbuf[MAXLINE];
356 >    static char  inpbuf[MAXLINE];
357  
298    infile = file;
358      infp = fp;
359      linbuf = inpbuf;
360 +    infile = fn;
361 +    lineno = ln;
362      linepos = 0;
363      inpbuf[0] = '\0';
364      scan();
365   }
366  
367  
368 < initstr(file, s)                /* prepare input string */
308 < char  *file;
368 > initstr(s, fn, ln)              /* prepare input string */
369   char  *s;
370 + char  *fn;
371 + int  ln;
372   {
311    infile = file;
373      infp = NULL;
374 +    infile = fn;
375 +    lineno = ln;
376      linbuf = s;
377      linepos = 0;
378      scan();
379   }
380  
381  
382 < scan()                          /* scan next character */
382 > getscanpos(fnp, lnp, spp, fpp)  /* return current scan position */
383 > char  **fnp;
384 > int  *lnp;
385 > char  **spp;
386 > FILE  **fpp;
387   {
388 +    if (fnp != NULL) *fnp = infile;
389 +    if (lnp != NULL) *lnp = lineno;
390 +    if (spp != NULL) *spp = linbuf+linepos;
391 +    if (fpp != NULL) *fpp = infp;
392 + }
393 +
394 +
395 + int
396 + scan()                          /* scan next character, return literal next */
397 + {
398 +    register int  lnext = 0;
399 +
400      do {
401          if (linbuf[linepos] == '\0')
402              if (infp == NULL || fgets(linbuf, MAXLINE, infp) == NULL)
403                  nextc = EOF;
404              else {
405                  nextc = linbuf[0];
406 +                lineno++;
407                  linepos = 1;
408              }
409          else
410              nextc = linbuf[linepos++];
411 +        if (!lnext)
412 +                lnext = nextc;
413          if (nextc == '{') {
414              scan();
415              while (nextc != '}')
# Line 338 | Line 420 | scan()                         /* scan next character */
420              scan();
421          }
422      } while (isspace(nextc));
423 +    return(lnext);
424   }
425  
426  
427 + char *
428 + long2ascii(l)                         /* convert long to ascii */
429 + long  l;
430 + {
431 +    static char  buf[16];
432 +    register char  *cp;
433 +    int  neg = 0;
434 +
435 +    if (l == 0)
436 +        return("0");
437 +    if (l < 0) {
438 +        l = -l;
439 +        neg++;
440 +    }
441 +    cp = buf + sizeof(buf);
442 +    *--cp = '\0';
443 +    while (l) {
444 +        *--cp = l % 10 + '0';
445 +        l /= 10;
446 +    }
447 +    if (neg)
448 +        *--cp = '-';
449 +    return(cp);
450 + }
451 +
452 +
453   syntax(err)                     /* report syntax error and quit */
454   char  *err;
455   {
456      register int  i;
457  
458 +    if (infile != NULL || lineno != 0) {
459 +        if (infile != NULL) eputs(infile);
460 +        if (lineno != 0) {
461 +            eputs(infile != NULL ? ", line " : "line ");
462 +            eputs(long2ascii((long)lineno));
463 +        }
464 +        eputs(":\n");
465 +    }
466      eputs(linbuf);
467 <    if (linbuf[0] == '\0' || linbuf[strlen(linbuf)-1] != '\n')
467 >    if (linbuf[strlen(linbuf)-1] != '\n')
468          eputs("\n");
469      for (i = 0; i < linepos-1; i++)
470          eputs(linbuf[i] == '\t' ? "\t" : " ");
471      eputs("^ ");
355    if (infile != NULL) {
356        eputs(infile);
357        eputs(": ");
358    }
472      eputs(err);
473      eputs("\n");
474      quit(1);
# Line 363 | Line 476 | char  *err;
476  
477  
478   addekid(ep, ekid)                       /* add a child to ep */
479 < register EPNODE  *ep;
480 < EPNODE  *ekid;
479 > register EPNODE  *ep;
480 > EPNODE  *ekid;
481   {
482      if (ep->v.kid == NULL)
483          ep->v.kid = ekid;
# Line 377 | Line 490 | EPNODE  *ekid;
490   }
491  
492  
493 + #if  defined(VARIABLE) || defined(FUNCTION)
494   char *
495   getname()                       /* scan an identifier */
496   {
497 <    static char  str[MAXWORD+1];
498 <    register int  i;
497 >    static char  str[MAXWORD+1];
498 >    register int  i, lnext;
499  
500 <    for (i = 0; i < MAXWORD && isid(nextc); i++, scan())
501 <        str[i] = nextc;
500 >    lnext = nextc;
501 >    for (i = 0; i < MAXWORD && isid(lnext); i++, lnext = scan())
502 >        str[i] = lnext;
503      str[i] = '\0';
504 +    while (isid(lnext))         /* skip rest of name */
505 +        lnext = scan();
506  
507      return(str);
508   }
509 + #endif
510  
511  
512   int
513   getinum()                       /* scan a positive integer */
514   {
515 <    register int  n;
515 >    register int  n, lnext;
516  
517      n = 0;
518 <    while (isdigit(nextc)) {
519 <        n = n * 10 + nextc - '0';
520 <        scan();
518 >    lnext = nextc;
519 >    while (isdigit(lnext)) {
520 >        n = n * 10 + lnext - '0';
521 >        lnext = scan();
522      }
523      return(n);
524   }
# Line 408 | Line 527 | getinum()                      /* scan a positive integer */
527   double
528   getnum()                        /* scan a positive float */
529   {
530 <    register int  i;
530 >    register int  i, lnext;
531      char  str[MAXWORD+1];
532  
533      i = 0;
534 <    while (isdigit(nextc) && i < MAXWORD) {
535 <        str[i++] = nextc;
536 <        scan();
534 >    lnext = nextc;
535 >    while (isdigit(lnext) && i < MAXWORD) {
536 >        str[i++] = lnext;
537 >        lnext = scan();
538      }
539 <    if (nextc == '.' && i < MAXWORD) {
540 <        str[i++] = nextc;
541 <        scan();
542 <        while (isdigit(nextc) && i < MAXWORD) {
543 <            str[i++] = nextc;
544 <            scan();
539 >    if (lnext == '.' && i < MAXWORD) {
540 >        str[i++] = lnext;
541 >        lnext = scan();
542 >        while (isdigit(lnext) && i < MAXWORD) {
543 >            str[i++] = lnext;
544 >            lnext = scan();
545          }
546      }
547 <    if ((nextc == 'e' || nextc == 'E') && i < MAXWORD) {
548 <        str[i++] = nextc;
549 <        scan();
550 <        if ((nextc == '-' || nextc == '+') && i < MAXWORD) {
551 <            str[i++] = nextc;
552 <            scan();
547 >    if ((lnext == 'e' || lnext == 'E') && i < MAXWORD) {
548 >        str[i++] = lnext;
549 >        lnext = scan();
550 >        if ((lnext == '-' || lnext == '+') && i < MAXWORD) {
551 >            str[i++] = lnext;
552 >            lnext = scan();
553          }
554 <        while (isdigit(nextc) && i < MAXWORD) {
555 <            str[i++] = nextc;
556 <            scan();
554 >        while (isdigit(lnext) && i < MAXWORD) {
555 >            str[i++] = lnext;
556 >            lnext = scan();
557          }
558      }
559      str[i] = '\0';
# Line 444 | Line 564 | getnum()                       /* scan a positive float */
564  
565   EPNODE *
566   getE1()                         /* E1 -> E1 ADDOP E2 */
567 <                                /*       E2 */
567 >                                /*       E2 */
568   {
569      register EPNODE  *ep1, *ep2;
570  
# Line 455 | Line 575 | getE1()                                /* E1 -> E1 ADDOP E2 */
575          scan();
576          addekid(ep2, ep1);
577          addekid(ep2, getE2());
578 < #ifdef  RCONST
578 > #ifdef  RCONST
579          if (ep1->type == NUM && ep1->sibling->type == NUM)
580                  ep2 = rconst(ep2);
581   #endif
# Line 467 | Line 587 | getE1()                                /* E1 -> E1 ADDOP E2 */
587  
588   EPNODE *
589   getE2()                         /* E2 -> E2 MULOP E3 */
590 <                                /*       E3 */
590 >                                /*       E3 */
591   {
592      register EPNODE  *ep1, *ep2;
593  
# Line 478 | Line 598 | getE2()                                /* E2 -> E2 MULOP E3 */
598          scan();
599          addekid(ep2, ep1);
600          addekid(ep2, getE3());
601 < #ifdef  RCONST
601 > #ifdef  RCONST
602          if (ep1->type == NUM && ep1->sibling->type == NUM)
603                  ep2 = rconst(ep2);
604   #endif
# Line 489 | Line 609 | getE2()                                /* E2 -> E2 MULOP E3 */
609  
610  
611   EPNODE *
612 < getE3()                         /* E3 -> E3 ^ E4 */
613 <                                /*       E4 */
612 > getE3()                         /* E3 -> E4 ^ E3 */
613 >                                /*       E4 */
614   {
615      register EPNODE  *ep1, *ep2;
616  
617      ep1 = getE4();
618 <    while (nextc == '^') {
618 >    if (nextc == '^') {
619          ep2 = newnode();
620          ep2->type = nextc;
621          scan();
622          addekid(ep2, ep1);
623 <        addekid(ep2, getE4());
624 < #ifdef  RCONST
623 >        addekid(ep2, getE3());
624 > #ifdef  RCONST
625          if (ep1->type == NUM && ep1->sibling->type == NUM)
626                  ep2 = rconst(ep2);
627   #endif
628 <        ep1 = ep2;
628 >        return(ep2);
629      }
630      return(ep1);
631   }
# Line 513 | Line 633 | getE3()                                /* E3 -> E3 ^ E4 */
633  
634   EPNODE *
635   getE4()                         /* E4 -> ADDOP E5 */
636 <                                /*       E5 */
636 >                                /*       E5 */
637   {
638 <    register EPNODE  *ep1;
638 >    register EPNODE  *ep1, *ep2;
639  
640      if (nextc == '-') {
641          scan();
642 <        ep1 = newnode();
643 < #ifndef  RCONST
644 <        if (isdecimal(nextc)) {
645 <            ep1->type = NUM;
526 <            ep1->v.num = -getnum();
527 <            return(ep1);
642 >        ep2 = getE5();
643 >        if (ep2->type == NUM) {
644 >                ep2->v.num = -ep2->v.num;
645 >                return(ep2);
646          }
647 < #endif
647 >        if (ep2->type == UMINUS) {      /* don't generate -(-E5) */
648 >            efree((char *)ep2);
649 >            return(ep2->v.kid);
650 >        }
651 >        ep1 = newnode();
652          ep1->type = UMINUS;
653 <        addekid(ep1, getE5());
532 < #ifdef  RCONST
533 <        if (ep1->v.kid->type == NUM)
534 <                ep1 = rconst(ep1);
535 < #endif
653 >        addekid(ep1, ep2);
654          return(ep1);
655      }
656      if (nextc == '+')
# Line 543 | Line 661 | getE4()                                /* E4 -> ADDOP E5 */
661  
662   EPNODE *
663   getE5()                         /* E5 -> (E1) */
664 <                                /*       VAR */
665 <                                /*       NUM */
666 <                                /*       $N */
667 <                                /*       FUNC(E1,..) */
668 <                                /*       ARG */
664 >                                /*       VAR */
665 >                                /*       NUM */
666 >                                /*       $N */
667 >                                /*       FUNC(E1,..) */
668 >                                /*       ARG */
669   {
670 <    int  i;
670 >    int  i;
671 >    char  *nam;
672      register EPNODE  *ep1, *ep2;
673  
674      if (nextc == '(') {
# Line 561 | Line 680 | getE5()                                /* E5 -> (E1) */
680          return(ep1);
681      }
682  
683 < #ifdef  INCHAN
683 > #ifdef  INCHAN
684      if (nextc == '$') {
685          scan();
686          ep1 = newnode();
# Line 572 | Line 691 | getE5()                                /* E5 -> (E1) */
691   #endif
692  
693   #if  defined(VARIABLE) || defined(FUNCTION)
694 <    if (isalpha(nextc)) {
695 <        ep1 = newnode();
577 <        ep1->type = VAR;
578 <        ep1->v.ln = varinsert(getname());
579 <
694 >    if (isalpha(nextc) || nextc == CNTXMARK) {
695 >        nam = getname();
696   #if  defined(VARIABLE) && defined(FUNCTION)
697 +        ep1 = NULL;
698          if (curfunc != NULL)
699              for (i = 1, ep2 = curfunc->v.kid->sibling;
700 <                                ep2 != NULL; i++, ep2 = ep2->sibling)
701 <                if (!strcmp(ep2->v.name, ep1->v.ln->name)) {
585 <                    epfree(ep1);
700 >                                ep2 != NULL; i++, ep2 = ep2->sibling)
701 >                if (!strcmp(ep2->v.name, nam)) {
702                      ep1 = newnode();
703                      ep1->type = ARG;
704                      ep1->v.chan = i;
705                      break;
706                  }
707 +        if (ep1 == NULL)
708   #endif
709 < #ifdef  FUNCTION
709 >        {
710 >            ep1 = newnode();
711 >            ep1->type = VAR;
712 >            ep1->v.ln = varinsert(nam);
713 >        }
714 > #ifdef  FUNCTION
715          if (nextc == '(') {
716              ep2 = newnode();
717              ep2->type = FUNC;
# Line 603 | Line 725 | getE5()                                /* E5 -> (E1) */
725                  syntax("')' expected");
726              scan();
727          }
728 < #ifndef  VARIABLE
728 > #ifndef  VARIABLE
729          else
730              syntax("'(' expected");
731   #endif
732   #endif
733 + #ifdef  RCONST
734 +        if (isconstvar(ep1))
735 +            ep1 = rconst(ep1);
736 + #endif
737          return(ep1);
738      }
739   #endif
# Line 622 | Line 748 | getE5()                                /* E5 -> (E1) */
748   }
749  
750  
751 < #ifdef  RCONST
751 > #ifdef  RCONST
752   EPNODE *
753   rconst(epar)                    /* reduce a constant expression */
754 < register EPNODE  *epar;
754 > register EPNODE  *epar;
755   {
756      register EPNODE  *ep;
757  
# Line 634 | Line 760 | register EPNODE  *epar;
760      errno = 0;
761      ep->v.num = evalue(epar);
762      if (errno)
763 <        syntax("bad constant expression");
763 >        syntax("bad constant expression");
764      epfree(epar);
765  
766      return(ep);
767   }
768 +
769 +
770 + isconstvar(ep)                  /* is ep linked to a constant expression? */
771 + register EPNODE  *ep;
772 + {
773 + #ifdef  VARIABLE
774 +    register EPNODE  *ep1;
775 + #ifdef  FUNCTION
776 +
777 +    if (ep->type == FUNC) {
778 +        if (!isconstfun(ep->v.kid))
779 +                return(0);
780 +        for (ep1 = ep->v.kid->sibling; ep1 != NULL; ep1 = ep1->sibling)
781 +            if (ep1->type != NUM && !isconstfun(ep1))
782 +                return(0);
783 +        return(1);
784 +    }
785 + #endif
786 +    if (ep->type != VAR)
787 +        return(0);
788 +    ep1 = ep->v.ln->def;
789 +    if (ep1 == NULL || ep1->type != ':')
790 +        return(0);
791 + #ifdef  FUNCTION
792 +    if (ep1->v.kid->type != SYM)
793 +        return(0);
794 + #endif
795 +    return(1);
796 + #else
797 +    return(ep->type == FUNC);
798 + #endif
799 + }
800 +
801 +
802 + #if  defined(FUNCTION) && defined(VARIABLE)
803 + isconstfun(ep)                  /* is ep linked to a constant function? */
804 + register EPNODE  *ep;
805 + {
806 +    register EPNODE  *dp;
807 +    register LIBR  *lp;
808 +
809 +    if (ep->type != VAR)
810 +        return(0);
811 +    if ((dp = ep->v.ln->def) != NULL && dp->v.kid->type == FUNC)
812 +        return(dp->type == ':');
813 +    if ((lp = ep->v.ln->lib) != NULL)
814 +        return(lp->atyp == ':');
815 +    return(0);
816 + }
817 + #endif
818   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines