ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rcalc.c
Revision: 1.17
Committed: Wed Feb 16 17:20:22 2005 UTC (19 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.16: +6 -1 lines
Log Message:
Added error check for files given with -n option

File Contents

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