Blame


1 63a68686 2008-11-03 jas /****************************************************************
2 63a68686 2008-11-03 jas Copyright (C) Lucent Technologies 1997
3 63a68686 2008-11-03 jas All Rights Reserved
4 63a68686 2008-11-03 jas
5 63a68686 2008-11-03 jas Permission to use, copy, modify, and distribute this software and
6 63a68686 2008-11-03 jas its documentation for any purpose and without fee is hereby
7 63a68686 2008-11-03 jas granted, provided that the above copyright notice appear in all
8 63a68686 2008-11-03 jas copies and that both that the copyright notice and this
9 63a68686 2008-11-03 jas permission notice and warranty disclaimer appear in supporting
10 63a68686 2008-11-03 jas documentation, and that the name Lucent Technologies or any of
11 63a68686 2008-11-03 jas its entities not be used in advertising or publicity pertaining
12 63a68686 2008-11-03 jas to distribution of the software without specific, written prior
13 63a68686 2008-11-03 jas permission.
14 63a68686 2008-11-03 jas
15 63a68686 2008-11-03 jas LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 63a68686 2008-11-03 jas INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17 63a68686 2008-11-03 jas IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18 63a68686 2008-11-03 jas SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 63a68686 2008-11-03 jas WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20 63a68686 2008-11-03 jas IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21 63a68686 2008-11-03 jas ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22 63a68686 2008-11-03 jas THIS SOFTWARE.
23 63a68686 2008-11-03 jas ****************************************************************/
24 63a68686 2008-11-03 jas
25 63a68686 2008-11-03 jas #define DEBUG
26 63a68686 2008-11-03 jas #include <stdio.h>
27 63a68686 2008-11-03 jas #include <string.h>
28 63a68686 2008-11-03 jas #include <ctype.h>
29 63a68686 2008-11-03 jas #include <errno.h>
30 63a68686 2008-11-03 jas #include <stdlib.h>
31 63a68686 2008-11-03 jas #include <stdarg.h>
32 13094506 2019-10-29 crossd #include <utf.h>
33 63a68686 2008-11-03 jas #include "awk.h"
34 63a68686 2008-11-03 jas #include "y.tab.h"
35 63a68686 2008-11-03 jas
36 63a68686 2008-11-03 jas FILE *infile = NULL;
37 63a68686 2008-11-03 jas char *file = "";
38 63a68686 2008-11-03 jas char *record;
39 63a68686 2008-11-03 jas int recsize = RECSIZE;
40 63a68686 2008-11-03 jas char *fields;
41 63a68686 2008-11-03 jas int fieldssize = RECSIZE;
42 63a68686 2008-11-03 jas
43 63a68686 2008-11-03 jas Cell **fldtab; /* pointers to Cells */
44 63a68686 2008-11-03 jas char inputFS[100] = " ";
45 63a68686 2008-11-03 jas
46 63a68686 2008-11-03 jas #define MAXFLD 200
47 63a68686 2008-11-03 jas int nfields = MAXFLD; /* last allocated slot for $i */
48 63a68686 2008-11-03 jas
49 63a68686 2008-11-03 jas int donefld; /* 1 = implies rec broken into fields */
50 63a68686 2008-11-03 jas int donerec; /* 1 = record is valid (no flds have changed) */
51 63a68686 2008-11-03 jas
52 63a68686 2008-11-03 jas int lastfld = 0; /* last used field */
53 63a68686 2008-11-03 jas int argno = 1; /* current input argument number */
54 63a68686 2008-11-03 jas extern Awkfloat *ARGC;
55 63a68686 2008-11-03 jas
56 63a68686 2008-11-03 jas static Cell dollar0 = { OCELL, CFLD, NULL, "", 0.0, REC|STR|DONTFREE };
57 63a68686 2008-11-03 jas static Cell dollar1 = { OCELL, CFLD, NULL, "", 0.0, FLD|STR|DONTFREE };
58 63a68686 2008-11-03 jas
59 63a68686 2008-11-03 jas void recinit(unsigned int n)
60 63a68686 2008-11-03 jas {
61 63a68686 2008-11-03 jas record = (char *) malloc(n);
62 63a68686 2008-11-03 jas fields = (char *) malloc(n);
63 63a68686 2008-11-03 jas fldtab = (Cell **) malloc((nfields+1) * sizeof(Cell *));
64 63a68686 2008-11-03 jas if (record == NULL || fields == NULL || fldtab == NULL)
65 63a68686 2008-11-03 jas FATAL("out of space for $0 and fields");
66 63a68686 2008-11-03 jas fldtab[0] = (Cell *) malloc(sizeof (Cell));
67 63a68686 2008-11-03 jas *fldtab[0] = dollar0;
68 63a68686 2008-11-03 jas fldtab[0]->sval = record;
69 63a68686 2008-11-03 jas fldtab[0]->nval = tostring("0");
70 63a68686 2008-11-03 jas makefields(1, nfields);
71 63a68686 2008-11-03 jas }
72 63a68686 2008-11-03 jas
73 63a68686 2008-11-03 jas void makefields(int n1, int n2) /* create $n1..$n2 inclusive */
74 63a68686 2008-11-03 jas {
75 63a68686 2008-11-03 jas char temp[50];
76 63a68686 2008-11-03 jas int i;
77 63a68686 2008-11-03 jas
78 63a68686 2008-11-03 jas for (i = n1; i <= n2; i++) {
79 63a68686 2008-11-03 jas fldtab[i] = (Cell *) malloc(sizeof (struct Cell));
80 63a68686 2008-11-03 jas if (fldtab[i] == NULL)
81 63a68686 2008-11-03 jas FATAL("out of space in makefields %d", i);
82 63a68686 2008-11-03 jas *fldtab[i] = dollar1;
83 63a68686 2008-11-03 jas sprintf(temp, "%d", i);
84 63a68686 2008-11-03 jas fldtab[i]->nval = tostring(temp);
85 63a68686 2008-11-03 jas }
86 63a68686 2008-11-03 jas }
87 63a68686 2008-11-03 jas
88 63a68686 2008-11-03 jas void initgetrec(void)
89 63a68686 2008-11-03 jas {
90 63a68686 2008-11-03 jas int i;
91 63a68686 2008-11-03 jas char *p;
92 63a68686 2008-11-03 jas
93 63a68686 2008-11-03 jas for (i = 1; i < *ARGC; i++) {
94 63a68686 2008-11-03 jas if (!isclvar(p = getargv(i))) { /* find 1st real filename */
95 63a68686 2008-11-03 jas setsval(lookup("FILENAME", symtab), getargv(i));
96 63a68686 2008-11-03 jas return;
97 63a68686 2008-11-03 jas }
98 63a68686 2008-11-03 jas setclvar(p); /* a commandline assignment before filename */
99 63a68686 2008-11-03 jas argno++;
100 63a68686 2008-11-03 jas }
101 63a68686 2008-11-03 jas infile = stdin; /* no filenames, so use stdin */
102 63a68686 2008-11-03 jas }
103 63a68686 2008-11-03 jas
104 63a68686 2008-11-03 jas int getrec(char **pbuf, int *pbufsize, int isrecord) /* get next input record */
105 63a68686 2008-11-03 jas { /* note: cares whether buf == record */
106 63a68686 2008-11-03 jas int c;
107 63a68686 2008-11-03 jas static int firsttime = 1;
108 63a68686 2008-11-03 jas char *buf = *pbuf;
109 63a68686 2008-11-03 jas int bufsize = *pbufsize;
110 63a68686 2008-11-03 jas
111 63a68686 2008-11-03 jas if (firsttime) {
112 63a68686 2008-11-03 jas firsttime = 0;
113 63a68686 2008-11-03 jas initgetrec();
114 63a68686 2008-11-03 jas }
115 63a68686 2008-11-03 jas dprintf( ("RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n",
116 63a68686 2008-11-03 jas *RS, *FS, *ARGC, *FILENAME) );
117 63a68686 2008-11-03 jas if (isrecord) {
118 63a68686 2008-11-03 jas donefld = 0;
119 63a68686 2008-11-03 jas donerec = 1;
120 63a68686 2008-11-03 jas }
121 63a68686 2008-11-03 jas buf[0] = 0;
122 63a68686 2008-11-03 jas while (argno < *ARGC || infile == stdin) {
123 63a68686 2008-11-03 jas dprintf( ("argno=%d, file=|%s|\n", argno, file) );
124 63a68686 2008-11-03 jas if (infile == NULL) { /* have to open a new file */
125 63a68686 2008-11-03 jas file = getargv(argno);
126 63a68686 2008-11-03 jas if (*file == '\0') { /* it's been zapped */
127 63a68686 2008-11-03 jas argno++;
128 63a68686 2008-11-03 jas continue;
129 63a68686 2008-11-03 jas }
130 63a68686 2008-11-03 jas if (isclvar(file)) { /* a var=value arg */
131 63a68686 2008-11-03 jas setclvar(file);
132 63a68686 2008-11-03 jas argno++;
133 63a68686 2008-11-03 jas continue;
134 63a68686 2008-11-03 jas }
135 63a68686 2008-11-03 jas *FILENAME = file;
136 63a68686 2008-11-03 jas dprintf( ("opening file %s\n", file) );
137 63a68686 2008-11-03 jas if (*file == '-' && *(file+1) == '\0')
138 63a68686 2008-11-03 jas infile = stdin;
139 63a68686 2008-11-03 jas else if ((infile = fopen(file, "r")) == NULL)
140 63a68686 2008-11-03 jas FATAL("can't open file %s", file);
141 63a68686 2008-11-03 jas setfval(fnrloc, 0.0);
142 63a68686 2008-11-03 jas }
143 63a68686 2008-11-03 jas c = readrec(&buf, &bufsize, infile);
144 63a68686 2008-11-03 jas if (c != 0 || buf[0] != '\0') { /* normal record */
145 63a68686 2008-11-03 jas if (isrecord) {
146 63a68686 2008-11-03 jas if (freeable(fldtab[0]))
147 63a68686 2008-11-03 jas xfree(fldtab[0]->sval);
148 63a68686 2008-11-03 jas fldtab[0]->sval = buf; /* buf == record */
149 63a68686 2008-11-03 jas fldtab[0]->tval = REC | STR | DONTFREE;
150 63a68686 2008-11-03 jas if (is_number(fldtab[0]->sval)) {
151 63a68686 2008-11-03 jas fldtab[0]->fval = atof(fldtab[0]->sval);
152 63a68686 2008-11-03 jas fldtab[0]->tval |= NUM;
153 63a68686 2008-11-03 jas }
154 63a68686 2008-11-03 jas }
155 63a68686 2008-11-03 jas setfval(nrloc, nrloc->fval+1);
156 63a68686 2008-11-03 jas setfval(fnrloc, fnrloc->fval+1);
157 63a68686 2008-11-03 jas *pbuf = buf;
158 63a68686 2008-11-03 jas *pbufsize = bufsize;
159 63a68686 2008-11-03 jas return 1;
160 63a68686 2008-11-03 jas }
161 63a68686 2008-11-03 jas /* EOF arrived on this file; set up next */
162 63a68686 2008-11-03 jas if (infile != stdin)
163 63a68686 2008-11-03 jas fclose(infile);
164 63a68686 2008-11-03 jas infile = NULL;
165 63a68686 2008-11-03 jas argno++;
166 63a68686 2008-11-03 jas }
167 63a68686 2008-11-03 jas *pbuf = buf;
168 63a68686 2008-11-03 jas *pbufsize = bufsize;
169 63a68686 2008-11-03 jas return 0; /* true end of file */
170 63a68686 2008-11-03 jas }
171 63a68686 2008-11-03 jas
172 63a68686 2008-11-03 jas void nextfile(void)
173 63a68686 2008-11-03 jas {
174 63a68686 2008-11-03 jas if (infile != stdin)
175 63a68686 2008-11-03 jas fclose(infile);
176 63a68686 2008-11-03 jas infile = NULL;
177 63a68686 2008-11-03 jas argno++;
178 63a68686 2008-11-03 jas }
179 63a68686 2008-11-03 jas
180 63a68686 2008-11-03 jas int readrec(char **pbuf, int *pbufsize, FILE *inf) /* read one record into buf */
181 63a68686 2008-11-03 jas {
182 63a68686 2008-11-03 jas int sep, c;
183 63a68686 2008-11-03 jas char *rr, *buf = *pbuf;
184 63a68686 2008-11-03 jas int bufsize = *pbufsize;
185 63a68686 2008-11-03 jas
186 63a68686 2008-11-03 jas if (strlen(*FS) >= sizeof(inputFS))
187 63a68686 2008-11-03 jas FATAL("field separator %.10s... is too long", *FS);
188 63a68686 2008-11-03 jas strcpy(inputFS, *FS); /* for subsequent field splitting */
189 63a68686 2008-11-03 jas if ((sep = **RS) == 0) {
190 63a68686 2008-11-03 jas sep = '\n';
191 63a68686 2008-11-03 jas while ((c=getc(inf)) == '\n' && c != EOF) /* skip leading \n's */
192 63a68686 2008-11-03 jas ;
193 63a68686 2008-11-03 jas if (c != EOF)
194 63a68686 2008-11-03 jas ungetc(c, inf);
195 63a68686 2008-11-03 jas }
196 63a68686 2008-11-03 jas for (rr = buf; ; ) {
197 63a68686 2008-11-03 jas for (; (c=getc(inf)) != sep && c != EOF; ) {
198 63a68686 2008-11-03 jas if (rr-buf+1 > bufsize)
199 63a68686 2008-11-03 jas if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 1"))
200 63a68686 2008-11-03 jas FATAL("input record `%.30s...' too long", buf);
201 63a68686 2008-11-03 jas *rr++ = c;
202 63a68686 2008-11-03 jas }
203 63a68686 2008-11-03 jas if (**RS == sep || c == EOF)
204 63a68686 2008-11-03 jas break;
205 63a68686 2008-11-03 jas if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */
206 63a68686 2008-11-03 jas break;
207 63a68686 2008-11-03 jas if (!adjbuf(&buf, &bufsize, 2+rr-buf, recsize, &rr, "readrec 2"))
208 63a68686 2008-11-03 jas FATAL("input record `%.30s...' too long", buf);
209 63a68686 2008-11-03 jas *rr++ = '\n';
210 63a68686 2008-11-03 jas *rr++ = c;
211 63a68686 2008-11-03 jas }
212 63a68686 2008-11-03 jas if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 3"))
213 63a68686 2008-11-03 jas FATAL("input record `%.30s...' too long", buf);
214 63a68686 2008-11-03 jas *rr = 0;
215 63a68686 2008-11-03 jas dprintf( ("readrec saw <%s>, returns %d\n", buf, c == EOF && rr == buf ? 0 : 1) );
216 63a68686 2008-11-03 jas *pbuf = buf;
217 63a68686 2008-11-03 jas *pbufsize = bufsize;
218 63a68686 2008-11-03 jas return c == EOF && rr == buf ? 0 : 1;
219 63a68686 2008-11-03 jas }
220 63a68686 2008-11-03 jas
221 63a68686 2008-11-03 jas char *getargv(int n) /* get ARGV[n] */
222 63a68686 2008-11-03 jas {
223 63a68686 2008-11-03 jas Cell *x;
224 63a68686 2008-11-03 jas char *s, temp[50];
225 63a68686 2008-11-03 jas extern Array *ARGVtab;
226 63a68686 2008-11-03 jas
227 63a68686 2008-11-03 jas sprintf(temp, "%d", n);
228 63a68686 2008-11-03 jas x = setsymtab(temp, "", 0.0, STR, ARGVtab);
229 63a68686 2008-11-03 jas s = getsval(x);
230 63a68686 2008-11-03 jas dprintf( ("getargv(%d) returns |%s|\n", n, s) );
231 63a68686 2008-11-03 jas return s;
232 63a68686 2008-11-03 jas }
233 63a68686 2008-11-03 jas
234 63a68686 2008-11-03 jas void setclvar(char *s) /* set var=value from s */
235 63a68686 2008-11-03 jas {
236 63a68686 2008-11-03 jas char *p;
237 63a68686 2008-11-03 jas Cell *q;
238 63a68686 2008-11-03 jas
239 63a68686 2008-11-03 jas for (p=s; *p != '='; p++)
240 63a68686 2008-11-03 jas ;
241 63a68686 2008-11-03 jas *p++ = 0;
242 63a68686 2008-11-03 jas p = qstring(p, '\0');
243 63a68686 2008-11-03 jas q = setsymtab(s, p, 0.0, STR, symtab);
244 63a68686 2008-11-03 jas setsval(q, p);
245 63a68686 2008-11-03 jas if (is_number(q->sval)) {
246 63a68686 2008-11-03 jas q->fval = atof(q->sval);
247 63a68686 2008-11-03 jas q->tval |= NUM;
248 63a68686 2008-11-03 jas }
249 63a68686 2008-11-03 jas dprintf( ("command line set %s to |%s|\n", s, p) );
250 63a68686 2008-11-03 jas }
251 63a68686 2008-11-03 jas
252 63a68686 2008-11-03 jas
253 63a68686 2008-11-03 jas void fldbld(void) /* create fields from current record */
254 63a68686 2008-11-03 jas {
255 63a68686 2008-11-03 jas /* this relies on having fields[] the same length as $0 */
256 63a68686 2008-11-03 jas /* the fields are all stored in this one array with \0's */
257 63a68686 2008-11-03 jas char *r, *fr, sep;
258 63a68686 2008-11-03 jas Cell *p;
259 63a68686 2008-11-03 jas int i, j, n;
260 63a68686 2008-11-03 jas
261 63a68686 2008-11-03 jas if (donefld)
262 63a68686 2008-11-03 jas return;
263 63a68686 2008-11-03 jas if (!isstr(fldtab[0]))
264 63a68686 2008-11-03 jas getsval(fldtab[0]);
265 63a68686 2008-11-03 jas r = fldtab[0]->sval;
266 63a68686 2008-11-03 jas n = strlen(r);
267 63a68686 2008-11-03 jas if (n > fieldssize) {
268 63a68686 2008-11-03 jas xfree(fields);
269 63a68686 2008-11-03 jas if ((fields = (char *) malloc(n+1)) == NULL)
270 63a68686 2008-11-03 jas FATAL("out of space for fields in fldbld %d", n);
271 63a68686 2008-11-03 jas fieldssize = n;
272 63a68686 2008-11-03 jas }
273 63a68686 2008-11-03 jas fr = fields;
274 63a68686 2008-11-03 jas i = 0; /* number of fields accumulated here */
275 63a68686 2008-11-03 jas if (strlen(inputFS) > 1) { /* it's a regular expression */
276 63a68686 2008-11-03 jas i = refldbld(r, inputFS);
277 63a68686 2008-11-03 jas } else if ((sep = *inputFS) == ' ') { /* default whitespace */
278 63a68686 2008-11-03 jas for (i = 0; ; ) {
279 63a68686 2008-11-03 jas while (*r == ' ' || *r == '\t' || *r == '\n')
280 63a68686 2008-11-03 jas r++;
281 63a68686 2008-11-03 jas if (*r == 0)
282 63a68686 2008-11-03 jas break;
283 63a68686 2008-11-03 jas i++;
284 63a68686 2008-11-03 jas if (i > nfields)
285 63a68686 2008-11-03 jas growfldtab(i);
286 63a68686 2008-11-03 jas if (freeable(fldtab[i]))
287 63a68686 2008-11-03 jas xfree(fldtab[i]->sval);
288 63a68686 2008-11-03 jas fldtab[i]->sval = fr;
289 63a68686 2008-11-03 jas fldtab[i]->tval = FLD | STR | DONTFREE;
290 63a68686 2008-11-03 jas do
291 63a68686 2008-11-03 jas *fr++ = *r++;
292 63a68686 2008-11-03 jas while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0');
293 63a68686 2008-11-03 jas *fr++ = 0;
294 63a68686 2008-11-03 jas }
295 63a68686 2008-11-03 jas *fr = 0;
296 63a68686 2008-11-03 jas } else if ((sep = *inputFS) == 0) { /* new: FS="" => 1 char/field */
297 13094506 2019-10-29 crossd int nb;
298 13094506 2019-10-29 crossd for (i = 0; *r != 0; r += nb) {
299 13094506 2019-10-29 crossd Rune rr;
300 13094506 2019-10-29 crossd char buf[UTFmax+1];
301 13094506 2019-10-29 crossd
302 63a68686 2008-11-03 jas i++;
303 63a68686 2008-11-03 jas if (i > nfields)
304 63a68686 2008-11-03 jas growfldtab(i);
305 63a68686 2008-11-03 jas if (freeable(fldtab[i]))
306 63a68686 2008-11-03 jas xfree(fldtab[i]->sval);
307 13094506 2019-10-29 crossd nb = chartorune(&rr, r);
308 13094506 2019-10-29 crossd memmove(buf, r, nb);
309 13094506 2019-10-29 crossd buf[nb] = '\0';
310 63a68686 2008-11-03 jas fldtab[i]->sval = tostring(buf);
311 63a68686 2008-11-03 jas fldtab[i]->tval = FLD | STR;
312 63a68686 2008-11-03 jas }
313 63a68686 2008-11-03 jas *fr = 0;
314 63a68686 2008-11-03 jas } else if (*r != 0) { /* if 0, it's a null field */
315 63a68686 2008-11-03 jas for (;;) {
316 63a68686 2008-11-03 jas i++;
317 63a68686 2008-11-03 jas if (i > nfields)
318 63a68686 2008-11-03 jas growfldtab(i);
319 63a68686 2008-11-03 jas if (freeable(fldtab[i]))
320 63a68686 2008-11-03 jas xfree(fldtab[i]->sval);
321 63a68686 2008-11-03 jas fldtab[i]->sval = fr;
322 63a68686 2008-11-03 jas fldtab[i]->tval = FLD | STR | DONTFREE;
323 63a68686 2008-11-03 jas while (*r != sep && *r != '\n' && *r != '\0') /* \n is always a separator */
324 63a68686 2008-11-03 jas *fr++ = *r++;
325 63a68686 2008-11-03 jas *fr++ = 0;
326 63a68686 2008-11-03 jas if (*r++ == 0)
327 63a68686 2008-11-03 jas break;
328 63a68686 2008-11-03 jas }
329 63a68686 2008-11-03 jas *fr = 0;
330 63a68686 2008-11-03 jas }
331 63a68686 2008-11-03 jas if (i > nfields)
332 63a68686 2008-11-03 jas FATAL("record `%.30s...' has too many fields; can't happen", r);
333 63a68686 2008-11-03 jas cleanfld(i+1, lastfld); /* clean out junk from previous record */
334 63a68686 2008-11-03 jas lastfld = i;
335 63a68686 2008-11-03 jas donefld = 1;
336 63a68686 2008-11-03 jas for (j = 1; j <= lastfld; j++) {
337 63a68686 2008-11-03 jas p = fldtab[j];
338 63a68686 2008-11-03 jas if(is_number(p->sval)) {
339 63a68686 2008-11-03 jas p->fval = atof(p->sval);
340 63a68686 2008-11-03 jas p->tval |= NUM;
341 63a68686 2008-11-03 jas }
342 63a68686 2008-11-03 jas }
343 63a68686 2008-11-03 jas setfval(nfloc, (Awkfloat) lastfld);
344 63a68686 2008-11-03 jas if (dbg) {
345 63a68686 2008-11-03 jas for (j = 0; j <= lastfld; j++) {
346 63a68686 2008-11-03 jas p = fldtab[j];
347 63a68686 2008-11-03 jas printf("field %d (%s): |%s|\n", j, p->nval, p->sval);
348 63a68686 2008-11-03 jas }
349 63a68686 2008-11-03 jas }
350 63a68686 2008-11-03 jas }
351 63a68686 2008-11-03 jas
352 63a68686 2008-11-03 jas void cleanfld(int n1, int n2) /* clean out fields n1 .. n2 inclusive */
353 63a68686 2008-11-03 jas { /* nvals remain intact */
354 63a68686 2008-11-03 jas Cell *p;
355 63a68686 2008-11-03 jas int i;
356 63a68686 2008-11-03 jas
357 63a68686 2008-11-03 jas for (i = n1; i <= n2; i++) {
358 63a68686 2008-11-03 jas p = fldtab[i];
359 63a68686 2008-11-03 jas if (freeable(p))
360 63a68686 2008-11-03 jas xfree(p->sval);
361 63a68686 2008-11-03 jas p->sval = "";
362 63a68686 2008-11-03 jas p->tval = FLD | STR | DONTFREE;
363 63a68686 2008-11-03 jas }
364 63a68686 2008-11-03 jas }
365 63a68686 2008-11-03 jas
366 63a68686 2008-11-03 jas void newfld(int n) /* add field n after end of existing lastfld */
367 63a68686 2008-11-03 jas {
368 63a68686 2008-11-03 jas if (n > nfields)
369 63a68686 2008-11-03 jas growfldtab(n);
370 63a68686 2008-11-03 jas cleanfld(lastfld+1, n);
371 63a68686 2008-11-03 jas lastfld = n;
372 63a68686 2008-11-03 jas setfval(nfloc, (Awkfloat) n);
373 63a68686 2008-11-03 jas }
374 63a68686 2008-11-03 jas
375 63a68686 2008-11-03 jas Cell *fieldadr(int n) /* get nth field */
376 63a68686 2008-11-03 jas {
377 63a68686 2008-11-03 jas if (n < 0)
378 63a68686 2008-11-03 jas FATAL("trying to access field %d", n);
379 63a68686 2008-11-03 jas if (n > nfields) /* fields after NF are empty */
380 63a68686 2008-11-03 jas growfldtab(n); /* but does not increase NF */
381 63a68686 2008-11-03 jas return(fldtab[n]);
382 63a68686 2008-11-03 jas }
383 63a68686 2008-11-03 jas
384 63a68686 2008-11-03 jas void growfldtab(int n) /* make new fields up to at least $n */
385 63a68686 2008-11-03 jas {
386 63a68686 2008-11-03 jas int nf = 2 * nfields;
387 63a68686 2008-11-03 jas
388 63a68686 2008-11-03 jas if (n > nf)
389 63a68686 2008-11-03 jas nf = n;
390 63a68686 2008-11-03 jas fldtab = (Cell **) realloc(fldtab, (nf+1) * (sizeof (struct Cell *)));
391 63a68686 2008-11-03 jas if (fldtab == NULL)
392 63a68686 2008-11-03 jas FATAL("out of space creating %d fields", nf);
393 63a68686 2008-11-03 jas makefields(nfields+1, nf);
394 63a68686 2008-11-03 jas nfields = nf;
395 63a68686 2008-11-03 jas }
396 63a68686 2008-11-03 jas
397 63a68686 2008-11-03 jas int refldbld(char *rec, char *fs) /* build fields from reg expr in FS */
398 63a68686 2008-11-03 jas {
399 63a68686 2008-11-03 jas /* this relies on having fields[] the same length as $0 */
400 63a68686 2008-11-03 jas /* the fields are all stored in this one array with \0's */
401 63a68686 2008-11-03 jas char *fr;
402 63a68686 2008-11-03 jas void *p;
403 63a68686 2008-11-03 jas int i, n;
404 63a68686 2008-11-03 jas
405 63a68686 2008-11-03 jas n = strlen(rec);
406 63a68686 2008-11-03 jas if (n > fieldssize) {
407 63a68686 2008-11-03 jas xfree(fields);
408 63a68686 2008-11-03 jas if ((fields = (char *) malloc(n+1)) == NULL)
409 63a68686 2008-11-03 jas FATAL("out of space for fields in refldbld %d", n);
410 63a68686 2008-11-03 jas fieldssize = n;
411 63a68686 2008-11-03 jas }
412 63a68686 2008-11-03 jas fr = fields;
413 63a68686 2008-11-03 jas *fr = '\0';
414 63a68686 2008-11-03 jas if (*rec == '\0')
415 63a68686 2008-11-03 jas return 0;
416 63a68686 2008-11-03 jas p = compre(fs);
417 63a68686 2008-11-03 jas dprintf( ("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs) );
418 63a68686 2008-11-03 jas for (i = 1; ; i++) {
419 63a68686 2008-11-03 jas if (i > nfields)
420 63a68686 2008-11-03 jas growfldtab(i);
421 63a68686 2008-11-03 jas if (freeable(fldtab[i]))
422 63a68686 2008-11-03 jas xfree(fldtab[i]->sval);
423 63a68686 2008-11-03 jas fldtab[i]->tval = FLD | STR | DONTFREE;
424 63a68686 2008-11-03 jas fldtab[i]->sval = fr;
425 63a68686 2008-11-03 jas dprintf( ("refldbld: i=%d\n", i) );
426 63a68686 2008-11-03 jas if (nematch(p, rec, rec)) {
427 63a68686 2008-11-03 jas dprintf( ("match %s (%d chars)\n", patbeg, patlen) );
428 63a68686 2008-11-03 jas strncpy(fr, rec, patbeg-rec);
429 63a68686 2008-11-03 jas fr += patbeg - rec + 1;
430 63a68686 2008-11-03 jas *(fr-1) = '\0';
431 63a68686 2008-11-03 jas rec = patbeg + patlen;
432 63a68686 2008-11-03 jas } else {
433 63a68686 2008-11-03 jas dprintf( ("no match %s\n", rec) );
434 63a68686 2008-11-03 jas strcpy(fr, rec);
435 63a68686 2008-11-03 jas break;
436 63a68686 2008-11-03 jas }
437 63a68686 2008-11-03 jas }
438 fa325e9b 2020-01-10 cross return i;
439 63a68686 2008-11-03 jas }
440 63a68686 2008-11-03 jas
441 63a68686 2008-11-03 jas void recbld(void) /* create $0 from $1..$NF if necessary */
442 63a68686 2008-11-03 jas {
443 63a68686 2008-11-03 jas int i;
444 63a68686 2008-11-03 jas char *r, *p;
445 63a68686 2008-11-03 jas
446 63a68686 2008-11-03 jas if (donerec == 1)
447 63a68686 2008-11-03 jas return;
448 63a68686 2008-11-03 jas r = record;
449 63a68686 2008-11-03 jas for (i = 1; i <= *NF; i++) {
450 63a68686 2008-11-03 jas p = getsval(fldtab[i]);
451 63a68686 2008-11-03 jas if (!adjbuf(&record, &recsize, 1+strlen(p)+r-record, recsize, &r, "recbld 1"))
452 63a68686 2008-11-03 jas FATAL("created $0 `%.30s...' too long", record);
453 63a68686 2008-11-03 jas while ((*r = *p++) != 0)
454 63a68686 2008-11-03 jas r++;
455 63a68686 2008-11-03 jas if (i < *NF) {
456 63a68686 2008-11-03 jas if (!adjbuf(&record, &recsize, 2+strlen(*OFS)+r-record, recsize, &r, "recbld 2"))
457 63a68686 2008-11-03 jas FATAL("created $0 `%.30s...' too long", record);
458 63a68686 2008-11-03 jas for (p = *OFS; (*r = *p++) != 0; )
459 63a68686 2008-11-03 jas r++;
460 63a68686 2008-11-03 jas }
461 63a68686 2008-11-03 jas }
462 63a68686 2008-11-03 jas if (!adjbuf(&record, &recsize, 2+r-record, recsize, &r, "recbld 3"))
463 63a68686 2008-11-03 jas FATAL("built giant record `%.30s...'", record);
464 63a68686 2008-11-03 jas *r = '\0';
465 63a68686 2008-11-03 jas dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) );
466 63a68686 2008-11-03 jas
467 63a68686 2008-11-03 jas if (freeable(fldtab[0]))
468 63a68686 2008-11-03 jas xfree(fldtab[0]->sval);
469 63a68686 2008-11-03 jas fldtab[0]->tval = REC | STR | DONTFREE;
470 63a68686 2008-11-03 jas fldtab[0]->sval = record;
471 63a68686 2008-11-03 jas
472 63a68686 2008-11-03 jas dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) );
473 63a68686 2008-11-03 jas dprintf( ("recbld = |%s|\n", record) );
474 63a68686 2008-11-03 jas donerec = 1;
475 63a68686 2008-11-03 jas }
476 63a68686 2008-11-03 jas
477 63a68686 2008-11-03 jas int errorflag = 0;
478 63a68686 2008-11-03 jas
479 63a68686 2008-11-03 jas void yyerror(char *s)
480 63a68686 2008-11-03 jas {
481 63a68686 2008-11-03 jas SYNTAX(s);
482 63a68686 2008-11-03 jas }
483 63a68686 2008-11-03 jas
484 63a68686 2008-11-03 jas void SYNTAX(char *fmt, ...)
485 63a68686 2008-11-03 jas {
486 63a68686 2008-11-03 jas extern char *cmdname, *curfname;
487 63a68686 2008-11-03 jas static int been_here = 0;
488 63a68686 2008-11-03 jas va_list varg;
489 63a68686 2008-11-03 jas
490 63a68686 2008-11-03 jas if (been_here++ > 2)
491 63a68686 2008-11-03 jas return;
492 63a68686 2008-11-03 jas fprintf(stderr, "%s: ", cmdname);
493 63a68686 2008-11-03 jas va_start(varg, fmt);
494 63a68686 2008-11-03 jas vfprintf(stderr, fmt, varg);
495 63a68686 2008-11-03 jas va_end(varg);
496 63a68686 2008-11-03 jas if(compile_time == 1 && cursource() != NULL)
497 63a68686 2008-11-03 jas fprintf(stderr, " at %s:%d", cursource(), lineno);
498 63a68686 2008-11-03 jas else
499 63a68686 2008-11-03 jas fprintf(stderr, " at line %d", lineno);
500 63a68686 2008-11-03 jas if (curfname != NULL)
501 63a68686 2008-11-03 jas fprintf(stderr, " in function %s", curfname);
502 63a68686 2008-11-03 jas fprintf(stderr, "\n");
503 63a68686 2008-11-03 jas errorflag = 2;
504 63a68686 2008-11-03 jas eprint();
505 63a68686 2008-11-03 jas }
506 63a68686 2008-11-03 jas
507 63a68686 2008-11-03 jas void fpecatch(int n)
508 63a68686 2008-11-03 jas {
509 63a68686 2008-11-03 jas FATAL("floating point exception %d", n);
510 63a68686 2008-11-03 jas }
511 63a68686 2008-11-03 jas
512 63a68686 2008-11-03 jas extern int bracecnt, brackcnt, parencnt;
513 63a68686 2008-11-03 jas
514 63a68686 2008-11-03 jas void bracecheck(void)
515 63a68686 2008-11-03 jas {
516 63a68686 2008-11-03 jas int c;
517 63a68686 2008-11-03 jas static int beenhere = 0;
518 63a68686 2008-11-03 jas
519 63a68686 2008-11-03 jas if (beenhere++)
520 63a68686 2008-11-03 jas return;
521 63a68686 2008-11-03 jas while ((c = input()) != EOF && c != '\0')
522 63a68686 2008-11-03 jas bclass(c);
523 63a68686 2008-11-03 jas bcheck2(bracecnt, '{', '}');
524 63a68686 2008-11-03 jas bcheck2(brackcnt, '[', ']');
525 63a68686 2008-11-03 jas bcheck2(parencnt, '(', ')');
526 63a68686 2008-11-03 jas }
527 63a68686 2008-11-03 jas
528 63a68686 2008-11-03 jas void bcheck2(int n, int c1, int c2)
529 63a68686 2008-11-03 jas {
530 63a68686 2008-11-03 jas if (n == 1)
531 63a68686 2008-11-03 jas fprintf(stderr, "\tmissing %c\n", c2);
532 63a68686 2008-11-03 jas else if (n > 1)
533 63a68686 2008-11-03 jas fprintf(stderr, "\t%d missing %c's\n", n, c2);
534 63a68686 2008-11-03 jas else if (n == -1)
535 63a68686 2008-11-03 jas fprintf(stderr, "\textra %c\n", c2);
536 63a68686 2008-11-03 jas else if (n < -1)
537 63a68686 2008-11-03 jas fprintf(stderr, "\t%d extra %c's\n", -n, c2);
538 63a68686 2008-11-03 jas }
539 63a68686 2008-11-03 jas
540 63a68686 2008-11-03 jas void FATAL(char *fmt, ...)
541 63a68686 2008-11-03 jas {
542 63a68686 2008-11-03 jas extern char *cmdname;
543 63a68686 2008-11-03 jas va_list varg;
544 63a68686 2008-11-03 jas
545 63a68686 2008-11-03 jas fflush(stdout);
546 63a68686 2008-11-03 jas fprintf(stderr, "%s: ", cmdname);
547 63a68686 2008-11-03 jas va_start(varg, fmt);
548 63a68686 2008-11-03 jas vfprintf(stderr, fmt, varg);
549 63a68686 2008-11-03 jas va_end(varg);
550 63a68686 2008-11-03 jas error();
551 63a68686 2008-11-03 jas if (dbg > 1) /* core dump if serious debugging on */
552 63a68686 2008-11-03 jas abort();
553 63a68686 2008-11-03 jas exit(2);
554 63a68686 2008-11-03 jas }
555 63a68686 2008-11-03 jas
556 63a68686 2008-11-03 jas void WARNING(char *fmt, ...)
557 63a68686 2008-11-03 jas {
558 63a68686 2008-11-03 jas extern char *cmdname;
559 63a68686 2008-11-03 jas va_list varg;
560 63a68686 2008-11-03 jas
561 63a68686 2008-11-03 jas fflush(stdout);
562 63a68686 2008-11-03 jas fprintf(stderr, "%s: ", cmdname);
563 63a68686 2008-11-03 jas va_start(varg, fmt);
564 63a68686 2008-11-03 jas vfprintf(stderr, fmt, varg);
565 63a68686 2008-11-03 jas va_end(varg);
566 63a68686 2008-11-03 jas error();
567 63a68686 2008-11-03 jas }
568 63a68686 2008-11-03 jas
569 63a68686 2008-11-03 jas void error()
570 63a68686 2008-11-03 jas {
571 63a68686 2008-11-03 jas extern Node *curnode;
572 63a68686 2008-11-03 jas int line;
573 63a68686 2008-11-03 jas
574 63a68686 2008-11-03 jas fprintf(stderr, "\n");
575 63a68686 2008-11-03 jas if (compile_time != 2 && NR && *NR > 0) {
576 63a68686 2008-11-03 jas if (strcmp(*FILENAME, "-") != 0)
577 63a68686 2008-11-03 jas fprintf(stderr, " input record %s:%d", *FILENAME, (int) (*FNR));
578 63a68686 2008-11-03 jas else
579 63a68686 2008-11-03 jas fprintf(stderr, " input record number %d", (int) (*FNR));
580 63a68686 2008-11-03 jas fprintf(stderr, "\n");
581 63a68686 2008-11-03 jas }
582 63a68686 2008-11-03 jas if (compile_time != 2 && curnode)
583 63a68686 2008-11-03 jas line = curnode->lineno;
584 63a68686 2008-11-03 jas else if (compile_time != 2 && lineno)
585 63a68686 2008-11-03 jas line = lineno;
586 63a68686 2008-11-03 jas else
587 63a68686 2008-11-03 jas line = -1;
588 63a68686 2008-11-03 jas if (compile_time == 1 && cursource() != NULL){
589 63a68686 2008-11-03 jas if(line >= 0)
590 63a68686 2008-11-03 jas fprintf(stderr, " source %s:%d", cursource(), line);
591 63a68686 2008-11-03 jas else
592 63a68686 2008-11-03 jas fprintf(stderr, " source file %s", cursource());
593 63a68686 2008-11-03 jas }else if(line >= 0)
594 63a68686 2008-11-03 jas fprintf(stderr, " source line %d", line);
595 63a68686 2008-11-03 jas fprintf(stderr, "\n");
596 63a68686 2008-11-03 jas eprint();
597 63a68686 2008-11-03 jas }
598 63a68686 2008-11-03 jas
599 63a68686 2008-11-03 jas void eprint(void) /* try to print context around error */
600 63a68686 2008-11-03 jas {
601 63a68686 2008-11-03 jas char *p, *q;
602 63a68686 2008-11-03 jas int c;
603 63a68686 2008-11-03 jas static int been_here = 0;
604 63a68686 2008-11-03 jas extern char ebuf[], *ep;
605 63a68686 2008-11-03 jas
606 63a68686 2008-11-03 jas if (compile_time == 2 || compile_time == 0 || been_here++ > 0)
607 63a68686 2008-11-03 jas return;
608 63a68686 2008-11-03 jas p = ep - 1;
609 63a68686 2008-11-03 jas if (p > ebuf && *p == '\n')
610 63a68686 2008-11-03 jas p--;
611 63a68686 2008-11-03 jas for ( ; p > ebuf && *p != '\n' && *p != '\0'; p--)
612 63a68686 2008-11-03 jas ;
613 63a68686 2008-11-03 jas while (*p == '\n')
614 63a68686 2008-11-03 jas p++;
615 63a68686 2008-11-03 jas fprintf(stderr, " context is\n\t");
616 63a68686 2008-11-03 jas for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
617 63a68686 2008-11-03 jas ;
618 63a68686 2008-11-03 jas for ( ; p < q; p++)
619 63a68686 2008-11-03 jas if (*p)
620 63a68686 2008-11-03 jas putc(*p, stderr);
621 63a68686 2008-11-03 jas fprintf(stderr, " >>> ");
622 63a68686 2008-11-03 jas for ( ; p < ep; p++)
623 63a68686 2008-11-03 jas if (*p)
624 63a68686 2008-11-03 jas putc(*p, stderr);
625 63a68686 2008-11-03 jas fprintf(stderr, " <<< ");
626 63a68686 2008-11-03 jas if (*ep)
627 63a68686 2008-11-03 jas while ((c = input()) != '\n' && c != '\0' && c != EOF) {
628 63a68686 2008-11-03 jas putc(c, stderr);
629 63a68686 2008-11-03 jas bclass(c);
630 63a68686 2008-11-03 jas }
631 63a68686 2008-11-03 jas putc('\n', stderr);
632 63a68686 2008-11-03 jas ep = ebuf;
633 63a68686 2008-11-03 jas }
634 63a68686 2008-11-03 jas
635 63a68686 2008-11-03 jas void bclass(int c)
636 63a68686 2008-11-03 jas {
637 63a68686 2008-11-03 jas switch (c) {
638 63a68686 2008-11-03 jas case '{': bracecnt++; break;
639 63a68686 2008-11-03 jas case '}': bracecnt--; break;
640 63a68686 2008-11-03 jas case '[': brackcnt++; break;
641 63a68686 2008-11-03 jas case ']': brackcnt--; break;
642 63a68686 2008-11-03 jas case '(': parencnt++; break;
643 63a68686 2008-11-03 jas case ')': parencnt--; break;
644 63a68686 2008-11-03 jas }
645 63a68686 2008-11-03 jas }
646 63a68686 2008-11-03 jas
647 63a68686 2008-11-03 jas double errcheck(double x, char *s)
648 63a68686 2008-11-03 jas {
649 63a68686 2008-11-03 jas
650 63a68686 2008-11-03 jas if (errno == EDOM) {
651 63a68686 2008-11-03 jas errno = 0;
652 63a68686 2008-11-03 jas WARNING("%s argument out of domain", s);
653 63a68686 2008-11-03 jas x = 1;
654 63a68686 2008-11-03 jas } else if (errno == ERANGE) {
655 63a68686 2008-11-03 jas errno = 0;
656 63a68686 2008-11-03 jas WARNING("%s result out of range", s);
657 63a68686 2008-11-03 jas x = 1;
658 63a68686 2008-11-03 jas }
659 63a68686 2008-11-03 jas return x;
660 63a68686 2008-11-03 jas }
661 63a68686 2008-11-03 jas
662 63a68686 2008-11-03 jas int isclvar(char *s) /* is s of form var=something ? */
663 63a68686 2008-11-03 jas {
664 63a68686 2008-11-03 jas char *os = s;
665 63a68686 2008-11-03 jas
666 63a68686 2008-11-03 jas if (!isalpha(*s) && *s != '_')
667 63a68686 2008-11-03 jas return 0;
668 63a68686 2008-11-03 jas for ( ; *s; s++)
669 63a68686 2008-11-03 jas if (!(isalnum(*s) || *s == '_'))
670 63a68686 2008-11-03 jas break;
671 63a68686 2008-11-03 jas return *s == '=' && s > os && *(s+1) != '=';
672 63a68686 2008-11-03 jas }
673 63a68686 2008-11-03 jas
674 63a68686 2008-11-03 jas /* strtod is supposed to be a proper test of what's a valid number */
675 63a68686 2008-11-03 jas
676 63a68686 2008-11-03 jas #include <math.h>
677 63a68686 2008-11-03 jas int is_number(char *s)
678 63a68686 2008-11-03 jas {
679 63a68686 2008-11-03 jas double r;
680 63a68686 2008-11-03 jas char *ep;
681 63a68686 2008-11-03 jas
682 63a68686 2008-11-03 jas /*
683 63a68686 2008-11-03 jas * fast could-it-be-a-number check before calling strtod,
684 63a68686 2008-11-03 jas * which takes a surprisingly long time to reject non-numbers.
685 63a68686 2008-11-03 jas */
686 63a68686 2008-11-03 jas switch (*s) {
687 63a68686 2008-11-03 jas case '0': case '1': case '2': case '3': case '4':
688 63a68686 2008-11-03 jas case '5': case '6': case '7': case '8': case '9':
689 63a68686 2008-11-03 jas case '\t':
690 63a68686 2008-11-03 jas case '\n':
691 63a68686 2008-11-03 jas case '\v':
692 63a68686 2008-11-03 jas case '\f':
693 63a68686 2008-11-03 jas case '\r':
694 63a68686 2008-11-03 jas case ' ':
695 63a68686 2008-11-03 jas case '-':
696 63a68686 2008-11-03 jas case '+':
697 63a68686 2008-11-03 jas case '.':
698 63a68686 2008-11-03 jas case 'n': /* nans */
699 63a68686 2008-11-03 jas case 'N':
700 63a68686 2008-11-03 jas case 'i': /* infs */
701 63a68686 2008-11-03 jas case 'I':
702 63a68686 2008-11-03 jas break;
703 63a68686 2008-11-03 jas default:
704 63a68686 2008-11-03 jas return 0; /* can't be a number */
705 63a68686 2008-11-03 jas }
706 63a68686 2008-11-03 jas
707 63a68686 2008-11-03 jas errno = 0;
708 63a68686 2008-11-03 jas r = strtod(s, &ep);
709 63a68686 2008-11-03 jas if (ep == s || r == HUGE_VAL || errno == ERANGE)
710 63a68686 2008-11-03 jas return 0;
711 63a68686 2008-11-03 jas while (*ep == ' ' || *ep == '\t' || *ep == '\n')
712 63a68686 2008-11-03 jas ep++;
713 63a68686 2008-11-03 jas if (*ep == '\0')
714 63a68686 2008-11-03 jas return 1;
715 63a68686 2008-11-03 jas else
716 63a68686 2008-11-03 jas return 0;
717 63a68686 2008-11-03 jas }