Back to index

radiance  4R0+20100331
Defines | Functions | Variables
calexpr.c File Reference
#include "copyright.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <math.h>
#include <stdlib.h>
#include "rtmisc.h"
#include "rtio.h"
#include "rterror.h"
#include "calcomp.h"

Go to the source code of this file.

Defines

#define MAXLINE   256 /* maximum line length */
#define newnode()   (EPNODE *)ecalloc(1, sizeof(EPNODE))
#define isdecimal(c)   (isdigit(c) || (c) == '.')

Functions

static double euminus (EPNODE *)
static double eargument (EPNODE *)
static double enumber (EPNODE *)
static double echannel (EPNODE *)
static double eadd (EPNODE *)
static double esubtr (EPNODE *)
static double emult (EPNODE *)
static double edivi (EPNODE *)
static double epow (EPNODE *)
static double ebotch (EPNODE *)
EPNODEeparse (char *expr)
double eval (char *expr)
int epcmp (register EPNODE *ep1, register EPNODE *ep2)
void epfree (register EPNODE *epar)
EPNODEekid (register EPNODE *ep, register int n)
int nekids (register EPNODE *ep)
void initfile (FILE *fp, char *fn, int ln)
void initstr (char *s, char *fn, int ln)
void getscanpos (char **fnp, int *lnp, char **spp, FILE **fpp)
int scan (void)
char * long2ascii (long l)
void syntax (char *err)
void addekid (register EPNODE *ep, EPNODE *ekid)
char * getname (void)
int getinum (void)
double getnum (void)
EPNODEgetE1 (void)
EPNODEgetE2 (void)
EPNODEgetE3 (void)
EPNODEgetE4 (void)
EPNODEgetE5 (void)
EPNODErconst (register EPNODE *epar)
int isconstvar (register EPNODE *ep)
int isconstfun (register EPNODE *ep)

Variables

static const char RCSid [] = "$Id: calexpr.c,v 2.33 2009/06/14 18:21:58 greg Exp $"
unsigned int esupport
int eofc = 0
int nextc
double(* eoper [])(EPNODE *)
static FILE * infp
static char * linbuf
static char * infile
static int lineno
static int linepos

Define Documentation

#define isdecimal (   c)    (isdigit(c) || (c) == '.')

Definition at line 38 of file calexpr.c.

#define MAXLINE   256 /* maximum line length */

Definition at line 34 of file calexpr.c.

#define newnode ( )    (EPNODE *)ecalloc(1, sizeof(EPNODE))

Definition at line 36 of file calexpr.c.


Function Documentation

void addekid ( register EPNODE ep,
EPNODE ekid 
)

Definition at line 493 of file calexpr.c.

{
    if (ep->v.kid == NULL)
       ep->v.kid = ekid;
    else {
       for (ep = ep->v.kid; ep->sibling != NULL; ep = ep->sibling)
           ;
       ep->sibling = ekid;
    }
    ekid->sibling = NULL;
}

Here is the call graph for this function:

static double eadd ( EPNODE ep) [static]

Definition at line 239 of file calexpr.c.

{
    register EPNODE  *ep1 = ep->v.kid;

    return(evalue(ep1) + evalue(ep1->sibling));
}
static double eargument ( EPNODE ep)

Definition at line 205 of file calexpr.c.

{
    return(argument(ep->v.chan));
}

Here is the call graph for this function:

static double ebotch ( EPNODE ep) [static]

Definition at line 313 of file calexpr.c.

{
    eputs("Bad expression!\n");
    quit(1);
       return 0.0; /* pro forma return */
}

Here is the call graph for this function:

static double echannel ( EPNODE ep) [static]

Definition at line 231 of file calexpr.c.

{
    return(chanvalue(ep->v.chan));
}

Here is the call graph for this function:

static double edivi ( EPNODE ep)

Definition at line 269 of file calexpr.c.

{
    register EPNODE  *ep1 = ep->v.kid;
    double  d;

    d = evalue(ep1->sibling);
    if (d == 0.0) {
       wputs("Division by zero\n");
       errno = ERANGE;
       return(0.0);
    }
    return(evalue(ep1) / d);
}

Here is the call graph for this function:

EPNODE* ekid ( register EPNODE ep,
register int  n 
)

Definition at line 324 of file calexpr.c.

{

    for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
       if (--n < 0)
           break;

    return(ep);
}
static double emult ( EPNODE ep)
static double enumber ( EPNODE ep)

Definition at line 213 of file calexpr.c.

{
    return(ep->v.num);
}
EPNODE* eparse ( char *  expr)

Definition at line 88 of file calexpr.c.

{
    EPNODE  *ep;

    initstr(expr, NULL, 0);
    curfunc = NULL;
    ep = getE1();
    if (nextc != EOF)
       syntax("unexpected character");
    return(ep);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int epcmp ( register EPNODE ep1,
register EPNODE ep2 
)

Definition at line 119 of file calexpr.c.

{
       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);
       }
}

Here is the call graph for this function:

void epfree ( register EPNODE epar)

Definition at line 169 of file calexpr.c.

{
    register 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);
}

Here is the call graph for this function:

static double epow ( EPNODE ep)

Definition at line 286 of file calexpr.c.

{
    register EPNODE  *ep1 = ep->v.kid;
    double  d;
    int        lasterrno;

    lasterrno = errno;
    errno = 0;
    d = pow(evalue(ep1), evalue(ep1->sibling));
#ifdef  isnan
    if (errno == 0)
       if (isnan(d))
           errno = EDOM;
       else if (isinf(d))
           errno = ERANGE;
#endif
    if (errno == EDOM || errno == ERANGE) {
       wputs("Illegal power\n");
       return(0.0);
    }
    errno = lasterrno;
    return(d);
}

Here is the call graph for this function:

static double esubtr ( EPNODE ep)

Definition at line 249 of file calexpr.c.

{
    register EPNODE  *ep1 = ep->v.kid;

    return(evalue(ep1) - evalue(ep1->sibling));
}
static double euminus ( EPNODE ep) [static]

Definition at line 221 of file calexpr.c.

{
    register EPNODE  *ep1 = ep->v.kid;

    return(-evalue(ep1));
}
double eval ( char *  expr)

Definition at line 104 of file calexpr.c.

{
    register EPNODE  *ep;
    double  rval;

    ep = eparse(expr);
    rval = evalue(ep);
    epfree(ep);
    return(rval);
}

Here is the call graph for this function:

Here is the caller graph for this function:

EPNODE* getE1 ( void  )

Definition at line 584 of file calexpr.c.

{
    register EPNODE  *ep1, *ep2;

    ep1 = getE2();
    while (nextc == '+' || nextc == '-') {
       ep2 = newnode();
       ep2->type = nextc;
       scan();
       addekid(ep2, ep1);
       addekid(ep2, getE2());
       if (esupport&E_RCONST &&
                     ep1->type == NUM && ep1->sibling->type == NUM)
              ep2 = rconst(ep2);
       ep1 = ep2;
    }
    return(ep1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

EPNODE* getE2 ( void  )

Definition at line 606 of file calexpr.c.

{
    register EPNODE  *ep1, *ep2;

    ep1 = getE3();
    while (nextc == '*' || nextc == '/') {
       ep2 = newnode();
       ep2->type = nextc;
       scan();
       addekid(ep2, ep1);
       addekid(ep2, getE3());
       if (esupport&E_RCONST &&
                     ep1->type == NUM && ep1->sibling->type == NUM)
              ep2 = rconst(ep2);
       ep1 = ep2;
    }
    return(ep1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

EPNODE* getE3 ( void  )

Definition at line 628 of file calexpr.c.

{
    register EPNODE  *ep1, *ep2;

    ep1 = getE4();
    if (nextc == '^') {
       ep2 = newnode();
       ep2->type = nextc;
       scan();
       addekid(ep2, ep1);
       addekid(ep2, getE3());
       if (esupport&E_RCONST &&
                     ep1->type == NUM && ep1->sibling->type == NUM)
              ep2 = rconst(ep2);
       return(ep2);
    }
    return(ep1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

EPNODE* getE4 ( void  )

Definition at line 650 of file calexpr.c.

{
    register EPNODE  *ep1, *ep2;

    if (nextc == '-') {
       scan();
       ep2 = getE5();
       if (ep2->type == NUM) {
              ep2->v.num = -ep2->v.num;
              return(ep2);
       }
       if (ep2->type == UMINUS) {  /* don't generate -(-E5) */
           ep1 = ep2->v.kid;
           efree((char *)ep2);
           return(ep1);
       }
       ep1 = newnode();
       ep1->type = UMINUS;
       addekid(ep1, ep2);
       return(ep1);
    }
    if (nextc == '+')
       scan();
    return(getE5());
}

Here is the call graph for this function:

Here is the caller graph for this function:

EPNODE* getE5 ( void  )

Definition at line 679 of file calexpr.c.

{
       int     i;
       char  *nam;
       register EPNODE  *ep1, *ep2;

       if (nextc == '(') {
              scan();
              ep1 = getE1();
              if (nextc != ')')
                     syntax("')' expected");
              scan();
              return(ep1);
       }

       if (esupport&E_INCHAN && nextc == '$') {
              scan();
              ep1 = newnode();
              ep1->type = CHAN;
              ep1->v.chan = getinum();
              return(ep1);
       }

       if (esupport&(E_VARIABLE|E_FUNCTION) &&
                     (isalpha(nextc) || nextc == CNTXMARK)) {
              nam = getname();
              ep1 = NULL;
              if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
                            && curfunc != NULL)
                     for (i = 1, ep2 = curfunc->v.kid->sibling;
                                   ep2 != NULL; i++, ep2 = ep2->sibling)
                            if (!strcmp(ep2->v.name, nam)) {
                                   ep1 = newnode();
                                   ep1->type = ARG;
                                   ep1->v.chan = i;
                                   break;
                            }
              if (ep1 == NULL) {
                     ep1 = newnode();
                     ep1->type = VAR;
                     ep1->v.ln = varinsert(nam);
              }
              if (esupport&E_FUNCTION && nextc == '(') {
                     ep2 = newnode();
                     ep2->type = FUNC;
                     addekid(ep2, ep1);
                     ep1 = ep2;
                     do {
                            scan();
                            addekid(ep1, getE1());
                     } while (nextc == ',');
                     if (nextc != ')')
                            syntax("')' expected");
                     scan();
              } else if (!(esupport&E_VARIABLE))
                     syntax("'(' expected");
              if (esupport&E_RCONST && isconstvar(ep1))
                     ep1 = rconst(ep1);
              return(ep1);
       }

       if (isdecimal(nextc)) {
              ep1 = newnode();
              ep1->type = NUM;
              ep1->v.num = getnum();
              return(ep1);
       }
       syntax("unexpected character");
       return NULL; /* pro forma return */
}

Here is the call graph for this function:

Here is the caller graph for this function:

int getinum ( void  )

Definition at line 527 of file calexpr.c.

{
    register int  n, lnext;

    n = 0;
    lnext = nextc;
    while (isdigit(lnext)) {
       n = n * 10 + lnext - '0';
       lnext = scan();
    }
    return(n);
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* getname ( void  )

Definition at line 510 of file calexpr.c.

{
    static char       str[RMAXWORD+1];
    register int  i, lnext;

    lnext = nextc;
    for (i = 0; i < RMAXWORD && isid(lnext); i++, lnext = scan())
       str[i] = lnext;
    str[i] = '\0';
    while (isid(lnext))            /* skip rest of name */
       lnext = scan();

    return(str);
}

Here is the call graph for this function:

Here is the caller graph for this function:

double getnum ( void  )

Definition at line 542 of file calexpr.c.

{
    register int  i, lnext;
    char  str[RMAXWORD+1];

    i = 0;
    lnext = nextc;
    while (isdigit(lnext) && i < RMAXWORD) {
       str[i++] = lnext;
       lnext = scan();
    }
    if (lnext == '.' && i < RMAXWORD) {
       str[i++] = lnext;
       lnext = scan();
       if (i == 1 && !isdigit(lnext))
           syntax("badly formed number");
       while (isdigit(lnext) && i < RMAXWORD) {
           str[i++] = lnext;
           lnext = scan();
       }
    }
    if ((lnext == 'e') | (lnext == 'E') && i < RMAXWORD) {
       str[i++] = lnext;
       lnext = scan();
       if ((lnext == '-') | (lnext == '+') && i < RMAXWORD) {
           str[i++] = lnext;
           lnext = scan();
       }
       if (!isdigit(lnext))
           syntax("missing exponent");
       while (isdigit(lnext) && i < RMAXWORD) {
           str[i++] = lnext;
           lnext = scan();
       }
    }
    str[i] = '\0';

    return(atof(str));
}

Here is the call graph for this function:

Here is the caller graph for this function:

void getscanpos ( char **  fnp,
int *  lnp,
char **  spp,
FILE **  fpp 
)

Definition at line 388 of file calexpr.c.

{
    if (fnp != NULL) *fnp = infile;
    if (lnp != NULL) *lnp = lineno;
    if (spp != NULL) *spp = linbuf+linepos;
    if (fpp != NULL) *fpp = infp;
}
void initfile ( FILE *  fp,
char *  fn,
int  ln 
)

Definition at line 353 of file calexpr.c.

{
    static char       inpbuf[MAXLINE];

    infp = fp;
    linbuf = inpbuf;
    infile = fn;
    lineno = ln;
    linepos = 0;
    inpbuf[0] = '\0';
    scan();
}

Here is the call graph for this function:

Here is the caller graph for this function:

void initstr ( char *  s,
char *  fn,
int  ln 
)

Definition at line 372 of file calexpr.c.

{
    infp = NULL;
    infile = fn;
    lineno = ln;
    linbuf = s;
    linepos = 0;
    scan();
}

Here is the call graph for this function:

Here is the caller graph for this function:

int isconstfun ( register EPNODE ep)

Definition at line 802 of file calexpr.c.

{
    register EPNODE  *dp;
    register LIBR  *lp;

    if (ep->type != VAR)
       return(0);
    if ((dp = ep->v.ln->def) != NULL) {
       if (dp->v.kid->type == FUNC)
           return(dp->type == ':');
       else
           return(0);              /* don't identify masked library functions */
    }
    if ((lp = ep->v.ln->lib) != NULL)
       return(lp->atyp == ':');
    return(0);
}
int isconstvar ( register EPNODE ep)

Definition at line 776 of file calexpr.c.

{
    register EPNODE  *ep1;

    if (esupport&E_FUNCTION && 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);
    }
    if (ep->type != VAR)
       return(0);
    ep1 = ep->v.ln->def;
    if (ep1 == NULL || ep1->type != ':')
       return(0);
    if (esupport&E_FUNCTION && ep1->v.kid->type != SYM)
       return(0);
    return(1);
}

Here is the call graph for this function:

char* long2ascii ( long  l)

Definition at line 439 of file calexpr.c.

{
    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);
}

Here is the caller graph for this function:

int nekids ( register EPNODE ep)

Definition at line 339 of file calexpr.c.

{
    register int  n = 0;

    for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
       n++;

    return(n);
}
EPNODE* rconst ( register EPNODE epar)

Definition at line 757 of file calexpr.c.

{
    register 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);
}

Here is the call graph for this function:

int scan ( void  )

Definition at line 403 of file calexpr.c.

{
    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 == eofc) {
              nextc = EOF;
              break;
       }
       if (nextc == '{') {
           scan();
           while (nextc != '}')
              if (nextc == EOF)
                  syntax("'}' expected");
              else
                  scan();
           scan();
       }
    } while (isspace(nextc));
    return(lnext);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void syntax ( char *  err)

Definition at line 466 of file calexpr.c.

{
    register int  i;

    if (infile != NULL || lineno != 0) {
       if (infile != NULL) eputs(infile);
       if (lineno != 0) {
           eputs(infile != NULL ? ", line " : "line ");
           eputs(long2ascii((long)lineno));
       }
       eputs(":\n");
    }
    eputs(linbuf);
    if (linbuf[strlen(linbuf)-1] != '\n')
       eputs("\n");
    for (i = 0; i < linepos-1; i++)
       eputs(linbuf[i] == '\t' ? "\t" : " ");
    eputs("^ ");
    eputs(err);
    eputs("\n");
    quit(1);
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

int eofc = 0

Definition at line 50 of file calexpr.c.

double(* eoper[])(EPNODE *)
Initial value:
 {     
       ebotch,
       evariable,
       enumber,
       euminus,
       echannel,
       efunc,
       eargument,
       ebotch,
       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,0,
       emult,
       eadd,
       0,
       esubtr,
       0,
       edivi,
       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,
}

Definition at line 53 of file calexpr.c.

unsigned int esupport
Initial value:

Definition at line 47 of file calexpr.c.

char* infile [static]

Definition at line 82 of file calexpr.c.

FILE* infp [static]

Definition at line 80 of file calexpr.c.

char* linbuf [static]

Definition at line 81 of file calexpr.c.

int lineno [static]

Definition at line 83 of file calexpr.c.

int linepos [static]

Definition at line 84 of file calexpr.c.

int nextc

Definition at line 51 of file calexpr.c.

const char RCSid[] = "$Id: calexpr.c,v 2.33 2009/06/14 18:21:58 greg Exp $" [static]

Definition at line 2 of file calexpr.c.