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