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