ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rcalc.c
Revision: 1.27
Committed: Thu Aug 18 00:52:47 2016 UTC (7 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R2, rad5R1
Changes since 1.26: +6 -6 lines
Log Message:
Switched over to more efficient fread/fwrite replacements getbinary/putbinary

File Contents

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