xref: /illumos-gate/usr/src/cmd/awk/lib.c (revision 3ee4fc2a)
1*3ee4fc2aSCody Peter Mello /*
2*3ee4fc2aSCody Peter Mello  * Copyright (C) Lucent Technologies 1997
3*3ee4fc2aSCody Peter Mello  * All Rights Reserved
4*3ee4fc2aSCody Peter Mello  *
5*3ee4fc2aSCody Peter Mello  * Permission to use, copy, modify, and distribute this software and
6*3ee4fc2aSCody Peter Mello  * its documentation for any purpose and without fee is hereby
7*3ee4fc2aSCody Peter Mello  * granted, provided that the above copyright notice appear in all
8*3ee4fc2aSCody Peter Mello  * copies and that both that the copyright notice and this
9*3ee4fc2aSCody Peter Mello  * permission notice and warranty disclaimer appear in supporting
10*3ee4fc2aSCody Peter Mello  * documentation, and that the name Lucent Technologies or any of
11*3ee4fc2aSCody Peter Mello  * its entities not be used in advertising or publicity pertaining
12*3ee4fc2aSCody Peter Mello  * to distribution of the software without specific, written prior
13*3ee4fc2aSCody Peter Mello  * permission.
14*3ee4fc2aSCody Peter Mello  *
15*3ee4fc2aSCody Peter Mello  * LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16*3ee4fc2aSCody Peter Mello  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17*3ee4fc2aSCody Peter Mello  * IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18*3ee4fc2aSCody Peter Mello  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19*3ee4fc2aSCody Peter Mello  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20*3ee4fc2aSCody Peter Mello  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21*3ee4fc2aSCody Peter Mello  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22*3ee4fc2aSCody Peter Mello  * THIS SOFTWARE.
23*3ee4fc2aSCody Peter Mello  */
24*3ee4fc2aSCody Peter Mello 
257c478bd9Sstevel@tonic-gate /*
267c478bd9Sstevel@tonic-gate  * CDDL HEADER START
277c478bd9Sstevel@tonic-gate  *
287c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
298ef4c21aSnakanon  * Common Development and Distribution License (the "License").
308ef4c21aSnakanon  * You may not use this file except in compliance with the License.
317c478bd9Sstevel@tonic-gate  *
327c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
337c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
347c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
357c478bd9Sstevel@tonic-gate  * and limitations under the License.
367c478bd9Sstevel@tonic-gate  *
377c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
387c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
397c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
407c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
417c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
427c478bd9Sstevel@tonic-gate  *
437c478bd9Sstevel@tonic-gate  * CDDL HEADER END
447c478bd9Sstevel@tonic-gate  */
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate /*
478ef4c21aSnakanon  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
481ee2e5faSnakanon  * Use is subject to license terms.
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate 
511ee2e5faSnakanon /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
521ee2e5faSnakanon /*	  All Rights Reserved  	*/
531ee2e5faSnakanon 
54*3ee4fc2aSCody Peter Mello /*	Copyright (c) Lucent Technologies 1997	*/
55*3ee4fc2aSCody Peter Mello /*	  All Rights Reserved  	*/
567c478bd9Sstevel@tonic-gate 
57*3ee4fc2aSCody Peter Mello #include <stdio.h>
58*3ee4fc2aSCody Peter Mello #include <string.h>
59*3ee4fc2aSCody Peter Mello #include <ctype.h>
607c478bd9Sstevel@tonic-gate #include <errno.h>
61*3ee4fc2aSCody Peter Mello #include <stdlib.h>
62*3ee4fc2aSCody Peter Mello #include <stdarg.h>
637c478bd9Sstevel@tonic-gate #include "awk.h"
647c478bd9Sstevel@tonic-gate #include "y.tab.h"
657c478bd9Sstevel@tonic-gate 
66*3ee4fc2aSCody Peter Mello static FILE	*infile	= NULL;
67*3ee4fc2aSCody Peter Mello static char	*file	= "";
68*3ee4fc2aSCody Peter Mello char	*record;
69*3ee4fc2aSCody Peter Mello size_t	recsize	= RECSIZE;
70*3ee4fc2aSCody Peter Mello static char	*fields;
71*3ee4fc2aSCody Peter Mello static size_t	fieldssize = RECSIZE;
72*3ee4fc2aSCody Peter Mello static char	*rtbuf;
73*3ee4fc2aSCody Peter Mello static size_t	rtbufsize = RECSIZE;
747c478bd9Sstevel@tonic-gate 
75*3ee4fc2aSCody Peter Mello Cell	**fldtab;	/* pointers to Cells */
76*3ee4fc2aSCody Peter Mello char	inputFS[100] = " ";
777c478bd9Sstevel@tonic-gate 
78*3ee4fc2aSCody Peter Mello #define	MAXFLD	2
79*3ee4fc2aSCody Peter Mello int	nfields	= MAXFLD;	/* last allocated slot for $i */
807c478bd9Sstevel@tonic-gate 
81*3ee4fc2aSCody Peter Mello int	donefld;	/* 1 = implies rec broken into fields */
82*3ee4fc2aSCody Peter Mello int	donerec;	/* 1 = record is valid (no flds have changed) */
831ee2e5faSnakanon 
84*3ee4fc2aSCody Peter Mello static int	lastfld	= 0;	/* last used field */
851ee2e5faSnakanon static int	argno	= 1;	/* current input argument number */
861ee2e5faSnakanon 
87*3ee4fc2aSCody Peter Mello static Cell dollar0 = { OCELL, CFLD, NULL, "", 0.0, REC|STR|DONTFREE };
88*3ee4fc2aSCody Peter Mello static Cell dollar1 = { OCELL, CFLD, NULL, "", 0.0, FLD|STR|DONTFREE };
89*3ee4fc2aSCody Peter Mello 
90*3ee4fc2aSCody Peter Mello static	char	*getargv(int);
911ee2e5faSnakanon static	void	cleanfld(int, int);
92*3ee4fc2aSCody Peter Mello static	int	refldbld(const char *, const char *);
931ee2e5faSnakanon static	void	bcheck2(int, int, int);
941ee2e5faSnakanon static	void	eprint(void);
951ee2e5faSnakanon static	void	bclass(int);
961ee2e5faSnakanon 
97*3ee4fc2aSCody Peter Mello void
recinit(unsigned int n)98*3ee4fc2aSCody Peter Mello recinit(unsigned int n)
99*3ee4fc2aSCody Peter Mello {
100*3ee4fc2aSCody Peter Mello 	if ((record = (char *)malloc(n)) == NULL ||
101*3ee4fc2aSCody Peter Mello 	    (fields = (char *)malloc(n+2)) == NULL ||
102*3ee4fc2aSCody Peter Mello 	    (fldtab = (Cell **)malloc((nfields+1) * sizeof (Cell *))) == NULL ||
103*3ee4fc2aSCody Peter Mello 	    (fldtab[0] = (Cell *)malloc(sizeof (Cell))) == NULL)
104*3ee4fc2aSCody Peter Mello 		FATAL("out of space for $0 and fields");
105*3ee4fc2aSCody Peter Mello 	*fldtab[0] = dollar0;
106*3ee4fc2aSCody Peter Mello 	fldtab[0]->sval = record;
107*3ee4fc2aSCody Peter Mello 	fldtab[0]->nval = tostring("0");
108*3ee4fc2aSCody Peter Mello 	makefields(1, nfields);
109*3ee4fc2aSCody Peter Mello }
110*3ee4fc2aSCody Peter Mello 
111*3ee4fc2aSCody Peter Mello void
makefields(int n1,int n2)112*3ee4fc2aSCody Peter Mello makefields(int n1, int n2)		/* create $n1..$n2 inclusive */
113*3ee4fc2aSCody Peter Mello {
114*3ee4fc2aSCody Peter Mello 	char temp[50];
115*3ee4fc2aSCody Peter Mello 	int i;
116*3ee4fc2aSCody Peter Mello 
117*3ee4fc2aSCody Peter Mello 	for (i = n1; i <= n2; i++) {
118*3ee4fc2aSCody Peter Mello 		fldtab[i] = (Cell *)malloc(sizeof (Cell));
119*3ee4fc2aSCody Peter Mello 		if (fldtab[i] == NULL)
120*3ee4fc2aSCody Peter Mello 			FATAL("out of space in makefields %d", i);
121*3ee4fc2aSCody Peter Mello 		*fldtab[i] = dollar1;
122*3ee4fc2aSCody Peter Mello 		(void) sprintf(temp, "%d", i);
123*3ee4fc2aSCody Peter Mello 		fldtab[i]->nval = tostring(temp);
124*3ee4fc2aSCody Peter Mello 	}
125*3ee4fc2aSCody Peter Mello }
126*3ee4fc2aSCody Peter Mello 
1271ee2e5faSnakanon static void
initgetrec(void)1281ee2e5faSnakanon initgetrec(void)
1297c478bd9Sstevel@tonic-gate {
1307c478bd9Sstevel@tonic-gate 	int i;
131*3ee4fc2aSCody Peter Mello 	char *p;
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	for (i = 1; i < *ARGC; i++) {
134*3ee4fc2aSCody Peter Mello 		p = getargv(i); /* find 1st real filename */
135*3ee4fc2aSCody Peter Mello 		if (p == NULL || *p == '\0') {  /* deleted or zapped */
136*3ee4fc2aSCody Peter Mello 			argno++;
137*3ee4fc2aSCody Peter Mello 			continue;
138*3ee4fc2aSCody Peter Mello 		}
139*3ee4fc2aSCody Peter Mello 		if (!isclvar(p)) {
140*3ee4fc2aSCody Peter Mello 			(void) setsval(lookup("FILENAME", symtab), p);
1417c478bd9Sstevel@tonic-gate 			return;
142*3ee4fc2aSCody Peter Mello 		}
1437c478bd9Sstevel@tonic-gate 		setclvar(p);	/* a commandline assignment before filename */
1447c478bd9Sstevel@tonic-gate 		argno++;
1457c478bd9Sstevel@tonic-gate 	}
1467c478bd9Sstevel@tonic-gate 	infile = stdin;		/* no filenames, so use stdin */
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate 
149*3ee4fc2aSCody Peter Mello /*
150*3ee4fc2aSCody Peter Mello  * POSIX specifies that fields are supposed to be evaluated as if they were
151*3ee4fc2aSCody Peter Mello  * split using the value of FS at the time that the record's value ($0) was
152*3ee4fc2aSCody Peter Mello  * read.
153*3ee4fc2aSCody Peter Mello  *
154*3ee4fc2aSCody Peter Mello  * Since field-splitting is done lazily, we save the current value of FS
155*3ee4fc2aSCody Peter Mello  * whenever a new record is read in (implicitly or via getline), or when
156*3ee4fc2aSCody Peter Mello  * a new value is assigned to $0.
157*3ee4fc2aSCody Peter Mello  */
158*3ee4fc2aSCody Peter Mello void
savefs(void)159*3ee4fc2aSCody Peter Mello savefs(void)
160*3ee4fc2aSCody Peter Mello {
161*3ee4fc2aSCody Peter Mello 	if (strlen(getsval(fsloc)) >= sizeof (inputFS))
162*3ee4fc2aSCody Peter Mello 		FATAL("field separator %.10s... is too long", *FS);
163*3ee4fc2aSCody Peter Mello 	(void) strcpy(inputFS, *FS);
164*3ee4fc2aSCody Peter Mello }
165*3ee4fc2aSCody Peter Mello 
166*3ee4fc2aSCody Peter Mello static int firsttime = 1;
167*3ee4fc2aSCody Peter Mello 
168*3ee4fc2aSCody Peter Mello /*
169*3ee4fc2aSCody Peter Mello  * get next input record
170*3ee4fc2aSCody Peter Mello  * note: cares whether buf == record
171*3ee4fc2aSCody Peter Mello  */
1721ee2e5faSnakanon int
getrec(char ** pbuf,size_t * pbufsize,int isrecord)173*3ee4fc2aSCody Peter Mello getrec(char **pbuf, size_t *pbufsize, int isrecord)
1747c478bd9Sstevel@tonic-gate {
1757c478bd9Sstevel@tonic-gate 	int c;
176*3ee4fc2aSCody Peter Mello 	char *buf = *pbuf;
177*3ee4fc2aSCody Peter Mello 	uschar saveb0;
178*3ee4fc2aSCody Peter Mello 	size_t bufsize = *pbufsize, savebufsize = bufsize;
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	if (firsttime) {
1817c478bd9Sstevel@tonic-gate 		firsttime = 0;
1827c478bd9Sstevel@tonic-gate 		initgetrec();
1837c478bd9Sstevel@tonic-gate 	}
1847c478bd9Sstevel@tonic-gate 	dprintf(("RS=<%s>, FS=<%s>, ARGC=%f, FILENAME=%s\n",
1851ee2e5faSnakanon 	    *RS, *FS, *ARGC, *FILENAME));
186*3ee4fc2aSCody Peter Mello 	if (isrecord) {
187*3ee4fc2aSCody Peter Mello 		donefld = 0;
188*3ee4fc2aSCody Peter Mello 		donerec = 1;
189*3ee4fc2aSCody Peter Mello 		savefs();
190*3ee4fc2aSCody Peter Mello 	}
191*3ee4fc2aSCody Peter Mello 	saveb0 = buf[0];
192*3ee4fc2aSCody Peter Mello 	buf[0] = '\0';
1937c478bd9Sstevel@tonic-gate 	while (argno < *ARGC || infile == stdin) {
1947c478bd9Sstevel@tonic-gate 		dprintf(("argno=%d, file=|%s|\n", argno, file));
1957c478bd9Sstevel@tonic-gate 		if (infile == NULL) {	/* have to open a new file */
1967c478bd9Sstevel@tonic-gate 			file = getargv(argno);
197*3ee4fc2aSCody Peter Mello 			if (file == NULL || *file == '\0') {
198*3ee4fc2aSCody Peter Mello 				/* deleted or zapped */
1997c478bd9Sstevel@tonic-gate 				argno++;
2007c478bd9Sstevel@tonic-gate 				continue;
2017c478bd9Sstevel@tonic-gate 			}
202*3ee4fc2aSCody Peter Mello 			if (isclvar(file)) {
203*3ee4fc2aSCody Peter Mello 				/* a var=value arg */
2047c478bd9Sstevel@tonic-gate 				setclvar(file);
2057c478bd9Sstevel@tonic-gate 				argno++;
2067c478bd9Sstevel@tonic-gate 				continue;
2077c478bd9Sstevel@tonic-gate 			}
2087c478bd9Sstevel@tonic-gate 			*FILENAME = file;
2097c478bd9Sstevel@tonic-gate 			dprintf(("opening file %s\n", file));
2107c478bd9Sstevel@tonic-gate 			if (*file == '-' && *(file+1) == '\0')
2117c478bd9Sstevel@tonic-gate 				infile = stdin;
212*3ee4fc2aSCody Peter Mello 			else if ((infile = fopen(file, "rF")) == NULL)
213*3ee4fc2aSCody Peter Mello 				FATAL("can't open file %s", file);
2141ee2e5faSnakanon 			(void) setfval(fnrloc, 0.0);
2157c478bd9Sstevel@tonic-gate 		}
216*3ee4fc2aSCody Peter Mello 		c = readrec(&buf, &bufsize, infile);
2171ee2e5faSnakanon 
2187c478bd9Sstevel@tonic-gate 		if (c != 0 || buf[0] != '\0') {	/* normal record */
219*3ee4fc2aSCody Peter Mello 			if (isrecord) {
220*3ee4fc2aSCody Peter Mello 				if (freeable(recloc))
2217c478bd9Sstevel@tonic-gate 					xfree(recloc->sval);
222*3ee4fc2aSCody Peter Mello 				recloc->sval = buf;	/* buf == record */
2237c478bd9Sstevel@tonic-gate 				recloc->tval = REC | STR | DONTFREE;
2241ee2e5faSnakanon 				if (is_number(recloc->sval)) {
2251ee2e5faSnakanon 					recloc->fval =
226*3ee4fc2aSCody Peter Mello 					    atof(recloc->sval);
2277c478bd9Sstevel@tonic-gate 					recloc->tval |= NUM;
2287c478bd9Sstevel@tonic-gate 				}
2297c478bd9Sstevel@tonic-gate 			}
2301ee2e5faSnakanon 			(void) setfval(nrloc, nrloc->fval+1);
2311ee2e5faSnakanon 			(void) setfval(fnrloc, fnrloc->fval+1);
232*3ee4fc2aSCody Peter Mello 			*pbuf = buf;
233*3ee4fc2aSCody Peter Mello 			*pbufsize = bufsize;
2347c478bd9Sstevel@tonic-gate 			return (1);
2357c478bd9Sstevel@tonic-gate 		}
2367c478bd9Sstevel@tonic-gate 		/* EOF arrived on this file; set up next */
2377c478bd9Sstevel@tonic-gate 		if (infile != stdin)
2381ee2e5faSnakanon 			(void) fclose(infile);
2397c478bd9Sstevel@tonic-gate 		infile = NULL;
2407c478bd9Sstevel@tonic-gate 		argno++;
2417c478bd9Sstevel@tonic-gate 	}
242*3ee4fc2aSCody Peter Mello 	buf[0] = saveb0;
243*3ee4fc2aSCody Peter Mello 	*pbuf = buf;
244*3ee4fc2aSCody Peter Mello 	*pbufsize = savebufsize;
2457c478bd9Sstevel@tonic-gate 	return (0);	/* true end of file */
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate 
248*3ee4fc2aSCody Peter Mello void
nextfile(void)249*3ee4fc2aSCody Peter Mello nextfile(void)
250*3ee4fc2aSCody Peter Mello {
251*3ee4fc2aSCody Peter Mello 	if (infile != NULL && infile != stdin)
252*3ee4fc2aSCody Peter Mello 		(void) fclose(infile);
253*3ee4fc2aSCody Peter Mello 	infile = NULL;
254*3ee4fc2aSCody Peter Mello 	argno++;
255*3ee4fc2aSCody Peter Mello }
256*3ee4fc2aSCody Peter Mello 
257*3ee4fc2aSCody Peter Mello /*
258*3ee4fc2aSCody Peter Mello  * read one record into buf
259*3ee4fc2aSCody Peter Mello  */
2601ee2e5faSnakanon int
readrec(char ** pbuf,size_t * pbufsize,FILE * inf)261*3ee4fc2aSCody Peter Mello readrec(char **pbuf, size_t *pbufsize, FILE *inf)
2627c478bd9Sstevel@tonic-gate {
263cb4658fbSceastha 	int sep, c;
264*3ee4fc2aSCody Peter Mello 	char *rr, *rt, *buf = *pbuf;
265*3ee4fc2aSCody Peter Mello 	size_t bufsize = *pbufsize;
266*3ee4fc2aSCody Peter Mello 	char *rs = getsval(rsloc);
267*3ee4fc2aSCody Peter Mello 
268*3ee4fc2aSCody Peter Mello 	if (rtbuf == NULL && (rtbuf = malloc(rtbufsize)) == NULL)
269*3ee4fc2aSCody Peter Mello 		FATAL("out of memory in readrec");
2707c478bd9Sstevel@tonic-gate 
271*3ee4fc2aSCody Peter Mello 	rr = buf;
272*3ee4fc2aSCody Peter Mello 	rt = rtbuf;
273*3ee4fc2aSCody Peter Mello 
274*3ee4fc2aSCody Peter Mello 	if ((sep = *rs) == '\0') {
2757c478bd9Sstevel@tonic-gate 		sep = '\n';
2767c478bd9Sstevel@tonic-gate 		/* skip leading \n's */
2777c478bd9Sstevel@tonic-gate 		while ((c = getc(inf)) == '\n' && c != EOF)
2787c478bd9Sstevel@tonic-gate 			;
2797c478bd9Sstevel@tonic-gate 		if (c != EOF)
2801ee2e5faSnakanon 			(void) ungetc(c, inf);
2817c478bd9Sstevel@tonic-gate 	}
282*3ee4fc2aSCody Peter Mello 	while ((c = getc(inf)) != EOF) {
283*3ee4fc2aSCody Peter Mello 		if (c != sep) {
284*3ee4fc2aSCody Peter Mello 			if (rr-buf+1 > bufsize) {
285*3ee4fc2aSCody Peter Mello 				(void) adjbuf(&buf, &bufsize,
286*3ee4fc2aSCody Peter Mello 				    1+rr-buf, recsize, &rr, "readrec1");
287*3ee4fc2aSCody Peter Mello 			}
288*3ee4fc2aSCody Peter Mello 			*rr++ = c;
289*3ee4fc2aSCody Peter Mello 			continue;
290*3ee4fc2aSCody Peter Mello 		}
291*3ee4fc2aSCody Peter Mello 
292*3ee4fc2aSCody Peter Mello 		/*
293*3ee4fc2aSCody Peter Mello 		 * Ensure enough space for either a single separator
294*3ee4fc2aSCody Peter Mello 		 * character, or at least two '\n' chars (when RS is
295*3ee4fc2aSCody Peter Mello 		 * the empty string).
296*3ee4fc2aSCody Peter Mello 		 */
297*3ee4fc2aSCody Peter Mello 		(void) adjbuf(&rtbuf, &rtbufsize,
298*3ee4fc2aSCody Peter Mello 		    2+rt-rtbuf, recsize, &rt, "readrec2");
299*3ee4fc2aSCody Peter Mello 
300*3ee4fc2aSCody Peter Mello 		if (*rs == sep) {
301*3ee4fc2aSCody Peter Mello 			*rt++ = sep;
302*3ee4fc2aSCody Peter Mello 			break;
3037c478bd9Sstevel@tonic-gate 		}
304*3ee4fc2aSCody Peter Mello 
305*3ee4fc2aSCody Peter Mello 		if ((c = getc(inf)) == '\n') { /* 2 in a row */
306*3ee4fc2aSCody Peter Mello 			*rt++ = '\n';
307*3ee4fc2aSCody Peter Mello 			*rt++ = '\n';
308*3ee4fc2aSCody Peter Mello 			while ((c = getc(inf)) == '\n' && c != EOF) {
309*3ee4fc2aSCody Peter Mello 				/* Read any further \n's and add them to RT. */
310*3ee4fc2aSCody Peter Mello 				(void) adjbuf(&rtbuf, &rtbufsize,
311*3ee4fc2aSCody Peter Mello 				    1+rt-rtbuf, recsize, &rt, "readrec3");
312*3ee4fc2aSCody Peter Mello 				*rt++ = '\n';
313*3ee4fc2aSCody Peter Mello 			}
314*3ee4fc2aSCody Peter Mello 			if (c != EOF)
315*3ee4fc2aSCody Peter Mello 				(void) ungetc(c, inf);
3167c478bd9Sstevel@tonic-gate 			break;
317*3ee4fc2aSCody Peter Mello 		}
318*3ee4fc2aSCody Peter Mello 
319*3ee4fc2aSCody Peter Mello 		if (c == EOF) {
320*3ee4fc2aSCody Peter Mello 			*rt++ = '\n';
3217c478bd9Sstevel@tonic-gate 			break;
322*3ee4fc2aSCody Peter Mello 		}
323*3ee4fc2aSCody Peter Mello 
324*3ee4fc2aSCody Peter Mello 		(void) adjbuf(&buf, &bufsize,
325*3ee4fc2aSCody Peter Mello 		    2+rr-buf, recsize, &rr, "readrec4");
326*3ee4fc2aSCody Peter Mello 		*rr++ = '\n';
327*3ee4fc2aSCody Peter Mello 		*rr++ = c;
3287c478bd9Sstevel@tonic-gate 	}
329*3ee4fc2aSCody Peter Mello 	(void) adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec5");
330*3ee4fc2aSCody Peter Mello 	(void) adjbuf(&rtbuf, &rtbufsize, 1+rt-rtbuf, recsize, &rt, "readrec6");
331*3ee4fc2aSCody Peter Mello 	*rr = '\0';
332*3ee4fc2aSCody Peter Mello 	*rt = '\0';
3337c478bd9Sstevel@tonic-gate 	dprintf(("readrec saw <%s>, returns %d\n",
334*3ee4fc2aSCody Peter Mello 	    buf, c == EOF && rr == buf ? 0 : 1));
335*3ee4fc2aSCody Peter Mello 	*pbuf = buf;
336*3ee4fc2aSCody Peter Mello 	*pbufsize = bufsize;
337*3ee4fc2aSCody Peter Mello 	if (c == EOF && rr == buf) {
338*3ee4fc2aSCody Peter Mello 		return (0);
339*3ee4fc2aSCody Peter Mello 	} else {
340*3ee4fc2aSCody Peter Mello 		(void) setsval(rtloc, rtbuf);
341*3ee4fc2aSCody Peter Mello 		return (1);
342*3ee4fc2aSCody Peter Mello 	}
3437c478bd9Sstevel@tonic-gate }
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate /* get ARGV[n] */
346*3ee4fc2aSCody Peter Mello static char *
getargv(int n)3471ee2e5faSnakanon getargv(int n)
3487c478bd9Sstevel@tonic-gate {
3497c478bd9Sstevel@tonic-gate 	Cell *x;
350*3ee4fc2aSCody Peter Mello 	char *s, temp[50];
3517c478bd9Sstevel@tonic-gate 	extern Array *ARGVtab;
3527c478bd9Sstevel@tonic-gate 
353*3ee4fc2aSCody Peter Mello 	(void) sprintf(temp, "%d", n);
354*3ee4fc2aSCody Peter Mello 	if (lookup(temp, ARGVtab) == NULL)
355*3ee4fc2aSCody Peter Mello 		return (NULL);
356*3ee4fc2aSCody Peter Mello 	x = setsymtab(temp, "", 0.0, STR, ARGVtab);
3577c478bd9Sstevel@tonic-gate 	s = getsval(x);
3587c478bd9Sstevel@tonic-gate 	dprintf(("getargv(%d) returns |%s|\n", n, s));
3597c478bd9Sstevel@tonic-gate 	return (s);
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate 
3621ee2e5faSnakanon void
setclvar(char * s)363*3ee4fc2aSCody Peter Mello setclvar(char *s)	/* set var=value from s */
3647c478bd9Sstevel@tonic-gate {
365*3ee4fc2aSCody Peter Mello 	char *p;
3667c478bd9Sstevel@tonic-gate 	Cell *q;
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	for (p = s; *p != '='; p++)
3697c478bd9Sstevel@tonic-gate 		;
3707c478bd9Sstevel@tonic-gate 	*p++ = 0;
3717c478bd9Sstevel@tonic-gate 	p = qstring(p, '\0');
3727c478bd9Sstevel@tonic-gate 	q = setsymtab(s, p, 0.0, STR, symtab);
3731ee2e5faSnakanon 	(void) setsval(q, p);
3741ee2e5faSnakanon 	if (is_number(q->sval)) {
375*3ee4fc2aSCody Peter Mello 		q->fval = atof(q->sval);
3767c478bd9Sstevel@tonic-gate 		q->tval |= NUM;
3777c478bd9Sstevel@tonic-gate 	}
3787c478bd9Sstevel@tonic-gate 	dprintf(("command line set %s to |%s|\n", s, p));
3791ee2e5faSnakanon 	free(p);
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate 
3821ee2e5faSnakanon void
fldbld(void)383*3ee4fc2aSCody Peter Mello fldbld(void)	/* create fields from current record */
3847c478bd9Sstevel@tonic-gate {
385*3ee4fc2aSCody Peter Mello 	/* this relies on having fields[] the same length as $0 */
386*3ee4fc2aSCody Peter Mello 	/* the fields are all stored in this one array with \0's */
387*3ee4fc2aSCody Peter Mello 	/* possibly with a final trailing \0 not associated with any field */
388*3ee4fc2aSCody Peter Mello 	char *r, *fr, sep;
3897c478bd9Sstevel@tonic-gate 	Cell *p;
390*3ee4fc2aSCody Peter Mello 	int i, j, n;
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	if (donefld)
3937c478bd9Sstevel@tonic-gate 		return;
394*3ee4fc2aSCody Peter Mello 	if (!isstr(fldtab[0]))
395*3ee4fc2aSCody Peter Mello 		(void) getsval(fldtab[0]);
396*3ee4fc2aSCody Peter Mello 	r = fldtab[0]->sval;
397*3ee4fc2aSCody Peter Mello 	n = strlen(r);
398*3ee4fc2aSCody Peter Mello 	if (n > fieldssize) {
399*3ee4fc2aSCody Peter Mello 		xfree(fields);
400*3ee4fc2aSCody Peter Mello 		/* possibly 2 final \0s */
401*3ee4fc2aSCody Peter Mello 		if ((fields = (char *)malloc(n + 2)) == NULL)
402*3ee4fc2aSCody Peter Mello 			FATAL("out of space for fields in fldbld %d", n);
403*3ee4fc2aSCody Peter Mello 		fieldssize = n;
404*3ee4fc2aSCody Peter Mello 	}
4057c478bd9Sstevel@tonic-gate 	fr = fields;
4061ee2e5faSnakanon 
4077c478bd9Sstevel@tonic-gate 	i = 0;	/* number of fields accumulated here */
408*3ee4fc2aSCody Peter Mello 	if (strlen(inputFS) > 1) {	/* it's a regular expression */
409*3ee4fc2aSCody Peter Mello 		i = refldbld(r, inputFS);
410*3ee4fc2aSCody Peter Mello 	} else if ((sep = *inputFS) == ' ') {	/* default whitespace */
4117c478bd9Sstevel@tonic-gate 		for (i = 0; ; ) {
4127c478bd9Sstevel@tonic-gate 			while (*r == ' ' || *r == '\t' || *r == '\n')
4137c478bd9Sstevel@tonic-gate 				r++;
414*3ee4fc2aSCody Peter Mello 			if (*r == '\0')
4157c478bd9Sstevel@tonic-gate 				break;
4167c478bd9Sstevel@tonic-gate 			i++;
417*3ee4fc2aSCody Peter Mello 			if (i > nfields)
418*3ee4fc2aSCody Peter Mello 				growfldtab(i);
419*3ee4fc2aSCody Peter Mello 			if (freeable(fldtab[i]))
420*3ee4fc2aSCody Peter Mello 				xfree(fldtab[i]->sval);
421*3ee4fc2aSCody Peter Mello 			fldtab[i]->sval = fr;
422*3ee4fc2aSCody Peter Mello 			fldtab[i]->tval = FLD | STR | DONTFREE;
4237c478bd9Sstevel@tonic-gate 			do
4247c478bd9Sstevel@tonic-gate 				*fr++ = *r++;
4257c478bd9Sstevel@tonic-gate 			while (*r != ' ' && *r != '\t' && *r != '\n' &&
4261ee2e5faSnakanon 			    *r != '\0')
4271ee2e5faSnakanon 				;
428*3ee4fc2aSCody Peter Mello 			*fr++ = '\0';
429*3ee4fc2aSCody Peter Mello 		}
430*3ee4fc2aSCody Peter Mello 		*fr = '\0';
431*3ee4fc2aSCody Peter Mello 	} else if ((sep = *inputFS) == '\0') {
432*3ee4fc2aSCody Peter Mello 		/* new: FS="" => 1 char/field */
433*3ee4fc2aSCody Peter Mello 		for (i = 0; *r != '\0'; r++) {
434*3ee4fc2aSCody Peter Mello 			char buf[2];
435*3ee4fc2aSCody Peter Mello 			i++;
436*3ee4fc2aSCody Peter Mello 			if (i > nfields)
437*3ee4fc2aSCody Peter Mello 				growfldtab(i);
438*3ee4fc2aSCody Peter Mello 			if (freeable(fldtab[i]))
439*3ee4fc2aSCody Peter Mello 				xfree(fldtab[i]->sval);
440*3ee4fc2aSCody Peter Mello 			buf[0] = *r;
441*3ee4fc2aSCody Peter Mello 			buf[1] = '\0';
442*3ee4fc2aSCody Peter Mello 			fldtab[i]->sval = tostring(buf);
443*3ee4fc2aSCody Peter Mello 			fldtab[i]->tval = FLD | STR;
4447c478bd9Sstevel@tonic-gate 		}
445*3ee4fc2aSCody Peter Mello 		*fr = '\0';
446*3ee4fc2aSCody Peter Mello 	} else if (*r != '\0') {	/* if 0, it's a null field */
447*3ee4fc2aSCody Peter Mello 		/*
448*3ee4fc2aSCody Peter Mello 		 * subtlecase : if length(FS) == 1 && length(RS > 0)
449*3ee4fc2aSCody Peter Mello 		 * \n is NOT a field separator (cf awk book 61,84).
450*3ee4fc2aSCody Peter Mello 		 * this variable is tested in the inner while loop.
451*3ee4fc2aSCody Peter Mello 		 */
452*3ee4fc2aSCody Peter Mello 		int rtest = '\n';  /* normal case */
453*3ee4fc2aSCody Peter Mello 		if (strlen(*RS) > 0)
454*3ee4fc2aSCody Peter Mello 			rtest = '\0';
4557c478bd9Sstevel@tonic-gate 		for (;;) {
4567c478bd9Sstevel@tonic-gate 			i++;
457*3ee4fc2aSCody Peter Mello 			if (i > nfields)
458*3ee4fc2aSCody Peter Mello 				growfldtab(i);
459*3ee4fc2aSCody Peter Mello 			if (freeable(fldtab[i]))
460*3ee4fc2aSCody Peter Mello 				xfree(fldtab[i]->sval);
461*3ee4fc2aSCody Peter Mello 			fldtab[i]->sval = fr;
462*3ee4fc2aSCody Peter Mello 			fldtab[i]->tval = FLD | STR | DONTFREE;
463*3ee4fc2aSCody Peter Mello 			/* \n is always a separator */
464*3ee4fc2aSCody Peter Mello 			while (*r != sep && *r != rtest && *r != '\0')
4657c478bd9Sstevel@tonic-gate 				*fr++ = *r++;
466*3ee4fc2aSCody Peter Mello 			*fr++ = '\0';
467*3ee4fc2aSCody Peter Mello 			if (*r++ == '\0')
4687c478bd9Sstevel@tonic-gate 				break;
4697c478bd9Sstevel@tonic-gate 		}
470*3ee4fc2aSCody Peter Mello 		*fr = '\0';
4717c478bd9Sstevel@tonic-gate 	}
472*3ee4fc2aSCody Peter Mello 	if (i > nfields)
473*3ee4fc2aSCody Peter Mello 		FATAL("record `%.30s...' has too many fields; can't happen", r);
4747c478bd9Sstevel@tonic-gate 	/* clean out junk from previous record */
475*3ee4fc2aSCody Peter Mello 	cleanfld(i+1, lastfld);
476*3ee4fc2aSCody Peter Mello 	lastfld = i;
4777c478bd9Sstevel@tonic-gate 	donefld = 1;
478*3ee4fc2aSCody Peter Mello 	for (j = 1; j <= lastfld; j++) {
479*3ee4fc2aSCody Peter Mello 		p = fldtab[j];
4801ee2e5faSnakanon 		if (is_number(p->sval)) {
481*3ee4fc2aSCody Peter Mello 			p->fval = atof(p->sval);
4827c478bd9Sstevel@tonic-gate 			p->tval |= NUM;
4837c478bd9Sstevel@tonic-gate 		}
4847c478bd9Sstevel@tonic-gate 	}
485*3ee4fc2aSCody Peter Mello 	(void) setfval(nfloc, (Awkfloat)lastfld);
486*3ee4fc2aSCody Peter Mello 	donerec = 1; /* restore */
4871ee2e5faSnakanon 	if (dbg) {
488*3ee4fc2aSCody Peter Mello 		for (j = 0; j <= lastfld; j++) {
489*3ee4fc2aSCody Peter Mello 			p = fldtab[j];
490*3ee4fc2aSCody Peter Mello 			(void) printf("field %d (%s): |%s|\n",
491*3ee4fc2aSCody Peter Mello 			    j, p->nval, p->sval);
4921ee2e5faSnakanon 		}
4931ee2e5faSnakanon 	}
4947c478bd9Sstevel@tonic-gate }
4957c478bd9Sstevel@tonic-gate 
496*3ee4fc2aSCody Peter Mello /* clean out fields n1 .. n2 inclusive; nvals remain intact */
4971ee2e5faSnakanon static void
cleanfld(int n1,int n2)498*3ee4fc2aSCody Peter Mello cleanfld(int n1, int n2)
4997c478bd9Sstevel@tonic-gate {
500cb4658fbSceastha 	Cell *p;
501*3ee4fc2aSCody Peter Mello 	int i;
5027c478bd9Sstevel@tonic-gate 
503*3ee4fc2aSCody Peter Mello 	for (i = n1; i <= n2; i++) {
504*3ee4fc2aSCody Peter Mello 		p = fldtab[i];
505*3ee4fc2aSCody Peter Mello 		if (freeable(p))
5067c478bd9Sstevel@tonic-gate 			xfree(p->sval);
507*3ee4fc2aSCody Peter Mello 		p->sval = "";
5087c478bd9Sstevel@tonic-gate 		p->tval = FLD | STR | DONTFREE;
5097c478bd9Sstevel@tonic-gate 	}
5107c478bd9Sstevel@tonic-gate }
5117c478bd9Sstevel@tonic-gate 
5121ee2e5faSnakanon void
newfld(int n)513*3ee4fc2aSCody Peter Mello newfld(int n)	/* add field n after end of existing lastfld */
5147c478bd9Sstevel@tonic-gate {
515*3ee4fc2aSCody Peter Mello 	if (n > nfields)
516*3ee4fc2aSCody Peter Mello 		growfldtab(n);
517*3ee4fc2aSCody Peter Mello 	cleanfld(lastfld+1, n);
518*3ee4fc2aSCody Peter Mello 	lastfld = n;
519*3ee4fc2aSCody Peter Mello 	(void) setfval(nfloc, (Awkfloat)n);
5207c478bd9Sstevel@tonic-gate }
5217c478bd9Sstevel@tonic-gate 
522*3ee4fc2aSCody Peter Mello void
setlastfld(int n)523*3ee4fc2aSCody Peter Mello setlastfld(int n)	/* set lastfld cleaning fldtab cells if necessary */
5241ee2e5faSnakanon {
525*3ee4fc2aSCody Peter Mello 	if (n < 0)
526*3ee4fc2aSCody Peter Mello 		FATAL("cannot set NF to a negative value");
527*3ee4fc2aSCody Peter Mello 	if (n > nfields)
528*3ee4fc2aSCody Peter Mello 		growfldtab(n);
529*3ee4fc2aSCody Peter Mello 
530*3ee4fc2aSCody Peter Mello 	if (lastfld < n)
531*3ee4fc2aSCody Peter Mello 		cleanfld(lastfld+1, n);
5321ee2e5faSnakanon 	else
533*3ee4fc2aSCody Peter Mello 		cleanfld(n+1, lastfld);
5341ee2e5faSnakanon 
535*3ee4fc2aSCody Peter Mello 	lastfld = n;
5361ee2e5faSnakanon }
5371ee2e5faSnakanon 
5381ee2e5faSnakanon Cell *
fieldadr(int n)539*3ee4fc2aSCody Peter Mello fieldadr(int n)	/* get nth field */
5401ee2e5faSnakanon {
541*3ee4fc2aSCody Peter Mello 	if (n < 0)
542*3ee4fc2aSCody Peter Mello 		FATAL("trying to access out of range field %d", n);
543*3ee4fc2aSCody Peter Mello 	if (n > nfields)	/* fields after NF are empty */
544*3ee4fc2aSCody Peter Mello 		growfldtab(n);	/* but does not increase NF */
545*3ee4fc2aSCody Peter Mello 	return (fldtab[n]);
5461ee2e5faSnakanon }
5471ee2e5faSnakanon 
548*3ee4fc2aSCody Peter Mello void
growfldtab(int n)549*3ee4fc2aSCody Peter Mello growfldtab(int n)	/* make new fields up to at least $n */
5501ee2e5faSnakanon {
551*3ee4fc2aSCody Peter Mello 	int nf = 2 * nfields;
552*3ee4fc2aSCody Peter Mello 	size_t s;
553*3ee4fc2aSCody Peter Mello 
554*3ee4fc2aSCody Peter Mello 	if (n > nf)
555*3ee4fc2aSCody Peter Mello 		nf = n;
556*3ee4fc2aSCody Peter Mello 	s = (nf+1) * (sizeof (Cell *));  /* freebsd: how much do we need? */
557*3ee4fc2aSCody Peter Mello 	if (s / sizeof (Cell *) - 1 == nf) /* didn't overflow */
558*3ee4fc2aSCody Peter Mello 		fldtab = (Cell **)realloc(fldtab, s);
559*3ee4fc2aSCody Peter Mello 	else					/* overflow sizeof int */
560*3ee4fc2aSCody Peter Mello 		xfree(fldtab);	/* make it null */
561*3ee4fc2aSCody Peter Mello 	if (fldtab == NULL)
562*3ee4fc2aSCody Peter Mello 		FATAL("out of space creating %d fields", nf);
563*3ee4fc2aSCody Peter Mello 	makefields(nfields+1, nf);
564*3ee4fc2aSCody Peter Mello 	nfields = nf;
5651ee2e5faSnakanon }
5661ee2e5faSnakanon 
567*3ee4fc2aSCody Peter Mello /* build fields from reg expr in FS */
5681ee2e5faSnakanon static int
refldbld(const char * rec,const char * fs)569*3ee4fc2aSCody Peter Mello refldbld(const char *rec, const char *fs)
5707c478bd9Sstevel@tonic-gate {
571*3ee4fc2aSCody Peter Mello 	/* this relies on having fields[] the same length as $0 */
572*3ee4fc2aSCody Peter Mello 	/* the fields are all stored in this one array with \0's */
573*3ee4fc2aSCody Peter Mello 	char *fr;
574*3ee4fc2aSCody Peter Mello 	int i, tempstat, n;
5757c478bd9Sstevel@tonic-gate 	fa *pfa;
5767c478bd9Sstevel@tonic-gate 
577*3ee4fc2aSCody Peter Mello 	n = strlen(rec);
578*3ee4fc2aSCody Peter Mello 	if (n > fieldssize) {
579*3ee4fc2aSCody Peter Mello 		xfree(fields);
580*3ee4fc2aSCody Peter Mello 		if ((fields = (char *)malloc(n+1)) == NULL)
581*3ee4fc2aSCody Peter Mello 			FATAL("out of space for fields in refldbld %d", n);
582*3ee4fc2aSCody Peter Mello 		fieldssize = n;
583*3ee4fc2aSCody Peter Mello 	}
5847c478bd9Sstevel@tonic-gate 	fr = fields;
5857c478bd9Sstevel@tonic-gate 	*fr = '\0';
5867c478bd9Sstevel@tonic-gate 	if (*rec == '\0')
5877c478bd9Sstevel@tonic-gate 		return (0);
5887c478bd9Sstevel@tonic-gate 	pfa = makedfa(fs, 1);
5897c478bd9Sstevel@tonic-gate 	dprintf(("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs));
5907c478bd9Sstevel@tonic-gate 	tempstat = pfa->initstat;
5911ee2e5faSnakanon 	for (i = 1; ; i++) {
592*3ee4fc2aSCody Peter Mello 		if (i > nfields)
593*3ee4fc2aSCody Peter Mello 			growfldtab(i);
594*3ee4fc2aSCody Peter Mello 		if (freeable(fldtab[i]))
595*3ee4fc2aSCody Peter Mello 			xfree(fldtab[i]->sval);
596*3ee4fc2aSCody Peter Mello 		fldtab[i]->tval = FLD | STR | DONTFREE;
597*3ee4fc2aSCody Peter Mello 		fldtab[i]->sval = fr;
5987c478bd9Sstevel@tonic-gate 		dprintf(("refldbld: i=%d\n", i));
5997c478bd9Sstevel@tonic-gate 		if (nematch(pfa, rec)) {
600*3ee4fc2aSCody Peter Mello 			pfa->initstat = 2;	/* horrible coupling to b.c */
6017c478bd9Sstevel@tonic-gate 			dprintf(("match %s (%d chars)\n", patbeg, patlen));
602*3ee4fc2aSCody Peter Mello 			(void) strncpy(fr, rec, patbeg-rec);
6037c478bd9Sstevel@tonic-gate 			fr += patbeg - rec + 1;
6047c478bd9Sstevel@tonic-gate 			*(fr-1) = '\0';
6057c478bd9Sstevel@tonic-gate 			rec = patbeg + patlen;
6067c478bd9Sstevel@tonic-gate 		} else {
6077c478bd9Sstevel@tonic-gate 			dprintf(("no match %s\n", rec));
608*3ee4fc2aSCody Peter Mello 			(void) strcpy(fr, rec);
6097c478bd9Sstevel@tonic-gate 			pfa->initstat = tempstat;
6107c478bd9Sstevel@tonic-gate 			break;
6117c478bd9Sstevel@tonic-gate 		}
6127c478bd9Sstevel@tonic-gate 	}
6137c478bd9Sstevel@tonic-gate 	return (i);
6147c478bd9Sstevel@tonic-gate }
6157c478bd9Sstevel@tonic-gate 
6161ee2e5faSnakanon void
recbld(void)617*3ee4fc2aSCody Peter Mello recbld(void)	/* create $0 from $1..$NF if necessary */
6187c478bd9Sstevel@tonic-gate {
6197c478bd9Sstevel@tonic-gate 	int i;
620*3ee4fc2aSCody Peter Mello 	char *p;
6211ee2e5faSnakanon 	size_t cnt, len, olen;
622*3ee4fc2aSCody Peter Mello 	char *sep = getsval(ofsloc);
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 	if (donerec == 1)
6257c478bd9Sstevel@tonic-gate 		return;
6261ee2e5faSnakanon 	cnt = 0;
627*3ee4fc2aSCody Peter Mello 	olen = strlen(sep);
6287c478bd9Sstevel@tonic-gate 	for (i = 1; i <= *NF; i++) {
629*3ee4fc2aSCody Peter Mello 		p = getsval(fldtab[i]);
630*3ee4fc2aSCody Peter Mello 		len = strlen(p);
631*3ee4fc2aSCody Peter Mello 		expand_buf(&record, &recsize, cnt + len + olen);
6328ef4c21aSnakanon 		(void) memcpy(&record[cnt], p, len);
6331ee2e5faSnakanon 		cnt += len;
6341ee2e5faSnakanon 		if (i < *NF) {
635*3ee4fc2aSCody Peter Mello 			(void) memcpy(&record[cnt], sep, olen);
6361ee2e5faSnakanon 			cnt += olen;
6371ee2e5faSnakanon 		}
6387c478bd9Sstevel@tonic-gate 	}
6398ef4c21aSnakanon 	record[cnt] = '\0';
640*3ee4fc2aSCody Peter Mello 	dprintf(("in recbld inputFS=%s, recloc=%p\n", inputFS, (void *)recloc));
641*3ee4fc2aSCody Peter Mello 	if (freeable(recloc))
6428ef4c21aSnakanon 		xfree(recloc->sval);
6437c478bd9Sstevel@tonic-gate 	recloc->tval = REC | STR | DONTFREE;
6448ef4c21aSnakanon 	recloc->sval = record;
645*3ee4fc2aSCody Peter Mello 	dprintf(("in recbld inputFS=%s, recloc=%p\n", inputFS, (void *)recloc));
6467c478bd9Sstevel@tonic-gate 	dprintf(("recbld = |%s|\n", record));
6477c478bd9Sstevel@tonic-gate 	donerec = 1;
6487c478bd9Sstevel@tonic-gate }
6497c478bd9Sstevel@tonic-gate 
650*3ee4fc2aSCody Peter Mello int	errorflag	= 0;
651*3ee4fc2aSCody Peter Mello 
652*3ee4fc2aSCody Peter Mello void
yyerror(const char * s)653*3ee4fc2aSCody Peter Mello yyerror(const char *s)
6547c478bd9Sstevel@tonic-gate {
655*3ee4fc2aSCody Peter Mello 	SYNTAX("%s", s);
6567c478bd9Sstevel@tonic-gate }
6577c478bd9Sstevel@tonic-gate 
6581ee2e5faSnakanon void
SYNTAX(const char * fmt,...)659*3ee4fc2aSCody Peter Mello SYNTAX(const char *fmt, ...)
6607c478bd9Sstevel@tonic-gate {
661*3ee4fc2aSCody Peter Mello 	extern char *cmdname, *curfname;
6627c478bd9Sstevel@tonic-gate 	static int been_here = 0;
663*3ee4fc2aSCody Peter Mello 	va_list varg;
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate 	if (been_here++ > 2)
6667c478bd9Sstevel@tonic-gate 		return;
667*3ee4fc2aSCody Peter Mello 	(void) fprintf(stderr, "%s: ", cmdname);
668*3ee4fc2aSCody Peter Mello 	va_start(varg, fmt);
669*3ee4fc2aSCody Peter Mello 	(void) vfprintf(stderr, fmt, varg);
670*3ee4fc2aSCody Peter Mello 	va_end(varg);
671*3ee4fc2aSCody Peter Mello 	(void) fprintf(stderr, " at source line %lld", lineno);
6727c478bd9Sstevel@tonic-gate 	if (curfname != NULL)
673*3ee4fc2aSCody Peter Mello 		(void) fprintf(stderr, " in function %s", curfname);
674*3ee4fc2aSCody Peter Mello 	if (compile_time == 1 && cursource() != NULL)
675*3ee4fc2aSCody Peter Mello 		(void) fprintf(stderr, " source file %s", cursource());
6761ee2e5faSnakanon 	(void) fprintf(stderr, "\n");
6777c478bd9Sstevel@tonic-gate 	errorflag = 2;
6787c478bd9Sstevel@tonic-gate 	eprint();
6797c478bd9Sstevel@tonic-gate }
6807c478bd9Sstevel@tonic-gate 
6811ee2e5faSnakanon void
fpecatch(int n)682*3ee4fc2aSCody Peter Mello fpecatch(int n)
6837c478bd9Sstevel@tonic-gate {
684*3ee4fc2aSCody Peter Mello 	FATAL("floating point exception %d", n);
6857c478bd9Sstevel@tonic-gate }
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate extern int bracecnt, brackcnt, parencnt;
6887c478bd9Sstevel@tonic-gate 
6891ee2e5faSnakanon void
bracecheck(void)6901ee2e5faSnakanon bracecheck(void)
6917c478bd9Sstevel@tonic-gate {
6927c478bd9Sstevel@tonic-gate 	int c;
6937c478bd9Sstevel@tonic-gate 	static int beenhere = 0;
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	if (beenhere++)
6967c478bd9Sstevel@tonic-gate 		return;
6977c478bd9Sstevel@tonic-gate 	while ((c = input()) != EOF && c != '\0')
6987c478bd9Sstevel@tonic-gate 		bclass(c);
6997c478bd9Sstevel@tonic-gate 	bcheck2(bracecnt, '{', '}');
7007c478bd9Sstevel@tonic-gate 	bcheck2(brackcnt, '[', ']');
7017c478bd9Sstevel@tonic-gate 	bcheck2(parencnt, '(', ')');
7027c478bd9Sstevel@tonic-gate }
7037c478bd9Sstevel@tonic-gate 
7041ee2e5faSnakanon /*ARGSUSED*/
7051ee2e5faSnakanon static void
bcheck2(int n,int c1,int c2)7061ee2e5faSnakanon bcheck2(int n, int c1, int c2)
7077c478bd9Sstevel@tonic-gate {
7087c478bd9Sstevel@tonic-gate 	if (n == 1)
7091ee2e5faSnakanon 		(void) fprintf(stderr, gettext("\tmissing %c\n"), c2);
7107c478bd9Sstevel@tonic-gate 	else if (n > 1)
7111ee2e5faSnakanon 		(void) fprintf(stderr, gettext("\t%d missing %c's\n"), n, c2);
7127c478bd9Sstevel@tonic-gate 	else if (n == -1)
7131ee2e5faSnakanon 		(void) fprintf(stderr, gettext("\textra %c\n"), c2);
7147c478bd9Sstevel@tonic-gate 	else if (n < -1)
7151ee2e5faSnakanon 		(void) fprintf(stderr, gettext("\t%d extra %c's\n"), -n, c2);
7167c478bd9Sstevel@tonic-gate }
7177c478bd9Sstevel@tonic-gate 
7181ee2e5faSnakanon void
FATAL(const char * fmt,...)719*3ee4fc2aSCody Peter Mello FATAL(const char *fmt, ...)
7207c478bd9Sstevel@tonic-gate {
721*3ee4fc2aSCody Peter Mello 	extern char *cmdname;
722*3ee4fc2aSCody Peter Mello 	va_list varg;
723*3ee4fc2aSCody Peter Mello 
724*3ee4fc2aSCody Peter Mello 	(void) fflush(stdout);
725*3ee4fc2aSCody Peter Mello 	(void) fprintf(stderr, "%s: ", cmdname);
726*3ee4fc2aSCody Peter Mello 	va_start(varg, fmt);
727*3ee4fc2aSCody Peter Mello 	(void) vfprintf(stderr, fmt, varg);
728*3ee4fc2aSCody Peter Mello 	va_end(varg);
729*3ee4fc2aSCody Peter Mello 	error();
730*3ee4fc2aSCody Peter Mello 	if (dbg > 1)		/* core dump if serious debugging on */
731*3ee4fc2aSCody Peter Mello 		abort();
732*3ee4fc2aSCody Peter Mello 	exit(2);
733*3ee4fc2aSCody Peter Mello }
734*3ee4fc2aSCody Peter Mello 
735*3ee4fc2aSCody Peter Mello void
WARNING(const char * fmt,...)736*3ee4fc2aSCody Peter Mello WARNING(const char *fmt, ...)
737*3ee4fc2aSCody Peter Mello {
738*3ee4fc2aSCody Peter Mello 	extern char *cmdname;
739*3ee4fc2aSCody Peter Mello 	va_list varg;
7407c478bd9Sstevel@tonic-gate 
7411ee2e5faSnakanon 	(void) fflush(stdout);
7421ee2e5faSnakanon 	(void) fprintf(stderr, "%s: ", cmdname);
743*3ee4fc2aSCody Peter Mello 	va_start(varg, fmt);
744*3ee4fc2aSCody Peter Mello 	(void) vfprintf(stderr, fmt, varg);
745*3ee4fc2aSCody Peter Mello 	va_end(varg);
746*3ee4fc2aSCody Peter Mello 	error();
747*3ee4fc2aSCody Peter Mello }
748*3ee4fc2aSCody Peter Mello 
749*3ee4fc2aSCody Peter Mello void
error(void)750*3ee4fc2aSCody Peter Mello error(void)
751*3ee4fc2aSCody Peter Mello {
752*3ee4fc2aSCody Peter Mello 	extern Node *curnode;
753*3ee4fc2aSCody Peter Mello 
7541ee2e5faSnakanon 	(void) fprintf(stderr, "\n");
7557c478bd9Sstevel@tonic-gate 	if (compile_time != 2 && NR && *NR > 0) {
7561ee2e5faSnakanon 		(void) fprintf(stderr,
7571ee2e5faSnakanon 		    gettext(" input record number %g"), *FNR);
758*3ee4fc2aSCody Peter Mello 		if (strcmp(*FILENAME, "-") != 0)
7591ee2e5faSnakanon 			(void) fprintf(stderr, gettext(", file %s"), *FILENAME);
7601ee2e5faSnakanon 		(void) fprintf(stderr, "\n");
7617c478bd9Sstevel@tonic-gate 	}
7627c478bd9Sstevel@tonic-gate 	if (compile_time != 2 && curnode)
763*3ee4fc2aSCody Peter Mello 		(void) fprintf(stderr, gettext(" source line number %lld"),
7647c478bd9Sstevel@tonic-gate 		    curnode->lineno);
7651ee2e5faSnakanon 	else if (compile_time != 2 && lineno) {
7661ee2e5faSnakanon 		(void) fprintf(stderr,
767*3ee4fc2aSCody Peter Mello 		    gettext(" source line number %lld"), lineno);
7681ee2e5faSnakanon 	}
769*3ee4fc2aSCody Peter Mello 	if (compile_time == 1 && cursource() != NULL)
770*3ee4fc2aSCody Peter Mello 		(void) fprintf(stderr, gettext(" source file %s"), cursource());
771*3ee4fc2aSCody Peter Mello 	(void) fprintf(stderr, "\n");
7727c478bd9Sstevel@tonic-gate 	eprint();
7737c478bd9Sstevel@tonic-gate }
7747c478bd9Sstevel@tonic-gate 
7751ee2e5faSnakanon static void
eprint(void)7761ee2e5faSnakanon eprint(void)	/* try to print context around error */
7777c478bd9Sstevel@tonic-gate {
778*3ee4fc2aSCody Peter Mello 	char *p, *q;
7797c478bd9Sstevel@tonic-gate 	int c;
7807c478bd9Sstevel@tonic-gate 	static int been_here = 0;
781*3ee4fc2aSCody Peter Mello 	extern char ebuf[], *ep;
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate 	if (compile_time == 2 || compile_time == 0 || been_here++ > 0)
7847c478bd9Sstevel@tonic-gate 		return;
785*3ee4fc2aSCody Peter Mello 	if (ebuf == ep)
786*3ee4fc2aSCody Peter Mello 		return;
7877c478bd9Sstevel@tonic-gate 	p = ep - 1;
7887c478bd9Sstevel@tonic-gate 	if (p > ebuf && *p == '\n')
7897c478bd9Sstevel@tonic-gate 		p--;
7907c478bd9Sstevel@tonic-gate 	for (; p > ebuf && *p != '\n' && *p != '\0'; p--)
7917c478bd9Sstevel@tonic-gate 		;
7927c478bd9Sstevel@tonic-gate 	while (*p == '\n')
7937c478bd9Sstevel@tonic-gate 		p++;
7941ee2e5faSnakanon 	(void) fprintf(stderr, gettext(" context is\n\t"));
7951ee2e5faSnakanon 	for (q = ep-1; q >= p && *q != ' ' && *q != '\t' && *q != '\n'; q--)
7967c478bd9Sstevel@tonic-gate 		;
7977c478bd9Sstevel@tonic-gate 	for (; p < q; p++)
7987c478bd9Sstevel@tonic-gate 		if (*p)
7991ee2e5faSnakanon 			(void) putc(*p, stderr);
8001ee2e5faSnakanon 	(void) fprintf(stderr, " >>> ");
8017c478bd9Sstevel@tonic-gate 	for (; p < ep; p++)
8027c478bd9Sstevel@tonic-gate 		if (*p)
8031ee2e5faSnakanon 			(void) putc(*p, stderr);
8041ee2e5faSnakanon 	(void) fprintf(stderr, " <<< ");
8057c478bd9Sstevel@tonic-gate 	if (*ep)
8067c478bd9Sstevel@tonic-gate 		while ((c = input()) != '\n' && c != '\0' && c != EOF) {
8071ee2e5faSnakanon 			(void) putc(c, stderr);
8087c478bd9Sstevel@tonic-gate 			bclass(c);
8097c478bd9Sstevel@tonic-gate 		}
8101ee2e5faSnakanon 	(void) putc('\n', stderr);
8117c478bd9Sstevel@tonic-gate 	ep = ebuf;
8127c478bd9Sstevel@tonic-gate }
8137c478bd9Sstevel@tonic-gate 
8141ee2e5faSnakanon static void
bclass(int c)8151ee2e5faSnakanon bclass(int c)
8167c478bd9Sstevel@tonic-gate {
8177c478bd9Sstevel@tonic-gate 	switch (c) {
8187c478bd9Sstevel@tonic-gate 	case '{': bracecnt++; break;
8197c478bd9Sstevel@tonic-gate 	case '}': bracecnt--; break;
8207c478bd9Sstevel@tonic-gate 	case '[': brackcnt++; break;
8217c478bd9Sstevel@tonic-gate 	case ']': brackcnt--; break;
8227c478bd9Sstevel@tonic-gate 	case '(': parencnt++; break;
8237c478bd9Sstevel@tonic-gate 	case ')': parencnt--; break;
8247c478bd9Sstevel@tonic-gate 	}
8257c478bd9Sstevel@tonic-gate }
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate double
errcheck(double x,const char * s)828*3ee4fc2aSCody Peter Mello errcheck(double x, const char *s)
8297c478bd9Sstevel@tonic-gate {
8307c478bd9Sstevel@tonic-gate 	if (errno == EDOM) {
8317c478bd9Sstevel@tonic-gate 		errno = 0;
832*3ee4fc2aSCody Peter Mello 		WARNING("%s argument out of domain", s);
8337c478bd9Sstevel@tonic-gate 		x = 1;
8347c478bd9Sstevel@tonic-gate 	} else if (errno == ERANGE) {
8357c478bd9Sstevel@tonic-gate 		errno = 0;
836*3ee4fc2aSCody Peter Mello 		WARNING("%s result out of range", s);
8377c478bd9Sstevel@tonic-gate 		x = 1;
8387c478bd9Sstevel@tonic-gate 	}
8397c478bd9Sstevel@tonic-gate 	return (x);
8407c478bd9Sstevel@tonic-gate }
8417c478bd9Sstevel@tonic-gate 
8421ee2e5faSnakanon int
isclvar(const char * s)843*3ee4fc2aSCody Peter Mello isclvar(const char *s)	/* is s of form var=something ? */
8447c478bd9Sstevel@tonic-gate {
845cb4658fbSceastha 	if (s != NULL) {
846cb4658fbSceastha 
847cb4658fbSceastha 		/* Must begin with an underscore or alphabetic character */
848cb4658fbSceastha 		if (isalpha(*s) || (*s == '_')) {
849cb4658fbSceastha 
850cb4658fbSceastha 			for (s++; *s; s++) {
851cb4658fbSceastha 				/*
852cb4658fbSceastha 				 * followed by a sequence of underscores,
853cb4658fbSceastha 				 * digits, and alphabetics
854cb4658fbSceastha 				 */
855cb4658fbSceastha 				if (!(isalnum(*s) || *s == '_')) {
856cb4658fbSceastha 					break;
857cb4658fbSceastha 				}
858cb4658fbSceastha 			}
859cb4658fbSceastha 			return (*s == '=' && *(s + 1) != '=');
860cb4658fbSceastha 		}
861cb4658fbSceastha 	}
8627c478bd9Sstevel@tonic-gate 
863cb4658fbSceastha 	return (0);
8647c478bd9Sstevel@tonic-gate }
8657c478bd9Sstevel@tonic-gate 
866*3ee4fc2aSCody Peter Mello #include <math.h>
8671ee2e5faSnakanon int
is_number(const char * s)868*3ee4fc2aSCody Peter Mello is_number(const char *s)
8697c478bd9Sstevel@tonic-gate {
870*3ee4fc2aSCody Peter Mello 	double r;
871*3ee4fc2aSCody Peter Mello 	char *ep;
872*3ee4fc2aSCody Peter Mello 	errno = 0;
873*3ee4fc2aSCody Peter Mello 	r = strtod(s, &ep);
874*3ee4fc2aSCody Peter Mello 	if (ep == s || r == HUGE_VAL || errno == ERANGE)
8757c478bd9Sstevel@tonic-gate 		return (0);
876*3ee4fc2aSCody Peter Mello 	while (*ep == ' ' || *ep == '\t' || *ep == '\n')
877*3ee4fc2aSCody Peter Mello 		ep++;
878*3ee4fc2aSCody Peter Mello 	if (*ep == '\0')
8797c478bd9Sstevel@tonic-gate 		return (1);
8807c478bd9Sstevel@tonic-gate 	else
8817c478bd9Sstevel@tonic-gate 		return (0);
8827c478bd9Sstevel@tonic-gate }
8831ee2e5faSnakanon 
8841ee2e5faSnakanon void
r_expand_buf(char ** optr,size_t * sizep,size_t req)885*3ee4fc2aSCody Peter Mello r_expand_buf(char **optr, size_t *sizep, size_t req)
8861ee2e5faSnakanon {
887*3ee4fc2aSCody Peter Mello 	char	*nptr;
8881ee2e5faSnakanon 	size_t	amt, size = *sizep;
8891ee2e5faSnakanon 
8901ee2e5faSnakanon 	if (size != 0 && req < (size - 1))
8911ee2e5faSnakanon 		return;
8921ee2e5faSnakanon 	amt = req + 1 - size;
8931ee2e5faSnakanon 	amt = (amt / LINE_INCR + 1) * LINE_INCR;
8941ee2e5faSnakanon 
8951ee2e5faSnakanon 	if ((nptr = realloc(*optr, size + amt)) == NULL)
896*3ee4fc2aSCody Peter Mello 		FATAL("out of space in expand_buf");
8971ee2e5faSnakanon 	/* initial buffer should have NULL terminated */
8981ee2e5faSnakanon 	if (size == 0)
8991ee2e5faSnakanon 		*nptr = '\0';
9001ee2e5faSnakanon 	*sizep += amt;
9011ee2e5faSnakanon 	*optr = nptr;
9021ee2e5faSnakanon }
903