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