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