Back to index

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

Go to the source code of this file.

Defines

#define NHASH   521 /* hash size (a prime!) */
#define hash(s)   (shash(s)%NHASH)
#define newnode()   (EPNODE *)ecalloc(1, sizeof(EPNODE))
#define MAXCLOCK   (1L<<31) /* clock wrap value */
#define MAXCNTX   1023 /* maximum context length */
#define dname(ep)

Functions

static double dvalue (char *name, EPNODE *d)
void fcompile (char *fname)
void scompile (char *str, char *fn, int ln)
double varvalue (char *vname)
double evariable (EPNODE *ep)
void varset (char *vname, int assign, double val)
void dclear (char *name)
void dremove (char *name)
int vardefined (char *name)
char * setcontext (register char *ctx)
char * pushcontext (char *ctx)
char * popcontext (void)
char * qualname (register char *nam, int lvl)
int incontext (register char *qn)
void chanout (void(*cs)(int n, double v))
void dcleanup (int lvl)
EPNODEdlookup (char *name)
VARDEF * varlookup (char *name)
VARDEF * varinsert (char *name)
void libupdate (char *fn)
void varfree (register VARDEF *ln)
EPNODEdfirst (void)
EPNODEdnext (void)
EPNODEdpop (char *name)
void dpush (char *nm, register EPNODE *ep)
void addchan (EPNODE *sp)
void getstatement (void)
EPNODEgetdefn (void)
EPNODEgetchan (void)

Variables

static const char RCSid [] = "$Id: caldefn.c,v 2.24 2010/03/05 17:28:46 greg Exp $"
unsigned long eclock = 0
static char context [MAXCNTX+1]
static VARDEF * hashtbl [NHASH]
static int htndx
static VARDEF * htpos
static EPNODEochpos
static EPNODEoutchan
EPNODEcurfunc = NULL

Define Documentation

#define dname (   ep)
Value:
((ep)->v.kid->type == SYM ? \
                     (ep)->v.kid->v.name : \
                     (ep)->v.kid->v.kid->v.name)

Definition at line 64 of file caldefn.c.

#define hash (   s)    (shash(s)%NHASH)

Definition at line 43 of file caldefn.c.

#define MAXCLOCK   (1L<<31) /* clock wrap value */

Definition at line 49 of file caldefn.c.

#define MAXCNTX   1023 /* maximum context length */

Definition at line 53 of file caldefn.c.

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

Definition at line 45 of file caldefn.c.

#define NHASH   521 /* hash size (a prime!) */

Definition at line 40 of file caldefn.c.


Function Documentation

void addchan ( EPNODE sp)

Definition at line 529 of file caldefn.c.

{
    int        ch = sp->v.kid->v.chan;
    register 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;

}

Here is the call graph for this function:

Here is the caller graph for this function:

void chanout ( void(*)(int n, double v cs)

Definition at line 331 of file caldefn.c.

{
    register EPNODE  *ep;

    for (ep = outchan; ep != NULL; ep = ep->sibling)
       (*cs)(ep->v.kid->v.chan, evalue(ep->v.kid->sibling));

}

Here is the caller graph for this function:

void dcleanup ( int  lvl)

Definition at line 344 of file caldefn.c.

{
    register int  i;
    register VARDEF  *vp;
    register 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;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void dclear ( char *  name)

Definition at line 161 of file caldefn.c.

{
    register EPNODE  *ep;

    while ((ep = dpop(name)) != NULL) {
       if (ep->type == ':') {
           dpush(name, ep);        /* don't clear constants */
           return;
       }
       epfree(ep);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

EPNODE* dfirst ( void  )

Definition at line 465 of file caldefn.c.

{
    htndx = 0;
    htpos = NULL;
    ochpos = outchan;
    return(dnext());
}

Here is the call graph for this function:

Here is the caller graph for this function:

EPNODE* dlookup ( char *  name)

Definition at line 369 of file caldefn.c.

{
    register VARDEF  *vp;
    
    if ((vp = varlookup(name)) == NULL)
       return(NULL);
    return(vp->def);
}

Here is the call graph for this function:

Here is the caller graph for this function:

EPNODE* dnext ( void  )

Definition at line 475 of file caldefn.c.

{
    register EPNODE  *ep;
    register char  *nm;

    while (htndx < NHASH) {
       if (htpos == NULL)
              htpos = hashtbl[htndx++];
       while (htpos != NULL) {
           ep = htpos->def;
           nm = htpos->name;
           htpos = htpos->next;
           if (ep != NULL && incontext(nm))
              return(ep);
       }
    }
    if ((ep = ochpos) != NULL)
       ochpos = ep->sibling;
    return(ep);
}

Here is the call graph for this function:

Here is the caller graph for this function:

EPNODE* dpop ( char *  name)

Definition at line 498 of file caldefn.c.

{
    register VARDEF  *vp;
    register EPNODE  *dp;
    
    if ((vp = varlookup(name)) == NULL || vp->def == NULL)
       return(NULL);
    dp = vp->def;
    vp->def = dp->sibling;
    varfree(vp);
    return(dp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void dpush ( char *  nm,
register EPNODE ep 
)

Definition at line 515 of file caldefn.c.

{
    register VARDEF  *vp;

    vp = varinsert(nm);
    ep->sibling = vp->def;
    vp->def = ep;
}

Here is the call graph for this function:

void dremove ( char *  name)

Definition at line 178 of file caldefn.c.

{
    register EPNODE  *ep;

    while ((ep = dpop(name)) != NULL)
       epfree(ep);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static double dvalue ( char *  name,
EPNODE d 
) [static]

Definition at line 696 of file caldefn.c.

{
    register EPNODE  *ep1, *ep2;
    
    if (d == NULL || d->v.kid->type != SYM) {
       eputs(name);
       eputs(": undefined variable\n");
       quit(1);
    }
    ep1 = d->v.kid->sibling;                     /* get expression */
    if (ep1->type == NUM)
       return(ep1->v.num);                /* return if number */
    ep2 = ep1->sibling;                          /* check time */
    if (eclock >= MAXCLOCK)
       eclock = 1;                        /* wrap clock counter */
    if (ep2->v.tick < MAXCLOCK &&
              (ep2->v.tick == 0) | (ep2->v.tick != eclock)) {
       ep2->v.tick = d->type == ':' ? MAXCLOCK : eclock;
       ep2 = ep2->sibling;
       ep2->v.num = evalue(ep1);          /* needs new value */
    } else
       ep2 = ep2->sibling;                /* else reuse old value */

    return(ep2->v.num);
}

Here is the call graph for this function:

Here is the caller graph for this function:

double evariable ( EPNODE ep)

Definition at line 114 of file caldefn.c.

{
    register VARDEF  *dp = ep->v.ln;

    return(dvalue(dp->name, dp->def));
}

Here is the call graph for this function:

void fcompile ( char *  fname)

Definition at line 70 of file caldefn.c.

{
    FILE  *fp;

    if (fname == NULL)
       fp = stdin;
    else if ((fp = fopen(fname, "r")) == NULL) {
       eputs(fname);
       eputs(": cannot open\n");
       quit(1);
    }
    initfile(fp, fname, 0);
    while (nextc != EOF)
       getstatement();
    if (fname != NULL)
       fclose(fp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

EPNODE* getchan ( void  )

Definition at line 664 of file caldefn.c.

{
    register EPNODE  *ep1, *ep2;

    if (nextc != '$')
       syntax("missing '$'");
    scan();

    ep1 = newnode();
    ep1->type = CHAN;
    ep1->v.chan = getinum();

    if (nextc != '=')
       syntax("'=' expected");
    scan();

    ep2 = newnode();
    ep2->type = '=';
    addekid(ep2, ep1);
    addekid(ep2, getE1());

    return(ep2);
}

Here is the call graph for this function:

Here is the caller graph for this function:

EPNODE* getdefn ( void  )

Definition at line 604 of file caldefn.c.

{
    register EPNODE  *ep1, *ep2;

    if (!isalpha(nextc) && nextc != CNTXMARK)
       syntax("illegal variable name");

    ep1 = newnode();
    ep1->type = SYM;
    ep1->v.name = savestr(getname());

    if (esupport&E_FUNCTION && nextc == '(') {
       ep2 = newnode();
       ep2->type = FUNC;
       addekid(ep2, ep1);
       ep1 = ep2;
       do {
           scan();
           if (!isalpha(nextc))
              syntax("illegal parameter name");
           ep2 = newnode();
           ep2->type = SYM;
           ep2->v.name = savestr(getname());
           addekid(ep1, ep2);
       } while (nextc == ',');
       if (nextc != ')')
           syntax("')' expected");
       scan();
       curfunc = ep1;
    }

    if (nextc != '=' && nextc != ':')
       syntax("'=' or ':' expected");

    ep2 = newnode();
    ep2->type = nextc;
    scan();
    addekid(ep2, ep1);
    addekid(ep2, getE1());

    if (ep1->type == SYM && ep1->sibling->type != NUM) {
       ep1 = newnode();
       ep1->type = CLKT;
       ep1->v.tick = 0;
       addekid(ep2, ep1);
       ep1 = newnode();
       ep1->type = NUM;
       addekid(ep2, ep1);
    }
    curfunc = NULL;

    return(ep2);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void getstatement ( void  )

Definition at line 560 of file caldefn.c.

{
    register EPNODE  *ep;
    char  *qname;
    register VARDEF  *vdef;

    if (nextc == ';') {            /* empty statement */
       scan();
       return;
    }
    if (esupport&E_OUTCHAN &&
              nextc == '$') {             /* channel assignment */
       ep = getchan();
       addchan(ep);
    } else {                       /* ordinary definition */
       ep = getdefn();
       qname = qualname(dname(ep), 0);
       if (esupport&E_REDEFW && (vdef = varlookup(qname)) != NULL) {
           if (vdef->def != NULL && epcmp(ep, vdef->def)) {
              wputs(qname);
              if (vdef->def->type == ':')
                  wputs(": redefined constant expression\n");
              else
                  wputs(": redefined\n");
           } else if (ep->v.kid->type == FUNC && vdef->lib != NULL) {
              wputs(qname);
              wputs(": definition hides library function\n");
           }
       }
       if (ep->type == ':')
           dremove(qname);
       else
           dclear(qname);
       dpush(qname, ep);
    }
    if (nextc != EOF) {
       if (nextc != ';')
           syntax("';' expected");
       scan();
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int incontext ( register char *  qn)

Definition at line 318 of file caldefn.c.

{
    if (!context[0])               /* global context accepts all */
       return(1);
    while (*qn && *qn != CNTXMARK) /* find context mark */
       qn++;
    return(!strcmp(qn, context));
}

Here is the call graph for this function:

void libupdate ( char *  fn)

Definition at line 425 of file caldefn.c.

{
    register int  i;
    register VARDEF  *vp;
                                   /* if fn is NULL then relink all */
    for (i = 0; i < NHASH; i++)
       for (vp = hashtbl[i]; vp != NULL; vp = vp->next)
           if (vp->lib != NULL || fn == NULL || !strcmp(fn, vp->name))
              vp->lib = liblookup(vp->name);
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* popcontext ( void  )

Definition at line 254 of file caldefn.c.

{
    register char  *cp1, *cp2;

    if (!context[0])               /* nothing left to pop */
       return(context);
    cp2 = context;                 /* find mark */
    while (*++cp2 && *cp2 != CNTXMARK)
       ;
    cp1 = context;                 /* copy tail to front */
    while ( (*cp1++ = *cp2++) )
       ;
    return(context);
}
char* pushcontext ( char *  ctx)

Definition at line 234 of file caldefn.c.

{
    char  oldcontext[MAXCNTX+1];
    register int  n;

    strcpy(oldcontext, context);   /* save old context */
    setcontext(ctx);               /* set new context */
    n = strlen(context);           /* tack on old */
    if (n+strlen(oldcontext) > MAXCNTX) {
       strncpy(context+n, oldcontext, MAXCNTX-n);
       context[MAXCNTX] = '\0';
    } else
       strcpy(context+n, oldcontext);
    return(context);
}

Here is the call graph for this function:

char* qualname ( register char *  nam,
int  lvl 
)

Definition at line 271 of file caldefn.c.

{
    static char       nambuf[RMAXWORD+1];
    register char  *cp = nambuf, *cpp;
                            /* check for explicit local */
    if (*nam == CNTXMARK)
       if (lvl > 0)         /* only action is to refuse search */
           return(NULL);
       else
           nam++;
    else if (nam == nambuf) /* check for repeat call */
       return(lvl > 0 ? NULL : nam);
                            /* copy name to static buffer */
    while (*nam) {
       if (cp >= nambuf+RMAXWORD)
              goto toolong;
       *cp++ = *nam++;
    }
                            /* check for explicit global */
    if (cp > nambuf && cp[-1] == CNTXMARK) {
       if (lvl > 0)
           return(NULL);
       *--cp = '\0';
       return(nambuf);             /* already qualified */
    }
    cpp = context;          /* else skip the requested levels */
    while (lvl-- > 0) {
       if (!*cpp)
           return(NULL);    /* return NULL if past global level */
       while (*++cpp && *cpp != CNTXMARK)
           ;
    }
    while (*cpp) {          /* copy context to static buffer */
       if (cp >= nambuf+RMAXWORD)
           goto toolong;
       *cp++ = *cpp++;
    }
toolong:
    *cp = '\0';
    return(nambuf);         /* return qualified name */
}
void scompile ( char *  str,
char *  fn,
int  ln 
)

Definition at line 92 of file caldefn.c.

{
    initstr(str, fn, ln);
    while (nextc != EOF)
       getstatement();
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* setcontext ( register char *  ctx)

Definition at line 201 of file caldefn.c.

{
    register char  *cpp;

    if (ctx == NULL)
       return(context);            /* just asking */
    while (*ctx == CNTXMARK)
       ctx++;                      /* skip past marks */
    if (!*ctx) {
       context[0] = '\0';          /* empty means clear context */
       return(context);
    }
    cpp = context;                 /* start context with mark */
    *cpp++ = CNTXMARK;
    do {                           /* carefully copy new context */
       if (cpp >= context+MAXCNTX)
           break;                  /* just copy what we can */
       if (isid(*ctx))
           *cpp++ = *ctx++;
       else {
           *cpp++ = '_'; ctx++;
       }
    } while (*ctx);
    while (cpp[-1] == CNTXMARK)           /* cannot end in context mark */
       cpp--;
    *cpp = '\0';
    return(context);
}
int vardefined ( char *  name)

Definition at line 190 of file caldefn.c.

{
    register EPNODE  *dp;

    return((dp = dlookup(name)) != NULL && dp->v.kid->type == SYM);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void varfree ( register VARDEF *  ln)

Definition at line 440 of file caldefn.c.

{
    register VARDEF  *vp;
    int        hv;

    if (--ln->nlinks > 0)
       return;                            /* still active */

    hv = hash(ln->name);
    vp = hashtbl[hv];
    if (vp == ln)
       hashtbl[hv] = vp->next;
    else {
       while (vp->next != ln)             /* must be in list */
              vp = vp->next;
       vp->next = ln->next;
    }
    freestr(ln->name);
    efree((char *)ln);
}

Here is the call graph for this function:

VARDEF* varinsert ( char *  name)

Definition at line 399 of file caldefn.c.

{
    register VARDEF  *vp;
    int        hv;
    
    if ((vp = varlookup(name)) != NULL) {
       vp->nlinks++;
       return(vp);
    }
    vp = (VARDEF *)emalloc(sizeof(VARDEF));
    vp->lib = liblookup(name);
    if (vp->lib == NULL)           /* if name not in library */
       name = qualname(name, 0);   /* use fully qualified version */
    hv = hash(name);
    vp->name = savestr(name);
    vp->nlinks = 1;
    vp->def = NULL;
    vp->next = hashtbl[hv];
    hashtbl[hv] = vp;
    return(vp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

VARDEF* varlookup ( char *  name)

Definition at line 382 of file caldefn.c.

{
    int        lvl = 0;
    register char  *qname;
    register VARDEF  *vp;
                            /* find most qualified match */
    while ((qname = qualname(name, lvl++)) != NULL)
       for (vp = hashtbl[hash(qname)]; vp != NULL; vp = vp->next)
           if (!strcmp(vp->name, qname))
              return(vp);
    return(NULL);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void varset ( char *  vname,
int  assign,
double  val 
)

Definition at line 125 of file caldefn.c.

{
    char  *qname;
    register EPNODE  *ep1, *ep2;
                                   /* get qualified name */
    qname = qualname(vname, 0);
                                   /* check for quick set */
    if ((ep1 = dlookup(qname)) != NULL && ep1->v.kid->type == SYM) {
       ep2 = ep1->v.kid->sibling;
       if (ep2->type == NUM) {
           ep2->v.num = val;
           ep1->type = assign;
           return;
       }
    }
                                   /* hand build definition */
    ep1 = newnode();
    ep1->type = assign;
    ep2 = newnode();
    ep2->type = SYM;
    ep2->v.name = savestr(vname);
    addekid(ep1, ep2);
    ep2 = newnode();
    ep2->type = NUM;
    ep2->v.num = val;
    addekid(ep1, ep2);
    dremove(qname);
    dpush(qname, ep1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

double varvalue ( char *  vname)

Definition at line 105 of file caldefn.c.

{
    return(dvalue(vname, dlookup(vname)));
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

char context[MAXCNTX+1] [static]

Definition at line 55 of file caldefn.c.

EPNODE* curfunc = NULL

Definition at line 63 of file caldefn.c.

unsigned long eclock = 0

Definition at line 51 of file caldefn.c.

VARDEF* hashtbl[NHASH] [static]

Definition at line 57 of file caldefn.c.

int htndx [static]

Definition at line 58 of file caldefn.c.

VARDEF* htpos [static]

Definition at line 59 of file caldefn.c.

EPNODE* ochpos [static]

Definition at line 60 of file caldefn.c.

EPNODE* outchan [static]

Definition at line 61 of file caldefn.c.

const char RCSid[] = "$Id: caldefn.c,v 2.24 2010/03/05 17:28:46 greg Exp $" [static]

Definition at line 2 of file caldefn.c.