ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rcalc.c
Revision: 1.22
Committed: Thu Dec 19 16:38:12 2013 UTC (10 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.21: +11 -5 lines
Log Message:
Changed rcalc and icalc to search RAYPATH for input *.cal files

File Contents

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