ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rcalc.c
Revision: 1.5
Committed: Sun Jun 8 12:03:09 2003 UTC (20 years, 10 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 1.4: +82 -51 lines
Log Message:
Reduced compile warnings/errors on Windows.

File Contents

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