Back to index

radiance  4R0+20100331
mgvars.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: mgvars.c,v 1.6 2004/03/28 20:33:13 schorsch Exp $";
00003 #endif
00004 /*
00005  *  mgvars.c - routines dealing with graph variables.
00006  *
00007  *     6/23/86
00008  *
00009  *     Greg Ward Larson
00010  */
00011 
00012 #include  <stdio.h>
00013 #include  <stdlib.h>
00014 #include  <math.h>
00015 #include  <string.h>
00016 #include  <ctype.h>
00017 
00018 #include  "rtprocess.h"
00019 #include  "rtmisc.h"
00020 #include  "rterror.h"
00021 #include  "rtio.h"
00022 #include  "calcomp.h"
00023 #include  "mgvars.h"
00024 
00025 #define  MAXLINE     512
00026 
00027 #define  isnum(c) (isdigit(c)||(c)=='-'||(c)=='+'||(c)=='.'||(c)=='e'||(c)=='E')
00028 
00029 static void mgprint(register VARIABLE *vp, FILE *fp);
00030 static void setivar(char *vname, char *fname, char *definition);
00031 static char *findfile(char *fname, register char **pathlist);
00032 static void loaddata(char *fname, FILE *fp, register DARRAY *dp);
00033 static void undefine(register VARIABLE *vp);
00034 
00035 extern char *progname, *libpath[];
00036 
00037 IVAR  *ivhead = NULL;                     /* intermediate variables */
00038 
00039 VARIABLE  gparam[NVARS] = {        /* standard variables */
00040        { "fthick", REAL, "frame thickness" },
00041        { "grid", REAL, "grid on?" },
00042        { "legend", STRING, "legend title" },
00043        { "othick", REAL, "origin thickness" },
00044        { "period", REAL, "period of polar plot" },
00045        { "subtitle", STRING },
00046        { "symfile", STRING, "symbol file" },
00047        { "tstyle", REAL, "tick mark style" },
00048        { "title", STRING },
00049        { "xlabel", STRING },
00050        { "xmap", FUNCTION, "x axis mapping function" },
00051        { "xmax", REAL },
00052        { "xmin", REAL },
00053        { "xstep", REAL },
00054        { "ylabel", STRING },
00055        { "ymap", FUNCTION, "y axis mapping function" },
00056        { "ymax", REAL },
00057        { "ymin", REAL },
00058        { "ystep", REAL },
00059 };
00060 
00061 VARIABLE  cparam[MAXCUR][NCVARS] = {      /* curve variables */
00062        {
00063               { "A", FUNCTION, "function for curve A" },
00064               { "Acolor", REAL, "color for A" },
00065               { "Adata", DATA, "point data for A" },
00066               { "Alabel", STRING },
00067               { "Alintype", REAL, "line type for A" },
00068               { "Anpoints", REAL, "number of points for A" },
00069               { "Asymsize", REAL, "symbol size for A" },
00070               { "Asymtype", STRING, "symbol type for A" },
00071               { "Athick", REAL, "line thickness for A" },
00072        }, {
00073               { "B", FUNCTION, "function for curve B" },
00074               { "Bcolor", REAL, "color for B" },
00075               { "Bdata", DATA, "point data for B" },
00076               { "Blabel", STRING },
00077               { "Blintype", REAL, "line type for B" },
00078               { "Bnpoints", REAL, "number of points for B" },
00079               { "Bsymsize", REAL, "symbol size for B" },
00080               { "Bsymtype", STRING, "symbol type for B" },
00081               { "Bthick", REAL, "line thickness for B" },
00082        }, {
00083               { "C", FUNCTION, "function for curve C" },
00084               { "Ccolor", REAL, "color for C" },
00085               { "Cdata", DATA, "point data for C" },
00086               { "Clabel", STRING },
00087               { "Clintype", REAL, "line type for C" },
00088               { "Cnpoints", REAL, "number of points for C" },
00089               { "Csymsize", REAL, "symbol size for C" },
00090               { "Csymtype", STRING, "symbol type for C" },
00091               { "Cthick", REAL, "line thickness for C" },
00092        }, {
00093               { "D", FUNCTION, "function for curve D" },
00094               { "Dcolor", REAL, "color for D" },
00095               { "Ddata", DATA, "point data for D" },
00096               { "Dlabel", STRING },
00097               { "Dlintype", REAL, "line type for D" },
00098               { "Dnpoints", REAL, "number of points for D" },
00099               { "Dsymsize", REAL, "symbol size for D" },
00100               { "Dsymtype", STRING, "symbol type for D" },
00101               { "Dthick", REAL, "line thickness for D" },
00102        }, {
00103               { "E", FUNCTION, "function for curve E" },
00104               { "Ecolor", REAL, "color for E" },
00105               { "Edata", DATA, "point data for E" },
00106               { "Elabel", STRING },
00107               { "Elintype", REAL, "line type for E" },
00108               { "Enpoints", REAL, "number of points for E" },
00109               { "Esymsize", REAL, "symbol size for E" },
00110               { "Esymtype", STRING, "symbol type for E" },
00111               { "Ethick", REAL, "line thickness for E" },
00112        }, {
00113               { "F", FUNCTION, "function for curve F" },
00114               { "Fcolor", REAL, "color for F" },
00115               { "Fdata", DATA, "point data for F" },
00116               { "Flabel", STRING },
00117               { "Flintype", REAL, "line type for F" },
00118               { "Fnpoints", REAL, "number of points for F" },
00119               { "Fsymsize", REAL, "symbol size for F" },
00120               { "Fsymtype", STRING, "symbol type for F" },
00121               { "Fthick", REAL, "line thickness for F" },
00122        }, {
00123               { "G", FUNCTION, "function for curve G" },
00124               { "Gcolor", REAL, "color for G" },
00125               { "Gdata", DATA, "point data for G" },
00126               { "Glabel", STRING },
00127               { "Glintype", REAL, "line type for G" },
00128               { "Gnpoints", REAL, "number of points for G" },
00129               { "Gsymsize", REAL, "symbol size for G" },
00130               { "Gsymtype", STRING, "symbol type for G" },
00131               { "Gthick", REAL, "line thickness for G" },
00132        }, {
00133               { "H", FUNCTION, "function for curve H" },
00134               { "Hcolor", REAL, "color for H" },
00135               { "Hdata", DATA, "point data for H" },
00136               { "Hlabel", STRING },
00137               { "Hlintype", REAL, "line type for H" },
00138               { "Hnpoints", REAL, "number of points for H" },
00139               { "Hsymsize", REAL, "symbol size for H" },
00140               { "Hsymtype", STRING, "symbol type for H" },
00141               { "Hthick", REAL, "line thickness for H" },
00142        },
00143 };
00144 
00145 
00146 void
00147 mgclearall(void)                   /* clear all variable settings */
00148 {
00149        int  j;
00150        register IVAR  *iv;
00151        register int  i;
00152 
00153        for (iv = ivhead; iv != NULL; iv = iv->next) {
00154               dremove(iv->name);
00155               freestr(iv->name);
00156               freestr(iv->dfn);
00157               efree((char *)iv);
00158        }
00159        ivhead = NULL;
00160 
00161        for (i = 0; i < NVARS; i++)
00162               if (gparam[i].flags & DEFINED)
00163                      undefine(&gparam[i]);
00164        
00165        for (j = 0; j < MAXCUR; j++)
00166               for (i = 0; i < NCVARS; i++)
00167                      if (cparam[j][i].flags & DEFINED)
00168                             undefine(&cparam[j][i]);
00169 }
00170 
00171 
00172 void
00173 mgload(                     /* load a file */
00174 char  *file
00175 )
00176 {
00177        FILE  *fp;
00178        char  sbuf[MAXLINE], *fgets();
00179        int  inquote;
00180        register char  *cp, *cp2;
00181 
00182        if (file == NULL) {
00183               fp = stdin;
00184               file = "<stdin>";
00185        } else if ((fp = fopen(file, "r")) == NULL) {
00186               fprintf(stderr, "%s: Cannot open: %s\n", progname, file);
00187               quit(1);
00188        }
00189        while (fgets(sbuf+1, sizeof(sbuf)-1, fp) != NULL) {
00190               inquote = 0;
00191               cp2 = sbuf;
00192               for (cp = sbuf+1; *cp; cp++)       /* condition the input line */
00193                      switch (*cp) {
00194                      case '#':
00195                             if (!inquote) {
00196                                    cp[0] = '\n';
00197                                    cp[1] = '\0';
00198                                    break;
00199                             }
00200                             *cp2++ = *cp;
00201                             break;
00202                      case '"':
00203                             inquote = !inquote;
00204                             break;
00205                      case '\\':
00206                             if (!cp[1])
00207                                    break;
00208                             if (cp[1] == '\n') {
00209                                    cp[0] = '\0';
00210                                    fgets(cp, sizeof(sbuf)-(cp-sbuf), fp);
00211                                    cp--;
00212                                    break;
00213                             }
00214                             *cp2++ = *++cp;
00215                             break;
00216                      case ' ':
00217                      case '\t':
00218                      case '\n':
00219                             if (!inquote)
00220                                    break;
00221                             *cp2++ = *cp;
00222                             break;
00223                      default:
00224                             *cp2++ = *cp;
00225                             break;
00226                      }
00227               *cp2 = '\0';
00228               if (inquote) {
00229                      fputs(sbuf, stderr);
00230                      fprintf(stderr, "%s: %s: Missing quote\n",
00231                                    progname, file);
00232                      quit(1);
00233               }
00234               if (sbuf[0])
00235                      setmgvar(file, fp, sbuf);
00236        }
00237        if (fp != stdin)
00238               fclose(fp);
00239 }
00240 
00241 
00242 void
00243 mgsave(                            /* save our variables */
00244 char  *file
00245 )
00246 {
00247        FILE  *fp;
00248        int  j;
00249        register IVAR  *iv;
00250        register int  i;
00251 
00252        if (file == NULL)
00253               fp = stdout;
00254        else if ((fp = fopen(file, "w")) == NULL) {
00255               fprintf(stderr, "%s: Cannot write: %s\n", progname, file);
00256               quit(1);
00257        }
00258        for (iv = ivhead; iv != NULL; iv = iv->next)
00259               fprintf(fp, "%s\n", iv->dfn);
00260 
00261        for (i = 0; i < NVARS; i++)
00262               if (gparam[i].flags & DEFINED)
00263                      mgprint(&gparam[i], fp);
00264        
00265        for (j = 0; j < MAXCUR; j++)
00266               for (i = 0; i < NCVARS; i++)
00267                      if (cparam[j][i].flags & DEFINED)
00268                             mgprint(&cparam[j][i], fp);
00269 
00270        if (fp != stdout)
00271               fclose(fp);
00272 }
00273 
00274 
00275 void
00276 setmgvar(            /* set a variable */
00277 char  *fname,
00278 FILE  *fp,
00279 char  *string
00280 )
00281 {
00282        char  name[128];
00283        FILE  *fp2;
00284        register int  i;
00285        register char  *s;
00286        register VARIABLE  *vp;
00287 
00288        if (!strncmp(string, "include=", 8)) {    /* include file */
00289               if ((s = findfile(string+8, libpath)) == NULL) {
00290                      fprintf(stderr, "%s\n", string);
00291                      fprintf(stderr, "%s: %s: File not found: %s\n",
00292                                    progname, fname, string+8);
00293                      quit(1);
00294               }
00295               strcpy(name, s);
00296               mgload(name);
00297               return;
00298        }
00299        s = string;
00300        i = 0;
00301        while (i < sizeof(name)-1 && isid(*s))
00302               name[i++] = *s++;
00303        name[i] = '\0';
00304        vp = vlookup(name);
00305        if (vp != NULL) {
00306               undefine(vp);
00307               switch (vp->type) {
00308               case REAL:
00309               case FUNCTION:
00310                      if ((*s == '(') != (vp->type == FUNCTION)) {
00311                             fprintf(stderr, "%s\n", string);
00312                             fprintf(stderr,
00313                                    "%s: %s: Bad %s declaration: %s\n",
00314                                    progname, fname,
00315                                    vp->type == FUNCTION ?
00316                                    "function" : "variable",
00317                                    name);
00318                             quit(1);
00319                      }
00320                      scompile(string, fname, 0);
00321                      vp->v.dfn = savestr(string);
00322                      break;
00323               case STRING:
00324                      if (*s++ != '=') {
00325                             fprintf(stderr, "%s\n", string);
00326                             fprintf(stderr, "%s: %s: Missing '='\n",
00327                                           progname, fname);
00328                             quit(1);
00329                      }
00330                      vp->v.s = savestr(s);
00331                      break;
00332               case DATA:
00333                      if (*s++ != '=') {
00334                             fprintf(stderr, "%s\n", string);
00335                             fprintf(stderr, "%s: %s: Missing '='\n",
00336                                           progname, fname);
00337                             quit(1);
00338                      }
00339                      if (!*s) {
00340                             loaddata(fname, fp, &vp->v.d);
00341                      } else if (*s == '!') {
00342                             if ((fp2 = popen(s+1, "r")) == NULL) {
00343                                    fprintf(stderr, "%s\n", string);
00344                                    fprintf(stderr,
00345                                    "%s: %s: Cannot execute: %s\n",
00346                                                  progname, fname, s+1);
00347                                    quit(1);
00348                             }
00349                             loaddata(s, fp2, &vp->v.d);
00350                             pclose(fp2);
00351                      } else {
00352                             if ((fp2 = fopen(s, "r")) == NULL) {
00353                                 fprintf(stderr, "%s\n", string);
00354                                 fprintf(stderr,
00355                                        "%s: %s: Data file not found: %s\n",
00356                                        progname, fname, s);
00357                                 quit(1);
00358                             }
00359                             loaddata(s, fp2, &vp->v.d);
00360                             fclose(fp2);
00361                      }
00362                      break;
00363               }
00364               vp->flags |= DEFINED;
00365        } else
00366               setivar(name, fname, string);             /* intermediate */
00367 }
00368 
00369 
00370 static void
00371 setivar(      /* set an intermediate variable */
00372 char  *vname,
00373 char  *fname,
00374 char  *definition
00375 )
00376 {
00377        IVAR  ivbeg;
00378        register IVAR  *iv;
00379 
00380        scompile(definition, fname, 0);           /* compile the string */
00381 
00382        ivbeg.next = ivhead;
00383        for (iv = &ivbeg; iv->next != NULL; iv = iv->next)
00384               if (!strcmp(vname, iv->next->name)) {
00385                      iv = iv->next;
00386                      freestr(iv->dfn);
00387                      iv->dfn = savestr(definition);
00388                      return;
00389               }
00390 
00391        iv->next = (IVAR *)emalloc(sizeof(IVAR));
00392        iv = iv->next;
00393        iv->name = savestr(vname);
00394        iv->dfn = savestr(definition);
00395        iv->next = NULL;
00396        ivhead = ivbeg.next;
00397 }
00398 
00399 
00400 void
00401 mgtoa(               /* get a variable's value in ascii form */
00402 register char  *s,
00403 VARIABLE  *vp
00404 )
00405 {
00406        register  char  *sv;
00407 
00408        if (!(vp->flags & DEFINED)) {
00409               strcpy(s, "UNDEFINED");
00410               return;
00411        }
00412        switch (vp->type) {
00413        case REAL:
00414        case FUNCTION:
00415               sv = vp->v.dfn;
00416               while (*sv != '=' && *sv != ':')
00417                      sv++;
00418               while (*++sv && *sv != ';')
00419                      *s++ = *sv;
00420               *s = '\0';
00421               break;
00422        case STRING:
00423               strcpy(s, vp->v.s);
00424               break;
00425        case DATA:
00426               strcpy(s, "DATA");
00427               break;
00428        }
00429 }
00430 
00431 
00432 static void
00433 mgprint(                    /* print a variable definition */
00434 register VARIABLE  *vp,
00435 FILE  *fp
00436 )
00437 {
00438        register int  i;
00439        
00440        switch (vp->type) {
00441        case REAL:
00442        case FUNCTION:
00443               fprintf(fp, "%s\n", vp->v.dfn);
00444               break;
00445        case STRING:
00446               fprintf(fp, "%s=\"", vp->name);
00447               for (i = 0; vp->v.s[i]; i++)
00448                      switch (vp->v.s[i]) {
00449                      case '"':
00450                      case '\\':
00451                             putc('\\', fp);
00452                      /* fall through */
00453                      default:
00454                             putc(vp->v.s[i], fp);
00455                             break;
00456                      }
00457               fprintf(fp, "\"\n");
00458               break;
00459        case DATA:
00460               fprintf(fp, "%s=", vp->name);
00461               for (i = 0; i < vp->v.d.size; i++) {
00462                      if (i % 4 == 0)
00463                             fprintf(fp, "\n");
00464                      fprintf(fp, "\t%10e", vp->v.d.data[i]);
00465               }
00466               fprintf(fp, "\n;\n");
00467               break;
00468        }
00469 }
00470 
00471 
00472 static void
00473 undefine(                   /* undefine a variable */
00474 register VARIABLE  *vp
00475 )
00476 {
00477        if (vp == NULL || !(vp->flags & DEFINED))
00478               return;
00479 
00480        switch (vp->type) {
00481        case REAL:
00482        case FUNCTION:
00483               dremove(vp->name);
00484               freestr(vp->v.dfn);
00485               break;
00486        case STRING:
00487               freestr(vp->v.s);
00488               break;
00489        case DATA:
00490               efree((char *)vp->v.d.data);
00491               break;
00492        }
00493        vp->flags &= ~DEFINED;
00494 }
00495 
00496 
00497 VARIABLE *
00498 vlookup(vname)                     /* look up a variable by its name */
00499 char  *vname;
00500 {
00501        register int  i;
00502        register VARIABLE  *vp;
00503 
00504        i = vname[0] - 'A';
00505        if (i >= 0 && i < MAXCUR)          /* curve variables */
00506               for (vp = cparam[i], i = 0; i < NCVARS; vp++, i++)
00507                      if (!strcmp(vp->name, vname))
00508                             return(vp);
00509                                           /* standard variables */
00510        for (vp = gparam; vp < &gparam[NVARS]; vp++)
00511               if (!strcmp(vp->name, vname))
00512                      return(vp);
00513        return(NULL);                      /* not found */
00514 }
00515 
00516 
00517 static void
00518 loaddata(                   /* load data from a stream */
00519 char  *fname,
00520 FILE  *fp,
00521 register DARRAY  *dp
00522 )
00523 {
00524        char  sbuf[MAXLINE], *fgets();
00525        register char  *cp;
00526 
00527        dp->size = 0;
00528        dp->data = NULL;
00529        while (fgets(sbuf, sizeof(sbuf), fp) != NULL) {
00530               cp = sbuf;
00531               while (*cp) {
00532                      while (isspace(*cp) || *cp == ',')
00533                             cp++;
00534                      if (isnum(*cp)) {
00535                             dp->data = (float *)erealloc((char *)dp->data,
00536                                           (dp->size+1)*sizeof(float));
00537                             dp->data[dp->size++] = atof(cp);
00538                             do
00539                                    cp++;
00540                             while (isnum(*cp));
00541                      } else if (*cp == ';') {
00542                             return;
00543                      } else if (*cp) {
00544                             fputs(sbuf, stderr);
00545                             fprintf(stderr, "%s: %s: Bad data\n",
00546                                           progname, fname);
00547                             quit(1);
00548                      }
00549               }
00550        }
00551 }
00552 
00553 
00554 static char *
00555 findfile(     /* find the file fname, return full path */
00556 char  *fname,
00557 register char  **pathlist
00558 )
00559 {
00560        static char  ffname[128];
00561        register int  fd;
00562 
00563        if (fname[0] == '/')
00564               return(fname);
00565 
00566        while (*pathlist != NULL) {
00567               strcpy(ffname, *pathlist);
00568               strcat(ffname, fname);
00569               if ((fd = open(ffname, 0)) != -1) {
00570                      close(fd);
00571                      return(ffname);
00572               }
00573               pathlist++;
00574        }
00575        return(NULL);
00576 }
00577 
00578 
00579 int
00580 mgcurve(                    /* get a curve's (unmapped) values */
00581        int  c,
00582        void (*f)(int c, double x, double y)
00583 )
00584 {
00585        int  nargs;
00586        double  x[2], step;
00587        register VARIABLE  *cv;
00588        register float  *p;
00589        register int npts = 0;
00590 
00591        if (c < 0 || c >= MAXCUR)
00592               return(-1);
00593        cv = cparam[c];
00594 
00595        if (cv[C].flags & DEFINED) {              /* function or map */
00596 
00597               nargs = fundefined(cv[C].name);
00598               if (nargs < 1 || nargs > 2) {
00599                      fprintf(stderr, "%s: bad # of arguments for '%c'\n",
00600                                    progname, c+'A');
00601                      quit(1);
00602               }
00603 
00604               if (cv[CDATA].flags & DEFINED) {          /* map */
00605                      npts = cv[CDATA].v.d.size / nargs;
00606                      p = cv[CDATA].v.d.data;
00607                      while (npts--) {
00608                             x[0] = *p++;
00609                             if (nargs == 2)
00610                                    x[1] = *p++;
00611                             (*f)(c, x[0],
00612                                    funvalue(cv[C].name, nargs, x));
00613                      }
00614                      npts = cv[CDATA].v.d.size / nargs;
00615               } else if ( nargs == 1 &&                 /* function */
00616                             gparam[XMIN].flags & DEFINED &&
00617                             gparam[XMAX].flags & DEFINED &&
00618                             cv[CNPOINTS].flags & DEFINED ) {
00619                      npts = varvalue(cv[CNPOINTS].name);
00620                      if (npts > 1)
00621                             step = (varvalue(gparam[XMAX].name) -
00622                                    varvalue(gparam[XMIN].name)) /
00623                                    (npts - 1);
00624                      else
00625                             step = 0.0;
00626                      for (x[0] = varvalue(gparam[XMIN].name);
00627                                    npts--; x[0] += step)
00628                             (*f)(c, x[0],
00629                                    funvalue(cv[C].name, 1, x));
00630                      npts = varvalue(cv[CNPOINTS].name);
00631               } else {
00632                      fprintf(stderr,
00633                      "%s: function '%c' needs %cdata or xmin, xmax, %cnpoints\n",
00634                                    progname, c+'A', c+'A', c+'A');
00635                      quit(1);
00636               }
00637 
00638        } else if (cv[CDATA].flags & DEFINED) {   /* data */
00639 
00640               npts = cv[CDATA].v.d.size / 2;
00641               p = cv[CDATA].v.d.data;
00642               while (npts--) {
00643                      (*f)(c, p[0], p[1]);
00644                      p += 2;
00645               }
00646               npts = cv[CDATA].v.d.size / 2;
00647 
00648        } else
00649 
00650               npts = 0;
00651 
00652        return(npts);
00653 }