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