xref: /original-bsd/contrib/awk.research/lib.c (revision 72bcf366)
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