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