ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rcalc.c
Revision: 1.10
Committed: Thu Nov 6 05:39:33 2003 UTC (20 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.9: +37 -2 lines
Log Message:
Added an in(n) column function to rcalc

File Contents

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