ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rcalc.c
Revision: 1.1
Committed: Sat Feb 22 02:07:20 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2     static const char RCSid[] = "$Id$";
3     #endif
4     /*
5     * rcalc.c - record calculator program.
6     *
7     * 9/11/87
8     */
9    
10     #include <stdio.h>
11    
12     #include <stdlib.h>
13    
14     #include <math.h>
15    
16     #include <ctype.h>
17    
18     #include "calcomp.h"
19    
20     #ifdef CPM
21     #define getc agetc /* text files only, right? */
22     #endif
23    
24     #define isnum(c) (isdigit(c) || (c)=='-' || (c)=='.' \
25     || (c)=='+' || (c)=='e' || (c)=='E')
26    
27     #define isblnk(c) (igneol ? isspace(c) : (c)==' '||(c)=='\t')
28    
29     #define INBSIZ 4096 /* longest record */
30     #define MAXCOL 32 /* number of columns recorded */
31    
32     /* field type specifications */
33     #define F_NUL 0 /* empty */
34     #define F_TYP 0x7000 /* mask for type */
35     #define F_WID 0x0fff /* mask for width */
36     #define T_LIT 0x1000 /* string literal */
37     #define T_STR 0x2000 /* string variable */
38     #define T_NUM 0x3000 /* numeric value */
39    
40     struct strvar { /* string variable */
41     char *name;
42     char *val;
43     char *preset;
44     struct strvar *next;
45     };
46    
47     struct field { /* record format structure */
48     int type; /* type of field (& width) */
49     union {
50     char *sl; /* string literal */
51     struct strvar *sv; /* string variable */
52     char *nv; /* numeric variable */
53     EPNODE *ne; /* numeric expression */
54     } f; /* field contents */
55     struct field *next; /* next field in record */
56     };
57    
58     #define savqstr(s) strcpy(emalloc(strlen(s)+1),s)
59     #define freqstr(s) efree(s)
60    
61     extern char *strcpy(), *emalloc(), *savestr();
62     struct strvar *getsvar();
63    
64     struct field *inpfmt = NULL; /* input record format */
65     struct field *outfmt = NULL; /* output record structure */
66     struct strvar *svhead = NULL; /* string variables */
67    
68     int blnkeq = 1; /* blanks compare equal? */
69     int igneol = 0; /* ignore end of line? */
70     char sepchar = '\t'; /* input/output separator */
71     int noinput = 0; /* no input records? */
72     char inpbuf[INBSIZ]; /* input buffer */
73     double colval[MAXCOL]; /* input column values */
74     unsigned long colflg = 0; /* column retrieved flags */
75     int colpos; /* output column position */
76    
77     int nowarn = 0; /* non-fatal diagnostic output */
78     int unbuff = 0; /* unbuffered output (flush each record) */
79    
80     struct {
81     FILE *fin; /* input file */
82     int chr; /* next character */
83     char *beg; /* home position */
84     char *pos; /* scan position */
85     char *end; /* read position */
86     } ipb; /* circular lookahead buffer */
87    
88    
89     main(argc, argv)
90     int argc;
91     char *argv[];
92     {
93     int i;
94    
95     esupport |= (E_VARIABLE|E_FUNCTION|E_INCHAN|E_OUTCHAN|E_RCONST);
96    
97     #ifdef BIGGERLIB
98     biggerlib();
99     #endif
100     varset("PI", ':', 3.14159265358979323846);
101    
102     for (i = 1; i < argc && argv[i][0] == '-'; i++)
103     switch (argv[i][1]) {
104     case 'b':
105     blnkeq = !blnkeq;
106     break;
107     case 'l':
108     igneol = !igneol;
109     break;
110     case 't':
111     sepchar = argv[i][2];
112     break;
113     case 's':
114     svpreset(argv[++i]);
115     break;
116     case 'f':
117     fcompile(argv[++i]);
118     break;
119     case 'e':
120     scompile(argv[++i], NULL, 0);
121     break;
122     case 'n':
123     noinput = 1;
124     break;
125     case 'i':
126     readfmt(argv[++i], 0);
127     break;
128     case 'o':
129     readfmt(argv[++i], 1);
130     break;
131     case 'w':
132     nowarn = !nowarn;
133     break;
134     case 'u':
135     unbuff = !unbuff;
136     break;
137     default:
138     eputs("Usage: ");
139     eputs(argv[0]);
140     eputs(" [-b][-l][-n][-w][-u][-tS][-s svar=sval][-e expr][-f source][-i infmt][-o outfmt] [file]\n");
141     quit(1);
142     }
143    
144     if (noinput) { /* produce a single output record */
145     eclock++;
146     putout();
147     quit(0);
148     }
149    
150     if (blnkeq) /* for efficiency */
151     nbsynch();
152    
153     if (i == argc) /* from stdin */
154     execute(NULL);
155     else /* from one or more files */
156     for ( ; i < argc; i++)
157     execute(argv[i]);
158    
159     quit(0);
160     }
161    
162    
163     nbsynch() /* non-blank starting synch character */
164     {
165     if (inpfmt == NULL || (inpfmt->type & F_TYP) != T_LIT)
166     return;
167     while (isblnk(*inpfmt->f.sl))
168     inpfmt->f.sl++;
169     if (!*inpfmt->f.sl)
170     inpfmt = inpfmt->next;
171     }
172    
173    
174     execute(file) /* process a file */
175     char *file;
176     {
177     int conditional = vardefined("cond");
178     long nrecs = 0;
179     long nout = 0;
180     FILE *fp;
181    
182     if (file == NULL)
183     fp = stdin;
184     else if ((fp = fopen(file, "r")) == NULL) {
185     eputs(file);
186     eputs(": cannot open\n");
187     quit(1);
188     }
189     if (inpfmt != NULL)
190     initinp(fp);
191    
192     while (inpfmt != NULL ? getrec() : fgets(inpbuf, INBSIZ, fp) != NULL) {
193     varset("recno", '=', (double)++nrecs);
194     colflg = 0;
195     eclock++;
196     if (!conditional || varvalue("cond") > 0.0) {
197     varset("outno", '=', (double)++nout);
198     putout();
199     }
200     }
201     fclose(fp);
202     }
203    
204    
205     putout() /* produce an output record */
206     {
207     extern int chanset();
208    
209     colpos = 0;
210     if (outfmt != NULL)
211     putrec();
212     else
213     chanout(chanset);
214     if (colpos)
215     putchar('\n');
216     if (unbuff)
217     fflush(stdout);
218     }
219    
220    
221     double
222     chanvalue(n) /* return value for column n */
223     int n;
224     {
225     int i;
226     register char *cp;
227    
228     if (noinput || inpfmt != NULL) {
229     eputs("no column input\n");
230     quit(1);
231     }
232     if (n < 1) {
233     eputs("illegal channel number\n");
234     quit(1);
235     }
236     if (n <= MAXCOL && colflg & 1L<<(n-1))
237     return(colval[n-1]);
238    
239     cp = inpbuf;
240     for (i = 1; i < n; i++)
241     if (blnkeq && isspace(sepchar)) {
242     while (isspace(*cp))
243     cp++;
244     while (*cp && !isspace(*cp))
245     cp++;
246     } else
247     while (*cp && *cp++ != sepchar)
248     ;
249    
250     while (isspace(*cp)) /* some atof()'s don't like tabs */
251     cp++;
252    
253     if (n <= MAXCOL) {
254     colflg |= 1L<<(n-1);
255     return(colval[n-1] = atof(cp));
256     } else
257     return(atof(cp));
258     }
259    
260    
261     chanset(n, v) /* output column n */
262     int n;
263     double v;
264     {
265     if (colpos == 0) /* no leading separator */
266     colpos = 1;
267     while (colpos < n) {
268     putchar(sepchar);
269     colpos++;
270     }
271     printf("%.9g", v);
272     }
273    
274    
275     readfmt(spec, output) /* read record format */
276     char *spec;
277     int output;
278     {
279     int fd;
280     char *inptr;
281     struct field fmt;
282     int res;
283     register struct field *f;
284     /* check for inline format */
285     for (inptr = spec; *inptr; inptr++)
286     if (*inptr == '$')
287     break;
288     if (*inptr) /* inline */
289     inptr = spec;
290     else { /* from file */
291     if ((fd = open(spec, 0)) == -1) {
292     eputs(spec);
293     eputs(": cannot open\n");
294     quit(1);
295     }
296     res = read(fd, inpbuf+1, INBSIZ-1);
297     if (res <= 0 || res >= INBSIZ-1) {
298     eputs(spec);
299     if (res < 0)
300     eputs(": read error\n");
301     else if (res == 0)
302     eputs(": empty file\n");
303     else if (res >= INBSIZ-1)
304     eputs(": format too long\n");
305     quit(1);
306     }
307     close(fd);
308     (inptr=inpbuf+1)[res] = '\0';
309     }
310     f = &fmt; /* get fields */
311     while ((res = readfield(&inptr)) != F_NUL) {
312     f->next = (struct field *)emalloc(sizeof(struct field));
313     f = f->next;
314     f->type = res;
315     switch (res & F_TYP) {
316     case T_LIT:
317     f->f.sl = savqstr(inpbuf);
318     break;
319     case T_STR:
320     f->f.sv = getsvar(inpbuf);
321     break;
322     case T_NUM:
323     if (output)
324     f->f.ne = eparse(inpbuf);
325     else
326     f->f.nv = savestr(inpbuf);
327     break;
328     }
329     /* add final newline if necessary */
330     if (!igneol && *inptr == '\0' && inptr[-1] != '\n')
331     inptr = "\n";
332     }
333     f->next = NULL;
334     if (output)
335     outfmt = fmt.next;
336     else
337     inpfmt = fmt.next;
338     }
339    
340    
341     int
342     readfield(pp) /* get next field in format */
343     register char **pp;
344     {
345     int type = F_NUL;
346     int width = 0;
347     register char *cp;
348    
349     cp = inpbuf;
350     while (cp < &inpbuf[INBSIZ-1] && **pp != '\0') {
351     width++;
352     switch (type) {
353     case F_NUL:
354     if (**pp == '$') {
355     (*pp)++;
356     width++;
357     if (**pp == '{') {
358     type = T_NUM;
359     (*pp)++;
360     continue;
361     } else if (**pp == '(') {
362     type = T_STR;
363     (*pp)++;
364     continue;
365     } else if (**pp != '$') {
366     eputs("format error\n");
367     quit(1);
368     }
369     width--;
370     }
371     type = T_LIT;
372     *cp++ = *(*pp)++;
373     continue;
374     case T_LIT:
375     if (**pp == '$') {
376     width--;
377     break;
378     }
379     *cp++ = *(*pp)++;
380     continue;
381     case T_NUM:
382     if (**pp == '}') {
383     (*pp)++;
384     break;
385     }
386     if (!isspace(**pp))
387     *cp++ = **pp;
388     (*pp)++;
389     continue;
390     case T_STR:
391     if (**pp == ')') {
392     (*pp)++;
393     break;
394     }
395     if (!isspace(**pp))
396     *cp++ = **pp;
397     (*pp)++;
398     continue;
399     }
400     break;
401     }
402     *cp = '\0';
403     return(type | width);
404     }
405    
406    
407     struct strvar *
408     getsvar(svname) /* get string variable */
409     char *svname;
410     {
411     register struct strvar *sv;
412    
413     for (sv = svhead; sv != NULL; sv = sv->next)
414     if (!strcmp(sv->name, svname))
415     return(sv);
416     sv = (struct strvar *)emalloc(sizeof(struct strvar));
417     sv->name = savqstr(svname);
418     sv->val = sv->preset = NULL;
419     sv->next = svhead;
420     svhead = sv;
421     return(sv);
422     }
423    
424    
425     svpreset(eqn) /* preset a string variable */
426     char *eqn;
427     {
428     register struct strvar *sv;
429     register char *val;
430    
431     for (val = eqn; *val != '='; val++)
432     if (!*val)
433     return;
434     *val++ = '\0';
435     sv = getsvar(eqn);
436     if (sv->preset != NULL)
437     freqstr(sv->preset);
438     if (sv->val != NULL)
439     freqstr(sv->val);
440     sv->val = sv->preset = savqstr(val);
441     *--val = '=';
442     }
443    
444    
445     clearrec() /* clear input record variables */
446     {
447     register struct field *f;
448    
449     for (f = inpfmt; f != NULL; f = f->next)
450     switch (f->type & F_TYP) {
451     case T_NUM:
452     dremove(f->f.nv);
453     break;
454     case T_STR:
455     if (f->f.sv->val != f->f.sv->preset) {
456     freqstr(f->f.sv->val);
457     f->f.sv->val = f->f.sv->preset;
458     }
459     break;
460     }
461     }
462    
463    
464     getrec() /* get next record from file */
465     {
466     int eatline;
467     register struct field *f;
468    
469     while (ipb.chr != EOF) {
470     eatline = !igneol && ipb.chr != '\n';
471     if (blnkeq) /* beware of nbsynch() */
472     while (isblnk(ipb.chr))
473     scaninp();
474     clearrec(); /* start with fresh record */
475     for (f = inpfmt; f != NULL; f = f->next)
476     if (getfield(f) == -1)
477     break;
478     if (f == NULL) {
479     advinp();
480     return(1);
481     }
482     resetinp();
483     if (eatline) { /* eat rest of line */
484     while (ipb.chr != '\n') {
485     if (ipb.chr == EOF)
486     return(0);
487     scaninp();
488     }
489     scaninp();
490     advinp();
491     }
492     }
493     return(0);
494     }
495    
496    
497     getfield(f) /* get next field */
498     register struct field *f;
499     {
500     static char buf[MAXWORD+1]; /* no recursion! */
501     int delim, inword;
502     double d;
503     char *np;
504     register char *cp;
505    
506     switch (f->type & F_TYP) {
507     case T_LIT:
508     cp = f->f.sl;
509     do {
510     if (blnkeq && isblnk(*cp)) {
511     if (!isblnk(ipb.chr))
512     return(-1);
513     do
514     cp++;
515     while (isblnk(*cp));
516     do
517     scaninp();
518     while (isblnk(ipb.chr));
519     } else if (*cp == ipb.chr) {
520     cp++;
521     scaninp();
522     } else
523     return(-1);
524     } while (*cp);
525     return(0);
526     case T_STR:
527     if (f->next == NULL || (f->next->type & F_TYP) != T_LIT)
528     delim = EOF;
529     else
530     delim = f->next->f.sl[0];
531     cp = buf;
532     do {
533     if (ipb.chr == EOF)
534     inword = 0;
535     else if (blnkeq && delim != EOF)
536     inword = isblnk(delim) ?
537     !isblnk(ipb.chr)
538     : ipb.chr != delim;
539     else
540     inword = cp-buf < (f->type & F_WID);
541     if (inword) {
542     *cp++ = ipb.chr;
543     scaninp();
544     }
545     } while (inword && cp < &buf[MAXWORD]);
546     *cp = '\0';
547     if (f->f.sv->val == NULL)
548     f->f.sv->val = savqstr(buf); /* first setting */
549     else if (strcmp(f->f.sv->val, buf))
550     return(-1); /* doesn't match! */
551     return(0);
552     case T_NUM:
553     if (f->next == NULL || (f->next->type & F_TYP) != T_LIT)
554     delim = EOF;
555     else
556     delim = f->next->f.sl[0];
557     np = NULL;
558     cp = buf;
559     do {
560     if (!((np==NULL&&isblnk(ipb.chr)) || isnum(ipb.chr)))
561     inword = 0;
562     else if (blnkeq && delim != EOF)
563     inword = isblnk(delim) ?
564     !isblnk(ipb.chr)
565     : ipb.chr != delim;
566     else
567     inword = cp-buf < (f->type & F_WID);
568     if (inword) {
569     if (np==NULL && !isblnk(ipb.chr))
570     np = cp;
571     *cp++ = ipb.chr;
572     scaninp();
573     }
574     } while (inword && cp < &buf[MAXWORD]);
575     *cp = '\0';
576     d = np==NULL ? 0. : atof(np);
577     if (!vardefined(f->f.nv))
578     varset(f->f.nv, '=', d); /* first setting */
579     else if ((d = (varvalue(f->f.nv)-d)/(d==0.?1.:d)) > .001
580     || d < -.001)
581     return(-1); /* doesn't match! */
582     return(0);
583     }
584     }
585    
586    
587     putrec() /* output a record */
588     {
589     char fmt[32];
590     register int n;
591     register struct field *f;
592     int adlast, adnext;
593    
594     adlast = 0;
595     for (f = outfmt; f != NULL; f = f->next) {
596     adnext = blnkeq &&
597     f->next != NULL &&
598     !( (f->next->type&F_TYP) == T_LIT &&
599     f->next->f.sl[0] == ' ' );
600     switch (f->type & F_TYP) {
601     case T_LIT:
602     fputs(f->f.sl, stdout);
603     adlast = f->f.sl[(f->type&F_WID)-1] != ' ';
604     break;
605     case T_STR:
606     if (f->f.sv->val == NULL) {
607     eputs(f->f.sv->name);
608     eputs(": undefined string\n");
609     quit(1);
610     }
611     n = (int)(f->type & F_WID) - strlen(f->f.sv->val);
612     if (adlast)
613     fputs(f->f.sv->val, stdout);
614     if (!(adlast && adnext))
615     while (n-- > 0)
616     putchar(' ');
617     if (!adlast)
618     fputs(f->f.sv->val, stdout);
619     adlast = 1;
620     break;
621     case T_NUM:
622     n = f->type & F_WID;
623     if (adlast && adnext)
624     strcpy(fmt, "%g");
625     else if (adlast)
626     sprintf(fmt, "%%-%dg", n);
627     else
628     sprintf(fmt, "%%%dg", n);
629     printf(fmt, evalue(f->f.ne));
630     adlast = 1;
631     break;
632     }
633     }
634     }
635    
636    
637     initinp(fp) /* prepare lookahead buffer */
638     FILE *fp;
639     {
640     ipb.fin = fp;
641     ipb.beg = ipb.end = inpbuf;
642     ipb.pos = inpbuf-1; /* position before beginning */
643     ipb.chr = '\0';
644     scaninp();
645     }
646    
647    
648     scaninp() /* scan next character */
649     {
650     if (ipb.chr == EOF)
651     return;
652     if (++ipb.pos >= &inpbuf[INBSIZ])
653     ipb.pos = inpbuf;
654     if (ipb.pos == ipb.end) { /* new character */
655     if ((ipb.chr = getc(ipb.fin)) != EOF) {
656     *ipb.end = ipb.chr;
657     if (++ipb.end >= &inpbuf[INBSIZ])
658     ipb.end = inpbuf;
659     if (ipb.end == ipb.beg)
660     ipb.beg = NULL;
661     }
662     } else
663     ipb.chr = *ipb.pos;
664     }
665    
666    
667     advinp() /* move home to current position */
668     {
669     ipb.beg = ipb.pos;
670     }
671    
672    
673     resetinp() /* rewind position and advance 1 */
674     {
675     if (ipb.beg == NULL) /* full */
676     ipb.beg = ipb.end;
677     ipb.pos = ipb.beg;
678     ipb.chr = *ipb.pos;
679     if (++ipb.beg >= &inpbuf[INBSIZ])
680     ipb.beg = inpbuf;
681     scaninp();
682     }
683    
684    
685     void
686     eputs(msg)
687     char *msg;
688     {
689     fputs(msg, stderr);
690     }
691    
692    
693     void
694     wputs(msg)
695     char *msg;
696     {
697     if (!nowarn)
698     eputs(msg);
699     }
700    
701    
702     void
703     quit(code)
704     int code;
705     {
706     exit(code);
707     }