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"
43 #define tempfree(x) if (istemp(x)) tfree(x); else
50 void tempfree(Cell *p) {
51 if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) {
52 WARNING("bad csub %d in Cell %d %s",
53 p->csub, p->ctype, p->sval);
60 /* do we really need these? */
62 /* #ifndef FOPEN_MAX */
63 /* #define FOPEN_MAX _NFILE */
67 /* #ifndef FOPEN_MAX */
68 /* #define FOPEN_MAX 40 */ /* max number of open files */
71 /* #ifndef RAND_MAX */
72 /* #define RAND_MAX 32767 */ /* all that ansi guarantees */
76 extern int pairstack
[];
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
};
82 Cell
*True
= &truecell
;
83 static Cell falsecell
={ OBOOL
, BFALSE
, 0, 0, 0.0, NUM
};
84 Cell
*False
= &falsecell
;
85 static Cell breakcell
={ OJUMP
, JBREAK
, 0, 0, 0.0, NUM
};
86 Cell
*jbreak
= &breakcell
;
87 static Cell contcell
={ OJUMP
, JCONT
, 0, 0, 0.0, NUM
};
88 Cell
*jcont
= &contcell
;
89 static Cell nextcell
={ OJUMP
, JNEXT
, 0, 0, 0.0, NUM
};
90 Cell
*jnext
= &nextcell
;
91 static Cell nextfilecell
={ OJUMP
, JNEXTFILE
, 0, 0, 0.0, NUM
};
92 Cell
*jnextfile
= &nextfilecell
;
93 static Cell exitcell
={ OJUMP
, JEXIT
, 0, 0, 0.0, NUM
};
94 Cell
*jexit
= &exitcell
;
95 static Cell retcell
={ OJUMP
, JRET
, 0, 0, 0.0, NUM
};
96 Cell
*jret
= &retcell
;
97 static Cell tempcell
={ OCELL
, CTEMP
, 0, "", 0.0, NUM
|STR
|DONTFREE
};
99 Node
*curnode
= NULL
; /* the node being executed, for debugging */
101 /* buffer memory management */
102 int adjbuf(uschar
**pbuf
, int *psiz
, int minlen
, int quantum
, uschar
**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
, *pbuf
, tbuf
) );
125 FATAL("out of memory in %s", whatrtn
);
131 *pbptr
= tbuf
+ boff
;
136 void run(Node
*a
) /* execution of parse tree starts here */
143 Cell
*execute(Node
*u
) /* execute a node of the parse tree */
145 Cell
*(*proc
)(Node
**, int);
151 for (a
= u
; ; a
= a
->nnext
) {
154 x
= (Cell
*) (a
->narg
[0]);
155 if (isfld(x
) && !donefld
)
157 else if (isrec(x
) && !donerec
)
161 if (notlegal(a
->nobj
)) /* probably a Cell* but too risky to print */
162 FATAL("illegal statement");
163 proc
= proctab
[a
->nobj
-FIRSTTOKEN
];
164 x
= (*proc
)(a
->narg
, a
->nobj
);
165 if (isfld(x
) && !donefld
)
167 else if (isrec(x
) && !donerec
)
173 if (a
->nnext
== NULL
)
180 Cell
*program(Node
**a
, int n
) /* execute an awk program */
181 { /* a[0] = BEGIN, a[1] = body, a[2] = END */
184 if (setjmp(env
) != 0)
186 if (a
[0]) { /* BEGIN */
191 FATAL("illegal break, continue, next or nextfile from BEGIN");
195 while (getrec(&record
, &recsize
, 1) > 0) {
202 if (setjmp(env
) != 0) /* handles exit within END */
204 if (a
[2]) { /* END */
206 if (isbreak(x
) || isnext(x
) || iscont(x
))
207 FATAL("illegal break, continue, next or nextfile from END");
214 struct Frame
{ /* stack frame for awk function calls */
215 int nargs
; /* number of arguments in this call */
216 Cell
*fcncell
; /* pointer to Cell for function */
217 Cell
**args
; /* pointer to array of arguments after execute */
218 Cell
*retval
; /* return value */
221 #define NARGS 50 /* max args in a call */
223 struct Frame
*frame
= NULL
; /* base of stack frames; dynamically allocated */
224 int nframe
= 0; /* number of frames allocated */
225 struct Frame
*fp
= NULL
; /* frame pointer. bottom level unused */
227 Cell
*call(Node
**a
, int n
) /* function call. very kludgy and fragile */
229 static const Cell newcopycell
= { OCELL
, CCOPY
, 0, "", 0.0, NUM
|STR
|DONTFREE
};
231 int freed
= 0; /* handles potential double freeing when fcn & param share a tempcell */
233 Cell
*args
[NARGS
], *oargs
[NARGS
]; /* BUG: fixed size arrays */
237 fcn
= execute(a
[0]); /* the function itself */
240 FATAL("calling undefined function %s", s
);
242 fp
= frame
= (struct Frame
*) calloc(nframe
+= 100, sizeof(struct Frame
));
244 FATAL("out of space for stack frames calling %s", s
);
246 for (ncall
= 0, x
= a
[1]; x
!= NULL
; x
= x
->nnext
) /* args in call */
248 ndef
= (int) fcn
->fval
; /* args in defn */
249 dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s
, ncall
, ndef
, (int) (fp
-frame
)) );
251 WARNING("function %s called with %d args, uses only %d",
253 if (ncall
+ ndef
> NARGS
)
254 FATAL("function %s has %d arguments, limit %d", s
, ncall
+ndef
, NARGS
);
255 for (i
= 0, x
= a
[1]; x
!= NULL
; i
++, x
= x
->nnext
) { /* get call args */
256 dprintf( ("evaluate args[%d], fp=%d:\n", i
, (int) (fp
-frame
)) );
259 dprintf( ("args[%d]: %s %f <%s>, t=%o\n",
260 i
, NN(y
->nval
), y
->fval
, isarr(y
) ? "(array)" : NN(y
->sval
), y
->tval
) );
262 FATAL("can't use function %s as argument in %s", y
->nval
, s
);
264 args
[i
] = y
; /* arrays by ref */
266 args
[i
] = copycell(y
);
269 for ( ; i
< ndef
; i
++) { /* add null args for ones not provided */
271 *args
[i
] = newcopycell
;
273 fp
++; /* now ok to up frame */
274 if (fp
>= frame
+ nframe
) {
275 int dfp
= fp
- frame
; /* old index */
276 frame
= (struct Frame
*)
277 realloc((char *) frame
, (nframe
+= 100) * sizeof(struct Frame
));
279 FATAL("out of space for stack frames in %s", s
);
284 fp
->nargs
= ndef
; /* number defined with (excess are locals) */
285 fp
->retval
= gettemp();
287 dprintf( ("start exec of %s, fp=%d\n", s
, (int) (fp
-frame
)) );
288 y
= execute((Node
*)(fcn
->sval
)); /* execute body */
289 dprintf( ("finished exec of %s, fp=%d\n", s
, (int) (fp
-frame
)) );
291 for (i
= 0; i
< ndef
; i
++) {
292 Cell
*t
= fp
->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
= fp
->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), fp->nargs=%d\n", n
, fp
->nargs
) );
352 FATAL("argument #%d of function %s was not supplied",
353 n
+1, fp
->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(fp
->retval
, getsval(y
));
374 fp
->retval
->fval
= getfval(y
);
375 fp
->retval
->tval
|= NUM
;
377 else if (y
->tval
& STR
)
378 setsval(fp
->retval
, getsval(y
));
379 else if (y
->tval
& NUM
)
380 setfval(fp
->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
*get_line(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
;
410 if ((buf
= (char *) malloc(bufsize
)) == NULL
)
411 FATAL("out of memory in get_line");
413 fflush(stdout
); /* in case someone is waiting for a prompt */
415 if (a
[1] != NULL
) { /* get_line < file */
416 x
= execute(a
[2]); /* filename */
418 if (mode
== '|') /* input pipe */
419 mode
= LE
; /* arbitrary flag */
420 fp
= openfile(mode
, getsval(x
));
425 n
= readrec(&buf
, &bufsize
, fp
);
428 } else if (a
[0] != NULL
) { /* get_line var <file */
432 } else { /* get_line <file */
433 setsval(fldtab
[0], buf
);
434 if (is_number(fldtab
[0]->sval
)) {
435 fldtab
[0]->fval
= atof(fldtab
[0]->sval
);
436 fldtab
[0]->tval
|= NUM
;
439 } else { /* bare get_line; use current input */
440 if (a
[0] == NULL
) /* get_line */
441 n
= getrec(&record
, &recsize
, 1);
442 else { /* get_line var */
443 n
= getrec(&buf
, &bufsize
, 0);
449 setfval(r
, (Awkfloat
) n
);
454 Cell
*getnf(Node
**a
, int n
) /* get NF */
458 return (Cell
*) a
[0];
461 Cell
*array(Node
**a
, int n
) /* a[0] is symtab, a[1] is list of subscripts */
468 int nsub
= strlen(*SUBSEP
);
470 if ((buf
= (char *) malloc(bufsz
)) == NULL
)
471 FATAL("out of memory in array");
473 x
= execute(a
[0]); /* Cell* for symbol table */
475 for (np
= a
[1]; np
; np
= np
->nnext
) {
476 y
= execute(np
); /* subscript */
478 if (!adjbuf(&buf
, &bufsz
, strlen(buf
)+strlen(s
)+nsub
+1, recsize
, 0, "array"))
479 FATAL("out of memory for %s[%s...]", x
->nval
, buf
);
480 strlcat(buf
, s
, bufsz
);
482 strlcat(buf
, *SUBSEP
, bufsz
);
486 dprintf( ("making %s into an array\n", NN(x
->nval
)) );
489 x
->tval
&= ~(STR
|NUM
|DONTFREE
);
491 x
->sval
= (char *) makesymtab(NSYMTAB
);
493 z
= setsymtab(buf
, "", 0.0, STR
|NUM
, (Array
*) x
->sval
);
501 Cell
*awkdelete(Node
**a
, int n
) /* a[0] is symtab, a[1] is list of subscripts */
506 int nsub
= strlen(*SUBSEP
);
508 x
= execute(a
[0]); /* Cell* for symbol table */
511 if (a
[1] == 0) { /* delete the elements, not the table */
515 x
->sval
= (char *) makesymtab(NSYMTAB
);
519 if ((buf
= malloc(bufsz
)) == NULL
)
520 FATAL("out of memory in adelete");
522 for (np
= a
[1]; np
; np
= np
->nnext
) {
523 y
= execute(np
); /* subscript */
525 if (!adjbuf(&buf
, &bufsz
, strlen(buf
)+strlen(s
)+nsub
+1, recsize
, 0, "awkdelete"))
526 FATAL("out of memory deleting %s[%s...]", x
->nval
, buf
);
527 strlcat(buf
, s
, bufsz
);
529 strlcat(buf
, *SUBSEP
, bufsz
);
539 Cell
*intest(Node
**a
, int n
) /* a[0] is index (list), a[1] is symtab */
546 int nsub
= strlen(*SUBSEP
);
548 ap
= execute(a
[1]); /* array name */
550 dprintf( ("making %s into an array\n", ap
->nval
) );
553 ap
->tval
&= ~(STR
|NUM
|DONTFREE
);
555 ap
->sval
= (char *) makesymtab(NSYMTAB
);
557 if ((buf
= malloc(bufsz
)) == NULL
) {
558 FATAL("out of memory in intest");
561 for (p
= a
[0]; p
; p
= p
->nnext
) {
562 x
= execute(p
); /* expr */
564 if (!adjbuf(&buf
, &bufsz
, strlen(buf
)+strlen(s
)+nsub
+1, recsize
, 0, "intest"))
565 FATAL("out of memory deleting %s[%s...]", x
->nval
, buf
);
569 strcat(buf
, *SUBSEP
);
571 k
= lookup(buf
, (Array
*) ap
->sval
);
581 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] == 0) /* 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(Cell
));
709 FATAL("out of space for temporaries");
710 for(i
= 1; i
< 100; i
++)
711 tmps
[i
-1].cnext
= &tmps
[i
];
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
))) /* 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]) */
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 */
824 int fmtwd
; /* format width */
827 int bufsize
= *pbufsize
;
828 #define FMTSZ(a) (fmtsz - ((a) - fmt))
829 #define BUFSZ(a) (bufsize - ((a) - buf))
833 if ((fmt
= (char *) malloc(fmtsz
)) == NULL
)
834 FATAL("out of memory in format()");
836 adjbuf(&buf
, &bufsize
, MAXNUMSIZE
+1+p
-buf
, recsize
, &p
, "format1");
846 /* have to be real careful in case this is a huge number, eg, %100000d */
850 adjbuf(&buf
, &bufsize
, fmtwd
+1+p
-buf
, recsize
, &p
, "format2");
851 for (t
= fmt
; (*t
++ = *s
) != '\0'; s
++) {
852 if (!adjbuf(&fmt
, &fmtsz
, MAXNUMSIZE
+1+t
-fmt
, recsize
, &t
, "format3"))
853 FATAL("format item %.30s... ran format() out of memory", os
);
854 if (*s
== 'l' || *s
== 'h' || *s
== 'L')
856 if (isalpha((uschar
)*s
))
857 break; /* the ansi panoply */
860 FATAL("not enough args in printf("
864 snprintf(t
- 1, FMTSZ(t
- 1),
865 "%d", fmtwd
=(int) getfval(x
));
868 adjbuf(&buf
, &bufsize
, fmtwd
+1+p
-buf
, recsize
, &p
, "format");
869 t
= fmt
+ strlen(fmt
);
876 adjbuf(&buf
, &bufsize
, fmtwd
+1+p
-buf
, recsize
, &p
, "format4");
879 case 'f': case 'e': case 'g': case 'E': case 'G':
884 if(*(s
-1) == 'l') break;
889 case 'o': case 'x': case 'X': case 'u':
890 flag
= *(s
-1) == 'l' ? 'd' : 'u';
900 WARNING("weird printf conversion %s", fmt
);
905 FATAL("not enough args in printf(%s)", os
);
911 adjbuf(&buf
, &bufsize
, 1+n
+p
-buf
, recsize
, &p
, "format5");
913 case '?': snprintf(p
, BUFSZ(p
), "%s", fmt
); /* unknown, so dump it too */
918 adjbuf(&buf
, &bufsize
, 1+strlen(p
)+n
+p
-buf
, recsize
, &p
, "format6");
920 snprintf(p
, BUFSZ(p
), "%s", t
);
922 case 'f': snprintf(p
, BUFSZ(p
), fmt
, getfval(x
)); break;
923 case 'd': snprintf(p
, BUFSZ(p
), fmt
, (long) getfval(x
)); break;
924 case 'u': snprintf(p
, BUFSZ(p
), fmt
, (int) getfval(x
)); break;
930 if (!adjbuf(&buf
, &bufsize
, 1+n
+p
-buf
, recsize
, &p
, "format7"))
931 FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n
, t
);
932 snprintf(p
, BUFSZ(p
), fmt
, t
);
937 snprintf(p
, BUFSZ(p
), fmt
, (int) getfval(x
));
939 *p
++ = '\0'; /* explicit null byte */
940 *p
= '\0'; /* next output will start here */
943 snprintf(p
, BUFSZ(p
), fmt
, getsval(x
)[0]);
946 FATAL("can't happen: bad conversion %c in format()", flag
);
954 for ( ; a
; a
= a
->nnext
) /* evaluate any remaining args */
961 Cell
*awksprintf(Node
**a
, int n
) /* sprintf(a[0]) */
968 if ((buf
= (char *) malloc(bufsz
)) == NULL
)
969 FATAL("out of memory in awksprintf");
972 if (format(&buf
, &bufsz
, getsval(x
), y
) == -1)
973 FATAL("sprintf string %.30s... too long. can't happen.", buf
);
981 Cell
*awkprintf(Node
**a
, int n
) /* printf */
982 { /* a[0] is list of args, starting with format string */
983 /* a[1] is redirection operator, a[2] is redirection file */
991 if ((buf
= (char *) malloc(bufsz
)) == NULL
)
992 FATAL("out of memory in awkprintf");
995 if ((len
= format(&buf
, &bufsz
, getsval(x
), y
)) == -1)
996 FATAL("printf string %.30s... too long. can't happen.", buf
);
999 /* fputs(buf, stdout); */
1000 fwrite(buf
, len
, 1, stdout
);
1002 FATAL("write error on stdout");
1004 fp
= redirect(ptoi(a
[1]), a
[2]);
1005 /* fputs(buf, fp); */
1006 fwrite(buf
, len
, 1, fp
);
1009 FATAL("write error on %s", filename(fp
));
1015 Cell
*arith(Node
**a
, int n
) /* a[0] + a[1], etc. also -a[0] */
1042 FATAL("division by zero");
1047 FATAL("division by zero in mod");
1055 if (j
>= 0 && modf(j
, &v
) == 0.0) /* pos integer exponent */
1056 i
= ipow(i
, (int) j
);
1058 i
= errcheck(pow(i
, j
), "pow");
1060 default: /* can't happen */
1061 FATAL("illegal arithmetic operator %d", n
);
1067 double ipow(double x
, int n
) /* x**n. ought to be done by pow, but isn't always */
1080 Cell
*incrdecr(Node
**a
, int n
) /* a[0]++, etc. */
1088 k
= (n
== PREINCR
|| n
== POSTINCR
) ? 1 : -1;
1089 if (n
== PREINCR
|| n
== PREDECR
) {
1100 Cell
*assign(Node
**a
, int n
) /* a[0] = a[1], a[0] += a[1], etc. */
1101 { /* this is subtle; don't muck with it. */
1108 if (n
== ASSIGN
) { /* ordinary assignment */
1109 if (x
== y
&& !(x
->tval
& (FLD
|REC
))) /* self-assignment: */
1110 ; /* leave alone unless it's a field */
1111 else if ((y
->tval
& (STR
|NUM
)) == (STR
|NUM
)) {
1112 setsval(x
, getsval(y
));
1113 x
->fval
= getfval(y
);
1117 setsval(x
, getsval(y
));
1119 setfval(x
, getfval(y
));
1121 funnyvar(y
, "read value of");
1139 FATAL("division by zero in /=");
1144 FATAL("division by zero in %%=");
1149 if (yf
>= 0 && modf(yf
, &v
) == 0.0) /* pos integer exponent */
1150 xf
= ipow(xf
, (int) yf
);
1152 xf
= errcheck(pow(xf
, yf
), "pow");
1155 FATAL("illegal assignment operator %d", n
);
1163 Cell
*cat(Node
**a
, int q
) /* a[0] cat a[1] */
1173 n1
= strlen(x
->sval
);
1174 n2
= strlen(y
->sval
);
1175 s
= (char *) malloc(n1
+ n2
+ 1);
1177 FATAL("out of space concatenating %.15s... and %.15s...",
1180 strcpy(s
+n1
, y
->sval
);
1189 Cell
*pastat(Node
**a
, int n
) /* a[0] { a[1] } */
1205 Cell
*dopa2(Node
**a
, int n
) /* a[0], a[1] { a[2] } */
1211 if (pairstack
[pair
] == 0) {
1214 pairstack
[pair
] = 1;
1217 if (pairstack
[pair
] == 1) {
1220 pairstack
[pair
] = 0;
1228 Cell
*split(Node
**a
, int nnn
) /* split(a[0], a[1], a[2]); a[3] is type */
1230 Cell
*x
= 0, *y
, *ap
;
1233 char *t
, temp
, num
[50], *fs
= 0;
1234 int n
, tempstat
, arg3type
;
1236 y
= execute(a
[0]); /* source string */
1238 arg3type
= ptoi(a
[3]);
1239 if (a
[2] == 0) /* fs string */
1241 else if (arg3type
== STRING
) { /* split(str,arr,"string") */
1244 } else if (arg3type
== REGEXPR
)
1245 fs
= "(regexpr)"; /* split(str,arr,/regexpr/) */
1247 FATAL("illegal type of split");
1249 ap
= execute(a
[1]); /* array name */
1251 dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s
, NN(ap
->nval
), fs
) );
1254 ap
->sval
= (char *) makesymtab(NSYMTAB
);
1257 if (*s
!= '\0' && (strlen(fs
) > 1 || arg3type
== REGEXPR
)) { /* reg expr */
1259 if (arg3type
== REGEXPR
) { /* it's ready already */
1262 pfa
= makedfa(fs
, 1);
1264 if (nematch(pfa
,s
)) {
1265 tempstat
= pfa
->initstat
;
1269 snprintf(num
, sizeof(num
), "%d", n
);
1273 setsymtab(num
, s
, atof(s
), STR
|NUM
, (Array
*) ap
->sval
);
1275 setsymtab(num
, s
, 0.0, STR
, (Array
*) ap
->sval
);
1277 s
= patbeg
+ patlen
;
1278 if (*(patbeg
+patlen
-1) == 0 || *s
== 0) {
1280 snprintf(num
, sizeof(num
), "%d", n
);
1281 setsymtab(num
, "", 0.0, STR
, (Array
*) ap
->sval
);
1282 pfa
->initstat
= tempstat
;
1285 } while (nematch(pfa
,s
));
1286 pfa
->initstat
= tempstat
; /* bwk: has to be here to reset */
1287 /* cf gsub and refldbld */
1290 snprintf(num
, sizeof(num
), "%d", n
);
1292 setsymtab(num
, s
, atof(s
), STR
|NUM
, (Array
*) ap
->sval
);
1294 setsymtab(num
, s
, 0.0, STR
, (Array
*) ap
->sval
);
1297 } else if (sep
== ' ') {
1299 while (*s
== ' ' || *s
== '\t' || *s
== '\n')
1307 while (*s
!=' ' && *s
!='\t' && *s
!='\n' && *s
!='\0');
1310 snprintf(num
, sizeof(num
), "%d", n
);
1312 setsymtab(num
, t
, atof(t
), STR
|NUM
, (Array
*) ap
->sval
);
1314 setsymtab(num
, t
, 0.0, STR
, (Array
*) ap
->sval
);
1319 } else if (sep
== 0) { /* new: split(s, a, "") => 1 char/elem */
1320 for (n
= 0; *s
!= 0; s
++) {
1323 snprintf(num
, sizeof(num
), "%d", n
);
1326 if (isdigit((uschar
)buf
[0]))
1327 setsymtab(num
, buf
, atof(buf
), STR
|NUM
, (Array
*) ap
->sval
);
1329 setsymtab(num
, buf
, 0.0, STR
, (Array
*) ap
->sval
);
1331 } else if (*s
!= 0) {
1335 while (*s
!= sep
&& *s
!= '\n' && *s
!= '\0')
1339 snprintf(num
, sizeof(num
), "%d", n
);
1341 setsymtab(num
, t
, atof(t
), STR
|NUM
, (Array
*) ap
->sval
);
1343 setsymtab(num
, t
, 0.0, STR
, (Array
*) ap
->sval
);
1351 if (a
[2] != 0 && arg3type
== STRING
) {
1360 Cell
*condexpr(Node
**a
, int n
) /* a[0] ? a[1] : a[2] */
1375 Cell
*ifstat(Node
**a
, int n
) /* if (a[0]) a[1]; else a[2] */
1383 } else if (a
[2] != 0) {
1390 Cell
*whilestat(Node
**a
, int n
) /* while (a[0]) a[1] */
1404 if (isnext(x
) || isexit(x
) || isret(x
))
1410 Cell
*dostat(Node
**a
, int n
) /* do a[0]; while(a[1]) */
1418 if (isnext(x
) || isexit(x
) || isret(x
))
1428 Cell
*forstat(Node
**a
, int n
) /* for (a[0]; a[1]; a[2]) a[3] */
1437 if (!istrue(x
)) return(x
);
1441 if (isbreak(x
)) /* turn off break */
1443 if (isnext(x
) || isexit(x
) || isret(x
))
1451 Cell
*instat(Node
**a
, int n
) /* for (a[0] in a[1]) a[2] */
1453 Cell
*x
, *vp
, *arrayp
, *cp
, *ncp
;
1458 arrayp
= execute(a
[1]);
1459 if (!isarr(arrayp
)) {
1462 tp
= (Array
*) arrayp
->sval
;
1464 for (i
= 0; i
< tp
->size
; i
++) { /* this routine knows too much */
1465 for (cp
= tp
->tab
[i
]; cp
!= NULL
; cp
= ncp
) {
1466 setsval(vp
, cp
->nval
);
1473 if (isnext(x
) || isexit(x
) || isret(x
)) {
1483 void flush_all(void);
1485 static char *nawk_toXXX(const char *s
,
1487 wint_t (*fun_wc
)(wint_t))
1491 const char *ps
= NULL
;
1493 mbstate_t mbs
, mbs2
;
1495 size_t sz
= MB_CUR_MAX
;
1500 for (pbuf
= buf
; *pbuf
; pbuf
++)
1501 *pbuf
= fun_c((uschar
)*pbuf
);
1505 /* upper/lower character may be shorter/longer */
1506 buf
= tostringN(s
, strlen(s
) * sz
+ 1);
1508 memset(&mbs
, 0, sizeof(mbs
));
1509 memset(&mbs2
, 0, sizeof(mbs2
));
1513 while (n
= mbrtowc(&wc
, ps
, sz
, &mbs
),
1514 n
> 0 && n
!= (size_t)-1 && n
!= (size_t)-2)
1518 n
= wcrtomb(pbuf
, fun_wc(wc
), &mbs2
);
1519 if (n
== (size_t)-1)
1520 FATAL("illegal wide character %s", s
);
1528 FATAL("illegal byte sequence %s", s
);
1534 static char *nawk_toupper(const char *s
)
1536 return nawk_toXXX(s
, toupper
, towupper
);
1539 static char *nawk_tolower(const char *s
)
1541 return nawk_toXXX(s
, tolower
, towlower
);
1544 Cell
*bltin(Node
**a
, int n
) /* builtin functions. a[0] is type, a[1] is arg list */
1557 nextarg
= a
[1]->nnext
;
1561 u
= ((Array
*) x
->sval
)->nelem
; /* GROT. should be function*/
1563 u
= strlen(getsval(x
));
1566 u
= errcheck(log(getfval(x
)), "log"); break;
1568 modf(getfval(x
), &u
); break;
1570 u
= errcheck(exp(getfval(x
)), "exp"); break;
1572 u
= errcheck(sqrt(getfval(x
)), "sqrt"); break;
1574 u
= sin(getfval(x
)); break;
1576 u
= cos(getfval(x
)); break;
1579 WARNING("atan2 requires two arguments; returning 1.0");
1582 y
= execute(a
[1]->nnext
);
1583 u
= atan2(getfval(x
), getfval(y
));
1585 nextarg
= nextarg
->nnext
;
1589 fflush(stdout
); /* in case something is buffered already */
1590 u
= (Awkfloat
) system(getsval(x
)) / 256; /* 256 is unix-dep */
1593 /* in principle, rand() returns something in 0..RAND_MAX */
1594 u
= (Awkfloat
) (rand() % RAND_MAX
) / RAND_MAX
;
1597 if (isrec(x
)) /* no argument provided */
1598 u
= time((time_t *)0);
1601 srand((unsigned int) u
);
1606 buf
= nawk_toupper(getsval(x
));
1608 buf
= nawk_tolower(getsval(x
));
1615 if (isrec(x
) || strlen(getsval(x
)) == 0) {
1616 flush_all(); /* fflush() or fflush("") -> all */
1618 } else if ((fp
= openfile(FFLUSH
, getsval(x
))) == NULL
)
1624 u
= time((time_t *) 0); break;
1626 /* strftime([format [,timestamp]]) */
1628 y
= execute(nextarg
), nextarg
= nextarg
->nnext
;
1629 tv
= (time_t) getfval(y
);
1632 tv
= time((time_t *) 0);
1633 tm
= localtime(&tv
);
1636 /* format argument not provided, use default */
1637 fmt
= tostring("%a %b %d %H:%M:%S %Z %Y");
1639 fmt
= tostring(getsval(x
));
1641 sz
= 32, buf
= NULL
;
1643 if ((buf
= realloc(buf
, (sz
*= 2))) == NULL
)
1644 FATAL("out of memory in strftime");
1645 } while(strftime(buf
, sz
, fmt
, tm
) == 0);
1653 default: /* can't happen */
1654 FATAL("illegal function type %d", t
);
1661 WARNING("warning: function has too many arguments");
1662 for ( ; nextarg
; nextarg
= nextarg
->nnext
)
1668 Cell
*printstat(Node
**a
, int n
) /* print a[0] */
1674 if (a
[1] == 0) /* a[1] is redirection operator, a[2] is file */
1677 fp
= redirect(ptoi(a
[1]), a
[2]);
1678 for (x
= a
[0]; x
!= NULL
; x
= x
->nnext
) {
1680 fputs(getpssval(y
), fp
);
1682 if (x
->nnext
== NULL
)
1690 FATAL("write error on %s", filename(fp
));
1694 Cell
*nullproc(Node
**a
, int n
)
1702 FILE *redirect(int a
, Node
*b
) /* set up all i/o redirections */
1710 fp
= openfile(a
, fname
);
1712 FATAL("can't open file %s", fname
);
1720 int mode
; /* '|', 'a', 'w' => LE/LT, GT */
1724 void stdinit(void) /* in case stdin, etc., are not constants */
1727 files
= calloc(nfiles
, sizeof(*files
));
1729 FATAL("can't allocate file memory for %zu files", nfiles
);
1730 files
[0].fp
= stdin
;
1731 files
[0].fname
= "/dev/stdin";
1733 files
[1].fp
= stdout
;
1734 files
[1].fname
= "/dev/stdout";
1736 files
[2].fp
= stderr
;
1737 files
[2].fname
= "/dev/stderr";
1741 FILE *openfile(int a
, const char *us
)
1749 FATAL("null file name in print or get_line");
1750 for (i
= 0; i
< nfiles
; i
++)
1751 if (files
[i
].fname
&& strcmp(s
, files
[i
].fname
) == 0) {
1752 if (a
== files
[i
].mode
|| (a
==APPEND
&& files
[i
].mode
==GT
))
1757 if (a
== FFLUSH
) /* didn't find it, so don't create it! */
1760 for (i
= 0; i
< nfiles
; i
++)
1761 if (files
[i
].fp
== NULL
)
1765 size_t nnf
= nfiles
+ FOPEN_MAX
;
1766 nf
= realloc(files
, nnf
* sizeof(*nf
));
1768 FATAL("cannot grow files for %s and %zu files", s
, nnf
);
1769 (void)memset(&nf
[nfiles
], 0, FOPEN_MAX
* sizeof(*nf
));
1773 fflush(stdout
); /* force a semblance of order */
1777 } else if (a
== APPEND
) {
1779 m
= GT
; /* so can mix > and >> */
1780 } else if (a
== '|') { /* output pipe */
1782 } else if (a
== LE
) { /* input pipe */
1784 } else if (a
== LT
) { /* get_line <file */
1785 fp
= strcmp(s
, "-") == 0 ? stdin
: fopen(s
, "r"); /* "-" is stdin */
1786 } else /* can't happen */
1787 FATAL("illegal redirection %d", a
);
1789 files
[i
].fname
= tostring(s
);
1796 const char *filename(FILE *fp
)
1800 for (i
= 0; i
< nfiles
; i
++)
1801 if (fp
== files
[i
].fp
)
1802 return files
[i
].fname
;
1806 Cell
*closefile(Node
**a
, int n
)
1816 for (i
= 0; i
< nfiles
; i
++) {
1817 if (files
[i
].fname
&& strcmp(x
->sval
, files
[i
].fname
) == 0) {
1818 if (ferror(files
[i
].fp
))
1819 WARNING( "i/o error occurred on %s", files
[i
].fname
);
1820 if (files
[i
].mode
== '|' || files
[i
].mode
== LE
)
1821 stat
= pclose(files
[i
].fp
) == -1;
1823 stat
= fclose(files
[i
].fp
) == EOF
;
1826 WARNING( "i/o error occurred closing %s",
1829 if (i
> 2) /* don't do /dev/std... */
1830 xfree(files
[i
].fname
);
1831 files
[i
].fname
= NULL
; /* watch out for ref thru this */
1837 setfval(x
, (Awkfloat
) stat
);
1846 for (i
= 0; i
< nfiles
; i
++) {
1848 if (ferror(files
[i
].fp
))
1849 WARNING( "i/o error occurred on %s", files
[i
].fname
);
1851 stat
= fpurge(files
[i
].fp
) == EOF
;
1853 stat
= fflush(files
[i
].fp
) == EOF
;
1854 else if (files
[i
].mode
== '|' || files
[i
].mode
== LE
)
1855 stat
= pclose(files
[i
].fp
) == -1;
1857 stat
= fclose(files
[i
].fp
) == EOF
;
1859 WARNING( "i/o error occurred while closing %s", files
[i
].fname
);
1864 void flush_all(void)
1868 for (i
= 0; i
< nfiles
; i
++)
1870 fflush(files
[i
].fp
);
1873 void backsub(uschar
**pb_ptr
, const uschar
**sptr_ptr
);
1875 Cell
*sub(Node
**a
, int nnn
) /* substitute command */
1879 Cell
*x
, *y
, *result
;
1880 uschar
*t
, *buf
, *pb
;
1882 int bufsz
= recsize
;
1884 if ((buf
= (char *) malloc(bufsz
)) == NULL
)
1885 FATAL("out of memory in sub");
1886 x
= execute(a
[3]); /* target string */
1888 if (a
[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1889 pfa
= (fa
*) a
[1]; /* regular expression */
1892 pfa
= makedfa(getsval(y
), 1);
1895 y
= execute(a
[2]); /* replacement string */
1897 if (pmatch(pfa
, t
)) {
1899 adjbuf(&buf
, &bufsz
, 1+patbeg
-sptr
, recsize
, 0, "sub");
1901 while (sptr
< patbeg
)
1904 while (*sptr
!= 0) {
1905 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "sub");
1906 if (*sptr
== '\\') {
1907 backsub(&pb
, &sptr
);
1908 } else if (*sptr
== '&') {
1910 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "sub");
1911 for (q
= patbeg
; q
< patbeg
+patlen
; )
1917 if (pb
> buf
+ bufsz
)
1918 FATAL("sub result1 %.30s too big; can't happen", buf
);
1919 sptr
= patbeg
+ patlen
;
1920 if ((patlen
== 0 && *patbeg
) || (patlen
&& *(sptr
-1))) {
1921 adjbuf(&buf
, &bufsz
, 1+strlen(sptr
)+pb
-buf
, 0, &pb
, "sub");
1922 while ((*pb
++ = *sptr
++) != 0)
1925 if (pb
> buf
+ bufsz
)
1926 FATAL("sub result2 %.30s too big; can't happen", buf
);
1927 setsval(x
, buf
); /* BUG: should be able to avoid copy */
1936 Cell
*gsub(Node
**a
, int nnn
) /* global substitute */
1944 int mflag
, tempstat
, num
;
1945 int bufsz
= recsize
;
1947 if ((buf
= (char *) malloc(bufsz
)) == NULL
)
1948 FATAL("out of memory in gsub");
1949 mflag
= 0; /* if mflag == 0, can replace empty string */
1951 x
= execute(a
[3]); /* target string */
1953 if (a
[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1954 pfa
= (fa
*) a
[1]; /* regular expression */
1957 pfa
= makedfa(getsval(y
), 1);
1960 y
= execute(a
[2]); /* replacement string */
1961 if (pmatch(pfa
, t
)) {
1962 tempstat
= pfa
->initstat
;
1967 if (patlen
== 0 && *patbeg
!= 0) { /* matched empty string */
1968 if (mflag
== 0) { /* can replace empty */
1971 while (*sptr
!= 0) {
1972 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "gsub");
1973 if (*sptr
== '\\') {
1974 backsub(&pb
, &sptr
);
1975 } else if (*sptr
== '&') {
1977 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "gsub");
1978 for (q
= patbeg
; q
< patbeg
+patlen
; )
1984 if (*t
== 0) /* at end */
1986 adjbuf(&buf
, &bufsz
, 2+pb
-buf
, recsize
, &pb
, "gsub");
1988 if (pb
> buf
+ bufsz
) /* BUG: not sure of this test */
1989 FATAL("gsub result0 %.30s too big; can't happen", buf
);
1992 else { /* matched nonempty string */
1995 adjbuf(&buf
, &bufsz
, 1+(patbeg
-sptr
)+pb
-buf
, recsize
, &pb
, "gsub");
1996 while (sptr
< patbeg
)
1999 while (*sptr
!= 0) {
2000 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "gsub");
2001 if (*sptr
== '\\') {
2002 backsub(&pb
, &sptr
);
2003 } else if (*sptr
== '&') {
2005 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "gsub");
2006 for (q
= patbeg
; q
< patbeg
+patlen
; )
2011 t
= patbeg
+ patlen
;
2012 if (patlen
== 0 || *t
== 0 || *(t
-1) == 0)
2014 if (pb
> buf
+ bufsz
)
2015 FATAL("gsub result1 %.30s too big; can't happen", buf
);
2018 } while (pmatch(pfa
,t
));
2020 adjbuf(&buf
, &bufsz
, 1+strlen(sptr
)+pb
-buf
, 0, &pb
, "gsub");
2021 while ((*pb
++ = *sptr
++) != 0)
2023 done
: if (pb
> buf
+ bufsz
)
2024 FATAL("gsub result2 %.30s too big; can't happen", buf
);
2026 setsval(x
, buf
); /* BUG: should be able to avoid copy + free */
2027 pfa
->initstat
= tempstat
;
2038 Cell
*gensub(Node
**a
, int nnn
) /* global selective substitute */
2039 /* XXX incomplete - doesn't support backreferences \0 ... \9 */
2041 Cell
*x
, *y
, *res
, *h
;
2044 uschar
*q
, *pb
, *t
, *buf
;
2046 int mflag
, tempstat
, num
, whichm
;
2047 int bufsz
= recsize
;
2049 if ((buf
= (char *) malloc(bufsz
)) == NULL
)
2050 FATAL("out of memory in gensub");
2051 mflag
= 0; /* if mflag == 0, can replace empty string */
2053 x
= execute(a
[4]); /* source string */
2055 res
= copycell(x
); /* target string - initially copy of source */
2056 if (a
[0] == 0) /* 0 => a[1] is already-compiled regexpr */
2057 pfa
= (fa
*) a
[1]; /* regular expression */
2060 pfa
= makedfa(getsval(y
), 1);
2063 y
= execute(a
[2]); /* replacement string */
2064 h
= execute(a
[3]); /* which matches should be replaced */
2066 if (sptr
[0] == 'g' || sptr
[0] == 'G')
2070 * The specified number is index of replacement, starting
2071 * from 1. GNU awk treats index lower than 0 same as
2072 * 1, we do same for compatibility.
2074 whichm
= (int) getfval(h
) - 1;
2080 if (pmatch(pfa
, t
)) {
2083 tempstat
= pfa
->initstat
;
2088 * XXX if there are any backreferences in subst string,
2091 for(sl
=rptr
; (sl
= strchr(sl
, '\\')) && sl
[1]; sl
++) {
2092 if (strchr("0123456789", sl
[1])) {
2093 FATAL("gensub doesn't support backreferences (subst \"%s\")", rptr
);
2098 if (whichm
>= 0 && whichm
!= num
) {
2100 adjbuf(&buf
, &bufsz
, (pb
- buf
) + (patbeg
- t
) + patlen
, recsize
, &pb
, "gensub");
2102 /* copy the part of string up to and including
2103 * match to output buffer */
2104 while (t
< patbeg
+ patlen
)
2109 if (patlen
== 0 && *patbeg
!= 0) { /* matched empty string */
2110 if (mflag
== 0) { /* can replace empty */
2113 while (*sptr
!= 0) {
2114 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "gensub");
2115 if (*sptr
== '\\') {
2116 backsub(&pb
, &sptr
);
2117 } else if (*sptr
== '&') {
2119 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "gensub");
2120 for (q
= patbeg
; q
< patbeg
+patlen
; )
2126 if (*t
== 0) /* at end */
2128 adjbuf(&buf
, &bufsz
, 2+pb
-buf
, recsize
, &pb
, "gensub");
2130 if (pb
> buf
+ bufsz
) /* BUG: not sure of this test */
2131 FATAL("gensub result0 %.30s too big; can't happen", buf
);
2134 else { /* matched nonempty string */
2137 adjbuf(&buf
, &bufsz
, 1+(patbeg
-sptr
)+pb
-buf
, recsize
, &pb
, "gensub");
2138 while (sptr
< patbeg
)
2141 while (*sptr
!= 0) {
2142 adjbuf(&buf
, &bufsz
, 5+pb
-buf
, recsize
, &pb
, "gensub");
2143 if (*sptr
== '\\') {
2144 backsub(&pb
, &sptr
);
2145 } else if (*sptr
== '&') {
2147 adjbuf(&buf
, &bufsz
, 1+patlen
+pb
-buf
, recsize
, &pb
, "gensub");
2148 for (q
= patbeg
; q
< patbeg
+patlen
; )
2153 t
= patbeg
+ patlen
;
2154 if (patlen
== 0 || *t
== 0 || *(t
-1) == 0)
2156 if (pb
> buf
+ bufsz
)
2157 FATAL("gensub result1 %.30s too big; can't happen", buf
);
2160 } while (pmatch(pfa
,t
));
2162 adjbuf(&buf
, &bufsz
, 1+strlen(sptr
)+pb
-buf
, 0, &pb
, "gensub");
2163 while ((*pb
++ = *sptr
++) != 0)
2165 done
: if (pb
> buf
+ bufsz
)
2166 FATAL("gensub result2 %.30s too big; can't happen", buf
);
2169 pfa
->initstat
= tempstat
;
2177 void backsub(uschar
**pb_ptr
, const uschar
**sptr_ptr
)/* handle \\& variations */
2178 { /* sptr[0] == '\\' */
2179 uschar
*pb
= *pb_ptr
;
2180 const uschar
*sptr
= *sptr_ptr
;
2182 if (sptr
[1] == '\\') {
2183 if (sptr
[2] == '\\' && sptr
[3] == '&') { /* \\\& -> \& */
2187 } else if (sptr
[2] == '&') { /* \\& -> \ + matched */
2190 } else { /* \\x -> \\x */
2194 } else if (sptr
[1] == '&') { /* literal & */
2197 } else /* literal \ */