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