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