ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rcalc.c
Revision: 1.22
Committed: Thu Dec 19 16:38:12 2013 UTC (10 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.21: +11 -5 lines
Log Message:
Changed rcalc and icalc to search RAYPATH for input *.cal files

File Contents

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