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