1 /**************************************************************** 2 Copyright (C) Lucent Technologies 1997 3 All Rights Reserved 4 5 Permission to use, copy, modify, and distribute this software and 6 its documentation for any purpose and without fee is hereby 7 granted, provided that the above copyright notice appear in all 8 copies and that both that the copyright notice and this 9 permission notice and warranty disclaimer appear in supporting 10 documentation, and that the name Lucent Technologies or any of 11 its entities not be used in advertising or publicity pertaining 12 to distribution of the software without specific, written prior 13 permission. 14 15 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 17 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 18 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 20 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 21 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 22 THIS SOFTWARE. 23 ****************************************************************/ 24 25 #define DEBUG 26 #include <stdio.h> 27 #include <ctype.h> 28 #include <setjmp.h> 29 #include <limits.h> 30 #include <math.h> 31 #include <string.h> 32 #include <stdlib.h> 33 #include <time.h> 34 #include "awk.h" 35 #include "ytab.h" 36 37 #define tempfree(x) if (istemp(x)) tfree(x); else 38 39 /* 40 #undef tempfree 41 42 void tempfree(Cell *p) { 43 if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) { 44 WARNING("bad csub %d in Cell %d %s", 45 p->csub, p->ctype, p->sval); 46 } 47 if (istemp(p)) 48 tfree(p); 49 } 50 */ 51 52 /* do we really need these? */ 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 extern int pairstack[]; 69 extern Awkfloat srand_seed; 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 /* buffer memory management */ 95 int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr, 96 const char *whatrtn) 97 /* pbuf: address of pointer to buffer being managed 98 * psiz: address of buffer size variable 99 * minlen: minimum length of buffer needed 100 * quantum: buffer size quantum 101 * pbptr: address of movable pointer into buffer, or 0 if none 102 * whatrtn: name of the calling routine if failure should cause fatal error 103 * 104 * return 0 for realloc failure, !=0 for success 105 */ 106 { 107 if (minlen > *psiz) { 108 char *tbuf; 109 int rminlen = quantum ? minlen % quantum : 0; 110 int boff = pbptr ? *pbptr - *pbuf : 0; 111 /* round up to next multiple of quantum */ 112 if (rminlen) 113 minlen += quantum - rminlen; 114 tbuf = (char *) realloc(*pbuf, minlen); 115 dprintf( ("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, *pbuf, tbuf) ); 116 if (tbuf == NULL) { 117 if (whatrtn) 118 FATAL("out of memory in %s", whatrtn); 119 return 0; 120 } 121 *pbuf = tbuf; 122 *psiz = minlen; 123 if (pbptr) 124 *pbptr = tbuf + boff; 125 } 126 return 1; 127 } 128 129 void run(Node *a) /* execution of parse tree starts here */ 130 { 131 extern void stdinit(void); 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 *awkgetline(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, "array")) 470 FATAL("out of memory for %s[%s...]", x->nval, buf); 471 strcat(buf, s); 472 if (np->nnext) 473 strcat(buf, *SUBSEP); 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, "awkdelete")) 517 FATAL("out of memory deleting %s[%s...]", x->nval, buf); 518 strcat(buf, s); 519 if (np->nnext) 520 strcat(buf, *SUBSEP); 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, "intest")) 556 FATAL("out of memory deleting %s[%s...]", x->nval, buf); 557 strcat(buf, s); 558 tempfree(x); 559 if (p->nnext) 560 strcat(buf, *SUBSEP); 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, "format1"); 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, "format2"); 840 for (t = fmt; (*t++ = *s) != '\0'; s++) { 841 if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3")) 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 x = execute(a); 847 a = a->nnext; 848 sprintf(t-1, "%d", fmtwd=(int) getfval(x)); 849 if (fmtwd < 0) 850 fmtwd = -fmtwd; 851 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format"); 852 t = fmt + strlen(fmt); 853 tempfree(x); 854 } 855 } 856 *t = '\0'; 857 if (fmtwd < 0) 858 fmtwd = -fmtwd; 859 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format4"); 860 861 switch (*s) { 862 case 'f': case 'e': case 'g': case 'E': case 'G': 863 flag = 'f'; 864 break; 865 case 'd': case 'i': 866 flag = 'd'; 867 if(*(s-1) == 'l') break; 868 *(t-1) = 'l'; 869 *t = 'd'; 870 *++t = '\0'; 871 break; 872 case 'o': case 'x': case 'X': case 'u': 873 flag = *(s-1) == 'l' ? 'd' : 'u'; 874 break; 875 case 's': 876 flag = 's'; 877 break; 878 case 'c': 879 flag = 'c'; 880 break; 881 default: 882 WARNING("weird printf conversion %s", fmt); 883 flag = '?'; 884 break; 885 } 886 if (a == NULL) 887 FATAL("not enough args in printf(%s)", os); 888 x = execute(a); 889 a = a->nnext; 890 n = MAXNUMSIZE; 891 if (fmtwd > n) 892 n = fmtwd; 893 adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format5"); 894 switch (flag) { 895 case '?': sprintf(p, "%s", fmt); /* unknown, so dump it too */ 896 t = getsval(x); 897 n = strlen(t); 898 if (fmtwd > n) 899 n = fmtwd; 900 adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format6"); 901 p += strlen(p); 902 sprintf(p, "%s", t); 903 break; 904 case 'f': sprintf(p, fmt, getfval(x)); break; 905 case 'd': sprintf(p, fmt, (long) getfval(x)); break; 906 case 'u': sprintf(p, fmt, (int) getfval(x)); break; 907 case 's': 908 t = getsval(x); 909 n = strlen(t); 910 if (fmtwd > n) 911 n = fmtwd; 912 if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format7")) 913 FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t); 914 sprintf(p, fmt, t); 915 break; 916 case 'c': 917 if (isnum(x)) { 918 if (getfval(x)) 919 sprintf(p, fmt, (int) getfval(x)); 920 else { 921 *p++ = '\0'; /* explicit null byte */ 922 *p = '\0'; /* next output will start here */ 923 } 924 } else 925 sprintf(p, fmt, getsval(x)[0]); 926 break; 927 default: 928 FATAL("can't happen: bad conversion %c in format()", flag); 929 } 930 tempfree(x); 931 p += strlen(p); 932 s++; 933 } 934 *p = '\0'; 935 free(fmt); 936 for ( ; a; a = a->nnext) /* evaluate any remaining args */ 937 execute(a); 938 *pbuf = buf; 939 *pbufsize = bufsize; 940 return p - buf; 941 } 942 943 Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */ 944 { 945 Cell *x; 946 Node *y; 947 char *buf; 948 int bufsz=3*recsize; 949 950 if ((buf = (char *) malloc(bufsz)) == NULL) 951 FATAL("out of memory in awksprintf"); 952 y = a[0]->nnext; 953 x = execute(a[0]); 954 if (format(&buf, &bufsz, getsval(x), y) == -1) 955 FATAL("sprintf string %.30s... too long. can't happen.", buf); 956 tempfree(x); 957 x = gettemp(); 958 x->sval = buf; 959 x->tval = STR; 960 return(x); 961 } 962 963 Cell *awkprintf(Node **a, int n) /* printf */ 964 { /* a[0] is list of args, starting with format string */ 965 /* a[1] is redirection operator, a[2] is redirection file */ 966 FILE *fp; 967 Cell *x; 968 Node *y; 969 char *buf; 970 int len; 971 int bufsz=3*recsize; 972 973 if ((buf = (char *) malloc(bufsz)) == NULL) 974 FATAL("out of memory in awkprintf"); 975 y = a[0]->nnext; 976 x = execute(a[0]); 977 if ((len = format(&buf, &bufsz, getsval(x), y)) == -1) 978 FATAL("printf string %.30s... too long. can't happen.", buf); 979 tempfree(x); 980 if (a[1] == NULL) { 981 /* fputs(buf, stdout); */ 982 fwrite(buf, len, 1, stdout); 983 if (ferror(stdout)) 984 FATAL("write error on stdout"); 985 } else { 986 fp = redirect(ptoi(a[1]), a[2]); 987 /* fputs(buf, fp); */ 988 fwrite(buf, len, 1, fp); 989 fflush(fp); 990 if (ferror(fp)) 991 FATAL("write error on %s", filename(fp)); 992 } 993 free(buf); 994 return(True); 995 } 996 997 Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */ 998 { 999 Awkfloat i, j = 0; 1000 double v; 1001 Cell *x, *y, *z; 1002 1003 x = execute(a[0]); 1004 i = getfval(x); 1005 tempfree(x); 1006 if (n != UMINUS) { 1007 y = execute(a[1]); 1008 j = getfval(y); 1009 tempfree(y); 1010 } 1011 z = gettemp(); 1012 switch (n) { 1013 case ADD: 1014 i += j; 1015 break; 1016 case MINUS: 1017 i -= j; 1018 break; 1019 case MULT: 1020 i *= j; 1021 break; 1022 case DIVIDE: 1023 if (j == 0) 1024 FATAL("division by zero"); 1025 i /= j; 1026 break; 1027 case MOD: 1028 if (j == 0) 1029 FATAL("division by zero in mod"); 1030 modf(i/j, &v); 1031 i = i - j * v; 1032 break; 1033 case UMINUS: 1034 i = -i; 1035 break; 1036 case POWER: 1037 if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */ 1038 i = ipow(i, (int) j); 1039 else 1040 i = errcheck(pow(i, j), "pow"); 1041 break; 1042 default: /* can't happen */ 1043 FATAL("illegal arithmetic operator %d", n); 1044 } 1045 setfval(z, i); 1046 return(z); 1047 } 1048 1049 double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */ 1050 { 1051 double v; 1052 1053 if (n <= 0) 1054 return 1; 1055 v = ipow(x, n/2); 1056 if (n % 2 == 0) 1057 return v * v; 1058 else 1059 return x * v * v; 1060 } 1061 1062 Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */ 1063 { 1064 Cell *x, *z; 1065 int k; 1066 Awkfloat xf; 1067 1068 x = execute(a[0]); 1069 xf = getfval(x); 1070 k = (n == PREINCR || n == POSTINCR) ? 1 : -1; 1071 if (n == PREINCR || n == PREDECR) { 1072 setfval(x, xf + k); 1073 return(x); 1074 } 1075 z = gettemp(); 1076 setfval(z, xf); 1077 setfval(x, xf + k); 1078 tempfree(x); 1079 return(z); 1080 } 1081 1082 Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */ 1083 { /* this is subtle; don't muck with it. */ 1084 Cell *x, *y; 1085 Awkfloat xf, yf; 1086 double v; 1087 1088 y = execute(a[1]); 1089 x = execute(a[0]); 1090 if (n == ASSIGN) { /* ordinary assignment */ 1091 if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: */ 1092 ; /* leave alone unless it's a field */ 1093 else if ((y->tval & (STR|NUM)) == (STR|NUM)) { 1094 setsval(x, getsval(y)); 1095 x->fval = getfval(y); 1096 x->tval |= NUM; 1097 } 1098 else if (isstr(y)) 1099 setsval(x, getsval(y)); 1100 else if (isnum(y)) 1101 setfval(x, getfval(y)); 1102 else 1103 funnyvar(y, "read value of"); 1104 tempfree(y); 1105 return(x); 1106 } 1107 xf = getfval(x); 1108 yf = getfval(y); 1109 switch (n) { 1110 case ADDEQ: 1111 xf += yf; 1112 break; 1113 case SUBEQ: 1114 xf -= yf; 1115 break; 1116 case MULTEQ: 1117 xf *= yf; 1118 break; 1119 case DIVEQ: 1120 if (yf == 0) 1121 FATAL("division by zero in /="); 1122 xf /= yf; 1123 break; 1124 case MODEQ: 1125 if (yf == 0) 1126 FATAL("division by zero in %%="); 1127 modf(xf/yf, &v); 1128 xf = xf - yf * v; 1129 break; 1130 case POWEQ: 1131 if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */ 1132 xf = ipow(xf, (int) yf); 1133 else 1134 xf = errcheck(pow(xf, yf), "pow"); 1135 break; 1136 default: 1137 FATAL("illegal assignment operator %d", n); 1138 break; 1139 } 1140 tempfree(y); 1141 setfval(x, xf); 1142 return(x); 1143 } 1144 1145 Cell *cat(Node **a, int q) /* a[0] cat a[1] */ 1146 { 1147 Cell *x, *y, *z; 1148 int n1, n2; 1149 char *s; 1150 1151 x = execute(a[0]); 1152 y = execute(a[1]); 1153 getsval(x); 1154 getsval(y); 1155 n1 = strlen(x->sval); 1156 n2 = strlen(y->sval) + 1; 1157 s = (char *) malloc(n1 + n2); 1158 if (s == NULL) 1159 FATAL("out of space concatenating %.15s... and %.15s...", 1160 x->sval, y->sval); 1161 memmove(s, x->sval, n1); 1162 memmove(s+n1, y->sval, n2); 1163 tempfree(x); 1164 tempfree(y); 1165 z = gettemp(); 1166 z->sval = s; 1167 z->tval = STR; 1168 return(z); 1169 } 1170 1171 Cell *pastat(Node **a, int n) /* a[0] { a[1] } */ 1172 { 1173 Cell *x; 1174 1175 if (a[0] == 0) 1176 x = execute(a[1]); 1177 else { 1178 x = execute(a[0]); 1179 if (istrue(x)) { 1180 tempfree(x); 1181 x = execute(a[1]); 1182 } 1183 } 1184 return x; 1185 } 1186 1187 Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */ 1188 { 1189 Cell *x; 1190 int pair; 1191 1192 pair = ptoi(a[3]); 1193 if (pairstack[pair] == 0) { 1194 x = execute(a[0]); 1195 if (istrue(x)) 1196 pairstack[pair] = 1; 1197 tempfree(x); 1198 } 1199 if (pairstack[pair] == 1) { 1200 x = execute(a[1]); 1201 if (istrue(x)) 1202 pairstack[pair] = 0; 1203 tempfree(x); 1204 x = execute(a[2]); 1205 return(x); 1206 } 1207 return(False); 1208 } 1209 1210 Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ 1211 { 1212 Cell *x = 0, *y, *ap; 1213 char *s; 1214 int sep; 1215 char *t, temp, num[50], *fs = 0; 1216 int n, tempstat, arg3type; 1217 1218 y = execute(a[0]); /* source string */ 1219 s = getsval(y); 1220 arg3type = ptoi(a[3]); 1221 if (a[2] == 0) /* fs string */ 1222 fs = *FS; 1223 else if (arg3type == STRING) { /* split(str,arr,"string") */ 1224 x = execute(a[2]); 1225 fs = getsval(x); 1226 } else if (arg3type == REGEXPR) 1227 fs = "(regexpr)"; /* split(str,arr,/regexpr/) */ 1228 else 1229 FATAL("illegal type of split"); 1230 sep = *fs; 1231 ap = execute(a[1]); /* array name */ 1232 freesymtab(ap); 1233 dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs) ); 1234 ap->tval &= ~STR; 1235 ap->tval |= ARR; 1236 ap->sval = (char *) makesymtab(NSYMTAB); 1237 1238 n = 0; 1239 if (arg3type == REGEXPR && strlen((char*)((fa*)a[2])->restr) == 0) { 1240 /* split(s, a, //); have to arrange that it looks like empty sep */ 1241 arg3type = 0; 1242 fs = ""; 1243 sep = 0; 1244 } 1245 if (*s != '\0' && (strlen(fs) > 1 || arg3type == REGEXPR)) { /* reg expr */ 1246 fa *pfa; 1247 if (arg3type == REGEXPR) { /* it's ready already */ 1248 pfa = (fa *) a[2]; 1249 } else { 1250 pfa = makedfa(fs, 1); 1251 } 1252 if (nematch(pfa,s)) { 1253 tempstat = pfa->initstat; 1254 pfa->initstat = 2; 1255 do { 1256 n++; 1257 sprintf(num, "%d", n); 1258 temp = *patbeg; 1259 *patbeg = '\0'; 1260 if (is_number(s)) 1261 setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval); 1262 else 1263 setsymtab(num, s, 0.0, STR, (Array *) ap->sval); 1264 *patbeg = temp; 1265 s = patbeg + patlen; 1266 if (*(patbeg+patlen-1) == 0 || *s == 0) { 1267 n++; 1268 sprintf(num, "%d", n); 1269 setsymtab(num, "", 0.0, STR, (Array *) ap->sval); 1270 pfa->initstat = tempstat; 1271 goto spdone; 1272 } 1273 } while (nematch(pfa,s)); 1274 pfa->initstat = tempstat; /* bwk: has to be here to reset */ 1275 /* cf gsub and refldbld */ 1276 } 1277 n++; 1278 sprintf(num, "%d", n); 1279 if (is_number(s)) 1280 setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval); 1281 else 1282 setsymtab(num, s, 0.0, STR, (Array *) ap->sval); 1283 spdone: 1284 pfa = NULL; 1285 } else if (sep == ' ') { 1286 for (n = 0; ; ) { 1287 while (*s == ' ' || *s == '\t' || *s == '\n') 1288 s++; 1289 if (*s == 0) 1290 break; 1291 n++; 1292 t = s; 1293 do 1294 s++; 1295 while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0'); 1296 temp = *s; 1297 *s = '\0'; 1298 sprintf(num, "%d", n); 1299 if (is_number(t)) 1300 setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval); 1301 else 1302 setsymtab(num, t, 0.0, STR, (Array *) ap->sval); 1303 *s = temp; 1304 if (*s != 0) 1305 s++; 1306 } 1307 } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */ 1308 for (n = 0; *s != 0; s++) { 1309 char buf[2]; 1310 n++; 1311 sprintf(num, "%d", n); 1312 buf[0] = *s; 1313 buf[1] = 0; 1314 if (isdigit((uschar)buf[0])) 1315 setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval); 1316 else 1317 setsymtab(num, buf, 0.0, STR, (Array *) ap->sval); 1318 } 1319 } else if (*s != 0) { 1320 for (;;) { 1321 n++; 1322 t = s; 1323 while (*s != sep && *s != '\n' && *s != '\0') 1324 s++; 1325 temp = *s; 1326 *s = '\0'; 1327 sprintf(num, "%d", n); 1328 if (is_number(t)) 1329 setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval); 1330 else 1331 setsymtab(num, t, 0.0, STR, (Array *) ap->sval); 1332 *s = temp; 1333 if (*s++ == 0) 1334 break; 1335 } 1336 } 1337 tempfree(ap); 1338 tempfree(y); 1339 if (a[2] != 0 && arg3type == STRING) { 1340 tempfree(x); 1341 } 1342 x = gettemp(); 1343 x->tval = NUM; 1344 x->fval = n; 1345 return(x); 1346 } 1347 1348 Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */ 1349 { 1350 Cell *x; 1351 1352 x = execute(a[0]); 1353 if (istrue(x)) { 1354 tempfree(x); 1355 x = execute(a[1]); 1356 } else { 1357 tempfree(x); 1358 x = execute(a[2]); 1359 } 1360 return(x); 1361 } 1362 1363 Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */ 1364 { 1365 Cell *x; 1366 1367 x = execute(a[0]); 1368 if (istrue(x)) { 1369 tempfree(x); 1370 x = execute(a[1]); 1371 } else if (a[2] != 0) { 1372 tempfree(x); 1373 x = execute(a[2]); 1374 } 1375 return(x); 1376 } 1377 1378 Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */ 1379 { 1380 Cell *x; 1381 1382 for (;;) { 1383 x = execute(a[0]); 1384 if (!istrue(x)) 1385 return(x); 1386 tempfree(x); 1387 x = execute(a[1]); 1388 if (isbreak(x)) { 1389 x = True; 1390 return(x); 1391 } 1392 if (isnext(x) || isexit(x) || isret(x)) 1393 return(x); 1394 tempfree(x); 1395 } 1396 } 1397 1398 Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */ 1399 { 1400 Cell *x; 1401 1402 for (;;) { 1403 x = execute(a[0]); 1404 if (isbreak(x)) 1405 return True; 1406 if (isnext(x) || isexit(x) || isret(x)) 1407 return(x); 1408 tempfree(x); 1409 x = execute(a[1]); 1410 if (!istrue(x)) 1411 return(x); 1412 tempfree(x); 1413 } 1414 } 1415 1416 Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */ 1417 { 1418 Cell *x; 1419 1420 x = execute(a[0]); 1421 tempfree(x); 1422 for (;;) { 1423 if (a[1]!=0) { 1424 x = execute(a[1]); 1425 if (!istrue(x)) return(x); 1426 else tempfree(x); 1427 } 1428 x = execute(a[3]); 1429 if (isbreak(x)) /* turn off break */ 1430 return True; 1431 if (isnext(x) || isexit(x) || isret(x)) 1432 return(x); 1433 tempfree(x); 1434 x = execute(a[2]); 1435 tempfree(x); 1436 } 1437 } 1438 1439 Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */ 1440 { 1441 Cell *x, *vp, *arrayp, *cp, *ncp; 1442 Array *tp; 1443 int i; 1444 1445 vp = execute(a[0]); 1446 arrayp = execute(a[1]); 1447 if (!isarr(arrayp)) { 1448 return True; 1449 } 1450 tp = (Array *) arrayp->sval; 1451 tempfree(arrayp); 1452 for (i = 0; i < tp->size; i++) { /* this routine knows too much */ 1453 for (cp = tp->tab[i]; cp != NULL; cp = ncp) { 1454 setsval(vp, cp->nval); 1455 ncp = cp->cnext; 1456 x = execute(a[2]); 1457 if (isbreak(x)) { 1458 tempfree(vp); 1459 return True; 1460 } 1461 if (isnext(x) || isexit(x) || isret(x)) { 1462 tempfree(vp); 1463 return(x); 1464 } 1465 tempfree(x); 1466 } 1467 } 1468 return True; 1469 } 1470 1471 Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */ 1472 { 1473 Cell *x, *y; 1474 Awkfloat u; 1475 int t; 1476 Awkfloat tmp; 1477 char *p, *buf; 1478 Node *nextarg; 1479 FILE *fp; 1480 void flush_all(void); 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 FSYSTEM: 1516 fflush(stdout); /* in case something is buffered already */ 1517 u = (Awkfloat) system(getsval(x)) / 256; /* 256 is unix-dep */ 1518 break; 1519 case FRAND: 1520 /* in principle, rand() returns something in 0..RAND_MAX */ 1521 u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX; 1522 break; 1523 case FSRAND: 1524 if (isrec(x)) /* no argument provided */ 1525 u = time((time_t *)0); 1526 else 1527 u = getfval(x); 1528 tmp = u; 1529 srand((unsigned int) u); 1530 u = srand_seed; 1531 srand_seed = tmp; 1532 break; 1533 case FTOUPPER: 1534 case FTOLOWER: 1535 buf = tostring(getsval(x)); 1536 if (t == FTOUPPER) { 1537 for (p = buf; *p; p++) 1538 if (islower((uschar) *p)) 1539 *p = toupper((uschar)*p); 1540 } else { 1541 for (p = buf; *p; p++) 1542 if (isupper((uschar) *p)) 1543 *p = tolower((uschar)*p); 1544 } 1545 tempfree(x); 1546 x = gettemp(); 1547 setsval(x, buf); 1548 free(buf); 1549 return x; 1550 case FFLUSH: 1551 if (isrec(x) || strlen(getsval(x)) == 0) { 1552 flush_all(); /* fflush() or fflush("") -> all */ 1553 u = 0; 1554 } else if ((fp = openfile(FFLUSH, getsval(x))) == NULL) 1555 u = EOF; 1556 else 1557 u = fflush(fp); 1558 break; 1559 default: /* can't happen */ 1560 FATAL("illegal function type %d", t); 1561 break; 1562 } 1563 tempfree(x); 1564 x = gettemp(); 1565 setfval(x, u); 1566 if (nextarg != 0) { 1567 WARNING("warning: function has too many arguments"); 1568 for ( ; nextarg; nextarg = nextarg->nnext) 1569 execute(nextarg); 1570 } 1571 return(x); 1572 } 1573 1574 Cell *printstat(Node **a, int n) /* print a[0] */ 1575 { 1576 Node *x; 1577 Cell *y; 1578 FILE *fp; 1579 1580 if (a[1] == 0) /* a[1] is redirection operator, a[2] is file */ 1581 fp = stdout; 1582 else 1583 fp = redirect(ptoi(a[1]), a[2]); 1584 for (x = a[0]; x != NULL; x = x->nnext) { 1585 y = execute(x); 1586 fputs(getpssval(y), fp); 1587 tempfree(y); 1588 if (x->nnext == NULL) 1589 fputs(*ORS, fp); 1590 else 1591 fputs(*OFS, fp); 1592 } 1593 if (a[1] != 0) 1594 fflush(fp); 1595 if (ferror(fp)) 1596 FATAL("write error on %s", filename(fp)); 1597 return(True); 1598 } 1599 1600 Cell *nullproc(Node **a, int n) 1601 { 1602 n = n; 1603 a = a; 1604 return 0; 1605 } 1606 1607 1608 FILE *redirect(int a, Node *b) /* set up all i/o redirections */ 1609 { 1610 FILE *fp; 1611 Cell *x; 1612 char *fname; 1613 1614 x = execute(b); 1615 fname = getsval(x); 1616 fp = openfile(a, fname); 1617 if (fp == NULL) 1618 FATAL("can't open file %s", fname); 1619 tempfree(x); 1620 return fp; 1621 } 1622 1623 struct files { 1624 FILE *fp; 1625 const char *fname; 1626 int mode; /* '|', 'a', 'w' => LE/LT, GT */ 1627 } *files; 1628 1629 int nfiles; 1630 1631 void stdinit(void) /* in case stdin, etc., are not constants */ 1632 { 1633 nfiles = FOPEN_MAX; 1634 files = calloc(nfiles, sizeof(*files)); 1635 if (files == NULL) 1636 FATAL("can't allocate file memory for %u files", nfiles); 1637 files[0].fp = stdin; 1638 files[0].fname = "/dev/stdin"; 1639 files[0].mode = LT; 1640 files[1].fp = stdout; 1641 files[1].fname = "/dev/stdout"; 1642 files[1].mode = GT; 1643 files[2].fp = stderr; 1644 files[2].fname = "/dev/stderr"; 1645 files[2].mode = GT; 1646 } 1647 1648 FILE *openfile(int a, const char *us) 1649 { 1650 const char *s = us; 1651 int i, m; 1652 FILE *fp = 0; 1653 1654 if (*s == '\0') 1655 FATAL("null file name in print or getline"); 1656 for (i=0; i < nfiles; i++) 1657 if (files[i].fname && strcmp(s, files[i].fname) == 0) { 1658 if (a == files[i].mode || (a==APPEND && files[i].mode==GT)) 1659 return files[i].fp; 1660 if (a == FFLUSH) 1661 return files[i].fp; 1662 } 1663 if (a == FFLUSH) /* didn't find it, so don't create it! */ 1664 return NULL; 1665 1666 for (i=0; i < nfiles; i++) 1667 if (files[i].fp == 0) 1668 break; 1669 if (i >= nfiles) { 1670 struct files *nf; 1671 int nnf = nfiles + FOPEN_MAX; 1672 nf = realloc(files, nnf * sizeof(*nf)); 1673 if (nf == NULL) 1674 FATAL("cannot grow files for %s and %d files", s, nnf); 1675 memset(&nf[nfiles], 0, FOPEN_MAX * sizeof(*nf)); 1676 nfiles = nnf; 1677 files = nf; 1678 } 1679 fflush(stdout); /* force a semblance of order */ 1680 m = a; 1681 if (a == GT) { 1682 fp = fopen(s, "w"); 1683 } else if (a == APPEND) { 1684 fp = fopen(s, "a"); 1685 m = GT; /* so can mix > and >> */ 1686 } else if (a == '|') { /* output pipe */ 1687 fp = popen(s, "w"); 1688 } else if (a == LE) { /* input pipe */ 1689 fp = popen(s, "r"); 1690 } else if (a == LT) { /* getline <file */ 1691 fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */ 1692 } else /* can't happen */ 1693 FATAL("illegal redirection %d", a); 1694 if (fp != NULL) { 1695 files[i].fname = tostring(s); 1696 files[i].fp = fp; 1697 files[i].mode = m; 1698 } 1699 return fp; 1700 } 1701 1702 const char *filename(FILE *fp) 1703 { 1704 int i; 1705 1706 for (i = 0; i < nfiles; i++) 1707 if (fp == files[i].fp) 1708 return files[i].fname; 1709 return "???"; 1710 } 1711 1712 Cell *closefile(Node **a, int n) 1713 { 1714 Cell *x; 1715 int i, stat; 1716 1717 n = n; 1718 x = execute(a[0]); 1719 getsval(x); 1720 stat = -1; 1721 for (i = 0; i < nfiles; i++) { 1722 if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) { 1723 if (ferror(files[i].fp)) 1724 WARNING( "i/o error occurred on %s", files[i].fname ); 1725 if (files[i].mode == '|' || files[i].mode == LE) 1726 stat = pclose(files[i].fp); 1727 else 1728 stat = fclose(files[i].fp); 1729 if (stat == EOF) 1730 WARNING( "i/o error occurred closing %s", files[i].fname ); 1731 if (i > 2) /* don't do /dev/std... */ 1732 xfree(files[i].fname); 1733 files[i].fname = NULL; /* watch out for ref thru this */ 1734 files[i].fp = NULL; 1735 } 1736 } 1737 tempfree(x); 1738 x = gettemp(); 1739 setfval(x, (Awkfloat) stat); 1740 return(x); 1741 } 1742 1743 void closeall(void) 1744 { 1745 int i, stat; 1746 1747 for (i = 0; i < FOPEN_MAX; i++) { 1748 if (files[i].fp) { 1749 if (ferror(files[i].fp)) 1750 WARNING( "i/o error occurred on %s", files[i].fname ); 1751 if (files[i].mode == '|' || files[i].mode == LE) 1752 stat = pclose(files[i].fp); 1753 else 1754 stat = fclose(files[i].fp); 1755 if (stat == EOF) 1756 WARNING( "i/o error occurred while closing %s", files[i].fname ); 1757 } 1758 } 1759 } 1760 1761 void flush_all(void) 1762 { 1763 int i; 1764 1765 for (i = 0; i < nfiles; i++) 1766 if (files[i].fp) 1767 fflush(files[i].fp); 1768 } 1769 1770 void backsub(char **pb_ptr, char **sptr_ptr); 1771 1772 Cell *sub(Node **a, int nnn) /* substitute command */ 1773 { 1774 char *sptr, *pb, *q; 1775 Cell *x, *y, *result; 1776 char *t, *buf; 1777 fa *pfa; 1778 int bufsz = recsize; 1779 1780 if ((buf = (char *) malloc(bufsz)) == NULL) 1781 FATAL("out of memory in sub"); 1782 x = execute(a[3]); /* target string */ 1783 t = getsval(x); 1784 if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ 1785 pfa = (fa *) a[1]; /* regular expression */ 1786 else { 1787 y = execute(a[1]); 1788 pfa = makedfa(getsval(y), 1); 1789 tempfree(y); 1790 } 1791 y = execute(a[2]); /* replacement string */ 1792 result = False; 1793 if (pmatch(pfa, t)) { 1794 sptr = t; 1795 adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub"); 1796 pb = buf; 1797 while (sptr < patbeg) 1798 *pb++ = *sptr++; 1799 sptr = getsval(y); 1800 while (*sptr != 0) { 1801 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub"); 1802 if (*sptr == '\\') { 1803 backsub(&pb, &sptr); 1804 } else if (*sptr == '&') { 1805 sptr++; 1806 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub"); 1807 for (q = patbeg; q < patbeg+patlen; ) 1808 *pb++ = *q++; 1809 } else 1810 *pb++ = *sptr++; 1811 } 1812 *pb = '\0'; 1813 if (pb > buf + bufsz) 1814 FATAL("sub result1 %.30s too big; can't happen", buf); 1815 sptr = patbeg + patlen; 1816 if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) { 1817 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub"); 1818 while ((*pb++ = *sptr++) != 0) 1819 ; 1820 } 1821 if (pb > buf + bufsz) 1822 FATAL("sub result2 %.30s too big; can't happen", buf); 1823 setsval(x, buf); /* BUG: should be able to avoid copy */ 1824 result = True;; 1825 } 1826 tempfree(x); 1827 tempfree(y); 1828 free(buf); 1829 return result; 1830 } 1831 1832 Cell *gsub(Node **a, int nnn) /* global substitute */ 1833 { 1834 Cell *x, *y; 1835 char *rptr, *sptr, *t, *pb, *q; 1836 char *buf; 1837 fa *pfa; 1838 int mflag, tempstat, num; 1839 int bufsz = recsize; 1840 1841 if ((buf = (char *) malloc(bufsz)) == NULL) 1842 FATAL("out of memory in gsub"); 1843 mflag = 0; /* if mflag == 0, can replace empty string */ 1844 num = 0; 1845 x = execute(a[3]); /* target string */ 1846 t = getsval(x); 1847 if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ 1848 pfa = (fa *) a[1]; /* regular expression */ 1849 else { 1850 y = execute(a[1]); 1851 pfa = makedfa(getsval(y), 1); 1852 tempfree(y); 1853 } 1854 y = execute(a[2]); /* replacement string */ 1855 if (pmatch(pfa, t)) { 1856 tempstat = pfa->initstat; 1857 pfa->initstat = 2; 1858 pb = buf; 1859 rptr = getsval(y); 1860 do { 1861 if (patlen == 0 && *patbeg != 0) { /* matched empty string */ 1862 if (mflag == 0) { /* can replace empty */ 1863 num++; 1864 sptr = rptr; 1865 while (*sptr != 0) { 1866 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub"); 1867 if (*sptr == '\\') { 1868 backsub(&pb, &sptr); 1869 } else if (*sptr == '&') { 1870 sptr++; 1871 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub"); 1872 for (q = patbeg; q < patbeg+patlen; ) 1873 *pb++ = *q++; 1874 } else 1875 *pb++ = *sptr++; 1876 } 1877 } 1878 if (*t == 0) /* at end */ 1879 goto done; 1880 adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub"); 1881 *pb++ = *t++; 1882 if (pb > buf + bufsz) /* BUG: not sure of this test */ 1883 FATAL("gsub result0 %.30s too big; can't happen", buf); 1884 mflag = 0; 1885 } 1886 else { /* matched nonempty string */ 1887 num++; 1888 sptr = t; 1889 adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub"); 1890 while (sptr < patbeg) 1891 *pb++ = *sptr++; 1892 sptr = rptr; 1893 while (*sptr != 0) { 1894 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub"); 1895 if (*sptr == '\\') { 1896 backsub(&pb, &sptr); 1897 } else if (*sptr == '&') { 1898 sptr++; 1899 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub"); 1900 for (q = patbeg; q < patbeg+patlen; ) 1901 *pb++ = *q++; 1902 } else 1903 *pb++ = *sptr++; 1904 } 1905 t = patbeg + patlen; 1906 if (patlen == 0 || *t == 0 || *(t-1) == 0) 1907 goto done; 1908 if (pb > buf + bufsz) 1909 FATAL("gsub result1 %.30s too big; can't happen", buf); 1910 mflag = 1; 1911 } 1912 } while (pmatch(pfa,t)); 1913 sptr = t; 1914 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub"); 1915 while ((*pb++ = *sptr++) != 0) 1916 ; 1917 done: if (pb < buf + bufsz) 1918 *pb = '\0'; 1919 else if (*(pb-1) != '\0') 1920 FATAL("gsub result2 %.30s truncated; can't happen", buf); 1921 setsval(x, buf); /* BUG: should be able to avoid copy + free */ 1922 pfa->initstat = tempstat; 1923 } 1924 tempfree(x); 1925 tempfree(y); 1926 x = gettemp(); 1927 x->tval = NUM; 1928 x->fval = num; 1929 free(buf); 1930 return(x); 1931 } 1932 1933 void backsub(char **pb_ptr, char **sptr_ptr) /* handle \\& variations */ 1934 { /* sptr[0] == '\\' */ 1935 char *pb = *pb_ptr, *sptr = *sptr_ptr; 1936 1937 if (sptr[1] == '\\') { 1938 if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */ 1939 *pb++ = '\\'; 1940 *pb++ = '&'; 1941 sptr += 4; 1942 } else if (sptr[2] == '&') { /* \\& -> \ + matched */ 1943 *pb++ = '\\'; 1944 sptr += 2; 1945 } else { /* \\x -> \\x */ 1946 *pb++ = *sptr++; 1947 *pb++ = *sptr++; 1948 } 1949 } else if (sptr[1] == '&') { /* literal & */ 1950 sptr++; 1951 *pb++ = *sptr++; 1952 } else /* literal \ */ 1953 *pb++ = *sptr++; 1954 1955 *pb_ptr = pb; 1956 *sptr_ptr = sptr; 1957 } 1958