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