|
|
1.1 ! root 1: /* ! 2: Copyright (c) 1989 AT&T ! 3: All Rights Reserved ! 4: ! 5: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. ! 6: ! 7: The copyright notice above does not evidence any ! 8: actual or intended publication of such source code. ! 9: */ ! 10: ! 11: #define tempfree(x) if (istemp(x)) tfree(x); else ! 12: ! 13: /* #define execute(p) (isvalue(p) ? (Cell *)((p)->narg[0]) : r_execute(p)) */ ! 14: #define execute(p) r_execute(p) ! 15: ! 16: #define DEBUG ! 17: #include <stdio.h> ! 18: #include <ctype.h> ! 19: #include <setjmp.h> ! 20: #include <math.h> ! 21: #include <string.h> ! 22: #include <stdlib.h> ! 23: #include <time.h> ! 24: #include "awk.h" ! 25: #include "y.tab.h" ! 26: ! 27: #ifdef _NFILE ! 28: #ifndef FOPEN_MAX ! 29: #define FOPEN_MAX _NFILE ! 30: #endif ! 31: #endif ! 32: ! 33: #ifndef FOPEN_MAX ! 34: #define FOPEN_MAX 40 /* max number of open files */ ! 35: #endif ! 36: ! 37: #ifndef RAND_MAX ! 38: #define RAND_MAX 32767 /* all that ansi guarantees */ ! 39: #endif ! 40: ! 41: jmp_buf env; ! 42: ! 43: #define getfval(p) (((p)->tval & (ARR|FLD|REC|NUM)) == NUM ? (p)->fval : r_getfval(p)) ! 44: #define getsval(p) (((p)->tval & (ARR|FLD|REC|STR)) == STR ? (p)->sval : r_getsval(p)) ! 45: ! 46: ! 47: #define PA2NUM 29 ! 48: int pairstack[PA2NUM], paircnt; ! 49: Node *winner = NULL; ! 50: Cell *tmps; ! 51: ! 52: static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM }; ! 53: Cell *true = &truecell; ! 54: static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM }; ! 55: Cell *false = &falsecell; ! 56: static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM }; ! 57: Cell *jbreak = &breakcell; ! 58: static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM }; ! 59: Cell *jcont = &contcell; ! 60: static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM }; ! 61: Cell *jnext = &nextcell; ! 62: static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM }; ! 63: Cell *jexit = &exitcell; ! 64: static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM }; ! 65: Cell *jret = &retcell; ! 66: static Cell tempcell ={ OCELL, CTEMP, 0, 0, 0.0, NUM }; ! 67: ! 68: Node *curnode = NULL; /* the node being executed, for debugging */ ! 69: ! 70: void run(Node *a) ! 71: { ! 72: execute(a); ! 73: closeall(); ! 74: } ! 75: ! 76: Cell *r_execute(Node *u) ! 77: { ! 78: register Cell *(*proc)(Node **, int); ! 79: register Cell *x; ! 80: register Node *a; ! 81: ! 82: if (u == NULL) ! 83: return(true); ! 84: for (a = u; ; a = a->nnext) { ! 85: curnode = a; ! 86: if (isvalue(a)) { ! 87: x = (Cell *) (a->narg[0]); ! 88: if ((x->tval & FLD) && !donefld) ! 89: fldbld(); ! 90: else if ((x->tval & REC) && !donerec) ! 91: recbld(); ! 92: return(x); ! 93: } ! 94: if (notlegal(a->nobj)) /* probably a Cell* but too risky to print */ ! 95: ERROR "illegal statement" FATAL; ! 96: proc = proctab[a->nobj-FIRSTTOKEN]; ! 97: x = (*proc)(a->narg, a->nobj); ! 98: if ((x->tval & FLD) && !donefld) ! 99: fldbld(); ! 100: else if ((x->tval & REC) && !donerec) ! 101: recbld(); ! 102: if (isexpr(a)) ! 103: return(x); ! 104: if (isjump(x)) ! 105: return(x); ! 106: if (a->nnext == NULL) ! 107: return(x); ! 108: tempfree(x); ! 109: } ! 110: } ! 111: ! 112: ! 113: Cell *program(Node **a, int n) ! 114: { ! 115: register Cell *x; ! 116: ! 117: if (setjmp(env) != 0) ! 118: goto ex; ! 119: if (a[0]) { /* BEGIN */ ! 120: x = execute(a[0]); ! 121: if (isexit(x)) ! 122: return(true); ! 123: if (isjump(x)) ! 124: ERROR "illegal break, continue or next from BEGIN" FATAL; ! 125: tempfree(x); ! 126: } ! 127: loop: ! 128: if (a[1] || a[2]) ! 129: while (getrec(record) > 0) { ! 130: x = execute(a[1]); ! 131: if (isexit(x)) ! 132: break; ! 133: tempfree(x); ! 134: } ! 135: ex: ! 136: if (setjmp(env) != 0) /* handles exit within END */ ! 137: goto ex1; ! 138: if (a[2]) { /* END */ ! 139: x = execute(a[2]); ! 140: if (isbreak(x) || isnext(x) || iscont(x)) ! 141: ERROR "illegal break, next, or continue from END" FATAL; ! 142: tempfree(x); ! 143: } ! 144: ex1: ! 145: return(true); ! 146: } ! 147: ! 148: struct Frame { ! 149: int nargs; /* number of arguments in this call */ ! 150: Cell *fcncell; /* pointer to Cell for function */ ! 151: Cell **args; /* pointer to array of arguments after execute */ ! 152: Cell *retval; /* return value */ ! 153: }; ! 154: ! 155: #define NARGS 30 ! 156: ! 157: struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */ ! 158: int nframe = 0; /* number of frames allocated */ ! 159: struct Frame *fp = NULL; /* frame pointer. bottom level unused */ ! 160: ! 161: Cell *call(Node **a, int n) ! 162: { ! 163: static Cell newcopycell = { OCELL, CCOPY, 0, (uchar *) "", 0.0, NUM|STR|DONTFREE }; ! 164: int i, ncall, ndef; ! 165: Node *x; ! 166: Cell *args[NARGS], *oargs[NARGS], *y, *z, *fcn; ! 167: uchar *s; ! 168: ! 169: fcn = execute(a[0]); /* the function itself */ ! 170: s = fcn->nval; ! 171: if (!isfunc(fcn)) ! 172: ERROR "calling undefined function %s", s FATAL; ! 173: if (frame == NULL) { ! 174: fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame)); ! 175: if (frame == NULL) ! 176: ERROR "out of space for stack frames calling %s", s FATAL; ! 177: } ! 178: for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */ ! 179: ncall++; ! 180: ndef = (int) fcn->fval; /* args in defn */ ! 181: dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, fp-frame) ); ! 182: if (ncall > ndef) ! 183: ERROR "function %s called with %d args, uses only %d", ! 184: s, ncall, ndef WARNING; ! 185: if (ncall + ndef > NARGS) ! 186: ERROR "function %s has %d arguments, limit %d", s, ncall+ndef, NARGS FATAL; ! 187: for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */ ! 188: dprintf( ("evaluate args[%d], fp=%d:\n", i, fp-frame) ); ! 189: y = execute(x); ! 190: oargs[i] = y; ! 191: dprintf( ("args[%d]: %s %f <%s>, t=%o\n", ! 192: i, y->nval, y->fval, isarr(y) ? "(array)" : (char*) y->sval, y->tval) ); ! 193: if (isfunc(y)) ! 194: ERROR "can't use function %s as argument in %s", y->nval, s FATAL; ! 195: if (isarr(y)) ! 196: args[i] = y; /* arrays by ref */ ! 197: else ! 198: args[i] = copycell(y); ! 199: tempfree(y); ! 200: } ! 201: for ( ; i < ndef; i++) { /* add null args for ones not provided */ ! 202: args[i] = gettemp(); ! 203: *args[i] = newcopycell; ! 204: } ! 205: fp++; /* now ok to up frame */ ! 206: if (fp >= frame + nframe) { ! 207: int dfp = fp - frame; /* old index */ ! 208: frame = (struct Frame *) ! 209: realloc((char *) frame, (nframe += 100) * sizeof(struct Frame)); ! 210: if (frame == NULL) ! 211: ERROR "out of space for stack frames in %s", s FATAL; ! 212: fp = frame + dfp; ! 213: } ! 214: fp->fcncell = fcn; ! 215: fp->args = args; ! 216: fp->nargs = ndef; /* number defined with (excess are locals) */ ! 217: fp->retval = gettemp(); ! 218: ! 219: dprintf( ("start exec of %s, fp=%d\n", s, fp-frame) ); ! 220: y = execute((Node *)(fcn->sval)); /* execute body */ ! 221: dprintf( ("finished exec of %s, fp=%d\n", s, fp-frame) ); ! 222: ! 223: for (i = 0; i < ndef; i++) { ! 224: Cell *t = fp->args[i]; ! 225: if (isarr(t)) { ! 226: if (t->csub == CCOPY) { ! 227: if (i >= ncall) { ! 228: freesymtab(t); ! 229: t->csub = CTEMP; ! 230: } else { ! 231: oargs[i]->tval = t->tval; ! 232: oargs[i]->tval &= ~(STR|NUM|DONTFREE); ! 233: oargs[i]->sval = t->sval; ! 234: tempfree(t); ! 235: } ! 236: } ! 237: } else if (t != y) { /* kludge to prevent freeing twice */ ! 238: t->csub = CTEMP; ! 239: tempfree(t); ! 240: } ! 241: } ! 242: tempfree(fcn); ! 243: if (isexit(y) || isnext(y)) ! 244: return y; ! 245: tempfree(y); /* this can free twice! */ ! 246: z = fp->retval; /* return value */ ! 247: dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) ); ! 248: fp--; ! 249: return(z); ! 250: } ! 251: ! 252: Cell *copycell(Cell *x) /* make a copy of a cell in a temp */ ! 253: { ! 254: Cell *y; ! 255: ! 256: y = gettemp(); ! 257: y->csub = CCOPY; /* prevents freeing until call is over */ ! 258: y->nval = x->nval; ! 259: y->sval = x->sval ? tostring(x->sval) : NULL; ! 260: y->fval = x->fval; ! 261: y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */ ! 262: /* is DONTFREE right? */ ! 263: return y; ! 264: } ! 265: ! 266: Cell *arg(Node **a, int n) ! 267: { ! 268: ! 269: n = (int) a[0]; /* argument number, counting from 0 */ ! 270: dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) ); ! 271: if (n+1 > fp->nargs) ! 272: ERROR "argument #%d of function %s was not supplied", ! 273: n+1, fp->fcncell->nval FATAL; ! 274: return fp->args[n]; ! 275: } ! 276: ! 277: Cell *jump(Node **a, int n) ! 278: { ! 279: register Cell *y; ! 280: ! 281: switch (n) { ! 282: case EXIT: ! 283: if (a[0] != NULL) { ! 284: y = execute(a[0]); ! 285: errorflag = getfval(y); ! 286: tempfree(y); ! 287: } ! 288: longjmp(env, 1); ! 289: case RETURN: ! 290: if (a[0] != NULL) { ! 291: y = execute(a[0]); ! 292: if ((y->tval & (STR|NUM)) == (STR|NUM)) { ! 293: setsval(fp->retval, getsval(y)); ! 294: fp->retval->fval = getfval(y); ! 295: fp->retval->tval |= NUM; ! 296: } ! 297: else if (y->tval & STR) ! 298: setsval(fp->retval, getsval(y)); ! 299: else if (y->tval & NUM) ! 300: setfval(fp->retval, getfval(y)); ! 301: else /* can't happen */ ! 302: ERROR "bad type variable %d", y->tval FATAL; ! 303: tempfree(y); ! 304: } ! 305: return(jret); ! 306: case NEXT: ! 307: return(jnext); ! 308: case BREAK: ! 309: return(jbreak); ! 310: case CONTINUE: ! 311: return(jcont); ! 312: default: /* can't happen */ ! 313: ERROR "illegal jump type %d", n FATAL; ! 314: } ! 315: return 0; /* not reached */ ! 316: } ! 317: ! 318: Cell *getline(Node **a, int n) ! 319: { ! 320: /* a[0] is variable, a[1] is operator, a[2] is filename */ ! 321: register Cell *r, *x; ! 322: uchar buf[RECSIZE]; ! 323: FILE *fp; ! 324: ! 325: fflush(stdout); /* in case someone is waiting for a prompt */ ! 326: r = gettemp(); ! 327: if (a[1] != NULL) { /* getline < file */ ! 328: x = execute(a[2]); /* filename */ ! 329: if ((int) a[1] == '|') /* input pipe */ ! 330: a[1] = (Node *) LE; /* arbitrary flag */ ! 331: fp = openfile((int) a[1], getsval(x)); ! 332: tempfree(x); ! 333: if (fp == NULL) ! 334: n = -1; ! 335: else ! 336: n = readrec(buf, sizeof(buf), fp); ! 337: if (n <= 0) { ! 338: ; ! 339: } else if (a[0] != NULL) { /* getline var <file */ ! 340: setsval(execute(a[0]), buf); ! 341: } else { /* getline <file */ ! 342: if (!(recloc->tval & DONTFREE)) ! 343: xfree(recloc->sval); ! 344: strcpy(record, buf); ! 345: recloc->sval = record; ! 346: recloc->tval = REC | STR | DONTFREE; ! 347: if (isnumber(recloc->sval)) { ! 348: recloc->fval = atof(recloc->sval); ! 349: recloc->tval |= NUM; ! 350: } ! 351: donerec = 1; donefld = 0; ! 352: } ! 353: } else { /* bare getline; use current input */ ! 354: if (a[0] == NULL) /* getline */ ! 355: n = getrec(record); ! 356: else { /* getline var */ ! 357: n = getrec(buf); ! 358: setsval(execute(a[0]), buf); ! 359: } ! 360: } ! 361: setfval(r, (Awkfloat) n); ! 362: return r; ! 363: } ! 364: ! 365: Cell *getnf(Node **a, int n) ! 366: { ! 367: if (donefld == 0) ! 368: fldbld(); ! 369: return (Cell *) a[0]; ! 370: } ! 371: ! 372: Cell *array(Node **a, int n) ! 373: { ! 374: register Cell *x, *y, *z; ! 375: register uchar *s; ! 376: register Node *np; ! 377: uchar buf[RECSIZE]; ! 378: ! 379: x = execute(a[0]); /* Cell* for symbol table */ ! 380: buf[0] = 0; ! 381: for (np = a[1]; np; np = np->nnext) { ! 382: y = execute(np); /* subscript */ ! 383: s = getsval(y); ! 384: strcat(buf, s); ! 385: if (np->nnext) ! 386: strcat(buf, *SUBSEP); ! 387: tempfree(y); ! 388: } ! 389: if (!isarr(x)) { ! 390: dprintf( ("making %s into an array\n", x->nval) ); ! 391: if (freeable(x)) ! 392: xfree(x->sval); ! 393: x->tval &= ~(STR|NUM|DONTFREE); ! 394: x->tval |= ARR; ! 395: x->sval = (uchar *) makesymtab(NSYMTAB); ! 396: } ! 397: z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval); ! 398: z->ctype = OCELL; ! 399: z->csub = CVAR; ! 400: tempfree(x); ! 401: return(z); ! 402: } ! 403: ! 404: Cell *adelete(Node **a, int n) ! 405: { ! 406: Cell *x, *y; ! 407: Node *np; ! 408: uchar buf[RECSIZE], *s; ! 409: ! 410: x = execute(a[0]); /* Cell* for symbol table */ ! 411: if (!isarr(x)) ! 412: return true; ! 413: buf[0] = 0; ! 414: for (np = a[1]; np; np = np->nnext) { ! 415: y = execute(np); /* subscript */ ! 416: s = getsval(y); ! 417: strcat(buf, s); ! 418: if (np->nnext) ! 419: strcat(buf, *SUBSEP); ! 420: tempfree(y); ! 421: } ! 422: freeelem(x, buf); ! 423: tempfree(x); ! 424: return true; ! 425: } ! 426: ! 427: Cell *intest(Node **a, int n) ! 428: { ! 429: register Cell *x, *ap, *k; ! 430: Node *p; ! 431: char buf[RECSIZE]; ! 432: uchar *s; ! 433: ! 434: ap = execute(a[1]); /* array name */ ! 435: /* if (!isarr(ap)) ! 436: ERROR "%s is not an array", ap->nval FATAL; */ ! 437: if (!isarr(ap)) { ! 438: dprintf( ("making %s into an array\n", ap->nval) ); ! 439: if (freeable(ap)) ! 440: xfree(ap->sval); ! 441: ap->tval &= ~(STR|NUM|DONTFREE); ! 442: ap->tval |= ARR; ! 443: ap->sval = (uchar *) makesymtab(NSYMTAB); ! 444: } ! 445: buf[0] = 0; ! 446: for (p = a[0]; p; p = p->nnext) { ! 447: x = execute(p); /* expr */ ! 448: s = getsval(x); ! 449: strcat(buf, s); ! 450: tempfree(x); ! 451: if (p->nnext) ! 452: strcat(buf, *SUBSEP); ! 453: } ! 454: k = lookup(buf, (Array *) ap->sval); ! 455: tempfree(ap); ! 456: if (k == NULL) ! 457: return(false); ! 458: else ! 459: return(true); ! 460: } ! 461: ! 462: ! 463: Cell *matchop(Node **a, int n) ! 464: { ! 465: register Cell *x, *y; ! 466: register uchar *s, *t; ! 467: register int i; ! 468: fa *pfa; ! 469: int (*mf)(fa *, uchar *) = match, mode = 0; ! 470: ! 471: if (n == MATCHFCN) { ! 472: mf = pmatch; ! 473: mode = 1; ! 474: } ! 475: x = execute(a[1]); ! 476: s = getsval(x); ! 477: if (a[0] == 0) ! 478: i = (*mf)((fa *) a[2], s); ! 479: else { ! 480: y = execute(a[2]); ! 481: t = getsval(y); ! 482: pfa = makedfa(t, mode); ! 483: i = (*mf)(pfa, s); ! 484: tempfree(y); ! 485: } ! 486: tempfree(x); ! 487: if (n == MATCHFCN) { ! 488: int start = patbeg - s + 1; ! 489: if (patlen < 0) ! 490: start = 0; ! 491: setfval(rstartloc, (Awkfloat) start); ! 492: setfval(rlengthloc, (Awkfloat) patlen); ! 493: x = gettemp(); ! 494: x->tval = NUM; ! 495: x->fval = start; ! 496: return x; ! 497: } else if (n == MATCH && i == 1 || n == NOTMATCH && i == 0) ! 498: return(true); ! 499: else ! 500: return(false); ! 501: } ! 502: ! 503: ! 504: Cell *boolop(Node **a, int n) ! 505: { ! 506: register Cell *x, *y; ! 507: register int i; ! 508: ! 509: x = execute(a[0]); ! 510: i = istrue(x); ! 511: tempfree(x); ! 512: switch (n) { ! 513: case BOR: ! 514: if (i) return(true); ! 515: y = execute(a[1]); ! 516: i = istrue(y); ! 517: tempfree(y); ! 518: if (i) return(true); ! 519: else return(false); ! 520: case AND: ! 521: if ( !i ) return(false); ! 522: y = execute(a[1]); ! 523: i = istrue(y); ! 524: tempfree(y); ! 525: if (i) return(true); ! 526: else return(false); ! 527: case NOT: ! 528: if (i) return(false); ! 529: else return(true); ! 530: default: /* can't happen */ ! 531: ERROR "unknown boolean operator %d", n FATAL; ! 532: } ! 533: return 0; /*NOTREACHED*/ ! 534: } ! 535: ! 536: Cell *relop(Node **a, int n) ! 537: { ! 538: register int i; ! 539: register Cell *x, *y; ! 540: Awkfloat j; ! 541: ! 542: x = execute(a[0]); ! 543: y = execute(a[1]); ! 544: if (x->tval&NUM && y->tval&NUM) { ! 545: j = x->fval - y->fval; ! 546: i = j<0? -1: (j>0? 1: 0); ! 547: } else { ! 548: i = strcmp(getsval(x), getsval(y)); ! 549: } ! 550: tempfree(x); ! 551: tempfree(y); ! 552: switch (n) { ! 553: case LT: if (i<0) return(true); ! 554: else return(false); ! 555: case LE: if (i<=0) return(true); ! 556: else return(false); ! 557: case NE: if (i!=0) return(true); ! 558: else return(false); ! 559: case EQ: if (i == 0) return(true); ! 560: else return(false); ! 561: case GE: if (i>=0) return(true); ! 562: else return(false); ! 563: case GT: if (i>0) return(true); ! 564: else return(false); ! 565: default: /* can't happen */ ! 566: ERROR "unknown relational operator %d", n FATAL; ! 567: } ! 568: return 0; /*NOTREACHED*/ ! 569: } ! 570: ! 571: void tfree(Cell *a) ! 572: { ! 573: if (freeable(a)) ! 574: xfree(a->sval); ! 575: if (a == tmps) ! 576: ERROR "tempcell list is curdled" FATAL; ! 577: a->cnext = tmps; ! 578: tmps = a; ! 579: } ! 580: ! 581: Cell *gettemp(void) ! 582: { int i; ! 583: register Cell *x; ! 584: ! 585: if (!tmps) { ! 586: tmps = (Cell *) calloc(100, sizeof(Cell)); ! 587: if (!tmps) ! 588: ERROR "out of space for temporaries" FATAL; ! 589: for(i = 1; i < 100; i++) ! 590: tmps[i-1].cnext = &tmps[i]; ! 591: tmps[i-1].cnext = 0; ! 592: } ! 593: x = tmps; ! 594: tmps = x->cnext; ! 595: *x = tempcell; ! 596: return(x); ! 597: } ! 598: ! 599: Cell *indirect(Node **a, int n) ! 600: { ! 601: register Cell *x; ! 602: register int m; ! 603: register uchar *s; ! 604: ! 605: x = execute(a[0]); ! 606: m = getfval(x); ! 607: if (m == 0 && !isnumber(s = getsval(x))) /* suspicion! */ ! 608: ERROR "illegal field $(%s)", s FATAL; ! 609: tempfree(x); ! 610: x = fieldadr(m); ! 611: x->ctype = OCELL; ! 612: x->csub = CFLD; ! 613: return(x); ! 614: } ! 615: ! 616: Cell *substr(Node **a, int nnn) ! 617: { ! 618: register int k, m, n; ! 619: register uchar *s; ! 620: int temp; ! 621: register Cell *x, *y, *z; ! 622: ! 623: x = execute(a[0]); ! 624: y = execute(a[1]); ! 625: if (a[2] != 0) ! 626: z = execute(a[2]); ! 627: s = getsval(x); ! 628: k = strlen(s) + 1; ! 629: if (k <= 1) { ! 630: tempfree(x); ! 631: tempfree(y); ! 632: if (a[2] != 0) ! 633: tempfree(z); ! 634: x = gettemp(); ! 635: setsval(x, ""); ! 636: return(x); ! 637: } ! 638: m = getfval(y); ! 639: if (m <= 0) ! 640: m = 1; ! 641: else if (m > k) ! 642: m = k; ! 643: tempfree(y); ! 644: if (a[2] != 0) { ! 645: n = getfval(z); ! 646: tempfree(z); ! 647: } else ! 648: n = k - 1; ! 649: if (n < 0) ! 650: n = 0; ! 651: else if (n > k - m) ! 652: n = k - m; ! 653: dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) ); ! 654: y = gettemp(); ! 655: temp = s[n+m-1]; /* with thanks to John Linderman */ ! 656: s[n+m-1] = '\0'; ! 657: setsval(y, s + m - 1); ! 658: s[n+m-1] = temp; ! 659: tempfree(x); ! 660: return(y); ! 661: } ! 662: ! 663: Cell *sindex(Node **a, int nnn) ! 664: { ! 665: register Cell *x, *y, *z; ! 666: register uchar *s1, *s2, *p1, *p2, *q; ! 667: Awkfloat v = 0.0; ! 668: ! 669: x = execute(a[0]); ! 670: s1 = getsval(x); ! 671: y = execute(a[1]); ! 672: s2 = getsval(y); ! 673: ! 674: z = gettemp(); ! 675: for (p1 = s1; *p1 != '\0'; p1++) { ! 676: for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++) ! 677: ; ! 678: if (*p2 == '\0') { ! 679: v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */ ! 680: break; ! 681: } ! 682: } ! 683: tempfree(x); ! 684: tempfree(y); ! 685: setfval(z, v); ! 686: return(z); ! 687: } ! 688: ! 689: format(uchar *buf, int bufsize, uchar *s, Node *a) ! 690: { ! 691: uchar fmt[RECSIZE]; ! 692: register uchar *p, *t, *os; ! 693: register Cell *x; ! 694: int flag = 0, n; ! 695: ! 696: os = s; ! 697: p = buf; ! 698: while (*s) { ! 699: if (p - buf >= bufsize) ! 700: return -1; ! 701: if (*s != '%') { ! 702: *p++ = *s++; ! 703: continue; ! 704: } ! 705: if (*(s+1) == '%') { ! 706: *p++ = '%'; ! 707: s += 2; ! 708: continue; ! 709: } ! 710: for (t=fmt; (*t++ = *s) != '\0'; s++) { ! 711: if (isalpha(*s) && *s != 'l' && *s != 'h' && *s != 'L') ! 712: break; /* the ansi panoply */ ! 713: if (*s == '*') { ! 714: x = execute(a); ! 715: a = a->nnext; ! 716: sprintf((char *)t-1, "%d", (int) getfval(x)); ! 717: t = fmt + strlen(fmt); ! 718: tempfree(x); ! 719: } ! 720: } ! 721: *t = '\0'; ! 722: if (t >= fmt + sizeof(fmt)) ! 723: ERROR "format item %.20s... too long", os FATAL; ! 724: switch (*s) { ! 725: case 'f': case 'e': case 'g': case 'E': case 'G': ! 726: flag = 1; ! 727: break; ! 728: case 'd': case 'i': ! 729: flag = 2; ! 730: if(*(s-1) == 'l') break; ! 731: *(t-1) = 'l'; ! 732: *t = 'd'; ! 733: *++t = '\0'; ! 734: break; ! 735: case 'o': case 'x': case 'X': case 'u': ! 736: flag = *(s-1) == 'l' ? 2 : 3; ! 737: break; ! 738: case 's': ! 739: flag = 4; ! 740: break; ! 741: case 'c': ! 742: flag = 5; ! 743: break; ! 744: default: ! 745: ERROR "weird printf conversion %s", fmt WARNING; ! 746: flag = 0; ! 747: break; ! 748: } ! 749: if (a == NULL) ! 750: ERROR "not enough args in printf(%s)", os FATAL; ! 751: x = execute(a); ! 752: a = a->nnext; ! 753: switch (flag) { ! 754: case 0: sprintf((char *)p, "%s", fmt); /* unknown, so dump it too */ ! 755: p += strlen(p); ! 756: sprintf((char *)p, "%s", getsval(x)); ! 757: break; ! 758: case 1: sprintf((char *)p, (char *)fmt, getfval(x)); break; ! 759: case 2: sprintf((char *)p, (char *)fmt, (long) getfval(x)); break; ! 760: case 3: sprintf((char *)p, (char *)fmt, (int) getfval(x)); break; ! 761: case 4: ! 762: t = getsval(x); ! 763: n = strlen(t); ! 764: if (n >= bufsize) ! 765: ERROR "huge string (%d chars) in printf %.30s...", ! 766: n, t FATAL; ! 767: sprintf((char *)p, (char *)fmt, t); ! 768: break; ! 769: case 5: isnum(x) ? sprintf((char *)p, (char *)fmt, (int) getfval(x)) ! 770: : sprintf((char *)p, (char *)fmt, getsval(x)[0]); ! 771: break; ! 772: } ! 773: tempfree(x); ! 774: p += strlen(p); ! 775: s++; ! 776: } ! 777: *p = '\0'; ! 778: for ( ; a; a = a->nnext) /* evaluate any remaining args */ ! 779: execute(a); ! 780: return 0; ! 781: } ! 782: ! 783: Cell *asprintf(Node **a, int n) ! 784: { ! 785: register Cell *x; ! 786: register Node *y; ! 787: uchar buf[3*RECSIZE]; ! 788: ! 789: y = a[0]->nnext; ! 790: x = execute(a[0]); ! 791: if (format(buf, sizeof buf, getsval(x), y) == -1) ! 792: ERROR "sprintf string %.40s... too long", buf FATAL; ! 793: tempfree(x); ! 794: x = gettemp(); ! 795: x->sval = tostring(buf); ! 796: x->tval = STR; ! 797: return(x); ! 798: } ! 799: ! 800: Cell *aprintf(Node **a, int n) ! 801: { ! 802: FILE *fp; ! 803: register Cell *x; ! 804: register Node *y; ! 805: uchar buf[3*RECSIZE]; ! 806: ! 807: y = a[0]->nnext; ! 808: x = execute(a[0]); ! 809: if (format(buf, sizeof buf, getsval(x), y) == -1) ! 810: ERROR "printf string %.40s... too long", buf FATAL; ! 811: tempfree(x); ! 812: if (a[1] == NULL) { ! 813: fputs((char *)buf, stdout); ! 814: if (ferror(stdout)) ! 815: ERROR "write error on stdout" FATAL; ! 816: } else { ! 817: fp = redirect((int)a[1], a[2]); ! 818: fputs((char *)buf, fp); ! 819: fflush(fp); ! 820: if (ferror(fp)) ! 821: ERROR "write error on %s", filename(fp) FATAL; ! 822: } ! 823: return(true); ! 824: } ! 825: ! 826: Cell *arith(Node **a, int n) ! 827: { ! 828: Awkfloat i, j; ! 829: double v; ! 830: register Cell *x, *y, *z; ! 831: ! 832: x = execute(a[0]); ! 833: i = getfval(x); ! 834: tempfree(x); ! 835: if (n != UMINUS) { ! 836: y = execute(a[1]); ! 837: j = getfval(y); ! 838: tempfree(y); ! 839: } ! 840: z = gettemp(); ! 841: switch (n) { ! 842: case ADD: ! 843: i += j; ! 844: break; ! 845: case MINUS: ! 846: i -= j; ! 847: break; ! 848: case MULT: ! 849: i *= j; ! 850: break; ! 851: case DIVIDE: ! 852: if (j == 0) ! 853: ERROR "division by zero" FATAL; ! 854: i /= j; ! 855: break; ! 856: case MOD: ! 857: if (j == 0) ! 858: ERROR "division by zero in mod" FATAL; ! 859: modf(i/j, &v); ! 860: i = i - j * v; ! 861: break; ! 862: case UMINUS: ! 863: i = -i; ! 864: break; ! 865: case POWER: ! 866: if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */ ! 867: i = ipow(i, (int) j); ! 868: else ! 869: i = errcheck(pow(i, j), "pow"); ! 870: break; ! 871: default: /* can't happen */ ! 872: ERROR "illegal arithmetic operator %d", n FATAL; ! 873: } ! 874: setfval(z, i); ! 875: return(z); ! 876: } ! 877: ! 878: double ipow(double x, int n) ! 879: { ! 880: double v; ! 881: ! 882: if (n <= 0) ! 883: return 1; ! 884: v = ipow(x, n/2); ! 885: if (n % 2 == 0) ! 886: return v * v; ! 887: else ! 888: return x * v * v; ! 889: } ! 890: ! 891: Cell *incrdecr(Node **a, int n) ! 892: { ! 893: register Cell *x, *z; ! 894: register int k; ! 895: Awkfloat xf; ! 896: ! 897: x = execute(a[0]); ! 898: xf = getfval(x); ! 899: k = (n == PREINCR || n == POSTINCR) ? 1 : -1; ! 900: if (n == PREINCR || n == PREDECR) { ! 901: setfval(x, xf + k); ! 902: return(x); ! 903: } ! 904: z = gettemp(); ! 905: setfval(z, xf); ! 906: setfval(x, xf + k); ! 907: tempfree(x); ! 908: return(z); ! 909: } ! 910: ! 911: Cell *assign(Node **a, int n) ! 912: { ! 913: register Cell *x, *y; ! 914: Awkfloat xf, yf; ! 915: double v; ! 916: ! 917: y = execute(a[1]); ! 918: x = execute(a[0]); ! 919: if (n == ASSIGN) { /* ordinary assignment */ ! 920: if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: leave alone! */ ! 921: ; /* unless it's a field */ ! 922: else if ((y->tval & (STR|NUM)) == (STR|NUM)) { ! 923: setsval(x, getsval(y)); ! 924: x->fval = getfval(y); ! 925: x->tval |= NUM; ! 926: } ! 927: else if (y->tval & STR) ! 928: setsval(x, getsval(y)); ! 929: else if (y->tval & NUM) ! 930: setfval(x, getfval(y)); ! 931: else ! 932: funnyvar(y, "read value of"); ! 933: tempfree(y); ! 934: return(x); ! 935: } ! 936: xf = getfval(x); ! 937: yf = getfval(y); ! 938: switch (n) { ! 939: case ADDEQ: ! 940: xf += yf; ! 941: break; ! 942: case SUBEQ: ! 943: xf -= yf; ! 944: break; ! 945: case MULTEQ: ! 946: xf *= yf; ! 947: break; ! 948: case DIVEQ: ! 949: if (yf == 0) ! 950: ERROR "division by zero in /=" FATAL; ! 951: xf /= yf; ! 952: break; ! 953: case MODEQ: ! 954: if (yf == 0) ! 955: ERROR "division by zero in %%=" FATAL; ! 956: modf(xf/yf, &v); ! 957: xf = xf - yf * v; ! 958: break; ! 959: case POWEQ: ! 960: if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */ ! 961: xf = ipow(xf, (int) yf); ! 962: else ! 963: xf = errcheck(pow(xf, yf), "pow"); ! 964: break; ! 965: default: ! 966: ERROR "illegal assignment operator %d", n FATAL; ! 967: break; ! 968: } ! 969: tempfree(y); ! 970: setfval(x, xf); ! 971: return(x); ! 972: } ! 973: ! 974: Cell *cat(Node **a, int q) ! 975: { ! 976: register Cell *x, *y, *z; ! 977: register int n1, n2; ! 978: register uchar *s; ! 979: ! 980: x = execute(a[0]); ! 981: y = execute(a[1]); ! 982: getsval(x); ! 983: getsval(y); ! 984: n1 = strlen(x->sval); ! 985: n2 = strlen(y->sval); ! 986: s = (uchar *) malloc(n1 + n2 + 1); ! 987: if (s == NULL) ! 988: ERROR "out of space concatenating %.15s... and %.15s...", ! 989: x->sval, y->sval FATAL; ! 990: strcpy(s, x->sval); ! 991: strcpy(s+n1, y->sval); ! 992: tempfree(y); ! 993: z = gettemp(); ! 994: z->sval = s; ! 995: z->tval = STR; ! 996: tempfree(x); ! 997: return(z); ! 998: } ! 999: ! 1000: Cell *pastat(Node **a, int n) /* a[0] { a[1] } */ ! 1001: { ! 1002: register Cell *x; ! 1003: ! 1004: if (a[0] == 0) ! 1005: x = execute(a[1]); ! 1006: else { ! 1007: x = execute(a[0]); ! 1008: if (istrue(x)) { ! 1009: tempfree(x); ! 1010: x = execute(a[1]); ! 1011: } ! 1012: } ! 1013: return x; ! 1014: } ! 1015: ! 1016: Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */ ! 1017: { ! 1018: register Cell *x; ! 1019: register int pair; ! 1020: ! 1021: pair = (int) a[3]; ! 1022: if (pairstack[pair] == 0) { ! 1023: x = execute(a[0]); ! 1024: if (istrue(x)) ! 1025: pairstack[pair] = 1; ! 1026: tempfree(x); ! 1027: } ! 1028: if (pairstack[pair] == 1) { ! 1029: x = execute(a[1]); ! 1030: if (istrue(x)) ! 1031: pairstack[pair] = 0; ! 1032: tempfree(x); ! 1033: x = execute(a[2]); ! 1034: return(x); ! 1035: } ! 1036: return(false); ! 1037: } ! 1038: ! 1039: Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ ! 1040: { ! 1041: Cell *x, *y, *ap; ! 1042: register uchar *s; ! 1043: register int sep; ! 1044: uchar *t, temp, num[10], *fs; ! 1045: int n, tempstat; ! 1046: ! 1047: y = execute(a[0]); /* source string */ ! 1048: s = getsval(y); ! 1049: if (a[2] == 0) /* fs string */ ! 1050: fs = *FS; ! 1051: else if ((int) a[3] == STRING) { /* split(str,arr,"string") */ ! 1052: x = execute(a[2]); ! 1053: fs = getsval(x); ! 1054: } else if ((int) a[3] == REGEXPR) ! 1055: fs = (uchar*) "(regexpr)"; /* split(str,arr,/regexpr/) */ ! 1056: else ! 1057: ERROR "illegal type of split()" FATAL; ! 1058: sep = *fs; ! 1059: ap = execute(a[1]); /* array name */ ! 1060: freesymtab(ap); ! 1061: dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs) ); ! 1062: ap->tval &= ~STR; ! 1063: ap->tval |= ARR; ! 1064: ap->sval = (uchar *) makesymtab(NSYMTAB); ! 1065: ! 1066: n = 0; ! 1067: if (*s != '\0' && strlen(fs) > 1 || (int) a[3] == REGEXPR) { /* reg expr */ ! 1068: fa *pfa; ! 1069: if ((int) a[3] == REGEXPR) { /* it's ready already */ ! 1070: pfa = (fa *) a[2]; ! 1071: } else { ! 1072: pfa = makedfa(fs, 1); ! 1073: } ! 1074: if (nematch(pfa,s)) { ! 1075: tempstat = pfa->initstat; ! 1076: pfa->initstat = 2; ! 1077: do { ! 1078: n++; ! 1079: sprintf((char *)num, "%d", n); ! 1080: temp = *patbeg; ! 1081: *patbeg = '\0'; ! 1082: if (isnumber(s)) ! 1083: setsymtab(num, s, atof((char *)s), STR|NUM, (Array *) ap->sval); ! 1084: else ! 1085: setsymtab(num, s, 0.0, STR, (Array *) ap->sval); ! 1086: *patbeg = temp; ! 1087: s = patbeg + patlen; ! 1088: if (*(patbeg+patlen-1) == 0 || *s == 0) { ! 1089: n++; ! 1090: sprintf((char *)num, "%d", n); ! 1091: setsymtab(num, "", 0.0, STR, (Array *) ap->sval); ! 1092: pfa->initstat = tempstat; ! 1093: goto spdone; ! 1094: } ! 1095: } while (nematch(pfa,s)); ! 1096: } ! 1097: n++; ! 1098: sprintf((char *)num, "%d", n); ! 1099: if (isnumber(s)) ! 1100: setsymtab(num, s, atof((char *)s), STR|NUM, (Array *) ap->sval); ! 1101: else ! 1102: setsymtab(num, s, 0.0, STR, (Array *) ap->sval); ! 1103: spdone: ! 1104: pfa = NULL; ! 1105: } else if (sep == ' ') { ! 1106: for (n = 0; ; ) { ! 1107: while (*s == ' ' || *s == '\t' || *s == '\n') ! 1108: s++; ! 1109: if (*s == 0) ! 1110: break; ! 1111: n++; ! 1112: t = s; ! 1113: do ! 1114: s++; ! 1115: while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0'); ! 1116: temp = *s; ! 1117: *s = '\0'; ! 1118: sprintf((char *)num, "%d", n); ! 1119: if (isnumber(t)) ! 1120: setsymtab(num, t, atof((char *)t), STR|NUM, (Array *) ap->sval); ! 1121: else ! 1122: setsymtab(num, t, 0.0, STR, (Array *) ap->sval); ! 1123: *s = temp; ! 1124: if (*s != 0) ! 1125: s++; ! 1126: } ! 1127: } else if (*s != 0) { ! 1128: for (;;) { ! 1129: n++; ! 1130: t = s; ! 1131: while (*s != sep && *s != '\n' && *s != '\0') ! 1132: s++; ! 1133: temp = *s; ! 1134: *s = '\0'; ! 1135: sprintf((char *)num, "%d", n); ! 1136: if (isnumber(t)) ! 1137: setsymtab(num, t, atof((char *)t), STR|NUM, (Array *) ap->sval); ! 1138: else ! 1139: setsymtab(num, t, 0.0, STR, (Array *) ap->sval); ! 1140: *s = temp; ! 1141: if (*s++ == 0) ! 1142: break; ! 1143: } ! 1144: } ! 1145: tempfree(ap); ! 1146: tempfree(y); ! 1147: if (a[2] != 0 && (int) a[3] == STRING) ! 1148: tempfree(x); ! 1149: x = gettemp(); ! 1150: x->tval = NUM; ! 1151: x->fval = n; ! 1152: return(x); ! 1153: } ! 1154: ! 1155: Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */ ! 1156: { ! 1157: register Cell *x; ! 1158: ! 1159: x = execute(a[0]); ! 1160: if (istrue(x)) { ! 1161: tempfree(x); ! 1162: x = execute(a[1]); ! 1163: } else { ! 1164: tempfree(x); ! 1165: x = execute(a[2]); ! 1166: } ! 1167: return(x); ! 1168: } ! 1169: ! 1170: Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */ ! 1171: { ! 1172: register Cell *x; ! 1173: ! 1174: x = execute(a[0]); ! 1175: if (istrue(x)) { ! 1176: tempfree(x); ! 1177: x = execute(a[1]); ! 1178: } else if (a[2] != 0) { ! 1179: tempfree(x); ! 1180: x = execute(a[2]); ! 1181: } ! 1182: return(x); ! 1183: } ! 1184: ! 1185: Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */ ! 1186: { ! 1187: register Cell *x; ! 1188: ! 1189: for (;;) { ! 1190: x = execute(a[0]); ! 1191: if (!istrue(x)) ! 1192: return(x); ! 1193: tempfree(x); ! 1194: x = execute(a[1]); ! 1195: if (isbreak(x)) { ! 1196: x = true; ! 1197: return(x); ! 1198: } ! 1199: if (isnext(x) || isexit(x) || isret(x)) ! 1200: return(x); ! 1201: tempfree(x); ! 1202: } ! 1203: } ! 1204: ! 1205: Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */ ! 1206: { ! 1207: register Cell *x; ! 1208: ! 1209: for (;;) { ! 1210: x = execute(a[0]); ! 1211: if (isbreak(x)) ! 1212: return true; ! 1213: if (isnext(x) || isexit(x) || isret(x)) ! 1214: return(x); ! 1215: tempfree(x); ! 1216: x = execute(a[1]); ! 1217: if (!istrue(x)) ! 1218: return(x); ! 1219: tempfree(x); ! 1220: } ! 1221: } ! 1222: ! 1223: Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */ ! 1224: { ! 1225: register Cell *x; ! 1226: ! 1227: x = execute(a[0]); ! 1228: tempfree(x); ! 1229: for (;;) { ! 1230: if (a[1]!=0) { ! 1231: x = execute(a[1]); ! 1232: if (!istrue(x)) return(x); ! 1233: else tempfree(x); ! 1234: } ! 1235: x = execute(a[3]); ! 1236: if (isbreak(x)) /* turn off break */ ! 1237: return true; ! 1238: if (isnext(x) || isexit(x) || isret(x)) ! 1239: return(x); ! 1240: tempfree(x); ! 1241: x = execute(a[2]); ! 1242: tempfree(x); ! 1243: } ! 1244: } ! 1245: ! 1246: Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */ ! 1247: { ! 1248: register Cell *x, *vp, *arrayp, *cp, *ncp; ! 1249: Array *tp; ! 1250: int i; ! 1251: ! 1252: vp = execute(a[0]); ! 1253: arrayp = execute(a[1]); ! 1254: if (!isarr(arrayp)) { ! 1255: /* ERROR "%s is not an array", arrayp->nval FATAL; */ ! 1256: return true; ! 1257: } ! 1258: tp = (Array *) arrayp->sval; ! 1259: tempfree(arrayp); ! 1260: for (i = 0; i < tp->size; i++) { /* this routine knows too much */ ! 1261: for (cp = tp->tab[i]; cp != NULL; cp = ncp) { ! 1262: setsval(vp, cp->nval); ! 1263: ncp = cp->cnext; ! 1264: x = execute(a[2]); ! 1265: if (isbreak(x)) { ! 1266: tempfree(vp); ! 1267: return true; ! 1268: } ! 1269: if (isnext(x) || isexit(x) || isret(x)) { ! 1270: tempfree(vp); ! 1271: return(x); ! 1272: } ! 1273: tempfree(x); ! 1274: } ! 1275: } ! 1276: return true; ! 1277: } ! 1278: ! 1279: /* if someone ever wants to run over the arrays in sorted order: */ ! 1280: ! 1281: /* ! 1282: *int qstrcmp(p, q) ! 1283: * uchar **p, **q; ! 1284: *{ ! 1285: * return strcmp(*p, *q); ! 1286: *} ! 1287: */ ! 1288: ! 1289: /*Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */ ! 1290: /*{ ! 1291: /* register Cell *x, *vp, *arrayp, *cp, *ncp, *ret; ! 1292: /* Array *tp; ! 1293: /* int i, ne; ! 1294: /*#define BIGENOUGH 1000 ! 1295: /* uchar *elems[BIGENOUGH], **ep; ! 1296: /* ! 1297: /* vp = execute(a[0]); ! 1298: /* arrayp = execute(a[1]); ! 1299: /* if (!isarr(arrayp)) ! 1300: /* ERROR "%s is not an array", arrayp->nval FATAL; ! 1301: /* tp = (Array *) arrayp->sval; ! 1302: /* tempfree(arrayp); ! 1303: /* ep = elems; ! 1304: /* ret = true; ! 1305: /* if (tp->nelem >= BIGENOUGH) ! 1306: /* ep = (uchar **) malloc(tp->nelem * sizeof(char *)); ! 1307: /* ! 1308: /* for (i = ne = 0; i < tp->size; i++) ! 1309: /* for (cp = tp->tab[i]; cp != NULL; cp = cp->cnext) ! 1310: /* ep[ne++] = cp->nval; ! 1311: /* if (ne != tp->nelem) ! 1312: /* ERROR "can't happen: lost elems %d vs. %d", ne, tp->nelem FATAL; ! 1313: /* qsort(ep, ne, sizeof(char *), qstrcmp); ! 1314: /* for (i = 0; i < ne; i++) { ! 1315: /* setsval(vp, ep[i]); ! 1316: /* x = execute(a[2]); ! 1317: /* if (isbreak(x)) { ! 1318: /* tempfree(vp); ! 1319: /* break; ! 1320: /* } ! 1321: /* if (isnext(x) || isexit(x) || isret(x)) { ! 1322: /* tempfree(vp); ! 1323: /* ret = x; ! 1324: /* break; ! 1325: /* } ! 1326: /* tempfree(x); ! 1327: /* } ! 1328: /* if (ep != elems) ! 1329: /* free(ep); ! 1330: /* return ret; ! 1331: /*} ! 1332: */ ! 1333: ! 1334: ! 1335: Cell *bltin(Node **a, int n) ! 1336: { ! 1337: register Cell *x, *y; ! 1338: Awkfloat u; ! 1339: register int t; ! 1340: uchar *p, buf[RECSIZE]; ! 1341: Node *nextarg; ! 1342: FILE *fp; ! 1343: ! 1344: t = (int) a[0]; ! 1345: x = execute(a[1]); ! 1346: nextarg = a[1]->nnext; ! 1347: switch (t) { ! 1348: case FLENGTH: ! 1349: u = (Awkfloat) strlen(getsval(x)); break; ! 1350: case FLOG: ! 1351: u = errcheck(log(getfval(x)), "log"); break; ! 1352: case FINT: ! 1353: modf(getfval(x), &u); break; ! 1354: case FEXP: ! 1355: u = errcheck(exp(getfval(x)), "exp"); break; ! 1356: case FSQRT: ! 1357: u = errcheck(sqrt(getfval(x)), "sqrt"); break; ! 1358: case FSIN: ! 1359: u = sin(getfval(x)); break; ! 1360: case FCOS: ! 1361: u = cos(getfval(x)); break; ! 1362: case FATAN: ! 1363: if (nextarg == 0) { ! 1364: ERROR "atan2 requires two arguments; returning 1.0" WARNING; ! 1365: u = 1.0; ! 1366: } else { ! 1367: y = execute(a[1]->nnext); ! 1368: u = atan2(getfval(x), getfval(y)); ! 1369: tempfree(y); ! 1370: nextarg = nextarg->nnext; ! 1371: } ! 1372: break; ! 1373: case FSYSTEM: ! 1374: fflush(stdout); /* in case something is buffered already */ ! 1375: u = (Awkfloat) system((char *)getsval(x)) / 256; /* 256 is unix-dep */ ! 1376: break; ! 1377: case FRAND: ! 1378: /* in principle, rand() returns something in 0..RAND_MAX */ ! 1379: u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX; ! 1380: break; ! 1381: case FSRAND: ! 1382: if (x->tval & REC) /* no argument provided */ ! 1383: u = time((long *)0); ! 1384: else ! 1385: u = getfval(x); ! 1386: srand((int) u); u = (int) u; ! 1387: break; ! 1388: case FTOUPPER: ! 1389: case FTOLOWER: ! 1390: strcpy(buf, getsval(x)); ! 1391: if (t == FTOUPPER) { ! 1392: for (p = buf; *p; p++) ! 1393: if (islower(*p)) ! 1394: *p = toupper(*p); ! 1395: } else { ! 1396: for (p = buf; *p; p++) ! 1397: if (isupper(*p)) ! 1398: *p = tolower(*p); ! 1399: } ! 1400: tempfree(x); ! 1401: x = gettemp(); ! 1402: setsval(x, buf); ! 1403: return x; ! 1404: case FFLUSH: ! 1405: if ((fp = openfile(GT, getsval(x))) == NULL) ! 1406: u = EOF; ! 1407: else ! 1408: u = fflush(fp); ! 1409: break; ! 1410: default: /* can't happen */ ! 1411: ERROR "illegal function type %d", t FATAL; ! 1412: break; ! 1413: } ! 1414: tempfree(x); ! 1415: x = gettemp(); ! 1416: setfval(x, u); ! 1417: if (nextarg != 0) { ! 1418: ERROR "warning: function has too many arguments" WARNING; ! 1419: for ( ; nextarg; nextarg = nextarg->nnext) ! 1420: execute(nextarg); ! 1421: } ! 1422: return(x); ! 1423: } ! 1424: ! 1425: Cell *printstat(Node **a, int n) ! 1426: { ! 1427: register Node *x; ! 1428: register Cell *y; ! 1429: FILE *fp; ! 1430: ! 1431: if (a[1] == 0) ! 1432: fp = stdout; ! 1433: else ! 1434: fp = redirect((int)a[1], a[2]); ! 1435: for (x = a[0]; x != NULL; x = x->nnext) { ! 1436: y = execute(x); ! 1437: fputs((char *)getsval(y), fp); ! 1438: tempfree(y); ! 1439: if (x->nnext == NULL) ! 1440: fputs((char *)*ORS, fp); ! 1441: else ! 1442: fputs((char *)*OFS, fp); ! 1443: } ! 1444: if (a[1] != 0) ! 1445: fflush(fp); ! 1446: if (ferror(fp)) ! 1447: ERROR "write error on %s", filename(fp) FATAL; ! 1448: return(true); ! 1449: } ! 1450: ! 1451: Cell *nullproc(Node **a, int n) ! 1452: { ! 1453: n; ! 1454: a; ! 1455: return 0; ! 1456: } ! 1457: ! 1458: ! 1459: FILE *redirect(int a, Node *b) ! 1460: { ! 1461: FILE *fp; ! 1462: Cell *x; ! 1463: uchar *fname; ! 1464: ! 1465: x = execute(b); ! 1466: fname = getsval(x); ! 1467: fp = openfile(a, fname); ! 1468: if (fp == NULL) ! 1469: ERROR "can't open file %s", fname FATAL; ! 1470: tempfree(x); ! 1471: return fp; ! 1472: } ! 1473: ! 1474: struct files { ! 1475: FILE *fp; ! 1476: uchar *fname; ! 1477: int mode; /* '|', 'a', 'w' => LE/LT, GT */ ! 1478: } files[FOPEN_MAX] ={ ! 1479: { stdin, "/dev/stdin", LT }, /* watch out: don't free this! */ ! 1480: { stdout, "/dev/stdout", GT }, ! 1481: { stderr, "/dev/stderr", GT } ! 1482: }; ! 1483: ! 1484: FILE *openfile(int a, uchar *us) ! 1485: { ! 1486: char *s = us; ! 1487: register int i, m; ! 1488: register FILE *fp; ! 1489: ! 1490: if (*s == '\0') ! 1491: ERROR "null file name in print or getline" FATAL; ! 1492: for (i=0; i < FOPEN_MAX; i++) ! 1493: if (files[i].fname && strcmp(s, files[i].fname) == 0) ! 1494: if (a == files[i].mode || a==APPEND && files[i].mode==GT) ! 1495: return files[i].fp; ! 1496: for (i=0; i < FOPEN_MAX; i++) ! 1497: if (files[i].fp == 0) ! 1498: break; ! 1499: if (i >= FOPEN_MAX) ! 1500: ERROR "%s makes too many open files", s FATAL; ! 1501: fflush(stdout); /* force a semblance of order */ ! 1502: m = a; ! 1503: if (a == GT) { ! 1504: fp = fopen(s, "w"); ! 1505: } else if (a == APPEND) { ! 1506: fp = fopen(s, "a"); ! 1507: m = GT; /* so can mix > and >> */ ! 1508: } else if (a == '|') { /* output pipe */ ! 1509: fp = popen(s, "w"); ! 1510: } else if (a == LE) { /* input pipe */ ! 1511: fp = popen(s, "r"); ! 1512: } else if (a == LT) { /* getline <file */ ! 1513: fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */ ! 1514: } else /* can't happen */ ! 1515: ERROR "illegal redirection %d", a FATAL; ! 1516: if (fp != NULL) { ! 1517: files[i].fname = tostring(s); ! 1518: files[i].fp = fp; ! 1519: files[i].mode = m; ! 1520: } ! 1521: return fp; ! 1522: } ! 1523: ! 1524: uchar *filename(FILE *fp) ! 1525: { ! 1526: int i; ! 1527: ! 1528: for (i = 0; i < FOPEN_MAX; i++) ! 1529: if (fp == files[i].fp) ! 1530: return files[i].fname; ! 1531: return "???"; ! 1532: } ! 1533: ! 1534: Cell *closefile(Node **a, int n) ! 1535: { ! 1536: register Cell *x; ! 1537: int i, stat; ! 1538: ! 1539: n; ! 1540: x = execute(a[0]); ! 1541: getsval(x); ! 1542: for (i = 0; i < FOPEN_MAX; i++) ! 1543: if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) { ! 1544: if (ferror(files[i].fp)) ! 1545: ERROR "i/o error occurred on %s", files[i].fname WARNING; ! 1546: if (files[i].mode == '|' || files[i].mode == LE) ! 1547: stat = pclose(files[i].fp); ! 1548: else ! 1549: stat = fclose(files[i].fp); ! 1550: if (stat == EOF) ! 1551: ERROR "i/o error occurred closing %s", files[i].fname WARNING; ! 1552: if (i > 2) /* don't do /dev/std... */ ! 1553: xfree(files[i].fname); ! 1554: files[i].fname = NULL; /* watch out for ref thru this */ ! 1555: files[i].fp = NULL; ! 1556: } ! 1557: tempfree(x); ! 1558: return(true); ! 1559: } ! 1560: ! 1561: void closeall(void) ! 1562: { ! 1563: int i, stat; ! 1564: ! 1565: for (i = 0; i < FOPEN_MAX; i++) ! 1566: if (files[i].fp) { ! 1567: if (ferror(files[i].fp)) ! 1568: ERROR "i/o error occurred on %s", files[i].fname WARNING; ! 1569: if (files[i].mode == '|' || files[i].mode == LE) ! 1570: stat = pclose(files[i].fp); ! 1571: else ! 1572: stat = fclose(files[i].fp); ! 1573: if (stat == EOF) ! 1574: ERROR "i/o error occurred while closing %s", files[i].fname WARNING; ! 1575: } ! 1576: } ! 1577: ! 1578: #define SUBSIZE (20 * RECSIZE) ! 1579: ! 1580: Cell *sub(Node **a, int nnn) ! 1581: { ! 1582: register uchar *sptr, *pb, *q; ! 1583: register Cell *x, *y, *result; ! 1584: uchar buf[SUBSIZE], *t; ! 1585: fa *pfa; ! 1586: ! 1587: x = execute(a[3]); /* target string */ ! 1588: t = getsval(x); ! 1589: if (a[0] == 0) ! 1590: pfa = (fa *) a[1]; /* regular expression */ ! 1591: else { ! 1592: y = execute(a[1]); ! 1593: pfa = makedfa(getsval(y), 1); ! 1594: tempfree(y); ! 1595: } ! 1596: y = execute(a[2]); /* replacement string */ ! 1597: result = false; ! 1598: if (pmatch(pfa, t)) { ! 1599: pb = buf; ! 1600: sptr = t; ! 1601: while (sptr < patbeg) ! 1602: *pb++ = *sptr++; ! 1603: sptr = getsval(y); ! 1604: while (*sptr != 0 && pb < buf + SUBSIZE - 1) ! 1605: if (*sptr == '\\' && *(sptr+1) == '&') { ! 1606: sptr++; /* skip \, */ ! 1607: *pb++ = *sptr++; /* add & */ ! 1608: } else if (*sptr == '&') { ! 1609: sptr++; ! 1610: for (q = patbeg; q < patbeg+patlen; ) ! 1611: *pb++ = *q++; ! 1612: } else ! 1613: *pb++ = *sptr++; ! 1614: *pb = '\0'; ! 1615: if (pb >= buf + SUBSIZE) ! 1616: ERROR "sub() result %.50s too big", buf FATAL; ! 1617: sptr = patbeg + patlen; ! 1618: if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) ! 1619: while (*pb++ = *sptr++) ! 1620: ; ! 1621: if (pb >= buf + SUBSIZE) ! 1622: ERROR "sub() result %.50s too big", buf FATAL; ! 1623: setsval(x, buf); ! 1624: result = true;; ! 1625: } ! 1626: tempfree(x); ! 1627: tempfree(y); ! 1628: return result; ! 1629: } ! 1630: ! 1631: Cell *gsub(Node **a, int nnn) ! 1632: { ! 1633: register Cell *x, *y; ! 1634: register uchar *rptr, *sptr, *t, *pb; ! 1635: uchar buf[SUBSIZE]; ! 1636: register fa *pfa; ! 1637: int mflag, tempstat, num; ! 1638: ! 1639: mflag = 0; /* if mflag == 0, can replace empty string */ ! 1640: num = 0; ! 1641: x = execute(a[3]); /* target string */ ! 1642: t = getsval(x); ! 1643: if (a[0] == 0) ! 1644: pfa = (fa *) a[1]; /* regular expression */ ! 1645: else { ! 1646: y = execute(a[1]); ! 1647: pfa = makedfa(getsval(y), 1); ! 1648: tempfree(y); ! 1649: } ! 1650: y = execute(a[2]); /* replacement string */ ! 1651: if (pmatch(pfa, t)) { ! 1652: tempstat = pfa->initstat; ! 1653: pfa->initstat = 2; ! 1654: pb = buf; ! 1655: rptr = getsval(y); ! 1656: do { ! 1657: /* ! 1658: uchar *p; ! 1659: int i; ! 1660: printf("target string: %s, *patbeg = %o, patlen = %d\n", ! 1661: t, *patbeg, patlen); ! 1662: printf(" match found: "); ! 1663: p=patbeg; ! 1664: for (i=0; i<patlen; i++) ! 1665: printf("%c", *p++); ! 1666: printf("\n"); ! 1667: */ ! 1668: if (patlen == 0 && *patbeg != 0) { /* matched empty string */ ! 1669: if (mflag == 0) { /* can replace empty */ ! 1670: num++; ! 1671: sptr = rptr; ! 1672: while (*sptr != 0 && pb < buf + SUBSIZE-1) ! 1673: if (*sptr == '\\' && *(sptr+1) == '&') { ! 1674: sptr++; ! 1675: *pb++ = *sptr++; ! 1676: } else if (*sptr == '&') { ! 1677: uchar *q; ! 1678: sptr++; ! 1679: for (q = patbeg; q < patbeg+patlen; ) ! 1680: *pb++ = *q++; ! 1681: } else ! 1682: *pb++ = *sptr++; ! 1683: } ! 1684: if (*t == 0) /* at end */ ! 1685: goto done; ! 1686: *pb++ = *t++; ! 1687: if (pb >= buf + SUBSIZE-1) ! 1688: ERROR "gsub() result %.50s too big", buf FATAL; ! 1689: mflag = 0; ! 1690: } ! 1691: else { /* matched nonempty string */ ! 1692: num++; ! 1693: sptr = t; ! 1694: while (sptr < patbeg && pb < buf + SUBSIZE-1) ! 1695: *pb++ = *sptr++; ! 1696: sptr = rptr; ! 1697: while (*sptr != 0 && pb < buf + SUBSIZE-1) ! 1698: if (*sptr == '\\' && *(sptr+1) == '&') { ! 1699: sptr++; ! 1700: *pb++ = *sptr++; ! 1701: } else if (*sptr == '&') { ! 1702: uchar *q; ! 1703: sptr++; ! 1704: for (q = patbeg; q < patbeg+patlen; ) ! 1705: *pb++ = *q++; ! 1706: } else ! 1707: *pb++ = *sptr++; ! 1708: t = patbeg + patlen; ! 1709: if ((*(t-1) == 0) || (*t == 0)) ! 1710: goto done; ! 1711: if (pb >= buf + SUBSIZE-1) ! 1712: ERROR "gsub() result %.50s too big", buf FATAL; ! 1713: mflag = 1; ! 1714: } ! 1715: } while (pmatch(pfa,t)); ! 1716: sptr = t; ! 1717: while (*pb++ = *sptr++) ! 1718: ; ! 1719: done: if (pb >= buf + SUBSIZE-1) ! 1720: ERROR "gsub() result %.50s too big", buf FATAL; ! 1721: *pb = '\0'; ! 1722: setsval(x, buf); ! 1723: pfa->initstat = tempstat; ! 1724: } ! 1725: tempfree(x); ! 1726: tempfree(y); ! 1727: x = gettemp(); ! 1728: x->tval = NUM; ! 1729: x->fval = num; ! 1730: return(x); ! 1731: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.