Logo Search packages:      
Sourcecode: radiance version File versions  Download package

mgvars.c

#ifndef lint
static const char RCSid[] = "$Id: mgvars.c,v 1.6 2004/03/28 20:33:13 schorsch Exp $";
#endif
/*
 *  mgvars.c - routines dealing with graph variables.
 *
 *     6/23/86
 *
 *     Greg Ward Larson
 */

#include  <stdio.h>
#include  <stdlib.h>
#include  <math.h>
#include  <string.h>
#include  <ctype.h>

#include  "rtprocess.h"
#include  "rtmisc.h"
#include  "rterror.h"
#include  "rtio.h"
#include  "calcomp.h"
#include  "mgvars.h"

#define  MAXLINE  512

#define  isnum(c) (isdigit(c)||(c)=='-'||(c)=='+'||(c)=='.'||(c)=='e'||(c)=='E')

static void mgprint(register VARIABLE *vp, FILE *fp);
static void setivar(char *vname, char *fname, char *definition);
static char *findfile(char *fname, register char **pathlist);
static void loaddata(char *fname, FILE *fp, register DARRAY *dp);
static void undefine(register VARIABLE *vp);

extern char *progname, *libpath[];

IVAR  *ivhead = NULL;               /* intermediate variables */

VARIABLE  gparam[NVARS] = {         /* standard variables */
      { "fthick", REAL, "frame thickness" },
      { "grid", REAL, "grid on?" },
      { "legend", STRING, "legend title" },
      { "othick", REAL, "origin thickness" },
      { "period", REAL, "period of polar plot" },
      { "subtitle", STRING },
      { "symfile", STRING, "symbol file" },
      { "tstyle", REAL, "tick mark style" },
      { "title", STRING },
      { "xlabel", STRING },
      { "xmap", FUNCTION, "x axis mapping function" },
      { "xmax", REAL },
      { "xmin", REAL },
      { "xstep", REAL },
      { "ylabel", STRING },
      { "ymap", FUNCTION, "y axis mapping function" },
      { "ymax", REAL },
      { "ymin", REAL },
      { "ystep", REAL },
};

