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