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 ****************************************************************/
38 #include <sys/types.h>
41 #include "awkgram.tab.h"
43 static void stdinit(void);
44 static void flush_all(void);
47 #define tempfree(x) do { if (istemp(x)) tfree(x); } while (/*CONSTCOND*/0)
49 void tempfree(Cell
*p
) {
50 if (p
->ctype
== OCELL
&& (p
->csub
< CUNK
|| p
->csub
> CFREE
)) {
51 WARNING("bad csub %d in Cell %d %s",
52 p
->csub
, p
->ctype
, p
->sval
);
59 /* do we really need these? */
61 /* #ifndef FOPEN_MAX */
62 /* #define FOPEN_MAX _NFILE */
66 /* #ifndef FOPEN_MAX */
67 /* #define FOPEN_MAX 40 */ /* max number of open files */
70 /* #ifndef RAND_MAX */
71 /* #define RAND_MAX 32767 */ /* all that ansi guarantees */
75 extern int pairstack
[];
76 extern Awkfloat srand_seed
;
78 Node
*winner
= NULL
; /* root of parse tree */
79 Cell
*tmps
; /* free temporary cells for execution */
81 static Cell truecell
={ OBOOL
, BTRUE
, 0, 0, 1.0, NUM
, NULL
, NULL
};
82 Cell
*True
= &truecell
;
83 static Cell falsecell
={ OBOOL
, BFALSE
, 0, 0, 0.0, NUM
, NULL
, NULL
};
84 Cell
*False
= &falsecell
;
85 static Cell breakcell
={ OJUMP
, JBREAK
, 0, 0, 0.0, NUM
, NULL
, NULL
};
86 Cell
*jbreak
= &breakcell
;
87 static Cell contcell
={ OJUMP
, JCONT
, 0, 0, 0.0, NUM
, NULL
, NULL
};
88 Cell
*jcont
= &contcell
;
89 static Cell nextcell
={ OJUMP
, JNEXT
, 0, 0, 0.0, NUM
, NULL
, NULL
};
90 Cell
*jnext
= &nextcell
;
91 static Cell nextfilecell
={ OJUMP
, JNEXTFILE
, 0, 0, 0.0, NUM
, NULL
, NULL
};
92 Cell
*jnextfile
= &nextfilecell
;
93 static Cell exitcell
={ OJUMP
, JEXIT
, 0, 0, 0.0, NUM
, NULL
, NULL
};
94 Cell
*jexit
= &exitcell
;
95 static Cell retcell
={ OJUMP
, JRET
, 0, 0, 0.0, NUM
, NULL
, NULL
};
96 Cell
*jret
= &retcell
;
97 static Cell tempcell
={ OCELL
, CTEMP
, 0, EMPTY
, 0.0, NUM
|STR
|DONTFREE
, NULL
, NULL
};
99 Node
*curnode
= NULL
; /* the node being executed, for debugging */
101 /* buffer memory management */
102 int adjbuf(char **pbuf
, int *psiz
, int minlen
, int quantum
, char **pbptr
,
104 /* pbuf: address of pointer to buffer being managed
105 * psiz: address of buffer size variable
106 * minlen: minimum length of buffer needed
107 * quantum: buffer size quantum
108 * pbptr: address of movable pointer into buffer, or 0 if none
109 * whatrtn: name of the calling routine if failure should cause fatal error
111 * return 0 for realloc failure, !=0 for success
114 if (minlen
> *psiz
) {
116 int rminlen
= quantum
? minlen
% quantum
: 0;
117 int boff
= pbptr
? *pbptr
- *pbuf
: 0;
118 /* round up to next multiple of quantum */
120 minlen
+= quantum
- rminlen
;
121 tbuf
= (char *) realloc(*pbuf
, minlen
);
122 DPRINTF("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn
, *psiz
, minlen
, (void*)*pbuf
, (void*)tbuf
);
125 FATAL("out of memory in %s", whatrtn
);
131 *pbptr
= tbuf
+ boff
;
136 void run(Node
*a
) /* execution of parse tree starts here */
144 Cell
*execute(Node
*u
) /* execute a node of the parse tree */
146 Cell
*(*proc
)(Node
**, int);
152 for (a
= u
; ; a
= a
->nnext
) {
155 x
= (Cell
*) (a
->narg
[0]);
156 if (isfld(x
) && !donefld
)
158 else if (isrec(x
) && !donerec
)
162 if (notlegal(a
->nobj
)) /* probably a Cell* but too risky to print */
163 FATAL("illegal statement");
164 proc
= proctab
[a
->nobj
-FIRSTTOKEN
];
165 x
= (*proc
)(a
->narg
, a
->nobj
);
166 if (isfld(x
) && !donefld
)
168 else if (isrec(x
) && !donerec
)
174 if (a
->nnext
== NULL
)
181 Cell
*program(Node
**a
, int n
) /* execute an awk program */
182 { /* a[0] = BEGIN, a[1] = body, a[2] = END */
185 if (setjmp(env
) != 0)
187 if (a
[0]) { /* BEGIN */
192 FATAL("illegal break, continue, next or nextfile from BEGIN");
196 while (getrec(&record
, &recsize
, true) > 0) {
203 if (setjmp(env
) != 0) /* handles exit within END */
205 if (a
[2]) { /* END */
207 if (isbreak(x
) || isnext(x
) || iscont(x
))
208 FATAL("illegal break, continue, next or nextfile from END");
215 struct Frame
{ /* stack frame for awk function calls */
216 int nargs
; /* number of arguments in this call */
217 Cell
*fcncell
; /* pointer to Cell for function */
218 Cell
**args
; /* pointer to array of arguments after execute */
219 Cell
*retval
; /* return value */
222 #define NARGS 50 /* max args in a call */
224 struct Frame
*frame
= NULL
; /* base of stack frames; dynamically allocated */
225 int nframe
= 0; /* number of frames allocated */
226 struct Frame
*frp
= NULL
; /* frame pointer. bottom level unused */
228 Cell
*call(Node
**a
, int n
) /* function call. very kludgy and fragile */
230 static const Cell newcopycell
= { OCELL
, CCOPY
, 0, EMPTY
, 0.0, NUM
|STR
|DONTFREE
, NULL
, NULL
};
232 int freed
= 0; /* handles potential double freeing when fcn & param share a tempcell */
234 Cell
*args
[NARGS
], *oargs
[NARGS
]; /* BUG: fixed size arrays */
238 fcn
= execute(a
[0]); /* the function itself */
241 FATAL("calling undefined function %s", s
);
243 frp
= frame
= (struct Frame
*) calloc(nframe
+= 100, sizeof(*frame
));
245 FATAL("out of space for stack frames calling %s", s
);
247 for (ncall
= 0, x
= a
[1]; x
!= NULL
; x
= x
->nnext
) /* args in call */
249 ndef
= (int) fcn
->fval
; /* args in defn */
250 DPRINTF("calling %s, %d args (%d in defn), frp=%d\n", s
, ncall
, ndef
, (int) (frp
-frame
));
252 WARNING("function %s called with %d args, uses only %d",
254 if (ncall
+ ndef
> NARGS
)
255 FATAL("function %s has %d arguments, limit %d", s
, ncall
+ndef
, NARGS
);
256 for (i
= 0, x
= a
[1]; x
!= NULL
; i
++, x
= x
->nnext
) { /* get call args */
257 DPRINTF("evaluate args[%d], frp=%d:\n", i
, (int) (frp
-frame
));
260 DPRINTF("args[%d]: %s %f <%s>, t=%o\n",
261 i
, NN(y
->nval
), y
->fval
, isarr(y
) ? "(array)" : NN(y
->sval
), y
->tval
);
263 FATAL("can't use function %s as argument in %s", y
->nval
, s
);
265 args
[i
] = y
; /* arrays by ref */
267 args
[i
] = copycell(y
);
270 for ( ; i
< ndef
; i
++) { /* add null args for ones not provided */
272 *args
[i
] = newcopycell
;
274 frp
++; /* now ok to up frame */
275 if (frp
>= frame
+ nframe
) {
276 int dfp
= frp
- frame
; /* old index */
277 frame
= (struct Frame
*) realloc(frame
, (nframe
+= 100) * sizeof(*frame
));
279 FATAL("out of space for stack frames in %s", s
);
284 frp
->nargs
= ndef
; /* number defined with (excess are locals) */
285 frp
->retval
= gettemp();
287 DPRINTF("start exec of %s, frp=%d\n", s
, (int) (frp
-frame
));
288 y
= execute((Node
*)(fcn
->sval
)); /* execute body */
289 DPRINTF("finished exec of %s, frp=%d\n", s
, (int) (frp
-frame
));
291 for (i
= 0; i
< ndef
; i
++) {
292 Cell
*t
= frp
->args
[i
];
294 if (t
->csub
== CCOPY
) {
300 oargs
[i
]->tval
= t
->tval
;
301 oargs
[i
]->tval
&= ~(STR
|NUM
|DONTFREE
);
302 oargs
[i
]->sval
= t
->sval
;
306 } else if (t
!= y
) { /* kludge to prevent freeing twice */
309 } else if (t
== y
&& t
->csub
== CCOPY
) {
316 if (isexit(y
) || isnext(y
))
319 tempfree(y
); /* don't free twice! */
321 z
= frp
->retval
; /* return value */
322 DPRINTF("%s returns %g |%s| %o\n", s
, getfval(z
), getsval(z
), z
->tval
);
327 Cell
*copycell(Cell
*x
) /* make a copy of a cell in a temp */
331 /* copy is not constant or field */
334 y
->tval
= x
->tval
& ~(CON
|FLD
|REC
);
335 y
->csub
= CCOPY
; /* prevents freeing until call is over */
336 y
->nval
= x
->nval
; /* BUG? */
337 if (isstr(x
) /* || x->ctype == OCELL */) {
338 y
->sval
= tostring(x
->sval
);
339 y
->tval
&= ~DONTFREE
;
346 Cell
*arg(Node
**a
, int n
) /* nth argument of a function */
349 n
= ptoi(a
[0]); /* argument number, counting from 0 */
350 DPRINTF("arg(%d), frp->nargs=%d\n", n
, frp
->nargs
);
351 if (n
+1 > frp
->nargs
)
352 FATAL("argument #%d of function %s was not supplied",
353 n
+1, frp
->fcncell
->nval
);
357 Cell
*jump(Node
**a
, int n
) /* break, continue, next, nextfile, return */
365 errorflag
= (int) getfval(y
);
372 if ((y
->tval
& (STR
|NUM
)) == (STR
|NUM
)) {
373 setsval(frp
->retval
, getsval(y
));
374 frp
->retval
->fval
= getfval(y
);
375 frp
->retval
->tval
|= NUM
;
377 else if (y
->tval
& STR
)
378 setsval(frp
->retval
, getsval(y
));
379 else if (y
->tval
& NUM
)
380 setfval(frp
->retval
, getfval(y
));
381 else /* can't happen */
382 FATAL("bad type variable %d", y
->tval
);
395 default: /* can't happen */
396 FATAL("illegal jump type %d", n
);
398 return 0; /* not reached */
401 Cell
*awkgetline(Node
**a
, int n
) /* get next line from specific input */
402 { /* a[0] is variable, a[1] is operator, a[2] is filename */
404 extern Cell
**fldtab
;
407 int bufsize
= recsize
;
412 if ((buf
= (char *) malloc(bufsize
)) == NULL
)
413 FATAL("out of memory in getline");
415 fflush(stdout
); /* in case someone is waiting for a prompt */
417 if (a
[1] != NULL
) { /* getline < file */
418 x
= execute(a
[2]); /* filename */
420 if (mode
== '|') /* input pipe */
421 mode
= LE
; /* arbitrary flag */
422 fp
= openfile(mode
, getsval(x
), &newflag
);
427 n
= readrec(&buf
, &bufsize
, fp
, newflag
);
430 } else if (a
[0] != NULL
) { /* getline var <file */
433 if (is_number(x
->sval
, & result
)) {
438 } else { /* getline <file */
439 setsval(fldtab
[0], buf
);
440 if (is_number(fldtab
[0]->sval
, & result
)) {
441 fldtab
[0]->fval
= result
;
442 fldtab
[0]->tval
|= NUM
;
445 } else { /* bare getline; use current input */
446 if (a
[0] == NULL
) /* getline */
447 n
= getrec(&record
, &recsize
, true);
448 else { /* getline var */
449 n
= getrec(&buf
, &bufsize
, false);
453 if (is_number(x
->sval
, & result
)) {
461 setfval(r
, (Awkfloat
) n
);
466 Cell
*getnf(Node
**a
, int n
) /* get NF */
470 return (Cell
*) a
[0];
474 makearraystring(Node
*p
, const char *func
)
480 if ((buf
= (char *) malloc(bufsz
)) == NULL
) {
481 FATAL("%s: out of memory", func
);
487 for (; p
; p
= p
->nnext
) {
488 Cell
*x
= execute(p
); /* expr */
489 char *s
= getsval(x
);
490 size_t seplen
= strlen(getsval(subseploc
));
491 size_t nsub
= p
->nnext
? seplen
: 0;
492 size_t slen
= strlen(s
);
493 size_t tlen
= blen
+ slen
+ nsub
;
495 if (!adjbuf(&buf
, &bufsz
, tlen
+ 1, recsize
, 0, func
)) {
496 FATAL("%s: out of memory %s[%s...]",
499 memcpy(buf
+ blen
, s
, slen
);
501 memcpy(buf
+ blen
+ slen
, *SUBSEP
, nsub
);
510 Cell
*array(Node
**a
, int n
) /* a[0] is symtab, a[1] is list of subscripts */
515 x
= execute(a
[0]); /* Cell* for symbol table */
516 buf
= makearraystring(a
[1], __func__
);
518 DPRINTF("making %s into an array\n", NN(x
->nval
));
521 x
->tval
&= ~(STR
|NUM
|DONTFREE
);
523 x
->sval
= (char *) makesymtab(NSYMTAB
);
525 z
= setsymtab(buf
, "", 0.0, STR
|NUM
, (Array
*) x
->sval
);
533 Cell
*awkdelete(Node
**a
, int n
) /* a[0] is symtab, a[1] is list of subscripts */
537 x
= execute(a
[0]); /* Cell* for symbol table */
538 if (x
== symtabloc
) {
539 FATAL("cannot delete SYMTAB or its elements");
543 if (a
[1] == NULL
) { /* delete the elements, not the table */
547 x
->sval
= (char *) makesymtab(NSYMTAB
);
549 char *buf
= makearraystring(a
[1], __func__
);
557 Cell
*intest(Node
**a
, int n
) /* a[0] is index (list), a[1] is symtab */
562 ap
= execute(a
[1]); /* array name */
564 DPRINTF("making %s into an array\n", ap
->nval
);
567 ap
->tval
&= ~(STR
|NUM
|DONTFREE
);
569 ap
->sval
= (char *) makesymtab(NSYMTAB
);
571 buf
= makearraystring(a
[0], __func__
);
572 k
= lookup(buf
, (Array
*) ap
->sval
);
582 Cell
*matchop(Node
**a
, int n
) /* ~ and match() */
588 int (*mf
)(fa
*, const char *) = match
, mode
= 0;
594 x
= execute(a
[1]); /* a[1] = target text */
596 if (a
[0] == NULL
) /* a[1] == 0: already-compiled reg expr */
597 i
= (*mf
)((fa
*) a
[2], s
);
599 y
= execute(a
[2]); /* a[2] = regular expr */
601 pfa
= makedfa(t
, mode
);
607 int start
= patbeg
- s
+ 1;
610 setfval(rstartloc
, (Awkfloat
) start
);
611 setfval(rlengthloc
, (Awkfloat
) patlen
);
616 } else if ((n
== MATCH
&& i
== 1) || (n
== NOTMATCH
&& i
== 0))
623 Cell
*boolop(Node
**a
, int n
) /* a[0] || a[1], a[0] && a[1], !a[0] */
640 if ( !i
) return(False
);
647 if (i
) return(False
);
649 default: /* can't happen */
650 FATAL("unknown boolean operator %d", n
);
652 return 0; /*NOTREACHED*/
655 Cell
*relop(Node
**a
, int n
) /* a[0 < a[1], etc. */
663 if (x
->tval
&NUM
&& y
->tval
&NUM
) {
664 j
= x
->fval
- y
->fval
;
665 i
= j
<0? -1: (j
>0? 1: 0);
667 i
= strcmp(getsval(x
), getsval(y
));
672 case LT
: if (i
<0) return(True
);
674 case LE
: if (i
<=0) return(True
);
676 case NE
: if (i
!=0) return(True
);
678 case EQ
: if (i
== 0) return(True
);
680 case GE
: if (i
>=0) return(True
);
682 case GT
: if (i
>0) return(True
);
684 default: /* can't happen */
685 FATAL("unknown relational operator %d", n
);
687 return 0; /*NOTREACHED*/
690 void tfree(Cell
*a
) /* free a tempcell */
693 DPRINTF("freeing %s %s %o\n", NN(a
->nval
), NN(a
->sval
), a
->tval
);
697 FATAL("tempcell list is curdled");
702 Cell
*gettemp(void) /* get a tempcell */
707 tmps
= (Cell
*) calloc(100, sizeof(*tmps
));
709 FATAL("out of space for temporaries");
710 for (i
= 1; i
< 100; i
++)
711 tmps
[i
-1].cnext
= &tmps
[i
];
712 tmps
[i
-1].cnext
= NULL
;
720 Cell
*indirect(Node
**a
, int n
) /* $( a[0] ) */
728 val
= getfval(x
); /* freebsd: defend against super large field numbers */
729 if ((Awkfloat
)INT_MAX
< val
)
730 FATAL("trying to access out of range field %s", x
->nval
);
732 if (m
== 0 && !is_number(s
= getsval(x
), NULL
)) /* suspicion! */
733 FATAL("illegal field $(%s), name \"%s\"", s
, x
->nval
);
734 /* BUG: can x->nval ever be null??? */
737 x
->ctype
= OCELL
; /* BUG? why are these needed? */
742 Cell
*substr(Node
**a
, int nnn
) /* substr(a[0], a[1], a[2]) */
747 Cell
*x
, *y
, *z
= NULL
;
765 m
= (int) getfval(y
);
772 n
= (int) getfval(z
);
780 DPRINTF("substr: m=%d, n=%d, s=%s\n", m
, n
, s
);
782 temp
= s
[n
+m
-1]; /* with thanks to John Linderman */
784 setsval(y
, s
+ m
- 1);
790 Cell
*sindex(Node
**a
, int nnn
) /* index(a[0], a[1]) */
793 char *s1
, *s2
, *p1
, *p2
, *q
;
802 for (p1
= s1
; *p1
!= '\0'; p1
++) {
803 for (q
= p1
, p2
= s2
; *p2
!= '\0' && *q
== *p2
; q
++, p2
++)
806 v
= (Awkfloat
) (p1
- s1
+ 1); /* origin 1 */
816 #define MAXNUMSIZE 50
818 int format(char **pbuf
, int *pbufsize
, const char *s
, Node
*a
) /* printf-like conversions */
825 int fmtwd
; /* format width */
828 int bufsize
= *pbufsize
;
829 #define FMTSZ(a) (fmtsz - ((a) - fmt))
830 #define BUFSZ(a) (bufsize - ((a) - buf))
832 static bool first
= true;
833 static bool have_a_format
= false;
838 snprintf(xbuf
, sizeof(xbuf
), "%a", 42.0);
839 have_a_format
= (strcmp(xbuf
, "0x1.5p+5") == 0);
845 if ((fmt
= (char *) malloc(fmtsz
)) == NULL
)
846 FATAL("out of memory in format()");
848 adjbuf(&buf
, &bufsize
, MAXNUMSIZE
+1+p
-buf
, recsize
, &p
, "format1");
858 /* have to be real careful in case this is a huge number, eg, %100000d */
862 adjbuf(&buf
, &bufsize
, fmtwd
+1+p
-buf
, recsize
, &p
, "format2");
863 for (t
= fmt
; (*t
++ = *s
) != '\0'; s
++) {
864 if (!adjbuf(&fmt
, &fmtsz
, MAXNUMSIZE
+1+t
-fmt
, recsize
, &t
, "format3"))
865 FATAL("format item %.30s... ran format() out of memory", os
);
866 /* Ignore size specifiers */
867 if (strchr("hjLlqtz", *s
) != NULL
) { /* the ansi panoply */
871 if (isalpha((uschar
)*s
))
874 FATAL("'$' not permitted in awk formats");
878 FATAL("not enough args in printf(%s)", os
);
882 snprintf(t
- 1, FMTSZ(t
- 1),
883 "%d", fmtwd
=(int) getfval(x
));
886 adjbuf(&buf
, &bufsize
, fmtwd
+1+p
-buf
, recsize
, &p
, "format");
887 t
= fmt
+ strlen(fmt
);
894 adjbuf(&buf
, &bufsize
, fmtwd
+1+p
-buf
, recsize
, &p
, "format4");
902 case 'f': case 'e': case 'g': case 'E': case 'G':
905 case 'd': case 'i': case 'o': case 'x': case 'X': case 'u':
906 flag
= (*s
== 'd' || *s
== 'i') ? 'd' : 'u';
918 WARNING("weird printf conversion %s", fmt
);
923 FATAL("not enough args in printf(%s)", os
);
929 adjbuf(&buf
, &bufsize
, 1+n
+p
-buf
, recsize
, &p
, "format5");
931 case '?': snprintf(p
, BUFSZ(p
), "%s", fmt
); /* unknown, so dump it too */
936 adjbuf(&buf
, &bufsize
, 1+strlen(p
)+n
+p
-buf
, recsize
, &p
, "format6");
938 snprintf(p
, BUFSZ(p
), "%s", t
);
942 case 'f': snprintf(p
, BUFSZ(p
), fmt
, getfval(x
)); break;
943 case 'd': snprintf(p
, BUFSZ(p
), fmt
, (intmax_t) getfval(x
)); break;
944 case 'u': snprintf(p
, BUFSZ(p
), fmt
, (uintmax_t) getfval(x
)); break;
950 if (!adjbuf(&buf
, &bufsize
, 1+n
+p
-buf
, recsize
, &p
, "format7"))
951 FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n
, t
);
952 snprintf(p
, BUFSZ(p
), fmt
, t
);
957 snprintf(p
, BUFSZ(p
), fmt
, (int) getfval(x
));
959 *p
++ = '\0'; /* explicit null byte */
960 *p
= '\0'; /* next output will start here */
963 snprintf(p
, BUFSZ(p
), fmt
, getsval(x
)[0]);
966 FATAL("can't happen: bad conversion %c in format()", flag
);
974 for ( ; a
; a
= a
->nnext
) { /* evaluate any remaining args */
983 Cell
*awksprintf(Node
**a
, int n
) /* sprintf(a[0]) */
990 if ((buf
= (char *) malloc(bufsz
)) == NULL
)
991 FATAL("out of memory in awksprintf");
994 if (format(&buf
, &bufsz
, getsval(x
), y
) == -1)
995 FATAL("sprintf string %.30s... too long. can't happen.", buf
);
1003 Cell
*awkprintf(Node
**a
, int n
) /* printf */
1004 { /* a[0] is list of args, starting with format string */
1005 /* a[1] is redirection operator, a[2] is redirection file */
1011 int bufsz
=3*recsize
;
1013 if ((buf
= (char *) malloc(bufsz
)) == NULL
)
1014 FATAL("out of memory in awkprintf");
1017 if ((len
= format(&buf
, &bufsz
, getsval(x
), y
)) == -1)
1018 FATAL("printf string %.30s... too long. can't happen.", buf
);
1021 /* fputs(buf, stdout); */
1022 fwrite(buf
, len
, 1, stdout
);
1024 FATAL("write error on stdout");
1026 fp
= redirect(ptoi(a
[1]), a
[2]);
1027 /* fputs(buf, fp); */
1028 fwrite(buf
, len
, 1, fp
);
1031 FATAL("write error on %s", filename(fp
));
1037 Cell
*arith(Node
**a
, int n
) /* a[0] + a[1], etc. also -a[0] */
1046 if (n
!= UMINUS
&& n
!= UPLUS
) {
1064 FATAL("division by zero");
1069 FATAL("division by zero in mod");
1076 case UPLUS
: /* handled by getfval(), above */
1079 if (j
>= 0 && modf(j
, &v
) == 0.0) /* pos integer exponent */
1080 i
= ipow(i
, (int) j
);
1083 i
= errcheck(pow(i
, j
), "pow");
1086 default: /* can't happen */
1087 FATAL("illegal arithmetic operator %d", n
);
1093 double ipow(double x
, int n
) /* x**n. ought to be done by pow, but isn't always */
1106 Cell
*incrdecr(Node
**a
, int n
) /* a[0]++, etc. */
1114 k
= (n
== PREINCR
|| n
== POSTINCR
) ? 1 : -1;
1115 if (n
== PREINCR
|| n
== PREDECR
) {
1126 Cell
*assign(Node
**a
, int n
) /* a[0] = a[1], a[0] += a[1], etc. */
1127 { /* this is subtle; don't muck with it. */
1134 if (n
== ASSIGN
) { /* ordinary assignment */
1135 if (x
== y
&& !(x
->tval
& (FLD
|REC
)) && x
!= nfloc
)
1136 ; /* self-assignment: leave alone unless it's a field or NF */
1137 else if ((y
->tval
& (STR
|NUM
)) == (STR
|NUM
)) {
1138 setsval(x
, getsval(y
));
1139 x
->fval
= getfval(y
);
1143 setsval(x
, getsval(y
));
1145 setfval(x
, getfval(y
));
1147 funnyvar(y
, "read value of");
1165 FATAL("division by zero in /=");
1170 FATAL("division by zero in %%=");
1175 if (yf
>= 0 && modf(yf
, &v
) == 0.0) /* pos integer exponent */
1176 xf
= ipow(xf
, (int) yf
);
1179 xf
= errcheck(pow(xf
, yf
), "pow");
1183 FATAL("illegal assignment operator %d", n
);
1191 Cell
*cat(Node
**a
, int q
) /* a[0] cat a[1] */
1199 n1
= strlen(getsval(x
));
1200 adjbuf(&s
, &ssz
, n1
+ 1, recsize
, 0, "cat1");
1201 memcpy(s
, x
->sval
, n1
);
1206 n2
= strlen(getsval(y
));
1207 adjbuf(&s
, &ssz
, n1
+ n2
+ 1, recsize
, 0, "cat2");
1208 memcpy(s
+ n1
, y
->sval
, n2
);
1220 Cell
*pastat(Node
**a
, int n
) /* a[0] { a[1] } */
1236 Cell
*dopa2(Node
**a
, int n
) /* a[0], a[1] { a[2] } */
1242 if (pairstack
[pair
] == 0) {
1245 pairstack
[pair
] = 1;
1248 if (pairstack
[pair
] == 1) {
1251 pairstack
[pair
] = 0;
1259 Cell
*split(Node
**a
, int nnn
) /* split(a[0], a[1], a[2]); a[3] is type */
1261 Cell
*x
= NULL
, *y
, *ap
;
1262 const char *s
, *origs
, *t
;
1263 const char *fs
= NULL
;
1264 char *origfs
= NULL
;
1267 int n
, tempstat
, arg3type
;
1270 y
= execute(a
[0]); /* source string */
1271 origs
= s
= strdup(getsval(y
));
1273 arg3type
= ptoi(a
[3]);
1274 if (a
[2] == NULL
) /* fs string */
1275 fs
= getsval(fsloc
);
1276 else if (arg3type
== STRING
) { /* split(str,arr,"string") */
1278 fs
= origfs
= strdup(getsval(x
));
1280 } else if (arg3type
== REGEXPR
)
1281 fs
= "(regexpr)"; /* split(str,arr,/regexpr/) */
1283 FATAL("illegal type of split");
1285 ap
= execute(a
[1]); /* array name */
1287 DPRINTF("split: s=|%s|, a=%s, sep=|%s|\n", s
, NN(ap
->nval
), fs
);
1290 ap
->sval
= (char *) makesymtab(NSYMTAB
);
1293 if (arg3type
== REGEXPR
&& strlen((char*)((fa
*)a
[2])->restr
) == 0) {
1294 /* split(s, a, //); have to arrange that it looks like empty sep */
1299 if (*s
!= '\0' && (strlen(fs
) > 1 || arg3type
== REGEXPR
)) { /* reg expr */
1301 if (arg3type
== REGEXPR
) { /* it's ready already */
1304 pfa
= makedfa(fs
, 1);
1306 if (nematch(pfa
,s
)) {
1307 tempstat
= pfa
->initstat
;
1311 snprintf(num
, sizeof(num
), "%d", n
);
1313 setptr(patbeg
, '\0');
1314 if (is_number(s
, & result
))
1315 setsymtab(num
, s
, result
, STR
|NUM
, (Array
*) ap
->sval
);
1317 setsymtab(num
, s
, 0.0, STR
, (Array
*) ap
->sval
);
1318 setptr(patbeg
, temp
);
1319 s
= patbeg
+ patlen
;
1320 if (*(patbeg
+patlen
-1) == '\0' || *s
== '\0') {
1322 snprintf(num
, sizeof(num
), "%d", n
);
1323 setsymtab(num
, "", 0.0, STR
, (Array
*) ap
->sval
);
1324 pfa
->initstat
= tempstat
;
1327 } while (nematch(pfa
,s
));
1328 pfa
->initstat
= tempstat
; /* bwk: has to be here to reset */
1329 /* cf gsub and refldbld */
1332 snprintf(num
, sizeof(num
), "%d", n
);
1333 if (is_number(s
, & result
))
1334 setsymtab(num
, s
, result
, STR
|NUM
, (Array
*) ap
->sval
);
1336 setsymtab(num
, s
, 0.0, STR
, (Array
*) ap
->sval
);
1339 } else if (sep
== ' ') {
1341 #define ISWS(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
1350 while (*s
!= '\0' && !ISWS(*s
));
1353 snprintf(num
, sizeof(num
), "%d", n
);
1354 if (is_number(t
, & result
))
1355 setsymtab(num
, t
, result
, STR
|NUM
, (Array
*) ap
->sval
);
1357 setsymtab(num
, t
, 0.0, STR
, (Array
*) ap
->sval
);
1362 } else if (sep
== 0) { /* new: split(s, a, "") => 1 char/elem */
1363 for (n
= 0; *s
!= '\0'; s
++) {
1366 snprintf(num
, sizeof(num
), "%d", n
);
1369 if (isdigit((uschar
)buf
[0]))
1370 setsymtab(num
, buf
, atof(buf
), STR
|NUM
, (Array
*) ap
->sval
);
1372 setsymtab(num
, buf
, 0.0, STR
, (Array
*) ap
->sval
);
1374 } else if (*s
!= '\0') {
1378 while (*s
!= sep
&& *s
!= '\n' && *s
!= '\0')
1382 snprintf(num
, sizeof(num
), "%d", n
);
1383 if (is_number(t
, & result
))
1384 setsymtab(num
, t
, result
, STR
|NUM
, (Array
*) ap
->sval
);
1386 setsymtab(num
, t
, 0.0, STR
, (Array
*) ap
->sval
);
1401 Cell
*condexpr(Node
**a
, int n
) /* a[0] ? a[1] : a[2] */
1416 Cell
*ifstat(Node
**a
, int n
) /* if (a[0]) a[1]; else a[2] */
1424 } else if (a
[2] != NULL
) {
1431 Cell
*whilestat(Node
**a
, int n
) /* while (a[0]) a[1] */
1445 if (isnext(x
) || isexit(x
) || isret(x
))
1451 Cell
*dostat(Node
**a
, int n
) /* do a[0]; while(a[1]) */
1459 if (isnext(x
) || isexit(x
) || isret(x
))
1469 Cell
*forstat(Node
**a
, int n
) /* for (a[0]; a[1]; a[2]) a[3] */
1478 if (!istrue(x
)) return(x
);
1482 if (isbreak(x
)) /* turn off break */
1484 if (isnext(x
) || isexit(x
) || isret(x
))
1492 Cell
*instat(Node
**a
, int n
) /* for (a[0] in a[1]) a[2] */
1494 Cell
*x
, *vp
, *arrayp
, *cp
, *ncp
;
1499 arrayp
= execute(a
[1]);
1500 if (!isarr(arrayp
)) {
1503 tp
= (Array
*) arrayp
->sval
;
1505 for (i
= 0; i
< tp
->size
; i
++) { /* this routine knows too much */
1506 for (cp
= tp
->tab
[i
]; cp
!= NULL
; cp
= ncp
) {
1507 setsval(vp
, cp
->nval
);
1514 if (isnext(x
) || isexit(x
) || isret(x
)) {
1524 static char *nawk_convert(const char *s
, int (*fun_c
)(int),
1525 wint_t (*fun_wc
)(wint_t))
1529 const char *ps
= NULL
;
1532 size_t sz
= MB_CUR_MAX
;
1537 for (pbuf
= buf
; *pbuf
; pbuf
++)
1538 *pbuf
= fun_c((uschar
)*pbuf
);
1542 /* upper/lower character may be shorter/longer */
1543 buf
= tostringN(s
, strlen(s
) * sz
+ 1);
1545 (void) mbtowc(NULL
, NULL
, 0); /* reset internal state */
1547 * Reset internal state here too.
1548 * Assign result to avoid a compiler warning. (Casting to void
1550 * Increment said variable to avoid a different warning.
1552 int unused
= wctomb(NULL
, L
'\0');
1557 while (n
= mbtowc(&wc
, ps
, sz
),
1558 n
> 0 && n
!= (size_t)-1 && n
!= (size_t)-2)
1562 n
= wctomb(pbuf
, fun_wc(wc
));
1563 if (n
== (size_t)-1)
1564 FATAL("illegal wide character %s", s
);
1572 FATAL("illegal byte sequence %s", s
);
1579 static wint_t towupper(wint_t wc
)
1581 if (wc
>= 0 && wc
< 256)
1582 return toupper(wc
& 0xFF);
1587 static wint_t towlower(wint_t wc
)
1589 if (wc
>= 0 && wc
< 256)
1590 return tolower(wc
& 0xFF);
1596 static char *nawk_toupper(const char *s
)
1598 return nawk_convert(s
, toupper
, towupper
);
1601 static char *nawk_tolower(const char *s
)
1603 return nawk_convert(s
, tolower
, towlower
);
1606 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 fflush(stdout
); /* in case something is buffered already */
1658 status
= system(getsval(x
));
1661 if (WIFEXITED(status
)) {
1662 u
= WEXITSTATUS(status
);
1663 } else if (WIFSIGNALED(status
)) {
1664 u
= WTERMSIG(status
) + 256;
1666 if (WCOREDUMP(status
))
1669 } else /* something else?!? */
1674 /* random() returns numbers in [0..2^31-1]
1675 * in order to get a number in [0, 1), divide it by 2^31
1677 u
= (Awkfloat
) random() / (0x7fffffffL
+ 0x1UL
);
1680 if (isrec(x
)) /* no argument provided */
1681 u
= time((time_t *)0);
1685 srandom((unsigned long) u
);
1692 buf
= nawk_toupper(getsval(x
));
1694 buf
= nawk_tolower(getsval(x
));
1701 if (isrec(x
) || strlen(getsval(x
)) == 0) {
1702 flush_all(); /* fflush() or fflush("") -> all */
1704 } else if ((fp
= openfile(FFLUSH
, getsval(x
), NULL
)) == NULL
)
1709 default: /* can't happen */
1710 FATAL("illegal function type %d", t
);
1716 if (nextarg
!= NULL
) {
1717 WARNING("warning: function has too many arguments");
1718 for ( ; nextarg
; nextarg
= nextarg
->nnext
) {
1719 y
= execute(nextarg
);
1726 Cell
*printstat(Node
**a
, int n
) /* print a[0] */
1732 if (a
[1] == NULL
) /* a[1] is redirection operator, a[2] is file */
1735 fp
= redirect(ptoi(a
[1]), a
[2]);
1736 for (x
= a
[0]; x
!= NULL
; x
= x
->nnext
) {
1738 fputs(getpssval(y
), fp
);
1740 if (x
->nnext
== NULL
)
1741 fputs(getsval(orsloc
), fp
);
1743 fputs(getsval(ofsloc
), fp
);
1748 FATAL("write error on %s", filename(fp
));
1752 Cell
*nullproc(Node
**a
, int n
)
1758 FILE *redirect(int a
, Node
*b
) /* set up all i/o redirections */
1766 fp
= openfile(a
, fname
, NULL
);
1768 FATAL("can't open file %s", fname
);
1776 int mode
; /* '|', 'a', 'w' => LE/LT, GT */
1781 static void stdinit(void) /* in case stdin, etc., are not constants */
1784 files
= (struct files
*) calloc(nfiles
, sizeof(*files
));
1786 FATAL("can't allocate file memory for %zu files", nfiles
);
1787 files
[0].fp
= stdin
;
1788 files
[0].fname
= tostring("/dev/stdin");
1790 files
[1].fp
= stdout
;
1791 files
[1].fname
= tostring("/dev/stdout");
1793 files
[2].fp
= stderr
;
1794 files
[2].fname
= tostring("/dev/stderr");
1798 FILE *openfile(int a
, const char *us
, bool *pnewflag
)
1806 FATAL("null file name in print or getline");
1807 for (i
= 0; i
< nfiles
; i
++)
1808 if (files
[i
].fname
&& strcmp(s
, files
[i
].fname
) == 0 &&
1809 (a
== files
[i
].mode
|| (a
==APPEND
&& files
[i
].mode
==GT
) ||
1815 if (a
== FFLUSH
) /* didn't find it, so don't create it! */
1818 for (i
= 0; i
< nfiles
; i
++)
1819 if (files
[i
].fp
== NULL
)
1823 size_t nnf
= nfiles
+ FOPEN_MAX
;
1824 nf
= (struct files
*) realloc(files
, nnf
* sizeof(*nf
));
1826 FATAL("cannot grow files for %s and %zu files", s
, nnf
);
1827 memset(&nf
[nfiles
], 0, FOPEN_MAX
* sizeof(*nf
));
1831 fflush(stdout
); /* force a semblance of order */
1835 } else if (a
== APPEND
) {
1837 m
= GT
; /* so can mix > and >> */
1838 } else if (a
== '|') { /* output pipe */
1840 } else if (a
== LE
) { /* input pipe */
1842 } else if (a
== LT
) { /* getline <file */
1843 fp
= strcmp(s
, "-") == 0 ? stdin
: fopen(s
, "r"); /* "-" is stdin */
1844 } else /* can't happen */
1845 FATAL("illegal redirection %d", a
);
1847 files
[i
].fname
= tostring(s
);
1852 if (fp
!= stdin
&& fp
!= stdout
&& fp
!= stderr
)
1853 (void) fcntl(fileno(fp
), F_SETFD
, FD_CLOEXEC
);
1858 const char *filename(FILE *fp
)
1862 for (i
= 0; i
< nfiles
; i
++)
1863 if (fp
== files
[i
].fp
)
1864 return files
[i
].fname
;
1868 Cell
*closefile(Node
**a
, int n
)
1877 for (i
= 0; i
< nfiles
; i
++) {
1878 if (!files
[i
].fname
|| strcmp(x
->sval
, files
[i
].fname
) != 0)
1880 if (files
[i
].mode
== GT
|| files
[i
].mode
== '|')
1881 fflush(files
[i
].fp
);
1882 if (ferror(files
[i
].fp
)) {
1883 if ((files
[i
].mode
== GT
&& files
[i
].fp
!= stderr
)
1884 || files
[i
].mode
== '|')
1885 FATAL("write error on %s", files
[i
].fname
);
1887 WARNING("i/o error occurred on %s", files
[i
].fname
);
1889 if (files
[i
].fp
== stdin
|| files
[i
].fp
== stdout
||
1890 files
[i
].fp
== stderr
)
1891 stat
= freopen("/dev/null", "r+", files
[i
].fp
) == NULL
;
1892 else if (files
[i
].mode
== '|' || files
[i
].mode
== LE
)
1893 stat
= pclose(files
[i
].fp
) == -1;
1895 stat
= fclose(files
[i
].fp
) == EOF
;
1897 WARNING("i/o error occurred closing %s", files
[i
].fname
);
1898 xfree(files
[i
].fname
);
1899 files
[i
].fname
= NULL
; /* watch out for ref thru this */
1905 setfval(x
, (Awkfloat
) (stat
? -1 : 0));
1914 for (i
= 0; i
< nfiles
; i
++) {
1917 if (files
[i
].mode
== GT
|| files
[i
].mode
== '|')
1918 fflush(files
[i
].fp
);
1919 if (ferror(files
[i
].fp
)) {
1920 if ((files
[i
].mode
== GT
&& files
[i
].fp
!= stderr
)
1921 || files
[i
].mode
== '|')
1922 FATAL("write error on %s", files
[i
].fname
);
1924 WARNING("i/o error occurred on %s", files
[i
].fname
);
1926 if (files
[i
].fp
== stdin
|| files
[i
].fp
== stdout
||
1927 files
[i
].fp
== stderr
)
1929 if (files
[i
].mode
== '|' || files
[i
].mode
== LE
)
1930 stat
= pclose(files
[i
].fp
) == -1;
1932 stat
= fclose(files
[i
].fp
) == EOF
;
1934 WARNING("i/o error occurred while closing %s", files
[i
].fname
);
1938 static void flush_all(void)
1942 for (i
= 0; i
< nfiles
; i
++)
1944 fflush(files
[i
].fp
);
1947 void backsub(char **pb_ptr
, const char **sptr_ptr
);
1949 Cell
*sub(Node
**a
, int nnn
) /* substitute command */
1951 const char *sptr
, *q
;
1952 Cell
*x
, *y
, *result
;
1955 int bufsz
= recsize
;
1957 if ((buf
= (char *) malloc(bufsz
)) == NULL
)
1958 FATAL("out of memory in sub");
1959 x
= execute(a
[3]); /* target string */
1961 if (a
[0] == NULL
) /* 0 => a[1] is already-compiled regexpr */
1962 pfa
= (fa
*) a
[1]; /* regular expression */
1965 pfa
= makedfa(getsval(y
), 1);
1968 y
= execute(a
[2]); /* replacement string */
1970 if (pmatch(pfa
, t
)) {
1972 adjbuf(&buf
, &bufsz
, 1+patbeg
-sptr
, recsize
, 0, "sub");
1974 while (sptr
< patbeg
)
1977 while (*sptr
!= '\0') {
1978 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "sub");
1979 if (*sptr
== '\\') {
1980 backsub(&pb
, &sptr
);
1981 } else if (*sptr
== '&') {
1983 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "sub");
1984 for (q
= patbeg
; q
< patbeg
+patlen
; )
1990 if (pb
> buf
+ bufsz
)
1991 FATAL("sub result1 %.30s too big; can't happen", buf
);
1992 sptr
= patbeg
+ patlen
;
1993 if ((patlen
== 0 && *patbeg
) || (patlen
&& *(sptr
-1))) {
1994 adjbuf(&buf
, &bufsz
, 1+strlen(sptr
)+pb
-buf
, 0, &pb
, "sub");
1995 while ((*pb
++ = *sptr
++) != '\0')
1998 if (pb
> buf
+ bufsz
)
1999 FATAL("sub result2 %.30s too big; can't happen", buf
);
2000 setsval(x
, buf
); /* BUG: should be able to avoid copy */
2009 Cell
*gsub(Node
**a
, int nnn
) /* global substitute */
2013 const char *q
, *t
, *sptr
;
2016 int mflag
, tempstat
, num
;
2017 int bufsz
= recsize
;
2019 if ((buf
= (char *) malloc(bufsz
)) == NULL
)
2020 FATAL("out of memory in gsub");
2021 mflag
= 0; /* if mflag == 0, can replace empty string */
2023 x
= execute(a
[3]); /* target string */
2025 if (a
[0] == NULL
) /* 0 => a[1] is already-compiled regexpr */
2026 pfa
= (fa
*) a
[1]; /* regular expression */
2029 pfa
= makedfa(getsval(y
), 1);
2032 y
= execute(a
[2]); /* replacement string */
2033 if (pmatch(pfa
, t
)) {
2034 tempstat
= pfa
->initstat
;
2039 if (patlen
== 0 && *patbeg
!= '\0') { /* matched empty string */
2040 if (mflag
== 0) { /* can replace empty */
2043 while (*sptr
!= '\0') {
2044 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "gsub");
2045 if (*sptr
== '\\') {
2046 backsub(&pb
, &sptr
);
2047 } else if (*sptr
== '&') {
2049 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "gsub");
2050 for (q
= patbeg
; q
< patbeg
+patlen
; )
2056 if (*t
== '\0') /* at end */
2058 adjbuf(&buf
, &bufsz
, 2+pb
-buf
, recsize
, &pb
, "gsub");
2060 if (pb
> buf
+ bufsz
) /* BUG: not sure of this test */
2061 FATAL("gsub result0 %.30s too big; can't happen", buf
);
2064 else { /* matched nonempty string */
2067 adjbuf(&buf
, &bufsz
, 1+(patbeg
-sptr
)+pb
-buf
, recsize
, &pb
, "gsub");
2068 while (sptr
< patbeg
)
2071 while (*sptr
!= '\0') {
2072 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "gsub");
2073 if (*sptr
== '\\') {
2074 backsub(&pb
, &sptr
);
2075 } else if (*sptr
== '&') {
2077 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "gsub");
2078 for (q
= patbeg
; q
< patbeg
+patlen
; )
2083 t
= patbeg
+ patlen
;
2084 if (patlen
== 0 || *t
== '\0' || *(t
-1) == '\0')
2086 if (pb
> buf
+ bufsz
)
2087 FATAL("gsub result1 %.30s too big; can't happen", buf
);
2090 } while (pmatch(pfa
,t
));
2092 adjbuf(&buf
, &bufsz
, 1+strlen(sptr
)+pb
-buf
, 0, &pb
, "gsub");
2093 while ((*pb
++ = *sptr
++) != '\0')
2095 done
: if (pb
< buf
+ bufsz
)
2097 else if (*(pb
-1) != '\0')
2098 FATAL("gsub result2 %.30s truncated; can't happen", buf
);
2099 setsval(x
, buf
); /* BUG: should be able to avoid copy + free */
2100 pfa
->initstat
= tempstat
;
2111 void backsub(char **pb_ptr
, const char **sptr_ptr
) /* handle \\& variations */
2112 { /* sptr[0] == '\\' */
2114 const char *sptr
= *sptr_ptr
;
2115 static bool first
= true;
2116 static bool do_posix
= false;
2120 do_posix
= (getenv("POSIXLY_CORRECT") != NULL
);
2123 if (sptr
[1] == '\\') {
2124 if (sptr
[2] == '\\' && sptr
[3] == '&') { /* \\\& -> \& */
2128 } else if (sptr
[2] == '&') { /* \\& -> \ + matched */
2131 } else if (do_posix
) { /* \\x -> \x */
2134 } else { /* \\x -> \\x */
2138 } else if (sptr
[1] == '&') { /* literal & */
2141 } else /* literal \ */