VARIABLE  cparam[MAXCUR][NCVARS] = {      /* curve variables */
      {
            { "A", FUNCTION, "function for curve A" },
            { "Acolor", REAL, "color for A" },
            { "Adata", DATA, "point data for A" },
            { "Alabel", STRING },
            { "Alintype", REAL, "line type for A" },
            { "Anpoints", REAL, "number of points for A" },
            { "Asymsize", REAL, "symbol size for A" },
            { "Asymtype", STRING, "symbol type for A" },
            { "Athick", REAL, "line thickness for A" },
      }, {
            { "B", FUNCTION, "function for curve B" },
            { "Bcolor", REAL, "color for B" },
            { "Bdata", DATA, "point data for B" },
            { "Blabel", STRING },
            { "Blintype", REAL, "line type for B" },
            { "Bnpoints", REAL, "number of points for B" },
            { "Bsymsize", REAL, "symbol size for B" },
            { "Bsymtype", STRING, "symbol type for B" },
            { "Bthick", REAL, "line thickness for B" },
      }, {
            { "C", FUNCTION, "function for curve C" },
            { "Ccolor", REAL, "color for C" },
            { "Cdata", DATA, "point data for C" },
            { "Clabel", STRING },
            { "Clintype", REAL, "line type for C" },
            { "Cnpoints", REAL, "number of points for C" },
            { "Csymsize", REAL, "symbol size for C" },
            { "Csymtype", STRING, "symbol type for C" },
            { "Cthick", REAL, "line thickness for C" },
      }, {
            { "D", FUNCTION, "function for curve D" },
            { "Dcolor", REAL, "color for D" },
            { "Ddata", DATA, "point data for D" },
            { "Dlabel", STRING },
            { "Dlintype", REAL, "line type for D" },
            { "Dnpoints", REAL, "number of points for D" },
            { "Dsymsize", REAL, "symbol size for D" },
            { "Dsymtype", STRING, "symbol type for D" },
            { "Dthick", REAL, "line thickness for D" },
      }, {
            { "E", FUNCTION, "function for curve E" },
            { "Ecolor", REAL, "color for E" },
            { "Edata", DATA, "point data for E" },
            { "Elabel", STRING },
            { "Elintype", REAL, "line type for E" },
            { "Enpoints", REAL, "number of points for E" },
            { "Esymsize", REAL, "symbol size for E" },
            { "Esymtype", STRING, "symbol type for E" },
            { "Ethick", REAL, "line thickness for E" },
      }, {
            { "F", FUNCTION, "function for curve F" },
            { "Fcolor", REAL, "color for F" },
            { "Fdata", DATA, "point data for F" },
            { "Flabel", STRING },
            { "Flintype", REAL, "line type for F" },
            { "Fnpoints", REAL, "number of points for F" },
            { "Fsymsize", REAL, "symbol size for F" },
            { "Fsymtype", STRING, "symbol type for F" },
            { "Fthick", REAL, "line thickness for F" },
      }, {
            { "G", FUNCTION, "function for curve G" },
            { "Gcolor", REAL, "color for G" },
            { "Gdata", DATA, "point data for G" },
            { "Glabel", STRING },
            { "Glintype", REAL, "line type for G" },
            { "Gnpoints", REAL, "number of points for G" },
            { "Gsymsize", REAL, "symbol size for G" },
            { "Gsymtype", STRING, "symbol type for G" },
            { "Gthick", REAL, "line thickness for G" },
      }, {
            { "H", FUNCTION, "function for curve H" },
            { "Hcolor", REAL, "color for H" },
            { "Hdata", DATA, "point data for H" },
            { "Hlabel", STRING },
            { "Hlintype", REAL, "line type for H" },
            { "Hnpoints", REAL, "number of points for H" },
            { "Hsymsize", REAL, "symbol size for H" },
            { "Hsymtype", STRING, "symbol type for H" },
            { "Hthick", REAL, "line thickness for H" },
      },
};


void
mgclearall(void)              /* clear all variable settings */
{
      int  j;
      register IVAR  *iv;
      register int  i;

      for (iv = ivhead; iv != NULL; iv = iv->next) {
            dremove(iv->name);
            freestr(iv->name);
            freestr(iv->dfn);
            efree((char *)iv);
      }
      ivhead = NULL;

      for (i = 0; i < NVARS; i++)
            if (gparam[i].flags & DEFINED)
                  undefine(&gparam[i]);
      
      for (j = 0; j < MAXCUR; j++)
            for (i = 0; i < NCVARS; i++)
                  if (cparam[j][i].flags & DEFINED)
                        undefine(&cparam[j][i]);
}


void
mgload(                 /* load a file */
char  *file
)
{
      FILE  *fp;
      char  sbuf[MAXLINE], *fgets();
      int  inquote;
      register char  *cp, *cp2;

      if (file == NULL) {
            fp = stdin;
            file = "<stdin>";
      } else if ((fp = fopen(file, "r")) == NULL) {
            fprintf(stderr, "%s: Cannot open: %s\n", progname, file);
            quit(1);
      }
      while (fgets(sbuf+1, sizeof(sbuf)-1, fp) != NULL) {
            inquote = 0;
            cp2 = sbuf;
            for (cp = sbuf+1; *cp; cp++)  /* condition the input line */
                  switch (*cp) {
                  case '#':
                        if (!inquote) {
                              cp[0] = '\n';
                              cp[1] = '\0';
                              break;
                        }
                        *cp2++ = *cp;
                        break;
                  case '"':
                        inquote = !inquote;
                        break;
                  case '\\':
                        if (!cp[1])
                              break;
                        if (cp[1] == '\n') {
                              cp[0] = '\0';
                              fgets(cp, sizeof(sbuf)-(cp-sbuf), fp);
                              cp--;
                              break;
                        }
                        *cp2++ = *++cp;
                        break;
                  case ' ':
                  case '\t':
                  case '\n':
                        if (!inquote)
                              break;
                        *cp2++ = *cp;
                        break;
                  default:
                        *cp2++ = *cp;
                        break;
                  }
            *cp2 = '\0';
            if (inquote) {
                  fputs(sbuf, stderr);
                  fprintf(stderr, "%s: %s: Missing quote\n",
                              progname, file);
                  quit(1);
            }
            if (sbuf[0])
                  setmgvar(file, fp, sbuf);
      }
      if (fp != stdin)
            fclose(fp);
}


