1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.proprietary.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)run.c 4.10 (Berkeley) 05/26/93"; 10 #endif /* not lint */ 11 12 #include "sys/param.h" 13 #include "awk.def" 14 #include "math.h" 15 #include "awk.h" 16 #include "stdio.h" 17 #include "fcntl.h" 18 #define RECSIZE BUFSIZ 19 20 #define FILENUM NOFILE 21 struct 22 { 23 FILE *fp; 24 int type; 25 char *fname; 26 } files[FILENUM]; 27 FILE *popen(); 28 29 extern obj execute(), nodetoobj(), fieldel(), dopa2(), gettemp(); 30 #define PA2NUM 29 31 int pairstack[PA2NUM], paircnt; 32 node *winner = (node *)NULL; 33 #define MAXTMP 20 34 cell tmps[MAXTMP]; 35 static cell nullval ={EMPTY,EMPTY,0.0,NUM,0}; 36 obj true ={ OBOOL, BTRUE, 0 }; 37 obj false ={ OBOOL, BFALSE, 0 }; 38 39 run() 40 { 41 register int i; 42 43 execute(winner); 44 45 /* Wait for children to complete if output to a pipe. */ 46 for (i=0; i<FILENUM; i++) 47 if (files[i].fp && files[i].type == '|') 48 pclose(files[i].fp); 49 } 50 51 obj execute(u) node *u; 52 { 53 register obj (*proc)(); 54 obj x; 55 node *a; 56 extern char *printname[]; 57 58 if (u==(node *)NULL) 59 return(true); 60 for (a = u; ; a = a->nnext) { 61 if (cantexec(a)) 62 return(nodetoobj(a)); 63 if (a->ntype==NPA2) 64 proc=dopa2; 65 else { 66 if (notlegal(a->nobj)) 67 error(FATAL, "illegal statement %o", a); 68 proc = proctab[a->nobj-FIRSTTOKEN]; 69 } 70 x = (*proc)(a->narg,a->nobj); 71 if (isfld(x)) fldbld(); 72 if (isexpr(a)) 73 return(x); 74 /* a statement, goto next statement */ 75 if (isjump(x)) 76 return(x); 77 if (a->nnext == (node *)NULL) 78 return(x); 79 tempfree(x); 80 } 81 } 82 83 obj program(a, n) node **a; 84 { 85 obj x; 86 87 if (a[0] != NULL) { 88 x = execute(a[0]); 89 if (isexit(x)) 90 return(true); 91 if (isjump(x)) 92 error(FATAL, "unexpected break, continue or next"); 93 tempfree(x); 94 } 95 while (getrec()) { 96 x = execute(a[1]); 97 if (isexit(x)) break; 98 tempfree(x); 99 } 100 tempfree(x); 101 if (a[2] != NULL) { 102 x = execute(a[2]); 103 if (isbreak(x) || isnext(x) || iscont(x)) 104 error(FATAL, "unexpected break, continue or next"); 105 tempfree(x); 106 } 107 return(true); 108 } 109 110 obj getline() 111 { 112 obj x; 113 114 x = gettemp(); 115 setfval(x.optr, (awkfloat) getrec()); 116 return(x); 117 } 118 119 obj array(a,n) node **a; 120 { 121 obj x, y; 122 extern obj arrayel(); 123 124 x = execute(a[1]); 125 y = arrayel(a[0], x); 126 tempfree(x); 127 return(y); 128 } 129 130 obj arrayel(a,b) node *a; obj b; 131 { 132 char *s; 133 cell *x; 134 int i; 135 obj y; 136 137 s = getsval(b.optr); 138 x = (cell *) a; 139 if (!(x->tval&ARR)) { 140 strfree(x->sval); 141 x->tval &= ~STR; 142 x->tval |= ARR; 143 x->sval = (char *) makesymtab(); 144 } 145 y.optr = setsymtab(s, tostring(""), 0.0, STR|NUM, x->sval); 146 y.otype = OCELL; 147 y.osub = CVAR; 148 return(y); 149 } 150 151 obj matchop(a,n) node **a; 152 { 153 obj x; 154 char *s; 155 int i; 156 157 x = execute(a[0]); 158 if (isstr(x)) s = x.optr->sval; 159 else s = getsval(x.optr); 160 tempfree(x); 161 i = match(a[1], s); 162 if (n==MATCH && i==1 || n==NOTMATCH && i==0) 163 return(true); 164 else 165 return(false); 166 } 167 168 obj boolop(a,n) node **a; 169 { 170 obj x, y; 171 int i; 172 173 x = execute(a[0]); 174 i = istrue(x); 175 tempfree(x); 176 switch (n) { 177 default: 178 error(FATAL, "unknown boolean operator %d", n); 179 case BOR: 180 if (i) return(true); 181 y = execute(a[1]); 182 i = istrue(y); 183 tempfree(y); 184 if (i) return(true); 185 else return(false); 186 case AND: 187 if ( !i ) return(false); 188 y = execute(a[1]); 189 i = istrue(y); 190 tempfree(y); 191 if (i) return(true); 192 else return(false); 193 case NOT: 194 if (i) return(false); 195 else return(true); 196 } 197 } 198 199 obj relop(a,n) node **a; 200 { 201 int i; 202 obj x, y; 203 awkfloat j; 204 205 x = execute(a[0]); 206 y = execute(a[1]); 207 if (x.optr->tval&NUM && y.optr->tval&NUM) { 208 j = x.optr->fval - y.optr->fval; 209 i = j<0? -1: (j>0? 1: 0); 210 } else { 211 i = strcmp(getsval(x.optr), getsval(y.optr)); 212 } 213 tempfree(x); 214 tempfree(y); 215 switch (n) { 216 default: 217 error(FATAL, "unknown relational operator %d", n); 218 case LT: if (i<0) return(true); 219 else return(false); 220 case LE: if (i<=0) return(true); 221 else return(false); 222 case NE: if (i!=0) return(true); 223 else return(false); 224 case EQ: if (i==0) return(true); 225 else return(false); 226 case GE: if (i>=0) return(true); 227 else return(false); 228 case GT: if (i>0) return(true); 229 else return(false); 230 } 231 } 232 233 tempfree(a) obj a; 234 { 235 if (!istemp(a)) return; 236 strfree(a.optr->sval); 237 a.optr->tval = 0; 238 } 239 240 obj gettemp() 241 { 242 int i; 243 obj x; 244 245 for (i=0; i<MAXTMP; i++) 246 if (tmps[i].tval==0) 247 break; 248 if (i==MAXTMP) 249 error(FATAL, "out of temporaries in gettemp"); 250 x.optr = &tmps[i]; 251 tmps[i] = nullval; 252 x.otype = OCELL; 253 x.osub = CTEMP; 254 return(x); 255 } 256 257 obj indirect(a,n) node **a; 258 { 259 obj x; 260 int m; 261 cell *fieldadr(); 262 263 x = execute(a[0]); 264 m = getfval(x.optr); 265 tempfree(x); 266 x.optr = fieldadr(m); 267 x.otype = OCELL; 268 x.osub = CFLD; 269 return(x); 270 } 271 272 obj substr(a, nnn) node **a; 273 { 274 char *s, temp; 275 obj x; 276 int k, m, n; 277 278 x = execute(a[0]); 279 s = getsval(x.optr); 280 k = strlen(s) + 1; 281 tempfree(x); 282 x = execute(a[1]); 283 m = getfval(x.optr); 284 if (m <= 0) 285 m = 1; 286 else if (m > k) 287 m = k; 288 tempfree(x); 289 if (a[2] != nullstat) { 290 x = execute(a[2]); 291 n = getfval(x.optr); 292 tempfree(x); 293 } 294 else 295 n = k - 1; 296 if (n < 0) 297 n = 0; 298 else if (n > k - m) 299 n = k - m; 300 dprintf("substr: m=%d, n=%d, s=%s\n", m, n, s); 301 x = gettemp(); 302 temp = s[n+m-1]; /* with thanks to John Linderman */ 303 s[n+m-1] = '\0'; 304 setsval(x.optr, s + m - 1); 305 s[n+m-1] = temp; 306 return(x); 307 } 308 309 obj sindex(a, nnn) node **a; 310 { 311 obj x; 312 char *s1, *s2, *p1, *p2, *q; 313 314 x = execute(a[0]); 315 s1 = getsval(x.optr); 316 tempfree(x); 317 x = execute(a[1]); 318 s2 = getsval(x.optr); 319 tempfree(x); 320 321 x = gettemp(); 322 for (p1 = s1; *p1 != '\0'; p1++) { 323 for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++) 324 ; 325 if (*p2 == '\0') { 326 setfval(x.optr, (awkfloat) (p1 - s1 + 1)); /* origin 1 */ 327 return(x); 328 } 329 } 330 setfval(x.optr, 0.0); 331 return(x); 332 } 333 334 char *format(s,a) char *s; node *a; 335 { 336 char *buf, *p, fmt[200], *t, *os; 337 obj x; 338 int flag = 0; 339 awkfloat xf; 340 341 os = s; 342 p = buf = (char *)malloc(RECSIZE); 343 while (*s) { 344 if (*s != '%') { 345 *p++ = *s++; 346 continue; 347 } 348 if (*(s+1) == '%') { 349 *p++ = '%'; 350 s += 2; 351 continue; 352 } 353 for (t=fmt; (*t++ = *s) != '\0'; s++) 354 if (*s >= 'a' && *s <= 'z' && *s != 'l') 355 break; 356 *t = '\0'; 357 if (t >= fmt + sizeof(fmt)) 358 error(FATAL, "format item %.20s... too long", os); 359 switch (*s) { 360 case 'f': case 'e': case 'g': 361 flag = 1; 362 break; 363 case 'd': 364 flag = 2; 365 if(*(s-1) == 'l') break; 366 *(t-1) = 'l'; 367 *t = 'd'; 368 *++t = '\0'; 369 break; 370 case 'o': case 'x': 371 flag = *(s-1)=='l' ? 2 : 3; 372 break; 373 case 'c': 374 flag = 3; 375 break; 376 case 's': 377 flag = 4; 378 break; 379 default: 380 flag = 0; 381 break; 382 } 383 if (flag == 0) { 384 (void)sprintf(p, "%s", fmt); 385 p += strlen(p); 386 continue; 387 } 388 if (a == NULL) 389 error(FATAL, "not enough arguments in printf(%s)", os); 390 x = execute(a); 391 a = a->nnext; 392 if (flag != 4) /* watch out for converting to numbers! */ 393 xf = getfval(x.optr); 394 if (flag==1) (void)sprintf(p, fmt, xf); 395 else if (flag==2) (void)sprintf(p, fmt, (long)xf); 396 else if (flag==3) (void)sprintf(p, fmt, (int)xf); 397 else if (flag==4) (void)sprintf(p, fmt, x.optr->sval==NULL ? "" : getsval(x.optr)); 398 tempfree(x); 399 p += strlen(p); 400 s++; 401 } 402 *p = '\0'; 403 return(buf); 404 } 405 406 obj asprintf(a,n) node **a; 407 { 408 obj x; 409 node *y; 410 char *s; 411 412 y = a[0]->nnext; 413 x = execute(a[0]); 414 s = format(getsval(x.optr), y); 415 tempfree(x); 416 x = gettemp(); 417 x.optr->sval = s; 418 x.optr->tval = STR; 419 return(x); 420 } 421 422 obj arith(a,n) node **a; 423 { 424 awkfloat i,j; 425 obj x,y,z; 426 427 x = execute(a[0]); 428 i = getfval(x.optr); 429 tempfree(x); 430 if (n != UMINUS) { 431 y = execute(a[1]); 432 j = getfval(y.optr); 433 tempfree(y); 434 } 435 z = gettemp(); 436 switch (n) { 437 default: 438 error(FATAL, "illegal arithmetic operator %d", n); 439 case ADD: 440 i += j; 441 break; 442 case MINUS: 443 i -= j; 444 break; 445 case MULT: 446 i *= j; 447 break; 448 case DIVIDE: 449 if (j == 0) 450 error(FATAL, "division by zero"); 451 i /= j; 452 break; 453 case MOD: 454 if (j == 0) 455 error(FATAL, "division by zero"); 456 i = i - j*(long)(i/j); 457 break; 458 case UMINUS: 459 i = -i; 460 break; 461 } 462 setfval(z.optr, i); 463 return(z); 464 } 465 466 obj incrdecr(a, n) node **a; 467 { 468 obj x, z; 469 int k; 470 awkfloat xf; 471 472 x = execute(a[0]); 473 xf = getfval(x.optr); 474 k = (n == PREINCR || n == POSTINCR) ? 1 : -1; 475 if (n == PREINCR || n == PREDECR) { 476 setfval(x.optr, xf + k); 477 return(x); 478 } 479 z = gettemp(); 480 setfval(z.optr, xf); 481 setfval(x.optr, xf + k); 482 tempfree(x); 483 return(z); 484 } 485 486 487 obj assign(a,n) node **a; 488 { 489 obj x, y; 490 awkfloat xf, yf; 491 492 x = execute(a[0]); 493 y = execute(a[1]); 494 if (n == ASSIGN) { /* ordinary assignment */ 495 if ((y.optr->tval & (STR|NUM)) == (STR|NUM)) { 496 setsval(x.optr, y.optr->sval); 497 x.optr->fval = y.optr->fval; 498 x.optr->tval |= NUM; 499 } 500 else if (y.optr->tval & STR) 501 setsval(x.optr, y.optr->sval); 502 else if (y.optr->tval & NUM) 503 setfval(x.optr, y.optr->fval); 504 tempfree(y); 505 return(x); 506 } 507 xf = getfval(x.optr); 508 yf = getfval(y.optr); 509 switch (n) { 510 case ADDEQ: 511 xf += yf; 512 break; 513 case SUBEQ: 514 xf -= yf; 515 break; 516 case MULTEQ: 517 xf *= yf; 518 break; 519 case DIVEQ: 520 if (yf == 0) 521 error(FATAL, "division by zero"); 522 xf /= yf; 523 break; 524 case MODEQ: 525 if (yf == 0) 526 error(FATAL, "division by zero"); 527 xf = xf - yf*(long)(xf/yf); 528 break; 529 default: 530 error(FATAL, "illegal assignment operator %d", n); 531 break; 532 } 533 tempfree(y); 534 setfval(x.optr, xf); 535 return(x); 536 } 537 538 obj cat(a,q) node **a; 539 { 540 obj x,y,z; 541 int n1, n2; 542 char *s; 543 544 x = execute(a[0]); 545 y = execute(a[1]); 546 getsval(x.optr); 547 getsval(y.optr); 548 n1 = strlen(x.optr->sval); 549 n2 = strlen(y.optr->sval); 550 s = (char *) malloc(n1 + n2 + 1); 551 strcpy(s, x.optr->sval); 552 strcpy(s+n1, y.optr->sval); 553 tempfree(y); 554 z = gettemp(); 555 z.optr->sval = s; 556 z.optr->tval = STR; 557 tempfree(x); 558 return(z); 559 } 560 561 obj pastat(a,n) node **a; 562 { 563 obj x; 564 565 if (a[0]==nullstat) 566 x = true; 567 else 568 x = execute(a[0]); 569 if (istrue(x)) { 570 tempfree(x); 571 x = execute(a[1]); 572 } 573 return(x); 574 } 575 576 obj dopa2(a,n) node **a; 577 { 578 obj x; 579 580 if (pairstack[n]==0) { 581 x = execute(a[0]); 582 if (istrue(x)) 583 pairstack[n] = 1; 584 tempfree(x); 585 } 586 if (pairstack[n] == 1) { 587 x = execute(a[1]); 588 if (istrue(x)) 589 pairstack[n] = 0; 590 tempfree(x); 591 x = execute(a[2]); 592 return(x); 593 } 594 return(false); 595 } 596 597 obj aprintf(a,n) node **a; 598 { 599 obj x; 600 601 x = asprintf(a,n); 602 if (a[1]==NULL) { 603 printf("%s", x.optr->sval); 604 tempfree(x); 605 return(true); 606 } 607 redirprint(x.optr->sval, (int)a[1], a[2]); 608 return(x); 609 } 610 611 obj split(a,nnn) node **a; 612 { 613 obj x; 614 cell *ap; 615 register char *s, *p; 616 char *t, temp, num[5]; 617 register int sep; 618 int n, flag; 619 620 x = execute(a[0]); 621 s = getsval(x.optr); 622 tempfree(x); 623 if (a[2] == nullstat) 624 sep = **FS; 625 else { 626 x = execute(a[2]); 627 sep = getsval(x.optr)[0]; 628 tempfree(x); 629 } 630 ap = (cell *) a[1]; 631 freesymtab(ap); 632 dprintf("split: s=|%s|, a=%s, sep=|%c|\n", s, ap->nval, sep); 633 ap->tval &= ~STR; 634 ap->tval |= ARR; 635 ap->sval = (char *) makesymtab(); 636 637 n = 0; 638 if (sep == ' ') 639 for (n = 0; ; ) { 640 while (*s == ' ' || *s == '\t' || *s == '\n') 641 s++; 642 if (*s == 0) 643 break; 644 n++; 645 t = s; 646 do 647 s++; 648 while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0'); 649 temp = *s; 650 *s = '\0'; 651 (void)sprintf(num, "%d", n); 652 if (isanumber(t)) 653 setsymtab(num, tostring(t), atof(t), STR|NUM, ap->sval); 654 else 655 setsymtab(num, tostring(t), 0.0, STR, ap->sval); 656 *s = temp; 657 if (*s != 0) 658 s++; 659 } 660 else if (*s != 0) 661 for (;;) { 662 n++; 663 t = s; 664 while (*s != sep && *s != '\n' && *s != '\0') 665 s++; 666 temp = *s; 667 *s = '\0'; 668 (void)sprintf(num, "%d", n); 669 if (isanumber(t)) 670 setsymtab(num, tostring(t), atof(t), STR|NUM, ap->sval); 671 else 672 setsymtab(num, tostring(t), 0.0, STR, ap->sval); 673 *s = temp; 674 if (*s++ == 0) 675 break; 676 } 677 x = gettemp(); 678 x.optr->tval = NUM; 679 x.optr->fval = n; 680 return(x); 681 } 682 683 obj ifstat(a,n) node **a; 684 { 685 obj x; 686 687 x = execute(a[0]); 688 if (istrue(x)) { 689 tempfree(x); 690 x = execute(a[1]); 691 } 692 else if (a[2] != nullstat) { 693 tempfree(x); 694 x = execute(a[2]); 695 } 696 return(x); 697 } 698 699 obj whilestat(a,n) node **a; 700 { 701 obj x; 702 703 for (;;) { 704 x = execute(a[0]); 705 if (!istrue(x)) return(x); 706 tempfree(x); 707 x = execute(a[1]); 708 if (isbreak(x)) { 709 x = true; 710 return(x); 711 } 712 if (isnext(x) || isexit(x)) 713 return(x); 714 tempfree(x); 715 } 716 } 717 718 obj forstat(a,n) node **a; 719 { 720 obj x; 721 722 tempfree(execute(a[0])); 723 for (;;) { 724 if (a[1]!=nullstat) { 725 x = execute(a[1]); 726 if (!istrue(x)) return(x); 727 else tempfree(x); 728 } 729 x = execute(a[3]); 730 if (isbreak(x)) { /* turn off break */ 731 x = true; 732 return(x); 733 } 734 if (isnext(x) || isexit(x)) 735 return(x); 736 tempfree(x); 737 tempfree(execute(a[2])); 738 } 739 } 740 741 obj instat(a, n) node **a; 742 { 743 cell *vp, *arrayp, *cp, **tp; 744 obj x; 745 int i; 746 747 vp = (cell *) a[0]; 748 arrayp = (cell *) a[1]; 749 if (!(arrayp->tval & ARR)) 750 error(FATAL, "%s is not an array", arrayp->nval); 751 tp = (cell **) arrayp->sval; 752 for (i = 0; i < MAXSYM; i++) { /* this routine knows too much */ 753 for (cp = tp[i]; cp != NULL; cp = cp->nextval) { 754 setsval(vp, cp->nval); 755 x = execute(a[2]); 756 if (isbreak(x)) { 757 x = true; 758 return(x); 759 } 760 if (isnext(x) || isexit(x)) 761 return(x); 762 tempfree(x); 763 } 764 } 765 return (true); 766 } 767 768 obj jump(a,n) node **a; 769 { 770 obj x, y; 771 772 x.otype = OJUMP; 773 switch (n) { 774 default: 775 error(FATAL, "illegal jump type %d", n); 776 break; 777 case EXIT: 778 if (a[0] != 0) { 779 y = execute(a[0]); 780 errorflag = getfval(y.optr); 781 } 782 x.osub = JEXIT; 783 break; 784 case NEXT: 785 x.osub = JNEXT; 786 break; 787 case BREAK: 788 x.osub = JBREAK; 789 break; 790 case CONTINUE: 791 x.osub = JCONT; 792 break; 793 } 794 return(x); 795 } 796 797 obj fncn(a,n) node **a; 798 { 799 obj x; 800 awkfloat u; 801 int t; 802 803 t = (int) a[0]; 804 x = execute(a[1]); 805 if (t == FLENGTH) 806 u = (awkfloat) strlen(getsval(x.optr)); 807 else if (t == FLOG) 808 u = log(getfval(x.optr)); 809 else if (t == FINT) 810 u = (awkfloat) (long) getfval(x.optr); 811 else if (t == FEXP) 812 u = exp(getfval(x.optr)); 813 else if (t == FSQRT) 814 u = sqrt(getfval(x.optr)); 815 else 816 error(FATAL, "illegal function type %d", t); 817 tempfree(x); 818 x = gettemp(); 819 setfval(x.optr, u); 820 return(x); 821 } 822 823 obj print(a,n) node **a; 824 { 825 register node *x; 826 obj y; 827 char s[RECSIZE]; 828 829 s[0] = '\0'; 830 for (x=a[0]; x!=NULL; x=x->nnext) { 831 y = execute(x); 832 strcat(s, getsval(y.optr)); 833 tempfree(y); 834 if (x->nnext==NULL) 835 strcat(s, *ORS); 836 else 837 strcat(s, *OFS); 838 } 839 if (strlen(s) >= RECSIZE) 840 error(FATAL, "string %.20s ... too long to print", s); 841 if (a[1]==nullstat) { 842 printf("%s", s); 843 return(true); 844 } 845 redirprint(s, (int)a[1], a[2]); 846 return(false); 847 } 848 849 obj nullproc() {} 850 851 obj nodetoobj(a) node *a; 852 { 853 obj x; 854 855 x.optr = (cell *) a->nobj; 856 x.otype = OCELL; 857 x.osub = a->subtype; 858 if (isfld(x)) fldbld(); 859 return(x); 860 } 861 862 redirprint(s, a, b) char *s; node *b; 863 { 864 register int i; 865 obj x; 866 867 x = execute(b); 868 getsval(x.optr); 869 for (i=0; i<FILENUM; i++) 870 if (files[i].fp && strcmp(x.optr->sval, files[i].fname) == 0) 871 goto doit; 872 for (i=0; i<FILENUM; i++) 873 if (files[i].fp == 0) 874 break; 875 if (i >= FILENUM) 876 error(FATAL, "too many output files %d", i); 877 if (a == '|') /* a pipe! */ 878 files[i].fp = popen(x.optr->sval, "w"); 879 else if (a == APPEND) 880 files[i].fp = fopen(x.optr->sval, "a"); 881 else 882 files[i].fp = fopen(x.optr->sval, "w"); 883 if (files[i].fp == NULL) 884 error(FATAL, "can't open file %s", x.optr->sval); 885 if (fcntl(fileno(files[i].fp), F_SETFD, 1) < 0) 886 error(FATAL, "close on exec failure"); 887 files[i].fname = tostring(x.optr->sval); 888 files[i].type = a; 889 doit: 890 fprintf(files[i].fp, "%s", s); 891 #ifndef gcos 892 fflush(files[i].fp); /* in case someone is waiting for the output */ 893 #endif 894 tempfree(x); 895 } 896