ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rcalc.c
Revision: 1.21
Committed: Sun Jun 14 00:33:16 2009 UTC (14 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad4R1, rad4R0
Changes since 1.20: +3 -2 lines
Log Message:
Added new genklemsamp utility and made vwright more useful

File Contents

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