void
mgsave(                       /* save our variables */
char  *file
)
{
      FILE  *fp;
      int  j;
      register IVAR  *iv;
      register int  i;

      if (file == NULL)
            fp = stdout;
      else if ((fp = fopen(file, "w")) == NULL) {
            fprintf(stderr, "%s: Cannot write: %s\n", progname, file);
            quit(1);
      }
      for (iv = ivhead; iv != NULL; iv = iv->next)
            fprintf(fp, "%s\n", iv->dfn);

      for (i = 0; i < NVARS; i++)
            if (gparam[i].flags & DEFINED)
                  mgprint(&gparam[i], fp);
      
      for (j = 0; j < MAXCUR; j++)
            for (i = 0; i < NCVARS; i++)
                  if (cparam[j][i].flags & DEFINED)
                        mgprint(&cparam[j][i], fp);

      if (fp != stdout)
            fclose(fp);
}


void
setmgvar(         /* set a variable */
char  *fname,
FILE  *fp,
char  *string
)
{
      char  name[128];
      FILE  *fp2;
      register int  i;
      register char  *s;
      register VARIABLE  *vp;

      if (!strncmp(string, "include=", 8)) {    /* include file */
            if ((s = findfile(string+8, libpath)) == NULL) {
                  fprintf(stderr, "%s\n", string);
                  fprintf(stderr, "%s: %s: File not found: %s\n",
                              progname, fname, string+8);
                  quit(1);
            }
            strcpy(name, s);
            mgload(name);
            return;
      }
      s = string;
      i = 0;
      while (i < sizeof(name)-1 && isid(*s))
            name[i++] = *s++;
      name[i] = '\0';
      vp = vlookup(name);
      if (vp != NULL) {
            undefine(vp);
            switch (vp->type) {
            case REAL:
            case FUNCTION:
                  if ((*s == '(') != (vp->type == FUNCTION)) {
                        fprintf(stderr, "%s\n", string);
                        fprintf(stderr,
                              "%s: %s: Bad %s declaration: %s\n",
                              progname, fname,
                              vp->type == FUNCTION ?
                              "function" : "variable",
                              name);
                        quit(1);
                  }
                  scompile(string, fname, 0);
                  vp->v.dfn = savestr(string);
                  break;
            case STRING:
                  if (*s++ != '=') {
                        fprintf(stderr, "%s\n", string);
                        fprintf(stderr, "%s: %s: Missing '='\n",
                                    progname, fname);
                        quit(1);
                  }
                  vp->v.s = savestr(s);
                  break;
            case DATA:
                  if (*s++ != '=') {
                        fprintf(stderr, "%s\n", string);
                        fprintf(stderr, "%s: %s: Missing '='\n",
                                    progname, fname);
                        quit(1);
                  }
                  if (!*s) {
                        loaddata(fname, fp, &vp->v.d);
                  } else if (*s == '!') {
                        if ((fp2 = popen(s+1, "r")) == NULL) {
                              fprintf(stderr, "%s\n", string);
                              fprintf(stderr,
                              "%s: %s: Cannot execute: %s\n",
                                          progname, fname, s+1);
                              quit(1);
                        }
                        loaddata(s, fp2, &vp->v.d);
                        pclose(fp2);
                  } else {
                        if ((fp2 = fopen(s, "r")) == NULL) {
                            fprintf(stderr, "%s\n", string);
                            fprintf(stderr,
                                  "%s: %s: Data file not found: %s\n",
                                  progname, fname, s);
                            quit(1);
                        }
                        loaddata(s, fp2, &vp->v.d);
                        fclose(fp2);
                  }
                  break;
            }
            vp->flags |= DEFINED;
      } else
            setivar(name, fname, string);       /* intermediate */
}


