1 /* $OpenBSD: run.c,v 1.32 2011/04/20 22:28:39 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 *awkgetline(Node **a, int n) /* get next line from specific input */ 395 { /* a[0] is variable, a[1] is operator, a[2] is filename */ 396 Cell *r, *x; 397 extern Cell **fldtab; 398 FILE *fp; 399 char *buf; 400 int bufsize = recsize; 401 int mode; 402 403 if ((buf = (char *) malloc(bufsize)) == NULL) 404 FATAL("out of memory in getline"); 405 406 fflush(stdout); /* in case someone is waiting for a prompt */ 407 r = gettemp(); 408 if (a[1] != NULL) { /* getline < file */ 409 x = execute(a[2]); /* filename */ 410 mode = ptoi(a[1]); 411 if (mode == '|') /* input pipe */ 412 mode = LE; /* arbitrary flag */ 413 fp = openfile(mode, getsval(x)); 414 tempfree(x); 415 if (fp == NULL) 416 n = -1; 417 else 418 n = readrec(&buf, &bufsize, fp); 419 if (n <= 0) { 420 ; 421 } else if (a[0] != NULL) { /* getline var <file */ 422 x = execute(a[0]); 423 setsval(x, buf); 424 tempfree(x); 425 } else { /* getline <file */ 426 setsval(fldtab[0], buf); 427 if (is_number(fldtab[0]->sval)) { 428 fldtab[0]->fval = atof(fldtab[0]->sval); 429 fldtab[0]->tval |= NUM; 430 } 431 } 432 } else { /* bare getline; use current input */ 433 if (a[0] == NULL) /* getline */ 434 n = getrec(&record, &recsize, 1); 435 else { /* getline var */ 436 n = getrec(&buf, &bufsize, 0); 437 x = execute(a[0]); 438 setsval(x, buf); 439 tempfree(x); 440 } 441 } 442 setfval(r, (Awkfloat) n); 443 free(buf); 444 return r; 445 } 446 447 Cell *getnf(Node **a, int n) /* get NF */ 448 { 449 if (donefld == 0) 450 fldbld(); 451 return (Cell *) a[0]; 452 } 453 454 Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ 455 { 456 Cell *x, *y, *z; 457 char *s; 458 Node *np; 459 char *buf; 460 int bufsz = recsize; 461 int nsub = strlen(*SUBSEP); 462 463 if ((buf = (char *) malloc(bufsz)) == NULL) 464 FATAL("out of memory in array"); 465 466 x = execute(a[0]); /* Cell* for symbol table */ 467 buf[0] = 0; 468 for (np = a[1]; np; np = np->nnext) { 469 y = execute(np); /* subscript */ 470 s = getsval(y); 471 if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "array")) 472 FATAL("out of memory for %s[%s...]", x->nval, buf); 473 strlcat(buf, s, bufsz); 474 if (np->nnext) 475 strlcat(buf, *SUBSEP, bufsz); 476 tempfree(y); 477 } 478 if (!isarr(x)) { 479 dprintf( ("making %s into an array\n", NN(x->nval)) ); 480 if (freeable(x)) 481 xfree(x->sval); 482 x->tval &= ~(STR|NUM|DONTFREE); 483 x->tval |= ARR; 484 x->sval = (char *) makesymtab(NSYMTAB); 485 } 486 z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval); 487 z->ctype = OCELL; 488 z->csub = CVAR; 489 tempfree(x); 490 free(buf); 491 return(z); 492 } 493 494 Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ 495 { 496 Cell *x, *y; 497 Node *np; 498 char *s; 499 int nsub = strlen(*SUBSEP); 500 501 x = execute(a[0]); /* Cell* for symbol table */ 502 if (!isarr(x)) 503 return True; 504 if (a[1] == 0) { /* delete the elements, not the table */ 505 freesymtab(x); 506 x->tval &= ~STR; 507 x->tval |= ARR; 508 x->sval = (char *) makesymtab(NSYMTAB); 509 } else { 510 int bufsz = recsize; 511 char *buf; 512 if ((buf = (char *) malloc(bufsz)) == NULL) 513 FATAL("out of memory in adelete"); 514 buf[0] = 0; 515 for (np = a[1]; np; np = np->nnext) { 516 y = execute(np); /* subscript */ 517 s = getsval(y); 518 if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "awkdelete")) 519 FATAL("out of memory deleting %s[%s...]", x->nval, buf); 520 strlcat(buf, s, bufsz); 521 if (np->nnext) 522 strlcat(buf, *SUBSEP, bufsz); 523 tempfree(y); 524 } 525 freeelem(x, buf); 526 free(buf); 527 } 528 tempfree(x); 529 return True; 530 } 531 532 Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */ 533 { 534 Cell *x, *ap, *k; 535 Node *p; 536 char *buf; 537 char *s; 538 int bufsz = recsize; 539 int nsub = strlen(*SUBSEP); 540 541 ap = execute(a[1]); /* array name */ 542 if (!isarr(ap)) { 543 dprintf( ("making %s into an array\n", ap->nval) ); 544 if (freeable(ap)) 545 xfree(ap->sval); 546 ap->tval &= ~(STR|NUM|DONTFREE); 547 ap->tval |= ARR; 548 ap->sval = (char *) makesymtab(NSYMTAB); 549 } 550 if ((buf = (char *) malloc(bufsz)) == NULL) { 551 FATAL("out of memory in intest"); 552 } 553 buf[0] = 0; 554 for (p = a[0]; p; p = p->nnext) { 555 x = execute(p); /* expr */ 556 s = getsval(x); 557 if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "intest")) 558 FATAL("out of memory deleting %s[%s...]", x->nval, buf); 559 strlcat(buf, s, bufsz); 560 tempfree(x); 561 if (p->nnext) 562 strlcat(buf, *SUBSEP, bufsz); 563 } 564 k = lookup(buf, (Array *) ap->sval); 565 tempfree(ap); 566 free(buf); 567 if (k == NULL) 568 return(False); 569 else 570 return(True); 571 } 572 573 574 Cell *matchop(Node **a, int n) /* ~ and match() */ 575 { 576 Cell *x, *y; 577 char *s, *t; 578 int i; 579 fa *pfa; 580 int (*mf)(fa *, const char *) = match, mode = 0; 581 582 if (n == MATCHFCN) { 583 mf = pmatch; 584 mode = 1; 585 } 586 x = execute(a[1]); /* a[1] = target text */ 587 s = getsval(x); 588 if (a[0] == 0) /* a[1] == 0: already-compiled reg expr */ 589 i = (*mf)((fa *) a[2], s); 590 else { 591 y = execute(a[2]); /* a[2] = regular expr */ 592 t = getsval(y); 593 pfa = makedfa(t, mode); 594 i = (*mf)(pfa, s); 595 tempfree(y); 596 } 597 tempfree(x); 598 if (n == MATCHFCN) { 599 int start = patbeg - s + 1; 600 if (patlen < 0) 601 start = 0; 602 setfval(rstartloc, (Awkfloat) start); 603 setfval(rlengthloc, (Awkfloat) patlen); 604 x = gettemp(); 605 x->tval = NUM; 606 x->fval = start; 607 return x; 608 } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0)) 609 return(True); 610 else 611 return(False); 612 } 613 614 615 Cell *boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */ 616 { 617 Cell *x, *y; 618 int i; 619 620 x = execute(a[0]); 621 i = istrue(x); 622 tempfree(x); 623 switch (n) { 624 case BOR: 625 if (i) return(True); 626 y = execute(a[1]); 627 i = istrue(y); 628 tempfree(y); 629 if (i) return(True); 630 else return(False); 631 case AND: 632 if ( !i ) return(False); 633 y = execute(a[1]); 634 i = istrue(y); 635 tempfree(y); 636 if (i) return(True); 637 else return(False); 638 case NOT: 639 if (i) return(False); 640 else return(True); 641 default: /* can't happen */ 642 FATAL("unknown boolean operator %d", n); 643 } 644 return 0; /*NOTREACHED*/ 645 } 646 647 Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */ 648 { 649 int i; 650 Cell *x, *y; 651 Awkfloat j; 652 653 x = execute(a[0]); 654 y = execute(a[1]); 655 if (x->tval&NUM && y->tval&NUM) { 656 j = x->fval - y->fval; 657 i = j<0? -1: (j>0? 1: 0); 658 } else { 659 i = strcmp(getsval(x), getsval(y)); 660 } 661 tempfree(x); 662 tempfree(y); 663 switch (n) { 664 case LT: if (i<0) return(True); 665 else return(False); 666 case LE: if (i<=0) return(True); 667 else return(False); 668 case NE: if (i!=0) return(True); 669 else return(False); 670 case EQ: if (i == 0) return(True); 671 else return(False); 672 case GE: if (i>=0) return(True); 673 else return(False); 674 case GT: if (i>0) return(True); 675 else return(False); 676 default: /* can't happen */ 677 FATAL("unknown relational operator %d", n); 678 } 679 return 0; /*NOTREACHED*/ 680 } 681 682 void tfree(Cell *a) /* free a tempcell */ 683 { 684 if (freeable(a)) { 685 dprintf( ("freeing %s %s %o\n", NN(a->nval), NN(a->sval), a->tval) ); 686 xfree(a->sval); 687 } 688 if (a == tmps) 689 FATAL("tempcell list is curdled"); 690 a->cnext = tmps; 691 tmps = a; 692 } 693 694 Cell *gettemp(void) /* get a tempcell */ 695 { int i; 696 Cell *x; 697 698 if (!tmps) { 699 tmps = (Cell *) calloc(100, sizeof(Cell)); 700 if (!tmps) 701 FATAL("out of space for temporaries"); 702 for(i = 1; i < 100; i++) 703 tmps[i-1].cnext = &tmps[i]; 704 tmps[i-1].cnext = 0; 705 } 706 x = tmps; 707 tmps = x->cnext; 708 *x = tempcell; 709 return(x); 710 } 711 712 Cell *indirect(Node **a, int n) /* $( a[0] ) */ 713 { 714 Awkfloat val; 715 Cell *x; 716 int m; 717 char *s; 718 719 x = execute(a[0]); 720 val = getfval(x); /* freebsd: defend against super large field numbers */ 721 if ((Awkfloat)INT_MAX < val) 722 FATAL("trying to access out of range field %s", x->nval); 723 m = (int) val; 724 if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */ 725 FATAL("illegal field $(%s), name \"%s\"", s, x->nval); 726 /* BUG: can x->nval ever be null??? */ 727 tempfree(x); 728 x = fieldadr(m); 729 x->ctype = OCELL; /* BUG? why are these needed? */ 730 x->csub = CFLD; 731 return(x); 732 } 733 734 Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */ 735 { 736 int k, m, n; 737 char *s; 738 int temp; 739 Cell *x, *y, *z = 0; 740 741 x = execute(a[0]); 742 y = execute(a[1]); 743 if (a[2] != 0) 744 z = execute(a[2]); 745 s = getsval(x); 746 k = strlen(s) + 1; 747 if (k <= 1) { 748 tempfree(x); 749 tempfree(y); 750 if (a[2] != 0) { 751 tempfree(z); 752 } 753 x = gettemp(); 754 setsval(x, ""); 755 return(x); 756 } 757 m = (int) getfval(y); 758 if (m <= 0) 759 m = 1; 760 else if (m > k) 761 m = k; 762 tempfree(y); 763 if (a[2] != 0) { 764 n = (int) getfval(z); 765 tempfree(z); 766 } else 767 n = k - 1; 768 if (n < 0) 769 n = 0; 770 else if (n > k - m) 771 n = k - m; 772 dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) ); 773 y = gettemp(); 774 temp = s[n+m-1]; /* with thanks to John Linderman */ 775 s[n+m-1] = '\0'; 776 setsval(y, s + m - 1); 777 s[n+m-1] = temp; 778 tempfree(x); 779 return(y); 780 } 781 782 Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */ 783 { 784 Cell *x, *y, *z; 785 char *s1, *s2, *p1, *p2, *q; 786 Awkfloat v = 0.0; 787 788 x = execute(a[0]); 789 s1 = getsval(x); 790 y = execute(a[1]); 791 s2 = getsval(y); 792 793 z = gettemp(); 794 for (p1 = s1; *p1 != '\0'; p1++) { 795 for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++) 796 ; 797 if (*p2 == '\0') { 798 v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */ 799 break; 800 } 801 } 802 tempfree(x); 803 tempfree(y); 804 setfval(z, v); 805 return(z); 806 } 807 808 #define MAXNUMSIZE 50 809 810 int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like conversions */ 811 { 812 char *fmt; 813 char *p, *t; 814 const char *os; 815 Cell *x; 816 int flag = 0, n; 817 int fmtwd; /* format width */ 818 int fmtsz = recsize; 819 char *buf = *pbuf; 820 int bufsize = *pbufsize; 821 822 os = s; 823 p = buf; 824 if ((fmt = (char *) malloc(fmtsz)) == NULL) 825 FATAL("out of memory in format()"); 826 while (*s) { 827 adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format1"); 828 if (*s != '%') { 829 *p++ = *s++; 830 continue; 831 } 832 if (*(s+1) == '%') { 833 *p++ = '%'; 834 s += 2; 835 continue; 836 } 837 /* have to be real careful in case this is a huge number, eg, %100000d */ 838 fmtwd = atoi(s+1); 839 if (fmtwd < 0) 840 fmtwd = -fmtwd; 841 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format2"); 842 for (t = fmt; (*t++ = *s) != '\0'; s++) { 843 if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3")) 844 FATAL("format item %.30s... ran format() out of memory", os); 845 if (isalpha((uschar)*s) && *s != 'l' && *s != 'h' && *s != 'L') 846 break; /* the ansi panoply */ 847 if (*s == '*') { 848 if (a == NULL) 849 FATAL("not enough args in printf(%s)", os); 850 x = execute(a); 851 a = a->nnext; 852 snprintf(t-1, fmt + fmtsz - (t-1), "%d", fmtwd=(int) getfval(x)); 853 if (fmtwd < 0) 854 fmtwd = -fmtwd; 855 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format"); 856 t = fmt + strlen(fmt); 857 tempfree(x); 858 } 859 } 860 *t = '\0'; 861 if (fmtwd < 0) 862 fmtwd = -fmtwd; 863 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format4"); 864 865 switch (*s) { 866 case 'f': case 'e': case 'g': case 'E': case 'G': 867 flag = 'f'; 868 break; 869 case 'd': case 'i': 870 flag = 'd'; 871 if(*(s-1) == 'l') break; 872 *(t-1) = 'l'; 873 *t = 'd'; 874 *++t = '\0'; 875 break; 876 case 'o': case 'x': case 'X': case 'u': 877 flag = *(s-1) == 'l' ? 'd' : 'u'; 878 break; 879 case 's': 880 flag = 's'; 881 break; 882 case 'c': 883 flag = 'c'; 884 break; 885 default: 886 WARNING("weird printf conversion %s", fmt); 887 flag = '?'; 888 break; 889 } 890 if (a == NULL) 891 FATAL("not enough args in printf(%s)", os); 892 x = execute(a); 893 a = a->nnext; 894 n = MAXNUMSIZE; 895 if (fmtwd > n) 896 n = fmtwd; 897 adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format5"); 898 switch (flag) { 899 case '?': /* unknown, so dump it too */ 900 snprintf(p, buf + bufsize - p, "%s", fmt); 901 t = getsval(x); 902 n = strlen(t); 903 if (fmtwd > n) 904 n = fmtwd; 905 adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format6"); 906 p += strlen(p); 907 snprintf(p, buf + bufsize - p, "%s", t); 908 break; 909 case 'f': snprintf(p, buf + bufsize - p, fmt, getfval(x)); break; 910 case 'd': snprintf(p, buf + bufsize - p, fmt, (long) getfval(x)); break; 911 case 'u': snprintf(p, buf + bufsize - p, fmt, (int) getfval(x)); break; 912 case 's': 913 t = getsval(x); 914 n = strlen(t); 915 if (fmtwd > n) 916 n = fmtwd; 917 if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format7")) 918 FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t); 919 snprintf(p, buf + bufsize - p, fmt, t); 920 break; 921 case 'c': 922 if (isnum(x)) { 923 if (getfval(x)) 924 snprintf(p, buf + bufsize - p, fmt, (int) getfval(x)); 925 else { 926 *p++ = '\0'; /* explicit null byte */ 927 *p = '\0'; /* next output will start here */ 928 } 929 } else 930 snprintf(p, buf + bufsize - p, fmt, getsval(x)[0]); 931 break; 932 default: 933 FATAL("can't happen: bad conversion %c in format()", flag); 934 } 935 tempfree(x); 936 p += strlen(p); 937 s++; 938 } 939 *p = '\0'; 940 free(fmt); 941 for ( ; a; a = a->nnext) /* evaluate any remaining args */ 942 execute(a); 943 *pbuf = buf; 944 *pbufsize = bufsize; 945 return p - buf; 946 } 947 948 Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */ 949 { 950 Cell *x; 951 Node *y; 952 char *buf; 953 int bufsz=3*recsize; 954 955 if ((buf = (char *) malloc(bufsz)) == NULL) 956 FATAL("out of memory in awksprintf"); 957 y = a[0]->nnext; 958 x = execute(a[0]); 959 if (format(&buf, &bufsz, getsval(x), y) == -1) 960 FATAL("sprintf string %.30s... too long. can't happen.", buf); 961 tempfree(x); 962 x = gettemp(); 963 x->sval = buf; 964 x->tval = STR; 965 return(x); 966 } 967 968 Cell *awkprintf(Node **a, int n) /* printf */ 969 { /* a[0] is list of args, starting with format string */ 970 /* a[1] is redirection operator, a[2] is redirection file */ 971 FILE *fp; 972 Cell *x; 973 Node *y; 974 char *buf; 975 int len; 976 int bufsz=3*recsize; 977 978 if ((buf = (char *) malloc(bufsz)) == NULL) 979 FATAL("out of memory in awkprintf"); 980 y = a[0]->nnext; 981 x = execute(a[0]); 982 if ((len = format(&buf, &bufsz, getsval(x), y)) == -1) 983 FATAL("printf string %.30s... too long. can't happen.", buf); 984 tempfree(x); 985 if (a[1] == NULL) { 986 /* fputs(buf, stdout); */ 987 fwrite(buf, len, 1, stdout); 988 if (ferror(stdout)) 989 FATAL("write error on stdout"); 990 } else { 991 fp = redirect(ptoi(a[1]), a[2]); 992 /* fputs(buf, fp); */ 993 fwrite(buf, len, 1, fp); 994 fflush(fp); 995 if (ferror(fp)) 996 FATAL("write error on %s", filename(fp)); 997 } 998 free(buf); 999 return(True); 1000 } 1001 1002 Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */ 1003 { 1004 Awkfloat i, j = 0; 1005 double v; 1006 Cell *x, *y, *z; 1007 1008 x = execute(a[0]); 1009 i = getfval(x); 1010 tempfree(x); 1011 if (n != UMINUS) { 1012 y = execute(a[1]); 1013 j = getfval(y); 1014 tempfree(y); 1015 } 1016 z = gettemp(); 1017 switch (n) { 1018 case ADD: 1019 i += j; 1020 break; 1021 case MINUS: 1022 i -= j; 1023 break; 1024 case MULT: 1025 i *= j; 1026 break; 1027 case DIVIDE: 1028 if (j == 0) 1029 FATAL("division by zero"); 1030 i /= j; 1031 break; 1032 case MOD: 1033 if (j == 0) 1034 FATAL("division by zero in mod"); 1035 modf(i/j, &v); 1036 i = i - j * v; 1037 break; 1038 case UMINUS: 1039 i = -i; 1040 break; 1041 case POWER: 1042 if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */ 1043 i = ipow(i, (int) j); 1044 else 1045 i = errcheck(pow(i, j), "pow"); 1046 break; 1047 default: /* can't happen */ 1048 FATAL("illegal arithmetic operator %d", n); 1049 } 1050 setfval(z, i); 1051 return(z); 1052 } 1053 1054 double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */ 1055 { 1056 double v; 1057 1058 if (n <= 0) 1059 return 1; 1060 v = ipow(x, n/2); 1061 if (n % 2 == 0) 1062 return v * v; 1063 else 1064 return x * v * v; 1065 } 1066 1067 Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */ 1068 { 1069 Cell *x, *z; 1070 int k; 1071 Awkfloat xf; 1072 1073 x = execute(a[0]); 1074 xf = getfval(x); 1075 k = (n == PREINCR || n == POSTINCR) ? 1 : -1; 1076 if (n == PREINCR || n == PREDECR) { 1077 setfval(x, xf + k); 1078 return(x); 1079 } 1080 z = gettemp(); 1081 setfval(z, xf); 1082 setfval(x, xf + k); 1083 tempfree(x); 1084 return(z); 1085 } 1086 1087 Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */ 1088 { /* this is subtle; don't muck with it. */ 1089 Cell *x, *y; 1090 Awkfloat xf, yf; 1091 double v; 1092 1093 y = execute(a[1]); 1094 x = execute(a[0]); 1095 if (n == ASSIGN) { /* ordinary assignment */ 1096 if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: */ 1097 ; /* leave alone unless it's a field */ 1098 else if ((y->tval & (STR|NUM)) == (STR|NUM)) { 1099 setsval(x, getsval(y)); 1100 x->fval = getfval(y); 1101 x->tval |= NUM; 1102 } 1103 else if (isstr(y)) 1104 setsval(x, getsval(y)); 1105 else if (isnum(y)) 1106 setfval(x, getfval(y)); 1107 else 1108 funnyvar(y, "read value of"); 1109 tempfree(y); 1110 return(x); 1111 } 1112 xf = getfval(x); 1113 yf = getfval(y); 1114 switch (n) { 1115 case ADDEQ: 1116 xf += yf; 1117 break; 1118 case SUBEQ: 1119 xf -= yf; 1120 break; 1121 case MULTEQ: 1122 xf *= yf; 1123 break; 1124 case DIVEQ: 1125 if (yf == 0) 1126 FATAL("division by zero in /="); 1127 xf /= yf; 1128 break; 1129 case MODEQ: 1130 if (yf == 0) 1131 FATAL("division by zero in %%="); 1132 modf(xf/yf, &v); 1133 xf = xf - yf * v; 1134 break; 1135 case POWEQ: 1136 if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */ 1137 xf = ipow(xf, (int) yf); 1138 else 1139 xf = errcheck(pow(xf, yf), "pow"); 1140 break; 1141 default: 1142 FATAL("illegal assignment operator %d", n); 1143 break; 1144 } 1145 tempfree(y); 1146 setfval(x, xf); 1147 return(x); 1148 } 1149 1150 Cell *cat(Node **a, int q) /* a[0] cat a[1] */ 1151 { 1152 Cell *x, *y, *z; 1153 int n1, n2; 1154 char *s; 1155 size_t len; 1156 1157 x = execute(a[0]); 1158 y = execute(a[1]); 1159 getsval(x); 1160 getsval(y); 1161 n1 = strlen(x->sval); 1162 n2 = strlen(y->sval); 1163 len = n1 + n2 + 1; 1164 s = (char *) malloc(len); 1165 if (s == NULL) 1166 FATAL("out of space concatenating %.15s... and %.15s...", 1167 x->sval, y->sval); 1168 strlcpy(s, x->sval, len); 1169 strlcpy(s+n1, y->sval, len - n1); 1170 tempfree(x); 1171 tempfree(y); 1172 z = gettemp(); 1173 z->sval = s; 1174 z->tval = STR; 1175 return(z); 1176 } 1177 1178 Cell *pastat(Node **a, int n) /* a[0] { a[1] } */ 1179 { 1180 Cell *x; 1181 1182 if (a[0] == 0) 1183 x = execute(a[1]); 1184 else { 1185 x = execute(a[0]); 1186 if (istrue(x)) { 1187 tempfree(x); 1188 x = execute(a[1]); 1189 } 1190 } 1191 return x; 1192 } 1193 1194 Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */ 1195 { 1196 Cell *x; 1197 int pair; 1198 1199 pair = ptoi(a[3]); 1200 if (pairstack[pair] == 0) { 1201 x = execute(a[0]); 1202 if (istrue(x)) 1203 pairstack[pair] = 1; 1204 tempfree(x); 1205 } 1206 if (pairstack[pair] == 1) { 1207 x = execute(a[1]); 1208 if (istrue(x)) 1209 pairstack[pair] = 0; 1210 tempfree(x); 1211 x = execute(a[2]); 1212 return(x); 1213 } 1214 return(False); 1215 } 1216 1217 Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ 1218 { 1219 Cell *x = 0, *y, *ap; 1220 char *s; 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 static Awkfloat old_seed = 1; 1481 1482 t = ptoi(a[0]); 1483 x = execute(a[1]); 1484 nextarg = a[1]->nnext; 1485 switch (t) { 1486 case FLENGTH: 1487 if (isarr(x)) 1488 u = ((Array *) x->sval)->nelem; /* GROT. should be function*/ 1489 else 1490 u = strlen(getsval(x)); 1491 break; 1492 case FLOG: 1493 u = errcheck(log(getfval(x)), "log"); break; 1494 case FINT: 1495 modf(getfval(x), &u); break; 1496 case FEXP: 1497 u = errcheck(exp(getfval(x)), "exp"); break; 1498 case FSQRT: 1499 u = errcheck(sqrt(getfval(x)), "sqrt"); break; 1500 case FSIN: 1501 u = sin(getfval(x)); break; 1502 case FCOS: 1503 u = cos(getfval(x)); break; 1504 case FATAN: 1505 if (nextarg == 0) { 1506 WARNING("atan2 requires two arguments; returning 1.0"); 1507 u = 1.0; 1508 } else { 1509 y = execute(a[1]->nnext); 1510 u = atan2(getfval(x), getfval(y)); 1511 tempfree(y); 1512 nextarg = nextarg->nnext; 1513 } 1514 break; 1515 case FCOMPL: 1516 u = ~((int)getfval(x)); 1517 break; 1518 case FAND: 1519 if (nextarg == 0) { 1520 WARNING("and requires two arguments; returning 0"); 1521 u = 0; 1522 break; 1523 } 1524 y = execute(a[1]->nnext); 1525 u = ((int)getfval(x)) & ((int)getfval(y)); 1526 tempfree(y); 1527 nextarg = nextarg->nnext; 1528 break; 1529 case FFOR: 1530 if (nextarg == 0) { 1531 WARNING("or requires two arguments; returning 0"); 1532 u = 0; 1533 break; 1534 } 1535 y = execute(a[1]->nnext); 1536 u = ((int)getfval(x)) | ((int)getfval(y)); 1537 tempfree(y); 1538 nextarg = nextarg->nnext; 1539 break; 1540 case FXOR: 1541 if (nextarg == 0) { 1542 WARNING("or requires two arguments; returning 0"); 1543 u = 0; 1544 break; 1545 } 1546 y = execute(a[1]->nnext); 1547 u = ((int)getfval(x)) ^ ((int)getfval(y)); 1548 tempfree(y); 1549 nextarg = nextarg->nnext; 1550 break; 1551 case FLSHIFT: 1552 if (nextarg == 0) { 1553 WARNING("or requires two arguments; returning 0"); 1554 u = 0; 1555 break; 1556 } 1557 y = execute(a[1]->nnext); 1558 u = ((int)getfval(x)) << ((int)getfval(y)); 1559 tempfree(y); 1560 nextarg = nextarg->nnext; 1561 break; 1562 case FRSHIFT: 1563 if (nextarg == 0) { 1564 WARNING("or requires two arguments; returning 0"); 1565 u = 0; 1566 break; 1567 } 1568 y = execute(a[1]->nnext); 1569 u = ((int)getfval(x)) >> ((int)getfval(y)); 1570 tempfree(y); 1571 nextarg = nextarg->nnext; 1572 break; 1573 case FSYSTEM: 1574 fflush(stdout); /* in case something is buffered already */ 1575 u = (Awkfloat) system(getsval(x)) / 256; /* 256 is unix-dep */ 1576 break; 1577 case FRAND: 1578 if (use_arc4) 1579 u = (Awkfloat)arc4random() / 0xffffffff; 1580 else 1581 u = (Awkfloat) (random() % RAND_MAX) / RAND_MAX; 1582 break; 1583 case FSRAND: 1584 u = old_seed; 1585 if (isrec(x)) /* no argument provided, want arc4random() */ 1586 use_arc4 = 1; 1587 else { 1588 old_seed = getfval(x); 1589 srandom((unsigned int) old_seed); 1590 use_arc4 = 0; 1591 } 1592 break; 1593 case FTOUPPER: 1594 case FTOLOWER: 1595 buf = tostring(getsval(x)); 1596 if (t == FTOUPPER) { 1597 for (p = buf; *p; p++) 1598 if (islower((uschar) *p)) 1599 *p = toupper((uschar)*p); 1600 } else { 1601 for (p = buf; *p; p++) 1602 if (isupper((uschar) *p)) 1603 *p = tolower((uschar)*p); 1604 } 1605 tempfree(x); 1606 x = gettemp(); 1607 setsval(x, buf); 1608 free(buf); 1609 return x; 1610 case FFLUSH: 1611 if (isrec(x) || strlen(getsval(x)) == 0) { 1612 flush_all(); /* fflush() or fflush("") -> all */ 1613 u = 0; 1614 } else if ((fp = openfile(FFLUSH, getsval(x))) == NULL) 1615 u = EOF; 1616 else 1617 u = fflush(fp); 1618 break; 1619 default: /* can't happen */ 1620 FATAL("illegal function type %d", t); 1621 break; 1622 } 1623 tempfree(x); 1624 x = gettemp(); 1625 setfval(x, u); 1626 if (nextarg != 0) { 1627 WARNING("warning: function has too many arguments"); 1628 for ( ; nextarg; nextarg = nextarg->nnext) 1629 execute(nextarg); 1630 } 1631 return(x); 1632 } 1633 1634 Cell *printstat(Node **a, int n) /* print a[0] */ 1635 { 1636 Node *x; 1637 Cell *y; 1638 FILE *fp; 1639 1640 if (a[1] == 0) /* a[1] is redirection operator, a[2] is file */ 1641 fp = stdout; 1642 else 1643 fp = redirect(ptoi(a[1]), a[2]); 1644 for (x = a[0]; x != NULL; x = x->nnext) { 1645 y = execute(x); 1646 fputs(getpssval(y), fp); 1647 tempfree(y); 1648 if (x->nnext == NULL) 1649 fputs(*ORS, fp); 1650 else 1651 fputs(*OFS, fp); 1652 } 1653 if (a[1] != 0) 1654 fflush(fp); 1655 if (ferror(fp)) 1656 FATAL("write error on %s", filename(fp)); 1657 return(True); 1658 } 1659 1660 Cell *nullproc(Node **a, int n) 1661 { 1662 n = n; 1663 a = a; 1664 return 0; 1665 } 1666 1667 1668 FILE *redirect(int a, Node *b) /* set up all i/o redirections */ 1669 { 1670 FILE *fp; 1671 Cell *x; 1672 char *fname; 1673 1674 x = execute(b); 1675 fname = getsval(x); 1676 fp = openfile(a, fname); 1677 if (fp == NULL) 1678 FATAL("can't open file %s", fname); 1679 tempfree(x); 1680 return fp; 1681 } 1682 1683 struct files { 1684 FILE *fp; 1685 const char *fname; 1686 int mode; /* '|', 'a', 'w' => LE/LT, GT */ 1687 } files[FOPEN_MAX] ={ 1688 { NULL, "/dev/stdin", LT }, /* watch out: don't free this! */ 1689 { NULL, "/dev/stdout", GT }, 1690 { NULL, "/dev/stderr", GT } 1691 }; 1692 1693 void stdinit(void) /* in case stdin, etc., are not constants */ 1694 { 1695 files[0].fp = stdin; 1696 files[1].fp = stdout; 1697 files[2].fp = stderr; 1698 } 1699 1700 FILE *openfile(int a, const char *us) 1701 { 1702 const char *s = us; 1703 int i, m; 1704 FILE *fp = 0; 1705 1706 if (*s == '\0') 1707 FATAL("null file name in print or getline"); 1708 for (i=0; i < FOPEN_MAX; i++) 1709 if (files[i].fname && strcmp(s, files[i].fname) == 0) { 1710 if (a == files[i].mode || (a==APPEND && files[i].mode==GT)) 1711 return files[i].fp; 1712 if (a == FFLUSH) 1713 return files[i].fp; 1714 } 1715 if (a == FFLUSH) /* didn't find it, so don't create it! */ 1716 return NULL; 1717 1718 for (i=0; i < FOPEN_MAX; i++) 1719 if (files[i].fp == 0) 1720 break; 1721 if (i >= FOPEN_MAX) 1722 FATAL("%s makes too many open files", s); 1723 fflush(stdout); /* force a semblance of order */ 1724 m = a; 1725 if (a == GT) { 1726 fp = fopen(s, "w"); 1727 } else if (a == APPEND) { 1728 fp = fopen(s, "a"); 1729 m = GT; /* so can mix > and >> */ 1730 } else if (a == '|') { /* output pipe */ 1731 fp = popen(s, "w"); 1732 } else if (a == LE) { /* input pipe */ 1733 fp = popen(s, "r"); 1734 } else if (a == LT) { /* getline <file */ 1735 fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */ 1736 } else /* can't happen */ 1737 FATAL("illegal redirection %d", a); 1738 if (fp != NULL) { 1739 files[i].fname = tostring(s); 1740 files[i].fp = fp; 1741 files[i].mode = m; 1742 } 1743 return fp; 1744 } 1745 1746 const char *filename(FILE *fp) 1747 { 1748 int i; 1749 1750 for (i = 0; i < FOPEN_MAX; i++) 1751 if (fp == files[i].fp) 1752 return files[i].fname; 1753 return "???"; 1754 } 1755 1756 Cell *closefile(Node **a, int n) 1757 { 1758 Cell *x; 1759 int i, stat; 1760 1761 n = n; 1762 x = execute(a[0]); 1763 getsval(x); 1764 stat = -1; 1765 for (i = 0; i < FOPEN_MAX; i++) { 1766 if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) { 1767 if (ferror(files[i].fp)) 1768 WARNING( "i/o error occurred on %s", files[i].fname ); 1769 if (files[i].mode == '|' || files[i].mode == LE) 1770 stat = pclose(files[i].fp); 1771 else 1772 stat = fclose(files[i].fp); 1773 if (stat == EOF) 1774 WARNING( "i/o error occurred closing %s", files[i].fname ); 1775 if (i > 2) /* don't do /dev/std... */ 1776 xfree(files[i].fname); 1777 files[i].fname = NULL; /* watch out for ref thru this */ 1778 files[i].fp = NULL; 1779 } 1780 } 1781 tempfree(x); 1782 x = gettemp(); 1783 setfval(x, (Awkfloat) stat); 1784 return(x); 1785 } 1786 1787 void closeall(void) 1788 { 1789 int i, stat; 1790 1791 for (i = 0; i < FOPEN_MAX; i++) { 1792 if (files[i].fp) { 1793 if (ferror(files[i].fp)) 1794 WARNING( "i/o error occurred on %s", files[i].fname ); 1795 if (files[i].mode == '|' || files[i].mode == LE) 1796 stat = pclose(files[i].fp); 1797 else 1798 stat = fclose(files[i].fp); 1799 if (stat == EOF) 1800 WARNING( "i/o error occurred while closing %s", files[i].fname ); 1801 } 1802 } 1803 } 1804 1805 void flush_all(void) 1806 { 1807 int i; 1808 1809 for (i = 0; i < FOPEN_MAX; i++) 1810 if (files[i].fp) 1811 fflush(files[i].fp); 1812 } 1813 1814 void backsub(char **pb_ptr, char **sptr_ptr); 1815 1816 Cell *sub(Node **a, int nnn) /* substitute command */ 1817 { 1818 char *sptr, *pb, *q; 1819 Cell *x, *y, *result; 1820 char *t, *buf; 1821 fa *pfa; 1822 int bufsz = recsize; 1823 1824 if ((buf = (char *) malloc(bufsz)) == NULL) 1825 FATAL("out of memory in sub"); 1826 x = execute(a[3]); /* target string */ 1827 t = getsval(x); 1828 if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ 1829 pfa = (fa *) a[1]; /* regular expression */ 1830 else { 1831 y = execute(a[1]); 1832 pfa = makedfa(getsval(y), 1); 1833 tempfree(y); 1834 } 1835 y = execute(a[2]); /* replacement string */ 1836 result = False; 1837 if (pmatch(pfa, t)) { 1838 sptr = t; 1839 adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub"); 1840 pb = buf; 1841 while (sptr < patbeg) 1842 *pb++ = *sptr++; 1843 sptr = getsval(y); 1844 while (*sptr != 0) { 1845 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub"); 1846 if (*sptr == '\\') { 1847 backsub(&pb, &sptr); 1848 } else if (*sptr == '&') { 1849 sptr++; 1850 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub"); 1851 for (q = patbeg; q < patbeg+patlen; ) 1852 *pb++ = *q++; 1853 } else 1854 *pb++ = *sptr++; 1855 } 1856 *pb = '\0'; 1857 if (pb > buf + bufsz) 1858 FATAL("sub result1 %.30s too big; can't happen", buf); 1859 sptr = patbeg + patlen; 1860 if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) { 1861 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub"); 1862 while ((*pb++ = *sptr++) != 0) 1863 ; 1864 } 1865 if (pb > buf + bufsz) 1866 FATAL("sub result2 %.30s too big; can't happen", buf); 1867 setsval(x, buf); /* BUG: should be able to avoid copy */ 1868 result = True; 1869 } 1870 tempfree(x); 1871 tempfree(y); 1872 free(buf); 1873 return result; 1874 } 1875 1876 Cell *gsub(Node **a, int nnn) /* global substitute */ 1877 { 1878 Cell *x, *y; 1879 char *rptr, *sptr, *t, *pb, *q; 1880 char *buf; 1881 fa *pfa; 1882 int mflag, tempstat, num; 1883 int bufsz = recsize; 1884 1885 if ((buf = (char *) malloc(bufsz)) == NULL) 1886 FATAL("out of memory in gsub"); 1887 mflag = 0; /* if mflag == 0, can replace empty string */ 1888 num = 0; 1889 x = execute(a[3]); /* target string */ 1890 t = getsval(x); 1891 if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ 1892 pfa = (fa *) a[1]; /* regular expression */ 1893 else { 1894 y = execute(a[1]); 1895 pfa = makedfa(getsval(y), 1); 1896 tempfree(y); 1897 } 1898 y = execute(a[2]); /* replacement string */ 1899 if (pmatch(pfa, t)) { 1900 tempstat = pfa->initstat; 1901 pfa->initstat = 2; 1902 pb = buf; 1903 rptr = getsval(y); 1904 do { 1905 if (patlen == 0 && *patbeg != 0) { /* matched empty string */ 1906 if (mflag == 0) { /* can replace empty */ 1907 num++; 1908 sptr = rptr; 1909 while (*sptr != 0) { 1910 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub"); 1911 if (*sptr == '\\') { 1912 backsub(&pb, &sptr); 1913 } else if (*sptr == '&') { 1914 sptr++; 1915 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub"); 1916 for (q = patbeg; q < patbeg+patlen; ) 1917 *pb++ = *q++; 1918 } else 1919 *pb++ = *sptr++; 1920 } 1921 } 1922 if (*t == 0) /* at end */ 1923 goto done; 1924 adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub"); 1925 *pb++ = *t++; 1926 if (pb > buf + bufsz) /* BUG: not sure of this test */ 1927 FATAL("gsub result0 %.30s too big; can't happen", buf); 1928 mflag = 0; 1929 } 1930 else { /* matched nonempty string */ 1931 num++; 1932 sptr = t; 1933 adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub"); 1934 while (sptr < patbeg) 1935 *pb++ = *sptr++; 1936 sptr = rptr; 1937 while (*sptr != 0) { 1938 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub"); 1939 if (*sptr == '\\') { 1940 backsub(&pb, &sptr); 1941 } else if (*sptr == '&') { 1942 sptr++; 1943 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub"); 1944 for (q = patbeg; q < patbeg+patlen; ) 1945 *pb++ = *q++; 1946 } else 1947 *pb++ = *sptr++; 1948 } 1949 t = patbeg + patlen; 1950 if (patlen == 0 || *t == 0 || *(t-1) == 0) 1951 goto done; 1952 if (pb > buf + bufsz) 1953 FATAL("gsub result1 %.30s too big; can't happen", buf); 1954 mflag = 1; 1955 } 1956 } while (pmatch(pfa,t)); 1957 sptr = t; 1958 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub"); 1959 while ((*pb++ = *sptr++) != 0) 1960 ; 1961 done: if (pb < buf + bufsz) 1962 *pb = '\0'; 1963 else if (*(pb-1) != '\0') 1964 FATAL("gsub result2 %.30s truncated; can't happen", buf); 1965 setsval(x, buf); /* BUG: should be able to avoid copy + free */ 1966 pfa->initstat = tempstat; 1967 } 1968 tempfree(x); 1969 tempfree(y); 1970 x = gettemp(); 1971 x->tval = NUM; 1972 x->fval = num; 1973 free(buf); 1974 return(x); 1975 } 1976 1977 void backsub(char **pb_ptr, char **sptr_ptr) /* handle \\& variations */ 1978 { /* sptr[0] == '\\' */ 1979 char *pb = *pb_ptr, *sptr = *sptr_ptr; 1980 1981 if (sptr[1] == '\\') { 1982 if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */ 1983 *pb++ = '\\'; 1984 *pb++ = '&'; 1985 sptr += 4; 1986 } else if (sptr[2] == '&') { /* \\& -> \ + matched */ 1987 *pb++ = '\\'; 1988 sptr += 2; 1989 } else { /* \\x -> \\x */ 1990 *pb++ = *sptr++; 1991 *pb++ = *sptr++; 1992 } 1993 } else if (sptr[1] == '&') { /* literal & */ 1994 sptr++; 1995 *pb++ = *sptr++; 1996 } else /* literal \ */ 1997 *pb++ = *sptr++; 1998 1999 *pb_ptr = pb; 2000 *sptr_ptr = sptr; 2001 } 2002