ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/meta/mgvars.c
Revision: 1.6
Committed: Sun Mar 28 20:33:13 2004 UTC (20 years ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, rad5R2, rad4R2P2, rad5R0, rad5R1, rad3R7P2, rad3R7P1, rad4R2, rad4R1, rad4R0, rad3R6, rad3R6P1, rad3R8, rad3R9, rad4R2P1, rad5R3, HEAD
Changes since 1.5: +2 -1 lines
Log Message:
Continued ANSIfication, and other fixes and clarifications.

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: mgvars.c,v 1.5 2003/11/15 02:13:37 schorsch Exp $";
3 #endif
4 /*
5 * mgvars.c - routines dealing with graph variables.
6 *
7 * 6/23/86
8 *
9 * Greg Ward Larson
10 */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <math.h>
15 #include <string.h>
16 #include <ctype.h>
17
18 #include "rtprocess.h"
19 #include "rtmisc.h"
20 #include "rterror.h"
21 #include "rtio.h"
22 #include "calcomp.h"
23 #include "mgvars.h"
24
25 #define MAXLINE 512
26
27 #define isnum(c) (isdigit(c)||(c)=='-'||(c)=='+'||(c)=='.'||(c)=='e'||(c)=='E')
28
29 static void mgprint(register VARIABLE *vp, FILE *fp);
30 static void setivar(char *vname, char *fname, char *definition);
31 static char *findfile(char *fname, register char **pathlist);
32 static void loaddata(char *fname, FILE *fp, register DARRAY *dp);
33 static void undefine(register VARIABLE *vp);
34
35 extern char *progname, *libpath[];
36
37 IVAR *ivhead = NULL; /* intermediate variables */
38
39 VARIABLE gparam[NVARS] = { /* standard variables */
40 { "fthick", REAL, "frame thickness" },
41 { "grid", REAL, "grid on?" },
42 { "legend", STRING, "legend title" },
43 { "othick", REAL, "origin thickness" },
44 { "period", REAL, "period of polar plot" },
45 { "subtitle", STRING },
46 { "symfile", STRING, "symbol file" },
47 { "tstyle", REAL, "tick mark style" },
48 { "title", STRING },
49 { "xlabel", STRING },
50 { "xmap", FUNCTION, "x axis mapping function" },
51 { "xmax", REAL },
52 { "xmin", REAL },
53 { "xstep", REAL },
54 { "ylabel", STRING },
55 { "ymap", FUNCTION, "y axis mapping function" },
56 { "ymax", REAL },
57 { "ymin", REAL },
58 { "ystep", REAL },
59 };
60
61 VARIABLE cparam[MAXCUR][NCVARS] = { /* curve variables */
62 {
63 { "A", FUNCTION, "function for curve A" },
64 { "Acolor", REAL, "color for A" },
65 { "Adata", DATA, "point data for A" },
66 { "Alabel", STRING },
67 { "Alintype", REAL, "line type for A" },
68 { "Anpoints", REAL, "number of points for A" },
69 { "Asymsize", REAL, "symbol size for A" },
70 { "Asymtype", STRING, "symbol type for A" },
71 { "Athick", REAL, "line thickness for A" },
72 }, {
73 { "B", FUNCTION, "function for curve B" },
74 { "Bcolor", REAL, "color for B" },
75 { "Bdata", DATA, "point data for B" },
76 { "Blabel", STRING },
77 { "Blintype", REAL, "line type for B" },
78 { "Bnpoints", REAL, "number of points for B" },
79 { "Bsymsize", REAL, "symbol size for B" },
80 { "Bsymtype", STRING, "symbol type for B" },
81 { "Bthick", REAL, "line thickness for B" },
82 }, {
83 { "C", FUNCTION, "function for curve C" },
84 { "Ccolor", REAL, "color for C" },
85 { "Cdata", DATA, "point data for C" },
86 { "Clabel", STRING },
87 { "Clintype", REAL, "line type for C" },
88 { "Cnpoints", REAL, "number of points for C" },
89 { "Csymsize", REAL, "symbol size for C" },
90 { "Csymtype", STRING, "symbol type for C" },
91 { "Cthick", REAL, "line thickness for C" },
92 }, {
93 { "D", FUNCTION, "function for curve D" },
94 { "Dcolor", REAL, "color for D" },
95 { "Ddata", DATA, "point data for D" },
96 { "Dlabel", STRING },
97 { "Dlintype", REAL, "line type for D" },
98 { "Dnpoints", REAL, "number of points for D" },
99 { "Dsymsize", REAL, "symbol size for D" },
100 { "Dsymtype", STRING, "symbol type for D" },
101 { "Dthick", REAL, "line thickness for D" },
102 }, {
103 { "E", FUNCTION, "function for curve E" },
104 { "Ecolor", REAL, "color for E" },
105 { "Edata", DATA, "point data for E" },
106 { "Elabel", STRING },
107 { "Elintype", REAL, "line type for E" },
108 { "Enpoints", REAL, "number of points for E" },
109 { "Esymsize", REAL, "symbol size for E" },
110 { "Esymtype", STRING, "symbol type for E" },
111 { "Ethick", REAL, "line thickness for E" },
112 }, {
113 { "F", FUNCTION, "function for curve F" },
114 { "Fcolor", REAL, "color for F" },
115 { "Fdata", DATA, "point data for F" },
116 { "Flabel", STRING },
117 { "Flintype", REAL, "line type for F" },
118 { "Fnpoints", REAL, "number of points for F" },
119 { "Fsymsize", REAL, "symbol size for F" },
120 { "Fsymtype", STRING, "symbol type for F" },
121 { "Fthick", REAL, "line thickness for F" },
122 }, {
123 { "G", FUNCTION, "function for curve G" },
124 { "Gcolor", REAL, "color for G" },
125 { "Gdata", DATA, "point data for G" },
126 { "Glabel", STRING },
127 { "Glintype", REAL, "line type for G" },
128 { "Gnpoints", REAL, "number of points for G" },
129 { "Gsymsize", REAL, "symbol size for G" },
130 { "Gsymtype", STRING, "symbol type for G" },
131 { "Gthick", REAL, "line thickness for G" },
132 }, {
133 { "H", FUNCTION, "function for curve H" },
134 { "Hcolor", REAL, "color for H" },
135 { "Hdata", DATA, "point data for H" },
136 { "Hlabel", STRING },
137 { "Hlintype", REAL, "line type for H" },
138 { "Hnpoints", REAL, "number of points for H" },
139 { "Hsymsize", REAL, "symbol size for H" },
140 { "Hsymtype", STRING, "symbol type for H" },
141 { "Hthick", REAL, "line thickness for H" },
142 },
143 };
144
145
146 void
147 mgclearall(void) /* clear all variable settings */
148 {
149 int j;
150 register IVAR *iv;
151 register int i;
152
153 for (iv = ivhead; iv != NULL; iv = iv->next) {
154 dremove(iv->name);
155 freestr(iv->name);
156 freestr(iv->dfn);
157 efree((char *)iv);
158 }
159 ivhead = NULL;
160
161 for (i = 0; i < NVARS; i++)
162 if (gparam[i].flags & DEFINED)
163 undefine(&gparam[i]);
164
165 for (j = 0; j < MAXCUR; j++)
166 for (i = 0; i < NCVARS; i++)
167 if (cparam[j][i].flags & DEFINED)
168 undefine(&cparam[j][i]);
169 }
170
171
172 void
173 mgload( /* load a file */
174 char *file
175 )
176 {
177 FILE *fp;
178 char sbuf[MAXLINE], *fgets();
179 int inquote;
180 register char *cp, *cp2;
181
182 if (file == NULL) {
183 fp = stdin;
184 file = "<stdin>";
185 } else if ((fp = fopen(file, "r")) == NULL) {
186 fprintf(stderr, "%s: Cannot open: %s\n", progname, file);
187 quit(1);
188 }
189 while (fgets(sbuf+1, sizeof(sbuf)-1, fp) != NULL) {
190 inquote = 0;
191 cp2 = sbuf;
192 for (cp = sbuf+1; *cp; cp++) /* condition the input line */
193 switch (*cp) {
194 case '#':
195 if (!inquote) {
196 cp[0] = '\n';
197 cp[1] = '\0';
198 break;
199 }
200 *cp2++ = *cp;
201 break;
202 case '"':
203 inquote = !inquote;
204 break;
205 case '\\':
206 if (!cp[1])
207 break;
208 if (cp[1] == '\n') {
209 cp[0] = '\0';
210 fgets(cp, sizeof(sbuf)-(cp-sbuf), fp);
211 cp--;
212 break;
213 }
214 *cp2++ = *++cp;
215 break;
216 case ' ':
217 case '\t':
218 case '\n':
219 if (!inquote)
220 break;
221 *cp2++ = *cp;
222 break;
223 default:
224 *cp2++ = *cp;
225 break;
226 }
227 *cp2 = '\0';
228 if (inquote) {
229 fputs(sbuf, stderr);
230 fprintf(stderr, "%s: %s: Missing quote\n",
231 progname, file);
232 quit(1);
233 }
234 if (sbuf[0])
235 setmgvar(file, fp, sbuf);
236 }
237 if (fp != stdin)
238 fclose(fp);
239 }
240
241
242 void
243 mgsave( /* save our variables */
244 char *file
245 )
246 {
247 FILE *fp;
248 int j;
249 register IVAR *iv;
250 register int i;
251
252 if (file == NULL)
253 fp = stdout;
254 else if ((fp = fopen(file, "w")) == NULL) {
255 fprintf(stderr, "%s: Cannot write: %s\n", progname, file);
256 quit(1);
257 }
258 for (iv = ivhead; iv != NULL; iv = iv->next)
259 fprintf(fp, "%s\n", iv->dfn);
260
261 for (i = 0; i < NVARS; i++)
262 if (gparam[i].flags & DEFINED)
263 mgprint(&gparam[i], fp);
264
265 for (j = 0; j < MAXCUR; j++)
266 for (i = 0; i < NCVARS; i++)
267 if (cparam[j][i].flags & DEFINED)
268 mgprint(&cparam[j][i], fp);
269
270 if (fp != stdout)
271 fclose(fp);
272 }
273
274
275 void
276 setmgvar( /* set a variable */
277 char *fname,
278 FILE *fp,
279 char *string
280 )
281 {
282 char name[128];
283 FILE *fp2;
284 register int i;
285 register char *s;
286 register VARIABLE *vp;
287
288 if (!strncmp(string, "include=", 8)) { /* include file */
289 if ((s = findfile(string+8, libpath)) == NULL) {
290 fprintf(stderr, "%s\n", string);
291 fprintf(stderr, "%s: %s: File not found: %s\n",
292 progname, fname, string+8);
293 quit(1);
294 }
295 strcpy(name, s);
296 mgload(name);
297 return;
298 }
299 s = string;
300 i = 0;
301 while (i < sizeof(name)-1 && isid(*s))
302 name[i++] = *s++;
303 name[i] = '\0';
304 vp = vlookup(name);
305 if (vp != NULL) {
306 undefine(vp);
307 switch (vp->type) {
308 case REAL:
309 case FUNCTION:
310 if ((*s == '(') != (vp->type == FUNCTION)) {
311 fprintf(stderr, "%s\n", string);
312 fprintf(stderr,
313 "%s: %s: Bad %s declaration: %s\n",
314 progname, fname,
315 vp->type == FUNCTION ?
316 "function" : "variable",
317 name);
318 quit(1);
319 }
320 scompile(string, fname, 0);
321 vp->v.dfn = savestr(string);
322 break;
323 case STRING:
324 if (*s++ != '=') {
325 fprintf(stderr, "%s\n", string);
326 fprintf(stderr, "%s: %s: Missing '='\n",
327 progname, fname);
328 quit(1);
329 }
330 vp->v.s = savestr(s);
331 break;
332 case DATA:
333 if (*s++ != '=') {
334 fprintf(stderr, "%s\n", string);
335 fprintf(stderr, "%s: %s: Missing '='\n",
336 progname, fname);
337 quit(1);
338 }
339 if (!*s) {
340 loaddata(fname, fp, &vp->v.d);
341 } else if (*s == '!') {
342 if ((fp2 = popen(s+1, "r")) == NULL) {
343 fprintf(stderr, "%s\n", string);
344 fprintf(stderr,
345 "%s: %s: Cannot execute: %s\n",
346 progname, fname, s+1);
347 quit(1);
348 }
349 loaddata(s, fp2, &vp->v.d);
350 pclose(fp2);
351 } else {
352 if ((fp2 = fopen(s, "r")) == NULL) {
353 fprintf(stderr, "%s\n", string);
354 fprintf(stderr,
355 "%s: %s: Data file not found: %s\n",
356 progname, fname, s);
357 quit(1);
358 }
359 loaddata(s, fp2, &vp->v.d);
360 fclose(fp2);
361 }
362 break;
363 }
364 vp->flags |= DEFINED;
365 } else
366 setivar(name, fname, string); /* intermediate */
367 }
368
369
370 static void
371 setivar( /* set an intermediate variable */
372 char *vname,
373 char *fname,
374 char *definition
375 )
376 {
377 IVAR ivbeg;
378 register IVAR *iv;
379
380 scompile(definition, fname, 0); /* compile the string */
381
382 ivbeg.next = ivhead;
383 for (iv = &ivbeg; iv->next != NULL; iv = iv->next)
384 if (!strcmp(vname, iv->next->name)) {
385 iv = iv->next;
386 freestr(iv->dfn);
387 iv->dfn = savestr(definition);
388 return;
389 }
390
391 iv->next = (IVAR *)emalloc(sizeof(IVAR));
392 iv = iv->next;
393 iv->name = savestr(vname);
394 iv->dfn = savestr(definition);
395 iv->next = NULL;
396 ivhead = ivbeg.next;
397 }
398
399
400 void
401 mgtoa( /* get a variable's value in ascii form */
402 register char *s,
403 VARIABLE *vp
404 )
405 {
406 register char *sv;
407
408 if (!(vp->flags & DEFINED)) {
409 strcpy(s, "UNDEFINED");
410 return;
411 }
412 switch (vp->type) {
413 case REAL:
414 case FUNCTION:
415 sv = vp->v.dfn;
416 while (*sv != '=' && *sv != ':')
417 sv++;
418 while (*++sv && *sv != ';')
419 *s++ = *sv;
420 *s = '\0';
421 break;
422 case STRING:
423 strcpy(s, vp->v.s);
424 break;
425 case DATA:
426 strcpy(s, "DATA");
427 break;
428 }
429 }
430
431
432 static void
433 mgprint( /* print a variable definition */
434 register VARIABLE *vp,
435 FILE *fp
436 )
437 {
438 register int i;
439
440 switch (vp->type) {
441 case REAL:
442 case FUNCTION:
443 fprintf(fp, "%s\n", vp->v.dfn);
444 break;
445 case STRING:
446 fprintf(fp, "%s=\"", vp->name);
447 for (i = 0; vp->v.s[i]; i++)
448 switch (vp->v.s[i]) {
449 case '"':
450 case '\\':
451 putc('\\', fp);
452 /* fall through */
453 default:
454 putc(vp->v.s[i], fp);
455 break;
456 }
457 fprintf(fp, "\"\n");
458 break;
459 case DATA:
460 fprintf(fp, "%s=", vp->name);
461 for (i = 0; i < vp->v.d.size; i++) {
462 if (i % 4 == 0)
463 fprintf(fp, "\n");
464 fprintf(fp, "\t%10e", vp->v.d.data[i]);
465 }
466 fprintf(fp, "\n;\n");
467 break;
468 }
469 }
470
471
472 static void
473 undefine( /* undefine a variable */
474 register VARIABLE *vp
475 )
476 {
477 if (vp == NULL || !(vp->flags & DEFINED))
478 return;
479
480 switch (vp->type) {
481 case REAL:
482 case FUNCTION:
483 dremove(vp->name);
484 freestr(vp->v.dfn);
485 break;
486 case STRING:
487 freestr(vp->v.s);
488 break;
489 case DATA:
490 efree((char *)vp->v.d.data);
491 break;
492 }
493 vp->flags &= ~DEFINED;
494 }
495
496
497 VARIABLE *
498 vlookup(vname) /* look up a variable by its name */
499 char *vname;
500 {
501 register int i;
502 register VARIABLE *vp;
503
504 i = vname[0] - 'A';
505 if (i >= 0 && i < MAXCUR) /* curve variables */
506 for (vp = cparam[i], i = 0; i < NCVARS; vp++, i++)
507 if (!strcmp(vp->name, vname))
508 return(vp);
509 /* standard variables */
510 for (vp = gparam; vp < &gparam[NVARS]; vp++)
511 if (!strcmp(vp->name, vname))
512 return(vp);
513 return(NULL); /* not found */
514 }
515
516
517 static void
518 loaddata( /* load data from a stream */
519 char *fname,
520 FILE *fp,
521 register DARRAY *dp
522 )
523 {
524 char sbuf[MAXLINE], *fgets();
525 register char *cp;
526
527 dp->size = 0;
528 dp->data = NULL;
529 while (fgets(sbuf, sizeof(sbuf), fp) != NULL) {
530 cp = sbuf;
531 while (*cp) {
532 while (isspace(*cp) || *cp == ',')
533 cp++;
534 if (isnum(*cp)) {
535 dp->data = (float *)erealloc((char *)dp->data,
536 (dp->size+1)*sizeof(float));
537 dp->data[dp->size++] = atof(cp);
538 do
539 cp++;
540 while (isnum(*cp));
541 } else if (*cp == ';') {
542 return;
543 } else if (*cp) {
544 fputs(sbuf, stderr);
545 fprintf(stderr, "%s: %s: Bad data\n",
546 progname, fname);
547 quit(1);
548 }
549 }
550 }
551 }
552
553
554 static char *
555 findfile( /* find the file fname, return full path */
556 char *fname,
557 register char **pathlist
558 )
559 {
560 static char ffname[128];
561 register int fd;
562
563 if (fname[0] == '/')
564 return(fname);
565
566 while (*pathlist != NULL) {
567 strcpy(ffname, *pathlist);
568 strcat(ffname, fname);
569 if ((fd = open(ffname, 0)) != -1) {
570 close(fd);
571 return(ffname);
572 }
573 pathlist++;
574 }
575 return(NULL);
576 }
577
578
579 int
580 mgcurve( /* get a curve's (unmapped) values */
581 int c,
582 void (*f)(int c, double x, double y)
583 )
584 {
585 int nargs;
586 double x[2], step;
587 register VARIABLE *cv;
588 register float *p;
589 register int npts = 0;
590
591 if (c < 0 || c >= MAXCUR)
592 return(-1);
593 cv = cparam[c];
594
595 if (cv[C].flags & DEFINED) { /* function or map */
596
597 nargs = fundefined(cv[C].name);
598 if (nargs < 1 || nargs > 2) {
599 fprintf(stderr, "%s: bad # of arguments for '%c'\n",
600 progname, c+'A');
601 quit(1);
602 }
603
604 if (cv[CDATA].flags & DEFINED) { /* map */
605 npts = cv[CDATA].v.d.size / nargs;
606 p = cv[CDATA].v.d.data;
607 while (npts--) {
608 x[0] = *p++;
609 if (nargs == 2)
610 x[1] = *p++;
611 (*f)(c, x[0],
612 funvalue(cv[C].name, nargs, x));
613 }
614 npts = cv[CDATA].v.d.size / nargs;
615 } else if ( nargs == 1 && /* function */
616 gparam[XMIN].flags & DEFINED &&
617 gparam[XMAX].flags & DEFINED &&
618 cv[CNPOINTS].flags & DEFINED ) {
619 npts = varvalue(cv[CNPOINTS].name);
620 if (npts > 1)
621 step = (varvalue(gparam[XMAX].name) -
622 varvalue(gparam[XMIN].name)) /
623 (npts - 1);
624 else
625 step = 0.0;
626 for (x[0] = varvalue(gparam[XMIN].name);
627 npts--; x[0] += step)
628 (*f)(c, x[0],
629 funvalue(cv[C].name, 1, x));
630 npts = varvalue(cv[CNPOINTS].name);
631 } else {
632 fprintf(stderr,
633 "%s: function '%c' needs %cdata or xmin, xmax, %cnpoints\n",
634 progname, c+'A', c+'A', c+'A');
635 quit(1);
636 }
637
638 } else if (cv[CDATA].flags & DEFINED) { /* data */
639
640 npts = cv[CDATA].v.d.size / 2;
641 p = cv[CDATA].v.d.data;
642 while (npts--) {
643 (*f)(c, p[0], p[1]);
644 p += 2;
645 }
646 npts = cv[CDATA].v.d.size / 2;
647
648 } else
649
650 npts = 0;
651
652 return(npts);
653 }