static void
setivar(    /* set an intermediate variable */
char  *vname,
char  *fname,
char  *definition
)
{
      IVAR  ivbeg;
      register IVAR  *iv;

      scompile(definition, fname, 0);           /* compile the string */

      ivbeg.next = ivhead;
      for (iv = &ivbeg; iv->next != NULL; iv = iv->next)
            if (!strcmp(vname, iv->next->name)) {
                  iv = iv->next;
                  freestr(iv->dfn);
                  iv->dfn = savestr(definition);
                  return;
            }

      iv->next = (IVAR *)emalloc(sizeof(IVAR));
      iv = iv->next;
      iv->name = savestr(vname);
      iv->dfn = savestr(definition);
      iv->next = NULL;
      ivhead = ivbeg.next;
}


void
mgtoa(                  /* get a variable's value in ascii form */
register char  *s,
VARIABLE  *vp
)
{
      register  char  *sv;

      if (!(vp->flags & DEFINED)) {
            strcpy(s, "UNDEFINED");
            return;
      }
      switch (vp->type) {
      case REAL:
      case FUNCTION:
            sv = vp->v.dfn;
            while (*sv != '=' && *sv != ':')
                  sv++;
            while (*++sv && *sv != ';')
                  *s++ = *sv;
            *s = '\0';
            break;
      case STRING:
            strcpy(s, vp->v.s);
            break;
      case DATA:
            strcpy(s, "DATA");
            break;
      }
}


static void
mgprint(                /* print a variable definition */
register VARIABLE  *vp,
FILE  *fp
)
{
      register int  i;
      
      switch (vp->type) {
      case REAL:
      case FUNCTION:
            fprintf(fp, "%s\n", vp->v.dfn);
            break;
      case STRING:
            fprintf(fp, "%s=\"", vp->name);
            for (i = 0; vp->v.s[i]; i++)
                  switch (vp->v.s[i]) {
                  case '"':
                  case '\\':
                        putc('\\', fp);
                  /* fall through */
                  default:
                        putc(vp->v.s[i], fp);
                        break;
                  }
            fprintf(fp, "\"\n");
            break;
      case DATA:
            fprintf(fp, "%s=", vp->name);
            for (i = 0; i < vp->v.d.size; i++) {
                  if (i % 4 == 0)
                        fprintf(fp, "\n");
                  fprintf(fp, "\t%10e", vp->v.d.data[i]);
            }
            fprintf(fp, "\n;\n");
            break;
      }
}


static void
undefine(               /* undefine a variable */
register VARIABLE  *vp
)
{
      if (vp == NULL || !(vp->flags & DEFINED))
            return;

      switch (vp->type) {
      case REAL:
      case FUNCTION:
            dremove(vp->name);
            freestr(vp->v.dfn);
            break;
      case STRING:
            freestr(vp->v.s);
            break;
      case DATA:
            efree((char *)vp->v.d.data);
            break;
      }
      vp->flags &= ~DEFINED;
}


VARIABLE *
vlookup(vname)                /* look up a variable by its name */
char  *vname;
{
      register int  i;
      register VARIABLE  *vp;

      i = vname[0] - 'A';
      if (i >= 0 && i < MAXCUR)           /* curve variables */
            for (vp = cparam[i], i = 0; i < NCVARS; vp++, i++)
                  if (!strcmp(vp->name, vname))
                        return(vp);
                                    /* standard variables */
      for (vp = gparam; vp < &gparam[NVARS]; vp++)
            if (!strcmp(vp->name, vname))
                  return(vp);
      return(NULL);                       /* not found */
}


