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