ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rcalc.c
Revision: 1.23
Committed: Sun Mar 9 20:07:27 2014 UTC (10 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.22: +23 -18 lines
Log Message:
Added flockfile calls and fixed SET_FILE_BINARY usage for consistency

File Contents

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