ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rcalc.c
Revision: 1.12
Committed: Sun Mar 28 20:33:12 2004 UTC (20 years ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 1.11: +4 -2 lines
Log Message:
Continued ANSIfication, and other fixes and clarifications.

File Contents

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