14b588458SPeter Avalos /**************************************************************** 24b588458SPeter Avalos Copyright (C) Lucent Technologies 1997 34b588458SPeter Avalos All Rights Reserved 44b588458SPeter Avalos 54b588458SPeter Avalos Permission to use, copy, modify, and distribute this software and 64b588458SPeter Avalos its documentation for any purpose and without fee is hereby 74b588458SPeter Avalos granted, provided that the above copyright notice appear in all 84b588458SPeter Avalos copies and that both that the copyright notice and this 94b588458SPeter Avalos permission notice and warranty disclaimer appear in supporting 104b588458SPeter Avalos documentation, and that the name Lucent Technologies or any of 114b588458SPeter Avalos its entities not be used in advertising or publicity pertaining 124b588458SPeter Avalos to distribution of the software without specific, written prior 134b588458SPeter Avalos permission. 144b588458SPeter Avalos 154b588458SPeter Avalos LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 164b588458SPeter Avalos INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 174b588458SPeter Avalos IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 184b588458SPeter Avalos SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 194b588458SPeter Avalos WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 204b588458SPeter Avalos IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 214b588458SPeter Avalos ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 224b588458SPeter Avalos THIS SOFTWARE. 234b588458SPeter Avalos ****************************************************************/ 244b588458SPeter Avalos 254b588458SPeter Avalos #define DEBUG 264b588458SPeter Avalos #include <stdio.h> 274b588458SPeter Avalos #include <ctype.h> 28*1d48fce0SDaniel Fojt #include <errno.h> 29*1d48fce0SDaniel Fojt #include <wchar.h> 30*1d48fce0SDaniel Fojt #include <wctype.h> 31*1d48fce0SDaniel Fojt #include <fcntl.h> 324b588458SPeter Avalos #include <setjmp.h> 334b588458SPeter Avalos #include <limits.h> 344b588458SPeter Avalos #include <math.h> 354b588458SPeter Avalos #include <string.h> 364b588458SPeter Avalos #include <stdlib.h> 374b588458SPeter Avalos #include <time.h> 38*1d48fce0SDaniel Fojt #include <sys/types.h> 39*1d48fce0SDaniel Fojt #include <sys/wait.h> 404b588458SPeter Avalos #include "awk.h" 414b588458SPeter Avalos #include "ytab.h" 424b588458SPeter Avalos 43*1d48fce0SDaniel Fojt static void stdinit(void); 44*1d48fce0SDaniel Fojt static void flush_all(void); 454b588458SPeter Avalos 46*1d48fce0SDaniel Fojt #if 1 47*1d48fce0SDaniel Fojt #define tempfree(x) do { if (istemp(x)) tfree(x); } while (/*CONSTCOND*/0) 48*1d48fce0SDaniel Fojt #else 494b588458SPeter Avalos void tempfree(Cell *p) { 504b588458SPeter Avalos if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) { 514b588458SPeter Avalos WARNING("bad csub %d in Cell %d %s", 524b588458SPeter Avalos p->csub, p->ctype, p->sval); 534b588458SPeter Avalos } 544b588458SPeter Avalos if (istemp(p)) 554b588458SPeter Avalos tfree(p); 564b588458SPeter Avalos } 57*1d48fce0SDaniel Fojt #endif 584b588458SPeter Avalos 594b588458SPeter Avalos /* do we really need these? */ 604b588458SPeter Avalos /* #ifdef _NFILE */ 614b588458SPeter Avalos /* #ifndef FOPEN_MAX */ 624b588458SPeter Avalos /* #define FOPEN_MAX _NFILE */ 634b588458SPeter Avalos /* #endif */ 644b588458SPeter Avalos /* #endif */ 654b588458SPeter Avalos /* */ 664b588458SPeter Avalos /* #ifndef FOPEN_MAX */ 674b588458SPeter Avalos /* #define FOPEN_MAX 40 */ /* max number of open files */ 684b588458SPeter Avalos /* #endif */ 694b588458SPeter Avalos /* */ 704b588458SPeter Avalos /* #ifndef RAND_MAX */ 714b588458SPeter Avalos /* #define RAND_MAX 32767 */ /* all that ansi guarantees */ 724b588458SPeter Avalos /* #endif */ 734b588458SPeter Avalos 744b588458SPeter Avalos jmp_buf env; 754b588458SPeter Avalos extern int pairstack[]; 760020174dSPeter Avalos extern Awkfloat srand_seed; 774b588458SPeter Avalos 784b588458SPeter Avalos Node *winner = NULL; /* root of parse tree */ 794b588458SPeter Avalos Cell *tmps; /* free temporary cells for execution */ 804b588458SPeter Avalos 81*1d48fce0SDaniel Fojt static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM, NULL, NULL }; 824b588458SPeter Avalos Cell *True = &truecell; 83*1d48fce0SDaniel Fojt static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM, NULL, NULL }; 844b588458SPeter Avalos Cell *False = &falsecell; 85*1d48fce0SDaniel Fojt static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM, NULL, NULL }; 864b588458SPeter Avalos Cell *jbreak = &breakcell; 87*1d48fce0SDaniel Fojt static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM, NULL, NULL }; 884b588458SPeter Avalos Cell *jcont = &contcell; 89*1d48fce0SDaniel Fojt static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM, NULL, NULL }; 904b588458SPeter Avalos Cell *jnext = &nextcell; 91*1d48fce0SDaniel Fojt static Cell nextfilecell ={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM, NULL, NULL }; 924b588458SPeter Avalos Cell *jnextfile = &nextfilecell; 93*1d48fce0SDaniel Fojt static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM, NULL, NULL }; 944b588458SPeter Avalos Cell *jexit = &exitcell; 95*1d48fce0SDaniel Fojt static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM, NULL, NULL }; 964b588458SPeter Avalos Cell *jret = &retcell; 97*1d48fce0SDaniel Fojt static Cell tempcell ={ OCELL, CTEMP, 0, EMPTY, 0.0, NUM|STR|DONTFREE, NULL, NULL }; 984b588458SPeter Avalos 994b588458SPeter Avalos Node *curnode = NULL; /* the node being executed, for debugging */ 1004b588458SPeter Avalos 1014b588458SPeter Avalos /* buffer memory management */ 1024b588458SPeter Avalos int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr, 1034b588458SPeter Avalos const char *whatrtn) 1044b588458SPeter Avalos /* pbuf: address of pointer to buffer being managed 1054b588458SPeter Avalos * psiz: address of buffer size variable 1064b588458SPeter Avalos * minlen: minimum length of buffer needed 1074b588458SPeter Avalos * quantum: buffer size quantum 1084b588458SPeter Avalos * pbptr: address of movable pointer into buffer, or 0 if none 1094b588458SPeter Avalos * whatrtn: name of the calling routine if failure should cause fatal error 1104b588458SPeter Avalos * 1114b588458SPeter Avalos * return 0 for realloc failure, !=0 for success 1124b588458SPeter Avalos */ 1134b588458SPeter Avalos { 1144b588458SPeter Avalos if (minlen > *psiz) { 1154b588458SPeter Avalos char *tbuf; 1164b588458SPeter Avalos int rminlen = quantum ? minlen % quantum : 0; 1174b588458SPeter Avalos int boff = pbptr ? *pbptr - *pbuf : 0; 1184b588458SPeter Avalos /* round up to next multiple of quantum */ 1194b588458SPeter Avalos if (rminlen) 1204b588458SPeter Avalos minlen += quantum - rminlen; 121*1d48fce0SDaniel Fojt tbuf = realloc(*pbuf, minlen); 1224b588458SPeter Avalos dprintf( ("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, *pbuf, tbuf) ); 1234b588458SPeter Avalos if (tbuf == NULL) { 1244b588458SPeter Avalos if (whatrtn) 1254b588458SPeter Avalos FATAL("out of memory in %s", whatrtn); 1264b588458SPeter Avalos return 0; 1274b588458SPeter Avalos } 1284b588458SPeter Avalos *pbuf = tbuf; 1294b588458SPeter Avalos *psiz = minlen; 1304b588458SPeter Avalos if (pbptr) 1314b588458SPeter Avalos *pbptr = tbuf + boff; 1324b588458SPeter Avalos } 1334b588458SPeter Avalos return 1; 1344b588458SPeter Avalos } 1354b588458SPeter Avalos 1364b588458SPeter Avalos void run(Node *a) /* execution of parse tree starts here */ 1374b588458SPeter Avalos { 1384b588458SPeter Avalos 1394b588458SPeter Avalos stdinit(); 1404b588458SPeter Avalos execute(a); 1414b588458SPeter Avalos closeall(); 1424b588458SPeter Avalos } 1434b588458SPeter Avalos 1444b588458SPeter Avalos Cell *execute(Node *u) /* execute a node of the parse tree */ 1454b588458SPeter Avalos { 1464b588458SPeter Avalos Cell *(*proc)(Node **, int); 1474b588458SPeter Avalos Cell *x; 1484b588458SPeter Avalos Node *a; 1494b588458SPeter Avalos 1504b588458SPeter Avalos if (u == NULL) 1514b588458SPeter Avalos return(True); 1524b588458SPeter Avalos for (a = u; ; a = a->nnext) { 1534b588458SPeter Avalos curnode = a; 1544b588458SPeter Avalos if (isvalue(a)) { 1554b588458SPeter Avalos x = (Cell *) (a->narg[0]); 1564b588458SPeter Avalos if (isfld(x) && !donefld) 1574b588458SPeter Avalos fldbld(); 1584b588458SPeter Avalos else if (isrec(x) && !donerec) 1594b588458SPeter Avalos recbld(); 1604b588458SPeter Avalos return(x); 1614b588458SPeter Avalos } 1624b588458SPeter Avalos if (notlegal(a->nobj)) /* probably a Cell* but too risky to print */ 1634b588458SPeter Avalos FATAL("illegal statement"); 1644b588458SPeter Avalos proc = proctab[a->nobj-FIRSTTOKEN]; 1654b588458SPeter Avalos x = (*proc)(a->narg, a->nobj); 1664b588458SPeter Avalos if (isfld(x) && !donefld) 1674b588458SPeter Avalos fldbld(); 1684b588458SPeter Avalos else if (isrec(x) && !donerec) 1694b588458SPeter Avalos recbld(); 1704b588458SPeter Avalos if (isexpr(a)) 1714b588458SPeter Avalos return(x); 1724b588458SPeter Avalos if (isjump(x)) 1734b588458SPeter Avalos return(x); 1744b588458SPeter Avalos if (a->nnext == NULL) 1754b588458SPeter Avalos return(x); 1764b588458SPeter Avalos tempfree(x); 1774b588458SPeter Avalos } 1784b588458SPeter Avalos } 1794b588458SPeter Avalos 1804b588458SPeter Avalos 1814b588458SPeter Avalos Cell *program(Node **a, int n) /* execute an awk program */ 1824b588458SPeter Avalos { /* a[0] = BEGIN, a[1] = body, a[2] = END */ 1834b588458SPeter Avalos Cell *x; 1844b588458SPeter Avalos 1854b588458SPeter Avalos if (setjmp(env) != 0) 1864b588458SPeter Avalos goto ex; 1874b588458SPeter Avalos if (a[0]) { /* BEGIN */ 1884b588458SPeter Avalos x = execute(a[0]); 1894b588458SPeter Avalos if (isexit(x)) 1904b588458SPeter Avalos return(True); 1914b588458SPeter Avalos if (isjump(x)) 1924b588458SPeter Avalos FATAL("illegal break, continue, next or nextfile from BEGIN"); 1934b588458SPeter Avalos tempfree(x); 1944b588458SPeter Avalos } 1954b588458SPeter Avalos if (a[1] || a[2]) 196*1d48fce0SDaniel Fojt while (getrec(&record, &recsize, true) > 0) { 1974b588458SPeter Avalos x = execute(a[1]); 1984b588458SPeter Avalos if (isexit(x)) 1994b588458SPeter Avalos break; 2004b588458SPeter Avalos tempfree(x); 2014b588458SPeter Avalos } 2024b588458SPeter Avalos ex: 2034b588458SPeter Avalos if (setjmp(env) != 0) /* handles exit within END */ 2044b588458SPeter Avalos goto ex1; 2054b588458SPeter Avalos if (a[2]) { /* END */ 2064b588458SPeter Avalos x = execute(a[2]); 2074b588458SPeter Avalos if (isbreak(x) || isnext(x) || iscont(x)) 2084b588458SPeter Avalos FATAL("illegal break, continue, next or nextfile from END"); 2094b588458SPeter Avalos tempfree(x); 2104b588458SPeter Avalos } 2114b588458SPeter Avalos ex1: 2124b588458SPeter Avalos return(True); 2134b588458SPeter Avalos } 2144b588458SPeter Avalos 2154b588458SPeter Avalos struct Frame { /* stack frame for awk function calls */ 2164b588458SPeter Avalos int nargs; /* number of arguments in this call */ 2174b588458SPeter Avalos Cell *fcncell; /* pointer to Cell for function */ 2184b588458SPeter Avalos Cell **args; /* pointer to array of arguments after execute */ 2194b588458SPeter Avalos Cell *retval; /* return value */ 2204b588458SPeter Avalos }; 2214b588458SPeter Avalos 2224b588458SPeter Avalos #define NARGS 50 /* max args in a call */ 2234b588458SPeter Avalos 2244b588458SPeter Avalos struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */ 2254b588458SPeter Avalos int nframe = 0; /* number of frames allocated */ 226*1d48fce0SDaniel Fojt struct Frame *frp = NULL; /* frame pointer. bottom level unused */ 2274b588458SPeter Avalos 2284b588458SPeter Avalos Cell *call(Node **a, int n) /* function call. very kludgy and fragile */ 2294b588458SPeter Avalos { 230*1d48fce0SDaniel Fojt static const Cell newcopycell = { OCELL, CCOPY, 0, EMPTY, 0.0, NUM|STR|DONTFREE, NULL, NULL }; 2314b588458SPeter Avalos int i, ncall, ndef; 2324b588458SPeter Avalos int freed = 0; /* handles potential double freeing when fcn & param share a tempcell */ 2334b588458SPeter Avalos Node *x; 2344b588458SPeter Avalos Cell *args[NARGS], *oargs[NARGS]; /* BUG: fixed size arrays */ 2354b588458SPeter Avalos Cell *y, *z, *fcn; 2364b588458SPeter Avalos char *s; 2374b588458SPeter Avalos 2384b588458SPeter Avalos fcn = execute(a[0]); /* the function itself */ 2394b588458SPeter Avalos s = fcn->nval; 2404b588458SPeter Avalos if (!isfcn(fcn)) 2414b588458SPeter Avalos FATAL("calling undefined function %s", s); 2424b588458SPeter Avalos if (frame == NULL) { 243*1d48fce0SDaniel Fojt frp = frame = calloc(nframe += 100, sizeof(*frame)); 2444b588458SPeter Avalos if (frame == NULL) 2454b588458SPeter Avalos FATAL("out of space for stack frames calling %s", s); 2464b588458SPeter Avalos } 2474b588458SPeter Avalos for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */ 2484b588458SPeter Avalos ncall++; 2494b588458SPeter Avalos ndef = (int) fcn->fval; /* args in defn */ 250*1d48fce0SDaniel Fojt dprintf( ("calling %s, %d args (%d in defn), frp=%d\n", s, ncall, ndef, (int) (frp-frame)) ); 2514b588458SPeter Avalos if (ncall > ndef) 2524b588458SPeter Avalos WARNING("function %s called with %d args, uses only %d", 2534b588458SPeter Avalos s, ncall, ndef); 2544b588458SPeter Avalos if (ncall + ndef > NARGS) 2554b588458SPeter Avalos FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS); 2564b588458SPeter Avalos for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */ 257*1d48fce0SDaniel Fojt dprintf( ("evaluate args[%d], frp=%d:\n", i, (int) (frp-frame)) ); 2584b588458SPeter Avalos y = execute(x); 2594b588458SPeter Avalos oargs[i] = y; 2604b588458SPeter Avalos dprintf( ("args[%d]: %s %f <%s>, t=%o\n", 2614b588458SPeter Avalos i, NN(y->nval), y->fval, isarr(y) ? "(array)" : NN(y->sval), y->tval) ); 2624b588458SPeter Avalos if (isfcn(y)) 2634b588458SPeter Avalos FATAL("can't use function %s as argument in %s", y->nval, s); 2644b588458SPeter Avalos if (isarr(y)) 2654b588458SPeter Avalos args[i] = y; /* arrays by ref */ 2664b588458SPeter Avalos else 2674b588458SPeter Avalos args[i] = copycell(y); 2684b588458SPeter Avalos tempfree(y); 2694b588458SPeter Avalos } 2704b588458SPeter Avalos for ( ; i < ndef; i++) { /* add null args for ones not provided */ 2714b588458SPeter Avalos args[i] = gettemp(); 2724b588458SPeter Avalos *args[i] = newcopycell; 2734b588458SPeter Avalos } 274*1d48fce0SDaniel Fojt frp++; /* now ok to up frame */ 275*1d48fce0SDaniel Fojt if (frp >= frame + nframe) { 276*1d48fce0SDaniel Fojt int dfp = frp - frame; /* old index */ 277*1d48fce0SDaniel Fojt frame = realloc(frame, (nframe += 100) * sizeof(*frame)); 2784b588458SPeter Avalos if (frame == NULL) 2794b588458SPeter Avalos FATAL("out of space for stack frames in %s", s); 280*1d48fce0SDaniel Fojt frp = frame + dfp; 2814b588458SPeter Avalos } 282*1d48fce0SDaniel Fojt frp->fcncell = fcn; 283*1d48fce0SDaniel Fojt frp->args = args; 284*1d48fce0SDaniel Fojt frp->nargs = ndef; /* number defined with (excess are locals) */ 285*1d48fce0SDaniel Fojt frp->retval = gettemp(); 2864b588458SPeter Avalos 287*1d48fce0SDaniel Fojt dprintf( ("start exec of %s, frp=%d\n", s, (int) (frp-frame)) ); 2884b588458SPeter Avalos y = execute((Node *)(fcn->sval)); /* execute body */ 289*1d48fce0SDaniel Fojt dprintf( ("finished exec of %s, frp=%d\n", s, (int) (frp-frame)) ); 2904b588458SPeter Avalos 2914b588458SPeter Avalos for (i = 0; i < ndef; i++) { 292*1d48fce0SDaniel Fojt Cell *t = frp->args[i]; 2934b588458SPeter Avalos if (isarr(t)) { 2944b588458SPeter Avalos if (t->csub == CCOPY) { 2954b588458SPeter Avalos if (i >= ncall) { 2964b588458SPeter Avalos freesymtab(t); 2974b588458SPeter Avalos t->csub = CTEMP; 2984b588458SPeter Avalos tempfree(t); 2994b588458SPeter Avalos } else { 3004b588458SPeter Avalos oargs[i]->tval = t->tval; 3014b588458SPeter Avalos oargs[i]->tval &= ~(STR|NUM|DONTFREE); 3024b588458SPeter Avalos oargs[i]->sval = t->sval; 3034b588458SPeter Avalos tempfree(t); 3044b588458SPeter Avalos } 3054b588458SPeter Avalos } 3064b588458SPeter Avalos } else if (t != y) { /* kludge to prevent freeing twice */ 3074b588458SPeter Avalos t->csub = CTEMP; 3084b588458SPeter Avalos tempfree(t); 3094b588458SPeter Avalos } else if (t == y && t->csub == CCOPY) { 3104b588458SPeter Avalos t->csub = CTEMP; 3114b588458SPeter Avalos tempfree(t); 3124b588458SPeter Avalos freed = 1; 3134b588458SPeter Avalos } 3144b588458SPeter Avalos } 3154b588458SPeter Avalos tempfree(fcn); 3164b588458SPeter Avalos if (isexit(y) || isnext(y)) 3174b588458SPeter Avalos return y; 3184b588458SPeter Avalos if (freed == 0) { 3194b588458SPeter Avalos tempfree(y); /* don't free twice! */ 3204b588458SPeter Avalos } 321*1d48fce0SDaniel Fojt z = frp->retval; /* return value */ 3224b588458SPeter Avalos dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) ); 323*1d48fce0SDaniel Fojt frp--; 3244b588458SPeter Avalos return(z); 3254b588458SPeter Avalos } 3264b588458SPeter Avalos 3274b588458SPeter Avalos Cell *copycell(Cell *x) /* make a copy of a cell in a temp */ 3284b588458SPeter Avalos { 3294b588458SPeter Avalos Cell *y; 3304b588458SPeter Avalos 331*1d48fce0SDaniel Fojt /* copy is not constant or field */ 332*1d48fce0SDaniel Fojt 3334b588458SPeter Avalos y = gettemp(); 334*1d48fce0SDaniel Fojt y->tval = x->tval & ~(CON|FLD|REC); 3354b588458SPeter Avalos y->csub = CCOPY; /* prevents freeing until call is over */ 3364b588458SPeter Avalos y->nval = x->nval; /* BUG? */ 337*1d48fce0SDaniel Fojt if (isstr(x) /* || x->ctype == OCELL */) { 3384b588458SPeter Avalos y->sval = tostring(x->sval); 339*1d48fce0SDaniel Fojt y->tval &= ~DONTFREE; 340*1d48fce0SDaniel Fojt } else 341*1d48fce0SDaniel Fojt y->tval |= DONTFREE; 3424b588458SPeter Avalos y->fval = x->fval; 3434b588458SPeter Avalos return y; 3444b588458SPeter Avalos } 3454b588458SPeter Avalos 3464b588458SPeter Avalos Cell *arg(Node **a, int n) /* nth argument of a function */ 3474b588458SPeter Avalos { 3484b588458SPeter Avalos 3494b588458SPeter Avalos n = ptoi(a[0]); /* argument number, counting from 0 */ 350*1d48fce0SDaniel Fojt dprintf( ("arg(%d), frp->nargs=%d\n", n, frp->nargs) ); 351*1d48fce0SDaniel Fojt if (n+1 > frp->nargs) 3524b588458SPeter Avalos FATAL("argument #%d of function %s was not supplied", 353*1d48fce0SDaniel Fojt n+1, frp->fcncell->nval); 354*1d48fce0SDaniel Fojt return frp->args[n]; 3554b588458SPeter Avalos } 3564b588458SPeter Avalos 3574b588458SPeter Avalos Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */ 3584b588458SPeter Avalos { 3594b588458SPeter Avalos Cell *y; 3604b588458SPeter Avalos 3614b588458SPeter Avalos switch (n) { 3624b588458SPeter Avalos case EXIT: 3634b588458SPeter Avalos if (a[0] != NULL) { 3644b588458SPeter Avalos y = execute(a[0]); 3654b588458SPeter Avalos errorflag = (int) getfval(y); 3664b588458SPeter Avalos tempfree(y); 3674b588458SPeter Avalos } 3684b588458SPeter Avalos longjmp(env, 1); 3694b588458SPeter Avalos case RETURN: 3704b588458SPeter Avalos if (a[0] != NULL) { 3714b588458SPeter Avalos y = execute(a[0]); 3724b588458SPeter Avalos if ((y->tval & (STR|NUM)) == (STR|NUM)) { 373*1d48fce0SDaniel Fojt setsval(frp->retval, getsval(y)); 374*1d48fce0SDaniel Fojt frp->retval->fval = getfval(y); 375*1d48fce0SDaniel Fojt frp->retval->tval |= NUM; 3764b588458SPeter Avalos } 3774b588458SPeter Avalos else if (y->tval & STR) 378*1d48fce0SDaniel Fojt setsval(frp->retval, getsval(y)); 3794b588458SPeter Avalos else if (y->tval & NUM) 380*1d48fce0SDaniel Fojt setfval(frp->retval, getfval(y)); 3814b588458SPeter Avalos else /* can't happen */ 3824b588458SPeter Avalos FATAL("bad type variable %d", y->tval); 3834b588458SPeter Avalos tempfree(y); 3844b588458SPeter Avalos } 3854b588458SPeter Avalos return(jret); 3864b588458SPeter Avalos case NEXT: 3874b588458SPeter Avalos return(jnext); 3884b588458SPeter Avalos case NEXTFILE: 3894b588458SPeter Avalos nextfile(); 3904b588458SPeter Avalos return(jnextfile); 3914b588458SPeter Avalos case BREAK: 3924b588458SPeter Avalos return(jbreak); 3934b588458SPeter Avalos case CONTINUE: 3944b588458SPeter Avalos return(jcont); 3954b588458SPeter Avalos default: /* can't happen */ 3964b588458SPeter Avalos FATAL("illegal jump type %d", n); 3974b588458SPeter Avalos } 3984b588458SPeter Avalos return 0; /* not reached */ 3994b588458SPeter Avalos } 4004b588458SPeter Avalos 4014b588458SPeter Avalos Cell *awkgetline(Node **a, int n) /* get next line from specific input */ 4024b588458SPeter Avalos { /* a[0] is variable, a[1] is operator, a[2] is filename */ 4034b588458SPeter Avalos Cell *r, *x; 4044b588458SPeter Avalos extern Cell **fldtab; 4054b588458SPeter Avalos FILE *fp; 4064b588458SPeter Avalos char *buf; 4074b588458SPeter Avalos int bufsize = recsize; 4084b588458SPeter Avalos int mode; 409*1d48fce0SDaniel Fojt bool newflag; 4104b588458SPeter Avalos 411*1d48fce0SDaniel Fojt if ((buf = malloc(bufsize)) == NULL) 4124b588458SPeter Avalos FATAL("out of memory in getline"); 4134b588458SPeter Avalos 4144b588458SPeter Avalos fflush(stdout); /* in case someone is waiting for a prompt */ 4154b588458SPeter Avalos r = gettemp(); 4164b588458SPeter Avalos if (a[1] != NULL) { /* getline < file */ 4174b588458SPeter Avalos x = execute(a[2]); /* filename */ 4184b588458SPeter Avalos mode = ptoi(a[1]); 4194b588458SPeter Avalos if (mode == '|') /* input pipe */ 4204b588458SPeter Avalos mode = LE; /* arbitrary flag */ 421*1d48fce0SDaniel Fojt fp = openfile(mode, getsval(x), &newflag); 4224b588458SPeter Avalos tempfree(x); 4234b588458SPeter Avalos if (fp == NULL) 4244b588458SPeter Avalos n = -1; 4254b588458SPeter Avalos else 426*1d48fce0SDaniel Fojt n = readrec(&buf, &bufsize, fp, newflag); 4274b588458SPeter Avalos if (n <= 0) { 4284b588458SPeter Avalos ; 4294b588458SPeter Avalos } else if (a[0] != NULL) { /* getline var <file */ 4304b588458SPeter Avalos x = execute(a[0]); 4314b588458SPeter Avalos setsval(x, buf); 432*1d48fce0SDaniel Fojt if (is_number(x->sval)) { 433*1d48fce0SDaniel Fojt x->fval = atof(x->sval); 434*1d48fce0SDaniel Fojt x->tval |= NUM; 435*1d48fce0SDaniel Fojt } 4364b588458SPeter Avalos tempfree(x); 4374b588458SPeter Avalos } else { /* getline <file */ 4384b588458SPeter Avalos setsval(fldtab[0], buf); 4394b588458SPeter Avalos if (is_number(fldtab[0]->sval)) { 4404b588458SPeter Avalos fldtab[0]->fval = atof(fldtab[0]->sval); 4414b588458SPeter Avalos fldtab[0]->tval |= NUM; 4424b588458SPeter Avalos } 4434b588458SPeter Avalos } 4444b588458SPeter Avalos } else { /* bare getline; use current input */ 4454b588458SPeter Avalos if (a[0] == NULL) /* getline */ 446*1d48fce0SDaniel Fojt n = getrec(&record, &recsize, true); 4474b588458SPeter Avalos else { /* getline var */ 448*1d48fce0SDaniel Fojt n = getrec(&buf, &bufsize, false); 4494b588458SPeter Avalos x = execute(a[0]); 4504b588458SPeter Avalos setsval(x, buf); 451*1d48fce0SDaniel Fojt if (is_number(x->sval)) { 452*1d48fce0SDaniel Fojt x->fval = atof(x->sval); 453*1d48fce0SDaniel Fojt x->tval |= NUM; 454*1d48fce0SDaniel Fojt } 4554b588458SPeter Avalos tempfree(x); 4564b588458SPeter Avalos } 4574b588458SPeter Avalos } 4584b588458SPeter Avalos setfval(r, (Awkfloat) n); 4594b588458SPeter Avalos free(buf); 4604b588458SPeter Avalos return r; 4614b588458SPeter Avalos } 4624b588458SPeter Avalos 4634b588458SPeter Avalos Cell *getnf(Node **a, int n) /* get NF */ 4644b588458SPeter Avalos { 465*1d48fce0SDaniel Fojt if (!donefld) 4664b588458SPeter Avalos fldbld(); 4674b588458SPeter Avalos return (Cell *) a[0]; 4684b588458SPeter Avalos } 4694b588458SPeter Avalos 470*1d48fce0SDaniel Fojt static char * 471*1d48fce0SDaniel Fojt makearraystring(Node *p, const char *func) 4724b588458SPeter Avalos { 4734b588458SPeter Avalos char *buf; 4744b588458SPeter Avalos int bufsz = recsize; 475*1d48fce0SDaniel Fojt size_t blen, seplen; 4764b588458SPeter Avalos 477*1d48fce0SDaniel Fojt if ((buf = malloc(bufsz)) == NULL) { 478*1d48fce0SDaniel Fojt FATAL("%s: out of memory", func); 479*1d48fce0SDaniel Fojt } 480*1d48fce0SDaniel Fojt 481*1d48fce0SDaniel Fojt blen = 0; 482*1d48fce0SDaniel Fojt buf[blen] = '\0'; 483*1d48fce0SDaniel Fojt seplen = strlen(getsval(subseploc)); 484*1d48fce0SDaniel Fojt 485*1d48fce0SDaniel Fojt for (; p; p = p->nnext) { 486*1d48fce0SDaniel Fojt Cell *x = execute(p); /* expr */ 487*1d48fce0SDaniel Fojt char *s = getsval(x); 488*1d48fce0SDaniel Fojt size_t nsub = p->nnext ? seplen : 0; 489*1d48fce0SDaniel Fojt size_t slen = strlen(s); 490*1d48fce0SDaniel Fojt size_t tlen = blen + slen + nsub; 491*1d48fce0SDaniel Fojt 492*1d48fce0SDaniel Fojt if (!adjbuf(&buf, &bufsz, tlen + 1, recsize, 0, func)) { 493*1d48fce0SDaniel Fojt FATAL("%s: out of memory %s[%s...]", 494*1d48fce0SDaniel Fojt func, x->nval, buf); 495*1d48fce0SDaniel Fojt } 496*1d48fce0SDaniel Fojt memcpy(buf + blen, s, slen); 497*1d48fce0SDaniel Fojt if (nsub) { 498*1d48fce0SDaniel Fojt memcpy(buf + blen + slen, *SUBSEP, nsub); 499*1d48fce0SDaniel Fojt } 500*1d48fce0SDaniel Fojt buf[tlen] = '\0'; 501*1d48fce0SDaniel Fojt blen = tlen; 502*1d48fce0SDaniel Fojt tempfree(x); 503*1d48fce0SDaniel Fojt } 504*1d48fce0SDaniel Fojt return buf; 505*1d48fce0SDaniel Fojt } 506*1d48fce0SDaniel Fojt 507*1d48fce0SDaniel Fojt Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ 508*1d48fce0SDaniel Fojt { 509*1d48fce0SDaniel Fojt Cell *x, *z; 510*1d48fce0SDaniel Fojt char *buf; 5114b588458SPeter Avalos 5124b588458SPeter Avalos x = execute(a[0]); /* Cell* for symbol table */ 513*1d48fce0SDaniel Fojt buf = makearraystring(a[1], __func__); 5144b588458SPeter Avalos if (!isarr(x)) { 5154b588458SPeter Avalos dprintf( ("making %s into an array\n", NN(x->nval)) ); 5164b588458SPeter Avalos if (freeable(x)) 5174b588458SPeter Avalos xfree(x->sval); 5184b588458SPeter Avalos x->tval &= ~(STR|NUM|DONTFREE); 5194b588458SPeter Avalos x->tval |= ARR; 5204b588458SPeter Avalos x->sval = (char *) makesymtab(NSYMTAB); 5214b588458SPeter Avalos } 5224b588458SPeter Avalos z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval); 5234b588458SPeter Avalos z->ctype = OCELL; 5244b588458SPeter Avalos z->csub = CVAR; 5254b588458SPeter Avalos tempfree(x); 5264b588458SPeter Avalos free(buf); 5274b588458SPeter Avalos return(z); 5284b588458SPeter Avalos } 5294b588458SPeter Avalos 5304b588458SPeter Avalos Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ 5314b588458SPeter Avalos { 532*1d48fce0SDaniel Fojt Cell *x; 5334b588458SPeter Avalos 5344b588458SPeter Avalos x = execute(a[0]); /* Cell* for symbol table */ 535*1d48fce0SDaniel Fojt if (x == symtabloc) { 536*1d48fce0SDaniel Fojt FATAL("cannot delete SYMTAB or its elements"); 537*1d48fce0SDaniel Fojt } 5384b588458SPeter Avalos if (!isarr(x)) 5394b588458SPeter Avalos return True; 540*1d48fce0SDaniel Fojt if (a[1] == NULL) { /* delete the elements, not the table */ 5414b588458SPeter Avalos freesymtab(x); 5424b588458SPeter Avalos x->tval &= ~STR; 5434b588458SPeter Avalos x->tval |= ARR; 5444b588458SPeter Avalos x->sval = (char *) makesymtab(NSYMTAB); 5454b588458SPeter Avalos } else { 546*1d48fce0SDaniel Fojt char *buf = makearraystring(a[1], __func__); 5474b588458SPeter Avalos freeelem(x, buf); 5484b588458SPeter Avalos free(buf); 5494b588458SPeter Avalos } 5504b588458SPeter Avalos tempfree(x); 5514b588458SPeter Avalos return True; 5524b588458SPeter Avalos } 5534b588458SPeter Avalos 5544b588458SPeter Avalos Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */ 5554b588458SPeter Avalos { 556*1d48fce0SDaniel Fojt Cell *ap, *k; 5574b588458SPeter Avalos char *buf; 5584b588458SPeter Avalos 5594b588458SPeter Avalos ap = execute(a[1]); /* array name */ 5604b588458SPeter Avalos if (!isarr(ap)) { 5614b588458SPeter Avalos dprintf( ("making %s into an array\n", ap->nval) ); 5624b588458SPeter Avalos if (freeable(ap)) 5634b588458SPeter Avalos xfree(ap->sval); 5644b588458SPeter Avalos ap->tval &= ~(STR|NUM|DONTFREE); 5654b588458SPeter Avalos ap->tval |= ARR; 5664b588458SPeter Avalos ap->sval = (char *) makesymtab(NSYMTAB); 5674b588458SPeter Avalos } 568*1d48fce0SDaniel Fojt buf = makearraystring(a[0], __func__); 5694b588458SPeter Avalos k = lookup(buf, (Array *) ap->sval); 5704b588458SPeter Avalos tempfree(ap); 5714b588458SPeter Avalos free(buf); 5724b588458SPeter Avalos if (k == NULL) 5734b588458SPeter Avalos return(False); 5744b588458SPeter Avalos else 5754b588458SPeter Avalos return(True); 5764b588458SPeter Avalos } 5774b588458SPeter Avalos 5784b588458SPeter Avalos 5794b588458SPeter Avalos Cell *matchop(Node **a, int n) /* ~ and match() */ 5804b588458SPeter Avalos { 5814b588458SPeter Avalos Cell *x, *y; 5824b588458SPeter Avalos char *s, *t; 5834b588458SPeter Avalos int i; 5844b588458SPeter Avalos fa *pfa; 5854b588458SPeter Avalos int (*mf)(fa *, const char *) = match, mode = 0; 5864b588458SPeter Avalos 5874b588458SPeter Avalos if (n == MATCHFCN) { 5884b588458SPeter Avalos mf = pmatch; 5894b588458SPeter Avalos mode = 1; 5904b588458SPeter Avalos } 5914b588458SPeter Avalos x = execute(a[1]); /* a[1] = target text */ 5924b588458SPeter Avalos s = getsval(x); 593*1d48fce0SDaniel Fojt if (a[0] == NULL) /* a[1] == 0: already-compiled reg expr */ 5944b588458SPeter Avalos i = (*mf)((fa *) a[2], s); 5954b588458SPeter Avalos else { 5964b588458SPeter Avalos y = execute(a[2]); /* a[2] = regular expr */ 5974b588458SPeter Avalos t = getsval(y); 5984b588458SPeter Avalos pfa = makedfa(t, mode); 5994b588458SPeter Avalos i = (*mf)(pfa, s); 6004b588458SPeter Avalos tempfree(y); 6014b588458SPeter Avalos } 6024b588458SPeter Avalos tempfree(x); 6034b588458SPeter Avalos if (n == MATCHFCN) { 6044b588458SPeter Avalos int start = patbeg - s + 1; 6054b588458SPeter Avalos if (patlen < 0) 6064b588458SPeter Avalos start = 0; 6074b588458SPeter Avalos setfval(rstartloc, (Awkfloat) start); 6084b588458SPeter Avalos setfval(rlengthloc, (Awkfloat) patlen); 6094b588458SPeter Avalos x = gettemp(); 6104b588458SPeter Avalos x->tval = NUM; 6114b588458SPeter Avalos x->fval = start; 6124b588458SPeter Avalos return x; 6134b588458SPeter Avalos } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0)) 6144b588458SPeter Avalos return(True); 6154b588458SPeter Avalos else 6164b588458SPeter Avalos return(False); 6174b588458SPeter Avalos } 6184b588458SPeter Avalos 6194b588458SPeter Avalos 6204b588458SPeter Avalos Cell *boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */ 6214b588458SPeter Avalos { 6224b588458SPeter Avalos Cell *x, *y; 6234b588458SPeter Avalos int i; 6244b588458SPeter Avalos 6254b588458SPeter Avalos x = execute(a[0]); 6264b588458SPeter Avalos i = istrue(x); 6274b588458SPeter Avalos tempfree(x); 6284b588458SPeter Avalos switch (n) { 6294b588458SPeter Avalos case BOR: 6304b588458SPeter Avalos if (i) return(True); 6314b588458SPeter Avalos y = execute(a[1]); 6324b588458SPeter Avalos i = istrue(y); 6334b588458SPeter Avalos tempfree(y); 6344b588458SPeter Avalos if (i) return(True); 6354b588458SPeter Avalos else return(False); 6364b588458SPeter Avalos case AND: 6374b588458SPeter Avalos if ( !i ) return(False); 6384b588458SPeter Avalos y = execute(a[1]); 6394b588458SPeter Avalos i = istrue(y); 6404b588458SPeter Avalos tempfree(y); 6414b588458SPeter Avalos if (i) return(True); 6424b588458SPeter Avalos else return(False); 6434b588458SPeter Avalos case NOT: 6444b588458SPeter Avalos if (i) return(False); 6454b588458SPeter Avalos else return(True); 6464b588458SPeter Avalos default: /* can't happen */ 6474b588458SPeter Avalos FATAL("unknown boolean operator %d", n); 6484b588458SPeter Avalos } 6494b588458SPeter Avalos return 0; /*NOTREACHED*/ 6504b588458SPeter Avalos } 6514b588458SPeter Avalos 6524b588458SPeter Avalos Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */ 6534b588458SPeter Avalos { 6544b588458SPeter Avalos int i; 6554b588458SPeter Avalos Cell *x, *y; 6564b588458SPeter Avalos Awkfloat j; 6574b588458SPeter Avalos 6584b588458SPeter Avalos x = execute(a[0]); 6594b588458SPeter Avalos y = execute(a[1]); 6604b588458SPeter Avalos if (x->tval&NUM && y->tval&NUM) { 6614b588458SPeter Avalos j = x->fval - y->fval; 6624b588458SPeter Avalos i = j<0? -1: (j>0? 1: 0); 6634b588458SPeter Avalos } else { 6644b588458SPeter Avalos i = strcmp(getsval(x), getsval(y)); 6654b588458SPeter Avalos } 6664b588458SPeter Avalos tempfree(x); 6674b588458SPeter Avalos tempfree(y); 6684b588458SPeter Avalos switch (n) { 6694b588458SPeter Avalos case LT: if (i<0) return(True); 6704b588458SPeter Avalos else return(False); 6714b588458SPeter Avalos case LE: if (i<=0) return(True); 6724b588458SPeter Avalos else return(False); 6734b588458SPeter Avalos case NE: if (i!=0) return(True); 6744b588458SPeter Avalos else return(False); 6754b588458SPeter Avalos case EQ: if (i == 0) return(True); 6764b588458SPeter Avalos else return(False); 6774b588458SPeter Avalos case GE: if (i>=0) return(True); 6784b588458SPeter Avalos else return(False); 6794b588458SPeter Avalos case GT: if (i>0) return(True); 6804b588458SPeter Avalos else return(False); 6814b588458SPeter Avalos default: /* can't happen */ 6824b588458SPeter Avalos FATAL("unknown relational operator %d", n); 6834b588458SPeter Avalos } 6844b588458SPeter Avalos return 0; /*NOTREACHED*/ 6854b588458SPeter Avalos } 6864b588458SPeter Avalos 6874b588458SPeter Avalos void tfree(Cell *a) /* free a tempcell */ 6884b588458SPeter Avalos { 6894b588458SPeter Avalos if (freeable(a)) { 6904b588458SPeter Avalos dprintf( ("freeing %s %s %o\n", NN(a->nval), NN(a->sval), a->tval) ); 6914b588458SPeter Avalos xfree(a->sval); 6924b588458SPeter Avalos } 6934b588458SPeter Avalos if (a == tmps) 6944b588458SPeter Avalos FATAL("tempcell list is curdled"); 6954b588458SPeter Avalos a->cnext = tmps; 6964b588458SPeter Avalos tmps = a; 6974b588458SPeter Avalos } 6984b588458SPeter Avalos 6994b588458SPeter Avalos Cell *gettemp(void) /* get a tempcell */ 7004b588458SPeter Avalos { int i; 7014b588458SPeter Avalos Cell *x; 7024b588458SPeter Avalos 7034b588458SPeter Avalos if (!tmps) { 704*1d48fce0SDaniel Fojt tmps = calloc(100, sizeof(*tmps)); 7054b588458SPeter Avalos if (!tmps) 7064b588458SPeter Avalos FATAL("out of space for temporaries"); 7074b588458SPeter Avalos for (i = 1; i < 100; i++) 7084b588458SPeter Avalos tmps[i-1].cnext = &tmps[i]; 709*1d48fce0SDaniel Fojt tmps[i-1].cnext = NULL; 7104b588458SPeter Avalos } 7114b588458SPeter Avalos x = tmps; 7124b588458SPeter Avalos tmps = x->cnext; 7134b588458SPeter Avalos *x = tempcell; 7144b588458SPeter Avalos return(x); 7154b588458SPeter Avalos } 7164b588458SPeter Avalos 7174b588458SPeter Avalos Cell *indirect(Node **a, int n) /* $( a[0] ) */ 7184b588458SPeter Avalos { 7194b588458SPeter Avalos Awkfloat val; 7204b588458SPeter Avalos Cell *x; 7214b588458SPeter Avalos int m; 7224b588458SPeter Avalos char *s; 7234b588458SPeter Avalos 7244b588458SPeter Avalos x = execute(a[0]); 7254b588458SPeter Avalos val = getfval(x); /* freebsd: defend against super large field numbers */ 7264b588458SPeter Avalos if ((Awkfloat)INT_MAX < val) 7274b588458SPeter Avalos FATAL("trying to access out of range field %s", x->nval); 7284b588458SPeter Avalos m = (int) val; 7294b588458SPeter Avalos if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */ 7304b588458SPeter Avalos FATAL("illegal field $(%s), name \"%s\"", s, x->nval); 7314b588458SPeter Avalos /* BUG: can x->nval ever be null??? */ 7324b588458SPeter Avalos tempfree(x); 7334b588458SPeter Avalos x = fieldadr(m); 7344b588458SPeter Avalos x->ctype = OCELL; /* BUG? why are these needed? */ 7354b588458SPeter Avalos x->csub = CFLD; 7364b588458SPeter Avalos return(x); 7374b588458SPeter Avalos } 7384b588458SPeter Avalos 7394b588458SPeter Avalos Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */ 7404b588458SPeter Avalos { 7414b588458SPeter Avalos int k, m, n; 7424b588458SPeter Avalos char *s; 7434b588458SPeter Avalos int temp; 744*1d48fce0SDaniel Fojt Cell *x, *y, *z = NULL; 7454b588458SPeter Avalos 7464b588458SPeter Avalos x = execute(a[0]); 7474b588458SPeter Avalos y = execute(a[1]); 748*1d48fce0SDaniel Fojt if (a[2] != NULL) 7494b588458SPeter Avalos z = execute(a[2]); 7504b588458SPeter Avalos s = getsval(x); 7514b588458SPeter Avalos k = strlen(s) + 1; 7524b588458SPeter Avalos if (k <= 1) { 7534b588458SPeter Avalos tempfree(x); 7544b588458SPeter Avalos tempfree(y); 755*1d48fce0SDaniel Fojt if (a[2] != NULL) { 7564b588458SPeter Avalos tempfree(z); 7574b588458SPeter Avalos } 7584b588458SPeter Avalos x = gettemp(); 7594b588458SPeter Avalos setsval(x, ""); 7604b588458SPeter Avalos return(x); 7614b588458SPeter Avalos } 7624b588458SPeter Avalos m = (int) getfval(y); 7634b588458SPeter Avalos if (m <= 0) 7644b588458SPeter Avalos m = 1; 7654b588458SPeter Avalos else if (m > k) 7664b588458SPeter Avalos m = k; 7674b588458SPeter Avalos tempfree(y); 768*1d48fce0SDaniel Fojt if (a[2] != NULL) { 7694b588458SPeter Avalos n = (int) getfval(z); 7704b588458SPeter Avalos tempfree(z); 7714b588458SPeter Avalos } else 7724b588458SPeter Avalos n = k - 1; 7734b588458SPeter Avalos if (n < 0) 7744b588458SPeter Avalos n = 0; 7754b588458SPeter Avalos else if (n > k - m) 7764b588458SPeter Avalos n = k - m; 7774b588458SPeter Avalos dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) ); 7784b588458SPeter Avalos y = gettemp(); 7794b588458SPeter Avalos temp = s[n+m-1]; /* with thanks to John Linderman */ 7804b588458SPeter Avalos s[n+m-1] = '\0'; 7814b588458SPeter Avalos setsval(y, s + m - 1); 7824b588458SPeter Avalos s[n+m-1] = temp; 7834b588458SPeter Avalos tempfree(x); 7844b588458SPeter Avalos return(y); 7854b588458SPeter Avalos } 7864b588458SPeter Avalos 7874b588458SPeter Avalos Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */ 7884b588458SPeter Avalos { 7894b588458SPeter Avalos Cell *x, *y, *z; 7904b588458SPeter Avalos char *s1, *s2, *p1, *p2, *q; 7914b588458SPeter Avalos Awkfloat v = 0.0; 7924b588458SPeter Avalos 7934b588458SPeter Avalos x = execute(a[0]); 7944b588458SPeter Avalos s1 = getsval(x); 7954b588458SPeter Avalos y = execute(a[1]); 7964b588458SPeter Avalos s2 = getsval(y); 7974b588458SPeter Avalos 7984b588458SPeter Avalos z = gettemp(); 7994b588458SPeter Avalos for (p1 = s1; *p1 != '\0'; p1++) { 8004b588458SPeter Avalos for (q = p1, p2 = s2; *p2 != '\0' && *q == *p2; q++, p2++) 801*1d48fce0SDaniel Fojt continue; 8024b588458SPeter Avalos if (*p2 == '\0') { 8034b588458SPeter Avalos v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */ 8044b588458SPeter Avalos break; 8054b588458SPeter Avalos } 8064b588458SPeter Avalos } 8074b588458SPeter Avalos tempfree(x); 8084b588458SPeter Avalos tempfree(y); 8094b588458SPeter Avalos setfval(z, v); 8104b588458SPeter Avalos return(z); 8114b588458SPeter Avalos } 8124b588458SPeter Avalos 8134b588458SPeter Avalos #define MAXNUMSIZE 50 8144b588458SPeter Avalos 8154b588458SPeter Avalos int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like conversions */ 8164b588458SPeter Avalos { 8174b588458SPeter Avalos char *fmt; 8184b588458SPeter Avalos char *p, *t; 8194b588458SPeter Avalos const char *os; 8204b588458SPeter Avalos Cell *x; 8214b588458SPeter Avalos int flag = 0, n; 8224b588458SPeter Avalos int fmtwd; /* format width */ 8234b588458SPeter Avalos int fmtsz = recsize; 8244b588458SPeter Avalos char *buf = *pbuf; 8254b588458SPeter Avalos int bufsize = *pbufsize; 826*1d48fce0SDaniel Fojt #define FMTSZ(a) (fmtsz - ((a) - fmt)) 827*1d48fce0SDaniel Fojt #define BUFSZ(a) (bufsize - ((a) - buf)) 828*1d48fce0SDaniel Fojt 829*1d48fce0SDaniel Fojt static bool first = true; 830*1d48fce0SDaniel Fojt static bool have_a_format = false; 831*1d48fce0SDaniel Fojt 832*1d48fce0SDaniel Fojt if (first) { 833*1d48fce0SDaniel Fojt char xbuf[100]; 834*1d48fce0SDaniel Fojt 835*1d48fce0SDaniel Fojt snprintf(xbuf, sizeof(xbuf), "%a", 42.0); 836*1d48fce0SDaniel Fojt have_a_format = (strcmp(xbuf, "0x1.5p+5") == 0); 837*1d48fce0SDaniel Fojt first = false; 838*1d48fce0SDaniel Fojt } 8394b588458SPeter Avalos 8404b588458SPeter Avalos os = s; 8414b588458SPeter Avalos p = buf; 842*1d48fce0SDaniel Fojt if ((fmt = malloc(fmtsz)) == NULL) 8434b588458SPeter Avalos FATAL("out of memory in format()"); 8444b588458SPeter Avalos while (*s) { 8454b588458SPeter Avalos adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format1"); 8464b588458SPeter Avalos if (*s != '%') { 8474b588458SPeter Avalos *p++ = *s++; 8484b588458SPeter Avalos continue; 8494b588458SPeter Avalos } 8504b588458SPeter Avalos if (*(s+1) == '%') { 8514b588458SPeter Avalos *p++ = '%'; 8524b588458SPeter Avalos s += 2; 8534b588458SPeter Avalos continue; 8544b588458SPeter Avalos } 8554b588458SPeter Avalos /* have to be real careful in case this is a huge number, eg, %100000d */ 8564b588458SPeter Avalos fmtwd = atoi(s+1); 8574b588458SPeter Avalos if (fmtwd < 0) 8584b588458SPeter Avalos fmtwd = -fmtwd; 8594b588458SPeter Avalos adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format2"); 8604b588458SPeter Avalos for (t = fmt; (*t++ = *s) != '\0'; s++) { 8614b588458SPeter Avalos if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3")) 8624b588458SPeter Avalos FATAL("format item %.30s... ran format() out of memory", os); 863*1d48fce0SDaniel Fojt /* Ignore size specifiers */ 864*1d48fce0SDaniel Fojt if (strchr("hjLlqtz", *s) != NULL) { /* the ansi panoply */ 865*1d48fce0SDaniel Fojt t--; 866*1d48fce0SDaniel Fojt continue; 867*1d48fce0SDaniel Fojt } 868*1d48fce0SDaniel Fojt if (isalpha((uschar)*s)) 869*1d48fce0SDaniel Fojt break; 870*1d48fce0SDaniel Fojt if (*s == '$') { 871*1d48fce0SDaniel Fojt FATAL("'$' not permitted in awk formats"); 872*1d48fce0SDaniel Fojt } 8734b588458SPeter Avalos if (*s == '*') { 874*1d48fce0SDaniel Fojt if (a == NULL) { 875*1d48fce0SDaniel Fojt FATAL("not enough args in printf(%s)", os); 876*1d48fce0SDaniel Fojt } 8774b588458SPeter Avalos x = execute(a); 8784b588458SPeter Avalos a = a->nnext; 879*1d48fce0SDaniel Fojt snprintf(t - 1, FMTSZ(t - 1), 880*1d48fce0SDaniel Fojt "%d", fmtwd=(int) getfval(x)); 8814b588458SPeter Avalos if (fmtwd < 0) 8824b588458SPeter Avalos fmtwd = -fmtwd; 8834b588458SPeter Avalos adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format"); 8844b588458SPeter Avalos t = fmt + strlen(fmt); 8854b588458SPeter Avalos tempfree(x); 8864b588458SPeter Avalos } 8874b588458SPeter Avalos } 8884b588458SPeter Avalos *t = '\0'; 8894b588458SPeter Avalos if (fmtwd < 0) 8904b588458SPeter Avalos fmtwd = -fmtwd; 8914b588458SPeter Avalos adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format4"); 8924b588458SPeter Avalos switch (*s) { 893*1d48fce0SDaniel Fojt case 'a': case 'A': 894*1d48fce0SDaniel Fojt if (have_a_format) 895*1d48fce0SDaniel Fojt flag = *s; 896*1d48fce0SDaniel Fojt else 897*1d48fce0SDaniel Fojt flag = 'f'; 898*1d48fce0SDaniel Fojt break; 8994b588458SPeter Avalos case 'f': case 'e': case 'g': case 'E': case 'G': 9004b588458SPeter Avalos flag = 'f'; 9014b588458SPeter Avalos break; 902*1d48fce0SDaniel Fojt case 'd': case 'i': case 'o': case 'x': case 'X': case 'u': 903*1d48fce0SDaniel Fojt flag = (*s == 'd' || *s == 'i') ? 'd' : 'u'; 904*1d48fce0SDaniel Fojt *(t-1) = 'j'; 905*1d48fce0SDaniel Fojt *t = *s; 9064b588458SPeter Avalos *++t = '\0'; 9074b588458SPeter Avalos break; 9084b588458SPeter Avalos case 's': 9094b588458SPeter Avalos flag = 's'; 9104b588458SPeter Avalos break; 9114b588458SPeter Avalos case 'c': 9124b588458SPeter Avalos flag = 'c'; 9134b588458SPeter Avalos break; 9144b588458SPeter Avalos default: 9154b588458SPeter Avalos WARNING("weird printf conversion %s", fmt); 9164b588458SPeter Avalos flag = '?'; 9174b588458SPeter Avalos break; 9184b588458SPeter Avalos } 9194b588458SPeter Avalos if (a == NULL) 9204b588458SPeter Avalos FATAL("not enough args in printf(%s)", os); 9214b588458SPeter Avalos x = execute(a); 9224b588458SPeter Avalos a = a->nnext; 9234b588458SPeter Avalos n = MAXNUMSIZE; 9244b588458SPeter Avalos if (fmtwd > n) 9254b588458SPeter Avalos n = fmtwd; 9264b588458SPeter Avalos adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format5"); 9274b588458SPeter Avalos switch (flag) { 928*1d48fce0SDaniel Fojt case '?': snprintf(p, BUFSZ(p), "%s", fmt); /* unknown, so dump it too */ 9294b588458SPeter Avalos t = getsval(x); 9304b588458SPeter Avalos n = strlen(t); 9314b588458SPeter Avalos if (fmtwd > n) 9324b588458SPeter Avalos n = fmtwd; 9334b588458SPeter Avalos adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format6"); 9344b588458SPeter Avalos p += strlen(p); 935*1d48fce0SDaniel Fojt snprintf(p, BUFSZ(p), "%s", t); 9364b588458SPeter Avalos break; 937*1d48fce0SDaniel Fojt case 'a': 938*1d48fce0SDaniel Fojt case 'A': 939*1d48fce0SDaniel Fojt case 'f': snprintf(p, BUFSZ(p), fmt, getfval(x)); break; 940*1d48fce0SDaniel Fojt case 'd': snprintf(p, BUFSZ(p), fmt, (intmax_t) getfval(x)); break; 941*1d48fce0SDaniel Fojt case 'u': snprintf(p, BUFSZ(p), fmt, (uintmax_t) getfval(x)); break; 9424b588458SPeter Avalos case 's': 9434b588458SPeter Avalos t = getsval(x); 9444b588458SPeter Avalos n = strlen(t); 9454b588458SPeter Avalos if (fmtwd > n) 9464b588458SPeter Avalos n = fmtwd; 9474b588458SPeter Avalos if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format7")) 9484b588458SPeter Avalos FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t); 949*1d48fce0SDaniel Fojt snprintf(p, BUFSZ(p), fmt, t); 9504b588458SPeter Avalos break; 9514b588458SPeter Avalos case 'c': 9524b588458SPeter Avalos if (isnum(x)) { 953*1d48fce0SDaniel Fojt if ((int)getfval(x)) 954*1d48fce0SDaniel Fojt snprintf(p, BUFSZ(p), fmt, (int) getfval(x)); 9554b588458SPeter Avalos else { 9564b588458SPeter Avalos *p++ = '\0'; /* explicit null byte */ 9574b588458SPeter Avalos *p = '\0'; /* next output will start here */ 9584b588458SPeter Avalos } 9594b588458SPeter Avalos } else 960*1d48fce0SDaniel Fojt snprintf(p, BUFSZ(p), fmt, getsval(x)[0]); 9614b588458SPeter Avalos break; 9624b588458SPeter Avalos default: 9634b588458SPeter Avalos FATAL("can't happen: bad conversion %c in format()", flag); 9644b588458SPeter Avalos } 9654b588458SPeter Avalos tempfree(x); 9664b588458SPeter Avalos p += strlen(p); 9674b588458SPeter Avalos s++; 9684b588458SPeter Avalos } 9694b588458SPeter Avalos *p = '\0'; 9704b588458SPeter Avalos free(fmt); 9714b588458SPeter Avalos for ( ; a; a = a->nnext) /* evaluate any remaining args */ 9724b588458SPeter Avalos execute(a); 9734b588458SPeter Avalos *pbuf = buf; 9744b588458SPeter Avalos *pbufsize = bufsize; 9754b588458SPeter Avalos return p - buf; 9764b588458SPeter Avalos } 9774b588458SPeter Avalos 9784b588458SPeter Avalos Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */ 9794b588458SPeter Avalos { 9804b588458SPeter Avalos Cell *x; 9814b588458SPeter Avalos Node *y; 9824b588458SPeter Avalos char *buf; 9834b588458SPeter Avalos int bufsz=3*recsize; 9844b588458SPeter Avalos 985*1d48fce0SDaniel Fojt if ((buf = malloc(bufsz)) == NULL) 9864b588458SPeter Avalos FATAL("out of memory in awksprintf"); 9874b588458SPeter Avalos y = a[0]->nnext; 9884b588458SPeter Avalos x = execute(a[0]); 9894b588458SPeter Avalos if (format(&buf, &bufsz, getsval(x), y) == -1) 9904b588458SPeter Avalos FATAL("sprintf string %.30s... too long. can't happen.", buf); 9914b588458SPeter Avalos tempfree(x); 9924b588458SPeter Avalos x = gettemp(); 9934b588458SPeter Avalos x->sval = buf; 9944b588458SPeter Avalos x->tval = STR; 9954b588458SPeter Avalos return(x); 9964b588458SPeter Avalos } 9974b588458SPeter Avalos 9984b588458SPeter Avalos Cell *awkprintf(Node **a, int n) /* printf */ 9994b588458SPeter Avalos { /* a[0] is list of args, starting with format string */ 10004b588458SPeter Avalos /* a[1] is redirection operator, a[2] is redirection file */ 10014b588458SPeter Avalos FILE *fp; 10024b588458SPeter Avalos Cell *x; 10034b588458SPeter Avalos Node *y; 10044b588458SPeter Avalos char *buf; 10054b588458SPeter Avalos int len; 10064b588458SPeter Avalos int bufsz=3*recsize; 10074b588458SPeter Avalos 1008*1d48fce0SDaniel Fojt if ((buf = malloc(bufsz)) == NULL) 10094b588458SPeter Avalos FATAL("out of memory in awkprintf"); 10104b588458SPeter Avalos y = a[0]->nnext; 10114b588458SPeter Avalos x = execute(a[0]); 10124b588458SPeter Avalos if ((len = format(&buf, &bufsz, getsval(x), y)) == -1) 10134b588458SPeter Avalos FATAL("printf string %.30s... too long. can't happen.", buf); 10144b588458SPeter Avalos tempfree(x); 10154b588458SPeter Avalos if (a[1] == NULL) { 10164b588458SPeter Avalos /* fputs(buf, stdout); */ 10174b588458SPeter Avalos fwrite(buf, len, 1, stdout); 10184b588458SPeter Avalos if (ferror(stdout)) 10194b588458SPeter Avalos FATAL("write error on stdout"); 10204b588458SPeter Avalos } else { 10214b588458SPeter Avalos fp = redirect(ptoi(a[1]), a[2]); 10224b588458SPeter Avalos /* fputs(buf, fp); */ 10234b588458SPeter Avalos fwrite(buf, len, 1, fp); 10244b588458SPeter Avalos fflush(fp); 10254b588458SPeter Avalos if (ferror(fp)) 10264b588458SPeter Avalos FATAL("write error on %s", filename(fp)); 10274b588458SPeter Avalos } 10284b588458SPeter Avalos free(buf); 10294b588458SPeter Avalos return(True); 10304b588458SPeter Avalos } 10314b588458SPeter Avalos 10324b588458SPeter Avalos Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */ 10334b588458SPeter Avalos { 10344b588458SPeter Avalos Awkfloat i, j = 0; 10354b588458SPeter Avalos double v; 10364b588458SPeter Avalos Cell *x, *y, *z; 10374b588458SPeter Avalos 10384b588458SPeter Avalos x = execute(a[0]); 10394b588458SPeter Avalos i = getfval(x); 10404b588458SPeter Avalos tempfree(x); 1041*1d48fce0SDaniel Fojt if (n != UMINUS && n != UPLUS) { 10424b588458SPeter Avalos y = execute(a[1]); 10434b588458SPeter Avalos j = getfval(y); 10444b588458SPeter Avalos tempfree(y); 10454b588458SPeter Avalos } 10464b588458SPeter Avalos z = gettemp(); 10474b588458SPeter Avalos switch (n) { 10484b588458SPeter Avalos case ADD: 10494b588458SPeter Avalos i += j; 10504b588458SPeter Avalos break; 10514b588458SPeter Avalos case MINUS: 10524b588458SPeter Avalos i -= j; 10534b588458SPeter Avalos break; 10544b588458SPeter Avalos case MULT: 10554b588458SPeter Avalos i *= j; 10564b588458SPeter Avalos break; 10574b588458SPeter Avalos case DIVIDE: 10584b588458SPeter Avalos if (j == 0) 10594b588458SPeter Avalos FATAL("division by zero"); 10604b588458SPeter Avalos i /= j; 10614b588458SPeter Avalos break; 10624b588458SPeter Avalos case MOD: 10634b588458SPeter Avalos if (j == 0) 10644b588458SPeter Avalos FATAL("division by zero in mod"); 10654b588458SPeter Avalos modf(i/j, &v); 10664b588458SPeter Avalos i = i - j * v; 10674b588458SPeter Avalos break; 10684b588458SPeter Avalos case UMINUS: 10694b588458SPeter Avalos i = -i; 10704b588458SPeter Avalos break; 1071*1d48fce0SDaniel Fojt case UPLUS: /* handled by getfval(), above */ 1072*1d48fce0SDaniel Fojt break; 10734b588458SPeter Avalos case POWER: 10744b588458SPeter Avalos if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */ 10754b588458SPeter Avalos i = ipow(i, (int) j); 1076*1d48fce0SDaniel Fojt else { 1077*1d48fce0SDaniel Fojt errno = 0; 10784b588458SPeter Avalos i = errcheck(pow(i, j), "pow"); 1079*1d48fce0SDaniel Fojt } 10804b588458SPeter Avalos break; 10814b588458SPeter Avalos default: /* can't happen */ 10824b588458SPeter Avalos FATAL("illegal arithmetic operator %d", n); 10834b588458SPeter Avalos } 10844b588458SPeter Avalos setfval(z, i); 10854b588458SPeter Avalos return(z); 10864b588458SPeter Avalos } 10874b588458SPeter Avalos 10884b588458SPeter Avalos double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */ 10894b588458SPeter Avalos { 10904b588458SPeter Avalos double v; 10914b588458SPeter Avalos 10924b588458SPeter Avalos if (n <= 0) 10934b588458SPeter Avalos return 1; 10944b588458SPeter Avalos v = ipow(x, n/2); 10954b588458SPeter Avalos if (n % 2 == 0) 10964b588458SPeter Avalos return v * v; 10974b588458SPeter Avalos else 10984b588458SPeter Avalos return x * v * v; 10994b588458SPeter Avalos } 11004b588458SPeter Avalos 11014b588458SPeter Avalos Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */ 11024b588458SPeter Avalos { 11034b588458SPeter Avalos Cell *x, *z; 11044b588458SPeter Avalos int k; 11054b588458SPeter Avalos Awkfloat xf; 11064b588458SPeter Avalos 11074b588458SPeter Avalos x = execute(a[0]); 11084b588458SPeter Avalos xf = getfval(x); 11094b588458SPeter Avalos k = (n == PREINCR || n == POSTINCR) ? 1 : -1; 11104b588458SPeter Avalos if (n == PREINCR || n == PREDECR) { 11114b588458SPeter Avalos setfval(x, xf + k); 11124b588458SPeter Avalos return(x); 11134b588458SPeter Avalos } 11144b588458SPeter Avalos z = gettemp(); 11154b588458SPeter Avalos setfval(z, xf); 11164b588458SPeter Avalos setfval(x, xf + k); 11174b588458SPeter Avalos tempfree(x); 11184b588458SPeter Avalos return(z); 11194b588458SPeter Avalos } 11204b588458SPeter Avalos 11214b588458SPeter Avalos Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */ 11224b588458SPeter Avalos { /* this is subtle; don't muck with it. */ 11234b588458SPeter Avalos Cell *x, *y; 11244b588458SPeter Avalos Awkfloat xf, yf; 11254b588458SPeter Avalos double v; 11264b588458SPeter Avalos 11274b588458SPeter Avalos y = execute(a[1]); 11284b588458SPeter Avalos x = execute(a[0]); 11294b588458SPeter Avalos if (n == ASSIGN) { /* ordinary assignment */ 1130*1d48fce0SDaniel Fojt if (x == y && !(x->tval & (FLD|REC)) && x != nfloc) 1131*1d48fce0SDaniel Fojt ; /* self-assignment: leave alone unless it's a field or NF */ 11324b588458SPeter Avalos else if ((y->tval & (STR|NUM)) == (STR|NUM)) { 11334b588458SPeter Avalos setsval(x, getsval(y)); 11344b588458SPeter Avalos x->fval = getfval(y); 11354b588458SPeter Avalos x->tval |= NUM; 11364b588458SPeter Avalos } 11374b588458SPeter Avalos else if (isstr(y)) 11384b588458SPeter Avalos setsval(x, getsval(y)); 11394b588458SPeter Avalos else if (isnum(y)) 11404b588458SPeter Avalos setfval(x, getfval(y)); 11414b588458SPeter Avalos else 11424b588458SPeter Avalos funnyvar(y, "read value of"); 11434b588458SPeter Avalos tempfree(y); 11444b588458SPeter Avalos return(x); 11454b588458SPeter Avalos } 11464b588458SPeter Avalos xf = getfval(x); 11474b588458SPeter Avalos yf = getfval(y); 11484b588458SPeter Avalos switch (n) { 11494b588458SPeter Avalos case ADDEQ: 11504b588458SPeter Avalos xf += yf; 11514b588458SPeter Avalos break; 11524b588458SPeter Avalos case SUBEQ: 11534b588458SPeter Avalos xf -= yf; 11544b588458SPeter Avalos break; 11554b588458SPeter Avalos case MULTEQ: 11564b588458SPeter Avalos xf *= yf; 11574b588458SPeter Avalos break; 11584b588458SPeter Avalos case DIVEQ: 11594b588458SPeter Avalos if (yf == 0) 11604b588458SPeter Avalos FATAL("division by zero in /="); 11614b588458SPeter Avalos xf /= yf; 11624b588458SPeter Avalos break; 11634b588458SPeter Avalos case MODEQ: 11644b588458SPeter Avalos if (yf == 0) 11654b588458SPeter Avalos FATAL("division by zero in %%="); 11664b588458SPeter Avalos modf(xf/yf, &v); 11674b588458SPeter Avalos xf = xf - yf * v; 11684b588458SPeter Avalos break; 11694b588458SPeter Avalos case POWEQ: 11704b588458SPeter Avalos if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */ 11714b588458SPeter Avalos xf = ipow(xf, (int) yf); 1172*1d48fce0SDaniel Fojt else { 1173*1d48fce0SDaniel Fojt errno = 0; 11744b588458SPeter Avalos xf = errcheck(pow(xf, yf), "pow"); 1175*1d48fce0SDaniel Fojt } 11764b588458SPeter Avalos break; 11774b588458SPeter Avalos default: 11784b588458SPeter Avalos FATAL("illegal assignment operator %d", n); 11794b588458SPeter Avalos break; 11804b588458SPeter Avalos } 11814b588458SPeter Avalos tempfree(y); 11824b588458SPeter Avalos setfval(x, xf); 11834b588458SPeter Avalos return(x); 11844b588458SPeter Avalos } 11854b588458SPeter Avalos 11864b588458SPeter Avalos Cell *cat(Node **a, int q) /* a[0] cat a[1] */ 11874b588458SPeter Avalos { 11884b588458SPeter Avalos Cell *x, *y, *z; 11894b588458SPeter Avalos int n1, n2; 1190*1d48fce0SDaniel Fojt char *s = NULL; 1191*1d48fce0SDaniel Fojt int ssz = 0; 11924b588458SPeter Avalos 11934b588458SPeter Avalos x = execute(a[0]); 1194*1d48fce0SDaniel Fojt n1 = strlen(getsval(x)); 1195*1d48fce0SDaniel Fojt 11964b588458SPeter Avalos y = execute(a[1]); 1197*1d48fce0SDaniel Fojt n2 = strlen(getsval(y)); 1198*1d48fce0SDaniel Fojt 1199*1d48fce0SDaniel Fojt adjbuf(&s, &ssz, n1 + n2 + 1, recsize, 0, "cat"); 1200*1d48fce0SDaniel Fojt memcpy(s, x->sval, n1); 1201*1d48fce0SDaniel Fojt memcpy(s + n1, y->sval, n2); 1202*1d48fce0SDaniel Fojt s[n1 + n2] = '\0'; 1203*1d48fce0SDaniel Fojt 12044b588458SPeter Avalos tempfree(x); 12054b588458SPeter Avalos tempfree(y); 1206*1d48fce0SDaniel Fojt 12074b588458SPeter Avalos z = gettemp(); 12084b588458SPeter Avalos z->sval = s; 12094b588458SPeter Avalos z->tval = STR; 1210*1d48fce0SDaniel Fojt 12114b588458SPeter Avalos return(z); 12124b588458SPeter Avalos } 12134b588458SPeter Avalos 12144b588458SPeter Avalos Cell *pastat(Node **a, int n) /* a[0] { a[1] } */ 12154b588458SPeter Avalos { 12164b588458SPeter Avalos Cell *x; 12174b588458SPeter Avalos 1218*1d48fce0SDaniel Fojt if (a[0] == NULL) 12194b588458SPeter Avalos x = execute(a[1]); 12204b588458SPeter Avalos else { 12214b588458SPeter Avalos x = execute(a[0]); 12224b588458SPeter Avalos if (istrue(x)) { 12234b588458SPeter Avalos tempfree(x); 12244b588458SPeter Avalos x = execute(a[1]); 12254b588458SPeter Avalos } 12264b588458SPeter Avalos } 12274b588458SPeter Avalos return x; 12284b588458SPeter Avalos } 12294b588458SPeter Avalos 12304b588458SPeter Avalos Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */ 12314b588458SPeter Avalos { 12324b588458SPeter Avalos Cell *x; 12334b588458SPeter Avalos int pair; 12344b588458SPeter Avalos 12354b588458SPeter Avalos pair = ptoi(a[3]); 12364b588458SPeter Avalos if (pairstack[pair] == 0) { 12374b588458SPeter Avalos x = execute(a[0]); 12384b588458SPeter Avalos if (istrue(x)) 12394b588458SPeter Avalos pairstack[pair] = 1; 12404b588458SPeter Avalos tempfree(x); 12414b588458SPeter Avalos } 12424b588458SPeter Avalos if (pairstack[pair] == 1) { 12434b588458SPeter Avalos x = execute(a[1]); 12444b588458SPeter Avalos if (istrue(x)) 12454b588458SPeter Avalos pairstack[pair] = 0; 12464b588458SPeter Avalos tempfree(x); 12474b588458SPeter Avalos x = execute(a[2]); 12484b588458SPeter Avalos return(x); 12494b588458SPeter Avalos } 12504b588458SPeter Avalos return(False); 12514b588458SPeter Avalos } 12524b588458SPeter Avalos 12534b588458SPeter Avalos Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ 12544b588458SPeter Avalos { 1255*1d48fce0SDaniel Fojt Cell *x = NULL, *y, *ap; 1256*1d48fce0SDaniel Fojt const char *s, *origs, *t; 1257*1d48fce0SDaniel Fojt const char *fs = NULL; 1258*1d48fce0SDaniel Fojt char *origfs = NULL; 12594b588458SPeter Avalos int sep; 1260*1d48fce0SDaniel Fojt char temp, num[50]; 12614b588458SPeter Avalos int n, tempstat, arg3type; 12624b588458SPeter Avalos 12634b588458SPeter Avalos y = execute(a[0]); /* source string */ 12642078c1f0SJohn Marino origs = s = strdup(getsval(y)); 12654b588458SPeter Avalos arg3type = ptoi(a[3]); 1266*1d48fce0SDaniel Fojt if (a[2] == NULL) /* fs string */ 1267*1d48fce0SDaniel Fojt fs = getsval(fsloc); 12684b588458SPeter Avalos else if (arg3type == STRING) { /* split(str,arr,"string") */ 12694b588458SPeter Avalos x = execute(a[2]); 1270*1d48fce0SDaniel Fojt fs = origfs = strdup(getsval(x)); 1271*1d48fce0SDaniel Fojt tempfree(x); 12724b588458SPeter Avalos } else if (arg3type == REGEXPR) 12734b588458SPeter Avalos fs = "(regexpr)"; /* split(str,arr,/regexpr/) */ 12744b588458SPeter Avalos else 12754b588458SPeter Avalos FATAL("illegal type of split"); 12764b588458SPeter Avalos sep = *fs; 12774b588458SPeter Avalos ap = execute(a[1]); /* array name */ 12784b588458SPeter Avalos freesymtab(ap); 12794b588458SPeter Avalos dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs) ); 12804b588458SPeter Avalos ap->tval &= ~STR; 12814b588458SPeter Avalos ap->tval |= ARR; 12824b588458SPeter Avalos ap->sval = (char *) makesymtab(NSYMTAB); 12834b588458SPeter Avalos 12844b588458SPeter Avalos n = 0; 1285b12bae18SSascha Wildner if (arg3type == REGEXPR && strlen((char*)((fa*)a[2])->restr) == 0) { 1286b12bae18SSascha Wildner /* split(s, a, //); have to arrange that it looks like empty sep */ 1287b12bae18SSascha Wildner arg3type = 0; 1288b12bae18SSascha Wildner fs = ""; 1289b12bae18SSascha Wildner sep = 0; 1290b12bae18SSascha Wildner } 12914b588458SPeter Avalos if (*s != '\0' && (strlen(fs) > 1 || arg3type == REGEXPR)) { /* reg expr */ 12924b588458SPeter Avalos fa *pfa; 12934b588458SPeter Avalos if (arg3type == REGEXPR) { /* it's ready already */ 12944b588458SPeter Avalos pfa = (fa *) a[2]; 12954b588458SPeter Avalos } else { 12964b588458SPeter Avalos pfa = makedfa(fs, 1); 12974b588458SPeter Avalos } 12984b588458SPeter Avalos if (nematch(pfa,s)) { 12994b588458SPeter Avalos tempstat = pfa->initstat; 13004b588458SPeter Avalos pfa->initstat = 2; 13014b588458SPeter Avalos do { 13024b588458SPeter Avalos n++; 1303*1d48fce0SDaniel Fojt snprintf(num, sizeof(num), "%d", n); 13044b588458SPeter Avalos temp = *patbeg; 1305*1d48fce0SDaniel Fojt setptr(patbeg, '\0'); 13064b588458SPeter Avalos if (is_number(s)) 13074b588458SPeter Avalos setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval); 13084b588458SPeter Avalos else 13094b588458SPeter Avalos setsymtab(num, s, 0.0, STR, (Array *) ap->sval); 1310*1d48fce0SDaniel Fojt setptr(patbeg, temp); 13114b588458SPeter Avalos s = patbeg + patlen; 1312*1d48fce0SDaniel Fojt if (*(patbeg+patlen-1) == '\0' || *s == '\0') { 13134b588458SPeter Avalos n++; 1314*1d48fce0SDaniel Fojt snprintf(num, sizeof(num), "%d", n); 13154b588458SPeter Avalos setsymtab(num, "", 0.0, STR, (Array *) ap->sval); 13164b588458SPeter Avalos pfa->initstat = tempstat; 13174b588458SPeter Avalos goto spdone; 13184b588458SPeter Avalos } 13194b588458SPeter Avalos } while (nematch(pfa,s)); 13204b588458SPeter Avalos pfa->initstat = tempstat; /* bwk: has to be here to reset */ 13214b588458SPeter Avalos /* cf gsub and refldbld */ 13224b588458SPeter Avalos } 13234b588458SPeter Avalos n++; 1324*1d48fce0SDaniel Fojt snprintf(num, sizeof(num), "%d", n); 13254b588458SPeter Avalos if (is_number(s)) 13264b588458SPeter Avalos setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval); 13274b588458SPeter Avalos else 13284b588458SPeter Avalos setsymtab(num, s, 0.0, STR, (Array *) ap->sval); 13294b588458SPeter Avalos spdone: 13304b588458SPeter Avalos pfa = NULL; 13314b588458SPeter Avalos } else if (sep == ' ') { 13324b588458SPeter Avalos for (n = 0; ; ) { 1333*1d48fce0SDaniel Fojt #define ISWS(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') 1334*1d48fce0SDaniel Fojt while (ISWS(*s)) 13354b588458SPeter Avalos s++; 1336*1d48fce0SDaniel Fojt if (*s == '\0') 13374b588458SPeter Avalos break; 13384b588458SPeter Avalos n++; 13394b588458SPeter Avalos t = s; 13404b588458SPeter Avalos do 13414b588458SPeter Avalos s++; 1342*1d48fce0SDaniel Fojt while (*s != '\0' && !ISWS(*s)); 13434b588458SPeter Avalos temp = *s; 1344*1d48fce0SDaniel Fojt setptr(s, '\0'); 1345*1d48fce0SDaniel Fojt snprintf(num, sizeof(num), "%d", n); 13464b588458SPeter Avalos if (is_number(t)) 13474b588458SPeter Avalos setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval); 13484b588458SPeter Avalos else 13494b588458SPeter Avalos setsymtab(num, t, 0.0, STR, (Array *) ap->sval); 1350*1d48fce0SDaniel Fojt setptr(s, temp); 1351*1d48fce0SDaniel Fojt if (*s != '\0') 13524b588458SPeter Avalos s++; 13534b588458SPeter Avalos } 13544b588458SPeter Avalos } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */ 1355*1d48fce0SDaniel Fojt for (n = 0; *s != '\0'; s++) { 13564b588458SPeter Avalos char buf[2]; 13574b588458SPeter Avalos n++; 1358*1d48fce0SDaniel Fojt snprintf(num, sizeof(num), "%d", n); 13594b588458SPeter Avalos buf[0] = *s; 1360*1d48fce0SDaniel Fojt buf[1] = '\0'; 13614b588458SPeter Avalos if (isdigit((uschar)buf[0])) 13624b588458SPeter Avalos setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval); 13634b588458SPeter Avalos else 13644b588458SPeter Avalos setsymtab(num, buf, 0.0, STR, (Array *) ap->sval); 13654b588458SPeter Avalos } 1366*1d48fce0SDaniel Fojt } else if (*s != '\0') { 13674b588458SPeter Avalos for (;;) { 13684b588458SPeter Avalos n++; 13694b588458SPeter Avalos t = s; 13704b588458SPeter Avalos while (*s != sep && *s != '\n' && *s != '\0') 13714b588458SPeter Avalos s++; 13724b588458SPeter Avalos temp = *s; 1373*1d48fce0SDaniel Fojt setptr(s, '\0'); 1374*1d48fce0SDaniel Fojt snprintf(num, sizeof(num), "%d", n); 13754b588458SPeter Avalos if (is_number(t)) 13764b588458SPeter Avalos setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval); 13774b588458SPeter Avalos else 13784b588458SPeter Avalos setsymtab(num, t, 0.0, STR, (Array *) ap->sval); 1379*1d48fce0SDaniel Fojt setptr(s, temp); 1380*1d48fce0SDaniel Fojt if (*s++ == '\0') 13814b588458SPeter Avalos break; 13824b588458SPeter Avalos } 13834b588458SPeter Avalos } 13844b588458SPeter Avalos tempfree(ap); 13854b588458SPeter Avalos tempfree(y); 1386*1d48fce0SDaniel Fojt xfree(origs); 1387*1d48fce0SDaniel Fojt xfree(origfs); 13884b588458SPeter Avalos x = gettemp(); 13894b588458SPeter Avalos x->tval = NUM; 13904b588458SPeter Avalos x->fval = n; 13914b588458SPeter Avalos return(x); 13924b588458SPeter Avalos } 13934b588458SPeter Avalos 13944b588458SPeter Avalos Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */ 13954b588458SPeter Avalos { 13964b588458SPeter Avalos Cell *x; 13974b588458SPeter Avalos 13984b588458SPeter Avalos x = execute(a[0]); 13994b588458SPeter Avalos if (istrue(x)) { 14004b588458SPeter Avalos tempfree(x); 14014b588458SPeter Avalos x = execute(a[1]); 14024b588458SPeter Avalos } else { 14034b588458SPeter Avalos tempfree(x); 14044b588458SPeter Avalos x = execute(a[2]); 14054b588458SPeter Avalos } 14064b588458SPeter Avalos return(x); 14074b588458SPeter Avalos } 14084b588458SPeter Avalos 14094b588458SPeter Avalos Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */ 14104b588458SPeter Avalos { 14114b588458SPeter Avalos Cell *x; 14124b588458SPeter Avalos 14134b588458SPeter Avalos x = execute(a[0]); 14144b588458SPeter Avalos if (istrue(x)) { 14154b588458SPeter Avalos tempfree(x); 14164b588458SPeter Avalos x = execute(a[1]); 1417*1d48fce0SDaniel Fojt } else if (a[2] != NULL) { 14184b588458SPeter Avalos tempfree(x); 14194b588458SPeter Avalos x = execute(a[2]); 14204b588458SPeter Avalos } 14214b588458SPeter Avalos return(x); 14224b588458SPeter Avalos } 14234b588458SPeter Avalos 14244b588458SPeter Avalos Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */ 14254b588458SPeter Avalos { 14264b588458SPeter Avalos Cell *x; 14274b588458SPeter Avalos 14284b588458SPeter Avalos for (;;) { 14294b588458SPeter Avalos x = execute(a[0]); 14304b588458SPeter Avalos if (!istrue(x)) 14314b588458SPeter Avalos return(x); 14324b588458SPeter Avalos tempfree(x); 14334b588458SPeter Avalos x = execute(a[1]); 14344b588458SPeter Avalos if (isbreak(x)) { 14354b588458SPeter Avalos x = True; 14364b588458SPeter Avalos return(x); 14374b588458SPeter Avalos } 14384b588458SPeter Avalos if (isnext(x) || isexit(x) || isret(x)) 14394b588458SPeter Avalos return(x); 14404b588458SPeter Avalos tempfree(x); 14414b588458SPeter Avalos } 14424b588458SPeter Avalos } 14434b588458SPeter Avalos 14444b588458SPeter Avalos Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */ 14454b588458SPeter Avalos { 14464b588458SPeter Avalos Cell *x; 14474b588458SPeter Avalos 14484b588458SPeter Avalos for (;;) { 14494b588458SPeter Avalos x = execute(a[0]); 14504b588458SPeter Avalos if (isbreak(x)) 14514b588458SPeter Avalos return True; 14524b588458SPeter Avalos if (isnext(x) || isexit(x) || isret(x)) 14534b588458SPeter Avalos return(x); 14544b588458SPeter Avalos tempfree(x); 14554b588458SPeter Avalos x = execute(a[1]); 14564b588458SPeter Avalos if (!istrue(x)) 14574b588458SPeter Avalos return(x); 14584b588458SPeter Avalos tempfree(x); 14594b588458SPeter Avalos } 14604b588458SPeter Avalos } 14614b588458SPeter Avalos 14624b588458SPeter Avalos Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */ 14634b588458SPeter Avalos { 14644b588458SPeter Avalos Cell *x; 14654b588458SPeter Avalos 14664b588458SPeter Avalos x = execute(a[0]); 14674b588458SPeter Avalos tempfree(x); 14684b588458SPeter Avalos for (;;) { 1469*1d48fce0SDaniel Fojt if (a[1]!=NULL) { 14704b588458SPeter Avalos x = execute(a[1]); 14714b588458SPeter Avalos if (!istrue(x)) return(x); 14724b588458SPeter Avalos else tempfree(x); 14734b588458SPeter Avalos } 14744b588458SPeter Avalos x = execute(a[3]); 14754b588458SPeter Avalos if (isbreak(x)) /* turn off break */ 14764b588458SPeter Avalos return True; 14774b588458SPeter Avalos if (isnext(x) || isexit(x) || isret(x)) 14784b588458SPeter Avalos return(x); 14794b588458SPeter Avalos tempfree(x); 14804b588458SPeter Avalos x = execute(a[2]); 14814b588458SPeter Avalos tempfree(x); 14824b588458SPeter Avalos } 14834b588458SPeter Avalos } 14844b588458SPeter Avalos 14854b588458SPeter Avalos Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */ 14864b588458SPeter Avalos { 14874b588458SPeter Avalos Cell *x, *vp, *arrayp, *cp, *ncp; 14884b588458SPeter Avalos Array *tp; 14894b588458SPeter Avalos int i; 14904b588458SPeter Avalos 14914b588458SPeter Avalos vp = execute(a[0]); 14924b588458SPeter Avalos arrayp = execute(a[1]); 14934b588458SPeter Avalos if (!isarr(arrayp)) { 14944b588458SPeter Avalos return True; 14954b588458SPeter Avalos } 14964b588458SPeter Avalos tp = (Array *) arrayp->sval; 14974b588458SPeter Avalos tempfree(arrayp); 14984b588458SPeter Avalos for (i = 0; i < tp->size; i++) { /* this routine knows too much */ 14994b588458SPeter Avalos for (cp = tp->tab[i]; cp != NULL; cp = ncp) { 15004b588458SPeter Avalos setsval(vp, cp->nval); 15014b588458SPeter Avalos ncp = cp->cnext; 15024b588458SPeter Avalos x = execute(a[2]); 15034b588458SPeter Avalos if (isbreak(x)) { 15044b588458SPeter Avalos tempfree(vp); 15054b588458SPeter Avalos return True; 15064b588458SPeter Avalos } 15074b588458SPeter Avalos if (isnext(x) || isexit(x) || isret(x)) { 15084b588458SPeter Avalos tempfree(vp); 15094b588458SPeter Avalos return(x); 15104b588458SPeter Avalos } 15114b588458SPeter Avalos tempfree(x); 15124b588458SPeter Avalos } 15134b588458SPeter Avalos } 15144b588458SPeter Avalos return True; 15154b588458SPeter Avalos } 15164b588458SPeter Avalos 1517*1d48fce0SDaniel Fojt static char *nawk_convert(const char *s, int (*fun_c)(int), 1518*1d48fce0SDaniel Fojt wint_t (*fun_wc)(wint_t)) 1519*1d48fce0SDaniel Fojt { 1520*1d48fce0SDaniel Fojt char *buf = NULL; 1521*1d48fce0SDaniel Fojt char *pbuf = NULL; 1522*1d48fce0SDaniel Fojt const char *ps = NULL; 1523*1d48fce0SDaniel Fojt size_t n = 0; 1524*1d48fce0SDaniel Fojt mbstate_t mbs, mbs2; 1525*1d48fce0SDaniel Fojt wchar_t wc; 1526*1d48fce0SDaniel Fojt size_t sz = MB_CUR_MAX; 1527*1d48fce0SDaniel Fojt 1528*1d48fce0SDaniel Fojt if (sz == 1) { 1529*1d48fce0SDaniel Fojt buf = tostring(s); 1530*1d48fce0SDaniel Fojt 1531*1d48fce0SDaniel Fojt for (pbuf = buf; *pbuf; pbuf++) 1532*1d48fce0SDaniel Fojt *pbuf = fun_c((uschar)*pbuf); 1533*1d48fce0SDaniel Fojt 1534*1d48fce0SDaniel Fojt return buf; 1535*1d48fce0SDaniel Fojt } else { 1536*1d48fce0SDaniel Fojt /* upper/lower character may be shorter/longer */ 1537*1d48fce0SDaniel Fojt buf = tostringN(s, strlen(s) * sz + 1); 1538*1d48fce0SDaniel Fojt 1539*1d48fce0SDaniel Fojt memset(&mbs, 0, sizeof(mbs)); 1540*1d48fce0SDaniel Fojt memset(&mbs2, 0, sizeof(mbs2)); 1541*1d48fce0SDaniel Fojt 1542*1d48fce0SDaniel Fojt ps = s; 1543*1d48fce0SDaniel Fojt pbuf = buf; 1544*1d48fce0SDaniel Fojt while (n = mbrtowc(&wc, ps, sz, &mbs), 1545*1d48fce0SDaniel Fojt n > 0 && n != (size_t)-1 && n != (size_t)-2) 1546*1d48fce0SDaniel Fojt { 1547*1d48fce0SDaniel Fojt ps += n; 1548*1d48fce0SDaniel Fojt 1549*1d48fce0SDaniel Fojt n = wcrtomb(pbuf, fun_wc(wc), &mbs2); 1550*1d48fce0SDaniel Fojt if (n == (size_t)-1) 1551*1d48fce0SDaniel Fojt FATAL("illegal wide character %s", s); 1552*1d48fce0SDaniel Fojt 1553*1d48fce0SDaniel Fojt pbuf += n; 1554*1d48fce0SDaniel Fojt } 1555*1d48fce0SDaniel Fojt 1556*1d48fce0SDaniel Fojt *pbuf = '\0'; 1557*1d48fce0SDaniel Fojt 1558*1d48fce0SDaniel Fojt if (n) 1559*1d48fce0SDaniel Fojt FATAL("illegal byte sequence %s", s); 1560*1d48fce0SDaniel Fojt 1561*1d48fce0SDaniel Fojt return buf; 1562*1d48fce0SDaniel Fojt } 1563*1d48fce0SDaniel Fojt } 1564*1d48fce0SDaniel Fojt 1565*1d48fce0SDaniel Fojt static char *nawk_toupper(const char *s) 1566*1d48fce0SDaniel Fojt { 1567*1d48fce0SDaniel Fojt return nawk_convert(s, toupper, towupper); 1568*1d48fce0SDaniel Fojt } 1569*1d48fce0SDaniel Fojt 1570*1d48fce0SDaniel Fojt static char *nawk_tolower(const char *s) 1571*1d48fce0SDaniel Fojt { 1572*1d48fce0SDaniel Fojt return nawk_convert(s, tolower, towlower); 1573*1d48fce0SDaniel Fojt } 1574*1d48fce0SDaniel Fojt 15754b588458SPeter Avalos Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */ 15764b588458SPeter Avalos { 15774b588458SPeter Avalos Cell *x, *y; 15784b588458SPeter Avalos Awkfloat u; 15794b588458SPeter Avalos int t; 15800020174dSPeter Avalos Awkfloat tmp; 1581*1d48fce0SDaniel Fojt char *buf; 15824b588458SPeter Avalos Node *nextarg; 15834b588458SPeter Avalos FILE *fp; 1584*1d48fce0SDaniel Fojt int status = 0; 15854b588458SPeter Avalos 15864b588458SPeter Avalos t = ptoi(a[0]); 15874b588458SPeter Avalos x = execute(a[1]); 15884b588458SPeter Avalos nextarg = a[1]->nnext; 15894b588458SPeter Avalos switch (t) { 15904b588458SPeter Avalos case FLENGTH: 15914b588458SPeter Avalos if (isarr(x)) 15924b588458SPeter Avalos u = ((Array *) x->sval)->nelem; /* GROT. should be function*/ 15934b588458SPeter Avalos else 15944b588458SPeter Avalos u = strlen(getsval(x)); 15954b588458SPeter Avalos break; 15964b588458SPeter Avalos case FLOG: 1597*1d48fce0SDaniel Fojt errno = 0; 1598*1d48fce0SDaniel Fojt u = errcheck(log(getfval(x)), "log"); 1599*1d48fce0SDaniel Fojt break; 16004b588458SPeter Avalos case FINT: 16014b588458SPeter Avalos modf(getfval(x), &u); break; 16024b588458SPeter Avalos case FEXP: 1603*1d48fce0SDaniel Fojt errno = 0; 1604*1d48fce0SDaniel Fojt u = errcheck(exp(getfval(x)), "exp"); 1605*1d48fce0SDaniel Fojt break; 16064b588458SPeter Avalos case FSQRT: 1607*1d48fce0SDaniel Fojt errno = 0; 1608*1d48fce0SDaniel Fojt u = errcheck(sqrt(getfval(x)), "sqrt"); 1609*1d48fce0SDaniel Fojt break; 16104b588458SPeter Avalos case FSIN: 16114b588458SPeter Avalos u = sin(getfval(x)); break; 16124b588458SPeter Avalos case FCOS: 16134b588458SPeter Avalos u = cos(getfval(x)); break; 16144b588458SPeter Avalos case FATAN: 1615*1d48fce0SDaniel Fojt if (nextarg == NULL) { 16164b588458SPeter Avalos WARNING("atan2 requires two arguments; returning 1.0"); 16174b588458SPeter Avalos u = 1.0; 16184b588458SPeter Avalos } else { 16194b588458SPeter Avalos y = execute(a[1]->nnext); 16204b588458SPeter Avalos u = atan2(getfval(x), getfval(y)); 16214b588458SPeter Avalos tempfree(y); 16224b588458SPeter Avalos nextarg = nextarg->nnext; 16234b588458SPeter Avalos } 16244b588458SPeter Avalos break; 16254b588458SPeter Avalos case FSYSTEM: 16264b588458SPeter Avalos fflush(stdout); /* in case something is buffered already */ 1627*1d48fce0SDaniel Fojt status = system(getsval(x)); 1628*1d48fce0SDaniel Fojt u = status; 1629*1d48fce0SDaniel Fojt if (status != -1) { 1630*1d48fce0SDaniel Fojt if (WIFEXITED(status)) { 1631*1d48fce0SDaniel Fojt u = WEXITSTATUS(status); 1632*1d48fce0SDaniel Fojt } else if (WIFSIGNALED(status)) { 1633*1d48fce0SDaniel Fojt u = WTERMSIG(status) + 256; 1634*1d48fce0SDaniel Fojt #ifdef WCOREDUMP 1635*1d48fce0SDaniel Fojt if (WCOREDUMP(status)) 1636*1d48fce0SDaniel Fojt u += 256; 1637*1d48fce0SDaniel Fojt #endif 1638*1d48fce0SDaniel Fojt } else /* something else?!? */ 1639*1d48fce0SDaniel Fojt u = 0; 1640*1d48fce0SDaniel Fojt } 16414b588458SPeter Avalos break; 16424b588458SPeter Avalos case FRAND: 1643*1d48fce0SDaniel Fojt /* random() returns numbers in [0..2^31-1] 1644*1d48fce0SDaniel Fojt * in order to get a number in [0, 1), divide it by 2^31 1645*1d48fce0SDaniel Fojt */ 1646*1d48fce0SDaniel Fojt u = (Awkfloat) random() / (0x7fffffffL + 0x1UL); 16474b588458SPeter Avalos break; 16484b588458SPeter Avalos case FSRAND: 16494b588458SPeter Avalos if (isrec(x)) /* no argument provided */ 16504b588458SPeter Avalos u = time((time_t *)0); 16514b588458SPeter Avalos else 16524b588458SPeter Avalos u = getfval(x); 16530020174dSPeter Avalos tmp = u; 1654*1d48fce0SDaniel Fojt srandom((unsigned long) u); 16550020174dSPeter Avalos u = srand_seed; 16560020174dSPeter Avalos srand_seed = tmp; 16574b588458SPeter Avalos break; 16584b588458SPeter Avalos case FTOUPPER: 16594b588458SPeter Avalos case FTOLOWER: 1660*1d48fce0SDaniel Fojt if (t == FTOUPPER) 1661*1d48fce0SDaniel Fojt buf = nawk_toupper(getsval(x)); 1662*1d48fce0SDaniel Fojt else 1663*1d48fce0SDaniel Fojt buf = nawk_tolower(getsval(x)); 16644b588458SPeter Avalos tempfree(x); 16654b588458SPeter Avalos x = gettemp(); 16664b588458SPeter Avalos setsval(x, buf); 16674b588458SPeter Avalos free(buf); 16684b588458SPeter Avalos return x; 16694b588458SPeter Avalos case FFLUSH: 16704b588458SPeter Avalos if (isrec(x) || strlen(getsval(x)) == 0) { 16714b588458SPeter Avalos flush_all(); /* fflush() or fflush("") -> all */ 16724b588458SPeter Avalos u = 0; 1673*1d48fce0SDaniel Fojt } else if ((fp = openfile(FFLUSH, getsval(x), NULL)) == NULL) 16744b588458SPeter Avalos u = EOF; 16754b588458SPeter Avalos else 16764b588458SPeter Avalos u = fflush(fp); 16774b588458SPeter Avalos break; 16784b588458SPeter Avalos default: /* can't happen */ 16794b588458SPeter Avalos FATAL("illegal function type %d", t); 16804b588458SPeter Avalos break; 16814b588458SPeter Avalos } 16824b588458SPeter Avalos tempfree(x); 16834b588458SPeter Avalos x = gettemp(); 16844b588458SPeter Avalos setfval(x, u); 1685*1d48fce0SDaniel Fojt if (nextarg != NULL) { 16864b588458SPeter Avalos WARNING("warning: function has too many arguments"); 16874b588458SPeter Avalos for ( ; nextarg; nextarg = nextarg->nnext) 16884b588458SPeter Avalos execute(nextarg); 16894b588458SPeter Avalos } 16904b588458SPeter Avalos return(x); 16914b588458SPeter Avalos } 16924b588458SPeter Avalos 16934b588458SPeter Avalos Cell *printstat(Node **a, int n) /* print a[0] */ 16944b588458SPeter Avalos { 16954b588458SPeter Avalos Node *x; 16964b588458SPeter Avalos Cell *y; 16974b588458SPeter Avalos FILE *fp; 16984b588458SPeter Avalos 1699*1d48fce0SDaniel Fojt if (a[1] == NULL) /* a[1] is redirection operator, a[2] is file */ 17004b588458SPeter Avalos fp = stdout; 17014b588458SPeter Avalos else 17024b588458SPeter Avalos fp = redirect(ptoi(a[1]), a[2]); 17034b588458SPeter Avalos for (x = a[0]; x != NULL; x = x->nnext) { 17044b588458SPeter Avalos y = execute(x); 17054b588458SPeter Avalos fputs(getpssval(y), fp); 17064b588458SPeter Avalos tempfree(y); 17074b588458SPeter Avalos if (x->nnext == NULL) 1708*1d48fce0SDaniel Fojt fputs(getsval(orsloc), fp); 17094b588458SPeter Avalos else 1710*1d48fce0SDaniel Fojt fputs(getsval(ofsloc), fp); 17114b588458SPeter Avalos } 1712*1d48fce0SDaniel Fojt if (a[1] != NULL) 17134b588458SPeter Avalos fflush(fp); 17144b588458SPeter Avalos if (ferror(fp)) 17154b588458SPeter Avalos FATAL("write error on %s", filename(fp)); 17164b588458SPeter Avalos return(True); 17174b588458SPeter Avalos } 17184b588458SPeter Avalos 17194b588458SPeter Avalos Cell *nullproc(Node **a, int n) 17204b588458SPeter Avalos { 17214b588458SPeter Avalos return 0; 17224b588458SPeter Avalos } 17234b588458SPeter Avalos 17244b588458SPeter Avalos 17254b588458SPeter Avalos FILE *redirect(int a, Node *b) /* set up all i/o redirections */ 17264b588458SPeter Avalos { 17274b588458SPeter Avalos FILE *fp; 17284b588458SPeter Avalos Cell *x; 17294b588458SPeter Avalos char *fname; 17304b588458SPeter Avalos 17314b588458SPeter Avalos x = execute(b); 17324b588458SPeter Avalos fname = getsval(x); 1733*1d48fce0SDaniel Fojt fp = openfile(a, fname, NULL); 17344b588458SPeter Avalos if (fp == NULL) 17354b588458SPeter Avalos FATAL("can't open file %s", fname); 17364b588458SPeter Avalos tempfree(x); 17374b588458SPeter Avalos return fp; 17384b588458SPeter Avalos } 17394b588458SPeter Avalos 17404b588458SPeter Avalos struct files { 17414b588458SPeter Avalos FILE *fp; 17424b588458SPeter Avalos const char *fname; 17434b588458SPeter Avalos int mode; /* '|', 'a', 'w' => LE/LT, GT */ 1744b12bae18SSascha Wildner } *files; 1745b12bae18SSascha Wildner 1746*1d48fce0SDaniel Fojt size_t nfiles; 17474b588458SPeter Avalos 1748*1d48fce0SDaniel Fojt static void stdinit(void) /* in case stdin, etc., are not constants */ 17494b588458SPeter Avalos { 1750b12bae18SSascha Wildner nfiles = FOPEN_MAX; 1751b12bae18SSascha Wildner files = calloc(nfiles, sizeof(*files)); 1752b12bae18SSascha Wildner if (files == NULL) 1753*1d48fce0SDaniel Fojt FATAL("can't allocate file memory for %zu files", nfiles); 17544b588458SPeter Avalos files[0].fp = stdin; 1755b12bae18SSascha Wildner files[0].fname = "/dev/stdin"; 1756b12bae18SSascha Wildner files[0].mode = LT; 17574b588458SPeter Avalos files[1].fp = stdout; 1758b12bae18SSascha Wildner files[1].fname = "/dev/stdout"; 1759b12bae18SSascha Wildner files[1].mode = GT; 17604b588458SPeter Avalos files[2].fp = stderr; 1761b12bae18SSascha Wildner files[2].fname = "/dev/stderr"; 1762b12bae18SSascha Wildner files[2].mode = GT; 17634b588458SPeter Avalos } 17644b588458SPeter Avalos 1765*1d48fce0SDaniel Fojt FILE *openfile(int a, const char *us, bool *pnewflag) 17664b588458SPeter Avalos { 17674b588458SPeter Avalos const char *s = us; 1768*1d48fce0SDaniel Fojt size_t i; 1769*1d48fce0SDaniel Fojt int m; 1770*1d48fce0SDaniel Fojt FILE *fp = NULL; 17714b588458SPeter Avalos 17724b588458SPeter Avalos if (*s == '\0') 17734b588458SPeter Avalos FATAL("null file name in print or getline"); 1774b12bae18SSascha Wildner for (i = 0; i < nfiles; i++) 1775*1d48fce0SDaniel Fojt if (files[i].fname && strcmp(s, files[i].fname) == 0 && 1776*1d48fce0SDaniel Fojt (a == files[i].mode || (a==APPEND && files[i].mode==GT) || 1777*1d48fce0SDaniel Fojt a == FFLUSH)) { 1778*1d48fce0SDaniel Fojt if (pnewflag) 1779*1d48fce0SDaniel Fojt *pnewflag = false; 17804b588458SPeter Avalos return files[i].fp; 17814b588458SPeter Avalos } 17824b588458SPeter Avalos if (a == FFLUSH) /* didn't find it, so don't create it! */ 17834b588458SPeter Avalos return NULL; 17844b588458SPeter Avalos 1785b12bae18SSascha Wildner for (i = 0; i < nfiles; i++) 1786*1d48fce0SDaniel Fojt if (files[i].fp == NULL) 17874b588458SPeter Avalos break; 1788b12bae18SSascha Wildner if (i >= nfiles) { 1789b12bae18SSascha Wildner struct files *nf; 1790*1d48fce0SDaniel Fojt size_t nnf = nfiles + FOPEN_MAX; 1791b12bae18SSascha Wildner nf = realloc(files, nnf * sizeof(*nf)); 1792b12bae18SSascha Wildner if (nf == NULL) 1793*1d48fce0SDaniel Fojt FATAL("cannot grow files for %s and %zu files", s, nnf); 1794b12bae18SSascha Wildner memset(&nf[nfiles], 0, FOPEN_MAX * sizeof(*nf)); 1795b12bae18SSascha Wildner nfiles = nnf; 1796b12bae18SSascha Wildner files = nf; 1797b12bae18SSascha Wildner } 17984b588458SPeter Avalos fflush(stdout); /* force a semblance of order */ 17994b588458SPeter Avalos m = a; 18004b588458SPeter Avalos if (a == GT) { 18014b588458SPeter Avalos fp = fopen(s, "w"); 18024b588458SPeter Avalos } else if (a == APPEND) { 18034b588458SPeter Avalos fp = fopen(s, "a"); 18044b588458SPeter Avalos m = GT; /* so can mix > and >> */ 18054b588458SPeter Avalos } else if (a == '|') { /* output pipe */ 18064b588458SPeter Avalos fp = popen(s, "w"); 18074b588458SPeter Avalos } else if (a == LE) { /* input pipe */ 18084b588458SPeter Avalos fp = popen(s, "r"); 18094b588458SPeter Avalos } else if (a == LT) { /* getline <file */ 18104b588458SPeter Avalos fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */ 18114b588458SPeter Avalos } else /* can't happen */ 18124b588458SPeter Avalos FATAL("illegal redirection %d", a); 18134b588458SPeter Avalos if (fp != NULL) { 18144b588458SPeter Avalos files[i].fname = tostring(s); 18154b588458SPeter Avalos files[i].fp = fp; 18164b588458SPeter Avalos files[i].mode = m; 1817*1d48fce0SDaniel Fojt if (pnewflag) 1818*1d48fce0SDaniel Fojt *pnewflag = true; 1819*1d48fce0SDaniel Fojt if (fp != stdin && fp != stdout && fp != stderr) 1820*1d48fce0SDaniel Fojt (void) fcntl(fileno(fp), F_SETFD, FD_CLOEXEC); 18214b588458SPeter Avalos } 18224b588458SPeter Avalos return fp; 18234b588458SPeter Avalos } 18244b588458SPeter Avalos 18254b588458SPeter Avalos const char *filename(FILE *fp) 18264b588458SPeter Avalos { 1827*1d48fce0SDaniel Fojt size_t i; 18284b588458SPeter Avalos 1829b12bae18SSascha Wildner for (i = 0; i < nfiles; i++) 18304b588458SPeter Avalos if (fp == files[i].fp) 18314b588458SPeter Avalos return files[i].fname; 18324b588458SPeter Avalos return "???"; 18334b588458SPeter Avalos } 18344b588458SPeter Avalos 18354b588458SPeter Avalos Cell *closefile(Node **a, int n) 18364b588458SPeter Avalos { 18374b588458SPeter Avalos Cell *x; 1838*1d48fce0SDaniel Fojt size_t i; 1839*1d48fce0SDaniel Fojt bool stat; 18404b588458SPeter Avalos 18414b588458SPeter Avalos x = execute(a[0]); 18424b588458SPeter Avalos getsval(x); 1843*1d48fce0SDaniel Fojt stat = true; 1844b12bae18SSascha Wildner for (i = 0; i < nfiles; i++) { 1845*1d48fce0SDaniel Fojt if (!files[i].fname || strcmp(x->sval, files[i].fname) != 0) 1846*1d48fce0SDaniel Fojt continue; 18474b588458SPeter Avalos if (ferror(files[i].fp)) 1848*1d48fce0SDaniel Fojt FATAL("i/o error occurred on %s", files[i].fname); 18494b588458SPeter Avalos if (files[i].mode == '|' || files[i].mode == LE) 1850*1d48fce0SDaniel Fojt stat = pclose(files[i].fp) == -1; 18514b588458SPeter Avalos else 1852*1d48fce0SDaniel Fojt stat = fclose(files[i].fp) == EOF; 1853*1d48fce0SDaniel Fojt if (stat) 1854*1d48fce0SDaniel Fojt FATAL("i/o error occurred closing %s", files[i].fname); 18554b588458SPeter Avalos if (i > 2) /* don't do /dev/std... */ 18564b588458SPeter Avalos xfree(files[i].fname); 18574b588458SPeter Avalos files[i].fname = NULL; /* watch out for ref thru this */ 18584b588458SPeter Avalos files[i].fp = NULL; 18594b588458SPeter Avalos } 18604b588458SPeter Avalos tempfree(x); 18614b588458SPeter Avalos x = gettemp(); 1862*1d48fce0SDaniel Fojt setfval(x, (Awkfloat) (stat ? -1 : 0)); 18634b588458SPeter Avalos return(x); 18644b588458SPeter Avalos } 18654b588458SPeter Avalos 18664b588458SPeter Avalos void closeall(void) 18674b588458SPeter Avalos { 1868*1d48fce0SDaniel Fojt size_t i; 1869*1d48fce0SDaniel Fojt bool stat = false; 18704b588458SPeter Avalos 1871*1d48fce0SDaniel Fojt for (i = 0; i < nfiles; i++) { 1872*1d48fce0SDaniel Fojt if (! files[i].fp) 1873*1d48fce0SDaniel Fojt continue; 18744b588458SPeter Avalos if (ferror(files[i].fp)) 1875*1d48fce0SDaniel Fojt FATAL( "i/o error occurred on %s", files[i].fname ); 18764b588458SPeter Avalos if (files[i].mode == '|' || files[i].mode == LE) 1877*1d48fce0SDaniel Fojt stat = pclose(files[i].fp) == -1; 18784b588458SPeter Avalos else 1879*1d48fce0SDaniel Fojt stat = fclose(files[i].fp) == EOF; 1880*1d48fce0SDaniel Fojt if (stat) 1881*1d48fce0SDaniel Fojt FATAL( "i/o error occurred while closing %s", files[i].fname ); 18824b588458SPeter Avalos } 18834b588458SPeter Avalos } 18844b588458SPeter Avalos 1885*1d48fce0SDaniel Fojt static void flush_all(void) 18864b588458SPeter Avalos { 1887*1d48fce0SDaniel Fojt size_t i; 18884b588458SPeter Avalos 1889b12bae18SSascha Wildner for (i = 0; i < nfiles; i++) 18904b588458SPeter Avalos if (files[i].fp) 18914b588458SPeter Avalos fflush(files[i].fp); 18924b588458SPeter Avalos } 18934b588458SPeter Avalos 1894*1d48fce0SDaniel Fojt void backsub(char **pb_ptr, const char **sptr_ptr); 18954b588458SPeter Avalos 18964b588458SPeter Avalos Cell *sub(Node **a, int nnn) /* substitute command */ 18974b588458SPeter Avalos { 1898*1d48fce0SDaniel Fojt const char *sptr, *q; 18994b588458SPeter Avalos Cell *x, *y, *result; 1900*1d48fce0SDaniel Fojt char *t, *buf, *pb; 19014b588458SPeter Avalos fa *pfa; 19024b588458SPeter Avalos int bufsz = recsize; 19034b588458SPeter Avalos 1904*1d48fce0SDaniel Fojt if ((buf = malloc(bufsz)) == NULL) 19054b588458SPeter Avalos FATAL("out of memory in sub"); 19064b588458SPeter Avalos x = execute(a[3]); /* target string */ 19074b588458SPeter Avalos t = getsval(x); 1908*1d48fce0SDaniel Fojt if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */ 19094b588458SPeter Avalos pfa = (fa *) a[1]; /* regular expression */ 19104b588458SPeter Avalos else { 19114b588458SPeter Avalos y = execute(a[1]); 19124b588458SPeter Avalos pfa = makedfa(getsval(y), 1); 19134b588458SPeter Avalos tempfree(y); 19144b588458SPeter Avalos } 19154b588458SPeter Avalos y = execute(a[2]); /* replacement string */ 19164b588458SPeter Avalos result = False; 19174b588458SPeter Avalos if (pmatch(pfa, t)) { 19184b588458SPeter Avalos sptr = t; 19194b588458SPeter Avalos adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub"); 19204b588458SPeter Avalos pb = buf; 19214b588458SPeter Avalos while (sptr < patbeg) 19224b588458SPeter Avalos *pb++ = *sptr++; 19234b588458SPeter Avalos sptr = getsval(y); 1924*1d48fce0SDaniel Fojt while (*sptr != '\0') { 19254b588458SPeter Avalos adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub"); 19264b588458SPeter Avalos if (*sptr == '\\') { 19274b588458SPeter Avalos backsub(&pb, &sptr); 19284b588458SPeter Avalos } else if (*sptr == '&') { 19294b588458SPeter Avalos sptr++; 19304b588458SPeter Avalos adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub"); 19314b588458SPeter Avalos for (q = patbeg; q < patbeg+patlen; ) 19324b588458SPeter Avalos *pb++ = *q++; 19334b588458SPeter Avalos } else 19344b588458SPeter Avalos *pb++ = *sptr++; 19354b588458SPeter Avalos } 19364b588458SPeter Avalos *pb = '\0'; 19374b588458SPeter Avalos if (pb > buf + bufsz) 19384b588458SPeter Avalos FATAL("sub result1 %.30s too big; can't happen", buf); 19394b588458SPeter Avalos sptr = patbeg + patlen; 19404b588458SPeter Avalos if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) { 19414b588458SPeter Avalos adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub"); 1942*1d48fce0SDaniel Fojt while ((*pb++ = *sptr++) != '\0') 1943*1d48fce0SDaniel Fojt continue; 19444b588458SPeter Avalos } 19454b588458SPeter Avalos if (pb > buf + bufsz) 19464b588458SPeter Avalos FATAL("sub result2 %.30s too big; can't happen", buf); 19474b588458SPeter Avalos setsval(x, buf); /* BUG: should be able to avoid copy */ 1948*1d48fce0SDaniel Fojt result = True; 19494b588458SPeter Avalos } 19504b588458SPeter Avalos tempfree(x); 19514b588458SPeter Avalos tempfree(y); 19524b588458SPeter Avalos free(buf); 19534b588458SPeter Avalos return result; 19544b588458SPeter Avalos } 19554b588458SPeter Avalos 19564b588458SPeter Avalos Cell *gsub(Node **a, int nnn) /* global substitute */ 19574b588458SPeter Avalos { 19584b588458SPeter Avalos Cell *x, *y; 1959*1d48fce0SDaniel Fojt char *rptr, *pb; 1960*1d48fce0SDaniel Fojt const char *q, *t, *sptr; 19614b588458SPeter Avalos char *buf; 19624b588458SPeter Avalos fa *pfa; 19634b588458SPeter Avalos int mflag, tempstat, num; 19644b588458SPeter Avalos int bufsz = recsize; 19654b588458SPeter Avalos 1966*1d48fce0SDaniel Fojt if ((buf = malloc(bufsz)) == NULL) 19674b588458SPeter Avalos FATAL("out of memory in gsub"); 19684b588458SPeter Avalos mflag = 0; /* if mflag == 0, can replace empty string */ 19694b588458SPeter Avalos num = 0; 19704b588458SPeter Avalos x = execute(a[3]); /* target string */ 19714b588458SPeter Avalos t = getsval(x); 1972*1d48fce0SDaniel Fojt if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */ 19734b588458SPeter Avalos pfa = (fa *) a[1]; /* regular expression */ 19744b588458SPeter Avalos else { 19754b588458SPeter Avalos y = execute(a[1]); 19764b588458SPeter Avalos pfa = makedfa(getsval(y), 1); 19774b588458SPeter Avalos tempfree(y); 19784b588458SPeter Avalos } 19794b588458SPeter Avalos y = execute(a[2]); /* replacement string */ 19804b588458SPeter Avalos if (pmatch(pfa, t)) { 19814b588458SPeter Avalos tempstat = pfa->initstat; 19824b588458SPeter Avalos pfa->initstat = 2; 19834b588458SPeter Avalos pb = buf; 19844b588458SPeter Avalos rptr = getsval(y); 19854b588458SPeter Avalos do { 1986*1d48fce0SDaniel Fojt if (patlen == 0 && *patbeg != '\0') { /* matched empty string */ 19874b588458SPeter Avalos if (mflag == 0) { /* can replace empty */ 19884b588458SPeter Avalos num++; 19894b588458SPeter Avalos sptr = rptr; 1990*1d48fce0SDaniel Fojt while (*sptr != '\0') { 19914b588458SPeter Avalos adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub"); 19924b588458SPeter Avalos if (*sptr == '\\') { 19934b588458SPeter Avalos backsub(&pb, &sptr); 19944b588458SPeter Avalos } else if (*sptr == '&') { 19954b588458SPeter Avalos sptr++; 19964b588458SPeter Avalos adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub"); 19974b588458SPeter Avalos for (q = patbeg; q < patbeg+patlen; ) 19984b588458SPeter Avalos *pb++ = *q++; 19994b588458SPeter Avalos } else 20004b588458SPeter Avalos *pb++ = *sptr++; 20014b588458SPeter Avalos } 20024b588458SPeter Avalos } 2003*1d48fce0SDaniel Fojt if (*t == '\0') /* at end */ 20044b588458SPeter Avalos goto done; 20054b588458SPeter Avalos adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub"); 20064b588458SPeter Avalos *pb++ = *t++; 20074b588458SPeter Avalos if (pb > buf + bufsz) /* BUG: not sure of this test */ 20084b588458SPeter Avalos FATAL("gsub result0 %.30s too big; can't happen", buf); 20094b588458SPeter Avalos mflag = 0; 20104b588458SPeter Avalos } 20114b588458SPeter Avalos else { /* matched nonempty string */ 20124b588458SPeter Avalos num++; 20134b588458SPeter Avalos sptr = t; 20144b588458SPeter Avalos adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub"); 20154b588458SPeter Avalos while (sptr < patbeg) 20164b588458SPeter Avalos *pb++ = *sptr++; 20174b588458SPeter Avalos sptr = rptr; 2018*1d48fce0SDaniel Fojt while (*sptr != '\0') { 20194b588458SPeter Avalos adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub"); 20204b588458SPeter Avalos if (*sptr == '\\') { 20214b588458SPeter Avalos backsub(&pb, &sptr); 20224b588458SPeter Avalos } else if (*sptr == '&') { 20234b588458SPeter Avalos sptr++; 20244b588458SPeter Avalos adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub"); 20254b588458SPeter Avalos for (q = patbeg; q < patbeg+patlen; ) 20264b588458SPeter Avalos *pb++ = *q++; 20274b588458SPeter Avalos } else 20284b588458SPeter Avalos *pb++ = *sptr++; 20294b588458SPeter Avalos } 20304b588458SPeter Avalos t = patbeg + patlen; 2031*1d48fce0SDaniel Fojt if (patlen == 0 || *t == '\0' || *(t-1) == '\0') 20324b588458SPeter Avalos goto done; 20334b588458SPeter Avalos if (pb > buf + bufsz) 20344b588458SPeter Avalos FATAL("gsub result1 %.30s too big; can't happen", buf); 20354b588458SPeter Avalos mflag = 1; 20364b588458SPeter Avalos } 20374b588458SPeter Avalos } while (pmatch(pfa,t)); 20384b588458SPeter Avalos sptr = t; 20394b588458SPeter Avalos adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub"); 2040*1d48fce0SDaniel Fojt while ((*pb++ = *sptr++) != '\0') 2041*1d48fce0SDaniel Fojt continue; 20424b588458SPeter Avalos done: if (pb < buf + bufsz) 20434b588458SPeter Avalos *pb = '\0'; 20444b588458SPeter Avalos else if (*(pb-1) != '\0') 20454b588458SPeter Avalos FATAL("gsub result2 %.30s truncated; can't happen", buf); 20464b588458SPeter Avalos setsval(x, buf); /* BUG: should be able to avoid copy + free */ 20474b588458SPeter Avalos pfa->initstat = tempstat; 20484b588458SPeter Avalos } 20494b588458SPeter Avalos tempfree(x); 20504b588458SPeter Avalos tempfree(y); 20514b588458SPeter Avalos x = gettemp(); 20524b588458SPeter Avalos x->tval = NUM; 20534b588458SPeter Avalos x->fval = num; 20544b588458SPeter Avalos free(buf); 20554b588458SPeter Avalos return(x); 20564b588458SPeter Avalos } 20574b588458SPeter Avalos 2058*1d48fce0SDaniel Fojt void backsub(char **pb_ptr, const char **sptr_ptr) /* handle \\& variations */ 20594b588458SPeter Avalos { /* sptr[0] == '\\' */ 2060*1d48fce0SDaniel Fojt char *pb = *pb_ptr; 2061*1d48fce0SDaniel Fojt const char *sptr = *sptr_ptr; 2062*1d48fce0SDaniel Fojt static bool first = true; 2063*1d48fce0SDaniel Fojt static bool do_posix = false; 2064*1d48fce0SDaniel Fojt 2065*1d48fce0SDaniel Fojt if (first) { 2066*1d48fce0SDaniel Fojt first = false; 2067*1d48fce0SDaniel Fojt do_posix = (getenv("POSIXLY_CORRECT") != NULL); 2068*1d48fce0SDaniel Fojt } 20694b588458SPeter Avalos 20704b588458SPeter Avalos if (sptr[1] == '\\') { 20714b588458SPeter Avalos if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */ 20724b588458SPeter Avalos *pb++ = '\\'; 20734b588458SPeter Avalos *pb++ = '&'; 20744b588458SPeter Avalos sptr += 4; 20754b588458SPeter Avalos } else if (sptr[2] == '&') { /* \\& -> \ + matched */ 20764b588458SPeter Avalos *pb++ = '\\'; 20774b588458SPeter Avalos sptr += 2; 2078*1d48fce0SDaniel Fojt } else if (do_posix) { /* \\x -> \x */ 2079*1d48fce0SDaniel Fojt sptr++; 2080*1d48fce0SDaniel Fojt *pb++ = *sptr++; 20814b588458SPeter Avalos } else { /* \\x -> \\x */ 20824b588458SPeter Avalos *pb++ = *sptr++; 20834b588458SPeter Avalos *pb++ = *sptr++; 20844b588458SPeter Avalos } 20854b588458SPeter Avalos } else if (sptr[1] == '&') { /* literal & */ 20864b588458SPeter Avalos sptr++; 20874b588458SPeter Avalos *pb++ = *sptr++; 20884b588458SPeter Avalos } else /* literal \ */ 20894b588458SPeter Avalos *pb++ = *sptr++; 20904b588458SPeter Avalos 20914b588458SPeter Avalos *pb_ptr = pb; 20924b588458SPeter Avalos *sptr_ptr = sptr; 20934b588458SPeter Avalos } 2094