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