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