Print this page
3731 Update nawk to version 20121220
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/awk/run.c
+++ new/usr/src/cmd/awk/run.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
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
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 (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 -/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 -/* All Rights Reserved */
26 +/*
27 + * Copyright (C) Lucent Technologies 1997
28 + * All Rights Reserved
29 + *
30 + * Permission to use, copy, modify, and distribute this software and
31 + * its documentation for any purpose and without fee is hereby
32 + * granted, provided that the above copyright notice appear in all
33 + * copies and that both that the copyright notice and this
34 + * permission notice and warranty disclaimer appear in supporting
35 + * documentation, and that the name Lucent Technologies or any of
36 + * its entities not be used in advertising or publicity pertaining
37 + * to distribution of the software without specific, written prior
38 + * permission.
39 + *
40 + * LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
41 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
42 + * IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
43 + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
44 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
45 + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
46 + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
47 + * THIS SOFTWARE.
48 + */
28 49
29 -#define tempfree(x, s) if (istemp(x)) tfree(x, s)
30 -
31 -#define execute(p) r_execute(p)
50 +#define tempfree(x) if (istemp(x)) tfree(x);
32 51
33 52 #define DEBUG
34 -#include "awk.h"
35 -#include <math.h>
36 -#include "y.tab.h"
37 -#include <stdio.h>
38 -#include <ctype.h>
39 -#include <setjmp.h>
40 -#include <time.h>
41 -
42 -#ifndef FOPEN_MAX
43 -#define FOPEN_MAX 15 /* max number of open files, from ANSI std. */
44 -#endif
45 -
53 +#include <setjmp.h>
54 +#include <math.h>
55 +#include <time.h>
56 +#include "awk.h"
57 +#include "y.tab.h"
58 +
59 +static Cell *execute(Node *);
60 +static Cell *gettemp(void);
61 +static Cell *copycell(Cell *);
62 +static FILE *openfile(int, const uchar *);
63 +static FILE *redirect(int, Node *);
64 +static const char *filename(FILE *);
65 +static void flush_all(void);
46 66
47 67 static jmp_buf env;
68 +extern Awkfloat srand_seed;
48 69
49 -static Cell *r_execute(Node *);
50 -static Cell *gettemp(char *), *copycell(Cell *);
51 -static FILE *openfile(int, uchar *), *redirect(int, Node *);
52 -
53 -int paircnt;
54 -Node *winner = NULL;
55 -
56 -static Cell *tmps;
70 +Node *winner = NULL; /* root of parse tree */
57 71
72 +static Cell *tmps; /* free temporary cells for execution */
58 73 static Cell truecell = { OBOOL, BTRUE, 0, 0, 1.0, NUM };
59 -Cell *true = &truecell;
74 +Cell *True = &truecell;
60 75 static Cell falsecell = { OBOOL, BFALSE, 0, 0, 0.0, NUM };
61 -Cell *false = &falsecell;
76 +Cell *False = &falsecell;
62 77 static Cell breakcell = { OJUMP, JBREAK, 0, 0, 0.0, NUM };
63 78 Cell *jbreak = &breakcell;
64 79 static Cell contcell = { OJUMP, JCONT, 0, 0, 0.0, NUM };
65 80 Cell *jcont = &contcell;
66 81 static Cell nextcell = { OJUMP, JNEXT, 0, 0, 0.0, NUM };
67 82 Cell *jnext = &nextcell;
83 +static Cell nextfilecell = { OJUMP, JNEXTFILE, 0, 0, 0.0, NUM };
84 +Cell *jnextfile = &nextfilecell;
68 85 static Cell exitcell = { OJUMP, JEXIT, 0, 0, 0.0, NUM };
69 86 Cell *jexit = &exitcell;
70 87 static Cell retcell = { OJUMP, JRET, 0, 0, 0.0, NUM };
71 88 Cell *jret = &retcell;
72 -static Cell tempcell = { OCELL, CTEMP, 0, 0, 0.0, NUM };
89 +static Cell tempcell = { OCELL, CTEMP, 0, (uchar *)"", 0.0, NUM|
90 + STR|DONTFREE};
73 91
74 92 Node *curnode = NULL; /* the node being executed, for debugging */
75 93
76 -static void tfree(Cell *, char *);
94 +static void tfree(Cell *);
77 95 static void closeall(void);
78 96 static double ipow(double, int);
97 +static void stdinit(void);
98 +
99 +/*
100 + * buffer memory management
101 + *
102 + * pbuf: address of pointer to buffer being managed
103 + * psiz: address of buffer size variable
104 + * minlen: minimum length of buffer needed
105 + * quantum: buffer size quantum
106 + * pbptr: address of movable pointer into buffer, or 0 if none
107 + * whatrtn: name of the calling routine if failure should cause fatal error
108 + *
109 + * return 0 for realloc failure, !=0 for success
110 + */
111 +int adjbuf(uchar **pbuf, size_t *psiz, int minlen, int quantum, uchar **pbptr,
112 + const char *whatrtn)
113 +{
114 + if (minlen > *psiz) {
115 + uchar *tbuf;
116 + int rminlen = quantum ? minlen % quantum : 0;
117 + int boff = pbptr ? *pbptr - *pbuf : 0;
118 + /* round up to next multiple of quantum */
119 + if (rminlen)
120 + minlen += quantum - rminlen;
121 + tbuf = (uchar *)realloc(*pbuf, minlen);
122 + dprintf(("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn,
123 + *psiz, minlen, (void *)*pbuf, (void *)tbuf));
124 + if (tbuf == NULL) {
125 + if (whatrtn)
126 + FATAL("out of memory in %s", whatrtn);
127 + return (0);
128 + }
129 + *pbuf = (uchar *)tbuf;
130 + *psiz = minlen;
131 + if (pbptr)
132 + *pbptr = tbuf + boff;
133 + }
134 + return (1);
135 +}
79 136
80 137 void
81 -run(Node *a)
138 +run(Node *a) /* execution of parse tree starts here */
82 139 {
140 + stdinit();
83 141 (void) execute(a);
84 142 closeall();
85 143 }
86 144
87 145 static Cell *
88 -r_execute(Node *u)
146 +execute(Node *u) /* execute a node of the parse tree */
89 147 {
90 - register Cell *(*proc)();
91 - register Cell *x;
92 - register Node *a;
148 + Cell *(*proc)(Node **, int);
149 + Cell *x;
150 + Node *a;
93 151
94 152 if (u == NULL)
95 - return (true);
153 + return (True);
96 154 for (a = u; ; a = a->nnext) {
97 155 curnode = a;
98 156 if (isvalue(a)) {
99 - x = (Cell *) (a->narg[0]);
100 - if ((x->tval & FLD) && !donefld)
157 + x = (Cell *)(a->narg[0]);
158 + if (isfld(x) && !donefld)
101 159 fldbld();
102 - else if ((x->tval & REC) && !donerec)
160 + else if (isrec(x) && !donerec)
103 161 recbld();
104 162 return (x);
105 163 }
106 164 /* probably a Cell* but too risky to print */
107 165 if (notlegal(a->nobj))
108 - ERROR "illegal statement" FATAL;
166 + FATAL("illegal statement");
109 167 proc = proctab[a->nobj-FIRSTTOKEN];
110 168 x = (*proc)(a->narg, a->nobj);
111 - if ((x->tval & FLD) && !donefld)
169 + if (isfld(x) && !donefld)
112 170 fldbld();
113 - else if ((x->tval & REC) && !donerec)
171 + else if (isrec(x) && !donerec)
114 172 recbld();
115 173 if (isexpr(a))
116 174 return (x);
117 - /* a statement, goto next statement */
118 175 if (isjump(x))
119 176 return (x);
120 177 if (a->nnext == (Node *)NULL)
121 178 return (x);
122 - tempfree(x, "execute");
179 + tempfree(x);
123 180 }
124 181 }
125 182
126 183 /*ARGSUSED*/
127 184 Cell *
128 -program(Node **a, int n)
129 -{
130 - register Cell *x;
185 +program(Node **a, int n) /* execute an awk program */
186 +{ /* a[0] = BEGIN, a[1] = body, a[2] = END */
187 + Cell *x;
131 188
132 189 if (setjmp(env) != 0)
133 190 goto ex;
134 191 if (a[0]) { /* BEGIN */
135 192 x = execute(a[0]);
136 193 if (isexit(x))
137 - return (true);
194 + return (True);
138 195 if (isjump(x)) {
139 - ERROR "illegal break, continue or next from BEGIN"
140 - FATAL;
196 + FATAL(
197 + "illegal break, continue, next or nextfile from BEGIN");
141 198 }
142 - tempfree(x, "");
199 + tempfree(x);
143 200 }
144 -loop:
145 - if (a[1] || a[2])
146 - while (getrec(&record, &record_size) > 0) {
201 +
202 + if (a[1] || a[2]) {
203 + while (getrec(&record, &record_size, 1) > 0) {
147 204 x = execute(a[1]);
148 205 if (isexit(x))
149 206 break;
150 - tempfree(x, "");
207 + tempfree(x);
151 208 }
209 + }
152 210 ex:
153 - if (setjmp(env) != 0)
211 + if (setjmp(env) != 0) /* handles exit within END */
154 212 goto ex1;
155 213 if (a[2]) { /* END */
156 214 x = execute(a[2]);
157 - if (iscont(x)) /* read some more */
158 - goto loop;
159 - if (isbreak(x) || isnext(x))
160 - ERROR "illegal break or next from END" FATAL;
161 - tempfree(x, "");
215 + if (isbreak(x) || isnext(x) || iscont(x))
216 + FATAL(
217 + "illegal break, continue, next or nextfile from END");
218 + tempfree(x);
162 219 }
163 220 ex1:
164 - return (true);
221 + return (True);
165 222 }
166 223
167 -struct Frame {
224 +struct Frame { /* stack frame for awk function calls */
168 225 int nargs; /* number of arguments in this call */
169 226 Cell *fcncell; /* pointer to Cell for function */
170 227 Cell **args; /* pointer to array of arguments after execute */
171 228 Cell *retval; /* return value */
172 229 };
173 230
174 -#define NARGS 30
231 +#define NARGS 50 /* max args in a call */
175 232
176 233 struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */
177 234 int nframe = 0; /* number of frames allocated */
178 235 struct Frame *fp = NULL; /* frame pointer. bottom level unused */
179 236
180 237 /*ARGSUSED*/
181 238 Cell *
182 -call(Node **a, int n)
239 +call(Node **a, int n) /* function call. very kludgy and fragile */
183 240 {
184 241 static Cell newcopycell =
185 - { OCELL, CCOPY, 0, (uchar *) "", 0.0, NUM|STR|DONTFREE };
186 - int i, ncall, ndef, freed = 0;
242 + { OCELL, CCOPY, 0, (uchar *) "", 0.0, NUM|STR|DONTFREE };
243 + int i, ncall, ndef;
244 + /* handles potential double freeing when fcn & param share a tempcell */
245 + int freed = 0;
187 246 Node *x;
188 - Cell *args[NARGS], *oargs[NARGS], *y, *z, *fcn;
247 + Cell *args[NARGS], *oargs[NARGS]; /* BUG: fixed size arrays */
248 + Cell *y, *z, *fcn;
189 249 uchar *s;
190 250
191 251 fcn = execute(a[0]); /* the function itself */
192 252 s = fcn->nval;
193 - if (!isfunc(fcn))
194 - ERROR "calling undefined function %s", s FATAL;
253 + if (!isfcn(fcn))
254 + FATAL("calling undefined function %s", s);
195 255 if (frame == NULL) {
196 256 fp = frame = (struct Frame *)calloc(nframe += 100,
197 257 sizeof (struct Frame));
198 258 if (frame == NULL) {
199 - ERROR "out of space for stack frames calling %s",
200 - s FATAL;
259 + FATAL("out of space for stack frames calling %s", s);
201 260 }
202 261 }
203 262 for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */
204 263 ncall++;
205 264 ndef = (int)fcn->fval; /* args in defn */
206 265 dprintf(("calling %s, %d args (%d in defn), fp=%d\n",
207 - s, ncall, ndef, fp-frame));
266 + s, ncall, ndef, (int)(fp-frame)));
267 +
208 268 if (ncall > ndef) {
209 - ERROR "function %s called with %d args, uses only %d",
210 - s, ncall, ndef WARNING;
269 + WARNING("function %s called with %d args, uses only %d",
270 + s, ncall, ndef);
211 271 }
212 272 if (ncall + ndef > NARGS) {
213 - ERROR "function %s has %d arguments, limit %d",
214 - s, ncall+ndef, NARGS FATAL;
273 + FATAL("function %s has %d arguments, limit %d",
274 + s, ncall + ndef, NARGS);
215 275 }
216 276 for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) {
217 277 /* get call args */
218 - dprintf(("evaluate args[%d], fp=%d:\n", i, fp-frame));
278 + dprintf(("evaluate args[%d], fp=%d:\n", i, (int)(fp-frame)));
219 279 y = execute(x);
220 280 oargs[i] = y;
221 281 dprintf(("args[%d]: %s %f <%s>, t=%o\n",
222 282 i, y->nval, y->fval,
223 283 isarr(y) ? "(array)" : (char *)y->sval, y->tval));
224 - if (isfunc(y)) {
225 - ERROR "can't use function %s as argument in %s",
226 - y->nval, s FATAL;
284 + if (isfcn(y)) {
285 + FATAL("can't use function %s as argument in %s",
286 + y->nval, s);
227 287 }
228 288 if (isarr(y))
229 289 args[i] = y; /* arrays by ref */
230 290 else
231 291 args[i] = copycell(y);
232 - tempfree(y, "callargs");
292 + tempfree(y);
233 293 }
234 294 for (; i < ndef; i++) { /* add null args for ones not provided */
235 - args[i] = gettemp("nullargs");
295 + args[i] = gettemp();
236 296 *args[i] = newcopycell;
237 297 }
238 298 fp++; /* now ok to up frame */
239 299 if (fp >= frame + nframe) {
240 300 int dfp = fp - frame; /* old index */
241 301 frame = (struct Frame *)
242 302 realloc(frame, (nframe += 100) * sizeof (struct Frame));
243 303 if (frame == NULL)
244 - ERROR "out of space for stack frames in %s", s FATAL;
304 + FATAL("out of space for stack frames in %s", s);
245 305 fp = frame + dfp;
246 306 }
247 307 fp->fcncell = fcn;
248 308 fp->args = args;
249 309 fp->nargs = ndef; /* number defined with (excess are locals) */
250 - fp->retval = gettemp("retval");
310 + fp->retval = gettemp();
251 311
252 - dprintf(("start exec of %s, fp=%d\n", s, fp-frame));
312 + dprintf(("start exec of %s, fp=%d\n", s, (int)(fp-frame)));
253 313 /*LINTED align*/
254 314 y = execute((Node *)(fcn->sval)); /* execute body */
255 - dprintf(("finished exec of %s, fp=%d\n", s, fp-frame));
315 + dprintf(("finished exec of %s, fp=%d\n", s, (int)(fp-frame)));
256 316
257 317 for (i = 0; i < ndef; i++) {
258 318 Cell *t = fp->args[i];
259 319 if (isarr(t)) {
260 320 if (t->csub == CCOPY) {
261 321 if (i >= ncall) {
262 322 freesymtab(t);
263 323 t->csub = CTEMP;
324 + tempfree(t);
264 325 } else {
265 326 oargs[i]->tval = t->tval;
266 327 oargs[i]->tval &= ~(STR|NUM|DONTFREE);
267 328 oargs[i]->sval = t->sval;
268 - tempfree(t, "oargsarr");
329 + tempfree(t);
269 330 }
270 331 }
271 - } else {
332 + } else if (t != y) { /* kludge to prevent freeing twice */
333 + t->csub = CTEMP;
334 + tempfree(t);
335 + } else if (t == y && t->csub == CCOPY) {
272 336 t->csub = CTEMP;
273 - tempfree(t, "fp->args");
274 - if (t == y) freed = 1;
337 + tempfree(t);
338 + freed = 1;
275 339 }
276 340 }
277 - tempfree(fcn, "call.fcn");
341 + tempfree(fcn);
278 342 if (isexit(y) || isnext(y))
279 343 return (y);
280 - if (!freed)
281 - tempfree(y, "fcn ret"); /* this can free twice! */
344 + if (freed == 0) {
345 + tempfree(y); /* don't free twice! */
346 + }
282 347 z = fp->retval; /* return value */
283 348 dprintf(("%s returns %g |%s| %o\n",
284 349 s, getfval(z), getsval(z), z->tval));
285 350 fp--;
286 351 return (z);
287 352 }
288 353
289 354 static Cell *
290 355 copycell(Cell *x) /* make a copy of a cell in a temp */
291 356 {
292 357 Cell *y;
293 358
294 - y = gettemp("copycell");
359 + y = gettemp();
295 360 y->csub = CCOPY; /* prevents freeing until call is over */
296 - y->nval = x->nval;
297 - y->sval = x->sval ? tostring(x->sval) : NULL;
361 + y->nval = x->nval; /* BUG? */
362 + if (isstr(x))
363 + y->sval = tostring(x->sval);
298 364 y->fval = x->fval;
299 365 /* copy is not constant or field is DONTFREE right? */
300 366 y->tval = x->tval & ~(CON|FLD|REC|DONTFREE);
301 367 return (y);
302 368 }
303 369
304 -/*ARGSUSED*/
305 370 Cell *
306 -arg(Node **a, int nnn)
371 +arg(Node **a, int n) /* nth argument of a function */
307 372 {
308 - int n;
309 373
310 - n = (int)a[0]; /* argument number, counting from 0 */
374 + n = ptoi(a[0]); /* argument number, counting from 0 */
311 375 dprintf(("arg(%d), fp->nargs=%d\n", n, fp->nargs));
312 - if (n+1 > fp->nargs) {
313 - ERROR "argument #%d of function %s was not supplied",
314 - n+1, fp->fcncell->nval FATAL;
376 + if (n + 1 > fp->nargs) {
377 + FATAL("argument #%d of function %s was not supplied",
378 + n + 1, fp->fcncell->nval);
315 379 }
316 380 return (fp->args[n]);
317 381 }
318 382
319 383 Cell *
320 -jump(Node **a, int n)
384 +jump(Node **a, int n) /* break, continue, next, nextfile, return */
321 385 {
322 - register Cell *y;
386 + Cell *y;
323 387
324 388 switch (n) {
325 389 case EXIT:
326 390 if (a[0] != NULL) {
327 391 y = execute(a[0]);
328 392 errorflag = (int)getfval(y);
329 - tempfree(y, "");
393 + tempfree(y);
330 394 }
331 395 longjmp(env, 1);
332 396 /*NOTREACHED*/
333 397 case RETURN:
334 398 if (a[0] != NULL) {
335 399 y = execute(a[0]);
336 400 if ((y->tval & (STR|NUM)) == (STR|NUM)) {
337 401 (void) setsval(fp->retval, getsval(y));
338 402 fp->retval->fval = getfval(y);
339 403 fp->retval->tval |= NUM;
340 404 } else if (y->tval & STR)
341 405 (void) setsval(fp->retval, getsval(y));
342 406 else if (y->tval & NUM)
343 407 (void) setfval(fp->retval, getfval(y));
344 - tempfree(y, "");
408 + else /* can't happen */
409 + FATAL("bad type variable %d", y->tval);
410 + tempfree(y);
345 411 }
346 412 return (jret);
347 413 case NEXT:
348 414 return (jnext);
415 + case NEXTFILE:
416 + nextfile();
417 + return (jnextfile);
349 418 case BREAK:
350 419 return (jbreak);
351 420 case CONTINUE:
352 421 return (jcont);
353 422 default: /* can't happen */
354 - ERROR "illegal jump type %d", n FATAL;
423 + FATAL("illegal jump type %d", n);
355 424 }
356 425 /*NOTREACHED*/
357 426 return (NULL);
358 427 }
359 428
429 +/*
430 + * get next line from specific input
431 + *
432 + * a[0] is variable, a[1] is operator, a[2] is filename
433 + */
360 434 Cell *
361 -getaline(Node **a, int n)
435 +awkgetline(Node **a, int n)
362 436 {
363 - /* a[0] is variable, a[1] is operator, a[2] is filename */
364 - register Cell *r, *x;
365 - uchar *buf;
437 + Cell *r, *x;
438 + extern Cell **fldtab;
366 439 FILE *fp;
367 - size_t len;
440 + uchar *buf;
441 + size_t bufsize = record_size;
442 + int mode;
443 +
444 + if ((buf = (uchar *)malloc(bufsize)) == NULL)
445 + FATAL("out of memory in getline");
368 446
369 447 (void) fflush(stdout); /* in case someone is waiting for a prompt */
370 - r = gettemp("");
448 + r = gettemp();
371 449 if (a[1] != NULL) { /* getline < file */
372 450 x = execute(a[2]); /* filename */
373 - if ((int)a[1] == '|') /* input pipe */
374 - a[1] = (Node *)LE; /* arbitrary flag */
375 - fp = openfile((int)a[1], getsval(x));
376 - tempfree(x, "");
377 - buf = NULL;
451 + mode = ptoi(a[1]);
452 + if (mode == '|') /* input pipe */
453 + mode = LE; /* arbitrary flag */
454 + fp = openfile(mode, getsval(x));
455 + tempfree(x);
378 456 if (fp == NULL)
379 457 n = -1;
380 458 else
381 - n = readrec(&buf, &len, fp);
382 - if (n > 0) {
383 - if (a[0] != NULL) { /* getline var <file */
384 - (void) setsval(execute(a[0]), buf);
385 - } else { /* getline <file */
386 - if (!(recloc->tval & DONTFREE))
387 - xfree(recloc->sval);
388 - expand_buf(&record, &record_size, len);
389 - (void) memcpy(record, buf, len);
390 - record[len] = '\0';
391 - recloc->sval = record;
392 - recloc->tval = REC | STR | DONTFREE;
393 - donerec = 1; donefld = 0;
459 + n = readrec(&buf, &bufsize, fp);
460 + if (a[0] != NULL) { /* getline var <file */
461 + x = execute(a[0]);
462 + (void) setsval(x, buf);
463 + tempfree(x);
464 + } else { /* getline <file */
465 + (void) setsval(fldtab[0], buf);
466 + if (is_number(fldtab[0]->sval)) {
467 + fldtab[0]->fval = atof((char *)fldtab[0]->sval);
468 + fldtab[0]->tval |= NUM;
394 469 }
395 470 }
396 - if (buf != NULL)
397 - free(buf);
398 471 } else { /* bare getline; use current input */
399 472 if (a[0] == NULL) /* getline */
400 - n = getrec(&record, &record_size);
473 + n = getrec(&record, &record_size, 1);
401 474 else { /* getline var */
402 - init_buf(&buf, &len, LINE_INCR);
403 - n = getrec(&buf, &len);
404 - (void) setsval(execute(a[0]), buf);
405 - free(buf);
475 + n = getrec(&buf, &bufsize, 0);
476 + x = execute(a[0]);
477 + (void) setsval(x, buf);
478 + tempfree(x);
406 479 }
407 480 }
408 481 (void) setfval(r, (Awkfloat)n);
482 + free(buf);
409 483 return (r);
410 484 }
411 485
412 486 /*ARGSUSED*/
413 487 Cell *
414 -getnf(Node **a, int n)
488 +getnf(Node **a, int n) /* get NF */
415 489 {
416 490 if (donefld == 0)
417 491 fldbld();
418 492 return ((Cell *)a[0]);
419 493 }
420 494
421 495 /*ARGSUSED*/
422 496 Cell *
423 -array(Node **a, int n)
497 +array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
424 498 {
425 - register Cell *x, *y, *z;
426 - register uchar *s;
427 - register Node *np;
428 - uchar *buf;
429 - size_t bsize, tlen, len, slen;
499 + Cell *x, *y, *z;
500 + uchar *s;
501 + Node *np;
502 + uchar *buf;
503 + size_t bufsz = record_size;
504 + size_t nsub = strlen((char *)*SUBSEP);
505 +
506 + if ((buf = (uchar *)malloc(bufsz)) == NULL)
507 + FATAL("out of memory in array");
430 508
431 509 x = execute(a[0]); /* Cell* for symbol table */
432 - init_buf(&buf, &bsize, LINE_INCR);
433 510 buf[0] = '\0';
434 - tlen = 0;
435 - slen = strlen((char *)*SUBSEP);
436 511 for (np = a[1]; np; np = np->nnext) {
437 512 y = execute(np); /* subscript */
438 513 s = getsval(y);
439 - len = strlen((char *)s);
440 - expand_buf(&buf, &bsize, tlen + len + slen);
441 - (void) memcpy(&buf[tlen], s, len);
442 - tlen += len;
443 - if (np->nnext) {
444 - (void) memcpy(&buf[tlen], *SUBSEP, slen);
445 - tlen += slen;
446 - }
447 - buf[tlen] = '\0';
448 - tempfree(y, "");
514 + if (!adjbuf(&buf, &bufsz, strlen((char *)buf) +
515 + strlen((char *)s) + nsub + 1, record_size, 0, "array"))
516 + FATAL("out of memory for %s[%s...]", x->nval, buf);
517 + (void) strcat((char *)buf, (char *)s);
518 + if (np->nnext)
519 + (void) strcat((char *)buf, (char *)*SUBSEP);
520 + tempfree(y);
449 521 }
450 522 if (!isarr(x)) {
451 523 dprintf(("making %s into an array\n", x->nval));
452 524 if (freeable(x))
453 525 xfree(x->sval);
454 526 x->tval &= ~(STR|NUM|DONTFREE);
455 527 x->tval |= ARR;
456 - x->sval = (uchar *) makesymtab(NSYMTAB);
528 + x->sval = (uchar *)makesymtab(NSYMTAB);
457 529 }
458 530 /*LINTED align*/
459 531 z = setsymtab(buf, (uchar *)"", 0.0, STR|NUM, (Array *)x->sval);
460 532 z->ctype = OCELL;
461 533 z->csub = CVAR;
462 - tempfree(x, "");
534 + tempfree(x);
463 535 free(buf);
464 536 return (z);
465 537 }
466 538
467 539 /*ARGSUSED*/
468 540 Cell *
469 -delete(Node **a, int n)
541 +awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
470 542 {
471 543 Cell *x, *y;
472 544 Node *np;
473 - uchar *buf, *s;
474 - size_t bsize, tlen, slen, len;
545 + uchar *s;
546 + size_t nsub = strlen((char *)*SUBSEP);
475 547
476 548 x = execute(a[0]); /* Cell* for symbol table */
477 549 if (!isarr(x))
478 - return (true);
479 - init_buf(&buf, &bsize, LINE_INCR);
480 - buf[0] = '\0';
481 - tlen = 0;
482 - slen = strlen((char *)*SUBSEP);
483 - for (np = a[1]; np; np = np->nnext) {
484 - y = execute(np); /* subscript */
485 - s = getsval(y);
486 - len = strlen((char *)s);
487 - expand_buf(&buf, &bsize, tlen + len + slen);
488 - (void) memcpy(&buf[tlen], s, len);
489 - tlen += len;
490 - if (np->nnext) {
491 - (void) memcpy(&buf[tlen], *SUBSEP, slen);
492 - tlen += slen;
550 + return (True);
551 + if (a[1] == 0) { /* delete the elements, not the table */
552 + freesymtab(x);
553 + x->tval &= ~STR;
554 + x->tval |= ARR;
555 + x->sval = (uchar *)makesymtab(NSYMTAB);
556 + } else {
557 + size_t bufsz = record_size;
558 + uchar *buf;
559 + if ((buf = (uchar *)malloc(bufsz)) == NULL)
560 + FATAL("out of memory in delete");
561 + buf[0] = '\0';
562 + for (np = a[1]; np; np = np->nnext) {
563 + y = execute(np); /* subscript */
564 + s = getsval(y);
565 + if (!adjbuf(&buf, &bufsz, strlen((char *)buf) +
566 + strlen((char *)s) + nsub + 1, record_size, 0,
567 + "awkdelete")) {
568 + FATAL("out of memory deleting %s[%s...]",
569 + x->nval, buf);
570 + }
571 + (void) strcat((char *)buf, (char *)s);
572 + if (np->nnext)
573 + (void) strcat((char *)buf, (char *)*SUBSEP);
574 + tempfree(y);
493 575 }
494 - buf[tlen] = '\0';
495 - tempfree(y, "");
576 + freeelem(x, buf);
577 + free(buf);
496 578 }
497 - freeelem(x, buf);
498 - tempfree(x, "");
499 - free(buf);
500 - return (true);
579 + tempfree(x);
580 + return (True);
501 581 }
502 582
503 583 /*ARGSUSED*/
504 584 Cell *
505 -intest(Node **a, int n)
585 +intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
506 586 {
507 - register Cell *x, *ap, *k;
587 + Cell *x, *ap, *k;
508 588 Node *p;
509 589 uchar *buf;
510 590 uchar *s;
511 - size_t bsize, tlen, slen, len;
591 + size_t bufsz = record_size;
592 + size_t nsub = strlen((char *)*SUBSEP);
512 593
513 594 ap = execute(a[1]); /* array name */
514 - if (!isarr(ap))
515 - ERROR "%s is not an array", ap->nval FATAL;
516 - init_buf(&buf, &bsize, LINE_INCR);
595 + if (!isarr(ap)) {
596 + dprintf(("making %s into an array\n", ap->nval));
597 + if (freeable(ap))
598 + xfree(ap->sval);
599 + ap->tval &= ~(STR|NUM|DONTFREE);
600 + ap->tval |= ARR;
601 + ap->sval = (uchar *)makesymtab(NSYMTAB);
602 + }
603 + if ((buf = (uchar *)malloc(bufsz)) == NULL) {
604 + FATAL("out of memory in intest");
605 + }
517 606 buf[0] = 0;
518 - tlen = 0;
519 - slen = strlen((char *)*SUBSEP);
520 607 for (p = a[0]; p; p = p->nnext) {
521 608 x = execute(p); /* expr */
522 609 s = getsval(x);
523 - len = strlen((char *)s);
524 - expand_buf(&buf, &bsize, tlen + len + slen);
525 - (void) memcpy(&buf[tlen], s, len);
526 - tlen += len;
527 - tempfree(x, "");
528 - if (p->nnext) {
529 - (void) memcpy(&buf[tlen], *SUBSEP, slen);
530 - tlen += slen;
531 - }
532 - buf[tlen] = '\0';
610 + if (!adjbuf(&buf, &bufsz, strlen((char *)buf) +
611 + strlen((char *)s) + nsub + 1, record_size, 0, "intest"))
612 + FATAL("out of memory deleting %s[%s...]", x->nval, buf);
613 + (void) strcat((char *)buf, (char *)s);
614 + tempfree(x);
615 + if (p->nnext)
616 + (void) strcat((char *)buf, (char *)*SUBSEP);
533 617 }
534 618 /*LINTED align*/
535 619 k = lookup(buf, (Array *)ap->sval);
536 - tempfree(ap, "");
620 + tempfree(ap);
537 621 free(buf);
538 622 if (k == NULL)
539 - return (false);
623 + return (False);
540 624 else
541 - return (true);
625 + return (True);
542 626 }
543 627
544 -
545 628 Cell *
546 -matchop(Node **a, int n)
629 +matchop(Node **a, int n) /* ~ and match() */
547 630 {
548 - register Cell *x, *y;
549 - register uchar *s, *t;
550 - register int i;
631 + Cell *x, *y;
632 + uchar *s, *t;
633 + int i;
551 634 fa *pfa;
552 - int (*mf)() = match, mode = 0;
635 + int (*mf)(fa *, const uchar *) = match, mode = 0;
553 636
554 637 if (n == MATCHFCN) {
555 638 mf = pmatch;
556 639 mode = 1;
557 640 }
558 - x = execute(a[1]);
641 + x = execute(a[1]); /* a[1] = target text */
559 642 s = getsval(x);
560 - if (a[0] == 0)
561 - i = (*mf)(a[2], s);
643 + if (a[0] == 0) /* a[1] == 0: already-compiled reg expr */
644 + i = (*mf)((fa *)a[2], s);
562 645 else {
563 - y = execute(a[2]);
646 + y = execute(a[2]); /* a[2] = regular expr */
564 647 t = getsval(y);
565 648 pfa = makedfa(t, mode);
566 649 i = (*mf)(pfa, s);
567 - tempfree(y, "");
650 + tempfree(y);
568 651 }
569 - tempfree(x, "");
652 + tempfree(x);
570 653 if (n == MATCHFCN) {
571 654 int start = patbeg - s + 1;
572 655 if (patlen < 0)
573 656 start = 0;
574 657 (void) setfval(rstartloc, (Awkfloat)start);
575 658 (void) setfval(rlengthloc, (Awkfloat)patlen);
576 - x = gettemp("");
659 + x = gettemp();
577 660 x->tval = NUM;
578 661 x->fval = start;
579 662 return (x);
580 - } else if (n == MATCH && i == 1 || n == NOTMATCH && i == 0)
581 - return (true);
663 + } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
664 + return (True);
582 665 else
583 - return (false);
666 + return (False);
584 667 }
585 668
586 -
587 669 Cell *
588 -boolop(Node **a, int n)
670 +boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */
589 671 {
590 - register Cell *x, *y;
591 - register int i;
672 + Cell *x, *y;
673 + int i;
592 674
593 675 x = execute(a[0]);
594 676 i = istrue(x);
595 - tempfree(x, "");
677 + tempfree(x);
596 678 switch (n) {
597 679 case BOR:
598 680 if (i)
599 - return (true);
681 + return (True);
600 682 y = execute(a[1]);
601 683 i = istrue(y);
602 - tempfree(y, "");
603 - return (i ? true : false);
684 + tempfree(y);
685 + return (i ? True : False);
604 686 case AND:
605 687 if (!i)
606 - return (false);
688 + return (False);
607 689 y = execute(a[1]);
608 690 i = istrue(y);
609 - tempfree(y, "");
610 - return (i ? true : false);
691 + tempfree(y);
692 + return (i ? True : False);
611 693 case NOT:
612 - return (i ? false : true);
694 + return (i ? False : True);
613 695 default: /* can't happen */
614 - ERROR "unknown boolean operator %d", n FATAL;
696 + FATAL("unknown boolean operator %d", n);
615 697 }
616 698 /*NOTREACHED*/
617 699 return (NULL);
618 700 }
619 701
620 702 Cell *
621 -relop(Node **a, int n)
703 +relop(Node **a, int n) /* a[0 < a[1], etc. */
622 704 {
623 - register int i;
624 - register Cell *x, *y;
705 + int i;
706 + Cell *x, *y;
625 707 Awkfloat j;
626 708
627 709 x = execute(a[0]);
628 710 y = execute(a[1]);
629 - if (x->tval&NUM && y->tval&NUM) {
711 + if (x->tval & NUM && y->tval & NUM) {
630 712 j = x->fval - y->fval;
631 713 i = j < 0 ? -1: (j > 0 ? 1: 0);
632 714 } else {
633 715 i = strcmp((char *)getsval(x), (char *)getsval(y));
634 716 }
635 - tempfree(x, "");
636 - tempfree(y, "");
717 + tempfree(x);
718 + tempfree(y);
637 719 switch (n) {
638 - case LT: return (i < 0 ? true : false);
639 - case LE: return (i <= 0 ? true : false);
640 - case NE: return (i != 0 ? true : false);
641 - case EQ: return (i == 0 ? true : false);
642 - case GE: return (i >= 0 ? true : false);
643 - case GT: return (i > 0 ? true : false);
720 + case LT: return (i < 0 ? True : False);
721 + case LE: return (i <= 0 ? True : False);
722 + case NE: return (i != 0 ? True : False);
723 + case EQ: return (i == 0 ? True : False);
724 + case GE: return (i >= 0 ? True : False);
725 + case GT: return (i > 0 ? True : False);
644 726 default: /* can't happen */
645 - ERROR "unknown relational operator %d", n FATAL;
727 + FATAL("unknown relational operator %d", n);
646 728 }
647 729 /*NOTREACHED*/
648 - return (false);
730 + return (False);
649 731 }
650 732
651 733 static void
652 -tfree(Cell *a, char *s)
734 +tfree(Cell *a) /* free a tempcell */
653 735 {
654 - if (dbg > 1) {
655 - (void) printf("## tfree %.8s %06lo %s\n",
656 - s, (ulong_t)a, a->sval ? a->sval : (uchar *)"");
657 - }
658 - if (freeable(a))
736 + if (freeable(a)) {
737 + dprintf(("freeing %s %s %o\n", (char *)a->nval,
738 + (char *)a->sval, a->tval));
659 739 xfree(a->sval);
740 + }
660 741 if (a == tmps)
661 - ERROR "tempcell list is curdled" FATAL;
742 + FATAL("tempcell list is curdled");
662 743 a->cnext = tmps;
663 744 tmps = a;
664 745 }
665 746
666 747 static Cell *
667 -gettemp(char *s)
748 +gettemp(void) /* get a tempcell */
668 749 {
669 750 int i;
670 - register Cell *x;
751 + Cell *x;
671 752
672 753 if (!tmps) {
673 754 tmps = (Cell *)calloc(100, sizeof (Cell));
674 755 if (!tmps)
675 - ERROR "no space for temporaries" FATAL;
756 + FATAL("out of space for temporaries");
676 757 for (i = 1; i < 100; i++)
677 - tmps[i-1].cnext = &tmps[i];
678 - tmps[i-1].cnext = 0;
758 + tmps[i - 1].cnext = &tmps[i];
759 + tmps[i - 1].cnext = 0;
679 760 }
680 761 x = tmps;
681 762 tmps = x->cnext;
682 763 *x = tempcell;
683 - if (dbg > 1)
684 - (void) printf("## gtemp %.8s %06lo\n", s, (ulong_t)x);
685 764 return (x);
686 765 }
687 766
688 767 /*ARGSUSED*/
689 768 Cell *
690 -indirect(Node **a, int n)
769 +indirect(Node **a, int n) /* $( a[0] ) */
691 770 {
692 - register Cell *x;
693 - register int m;
694 - register uchar *s;
771 + Awkfloat val;
772 + Cell *x;
773 + int m;
774 + uchar *s;
695 775
696 776 x = execute(a[0]);
697 - m = (int)getfval(x);
777 + /* freebsd: defend against super large field numbers */
778 + val = getfval(x);
779 + if ((Awkfloat)INT_MAX < val)
780 + FATAL("trying to access out of range field %s", x->nval);
781 + m = (int)val;
698 782 if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */
699 - ERROR "illegal field $(%s)", s FATAL;
700 - tempfree(x, "");
783 + FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
784 + /* BUG: can x->nval ever be null??? */
785 + tempfree(x);
701 786 x = fieldadr(m);
702 - x->ctype = OCELL;
787 + x->ctype = OCELL; /* BUG? why are these needed? */
703 788 x->csub = CFLD;
704 789 return (x);
705 790 }
706 791
707 792 /*ARGSUSED*/
708 793 Cell *
709 -substr(Node **a, int nnn)
794 +substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */
710 795 {
711 - register int k, m, n;
712 - register uchar *s;
796 + int k, m, n;
797 + uchar *s;
713 798 int temp;
714 - register Cell *x, *y, *z;
799 + Cell *x, *y, *z = 0;
715 800
716 801 x = execute(a[0]);
717 802 y = execute(a[1]);
718 803 if (a[2] != 0)
719 804 z = execute(a[2]);
720 805 s = getsval(x);
721 806 k = strlen((char *)s) + 1;
722 807 if (k <= 1) {
723 - tempfree(x, "");
724 - tempfree(y, "");
725 - if (a[2] != 0)
726 - tempfree(z, "");
727 - x = gettemp("");
808 + tempfree(x);
809 + tempfree(y);
810 + if (a[2] != 0) {
811 + tempfree(z);
812 + }
813 + x = gettemp();
728 814 (void) setsval(x, (uchar *)"");
729 815 return (x);
730 816 }
731 817 m = (int)getfval(y);
732 818 if (m <= 0)
733 819 m = 1;
734 820 else if (m > k)
735 821 m = k;
736 - tempfree(y, "");
822 + tempfree(y);
737 823 if (a[2] != 0) {
738 824 n = (int)getfval(z);
739 - tempfree(z, "");
825 + tempfree(z);
740 826 } else
741 827 n = k - 1;
742 828 if (n < 0)
743 829 n = 0;
744 830 else if (n > k - m)
745 831 n = k - m;
746 832 dprintf(("substr: m=%d, n=%d, s=%s\n", m, n, s));
747 - y = gettemp("");
833 + y = gettemp();
748 834 temp = s[n + m - 1]; /* with thanks to John Linderman */
749 835 s[n + m - 1] = '\0';
750 836 (void) setsval(y, s + m - 1);
751 837 s[n + m - 1] = temp;
752 - tempfree(x, "");
838 + tempfree(x);
753 839 return (y);
754 840 }
755 841
756 842 /*ARGSUSED*/
757 843 Cell *
758 -sindex(Node **a, int nnn)
844 +sindex(Node **a, int nnn) /* index(a[0], a[1]) */
759 845 {
760 - register Cell *x, *y, *z;
761 - register uchar *s1, *s2, *p1, *p2, *q;
846 + Cell *x, *y, *z;
847 + uchar *s1, *s2, *p1, *p2, *q;
762 848 Awkfloat v = 0.0;
763 849
764 850 x = execute(a[0]);
765 851 s1 = getsval(x);
766 852 y = execute(a[1]);
767 853 s2 = getsval(y);
768 854
769 - z = gettemp("");
855 + z = gettemp();
770 856 for (p1 = s1; *p1 != '\0'; p1++) {
771 857 for (q = p1, p2 = s2; *p2 != '\0' && *q == *p2; q++, p2++)
772 858 ;
773 859 if (*p2 == '\0') {
774 - v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */
860 + v = (Awkfloat)(p1 - s1 + 1); /* origin 1 */
775 861 break;
776 862 }
777 863 }
778 - tempfree(x, "");
779 - tempfree(y, "");
864 + tempfree(x);
865 + tempfree(y);
780 866 (void) setfval(z, v);
781 867 return (z);
782 868 }
783 869
784 -void
785 -format(uchar **bufp, uchar *s, Node *a)
870 +#define MAXNUMSIZE 50
871 +
872 +/*
873 + * printf-like conversions
874 + */
875 +int
876 +format(uchar **bufp, size_t *pbufsize, const uchar *s, Node *a)
786 877 {
787 878 uchar *fmt;
788 - register uchar *os;
789 - register Cell *x;
790 - int flag = 0, len;
791 - uchar_t *buf;
792 - size_t bufsize, fmtsize, cnt, tcnt, ret;
879 + uchar *p, *t;
880 + const uchar *os;
881 + Cell *x;
882 + int flag = 0, n;
883 + int fmtwd; /* format width */
884 + size_t fmtsz = record_size;
885 + uchar_t *buf = *bufp;
886 + size_t bufsize = *pbufsize;
793 887
794 - init_buf(&buf, &bufsize, LINE_INCR);
795 - init_buf(&fmt, &fmtsize, LINE_INCR);
796 888 os = s;
797 - cnt = 0;
889 + p = buf;
890 + if ((fmt = (uchar *)malloc(fmtsz)) == NULL)
891 + FATAL("out of memory in format()");
798 892 while (*s) {
893 + (void) adjbuf(&buf, &bufsize, MAXNUMSIZE + 1 + p - buf,
894 + record_size, &p, "format1");
799 895 if (*s != '%') {
800 - expand_buf(&buf, &bufsize, cnt);
801 - buf[cnt++] = *s++;
896 + *p++ = *s++;
802 897 continue;
803 898 }
804 899 if (*(s+1) == '%') {
805 - expand_buf(&buf, &bufsize, cnt);
806 - buf[cnt++] = '%';
900 + *p++ = '%';
807 901 s += 2;
808 902 continue;
809 903 }
810 - for (tcnt = 0; ; s++) {
811 - expand_buf(&fmt, &fmtsize, tcnt);
812 - fmt[tcnt++] = *s;
813 - if (*s == '\0')
814 - break;
815 - if (isalpha(*s) && *s != 'l' && *s != 'h' && *s != 'L')
816 - break; /* the ansi panoply */
904 + /*
905 + * have to be real careful in case this is a huge number,
906 + * eg, %100000d
907 + */
908 + fmtwd = atoi((char *)s + 1);
909 + if (fmtwd < 0)
910 + fmtwd = -fmtwd;
911 + (void) adjbuf(&buf, &bufsize, fmtwd + 1 + p - buf,
912 + record_size, &p, "format2");
913 + for (t = fmt; (*t++ = *s) != '\0'; s++) {
914 + if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE + 1 + t - fmt,
915 + record_size, &t, "format3"))
916 + FATAL(
917 + "format item %.30s... ran format() out of memory", os);
918 + if (isalpha((uchar)*s) && *s != 'l' && *s != 'h' &&
919 + *s != 'L')
920 + break; /* the ansi panoply */
817 921 if (*s == '*') {
818 - if (a == NULL) {
819 - ERROR
820 - "not enough args in printf(%s) or sprintf(%s)", os, os FATAL;
821 - }
822 922 x = execute(a);
823 923 a = a->nnext;
824 - tcnt--;
825 - expand_buf(&fmt, &fmtsize, tcnt + 12);
826 - ret = sprintf((char *)&fmt[tcnt], "%d",
827 - (int)getfval(x));
828 - tcnt += ret;
829 - tempfree(x, "");
924 + (void) sprintf((char *)t - 1, "%d",
925 + fmtwd = (int)getfval(x));
926 + if (fmtwd < 0)
927 + fmtwd = -fmtwd;
928 + (void) adjbuf(&buf, &bufsize, fmtwd + 1 + p -
929 + buf, record_size, &p, "format");
930 + t = fmt + strlen((char *)fmt);
931 + tempfree(x);
830 932 }
831 933 }
832 - fmt[tcnt] = '\0';
934 + *t = '\0';
935 + if (fmtwd < 0)
936 + fmtwd = -fmtwd;
937 + (void) adjbuf(&buf, &bufsize, fmtwd + 1 + p - buf,
938 + record_size, &p, "format4");
833 939
834 940 switch (*s) {
835 941 case 'f': case 'e': case 'g': case 'E': case 'G':
836 - flag = 1;
942 + flag = 'f';
837 943 break;
838 944 case 'd': case 'i':
839 - flag = 2;
945 + flag = 'd';
840 946 if (*(s-1) == 'l')
841 947 break;
842 - fmt[tcnt - 1] = 'l';
843 - expand_buf(&fmt, &fmtsize, tcnt);
844 - fmt[tcnt++] = 'd';
845 - fmt[tcnt] = '\0';
948 + *(t-1) = 'l';
949 + *t = 'd';
950 + *++t = '\0';
846 951 break;
847 952 case 'o': case 'x': case 'X': case 'u':
848 - flag = *(s-1) == 'l' ? 2 : 3;
953 + flag = *(s-1) == 'l' ? 'd' : 'u';
849 954 break;
850 955 case 's':
851 - flag = 4;
956 + flag = 's';
852 957 break;
853 958 case 'c':
854 - flag = 5;
959 + flag = 'c';
855 960 break;
856 961 default:
857 - flag = 0;
962 + WARNING("weird printf conversion %s", fmt);
963 + flag = '?';
858 964 break;
859 965 }
860 - if (flag == 0) {
861 - len = strlen((char *)fmt);
862 - expand_buf(&buf, &bufsize, cnt + len);
863 - (void) memcpy(&buf[cnt], fmt, len);
864 - cnt += len;
865 - buf[cnt] = '\0';
866 - continue;
867 - }
868 966 if (a == NULL) {
869 - ERROR
870 - "not enough args in printf(%s) or sprintf(%s)", os, os FATAL;
967 + FATAL(
968 + "not enough args in printf(%s)", os);
871 969 }
872 970 x = execute(a);
873 971 a = a->nnext;
874 - for (;;) {
875 - /* make sure we have at least 1 byte space */
876 - expand_buf(&buf, &bufsize, cnt + 1);
877 - len = bufsize - cnt;
878 - switch (flag) {
879 - case 1:
880 - /*LINTED*/
881 - ret = snprintf((char *)&buf[cnt], len,
882 - (char *)fmt, getfval(x));
883 - break;
884 - case 2:
885 - /*LINTED*/
886 - ret = snprintf((char *)&buf[cnt], len,
887 - (char *)fmt, (long)getfval(x));
888 - break;
889 - case 3:
890 - /*LINTED*/
891 - ret = snprintf((char *)&buf[cnt], len,
892 - (char *)fmt, (int)getfval(x));
893 - break;
894 - case 4:
895 - /*LINTED*/
896 - ret = snprintf((char *)&buf[cnt], len,
897 - (char *)fmt, getsval(x));
898 - break;
899 - case 5:
900 - if (isnum(x)) {
901 - /*LINTED*/
902 - ret = snprintf((char *)&buf[cnt], len,
903 - (char *)fmt, (int)getfval(x));
904 - } else {
905 - /*LINTED*/
906 - ret = snprintf((char *)&buf[cnt], len,
907 - (char *)fmt, getsval(x)[0]);
972 + n = MAXNUMSIZE;
973 + if (fmtwd > n)
974 + n = fmtwd;
975 + (void) adjbuf(&buf, &bufsize, 1 + n + p - buf, record_size,
976 + &p, "format5");
977 +
978 + switch (flag) {
979 + case '?':
980 + /* unknown, so dump it too */
981 + /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */
982 + (void) sprintf((char *)p, "%s", (char *)fmt);
983 + t = getsval(x);
984 + n = strlen((char *)t);
985 + if (fmtwd > n)
986 + n = fmtwd;
987 + (void) adjbuf(&buf, &bufsize, 1 + strlen((char *)p) +
988 + n + p - buf, record_size, &p, "format6");
989 + p += strlen((char *)p);
990 + /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */
991 + (void) sprintf((char *)p, "%s", t);
992 + break;
993 + case 'f':
994 + /* LINTED E_SEC_PRINTF_VAR_FMT */
995 + (void) sprintf((char *)p, (char *)fmt, getfval(x));
996 + break;
997 + case 'd':
998 + /* LINTED E_SEC_PRINTF_VAR_FMT */
999 + (void) sprintf((char *)p, (char *)fmt,
1000 + (long) getfval(x));
1001 + break;
1002 + case 'u':
1003 + /* LINTED E_SEC_PRINTF_VAR_FMT */
1004 + (void) sprintf((char *)p, (char *)fmt,
1005 + (int) getfval(x));
1006 + break;
1007 + case 's':
1008 + t = getsval(x);
1009 + n = strlen((char *)t);
1010 + if (fmtwd > n)
1011 + n = fmtwd;
1012 + if (!adjbuf(&buf, &bufsize, 1+n+p-buf, record_size,
1013 + &p, "format7"))
1014 + FATAL(
1015 + "huge string/format (%d chars) in printf %.30s... "
1016 + "ran format() out of memory", n, t);
1017 + /* LINTED E_SEC_PRINTF_VAR_FMT */
1018 + (void) sprintf((char *)p, (char *)fmt, t);
1019 + break;
1020 + case 'c':
1021 + if (isnum(x)) {
1022 + if (getfval(x))
1023 + /* LINTED E_SEC_PRINTF_VAR_FMT */
1024 + (void) sprintf((char *)p, (char *)fmt,
1025 + (int) getfval(x));
1026 + else {
1027 + *p++ = '\0'; /* explicit null byte */
1028 + /* next output will start here */
1029 + *p = '\0';
908 1030 }
909 - break;
910 - default:
911 - ret = 0;
1031 + } else {
1032 + /* LINTED E_SEC_PRINTF_VAR_FMT */
1033 + (void) sprintf((char *)p, (char *)fmt,
1034 + getsval(x)[0]);
912 1035 }
913 - if (ret < len)
914 - break;
915 - expand_buf(&buf, &bufsize, cnt + ret);
1036 + break;
1037 + default:
1038 + FATAL("can't happen: bad conversion %c in format()",
1039 + flag);
916 1040 }
917 - tempfree(x, "");
918 - cnt += ret;
1041 + tempfree(x);
1042 + p += strlen((char *)p);
919 1043 s++;
920 1044 }
921 - buf[cnt] = '\0';
1045 + *p = '\0';
1046 + free(fmt);
922 1047 for (; a; a = a->nnext) /* evaluate any remaining args */
923 1048 (void) execute(a);
924 - *bufp = tostring(buf);
925 - free(buf);
926 - free(fmt);
1049 + *bufp = buf;
1050 + *pbufsize = bufsize;
1051 + return (p - buf);
927 1052 }
928 1053
929 1054 /*ARGSUSED*/
930 1055 Cell *
931 -a_sprintf(Node **a, int n)
1056 +awksprintf(Node **a, int n) /* sprintf(a[0]) */
932 1057 {
933 - register Cell *x;
934 - register Node *y;
1058 + Cell *x;
1059 + Node *y;
935 1060 uchar *buf;
1061 + size_t bufsz = 3 * record_size;
936 1062
1063 + if ((buf = (uchar *)malloc(bufsz)) == NULL)
1064 + FATAL("out of memory in awksprintf");
937 1065 y = a[0]->nnext;
938 1066 x = execute(a[0]);
939 - format(&buf, getsval(x), y);
940 - tempfree(x, "");
941 - x = gettemp("");
1067 + if (format(&buf, &bufsz, getsval(x), y) == -1)
1068 + FATAL("sprintf string %.30s... too long. can't happen.", buf);
1069 + tempfree(x);
1070 + x = gettemp();
942 1071 x->sval = buf;
943 1072 x->tval = STR;
944 1073 return (x);
945 1074 }
946 1075
947 1076 /*ARGSUSED*/
948 1077 Cell *
949 -aprintf(Node **a, int n)
950 -{
1078 +awkprintf(Node **a, int n) /* printf */
1079 +{ /* a[0] is list of args, starting with format string */
1080 + /* a[1] is redirection operator, a[2] is redirection file */
951 1081 FILE *fp;
952 - register Cell *x;
953 - register Node *y;
1082 + Cell *x;
1083 + Node *y;
954 1084 uchar *buf;
1085 + int len;
1086 + size_t bufsz = 3 * record_size;
955 1087
1088 + if ((buf = (uchar *)malloc(bufsz)) == NULL)
1089 + FATAL("out of memory in awkprintf");
956 1090 y = a[0]->nnext;
957 1091 x = execute(a[0]);
958 - format(&buf, getsval(x), y);
959 - tempfree(x, "");
960 - if (a[1] == NULL)
961 - (void) fputs((char *)buf, stdout);
962 - else {
963 - fp = redirect((int)a[1], a[2]);
964 - (void) fputs((char *)buf, fp);
1092 + if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
1093 + FATAL("printf string %.30s... too long. can't happen.", buf);
1094 + tempfree(x);
1095 + if (a[1] == NULL) {
1096 + /* fputs(buf, stdout); */
1097 + (void) fwrite((char *)buf, len, 1, stdout);
1098 + if (ferror(stdout))
1099 + FATAL("write error on stdout");
1100 + } else {
1101 + fp = redirect(ptoi(a[1]), a[2]);
1102 + /* fputs(buf, fp); */
1103 + (void) fwrite(buf, len, 1, fp);
965 1104 (void) fflush(fp);
1105 + if (ferror(fp))
1106 + FATAL("write error on %s", filename(fp));
966 1107 }
967 1108 free(buf);
968 - return (true);
1109 + return (True);
969 1110 }
970 1111
971 1112 Cell *
972 -arith(Node **a, int n)
1113 +arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */
973 1114 {
974 - Awkfloat i, j;
1115 + Awkfloat i, j = 0;
975 1116 double v;
976 - register Cell *x, *y, *z;
1117 + Cell *x, *y, *z;
977 1118
978 1119 x = execute(a[0]);
979 1120 i = getfval(x);
980 - tempfree(x, "");
1121 + tempfree(x);
981 1122 if (n != UMINUS) {
982 1123 y = execute(a[1]);
983 1124 j = getfval(y);
984 - tempfree(y, "");
1125 + tempfree(y);
985 1126 }
986 - z = gettemp("");
1127 + z = gettemp();
987 1128 switch (n) {
988 1129 case ADD:
989 1130 i += j;
990 1131 break;
991 1132 case MINUS:
992 1133 i -= j;
993 1134 break;
994 1135 case MULT:
995 1136 i *= j;
996 1137 break;
997 1138 case DIVIDE:
998 1139 if (j == 0)
999 - ERROR "division by zero" FATAL;
1140 + FATAL("division by zero");
1000 1141 i /= j;
1001 1142 break;
1002 1143 case MOD:
1003 1144 if (j == 0)
1004 - ERROR "division by zero in mod" FATAL;
1145 + FATAL("division by zero in mod");
1005 1146 (void) modf(i/j, &v);
1006 1147 i = i - j * v;
1007 1148 break;
1008 1149 case UMINUS:
1009 1150 i = -i;
1010 1151 break;
1011 1152 case POWER:
1012 1153 if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
1013 1154 i = ipow(i, (int)j);
1014 1155 else
1015 1156 i = errcheck(pow(i, j), "pow");
1016 1157 break;
1017 1158 default: /* can't happen */
1018 - ERROR "illegal arithmetic operator %d", n FATAL;
1159 + FATAL("illegal arithmetic operator %d", n);
1019 1160 }
1020 1161 (void) setfval(z, i);
1021 1162 return (z);
1022 1163 }
1023 1164
1024 1165 static double
1025 -ipow(double x, int n)
1166 +ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */
1026 1167 {
1027 1168 double v;
1028 1169
1029 1170 if (n <= 0)
1030 1171 return (1.0);
1031 - v = ipow(x, n/2);
1172 + v = ipow(x, n / 2);
1032 1173 if (n % 2 == 0)
1033 1174 return (v * v);
1034 1175 else
1035 1176 return (x * v * v);
1036 1177 }
1037 1178
1038 1179 Cell *
1039 -incrdecr(Node **a, int n)
1180 +incrdecr(Node **a, int n) /* a[0]++, etc. */
1040 1181 {
1041 - register Cell *x, *z;
1042 - register int k;
1182 + Cell *x, *z;
1183 + int k;
1043 1184 Awkfloat xf;
1044 1185
1045 1186 x = execute(a[0]);
1046 1187 xf = getfval(x);
1047 1188 k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
1048 1189 if (n == PREINCR || n == PREDECR) {
1049 1190 (void) setfval(x, xf + k);
1050 1191 return (x);
1051 1192 }
1052 - z = gettemp("");
1193 + z = gettemp();
1053 1194 (void) setfval(z, xf);
1054 1195 (void) setfval(x, xf + k);
1055 - tempfree(x, "");
1196 + tempfree(x);
1056 1197 return (z);
1057 1198 }
1058 1199
1059 1200 Cell *
1060 -assign(Node **a, int n)
1061 -{
1062 - register Cell *x, *y;
1201 +assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */
1202 +{ /* this is subtle; don't muck with it. */
1203 + Cell *x, *y;
1063 1204 Awkfloat xf, yf;
1064 1205 double v;
1065 1206
1066 1207 y = execute(a[1]);
1067 - x = execute(a[0]); /* order reversed from before... */
1208 + x = execute(a[0]);
1068 1209 if (n == ASSIGN) { /* ordinary assignment */
1069 - if ((y->tval & (STR|NUM)) == (STR|NUM)) {
1210 + /* self-assignment: */
1211 + /* LINTED E_NOP_IF_STMT */
1212 + if (x == y && !(x->tval & (FLD|REC)))
1213 + /* leave alone unless it's a field */
1214 + ;
1215 + else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
1070 1216 (void) setsval(x, getsval(y));
1071 1217 x->fval = getfval(y);
1072 1218 x->tval |= NUM;
1073 - } else if (y->tval & STR)
1219 + } else if (isstr(y))
1074 1220 (void) setsval(x, getsval(y));
1075 - else if (y->tval & NUM)
1221 + else if (isnum(y))
1076 1222 (void) setfval(x, getfval(y));
1077 1223 else
1078 1224 funnyvar(y, "read value of");
1079 - tempfree(y, "");
1225 + tempfree(y);
1080 1226 return (x);
1081 1227 }
1082 1228 xf = getfval(x);
1083 1229 yf = getfval(y);
1084 1230 switch (n) {
1085 1231 case ADDEQ:
1086 1232 xf += yf;
1087 1233 break;
1088 1234 case SUBEQ:
1089 1235 xf -= yf;
1090 1236 break;
1091 1237 case MULTEQ:
1092 1238 xf *= yf;
1093 1239 break;
1094 1240 case DIVEQ:
1095 1241 if (yf == 0)
1096 - ERROR "division by zero in /=" FATAL;
1242 + FATAL("division by zero in /=");
1097 1243 xf /= yf;
1098 1244 break;
1099 1245 case MODEQ:
1100 1246 if (yf == 0)
1101 - ERROR "division by zero in %%=" FATAL;
1247 + FATAL("division by zero in %%=");
1102 1248 (void) modf(xf/yf, &v);
1103 1249 xf = xf - yf * v;
1104 1250 break;
1105 1251 case POWEQ:
1106 1252 if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */
1107 1253 xf = ipow(xf, (int)yf);
1108 1254 else
1109 1255 xf = errcheck(pow(xf, yf), "pow");
1110 1256 break;
1111 1257 default:
1112 - ERROR "illegal assignment operator %d", n FATAL;
1258 + FATAL("illegal assignment operator %d", n);
1113 1259 break;
1114 1260 }
1115 - tempfree(y, "");
1261 + tempfree(y);
1116 1262 (void) setfval(x, xf);
1117 1263 return (x);
1118 1264 }
1119 1265
1120 1266 /*ARGSUSED*/
1121 1267 Cell *
1122 -cat(Node **a, int q)
1268 +cat(Node **a, int q) /* a[0] cat a[1] */
1123 1269 {
1124 - register Cell *x, *y, *z;
1125 - register int n1, n2;
1126 - register uchar *s;
1270 + Cell *x, *y, *z;
1271 + int n1, n2;
1272 + uchar *s;
1127 1273
1128 1274 x = execute(a[0]);
1129 1275 y = execute(a[1]);
1130 1276 (void) getsval(x);
1131 1277 (void) getsval(y);
1132 1278 n1 = strlen((char *)x->sval);
1133 1279 n2 = strlen((char *)y->sval);
1134 1280 s = (uchar *)malloc(n1 + n2 + 1);
1135 1281 if (s == NULL) {
1136 - ERROR "out of space concatenating %.15s and %.15s",
1137 - x->sval, y->sval FATAL;
1282 + FATAL("out of space concatenating %.15s... and %.15s...",
1283 + x->sval, y->sval);
1138 1284 }
1139 1285 (void) strcpy((char *)s, (char *)x->sval);
1140 1286 (void) strcpy((char *)s + n1, (char *)y->sval);
1141 - tempfree(y, "");
1142 - z = gettemp("");
1287 + tempfree(x);
1288 + tempfree(y);
1289 + z = gettemp();
1143 1290 z->sval = s;
1144 1291 z->tval = STR;
1145 - tempfree(x, "");
1146 1292 return (z);
1147 1293 }
1148 1294
1149 1295 /*ARGSUSED*/
1150 1296 Cell *
1151 -pastat(Node **a, int n)
1297 +pastat(Node **a, int n) /* a[0] { a[1] } */
1152 1298 {
1153 - register Cell *x;
1299 + Cell *x;
1154 1300
1155 1301 if (a[0] == 0)
1156 1302 x = execute(a[1]);
1157 1303 else {
1158 1304 x = execute(a[0]);
1159 1305 if (istrue(x)) {
1160 - tempfree(x, "");
1306 + tempfree(x);
1161 1307 x = execute(a[1]);
1162 1308 }
1163 1309 }
1164 1310 return (x);
1165 1311 }
1166 1312
1167 1313 /*ARGSUSED*/
1168 1314 Cell *
1169 -dopa2(Node **a, int n)
1315 +dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */
1170 1316 {
1171 - Cell *x;
1172 - int pair;
1173 - static int *pairstack = NULL;
1174 -
1175 - if (!pairstack) {
1176 - /* first time */
1177 - dprintf(("paircnt: %d\n", paircnt));
1178 - pairstack = (int *)malloc(sizeof (int) * paircnt);
1179 - if (!pairstack)
1180 - ERROR "out of space in dopa2" FATAL;
1181 - (void) memset(pairstack, 0, sizeof (int) * paircnt);
1182 - }
1317 + Cell *x;
1318 + int pair;
1183 1319
1184 - pair = (int)a[3];
1320 + pair = ptoi(a[3]);
1185 1321 if (pairstack[pair] == 0) {
1186 1322 x = execute(a[0]);
1187 1323 if (istrue(x))
1188 1324 pairstack[pair] = 1;
1189 - tempfree(x, "");
1325 + tempfree(x);
1190 1326 }
1191 1327 if (pairstack[pair] == 1) {
1192 1328 x = execute(a[1]);
1193 1329 if (istrue(x))
1194 1330 pairstack[pair] = 0;
1195 - tempfree(x, "");
1331 + tempfree(x);
1196 1332 x = execute(a[2]);
1197 1333 return (x);
1198 1334 }
1199 - return (false);
1335 + return (False);
1200 1336 }
1201 1337
1202 1338 /*ARGSUSED*/
1203 1339 Cell *
1204 -split(Node **a, int nnn)
1340 +split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
1205 1341 {
1206 - Cell *x, *y, *ap;
1207 - register uchar *s;
1208 - register int sep;
1209 - uchar *t, temp, num[11], *fs;
1210 - int n, tempstat;
1342 + Cell *x = 0, *y, *ap;
1343 + uchar *s, *origs;
1344 + int sep;
1345 + uchar *t, temp, num[50], *fs = 0;
1346 + int n, tempstat, arg3type;
1211 1347
1212 1348 y = execute(a[0]); /* source string */
1213 - s = getsval(y);
1349 + origs = s = (uchar *)strdup((char *)getsval(y));
1350 + arg3type = ptoi(a[3]);
1214 1351 if (a[2] == 0) /* fs string */
1215 1352 fs = *FS;
1216 - else if ((int)a[3] == STRING) { /* split(str,arr,"string") */
1353 + else if (arg3type == STRING) { /* split(str,arr,"string") */
1217 1354 x = execute(a[2]);
1218 1355 fs = getsval(x);
1219 - } else if ((int)a[3] == REGEXPR)
1356 + } else if (arg3type == REGEXPR)
1220 1357 fs = (uchar *)"(regexpr)"; /* split(str,arr,/regexpr/) */
1221 1358 else
1222 - ERROR "illegal type of split()" FATAL;
1359 + FATAL("illegal type of split");
1223 1360 sep = *fs;
1224 1361 ap = execute(a[1]); /* array name */
1225 1362 freesymtab(ap);
1226 1363 dprintf(("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs));
1227 1364 ap->tval &= ~STR;
1228 1365 ap->tval |= ARR;
1229 1366 ap->sval = (uchar *)makesymtab(NSYMTAB);
1230 1367
1231 1368 n = 0;
1232 - if (*s != '\0' && strlen((char *)fs) > 1 || (int)a[3] == REGEXPR) {
1369 + if (arg3type == REGEXPR && strlen((char *)((fa *)a[2])->restr) == 0) {
1370 + arg3type = 0;
1371 + fs = (uchar *)"";
1372 + sep = 0;
1373 + }
1374 + if (*s != '\0' && (strlen((char *)fs) > 1 || arg3type == REGEXPR)) {
1233 1375 /* reg expr */
1234 1376 fa *pfa;
1235 - if ((int)a[3] == REGEXPR) { /* it's ready already */
1377 + if (arg3type == REGEXPR) { /* it's ready already */
1236 1378 pfa = (fa *)a[2];
1237 1379 } else {
1238 1380 pfa = makedfa(fs, 1);
1239 1381 }
1240 1382 if (nematch(pfa, s)) {
1241 1383 tempstat = pfa->initstat;
1242 1384 pfa->initstat = 2;
1243 1385 do {
1244 1386 n++;
1245 1387 (void) sprintf((char *)num, "%d", n);
1246 1388 temp = *patbeg;
1247 1389 *patbeg = '\0';
1248 1390 if (is_number(s)) {
1249 1391 (void) setsymtab(num, s,
1250 1392 atof((char *)s),
1251 1393 /*LINTED align*/
1252 1394 STR|NUM, (Array *)ap->sval);
1253 1395 } else {
1254 1396 (void) setsymtab(num, s, 0.0,
1255 1397 /*LINTED align*/
1256 1398 STR, (Array *)ap->sval);
1257 1399 }
1258 1400 *patbeg = temp;
1259 1401 s = patbeg + patlen;
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
1260 1402 if (*(patbeg+patlen-1) == 0 || *s == 0) {
1261 1403 n++;
1262 1404 (void) sprintf((char *)num, "%d", n);
1263 1405 (void) setsymtab(num, (uchar *)"", 0.0,
1264 1406 /*LINTED align*/
1265 1407 STR, (Array *)ap->sval);
1266 1408 pfa->initstat = tempstat;
1267 1409 goto spdone;
1268 1410 }
1269 1411 } while (nematch(pfa, s));
1412 + /* bwk: has to be here to reset */
1413 + pfa->initstat = tempstat;
1414 + /* cf gsub and refldbld */
1270 1415 }
1271 1416 n++;
1272 1417 (void) sprintf((char *)num, "%d", n);
1273 1418 if (is_number(s)) {
1274 1419 (void) setsymtab(num, s, atof((char *)s),
1275 1420 /*LINTED align*/
1276 1421 STR|NUM, (Array *)ap->sval);
1277 1422 } else {
1278 1423 /*LINTED align*/
1279 1424 (void) setsymtab(num, s, 0.0, STR, (Array *)ap->sval);
1280 1425 }
1281 1426 spdone:
1282 1427 pfa = NULL;
1283 1428 } else if (sep == ' ') {
1284 1429 for (n = 0; ; ) {
1285 1430 while (*s == ' ' || *s == '\t' || *s == '\n')
1286 1431 s++;
1287 1432 if (*s == 0)
1288 1433 break;
1289 1434 n++;
1290 1435 t = s;
1291 1436 do
1292 1437 s++;
1293 1438 while (*s != ' ' && *s != '\t' &&
1294 1439 *s != '\n' && *s != '\0')
1295 1440 ;
1296 1441 temp = *s;
1297 1442 *s = '\0';
1298 1443 (void) sprintf((char *)num, "%d", n);
1299 1444 if (is_number(t)) {
1300 1445 (void) setsymtab(num, t, atof((char *)t),
1301 1446 /*LINTED align*/
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
1302 1447 STR|NUM, (Array *)ap->sval);
1303 1448 } else {
1304 1449 (void) setsymtab(num, t, 0.0,
1305 1450 /*LINTED align*/
1306 1451 STR, (Array *)ap->sval);
1307 1452 }
1308 1453 *s = temp;
1309 1454 if (*s != 0)
1310 1455 s++;
1311 1456 }
1457 + } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */
1458 + for (n = 0; *s != 0; s++) {
1459 + uchar buf[2];
1460 + n++;
1461 + (void) sprintf((char *)num, "%d", n);
1462 + buf[0] = *s;
1463 + buf[1] = 0;
1464 + if (isdigit(buf[0])) {
1465 + (void) setsymtab(num, buf, atof((char *)buf),
1466 + /* LINTED align */
1467 + STR | NUM, (Array *)ap->sval);
1468 + } else {
1469 + (void) setsymtab(num, buf, 0.0,
1470 + /* LINTED align */
1471 + STR, (Array *)ap->sval);
1472 + }
1473 + }
1312 1474 } else if (*s != 0) {
1313 1475 for (;;) {
1314 1476 n++;
1315 1477 t = s;
1316 1478 while (*s != sep && *s != '\n' && *s != '\0')
1317 1479 s++;
1318 1480 temp = *s;
1319 1481 *s = '\0';
1320 1482 (void) sprintf((char *)num, "%d", n);
1321 1483 if (is_number(t)) {
1322 1484 (void) setsymtab(num, t, atof((char *)t),
1323 1485 /*LINTED align*/
1324 1486 STR|NUM, (Array *)ap->sval);
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
1325 1487 } else {
1326 1488 (void) setsymtab(num, t, 0.0,
1327 1489 /*LINTED align*/
1328 1490 STR, (Array *)ap->sval);
1329 1491 }
1330 1492 *s = temp;
1331 1493 if (*s++ == 0)
1332 1494 break;
1333 1495 }
1334 1496 }
1335 - tempfree(ap, "");
1336 - tempfree(y, "");
1337 - if (a[2] != 0 && (int)a[3] == STRING)
1338 - tempfree(x, "");
1339 - x = gettemp("");
1497 + tempfree(ap);
1498 + tempfree(y);
1499 + free(origs);
1500 + if (a[2] != 0 && arg3type == STRING) {
1501 + tempfree(x);
1502 + }
1503 + x = gettemp();
1340 1504 x->tval = NUM;
1341 1505 x->fval = n;
1342 1506 return (x);
1343 1507 }
1344 1508
1345 1509 /*ARGSUSED*/
1346 1510 Cell *
1347 -condexpr(Node **a, int n)
1511 +condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */
1348 1512 {
1349 - register Cell *x;
1513 + Cell *x;
1350 1514
1351 1515 x = execute(a[0]);
1352 1516 if (istrue(x)) {
1353 - tempfree(x, "");
1517 + tempfree(x);
1354 1518 x = execute(a[1]);
1355 1519 } else {
1356 - tempfree(x, "");
1520 + tempfree(x);
1357 1521 x = execute(a[2]);
1358 1522 }
1359 1523 return (x);
1360 1524 }
1361 1525
1362 1526 /*ARGSUSED*/
1363 1527 Cell *
1364 -ifstat(Node **a, int n)
1528 +ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */
1365 1529 {
1366 - register Cell *x;
1530 + Cell *x;
1367 1531
1368 1532 x = execute(a[0]);
1369 1533 if (istrue(x)) {
1370 - tempfree(x, "");
1534 + tempfree(x);
1371 1535 x = execute(a[1]);
1372 1536 } else if (a[2] != 0) {
1373 - tempfree(x, "");
1537 + tempfree(x);
1374 1538 x = execute(a[2]);
1375 1539 }
1376 1540 return (x);
1377 1541 }
1378 1542
1379 1543 /*ARGSUSED*/
1380 1544 Cell *
1381 -whilestat(Node **a, int n)
1545 +whilestat(Node **a, int n) /* while (a[0]) a[1] */
1382 1546 {
1383 - register Cell *x;
1547 + Cell *x;
1384 1548
1385 1549 for (;;) {
1386 1550 x = execute(a[0]);
1387 1551 if (!istrue(x))
1388 1552 return (x);
1389 - tempfree(x, "");
1553 + tempfree(x);
1390 1554 x = execute(a[1]);
1391 1555 if (isbreak(x)) {
1392 - x = true;
1556 + x = True;
1393 1557 return (x);
1394 1558 }
1395 1559 if (isnext(x) || isexit(x) || isret(x))
1396 1560 return (x);
1397 - tempfree(x, "");
1561 + tempfree(x);
1398 1562 }
1399 1563 }
1400 1564
1401 1565 /*ARGSUSED*/
1402 1566 Cell *
1403 -dostat(Node **a, int n)
1567 +dostat(Node **a, int n) /* do a[0]; while(a[1]) */
1404 1568 {
1405 - register Cell *x;
1569 + Cell *x;
1406 1570
1407 1571 for (;;) {
1408 1572 x = execute(a[0]);
1409 1573 if (isbreak(x))
1410 - return (true);
1574 + return (True);
1411 1575 if (isnext(x) || isexit(x) || isret(x))
1412 1576 return (x);
1413 - tempfree(x, "");
1577 + tempfree(x);
1414 1578 x = execute(a[1]);
1415 1579 if (!istrue(x))
1416 1580 return (x);
1417 - tempfree(x, "");
1581 + tempfree(x);
1418 1582 }
1419 1583 }
1420 1584
1421 1585 /*ARGSUSED*/
1422 1586 Cell *
1423 -forstat(Node **a, int n)
1587 +forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */
1424 1588 {
1425 - register Cell *x;
1589 + Cell *x;
1426 1590
1427 1591 x = execute(a[0]);
1428 - tempfree(x, "");
1592 + tempfree(x);
1429 1593 for (;;) {
1430 1594 if (a[1] != 0) {
1431 1595 x = execute(a[1]);
1432 1596 if (!istrue(x))
1433 1597 return (x);
1434 1598 else
1435 - tempfree(x, "");
1599 + tempfree(x);
1436 1600 }
1437 1601 x = execute(a[3]);
1438 1602 if (isbreak(x)) /* turn off break */
1439 - return (true);
1603 + return (True);
1440 1604 if (isnext(x) || isexit(x) || isret(x))
1441 1605 return (x);
1442 - tempfree(x, "");
1606 + tempfree(x);
1443 1607 x = execute(a[2]);
1444 - tempfree(x, "");
1608 + tempfree(x);
1445 1609 }
1446 1610 }
1447 1611
1448 1612 /*ARGSUSED*/
1449 1613 Cell *
1450 -instat(Node **a, int n)
1614 +instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */
1451 1615 {
1452 - register Cell *x, *vp, *arrayp, *cp, *ncp;
1616 + Cell *x, *vp, *arrayp, *cp, *ncp;
1453 1617 Array *tp;
1454 1618 int i;
1455 1619
1456 1620 vp = execute(a[0]);
1457 1621 arrayp = execute(a[1]);
1458 - if (!isarr(arrayp))
1459 - ERROR "%s is not an array", arrayp->nval FATAL;
1622 + if (!isarr(arrayp)) {
1623 + return (True);
1624 + }
1460 1625 /*LINTED align*/
1461 1626 tp = (Array *)arrayp->sval;
1462 - tempfree(arrayp, "");
1627 + tempfree(arrayp);
1463 1628 for (i = 0; i < tp->size; i++) { /* this routine knows too much */
1464 1629 for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1465 1630 (void) setsval(vp, cp->nval);
1466 1631 ncp = cp->cnext;
1467 1632 x = execute(a[2]);
1468 1633 if (isbreak(x)) {
1469 - tempfree(vp, "");
1470 - return (true);
1634 + tempfree(vp);
1635 + return (True);
1471 1636 }
1472 1637 if (isnext(x) || isexit(x) || isret(x)) {
1473 - tempfree(vp, "");
1638 + tempfree(vp);
1474 1639 return (x);
1475 1640 }
1476 - tempfree(x, "");
1641 + tempfree(x);
1477 1642 }
1478 1643 }
1479 - return (true);
1644 + return (True);
1480 1645 }
1481 1646
1647 +/*
1648 + * builtin functions. a[0] is type, a[1] is arg list
1649 + */
1482 1650 /*ARGSUSED*/
1483 1651 Cell *
1484 1652 bltin(Node **a, int n)
1485 1653 {
1486 - register Cell *x, *y;
1654 + Cell *x, *y;
1487 1655 Awkfloat u;
1488 - register int t;
1656 + int t;
1657 + Awkfloat tmp;
1489 1658 uchar *p, *buf;
1490 1659 Node *nextarg;
1660 + FILE *fp;
1491 1661
1492 - t = (int)a[0];
1662 + t = ptoi(a[0]);
1493 1663 x = execute(a[1]);
1494 1664 nextarg = a[1]->nnext;
1495 1665 switch (t) {
1496 1666 case FLENGTH:
1497 - u = (Awkfloat)strlen((char *)getsval(x)); break;
1667 + if (isarr(x)) {
1668 + /* GROT. should be function */
1669 + /* LINTED align */
1670 + u = (Awkfloat)((Array *)x->sval)->nelem;
1671 + } else {
1672 + u = (Awkfloat)strlen((char *)getsval(x));
1673 + }
1674 + break;
1498 1675 case FLOG:
1499 1676 u = errcheck(log(getfval(x)), "log"); break;
1500 1677 case FINT:
1501 1678 (void) modf(getfval(x), &u); break;
1502 1679 case FEXP:
1503 1680 u = errcheck(exp(getfval(x)), "exp"); break;
1504 1681 case FSQRT:
1505 1682 u = errcheck(sqrt(getfval(x)), "sqrt"); break;
1506 1683 case FSIN:
1507 1684 u = sin(getfval(x)); break;
1508 1685 case FCOS:
1509 1686 u = cos(getfval(x)); break;
1510 1687 case FATAN:
1511 1688 if (nextarg == 0) {
1512 - ERROR "atan2 requires two arguments; returning 1.0"
1513 - WARNING;
1689 + WARNING("atan2 requires two arguments; returning 1.0");
1514 1690 u = 1.0;
1515 1691 } else {
1516 1692 y = execute(a[1]->nnext);
1517 1693 u = atan2(getfval(x), getfval(y));
1518 - tempfree(y, "");
1694 + tempfree(y);
1519 1695 nextarg = nextarg->nnext;
1520 1696 }
1521 1697 break;
1522 1698 case FSYSTEM:
1523 1699 /* in case something is buffered already */
1524 1700 (void) fflush(stdout);
1525 1701 /* 256 is unix-dep */
1526 1702 u = (Awkfloat)system((char *)getsval(x)) / 256;
1527 1703 break;
1528 1704 case FRAND:
1529 - u = (Awkfloat)(rand() % 32767) / 32767.0;
1705 + /* in principle, rand() returns something in 0..RAND_MAX */
1706 + u = (Awkfloat)(rand() % RAND_MAX) / RAND_MAX;
1530 1707 break;
1531 1708 case FSRAND:
1532 - if (x->tval & REC) /* no argument provided */
1709 + if (isrec(x)) /* no argument provided */
1533 1710 u = time((time_t *)0);
1534 1711 else
1535 1712 u = getfval(x);
1536 - srand((int)u); u = (int)u;
1713 + tmp = u;
1714 + srand((unsigned int)u);
1715 + u = srand_seed;
1716 + srand_seed = tmp;
1537 1717 break;
1538 1718 case FTOUPPER:
1539 1719 case FTOLOWER:
1540 1720 buf = tostring(getsval(x));
1541 1721 if (t == FTOUPPER) {
1542 1722 for (p = buf; *p; p++)
1543 1723 if (islower(*p))
1544 1724 *p = toupper(*p);
1545 1725 } else {
1546 1726 for (p = buf; *p; p++)
1547 1727 if (isupper(*p))
1548 1728 *p = tolower(*p);
1549 1729 }
1550 - tempfree(x, "");
1551 - x = gettemp("");
1730 + tempfree(x);
1731 + x = gettemp();
1552 1732 (void) setsval(x, buf);
1553 1733 free(buf);
1554 1734 return (x);
1735 + case FFLUSH:
1736 + if (isrec(x) || strlen((char *)getsval(x)) == 0) {
1737 + /* fflush() or fflush("") -> all */
1738 + flush_all();
1739 + u = 0;
1740 + } else if ((fp = openfile(FFLUSH, getsval(x))) == NULL)
1741 + u = EOF;
1742 + else
1743 + u = fflush(fp);
1744 + break;
1555 1745 default: /* can't happen */
1556 - ERROR "illegal function type %d", t FATAL;
1746 + FATAL("illegal function type %d", t);
1557 1747 break;
1558 1748 }
1559 - tempfree(x, "");
1560 - x = gettemp("");
1749 + tempfree(x);
1750 + x = gettemp();
1561 1751 (void) setfval(x, u);
1562 1752 if (nextarg != 0) {
1563 - ERROR "warning: function has too many arguments" WARNING;
1753 + WARNING("warning: function has too many arguments");
1564 1754 for (; nextarg; nextarg = nextarg->nnext)
1565 1755 (void) execute(nextarg);
1566 1756 }
1567 1757 return (x);
1568 1758 }
1569 1759
1570 1760 /*ARGSUSED*/
1571 1761 Cell *
1572 -print(Node **a, int n)
1762 +printstat(Node **a, int n) /* print a[0] */
1573 1763 {
1574 - register Node *x;
1575 - register Cell *y;
1764 + Node *x;
1765 + Cell *y;
1576 1766 FILE *fp;
1577 1767
1578 - if (a[1] == 0)
1768 + if (a[1] == 0) /* a[1] is redirection operator, a[2] is file */
1579 1769 fp = stdout;
1580 1770 else
1581 - fp = redirect((int)a[1], a[2]);
1771 + fp = redirect(ptoi(a[1]), a[2]);
1582 1772 for (x = a[0]; x != NULL; x = x->nnext) {
1583 1773 y = execute(x);
1584 1774 (void) fputs((char *)getsval(y), fp);
1585 - tempfree(y, "");
1775 + tempfree(y);
1586 1776 if (x->nnext == NULL)
1587 1777 (void) fputs((char *)*ORS, fp);
1588 1778 else
1589 1779 (void) fputs((char *)*OFS, fp);
1590 1780 }
1591 1781 if (a[1] != 0)
1592 1782 (void) fflush(fp);
1593 - return (true);
1783 + if (ferror(fp))
1784 + FATAL("write error on %s", filename(fp));
1785 + return (True);
1594 1786 }
1595 1787
1596 1788 /*ARGSUSED*/
1597 1789 Cell *
1598 1790 nullproc(Node **a, int n)
1599 1791 {
1600 1792 return (0);
1601 1793 }
1602 1794
1603 -struct {
1604 - FILE *fp;
1605 - uchar *fname;
1606 - int mode; /* '|', 'a', 'w' */
1607 -} files[FOPEN_MAX];
1608 -
1609 1795 static FILE *
1610 -redirect(int a, Node *b)
1796 +redirect(int a, Node *b) /* set up all i/o redirections */
1611 1797 {
1612 1798 FILE *fp;
1613 1799 Cell *x;
1614 1800 uchar *fname;
1615 1801
1616 1802 x = execute(b);
1617 1803 fname = getsval(x);
1618 1804 fp = openfile(a, fname);
1619 1805 if (fp == NULL)
1620 - ERROR "can't open file %s", fname FATAL;
1621 - tempfree(x, "");
1806 + FATAL("can't open file %s", fname);
1807 + tempfree(x);
1622 1808 return (fp);
1623 1809 }
1624 1810
1811 +struct files {
1812 + FILE *fp;
1813 + const uchar *fname;
1814 + int mode; /* '|', 'a', 'w' => LE/LT, GT */
1815 +} *files;
1816 +
1817 +int nfiles;
1818 +
1819 +static void
1820 +stdinit(void) /* in case stdin, etc., are not constants */
1821 +{
1822 + nfiles = FOPEN_MAX;
1823 + files = calloc(nfiles, sizeof (*files));
1824 + if (files == NULL)
1825 + FATAL("can't allocate file memory for %u files", nfiles);
1826 + files[0].fp = stdin;
1827 + files[0].fname = (uchar *)"/dev/stdin";
1828 + files[0].mode = LT;
1829 + files[1].fp = stdout;
1830 + files[1].fname = (uchar *)"/dev/stdout";
1831 + files[1].mode = GT;
1832 + files[2].fp = stderr;
1833 + files[2].fname = (uchar *)"/dev/stderr";
1834 + files[2].mode = GT;
1835 +}
1836 +
1625 1837 static FILE *
1626 -openfile(int a, uchar *s)
1838 +openfile(int a, const uchar *us)
1627 1839 {
1628 - register int i, m;
1629 - register FILE *fp;
1840 + const uchar *s = us;
1841 + int i, m;
1842 + FILE *fp = 0;
1630 1843
1631 1844 if (*s == '\0')
1632 - ERROR "null file name in print or getline" FATAL;
1633 - for (i = 0; i < FOPEN_MAX; i++) {
1845 + FATAL("null file name in print or getline");
1846 + for (i = 0; i < nfiles; i++) {
1634 1847 if (files[i].fname &&
1635 - strcmp((char *)s, (char *)files[i].fname) == 0) {
1848 + (strcmp((char *)s, (char *)files[i].fname) == 0)) {
1636 1849 if (a == files[i].mode ||
1637 - a == APPEND && files[i].mode == GT) {
1850 + (a == APPEND && files[i].mode == GT)) {
1638 1851 return (files[i].fp);
1639 1852 }
1853 + if (a == FFLUSH)
1854 + return (files[i].fp);
1640 1855 }
1641 1856 }
1642 - for (i = 0; i < FOPEN_MAX; i++) {
1857 + if (a == FFLUSH) /* didn't find it, so don't create it! */
1858 + return (NULL);
1859 +
1860 + for (i = 0; i < nfiles; i++) {
1643 1861 if (files[i].fp == 0)
1644 1862 break;
1645 1863 }
1646 - if (i >= FOPEN_MAX)
1647 - ERROR "%s makes too many open files", s FATAL;
1864 + if (i >= nfiles) {
1865 + struct files *nf;
1866 + int nnf = nfiles + FOPEN_MAX;
1867 + nf = realloc(files, nnf * sizeof (*nf));
1868 + if (nf == NULL)
1869 + FATAL("cannot grow files for %s and %d files", s, nnf);
1870 + (void) memset(&nf[nfiles], 0, FOPEN_MAX * sizeof (*nf));
1871 + nfiles = nnf;
1872 + files = nf;
1873 + }
1648 1874 (void) fflush(stdout); /* force a semblance of order */
1649 1875 m = a;
1650 1876 if (a == GT) {
1651 1877 fp = fopen((char *)s, "w");
1652 1878 } else if (a == APPEND) {
1653 1879 fp = fopen((char *)s, "a");
1654 1880 m = GT; /* so can mix > and >> */
1655 1881 } else if (a == '|') { /* output pipe */
1656 1882 fp = popen((char *)s, "w");
1657 1883 } else if (a == LE) { /* input pipe */
1658 1884 fp = popen((char *)s, "r");
1659 1885 } else if (a == LT) { /* getline <file */
1660 1886 fp = strcmp((char *)s, "-") == 0 ?
1661 1887 stdin : fopen((char *)s, "r"); /* "-" is stdin */
1662 1888 } else /* can't happen */
1663 - ERROR "illegal redirection" FATAL;
1889 + FATAL("illegal redirection %d", a);
1664 1890 if (fp != NULL) {
1665 1891 files[i].fname = tostring(s);
1666 1892 files[i].fp = fp;
1667 1893 files[i].mode = m;
1668 1894 }
1669 1895 return (fp);
1670 1896 }
1671 1897
1898 +static const char *
1899 +filename(FILE *fp)
1900 +{
1901 + int i;
1902 +
1903 + for (i = 0; i < nfiles; i++) {
1904 + if (fp == files[i].fp)
1905 + return ((char *)files[i].fname);
1906 + }
1907 +
1908 + return ("???");
1909 +}
1910 +
1672 1911 /*ARGSUSED*/
1673 1912 Cell *
1674 1913 closefile(Node **a, int n)
1675 1914 {
1676 - register Cell *x;
1915 + Cell *x;
1677 1916 int i, stat;
1678 1917
1679 1918 x = execute(a[0]);
1680 1919 (void) getsval(x);
1681 - for (i = 0; i < FOPEN_MAX; i++) {
1920 + stat = -1;
1921 + for (i = 0; i < nfiles; i++) {
1682 1922 if (files[i].fname &&
1683 1923 strcmp((char *)x->sval, (char *)files[i].fname) == 0) {
1684 1924 if (ferror(files[i].fp)) {
1685 - ERROR "i/o error occurred on %s",
1686 - files[i].fname WARNING;
1925 + WARNING("i/o error occurred on %s",
1926 + files[i].fname);
1687 1927 }
1688 1928 if (files[i].mode == '|' || files[i].mode == LE)
1689 1929 stat = pclose(files[i].fp);
1690 1930 else
1691 1931 stat = fclose(files[i].fp);
1692 1932 if (stat == EOF) {
1693 - ERROR "i/o error occurred closing %s",
1694 - files[i].fname WARNING;
1933 + WARNING("i/o error occurred closing %s",
1934 + files[i].fname);
1695 1935 }
1696 - xfree(files[i].fname);
1936 + if (i > 2) /* don't do /dev/std... */
1937 + xfree(files[i].fname);
1697 1938 /* watch out for ref thru this */
1698 1939 files[i].fname = NULL;
1699 1940 files[i].fp = NULL;
1700 1941 }
1701 1942 }
1702 - tempfree(x, "close");
1703 - return (true);
1943 + tempfree(x);
1944 + x = gettemp();
1945 + (void) setfval(x, (Awkfloat)stat);
1946 + return (x);
1704 1947 }
1705 1948
1706 1949 static void
1707 1950 closeall(void)
1708 1951 {
1709 1952 int i, stat;
1710 1953
1711 1954 for (i = 0; i < FOPEN_MAX; i++) {
1712 1955 if (files[i].fp) {
1713 1956 if (ferror(files[i].fp)) {
1714 - ERROR "i/o error occurred on %s",
1715 - files[i].fname WARNING;
1957 + WARNING("i/o error occurred on %s",
1958 + files[i].fname);
1716 1959 }
1717 1960 if (files[i].mode == '|' || files[i].mode == LE)
1718 1961 stat = pclose(files[i].fp);
1719 1962 else
1720 1963 stat = fclose(files[i].fp);
1721 1964 if (stat == EOF) {
1722 - ERROR "i/o error occurred while closing %s",
1723 - files[i].fname WARNING;
1965 + WARNING("i/o error occurred while closing %s",
1966 + files[i].fname);
1724 1967 }
1725 1968 }
1726 1969 }
1727 1970 }
1728 1971
1972 +static void
1973 +flush_all(void)
1974 +{
1975 + int i;
1976 +
1977 + for (i = 0; i < nfiles; i++)
1978 + if (files[i].fp)
1979 + (void) fflush(files[i].fp);
1980 +}
1981 +
1982 +void backsub(uchar **pb_ptr, uchar **sptr_ptr);
1983 +
1729 1984 /*ARGSUSED*/
1730 1985 Cell *
1731 -sub(Node **a, int nnn)
1986 +sub(Node **a, int nnn) /* substitute command */
1732 1987 {
1733 - register uchar *sptr;
1734 - register Cell *x, *y, *result;
1735 - uchar *buf, *t;
1988 + uchar *sptr, *pb, *q;
1989 + Cell *x, *y, *result;
1990 + uchar *t, *buf;
1736 1991 fa *pfa;
1737 - size_t bsize, cnt, len;
1992 + size_t bufsz = record_size;
1738 1993
1994 + if ((buf = (uchar *)malloc(bufsz)) == NULL)
1995 + FATAL("out of memory in sub");
1739 1996 x = execute(a[3]); /* target string */
1740 1997 t = getsval(x);
1741 - if (a[0] == 0)
1998 + if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1742 1999 pfa = (fa *)a[1]; /* regular expression */
1743 2000 else {
1744 2001 y = execute(a[1]);
1745 2002 pfa = makedfa(getsval(y), 1);
1746 - tempfree(y, "");
2003 + tempfree(y);
1747 2004 }
1748 2005 y = execute(a[2]); /* replacement string */
1749 - result = false;
2006 + result = False;
1750 2007 if (pmatch(pfa, t)) {
1751 - init_buf(&buf, &bsize, LINE_INCR);
1752 - cnt = 0;
1753 2008 sptr = t;
1754 - len = patbeg - sptr;
1755 - if (len > 0) {
1756 - expand_buf(&buf, &bsize, cnt + len);
1757 - (void) memcpy(buf, sptr, len);
1758 - cnt += len;
1759 - }
2009 + (void) adjbuf(&buf, &bufsz, 1+patbeg-sptr, record_size,
2010 + 0, "sub");
2011 + pb = buf;
2012 + while (sptr < patbeg)
2013 + *pb++ = *sptr++;
1760 2014 sptr = getsval(y);
1761 2015 while (*sptr != 0) {
1762 - expand_buf(&buf, &bsize, cnt);
1763 - if (*sptr == '\\' &&
1764 - (*(sptr+1) == '&' || *(sptr+1) == '\\')) {
1765 - sptr++; /* skip \, */
1766 - buf[cnt++] = *sptr++; /* add & or \ */
2016 + (void) adjbuf(&buf, &bufsz, 5 + pb - buf, record_size,
2017 + &pb, "sub");
2018 + if (*sptr == '\\') {
2019 + backsub(&pb, &sptr);
1767 2020 } else if (*sptr == '&') {
1768 - expand_buf(&buf, &bsize, cnt + patlen);
1769 2021 sptr++;
1770 - (void) memcpy(&buf[cnt], patbeg, patlen);
1771 - cnt += patlen;
2022 + (void) adjbuf(&buf, &bufsz, 1+patlen+pb-buf,
2023 + record_size, &pb, "sub");
2024 + for (q = patbeg; q < patbeg + patlen; )
2025 + *pb++ = *q++;
1772 2026 } else {
1773 - buf[cnt++] = *sptr++;
2027 + *pb++ = *sptr++;
1774 2028 }
1775 2029 }
2030 + *pb = '\0';
2031 + if (pb > buf + bufsz)
2032 + FATAL("sub result1 %.30s too big; can't happen", buf);
1776 2033 sptr = patbeg + patlen;
1777 2034 if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
1778 - len = strlen((char *)sptr);
1779 - expand_buf(&buf, &bsize, cnt + len);
1780 - (void) memcpy(&buf[cnt], sptr, len);
1781 - cnt += len;
2035 + (void) adjbuf(&buf, &bufsz, 1 + strlen((char *)sptr) +
2036 + pb - buf, 0, &pb, "sub");
2037 + while ((*pb++ = *sptr++) != 0)
2038 + ;
1782 2039 }
1783 - buf[cnt] = '\0';
2040 + if (pb > buf + bufsz)
2041 + FATAL("sub result2 %.30s too big; can't happen", buf);
2042 + /* BUG: should be able to avoid copy */
1784 2043 (void) setsval(x, buf);
1785 - free(buf);
1786 - result = true;
2044 + result = True;
1787 2045 }
1788 - tempfree(x, "");
1789 - tempfree(y, "");
2046 + tempfree(x);
2047 + tempfree(y);
2048 + free(buf);
1790 2049 return (result);
1791 2050 }
1792 2051
1793 2052 /*ARGSUSED*/
1794 2053 Cell *
1795 -gsub(Node **a, int nnn)
2054 +gsub(Node **a, int nnn) /* global substitute */
1796 2055 {
1797 - register Cell *x, *y;
1798 - register uchar *rptr, *sptr, *t;
2056 + Cell *x, *y;
2057 + uchar *rptr, *sptr, *t, *pb, *q;
1799 2058 uchar *buf;
1800 - register fa *pfa;
2059 + fa *pfa;
1801 2060 int mflag, tempstat, num;
1802 - size_t bsize, cnt, len;
2061 + size_t bufsz = record_size;
1803 2062
2063 + if ((buf = (uchar *)malloc(bufsz)) == NULL)
2064 + FATAL("out of memory in gsub");
1804 2065 mflag = 0; /* if mflag == 0, can replace empty string */
1805 2066 num = 0;
1806 2067 x = execute(a[3]); /* target string */
1807 2068 t = getsval(x);
1808 - if (a[0] == 0)
1809 - pfa = (fa *) a[1]; /* regular expression */
2069 + if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */
2070 + pfa = (fa *)a[1]; /* regular expression */
1810 2071 else {
1811 2072 y = execute(a[1]);
1812 2073 pfa = makedfa(getsval(y), 1);
1813 - tempfree(y, "");
2074 + tempfree(y);
1814 2075 }
1815 2076 y = execute(a[2]); /* replacement string */
1816 2077 if (pmatch(pfa, t)) {
1817 2078 tempstat = pfa->initstat;
1818 2079 pfa->initstat = 2;
1819 - init_buf(&buf, &bsize, LINE_INCR);
2080 + pb = buf;
1820 2081 rptr = getsval(y);
1821 - cnt = 0;
1822 2082 do {
1823 2083 if (patlen == 0 && *patbeg != 0) {
1824 2084 /* matched empty string */
1825 2085 if (mflag == 0) { /* can replace empty */
1826 2086 num++;
1827 2087 sptr = rptr;
1828 2088 while (*sptr != 0) {
1829 - expand_buf(&buf, &bsize, cnt);
1830 - if (*sptr == '\\' &&
1831 - (*(sptr+1) == '&' ||
1832 - *(sptr+1) == '\\')) {
1833 - sptr++;
1834 - buf[cnt++] = *sptr++;
1835 - } else if (*sptr == '&') {
1836 - expand_buf(&buf,
1837 - &bsize,
1838 - cnt + patlen);
1839 - sptr++;
1840 - (void) memcpy(&buf[cnt],
1841 - patbeg, patlen);
1842 - cnt += patlen;
1843 - } else {
1844 - buf[cnt++] = *sptr++;
1845 - }
2089 + (void) adjbuf(&buf, &bufsz, 5+pb-buf,
2090 + record_size, &pb, "gsub");
2091 + if (*sptr == '\\') {
2092 + backsub(&pb, &sptr);
2093 + } else if (*sptr == '&') {
2094 + sptr++;
2095 + (void) adjbuf(&buf, &bufsz, 1 +
2096 + patlen+pb-buf, record_size,
2097 + &pb, "gsub");
2098 + for (q = patbeg; q < patbeg+patlen; )
2099 + *pb++ = *q++;
2100 + } else {
2101 + *pb++ = *sptr++;
2102 + }
1846 2103 }
1847 2104 }
1848 2105 if (*t == 0) /* at end */
1849 2106 goto done;
1850 - expand_buf(&buf, &bsize, cnt);
1851 - buf[cnt++] = *t++;
2107 + (void) adjbuf(&buf, &bufsz, 2 + pb - buf,
2108 + record_size, &pb, "gsub");
2109 + *pb++ = *t++;
2110 + /* BUG: not sure of this test */
2111 + if (pb > buf + bufsz)
2112 + FATAL(
2113 + "gsub result0 %.30s too big; can't happen", buf);
1852 2114 mflag = 0;
1853 2115 } else { /* matched nonempty string */
1854 2116 num++;
1855 2117 sptr = t;
1856 - len = patbeg - sptr;
1857 - if (len > 0) {
1858 - expand_buf(&buf, &bsize, cnt + len);
1859 - (void) memcpy(&buf[cnt], sptr, len);
1860 - cnt += len;
1861 - }
2118 + (void) adjbuf(&buf, &bufsz, 1 +
2119 + (patbeg - sptr) + pb - buf, record_size,
2120 + &pb, "gsub");
2121 + while (sptr < patbeg)
2122 + *pb++ = *sptr++;
1862 2123 sptr = rptr;
1863 2124 while (*sptr != 0) {
1864 - expand_buf(&buf, &bsize, cnt);
1865 - if (*sptr == '\\' &&
1866 - (*(sptr+1) == '&' ||
1867 - *(sptr+1) == '\\')) {
1868 - sptr++;
1869 - buf[cnt++] = *sptr++;
2125 + (void) adjbuf(&buf, &bufsz, 5 + pb -
2126 + buf, record_size, &pb, "gsub");
2127 + if (*sptr == '\\') {
2128 + backsub(&pb, &sptr);
1870 2129 } else if (*sptr == '&') {
1871 - expand_buf(&buf, &bsize,
1872 - cnt + patlen);
1873 2130 sptr++;
1874 - (void) memcpy(&buf[cnt],
1875 - patbeg, patlen);
1876 - cnt += patlen;
2131 + (void) adjbuf(&buf, &bufsz, 1 +
2132 + patlen + pb - buf, record_size,
2133 + &pb, "gsub");
2134 + for (q = patbeg; q < patbeg + patlen; )
2135 + *pb++ = *q++;
1877 2136 } else {
1878 - buf[cnt++] = *sptr++;
2137 + *pb++ = *sptr++;
1879 2138 }
1880 2139 }
1881 2140 t = patbeg + patlen;
1882 - if ((*(t-1) == 0) || (*t == 0))
2141 + if (patlen == 0 || *t == 0 || *(t - 1) == 0)
1883 2142 goto done;
2143 + if (pb > buf + bufsz)
2144 + FATAL(
2145 + "gsub result1 %.30s too big; can't happen", buf);
1884 2146 mflag = 1;
1885 2147 }
1886 2148 } while (pmatch(pfa, t));
1887 2149 sptr = t;
1888 - len = strlen((char *)sptr);
1889 - expand_buf(&buf, &bsize, len + cnt);
1890 - (void) memcpy(&buf[cnt], sptr, len);
1891 - cnt += len;
1892 - done:
1893 - buf[cnt] = '\0';
2150 + (void) adjbuf(&buf, &bufsz, 1 + strlen((char *)sptr) + pb -
2151 + buf, 0, &pb, "gsub");
2152 + while ((*pb++ = *sptr++) != 0)
2153 + ;
2154 + done: if (pb < buf + bufsz)
2155 + *pb = '\0';
2156 + else if (*(pb-1) != '\0')
2157 + FATAL("gsub result2 %.30s truncated; can't happen",
2158 + buf);
2159 + /* BUG: should be able to avoid copy + free */
1894 2160 (void) setsval(x, buf);
1895 - free(buf);
1896 2161 pfa->initstat = tempstat;
1897 2162 }
1898 - tempfree(x, "");
1899 - tempfree(y, "");
1900 - x = gettemp("");
2163 + tempfree(x);
2164 + tempfree(y);
2165 + x = gettemp();
1901 2166 x->tval = NUM;
1902 2167 x->fval = num;
2168 + free(buf);
1903 2169 return (x);
1904 2170 }
2171 +
2172 +void
2173 +backsub(uchar **pb_ptr, uchar **sptr_ptr) /* handle \\& variations */
2174 +{ /* sptr[0] == '\\' */
2175 + uchar *pb = *pb_ptr, *sptr = *sptr_ptr;
2176 +
2177 + if (sptr[1] == '\\') {
2178 + if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
2179 + *pb++ = '\\';
2180 + *pb++ = '&';
2181 + sptr += 4;
2182 + } else if (sptr[2] == '&') { /* \\& -> \ + matched */
2183 + *pb++ = '\\';
2184 + sptr += 2;
2185 + } else { /* \\x -> \\x */
2186 + *pb++ = *sptr++;
2187 + *pb++ = *sptr++;
2188 + }
2189 + } else if (sptr[1] == '&') { /* literal & */
2190 + sptr++;
2191 + *pb++ = *sptr++;
2192 + } else /* literal \ */
2193 + *pb++ = *sptr++;
2194 +
2195 + *pb_ptr = pb;
2196 + *sptr_ptr = sptr;
2197 +}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX