Print this page
3731 Update nawk to version 20121220
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/awk/lib.c
+++ new/usr/src/cmd/awk/lib.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 -/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 -/* All Rights Reserved */
29 -
30 -#pragma ident "%Z%%M% %I% %E% SMI"
27 +/*
28 + * Copyright (C) Lucent Technologies 1997
29 + * All Rights Reserved
30 + *
31 + * Permission to use, copy, modify, and distribute this software and
32 + * its documentation for any purpose and without fee is hereby
33 + * granted, provided that the above copyright notice appear in all
34 + * copies and that both that the copyright notice and this
35 + * permission notice and warranty disclaimer appear in supporting
36 + * documentation, and that the name Lucent Technologies or any of
37 + * its entities not be used in advertising or publicity pertaining
38 + * to distribution of the software without specific, written prior
39 + * permission.
40 + *
41 + * LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
42 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
43 + * IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
44 + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
45 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
46 + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
47 + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
48 + * THIS SOFTWARE.
49 + */
31 50
32 51 #include <errno.h>
52 +#include <stdarg.h>
53 +#include <math.h>
33 54 #include "awk.h"
34 55 #include "y.tab.h"
35 56
36 57 uchar *record;
37 -size_t record_size;
58 +size_t record_size = RECSIZE;
59 +
60 +Cell **fldtab; /* pointers to Cells */
61 +char inputFS[100] = " ";
62 +
63 +#define MAXFLD 2
64 +int nfields = MAXFLD; /* last allocated slot for $i */
38 65
39 66 int donefld; /* 1 = implies rec broken into fields */
40 67 int donerec; /* 1 = record is valid (no flds have changed) */
41 68
42 -static struct fldtab_chunk {
43 - struct fldtab_chunk *next;
44 - Cell fields[FLD_INCR];
45 -} *fldtab_head, *fldtab_tail;
46 -
47 -static size_t fldtab_maxidx;
69 +int lastfld = 0; /* last used field */
48 70
49 71 static FILE *infile = NULL;
50 72 static uchar *file = (uchar*) "";
51 73 static uchar *fields;
52 -static size_t fields_size = LINE_INCR;
74 +static size_t fields_size = RECSIZE;
53 75
54 -static int maxfld = 0; /* last used field */
55 76 static int argno = 1; /* current input argument number */
56 77
57 78 static uchar *getargv(int);
58 79 static void cleanfld(int, int);
59 80 static int refldbld(uchar *, uchar *);
60 81 static void bcheck2(int, int, int);
61 82 static void eprint(void);
62 83 static void bclass(int);
84 +static void makefields(int, int);
85 +
86 +
87 +static Cell dollar0 = { OCELL, CFLD, NULL, (uchar *)"", 0.0, REC|STR|DONTFREE };
88 +static Cell dollar1 = { OCELL, CFLD, NULL, (uchar *)"", 0.0, FLD|STR|DONTFREE };
89 +
90 +void
91 +recinit(unsigned int n)
92 +{
93 + if ((record = (uchar *)malloc(n)) == NULL ||
94 + (fields = (uchar *)malloc(n+1)) == NULL ||
95 + (fldtab = (Cell **)malloc((nfields + 1) *
96 + sizeof (Cell *))) == NULL ||
97 + (fldtab[0] = (Cell *)malloc(sizeof (Cell))) == NULL)
98 + FATAL("out of space for $0 and fields");
99 + *fldtab[0] = dollar0;
100 + fldtab[0]->sval = record;
101 + fldtab[0]->nval = tostring((uchar *)"0");
102 + makefields(1, nfields);
103 +}
104 +
105 +static void
106 +makefields(int n1, int n2) /* create $n1..$n2 inclusive */
107 +{
108 + char temp[50];
109 + int i;
110 +
111 + for (i = n1; i <= n2; i++) {
112 + fldtab[i] = (Cell *)malloc(sizeof (struct Cell));
113 + if (fldtab[i] == NULL)
114 + FATAL("out of space in makefields %d", i);
115 + *fldtab[i] = dollar1;
116 + (void) sprintf(temp, "%d", i);
117 + fldtab[i]->nval = tostring((uchar *)temp);
118 + }
119 +}
63 120
64 121 static void
65 122 initgetrec(void)
66 123 {
67 124 int i;
68 125 uchar *p;
69 126
70 127 for (i = 1; i < *ARGC; i++) {
71 - if (!isclvar(p = getargv(i))) /* find 1st real filename */
128 + p = getargv(i); /* find 1st real filename */
129 + if (p == NULL || *p == '\0') { /* deleted or zapped */
130 + argno++;
131 + continue;
132 + }
133 + if (!isclvar(p)) {
134 + (void) setsval(lookup((uchar *)"FILENAME", symtab), p);
72 135 return;
136 + }
73 137 setclvar(p); /* a commandline assignment before filename */
74 138 argno++;
75 139 }
76 140 infile = stdin; /* no filenames, so use stdin */
77 - /* *FILENAME = file = (uchar*) "-"; */
78 141 }
79 142
143 +static int firsttime = 1;
144 +
80 145 int
81 -getrec(uchar **bufp, size_t *bufsizep)
82 -{
146 +getrec(uchar **pbuf, size_t *pbufsize, int isrecord)
147 +{ /* get next input record */
148 + /* note: cares whether buf == record */
83 149 int c;
84 - static int firsttime = 1;
85 - uchar_t *buf, *nbuf;
86 - size_t len;
150 + uchar_t *buf = *pbuf;
151 + uchar saveb0;
152 + size_t bufsize = *pbufsize, savebufsize = bufsize;
87 153
88 154 if (firsttime) {
89 155 firsttime = 0;
90 156 initgetrec();
91 157 }
92 158 dprintf(("RS=<%s>, FS=<%s>, ARGC=%f, FILENAME=%s\n",
93 159 *RS, *FS, *ARGC, *FILENAME));
94 - donefld = 0;
95 - donerec = 1;
160 + if (isrecord) {
161 + donefld = 0;
162 + donerec = 1;
163 + }
164 + saveb0 = buf[0];
165 + buf[0] = 0;
96 166 while (argno < *ARGC || infile == stdin) {
97 167 dprintf(("argno=%d, file=|%s|\n", argno, file));
98 168 if (infile == NULL) { /* have to open a new file */
99 169 file = getargv(argno);
100 - if (*file == '\0') { /* it's been zapped */
170 + /* deleted or zapped */
171 + if (file == NULL || *file == '\0') {
101 172 argno++;
102 173 continue;
103 174 }
104 175 if (isclvar(file)) { /* a var=value arg */
105 176 setclvar(file);
106 177 argno++;
107 178 continue;
108 179 }
109 180 *FILENAME = file;
110 181 dprintf(("opening file %s\n", file));
111 182 if (*file == '-' && *(file+1) == '\0')
112 183 infile = stdin;
113 184 else if ((infile = fopen((char *)file, "r")) == NULL)
114 - ERROR "can't open file %s", file FATAL;
185 + FATAL("can't open file %s", file);
115 186 (void) setfval(fnrloc, 0.0);
116 187 }
117 - c = readrec(&nbuf, &len, infile);
118 - expand_buf(bufp, bufsizep, len);
119 - buf = *bufp;
120 - (void) memcpy(buf, nbuf, len);
121 - buf[len] = '\0';
122 - free(nbuf);
123 -
188 + c = readrec(&buf, &bufsize, infile);
124 189 if (c != 0 || buf[0] != '\0') { /* normal record */
125 - if (bufp == &record) {
126 - if (!(recloc->tval & DONTFREE))
127 - xfree(recloc->sval);
128 - recloc->sval = record;
129 - recloc->tval = REC | STR | DONTFREE;
130 - if (is_number(recloc->sval)) {
131 - recloc->fval =
132 - atof((const char *)recloc->sval);
133 - recloc->tval |= NUM;
190 + if (isrecord) {
191 + if (freeable(fldtab[0]))
192 + xfree(fldtab[0]->sval);
193 + fldtab[0]->sval = buf; /* buf == record */
194 + fldtab[0]->tval = REC | STR | DONTFREE;
195 + if (is_number(fldtab[0]->sval)) {
196 + fldtab[0]->fval =
197 + atof((const char *)fldtab[0]->sval);
198 + fldtab[0]->tval |= NUM;
134 199 }
135 200 }
136 201 (void) setfval(nrloc, nrloc->fval+1);
137 202 (void) setfval(fnrloc, fnrloc->fval+1);
203 + *pbuf = buf;
204 + *pbufsize = bufsize;
138 205 return (1);
139 206 }
140 207 /* EOF arrived on this file; set up next */
141 208 if (infile != stdin)
142 209 (void) fclose(infile);
143 210 infile = NULL;
144 211 argno++;
145 212 }
213 + buf[0] = saveb0;
214 + *pbuf = buf;
215 + *pbufsize = savebufsize;
146 216 return (0); /* true end of file */
147 217 }
148 218
219 +void
220 +nextfile(void)
221 +{
222 + if (infile != NULL && infile != stdin)
223 + (void) fclose(infile);
224 + infile = NULL;
225 + argno++;
226 +}
227 +
228 +/*
229 + * read one record into buf
230 + */
149 231 int
150 -readrec(uchar **bufp, size_t *sizep, FILE *inf) /* read one record into buf */
232 +readrec(uchar **pbuf, size_t *pbufsize, FILE *inf)
151 233 {
152 234 int sep, c;
153 - uchar *buf;
154 - int count;
155 - size_t bufsize;
235 + uchar *rr, *buf = *pbuf;
236 + size_t bufsize = *pbufsize;
237 +
238 + if (strlen((char *)*FS) >= sizeof (inputFS))
239 + FATAL("field separator %.10s... is too long", *FS);
240 + /*
241 + * fflush(stdout); avoids some buffering problem
242 + * but makes it 25% slower
243 + */
156 244
157 - init_buf(&buf, &bufsize, LINE_INCR);
245 + /* for subsequent field splitting */
246 + (void) strcpy(inputFS, (char *)*FS);
158 247 if ((sep = **RS) == 0) {
159 248 sep = '\n';
160 249 /* skip leading \n's */
161 250 while ((c = getc(inf)) == '\n' && c != EOF)
162 251 ;
163 252 if (c != EOF)
164 253 (void) ungetc(c, inf);
165 254 }
166 - count = 0;
167 - for (;;) {
168 - while ((c = getc(inf)) != sep && c != EOF) {
169 - expand_buf(&buf, &bufsize, count);
170 - buf[count++] = c;
255 + for (rr = buf; ; ) {
256 + for (; (c = getc(inf)) != sep && c != EOF; ) {
257 + if (rr-buf+1 > bufsize)
258 + if (!adjbuf(&buf, &bufsize, 1+rr-buf,
259 + record_size, &rr, "readrec 1"))
260 + FATAL(
261 + "input record `%.30s...' too long", buf);
262 + *rr++ = c;
171 263 }
172 264 if (**RS == sep || c == EOF)
173 265 break;
174 266 if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */
175 267 break;
176 - expand_buf(&buf, &bufsize, count + 1);
177 - buf[count++] = '\n';
178 - buf[count++] = c;
179 - }
180 - buf[count] = '\0';
268 + if (!adjbuf(&buf, &bufsize, 2+rr-buf, record_size, &rr,
269 + "readrec 2"))
270 + FATAL("input record `%.30s...' too long", buf);
271 + *rr++ = '\n';
272 + *rr++ = c;
273 + }
274 + if (!adjbuf(&buf, &bufsize, 1+rr-buf, record_size, &rr, "readrec 3"))
275 + FATAL("input record `%.30s...' too long", buf);
276 + *rr = 0;
181 277 dprintf(("readrec saw <%s>, returns %d\n",
182 - buf, c == EOF && count == 0 ? 0 : 1));
183 - *bufp = buf;
184 - *sizep = count;
185 - return (c == EOF && count == 0 ? 0 : 1);
278 + buf, c == EOF && rr == buf ? 0 : 1));
279 + *pbuf = buf;
280 + *pbufsize = bufsize;
281 + return (c == EOF && rr == buf ? 0 : 1);
186 282 }
187 283
188 -/* get ARGV[n] */
189 284 static uchar *
190 -getargv(int n)
285 +getargv(int n) /* get ARGV[n] */
191 286 {
192 287 Cell *x;
193 - uchar *s, temp[11];
288 + uchar *s, temp[50];
194 289 extern Array *ARGVtab;
195 290
196 291 (void) sprintf((char *)temp, "%d", n);
292 + if (lookup(temp, ARGVtab) == NULL)
293 + return (NULL);
197 294 x = setsymtab(temp, (uchar *)"", 0.0, STR, ARGVtab);
198 295 s = getsval(x);
199 296 dprintf(("getargv(%d) returns |%s|\n", n, s));
200 297 return (s);
201 298 }
202 299
203 300 void
204 301 setclvar(uchar *s) /* set var=value from s */
205 302 {
206 303 uchar *p;
207 304 Cell *q;
208 305
209 306 for (p = s; *p != '='; p++)
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
210 307 ;
211 308 *p++ = 0;
212 309 p = qstring(p, '\0');
213 310 q = setsymtab(s, p, 0.0, STR, symtab);
214 311 (void) setsval(q, p);
215 312 if (is_number(q->sval)) {
216 313 q->fval = atof((const char *)q->sval);
217 314 q->tval |= NUM;
218 315 }
219 316 dprintf(("command line set %s to |%s|\n", s, p));
220 - free(p);
221 317 }
222 318
223 319 void
224 -fldbld(void)
320 +fldbld(void) /* create fields from current record */
225 321 {
322 + /* this relies on having fields[] the same length as $0 */
323 + /* the fields are all stored in this one array with \0's */
324 + /* possibly with a final trailing \0 not associated with any field */
226 325 uchar *r, *fr, sep;
227 326 Cell *p;
228 - int i;
229 - size_t len;
327 + int i, j;
328 + size_t n;
230 329
231 330 if (donefld)
232 331 return;
233 - if (!(recloc->tval & STR))
234 - (void) getsval(recloc);
235 - r = recloc->sval; /* was record! */
236 -
237 - /* make sure fields is always allocated */
238 - adjust_buf(&fields, fields_size);
239 -
240 - /*
241 - * make sure fields has enough size. We don't expand the buffer
242 - * in the middle of the loop, since p->sval has already pointed
243 - * the address in the fields.
244 - */
245 - len = strlen((char *)r) + 1;
246 - expand_buf(&fields, &fields_size, len);
332 + if (!isstr(fldtab[0]))
333 + (void) getsval(fldtab[0]);
334 + r = fldtab[0]->sval;
335 + n = strlen((char *)r);
336 + if (n > fields_size) {
337 + xfree(fields);
338 + /* possibly 2 final \0s */
339 + if ((fields = (uchar *)malloc(n + 2)) == NULL)
340 + FATAL("out of space for fields in fldbld %d", n);
341 + fields_size = n;
342 + }
247 343 fr = fields;
248 -
249 344 i = 0; /* number of fields accumulated here */
250 - if (strlen((char *)*FS) > 1) { /* it's a regular expression */
251 - i = refldbld(r, *FS);
252 - } else if ((sep = **FS) == ' ') {
345 + (void) strcpy(inputFS, (char *)*FS);
346 + if (strlen(inputFS) > 1) { /* it's a regular expression */
347 + i = refldbld(r, (uchar *)inputFS);
348 + } else if ((sep = *inputFS) == ' ') { /* default whitespace */
253 349 for (i = 0; ; ) {
254 350 while (*r == ' ' || *r == '\t' || *r == '\n')
255 351 r++;
256 352 if (*r == 0)
257 353 break;
258 354 i++;
259 - p = getfld(i);
260 - if (!(p->tval & DONTFREE))
261 - xfree(p->sval);
262 - p->sval = fr;
263 - p->tval = FLD | STR | DONTFREE;
355 + if (i > nfields)
356 + growfldtab(i);
357 + if (freeable(fldtab[i]))
358 + xfree(fldtab[i]->sval);
359 + fldtab[i]->sval = fr;
360 + fldtab[i]->tval = FLD | STR | DONTFREE;
264 361 do
265 362 *fr++ = *r++;
266 363 while (*r != ' ' && *r != '\t' && *r != '\n' &&
267 364 *r != '\0')
268 365 ;
269 366 *fr++ = 0;
270 367 }
271 368 *fr = 0;
369 + } else if ((sep = *inputFS) == 0) { /* new: FS="" => 1 char/field */
370 + for (i = 0; *r != 0; r++) {
371 + uchar buf[2];
372 + i++;
373 + if (i > nfields)
374 + growfldtab(i);
375 + if (freeable(fldtab[i]))
376 + xfree(fldtab[i]->sval);
377 + buf[0] = *r;
378 + buf[1] = 0;
379 + fldtab[i]->sval = tostring(buf);
380 + fldtab[i]->tval = FLD | STR;
381 + }
382 + *fr = 0;
272 383 } else if (*r != 0) { /* if 0, it's a null field */
384 + /*
385 + * subtlecase : if length(FS) == 1 && length(RS > 0)
386 + * \n is NOT a field separator (cf awk book 61,84).
387 + * this variable is tested in the inner while loop.
388 + */
389 + int rtest = '\n'; /* normal case */
390 + if (strlen((char *)*RS) > 0)
391 + rtest = '\0';
273 392 for (;;) {
274 393 i++;
275 - p = getfld(i);
276 - if (!(p->tval & DONTFREE))
277 - xfree(p->sval);
278 - p->sval = fr;
279 - p->tval = FLD | STR | DONTFREE;
280 - /* \n always a separator */
281 - while (*r != sep && *r != '\n' && *r != '\0')
394 + if (i > nfields)
395 + growfldtab(i);
396 + if (freeable(fldtab[i]))
397 + xfree(fldtab[i]->sval);
398 + fldtab[i]->sval = fr;
399 + fldtab[i]->tval = FLD | STR | DONTFREE;
400 + /* \n is always a separator */
401 + while (*r != sep && *r != rtest && *r != '\0')
282 402 *fr++ = *r++;
283 403 *fr++ = 0;
284 404 if (*r++ == 0)
285 405 break;
286 406 }
287 407 *fr = 0;
288 408 }
409 + if (i > nfields)
410 + FATAL("record `%.30s...' has too many fields; can't happen", r);
289 411 /* clean out junk from previous record */
290 - cleanfld(i, maxfld);
291 - maxfld = i;
412 + cleanfld(i + 1, lastfld);
413 + lastfld = i;
292 414 donefld = 1;
293 - for (i = 1; i <= maxfld; i++) {
294 - p = getfld(i);
415 + for (j = 1; j <= lastfld; j++) {
416 + p = fldtab[j];
295 417 if (is_number(p->sval)) {
296 418 p->fval = atof((const char *)p->sval);
297 419 p->tval |= NUM;
298 420 }
299 421 }
300 -
301 - (void) setfval(nfloc, (Awkfloat) maxfld);
422 + (void) setfval(nfloc, (Awkfloat)lastfld);
302 423 if (dbg) {
303 - for (i = 0; i <= maxfld; i++) {
304 - p = getfld(i);
305 - (void) printf("field %d: |%s|\n", i, p->sval);
424 + for (j = 0; j <= lastfld; j++) {
425 + p = fldtab[j];
426 + (void) printf("field %d (%s): |%s|\n", j, p->nval,
427 + p->sval);
306 428 }
307 429 }
308 430 }
309 431
310 432 static void
311 433 cleanfld(int n1, int n2) /* clean out fields n1..n2 inclusive */
312 -{
313 - static uchar *nullstat = (uchar *) "";
434 +{ /* nvals remain intact */
435 + static uchar *nullstat = (uchar *)"";
314 436 Cell *p;
315 - int i;
437 + int i;
316 438
317 - for (i = n2; i > n1; i--) {
318 - p = getfld(i);
319 - if (!(p->tval & DONTFREE))
439 + for (i = n1; i <= n2; i++) {
440 + p = fldtab[i];
441 + if (freeable(p))
320 442 xfree(p->sval);
321 - p->tval = FLD | STR | DONTFREE;
322 443 p->sval = nullstat;
444 + p->tval = FLD | STR | DONTFREE;
323 445 }
324 446 }
325 447
326 448 void
327 -newfld(int n) /* add field n (after end) */
449 +newfld(int n) /* add field n after end of existing lastfld */
328 450 {
329 - if (n < 0)
330 - ERROR "accessing invalid field", record FATAL;
331 - (void) getfld(n);
332 - cleanfld(maxfld, n);
333 - maxfld = n;
334 - (void) setfval(nfloc, (Awkfloat) n);
335 -}
336 -
337 -/*
338 - * allocate field table. We don't reallocate the table since there
339 - * might be somewhere recording the address of the table.
340 - */
341 -static void
342 -morefld(void)
343 -{
344 - int i;
345 - struct fldtab_chunk *fldcp;
346 - Cell *newfld;
347 -
348 - if ((fldcp = calloc(sizeof (struct fldtab_chunk), 1)) == NULL)
349 - ERROR "out of space in morefld" FATAL;
350 -
351 - newfld = &fldcp->fields[0];
352 - for (i = 0; i < FLD_INCR; i++) {
353 - newfld[i].ctype = OCELL;
354 - newfld[i].csub = CFLD;
355 - newfld[i].nval = NULL;
356 - newfld[i].sval = (uchar *)"";
357 - newfld[i].fval = 0.0;
358 - newfld[i].tval = FLD|STR|DONTFREE;
359 - newfld[i].cnext = NULL;
360 - }
361 - /*
362 - * link this field chunk
363 - */
364 - if (fldtab_head == NULL)
365 - fldtab_head = fldcp;
366 - else
367 - fldtab_tail->next = fldcp;
368 - fldtab_tail = fldcp;
369 - fldcp->next = NULL;
370 -
371 - fldtab_maxidx += FLD_INCR;
451 + if (n > nfields)
452 + growfldtab(n);
453 + cleanfld(lastfld + 1, n);
454 + lastfld = n;
455 + (void) setfval(nfloc, (Awkfloat)n);
372 456 }
373 457
374 458 Cell *
375 -getfld(int idx)
459 +fieldadr(int n) /* get nth field */
376 460 {
377 - struct fldtab_chunk *fldcp;
378 - int cbase;
379 -
380 - if (idx < 0)
381 - ERROR "trying to access field %d", idx FATAL;
382 - while (idx >= fldtab_maxidx)
383 - morefld();
384 - cbase = 0;
385 - for (fldcp = fldtab_head; fldcp != NULL; fldcp = fldcp->next) {
386 - if (idx < (cbase + FLD_INCR))
387 - return (&fldcp->fields[idx - cbase]);
388 - cbase += FLD_INCR;
389 - }
390 - /* should never happen */
391 - ERROR "trying to access invalid field %d", idx FATAL;
392 - return (NULL);
461 + if (n < 0)
462 + FATAL("trying to access out of range field %d", n);
463 + if (n > nfields) /* fields after NF are empty */
464 + growfldtab(n); /* but does not increase NF */
465 + return (fldtab[n]);
393 466 }
394 467
395 -int
396 -fldidx(Cell *vp)
397 -{
398 - struct fldtab_chunk *fldcp;
399 - Cell *tbl;
400 - int cbase;
401 -
402 - cbase = 0;
403 - for (fldcp = fldtab_head; fldcp != NULL; fldcp = fldcp->next) {
404 - tbl = &fldcp->fields[0];
405 - if (vp >= tbl && vp < (tbl + FLD_INCR))
406 - return (cbase + (vp - tbl));
407 - cbase += FLD_INCR;
408 - }
409 - /* should never happen */
410 - ERROR "trying to access unknown field" FATAL;
411 - return (0);
468 +void
469 +growfldtab(int n) /* make new fields up to at least $n */
470 +{
471 + int nf = 2 * nfields;
472 + size_t s;
473 +
474 + if (n > nf)
475 + nf = n;
476 + /* freebsd: how much do we need? */
477 + s = (nf + 1) * (sizeof (struct Cell *));
478 + if (s / sizeof (struct Cell *) - 1 == nf) /* didn't overflow */
479 + fldtab = (Cell **) realloc(fldtab, s);
480 + else /* overflow sizeof int */
481 + xfree(fldtab); /* make it null */
482 + if (fldtab == NULL)
483 + FATAL("out of space creating %d fields", nf);
484 + makefields(nfields + 1, nf);
485 + nfields = nf;
412 486 }
413 487
414 488 static int
415 489 refldbld(uchar *rec, uchar *fs) /* build fields from reg expr in FS */
416 490 {
491 + /* this relies on having fields[] the same length as $0 */
492 + /* the fields are all stored in this one array with \0's */
417 493 uchar *fr;
418 494 int i, tempstat;
419 495 fa *pfa;
420 - Cell *p;
421 - size_t len;
496 + size_t n;
422 497
423 - /* make sure fields is allocated */
424 - adjust_buf(&fields, fields_size);
498 + n = strlen((char *)rec);
499 + if (n > fields_size) {
500 + xfree(fields);
501 + if ((fields = (uchar *)malloc(n + 1)) == NULL)
502 + FATAL("out of space for fields in refldbld %d", n);
503 + fields_size = n;
504 + }
425 505 fr = fields;
426 506 *fr = '\0';
427 507 if (*rec == '\0')
428 508 return (0);
429 -
430 - len = strlen((char *)rec) + 1;
431 - expand_buf(&fields, &fields_size, len);
432 - fr = fields;
433 -
434 509 pfa = makedfa(fs, 1);
435 510 dprintf(("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs));
436 511 tempstat = pfa->initstat;
437 512 for (i = 1; ; i++) {
438 - p = getfld(i);
439 - if (!(p->tval & DONTFREE))
440 - xfree(p->sval);
441 - p->tval = FLD | STR | DONTFREE;
442 - p->sval = fr;
513 + if (i > nfields)
514 + growfldtab(i);
515 + if (freeable(fldtab[i]))
516 + xfree(fldtab[i]->sval);
517 + fldtab[i]->tval = FLD | STR | DONTFREE;
518 + fldtab[i]->sval = fr;
443 519 dprintf(("refldbld: i=%d\n", i));
444 520 if (nematch(pfa, rec)) {
445 - pfa->initstat = 2;
521 + pfa->initstat = 2; /* horrible coupling to b.c */
446 522 dprintf(("match %s (%d chars)\n", patbeg, patlen));
447 523 (void) strncpy((char *)fr, (char *)rec, patbeg-rec);
448 524 fr += patbeg - rec + 1;
449 525 *(fr-1) = '\0';
450 526 rec = patbeg + patlen;
451 527 } else {
452 528 dprintf(("no match %s\n", rec));
453 529 (void) strcpy((char *)fr, (char *)rec);
454 530 pfa->initstat = tempstat;
455 531 break;
456 532 }
457 533 }
458 534 return (i);
459 535 }
460 536
461 537 void
462 -recbld(void)
538 +recbld(void) /* create $0 from $1..$NF if necessary */
463 539 {
464 540 int i;
465 - uchar *p;
466 - size_t cnt, len, olen;
541 + uchar *r, *p;
467 542
468 543 if (donerec == 1)
469 544 return;
470 - cnt = 0;
471 - olen = strlen((char *)*OFS);
545 + r = record;
472 546 for (i = 1; i <= *NF; i++) {
473 - p = getsval(getfld(i));
474 - len = strlen((char *)p);
475 - expand_buf(&record, &record_size, cnt + len + olen);
476 - (void) memcpy(&record[cnt], p, len);
477 - cnt += len;
547 + p = getsval(fldtab[i]);
548 + if (!adjbuf(&record, &record_size, 1 + strlen((char *)p) + r -
549 + record, record_size, &r, "recbld 1"))
550 + FATAL("created $0 `%.30s...' too long", record);
551 + while ((*r = *p++) != 0)
552 + r++;
478 553 if (i < *NF) {
479 - (void) memcpy(&record[cnt], *OFS, olen);
480 - cnt += olen;
554 + if (!adjbuf(&record, &record_size, 2 +
555 + strlen((char *)*OFS) + r - record, record_size,
556 + &r, "recbld 2"))
557 + FATAL("created $0 `%.30s...' too long", record);
558 + for (p = *OFS; (*r = *p++) != 0; )
559 + r++;
481 560 }
482 561 }
483 - record[cnt] = '\0';
484 - dprintf(("in recbld FS=%o, recloc=%p\n", **FS, (void *)recloc));
485 - if (!(recloc->tval & DONTFREE))
486 - xfree(recloc->sval);
487 - recloc->tval = REC | STR | DONTFREE;
488 - recloc->sval = record;
489 - dprintf(("in recbld FS=%o, recloc=%p\n", **FS, (void *)recloc));
562 + if (!adjbuf(&record, &record_size, 2 + r - record, record_size, &r,
563 + "recbld 3"))
564 + FATAL("built giant record `%.30s...'", record);
565 + *r = '\0';
566 + dprintf(("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS,
567 + (void *)fldtab[0]));
568 +
569 + if (freeable(fldtab[0]))
570 + xfree(fldtab[0]->sval);
571 + fldtab[0]->tval = REC | STR | DONTFREE;
572 + fldtab[0]->sval = record;
573 +
574 + dprintf(("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS,
575 + (void *)fldtab[0]));
490 576 dprintf(("recbld = |%s|\n", record));
491 577 donerec = 1;
492 578 }
493 579
494 -Cell *
495 -fieldadr(int n)
496 -{
497 - if (n < 0)
498 - ERROR "trying to access field %d", n FATAL;
499 - return (getfld(n));
500 -}
501 -
502 580 int errorflag = 0;
503 -char errbuf[200];
504 581
505 582 void
506 583 yyerror(char *s)
507 584 {
585 + SYNTAX("%s", s);
586 +}
587 +
588 +void
589 +SYNTAX(const char *fmt, ...)
590 +{
508 591 extern uchar *cmdname, *curfname;
509 592 static int been_here = 0;
593 + va_list varg;
510 594
511 595 if (been_here++ > 2)
512 596 return;
513 - (void) fprintf(stderr, "%s: %s", cmdname, s);
597 + (void) fprintf(stderr, "%s: ", cmdname);
598 + va_start(varg, fmt);
599 + (void) vfprintf(stderr, fmt, varg);
600 + va_end(varg);
514 601 (void) fprintf(stderr, gettext(" at source line %lld"), lineno);
515 602 if (curfname != NULL)
516 603 (void) fprintf(stderr, gettext(" in function %s"), curfname);
604 + if (compile_time == 1 && cursource() != NULL)
605 + (void) fprintf(stderr, gettext(" source file %s"), cursource());
517 606 (void) fprintf(stderr, "\n");
518 607 errorflag = 2;
519 608 eprint();
520 609 }
521 610
522 -/*ARGSUSED*/
523 611 void
524 -fpecatch(int sig)
612 +fpecatch(int n)
525 613 {
526 - ERROR "floating point exception" FATAL;
614 + FATAL("floating point exception %d", n);
527 615 }
528 616
529 617 extern int bracecnt, brackcnt, parencnt;
530 618
531 619 void
532 620 bracecheck(void)
533 621 {
534 622 int c;
535 623 static int beenhere = 0;
536 624
537 625 if (beenhere++)
538 626 return;
539 627 while ((c = input()) != EOF && c != '\0')
540 628 bclass(c);
541 629 bcheck2(bracecnt, '{', '}');
542 630 bcheck2(brackcnt, '[', ']');
543 631 bcheck2(parencnt, '(', ')');
544 632 }
545 633
546 634 /*ARGSUSED*/
547 635 static void
548 636 bcheck2(int n, int c1, int c2)
549 637 {
550 638 if (n == 1)
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
551 639 (void) fprintf(stderr, gettext("\tmissing %c\n"), c2);
552 640 else if (n > 1)
553 641 (void) fprintf(stderr, gettext("\t%d missing %c's\n"), n, c2);
554 642 else if (n == -1)
555 643 (void) fprintf(stderr, gettext("\textra %c\n"), c2);
556 644 else if (n < -1)
557 645 (void) fprintf(stderr, gettext("\t%d extra %c's\n"), -n, c2);
558 646 }
559 647
560 648 void
561 -error(int f, char *s)
649 +FATAL(const char *fmt, ...)
562 650 {
563 - extern Node *curnode;
564 651 extern uchar *cmdname;
652 + va_list varg;
565 653
566 654 (void) fflush(stdout);
567 655 (void) fprintf(stderr, "%s: ", cmdname);
568 - (void) fprintf(stderr, "%s", s);
656 + va_start(varg, fmt);
657 + (void) vfprintf(stderr, fmt, varg);
658 + va_end(varg);
659 + error();
660 + if (dbg > 1) /* core dump if serious debugging on */
661 + abort();
662 + exit(2);
663 +}
664 +
665 +void
666 +WARNING(const char *fmt, ...)
667 +{
668 + extern uchar *cmdname;
669 + va_list varg;
670 +
671 + (void) fflush(stdout);
672 + (void) fprintf(stderr, "%s: ", cmdname);
673 + va_start(varg, fmt);
674 + (void) vfprintf(stderr, fmt, varg);
675 + va_end(varg);
676 + error();
677 +}
678 +
679 +void
680 +error(void)
681 +{
682 + extern Node *curnode;
683 +
569 684 (void) fprintf(stderr, "\n");
570 685 if (compile_time != 2 && NR && *NR > 0) {
571 686 (void) fprintf(stderr,
572 - gettext(" input record number %g"), *FNR);
687 + gettext(" input record number %g"), (int) (*FNR));
573 688 if (strcmp((char *)*FILENAME, "-") != 0)
574 689 (void) fprintf(stderr, gettext(", file %s"), *FILENAME);
575 690 (void) fprintf(stderr, "\n");
576 691 }
577 692 if (compile_time != 2 && curnode)
578 - (void) fprintf(stderr, gettext(" source line number %lld\n"),
693 + (void) fprintf(stderr, gettext(" source line number %d"),
579 694 curnode->lineno);
580 695 else if (compile_time != 2 && lineno) {
581 696 (void) fprintf(stderr,
582 - gettext(" source line number %lld\n"), lineno);
697 + gettext(" source line number %d"), lineno);
583 698 }
699 + if (compile_time == 1 && cursource() != NULL)
700 + (void) fprintf(stderr,
701 + gettext(" source file %s"), cursource());
702 + (void) fprintf(stderr, "\n");
584 703 eprint();
585 - if (f) {
586 - if (dbg)
587 - abort();
588 - exit(2);
589 - }
590 704 }
591 705
592 706 static void
593 707 eprint(void) /* try to print context around error */
594 708 {
595 709 uchar *p, *q;
596 710 int c;
597 711 static int been_here = 0;
598 - extern uchar ebuf[300], *ep;
712 + extern uchar ebuf[], *ep;
599 713
600 714 if (compile_time == 2 || compile_time == 0 || been_here++ > 0)
601 715 return;
602 716 p = ep - 1;
603 717 if (p > ebuf && *p == '\n')
604 718 p--;
605 719 for (; p > ebuf && *p != '\n' && *p != '\0'; p--)
606 720 ;
607 721 while (*p == '\n')
608 722 p++;
609 723 (void) fprintf(stderr, gettext(" context is\n\t"));
610 724 for (q = ep-1; q >= p && *q != ' ' && *q != '\t' && *q != '\n'; q--)
611 725 ;
612 726 for (; p < q; p++)
613 727 if (*p)
614 728 (void) putc(*p, stderr);
615 729 (void) fprintf(stderr, " >>> ");
616 730 for (; p < ep; p++)
617 731 if (*p)
618 732 (void) putc(*p, stderr);
619 733 (void) fprintf(stderr, " <<< ");
620 734 if (*ep)
621 735 while ((c = input()) != '\n' && c != '\0' && c != EOF) {
622 736 (void) putc(c, stderr);
623 737 bclass(c);
624 738 }
625 739 (void) putc('\n', stderr);
626 740 ep = ebuf;
627 741 }
628 742
629 743 static void
630 744 bclass(int c)
631 745 {
632 746 switch (c) {
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
633 747 case '{': bracecnt++; break;
634 748 case '}': bracecnt--; break;
635 749 case '[': brackcnt++; break;
636 750 case ']': brackcnt--; break;
637 751 case '(': parencnt++; break;
638 752 case ')': parencnt--; break;
639 753 }
640 754 }
641 755
642 756 double
643 -errcheck(double x, char *s)
757 +errcheck(double x, const char *s)
644 758 {
645 - extern int errno;
646 -
647 759 if (errno == EDOM) {
648 760 errno = 0;
649 - ERROR "%s argument out of domain", s WARNING;
761 + WARNING("%s argument out of domain", s);
650 762 x = 1;
651 763 } else if (errno == ERANGE) {
652 764 errno = 0;
653 - ERROR "%s result out of range", s WARNING;
765 + WARNING("%s result out of range", s);
654 766 x = 1;
655 767 }
656 768 return (x);
657 769 }
658 770
659 -void
660 -PUTS(uchar *s)
661 -{
662 - dprintf(("%s\n", s));
663 -}
664 -
665 771 int
666 -isclvar(uchar *s) /* is s of form var=something? */
772 +isclvar(const uchar *s) /* is s of form var=something? */
667 773 {
668 - if (s != NULL) {
774 + const uchar *os = s;
669 775
670 - /* Must begin with an underscore or alphabetic character */
671 - if (isalpha(*s) || (*s == '_')) {
672 -
673 - for (s++; *s; s++) {
674 - /*
675 - * followed by a sequence of underscores,
676 - * digits, and alphabetics
677 - */
678 - if (!(isalnum(*s) || *s == '_')) {
679 - break;
680 - }
681 - }
682 - return (*s == '=' && *(s + 1) != '=');
683 - }
776 + if (!isalpha(*s) && *s != '_')
777 + return (0);
778 + for (; *s; s++) {
779 + if (!(isalnum(*s) || *s == '_'))
780 + break;
684 781 }
685 782
686 - return (0);
783 + return (*s == '=' && s > os && *(s+1) != '=');
687 784 }
688 785
689 -#define MAXEXPON 38 /* maximum exponent for fp number */
786 +/* strtod is supposed to be a proper test of what's a valid number */
787 +/* appears to be broken in gcc on linux: thinks 0x123 is a valid FP number */
788 +/* wrong: violates 4.10.1.4 of ansi C standard */
690 789
691 790 int
692 -is_number(uchar *s)
791 +is_number(const uchar *s)
693 792 {
694 - int d1, d2;
695 - int point;
696 - uchar *es;
697 - extern char radixpoint;
698 -
699 - d1 = d2 = point = 0;
700 - while (*s == ' ' || *s == '\t' || *s == '\n')
701 - s++;
702 - if (*s == '\0')
703 - return (0); /* empty stuff isn't number */
704 - if (*s == '+' || *s == '-')
705 - s++;
706 - if (!isdigit(*s) && *s != radixpoint)
707 - return (0);
708 - if (isdigit(*s)) {
709 - do {
710 - d1++;
711 - s++;
712 - } while (isdigit(*s));
713 - }
714 - if (d1 >= MAXEXPON)
715 - return (0); /* too many digits to convert */
716 - if (*s == radixpoint) {
717 - point++;
718 - s++;
719 - }
720 - if (isdigit(*s)) {
721 - d2++;
722 - do {
723 - s++;
724 - } while (isdigit(*s));
725 - }
726 - if (!(d1 || point && d2))
793 + double r;
794 + char *ep;
795 + errno = 0;
796 + r = strtod((const char *)s, &ep);
797 + if (ep == (char *)s || r == HUGE_VAL || errno == ERANGE)
727 798 return (0);
728 - if (*s == 'e' || *s == 'E') {
729 - s++;
730 - if (*s == '+' || *s == '-')
731 - s++;
732 - if (!isdigit(*s))
733 - return (0);
734 - es = s;
735 - do {
736 - s++;
737 - } while (isdigit(*s));
738 - if (s - es > 2) {
739 - return (0);
740 - } else if (s - es == 2 &&
741 - (int)(10 * (*es-'0') + *(es+1)-'0') >= MAXEXPON) {
742 - return (0);
743 - }
744 - }
745 - while (*s == ' ' || *s == '\t' || *s == '\n')
746 - s++;
747 - if (*s == '\0')
799 + while (*ep == ' ' || *ep == '\t' || *ep == '\n')
800 + ep++;
801 + if (*ep == '\0')
748 802 return (1);
749 803 else
750 804 return (0);
751 805 }
752 -
753 -void
754 -init_buf(uchar **optr, size_t *sizep, size_t amt)
755 -{
756 - uchar *nptr = NULL;
757 -
758 - if ((nptr = malloc(amt)) == NULL)
759 - ERROR "out of space in init_buf" FATAL;
760 - /* initial buffer should have NULL terminated */
761 - *nptr = '\0';
762 - if (sizep != NULL)
763 - *sizep = amt;
764 - *optr = nptr;
765 -}
766 -
767 -void
768 -r_expand_buf(uchar **optr, size_t *sizep, size_t req)
769 -{
770 - uchar *nptr;
771 - size_t amt, size = *sizep;
772 -
773 - if (size != 0 && req < (size - 1))
774 - return;
775 - amt = req + 1 - size;
776 - amt = (amt / LINE_INCR + 1) * LINE_INCR;
777 -
778 - if ((nptr = realloc(*optr, size + amt)) == NULL)
779 - ERROR "out of space in expand_buf" FATAL;
780 - /* initial buffer should have NULL terminated */
781 - if (size == 0)
782 - *nptr = '\0';
783 - *sizep += amt;
784 - *optr = nptr;
785 -}
786 -
787 -void
788 -adjust_buf(uchar **optr, size_t size)
789 -{
790 - uchar *nptr;
791 -
792 - if ((nptr = realloc(*optr, size)) == NULL)
793 - ERROR "out of space in adjust_buf" FATAL;
794 - *optr = nptr;
795 -}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX