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