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 */
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 (*s
!= '\0' && (strlen(fs
) > 1 || arg3type
== REGEXPR
)) { /* reg expr */
1264 if (arg3type
== REGEXPR
) { /* it's ready already */
1267 pfa
= makedfa(fs
, 1);
1269 if (nematch(pfa
,s
)) {
1270 tempstat
= pfa
->initstat
;
1274 snprintf(num
, sizeof(num
), "%d", n
);
1278 setsymtab(num
, s
, atof(s
), STR
|NUM
, (Array
*) ap
->sval
);
1280 setsymtab(num
, s
, 0.0, STR
, (Array
*) ap
->sval
);
1282 s
= patbeg
+ patlen
;
1283 if (*(patbeg
+patlen
-1) == 0 || *s
== 0) {
1285 snprintf(num
, sizeof(num
), "%d", n
);
1286 setsymtab(num
, "", 0.0, STR
, (Array
*) ap
->sval
);
1287 pfa
->initstat
= tempstat
;
1290 } while (nematch(pfa
,s
));
1291 pfa
->initstat
= tempstat
; /* bwk: has to be here to reset */
1292 /* cf gsub and refldbld */
1295 snprintf(num
, sizeof(num
), "%d", n
);
1297 setsymtab(num
, s
, atof(s
), STR
|NUM
, (Array
*) ap
->sval
);
1299 setsymtab(num
, s
, 0.0, STR
, (Array
*) ap
->sval
);
1302 } else if (sep
== ' ') {
1304 while (*s
== ' ' || *s
== '\t' || *s
== '\n')
1312 while (*s
!=' ' && *s
!='\t' && *s
!='\n' && *s
!='\0');
1315 snprintf(num
, sizeof(num
), "%d", n
);
1317 setsymtab(num
, t
, atof(t
), STR
|NUM
, (Array
*) ap
->sval
);
1319 setsymtab(num
, t
, 0.0, STR
, (Array
*) ap
->sval
);
1324 } else if (sep
== 0) { /* new: split(s, a, "") => 1 char/elem */
1325 for (n
= 0; *s
!= 0; s
++) {
1328 snprintf(num
, sizeof(num
), "%d", n
);
1331 if (isdigit((uschar
)buf
[0]))
1332 setsymtab(num
, buf
, atof(buf
), STR
|NUM
, (Array
*) ap
->sval
);
1334 setsymtab(num
, buf
, 0.0, STR
, (Array
*) ap
->sval
);
1336 } else if (*s
!= 0) {
1340 while (*s
!= sep
&& *s
!= '\n' && *s
!= '\0')
1344 snprintf(num
, sizeof(num
), "%d", n
);
1346 setsymtab(num
, t
, atof(t
), STR
|NUM
, (Array
*) ap
->sval
);
1348 setsymtab(num
, t
, 0.0, STR
, (Array
*) ap
->sval
);
1356 if (a
[2] != 0 && arg3type
== STRING
) {
1365 Cell
*condexpr(Node
**a
, int n
) /* a[0] ? a[1] : a[2] */
1380 Cell
*ifstat(Node
**a
, int n
) /* if (a[0]) a[1]; else a[2] */
1388 } else if (a
[2] != 0) {
1395 Cell
*whilestat(Node
**a
, int n
) /* while (a[0]) a[1] */
1409 if (isnext(x
) || isexit(x
) || isret(x
))
1415 Cell
*dostat(Node
**a
, int n
) /* do a[0]; while(a[1]) */
1423 if (isnext(x
) || isexit(x
) || isret(x
))
1433 Cell
*forstat(Node
**a
, int n
) /* for (a[0]; a[1]; a[2]) a[3] */
1442 if (!istrue(x
)) return(x
);
1446 if (isbreak(x
)) /* turn off break */
1448 if (isnext(x
) || isexit(x
) || isret(x
))
1456 Cell
*instat(Node
**a
, int n
) /* for (a[0] in a[1]) a[2] */
1458 Cell
*x
, *vp
, *arrayp
, *cp
, *ncp
;
1463 arrayp
= execute(a
[1]);
1464 if (!isarr(arrayp
)) {
1467 tp
= (Array
*) arrayp
->sval
;
1469 for (i
= 0; i
< tp
->size
; i
++) { /* this routine knows too much */
1470 for (cp
= tp
->tab
[i
]; cp
!= NULL
; cp
= ncp
) {
1471 setsval(vp
, cp
->nval
);
1478 if (isnext(x
) || isexit(x
) || isret(x
)) {
1488 void flush_all(void);
1490 static char *nawk_toXXX(const char *s
,
1492 wint_t (*fun_wc
)(wint_t))
1496 const char *ps
= NULL
;
1498 mbstate_t mbs
, mbs2
;
1500 size_t sz
= MB_CUR_MAX
;
1505 for (pbuf
= buf
; *pbuf
; pbuf
++)
1506 *pbuf
= fun_c((uschar
)*pbuf
);
1510 /* upper/lower character may be shorter/longer */
1511 buf
= tostringN(s
, strlen(s
) * sz
+ 1);
1513 memset(&mbs
, 0, sizeof(mbs
));
1514 memset(&mbs2
, 0, sizeof(mbs2
));
1518 while (n
= mbrtowc(&wc
, ps
, sz
, &mbs
),
1519 n
> 0 && n
!= (size_t)-1 && n
!= (size_t)-2)
1523 n
= wcrtomb(pbuf
, fun_wc(wc
), &mbs2
);
1524 if (n
== (size_t)-1)
1525 FATAL("illegal wide character %s", s
);
1533 FATAL("illegal byte sequence %s", s
);
1539 static char *nawk_toupper(const char *s
)
1541 return nawk_toXXX(s
, toupper
, towupper
);
1544 static char *nawk_tolower(const char *s
)
1546 return nawk_toXXX(s
, tolower
, towlower
);
1549 Cell
*bltin(Node
**a
, int n
) /* builtin functions. a[0] is type, a[1] is arg list */
1563 nextarg
= a
[1]->nnext
;
1567 u
= ((Array
*) x
->sval
)->nelem
; /* GROT. should be function*/
1569 u
= strlen(getsval(x
));
1572 u
= errcheck(log(getfval(x
)), "log"); break;
1574 modf(getfval(x
), &u
); break;
1576 u
= errcheck(exp(getfval(x
)), "exp"); break;
1578 u
= errcheck(sqrt(getfval(x
)), "sqrt"); break;
1580 u
= sin(getfval(x
)); break;
1582 u
= cos(getfval(x
)); break;
1585 WARNING("atan2 requires two arguments; returning 1.0");
1588 y
= execute(a
[1]->nnext
);
1589 u
= atan2(getfval(x
), getfval(y
));
1591 nextarg
= nextarg
->nnext
;
1595 fflush(stdout
); /* in case something is buffered already */
1596 u
= (Awkfloat
) system(getsval(x
)) / 256; /* 256 is unix-dep */
1599 /* in principle, rand() returns something in 0..RAND_MAX */
1600 u
= (Awkfloat
) (rand() % RAND_MAX
) / RAND_MAX
;
1603 if (isrec(x
)) /* no argument provided */
1604 u
= time((time_t *)0);
1607 srand(tmp
= (unsigned int) u
);
1614 buf
= nawk_toupper(getsval(x
));
1616 buf
= nawk_tolower(getsval(x
));
1623 if (isrec(x
) || strlen(getsval(x
)) == 0) {
1624 flush_all(); /* fflush() or fflush("") -> all */
1626 } else if ((fp
= openfile(FFLUSH
, getsval(x
), NULL
)) == NULL
)
1632 u
= time((time_t *) 0); break;
1634 /* strftime([format [,timestamp]]) */
1636 y
= execute(nextarg
), nextarg
= nextarg
->nnext
;
1637 tv
= (time_t) getfval(y
);
1640 tv
= time((time_t *) 0);
1641 tm
= localtime(&tv
);
1644 /* format argument not provided, use default */
1645 fmt
= tostring("%a %b %d %H:%M:%S %Z %Y");
1647 fmt
= tostring(getsval(x
));
1649 sz
= 32, buf
= NULL
;
1651 if ((buf
= realloc(buf
, (sz
*= 2))) == NULL
)
1652 FATAL("out of memory in strftime");
1653 } while(strftime(buf
, sz
, fmt
, tm
) == 0);
1661 default: /* can't happen */
1662 FATAL("illegal function type %d", t
);
1669 WARNING("warning: function has too many arguments");
1670 for ( ; nextarg
; nextarg
= nextarg
->nnext
)
1676 Cell
*printstat(Node
**a
, int n
) /* print a[0] */
1682 if (a
[1] == 0) /* a[1] is redirection operator, a[2] is file */
1685 fp
= redirect(ptoi(a
[1]), a
[2]);
1686 for (x
= a
[0]; x
!= NULL
; x
= x
->nnext
) {
1688 fputs(getpssval(y
), fp
);
1690 if (x
->nnext
== NULL
)
1698 FATAL("write error on %s", filename(fp
));
1702 Cell
*nullproc(Node
**a
, int n
)
1710 FILE *redirect(int a
, Node
*b
) /* set up all i/o redirections */
1718 fp
= openfile(a
, fname
, NULL
);
1720 FATAL("can't open file %s", fname
);
1728 int mode
; /* '|', 'a', 'w' => LE/LT, GT */
1732 void stdinit(void) /* in case stdin, etc., are not constants */
1735 files
= calloc(nfiles
, sizeof(*files
));
1737 FATAL("can't allocate file memory for %zu files", nfiles
);
1738 files
[0].fp
= stdin
;
1739 files
[0].fname
= "/dev/stdin";
1741 files
[1].fp
= stdout
;
1742 files
[1].fname
= "/dev/stdout";
1744 files
[2].fp
= stderr
;
1745 files
[2].fname
= "/dev/stderr";
1749 FILE *openfile(int a
, const char *us
, int *pnewflag
)
1757 FATAL("null file name in print or getline");
1758 for (i
= 0; i
< nfiles
; i
++)
1759 if (files
[i
].fname
&& strcmp(s
, files
[i
].fname
) == 0 &&
1760 (a
== files
[i
].mode
|| (a
==APPEND
&& files
[i
].mode
==GT
) ||
1766 if (a
== FFLUSH
) /* didn't find it, so don't create it! */
1769 for (i
= 0; i
< nfiles
; i
++)
1770 if (files
[i
].fp
== NULL
)
1774 size_t nnf
= nfiles
+ FOPEN_MAX
;
1775 nf
= realloc(files
, nnf
* sizeof(*nf
));
1777 FATAL("cannot grow files for %s and %zu files", s
, nnf
);
1778 (void)memset(&nf
[nfiles
], 0, FOPEN_MAX
* sizeof(*nf
));
1782 fflush(stdout
); /* force a semblance of order */
1786 } else if (a
== APPEND
) {
1788 m
= GT
; /* so can mix > and >> */
1789 } else if (a
== '|') { /* output pipe */
1791 } else if (a
== LE
) { /* input pipe */
1793 } else if (a
== LT
) { /* getline <file */
1794 fp
= strcmp(s
, "-") == 0 ? stdin
: fopen(s
, "r"); /* "-" is stdin */
1795 } else /* can't happen */
1796 FATAL("illegal redirection %d", a
);
1798 files
[i
].fname
= tostring(s
);
1807 const char *filename(FILE *fp
)
1811 for (i
= 0; i
< nfiles
; i
++)
1812 if (fp
== files
[i
].fp
)
1813 return files
[i
].fname
;
1817 Cell
*closefile(Node
**a
, int n
)
1827 for (i
= 0; i
< nfiles
; i
++) {
1828 if (files
[i
].fname
&& strcmp(x
->sval
, files
[i
].fname
) == 0) {
1829 if (ferror(files
[i
].fp
))
1830 WARNING( "i/o error occurred on %s", files
[i
].fname
);
1831 if (files
[i
].mode
== '|' || files
[i
].mode
== LE
)
1832 stat
= pclose(files
[i
].fp
) == -1;
1834 stat
= fclose(files
[i
].fp
) == EOF
;
1837 WARNING( "i/o error occurred closing %s",
1840 if (i
> 2) /* don't do /dev/std... */
1841 free(__UNCONST(files
[i
].fname
));
1842 files
[i
].fname
= NULL
; /* watch out for ref thru this */
1848 setfval(x
, (Awkfloat
) stat
);
1857 for (i
= 0; i
< nfiles
; i
++) {
1859 if (ferror(files
[i
].fp
))
1860 WARNING( "i/o error occurred on %s", files
[i
].fname
);
1862 stat
= fpurge(files
[i
].fp
) == EOF
;
1864 stat
= fflush(files
[i
].fp
) == EOF
;
1865 else if (files
[i
].mode
== '|' || files
[i
].mode
== LE
)
1866 stat
= pclose(files
[i
].fp
) == -1;
1868 stat
= fclose(files
[i
].fp
) == EOF
;
1870 WARNING( "i/o error occurred while closing %s", files
[i
].fname
);
1875 void flush_all(void)
1879 for (i
= 0; i
< nfiles
; i
++)
1881 fflush(files
[i
].fp
);
1884 void backsub(uschar
**pb_ptr
, const uschar
**sptr_ptr
);
1886 Cell
*sub(Node
**a
, int nnn
) /* substitute command */
1890 Cell
*x
, *y
, *result
;
1891 uschar
*t
, *buf
, *pb
;
1893 int bufsz
= recsize
;
1895 if ((buf
= malloc(bufsz
)) == NULL
)
1896 FATAL("out of memory in sub");
1897 x
= execute(a
[3]); /* target string */
1899 if (a
[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1900 pfa
= (fa
*) a
[1]; /* regular expression */
1903 pfa
= makedfa(getsval(y
), 1);
1906 y
= execute(a
[2]); /* replacement string */
1908 if (pmatch(pfa
, t
)) {
1910 adjbuf(&buf
, &bufsz
, 1+patbeg
-sptr
, recsize
, 0, "sub");
1912 while (sptr
< patbeg
)
1915 while (*sptr
!= 0) {
1916 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "sub");
1917 if (*sptr
== '\\') {
1918 backsub(&pb
, &sptr
);
1919 } else if (*sptr
== '&') {
1921 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "sub");
1922 for (q
= patbeg
; q
< patbeg
+patlen
; )
1928 if (pb
> buf
+ bufsz
)
1929 FATAL("sub result1 %.30s too big; can't happen", buf
);
1930 sptr
= patbeg
+ patlen
;
1931 if ((patlen
== 0 && *patbeg
) || (patlen
&& *(sptr
-1))) {
1932 adjbuf(&buf
, &bufsz
, 1+strlen(sptr
)+pb
-buf
, 0, &pb
, "sub");
1933 while ((*pb
++ = *sptr
++) != 0)
1936 if (pb
> buf
+ bufsz
)
1937 FATAL("sub result2 %.30s too big; can't happen", buf
);
1938 setsval(x
, buf
); /* BUG: should be able to avoid copy */
1947 Cell
*gsub(Node
**a
, int nnn
) /* global substitute */
1955 int mflag
, tempstat
, num
;
1956 int bufsz
= recsize
;
1958 if ((buf
= malloc(bufsz
)) == NULL
)
1959 FATAL("out of memory in gsub");
1960 mflag
= 0; /* if mflag == 0, can replace empty string */
1962 x
= execute(a
[3]); /* target string */
1964 if (a
[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1965 pfa
= (fa
*) a
[1]; /* regular expression */
1968 pfa
= makedfa(getsval(y
), 1);
1971 y
= execute(a
[2]); /* replacement string */
1972 if (pmatch(pfa
, t
)) {
1973 tempstat
= pfa
->initstat
;
1978 if (patlen
== 0 && *patbeg
!= 0) { /* matched empty string */
1979 if (mflag
== 0) { /* can replace empty */
1982 while (*sptr
!= 0) {
1983 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "gsub");
1984 if (*sptr
== '\\') {
1985 backsub(&pb
, &sptr
);
1986 } else if (*sptr
== '&') {
1988 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "gsub");
1989 for (q
= patbeg
; q
< patbeg
+patlen
; )
1995 if (*t
== 0) /* at end */
1997 adjbuf(&buf
, &bufsz
, 2+pb
-buf
, recsize
, &pb
, "gsub");
1999 if (pb
> buf
+ bufsz
) /* BUG: not sure of this test */
2000 FATAL("gsub result0 %.30s too big; can't happen", buf
);
2003 else { /* matched nonempty string */
2006 adjbuf(&buf
, &bufsz
, 1+(patbeg
-sptr
)+pb
-buf
, recsize
, &pb
, "gsub");
2007 while (sptr
< patbeg
)
2010 while (*sptr
!= 0) {
2011 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "gsub");
2012 if (*sptr
== '\\') {
2013 backsub(&pb
, &sptr
);
2014 } else if (*sptr
== '&') {
2016 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "gsub");
2017 for (q
= patbeg
; q
< patbeg
+patlen
; )
2022 t
= patbeg
+ patlen
;
2023 if (patlen
== 0 || *t
== 0 || *(t
-1) == 0)
2025 if (pb
> buf
+ bufsz
)
2026 FATAL("gsub result1 %.30s too big; can't happen", buf
);
2029 } while (pmatch(pfa
,t
));
2031 adjbuf(&buf
, &bufsz
, 1+strlen(sptr
)+pb
-buf
, 0, &pb
, "gsub");
2032 while ((*pb
++ = *sptr
++) != 0)
2034 done
: if (pb
< buf
+ bufsz
)
2036 else if (*(pb
-1) != '\0')
2037 FATAL("gsub result2 %.30s truncated; can't happen", buf
);
2038 setsval(x
, buf
); /* BUG: should be able to avoid copy + free */
2039 pfa
->initstat
= tempstat
;
2050 Cell
*gensub(Node
**a
, int nnn
) /* global selective substitute */
2051 /* XXX incomplete - doesn't support backreferences \0 ... \9 */
2053 Cell
*x
, *y
, *res
, *h
;
2056 uschar
*q
, *pb
, *t
, *buf
;
2058 int mflag
, tempstat
, num
, whichm
;
2059 int bufsz
= recsize
;
2061 if ((buf
= malloc(bufsz
)) == NULL
)
2062 FATAL("out of memory in gensub");
2063 mflag
= 0; /* if mflag == 0, can replace empty string */
2065 x
= execute(a
[4]); /* source string */
2067 res
= copycell(x
); /* target string - initially copy of source */
2068 if (a
[0] == 0) /* 0 => a[1] is already-compiled regexpr */
2069 pfa
= (fa
*) a
[1]; /* regular expression */
2072 pfa
= makedfa(getsval(y
), 1);
2075 y
= execute(a
[2]); /* replacement string */
2076 h
= execute(a
[3]); /* which matches should be replaced */
2078 if (sptr
[0] == 'g' || sptr
[0] == 'G')
2082 * The specified number is index of replacement, starting
2083 * from 1. GNU awk treats index lower than 0 same as
2084 * 1, we do same for compatibility.
2086 whichm
= (int) getfval(h
) - 1;
2092 if (pmatch(pfa
, t
)) {
2095 tempstat
= pfa
->initstat
;
2100 * XXX if there are any backreferences in subst string,
2103 for(sl
=rptr
; (sl
= strchr(sl
, '\\')) && sl
[1]; sl
++) {
2104 if (strchr("0123456789", sl
[1])) {
2105 FATAL("gensub doesn't support backreferences (subst \"%s\")", rptr
);
2110 if (whichm
>= 0 && whichm
!= num
) {
2112 adjbuf(&buf
, &bufsz
, (pb
- buf
) + (patbeg
- t
) + patlen
, recsize
, &pb
, "gensub");
2114 /* copy the part of string up to and including
2115 * match to output buffer */
2116 while (t
< patbeg
+ patlen
)
2121 if (patlen
== 0 && *patbeg
!= 0) { /* matched empty string */
2122 if (mflag
== 0) { /* can replace empty */
2125 while (*sptr
!= 0) {
2126 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "gensub");
2127 if (*sptr
== '\\') {
2128 backsub(&pb
, &sptr
);
2129 } else if (*sptr
== '&') {
2131 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "gensub");
2132 for (q
= patbeg
; q
< patbeg
+patlen
; )
2138 if (*t
== 0) /* at end */
2140 adjbuf(&buf
, &bufsz
, 2+pb
-buf
, recsize
, &pb
, "gensub");
2142 if (pb
> buf
+ bufsz
) /* BUG: not sure of this test */
2143 FATAL("gensub result0 %.30s too big; can't happen", buf
);
2146 else { /* matched nonempty string */
2149 adjbuf(&buf
, &bufsz
, 1+(patbeg
-sptr
)+pb
-buf
, recsize
, &pb
, "gensub");
2150 while (sptr
< patbeg
)
2153 while (*sptr
!= 0) {
2154 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "gensub");
2155 if (*sptr
== '\\') {
2156 backsub(&pb
, &sptr
);
2157 } else if (*sptr
== '&') {
2159 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "gensub");
2160 for (q
= patbeg
; q
< patbeg
+patlen
; )
2165 t
= patbeg
+ patlen
;
2166 if (patlen
== 0 || *t
== 0 || *(t
-1) == 0)
2168 if (pb
> buf
+ bufsz
)
2169 FATAL("gensub result1 %.30s too big; can't happen", buf
);
2172 } while (pmatch(pfa
,t
));
2174 adjbuf(&buf
, &bufsz
, 1+strlen(sptr
)+pb
-buf
, 0, &pb
, "gensub");
2175 while ((*pb
++ = *sptr
++) != 0)
2177 done
: if (pb
> buf
+ bufsz
)
2178 FATAL("gensub result2 %.30s too big; can't happen", buf
);
2181 pfa
->initstat
= tempstat
;
2189 void backsub(uschar
**pb_ptr
, const uschar
**sptr_ptr
)/* handle \\& variations */
2190 { /* sptr[0] == '\\' */
2191 uschar
*pb
= *pb_ptr
;
2192 const uschar
*sptr
= *sptr_ptr
;
2194 if (sptr
[1] == '\\') {
2195 if (sptr
[2] == '\\' && sptr
[3] == '&') { /* \\\& -> \& */
2199 } else if (sptr
[2] == '&') { /* \\& -> \ + matched */
2202 } else { /* \\x -> \\x */
2206 } else if (sptr
[1] == '&') { /* literal & */
2209 } else /* literal \ */