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