ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rcalc.c
Revision: 1.8
Committed: Fri Aug 1 14:14:23 2003 UTC (20 years, 8 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 1.7: +1 -5 lines
Log Message:
Eliminated CPM, MAC, and UNIX conditional compiles.

File Contents

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