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 #if HAVE_NBTOOL_CONFIG_H
26 #include "nbtool_config.h"
44 #define tempfree(x) do { if (istemp(x)) tfree(x); } while (/*CONSTCOND*/0)
51 void tempfree(Cell *p) {
52 if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) {
53 WARNING("bad csub %d in Cell %d %s",
54 p->csub, p->ctype, p->sval);
61 /* do we really need these? */
63 /* #ifndef FOPEN_MAX */
64 /* #define FOPEN_MAX _NFILE */
68 /* #ifndef FOPEN_MAX */
69 /* #define FOPEN_MAX 40 */ /* max number of open files */
72 /* #ifndef RAND_MAX */
73 /* #define RAND_MAX 32767 */ /* all that ansi guarantees */
77 extern int pairstack
[];
78 extern unsigned int srand_seed
;
80 Node
*winner
= NULL
; /* root of parse tree */
81 Cell
*tmps
; /* free temporary cells for execution */
83 static Cell truecell
={ OBOOL
, BTRUE
, 0, 0, 1.0, NUM
, NULL
};
84 Cell
*True
= &truecell
;
85 static Cell falsecell
={ OBOOL
, BFALSE
, 0, 0, 0.0, NUM
, NULL
};
86 Cell
*False
= &falsecell
;
87 static Cell breakcell
={ OJUMP
, JBREAK
, 0, 0, 0.0, NUM
, NULL
};
88 Cell
*jbreak
= &breakcell
;
89 static Cell contcell
={ OJUMP
, JCONT
, 0, 0, 0.0, NUM
, NULL
};
90 Cell
*jcont
= &contcell
;
91 static Cell nextcell
={ OJUMP
, JNEXT
, 0, 0, 0.0, NUM
, NULL
};
92 Cell
*jnext
= &nextcell
;
93 static Cell nextfilecell
={ OJUMP
, JNEXTFILE
, 0, 0, 0.0, NUM
, NULL
};
94 Cell
*jnextfile
= &nextfilecell
;
95 static Cell exitcell
={ OJUMP
, JEXIT
, 0, 0, 0.0, NUM
, NULL
};
96 Cell
*jexit
= &exitcell
;
97 static Cell retcell
={ OJUMP
, JRET
, 0, 0, 0.0, NUM
, NULL
};
98 Cell
*jret
= &retcell
;
99 static Cell tempcell
={ OCELL
, CTEMP
, 0, EMPTY
, 0.0, NUM
|STR
|DONTFREE
, NULL
};
101 Node
*curnode
= NULL
; /* the node being executed, for debugging */
103 /* buffer memory management */
104 int adjbuf(uschar
**pbuf
, int *psiz
, int minlen
, int quantum
, uschar
**pbptr
,
106 /* pbuf: address of pointer to buffer being managed
107 * psiz: address of buffer size variable
108 * minlen: minimum length of buffer needed
109 * quantum: buffer size quantum
110 * pbptr: address of movable pointer into buffer, or 0 if none
111 * whatrtn: name of the calling routine if failure should cause fatal error
113 * return 0 for realloc failure, !=0 for success
116 if (minlen
> *psiz
) {
118 int rminlen
= quantum
? minlen
% quantum
: 0;
119 int boff
= pbptr
? *pbptr
- *pbuf
: 0;
120 /* round up to next multiple of quantum */
122 minlen
+= quantum
- rminlen
;
123 tbuf
= realloc(*pbuf
, minlen
);
124 dprintf( ("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn
, *psiz
, minlen
, *pbuf
, tbuf
) );
127 FATAL("out of memory in %s", whatrtn
);
133 *pbptr
= tbuf
+ boff
;
138 void run(Node
*a
) /* execution of parse tree starts here */
145 Cell
*execute(Node
*u
) /* execute a node of the parse tree */
147 Cell
*(*proc
)(Node
**, int);
153 for (a
= u
; ; a
= a
->nnext
) {
156 x
= (Cell
*) (a
->narg
[0]);
157 if (isfld(x
) && !donefld
)
159 else if (isrec(x
) && !donerec
)
163 if (notlegal(a
->nobj
)) /* probably a Cell* but too risky to print */
164 FATAL("illegal statement");
165 proc
= proctab
[a
->nobj
-FIRSTTOKEN
];
166 x
= (*proc
)(a
->narg
, a
->nobj
);
167 if (isfld(x
) && !donefld
)
169 else if (isrec(x
) && !donerec
)
175 if (a
->nnext
== NULL
)
182 Cell
*program(Node
**a
, int n
) /* execute an awk program */
183 { /* a[0] = BEGIN, a[1] = body, a[2] = END */
186 if (setjmp(env
) != 0)
188 if (a
[0]) { /* BEGIN */
193 FATAL("illegal break, continue, next or nextfile from BEGIN");
197 while (getrec(&record
, &recsize
, 1) > 0) {
204 if (setjmp(env
) != 0) /* handles exit within END */
206 if (a
[2]) { /* END */
208 if (isbreak(x
) || isnext(x
) || iscont(x
))
209 FATAL("illegal break, continue, next or nextfile from END");
216 struct Frame
{ /* stack frame for awk function calls */
217 int nargs
; /* number of arguments in this call */
218 Cell
*fcncell
; /* pointer to Cell for function */
219 Cell
**args
; /* pointer to array of arguments after execute */
220 Cell
*retval
; /* return value */
223 #define NARGS 50 /* max args in a call */
225 struct Frame
*frame
= NULL
; /* base of stack frames; dynamically allocated */
226 int nframe
= 0; /* number of frames allocated */
227 struct Frame
*frp
= NULL
; /* frame pointer. bottom level unused */
229 Cell
*call(Node
**a
, int n
) /* function call. very kludgy and fragile */
231 static const Cell newcopycell
= { OCELL
, CCOPY
, 0, EMPTY
, 0.0, NUM
|STR
|DONTFREE
, NULL
};
233 int freed
= 0; /* handles potential double freeing when fcn & param share a tempcell */
235 Cell
*args
[NARGS
], *oargs
[NARGS
]; /* BUG: fixed size arrays */
239 fcn
= execute(a
[0]); /* the function itself */
242 FATAL("calling undefined function %s", s
);
244 frp
= frame
= calloc(nframe
+= 100, sizeof(*frp
));
246 FATAL("out of space for stack frames calling %s", s
);
248 for (ncall
= 0, x
= a
[1]; x
!= NULL
; x
= x
->nnext
) /* args in call */
250 ndef
= (int) fcn
->fval
; /* args in defn */
251 dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s
, ncall
, ndef
, (int) (frp
-frame
)) );
253 WARNING("function %s called with %d args, uses only %d",
255 if (ncall
+ ndef
> NARGS
)
256 FATAL("function %s has %d arguments, limit %d", s
, ncall
+ndef
, NARGS
);
257 for (i
= 0, x
= a
[1]; x
!= NULL
; i
++, x
= x
->nnext
) { /* get call args */
258 dprintf( ("evaluate args[%d], fp=%d:\n", i
, (int) (frp
-frame
)) );
261 dprintf( ("args[%d]: %s %f <%s>, t=%o\n",
262 i
, NN(y
->nval
), y
->fval
, isarr(y
) ? "(array)" : NN(y
->sval
), y
->tval
) );
264 FATAL("can't use function %s as argument in %s", y
->nval
, s
);
266 args
[i
] = y
; /* arrays by ref */
268 args
[i
] = copycell(y
);
271 for ( ; i
< ndef
; i
++) { /* add null args for ones not provided */
273 *args
[i
] = newcopycell
;
275 frp
++; /* now ok to up frame */
276 if (frp
>= frame
+ nframe
) {
277 int dfp
= frp
- frame
; /* old index */
278 frame
= realloc(frame
, (nframe
+= 100) * sizeof(*frame
));
280 FATAL("out of space for stack frames in %s", s
);
285 frp
->nargs
= ndef
; /* number defined with (excess are locals) */
286 frp
->retval
= gettemp();
288 dprintf( ("start exec of %s, fp=%d\n", s
, (int) (frp
-frame
)) );
289 y
= execute((Node
*)(fcn
->sval
)); /* execute body */
290 dprintf( ("finished exec of %s, fp=%d\n", s
, (int) (frp
-frame
)) );
292 for (i
= 0; i
< ndef
; i
++) {
293 Cell
*t
= frp
->args
[i
];
295 if (t
->csub
== CCOPY
) {
301 oargs
[i
]->tval
= t
->tval
;
302 oargs
[i
]->tval
&= ~(STR
|NUM
|DONTFREE
);
303 oargs
[i
]->sval
= t
->sval
;
307 } else if (t
!= y
) { /* kludge to prevent freeing twice */
310 } else if (t
== y
&& t
->csub
== CCOPY
) {
317 if (isexit(y
) || isnext(y
))
320 tempfree(y
); /* don't free twice! */
322 z
= frp
->retval
; /* return value */
323 dprintf( ("%s returns %g |%s| %o\n", s
, getfval(z
), getsval(z
), z
->tval
) );
328 Cell
*copycell(Cell
*x
) /* make a copy of a cell in a temp */
332 /* copy is not constant or field */
335 y
->tval
= x
->tval
& ~(CON
|FLD
|REC
);
336 y
->csub
= CCOPY
; /* prevents freeing until call is over */
337 y
->nval
= x
->nval
; /* BUG? */
338 if (isstr(x
) /* || x->ctype == OCELL */) {
339 y
->sval
= tostring(x
->sval
);
340 y
->tval
&= ~DONTFREE
;
347 Cell
*arg(Node
**a
, int n
) /* nth argument of a function */
350 n
= ptoi(a
[0]); /* argument number, counting from 0 */
351 dprintf( ("arg(%d), fp->nargs=%d\n", n
, frp
->nargs
) );
352 if (n
+1 > frp
->nargs
)
353 FATAL("argument #%d of function %s was not supplied",
354 n
+1, frp
->fcncell
->nval
);
358 Cell
*jump(Node
**a
, int n
) /* break, continue, next, nextfile, return */
366 errorflag
= (int) getfval(y
);
373 if ((y
->tval
& (STR
|NUM
)) == (STR
|NUM
)) {
374 setsval(frp
->retval
, getsval(y
));
375 frp
->retval
->fval
= getfval(y
);
376 frp
->retval
->tval
|= NUM
;
378 else if (y
->tval
& STR
)
379 setsval(frp
->retval
, getsval(y
));
380 else if (y
->tval
& NUM
)
381 setfval(frp
->retval
, getfval(y
));
382 else /* can't happen */
383 FATAL("bad type variable %d", y
->tval
);
396 default: /* can't happen */
397 FATAL("illegal jump type %d", n
);
399 return 0; /* not reached */
402 Cell
*awkgetline(Node
**a
, int n
) /* get next line from specific input */
403 { /* a[0] is variable, a[1] is operator, a[2] is filename */
405 extern Cell
**fldtab
;
408 int bufsize
= recsize
;
411 if ((buf
= malloc(bufsize
)) == NULL
)
412 FATAL("out of memory in getline");
414 fflush(stdout
); /* in case someone is waiting for a prompt */
416 if (a
[1] != NULL
) { /* getline < file */
417 x
= execute(a
[2]); /* filename */
419 if (mode
== '|') /* input pipe */
420 mode
= LE
; /* arbitrary flag */
421 fp
= openfile(mode
, getsval(x
), &newflag
);
426 n
= readrec(&buf
, &bufsize
, fp
, newflag
);
429 } else if (a
[0] != NULL
) { /* getline var <file */
433 } else { /* getline <file */
434 setsval(fldtab
[0], buf
);
435 if (is_number(fldtab
[0]->sval
)) {
436 fldtab
[0]->fval
= atof(fldtab
[0]->sval
);
437 fldtab
[0]->tval
|= NUM
;
440 } else { /* bare getline; use current input */
441 if (a
[0] == NULL
) /* getline */
442 n
= getrec(&record
, &recsize
, 1);
443 else { /* getline var */
444 n
= getrec(&buf
, &bufsize
, 0);
450 setfval(r
, (Awkfloat
) n
);
455 Cell
*getnf(Node
**a
, int n
) /* get NF */
459 return (Cell
*) a
[0];
462 Cell
*array(Node
**a
, int n
) /* a[0] is symtab, a[1] is list of subscripts */
469 int nsub
= strlen(*SUBSEP
);
471 if ((buf
= malloc(bufsz
)) == NULL
)
472 FATAL("out of memory in array");
474 x
= execute(a
[0]); /* Cell* for symbol table */
476 for (np
= a
[1]; np
; np
= np
->nnext
) {
477 y
= execute(np
); /* subscript */
479 if (!adjbuf(&buf
, &bufsz
, strlen(buf
)+strlen(s
)+nsub
+1, recsize
, 0, "array"))
480 FATAL("out of memory for %s[%s...]", x
->nval
, buf
);
481 strlcat(buf
, s
, bufsz
);
483 strlcat(buf
, *SUBSEP
, bufsz
);
487 dprintf( ("making %s into an array\n", NN(x
->nval
)) );
490 x
->tval
&= ~(STR
|NUM
|DONTFREE
);
492 x
->sval
= (char *) makesymtab(NSYMTAB
);
494 z
= setsymtab(buf
, "", 0.0, STR
|NUM
, (Array
*) x
->sval
);
502 Cell
*awkdelete(Node
**a
, int n
) /* a[0] is symtab, a[1] is list of subscripts */
507 int nsub
= strlen(*SUBSEP
);
509 x
= execute(a
[0]); /* Cell* for symbol table */
512 if (a
[1] == 0) { /* delete the elements, not the table */
516 x
->sval
= (char *) makesymtab(NSYMTAB
);
520 if ((buf
= malloc(bufsz
)) == NULL
)
521 FATAL("out of memory in adelete");
523 for (np
= a
[1]; np
; np
= np
->nnext
) {
524 y
= execute(np
); /* subscript */
526 if (!adjbuf(&buf
, &bufsz
, strlen(buf
)+strlen(s
)+nsub
+1, recsize
, 0, "awkdelete"))
527 FATAL("out of memory deleting %s[%s...]", x
->nval
, buf
);
528 strlcat(buf
, s
, bufsz
);
530 strlcat(buf
, *SUBSEP
, bufsz
);
540 Cell
*intest(Node
**a
, int n
) /* a[0] is index (list), a[1] is symtab */
547 int nsub
= strlen(*SUBSEP
);
549 ap
= execute(a
[1]); /* array name */
551 dprintf( ("making %s into an array\n", ap
->nval
) );
554 ap
->tval
&= ~(STR
|NUM
|DONTFREE
);
556 ap
->sval
= (char *) makesymtab(NSYMTAB
);
558 if ((buf
= malloc(bufsz
)) == NULL
) {
559 FATAL("out of memory in intest");
562 for (p
= a
[0]; p
; p
= p
->nnext
) {
563 x
= execute(p
); /* expr */
565 if (!adjbuf(&buf
, &bufsz
, strlen(buf
)+strlen(s
)+nsub
+1, recsize
, 0, "intest"))
566 FATAL("out of memory deleting %s[%s...]", x
->nval
, buf
);
570 strcat(buf
, *SUBSEP
);
572 k
= lookup(buf
, (Array
*) ap
->sval
);
582 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] == 0) /* 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
= 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
];
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
))) /* 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]) */
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 */
825 int fmtwd
; /* format width */
828 int bufsize
= *pbufsize
;
829 #define FMTSZ(a) (fmtsz - ((a) - fmt))
830 #define BUFSZ(a) (bufsize - ((a) - buf))
834 if ((fmt
= malloc(fmtsz
)) == NULL
)
835 FATAL("out of memory in format()");
837 adjbuf(&buf
, &bufsize
, MAXNUMSIZE
+1+p
-buf
, recsize
, &p
, "format1");
847 /* have to be real careful in case this is a huge number, eg, %100000d */
851 adjbuf(&buf
, &bufsize
, fmtwd
+1+p
-buf
, recsize
, &p
, "format2");
852 for (t
= fmt
; (*t
++ = *s
) != '\0'; s
++) {
853 if (!adjbuf(&fmt
, &fmtsz
, MAXNUMSIZE
+1+t
-fmt
, recsize
, &t
, "format3"))
854 FATAL("format item %.30s... ran format() out of memory", os
);
855 if (*s
== 'l' || *s
== 'h' || *s
== 'L')
857 if (isalpha((uschar
)*s
))
858 break; /* the ansi panoply */
861 FATAL("not enough args in printf("
865 snprintf(t
- 1, FMTSZ(t
- 1),
866 "%d", fmtwd
=(int) getfval(x
));
869 adjbuf(&buf
, &bufsize
, fmtwd
+1+p
-buf
, recsize
, &p
, "format");
870 t
= fmt
+ strlen(fmt
);
877 adjbuf(&buf
, &bufsize
, fmtwd
+1+p
-buf
, recsize
, &p
, "format4");
880 case 'f': case 'e': case 'g': case 'E': case 'G':
885 if(*(s
-1) == 'l') break;
890 case 'o': case 'x': case 'X': case 'u':
891 flag
= *(s
-1) == 'l' ? 'd' : 'u';
904 WARNING("weird printf conversion %s", fmt
);
909 FATAL("not enough args in printf(%s)", os
);
915 adjbuf(&buf
, &bufsize
, 1+n
+p
-buf
, recsize
, &p
, "format5");
917 case '?': snprintf(p
, BUFSZ(p
), "%s", fmt
); /* unknown, so dump it too */
922 adjbuf(&buf
, &bufsize
, 1+strlen(p
)+n
+p
-buf
, recsize
, &p
, "format6");
924 snprintf(p
, BUFSZ(p
), "%s", t
);
926 case 'f': snprintf(p
, BUFSZ(p
), fmt
, getfval(x
)); break;
927 case 'd': snprintf(p
, BUFSZ(p
), fmt
, (intmax_t) getfval(x
)); break;
928 case 'u': snprintf(p
, BUFSZ(p
), fmt
, (uintmax_t) getfval(x
)); break;
934 if (!adjbuf(&buf
, &bufsize
, 1+n
+p
-buf
, recsize
, &p
, "format7"))
935 FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n
, t
);
936 snprintf(p
, BUFSZ(p
), fmt
, t
);
941 snprintf(p
, BUFSZ(p
), fmt
, (int) getfval(x
));
943 *p
++ = '\0'; /* explicit null byte */
944 *p
= '\0'; /* next output will start here */
947 snprintf(p
, BUFSZ(p
), fmt
, getsval(x
)[0]);
950 FATAL("can't happen: bad conversion %c in format()", flag
);
958 for ( ; a
; a
= a
->nnext
) /* evaluate any remaining args */
965 Cell
*awksprintf(Node
**a
, int n
) /* sprintf(a[0]) */
972 if ((buf
= malloc(bufsz
)) == NULL
)
973 FATAL("out of memory in awksprintf");
976 if (format(&buf
, &bufsz
, getsval(x
), y
) == -1)
977 FATAL("sprintf string %.30s... too long. can't happen.", buf
);
985 Cell
*awkprintf(Node
**a
, int n
) /* printf */
986 { /* a[0] is list of args, starting with format string */
987 /* a[1] is redirection operator, a[2] is redirection file */
995 if ((buf
= malloc(bufsz
)) == NULL
)
996 FATAL("out of memory in awkprintf");
999 if ((len
= format(&buf
, &bufsz
, getsval(x
), y
)) == -1)
1000 FATAL("printf string %.30s... too long. can't happen.", buf
);
1003 /* fputs(buf, stdout); */
1004 fwrite(buf
, len
, 1, stdout
);
1006 FATAL("write error on stdout");
1008 fp
= redirect(ptoi(a
[1]), a
[2]);
1009 /* fputs(buf, fp); */
1010 fwrite(buf
, len
, 1, fp
);
1013 FATAL("write error on %s", filename(fp
));
1019 Cell
*arith(Node
**a
, int n
) /* a[0] + a[1], etc. also -a[0] */
1046 FATAL("division by zero");
1051 FATAL("division by zero in mod");
1059 if (j
>= 0 && modf(j
, &v
) == 0.0) /* pos integer exponent */
1060 i
= ipow(i
, (int) j
);
1062 i
= errcheck(pow(i
, j
), "pow");
1064 default: /* can't happen */
1065 FATAL("illegal arithmetic operator %d", n
);
1071 double ipow(double x
, int n
) /* x**n. ought to be done by pow, but isn't always */
1084 Cell
*incrdecr(Node
**a
, int n
) /* a[0]++, etc. */
1092 k
= (n
== PREINCR
|| n
== POSTINCR
) ? 1 : -1;
1093 if (n
== PREINCR
|| n
== PREDECR
) {
1104 Cell
*assign(Node
**a
, int n
) /* a[0] = a[1], a[0] += a[1], etc. */
1105 { /* this is subtle; don't muck with it. */
1112 if (n
== ASSIGN
) { /* ordinary assignment */
1113 if (x
== y
&& !(x
->tval
& (FLD
|REC
))) /* self-assignment: */
1114 ; /* leave alone unless it's a field */
1115 else if ((y
->tval
& (STR
|NUM
)) == (STR
|NUM
)) {
1116 setsval(x
, getsval(y
));
1117 x
->fval
= getfval(y
);
1121 setsval(x
, getsval(y
));
1123 setfval(x
, getfval(y
));
1125 funnyvar(y
, "read value of");
1143 FATAL("division by zero in /=");
1148 FATAL("division by zero in %%=");
1153 if (yf
>= 0 && modf(yf
, &v
) == 0.0) /* pos integer exponent */
1154 xf
= ipow(xf
, (int) yf
);
1156 xf
= errcheck(pow(xf
, yf
), "pow");
1159 FATAL("illegal assignment operator %d", n
);
1167 Cell
*cat(Node
**a
, int q
) /* a[0] cat a[1] */
1177 n1
= strlen(x
->sval
);
1178 n2
= strlen(y
->sval
);
1179 s
= malloc(n1
+ n2
+ 1);
1181 FATAL("out of space concatenating %.15s... and %.15s...",
1184 strcpy(s
+n1
, y
->sval
);
1193 Cell
*pastat(Node
**a
, int n
) /* a[0] { a[1] } */
1209 Cell
*dopa2(Node
**a
, int n
) /* a[0], a[1] { a[2] } */
1215 if (pairstack
[pair
] == 0) {
1218 pairstack
[pair
] = 1;
1221 if (pairstack
[pair
] == 1) {
1224 pairstack
[pair
] = 0;
1232 static char regexpr
[] = "(regexpr)";
1233 Cell
*split(Node
**a
, int nnn
) /* split(a[0], a[1], a[2]); a[3] is type */
1235 Cell
*x
= 0, *y
, *ap
;
1238 char *t
, temp
, num
[50], *fs
= 0;
1239 int n
, tempstat
, arg3type
;
1241 y
= execute(a
[0]); /* source string */
1242 origs
= s
= strdup(getsval(y
));
1243 arg3type
= ptoi(a
[3]);
1244 if (a
[2] == 0) /* fs string */
1246 else if (arg3type
== STRING
) { /* split(str,arr,"string") */
1249 } else if (arg3type
== REGEXPR
)
1250 fs
= regexpr
; /* split(str,arr,/regexpr/) */
1252 FATAL("illegal type of split");
1254 ap
= execute(a
[1]); /* array name */
1256 dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s
, NN(ap
->nval
), fs
) );
1259 ap
->sval
= (char *) makesymtab(NSYMTAB
);
1262 if (arg3type
== REGEXPR
&& strlen((char*)((fa
*)a
[2])->restr
) == 0) {
1263 /* split(s, a, //); have to arrange that it looks like empty sep */
1268 if (*s
!= '\0' && (strlen(fs
) > 1 || arg3type
== REGEXPR
)) { /* reg expr */
1270 if (arg3type
== REGEXPR
) { /* it's ready already */
1273 pfa
= makedfa(fs
, 1);
1275 if (nematch(pfa
,s
)) {
1276 tempstat
= pfa
->initstat
;
1280 snprintf(num
, sizeof(num
), "%d", n
);
1284 setsymtab(num
, s
, atof(s
), STR
|NUM
, (Array
*) ap
->sval
);
1286 setsymtab(num
, s
, 0.0, STR
, (Array
*) ap
->sval
);
1288 s
= patbeg
+ patlen
;
1289 if (*(patbeg
+patlen
-1) == 0 || *s
== 0) {
1291 snprintf(num
, sizeof(num
), "%d", n
);
1292 setsymtab(num
, "", 0.0, STR
, (Array
*) ap
->sval
);
1293 pfa
->initstat
= tempstat
;
1296 } while (nematch(pfa
,s
));
1297 pfa
->initstat
= tempstat
; /* bwk: has to be here to reset */
1298 /* cf gsub and refldbld */
1301 snprintf(num
, sizeof(num
), "%d", n
);
1303 setsymtab(num
, s
, atof(s
), STR
|NUM
, (Array
*) ap
->sval
);
1305 setsymtab(num
, s
, 0.0, STR
, (Array
*) ap
->sval
);
1308 } else if (sep
== ' ') {
1310 while (*s
== ' ' || *s
== '\t' || *s
== '\n')
1318 while (*s
!=' ' && *s
!='\t' && *s
!='\n' && *s
!='\0');
1321 snprintf(num
, sizeof(num
), "%d", n
);
1323 setsymtab(num
, t
, atof(t
), STR
|NUM
, (Array
*) ap
->sval
);
1325 setsymtab(num
, t
, 0.0, STR
, (Array
*) ap
->sval
);
1330 } else if (sep
== 0) { /* new: split(s, a, "") => 1 char/elem */
1331 for (n
= 0; *s
!= 0; s
++) {
1334 snprintf(num
, sizeof(num
), "%d", n
);
1337 if (isdigit((uschar
)buf
[0]))
1338 setsymtab(num
, buf
, atof(buf
), STR
|NUM
, (Array
*) ap
->sval
);
1340 setsymtab(num
, buf
, 0.0, STR
, (Array
*) ap
->sval
);
1342 } else if (*s
!= 0) {
1346 while (*s
!= sep
&& *s
!= '\n' && *s
!= '\0')
1350 snprintf(num
, sizeof(num
), "%d", n
);
1352 setsymtab(num
, t
, atof(t
), STR
|NUM
, (Array
*) ap
->sval
);
1354 setsymtab(num
, t
, 0.0, STR
, (Array
*) ap
->sval
);
1363 if (a
[2] != 0 && arg3type
== STRING
) {
1372 Cell
*condexpr(Node
**a
, int n
) /* a[0] ? a[1] : a[2] */
1387 Cell
*ifstat(Node
**a
, int n
) /* if (a[0]) a[1]; else a[2] */
1395 } else if (a
[2] != 0) {
1402 Cell
*whilestat(Node
**a
, int n
) /* while (a[0]) a[1] */
1416 if (isnext(x
) || isexit(x
) || isret(x
))
1422 Cell
*dostat(Node
**a
, int n
) /* do a[0]; while(a[1]) */
1430 if (isnext(x
) || isexit(x
) || isret(x
))
1440 Cell
*forstat(Node
**a
, int n
) /* for (a[0]; a[1]; a[2]) a[3] */
1449 if (!istrue(x
)) return(x
);
1453 if (isbreak(x
)) /* turn off break */
1455 if (isnext(x
) || isexit(x
) || isret(x
))
1463 Cell
*instat(Node
**a
, int n
) /* for (a[0] in a[1]) a[2] */
1465 Cell
*x
, *vp
, *arrayp
, *cp
, *ncp
;
1470 arrayp
= execute(a
[1]);
1471 if (!isarr(arrayp
)) {
1474 tp
= (Array
*) arrayp
->sval
;
1476 for (i
= 0; i
< tp
->size
; i
++) { /* this routine knows too much */
1477 for (cp
= tp
->tab
[i
]; cp
!= NULL
; cp
= ncp
) {
1478 setsval(vp
, cp
->nval
);
1485 if (isnext(x
) || isexit(x
) || isret(x
)) {
1495 void flush_all(void);
1497 static char *nawk_toXXX(const char *s
,
1499 wint_t (*fun_wc
)(wint_t))
1503 const char *ps
= NULL
;
1505 mbstate_t mbs
, mbs2
;
1507 size_t sz
= MB_CUR_MAX
;
1512 for (pbuf
= buf
; *pbuf
; pbuf
++)
1513 *pbuf
= fun_c((uschar
)*pbuf
);
1517 /* upper/lower character may be shorter/longer */
1518 buf
= tostringN(s
, strlen(s
) * sz
+ 1);
1520 memset(&mbs
, 0, sizeof(mbs
));
1521 memset(&mbs2
, 0, sizeof(mbs2
));
1525 while (n
= mbrtowc(&wc
, ps
, sz
, &mbs
),
1526 n
> 0 && n
!= (size_t)-1 && n
!= (size_t)-2)
1530 n
= wcrtomb(pbuf
, fun_wc(wc
), &mbs2
);
1531 if (n
== (size_t)-1)
1532 FATAL("illegal wide character %s", s
);
1540 FATAL("illegal byte sequence %s", s
);
1546 static char *nawk_toupper(const char *s
)
1548 return nawk_toXXX(s
, toupper
, towupper
);
1551 static char *nawk_tolower(const char *s
)
1553 return nawk_toXXX(s
, tolower
, towlower
);
1556 Cell
*bltin(Node
**a
, int n
) /* builtin functions. a[0] is type, a[1] is arg list */
1570 nextarg
= a
[1]->nnext
;
1574 u
= ((Array
*) x
->sval
)->nelem
; /* GROT. should be function*/
1576 u
= strlen(getsval(x
));
1579 u
= errcheck(log(getfval(x
)), "log"); break;
1581 modf(getfval(x
), &u
); break;
1583 u
= errcheck(exp(getfval(x
)), "exp"); break;
1585 u
= errcheck(sqrt(getfval(x
)), "sqrt"); break;
1587 u
= sin(getfval(x
)); break;
1589 u
= cos(getfval(x
)); break;
1592 WARNING("atan2 requires two arguments; returning 1.0");
1595 y
= execute(a
[1]->nnext
);
1596 u
= atan2(getfval(x
), getfval(y
));
1598 nextarg
= nextarg
->nnext
;
1602 fflush(stdout
); /* in case something is buffered already */
1603 u
= (Awkfloat
) system(getsval(x
)) / 256; /* 256 is unix-dep */
1606 /* in principle, rand() returns something in 0..RAND_MAX */
1607 u
= (Awkfloat
) (rand() % RAND_MAX
) / RAND_MAX
;
1610 if (isrec(x
)) /* no argument provided */
1611 u
= time((time_t *)0);
1614 tmp
= (unsigned int) u
;
1622 buf
= nawk_toupper(getsval(x
));
1624 buf
= nawk_tolower(getsval(x
));
1631 if (isrec(x
) || strlen(getsval(x
)) == 0) {
1632 flush_all(); /* fflush() or fflush("") -> all */
1634 } else if ((fp
= openfile(FFLUSH
, getsval(x
), NULL
)) == NULL
)
1640 u
= time((time_t *) 0); break;
1642 /* strftime([format [,timestamp]]) */
1644 y
= execute(nextarg
), nextarg
= nextarg
->nnext
;
1645 tv
= (time_t) getfval(y
);
1648 tv
= time((time_t *) 0);
1649 tm
= localtime(&tv
);
1651 FATAL("bad time %jd", (intmax_t)tv
);
1654 /* format argument not provided, use default */
1655 fmt
= tostring("%a %b %d %H:%M:%S %Z %Y");
1657 fmt
= tostring(getsval(x
));
1659 sz
= 32, buf
= NULL
;
1661 if ((buf
= realloc(buf
, (sz
*= 2))) == NULL
)
1662 FATAL("out of memory in strftime");
1663 } while(strftime(buf
, sz
, fmt
, tm
) == 0);
1671 default: /* can't happen */
1672 FATAL("illegal function type %d", t
);
1679 WARNING("warning: function has too many arguments");
1680 for ( ; nextarg
; nextarg
= nextarg
->nnext
)
1686 Cell
*printstat(Node
**a
, int n
) /* print a[0] */
1692 if (a
[1] == 0) /* a[1] is redirection operator, a[2] is file */
1695 fp
= redirect(ptoi(a
[1]), a
[2]);
1696 for (x
= a
[0]; x
!= NULL
; x
= x
->nnext
) {
1698 fputs(getpssval(y
), fp
);
1700 if (x
->nnext
== NULL
)
1708 FATAL("write error on %s", filename(fp
));
1712 Cell
*nullproc(Node
**a
, int n
)
1720 FILE *redirect(int a
, Node
*b
) /* set up all i/o redirections */
1728 fp
= openfile(a
, fname
, NULL
);
1730 FATAL("can't open file %s", fname
);
1738 int mode
; /* '|', 'a', 'w' => LE/LT, GT */
1743 void stdinit(void) /* in case stdin, etc., are not constants */
1746 files
= calloc(nfiles
, sizeof(*files
));
1748 FATAL("can't allocate file memory for %zu files", nfiles
);
1749 files
[0].fp
= stdin
;
1750 files
[0].fname
= "/dev/stdin";
1752 files
[1].fp
= stdout
;
1753 files
[1].fname
= "/dev/stdout";
1755 files
[2].fp
= stderr
;
1756 files
[2].fname
= "/dev/stderr";
1760 FILE *openfile(int a
, const char *us
, int *pnewflag
)
1768 FATAL("null file name in print or getline");
1769 for (i
= 0; i
< nfiles
; i
++)
1770 if (files
[i
].fname
&& strcmp(s
, files
[i
].fname
) == 0 &&
1771 (a
== files
[i
].mode
|| (a
==APPEND
&& files
[i
].mode
==GT
) ||
1777 if (a
== FFLUSH
) /* didn't find it, so don't create it! */
1780 for (i
= 0; i
< nfiles
; i
++)
1781 if (files
[i
].fp
== NULL
)
1785 size_t nnf
= nfiles
+ FOPEN_MAX
;
1786 nf
= realloc(files
, nnf
* sizeof(*nf
));
1788 FATAL("cannot grow files for %s and %zu files", s
, nnf
);
1789 (void)memset(&nf
[nfiles
], 0, FOPEN_MAX
* sizeof(*nf
));
1793 fflush(stdout
); /* force a semblance of order */
1797 } else if (a
== APPEND
) {
1799 m
= GT
; /* so can mix > and >> */
1800 } else if (a
== '|') { /* output pipe */
1802 } else if (a
== LE
) { /* input pipe */
1804 } else if (a
== LT
) { /* getline <file */
1805 fp
= strcmp(s
, "-") == 0 ? stdin
: fopen(s
, "r"); /* "-" is stdin */
1806 } else /* can't happen */
1807 FATAL("illegal redirection %d", a
);
1809 files
[i
].fname
= tostring(s
);
1818 const char *filename(FILE *fp
)
1822 for (i
= 0; i
< nfiles
; i
++)
1823 if (fp
== files
[i
].fp
)
1824 return files
[i
].fname
;
1828 Cell
*closefile(Node
**a
, int n
)
1838 for (i
= 0; i
< nfiles
; i
++) {
1839 if (files
[i
].fname
&& strcmp(x
->sval
, files
[i
].fname
) == 0) {
1840 if (ferror(files
[i
].fp
))
1841 WARNING( "i/o error occurred on %s", files
[i
].fname
);
1842 if (files
[i
].mode
== '|' || files
[i
].mode
== LE
)
1843 stat
= pclose(files
[i
].fp
) == -1;
1845 stat
= fclose(files
[i
].fp
) == EOF
;
1848 WARNING( "i/o error occurred closing %s",
1851 if (i
> 2) /* don't do /dev/std... */
1852 free(__UNCONST(files
[i
].fname
));
1853 files
[i
].fname
= NULL
; /* watch out for ref thru this */
1859 setfval(x
, (Awkfloat
) stat
);
1868 for (i
= 0; i
< nfiles
; i
++) {
1870 if (ferror(files
[i
].fp
))
1871 WARNING( "i/o error occurred on %s", files
[i
].fname
);
1873 stat
= fpurge(files
[i
].fp
) == EOF
;
1875 stat
= fflush(files
[i
].fp
) == EOF
;
1876 else if (files
[i
].mode
== '|' || files
[i
].mode
== LE
)
1877 stat
= pclose(files
[i
].fp
) == -1;
1879 stat
= fclose(files
[i
].fp
) == EOF
;
1881 WARNING( "i/o error occurred while closing %s", files
[i
].fname
);
1886 void flush_all(void)
1890 for (i
= 0; i
< nfiles
; i
++)
1892 fflush(files
[i
].fp
);
1895 void backsub(uschar
**pb_ptr
, const uschar
**sptr_ptr
);
1897 Cell
*sub(Node
**a
, int nnn
) /* substitute command */
1901 Cell
*x
, *y
, *result
;
1902 uschar
*t
, *buf
, *pb
;
1904 int bufsz
= recsize
;
1906 if ((buf
= malloc(bufsz
)) == NULL
)
1907 FATAL("out of memory in sub");
1908 x
= execute(a
[3]); /* target string */
1910 if (a
[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1911 pfa
= (fa
*) a
[1]; /* regular expression */
1914 pfa
= makedfa(getsval(y
), 1);
1917 y
= execute(a
[2]); /* replacement string */
1919 if (pmatch(pfa
, t
)) {
1921 adjbuf(&buf
, &bufsz
, 1+patbeg
-sptr
, recsize
, 0, "sub");
1923 while (sptr
< patbeg
)
1926 while (*sptr
!= 0) {
1927 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "sub");
1928 if (*sptr
== '\\') {
1929 backsub(&pb
, &sptr
);
1930 } else if (*sptr
== '&') {
1932 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "sub");
1933 for (q
= patbeg
; q
< patbeg
+patlen
; )
1939 if (pb
> buf
+ bufsz
)
1940 FATAL("sub result1 %.30s too big; can't happen", buf
);
1941 sptr
= patbeg
+ patlen
;
1942 if ((patlen
== 0 && *patbeg
) || (patlen
&& *(sptr
-1))) {
1943 adjbuf(&buf
, &bufsz
, 1+strlen(sptr
)+pb
-buf
, 0, &pb
, "sub");
1944 while ((*pb
++ = *sptr
++) != 0)
1947 if (pb
> buf
+ bufsz
)
1948 FATAL("sub result2 %.30s too big; can't happen", buf
);
1949 setsval(x
, buf
); /* BUG: should be able to avoid copy */
1958 Cell
*gsub(Node
**a
, int nnn
) /* global substitute */
1966 int mflag
, tempstat
, num
;
1967 int bufsz
= recsize
;
1969 if ((buf
= malloc(bufsz
)) == NULL
)
1970 FATAL("out of memory in gsub");
1971 mflag
= 0; /* if mflag == 0, can replace empty string */
1973 x
= execute(a
[3]); /* target string */
1975 if (a
[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1976 pfa
= (fa
*) a
[1]; /* regular expression */
1979 pfa
= makedfa(getsval(y
), 1);
1982 y
= execute(a
[2]); /* replacement string */
1983 if (pmatch(pfa
, t
)) {
1984 tempstat
= pfa
->initstat
;
1989 if (patlen
== 0 && *patbeg
!= 0) { /* matched empty string */
1990 if (mflag
== 0) { /* can replace empty */
1993 while (*sptr
!= 0) {
1994 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "gsub");
1995 if (*sptr
== '\\') {
1996 backsub(&pb
, &sptr
);
1997 } else if (*sptr
== '&') {
1999 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "gsub");
2000 for (q
= patbeg
; q
< patbeg
+patlen
; )
2006 if (*t
== 0) /* at end */
2008 adjbuf(&buf
, &bufsz
, 2+pb
-buf
, recsize
, &pb
, "gsub");
2010 if (pb
> buf
+ bufsz
) /* BUG: not sure of this test */
2011 FATAL("gsub result0 %.30s too big; can't happen", buf
);
2014 else { /* matched nonempty string */
2017 adjbuf(&buf
, &bufsz
, 1+(patbeg
-sptr
)+pb
-buf
, recsize
, &pb
, "gsub");
2018 while (sptr
< patbeg
)
2021 while (*sptr
!= 0) {
2022 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "gsub");
2023 if (*sptr
== '\\') {
2024 backsub(&pb
, &sptr
);
2025 } else if (*sptr
== '&') {
2027 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "gsub");
2028 for (q
= patbeg
; q
< patbeg
+patlen
; )
2033 t
= patbeg
+ patlen
;
2034 if (patlen
== 0 || *t
== 0 || *(t
-1) == 0)
2036 if (pb
> buf
+ bufsz
)
2037 FATAL("gsub result1 %.30s too big; can't happen", buf
);
2040 } while (pmatch(pfa
,t
));
2042 adjbuf(&buf
, &bufsz
, 1+strlen(sptr
)+pb
-buf
, 0, &pb
, "gsub");
2043 while ((*pb
++ = *sptr
++) != 0)
2045 done
: if (pb
< buf
+ bufsz
)
2047 else if (*(pb
-1) != '\0')
2048 FATAL("gsub result2 %.30s truncated; can't happen", buf
);
2049 setsval(x
, buf
); /* BUG: should be able to avoid copy + free */
2050 pfa
->initstat
= tempstat
;
2061 Cell
*gensub(Node
**a
, int nnn
) /* global selective substitute */
2062 /* XXX incomplete - doesn't support backreferences \0 ... \9 */
2064 Cell
*x
, *y
, *res
, *h
;
2067 uschar
*q
, *pb
, *t
, *buf
;
2069 int mflag
, tempstat
, num
, whichm
;
2070 int bufsz
= recsize
;
2072 if ((buf
= malloc(bufsz
)) == NULL
)
2073 FATAL("out of memory in gensub");
2074 mflag
= 0; /* if mflag == 0, can replace empty string */
2076 x
= execute(a
[4]); /* source string */
2078 res
= copycell(x
); /* target string - initially copy of source */
2079 res
->csub
= CTEMP
; /* result values are temporary */
2080 if (a
[0] == 0) /* 0 => a[1] is already-compiled regexpr */
2081 pfa
= (fa
*) a
[1]; /* regular expression */
2084 pfa
= makedfa(getsval(y
), 1);
2087 y
= execute(a
[2]); /* replacement string */
2088 h
= execute(a
[3]); /* which matches should be replaced */
2090 if (sptr
[0] == 'g' || sptr
[0] == 'G')
2094 * The specified number is index of replacement, starting
2095 * from 1. GNU awk treats index lower than 0 same as
2096 * 1, we do same for compatibility.
2098 whichm
= (int) getfval(h
) - 1;
2104 if (pmatch(pfa
, t
)) {
2107 tempstat
= pfa
->initstat
;
2112 * XXX if there are any backreferences in subst string,
2115 for(sl
=rptr
; (sl
= strchr(sl
, '\\')) && sl
[1]; sl
++) {
2116 if (strchr("0123456789", sl
[1])) {
2117 FATAL("gensub doesn't support backreferences (subst \"%s\")", rptr
);
2122 if (whichm
>= 0 && whichm
!= num
) {
2124 adjbuf(&buf
, &bufsz
, (pb
- buf
) + (patbeg
- t
) + patlen
, recsize
, &pb
, "gensub");
2126 /* copy the part of string up to and including
2127 * match to output buffer */
2128 while (t
< patbeg
+ patlen
)
2133 if (patlen
== 0 && *patbeg
!= 0) { /* matched empty string */
2134 if (mflag
== 0) { /* can replace empty */
2137 while (*sptr
!= 0) {
2138 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "gensub");
2139 if (*sptr
== '\\') {
2140 backsub(&pb
, &sptr
);
2141 } else if (*sptr
== '&') {
2143 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "gensub");
2144 for (q
= patbeg
; q
< patbeg
+patlen
; )
2150 if (*t
== 0) /* at end */
2152 adjbuf(&buf
, &bufsz
, 2+pb
-buf
, recsize
, &pb
, "gensub");
2154 if (pb
> buf
+ bufsz
) /* BUG: not sure of this test */
2155 FATAL("gensub result0 %.30s too big; can't happen", buf
);
2158 else { /* matched nonempty string */
2161 adjbuf(&buf
, &bufsz
, 1+(patbeg
-sptr
)+pb
-buf
, recsize
, &pb
, "gensub");
2162 while (sptr
< patbeg
)
2165 while (*sptr
!= 0) {
2166 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "gensub");
2167 if (*sptr
== '\\') {
2168 backsub(&pb
, &sptr
);
2169 } else if (*sptr
== '&') {
2171 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "gensub");
2172 for (q
= patbeg
; q
< patbeg
+patlen
; )
2177 t
= patbeg
+ patlen
;
2178 if (patlen
== 0 || *t
== 0 || *(t
-1) == 0)
2180 if (pb
> buf
+ bufsz
)
2181 FATAL("gensub result1 %.30s too big; can't happen", buf
);
2184 } while (pmatch(pfa
,t
));
2186 adjbuf(&buf
, &bufsz
, 1+strlen(sptr
)+pb
-buf
, 0, &pb
, "gensub");
2187 while ((*pb
++ = *sptr
++) != 0)
2189 done
: if (pb
> buf
+ bufsz
)
2190 FATAL("gensub result2 %.30s too big; can't happen", buf
);
2193 pfa
->initstat
= tempstat
;
2201 void backsub(uschar
**pb_ptr
, const uschar
**sptr_ptr
)/* handle \\& variations */
2202 { /* sptr[0] == '\\' */
2203 uschar
*pb
= *pb_ptr
;
2204 const uschar
*sptr
= *sptr_ptr
;
2206 if (sptr
[1] == '\\') {
2207 if (sptr
[2] == '\\' && sptr
[3] == '&') { /* \\\& -> \& */
2211 } else if (sptr
[2] == '&') { /* \\& -> \ + matched */
2214 } else { /* \\x -> \\x */
2218 } else if (sptr
[1] == '&') { /* literal & */
2221 } else /* literal \ */