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