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 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, y->nval, y->fval, isarr(y) ? "(array)" : 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", 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 *, 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", a->nval, 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, char *s, Node *a) /* printf-like conversions */ 794 { 795 char *fmt; 796 char *p, *t, *os; 797 Cell *x; 798 int flag = 0, n; 799 int fmtwd; /* format width */ 800 int fmtsz = recsize; 801 char *buf = *pbuf; 802 int bufsize = *pbufsize; 803 804 os = s; 805 p = buf; 806 if ((fmt = (char *) malloc(fmtsz)) == NULL) 807 FATAL("out of memory in format()"); 808 while (*s) { 809 adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format"); 810 if (*s != '%') { 811 *p++ = *s++; 812 continue; 813 } 814 if (*(s+1) == '%') { 815 *p++ = '%'; 816 s += 2; 817 continue; 818 } 819 /* have to be real careful in case this is a huge number, eg, %100000d */ 820 fmtwd = atoi(s+1); 821 if (fmtwd < 0) 822 fmtwd = -fmtwd; 823 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format"); 824 for (t = fmt; (*t++ = *s) != '\0'; s++) { 825 if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, 0)) 826 FATAL("format item %.30s... ran format() out of memory", os); 827 if (isalpha((uschar)*s) && *s != 'l' && *s != 'h' && *s != 'L') 828 break; /* the ansi panoply */ 829 if (*s == '*') { 830 x = execute(a); 831 a = a->nnext; 832 sprintf(t-1, "%d", fmtwd=(int) getfval(x)); 833 if (fmtwd < 0) 834 fmtwd = -fmtwd; 835 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format"); 836 t = fmt + strlen(fmt); 837 tempfree(x); 838 } 839 } 840 *t = '\0'; 841 if (fmtwd < 0) 842 fmtwd = -fmtwd; 843 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format"); 844 845 switch (*s) { 846 case 'f': case 'e': case 'g': case 'E': case 'G': 847 flag = 1; 848 break; 849 case 'd': case 'i': 850 flag = 2; 851 if(*(s-1) == 'l') break; 852 *(t-1) = 'l'; 853 *t = 'd'; 854 *++t = '\0'; 855 break; 856 case 'o': case 'x': case 'X': case 'u': 857 flag = *(s-1) == 'l' ? 2 : 3; 858 break; 859 case 's': 860 flag = 4; 861 break; 862 case 'c': 863 flag = 5; 864 break; 865 default: 866 WARNING("weird printf conversion %s", fmt); 867 flag = 0; 868 break; 869 } 870 if (a == NULL) 871 FATAL("not enough args in printf(%s)", os); 872 x = execute(a); 873 a = a->nnext; 874 n = MAXNUMSIZE; 875 if (fmtwd > n) 876 n = fmtwd; 877 adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format"); 878 switch (flag) { 879 case 0: sprintf(p, "%s", fmt); /* unknown, so dump it too */ 880 t = getsval(x); 881 n = strlen(t); 882 if (fmtwd > n) 883 n = fmtwd; 884 adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format"); 885 p += strlen(p); 886 sprintf(p, "%s", t); 887 break; 888 case 1: sprintf(p, fmt, getfval(x)); break; 889 case 2: sprintf(p, fmt, (long) getfval(x)); break; 890 case 3: sprintf(p, fmt, (int) getfval(x)); break; 891 case 4: 892 t = getsval(x); 893 n = strlen(t); 894 if (fmtwd > n) 895 n = fmtwd; 896 if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, 0)) 897 FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t); 898 sprintf(p, fmt, t); 899 break; 900 case 5: 901 if (isnum(x)) { 902 if (getfval(x)) 903 sprintf(p, fmt, (int) getfval(x)); 904 else 905 *p++ = '\0'; 906 } else 907 sprintf(p, fmt, getsval(x)[0]); 908 break; 909 } 910 tempfree(x); 911 p += strlen(p); 912 s++; 913 } 914 *p = '\0'; 915 free(fmt); 916 for ( ; a; a = a->nnext) /* evaluate any remaining args */ 917 execute(a); 918 *pbuf = buf; 919 *pbufsize = bufsize; 920 return p - buf; 921 } 922 923 Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */ 924 { 925 Cell *x; 926 Node *y; 927 char *buf; 928 int bufsz=3*recsize; 929 930 if ((buf = (char *) malloc(bufsz)) == NULL) 931 FATAL("out of memory in awksprintf"); 932 y = a[0]->nnext; 933 x = execute(a[0]); 934 if (format(&buf, &bufsz, getsval(x), y) == -1) 935 FATAL("sprintf string %.30s... too long. can't happen.", buf); 936 tempfree(x); 937 x = gettemp(); 938 x->sval = buf; 939 x->tval = STR; 940 return(x); 941 } 942 943 Cell *awkprintf(Node **a, int n) /* printf */ 944 { /* a[0] is list of args, starting with format string */ 945 /* a[1] is redirection operator, a[2] is redirection file */ 946 FILE *fp; 947 Cell *x; 948 Node *y; 949 char *buf; 950 int len; 951 int bufsz=3*recsize; 952 953 if ((buf = (char *) malloc(bufsz)) == NULL) 954 FATAL("out of memory in awkprintf"); 955 y = a[0]->nnext; 956 x = execute(a[0]); 957 if ((len = format(&buf, &bufsz, getsval(x), y)) == -1) 958 FATAL("printf string %.30s... too long. can't happen.", buf); 959 tempfree(x); 960 if (a[1] == NULL) { 961 /* fputs(buf, stdout); */ 962 fwrite(buf, len, 1, stdout); 963 if (ferror(stdout)) 964 FATAL("write error on stdout"); 965 } else { 966 fp = redirect(ptoi(a[1]), a[2]); 967 /* fputs(buf, fp); */ 968 fwrite(buf, len, 1, fp); 969 fflush(fp); 970 if (ferror(fp)) 971 FATAL("write error on %s", filename(fp)); 972 } 973 free(buf); 974 return(True); 975 } 976 977 Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */ 978 { 979 Awkfloat i, j = 0; 980 double v; 981 Cell *x, *y, *z; 982 983 x = execute(a[0]); 984 i = getfval(x); 985 tempfree(x); 986 if (n != UMINUS) { 987 y = execute(a[1]); 988 j = getfval(y); 989 tempfree(y); 990 } 991 z = gettemp(); 992 switch (n) { 993 case ADD: 994 i += j; 995 break; 996 case MINUS: 997 i -= j; 998 break; 999 case MULT: 1000 i *= j; 1001 break; 1002 case DIVIDE: 1003 if (j == 0) 1004 FATAL("division by zero"); 1005 i /= j; 1006 break; 1007 case MOD: 1008 if (j == 0) 1009 FATAL("division by zero in mod"); 1010 modf(i/j, &v); 1011 i = i - j * v; 1012 break; 1013 case UMINUS: 1014 i = -i; 1015 break; 1016 case POWER: 1017 if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */ 1018 i = ipow(i, (int) j); 1019 else 1020 i = errcheck(pow(i, j), "pow"); 1021 break; 1022 default: /* can't happen */ 1023 FATAL("illegal arithmetic operator %d", n); 1024 } 1025 setfval(z, i); 1026 return(z); 1027 } 1028 1029 double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */ 1030 { 1031 double v; 1032 1033 if (n <= 0) 1034 return 1; 1035 v = ipow(x, n/2); 1036 if (n % 2 == 0) 1037 return v * v; 1038 else 1039 return x * v * v; 1040 } 1041 1042 Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */ 1043 { 1044 Cell *x, *z; 1045 int k; 1046 Awkfloat xf; 1047 1048 x = execute(a[0]); 1049 xf = getfval(x); 1050 k = (n == PREINCR || n == POSTINCR) ? 1 : -1; 1051 if (n == PREINCR || n == PREDECR) { 1052 setfval(x, xf + k); 1053 return(x); 1054 } 1055 z = gettemp(); 1056 setfval(z, xf); 1057 setfval(x, xf + k); 1058 tempfree(x); 1059 return(z); 1060 } 1061 1062 Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */ 1063 { /* this is subtle; don't muck with it. */ 1064 Cell *x, *y; 1065 Awkfloat xf, yf; 1066 double v; 1067 1068 y = execute(a[1]); 1069 x = execute(a[0]); 1070 if (n == ASSIGN) { /* ordinary assignment */ 1071 if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: */ 1072 ; /* leave alone unless it's a field */ 1073 else if ((y->tval & (STR|NUM)) == (STR|NUM)) { 1074 setsval(x, getsval(y)); 1075 x->fval = getfval(y); 1076 x->tval |= NUM; 1077 } 1078 else if (isstr(y)) 1079 setsval(x, getsval(y)); 1080 else if (isnum(y)) 1081 setfval(x, getfval(y)); 1082 else 1083 funnyvar(y, "read value of"); 1084 tempfree(y); 1085 return(x); 1086 } 1087 xf = getfval(x); 1088 yf = getfval(y); 1089 switch (n) { 1090 case ADDEQ: 1091 xf += yf; 1092 break; 1093 case SUBEQ: 1094 xf -= yf; 1095 break; 1096 case MULTEQ: 1097 xf *= yf; 1098 break; 1099 case DIVEQ: 1100 if (yf == 0) 1101 FATAL("division by zero in /="); 1102 xf /= yf; 1103 break; 1104 case MODEQ: 1105 if (yf == 0) 1106 FATAL("division by zero in %%="); 1107 modf(xf/yf, &v); 1108 xf = xf - yf * v; 1109 break; 1110 case POWEQ: 1111 if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */ 1112 xf = ipow(xf, (int) yf); 1113 else 1114 xf = errcheck(pow(xf, yf), "pow"); 1115 break; 1116 default: 1117 FATAL("illegal assignment operator %d", n); 1118 break; 1119 } 1120 tempfree(y); 1121 setfval(x, xf); 1122 return(x); 1123 } 1124 1125 Cell *cat(Node **a, int q) /* a[0] cat a[1] */ 1126 { 1127 Cell *x, *y, *z; 1128 int n1, n2; 1129 char *s; 1130 1131 x = execute(a[0]); 1132 y = execute(a[1]); 1133 getsval(x); 1134 getsval(y); 1135 n1 = strlen(x->sval); 1136 n2 = strlen(y->sval); 1137 s = (char *) malloc(n1 + n2 + 1); 1138 if (s == NULL) 1139 FATAL("out of space concatenating %.15s... and %.15s...", 1140 x->sval, y->sval); 1141 strcpy(s, x->sval); 1142 strcpy(s+n1, y->sval); 1143 tempfree(y); 1144 z = gettemp(); 1145 z->sval = s; 1146 z->tval = STR; 1147 tempfree(x); 1148 return(z); 1149 } 1150 1151 Cell *pastat(Node **a, int n) /* a[0] { a[1] } */ 1152 { 1153 Cell *x; 1154 1155 if (a[0] == 0) 1156 x = execute(a[1]); 1157 else { 1158 x = execute(a[0]); 1159 if (istrue(x)) { 1160 tempfree(x); 1161 x = execute(a[1]); 1162 } 1163 } 1164 return x; 1165 } 1166 1167 Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */ 1168 { 1169 Cell *x; 1170 int pair; 1171 1172 pair = ptoi(a[3]); 1173 if (pairstack[pair] == 0) { 1174 x = execute(a[0]); 1175 if (istrue(x)) 1176 pairstack[pair] = 1; 1177 tempfree(x); 1178 } 1179 if (pairstack[pair] == 1) { 1180 x = execute(a[1]); 1181 if (istrue(x)) 1182 pairstack[pair] = 0; 1183 tempfree(x); 1184 x = execute(a[2]); 1185 return(x); 1186 } 1187 return(False); 1188 } 1189 1190 Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ 1191 { 1192 Cell *x = 0, *y, *ap; 1193 char *s; 1194 int sep; 1195 char *t, temp, num[50], *fs = 0; 1196 int n, tempstat, arg3type; 1197 1198 y = execute(a[0]); /* source string */ 1199 s = getsval(y); 1200 arg3type = ptoi(a[3]); 1201 if (a[2] == 0) /* fs string */ 1202 fs = *FS; 1203 else if (arg3type == STRING) { /* split(str,arr,"string") */ 1204 x = execute(a[2]); 1205 fs = getsval(x); 1206 } else if (arg3type == REGEXPR) 1207 fs = "(regexpr)"; /* split(str,arr,/regexpr/) */ 1208 else 1209 FATAL("illegal type of split"); 1210 sep = *fs; 1211 ap = execute(a[1]); /* array name */ 1212 n = y->tval; 1213 y->tval |= DONTFREE; /* split(a[x], a); */ 1214 freesymtab(ap); 1215 y->tval = n; 1216 dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs) ); 1217 ap->tval &= ~STR; 1218 ap->tval |= ARR; 1219 ap->sval = (char *) makesymtab(NSYMTAB); 1220 1221 n = 0; 1222 if ((*s != '\0' && strlen(fs) > 1) || arg3type == REGEXPR) { /* reg expr */ 1223 fa *pfa; 1224 if (arg3type == REGEXPR) { /* it's ready already */ 1225 pfa = (fa *) a[2]; 1226 } else { 1227 pfa = makedfa(fs, 1); 1228 } 1229 if (nematch(pfa,s)) { 1230 tempstat = pfa->initstat; 1231 pfa->initstat = 2; 1232 do { 1233 n++; 1234 sprintf(num, "%d", n); 1235 temp = *patbeg; 1236 *patbeg = '\0'; 1237 if (is_number(s)) 1238 setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval); 1239 else 1240 setsymtab(num, s, 0.0, STR, (Array *) ap->sval); 1241 *patbeg = temp; 1242 s = patbeg + patlen; 1243 if (*(patbeg+patlen-1) == 0 || *s == 0) { 1244 n++; 1245 sprintf(num, "%d", n); 1246 setsymtab(num, "", 0.0, STR, (Array *) ap->sval); 1247 pfa->initstat = tempstat; 1248 goto spdone; 1249 } 1250 } while (nematch(pfa,s)); 1251 } 1252 n++; 1253 sprintf(num, "%d", n); 1254 if (is_number(s)) 1255 setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval); 1256 else 1257 setsymtab(num, s, 0.0, STR, (Array *) ap->sval); 1258 spdone: 1259 pfa = NULL; 1260 } else if (sep == ' ') { 1261 for (n = 0; ; ) { 1262 while (*s == ' ' || *s == '\t' || *s == '\n') 1263 s++; 1264 if (*s == 0) 1265 break; 1266 n++; 1267 t = s; 1268 do 1269 s++; 1270 while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0'); 1271 temp = *s; 1272 *s = '\0'; 1273 sprintf(num, "%d", n); 1274 if (is_number(t)) 1275 setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval); 1276 else 1277 setsymtab(num, t, 0.0, STR, (Array *) ap->sval); 1278 *s = temp; 1279 if (*s != 0) 1280 s++; 1281 } 1282 } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */ 1283 for (n = 0; *s != 0; s++) { 1284 char buf[2]; 1285 n++; 1286 sprintf(num, "%d", n); 1287 buf[0] = *s; 1288 buf[1] = 0; 1289 if (isdigit((uschar)buf[0])) 1290 setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval); 1291 else 1292 setsymtab(num, buf, 0.0, STR, (Array *) ap->sval); 1293 } 1294 } else if (*s != 0) { 1295 for (;;) { 1296 n++; 1297 t = s; 1298 while (*s != sep && *s != '\n' && *s != '\0') 1299 s++; 1300 temp = *s; 1301 *s = '\0'; 1302 sprintf(num, "%d", n); 1303 if (is_number(t)) 1304 setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval); 1305 else 1306 setsymtab(num, t, 0.0, STR, (Array *) ap->sval); 1307 *s = temp; 1308 if (*s++ == 0) 1309 break; 1310 } 1311 } 1312 tempfree(ap); 1313 tempfree(y); 1314 if (a[2] != 0 && arg3type == STRING) { 1315 tempfree(x); 1316 } 1317 x = gettemp(); 1318 x->tval = NUM; 1319 x->fval = n; 1320 return(x); 1321 } 1322 1323 Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */ 1324 { 1325 Cell *x; 1326 1327 x = execute(a[0]); 1328 if (istrue(x)) { 1329 tempfree(x); 1330 x = execute(a[1]); 1331 } else { 1332 tempfree(x); 1333 x = execute(a[2]); 1334 } 1335 return(x); 1336 } 1337 1338 Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */ 1339 { 1340 Cell *x; 1341 1342 x = execute(a[0]); 1343 if (istrue(x)) { 1344 tempfree(x); 1345 x = execute(a[1]); 1346 } else if (a[2] != 0) { 1347 tempfree(x); 1348 x = execute(a[2]); 1349 } 1350 return(x); 1351 } 1352 1353 Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */ 1354 { 1355 Cell *x; 1356 1357 for (;;) { 1358 x = execute(a[0]); 1359 if (!istrue(x)) 1360 return(x); 1361 tempfree(x); 1362 x = execute(a[1]); 1363 if (isbreak(x)) { 1364 x = True; 1365 return(x); 1366 } 1367 if (isnext(x) || isexit(x) || isret(x)) 1368 return(x); 1369 tempfree(x); 1370 } 1371 } 1372 1373 Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */ 1374 { 1375 Cell *x; 1376 1377 for (;;) { 1378 x = execute(a[0]); 1379 if (isbreak(x)) 1380 return True; 1381 if (isnext(x) || isexit(x) || isret(x)) 1382 return(x); 1383 tempfree(x); 1384 x = execute(a[1]); 1385 if (!istrue(x)) 1386 return(x); 1387 tempfree(x); 1388 } 1389 } 1390 1391 Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */ 1392 { 1393 Cell *x; 1394 1395 x = execute(a[0]); 1396 tempfree(x); 1397 for (;;) { 1398 if (a[1]!=0) { 1399 x = execute(a[1]); 1400 if (!istrue(x)) return(x); 1401 else tempfree(x); 1402 } 1403 x = execute(a[3]); 1404 if (isbreak(x)) /* turn off break */ 1405 return True; 1406 if (isnext(x) || isexit(x) || isret(x)) 1407 return(x); 1408 tempfree(x); 1409 x = execute(a[2]); 1410 tempfree(x); 1411 } 1412 } 1413 1414 Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */ 1415 { 1416 Cell *x, *vp, *arrayp, *cp, *ncp; 1417 Array *tp; 1418 int i; 1419 1420 vp = execute(a[0]); 1421 arrayp = execute(a[1]); 1422 if (!isarr(arrayp)) { 1423 return True; 1424 } 1425 tp = (Array *) arrayp->sval; 1426 tempfree(arrayp); 1427 for (i = 0; i < tp->size; i++) { /* this routine knows too much */ 1428 for (cp = tp->tab[i]; cp != NULL; cp = ncp) { 1429 setsval(vp, cp->nval); 1430 ncp = cp->cnext; 1431 x = execute(a[2]); 1432 if (isbreak(x)) { 1433 tempfree(vp); 1434 return True; 1435 } 1436 if (isnext(x) || isexit(x) || isret(x)) { 1437 tempfree(vp); 1438 return(x); 1439 } 1440 tempfree(x); 1441 } 1442 } 1443 return True; 1444 } 1445 1446 Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */ 1447 { 1448 Cell *x, *y; 1449 Awkfloat u; 1450 int t; 1451 char *p, *buf; 1452 Node *nextarg; 1453 FILE *fp; 1454 1455 t = ptoi(a[0]); 1456 x = execute(a[1]); 1457 nextarg = a[1]->nnext; 1458 switch (t) { 1459 case FLENGTH: 1460 u = strlen(getsval(x)); break; 1461 case FLOG: 1462 u = errcheck(log(getfval(x)), "log"); break; 1463 case FINT: 1464 modf(getfval(x), &u); break; 1465 case FEXP: 1466 u = errcheck(exp(getfval(x)), "exp"); break; 1467 case FSQRT: 1468 u = errcheck(sqrt(getfval(x)), "sqrt"); break; 1469 case FSIN: 1470 u = sin(getfval(x)); break; 1471 case FCOS: 1472 u = cos(getfval(x)); break; 1473 case FATAN: 1474 if (nextarg == 0) { 1475 WARNING("atan2 requires two arguments; returning 1.0"); 1476 u = 1.0; 1477 } else { 1478 y = execute(a[1]->nnext); 1479 u = atan2(getfval(x), getfval(y)); 1480 tempfree(y); 1481 nextarg = nextarg->nnext; 1482 } 1483 break; 1484 case FSYSTEM: 1485 fflush(stdout); /* in case something is buffered already */ 1486 u = (Awkfloat) system(getsval(x)) / 256; /* 256 is unix-dep */ 1487 break; 1488 case FRAND: 1489 /* in principle, rand() returns something in 0..RAND_MAX */ 1490 u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX; 1491 break; 1492 case FSRAND: 1493 if (isrec(x)) /* no argument provided */ 1494 u = time((time_t *)0); 1495 else 1496 u = getfval(x); 1497 srand((unsigned int) u); 1498 break; 1499 case FTOUPPER: 1500 case FTOLOWER: 1501 buf = tostring(getsval(x)); 1502 if (t == FTOUPPER) { 1503 for (p = buf; *p; p++) 1504 if (islower((uschar) *p)) 1505 *p = toupper(*p); 1506 } else { 1507 for (p = buf; *p; p++) 1508 if (isupper((uschar) *p)) 1509 *p = tolower(*p); 1510 } 1511 tempfree(x); 1512 x = gettemp(); 1513 setsval(x, buf); 1514 free(buf); 1515 return x; 1516 case FFLUSH: 1517 if ((fp = openfile(FFLUSH, getsval(x))) == NULL) 1518 u = EOF; 1519 else 1520 u = fflush(fp); 1521 break; 1522 default: /* can't happen */ 1523 FATAL("illegal function type %d", t); 1524 break; 1525 } 1526 tempfree(x); 1527 x = gettemp(); 1528 setfval(x, u); 1529 if (nextarg != 0) { 1530 WARNING("warning: function has too many arguments"); 1531 for ( ; nextarg; nextarg = nextarg->nnext) 1532 execute(nextarg); 1533 } 1534 return(x); 1535 } 1536 1537 Cell *printstat(Node **a, int n) /* print a[0] */ 1538 { 1539 Node *x; 1540 Cell *y; 1541 FILE *fp; 1542 1543 if (a[1] == 0) /* a[1] is redirection operator, a[2] is file */ 1544 fp = stdout; 1545 else 1546 fp = redirect(ptoi(a[1]), a[2]); 1547 for (x = a[0]; x != NULL; x = x->nnext) { 1548 y = execute(x); 1549 fputs(getsval(y), fp); 1550 tempfree(y); 1551 if (x->nnext == NULL) 1552 fputs(*ORS, fp); 1553 else 1554 fputs(*OFS, fp); 1555 } 1556 if (a[1] != 0) 1557 fflush(fp); 1558 if (ferror(fp)) 1559 FATAL("write error on %s", filename(fp)); 1560 return(True); 1561 } 1562 1563 Cell *nullproc(Node **a, int n) 1564 { 1565 n = n; 1566 a = a; 1567 return 0; 1568 } 1569 1570 1571 FILE *redirect(int a, Node *b) /* set up all i/o redirections */ 1572 { 1573 FILE *fp; 1574 Cell *x; 1575 char *fname; 1576 1577 x = execute(b); 1578 fname = getsval(x); 1579 fp = openfile(a, fname); 1580 if (fp == NULL) 1581 FATAL("can't open file %s", fname); 1582 tempfree(x); 1583 return fp; 1584 } 1585 1586 struct files { 1587 FILE *fp; 1588 char *fname; 1589 int mode; /* '|', 'a', 'w' => LE/LT, GT */ 1590 } files[FOPEN_MAX] ={ 1591 { NULL, "/dev/stdin", LT }, /* watch out: don't free this! */ 1592 { NULL, "/dev/stdout", GT }, 1593 { NULL, "/dev/stderr", GT } 1594 }; 1595 1596 void stdinit(void) /* in case stdin, etc., are not constants */ 1597 { 1598 files[0].fp = stdin; 1599 files[1].fp = stdout; 1600 files[2].fp = stderr; 1601 } 1602 1603 FILE *openfile(int a, char *us) 1604 { 1605 char *s = us; 1606 int i, m; 1607 FILE *fp = 0; 1608 1609 if (*s == '\0') 1610 FATAL("null file name in print or getline"); 1611 for (i=0; i < FOPEN_MAX; i++) 1612 if (files[i].fname && strcmp(s, files[i].fname) == 0) { 1613 if (a == files[i].mode || (a==APPEND && files[i].mode==GT)) 1614 return files[i].fp; 1615 if (a == FFLUSH) 1616 return files[i].fp; 1617 } 1618 if (a == FFLUSH) /* didn't find it, so don't create it! */ 1619 return NULL; 1620 1621 for (i=0; i < FOPEN_MAX; i++) 1622 if (files[i].fp == 0) 1623 break; 1624 if (i >= FOPEN_MAX) 1625 FATAL("%s makes too many open files", s); 1626 fflush(stdout); /* force a semblance of order */ 1627 m = a; 1628 if (a == GT) { 1629 fp = fopen(s, "w"); 1630 } else if (a == APPEND) { 1631 fp = fopen(s, "a"); 1632 m = GT; /* so can mix > and >> */ 1633 } else if (a == '|') { /* output pipe */ 1634 fp = popen(s, "w"); 1635 } else if (a == LE) { /* input pipe */ 1636 fp = popen(s, "r"); 1637 } else if (a == LT) { /* getline <file */ 1638 fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */ 1639 } else /* can't happen */ 1640 FATAL("illegal redirection %d", a); 1641 if (fp != NULL) { 1642 files[i].fname = tostring(s); 1643 files[i].fp = fp; 1644 files[i].mode = m; 1645 } 1646 return fp; 1647 } 1648 1649 char *filename(FILE *fp) 1650 { 1651 int i; 1652 1653 for (i = 0; i < FOPEN_MAX; i++) 1654 if (fp == files[i].fp) 1655 return files[i].fname; 1656 return "?"; 1657 } 1658 1659 Cell *closefile(Node **a, int n) 1660 { 1661 Cell *x; 1662 int i, stat; 1663 1664 n = n; 1665 x = execute(a[0]); 1666 getsval(x); 1667 stat = -1; 1668 for (i = 0; i < FOPEN_MAX; i++) { 1669 if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) { 1670 if (ferror(files[i].fp)) 1671 WARNING( "i/o error occurred on %s", files[i].fname ); 1672 if (files[i].mode == '|' || files[i].mode == LE) 1673 stat = pclose(files[i].fp); 1674 else 1675 stat = fclose(files[i].fp); 1676 if (stat == EOF) 1677 WARNING( "i/o error occurred closing %s", files[i].fname ); 1678 if (i > 2) /* don't do /dev/std... */ 1679 xfree(files[i].fname); 1680 files[i].fname = NULL; /* watch out for ref thru this */ 1681 files[i].fp = NULL; 1682 } 1683 } 1684 tempfree(x); 1685 x = gettemp(); 1686 setfval(x, (Awkfloat) stat); 1687 return(x); 1688 } 1689 1690 void closeall(void) 1691 { 1692 int i, stat; 1693 1694 for (i = 0; i < FOPEN_MAX; i++) { 1695 if (files[i].fp) { 1696 if (ferror(files[i].fp)) 1697 WARNING( "i/o error occurred on %s", files[i].fname ); 1698 if (files[i].mode == '|' || files[i].mode == LE) 1699 stat = pclose(files[i].fp); 1700 else 1701 stat = fclose(files[i].fp); 1702 if (stat == EOF && i != 0) 1703 WARNING( "i/o error occurred while closing %s", files[i].fname ); 1704 } 1705 } 1706 } 1707 1708 void backsub(char **pb_ptr, char **sptr_ptr); 1709 1710 Cell *sub(Node **a, int nnn) /* substitute command */ 1711 { 1712 char *sptr, *pb, *q; 1713 Cell *x, *y, *result; 1714 char *t, *buf; 1715 fa *pfa; 1716 int bufsz = recsize; 1717 1718 if ((buf = (char *) malloc(bufsz)) == NULL) 1719 FATAL("out of memory in sub"); 1720 x = execute(a[3]); /* target string */ 1721 t = getsval(x); 1722 if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ 1723 pfa = (fa *) a[1]; /* regular expression */ 1724 else { 1725 y = execute(a[1]); 1726 pfa = makedfa(getsval(y), 1); 1727 tempfree(y); 1728 } 1729 y = execute(a[2]); /* replacement string */ 1730 result = False; 1731 if (pmatch(pfa, t)) { 1732 sptr = t; 1733 adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub"); 1734 pb = buf; 1735 while (sptr < patbeg) 1736 *pb++ = *sptr++; 1737 sptr = getsval(y); 1738 while (*sptr != 0) { 1739 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub"); 1740 if (*sptr == '\\') { 1741 backsub(&pb, &sptr); 1742 } else if (*sptr == '&') { 1743 sptr++; 1744 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub"); 1745 for (q = patbeg; q < patbeg+patlen; ) 1746 *pb++ = *q++; 1747 } else 1748 *pb++ = *sptr++; 1749 } 1750 *pb = '\0'; 1751 if (pb > buf + bufsz) 1752 FATAL("sub result1 %.30s too big; can't happen", buf); 1753 sptr = patbeg + patlen; 1754 if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) { 1755 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub"); 1756 while ((*pb++ = *sptr++) != 0) 1757 ; 1758 } 1759 if (pb > buf + bufsz) 1760 FATAL("sub result2 %.30s too big; can't happen", buf); 1761 setsval(x, buf); /* BUG: should be able to avoid copy */ 1762 result = True;; 1763 } 1764 tempfree(x); 1765 tempfree(y); 1766 free(buf); 1767 return result; 1768 } 1769 1770 Cell *gsub(Node **a, int nnn) /* global substitute */ 1771 { 1772 Cell *x, *y; 1773 char *rptr, *sptr, *t, *pb, *q; 1774 char *buf; 1775 fa *pfa; 1776 int mflag, tempstat, num; 1777 int bufsz = recsize; 1778 1779 if ((buf = (char *) malloc(bufsz)) == NULL) 1780 FATAL("out of memory in gsub"); 1781 mflag = 0; /* if mflag == 0, can replace empty string */ 1782 num = 0; 1783 x = execute(a[3]); /* target string */ 1784 t = getsval(x); 1785 if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ 1786 pfa = (fa *) a[1]; /* regular expression */ 1787 else { 1788 y = execute(a[1]); 1789 pfa = makedfa(getsval(y), 1); 1790 tempfree(y); 1791 } 1792 y = execute(a[2]); /* replacement string */ 1793 if (pmatch(pfa, t)) { 1794 tempstat = pfa->initstat; 1795 pfa->initstat = 2; 1796 pb = buf; 1797 rptr = getsval(y); 1798 do { 1799 if (patlen == 0 && *patbeg != 0) { /* matched empty string */ 1800 if (mflag == 0) { /* can replace empty */ 1801 num++; 1802 sptr = rptr; 1803 while (*sptr != 0) { 1804 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub"); 1805 if (*sptr == '\\') { 1806 backsub(&pb, &sptr); 1807 } else if (*sptr == '&') { 1808 sptr++; 1809 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub"); 1810 for (q = patbeg; q < patbeg+patlen; ) 1811 *pb++ = *q++; 1812 } else 1813 *pb++ = *sptr++; 1814 } 1815 } 1816 if (*t == 0) /* at end */ 1817 goto done; 1818 adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub"); 1819 *pb++ = *t++; 1820 if (pb > buf + bufsz) /* BUG: not sure of this test */ 1821 FATAL("gsub result0 %.30s too big; can't happen", buf); 1822 mflag = 0; 1823 } 1824 else { /* matched nonempty string */ 1825 num++; 1826 sptr = t; 1827 adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub"); 1828 while (sptr < patbeg) 1829 *pb++ = *sptr++; 1830 sptr = rptr; 1831 while (*sptr != 0) { 1832 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub"); 1833 if (*sptr == '\\') { 1834 backsub(&pb, &sptr); 1835 } else if (*sptr == '&') { 1836 sptr++; 1837 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub"); 1838 for (q = patbeg; q < patbeg+patlen; ) 1839 *pb++ = *q++; 1840 } else 1841 *pb++ = *sptr++; 1842 } 1843 t = patbeg + patlen; 1844 if (patlen == 0 || *t == 0 || *(t-1) == 0) 1845 goto done; 1846 if (pb > buf + bufsz) 1847 FATAL("gsub result1 %.30s too big; can't happen", buf); 1848 mflag = 1; 1849 } 1850 } while (pmatch(pfa,t)); 1851 sptr = t; 1852 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub"); 1853 while ((*pb++ = *sptr++) != 0) 1854 ; 1855 done: if (pb > buf + bufsz) 1856 FATAL("gsub result2 %.30s too big; can't happen", buf); 1857 *pb = '\0'; 1858 setsval(x, buf); /* BUG: should be able to avoid copy + free */ 1859 pfa->initstat = tempstat; 1860 } 1861 tempfree(x); 1862 tempfree(y); 1863 x = gettemp(); 1864 x->tval = NUM; 1865 x->fval = num; 1866 free(buf); 1867 return(x); 1868 } 1869 1870 void backsub(char **pb_ptr, char **sptr_ptr) /* handle \\& variations */ 1871 { /* sptr[0] == '\\' */ 1872 char *pb = *pb_ptr, *sptr = *sptr_ptr; 1873 1874 if (sptr[1] == '\\') { 1875 if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */ 1876 *pb++ = '\\'; 1877 *pb++ = '&'; 1878 sptr += 4; 1879 } else if (sptr[2] == '&') { /* \\& -> \ + matched */ 1880 *pb++ = '\\'; 1881 sptr += 2; 1882 } else { /* \\x -> \\x */ 1883 *pb++ = *sptr++; 1884 *pb++ = *sptr++; 1885 } 1886 } else if (sptr[1] == '&') { /* literal & */ 1887 sptr++; 1888 *pb++ = *sptr++; 1889 } else /* literal \ */ 1890 *pb++ = *sptr++; 1891 1892 *pb_ptr = pb; 1893 *sptr_ptr = sptr; 1894 } 1895