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