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

# Content
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 esupport &= ~(E_REDEFW);
97
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 }