1d6b532c6Sbostic /****************************************************************
2d6b532c6Sbostic Copyright (C) AT&T 1993
3d6b532c6Sbostic All Rights Reserved
4d6b532c6Sbostic
5d6b532c6Sbostic Permission to use, copy, modify, and distribute this software and
6d6b532c6Sbostic its documentation for any purpose and without fee is hereby
7d6b532c6Sbostic granted, provided that the above copyright notice appear in all
8d6b532c6Sbostic copies and that both that the copyright notice and this
9d6b532c6Sbostic permission notice and warranty disclaimer appear in supporting
10d6b532c6Sbostic documentation, and that the name of AT&T or any of its entities
11d6b532c6Sbostic not be used in advertising or publicity pertaining to
12d6b532c6Sbostic distribution of the software without specific, written prior
13d6b532c6Sbostic permission.
14d6b532c6Sbostic
15d6b532c6Sbostic AT&T DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16d6b532c6Sbostic INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17d6b532c6Sbostic IN NO EVENT SHALL AT&T OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18d6b532c6Sbostic SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19d6b532c6Sbostic WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20d6b532c6Sbostic IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21d6b532c6Sbostic ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22d6b532c6Sbostic THIS SOFTWARE.
23d6b532c6Sbostic ****************************************************************/
24d6b532c6Sbostic
25d6b532c6Sbostic #define DEBUG
26d6b532c6Sbostic #include <stdio.h>
27d6b532c6Sbostic #include <string.h>
28d6b532c6Sbostic #include <ctype.h>
29d6b532c6Sbostic #include <errno.h>
30d6b532c6Sbostic #include <stdlib.h>
31d6b532c6Sbostic #include "awk.h"
32d6b532c6Sbostic #include "y.tab.h"
33d6b532c6Sbostic
34d6b532c6Sbostic #define getfval(p) (((p)->tval & (ARR|FLD|REC|NUM)) == NUM ? (p)->fval : r_getfval(p))
35d6b532c6Sbostic #define getsval(p) (((p)->tval & (ARR|FLD|REC|STR)) == STR ? (p)->sval : r_getsval(p))
36d6b532c6Sbostic
37d6b532c6Sbostic FILE *infile = NULL;
38d6b532c6Sbostic uchar *file = (uchar*) "";
39d6b532c6Sbostic int recsize = RECSIZE;
40d6b532c6Sbostic uchar *recdata;
41d6b532c6Sbostic uchar *record;
42d6b532c6Sbostic uchar *fields;
43d6b532c6Sbostic Cell *fldtab;
44d6b532c6Sbostic
45d6b532c6Sbostic #define MAXFLD 200
46d6b532c6Sbostic int nfields = MAXFLD; /* can be set from commandline in main */
47d6b532c6Sbostic
48d6b532c6Sbostic int donefld; /* 1 = implies rec broken into fields */
49d6b532c6Sbostic int donerec; /* 1 = record is valid (no flds have changed) */
50d6b532c6Sbostic
51d6b532c6Sbostic int maxfld = 0; /* last used field */
52d6b532c6Sbostic int argno = 1; /* current input argument number */
53d6b532c6Sbostic extern Awkfloat *ARGC;
54d6b532c6Sbostic
recinit(unsigned int n)55d6b532c6Sbostic void recinit(unsigned int n)
56d6b532c6Sbostic {
57d6b532c6Sbostic static Cell dollar0 = {
58d6b532c6Sbostic OCELL, CFLD, (uchar*) "$0", /*recdata*/0, 0.0, REC|STR|DONTFREE };
59d6b532c6Sbostic static Cell dollar1 = {
60d6b532c6Sbostic OCELL, CFLD, NULL, (uchar*) "", 0.0, FLD|STR|DONTFREE };
61d6b532c6Sbostic int i;
62d6b532c6Sbostic
63d6b532c6Sbostic record = recdata = (uchar *) malloc(n);
64d6b532c6Sbostic fields = (uchar *) malloc(n);
65d6b532c6Sbostic fldtab = (Cell *) malloc(nfields * sizeof(Cell));
66d6b532c6Sbostic if (recdata == NULL || fields == NULL || fldtab == NULL)
67d6b532c6Sbostic ERROR "out of space for $0 and fields" FATAL;
68d6b532c6Sbostic fldtab[0] = dollar0;
69d6b532c6Sbostic fldtab[0].sval = recdata;
70d6b532c6Sbostic for (i = 1; i < nfields; i++)
71d6b532c6Sbostic fldtab[i] = dollar1;
72d6b532c6Sbostic }
73d6b532c6Sbostic
initgetrec(void)74d6b532c6Sbostic void initgetrec(void)
75d6b532c6Sbostic {
76d6b532c6Sbostic int i;
77d6b532c6Sbostic uchar *p;
78d6b532c6Sbostic
79d6b532c6Sbostic for (i = 1; i < *ARGC; i++) {
80d6b532c6Sbostic if (!isclvar(p = getargv(i))) { /* find 1st real filename */
81d6b532c6Sbostic setsval(lookup("FILENAME", symtab), getargv(i));
82d6b532c6Sbostic return;
83d6b532c6Sbostic }
84d6b532c6Sbostic setclvar(p); /* a commandline assignment before filename */
85d6b532c6Sbostic argno++;
86d6b532c6Sbostic }
87d6b532c6Sbostic infile = stdin; /* no filenames, so use stdin */
88d6b532c6Sbostic }
89d6b532c6Sbostic
getrec(uchar * buf)90d6b532c6Sbostic getrec(uchar *buf) /* get next input record from whatever source */
91d6b532c6Sbostic { /* note: tests whether buf == record */
92d6b532c6Sbostic int c;
93d6b532c6Sbostic static int firsttime = 1;
94d6b532c6Sbostic
95d6b532c6Sbostic if (firsttime) {
96d6b532c6Sbostic firsttime = 0;
97d6b532c6Sbostic initgetrec();
98d6b532c6Sbostic }
99d6b532c6Sbostic dprintf( ("RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n",
100d6b532c6Sbostic *RS, *FS, *ARGC, *FILENAME) );
101d6b532c6Sbostic donefld = 0;
102d6b532c6Sbostic donerec = 1;
103d6b532c6Sbostic buf[0] = 0;
104d6b532c6Sbostic while (argno < *ARGC || infile == stdin) {
105d6b532c6Sbostic dprintf( ("argno=%d, file=|%s|\n", argno, file) );
106d6b532c6Sbostic if (infile == NULL) { /* have to open a new file */
107d6b532c6Sbostic file = getargv(argno);
108d6b532c6Sbostic if (*file == '\0') { /* it's been zapped */
109d6b532c6Sbostic argno++;
110d6b532c6Sbostic continue;
111d6b532c6Sbostic }
112d6b532c6Sbostic if (isclvar(file)) { /* a var=value arg */
113d6b532c6Sbostic setclvar(file);
114d6b532c6Sbostic argno++;
115d6b532c6Sbostic continue;
116d6b532c6Sbostic }
117d6b532c6Sbostic *FILENAME = file;
118d6b532c6Sbostic dprintf( ("opening file %s\n", file) );
119d6b532c6Sbostic if (*file == '-' && *(file+1) == '\0')
120d6b532c6Sbostic infile = stdin;
121d6b532c6Sbostic else if ((infile = fopen((char *)file, "r")) == NULL)
122d6b532c6Sbostic ERROR "can't open file %s", file FATAL;
123d6b532c6Sbostic setfval(fnrloc, 0.0);
124d6b532c6Sbostic }
125d6b532c6Sbostic c = readrec(buf, recsize, infile);
126d6b532c6Sbostic if (c != 0 || buf[0] != '\0') { /* normal record */
127d6b532c6Sbostic if (buf == record) {
128d6b532c6Sbostic if (!(recloc->tval & DONTFREE))
129d6b532c6Sbostic xfree(recloc->sval);
130d6b532c6Sbostic recloc->sval = record;
131d6b532c6Sbostic recloc->tval = REC | STR | DONTFREE;
132*72bcf366Sbostic if (is_a_number(recloc->sval)) {
133d6b532c6Sbostic recloc->fval = atof(recloc->sval);
134d6b532c6Sbostic recloc->tval |= NUM;
135d6b532c6Sbostic }
136d6b532c6Sbostic }
137d6b532c6Sbostic setfval(nrloc, nrloc->fval+1);
138d6b532c6Sbostic setfval(fnrloc, fnrloc->fval+1);
139d6b532c6Sbostic return 1;
140d6b532c6Sbostic }
141d6b532c6Sbostic /* EOF arrived on this file; set up next */
142d6b532c6Sbostic if (infile != stdin)
143d6b532c6Sbostic fclose(infile);
144d6b532c6Sbostic infile = NULL;
145d6b532c6Sbostic argno++;
146d6b532c6Sbostic }
147d6b532c6Sbostic return 0; /* true end of file */
148d6b532c6Sbostic }
149d6b532c6Sbostic
readrec(uchar * buf,int bufsize,FILE * inf)150d6b532c6Sbostic readrec(uchar *buf, int bufsize, FILE *inf) /* read one record into buf */
151d6b532c6Sbostic {
152d6b532c6Sbostic register int sep, c;
153d6b532c6Sbostic register uchar *rr;
154d6b532c6Sbostic register int nrr;
155d6b532c6Sbostic
156d6b532c6Sbostic if ((sep = **RS) == 0) {
157d6b532c6Sbostic sep = '\n';
158d6b532c6Sbostic while ((c=getc(inf)) == '\n' && c != EOF) /* skip leading \n's */
159d6b532c6Sbostic ;
160d6b532c6Sbostic if (c != EOF)
161d6b532c6Sbostic ungetc(c, inf);
162d6b532c6Sbostic }
163d6b532c6Sbostic for (rr = buf, nrr = bufsize; ; ) {
164d6b532c6Sbostic for (; (c=getc(inf)) != sep && c != EOF; *rr++ = c)
165d6b532c6Sbostic if (--nrr < 0)
166d6b532c6Sbostic ERROR "input record `%.30s...' too long; try -mr n", buf FATAL;
167d6b532c6Sbostic if (**RS == sep || c == EOF)
168d6b532c6Sbostic break;
169d6b532c6Sbostic if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */
170d6b532c6Sbostic break;
171d6b532c6Sbostic *rr++ = '\n';
172d6b532c6Sbostic *rr++ = c;
173d6b532c6Sbostic }
174d6b532c6Sbostic if (rr > buf + bufsize)
175d6b532c6Sbostic ERROR "input record `%.30s...' too long; try -mr n", buf FATAL;
176d6b532c6Sbostic *rr = 0;
177d6b532c6Sbostic dprintf( ("readrec saw <%s>, returns %d\n", buf, c == EOF && rr == buf ? 0 : 1) );
178d6b532c6Sbostic return c == EOF && rr == buf ? 0 : 1;
179d6b532c6Sbostic }
180d6b532c6Sbostic
getargv(int n)181d6b532c6Sbostic uchar *getargv(int n) /* get ARGV[n] */
182d6b532c6Sbostic {
183d6b532c6Sbostic Cell *x;
184d6b532c6Sbostic uchar *s, temp[10];
185d6b532c6Sbostic extern Array *ARGVtab;
186d6b532c6Sbostic
187d6b532c6Sbostic sprintf((char *)temp, "%d", n);
188d6b532c6Sbostic x = setsymtab(temp, "", 0.0, STR, ARGVtab);
189d6b532c6Sbostic s = getsval(x);
190d6b532c6Sbostic dprintf( ("getargv(%d) returns |%s|\n", n, s) );
191d6b532c6Sbostic return s;
192d6b532c6Sbostic }
193d6b532c6Sbostic
setclvar(uchar * s)194d6b532c6Sbostic void setclvar(uchar *s) /* set var=value from s */
195d6b532c6Sbostic {
196d6b532c6Sbostic uchar *p;
197d6b532c6Sbostic Cell *q;
198d6b532c6Sbostic
199d6b532c6Sbostic for (p=s; *p != '='; p++)
200d6b532c6Sbostic ;
201d6b532c6Sbostic *p++ = 0;
202d6b532c6Sbostic p = qstring(p, '\0');
203d6b532c6Sbostic q = setsymtab(s, p, 0.0, STR, symtab);
204d6b532c6Sbostic setsval(q, p);
205*72bcf366Sbostic if (is_a_number(q->sval)) {
206d6b532c6Sbostic q->fval = atof(q->sval);
207d6b532c6Sbostic q->tval |= NUM;
208d6b532c6Sbostic }
209d6b532c6Sbostic dprintf( ("command line set %s to |%s|\n", s, p) );
210d6b532c6Sbostic }
211d6b532c6Sbostic
212d6b532c6Sbostic
fldbld(void)213d6b532c6Sbostic void fldbld(void) /* create fields from current record */
214d6b532c6Sbostic {
215d6b532c6Sbostic register uchar *r, *fr, sep;
216d6b532c6Sbostic Cell *p;
217d6b532c6Sbostic int i;
218d6b532c6Sbostic
219d6b532c6Sbostic if (donefld)
220d6b532c6Sbostic return;
221d6b532c6Sbostic if (!(recloc->tval & STR))
222d6b532c6Sbostic getsval(recloc);
223d6b532c6Sbostic r = recloc->sval;
224d6b532c6Sbostic fr = fields;
225d6b532c6Sbostic i = 0; /* number of fields accumulated here */
226d6b532c6Sbostic if (strlen(*FS) > 1) { /* it's a regular expression */
227d6b532c6Sbostic i = refldbld(r, *FS);
228d6b532c6Sbostic } else if ((sep = **FS) == ' ') { /* default whitespace */
229d6b532c6Sbostic for (i = 0; ; ) {
230d6b532c6Sbostic while (*r == ' ' || *r == '\t' || *r == '\n')
231d6b532c6Sbostic r++;
232d6b532c6Sbostic if (*r == 0)
233d6b532c6Sbostic break;
234d6b532c6Sbostic i++;
235d6b532c6Sbostic if (i >= nfields)
236d6b532c6Sbostic break;
237d6b532c6Sbostic if (!(fldtab[i].tval & DONTFREE))
238d6b532c6Sbostic xfree(fldtab[i].sval);
239d6b532c6Sbostic fldtab[i].sval = fr;
240d6b532c6Sbostic fldtab[i].tval = FLD | STR | DONTFREE;
241d6b532c6Sbostic do
242d6b532c6Sbostic *fr++ = *r++;
243d6b532c6Sbostic while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0');
244d6b532c6Sbostic *fr++ = 0;
245d6b532c6Sbostic }
246d6b532c6Sbostic *fr = 0;
247d6b532c6Sbostic } else if (*r != 0) { /* if 0, it's a null field */
248d6b532c6Sbostic for (;;) {
249d6b532c6Sbostic i++;
250d6b532c6Sbostic if (i >= nfields)
251d6b532c6Sbostic break;
252d6b532c6Sbostic if (!(fldtab[i].tval & DONTFREE))
253d6b532c6Sbostic xfree(fldtab[i].sval);
254d6b532c6Sbostic fldtab[i].sval = fr;
255d6b532c6Sbostic fldtab[i].tval = FLD | STR | DONTFREE;
256d6b532c6Sbostic while (*r != sep && *r != '\n' && *r != '\0') /* \n is always a separator */
257d6b532c6Sbostic *fr++ = *r++;
258d6b532c6Sbostic *fr++ = 0;
259d6b532c6Sbostic if (*r++ == 0)
260d6b532c6Sbostic break;
261d6b532c6Sbostic }
262d6b532c6Sbostic *fr = 0;
263d6b532c6Sbostic }
264d6b532c6Sbostic if (i >= nfields)
265d6b532c6Sbostic ERROR "record `%.30s...' has too many fields; try -mf n", record FATAL;
266d6b532c6Sbostic /* clean out junk from previous record */
267d6b532c6Sbostic cleanfld(i, maxfld);
268d6b532c6Sbostic maxfld = i;
269d6b532c6Sbostic donefld = 1;
270d6b532c6Sbostic for (p = fldtab+1; p <= fldtab+maxfld; p++) {
271*72bcf366Sbostic if(is_a_number(p->sval)) {
272d6b532c6Sbostic p->fval = atof(p->sval);
273d6b532c6Sbostic p->tval |= NUM;
274d6b532c6Sbostic }
275d6b532c6Sbostic }
276d6b532c6Sbostic setfval(nfloc, (Awkfloat) maxfld);
277d6b532c6Sbostic if (dbg)
278d6b532c6Sbostic for (p = fldtab; p <= fldtab+maxfld; p++)
279d6b532c6Sbostic printf("field %d: |%s|\n", p-fldtab, p->sval);
280d6b532c6Sbostic }
281d6b532c6Sbostic
cleanfld(int n1,int n2)282d6b532c6Sbostic void cleanfld(int n1, int n2) /* clean out fields n1..n2 inclusive */
283d6b532c6Sbostic {
284d6b532c6Sbostic static uchar *nullstat = (uchar *) "";
285d6b532c6Sbostic register Cell *p, *q;
286d6b532c6Sbostic
287d6b532c6Sbostic for (p = &fldtab[n2], q = &fldtab[n1]; p > q; p--) {
288d6b532c6Sbostic if (!(p->tval & DONTFREE))
289d6b532c6Sbostic xfree(p->sval);
290d6b532c6Sbostic p->tval = FLD | STR | DONTFREE;
291d6b532c6Sbostic p->sval = nullstat;
292d6b532c6Sbostic }
293d6b532c6Sbostic }
294d6b532c6Sbostic
newfld(int n)295d6b532c6Sbostic void newfld(int n) /* add field n (after end) */
296d6b532c6Sbostic {
297d6b532c6Sbostic if (n >= nfields)
298d6b532c6Sbostic ERROR "creating too many fields (%d); try -mf n", n, record FATAL;
299d6b532c6Sbostic cleanfld(maxfld, n);
300d6b532c6Sbostic maxfld = n;
301d6b532c6Sbostic setfval(nfloc, (Awkfloat) n);
302d6b532c6Sbostic }
303d6b532c6Sbostic
refldbld(uchar * rec,uchar * fs)304d6b532c6Sbostic refldbld(uchar *rec, uchar *fs) /* build fields from reg expr in FS */
305d6b532c6Sbostic {
306d6b532c6Sbostic uchar *fr;
307d6b532c6Sbostic int i, tempstat;
308d6b532c6Sbostic fa *pfa;
309d6b532c6Sbostic
310d6b532c6Sbostic fr = fields;
311d6b532c6Sbostic *fr = '\0';
312d6b532c6Sbostic if (*rec == '\0')
313d6b532c6Sbostic return 0;
314d6b532c6Sbostic pfa = makedfa(fs, 1);
315d6b532c6Sbostic dprintf( ("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs) );
316d6b532c6Sbostic tempstat = pfa->initstat;
317d6b532c6Sbostic for (i = 1; i < nfields; i++) {
318d6b532c6Sbostic if (!(fldtab[i].tval & DONTFREE))
319d6b532c6Sbostic xfree(fldtab[i].sval);
320d6b532c6Sbostic fldtab[i].tval = FLD | STR | DONTFREE;
321d6b532c6Sbostic fldtab[i].sval = fr;
322d6b532c6Sbostic dprintf( ("refldbld: i=%d\n", i) );
323d6b532c6Sbostic if (nematch(pfa, rec)) {
324d6b532c6Sbostic pfa->initstat = 2; /* horrible coupling */
325d6b532c6Sbostic dprintf( ("match %s (%d chars)\n", patbeg, patlen) );
326d6b532c6Sbostic strncpy(fr, rec, patbeg-rec);
327d6b532c6Sbostic fr += patbeg - rec + 1;
328d6b532c6Sbostic *(fr-1) = '\0';
329d6b532c6Sbostic rec = patbeg + patlen;
330d6b532c6Sbostic } else {
331d6b532c6Sbostic dprintf( ("no match %s\n", rec) );
332d6b532c6Sbostic strcpy(fr, rec);
333d6b532c6Sbostic pfa->initstat = tempstat;
334d6b532c6Sbostic break;
335d6b532c6Sbostic }
336d6b532c6Sbostic }
337d6b532c6Sbostic return i;
338d6b532c6Sbostic }
339d6b532c6Sbostic
recbld(void)340d6b532c6Sbostic void recbld(void) /* create $0 from $1..$NF if necessary */
341d6b532c6Sbostic {
342d6b532c6Sbostic register int i;
343d6b532c6Sbostic register uchar *r, *p;
344d6b532c6Sbostic static uchar *rec = 0;
345d6b532c6Sbostic
346d6b532c6Sbostic if (donerec == 1)
347d6b532c6Sbostic return;
348d6b532c6Sbostic if (rec == 0) {
349d6b532c6Sbostic rec = (uchar *) malloc(recsize);
350d6b532c6Sbostic if (rec == 0)
351d6b532c6Sbostic ERROR "out of space building $0, record size %d", recsize FATAL;
352d6b532c6Sbostic }
353d6b532c6Sbostic r = rec;
354d6b532c6Sbostic for (i = 1; i <= *NF; i++) {
355d6b532c6Sbostic p = getsval(&fldtab[i]);
356d6b532c6Sbostic while (r < rec+recsize-1 && (*r = *p++))
357d6b532c6Sbostic r++;
358d6b532c6Sbostic if (i < *NF)
359d6b532c6Sbostic for (p = *OFS; r < rec+recsize-1 && (*r = *p++); )
360d6b532c6Sbostic r++;
361d6b532c6Sbostic }
362d6b532c6Sbostic if (r > rec + recsize - 1)
363d6b532c6Sbostic ERROR "built giant record `%.30s...'; try -mr n", record FATAL;
364d6b532c6Sbostic *r = '\0';
365d6b532c6Sbostic dprintf( ("in recbld FS=%o, recloc=%o\n", **FS, recloc) );
366d6b532c6Sbostic recloc->tval = REC | STR | DONTFREE;
367d6b532c6Sbostic recloc->sval = record = rec;
368d6b532c6Sbostic dprintf( ("in recbld FS=%o, recloc=%o\n", **FS, recloc) );
369d6b532c6Sbostic dprintf( ("recbld = |%s|\n", record) );
370d6b532c6Sbostic donerec = 1;
371d6b532c6Sbostic }
372d6b532c6Sbostic
fieldadr(int n)373d6b532c6Sbostic Cell *fieldadr(int n)
374d6b532c6Sbostic {
375d6b532c6Sbostic if (n < 0 || n >= nfields)
376d6b532c6Sbostic ERROR "trying to access field %d; try -mf n", n FATAL;
377d6b532c6Sbostic return(&fldtab[n]);
378d6b532c6Sbostic }
379d6b532c6Sbostic
380d6b532c6Sbostic int errorflag = 0;
381d6b532c6Sbostic char errbuf[200];
382d6b532c6Sbostic
yyerror(uchar * s)383d6b532c6Sbostic void yyerror(uchar *s)
384d6b532c6Sbostic {
385d6b532c6Sbostic extern uchar *cmdname, *curfname;
386d6b532c6Sbostic static int been_here = 0;
387d6b532c6Sbostic
388d6b532c6Sbostic if (been_here++ > 2)
389d6b532c6Sbostic return;
390d6b532c6Sbostic fprintf(stderr, "%s: %s", cmdname, s);
391d6b532c6Sbostic fprintf(stderr, " at source line %d", lineno);
392d6b532c6Sbostic if (curfname != NULL)
393d6b532c6Sbostic fprintf(stderr, " in function %s", curfname);
394d6b532c6Sbostic fprintf(stderr, "\n");
395d6b532c6Sbostic errorflag = 2;
396d6b532c6Sbostic eprint();
397d6b532c6Sbostic }
398d6b532c6Sbostic
fpecatch(int n)399d6b532c6Sbostic void fpecatch(int n)
400d6b532c6Sbostic {
401d6b532c6Sbostic ERROR "floating point exception %d", n FATAL;
402d6b532c6Sbostic }
403d6b532c6Sbostic
404d6b532c6Sbostic extern int bracecnt, brackcnt, parencnt;
405d6b532c6Sbostic
bracecheck(void)406d6b532c6Sbostic void bracecheck(void)
407d6b532c6Sbostic {
408d6b532c6Sbostic int c;
409d6b532c6Sbostic static int beenhere = 0;
410d6b532c6Sbostic
411d6b532c6Sbostic if (beenhere++)
412d6b532c6Sbostic return;
413*72bcf366Sbostic while ((c = lex_input()) != EOF && c != '\0')
414d6b532c6Sbostic bclass(c);
415d6b532c6Sbostic bcheck2(bracecnt, '{', '}');
416d6b532c6Sbostic bcheck2(brackcnt, '[', ']');
417d6b532c6Sbostic bcheck2(parencnt, '(', ')');
418d6b532c6Sbostic }
419d6b532c6Sbostic
bcheck2(int n,int c1,int c2)420d6b532c6Sbostic void bcheck2(int n, int c1, int c2)
421d6b532c6Sbostic {
422d6b532c6Sbostic if (n == 1)
423d6b532c6Sbostic fprintf(stderr, "\tmissing %c\n", c2);
424d6b532c6Sbostic else if (n > 1)
425d6b532c6Sbostic fprintf(stderr, "\t%d missing %c's\n", n, c2);
426d6b532c6Sbostic else if (n == -1)
427d6b532c6Sbostic fprintf(stderr, "\textra %c\n", c2);
428d6b532c6Sbostic else if (n < -1)
429d6b532c6Sbostic fprintf(stderr, "\t%d extra %c's\n", -n, c2);
430d6b532c6Sbostic }
431d6b532c6Sbostic
error(int f,char * s)432d6b532c6Sbostic void error(int f, char *s)
433d6b532c6Sbostic {
434d6b532c6Sbostic extern Node *curnode;
435d6b532c6Sbostic extern uchar *cmdname;
436d6b532c6Sbostic
437d6b532c6Sbostic fflush(stdout);
438d6b532c6Sbostic fprintf(stderr, "%s: ", cmdname);
439d6b532c6Sbostic fprintf(stderr, "%s", s);
440d6b532c6Sbostic fprintf(stderr, "\n");
441d6b532c6Sbostic if (compile_time != 2 && NR && *NR > 0) {
442d6b532c6Sbostic fprintf(stderr, " input record number %g", *FNR);
443d6b532c6Sbostic if (strcmp(*FILENAME, "-") != 0)
444d6b532c6Sbostic fprintf(stderr, ", file %s", *FILENAME);
445d6b532c6Sbostic fprintf(stderr, "\n");
446d6b532c6Sbostic }
447d6b532c6Sbostic if (compile_time != 2 && curnode)
448d6b532c6Sbostic fprintf(stderr, " source line number %d\n", curnode->lineno);
449d6b532c6Sbostic else if (compile_time != 2 && lineno)
450d6b532c6Sbostic fprintf(stderr, " source line number %d\n", lineno);
451d6b532c6Sbostic eprint();
452d6b532c6Sbostic if (f) {
453d6b532c6Sbostic if (dbg > 1) /* core dump if serious debugging on */
454d6b532c6Sbostic abort();
455d6b532c6Sbostic exit(2);
456d6b532c6Sbostic }
457d6b532c6Sbostic }
458d6b532c6Sbostic
eprint(void)459d6b532c6Sbostic void eprint(void) /* try to print context around error */
460d6b532c6Sbostic {
461*72bcf366Sbostic #if 0
462d6b532c6Sbostic uchar *p, *q;
463d6b532c6Sbostic int c;
464d6b532c6Sbostic static int been_here = 0;
465d6b532c6Sbostic extern uchar ebuf[], *ep;
466d6b532c6Sbostic
467d6b532c6Sbostic if (compile_time == 2 || compile_time == 0 || been_here++ > 0)
468d6b532c6Sbostic return;
469d6b532c6Sbostic p = ep - 1;
470d6b532c6Sbostic if (p > ebuf && *p == '\n')
471d6b532c6Sbostic p--;
472d6b532c6Sbostic for ( ; p > ebuf && *p != '\n' && *p != '\0'; p--)
473d6b532c6Sbostic ;
474d6b532c6Sbostic while (*p == '\n')
475d6b532c6Sbostic p++;
476d6b532c6Sbostic fprintf(stderr, " context is\n\t");
477d6b532c6Sbostic for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
478d6b532c6Sbostic ;
479d6b532c6Sbostic for ( ; p < q; p++)
480d6b532c6Sbostic if (*p)
481d6b532c6Sbostic putc(*p, stderr);
482d6b532c6Sbostic fprintf(stderr, " >>> ");
483d6b532c6Sbostic for ( ; p < ep; p++)
484d6b532c6Sbostic if (*p)
485d6b532c6Sbostic putc(*p, stderr);
486d6b532c6Sbostic fprintf(stderr, " <<< ");
487d6b532c6Sbostic if (*ep)
488d6b532c6Sbostic while ((c = input()) != '\n' && c != '\0' && c != EOF) {
489d6b532c6Sbostic putc(c, stderr);
490d6b532c6Sbostic bclass(c);
491d6b532c6Sbostic }
492d6b532c6Sbostic putc('\n', stderr);
493d6b532c6Sbostic ep = ebuf;
494*72bcf366Sbostic #endif
495d6b532c6Sbostic }
496d6b532c6Sbostic
bclass(int c)497d6b532c6Sbostic void bclass(int c)
498d6b532c6Sbostic {
499d6b532c6Sbostic switch (c) {
500d6b532c6Sbostic case '{': bracecnt++; break;
501d6b532c6Sbostic case '}': bracecnt--; break;
502d6b532c6Sbostic case '[': brackcnt++; break;
503d6b532c6Sbostic case ']': brackcnt--; break;
504d6b532c6Sbostic case '(': parencnt++; break;
505d6b532c6Sbostic case ')': parencnt--; break;
506d6b532c6Sbostic }
507d6b532c6Sbostic }
508d6b532c6Sbostic
errcheck(double x,uchar * s)509d6b532c6Sbostic double errcheck(double x, uchar *s)
510d6b532c6Sbostic {
511d6b532c6Sbostic extern int errno;
512d6b532c6Sbostic
513d6b532c6Sbostic if (errno == EDOM) {
514d6b532c6Sbostic errno = 0;
515d6b532c6Sbostic ERROR "%s argument out of domain", s WARNING;
516d6b532c6Sbostic x = 1;
517d6b532c6Sbostic } else if (errno == ERANGE) {
518d6b532c6Sbostic errno = 0;
519d6b532c6Sbostic ERROR "%s result out of range", s WARNING;
520d6b532c6Sbostic x = 1;
521d6b532c6Sbostic }
522d6b532c6Sbostic return x;
523d6b532c6Sbostic }
524d6b532c6Sbostic
isclvar(uchar * s)525d6b532c6Sbostic isclvar(uchar *s) /* is s of form var=something ? */
526d6b532c6Sbostic {
527d6b532c6Sbostic uchar *os = s;
528d6b532c6Sbostic
529d6b532c6Sbostic if (!isalpha(*s) && *s != '_')
530d6b532c6Sbostic return 0;
531d6b532c6Sbostic for ( ; *s; s++)
532d6b532c6Sbostic if (!(isalnum(*s) || *s == '_'))
533d6b532c6Sbostic break;
534d6b532c6Sbostic return *s == '=' && s > os && *(s+1) != '=';
535d6b532c6Sbostic }
536d6b532c6Sbostic
537d6b532c6Sbostic #define MAXEXPON 38 /* maximum exponent for fp number. should be IEEE */
538d6b532c6Sbostic
is_a_number(uchar * s)539*72bcf366Sbostic is_a_number(uchar *s) /* probably should be done by a library function */
540d6b532c6Sbostic {
541d6b532c6Sbostic register int d1, d2;
542d6b532c6Sbostic int point;
543d6b532c6Sbostic uchar *es;
544d6b532c6Sbostic
545d6b532c6Sbostic d1 = d2 = point = 0;
546d6b532c6Sbostic while (*s == ' ' || *s == '\t' || *s == '\n')
547d6b532c6Sbostic s++;
548d6b532c6Sbostic if (*s == '\0')
549d6b532c6Sbostic return(0); /* empty stuff isn't number */
550d6b532c6Sbostic if (*s == '+' || *s == '-')
551d6b532c6Sbostic s++;
552d6b532c6Sbostic if (!isdigit(*s) && *s != '.')
553d6b532c6Sbostic return(0);
554d6b532c6Sbostic if (isdigit(*s)) {
555d6b532c6Sbostic do {
556d6b532c6Sbostic d1++;
557d6b532c6Sbostic s++;
558d6b532c6Sbostic } while (isdigit(*s));
559d6b532c6Sbostic }
560d6b532c6Sbostic if (*s == '.') {
561d6b532c6Sbostic point++;
562d6b532c6Sbostic s++;
563d6b532c6Sbostic }
564d6b532c6Sbostic if (isdigit(*s)) {
565d6b532c6Sbostic d2++;
566d6b532c6Sbostic do {
567d6b532c6Sbostic s++;
568d6b532c6Sbostic } while (isdigit(*s));
569d6b532c6Sbostic }
570d6b532c6Sbostic if (!(d1 || point && d2))
571d6b532c6Sbostic return(0);
572d6b532c6Sbostic if (*s == 'e' || *s == 'E') {
573d6b532c6Sbostic s++;
574d6b532c6Sbostic if (*s == '+' || *s == '-')
575d6b532c6Sbostic s++;
576d6b532c6Sbostic if (!isdigit(*s))
577d6b532c6Sbostic return(0);
578d6b532c6Sbostic es = s;
579d6b532c6Sbostic do {
580d6b532c6Sbostic s++;
581d6b532c6Sbostic } while (isdigit(*s));
582d6b532c6Sbostic if (s - es > 2)
583d6b532c6Sbostic return(0);
584d6b532c6Sbostic else if (s - es == 2 && (int)(10 * (*es-'0') + *(es+1)-'0') >= MAXEXPON)
585d6b532c6Sbostic return(0);
586d6b532c6Sbostic }
587d6b532c6Sbostic while (*s == ' ' || *s == '\t' || *s == '\n')
588d6b532c6Sbostic s++;
589d6b532c6Sbostic if (*s == '\0')
590d6b532c6Sbostic return(1);
591d6b532c6Sbostic else
592d6b532c6Sbostic return(0);
593d6b532c6Sbostic }
594