1 /****************************************************************
2 Copyright (C) Lucent Technologies 1997
5 Permission to use, copy, modify, and distribute this software and
6 its documentation for any purpose and without fee is hereby
7 granted, provided that the above copyright notice appear in all
8 copies and that both that the copyright notice and this
9 permission notice and warranty disclaimer appear in supporting
10 documentation, and that the name Lucent Technologies or any of
11 its entities not be used in advertising or publicity pertaining
12 to distribution of the software without specific, written prior
15 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
23 ****************************************************************/
25 #include <sys/cdefs.h>
26 __FBSDID("$FreeBSD$");
41 #include <sys/types.h>
44 #include "awkgram.tab.h"
46 static void stdinit(void);
47 static void flush_all(void);
50 #define tempfree(x) do { if (istemp(x)) tfree(x); } while (/*CONSTCOND*/0)
52 void tempfree(Cell *p) {
53 if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) {
54 WARNING("bad csub %d in Cell %d %s",
55 p->csub, p->ctype, p->sval);
62 /* do we really need these? */
64 /* #ifndef FOPEN_MAX */
65 /* #define FOPEN_MAX _NFILE */
69 /* #ifndef FOPEN_MAX */
70 /* #define FOPEN_MAX 40 */ /* max number of open files */
73 /* #ifndef RAND_MAX */
74 /* #define RAND_MAX 32767 */ /* all that ansi guarantees */
78 extern int pairstack[];
79 extern Awkfloat srand_seed;
81 Node *winner = NULL; /* root of parse tree */
82 Cell *tmps; /* free temporary cells for execution */
84 static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM, NULL, NULL };
85 Cell *True = &truecell;
86 static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM, NULL, NULL };
87 Cell *False = &falsecell;
88 static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM, NULL, NULL };
89 Cell *jbreak = &breakcell;
90 static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM, NULL, NULL };
91 Cell *jcont = &contcell;
92 static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM, NULL, NULL };
93 Cell *jnext = &nextcell;
94 static Cell nextfilecell ={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM, NULL, NULL };
95 Cell *jnextfile = &nextfilecell;
96 static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM, NULL, NULL };
97 Cell *jexit = &exitcell;
98 static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM, NULL, NULL };
99 Cell *jret = &retcell;
100 static Cell tempcell ={ OCELL, CTEMP, 0, EMPTY, 0.0, NUM|STR|DONTFREE, NULL, NULL };
102 Node *curnode = NULL; /* the node being executed, for debugging */
104 /* buffer memory management */
105 int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,
107 /* pbuf: address of pointer to buffer being managed
108 * psiz: address of buffer size variable
109 * minlen: minimum length of buffer needed
110 * quantum: buffer size quantum
111 * pbptr: address of movable pointer into buffer, or 0 if none
112 * whatrtn: name of the calling routine if failure should cause fatal error
114 * return 0 for realloc failure, !=0 for success
117 if (minlen > *psiz) {
119 int rminlen = quantum ? minlen % quantum : 0;
120 int boff = pbptr ? *pbptr - *pbuf : 0;
121 /* round up to next multiple of quantum */
123 minlen += quantum - rminlen;
124 tbuf = (char *) realloc(*pbuf, minlen);
125 DPRINTF("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, (void*)*pbuf, (void*)tbuf);
128 FATAL("out of memory in %s", whatrtn);
134 *pbptr = tbuf + boff;
139 void run(Node *a) /* execution of parse tree starts here */
147 Cell *execute(Node *u) /* execute a node of the parse tree */
149 Cell *(*proc)(Node **, int);
155 for (a = u; ; a = a->nnext) {
158 x = (Cell *) (a->narg[0]);
159 if (isfld(x) && !donefld)
161 else if (isrec(x) && !donerec)
165 if (notlegal(a->nobj)) /* probably a Cell* but too risky to print */
166 FATAL("illegal statement");
167 proc = proctab[a->nobj-FIRSTTOKEN];
168 x = (*proc)(a->narg, a->nobj);
169 if (isfld(x) && !donefld)
171 else if (isrec(x) && !donerec)
177 if (a->nnext == NULL)
184 Cell *program(Node **a, int n) /* execute an awk program */
185 { /* a[0] = BEGIN, a[1] = body, a[2] = END */
188 if (setjmp(env) != 0)
190 if (a[0]) { /* BEGIN */
195 FATAL("illegal break, continue, next or nextfile from BEGIN");
199 while (getrec(&record, &recsize, true) > 0) {
206 if (setjmp(env) != 0) /* handles exit within END */
208 if (a[2]) { /* END */
210 if (isbreak(x) || isnext(x) || iscont(x))
211 FATAL("illegal break, continue, next or nextfile from END");
218 struct Frame { /* stack frame for awk function calls */
219 int nargs; /* number of arguments in this call */
220 Cell *fcncell; /* pointer to Cell for function */
221 Cell **args; /* pointer to array of arguments after execute */
222 Cell *retval; /* return value */
225 #define NARGS 50 /* max args in a call */
227 struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */
228 int nframe = 0; /* number of frames allocated */
229 struct Frame *frp = NULL; /* frame pointer. bottom level unused */
231 Cell *call(Node **a, int n) /* function call. very kludgy and fragile */
233 static const Cell newcopycell = { OCELL, CCOPY, 0, EMPTY, 0.0, NUM|STR|DONTFREE, NULL, NULL };
235 int freed = 0; /* handles potential double freeing when fcn & param share a tempcell */
237 Cell *args[NARGS], *oargs[NARGS]; /* BUG: fixed size arrays */
241 fcn = execute(a[0]); /* the function itself */
244 FATAL("calling undefined function %s", s);
246 frp = frame = (struct Frame *) calloc(nframe += 100, sizeof(*frame));
248 FATAL("out of space for stack frames calling %s", s);
250 for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */
252 ndef = (int) fcn->fval; /* args in defn */
253 DPRINTF("calling %s, %d args (%d in defn), frp=%d\n", s, ncall, ndef, (int) (frp-frame));
255 WARNING("function %s called with %d args, uses only %d",
257 if (ncall + ndef > NARGS)
258 FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS);
259 for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */
260 DPRINTF("evaluate args[%d], frp=%d:\n", i, (int) (frp-frame));
263 DPRINTF("args[%d]: %s %f <%s>, t=%o\n",
264 i, NN(y->nval), y->fval, isarr(y) ? "(array)" : NN(y->sval), y->tval);
266 FATAL("can't use function %s as argument in %s", y->nval, s);
268 args[i] = y; /* arrays by ref */
270 args[i] = copycell(y);
273 for ( ; i < ndef; i++) { /* add null args for ones not provided */
275 *args[i] = newcopycell;
277 frp++; /* now ok to up frame */
278 if (frp >= frame + nframe) {
279 int dfp = frp - frame; /* old index */
280 frame = (struct Frame *) realloc(frame, (nframe += 100) * sizeof(*frame));
282 FATAL("out of space for stack frames in %s", s);
287 frp->nargs = ndef; /* number defined with (excess are locals) */
288 frp->retval = gettemp();
290 DPRINTF("start exec of %s, frp=%d\n", s, (int) (frp-frame));
291 y = execute((Node *)(fcn->sval)); /* execute body */
292 DPRINTF("finished exec of %s, frp=%d\n", s, (int) (frp-frame));
294 for (i = 0; i < ndef; i++) {
295 Cell *t = frp->args[i];
297 if (t->csub == CCOPY) {
303 oargs[i]->tval = t->tval;
304 oargs[i]->tval &= ~(STR|NUM|DONTFREE);
305 oargs[i]->sval = t->sval;
309 } else if (t != y) { /* kludge to prevent freeing twice */
312 } else if (t == y && t->csub == CCOPY) {
319 if (isexit(y) || isnext(y))
322 tempfree(y); /* don't free twice! */
324 z = frp->retval; /* return value */
325 DPRINTF("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval);
330 Cell *copycell(Cell *x) /* make a copy of a cell in a temp */
334 /* copy is not constant or field */
337 y->tval = x->tval & ~(CON|FLD|REC);
338 y->csub = CCOPY; /* prevents freeing until call is over */
339 y->nval = x->nval; /* BUG? */
340 if (isstr(x) /* || x->ctype == OCELL */) {
341 y->sval = tostring(x->sval);
342 y->tval &= ~DONTFREE;
349 Cell *arg(Node **a, int n) /* nth argument of a function */
352 n = ptoi(a[0]); /* argument number, counting from 0 */
353 DPRINTF("arg(%d), frp->nargs=%d\n", n, frp->nargs);
354 if (n+1 > frp->nargs)
355 FATAL("argument #%d of function %s was not supplied",
356 n+1, frp->fcncell->nval);
360 Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */
368 errorflag = (int) getfval(y);
375 if ((y->tval & (STR|NUM)) == (STR|NUM)) {
376 setsval(frp->retval, getsval(y));
377 frp->retval->fval = getfval(y);
378 frp->retval->tval |= NUM;
380 else if (y->tval & STR)
381 setsval(frp->retval, getsval(y));
382 else if (y->tval & NUM)
383 setfval(frp->retval, getfval(y));
384 else /* can't happen */
385 FATAL("bad type variable %d", y->tval);
398 default: /* can't happen */
399 FATAL("illegal jump type %d", n);
401 return 0; /* not reached */
404 Cell *awkgetline(Node **a, int n) /* get next line from specific input */
405 { /* a[0] is variable, a[1] is operator, a[2] is filename */
407 extern Cell **fldtab;
410 int bufsize = recsize;
415 if ((buf = (char *) malloc(bufsize)) == NULL)
416 FATAL("out of memory in getline");
418 fflush(stdout); /* in case someone is waiting for a prompt */
420 if (a[1] != NULL) { /* getline < file */
421 x = execute(a[2]); /* filename */
423 if (mode == '|') /* input pipe */
424 mode = LE; /* arbitrary flag */
425 fp = openfile(mode, getsval(x), &newflag);
430 n = readrec(&buf, &bufsize, fp, newflag);
433 } else if (a[0] != NULL) { /* getline var <file */
436 if (is_number(x->sval, & result)) {
441 } else { /* getline <file */
442 setsval(fldtab[0], buf);
443 if (is_number(fldtab[0]->sval, & result)) {
444 fldtab[0]->fval = result;
445 fldtab[0]->tval |= NUM;
448 } else { /* bare getline; use current input */
449 if (a[0] == NULL) /* getline */
450 n = getrec(&record, &recsize, true);
451 else { /* getline var */
452 n = getrec(&buf, &bufsize, false);
455 if (is_number(x->sval, & result)) {
462 setfval(r, (Awkfloat) n);
467 Cell *getnf(Node **a, int n) /* get NF */
471 return (Cell *) a[0];
475 makearraystring(Node *p, const char *func)
481 if ((buf = (char *) malloc(bufsz)) == NULL) {
482 FATAL("%s: out of memory", func);
488 for (; p; p = p->nnext) {
489 Cell *x = execute(p); /* expr */
490 char *s = getsval(x);
491 size_t seplen = strlen(getsval(subseploc));
492 size_t nsub = p->nnext ? seplen : 0;
493 size_t slen = strlen(s);
494 size_t tlen = blen + slen + nsub;
496 if (!adjbuf(&buf, &bufsz, tlen + 1, recsize, 0, func)) {
497 FATAL("%s: out of memory %s[%s...]",
500 memcpy(buf + blen, s, slen);
502 memcpy(buf + blen + slen, *SUBSEP, nsub);
511 Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
516 x = execute(a[0]); /* Cell* for symbol table */
517 buf = makearraystring(a[1], __func__);
519 DPRINTF("making %s into an array\n", NN(x->nval));
522 x->tval &= ~(STR|NUM|DONTFREE);
524 x->sval = (char *) makesymtab(NSYMTAB);
526 z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
534 Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
538 x = execute(a[0]); /* Cell* for symbol table */
539 if (x == symtabloc) {
540 FATAL("cannot delete SYMTAB or its elements");
544 if (a[1] == NULL) { /* delete the elements, not the table */
548 x->sval = (char *) makesymtab(NSYMTAB);
550 char *buf = makearraystring(a[1], __func__);
558 Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
563 ap = execute(a[1]); /* array name */
565 DPRINTF("making %s into an array\n", ap->nval);
568 ap->tval &= ~(STR|NUM|DONTFREE);
570 ap->sval = (char *) makesymtab(NSYMTAB);
572 buf = makearraystring(a[0], __func__);
573 k = lookup(buf, (Array *) ap->sval);
583 Cell *matchop(Node **a, int n) /* ~ and match() */
589 int (*mf)(fa *, const char *) = match, mode = 0;
595 x = execute(a[1]); /* a[1] = target text */
597 if (a[0] == NULL) /* a[1] == 0: already-compiled reg expr */
598 i = (*mf)((fa *) a[2], s);
600 y = execute(a[2]); /* a[2] = regular expr */
602 pfa = makedfa(t, mode);
608 int start = patbeg - s + 1;
611 setfval(rstartloc, (Awkfloat) start);
612 setfval(rlengthloc, (Awkfloat) patlen);
617 } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
624 Cell *boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */
641 if ( !i ) return(False);
648 if (i) return(False);
650 default: /* can't happen */
651 FATAL("unknown boolean operator %d", n);
653 return 0; /*NOTREACHED*/
656 Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */
664 if (x->tval&NUM && y->tval&NUM) {
665 j = x->fval - y->fval;
666 i = j<0? -1: (j>0? 1: 0);
668 i = strcmp(getsval(x), getsval(y));
673 case LT: if (i<0) return(True);
675 case LE: if (i<=0) return(True);
677 case NE: if (i!=0) return(True);
679 case EQ: if (i == 0) return(True);
681 case GE: if (i>=0) return(True);
683 case GT: if (i>0) return(True);
685 default: /* can't happen */
686 FATAL("unknown relational operator %d", n);
688 return 0; /*NOTREACHED*/
691 void tfree(Cell *a) /* free a tempcell */
694 DPRINTF("freeing %s %s %o\n", NN(a->nval), NN(a->sval), a->tval);
698 FATAL("tempcell list is curdled");
703 Cell *gettemp(void) /* get a tempcell */
708 tmps = (Cell *) calloc(100, sizeof(*tmps));
710 FATAL("out of space for temporaries");
711 for (i = 1; i < 100; i++)
712 tmps[i-1].cnext = &tmps[i];
713 tmps[i-1].cnext = NULL;
721 Cell *indirect(Node **a, int n) /* $( a[0] ) */
729 val = getfval(x); /* freebsd: defend against super large field numbers */
730 if ((Awkfloat)INT_MAX < val)
731 FATAL("trying to access out of range field %s", x->nval);
733 if (m == 0 && !is_number(s = getsval(x), NULL)) /* suspicion! */
734 FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
735 /* BUG: can x->nval ever be null??? */
738 x->ctype = OCELL; /* BUG? why are these needed? */
743 Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */
748 Cell *x, *y, *z = NULL;
766 m = (int) getfval(y);
773 n = (int) getfval(z);
781 DPRINTF("substr: m=%d, n=%d, s=%s\n", m, n, s);
783 temp = s[n+m-1]; /* with thanks to John Linderman */
785 setsval(y, s + m - 1);
791 Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */
794 char *s1, *s2, *p1, *p2, *q;
803 for (p1 = s1; *p1 != '\0'; p1++) {
804 for (q = p1, p2 = s2; *p2 != '\0' && *q == *p2; q++, p2++)
807 v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */
817 #define MAXNUMSIZE 50
819 int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like conversions */
826 int fmtwd; /* format width */
829 int bufsize = *pbufsize;
830 #define FMTSZ(a) (fmtsz - ((a) - fmt))
831 #define BUFSZ(a) (bufsize - ((a) - buf))
833 static bool first = true;
834 static bool have_a_format = false;
839 snprintf(xbuf, sizeof(xbuf), "%a", 42.0);
840 have_a_format = (strcmp(xbuf, "0x1.5p+5") == 0);
846 if ((fmt = (char *) malloc(fmtsz)) == NULL)
847 FATAL("out of memory in format()");
849 adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format1");
859 /* have to be real careful in case this is a huge number, eg, %100000d */
863 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format2");
864 for (t = fmt; (*t++ = *s) != '\0'; s++) {
865 if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3"))
866 FATAL("format item %.30s... ran format() out of memory", os);
867 /* Ignore size specifiers */
868 if (strchr("hjLlqtz", *s) != NULL) { /* the ansi panoply */
872 if (isalpha((uschar)*s))
875 FATAL("'$' not permitted in awk formats");
879 FATAL("not enough args in printf(%s)", os);
883 snprintf(t - 1, FMTSZ(t - 1),
884 "%d", fmtwd=(int) getfval(x));
887 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
888 t = fmt + strlen(fmt);
895 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format4");
903 case 'f': case 'e': case 'g': case 'E': case 'G':
906 case 'd': case 'i': case 'o': case 'x': case 'X': case 'u':
907 flag = (*s == 'd' || *s == 'i') ? 'd' : 'u';
919 WARNING("weird printf conversion %s", fmt);
924 FATAL("not enough args in printf(%s)", os);
930 adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format5");
932 case '?': snprintf(p, BUFSZ(p), "%s", fmt); /* unknown, so dump it too */
937 adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format6");
939 snprintf(p, BUFSZ(p), "%s", t);
943 case 'f': snprintf(p, BUFSZ(p), fmt, getfval(x)); break;
944 case 'd': snprintf(p, BUFSZ(p), fmt, (intmax_t) getfval(x)); break;
945 case 'u': snprintf(p, BUFSZ(p), fmt, (uintmax_t) getfval(x)); break;
951 if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format7"))
952 FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t);
953 snprintf(p, BUFSZ(p), fmt, t);
958 snprintf(p, BUFSZ(p), fmt, (int) getfval(x));
960 *p++ = '\0'; /* explicit null byte */
961 *p = '\0'; /* next output will start here */
964 snprintf(p, BUFSZ(p), fmt, getsval(x)[0]);
967 FATAL("can't happen: bad conversion %c in format()", flag);
975 for ( ; a; a = a->nnext) /* evaluate any remaining args */
982 Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */
989 if ((buf = (char *) malloc(bufsz)) == NULL)
990 FATAL("out of memory in awksprintf");
993 if (format(&buf, &bufsz, getsval(x), y) == -1)
994 FATAL("sprintf string %.30s... too long. can't happen.", buf);
1002 Cell *awkprintf(Node **a, int n) /* printf */
1003 { /* a[0] is list of args, starting with format string */
1004 /* a[1] is redirection operator, a[2] is redirection file */
1010 int bufsz=3*recsize;
1012 if ((buf = (char *) malloc(bufsz)) == NULL)
1013 FATAL("out of memory in awkprintf");
1016 if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
1017 FATAL("printf string %.30s... too long. can't happen.", buf);
1020 /* fputs(buf, stdout); */
1021 fwrite(buf, len, 1, stdout);
1023 FATAL("write error on stdout");
1025 fp = redirect(ptoi(a[1]), a[2]);
1026 /* fputs(buf, fp); */
1027 fwrite(buf, len, 1, fp);
1030 FATAL("write error on %s", filename(fp));
1036 Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */
1045 if (n != UMINUS && n != UPLUS) {
1063 FATAL("division by zero");
1068 FATAL("division by zero in mod");
1075 case UPLUS: /* handled by getfval(), above */
1078 if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
1079 i = ipow(i, (int) j);
1082 i = errcheck(pow(i, j), "pow");
1085 default: /* can't happen */
1086 FATAL("illegal arithmetic operator %d", n);
1092 double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */
1105 Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */
1113 k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
1114 if (n == PREINCR || n == PREDECR) {
1125 Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */
1126 { /* this is subtle; don't muck with it. */
1133 if (n == ASSIGN) { /* ordinary assignment */
1134 if (x == y && !(x->tval & (FLD|REC)) && x != nfloc)
1135 ; /* self-assignment: leave alone unless it's a field or NF */
1136 else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
1137 setsval(x, getsval(y));
1138 x->fval = getfval(y);
1142 setsval(x, getsval(y));
1144 setfval(x, getfval(y));
1146 funnyvar(y, "read value of");
1164 FATAL("division by zero in /=");
1169 FATAL("division by zero in %%=");
1174 if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */
1175 xf = ipow(xf, (int) yf);
1178 xf = errcheck(pow(xf, yf), "pow");
1182 FATAL("illegal assignment operator %d", n);
1190 Cell *cat(Node **a, int q) /* a[0] cat a[1] */
1198 n1 = strlen(getsval(x));
1199 adjbuf(&s, &ssz, n1, recsize, 0, "cat1");
1200 memcpy(s, x->sval, n1);
1203 n2 = strlen(getsval(y));
1204 adjbuf(&s, &ssz, n1 + n2 + 1, recsize, 0, "cat2");
1205 memcpy(s + n1, y->sval, n2);
1218 Cell *pastat(Node **a, int n) /* a[0] { a[1] } */
1234 Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */
1240 if (pairstack[pair] == 0) {
1243 pairstack[pair] = 1;
1246 if (pairstack[pair] == 1) {
1249 pairstack[pair] = 0;
1257 Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
1259 Cell *x = NULL, *y, *ap;
1260 const char *s, *origs, *t;
1261 const char *fs = NULL;
1262 char *origfs = NULL;
1265 int n, tempstat, arg3type;
1268 y = execute(a[0]); /* source string */
1269 origs = s = strdup(getsval(y));
1270 arg3type = ptoi(a[3]);
1271 if (a[2] == NULL) /* fs string */
1272 fs = getsval(fsloc);
1273 else if (arg3type == STRING) { /* split(str,arr,"string") */
1275 fs = origfs = strdup(getsval(x));
1277 } else if (arg3type == REGEXPR)
1278 fs = "(regexpr)"; /* split(str,arr,/regexpr/) */
1280 FATAL("illegal type of split");
1282 ap = execute(a[1]); /* array name */
1284 DPRINTF("split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs);
1287 ap->sval = (char *) makesymtab(NSYMTAB);
1290 if (arg3type == REGEXPR && strlen((char*)((fa*)a[2])->restr) == 0) {
1291 /* split(s, a, //); have to arrange that it looks like empty sep */
1296 if (*s != '\0' && (strlen(fs) > 1 || arg3type == REGEXPR)) { /* reg expr */
1298 if (arg3type == REGEXPR) { /* it's ready already */
1301 pfa = makedfa(fs, 1);
1303 if (nematch(pfa,s)) {
1304 tempstat = pfa->initstat;
1308 snprintf(num, sizeof(num), "%d", n);
1310 setptr(patbeg, '\0');
1311 if (is_number(s, & result))
1312 setsymtab(num, s, result, STR|NUM, (Array *) ap->sval);
1314 setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1315 setptr(patbeg, temp);
1316 s = patbeg + patlen;
1317 if (*(patbeg+patlen-1) == '\0' || *s == '\0') {
1319 snprintf(num, sizeof(num), "%d", n);
1320 setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
1321 pfa->initstat = tempstat;
1324 } while (nematch(pfa,s));
1325 pfa->initstat = tempstat; /* bwk: has to be here to reset */
1326 /* cf gsub and refldbld */
1329 snprintf(num, sizeof(num), "%d", n);
1330 if (is_number(s, & result))
1331 setsymtab(num, s, result, STR|NUM, (Array *) ap->sval);
1333 setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1336 } else if (sep == ' ') {
1338 #define ISWS(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
1347 while (*s != '\0' && !ISWS(*s));
1350 snprintf(num, sizeof(num), "%d", n);
1351 if (is_number(t, & result))
1352 setsymtab(num, t, result, STR|NUM, (Array *) ap->sval);
1354 setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1359 } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */
1360 for (n = 0; *s != '\0'; s++) {
1363 snprintf(num, sizeof(num), "%d", n);
1366 if (isdigit((uschar)buf[0]))
1367 setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval);
1369 setsymtab(num, buf, 0.0, STR, (Array *) ap->sval);
1371 } else if (*s != '\0') {
1375 while (*s != sep && *s != '\n' && *s != '\0')
1379 snprintf(num, sizeof(num), "%d", n);
1380 if (is_number(t, & result))
1381 setsymtab(num, t, result, STR|NUM, (Array *) ap->sval);
1383 setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1399 Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */
1414 Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */
1422 } else if (a[2] != NULL) {
1429 Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */
1443 if (isnext(x) || isexit(x) || isret(x))
1449 Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */
1457 if (isnext(x) || isexit(x) || isret(x))
1467 Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */
1476 if (!istrue(x)) return(x);
1480 if (isbreak(x)) /* turn off break */
1482 if (isnext(x) || isexit(x) || isret(x))
1490 Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */
1492 Cell *x, *vp, *arrayp, *cp, *ncp;
1497 arrayp = execute(a[1]);
1498 if (!isarr(arrayp)) {
1501 tp = (Array *) arrayp->sval;
1503 for (i = 0; i < tp->size; i++) { /* this routine knows too much */
1504 for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1505 setsval(vp, cp->nval);
1512 if (isnext(x) || isexit(x) || isret(x)) {
1522 static char *nawk_convert(const char *s, int (*fun_c)(int),
1523 wint_t (*fun_wc)(wint_t))
1527 const char *ps = NULL;
1530 size_t sz = MB_CUR_MAX;
1535 for (pbuf = buf; *pbuf; pbuf++)
1536 *pbuf = fun_c((uschar)*pbuf);
1540 /* upper/lower character may be shorter/longer */
1541 buf = tostringN(s, strlen(s) * sz + 1);
1543 (void) mbtowc(NULL, NULL, 0); /* reset internal state */
1545 * Reset internal state here too.
1546 * Assign result to avoid a compiler warning. (Casting to void
1548 * Increment said variable to avoid a different warning.
1550 int unused = wctomb(NULL, L'\0');
1555 while (n = mbtowc(&wc, ps, sz),
1556 n > 0 && n != (size_t)-1 && n != (size_t)-2)
1560 n = wctomb(pbuf, fun_wc(wc));
1561 if (n == (size_t)-1)
1562 FATAL("illegal wide character %s", s);
1570 FATAL("illegal byte sequence %s", s);
1577 static wint_t towupper(wint_t wc)
1579 if (wc >= 0 && wc < 256)
1580 return toupper(wc & 0xFF);
1585 static wint_t towlower(wint_t wc)
1587 if (wc >= 0 && wc < 256)
1588 return tolower(wc & 0xFF);
1594 static char *nawk_toupper(const char *s)
1596 return nawk_convert(s, toupper, towupper);
1599 static char *nawk_tolower(const char *s)
1601 return nawk_convert(s, tolower, towlower);
1604 Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */
1619 nextarg = a[1]->nnext;
1623 u = ((Array *) x->sval)->nelem; /* GROT. should be function*/
1625 u = strlen(getsval(x));
1629 u = errcheck(log(getfval(x)), "log");
1632 modf(getfval(x), &u); break;
1635 u = errcheck(exp(getfval(x)), "exp");
1639 u = errcheck(sqrt(getfval(x)), "sqrt");
1642 u = sin(getfval(x)); break;
1644 u = cos(getfval(x)); break;
1646 if (nextarg == NULL) {
1647 WARNING("atan2 requires two arguments; returning 1.0");
1650 y = execute(a[1]->nnext);
1651 u = atan2(getfval(x), getfval(y));
1653 nextarg = nextarg->nnext;
1657 u = ~((int)getfval(x));
1661 WARNING("and requires two arguments; returning 0");
1665 y = execute(a[1]->nnext);
1666 u = ((int)getfval(x)) & ((int)getfval(y));
1668 nextarg = nextarg->nnext;
1672 WARNING("or requires two arguments; returning 0");
1676 y = execute(a[1]->nnext);
1677 u = ((int)getfval(x)) | ((int)getfval(y));
1679 nextarg = nextarg->nnext;
1683 WARNING("xor requires two arguments; returning 0");
1687 y = execute(a[1]->nnext);
1688 u = ((int)getfval(x)) ^ ((int)getfval(y));
1690 nextarg = nextarg->nnext;
1694 WARNING("lshift requires two arguments; returning 0");
1698 y = execute(a[1]->nnext);
1699 u = ((int)getfval(x)) << ((int)getfval(y));
1701 nextarg = nextarg->nnext;
1705 WARNING("rshift requires two arguments; returning 0");
1709 y = execute(a[1]->nnext);
1710 u = ((int)getfval(x)) >> ((int)getfval(y));
1712 nextarg = nextarg->nnext;
1715 fflush(stdout); /* in case something is buffered already */
1716 status = system(getsval(x));
1719 if (WIFEXITED(status)) {
1720 u = WEXITSTATUS(status);
1721 } else if (WIFSIGNALED(status)) {
1722 u = WTERMSIG(status) + 256;
1724 if (WCOREDUMP(status))
1727 } else /* something else?!? */
1732 /* random() returns numbers in [0..2^31-1]
1733 * in order to get a number in [0, 1), divide it by 2^31
1735 u = (Awkfloat) random() / (0x7fffffffL + 0x1UL);
1738 if (isrec(x)) /* no argument provided */
1739 u = time((time_t *)0);
1743 srandom((unsigned long) u);
1750 buf = nawk_toupper(getsval(x));
1752 buf = nawk_tolower(getsval(x));
1759 if (isrec(x) || strlen(getsval(x)) == 0) {
1760 flush_all(); /* fflush() or fflush("") -> all */
1762 } else if ((fp = openfile(FFLUSH, getsval(x), NULL)) == NULL)
1768 u = time((time_t *) 0);
1771 /* strftime([format [,timestamp]]) */
1773 y = execute(nextarg);
1774 nextarg = nextarg->nnext;
1775 tv = (time_t) getfval(y);
1778 tv = time((time_t *) 0);
1779 tm = localtime(&tv);
1781 FATAL("bad time %ld", (long)tv);
1784 /* format argument not provided, use default */
1785 fmt = tostring("%a %b %d %H:%M:%S %Z %Y");
1787 fmt = tostring(getsval(x));
1792 if ((buf = realloc(buf, (sz *= 2))) == NULL)
1793 FATAL("out of memory in strftime");
1794 } while (strftime(buf, sz, fmt, tm) == 0 && fmt[0] != '\0');
1802 default: /* can't happen */
1803 FATAL("illegal function type %d", t);
1809 if (nextarg != NULL) {
1810 WARNING("warning: function has too many arguments");
1811 for ( ; nextarg; nextarg = nextarg->nnext)
1817 Cell *printstat(Node **a, int n) /* print a[0] */
1823 if (a[1] == NULL) /* a[1] is redirection operator, a[2] is file */
1826 fp = redirect(ptoi(a[1]), a[2]);
1827 for (x = a[0]; x != NULL; x = x->nnext) {
1829 fputs(getpssval(y), fp);
1831 if (x->nnext == NULL)
1832 fputs(getsval(orsloc), fp);
1834 fputs(getsval(ofsloc), fp);
1839 FATAL("write error on %s", filename(fp));
1843 Cell *nullproc(Node **a, int n)
1849 FILE *redirect(int a, Node *b) /* set up all i/o redirections */
1857 fp = openfile(a, fname, NULL);
1859 FATAL("can't open file %s", fname);
1867 int mode; /* '|', 'a', 'w' => LE/LT, GT */
1872 static void stdinit(void) /* in case stdin, etc., are not constants */
1875 files = (struct files *) calloc(nfiles, sizeof(*files));
1877 FATAL("can't allocate file memory for %zu files", nfiles);
1878 files[0].fp = stdin;
1879 files[0].fname = "/dev/stdin";
1881 files[1].fp = stdout;
1882 files[1].fname = "/dev/stdout";
1884 files[2].fp = stderr;
1885 files[2].fname = "/dev/stderr";
1889 FILE *openfile(int a, const char *us, bool *pnewflag)
1897 FATAL("null file name in print or getline");
1898 for (i = 0; i < nfiles; i++)
1899 if (files[i].fname && strcmp(s, files[i].fname) == 0 &&
1900 (a == files[i].mode || (a==APPEND && files[i].mode==GT) ||
1906 if (a == FFLUSH) /* didn't find it, so don't create it! */
1909 for (i = 0; i < nfiles; i++)
1910 if (files[i].fp == NULL)
1914 size_t nnf = nfiles + FOPEN_MAX;
1915 nf = (struct files *) realloc(files, nnf * sizeof(*nf));
1917 FATAL("cannot grow files for %s and %zu files", s, nnf);
1918 memset(&nf[nfiles], 0, FOPEN_MAX * sizeof(*nf));
1922 fflush(stdout); /* force a semblance of order */
1926 } else if (a == APPEND) {
1928 m = GT; /* so can mix > and >> */
1929 } else if (a == '|') { /* output pipe */
1931 } else if (a == LE) { /* input pipe */
1933 } else if (a == LT) { /* getline <file */
1934 fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */
1935 } else /* can't happen */
1936 FATAL("illegal redirection %d", a);
1938 files[i].fname = tostring(s);
1943 if (fp != stdin && fp != stdout && fp != stderr)
1944 (void) fcntl(fileno(fp), F_SETFD, FD_CLOEXEC);
1949 const char *filename(FILE *fp)
1953 for (i = 0; i < nfiles; i++)
1954 if (fp == files[i].fp)
1955 return files[i].fname;
1959 Cell *closefile(Node **a, int n)
1968 for (i = 0; i < nfiles; i++) {
1969 if (!files[i].fname || strcmp(x->sval, files[i].fname) != 0)
1971 if (ferror(files[i].fp))
1972 FATAL("i/o error occurred on %s", files[i].fname);
1973 if (files[i].fp == stdin || files[i].fp == stdout ||
1974 files[i].fp == stderr)
1975 stat = freopen("/dev/null", "r+", files[i].fp) == NULL;
1976 else if (files[i].mode == '|' || files[i].mode == LE)
1977 stat = pclose(files[i].fp) == -1;
1979 stat = fclose(files[i].fp) == EOF;
1981 FATAL("i/o error occurred closing %s", files[i].fname);
1982 if (i > 2) /* don't do /dev/std... */
1983 xfree(files[i].fname);
1984 files[i].fname = NULL; /* watch out for ref thru this */
1990 setfval(x, (Awkfloat) (stat ? -1 : 0));
1999 for (i = 0; i < nfiles; i++) {
2002 if (ferror(files[i].fp))
2003 FATAL( "i/o error occurred on %s", files[i].fname );
2004 if (files[i].fp == stdin)
2006 if (files[i].mode == '|' || files[i].mode == LE)
2007 stat = pclose(files[i].fp) == -1;
2008 else if (files[i].fp == stdout || files[i].fp == stderr)
2009 stat = fflush(files[i].fp) == EOF;
2011 stat = fclose(files[i].fp) == EOF;
2013 FATAL( "i/o error occurred while closing %s", files[i].fname );
2017 static void flush_all(void)
2021 for (i = 0; i < nfiles; i++)
2023 fflush(files[i].fp);
2026 void backsub(char **pb_ptr, const char **sptr_ptr);
2028 Cell *sub(Node **a, int nnn) /* substitute command */
2030 const char *sptr, *q;
2031 Cell *x, *y, *result;
2034 int bufsz = recsize;
2036 if ((buf = (char *) malloc(bufsz)) == NULL)
2037 FATAL("out of memory in sub");
2038 x = execute(a[3]); /* target string */
2040 if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */
2041 pfa = (fa *) a[1]; /* regular expression */
2044 pfa = makedfa(getsval(y), 1);
2047 y = execute(a[2]); /* replacement string */
2049 if (pmatch(pfa, t)) {
2051 adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub");
2053 while (sptr < patbeg)
2056 while (*sptr != '\0') {
2057 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub");
2058 if (*sptr == '\\') {
2059 backsub(&pb, &sptr);
2060 } else if (*sptr == '&') {
2062 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub");
2063 for (q = patbeg; q < patbeg+patlen; )
2069 if (pb > buf + bufsz)
2070 FATAL("sub result1 %.30s too big; can't happen", buf);
2071 sptr = patbeg + patlen;
2072 if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
2073 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
2074 while ((*pb++ = *sptr++) != '\0')
2077 if (pb > buf + bufsz)
2078 FATAL("sub result2 %.30s too big; can't happen", buf);
2079 setsval(x, buf); /* BUG: should be able to avoid copy */
2088 Cell *gsub(Node **a, int nnn) /* global substitute */
2092 const char *q, *t, *sptr;
2095 int mflag, tempstat, num;
2096 int bufsz = recsize;
2098 if ((buf = (char *) malloc(bufsz)) == NULL)
2099 FATAL("out of memory in gsub");
2100 mflag = 0; /* if mflag == 0, can replace empty string */
2102 x = execute(a[3]); /* target string */
2104 if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */
2105 pfa = (fa *) a[1]; /* regular expression */
2108 pfa = makedfa(getsval(y), 1);
2111 y = execute(a[2]); /* replacement string */
2112 if (pmatch(pfa, t)) {
2113 tempstat = pfa->initstat;
2118 if (patlen == 0 && *patbeg != '\0') { /* matched empty string */
2119 if (mflag == 0) { /* can replace empty */
2122 while (*sptr != '\0') {
2123 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
2124 if (*sptr == '\\') {
2125 backsub(&pb, &sptr);
2126 } else if (*sptr == '&') {
2128 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
2129 for (q = patbeg; q < patbeg+patlen; )
2135 if (*t == '\0') /* at end */
2137 adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
2139 if (pb > buf + bufsz) /* BUG: not sure of this test */
2140 FATAL("gsub result0 %.30s too big; can't happen", buf);
2143 else { /* matched nonempty string */
2146 adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub");
2147 while (sptr < patbeg)
2150 while (*sptr != '\0') {
2151 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
2152 if (*sptr == '\\') {
2153 backsub(&pb, &sptr);
2154 } else if (*sptr == '&') {
2156 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
2157 for (q = patbeg; q < patbeg+patlen; )
2162 t = patbeg + patlen;
2163 if (patlen == 0 || *t == '\0' || *(t-1) == '\0')
2165 if (pb > buf + bufsz)
2166 FATAL("gsub result1 %.30s too big; can't happen", buf);
2169 } while (pmatch(pfa,t));
2171 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
2172 while ((*pb++ = *sptr++) != '\0')
2174 done: if (pb < buf + bufsz)
2176 else if (*(pb-1) != '\0')
2177 FATAL("gsub result2 %.30s truncated; can't happen", buf);
2178 setsval(x, buf); /* BUG: should be able to avoid copy + free */
2179 pfa->initstat = tempstat;
2190 Cell *gensub(Node **a, int nnn) /* global selective substitute */
2191 /* XXX incomplete - doesn't support backreferences \0 ... \9 */
2193 Cell *x, *y, *res, *h;
2199 int mflag, tempstat, num, whichm;
2200 int bufsz = recsize;
2202 if ((buf = malloc(bufsz)) == NULL)
2203 FATAL("out of memory in gensub");
2204 mflag = 0; /* if mflag == 0, can replace empty string */
2206 x = execute(a[4]); /* source string */
2208 res = copycell(x); /* target string - initially copy of source */
2209 res->csub = CTEMP; /* result values are temporary */
2210 if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */
2211 pfa = (fa *) a[1]; /* regular expression */
2214 pfa = makedfa(getsval(y), 1);
2217 y = execute(a[2]); /* replacement string */
2218 h = execute(a[3]); /* which matches should be replaced */
2220 if (sptr[0] == 'g' || sptr[0] == 'G')
2224 * The specified number is index of replacement, starting
2225 * from 1. GNU awk treats index lower than 0 same as
2226 * 1, we do same for compatibility.
2228 whichm = (int) getfval(h) - 1;
2234 if (pmatch(pfa, t)) {
2237 tempstat = pfa->initstat;
2242 * XXX if there are any backreferences in subst string,
2245 for (sl = rptr; (sl = strchr(sl, '\\')) && sl[1]; sl++) {
2246 if (strchr("0123456789", sl[1])) {
2247 FATAL("gensub doesn't support backreferences (subst \"%s\")", rptr);
2252 if (whichm >= 0 && whichm != num) {
2254 adjbuf(&buf, &bufsz, (pb - buf) + (patbeg - t) + patlen, recsize, &pb, "gensub");
2256 /* copy the part of string up to and including
2257 * match to output buffer */
2258 while (t < patbeg + patlen)
2263 if (patlen == 0 && *patbeg != 0) { /* matched empty string */
2264 if (mflag == 0) { /* can replace empty */
2267 while (*sptr != 0) {
2268 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gensub");
2269 if (*sptr == '\\') {
2270 backsub(&pb, &sptr);
2271 } else if (*sptr == '&') {
2273 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gensub");
2274 for (q = patbeg; q < patbeg+patlen; )
2280 if (*t == 0) /* at end */
2282 adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gensub");
2284 if (pb > buf + bufsz) /* BUG: not sure of this test */
2285 FATAL("gensub result0 %.30s too big; can't happen", buf);
2288 else { /* matched nonempty string */
2291 adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gensub");
2292 while (sptr < patbeg)
2295 while (*sptr != 0) {
2296 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gensub");
2297 if (*sptr == '\\') {
2298 backsub(&pb, &sptr);
2299 } else if (*sptr == '&') {
2301 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gensub");
2302 for (q = patbeg; q < patbeg+patlen; )
2307 t = patbeg + patlen;
2308 if (patlen == 0 || *t == 0 || *(t-1) == 0)
2310 if (pb > buf + bufsz)
2311 FATAL("gensub result1 %.30s too big; can't happen", buf);
2314 } while (pmatch(pfa,t));
2316 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gensub");
2317 while ((*pb++ = *sptr++) != 0)
2319 done: if (pb > buf + bufsz)
2320 FATAL("gensub result2 %.30s too big; can't happen", buf);
2323 pfa->initstat = tempstat;
2331 void backsub(char **pb_ptr, const char **sptr_ptr) /* handle \\& variations */
2332 { /* sptr[0] == '\\' */
2334 const char *sptr = *sptr_ptr;
2335 static bool first = true;
2336 static bool do_posix = false;
2340 do_posix = (getenv("POSIXLY_CORRECT") != NULL);
2343 if (sptr[1] == '\\') {
2344 if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
2348 } else if (sptr[2] == '&') { /* \\& -> \ + matched */
2351 } else if (do_posix) { /* \\x -> \x */
2354 } else { /* \\x -> \\x */
2358 } else if (sptr[1] == '&') { /* literal & */
2361 } else /* literal \ */