ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rcalc.c
Revision: 1.2
Committed: Fri Feb 28 20:29:01 2003 UTC (21 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 1.1: +3 -2 lines
Log Message:
Removed redefinition warning to get back old rcalc behavior

File Contents

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