ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rcalc.c
Revision: 1.14
Committed: Mon Oct 11 10:02:15 2004 UTC (19 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R6, rad3R6P1
Changes since 1.13: +4 -4 lines
Log Message:
Fixed bug in format parsing where extra EOL was sometimes added

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 1.14 static const char RCSid[] = "$Id: rcalc.c,v 1.13 2004/06/09 16:00:13 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     #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 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     eclock++;
214     putout();
215     quit(0);
216     }
217    
218     if (blnkeq) /* for efficiency */
219     nbsynch();
220    
221     if (i == argc) /* from stdin */
222     execute(NULL);
223     else /* from one or more files */
224     for ( ; i < argc; i++)
225     execute(argv[i]);
226    
227     quit(0);
228 schorsch 1.11 return 0; /* pro forma return */
229 greg 1.1 }
230    
231    
232 schorsch 1.5 static void
233     nbsynch(void) /* non-blank starting synch character */
234 greg 1.1 {
235     if (inpfmt == NULL || (inpfmt->type & F_TYP) != T_LIT)
236     return;
237     while (isblnk(*inpfmt->f.sl))
238     inpfmt->f.sl++;
239     if (!*inpfmt->f.sl)
240     inpfmt = inpfmt->next;
241     }
242    
243    
244 greg 1.10 static int
245 schorsch 1.5 getinputrec( /* get next input record */
246     FILE *fp
247     )
248 greg 1.3 {
249     if (inpfmt != NULL)
250     return(getrec());
251     if (nbicols > 0)
252     return(fread(inpbuf, sizeof(double),
253     nbicols, fp) == nbicols);
254     if (nbicols < 0)
255     return(fread(inpbuf, sizeof(float),
256     -nbicols, fp) == -nbicols);
257     return(fgets(inpbuf, INBSIZ, fp) != NULL);
258     }
259    
260    
261 schorsch 1.5 static void
262     execute( /* process a file */
263     char *file
264     )
265 greg 1.1 {
266     int conditional = vardefined("cond");
267     long nrecs = 0;
268     long nout = 0;
269     FILE *fp;
270    
271     if (file == NULL)
272     fp = stdin;
273     else if ((fp = fopen(file, "r")) == NULL) {
274     eputs(file);
275     eputs(": cannot open\n");
276     quit(1);
277     }
278     if (inpfmt != NULL)
279     initinp(fp);
280 greg 1.3
281     while (getinputrec(fp)) {
282 greg 1.1 varset("recno", '=', (double)++nrecs);
283     colflg = 0;
284     eclock++;
285     if (!conditional || varvalue("cond") > 0.0) {
286     varset("outno", '=', (double)++nout);
287     putout();
288     }
289     }
290     fclose(fp);
291     }
292    
293    
294 schorsch 1.5 static void
295     putout(void) /* produce an output record */
296 greg 1.1 {
297    
298     colpos = 0;
299     if (outfmt != NULL)
300     putrec();
301 greg 1.3 else if (bocols)
302     chanout(bchanset);
303 greg 1.1 else
304     chanout(chanset);
305 greg 1.4 if (colpos && !bocols)
306 greg 1.1 putchar('\n');
307     if (unbuff)
308     fflush(stdout);
309     }
310    
311 greg 1.10
312     static double
313     l_in(char *funame) /* function call for $channel */
314     {
315     int n;
316     register char *cp;
317     /* get argument as integer */
318     n = (int)(argument(1) + .5);
319     if (n != 0) /* return channel value */
320     return(chanvalue(n));
321     /* determine number of channels */
322     if (noinput || inpfmt != NULL)
323     return(0);
324     if (nbicols > 0)
325     return(nbicols);
326     if (nbicols < 0)
327     return(-nbicols);
328     cp = inpbuf; /* need to count */
329     for (n = 0; *cp; )
330     if (blnkeq && isspace(sepchar)) {
331     while (isspace(*cp))
332     cp++;
333     n += *cp != '\0';
334     while (*cp && !isspace(*cp))
335     cp++;
336     } else {
337     n += *cp != '\n';
338     while (*cp && *cp++ != sepchar)
339     ;
340     }
341     return(n);
342     }
343 greg 1.1
344     double
345 schorsch 1.5 chanvalue( /* return value for column n */
346     int n
347     )
348 greg 1.1 {
349     int i;
350     register char *cp;
351    
352     if (noinput || inpfmt != NULL) {
353     eputs("no column input\n");
354     quit(1);
355     }
356     if (n < 1) {
357     eputs("illegal channel number\n");
358     quit(1);
359     }
360 greg 1.3 if (nbicols > 0) {
361     if (n > nbicols)
362     return(0.0);
363     cp = inpbuf + (n-1)*sizeof(double);
364     return(*(double *)cp);
365     }
366     if (nbicols < 0) {
367     if (n > -nbicols)
368     return(0.0);
369     cp = inpbuf + (n-1)*sizeof(float);
370     return(*(float *)cp);
371     }
372 greg 1.1 if (n <= MAXCOL && colflg & 1L<<(n-1))
373     return(colval[n-1]);
374    
375     cp = inpbuf;
376     for (i = 1; i < n; i++)
377     if (blnkeq && isspace(sepchar)) {
378     while (isspace(*cp))
379     cp++;
380     while (*cp && !isspace(*cp))
381     cp++;
382     } else
383     while (*cp && *cp++ != sepchar)
384     ;
385    
386     while (isspace(*cp)) /* some atof()'s don't like tabs */
387     cp++;
388    
389     if (n <= MAXCOL) {
390     colflg |= 1L<<(n-1);
391     return(colval[n-1] = atof(cp));
392     } else
393     return(atof(cp));
394     }
395    
396    
397 greg 1.3 void
398 schorsch 1.5 chanset( /* output column n */
399     int n,
400     double v
401     )
402 greg 1.1 {
403     if (colpos == 0) /* no leading separator */
404     colpos = 1;
405     while (colpos < n) {
406     putchar(sepchar);
407     colpos++;
408     }
409     printf("%.9g", v);
410 greg 1.3 }
411    
412    
413     void
414 schorsch 1.5 bchanset( /* output binary channel n */
415     int n,
416     double v
417     )
418 greg 1.3 {
419     static char zerobuf[sizeof(double)];
420    
421     while (++colpos < n)
422     fwrite(zerobuf,
423     bocols>0 ? sizeof(double) : sizeof(float),
424     1, stdout);
425     if (bocols > 0)
426     fwrite(&v, sizeof(double), 1, stdout);
427     else {
428     float fval = v;
429     fwrite(&fval, sizeof(float), 1, stdout);
430     }
431 greg 1.1 }
432    
433    
434 schorsch 1.5 static void
435     readfmt( /* read record format */
436     char *spec,
437     int output
438     )
439 greg 1.1 {
440     int fd;
441     char *inptr;
442     struct field fmt;
443     int res;
444     register struct field *f;
445     /* check for inline format */
446     for (inptr = spec; *inptr; inptr++)
447     if (*inptr == '$')
448     break;
449     if (*inptr) /* inline */
450     inptr = spec;
451     else { /* from file */
452     if ((fd = open(spec, 0)) == -1) {
453     eputs(spec);
454     eputs(": cannot open\n");
455     quit(1);
456     }
457 greg 1.14 res = read(fd, inpbuf+2, INBSIZ-2);
458 greg 1.1 if (res <= 0 || res >= INBSIZ-1) {
459     eputs(spec);
460     if (res < 0)
461     eputs(": read error\n");
462     else if (res == 0)
463     eputs(": empty file\n");
464     else if (res >= INBSIZ-1)
465     eputs(": format too long\n");
466     quit(1);
467     }
468     close(fd);
469 greg 1.14 (inptr=inpbuf+2)[res] = '\0';
470 greg 1.1 }
471     f = &fmt; /* get fields */
472     while ((res = readfield(&inptr)) != F_NUL) {
473     f->next = (struct field *)emalloc(sizeof(struct field));
474     f = f->next;
475     f->type = res;
476     switch (res & F_TYP) {
477     case T_LIT:
478     f->f.sl = savqstr(inpbuf);
479     break;
480     case T_STR:
481     f->f.sv = getsvar(inpbuf);
482     break;
483     case T_NUM:
484     if (output)
485     f->f.ne = eparse(inpbuf);
486     else
487     f->f.nv = savestr(inpbuf);
488     break;
489     }
490     /* add final newline if necessary */
491     if (!igneol && *inptr == '\0' && inptr[-1] != '\n')
492     inptr = "\n";
493     }
494     f->next = NULL;
495     if (output)
496     outfmt = fmt.next;
497     else
498     inpfmt = fmt.next;
499     }
500    
501    
502 schorsch 1.5 static int
503     readfield( /* get next field in format */
504     register char **pp
505     )
506 greg 1.1 {
507     int type = F_NUL;
508     int width = 0;
509     register char *cp;
510    
511     cp = inpbuf;
512     while (cp < &inpbuf[INBSIZ-1] && **pp != '\0') {
513     width++;
514     switch (type) {
515     case F_NUL:
516     if (**pp == '$') {
517     (*pp)++;
518     width++;
519     if (**pp == '{') {
520     type = T_NUM;
521     (*pp)++;
522     continue;
523     } else if (**pp == '(') {
524     type = T_STR;
525     (*pp)++;
526     continue;
527     } else if (**pp != '$') {
528     eputs("format error\n");
529     quit(1);
530     }
531     width--;
532     }
533     type = T_LIT;
534     *cp++ = *(*pp)++;
535     continue;
536     case T_LIT:
537     if (**pp == '$') {
538     width--;
539     break;
540     }
541     *cp++ = *(*pp)++;
542     continue;
543     case T_NUM:
544     if (**pp == '}') {
545     (*pp)++;
546     break;
547     }
548     if (!isspace(**pp))
549     *cp++ = **pp;
550     (*pp)++;
551     continue;
552     case T_STR:
553     if (**pp == ')') {
554     (*pp)++;
555     break;
556     }
557     if (!isspace(**pp))
558     *cp++ = **pp;
559     (*pp)++;
560     continue;
561     }
562     break;
563     }
564     *cp = '\0';
565     return(type | width);
566     }
567    
568    
569     struct strvar *
570 schorsch 1.5 getsvar( /* get string variable */
571     char *svname
572     )
573 greg 1.1 {
574     register struct strvar *sv;
575    
576     for (sv = svhead; sv != NULL; sv = sv->next)
577     if (!strcmp(sv->name, svname))
578     return(sv);
579     sv = (struct strvar *)emalloc(sizeof(struct strvar));
580     sv->name = savqstr(svname);
581     sv->val = sv->preset = NULL;
582     sv->next = svhead;
583     svhead = sv;
584     return(sv);
585     }
586    
587    
588 schorsch 1.5 static void
589     svpreset( /* preset a string variable */
590     char *eqn
591     )
592 greg 1.1 {
593     register struct strvar *sv;
594     register char *val;
595    
596     for (val = eqn; *val != '='; val++)
597     if (!*val)
598     return;
599     *val++ = '\0';
600     sv = getsvar(eqn);
601     if (sv->preset != NULL)
602     freqstr(sv->preset);
603     if (sv->val != NULL)
604     freqstr(sv->val);
605     sv->val = sv->preset = savqstr(val);
606     *--val = '=';
607     }
608    
609    
610 schorsch 1.5 static void
611     clearrec(void) /* clear input record variables */
612 greg 1.1 {
613     register struct field *f;
614    
615     for (f = inpfmt; f != NULL; f = f->next)
616     switch (f->type & F_TYP) {
617     case T_NUM:
618     dremove(f->f.nv);
619     break;
620     case T_STR:
621     if (f->f.sv->val != f->f.sv->preset) {
622     freqstr(f->f.sv->val);
623     f->f.sv->val = f->f.sv->preset;
624     }
625     break;
626     }
627     }
628    
629    
630 schorsch 1.5 static int
631 greg 1.13 getrec(void) /* get next record from file */
632 greg 1.1 {
633     int eatline;
634     register struct field *f;
635 greg 1.14
636 greg 1.1 while (ipb.chr != EOF) {
637     eatline = !igneol && ipb.chr != '\n';
638     if (blnkeq) /* beware of nbsynch() */
639     while (isblnk(ipb.chr))
640 greg 1.13 resetinp();
641 greg 1.1 clearrec(); /* start with fresh record */
642     for (f = inpfmt; f != NULL; f = f->next)
643     if (getfield(f) == -1)
644     break;
645     if (f == NULL) {
646 greg 1.13 advinp(); /* got one! */
647 greg 1.1 return(1);
648     }
649 greg 1.13 resetinp(); /* eat false start */
650 greg 1.1 if (eatline) { /* eat rest of line */
651     while (ipb.chr != '\n') {
652     if (ipb.chr == EOF)
653     return(0);
654 greg 1.13 resetinp();
655 greg 1.1 }
656 greg 1.13 resetinp();
657 greg 1.1 }
658     }
659     return(0);
660     }
661    
662    
663 schorsch 1.5 static int
664     getfield( /* get next field */
665     register struct field *f
666     )
667 greg 1.1 {
668 schorsch 1.6 static char buf[RMAXWORD+1]; /* no recursion! */
669 greg 1.1 int delim, inword;
670     double d;
671     char *np;
672     register char *cp;
673    
674     switch (f->type & F_TYP) {
675     case T_LIT:
676     cp = f->f.sl;
677     do {
678     if (blnkeq && isblnk(*cp)) {
679     if (!isblnk(ipb.chr))
680     return(-1);
681     do
682     cp++;
683     while (isblnk(*cp));
684     do
685     scaninp();
686     while (isblnk(ipb.chr));
687     } else if (*cp == ipb.chr) {
688     cp++;
689     scaninp();
690     } else
691     return(-1);
692     } while (*cp);
693     return(0);
694     case T_STR:
695     if (f->next == NULL || (f->next->type & F_TYP) != T_LIT)
696     delim = EOF;
697     else
698     delim = f->next->f.sl[0];
699     cp = buf;
700     do {
701 greg 1.9 if (ipb.chr == EOF || ipb.chr == '\n')
702 greg 1.1 inword = 0;
703     else if (blnkeq && delim != EOF)
704     inword = isblnk(delim) ?
705     !isblnk(ipb.chr)
706     : ipb.chr != delim;
707     else
708     inword = cp-buf < (f->type & F_WID);
709     if (inword) {
710     *cp++ = ipb.chr;
711     scaninp();
712     }
713 schorsch 1.6 } while (inword && cp < &buf[RMAXWORD]);
714 greg 1.1 *cp = '\0';
715     if (f->f.sv->val == NULL)
716     f->f.sv->val = savqstr(buf); /* first setting */
717     else if (strcmp(f->f.sv->val, buf))
718     return(-1); /* doesn't match! */
719     return(0);
720     case T_NUM:
721     if (f->next == NULL || (f->next->type & F_TYP) != T_LIT)
722     delim = EOF;
723     else
724     delim = f->next->f.sl[0];
725     np = NULL;
726     cp = buf;
727     do {
728     if (!((np==NULL&&isblnk(ipb.chr)) || isnum(ipb.chr)))
729     inword = 0;
730     else if (blnkeq && delim != EOF)
731     inword = isblnk(delim) ?
732     !isblnk(ipb.chr)
733     : ipb.chr != delim;
734     else
735     inword = cp-buf < (f->type & F_WID);
736     if (inword) {
737     if (np==NULL && !isblnk(ipb.chr))
738     np = cp;
739     *cp++ = ipb.chr;
740     scaninp();
741     }
742 schorsch 1.6 } while (inword && cp < &buf[RMAXWORD]);
743 greg 1.1 *cp = '\0';
744     d = np==NULL ? 0. : atof(np);
745     if (!vardefined(f->f.nv))
746     varset(f->f.nv, '=', d); /* first setting */
747     else if ((d = (varvalue(f->f.nv)-d)/(d==0.?1.:d)) > .001
748     || d < -.001)
749     return(-1); /* doesn't match! */
750     return(0);
751     }
752 schorsch 1.5 return -1; /* pro forma return */
753 greg 1.1 }
754    
755    
756 schorsch 1.5 static void
757     putrec(void) /* output a record */
758 greg 1.1 {
759     char fmt[32];
760     register int n;
761     register struct field *f;
762     int adlast, adnext;
763    
764     adlast = 0;
765     for (f = outfmt; f != NULL; f = f->next) {
766     adnext = blnkeq &&
767     f->next != NULL &&
768     !( (f->next->type&F_TYP) == T_LIT &&
769     f->next->f.sl[0] == ' ' );
770     switch (f->type & F_TYP) {
771     case T_LIT:
772     fputs(f->f.sl, stdout);
773     adlast = f->f.sl[(f->type&F_WID)-1] != ' ';
774     break;
775     case T_STR:
776     if (f->f.sv->val == NULL) {
777     eputs(f->f.sv->name);
778     eputs(": undefined string\n");
779     quit(1);
780     }
781     n = (int)(f->type & F_WID) - strlen(f->f.sv->val);
782     if (adlast)
783     fputs(f->f.sv->val, stdout);
784     if (!(adlast && adnext))
785     while (n-- > 0)
786     putchar(' ');
787     if (!adlast)
788     fputs(f->f.sv->val, stdout);
789     adlast = 1;
790     break;
791     case T_NUM:
792     n = f->type & F_WID;
793     if (adlast && adnext)
794     strcpy(fmt, "%g");
795     else if (adlast)
796     sprintf(fmt, "%%-%dg", n);
797     else
798     sprintf(fmt, "%%%dg", n);
799     printf(fmt, evalue(f->f.ne));
800     adlast = 1;
801     break;
802     }
803     }
804     }
805    
806    
807 schorsch 1.5 static void
808     initinp(FILE *fp) /* prepare lookahead buffer */
809    
810 greg 1.1 {
811     ipb.fin = fp;
812     ipb.beg = ipb.end = inpbuf;
813     ipb.pos = inpbuf-1; /* position before beginning */
814     ipb.chr = '\0';
815     scaninp();
816     }
817    
818    
819 schorsch 1.5 static void
820     scaninp(void) /* scan next character */
821 greg 1.1 {
822     if (ipb.chr == EOF)
823     return;
824     if (++ipb.pos >= &inpbuf[INBSIZ])
825     ipb.pos = inpbuf;
826     if (ipb.pos == ipb.end) { /* new character */
827     if ((ipb.chr = getc(ipb.fin)) != EOF) {
828     *ipb.end = ipb.chr;
829     if (++ipb.end >= &inpbuf[INBSIZ])
830     ipb.end = inpbuf;
831     if (ipb.end == ipb.beg)
832     ipb.beg = NULL;
833     }
834     } else
835     ipb.chr = *ipb.pos;
836     }
837    
838    
839 schorsch 1.5 static void
840     advinp(void) /* move home to current position */
841 greg 1.1 {
842     ipb.beg = ipb.pos;
843     }
844    
845    
846 schorsch 1.5 static void
847     resetinp(void) /* rewind position and advance 1 */
848 greg 1.1 {
849     if (ipb.beg == NULL) /* full */
850     ipb.beg = ipb.end;
851     ipb.pos = ipb.beg;
852     ipb.chr = *ipb.pos;
853 greg 1.13 if (passive) /* transmit unmatched character? */
854     fputc(ipb.chr, stdout);
855 greg 1.1 if (++ipb.beg >= &inpbuf[INBSIZ])
856     ipb.beg = inpbuf;
857     scaninp();
858     }
859    
860    
861     void
862 schorsch 1.5 eputs(char *msg)
863 greg 1.1 {
864     fputs(msg, stderr);
865     }
866    
867    
868     void
869 schorsch 1.5 wputs(char *msg)
870 greg 1.1 {
871     if (!nowarn)
872     eputs(msg);
873     }
874    
875    
876     void
877 schorsch 1.5 quit(int code)
878 greg 1.1 {
879     exit(code);
880     }