static void
loaddata(               /* load data from a stream */
char  *fname,
FILE  *fp,
register DARRAY  *dp
)
{
      char  sbuf[MAXLINE], *fgets();
      register char  *cp;

      dp->size = 0;
      dp->data = NULL;
      while (fgets(sbuf, sizeof(sbuf), fp) != NULL) {
            cp = sbuf;
            while (*cp) {
                  while (isspace(*cp) || *cp == ',')
                        cp++;
                  if (isnum(*cp)) {
                        dp->data = (float *)erealloc((char *)dp->data,
                                    (dp->size+1)*sizeof(float));
                        dp->data[dp->size++] = atof(cp);
                        do
                              cp++;
                        while (isnum(*cp));
                  } else if (*cp == ';') {
                        return;
                  } else if (*cp) {
                        fputs(sbuf, stderr);
                        fprintf(stderr, "%s: %s: Bad data\n",
                                    progname, fname);
                        quit(1);
                  }
            }
      }
}


static char *
findfile(   /* find the file fname, return full path */
char  *fname,
register char  **pathlist
)
{
      static char  ffname[128];
      register int  fd;

      if (fname[0] == '/')
            return(fname);

      while (*pathlist != NULL) {
            strcpy(ffname, *pathlist);
            strcat(ffname, fname);
            if ((fd = open(ffname, 0)) != -1) {
                  close(fd);
                  return(ffname);
            }
            pathlist++;
      }
      return(NULL);
}


int
mgcurve(                /* get a curve's (unmapped) values */
      int  c,
      void (*f)(int c, double x, double y)
)
{
      int  nargs;
      double  x[2], step;
      register VARIABLE  *cv;
      register float  *p;
      register int npts = 0;

      if (c < 0 || c >= MAXCUR)
            return(-1);
      cv = cparam[c];

      if (cv[C].flags & DEFINED) {        /* function or map */

            nargs = fundefined(cv[C].name);
            if (nargs < 1 || nargs > 2) {
                  fprintf(stderr, "%s: bad # of arguments for '%c'\n",
                              progname, c+'A');
                  quit(1);
            }

            if (cv[CDATA].flags & DEFINED) {          /* map */
                  npts = cv[CDATA].v.d.size / nargs;
                  p = cv[CDATA].v.d.data;
                  while (npts--) {
                        x[0] = *p++;
                        if (nargs == 2)
                              x[1] = *p++;
                        (*f)(c, x[0],
                              funvalue(cv[C].name, nargs, x));
                  }
                  npts = cv[CDATA].v.d.size / nargs;
            } else if ( nargs == 1 &&                 /* function */
                        gparam[XMIN].flags & DEFINED &&
                        gparam[XMAX].flags & DEFINED &&
                        cv[CNPOINTS].flags & DEFINED ) {
                  npts = varvalue(cv[CNPOINTS].name);
                  if (npts > 1)
                        step = (varvalue(gparam[XMAX].name) -
                              varvalue(gparam[XMIN].name)) /
                              (npts - 1);
                  else
                        step = 0.0;
                  for (x[0] = varvalue(gparam[XMIN].name);
                              npts--; x[0] += step)
                        (*f)(c, x[0],
                              funvalue(cv[C].name, 1, x));
                  npts = varvalue(cv[CNPOINTS].name);
            } else {
                  fprintf(stderr,
                  "%s: function '%c' needs %cdata or xmin, xmax, %cnpoints\n",
                              progname, c+'A', c+'A', c+'A');
                  quit(1);
            }

      } else if (cv[CDATA].flags & DEFINED) {   /* data */

            npts = cv[CDATA].v.d.size / 2;
            p = cv[CDATA].v.d.data;
            while (npts--) {
                  (*f)(c, p[0], p[1]);
                  p += 2;
            }
            npts = cv[CDATA].v.d.size / 2;

      } else

            npts = 0;

      return(npts);
}

Generated by  Doxygen 1.6.0   Back to index