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