1 /* $OpenBSD: run.c,v 1.30 2008/10/06 20:38:33 millert 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 int use_arc4 = 1; 70 extern int pairstack[]; 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 = (struct Frame *) 274 realloc((char *) frame, (nframe += 100) * sizeof(struct Frame)); 275 if (frame == NULL) 276 FATAL("out of space for stack frames in %s", s); 277 fp = frame + dfp; 278 } 279 fp->fcncell = fcn; 280 fp->args = args; 281 fp->nargs = ndef; /* number defined with (excess are locals) */ 282 fp->retval = gettemp(); 283 284 dprintf( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) ); 285 y = execute((Node *)(fcn->sval)); /* execute body */ 286 dprintf( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) ); 287 288 for (i = 0; i < ndef; i++) { 289 Cell *t = fp->args[i]; 290 if (isarr(t)) { 291 if (t->csub == CCOPY) { 292 if (i >= ncall) { 293 freesymtab(t); 294 t->csub = CTEMP; 295 tempfree(t); 296 } else { 297 oargs[i]->tval = t->tval; 298 oargs[i]->tval &= ~(STR|NUM|DONTFREE); 299 oargs[i]->sval = t->sval; 300 tempfree(t); 301 } 302 } 303 } else if (t != y) { /* kludge to prevent freeing twice */ 304 t->csub = CTEMP; 305 tempfree(t); 306 } else if (t == y && t->csub == CCOPY) { 307 t->csub = CTEMP; 308 tempfree(t); 309 freed = 1; 310 } 311 } 312 tempfree(fcn); 313 if (isexit(y) || isnext(y)) 314 return y; 315 if (freed == 0) { 316 tempfree(y); /* don't free twice! */ 317 } 318 z = fp->retval; /* return value */ 319 dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) ); 320 fp--; 321 return(z); 322 } 323 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 *getline(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 (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(y); 1171 z = gettemp(); 1172 z->sval = s; 1173 z->tval = STR; 1174 tempfree(x); 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; 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 s = getsval(y); 1227 arg3type = ptoi(a[3]); 1228 if (a[2] == 0) /* fs string */ 1229 fs = *FS; 1230 else if (arg3type == STRING) { /* split(str,arr,"string") */ 1231 x = execute(a[2]); 1232 fs = getsval(x); 1233 } else if (arg3type == REGEXPR) 1234 fs = "(regexpr)"; /* split(str,arr,/regexpr/) */ 1235 else 1236 FATAL("illegal type of split"); 1237 sep = *fs; 1238 ap = execute(a[1]); /* array name */ 1239 freesymtab(ap); 1240 dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs) ); 1241 ap->tval &= ~STR; 1242 ap->tval |= ARR; 1243 ap->sval = (char *) makesymtab(NSYMTAB); 1244 1245 n = 0; 1246 if (*s != '\0' && (strlen(fs) > 1 || arg3type == REGEXPR)) { /* reg expr */ 1247 fa *pfa; 1248 if (arg3type == REGEXPR) { /* it's ready already */ 1249 pfa = (fa *) a[2]; 1250 } else { 1251 pfa = makedfa(fs, 1); 1252 } 1253 if (nematch(pfa,s)) { 1254 tempstat = pfa->initstat; 1255 pfa->initstat = 2; 1256 do { 1257 n++; 1258 snprintf(num, sizeof num, "%d", n); 1259 temp = *patbeg; 1260 *patbeg = '\0'; 1261 if (is_number(s)) 1262 setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval); 1263 else 1264 setsymtab(num, s, 0.0, STR, (Array *) ap->sval); 1265 *patbeg = temp; 1266 s = patbeg + patlen; 1267 if (*(patbeg+patlen-1) == 0 || *s == 0) { 1268 n++; 1269 snprintf(num, sizeof num, "%d", n); 1270 setsymtab(num, "", 0.0, STR, (Array *) ap->sval); 1271 pfa->initstat = tempstat; 1272 goto spdone; 1273 } 1274 } while (nematch(pfa,s)); 1275 pfa->initstat = tempstat; /* bwk: has to be here to reset */ 1276 /* cf gsub and refldbld */ 1277 } 1278 n++; 1279 snprintf(num, sizeof num, "%d", n); 1280 if (is_number(s)) 1281 setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval); 1282 else 1283 setsymtab(num, s, 0.0, STR, (Array *) ap->sval); 1284 spdone: 1285 pfa = NULL; 1286 } else if (sep == ' ') { 1287 for (n = 0; ; ) { 1288 while (*s == ' ' || *s == '\t' || *s == '\n') 1289 s++; 1290 if (*s == 0) 1291 break; 1292 n++; 1293 t = s; 1294 do 1295 s++; 1296 while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0'); 1297 temp = *s; 1298 *s = '\0'; 1299 snprintf(num, sizeof num, "%d", n); 1300 if (is_number(t)) 1301 setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval); 1302 else 1303 setsymtab(num, t, 0.0, STR, (Array *) ap->sval); 1304 *s = temp; 1305 if (*s != 0) 1306 s++; 1307 } 1308 } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */ 1309 for (n = 0; *s != 0; s++) { 1310 char buf[2]; 1311 n++; 1312 snprintf(num, sizeof num, "%d", n); 1313 buf[0] = *s; 1314 buf[1] = 0; 1315 if (isdigit((uschar)buf[0])) 1316 setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval); 1317 else 1318 setsymtab(num, buf, 0.0, STR, (Array *) ap->sval); 1319 } 1320 } else if (*s != 0) { 1321 for (;;) { 1322 n++; 1323 t = s; 1324 while (*s != sep && *s != '\n' && *s != '\0') 1325 s++; 1326 temp = *s; 1327 *s = '\0'; 1328 snprintf(num, sizeof num, "%d", n); 1329 if (is_number(t)) 1330 setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval); 1331 else 1332 setsymtab(num, t, 0.0, STR, (Array *) ap->sval); 1333 *s = temp; 1334 if (*s++ == 0) 1335 break; 1336 } 1337 } 1338 tempfree(ap); 1339 tempfree(y); 1340 if (a[2] != 0 && arg3type == STRING) { 1341 tempfree(x); 1342 } 1343 x = gettemp(); 1344 x->tval = NUM; 1345 x->fval = n; 1346 return(x); 1347 } 1348 1349 Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */ 1350 { 1351 Cell *x; 1352 1353 x = execute(a[0]); 1354 if (istrue(x)) { 1355 tempfree(x); 1356 x = execute(a[1]); 1357 } else { 1358 tempfree(x); 1359 x = execute(a[2]); 1360 } 1361 return(x); 1362 } 1363 1364 Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */ 1365 { 1366 Cell *x; 1367 1368 x = execute(a[0]); 1369 if (istrue(x)) { 1370 tempfree(x); 1371 x = execute(a[1]); 1372 } else if (a[2] != 0) { 1373 tempfree(x); 1374 x = execute(a[2]); 1375 } 1376 return(x); 1377 } 1378 1379 Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */ 1380 { 1381 Cell *x; 1382 1383 for (;;) { 1384 x = execute(a[0]); 1385 if (!istrue(x)) 1386 return(x); 1387 tempfree(x); 1388 x = execute(a[1]); 1389 if (isbreak(x)) { 1390 x = True; 1391 return(x); 1392 } 1393 if (isnext(x) || isexit(x) || isret(x)) 1394 return(x); 1395 tempfree(x); 1396 } 1397 } 1398 1399 Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */ 1400 { 1401 Cell *x; 1402 1403 for (;;) { 1404 x = execute(a[0]); 1405 if (isbreak(x)) 1406 return True; 1407 if (isnext(x) || isexit(x) || isret(x)) 1408 return(x); 1409 tempfree(x); 1410 x = execute(a[1]); 1411 if (!istrue(x)) 1412 return(x); 1413 tempfree(x); 1414 } 1415 } 1416 1417 Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */ 1418 { 1419 Cell *x; 1420 1421 x = execute(a[0]); 1422 tempfree(x); 1423 for (;;) { 1424 if (a[1]!=0) { 1425 x = execute(a[1]); 1426 if (!istrue(x)) return(x); 1427 else tempfree(x); 1428 } 1429 x = execute(a[3]); 1430 if (isbreak(x)) /* turn off break */ 1431 return True; 1432 if (isnext(x) || isexit(x) || isret(x)) 1433 return(x); 1434 tempfree(x); 1435 x = execute(a[2]); 1436 tempfree(x); 1437 } 1438 } 1439 1440 Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */ 1441 { 1442 Cell *x, *vp, *arrayp, *cp, *ncp; 1443 Array *tp; 1444 int i; 1445 1446 vp = execute(a[0]); 1447 arrayp = execute(a[1]); 1448 if (!isarr(arrayp)) { 1449 return True; 1450 } 1451 tp = (Array *) arrayp->sval; 1452 tempfree(arrayp); 1453 for (i = 0; i < tp->size; i++) { /* this routine knows too much */ 1454 for (cp = tp->tab[i]; cp != NULL; cp = ncp) { 1455 setsval(vp, cp->nval); 1456 ncp = cp->cnext; 1457 x = execute(a[2]); 1458 if (isbreak(x)) { 1459 tempfree(vp); 1460 return True; 1461 } 1462 if (isnext(x) || isexit(x) || isret(x)) { 1463 tempfree(vp); 1464 return(x); 1465 } 1466 tempfree(x); 1467 } 1468 } 1469 return True; 1470 } 1471 1472 Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */ 1473 { 1474 Cell *x, *y; 1475 Awkfloat u; 1476 int t; 1477 char *p, *buf; 1478 Node *nextarg; 1479 FILE *fp; 1480 1481 t = ptoi(a[0]); 1482 x = execute(a[1]); 1483 nextarg = a[1]->nnext; 1484 switch (t) { 1485 case FLENGTH: 1486 if (isarr(x)) 1487 u = ((Array *) x->sval)->nelem; /* GROT. should be function*/ 1488 else 1489 u = strlen(getsval(x)); 1490 break; 1491 case FLOG: 1492 u = errcheck(log(getfval(x)), "log"); break; 1493 case FINT: 1494 modf(getfval(x), &u); break; 1495 case FEXP: 1496 u = errcheck(exp(getfval(x)), "exp"); break; 1497 case FSQRT: 1498 u = errcheck(sqrt(getfval(x)), "sqrt"); break; 1499 case FSIN: 1500 u = sin(getfval(x)); break; 1501 case FCOS: 1502 u = cos(getfval(x)); break; 1503 case FATAN: 1504 if (nextarg == 0) { 1505 WARNING("atan2 requires two arguments; returning 1.0"); 1506 u = 1.0; 1507 } else { 1508 y = execute(a[1]->nnext); 1509 u = atan2(getfval(x), getfval(y)); 1510 tempfree(y); 1511 nextarg = nextarg->nnext; 1512 } 1513 break; 1514 case FCOMPL: 1515 u = ~((int)getfval(x)); 1516 break; 1517 case FAND: 1518 if (nextarg == 0) { 1519 WARNING("and requires two arguments; returning 0"); 1520 u = 0; 1521 break; 1522 } 1523 y = execute(a[1]->nnext); 1524 u = ((int)getfval(x)) & ((int)getfval(y)); 1525 tempfree(y); 1526 nextarg = nextarg->nnext; 1527 break; 1528 case FFOR: 1529 if (nextarg == 0) { 1530 WARNING("or requires two arguments; returning 0"); 1531 u = 0; 1532 break; 1533 } 1534 y = execute(a[1]->nnext); 1535 u = ((int)getfval(x)) | ((int)getfval(y)); 1536 tempfree(y); 1537 nextarg = nextarg->nnext; 1538 break; 1539 case FXOR: 1540 if (nextarg == 0) { 1541 WARNING("or requires two arguments; returning 0"); 1542 u = 0; 1543 break; 1544 } 1545 y = execute(a[1]->nnext); 1546 u = ((int)getfval(x)) ^ ((int)getfval(y)); 1547 tempfree(y); 1548 nextarg = nextarg->nnext; 1549 break; 1550 case FLSHIFT: 1551 if (nextarg == 0) { 1552 WARNING("or requires two arguments; returning 0"); 1553 u = 0; 1554 break; 1555 } 1556 y = execute(a[1]->nnext); 1557 u = ((int)getfval(x)) << ((int)getfval(y)); 1558 tempfree(y); 1559 nextarg = nextarg->nnext; 1560 break; 1561 case FRSHIFT: 1562 if (nextarg == 0) { 1563 WARNING("or requires two arguments; returning 0"); 1564 u = 0; 1565 break; 1566 } 1567 y = execute(a[1]->nnext); 1568 u = ((int)getfval(x)) >> ((int)getfval(y)); 1569 tempfree(y); 1570 nextarg = nextarg->nnext; 1571 break; 1572 case FSYSTEM: 1573 fflush(stdout); /* in case something is buffered already */ 1574 u = (Awkfloat) system(getsval(x)) / 256; /* 256 is unix-dep */ 1575 break; 1576 case FRAND: 1577 if (use_arc4) 1578 u = (Awkfloat)arc4random() / 0xffffffff; 1579 else 1580 u = (Awkfloat) (random() % RAND_MAX) / RAND_MAX; 1581 break; 1582 case FSRAND: 1583 if (isrec(x)) /* no argument provided, want arc4random() */ 1584 use_arc4 = 1; 1585 else { 1586 u = getfval(x); 1587 srandom((unsigned int) u); 1588 use_arc4 = 0; 1589 } 1590 break; 1591 case FTOUPPER: 1592 case FTOLOWER: 1593 buf = tostring(getsval(x)); 1594 if (t == FTOUPPER) { 1595 for (p = buf; *p; p++) 1596 if (islower((uschar) *p)) 1597 *p = toupper((uschar)*p); 1598 } else { 1599 for (p = buf; *p; p++) 1600 if (isupper((uschar) *p)) 1601 *p = tolower((uschar)*p); 1602 } 1603 tempfree(x); 1604 x = gettemp(); 1605 setsval(x, buf); 1606 free(buf); 1607 return x; 1608 case FFLUSH: 1609 if (isrec(x) || strlen(getsval(x)) == 0) { 1610 flush_all(); /* fflush() or fflush("") -> all */ 1611 u = 0; 1612 } else if ((fp = openfile(FFLUSH, getsval(x))) == NULL) 1613 u = EOF; 1614 else 1615 u = fflush(fp); 1616 break; 1617 default: /* can't happen */ 1618 FATAL("illegal function type %d", t); 1619 break; 1620 } 1621 tempfree(x); 1622 x = gettemp(); 1623 setfval(x, u); 1624 if (nextarg != 0) { 1625 WARNING("warning: function has too many arguments"); 1626 for ( ; nextarg; nextarg = nextarg->nnext) 1627 execute(nextarg); 1628 } 1629 return(x); 1630 } 1631 1632 Cell *printstat(Node **a, int n) /* print a[0] */ 1633 { 1634 Node *x; 1635 Cell *y; 1636 FILE *fp; 1637 1638 if (a[1] == 0) /* a[1] is redirection operator, a[2] is file */ 1639 fp = stdout; 1640 else 1641 fp = redirect(ptoi(a[1]), a[2]); 1642 for (x = a[0]; x != NULL; x = x->nnext) { 1643 y = execute(x); 1644 fputs(getpssval(y), fp); 1645 tempfree(y); 1646 if (x->nnext == NULL) 1647 fputs(*ORS, fp); 1648 else 1649 fputs(*OFS, fp); 1650 } 1651 if (a[1] != 0) 1652 fflush(fp); 1653 if (ferror(fp)) 1654 FATAL("write error on %s", filename(fp)); 1655 return(True); 1656 } 1657 1658 Cell *nullproc(Node **a, int n) 1659 { 1660 n = n; 1661 a = a; 1662 return 0; 1663 } 1664 1665 1666 FILE *redirect(int a, Node *b) /* set up all i/o redirections */ 1667 { 1668 FILE *fp; 1669 Cell *x; 1670 char *fname; 1671 1672 x = execute(b); 1673 fname = getsval(x); 1674 fp = openfile(a, fname); 1675 if (fp == NULL) 1676 FATAL("can't open file %s", fname); 1677 tempfree(x); 1678 return fp; 1679 } 1680 1681 struct files { 1682 FILE *fp; 1683 const char *fname; 1684 int mode; /* '|', 'a', 'w' => LE/LT, GT */ 1685 } files[FOPEN_MAX] ={ 1686 { NULL, "/dev/stdin", LT }, /* watch out: don't free this! */ 1687 { NULL, "/dev/stdout", GT }, 1688 { NULL, "/dev/stderr", GT } 1689 }; 1690 1691 void stdinit(void) /* in case stdin, etc., are not constants */ 1692 { 1693 files[0].fp = stdin; 1694 files[1].fp = stdout; 1695 files[2].fp = stderr; 1696 } 1697 1698 FILE *openfile(int a, const char *us) 1699 { 1700 const char *s = us; 1701 int i, m; 1702 FILE *fp = 0; 1703 1704 if (*s == '\0') 1705 FATAL("null file name in print or getline"); 1706 for (i=0; i < FOPEN_MAX; i++) 1707 if (files[i].fname && strcmp(s, files[i].fname) == 0) { 1708 if (a == files[i].mode || (a==APPEND && files[i].mode==GT)) 1709 return files[i].fp; 1710 if (a == FFLUSH) 1711 return files[i].fp; 1712 } 1713 if (a == FFLUSH) /* didn't find it, so don't create it! */ 1714 return NULL; 1715 1716 for (i=0; i < FOPEN_MAX; i++) 1717 if (files[i].fp == 0) 1718 break; 1719 if (i >= FOPEN_MAX) 1720 FATAL("%s makes too many open files", s); 1721 fflush(stdout); /* force a semblance of order */ 1722 m = a; 1723 if (a == GT) { 1724 fp = fopen(s, "w"); 1725 } else if (a == APPEND) { 1726 fp = fopen(s, "a"); 1727 m = GT; /* so can mix > and >> */ 1728 } else if (a == '|') { /* output pipe */ 1729 fp = popen(s, "w"); 1730 } else if (a == LE) { /* input pipe */ 1731 fp = popen(s, "r"); 1732 } else if (a == LT) { /* getline <file */ 1733 fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */ 1734 } else /* can't happen */ 1735 FATAL("illegal redirection %d", a); 1736 if (fp != NULL) { 1737 files[i].fname = tostring(s); 1738 files[i].fp = fp; 1739 files[i].mode = m; 1740 } 1741 return fp; 1742 } 1743 1744 const char *filename(FILE *fp) 1745 { 1746 int i; 1747 1748 for (i = 0; i < FOPEN_MAX; i++) 1749 if (fp == files[i].fp) 1750 return files[i].fname; 1751 return "???"; 1752 } 1753 1754 Cell *closefile(Node **a, int n) 1755 { 1756 Cell *x; 1757 int i, stat; 1758 1759 n = n; 1760 x = execute(a[0]); 1761 getsval(x); 1762 stat = -1; 1763 for (i = 0; i < FOPEN_MAX; i++) { 1764 if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) { 1765 if (ferror(files[i].fp)) 1766 WARNING( "i/o error occurred on %s", files[i].fname ); 1767 if (files[i].mode == '|' || files[i].mode == LE) 1768 stat = pclose(files[i].fp); 1769 else 1770 stat = fclose(files[i].fp); 1771 if (stat == EOF) 1772 WARNING( "i/o error occurred closing %s", files[i].fname ); 1773 if (i > 2) /* don't do /dev/std... */ 1774 xfree(files[i].fname); 1775 files[i].fname = NULL; /* watch out for ref thru this */ 1776 files[i].fp = NULL; 1777 } 1778 } 1779 tempfree(x); 1780 x = gettemp(); 1781 setfval(x, (Awkfloat) stat); 1782 return(x); 1783 } 1784 1785 void closeall(void) 1786 { 1787 int i, stat; 1788 1789 for (i = 0; i < FOPEN_MAX; i++) { 1790 if (files[i].fp) { 1791 if (ferror(files[i].fp)) 1792 WARNING( "i/o error occurred on %s", files[i].fname ); 1793 if (files[i].mode == '|' || files[i].mode == LE) 1794 stat = pclose(files[i].fp); 1795 else 1796 stat = fclose(files[i].fp); 1797 if (stat == EOF) 1798 WARNING( "i/o error occurred while closing %s", files[i].fname ); 1799 } 1800 } 1801 } 1802 1803 void flush_all(void) 1804 { 1805 int i; 1806 1807 for (i = 0; i < FOPEN_MAX; i++) 1808 if (files[i].fp) 1809 fflush(files[i].fp); 1810 } 1811 1812 void backsub(char **pb_ptr, char **sptr_ptr); 1813 1814 Cell *sub(Node **a, int nnn) /* substitute command */ 1815 { 1816 char *sptr, *pb, *q; 1817 Cell *x, *y, *result; 1818 char *t, *buf; 1819 fa *pfa; 1820 int bufsz = recsize; 1821 1822 if ((buf = (char *) malloc(bufsz)) == NULL) 1823 FATAL("out of memory in sub"); 1824 x = execute(a[3]); /* target string */ 1825 t = getsval(x); 1826 if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ 1827 pfa = (fa *) a[1]; /* regular expression */ 1828 else { 1829 y = execute(a[1]); 1830 pfa = makedfa(getsval(y), 1); 1831 tempfree(y); 1832 } 1833 y = execute(a[2]); /* replacement string */ 1834 result = False; 1835 if (pmatch(pfa, t)) { 1836 sptr = t; 1837 adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub"); 1838 pb = buf; 1839 while (sptr < patbeg) 1840 *pb++ = *sptr++; 1841 sptr = getsval(y); 1842 while (*sptr != 0) { 1843 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub"); 1844 if (*sptr == '\\') { 1845 backsub(&pb, &sptr); 1846 } else if (*sptr == '&') { 1847 sptr++; 1848 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub"); 1849 for (q = patbeg; q < patbeg+patlen; ) 1850 *pb++ = *q++; 1851 } else 1852 *pb++ = *sptr++; 1853 } 1854 *pb = '\0'; 1855 if (pb > buf + bufsz) 1856 FATAL("sub result1 %.30s too big; can't happen", buf); 1857 sptr = patbeg + patlen; 1858 if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) { 1859 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub"); 1860 while ((*pb++ = *sptr++) != 0) 1861 ; 1862 } 1863 if (pb > buf + bufsz) 1864 FATAL("sub result2 %.30s too big; can't happen", buf); 1865 setsval(x, buf); /* BUG: should be able to avoid copy */ 1866 result = True; 1867 } 1868 tempfree(x); 1869 tempfree(y); 1870 free(buf); 1871 return result; 1872 } 1873 1874 Cell *gsub(Node **a, int nnn) /* global substitute */ 1875 { 1876 Cell *x, *y; 1877 char *rptr, *sptr, *t, *pb, *q; 1878 char *buf; 1879 fa *pfa; 1880 int mflag, tempstat, num; 1881 int bufsz = recsize; 1882 1883 if ((buf = (char *) malloc(bufsz)) == NULL) 1884 FATAL("out of memory in gsub"); 1885 mflag = 0; /* if mflag == 0, can replace empty string */ 1886 num = 0; 1887 x = execute(a[3]); /* target string */ 1888 t = getsval(x); 1889 if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ 1890 pfa = (fa *) a[1]; /* regular expression */ 1891 else { 1892 y = execute(a[1]); 1893 pfa = makedfa(getsval(y), 1); 1894 tempfree(y); 1895 } 1896 y = execute(a[2]); /* replacement string */ 1897 if (pmatch(pfa, t)) { 1898 tempstat = pfa->initstat; 1899 pfa->initstat = 2; 1900 pb = buf; 1901 rptr = getsval(y); 1902 do { 1903 if (patlen == 0 && *patbeg != 0) { /* matched empty string */ 1904 if (mflag == 0) { /* can replace empty */ 1905 num++; 1906 sptr = rptr; 1907 while (*sptr != 0) { 1908 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub"); 1909 if (*sptr == '\\') { 1910 backsub(&pb, &sptr); 1911 } else if (*sptr == '&') { 1912 sptr++; 1913 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub"); 1914 for (q = patbeg; q < patbeg+patlen; ) 1915 *pb++ = *q++; 1916 } else 1917 *pb++ = *sptr++; 1918 } 1919 } 1920 if (*t == 0) /* at end */ 1921 goto done; 1922 adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub"); 1923 *pb++ = *t++; 1924 if (pb > buf + bufsz) /* BUG: not sure of this test */ 1925 FATAL("gsub result0 %.30s too big; can't happen", buf); 1926 mflag = 0; 1927 } 1928 else { /* matched nonempty string */ 1929 num++; 1930 sptr = t; 1931 adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub"); 1932 while (sptr < patbeg) 1933 *pb++ = *sptr++; 1934 sptr = rptr; 1935 while (*sptr != 0) { 1936 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub"); 1937 if (*sptr == '\\') { 1938 backsub(&pb, &sptr); 1939 } else if (*sptr == '&') { 1940 sptr++; 1941 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub"); 1942 for (q = patbeg; q < patbeg+patlen; ) 1943 *pb++ = *q++; 1944 } else 1945 *pb++ = *sptr++; 1946 } 1947 t = patbeg + patlen; 1948 if (patlen == 0 || *t == 0 || *(t-1) == 0) 1949 goto done; 1950 if (pb > buf + bufsz) 1951 FATAL("gsub result1 %.30s too big; can't happen", buf); 1952 mflag = 1; 1953 } 1954 } while (pmatch(pfa,t)); 1955 sptr = t; 1956 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub"); 1957 while ((*pb++ = *sptr++) != 0) 1958 ; 1959 done: if (pb > buf + bufsz) 1960 FATAL("gsub result2 %.30s too big; can't happen", buf); 1961 *pb = '\0'; 1962 setsval(x, buf); /* BUG: should be able to avoid copy + free */ 1963 pfa->initstat = tempstat; 1964 } 1965 tempfree(x); 1966 tempfree(y); 1967 x = gettemp(); 1968 x->tval = NUM; 1969 x->fval = num; 1970 free(buf); 1971 return(x); 1972 } 1973 1974 void backsub(char **pb_ptr, char **sptr_ptr) /* handle \\& variations */ 1975 { /* sptr[0] == '\\' */ 1976 char *pb = *pb_ptr, *sptr = *sptr_ptr; 1977 1978 if (sptr[1] == '\\') { 1979 if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */ 1980 *pb++ = '\\'; 1981 *pb++ = '&'; 1982 sptr += 4; 1983 } else if (sptr[2] == '&') { /* \\& -> \ + matched */ 1984 *pb++ = '\\'; 1985 sptr += 2; 1986 } else { /* \\x -> \\x */ 1987 *pb++ = *sptr++; 1988 *pb++ = *sptr++; 1989 } 1990 } else if (sptr[1] == '&') { /* literal & */ 1991 sptr++; 1992 *pb++ = *sptr++; 1993 } else /* literal \ */ 1994 *pb++ = *sptr++; 1995 1996 *pb_ptr = pb; 1997 *sptr_ptr = sptr; 1998 } 1999