Blame


1 63a68686 2008-11-03 jas /****************************************************************
2 63a68686 2008-11-03 jas Copyright (C) Lucent Technologies 1997
3 63a68686 2008-11-03 jas All Rights Reserved
4 63a68686 2008-11-03 jas
5 63a68686 2008-11-03 jas Permission to use, copy, modify, and distribute this software and
6 63a68686 2008-11-03 jas its documentation for any purpose and without fee is hereby
7 63a68686 2008-11-03 jas granted, provided that the above copyright notice appear in all
8 63a68686 2008-11-03 jas copies and that both that the copyright notice and this
9 63a68686 2008-11-03 jas permission notice and warranty disclaimer appear in supporting
10 63a68686 2008-11-03 jas documentation, and that the name Lucent Technologies or any of
11 63a68686 2008-11-03 jas its entities not be used in advertising or publicity pertaining
12 63a68686 2008-11-03 jas to distribution of the software without specific, written prior
13 63a68686 2008-11-03 jas permission.
14 63a68686 2008-11-03 jas
15 63a68686 2008-11-03 jas LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 63a68686 2008-11-03 jas INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17 63a68686 2008-11-03 jas IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18 63a68686 2008-11-03 jas SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 63a68686 2008-11-03 jas WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20 63a68686 2008-11-03 jas IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21 63a68686 2008-11-03 jas ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22 63a68686 2008-11-03 jas THIS SOFTWARE.
23 63a68686 2008-11-03 jas ****************************************************************/
24 63a68686 2008-11-03 jas
25 63a68686 2008-11-03 jas #define DEBUG
26 63a68686 2008-11-03 jas #include <stdio.h>
27 63a68686 2008-11-03 jas #include <ctype.h>
28 63a68686 2008-11-03 jas #include <setjmp.h>
29 63a68686 2008-11-03 jas #include <math.h>
30 63a68686 2008-11-03 jas #include <string.h>
31 63a68686 2008-11-03 jas #include <stdlib.h>
32 63a68686 2008-11-03 jas #include <time.h>
33 5a8bc789 2009-08-12 mt4swm #include <utf.h>
34 63a68686 2008-11-03 jas #include "awk.h"
35 63a68686 2008-11-03 jas #include "y.tab.h"
36 63a68686 2008-11-03 jas
37 63a68686 2008-11-03 jas #define tempfree(x) if (istemp(x)) tfree(x); else
38 63a68686 2008-11-03 jas
39 63a68686 2008-11-03 jas /*
40 63a68686 2008-11-03 jas #undef tempfree
41 63a68686 2008-11-03 jas
42 63a68686 2008-11-03 jas void tempfree(Cell *p) {
43 63a68686 2008-11-03 jas if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) {
44 63a68686 2008-11-03 jas WARNING("bad csub %d in Cell %d %s",
45 63a68686 2008-11-03 jas p->csub, p->ctype, p->sval);
46 63a68686 2008-11-03 jas }
47 63a68686 2008-11-03 jas if (istemp(p))
48 63a68686 2008-11-03 jas tfree(p);
49 63a68686 2008-11-03 jas }
50 63a68686 2008-11-03 jas */
51 63a68686 2008-11-03 jas
52 63a68686 2008-11-03 jas #ifdef _NFILE
53 63a68686 2008-11-03 jas #ifndef FOPEN_MAX
54 63a68686 2008-11-03 jas #define FOPEN_MAX _NFILE
55 63a68686 2008-11-03 jas #endif
56 63a68686 2008-11-03 jas #endif
57 63a68686 2008-11-03 jas
58 63a68686 2008-11-03 jas #ifndef FOPEN_MAX
59 63a68686 2008-11-03 jas #define FOPEN_MAX 40 /* max number of open files */
60 63a68686 2008-11-03 jas #endif
61 63a68686 2008-11-03 jas
62 63a68686 2008-11-03 jas #ifndef RAND_MAX
63 63a68686 2008-11-03 jas #define RAND_MAX 32767 /* all that ansi guarantees */
64 63a68686 2008-11-03 jas #endif
65 63a68686 2008-11-03 jas
66 63a68686 2008-11-03 jas jmp_buf env;
67 63a68686 2008-11-03 jas extern int pairstack[];
68 63a68686 2008-11-03 jas
69 63a68686 2008-11-03 jas Node *winner = NULL; /* root of parse tree */
70 63a68686 2008-11-03 jas Cell *tmps; /* free temporary cells for execution */
71 63a68686 2008-11-03 jas
72 63a68686 2008-11-03 jas static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM };
73 63a68686 2008-11-03 jas Cell *True = &truecell;
74 63a68686 2008-11-03 jas static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM };
75 63a68686 2008-11-03 jas Cell *False = &falsecell;
76 63a68686 2008-11-03 jas static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM };
77 63a68686 2008-11-03 jas Cell *jbreak = &breakcell;
78 63a68686 2008-11-03 jas static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM };
79 63a68686 2008-11-03 jas Cell *jcont = &contcell;
80 63a68686 2008-11-03 jas static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM };
81 63a68686 2008-11-03 jas Cell *jnext = &nextcell;
82 63a68686 2008-11-03 jas static Cell nextfilecell ={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM };
83 63a68686 2008-11-03 jas Cell *jnextfile = &nextfilecell;
84 63a68686 2008-11-03 jas static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM };
85 63a68686 2008-11-03 jas Cell *jexit = &exitcell;
86 63a68686 2008-11-03 jas static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM };
87 63a68686 2008-11-03 jas Cell *jret = &retcell;
88 63a68686 2008-11-03 jas static Cell tempcell ={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE };
89 63a68686 2008-11-03 jas
90 63a68686 2008-11-03 jas Node *curnode = NULL; /* the node being executed, for debugging */
91 63a68686 2008-11-03 jas
92 63a68686 2008-11-03 jas /* buffer memory management */
93 63a68686 2008-11-03 jas int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,
94 63a68686 2008-11-03 jas char *whatrtn)
95 63a68686 2008-11-03 jas /* pbuf: address of pointer to buffer being managed
96 63a68686 2008-11-03 jas * psiz: address of buffer size variable
97 63a68686 2008-11-03 jas * minlen: minimum length of buffer needed
98 63a68686 2008-11-03 jas * quantum: buffer size quantum
99 63a68686 2008-11-03 jas * pbptr: address of movable pointer into buffer, or 0 if none
100 63a68686 2008-11-03 jas * whatrtn: name of the calling routine if failure should cause fatal error
101 63a68686 2008-11-03 jas *
102 63a68686 2008-11-03 jas * return 0 for realloc failure, !=0 for success
103 63a68686 2008-11-03 jas */
104 63a68686 2008-11-03 jas {
105 63a68686 2008-11-03 jas if (minlen > *psiz) {
106 63a68686 2008-11-03 jas char *tbuf;
107 63a68686 2008-11-03 jas int rminlen = quantum ? minlen % quantum : 0;
108 63a68686 2008-11-03 jas int boff = pbptr ? *pbptr - *pbuf : 0;
109 63a68686 2008-11-03 jas /* round up to next multiple of quantum */
110 63a68686 2008-11-03 jas if (rminlen)
111 63a68686 2008-11-03 jas minlen += quantum - rminlen;
112 63a68686 2008-11-03 jas tbuf = (char *) realloc(*pbuf, minlen);
113 63a68686 2008-11-03 jas if (tbuf == NULL) {
114 63a68686 2008-11-03 jas if (whatrtn)
115 63a68686 2008-11-03 jas FATAL("out of memory in %s", whatrtn);
116 63a68686 2008-11-03 jas return 0;
117 63a68686 2008-11-03 jas }
118 63a68686 2008-11-03 jas *pbuf = tbuf;
119 63a68686 2008-11-03 jas *psiz = minlen;
120 63a68686 2008-11-03 jas if (pbptr)
121 63a68686 2008-11-03 jas *pbptr = tbuf + boff;
122 63a68686 2008-11-03 jas }
123 63a68686 2008-11-03 jas return 1;
124 63a68686 2008-11-03 jas }
125 63a68686 2008-11-03 jas
126 63a68686 2008-11-03 jas void run(Node *a) /* execution of parse tree starts here */
127 63a68686 2008-11-03 jas {
128 63a68686 2008-11-03 jas extern void stdinit(void);
129 63a68686 2008-11-03 jas
130 63a68686 2008-11-03 jas stdinit();
131 63a68686 2008-11-03 jas execute(a);
132 63a68686 2008-11-03 jas closeall();
133 63a68686 2008-11-03 jas }
134 63a68686 2008-11-03 jas
135 63a68686 2008-11-03 jas Cell *execute(Node *u) /* execute a node of the parse tree */
136 63a68686 2008-11-03 jas {
137 63a68686 2008-11-03 jas int nobj;
138 63a68686 2008-11-03 jas Cell *(*proc)(Node **, int);
139 63a68686 2008-11-03 jas Cell *x;
140 63a68686 2008-11-03 jas Node *a;
141 63a68686 2008-11-03 jas
142 63a68686 2008-11-03 jas if (u == NULL)
143 63a68686 2008-11-03 jas return(True);
144 63a68686 2008-11-03 jas for (a = u; ; a = a->nnext) {
145 63a68686 2008-11-03 jas curnode = a;
146 63a68686 2008-11-03 jas if (isvalue(a)) {
147 63a68686 2008-11-03 jas x = (Cell *) (a->narg[0]);
148 63a68686 2008-11-03 jas if (isfld(x) && !donefld)
149 63a68686 2008-11-03 jas fldbld();
150 63a68686 2008-11-03 jas else if (isrec(x) && !donerec)
151 63a68686 2008-11-03 jas recbld();
152 63a68686 2008-11-03 jas return(x);
153 63a68686 2008-11-03 jas }
154 63a68686 2008-11-03 jas nobj = a->nobj;
155 63a68686 2008-11-03 jas if (notlegal(nobj)) /* probably a Cell* but too risky to print */
156 63a68686 2008-11-03 jas FATAL("illegal statement");
157 63a68686 2008-11-03 jas proc = proctab[nobj-FIRSTTOKEN];
158 63a68686 2008-11-03 jas x = (*proc)(a->narg, nobj);
159 63a68686 2008-11-03 jas if (isfld(x) && !donefld)
160 63a68686 2008-11-03 jas fldbld();
161 63a68686 2008-11-03 jas else if (isrec(x) && !donerec)
162 63a68686 2008-11-03 jas recbld();
163 63a68686 2008-11-03 jas if (isexpr(a))
164 63a68686 2008-11-03 jas return(x);
165 63a68686 2008-11-03 jas if (isjump(x))
166 63a68686 2008-11-03 jas return(x);
167 63a68686 2008-11-03 jas if (a->nnext == NULL)
168 63a68686 2008-11-03 jas return(x);
169 63a68686 2008-11-03 jas tempfree(x);
170 63a68686 2008-11-03 jas }
171 63a68686 2008-11-03 jas }
172 63a68686 2008-11-03 jas
173 63a68686 2008-11-03 jas
174 63a68686 2008-11-03 jas Cell *program(Node **a, int n) /* execute an awk program */
175 63a68686 2008-11-03 jas { /* a[0] = BEGIN, a[1] = body, a[2] = END */
176 63a68686 2008-11-03 jas Cell *x;
177 63a68686 2008-11-03 jas
178 63a68686 2008-11-03 jas if (setjmp(env) != 0)
179 63a68686 2008-11-03 jas goto ex;
180 63a68686 2008-11-03 jas if (a[0]) { /* BEGIN */
181 63a68686 2008-11-03 jas x = execute(a[0]);
182 63a68686 2008-11-03 jas if (isexit(x))
183 63a68686 2008-11-03 jas return(True);
184 63a68686 2008-11-03 jas if (isjump(x))
185 63a68686 2008-11-03 jas FATAL("illegal break, continue, next or nextfile from BEGIN");
186 63a68686 2008-11-03 jas tempfree(x);
187 63a68686 2008-11-03 jas }
188 63a68686 2008-11-03 jas if (a[1] || a[2])
189 63a68686 2008-11-03 jas while (getrec(&record, &recsize, 1) > 0) {
190 63a68686 2008-11-03 jas x = execute(a[1]);
191 63a68686 2008-11-03 jas if (isexit(x))
192 63a68686 2008-11-03 jas break;
193 63a68686 2008-11-03 jas tempfree(x);
194 63a68686 2008-11-03 jas }
195 63a68686 2008-11-03 jas ex:
196 63a68686 2008-11-03 jas if (setjmp(env) != 0) /* handles exit within END */
197 63a68686 2008-11-03 jas goto ex1;
198 63a68686 2008-11-03 jas if (a[2]) { /* END */
199 63a68686 2008-11-03 jas x = execute(a[2]);
200 63a68686 2008-11-03 jas if (isbreak(x) || isnext(x) || iscont(x))
201 63a68686 2008-11-03 jas FATAL("illegal break, continue, next or nextfile from END");
202 63a68686 2008-11-03 jas tempfree(x);
203 63a68686 2008-11-03 jas }
204 63a68686 2008-11-03 jas ex1:
205 63a68686 2008-11-03 jas return(True);
206 63a68686 2008-11-03 jas }
207 63a68686 2008-11-03 jas
208 63a68686 2008-11-03 jas struct Frame { /* stack frame for awk function calls */
209 63a68686 2008-11-03 jas int nargs; /* number of arguments in this call */
210 63a68686 2008-11-03 jas Cell *fcncell; /* pointer to Cell for function */
211 63a68686 2008-11-03 jas Cell **args; /* pointer to array of arguments after execute */
212 63a68686 2008-11-03 jas Cell *retval; /* return value */
213 63a68686 2008-11-03 jas };
214 63a68686 2008-11-03 jas
215 63a68686 2008-11-03 jas #define NARGS 50 /* max args in a call */
216 63a68686 2008-11-03 jas
217 63a68686 2008-11-03 jas struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */
218 63a68686 2008-11-03 jas int nframe = 0; /* number of frames allocated */
219 63a68686 2008-11-03 jas struct Frame *fp = NULL; /* frame pointer. bottom level unused */
220 63a68686 2008-11-03 jas
221 63a68686 2008-11-03 jas Cell *call(Node **a, int n) /* function call. very kludgy and fragile */
222 63a68686 2008-11-03 jas {
223 63a68686 2008-11-03 jas static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE };
224 63a68686 2008-11-03 jas int i, ncall, ndef;
225 63a68686 2008-11-03 jas Node *x;
226 63a68686 2008-11-03 jas Cell *args[NARGS], *oargs[NARGS]; /* BUG: fixed size arrays */
227 63a68686 2008-11-03 jas Cell *y, *z, *fcn;
228 63a68686 2008-11-03 jas char *s;
229 63a68686 2008-11-03 jas
230 63a68686 2008-11-03 jas fcn = execute(a[0]); /* the function itself */
231 63a68686 2008-11-03 jas s = fcn->nval;
232 63a68686 2008-11-03 jas if (!isfcn(fcn))
233 63a68686 2008-11-03 jas FATAL("calling undefined function %s", s);
234 63a68686 2008-11-03 jas if (frame == NULL) {
235 63a68686 2008-11-03 jas fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
236 63a68686 2008-11-03 jas if (frame == NULL)
237 63a68686 2008-11-03 jas FATAL("out of space for stack frames calling %s", s);
238 63a68686 2008-11-03 jas }
239 63a68686 2008-11-03 jas for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */
240 63a68686 2008-11-03 jas ncall++;
241 63a68686 2008-11-03 jas ndef = (int) fcn->fval; /* args in defn */
242 63a68686 2008-11-03 jas dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) );
243 63a68686 2008-11-03 jas if (ncall > ndef)
244 63a68686 2008-11-03 jas WARNING("function %s called with %d args, uses only %d",
245 63a68686 2008-11-03 jas s, ncall, ndef);
246 63a68686 2008-11-03 jas if (ncall + ndef > NARGS)
247 63a68686 2008-11-03 jas FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS);
248 63a68686 2008-11-03 jas for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */
249 63a68686 2008-11-03 jas dprintf( ("evaluate args[%d], fp=%d:\n", i, (int) (fp-frame)) );
250 63a68686 2008-11-03 jas y = execute(x);
251 63a68686 2008-11-03 jas oargs[i] = y;
252 63a68686 2008-11-03 jas dprintf( ("args[%d]: %s %f <%s>, t=%o\n",
253 63a68686 2008-11-03 jas i, y->nval, y->fval, isarr(y) ? "(array)" : y->sval, y->tval) );
254 63a68686 2008-11-03 jas if (isfcn(y))
255 63a68686 2008-11-03 jas FATAL("can't use function %s as argument in %s", y->nval, s);
256 63a68686 2008-11-03 jas if (isarr(y))
257 63a68686 2008-11-03 jas args[i] = y; /* arrays by ref */
258 63a68686 2008-11-03 jas else
259 63a68686 2008-11-03 jas args[i] = copycell(y);
260 63a68686 2008-11-03 jas tempfree(y);
261 63a68686 2008-11-03 jas }
262 63a68686 2008-11-03 jas for ( ; i < ndef; i++) { /* add null args for ones not provided */
263 63a68686 2008-11-03 jas args[i] = gettemp();
264 63a68686 2008-11-03 jas *args[i] = newcopycell;
265 63a68686 2008-11-03 jas }
266 63a68686 2008-11-03 jas fp++; /* now ok to up frame */
267 63a68686 2008-11-03 jas if (fp >= frame + nframe) {
268 63a68686 2008-11-03 jas int dfp = fp - frame; /* old index */
269 63a68686 2008-11-03 jas frame = (struct Frame *)
270 63a68686 2008-11-03 jas realloc((char *) frame, (nframe += 100) * sizeof(struct Frame));
271 63a68686 2008-11-03 jas if (frame == NULL)
272 63a68686 2008-11-03 jas FATAL("out of space for stack frames in %s", s);
273 63a68686 2008-11-03 jas fp = frame + dfp;
274 63a68686 2008-11-03 jas }
275 63a68686 2008-11-03 jas fp->fcncell = fcn;
276 63a68686 2008-11-03 jas fp->args = args;
277 63a68686 2008-11-03 jas fp->nargs = ndef; /* number defined with (excess are locals) */
278 63a68686 2008-11-03 jas fp->retval = gettemp();
279 63a68686 2008-11-03 jas
280 63a68686 2008-11-03 jas dprintf( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) );
281 63a68686 2008-11-03 jas y = execute((Node *)(fcn->sval)); /* execute body */
282 63a68686 2008-11-03 jas dprintf( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) );
283 63a68686 2008-11-03 jas
284 63a68686 2008-11-03 jas for (i = 0; i < ndef; i++) {
285 63a68686 2008-11-03 jas Cell *t = fp->args[i];
286 63a68686 2008-11-03 jas if (isarr(t)) {
287 63a68686 2008-11-03 jas if (t->csub == CCOPY) {
288 63a68686 2008-11-03 jas if (i >= ncall) {
289 63a68686 2008-11-03 jas freesymtab(t);
290 63a68686 2008-11-03 jas t->csub = CTEMP;
291 63a68686 2008-11-03 jas tempfree(t);
292 63a68686 2008-11-03 jas } else {
293 63a68686 2008-11-03 jas oargs[i]->tval = t->tval;
294 63a68686 2008-11-03 jas oargs[i]->tval &= ~(STR|NUM|DONTFREE);
295 63a68686 2008-11-03 jas oargs[i]->sval = t->sval;
296 63a68686 2008-11-03 jas tempfree(t);
297 63a68686 2008-11-03 jas }
298 63a68686 2008-11-03 jas }
299 63a68686 2008-11-03 jas } else if (t != y) { /* kludge to prevent freeing twice */
300 63a68686 2008-11-03 jas t->csub = CTEMP;
301 63a68686 2008-11-03 jas tempfree(t);
302 63a68686 2008-11-03 jas }
303 63a68686 2008-11-03 jas }
304 63a68686 2008-11-03 jas tempfree(fcn);
305 63a68686 2008-11-03 jas if (isexit(y) || isnext(y) || isnextfile(y))
306 63a68686 2008-11-03 jas return y;
307 63a68686 2008-11-03 jas tempfree(y); /* this can free twice! */
308 63a68686 2008-11-03 jas z = fp->retval; /* return value */
309 63a68686 2008-11-03 jas dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );
310 63a68686 2008-11-03 jas fp--;
311 63a68686 2008-11-03 jas return(z);
312 63a68686 2008-11-03 jas }
313 63a68686 2008-11-03 jas
314 63a68686 2008-11-03 jas Cell *copycell(Cell *x) /* make a copy of a cell in a temp */
315 63a68686 2008-11-03 jas {
316 63a68686 2008-11-03 jas Cell *y;
317 63a68686 2008-11-03 jas
318 63a68686 2008-11-03 jas y = gettemp();
319 63a68686 2008-11-03 jas y->csub = CCOPY; /* prevents freeing until call is over */
320 63a68686 2008-11-03 jas y->nval = x->nval; /* BUG? */
321 63a68686 2008-11-03 jas y->sval = x->sval ? tostring(x->sval) : NULL;
322 63a68686 2008-11-03 jas y->fval = x->fval;
323 63a68686 2008-11-03 jas y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */
324 63a68686 2008-11-03 jas /* is DONTFREE right? */
325 63a68686 2008-11-03 jas return y;
326 63a68686 2008-11-03 jas }
327 63a68686 2008-11-03 jas
328 63a68686 2008-11-03 jas Cell *arg(Node **a, int n) /* nth argument of a function */
329 63a68686 2008-11-03 jas {
330 63a68686 2008-11-03 jas
331 63a68686 2008-11-03 jas n = ptoi(a[0]); /* argument number, counting from 0 */
332 63a68686 2008-11-03 jas dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );
333 63a68686 2008-11-03 jas if (n+1 > fp->nargs)
334 63a68686 2008-11-03 jas FATAL("argument #%d of function %s was not supplied",
335 63a68686 2008-11-03 jas n+1, fp->fcncell->nval);
336 63a68686 2008-11-03 jas return fp->args[n];
337 63a68686 2008-11-03 jas }
338 63a68686 2008-11-03 jas
339 63a68686 2008-11-03 jas Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */
340 63a68686 2008-11-03 jas {
341 63a68686 2008-11-03 jas Cell *y;
342 63a68686 2008-11-03 jas
343 63a68686 2008-11-03 jas switch (n) {
344 63a68686 2008-11-03 jas case EXIT:
345 63a68686 2008-11-03 jas if (a[0] != NULL) {
346 63a68686 2008-11-03 jas y = execute(a[0]);
347 63a68686 2008-11-03 jas errorflag = (int) getfval(y);
348 63a68686 2008-11-03 jas tempfree(y);
349 63a68686 2008-11-03 jas }
350 63a68686 2008-11-03 jas longjmp(env, 1);
351 63a68686 2008-11-03 jas case RETURN:
352 63a68686 2008-11-03 jas if (a[0] != NULL) {
353 63a68686 2008-11-03 jas y = execute(a[0]);
354 63a68686 2008-11-03 jas if ((y->tval & (STR|NUM)) == (STR|NUM)) {
355 63a68686 2008-11-03 jas setsval(fp->retval, getsval(y));
356 63a68686 2008-11-03 jas fp->retval->fval = getfval(y);
357 63a68686 2008-11-03 jas fp->retval->tval |= NUM;
358 63a68686 2008-11-03 jas }
359 63a68686 2008-11-03 jas else if (y->tval & STR)
360 63a68686 2008-11-03 jas setsval(fp->retval, getsval(y));
361 63a68686 2008-11-03 jas else if (y->tval & NUM)
362 63a68686 2008-11-03 jas setfval(fp->retval, getfval(y));
363 63a68686 2008-11-03 jas else /* can't happen */
364 63a68686 2008-11-03 jas FATAL("bad type variable %d", y->tval);
365 63a68686 2008-11-03 jas tempfree(y);
366 63a68686 2008-11-03 jas }
367 63a68686 2008-11-03 jas return(jret);
368 63a68686 2008-11-03 jas case NEXT:
369 63a68686 2008-11-03 jas return(jnext);
370 63a68686 2008-11-03 jas case NEXTFILE:
371 63a68686 2008-11-03 jas nextfile();
372 63a68686 2008-11-03 jas return(jnextfile);
373 63a68686 2008-11-03 jas case BREAK:
374 63a68686 2008-11-03 jas return(jbreak);
375 63a68686 2008-11-03 jas case CONTINUE:
376 63a68686 2008-11-03 jas return(jcont);
377 63a68686 2008-11-03 jas default: /* can't happen */
378 63a68686 2008-11-03 jas FATAL("illegal jump type %d", n);
379 63a68686 2008-11-03 jas }
380 63a68686 2008-11-03 jas return 0; /* not reached */
381 63a68686 2008-11-03 jas }
382 63a68686 2008-11-03 jas
383 63a68686 2008-11-03 jas Cell *getline(Node **a, int n) /* get next line from specific input */
384 63a68686 2008-11-03 jas { /* a[0] is variable, a[1] is operator, a[2] is filename */
385 63a68686 2008-11-03 jas Cell *r, *x;
386 63a68686 2008-11-03 jas extern Cell **fldtab;
387 63a68686 2008-11-03 jas FILE *fp;
388 63a68686 2008-11-03 jas char *buf;
389 63a68686 2008-11-03 jas int bufsize = recsize;
390 63a68686 2008-11-03 jas int mode;
391 63a68686 2008-11-03 jas
392 63a68686 2008-11-03 jas if ((buf = (char *) malloc(bufsize)) == NULL)
393 63a68686 2008-11-03 jas FATAL("out of memory in getline");
394 63a68686 2008-11-03 jas
395 63a68686 2008-11-03 jas fflush(stdout); /* in case someone is waiting for a prompt */
396 63a68686 2008-11-03 jas r = gettemp();
397 63a68686 2008-11-03 jas if (a[1] != NULL) { /* getline < file */
398 63a68686 2008-11-03 jas x = execute(a[2]); /* filename */
399 63a68686 2008-11-03 jas mode = ptoi(a[1]);
400 63a68686 2008-11-03 jas if (mode == '|') /* input pipe */
401 63a68686 2008-11-03 jas mode = LE; /* arbitrary flag */
402 63a68686 2008-11-03 jas fp = openfile(mode, getsval(x));
403 63a68686 2008-11-03 jas tempfree(x);
404 63a68686 2008-11-03 jas if (fp == NULL)
405 63a68686 2008-11-03 jas n = -1;
406 63a68686 2008-11-03 jas else
407 63a68686 2008-11-03 jas n = readrec(&buf, &bufsize, fp);
408 63a68686 2008-11-03 jas if (n <= 0) {
409 63a68686 2008-11-03 jas ;
410 63a68686 2008-11-03 jas } else if (a[0] != NULL) { /* getline var <file */
411 63a68686 2008-11-03 jas x = execute(a[0]);
412 63a68686 2008-11-03 jas setsval(x, buf);
413 63a68686 2008-11-03 jas tempfree(x);
414 63a68686 2008-11-03 jas } else { /* getline <file */
415 63a68686 2008-11-03 jas setsval(fldtab[0], buf);
416 63a68686 2008-11-03 jas if (is_number(fldtab[0]->sval)) {
417 63a68686 2008-11-03 jas fldtab[0]->fval = atof(fldtab[0]->sval);
418 63a68686 2008-11-03 jas fldtab[0]->tval |= NUM;
419 63a68686 2008-11-03 jas }
420 63a68686 2008-11-03 jas }
421 63a68686 2008-11-03 jas } else { /* bare getline; use current input */
422 63a68686 2008-11-03 jas if (a[0] == NULL) /* getline */
423 63a68686 2008-11-03 jas n = getrec(&record, &recsize, 1);
424 63a68686 2008-11-03 jas else { /* getline var */
425 63a68686 2008-11-03 jas n = getrec(&buf, &bufsize, 0);
426 63a68686 2008-11-03 jas x = execute(a[0]);
427 63a68686 2008-11-03 jas setsval(x, buf);
428 63a68686 2008-11-03 jas tempfree(x);
429 63a68686 2008-11-03 jas }
430 63a68686 2008-11-03 jas }
431 63a68686 2008-11-03 jas setfval(r, (Awkfloat) n);
432 63a68686 2008-11-03 jas free(buf);
433 63a68686 2008-11-03 jas return r;
434 63a68686 2008-11-03 jas }
435 63a68686 2008-11-03 jas
436 63a68686 2008-11-03 jas Cell *getnf(Node **a, int n) /* get NF */
437 63a68686 2008-11-03 jas {
438 63a68686 2008-11-03 jas if (donefld == 0)
439 63a68686 2008-11-03 jas fldbld();
440 63a68686 2008-11-03 jas return (Cell *) a[0];
441 63a68686 2008-11-03 jas }
442 63a68686 2008-11-03 jas
443 63a68686 2008-11-03 jas Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
444 63a68686 2008-11-03 jas {
445 63a68686 2008-11-03 jas Cell *x, *y, *z;
446 63a68686 2008-11-03 jas char *s;
447 63a68686 2008-11-03 jas Node *np;
448 63a68686 2008-11-03 jas char *buf;
449 63a68686 2008-11-03 jas int bufsz = recsize;
450 63a68686 2008-11-03 jas int nsub = strlen(*SUBSEP);
451 63a68686 2008-11-03 jas
452 63a68686 2008-11-03 jas if ((buf = (char *) malloc(bufsz)) == NULL)
453 63a68686 2008-11-03 jas FATAL("out of memory in array");
454 63a68686 2008-11-03 jas
455 63a68686 2008-11-03 jas x = execute(a[0]); /* Cell* for symbol table */
456 63a68686 2008-11-03 jas buf[0] = 0;
457 63a68686 2008-11-03 jas for (np = a[1]; np; np = np->nnext) {
458 63a68686 2008-11-03 jas y = execute(np); /* subscript */
459 63a68686 2008-11-03 jas s = getsval(y);
460 63a68686 2008-11-03 jas if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))
461 63a68686 2008-11-03 jas FATAL("out of memory for %s[%s...]", x->nval, buf);
462 63a68686 2008-11-03 jas strcat(buf, s);
463 63a68686 2008-11-03 jas if (np->nnext)
464 63a68686 2008-11-03 jas strcat(buf, *SUBSEP);
465 63a68686 2008-11-03 jas tempfree(y);
466 63a68686 2008-11-03 jas }
467 63a68686 2008-11-03 jas if (!isarr(x)) {
468 63a68686 2008-11-03 jas dprintf( ("making %s into an array\n", x->nval) );
469 63a68686 2008-11-03 jas if (freeable(x))
470 63a68686 2008-11-03 jas xfree(x->sval);
471 63a68686 2008-11-03 jas x->tval &= ~(STR|NUM|DONTFREE);
472 63a68686 2008-11-03 jas x->tval |= ARR;
473 63a68686 2008-11-03 jas x->sval = (char *) makesymtab(NSYMTAB);
474 63a68686 2008-11-03 jas }
475 63a68686 2008-11-03 jas z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
476 63a68686 2008-11-03 jas z->ctype = OCELL;
477 63a68686 2008-11-03 jas z->csub = CVAR;
478 63a68686 2008-11-03 jas tempfree(x);
479 63a68686 2008-11-03 jas free(buf);
480 63a68686 2008-11-03 jas return(z);
481 63a68686 2008-11-03 jas }
482 63a68686 2008-11-03 jas
483 63a68686 2008-11-03 jas Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
484 63a68686 2008-11-03 jas {
485 63a68686 2008-11-03 jas Cell *x, *y;
486 63a68686 2008-11-03 jas Node *np;
487 63a68686 2008-11-03 jas char *s;
488 63a68686 2008-11-03 jas int nsub = strlen(*SUBSEP);
489 63a68686 2008-11-03 jas
490 63a68686 2008-11-03 jas x = execute(a[0]); /* Cell* for symbol table */
491 63a68686 2008-11-03 jas if (!isarr(x))
492 63a68686 2008-11-03 jas return True;
493 63a68686 2008-11-03 jas if (a[1] == 0) { /* delete the elements, not the table */
494 63a68686 2008-11-03 jas freesymtab(x);
495 63a68686 2008-11-03 jas x->tval &= ~STR;
496 63a68686 2008-11-03 jas x->tval |= ARR;
497 63a68686 2008-11-03 jas x->sval = (char *) makesymtab(NSYMTAB);
498 63a68686 2008-11-03 jas } else {
499 63a68686 2008-11-03 jas int bufsz = recsize;
500 63a68686 2008-11-03 jas char *buf;
501 63a68686 2008-11-03 jas if ((buf = (char *) malloc(bufsz)) == NULL)
502 63a68686 2008-11-03 jas FATAL("out of memory in adelete");
503 63a68686 2008-11-03 jas buf[0] = 0;
504 63a68686 2008-11-03 jas for (np = a[1]; np; np = np->nnext) {
505 63a68686 2008-11-03 jas y = execute(np); /* subscript */
506 63a68686 2008-11-03 jas s = getsval(y);
507 63a68686 2008-11-03 jas if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))
508 63a68686 2008-11-03 jas FATAL("out of memory deleting %s[%s...]", x->nval, buf);
509 fa325e9b 2020-01-10 cross strcat(buf, s);
510 63a68686 2008-11-03 jas if (np->nnext)
511 63a68686 2008-11-03 jas strcat(buf, *SUBSEP);
512 63a68686 2008-11-03 jas tempfree(y);
513 63a68686 2008-11-03 jas }
514 63a68686 2008-11-03 jas freeelem(x, buf);
515 63a68686 2008-11-03 jas free(buf);
516 63a68686 2008-11-03 jas }
517 63a68686 2008-11-03 jas tempfree(x);
518 63a68686 2008-11-03 jas return True;
519 63a68686 2008-11-03 jas }
520 63a68686 2008-11-03 jas
521 63a68686 2008-11-03 jas Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
522 63a68686 2008-11-03 jas {
523 63a68686 2008-11-03 jas Cell *x, *ap, *k;
524 63a68686 2008-11-03 jas Node *p;
525 63a68686 2008-11-03 jas char *buf;
526 63a68686 2008-11-03 jas char *s;
527 63a68686 2008-11-03 jas int bufsz = recsize;
528 63a68686 2008-11-03 jas int nsub = strlen(*SUBSEP);
529 63a68686 2008-11-03 jas
530 63a68686 2008-11-03 jas ap = execute(a[1]); /* array name */
531 63a68686 2008-11-03 jas if (!isarr(ap)) {
532 63a68686 2008-11-03 jas dprintf( ("making %s into an array\n", ap->nval) );
533 63a68686 2008-11-03 jas if (freeable(ap))
534 63a68686 2008-11-03 jas xfree(ap->sval);
535 63a68686 2008-11-03 jas ap->tval &= ~(STR|NUM|DONTFREE);
536 63a68686 2008-11-03 jas ap->tval |= ARR;
537 63a68686 2008-11-03 jas ap->sval = (char *) makesymtab(NSYMTAB);
538 63a68686 2008-11-03 jas }
539 63a68686 2008-11-03 jas if ((buf = (char *) malloc(bufsz)) == NULL) {
540 63a68686 2008-11-03 jas FATAL("out of memory in intest");
541 63a68686 2008-11-03 jas }
542 63a68686 2008-11-03 jas buf[0] = 0;
543 63a68686 2008-11-03 jas for (p = a[0]; p; p = p->nnext) {
544 63a68686 2008-11-03 jas x = execute(p); /* expr */
545 63a68686 2008-11-03 jas s = getsval(x);
546 63a68686 2008-11-03 jas if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))
547 63a68686 2008-11-03 jas FATAL("out of memory deleting %s[%s...]", x->nval, buf);
548 63a68686 2008-11-03 jas strcat(buf, s);
549 63a68686 2008-11-03 jas tempfree(x);
550 63a68686 2008-11-03 jas if (p->nnext)
551 63a68686 2008-11-03 jas strcat(buf, *SUBSEP);
552 63a68686 2008-11-03 jas }
553 63a68686 2008-11-03 jas k = lookup(buf, (Array *) ap->sval);
554 63a68686 2008-11-03 jas tempfree(ap);
555 63a68686 2008-11-03 jas free(buf);
556 63a68686 2008-11-03 jas if (k == NULL)
557 63a68686 2008-11-03 jas return(False);
558 63a68686 2008-11-03 jas else
559 63a68686 2008-11-03 jas return(True);
560 63a68686 2008-11-03 jas }
561 63a68686 2008-11-03 jas
562 63a68686 2008-11-03 jas
563 63a68686 2008-11-03 jas Cell *matchop(Node **a, int n) /* ~ and match() */
564 63a68686 2008-11-03 jas {
565 63a68686 2008-11-03 jas Cell *x, *y;
566 63a68686 2008-11-03 jas char *s, *t;
567 63a68686 2008-11-03 jas int i;
568 63a68686 2008-11-03 jas void *p;
569 63a68686 2008-11-03 jas
570 63a68686 2008-11-03 jas x = execute(a[1]); /* a[1] = target text */
571 63a68686 2008-11-03 jas s = getsval(x);
572 63a68686 2008-11-03 jas if (a[0] == 0) /* a[1] == 0: already-compiled reg expr */
573 63a68686 2008-11-03 jas p = (void *) a[2];
574 63a68686 2008-11-03 jas else {
575 63a68686 2008-11-03 jas y = execute(a[2]); /* a[2] = regular expr */
576 63a68686 2008-11-03 jas t = getsval(y);
577 63a68686 2008-11-03 jas p = compre(t);
578 63a68686 2008-11-03 jas tempfree(y);
579 63a68686 2008-11-03 jas }
580 63a68686 2008-11-03 jas if (n == MATCHFCN)
581 63a68686 2008-11-03 jas i = pmatch(p, s, s);
582 63a68686 2008-11-03 jas else
583 63a68686 2008-11-03 jas i = match(p, s, s);
584 63a68686 2008-11-03 jas tempfree(x);
585 63a68686 2008-11-03 jas if (n == MATCHFCN) {
586 63a68686 2008-11-03 jas int start = countposn(s, patbeg-s)+1;
587 63a68686 2008-11-03 jas if (patlen < 0)
588 63a68686 2008-11-03 jas start = 0;
589 63a68686 2008-11-03 jas setfval(rstartloc, (Awkfloat) start);
590 63a68686 2008-11-03 jas setfval(rlengthloc, (Awkfloat) countposn(patbeg, patlen));
591 63a68686 2008-11-03 jas x = gettemp();
592 63a68686 2008-11-03 jas x->tval = NUM;
593 63a68686 2008-11-03 jas x->fval = start;
594 63a68686 2008-11-03 jas return x;
595 63a68686 2008-11-03 jas } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
596 63a68686 2008-11-03 jas return(True);
597 63a68686 2008-11-03 jas else
598 63a68686 2008-11-03 jas return(False);
599 63a68686 2008-11-03 jas }
600 63a68686 2008-11-03 jas
601 63a68686 2008-11-03 jas
602 63a68686 2008-11-03 jas Cell *boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */
603 63a68686 2008-11-03 jas {
604 63a68686 2008-11-03 jas Cell *x, *y;
605 63a68686 2008-11-03 jas int i;
606 63a68686 2008-11-03 jas
607 63a68686 2008-11-03 jas x = execute(a[0]);
608 63a68686 2008-11-03 jas i = istrue(x);
609 63a68686 2008-11-03 jas tempfree(x);
610 63a68686 2008-11-03 jas switch (n) {
611 63a68686 2008-11-03 jas case BOR:
612 63a68686 2008-11-03 jas if (i) return(True);
613 63a68686 2008-11-03 jas y = execute(a[1]);
614 63a68686 2008-11-03 jas i = istrue(y);
615 63a68686 2008-11-03 jas tempfree(y);
616 63a68686 2008-11-03 jas if (i) return(True);
617 63a68686 2008-11-03 jas else return(False);
618 63a68686 2008-11-03 jas case AND:
619 63a68686 2008-11-03 jas if ( !i ) return(False);
620 63a68686 2008-11-03 jas y = execute(a[1]);
621 63a68686 2008-11-03 jas i = istrue(y);
622 63a68686 2008-11-03 jas tempfree(y);
623 63a68686 2008-11-03 jas if (i) return(True);
624 63a68686 2008-11-03 jas else return(False);
625 63a68686 2008-11-03 jas case NOT:
626 63a68686 2008-11-03 jas if (i) return(False);
627 63a68686 2008-11-03 jas else return(True);
628 63a68686 2008-11-03 jas default: /* can't happen */
629 63a68686 2008-11-03 jas FATAL("unknown boolean operator %d", n);
630 63a68686 2008-11-03 jas }
631 63a68686 2008-11-03 jas return 0; /*NOTREACHED*/
632 63a68686 2008-11-03 jas }
633 63a68686 2008-11-03 jas
634 63a68686 2008-11-03 jas Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */
635 63a68686 2008-11-03 jas {
636 63a68686 2008-11-03 jas int i;
637 63a68686 2008-11-03 jas Cell *x, *y;
638 63a68686 2008-11-03 jas Awkfloat j;
639 63a68686 2008-11-03 jas
640 63a68686 2008-11-03 jas x = execute(a[0]);
641 63a68686 2008-11-03 jas y = execute(a[1]);
642 63a68686 2008-11-03 jas if (x->tval&NUM && y->tval&NUM) {
643 63a68686 2008-11-03 jas j = x->fval - y->fval;
644 63a68686 2008-11-03 jas i = j<0? -1: (j>0? 1: 0);
645 63a68686 2008-11-03 jas } else {
646 63a68686 2008-11-03 jas i = strcmp(getsval(x), getsval(y));
647 63a68686 2008-11-03 jas }
648 63a68686 2008-11-03 jas tempfree(x);
649 63a68686 2008-11-03 jas tempfree(y);
650 63a68686 2008-11-03 jas switch (n) {
651 63a68686 2008-11-03 jas case LT: if (i<0) return(True);
652 63a68686 2008-11-03 jas else return(False);
653 63a68686 2008-11-03 jas case LE: if (i<=0) return(True);
654 63a68686 2008-11-03 jas else return(False);
655 63a68686 2008-11-03 jas case NE: if (i!=0) return(True);
656 63a68686 2008-11-03 jas else return(False);
657 63a68686 2008-11-03 jas case EQ: if (i == 0) return(True);
658 63a68686 2008-11-03 jas else return(False);
659 63a68686 2008-11-03 jas case GE: if (i>=0) return(True);
660 63a68686 2008-11-03 jas else return(False);
661 63a68686 2008-11-03 jas case GT: if (i>0) return(True);
662 63a68686 2008-11-03 jas else return(False);
663 63a68686 2008-11-03 jas default: /* can't happen */
664 63a68686 2008-11-03 jas FATAL("unknown relational operator %d", n);
665 63a68686 2008-11-03 jas }
666 63a68686 2008-11-03 jas return 0; /*NOTREACHED*/
667 63a68686 2008-11-03 jas }
668 63a68686 2008-11-03 jas
669 63a68686 2008-11-03 jas void tfree(Cell *a) /* free a tempcell */
670 63a68686 2008-11-03 jas {
671 63a68686 2008-11-03 jas if (freeable(a)) {
672 63a68686 2008-11-03 jas dprintf( ("freeing %s %s %o\n", a->nval, a->sval, a->tval) );
673 63a68686 2008-11-03 jas xfree(a->sval);
674 63a68686 2008-11-03 jas }
675 63a68686 2008-11-03 jas if (a == tmps)
676 63a68686 2008-11-03 jas FATAL("tempcell list is curdled");
677 63a68686 2008-11-03 jas a->cnext = tmps;
678 63a68686 2008-11-03 jas tmps = a;
679 63a68686 2008-11-03 jas }
680 63a68686 2008-11-03 jas
681 63a68686 2008-11-03 jas Cell *gettemp(void) /* get a tempcell */
682 63a68686 2008-11-03 jas { int i;
683 63a68686 2008-11-03 jas Cell *x;
684 63a68686 2008-11-03 jas
685 63a68686 2008-11-03 jas if (!tmps) {
686 63a68686 2008-11-03 jas tmps = (Cell *) calloc(100, sizeof(Cell));
687 63a68686 2008-11-03 jas if (!tmps)
688 63a68686 2008-11-03 jas FATAL("out of space for temporaries");
689 63a68686 2008-11-03 jas for(i = 1; i < 100; i++)
690 63a68686 2008-11-03 jas tmps[i-1].cnext = &tmps[i];
691 63a68686 2008-11-03 jas tmps[i-1].cnext = 0;
692 63a68686 2008-11-03 jas }
693 63a68686 2008-11-03 jas x = tmps;
694 63a68686 2008-11-03 jas tmps = x->cnext;
695 63a68686 2008-11-03 jas *x = tempcell;
696 63a68686 2008-11-03 jas return(x);
697 63a68686 2008-11-03 jas }
698 63a68686 2008-11-03 jas
699 63a68686 2008-11-03 jas Cell *indirect(Node **a, int n) /* $( a[0] ) */
700 63a68686 2008-11-03 jas {
701 63a68686 2008-11-03 jas Cell *x;
702 63a68686 2008-11-03 jas int m;
703 63a68686 2008-11-03 jas char *s;
704 63a68686 2008-11-03 jas
705 63a68686 2008-11-03 jas x = execute(a[0]);
706 63a68686 2008-11-03 jas m = (int) getfval(x);
707 63a68686 2008-11-03 jas if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */
708 63a68686 2008-11-03 jas FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
709 63a68686 2008-11-03 jas /* BUG: can x->nval ever be null??? */
710 63a68686 2008-11-03 jas tempfree(x);
711 63a68686 2008-11-03 jas x = fieldadr(m);
712 63a68686 2008-11-03 jas x->ctype = OCELL; /* BUG? why are these needed? */
713 63a68686 2008-11-03 jas x->csub = CFLD;
714 63a68686 2008-11-03 jas return(x);
715 63a68686 2008-11-03 jas }
716 63a68686 2008-11-03 jas
717 63a68686 2008-11-03 jas Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */
718 63a68686 2008-11-03 jas {
719 63a68686 2008-11-03 jas int k, m, n;
720 63a68686 2008-11-03 jas char *s, *p;
721 63a68686 2008-11-03 jas int temp;
722 63a68686 2008-11-03 jas Cell *x, *y, *z = 0;
723 63a68686 2008-11-03 jas
724 63a68686 2008-11-03 jas x = execute(a[0]);
725 63a68686 2008-11-03 jas y = execute(a[1]);
726 63a68686 2008-11-03 jas if (a[2] != 0)
727 63a68686 2008-11-03 jas z = execute(a[2]);
728 63a68686 2008-11-03 jas s = getsval(x);
729 63a68686 2008-11-03 jas k = countposn(s, strlen(s)) + 1;
730 63a68686 2008-11-03 jas if (k <= 1) {
731 63a68686 2008-11-03 jas tempfree(x);
732 63a68686 2008-11-03 jas tempfree(y);
733 63a68686 2008-11-03 jas if (a[2] != 0)
734 63a68686 2008-11-03 jas tempfree(z);
735 63a68686 2008-11-03 jas x = gettemp();
736 63a68686 2008-11-03 jas setsval(x, "");
737 63a68686 2008-11-03 jas return(x);
738 63a68686 2008-11-03 jas }
739 63a68686 2008-11-03 jas m = (int) getfval(y);
740 63a68686 2008-11-03 jas if (m <= 0)
741 63a68686 2008-11-03 jas m = 1;
742 63a68686 2008-11-03 jas else if (m > k)
743 63a68686 2008-11-03 jas m = k;
744 63a68686 2008-11-03 jas tempfree(y);
745 63a68686 2008-11-03 jas if (a[2] != 0) {
746 63a68686 2008-11-03 jas n = (int) getfval(z);
747 63a68686 2008-11-03 jas tempfree(z);
748 63a68686 2008-11-03 jas } else
749 63a68686 2008-11-03 jas n = k - 1;
750 63a68686 2008-11-03 jas if (n < 0)
751 63a68686 2008-11-03 jas n = 0;
752 63a68686 2008-11-03 jas else if (n > k - m)
753 63a68686 2008-11-03 jas n = k - m;
754 63a68686 2008-11-03 jas dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) );
755 63a68686 2008-11-03 jas y = gettemp();
756 63a68686 2008-11-03 jas while (*s && --m)
757 63a68686 2008-11-03 jas s += mblen(s, k);
758 63a68686 2008-11-03 jas for (p = s; *p && n--; p += mblen(p, k))
759 63a68686 2008-11-03 jas ;
760 63a68686 2008-11-03 jas temp = *p; /* with thanks to John Linderman */
761 63a68686 2008-11-03 jas *p = '\0';
762 63a68686 2008-11-03 jas setsval(y, s);
763 63a68686 2008-11-03 jas *p = temp;
764 63a68686 2008-11-03 jas tempfree(x);
765 63a68686 2008-11-03 jas return(y);
766 63a68686 2008-11-03 jas }
767 63a68686 2008-11-03 jas
768 63a68686 2008-11-03 jas Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */
769 63a68686 2008-11-03 jas {
770 63a68686 2008-11-03 jas Cell *x, *y, *z;
771 63a68686 2008-11-03 jas char *s1, *s2, *p1, *p2, *q;
772 63a68686 2008-11-03 jas Awkfloat v = 0.0;
773 63a68686 2008-11-03 jas
774 63a68686 2008-11-03 jas x = execute(a[0]);
775 63a68686 2008-11-03 jas s1 = getsval(x);
776 63a68686 2008-11-03 jas y = execute(a[1]);
777 63a68686 2008-11-03 jas s2 = getsval(y);
778 63a68686 2008-11-03 jas
779 63a68686 2008-11-03 jas z = gettemp();
780 63a68686 2008-11-03 jas for (p1 = s1; *p1 != '\0'; p1++) {
781 63a68686 2008-11-03 jas for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
782 63a68686 2008-11-03 jas ;
783 63a68686 2008-11-03 jas if (*p2 == '\0') {
784 63a68686 2008-11-03 jas v = (Awkfloat) countposn(s1, p1-s1) + 1; /* origin 1 */
785 63a68686 2008-11-03 jas break;
786 63a68686 2008-11-03 jas }
787 63a68686 2008-11-03 jas }
788 63a68686 2008-11-03 jas tempfree(x);
789 63a68686 2008-11-03 jas tempfree(y);
790 63a68686 2008-11-03 jas setfval(z, v);
791 63a68686 2008-11-03 jas return(z);
792 63a68686 2008-11-03 jas }
793 63a68686 2008-11-03 jas
794 63a68686 2008-11-03 jas #define MAXNUMSIZE 50
795 63a68686 2008-11-03 jas
796 63a68686 2008-11-03 jas int format(char **pbuf, int *pbufsize, char *s, Node *a) /* printf-like conversions */
797 63a68686 2008-11-03 jas {
798 63a68686 2008-11-03 jas char *fmt;
799 63a68686 2008-11-03 jas char *p, *t, *os;
800 63a68686 2008-11-03 jas Cell *x;
801 63a68686 2008-11-03 jas int flag = 0, n;
802 63a68686 2008-11-03 jas int fmtwd; /* format width */
803 63a68686 2008-11-03 jas int fmtsz = recsize;
804 63a68686 2008-11-03 jas char *buf = *pbuf;
805 63a68686 2008-11-03 jas int bufsize = *pbufsize;
806 63a68686 2008-11-03 jas
807 63a68686 2008-11-03 jas os = s;
808 63a68686 2008-11-03 jas p = buf;
809 63a68686 2008-11-03 jas if ((fmt = (char *) malloc(fmtsz)) == NULL)
810 63a68686 2008-11-03 jas FATAL("out of memory in format()");
811 63a68686 2008-11-03 jas while (*s) {
812 63a68686 2008-11-03 jas adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format");
813 63a68686 2008-11-03 jas if (*s != '%') {
814 63a68686 2008-11-03 jas *p++ = *s++;
815 63a68686 2008-11-03 jas continue;
816 63a68686 2008-11-03 jas }
817 63a68686 2008-11-03 jas if (*(s+1) == '%') {
818 63a68686 2008-11-03 jas *p++ = '%';
819 63a68686 2008-11-03 jas s += 2;
820 63a68686 2008-11-03 jas continue;
821 63a68686 2008-11-03 jas }
822 63a68686 2008-11-03 jas /* have to be real careful in case this is a huge number, eg, %100000d */
823 63a68686 2008-11-03 jas fmtwd = atoi(s+1);
824 63a68686 2008-11-03 jas if (fmtwd < 0)
825 63a68686 2008-11-03 jas fmtwd = -fmtwd;
826 63a68686 2008-11-03 jas adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
827 63a68686 2008-11-03 jas for (t = fmt; (*t++ = *s) != '\0'; s++) {
828 63a68686 2008-11-03 jas if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, 0))
829 63a68686 2008-11-03 jas FATAL("format item %.30s... ran format() out of memory", os);
830 63a68686 2008-11-03 jas if (isalpha(*s) && *s != 'l' && *s != 'h' && *s != 'L')
831 63a68686 2008-11-03 jas break; /* the ansi panoply */
832 63a68686 2008-11-03 jas if (*s == '*') {
833 63a68686 2008-11-03 jas x = execute(a);
834 63a68686 2008-11-03 jas a = a->nnext;
835 63a68686 2008-11-03 jas sprintf(t-1, "%d", fmtwd=(int) getfval(x));
836 63a68686 2008-11-03 jas if (fmtwd < 0)
837 63a68686 2008-11-03 jas fmtwd = -fmtwd;
838 63a68686 2008-11-03 jas adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
839 63a68686 2008-11-03 jas t = fmt + strlen(fmt);
840 63a68686 2008-11-03 jas tempfree(x);
841 63a68686 2008-11-03 jas }
842 63a68686 2008-11-03 jas }
843 63a68686 2008-11-03 jas *t = '\0';
844 63a68686 2008-11-03 jas if (fmtwd < 0)
845 63a68686 2008-11-03 jas fmtwd = -fmtwd;
846 63a68686 2008-11-03 jas adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
847 63a68686 2008-11-03 jas
848 63a68686 2008-11-03 jas switch (*s) {
849 63a68686 2008-11-03 jas case 'f': case 'e': case 'g': case 'E': case 'G':
850 63a68686 2008-11-03 jas flag = 1;
851 63a68686 2008-11-03 jas break;
852 63a68686 2008-11-03 jas case 'd': case 'i':
853 63a68686 2008-11-03 jas flag = 2;
854 63a68686 2008-11-03 jas if(*(s-1) == 'l') break;
855 63a68686 2008-11-03 jas *(t-1) = 'l';
856 63a68686 2008-11-03 jas *t = 'd';
857 63a68686 2008-11-03 jas *++t = '\0';
858 63a68686 2008-11-03 jas break;
859 63a68686 2008-11-03 jas case 'o': case 'x': case 'X': case 'u':
860 63a68686 2008-11-03 jas flag = *(s-1) == 'l' ? 2 : 3;
861 63a68686 2008-11-03 jas break;
862 63a68686 2008-11-03 jas case 's':
863 63a68686 2008-11-03 jas flag = 4;
864 63a68686 2008-11-03 jas break;
865 63a68686 2008-11-03 jas case 'c':
866 63a68686 2008-11-03 jas flag = 5;
867 63a68686 2008-11-03 jas break;
868 63a68686 2008-11-03 jas default:
869 63a68686 2008-11-03 jas WARNING("weird printf conversion %s", fmt);
870 63a68686 2008-11-03 jas flag = 0;
871 63a68686 2008-11-03 jas break;
872 63a68686 2008-11-03 jas }
873 63a68686 2008-11-03 jas if (a == NULL)
874 63a68686 2008-11-03 jas FATAL("not enough args in printf(%s)", os);
875 63a68686 2008-11-03 jas x = execute(a);
876 63a68686 2008-11-03 jas a = a->nnext;
877 63a68686 2008-11-03 jas n = MAXNUMSIZE;
878 63a68686 2008-11-03 jas if (fmtwd > n)
879 63a68686 2008-11-03 jas n = fmtwd;
880 63a68686 2008-11-03 jas adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format");
881 63a68686 2008-11-03 jas switch (flag) {
882 63a68686 2008-11-03 jas case 0: sprintf(p, "%s", fmt); /* unknown, so dump it too */
883 63a68686 2008-11-03 jas t = getsval(x);
884 63a68686 2008-11-03 jas n = strlen(t);
885 63a68686 2008-11-03 jas if (fmtwd > n)
886 63a68686 2008-11-03 jas n = fmtwd;
887 63a68686 2008-11-03 jas adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format");
888 63a68686 2008-11-03 jas p += strlen(p);
889 63a68686 2008-11-03 jas sprintf(p, "%s", t);
890 63a68686 2008-11-03 jas break;
891 63a68686 2008-11-03 jas case 1: sprintf(p, fmt, getfval(x)); break;
892 63a68686 2008-11-03 jas case 2: sprintf(p, fmt, (long) getfval(x)); break;
893 63a68686 2008-11-03 jas case 3: sprintf(p, fmt, (int) getfval(x)); break;
894 63a68686 2008-11-03 jas case 4:
895 63a68686 2008-11-03 jas t = getsval(x);
896 63a68686 2008-11-03 jas n = strlen(t);
897 63a68686 2008-11-03 jas if (fmtwd > n)
898 63a68686 2008-11-03 jas n = fmtwd;
899 63a68686 2008-11-03 jas if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, 0))
900 63a68686 2008-11-03 jas FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t);
901 63a68686 2008-11-03 jas sprintf(p, fmt, t);
902 63a68686 2008-11-03 jas break;
903 63a68686 2008-11-03 jas case 5:
904 63a68686 2008-11-03 jas if (isnum(x)) {
905 63a68686 2008-11-03 jas if (getfval(x))
906 63a68686 2008-11-03 jas sprintf(p, fmt, (int) getfval(x));
907 63a68686 2008-11-03 jas else{
908 63a68686 2008-11-03 jas *p++ = '\0';
909 63a68686 2008-11-03 jas *p = '\0';
910 63a68686 2008-11-03 jas }
911 63a68686 2008-11-03 jas } else
912 63a68686 2008-11-03 jas sprintf(p, fmt, getsval(x)[0]);
913 63a68686 2008-11-03 jas break;
914 63a68686 2008-11-03 jas }
915 63a68686 2008-11-03 jas tempfree(x);
916 63a68686 2008-11-03 jas p += strlen(p);
917 63a68686 2008-11-03 jas s++;
918 63a68686 2008-11-03 jas }
919 63a68686 2008-11-03 jas *p = '\0';
920 63a68686 2008-11-03 jas free(fmt);
921 63a68686 2008-11-03 jas for ( ; a; a = a->nnext) /* evaluate any remaining args */
922 63a68686 2008-11-03 jas execute(a);
923 63a68686 2008-11-03 jas *pbuf = buf;
924 63a68686 2008-11-03 jas *pbufsize = bufsize;
925 63a68686 2008-11-03 jas return p - buf;
926 63a68686 2008-11-03 jas }
927 63a68686 2008-11-03 jas
928 63a68686 2008-11-03 jas Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */
929 63a68686 2008-11-03 jas {
930 63a68686 2008-11-03 jas Cell *x;
931 63a68686 2008-11-03 jas Node *y;
932 63a68686 2008-11-03 jas char *buf;
933 63a68686 2008-11-03 jas int bufsz=3*recsize;
934 63a68686 2008-11-03 jas
935 63a68686 2008-11-03 jas if ((buf = (char *) malloc(bufsz)) == NULL)
936 63a68686 2008-11-03 jas FATAL("out of memory in awksprintf");
937 63a68686 2008-11-03 jas y = a[0]->nnext;
938 63a68686 2008-11-03 jas x = execute(a[0]);
939 63a68686 2008-11-03 jas if (format(&buf, &bufsz, getsval(x), y) == -1)
940 63a68686 2008-11-03 jas FATAL("sprintf string %.30s... too long. can't happen.", buf);
941 63a68686 2008-11-03 jas tempfree(x);
942 63a68686 2008-11-03 jas x = gettemp();
943 63a68686 2008-11-03 jas x->sval = buf;
944 63a68686 2008-11-03 jas x->tval = STR;
945 63a68686 2008-11-03 jas return(x);
946 63a68686 2008-11-03 jas }
947 63a68686 2008-11-03 jas
948 63a68686 2008-11-03 jas Cell *awkprintf(Node **a, int n) /* printf */
949 63a68686 2008-11-03 jas { /* a[0] is list of args, starting with format string */
950 63a68686 2008-11-03 jas /* a[1] is redirection operator, a[2] is redirection file */
951 63a68686 2008-11-03 jas FILE *fp;
952 63a68686 2008-11-03 jas Cell *x;
953 63a68686 2008-11-03 jas Node *y;
954 63a68686 2008-11-03 jas char *buf;
955 63a68686 2008-11-03 jas int len;
956 63a68686 2008-11-03 jas int bufsz=3*recsize;
957 63a68686 2008-11-03 jas
958 63a68686 2008-11-03 jas if ((buf = (char *) malloc(bufsz)) == NULL)
959 63a68686 2008-11-03 jas FATAL("out of memory in awkprintf");
960 63a68686 2008-11-03 jas y = a[0]->nnext;
961 63a68686 2008-11-03 jas x = execute(a[0]);
962 63a68686 2008-11-03 jas if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
963 63a68686 2008-11-03 jas FATAL("printf string %.30s... too long. can't happen.", buf);
964 63a68686 2008-11-03 jas tempfree(x);
965 63a68686 2008-11-03 jas if (a[1] == NULL) {
966 63a68686 2008-11-03 jas /* fputs(buf, stdout); */
967 63a68686 2008-11-03 jas fwrite(buf, len, 1, stdout);
968 63a68686 2008-11-03 jas if (ferror(stdout))
969 63a68686 2008-11-03 jas FATAL("write error on stdout");
970 63a68686 2008-11-03 jas } else {
971 63a68686 2008-11-03 jas fp = redirect(ptoi(a[1]), a[2]);
972 63a68686 2008-11-03 jas /* fputs(buf, fp); */
973 63a68686 2008-11-03 jas fwrite(buf, len, 1, fp);
974 63a68686 2008-11-03 jas fflush(fp);
975 63a68686 2008-11-03 jas if (ferror(fp))
976 63a68686 2008-11-03 jas FATAL("write error on %s", filename(fp));
977 63a68686 2008-11-03 jas }
978 63a68686 2008-11-03 jas free(buf);
979 63a68686 2008-11-03 jas return(True);
980 63a68686 2008-11-03 jas }
981 63a68686 2008-11-03 jas
982 63a68686 2008-11-03 jas Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */
983 63a68686 2008-11-03 jas {
984 63a68686 2008-11-03 jas Awkfloat i, j = 0;
985 63a68686 2008-11-03 jas double v;
986 63a68686 2008-11-03 jas Cell *x, *y, *z;
987 63a68686 2008-11-03 jas
988 63a68686 2008-11-03 jas x = execute(a[0]);
989 63a68686 2008-11-03 jas i = getfval(x);
990 63a68686 2008-11-03 jas tempfree(x);
991 63a68686 2008-11-03 jas if (n != UMINUS) {
992 63a68686 2008-11-03 jas y = execute(a[1]);
993 63a68686 2008-11-03 jas j = getfval(y);
994 63a68686 2008-11-03 jas tempfree(y);
995 63a68686 2008-11-03 jas }
996 63a68686 2008-11-03 jas z = gettemp();
997 63a68686 2008-11-03 jas switch (n) {
998 63a68686 2008-11-03 jas case ADD:
999 63a68686 2008-11-03 jas i += j;
1000 63a68686 2008-11-03 jas break;
1001 63a68686 2008-11-03 jas case MINUS:
1002 63a68686 2008-11-03 jas i -= j;
1003 63a68686 2008-11-03 jas break;
1004 63a68686 2008-11-03 jas case MULT:
1005 63a68686 2008-11-03 jas i *= j;
1006 63a68686 2008-11-03 jas break;
1007 63a68686 2008-11-03 jas case DIVIDE:
1008 63a68686 2008-11-03 jas if (j == 0)
1009 63a68686 2008-11-03 jas FATAL("division by zero");
1010 63a68686 2008-11-03 jas i /= j;
1011 63a68686 2008-11-03 jas break;
1012 63a68686 2008-11-03 jas case MOD:
1013 63a68686 2008-11-03 jas if (j == 0)
1014 63a68686 2008-11-03 jas FATAL("division by zero in mod");
1015 63a68686 2008-11-03 jas modf(i/j, &v);
1016 63a68686 2008-11-03 jas i = i - j * v;
1017 63a68686 2008-11-03 jas break;
1018 63a68686 2008-11-03 jas case UMINUS:
1019 63a68686 2008-11-03 jas i = -i;
1020 63a68686 2008-11-03 jas break;
1021 63a68686 2008-11-03 jas case POWER:
1022 63a68686 2008-11-03 jas if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
1023 63a68686 2008-11-03 jas i = ipow(i, (int) j);
1024 63a68686 2008-11-03 jas else
1025 63a68686 2008-11-03 jas i = errcheck(pow(i, j), "pow");
1026 63a68686 2008-11-03 jas break;
1027 63a68686 2008-11-03 jas default: /* can't happen */
1028 63a68686 2008-11-03 jas FATAL("illegal arithmetic operator %d", n);
1029 63a68686 2008-11-03 jas }
1030 63a68686 2008-11-03 jas setfval(z, i);
1031 63a68686 2008-11-03 jas return(z);
1032 63a68686 2008-11-03 jas }
1033 63a68686 2008-11-03 jas
1034 63a68686 2008-11-03 jas double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */
1035 63a68686 2008-11-03 jas {
1036 63a68686 2008-11-03 jas double v;
1037 63a68686 2008-11-03 jas
1038 63a68686 2008-11-03 jas if (n <= 0)
1039 63a68686 2008-11-03 jas return 1;
1040 63a68686 2008-11-03 jas v = ipow(x, n/2);
1041 63a68686 2008-11-03 jas if (n % 2 == 0)
1042 63a68686 2008-11-03 jas return v * v;
1043 63a68686 2008-11-03 jas else
1044 63a68686 2008-11-03 jas return x * v * v;
1045 63a68686 2008-11-03 jas }
1046 63a68686 2008-11-03 jas
1047 63a68686 2008-11-03 jas Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */
1048 63a68686 2008-11-03 jas {
1049 63a68686 2008-11-03 jas Cell *x, *z;
1050 63a68686 2008-11-03 jas int k;
1051 63a68686 2008-11-03 jas Awkfloat xf;
1052 63a68686 2008-11-03 jas
1053 63a68686 2008-11-03 jas x = execute(a[0]);
1054 63a68686 2008-11-03 jas xf = getfval(x);
1055 63a68686 2008-11-03 jas k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
1056 63a68686 2008-11-03 jas if (n == PREINCR || n == PREDECR) {
1057 63a68686 2008-11-03 jas setfval(x, xf + k);
1058 63a68686 2008-11-03 jas return(x);
1059 63a68686 2008-11-03 jas }
1060 63a68686 2008-11-03 jas z = gettemp();
1061 63a68686 2008-11-03 jas setfval(z, xf);
1062 63a68686 2008-11-03 jas setfval(x, xf + k);
1063 63a68686 2008-11-03 jas tempfree(x);
1064 63a68686 2008-11-03 jas return(z);
1065 63a68686 2008-11-03 jas }
1066 63a68686 2008-11-03 jas
1067 63a68686 2008-11-03 jas Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */
1068 63a68686 2008-11-03 jas { /* this is subtle; don't muck with it. */
1069 63a68686 2008-11-03 jas Cell *x, *y;
1070 63a68686 2008-11-03 jas Awkfloat xf, yf;
1071 63a68686 2008-11-03 jas double v;
1072 63a68686 2008-11-03 jas
1073 63a68686 2008-11-03 jas y = execute(a[1]);
1074 63a68686 2008-11-03 jas x = execute(a[0]);
1075 63a68686 2008-11-03 jas if (n == ASSIGN) { /* ordinary assignment */
1076 63a68686 2008-11-03 jas if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: */
1077 63a68686 2008-11-03 jas ; /* leave alone unless it's a field */
1078 63a68686 2008-11-03 jas else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
1079 63a68686 2008-11-03 jas setsval(x, getsval(y));
1080 63a68686 2008-11-03 jas x->fval = getfval(y);
1081 63a68686 2008-11-03 jas x->tval |= NUM;
1082 63a68686 2008-11-03 jas }
1083 63a68686 2008-11-03 jas else if (isstr(y))
1084 63a68686 2008-11-03 jas setsval(x, getsval(y));
1085 63a68686 2008-11-03 jas else if (isnum(y))
1086 63a68686 2008-11-03 jas setfval(x, getfval(y));
1087 63a68686 2008-11-03 jas else
1088 63a68686 2008-11-03 jas funnyvar(y, "read value of");
1089 63a68686 2008-11-03 jas tempfree(y);
1090 63a68686 2008-11-03 jas return(x);
1091 63a68686 2008-11-03 jas }
1092 63a68686 2008-11-03 jas xf = getfval(x);
1093 63a68686 2008-11-03 jas yf = getfval(y);
1094 63a68686 2008-11-03 jas switch (n) {
1095 63a68686 2008-11-03 jas case ADDEQ:
1096 63a68686 2008-11-03 jas xf += yf;
1097 63a68686 2008-11-03 jas break;
1098 63a68686 2008-11-03 jas case SUBEQ:
1099 63a68686 2008-11-03 jas xf -= yf;
1100 63a68686 2008-11-03 jas break;
1101 63a68686 2008-11-03 jas case MULTEQ:
1102 63a68686 2008-11-03 jas xf *= yf;
1103 63a68686 2008-11-03 jas break;
1104 63a68686 2008-11-03 jas case DIVEQ:
1105 63a68686 2008-11-03 jas if (yf == 0)
1106 63a68686 2008-11-03 jas FATAL("division by zero in /=");
1107 63a68686 2008-11-03 jas xf /= yf;
1108 63a68686 2008-11-03 jas break;
1109 63a68686 2008-11-03 jas case MODEQ:
1110 63a68686 2008-11-03 jas if (yf == 0)
1111 63a68686 2008-11-03 jas FATAL("division by zero in %%=");
1112 63a68686 2008-11-03 jas modf(xf/yf, &v);
1113 63a68686 2008-11-03 jas xf = xf - yf * v;
1114 63a68686 2008-11-03 jas break;
1115 63a68686 2008-11-03 jas case POWEQ:
1116 63a68686 2008-11-03 jas if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */
1117 63a68686 2008-11-03 jas xf = ipow(xf, (int) yf);
1118 63a68686 2008-11-03 jas else
1119 63a68686 2008-11-03 jas xf = errcheck(pow(xf, yf), "pow");
1120 63a68686 2008-11-03 jas break;
1121 63a68686 2008-11-03 jas default:
1122 63a68686 2008-11-03 jas FATAL("illegal assignment operator %d", n);
1123 63a68686 2008-11-03 jas break;
1124 63a68686 2008-11-03 jas }
1125 63a68686 2008-11-03 jas tempfree(y);
1126 63a68686 2008-11-03 jas setfval(x, xf);
1127 63a68686 2008-11-03 jas return(x);
1128 63a68686 2008-11-03 jas }
1129 63a68686 2008-11-03 jas
1130 63a68686 2008-11-03 jas Cell *cat(Node **a, int q) /* a[0] cat a[1] */
1131 63a68686 2008-11-03 jas {
1132 63a68686 2008-11-03 jas Cell *x, *y, *z;
1133 63a68686 2008-11-03 jas int n1, n2;
1134 63a68686 2008-11-03 jas char *s;
1135 63a68686 2008-11-03 jas
1136 63a68686 2008-11-03 jas x = execute(a[0]);
1137 63a68686 2008-11-03 jas y = execute(a[1]);
1138 63a68686 2008-11-03 jas getsval(x);
1139 63a68686 2008-11-03 jas getsval(y);
1140 63a68686 2008-11-03 jas n1 = strlen(x->sval);
1141 63a68686 2008-11-03 jas n2 = strlen(y->sval);
1142 63a68686 2008-11-03 jas s = (char *) malloc(n1 + n2 + 1);
1143 63a68686 2008-11-03 jas if (s == NULL)
1144 63a68686 2008-11-03 jas FATAL("out of space concatenating %.15s... and %.15s...",
1145 63a68686 2008-11-03 jas x->sval, y->sval);
1146 63a68686 2008-11-03 jas strcpy(s, x->sval);
1147 63a68686 2008-11-03 jas strcpy(s+n1, y->sval);
1148 63a68686 2008-11-03 jas tempfree(y);
1149 63a68686 2008-11-03 jas z = gettemp();
1150 63a68686 2008-11-03 jas z->sval = s;
1151 63a68686 2008-11-03 jas z->tval = STR;
1152 63a68686 2008-11-03 jas tempfree(x);
1153 63a68686 2008-11-03 jas return(z);
1154 63a68686 2008-11-03 jas }
1155 63a68686 2008-11-03 jas
1156 63a68686 2008-11-03 jas Cell *pastat(Node **a, int n) /* a[0] { a[1] } */
1157 63a68686 2008-11-03 jas {
1158 63a68686 2008-11-03 jas Cell *x;
1159 63a68686 2008-11-03 jas
1160 63a68686 2008-11-03 jas if (a[0] == 0)
1161 63a68686 2008-11-03 jas x = execute(a[1]);
1162 63a68686 2008-11-03 jas else {
1163 63a68686 2008-11-03 jas x = execute(a[0]);
1164 63a68686 2008-11-03 jas if (istrue(x)) {
1165 63a68686 2008-11-03 jas tempfree(x);
1166 63a68686 2008-11-03 jas x = execute(a[1]);
1167 63a68686 2008-11-03 jas }
1168 63a68686 2008-11-03 jas }
1169 63a68686 2008-11-03 jas return x;
1170 63a68686 2008-11-03 jas }
1171 63a68686 2008-11-03 jas
1172 63a68686 2008-11-03 jas Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */
1173 63a68686 2008-11-03 jas {
1174 63a68686 2008-11-03 jas Cell *x;
1175 63a68686 2008-11-03 jas int pair;
1176 63a68686 2008-11-03 jas
1177 63a68686 2008-11-03 jas pair = ptoi(a[3]);
1178 63a68686 2008-11-03 jas if (pairstack[pair] == 0) {
1179 63a68686 2008-11-03 jas x = execute(a[0]);
1180 63a68686 2008-11-03 jas if (istrue(x))
1181 63a68686 2008-11-03 jas pairstack[pair] = 1;
1182 63a68686 2008-11-03 jas tempfree(x);
1183 63a68686 2008-11-03 jas }
1184 63a68686 2008-11-03 jas if (pairstack[pair] == 1) {
1185 63a68686 2008-11-03 jas x = execute(a[1]);
1186 63a68686 2008-11-03 jas if (istrue(x))
1187 63a68686 2008-11-03 jas pairstack[pair] = 0;
1188 63a68686 2008-11-03 jas tempfree(x);
1189 63a68686 2008-11-03 jas x = execute(a[2]);
1190 63a68686 2008-11-03 jas return(x);
1191 63a68686 2008-11-03 jas }
1192 63a68686 2008-11-03 jas return(False);
1193 63a68686 2008-11-03 jas }
1194 63a68686 2008-11-03 jas
1195 63a68686 2008-11-03 jas Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
1196 63a68686 2008-11-03 jas {
1197 63a68686 2008-11-03 jas Cell *x = 0, *y, *ap;
1198 5a8bc789 2009-08-12 mt4swm char *s, *t, *fs = 0;
1199 5a8bc789 2009-08-12 mt4swm char temp, num[50];
1200 5a8bc789 2009-08-12 mt4swm int n, nb, sep, arg3type;
1201 63a68686 2008-11-03 jas
1202 63a68686 2008-11-03 jas y = execute(a[0]); /* source string */
1203 63a68686 2008-11-03 jas s = getsval(y);
1204 63a68686 2008-11-03 jas arg3type = ptoi(a[3]);
1205 63a68686 2008-11-03 jas if (a[2] == 0) /* fs string */
1206 63a68686 2008-11-03 jas fs = *FS;
1207 63a68686 2008-11-03 jas else if (arg3type == STRING) { /* split(str,arr,"string") */
1208 63a68686 2008-11-03 jas x = execute(a[2]);
1209 63a68686 2008-11-03 jas fs = getsval(x);
1210 63a68686 2008-11-03 jas } else if (arg3type == REGEXPR)
1211 63a68686 2008-11-03 jas fs = "(regexpr)"; /* split(str,arr,/regexpr/) */
1212 63a68686 2008-11-03 jas else
1213 63a68686 2008-11-03 jas FATAL("illegal type of split");
1214 63a68686 2008-11-03 jas sep = *fs;
1215 63a68686 2008-11-03 jas ap = execute(a[1]); /* array name */
1216 63a68686 2008-11-03 jas freesymtab(ap);
1217 63a68686 2008-11-03 jas dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs) );
1218 63a68686 2008-11-03 jas ap->tval &= ~STR;
1219 63a68686 2008-11-03 jas ap->tval |= ARR;
1220 63a68686 2008-11-03 jas ap->sval = (char *) makesymtab(NSYMTAB);
1221 63a68686 2008-11-03 jas
1222 63a68686 2008-11-03 jas n = 0;
1223 63a68686 2008-11-03 jas if ((*s != '\0' && strlen(fs) > 1) || arg3type == REGEXPR) { /* reg expr */
1224 63a68686 2008-11-03 jas void *p;
1225 63a68686 2008-11-03 jas if (arg3type == REGEXPR) { /* it's ready already */
1226 63a68686 2008-11-03 jas p = (void *) a[2];
1227 63a68686 2008-11-03 jas } else {
1228 63a68686 2008-11-03 jas p = compre(fs);
1229 63a68686 2008-11-03 jas }
1230 63a68686 2008-11-03 jas t = s;
1231 63a68686 2008-11-03 jas if (nematch(p,s,t)) {
1232 63a68686 2008-11-03 jas do {
1233 63a68686 2008-11-03 jas n++;
1234 63a68686 2008-11-03 jas sprintf(num, "%d", n);
1235 63a68686 2008-11-03 jas temp = *patbeg;
1236 63a68686 2008-11-03 jas *patbeg = '\0';
1237 63a68686 2008-11-03 jas if (is_number(t))
1238 63a68686 2008-11-03 jas setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1239 63a68686 2008-11-03 jas else
1240 63a68686 2008-11-03 jas setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1241 63a68686 2008-11-03 jas *patbeg = temp;
1242 63a68686 2008-11-03 jas t = patbeg + patlen;
1243 63a68686 2008-11-03 jas if (t[-1] == 0 || *t == 0) {
1244 63a68686 2008-11-03 jas n++;
1245 63a68686 2008-11-03 jas sprintf(num, "%d", n);
1246 63a68686 2008-11-03 jas setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
1247 63a68686 2008-11-03 jas goto spdone;
1248 63a68686 2008-11-03 jas }
1249 63a68686 2008-11-03 jas } while (nematch(p,s,t));
1250 63a68686 2008-11-03 jas }
1251 63a68686 2008-11-03 jas n++;
1252 63a68686 2008-11-03 jas sprintf(num, "%d", n);
1253 63a68686 2008-11-03 jas if (is_number(t))
1254 63a68686 2008-11-03 jas setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1255 63a68686 2008-11-03 jas else
1256 63a68686 2008-11-03 jas setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1257 63a68686 2008-11-03 jas spdone:
1258 63a68686 2008-11-03 jas p = NULL;
1259 63a68686 2008-11-03 jas } else if (sep == ' ') {
1260 63a68686 2008-11-03 jas for (n = 0; ; ) {
1261 63a68686 2008-11-03 jas while (*s == ' ' || *s == '\t' || *s == '\n')
1262 63a68686 2008-11-03 jas s++;
1263 63a68686 2008-11-03 jas if (*s == 0)
1264 63a68686 2008-11-03 jas break;
1265 63a68686 2008-11-03 jas n++;
1266 63a68686 2008-11-03 jas t = s;
1267 63a68686 2008-11-03 jas do
1268 63a68686 2008-11-03 jas s++;
1269 63a68686 2008-11-03 jas while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
1270 63a68686 2008-11-03 jas temp = *s;
1271 63a68686 2008-11-03 jas *s = '\0';
1272 63a68686 2008-11-03 jas sprintf(num, "%d", n);
1273 63a68686 2008-11-03 jas if (is_number(t))
1274 63a68686 2008-11-03 jas setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1275 63a68686 2008-11-03 jas else
1276 63a68686 2008-11-03 jas setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1277 63a68686 2008-11-03 jas *s = temp;
1278 63a68686 2008-11-03 jas if (*s != 0)
1279 63a68686 2008-11-03 jas s++;
1280 63a68686 2008-11-03 jas }
1281 63a68686 2008-11-03 jas } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */
1282 5a8bc789 2009-08-12 mt4swm for (n = 0; *s != 0; s += nb) {
1283 5a8bc789 2009-08-12 mt4swm Rune r;
1284 5a8bc789 2009-08-12 mt4swm char buf[UTFmax+1];
1285 5a8bc789 2009-08-12 mt4swm
1286 63a68686 2008-11-03 jas n++;
1287 5a8bc789 2009-08-12 mt4swm snprintf(num, sizeof num, "%d", n);
1288 5a8bc789 2009-08-12 mt4swm nb = chartorune(&r, s);
1289 5a8bc789 2009-08-12 mt4swm memmove(buf, s, nb);
1290 5a8bc789 2009-08-12 mt4swm buf[nb] = '\0';
1291 63a68686 2008-11-03 jas if (isdigit(buf[0]))
1292 63a68686 2008-11-03 jas setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval);
1293 63a68686 2008-11-03 jas else
1294 63a68686 2008-11-03 jas setsymtab(num, buf, 0.0, STR, (Array *) ap->sval);
1295 63a68686 2008-11-03 jas }
1296 63a68686 2008-11-03 jas } else if (*s != 0) {
1297 63a68686 2008-11-03 jas for (;;) {
1298 63a68686 2008-11-03 jas n++;
1299 63a68686 2008-11-03 jas t = s;
1300 63a68686 2008-11-03 jas while (*s != sep && *s != '\n' && *s != '\0')
1301 63a68686 2008-11-03 jas s++;
1302 63a68686 2008-11-03 jas temp = *s;
1303 63a68686 2008-11-03 jas *s = '\0';
1304 63a68686 2008-11-03 jas sprintf(num, "%d", n);
1305 63a68686 2008-11-03 jas if (is_number(t))
1306 63a68686 2008-11-03 jas setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1307 63a68686 2008-11-03 jas else
1308 63a68686 2008-11-03 jas setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1309 63a68686 2008-11-03 jas *s = temp;
1310 63a68686 2008-11-03 jas if (*s++ == 0)
1311 63a68686 2008-11-03 jas break;
1312 63a68686 2008-11-03 jas }
1313 63a68686 2008-11-03 jas }
1314 63a68686 2008-11-03 jas tempfree(ap);
1315 63a68686 2008-11-03 jas tempfree(y);
1316 63a68686 2008-11-03 jas if (a[2] != 0 && arg3type == STRING)
1317 63a68686 2008-11-03 jas tempfree(x);
1318 63a68686 2008-11-03 jas x = gettemp();
1319 63a68686 2008-11-03 jas x->tval = NUM;
1320 63a68686 2008-11-03 jas x->fval = n;
1321 63a68686 2008-11-03 jas return(x);
1322 63a68686 2008-11-03 jas }
1323 63a68686 2008-11-03 jas
1324 63a68686 2008-11-03 jas Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */
1325 63a68686 2008-11-03 jas {
1326 63a68686 2008-11-03 jas Cell *x;
1327 63a68686 2008-11-03 jas
1328 63a68686 2008-11-03 jas x = execute(a[0]);
1329 63a68686 2008-11-03 jas if (istrue(x)) {
1330 63a68686 2008-11-03 jas tempfree(x);
1331 63a68686 2008-11-03 jas x = execute(a[1]);
1332 63a68686 2008-11-03 jas } else {
1333 63a68686 2008-11-03 jas tempfree(x);
1334 63a68686 2008-11-03 jas x = execute(a[2]);
1335 63a68686 2008-11-03 jas }
1336 63a68686 2008-11-03 jas return(x);
1337 63a68686 2008-11-03 jas }
1338 63a68686 2008-11-03 jas
1339 63a68686 2008-11-03 jas Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */
1340 63a68686 2008-11-03 jas {
1341 63a68686 2008-11-03 jas Cell *x;
1342 63a68686 2008-11-03 jas
1343 63a68686 2008-11-03 jas x = execute(a[0]);
1344 63a68686 2008-11-03 jas if (istrue(x)) {
1345 63a68686 2008-11-03 jas tempfree(x);
1346 63a68686 2008-11-03 jas x = execute(a[1]);
1347 63a68686 2008-11-03 jas } else if (a[2] != 0) {
1348 63a68686 2008-11-03 jas tempfree(x);
1349 63a68686 2008-11-03 jas x = execute(a[2]);
1350 63a68686 2008-11-03 jas }
1351 63a68686 2008-11-03 jas return(x);
1352 63a68686 2008-11-03 jas }
1353 63a68686 2008-11-03 jas
1354 63a68686 2008-11-03 jas Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */
1355 63a68686 2008-11-03 jas {
1356 63a68686 2008-11-03 jas Cell *x;
1357 63a68686 2008-11-03 jas
1358 63a68686 2008-11-03 jas for (;;) {
1359 63a68686 2008-11-03 jas x = execute(a[0]);
1360 63a68686 2008-11-03 jas if (!istrue(x))
1361 63a68686 2008-11-03 jas return(x);
1362 63a68686 2008-11-03 jas tempfree(x);
1363 63a68686 2008-11-03 jas x = execute(a[1]);
1364 63a68686 2008-11-03 jas if (isbreak(x)) {
1365 63a68686 2008-11-03 jas x = True;
1366 63a68686 2008-11-03 jas return(x);
1367 63a68686 2008-11-03 jas }
1368 63a68686 2008-11-03 jas if (isnext(x) || isexit(x) || isret(x))
1369 63a68686 2008-11-03 jas return(x);
1370 63a68686 2008-11-03 jas tempfree(x);
1371 63a68686 2008-11-03 jas }
1372 63a68686 2008-11-03 jas }
1373 63a68686 2008-11-03 jas
1374 63a68686 2008-11-03 jas Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */
1375 63a68686 2008-11-03 jas {
1376 63a68686 2008-11-03 jas Cell *x;
1377 63a68686 2008-11-03 jas
1378 63a68686 2008-11-03 jas for (;;) {
1379 63a68686 2008-11-03 jas x = execute(a[0]);
1380 63a68686 2008-11-03 jas if (isbreak(x))
1381 63a68686 2008-11-03 jas return True;
1382 63a68686 2008-11-03 jas if (isnext(x) || isnextfile(x) || isexit(x) || isret(x))
1383 63a68686 2008-11-03 jas return(x);
1384 63a68686 2008-11-03 jas tempfree(x);
1385 63a68686 2008-11-03 jas x = execute(a[1]);
1386 63a68686 2008-11-03 jas if (!istrue(x))
1387 63a68686 2008-11-03 jas return(x);
1388 63a68686 2008-11-03 jas tempfree(x);
1389 63a68686 2008-11-03 jas }
1390 63a68686 2008-11-03 jas }
1391 63a68686 2008-11-03 jas
1392 63a68686 2008-11-03 jas Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */
1393 63a68686 2008-11-03 jas {
1394 63a68686 2008-11-03 jas Cell *x;
1395 63a68686 2008-11-03 jas
1396 63a68686 2008-11-03 jas x = execute(a[0]);
1397 63a68686 2008-11-03 jas tempfree(x);
1398 63a68686 2008-11-03 jas for (;;) {
1399 63a68686 2008-11-03 jas if (a[1]!=0) {
1400 63a68686 2008-11-03 jas x = execute(a[1]);
1401 63a68686 2008-11-03 jas if (!istrue(x)) return(x);
1402 63a68686 2008-11-03 jas else tempfree(x);
1403 63a68686 2008-11-03 jas }
1404 63a68686 2008-11-03 jas x = execute(a[3]);
1405 63a68686 2008-11-03 jas if (isbreak(x)) /* turn off break */
1406 63a68686 2008-11-03 jas return True;
1407 63a68686 2008-11-03 jas if (isnext(x) || isexit(x) || isret(x))
1408 63a68686 2008-11-03 jas return(x);
1409 63a68686 2008-11-03 jas tempfree(x);
1410 63a68686 2008-11-03 jas x = execute(a[2]);
1411 63a68686 2008-11-03 jas tempfree(x);
1412 63a68686 2008-11-03 jas }
1413 63a68686 2008-11-03 jas }
1414 63a68686 2008-11-03 jas
1415 63a68686 2008-11-03 jas Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */
1416 63a68686 2008-11-03 jas {
1417 63a68686 2008-11-03 jas Cell *x, *vp, *arrayp, *cp, *ncp;
1418 63a68686 2008-11-03 jas Array *tp;
1419 63a68686 2008-11-03 jas int i;
1420 63a68686 2008-11-03 jas
1421 63a68686 2008-11-03 jas vp = execute(a[0]);
1422 63a68686 2008-11-03 jas arrayp = execute(a[1]);
1423 63a68686 2008-11-03 jas if (!isarr(arrayp)) {
1424 63a68686 2008-11-03 jas return True;
1425 63a68686 2008-11-03 jas }
1426 63a68686 2008-11-03 jas tp = (Array *) arrayp->sval;
1427 63a68686 2008-11-03 jas tempfree(arrayp);
1428 63a68686 2008-11-03 jas for (i = 0; i < tp->size; i++) { /* this routine knows too much */
1429 63a68686 2008-11-03 jas for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1430 63a68686 2008-11-03 jas setsval(vp, cp->nval);
1431 63a68686 2008-11-03 jas ncp = cp->cnext;
1432 63a68686 2008-11-03 jas x = execute(a[2]);
1433 63a68686 2008-11-03 jas if (isbreak(x)) {
1434 63a68686 2008-11-03 jas tempfree(vp);
1435 63a68686 2008-11-03 jas return True;
1436 63a68686 2008-11-03 jas }
1437 63a68686 2008-11-03 jas if (isnext(x) || isexit(x) || isret(x)) {
1438 63a68686 2008-11-03 jas tempfree(vp);
1439 63a68686 2008-11-03 jas return(x);
1440 63a68686 2008-11-03 jas }
1441 63a68686 2008-11-03 jas tempfree(x);
1442 63a68686 2008-11-03 jas }
1443 63a68686 2008-11-03 jas }
1444 63a68686 2008-11-03 jas return True;
1445 63a68686 2008-11-03 jas }
1446 63a68686 2008-11-03 jas
1447 63a68686 2008-11-03 jas Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */
1448 63a68686 2008-11-03 jas {
1449 63a68686 2008-11-03 jas Cell *x, *y;
1450 63a68686 2008-11-03 jas Awkfloat u;
1451 63a68686 2008-11-03 jas int t;
1452 63a68686 2008-11-03 jas wchar_t wc;
1453 63a68686 2008-11-03 jas char *p, *buf;
1454 63a68686 2008-11-03 jas char mbc[50];
1455 63a68686 2008-11-03 jas Node *nextarg;
1456 63a68686 2008-11-03 jas FILE *fp;
1457 5a8bc789 2009-08-12 mt4swm void flush_all(void);
1458 63a68686 2008-11-03 jas
1459 63a68686 2008-11-03 jas t = ptoi(a[0]);
1460 63a68686 2008-11-03 jas x = execute(a[1]);
1461 63a68686 2008-11-03 jas nextarg = a[1]->nnext;
1462 63a68686 2008-11-03 jas switch (t) {
1463 63a68686 2008-11-03 jas case FLENGTH:
1464 5a8bc789 2009-08-12 mt4swm if (isarr(x))
1465 5a8bc789 2009-08-12 mt4swm u = ((Array *) x->sval)->nelem; /* GROT. should be function*/
1466 5a8bc789 2009-08-12 mt4swm else {
1467 5a8bc789 2009-08-12 mt4swm p = getsval(x);
1468 5a8bc789 2009-08-12 mt4swm u = (Awkfloat) countposn(p, strlen(p));
1469 5a8bc789 2009-08-12 mt4swm }
1470 5a8bc789 2009-08-12 mt4swm break;
1471 63a68686 2008-11-03 jas case FLOG:
1472 63a68686 2008-11-03 jas u = errcheck(log(getfval(x)), "log"); break;
1473 63a68686 2008-11-03 jas case FINT:
1474 63a68686 2008-11-03 jas modf(getfval(x), &u); break;
1475 63a68686 2008-11-03 jas case FEXP:
1476 63a68686 2008-11-03 jas u = errcheck(exp(getfval(x)), "exp"); break;
1477 63a68686 2008-11-03 jas case FSQRT:
1478 63a68686 2008-11-03 jas u = errcheck(sqrt(getfval(x)), "sqrt"); break;
1479 63a68686 2008-11-03 jas case FSIN:
1480 63a68686 2008-11-03 jas u = sin(getfval(x)); break;
1481 63a68686 2008-11-03 jas case FCOS:
1482 63a68686 2008-11-03 jas u = cos(getfval(x)); break;
1483 63a68686 2008-11-03 jas case FATAN:
1484 63a68686 2008-11-03 jas if (nextarg == 0) {
1485 63a68686 2008-11-03 jas WARNING("atan2 requires two arguments; returning 1.0");
1486 63a68686 2008-11-03 jas u = 1.0;
1487 63a68686 2008-11-03 jas } else {
1488 63a68686 2008-11-03 jas y = execute(a[1]->nnext);
1489 63a68686 2008-11-03 jas u = atan2(getfval(x), getfval(y));
1490 63a68686 2008-11-03 jas tempfree(y);
1491 63a68686 2008-11-03 jas nextarg = nextarg->nnext;
1492 63a68686 2008-11-03 jas }
1493 63a68686 2008-11-03 jas break;
1494 63a68686 2008-11-03 jas case FSYSTEM:
1495 63a68686 2008-11-03 jas fflush(stdout); /* in case something is buffered already */
1496 63a68686 2008-11-03 jas u = (Awkfloat) system(getsval(x)) / 256; /* 256 is unix-dep */
1497 63a68686 2008-11-03 jas break;
1498 63a68686 2008-11-03 jas case FRAND:
1499 63a68686 2008-11-03 jas /* in principle, rand() returns something in 0..RAND_MAX */
1500 63a68686 2008-11-03 jas u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX;
1501 63a68686 2008-11-03 jas break;
1502 63a68686 2008-11-03 jas case FSRAND:
1503 63a68686 2008-11-03 jas if (isrec(x)) /* no argument provided */
1504 63a68686 2008-11-03 jas u = time((time_t *)0);
1505 63a68686 2008-11-03 jas else
1506 63a68686 2008-11-03 jas u = getfval(x);
1507 63a68686 2008-11-03 jas srand((unsigned int) u);
1508 63a68686 2008-11-03 jas break;
1509 63a68686 2008-11-03 jas case FTOUPPER:
1510 63a68686 2008-11-03 jas case FTOLOWER:
1511 63a68686 2008-11-03 jas buf = tostring(getsval(x));
1512 63a68686 2008-11-03 jas if (t == FTOUPPER) {
1513 63a68686 2008-11-03 jas for (p = buf; *p; p++)
1514 63a68686 2008-11-03 jas if (islower(*p))
1515 63a68686 2008-11-03 jas *p = toupper(*p);
1516 63a68686 2008-11-03 jas } else {
1517 63a68686 2008-11-03 jas for (p = buf; *p; p++)
1518 63a68686 2008-11-03 jas if (isupper(*p))
1519 63a68686 2008-11-03 jas *p = tolower(*p);
1520 63a68686 2008-11-03 jas }
1521 63a68686 2008-11-03 jas tempfree(x);
1522 63a68686 2008-11-03 jas x = gettemp();
1523 63a68686 2008-11-03 jas setsval(x, buf);
1524 63a68686 2008-11-03 jas free(buf);
1525 63a68686 2008-11-03 jas return x;
1526 63a68686 2008-11-03 jas case FFLUSH:
1527 5a8bc789 2009-08-12 mt4swm if (isrec(x) || strlen(getsval(x)) == 0) {
1528 5a8bc789 2009-08-12 mt4swm flush_all(); /* fflush() or fflush("") -> all */
1529 5a8bc789 2009-08-12 mt4swm u = 0;
1530 5a8bc789 2009-08-12 mt4swm } else if ((fp = openfile(FFLUSH, getsval(x))) == NULL)
1531 63a68686 2008-11-03 jas u = EOF;
1532 63a68686 2008-11-03 jas else
1533 63a68686 2008-11-03 jas u = fflush(fp);
1534 63a68686 2008-11-03 jas break;
1535 63a68686 2008-11-03 jas case FUTF:
1536 63a68686 2008-11-03 jas wc = (int)getfval(x);
1537 63a68686 2008-11-03 jas mbc[wctomb(mbc, wc)] = 0;
1538 63a68686 2008-11-03 jas tempfree(x);
1539 63a68686 2008-11-03 jas x = gettemp();
1540 63a68686 2008-11-03 jas setsval(x, mbc);
1541 63a68686 2008-11-03 jas return x;
1542 63a68686 2008-11-03 jas default: /* can't happen */
1543 63a68686 2008-11-03 jas FATAL("illegal function type %d", t);
1544 0cfb3760 2012-10-21 rsc return(NULL);
1545 63a68686 2008-11-03 jas }
1546 63a68686 2008-11-03 jas tempfree(x);
1547 63a68686 2008-11-03 jas x = gettemp();
1548 63a68686 2008-11-03 jas setfval(x, u);
1549 63a68686 2008-11-03 jas if (nextarg != 0) {
1550 63a68686 2008-11-03 jas WARNING("warning: function has too many arguments");
1551 63a68686 2008-11-03 jas for ( ; nextarg; nextarg = nextarg->nnext)
1552 63a68686 2008-11-03 jas execute(nextarg);
1553 63a68686 2008-11-03 jas }
1554 63a68686 2008-11-03 jas return(x);
1555 63a68686 2008-11-03 jas }
1556 63a68686 2008-11-03 jas
1557 63a68686 2008-11-03 jas Cell *printstat(Node **a, int n) /* print a[0] */
1558 63a68686 2008-11-03 jas {
1559 63a68686 2008-11-03 jas int r;
1560 63a68686 2008-11-03 jas Node *x;
1561 63a68686 2008-11-03 jas Cell *y;
1562 63a68686 2008-11-03 jas FILE *fp;
1563 63a68686 2008-11-03 jas
1564 63a68686 2008-11-03 jas if (a[1] == 0) /* a[1] is redirection operator, a[2] is file */
1565 63a68686 2008-11-03 jas fp = stdout;
1566 63a68686 2008-11-03 jas else
1567 63a68686 2008-11-03 jas fp = redirect(ptoi(a[1]), a[2]);
1568 63a68686 2008-11-03 jas for (x = a[0]; x != NULL; x = x->nnext) {
1569 63a68686 2008-11-03 jas y = execute(x);
1570 63a68686 2008-11-03 jas fputs(getsval(y), fp);
1571 63a68686 2008-11-03 jas tempfree(y);
1572 63a68686 2008-11-03 jas if (x->nnext == NULL)
1573 63a68686 2008-11-03 jas r = fputs(*ORS, fp);
1574 63a68686 2008-11-03 jas else
1575 63a68686 2008-11-03 jas r = fputs(*OFS, fp);
1576 63a68686 2008-11-03 jas if (r == EOF)
1577 63a68686 2008-11-03 jas FATAL("write error on %s", filename(fp));
1578 63a68686 2008-11-03 jas }
1579 63a68686 2008-11-03 jas if (a[1] != 0)
1580 63a68686 2008-11-03 jas if (fflush(fp) == EOF)
1581 63a68686 2008-11-03 jas FATAL("write error on %s", filename(fp));
1582 63a68686 2008-11-03 jas return(True);
1583 63a68686 2008-11-03 jas }
1584 63a68686 2008-11-03 jas
1585 63a68686 2008-11-03 jas Cell *nullproc(Node **a, int n)
1586 63a68686 2008-11-03 jas {
1587 63a68686 2008-11-03 jas return 0;
1588 63a68686 2008-11-03 jas }
1589 63a68686 2008-11-03 jas
1590 63a68686 2008-11-03 jas
1591 63a68686 2008-11-03 jas FILE *redirect(int a, Node *b) /* set up all i/o redirections */
1592 63a68686 2008-11-03 jas {
1593 63a68686 2008-11-03 jas FILE *fp;
1594 63a68686 2008-11-03 jas Cell *x;
1595 63a68686 2008-11-03 jas char *fname;
1596 63a68686 2008-11-03 jas
1597 63a68686 2008-11-03 jas x = execute(b);
1598 63a68686 2008-11-03 jas fname = getsval(x);
1599 63a68686 2008-11-03 jas fp = openfile(a, fname);
1600 63a68686 2008-11-03 jas if (fp == NULL)
1601 63a68686 2008-11-03 jas FATAL("can't open file %s", fname);
1602 63a68686 2008-11-03 jas tempfree(x);
1603 63a68686 2008-11-03 jas return fp;
1604 63a68686 2008-11-03 jas }
1605 63a68686 2008-11-03 jas
1606 63a68686 2008-11-03 jas struct files {
1607 63a68686 2008-11-03 jas FILE *fp;
1608 63a68686 2008-11-03 jas char *fname;
1609 63a68686 2008-11-03 jas int mode; /* '|', 'a', 'w' => LE/LT, GT */
1610 63a68686 2008-11-03 jas } files[FOPEN_MAX] ={
1611 63a68686 2008-11-03 jas { NULL, "/dev/stdin", LT }, /* watch out: don't free this! */
1612 63a68686 2008-11-03 jas { NULL, "/dev/stdout", GT },
1613 63a68686 2008-11-03 jas { NULL, "/dev/stderr", GT }
1614 63a68686 2008-11-03 jas };
1615 63a68686 2008-11-03 jas
1616 63a68686 2008-11-03 jas void stdinit(void) /* in case stdin, etc., are not constants */
1617 63a68686 2008-11-03 jas {
1618 63a68686 2008-11-03 jas files[0].fp = stdin;
1619 63a68686 2008-11-03 jas files[1].fp = stdout;
1620 63a68686 2008-11-03 jas files[2].fp = stderr;
1621 63a68686 2008-11-03 jas }
1622 63a68686 2008-11-03 jas
1623 63a68686 2008-11-03 jas FILE *openfile(int a, char *us)
1624 63a68686 2008-11-03 jas {
1625 63a68686 2008-11-03 jas char *s = us;
1626 63a68686 2008-11-03 jas int i, m;
1627 63a68686 2008-11-03 jas FILE *fp = 0;
1628 63a68686 2008-11-03 jas
1629 63a68686 2008-11-03 jas if (*s == '\0')
1630 63a68686 2008-11-03 jas FATAL("null file name in print or getline");
1631 63a68686 2008-11-03 jas for (i=0; i < FOPEN_MAX; i++)
1632 63a68686 2008-11-03 jas if (files[i].fname && strcmp(s, files[i].fname) == 0) {
1633 63a68686 2008-11-03 jas if (a == files[i].mode || (a==APPEND && files[i].mode==GT))
1634 63a68686 2008-11-03 jas return files[i].fp;
1635 63a68686 2008-11-03 jas if (a == FFLUSH)
1636 63a68686 2008-11-03 jas return files[i].fp;
1637 63a68686 2008-11-03 jas }
1638 63a68686 2008-11-03 jas if (a == FFLUSH) /* didn't find it, so don't create it! */
1639 63a68686 2008-11-03 jas return NULL;
1640 63a68686 2008-11-03 jas
1641 63a68686 2008-11-03 jas for (i=0; i < FOPEN_MAX; i++)
1642 63a68686 2008-11-03 jas if (files[i].fp == 0)
1643 63a68686 2008-11-03 jas break;
1644 63a68686 2008-11-03 jas if (i >= FOPEN_MAX)
1645 63a68686 2008-11-03 jas FATAL("%s makes too many open files", s);
1646 63a68686 2008-11-03 jas fflush(stdout); /* force a semblance of order */
1647 63a68686 2008-11-03 jas m = a;
1648 63a68686 2008-11-03 jas if (a == GT) {
1649 63a68686 2008-11-03 jas fp = fopen(s, "w");
1650 63a68686 2008-11-03 jas } else if (a == APPEND) {
1651 63a68686 2008-11-03 jas fp = fopen(s, "a");
1652 63a68686 2008-11-03 jas m = GT; /* so can mix > and >> */
1653 63a68686 2008-11-03 jas } else if (a == '|') { /* output pipe */
1654 63a68686 2008-11-03 jas fp = popen(s, "w");
1655 63a68686 2008-11-03 jas } else if (a == LE) { /* input pipe */
1656 63a68686 2008-11-03 jas fp = popen(s, "r");
1657 63a68686 2008-11-03 jas } else if (a == LT) { /* getline <file */
1658 63a68686 2008-11-03 jas fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */
1659 63a68686 2008-11-03 jas } else /* can't happen */
1660 63a68686 2008-11-03 jas FATAL("illegal redirection %d", a);
1661 63a68686 2008-11-03 jas if (fp != NULL) {
1662 63a68686 2008-11-03 jas files[i].fname = tostring(s);
1663 63a68686 2008-11-03 jas files[i].fp = fp;
1664 63a68686 2008-11-03 jas files[i].mode = m;
1665 63a68686 2008-11-03 jas }
1666 63a68686 2008-11-03 jas return fp;
1667 63a68686 2008-11-03 jas }
1668 63a68686 2008-11-03 jas
1669 63a68686 2008-11-03 jas char *filename(FILE *fp)
1670 63a68686 2008-11-03 jas {
1671 63a68686 2008-11-03 jas int i;
1672 63a68686 2008-11-03 jas
1673 63a68686 2008-11-03 jas for (i = 0; i < FOPEN_MAX; i++)
1674 63a68686 2008-11-03 jas if (fp == files[i].fp)
1675 63a68686 2008-11-03 jas return files[i].fname;
1676 63a68686 2008-11-03 jas return "???";
1677 63a68686 2008-11-03 jas }
1678 63a68686 2008-11-03 jas
1679 63a68686 2008-11-03 jas Cell *closefile(Node **a, int n)
1680 63a68686 2008-11-03 jas {
1681 63a68686 2008-11-03 jas Cell *x;
1682 63a68686 2008-11-03 jas int i, stat;
1683 63a68686 2008-11-03 jas
1684 63a68686 2008-11-03 jas x = execute(a[0]);
1685 63a68686 2008-11-03 jas getsval(x);
1686 63a68686 2008-11-03 jas for (i = 0; i < FOPEN_MAX; i++)
1687 63a68686 2008-11-03 jas if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) {
1688 63a68686 2008-11-03 jas if (ferror(files[i].fp))
1689 63a68686 2008-11-03 jas WARNING( "i/o error occurred on %s", files[i].fname );
1690 63a68686 2008-11-03 jas if (files[i].mode == '|' || files[i].mode == LE)
1691 63a68686 2008-11-03 jas stat = pclose(files[i].fp);
1692 63a68686 2008-11-03 jas else
1693 63a68686 2008-11-03 jas stat = fclose(files[i].fp);
1694 63a68686 2008-11-03 jas if (stat == EOF)
1695 63a68686 2008-11-03 jas WARNING( "i/o error occurred closing %s", files[i].fname );
1696 63a68686 2008-11-03 jas if (i > 2) /* don't do /dev/std... */
1697 63a68686 2008-11-03 jas xfree(files[i].fname);
1698 63a68686 2008-11-03 jas files[i].fname = NULL; /* watch out for ref thru this */
1699 63a68686 2008-11-03 jas files[i].fp = NULL;
1700 63a68686 2008-11-03 jas }
1701 63a68686 2008-11-03 jas tempfree(x);
1702 63a68686 2008-11-03 jas return(True);
1703 63a68686 2008-11-03 jas }
1704 63a68686 2008-11-03 jas
1705 63a68686 2008-11-03 jas void closeall(void)
1706 63a68686 2008-11-03 jas {
1707 63a68686 2008-11-03 jas int i, stat;
1708 63a68686 2008-11-03 jas
1709 63a68686 2008-11-03 jas for (i = 0; i < FOPEN_MAX; i++)
1710 63a68686 2008-11-03 jas if (files[i].fp) {
1711 63a68686 2008-11-03 jas if (ferror(files[i].fp))
1712 63a68686 2008-11-03 jas WARNING( "i/o error occurred on %s", files[i].fname );
1713 63a68686 2008-11-03 jas if (files[i].mode == '|' || files[i].mode == LE)
1714 63a68686 2008-11-03 jas stat = pclose(files[i].fp);
1715 63a68686 2008-11-03 jas else
1716 63a68686 2008-11-03 jas stat = fclose(files[i].fp);
1717 63a68686 2008-11-03 jas if (stat == EOF)
1718 63a68686 2008-11-03 jas WARNING( "i/o error occurred while closing %s", files[i].fname );
1719 63a68686 2008-11-03 jas }
1720 5a8bc789 2009-08-12 mt4swm }
1721 5a8bc789 2009-08-12 mt4swm
1722 5a8bc789 2009-08-12 mt4swm void flush_all(void)
1723 5a8bc789 2009-08-12 mt4swm {
1724 5a8bc789 2009-08-12 mt4swm int i;
1725 5a8bc789 2009-08-12 mt4swm
1726 5a8bc789 2009-08-12 mt4swm for (i = 0; i < FOPEN_MAX; i++)
1727 5a8bc789 2009-08-12 mt4swm if (files[i].fp)
1728 5a8bc789 2009-08-12 mt4swm fflush(files[i].fp);
1729 63a68686 2008-11-03 jas }
1730 63a68686 2008-11-03 jas
1731 63a68686 2008-11-03 jas void backsub(char **pb_ptr, char **sptr_ptr);
1732 63a68686 2008-11-03 jas
1733 63a68686 2008-11-03 jas Cell *sub(Node **a, int nnn) /* substitute command */
1734 63a68686 2008-11-03 jas {
1735 63a68686 2008-11-03 jas char *sptr, *pb, *q;
1736 63a68686 2008-11-03 jas Cell *x, *y, *result;
1737 63a68686 2008-11-03 jas char *t, *buf;
1738 63a68686 2008-11-03 jas void *p;
1739 63a68686 2008-11-03 jas int bufsz = recsize;
1740 63a68686 2008-11-03 jas
1741 63a68686 2008-11-03 jas if ((buf = (char *) malloc(bufsz)) == NULL)
1742 63a68686 2008-11-03 jas FATAL("out of memory in sub");
1743 63a68686 2008-11-03 jas x = execute(a[3]); /* target string */
1744 63a68686 2008-11-03 jas t = getsval(x);
1745 63a68686 2008-11-03 jas if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1746 63a68686 2008-11-03 jas p = (void *) a[1]; /* regular expression */
1747 63a68686 2008-11-03 jas else {
1748 63a68686 2008-11-03 jas y = execute(a[1]);
1749 63a68686 2008-11-03 jas p = compre(getsval(y));
1750 63a68686 2008-11-03 jas tempfree(y);
1751 63a68686 2008-11-03 jas }
1752 63a68686 2008-11-03 jas y = execute(a[2]); /* replacement string */
1753 63a68686 2008-11-03 jas result = False;
1754 63a68686 2008-11-03 jas if (pmatch(p, t, t)) {
1755 63a68686 2008-11-03 jas sptr = t;
1756 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub");
1757 63a68686 2008-11-03 jas pb = buf;
1758 63a68686 2008-11-03 jas while (sptr < patbeg)
1759 63a68686 2008-11-03 jas *pb++ = *sptr++;
1760 63a68686 2008-11-03 jas sptr = getsval(y);
1761 63a68686 2008-11-03 jas while (*sptr != 0) {
1762 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub");
1763 63a68686 2008-11-03 jas if (*sptr == '\\') {
1764 63a68686 2008-11-03 jas backsub(&pb, &sptr);
1765 63a68686 2008-11-03 jas } else if (*sptr == '&') {
1766 63a68686 2008-11-03 jas sptr++;
1767 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub");
1768 63a68686 2008-11-03 jas for (q = patbeg; q < patbeg+patlen; )
1769 63a68686 2008-11-03 jas *pb++ = *q++;
1770 63a68686 2008-11-03 jas } else
1771 63a68686 2008-11-03 jas *pb++ = *sptr++;
1772 63a68686 2008-11-03 jas }
1773 63a68686 2008-11-03 jas *pb = '\0';
1774 63a68686 2008-11-03 jas if (pb > buf + bufsz)
1775 63a68686 2008-11-03 jas FATAL("sub result1 %.30s too big; can't happen", buf);
1776 63a68686 2008-11-03 jas sptr = patbeg + patlen;
1777 63a68686 2008-11-03 jas if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
1778 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
1779 63a68686 2008-11-03 jas while ((*pb++ = *sptr++) != 0)
1780 63a68686 2008-11-03 jas ;
1781 63a68686 2008-11-03 jas }
1782 63a68686 2008-11-03 jas if (pb > buf + bufsz)
1783 63a68686 2008-11-03 jas FATAL("sub result2 %.30s too big; can't happen", buf);
1784 63a68686 2008-11-03 jas setsval(x, buf); /* BUG: should be able to avoid copy */
1785 63a68686 2008-11-03 jas result = True;;
1786 63a68686 2008-11-03 jas }
1787 63a68686 2008-11-03 jas tempfree(x);
1788 63a68686 2008-11-03 jas tempfree(y);
1789 63a68686 2008-11-03 jas free(buf);
1790 63a68686 2008-11-03 jas return result;
1791 63a68686 2008-11-03 jas }
1792 63a68686 2008-11-03 jas
1793 63a68686 2008-11-03 jas Cell *gsub(Node **a, int nnn) /* global substitute */
1794 63a68686 2008-11-03 jas {
1795 63a68686 2008-11-03 jas Cell *x, *y;
1796 63a68686 2008-11-03 jas char *rptr, *sptr, *t, *pb, *c;
1797 63a68686 2008-11-03 jas char *buf;
1798 63a68686 2008-11-03 jas void *p;
1799 63a68686 2008-11-03 jas int mflag, num;
1800 63a68686 2008-11-03 jas int bufsz = recsize;
1801 63a68686 2008-11-03 jas
1802 63a68686 2008-11-03 jas if ((buf = (char *)malloc(bufsz)) == NULL)
1803 63a68686 2008-11-03 jas FATAL("out of memory in gsub");
1804 63a68686 2008-11-03 jas mflag = 0; /* if mflag == 0, can replace empty string */
1805 63a68686 2008-11-03 jas num = 0;
1806 63a68686 2008-11-03 jas x = execute(a[3]); /* target string */
1807 63a68686 2008-11-03 jas c = t = getsval(x);
1808 63a68686 2008-11-03 jas if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1809 63a68686 2008-11-03 jas p = (void *) a[1]; /* regular expression */
1810 63a68686 2008-11-03 jas else {
1811 63a68686 2008-11-03 jas y = execute(a[1]);
1812 63a68686 2008-11-03 jas p = compre(getsval(y));
1813 63a68686 2008-11-03 jas tempfree(y);
1814 63a68686 2008-11-03 jas }
1815 63a68686 2008-11-03 jas y = execute(a[2]); /* replacement string */
1816 63a68686 2008-11-03 jas if (pmatch(p, t, c)) {
1817 63a68686 2008-11-03 jas pb = buf;
1818 63a68686 2008-11-03 jas rptr = getsval(y);
1819 63a68686 2008-11-03 jas do {
1820 63a68686 2008-11-03 jas if (patlen == 0 && *patbeg != 0) { /* matched empty string */
1821 63a68686 2008-11-03 jas if (mflag == 0) { /* can replace empty */
1822 63a68686 2008-11-03 jas num++;
1823 63a68686 2008-11-03 jas sptr = rptr;
1824 63a68686 2008-11-03 jas while (*sptr != 0) {
1825 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1826 63a68686 2008-11-03 jas if (*sptr == '\\') {
1827 63a68686 2008-11-03 jas backsub(&pb, &sptr);
1828 63a68686 2008-11-03 jas } else if (*sptr == '&') {
1829 63a68686 2008-11-03 jas char *q;
1830 63a68686 2008-11-03 jas sptr++;
1831 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1832 63a68686 2008-11-03 jas for (q = patbeg; q < patbeg+patlen; )
1833 63a68686 2008-11-03 jas *pb++ = *q++;
1834 63a68686 2008-11-03 jas } else
1835 63a68686 2008-11-03 jas *pb++ = *sptr++;
1836 63a68686 2008-11-03 jas }
1837 63a68686 2008-11-03 jas }
1838 63a68686 2008-11-03 jas if (*c == 0) /* at end */
1839 63a68686 2008-11-03 jas goto done;
1840 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
1841 63a68686 2008-11-03 jas *pb++ = *c++;
1842 63a68686 2008-11-03 jas if (pb > buf + bufsz) /* BUG: not sure of this test */
1843 63a68686 2008-11-03 jas FATAL("gsub result0 %.30s too big; can't happen", buf);
1844 63a68686 2008-11-03 jas mflag = 0;
1845 63a68686 2008-11-03 jas }
1846 63a68686 2008-11-03 jas else { /* matched nonempty string */
1847 63a68686 2008-11-03 jas num++;
1848 63a68686 2008-11-03 jas sptr = c;
1849 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub");
1850 63a68686 2008-11-03 jas while (sptr < patbeg)
1851 63a68686 2008-11-03 jas *pb++ = *sptr++;
1852 63a68686 2008-11-03 jas sptr = rptr;
1853 63a68686 2008-11-03 jas while (*sptr != 0) {
1854 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1855 63a68686 2008-11-03 jas if (*sptr == '\\') {
1856 63a68686 2008-11-03 jas backsub(&pb, &sptr);
1857 63a68686 2008-11-03 jas } else if (*sptr == '&') {
1858 63a68686 2008-11-03 jas char *q;
1859 63a68686 2008-11-03 jas sptr++;
1860 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1861 63a68686 2008-11-03 jas for (q = patbeg; q < patbeg+patlen; )
1862 63a68686 2008-11-03 jas *pb++ = *q++;
1863 63a68686 2008-11-03 jas } else
1864 63a68686 2008-11-03 jas *pb++ = *sptr++;
1865 63a68686 2008-11-03 jas }
1866 63a68686 2008-11-03 jas c = patbeg + patlen;
1867 63a68686 2008-11-03 jas if ((c[-1] == 0) || (*c == 0))
1868 63a68686 2008-11-03 jas goto done;
1869 63a68686 2008-11-03 jas if (pb > buf + bufsz)
1870 63a68686 2008-11-03 jas FATAL("gsub result1 %.30s too big; can't happen", buf);
1871 63a68686 2008-11-03 jas mflag = 1;
1872 63a68686 2008-11-03 jas }
1873 63a68686 2008-11-03 jas } while (pmatch(p, t, c));
1874 63a68686 2008-11-03 jas sptr = c;
1875 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
1876 63a68686 2008-11-03 jas while ((*pb++ = *sptr++) != 0)
1877 63a68686 2008-11-03 jas ;
1878 63a68686 2008-11-03 jas done: if (pb > buf + bufsz)
1879 63a68686 2008-11-03 jas FATAL("gsub result2 %.30s too big; can't happen", buf);
1880 63a68686 2008-11-03 jas *pb = '\0';
1881 63a68686 2008-11-03 jas setsval(x, buf); /* BUG: should be able to avoid copy + free */
1882 63a68686 2008-11-03 jas }
1883 63a68686 2008-11-03 jas tempfree(x);
1884 63a68686 2008-11-03 jas tempfree(y);
1885 63a68686 2008-11-03 jas x = gettemp();
1886 63a68686 2008-11-03 jas x->tval = NUM;
1887 63a68686 2008-11-03 jas x->fval = num;
1888 63a68686 2008-11-03 jas free(buf);
1889 63a68686 2008-11-03 jas return(x);
1890 63a68686 2008-11-03 jas }
1891 63a68686 2008-11-03 jas
1892 63a68686 2008-11-03 jas void backsub(char **pb_ptr, char **sptr_ptr) /* handle \\& variations */
1893 63a68686 2008-11-03 jas { /* sptr[0] == '\\' */
1894 63a68686 2008-11-03 jas char *pb = *pb_ptr, *sptr = *sptr_ptr;
1895 63a68686 2008-11-03 jas
1896 63a68686 2008-11-03 jas if (sptr[1] == '\\') {
1897 63a68686 2008-11-03 jas if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
1898 63a68686 2008-11-03 jas *pb++ = '\\';
1899 63a68686 2008-11-03 jas *pb++ = '&';
1900 63a68686 2008-11-03 jas sptr += 4;
1901 63a68686 2008-11-03 jas } else if (sptr[2] == '&') { /* \\& -> \ + matched */
1902 63a68686 2008-11-03 jas *pb++ = '\\';
1903 63a68686 2008-11-03 jas sptr += 2;
1904 63a68686 2008-11-03 jas } else { /* \\x -> \\x */
1905 63a68686 2008-11-03 jas *pb++ = *sptr++;
1906 63a68686 2008-11-03 jas *pb++ = *sptr++;
1907 63a68686 2008-11-03 jas }
1908 63a68686 2008-11-03 jas } else if (sptr[1] == '&') { /* literal & */
1909 63a68686 2008-11-03 jas sptr++;
1910 63a68686 2008-11-03 jas *pb++ = *sptr++;
1911 63a68686 2008-11-03 jas } else /* literal \ */
1912 63a68686 2008-11-03 jas *pb++ = *sptr++;
1913 63a68686 2008-11-03 jas
1914 63a68686 2008-11-03 jas *pb_ptr = pb;
1915 63a68686 2008-11-03 jas *sptr_ptr = sptr;
1916 63a68686 2008-11-03 jas }