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
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
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 ****************************************************************/
25 63a68686 2008-11-03 jas #define DEBUG
26 63a68686 2008-11-03 jas #include <stdio.h>
27 63a68686 2008-11-03 jas #include <ctype.h>
28 63a68686 2008-11-03 jas #include <setjmp.h>
29 63a68686 2008-11-03 jas #include <math.h>
30 63a68686 2008-11-03 jas #include <string.h>
31 63a68686 2008-11-03 jas #include <stdlib.h>
32 63a68686 2008-11-03 jas #include <time.h>
33 5a8bc789 2009-08-12 mt4swm #include <utf.h>
34 63a68686 2008-11-03 jas #include "awk.h"
35 63a68686 2008-11-03 jas #include "y.tab.h"
37 63a68686 2008-11-03 jas #define tempfree(x) if (istemp(x)) tfree(x); else
40 63a68686 2008-11-03 jas #undef tempfree
42 63a68686 2008-11-03 jas void tempfree(Cell *p) {
43 63a68686 2008-11-03 jas if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) {
44 63a68686 2008-11-03 jas WARNING("bad csub %d in Cell %d %s",
45 63a68686 2008-11-03 jas p->csub, p->ctype, p->sval);
47 63a68686 2008-11-03 jas if (istemp(p))
52 63a68686 2008-11-03 jas #ifdef _NFILE
53 63a68686 2008-11-03 jas #ifndef FOPEN_MAX
54 63a68686 2008-11-03 jas #define FOPEN_MAX _NFILE
58 63a68686 2008-11-03 jas #ifndef FOPEN_MAX
59 63a68686 2008-11-03 jas #define FOPEN_MAX 40 /* max number of open files */
62 63a68686 2008-11-03 jas #ifndef RAND_MAX
63 63a68686 2008-11-03 jas #define RAND_MAX 32767 /* all that ansi guarantees */
67 63a68686 2008-11-03 jas extern int pairstack[];
69 63a68686 2008-11-03 jas Node *winner = NULL; /* root of parse tree */
70 63a68686 2008-11-03 jas Cell *tmps; /* free temporary cells for execution */
72 63a68686 2008-11-03 jas static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM };
73 63a68686 2008-11-03 jas Cell *True = &truecell;
74 63a68686 2008-11-03 jas static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM };
75 63a68686 2008-11-03 jas Cell *False = &falsecell;
76 63a68686 2008-11-03 jas static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM };
77 63a68686 2008-11-03 jas Cell *jbreak = &breakcell;
78 63a68686 2008-11-03 jas static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM };
79 63a68686 2008-11-03 jas Cell *jcont = &contcell;
80 63a68686 2008-11-03 jas static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM };
81 63a68686 2008-11-03 jas Cell *jnext = &nextcell;
82 63a68686 2008-11-03 jas static Cell nextfilecell ={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM };
83 63a68686 2008-11-03 jas Cell *jnextfile = &nextfilecell;
84 63a68686 2008-11-03 jas static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM };
85 63a68686 2008-11-03 jas Cell *jexit = &exitcell;
86 63a68686 2008-11-03 jas static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM };
87 63a68686 2008-11-03 jas Cell *jret = &retcell;
88 63a68686 2008-11-03 jas static Cell tempcell ={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE };
90 63a68686 2008-11-03 jas Node *curnode = NULL; /* the node being executed, for debugging */
92 63a68686 2008-11-03 jas /* buffer memory management */
93 63a68686 2008-11-03 jas int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,
94 63a68686 2008-11-03 jas char *whatrtn)
95 63a68686 2008-11-03 jas /* pbuf: address of pointer to buffer being managed
96 63a68686 2008-11-03 jas * psiz: address of buffer size variable
97 63a68686 2008-11-03 jas * minlen: minimum length of buffer needed
98 63a68686 2008-11-03 jas * quantum: buffer size quantum
99 63a68686 2008-11-03 jas * pbptr: address of movable pointer into buffer, or 0 if none
100 63a68686 2008-11-03 jas * whatrtn: name of the calling routine if failure should cause fatal error
102 63a68686 2008-11-03 jas * return 0 for realloc failure, !=0 for success
105 63a68686 2008-11-03 jas if (minlen > *psiz) {
107 63a68686 2008-11-03 jas int rminlen = quantum ? minlen % quantum : 0;
108 63a68686 2008-11-03 jas int boff = pbptr ? *pbptr - *pbuf : 0;
109 63a68686 2008-11-03 jas /* round up to next multiple of quantum */
110 63a68686 2008-11-03 jas if (rminlen)
111 63a68686 2008-11-03 jas minlen += quantum - rminlen;
112 63a68686 2008-11-03 jas tbuf = (char *) realloc(*pbuf, minlen);
113 63a68686 2008-11-03 jas if (tbuf == NULL) {
114 63a68686 2008-11-03 jas if (whatrtn)
115 63a68686 2008-11-03 jas FATAL("out of memory in %s", whatrtn);
118 63a68686 2008-11-03 jas *pbuf = tbuf;
119 63a68686 2008-11-03 jas *psiz = minlen;
121 63a68686 2008-11-03 jas *pbptr = tbuf + boff;
126 63a68686 2008-11-03 jas void run(Node *a) /* execution of parse tree starts here */
128 63a68686 2008-11-03 jas extern void stdinit(void);
135 63a68686 2008-11-03 jas Cell *execute(Node *u) /* execute a node of the parse tree */
138 63a68686 2008-11-03 jas Cell *(*proc)(Node **, int);
142 63a68686 2008-11-03 jas if (u == NULL)
143 63a68686 2008-11-03 jas return(True);
144 63a68686 2008-11-03 jas for (a = u; ; a = a->nnext) {
145 63a68686 2008-11-03 jas curnode = a;
146 63a68686 2008-11-03 jas if (isvalue(a)) {
147 63a68686 2008-11-03 jas x = (Cell *) (a->narg[0]);
148 63a68686 2008-11-03 jas if (isfld(x) && !donefld)
150 63a68686 2008-11-03 jas else if (isrec(x) && !donerec)
154 63a68686 2008-11-03 jas nobj = a->nobj;
155 63a68686 2008-11-03 jas if (notlegal(nobj)) /* probably a Cell* but too risky to print */
156 63a68686 2008-11-03 jas FATAL("illegal statement");
157 63a68686 2008-11-03 jas proc = proctab[nobj-FIRSTTOKEN];
158 63a68686 2008-11-03 jas x = (*proc)(a->narg, nobj);
159 63a68686 2008-11-03 jas if (isfld(x) && !donefld)
161 63a68686 2008-11-03 jas else if (isrec(x) && !donerec)
163 63a68686 2008-11-03 jas if (isexpr(a))
165 63a68686 2008-11-03 jas if (isjump(x))
167 63a68686 2008-11-03 jas if (a->nnext == NULL)
169 63a68686 2008-11-03 jas tempfree(x);
174 63a68686 2008-11-03 jas Cell *program(Node **a, int n) /* execute an awk program */
175 63a68686 2008-11-03 jas { /* a[0] = BEGIN, a[1] = body, a[2] = END */
178 63a68686 2008-11-03 jas if (setjmp(env) != 0)
180 63a68686 2008-11-03 jas if (a[0]) { /* BEGIN */
181 63a68686 2008-11-03 jas x = execute(a[0]);
182 63a68686 2008-11-03 jas if (isexit(x))
183 63a68686 2008-11-03 jas return(True);
184 63a68686 2008-11-03 jas if (isjump(x))
185 63a68686 2008-11-03 jas FATAL("illegal break, continue, next or nextfile from BEGIN");
186 63a68686 2008-11-03 jas tempfree(x);
188 63a68686 2008-11-03 jas if (a[1] || a[2])
189 63a68686 2008-11-03 jas while (getrec(&record, &recsize, 1) > 0) {
190 63a68686 2008-11-03 jas x = execute(a[1]);
191 63a68686 2008-11-03 jas if (isexit(x))
193 63a68686 2008-11-03 jas tempfree(x);
196 63a68686 2008-11-03 jas if (setjmp(env) != 0) /* handles exit within END */
198 63a68686 2008-11-03 jas if (a[2]) { /* END */
199 63a68686 2008-11-03 jas x = execute(a[2]);
200 63a68686 2008-11-03 jas if (isbreak(x) || isnext(x) || iscont(x))
201 63a68686 2008-11-03 jas FATAL("illegal break, continue, next or nextfile from END");
202 63a68686 2008-11-03 jas tempfree(x);
205 63a68686 2008-11-03 jas return(True);
208 63a68686 2008-11-03 jas struct Frame { /* stack frame for awk function calls */
209 63a68686 2008-11-03 jas int nargs; /* number of arguments in this call */
210 63a68686 2008-11-03 jas Cell *fcncell; /* pointer to Cell for function */
211 63a68686 2008-11-03 jas Cell **args; /* pointer to array of arguments after execute */
212 63a68686 2008-11-03 jas Cell *retval; /* return value */
215 63a68686 2008-11-03 jas #define NARGS 50 /* max args in a call */
217 63a68686 2008-11-03 jas struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */
218 63a68686 2008-11-03 jas int nframe = 0; /* number of frames allocated */
219 63a68686 2008-11-03 jas struct Frame *fp = NULL; /* frame pointer. bottom level unused */
221 63a68686 2008-11-03 jas Cell *call(Node **a, int n) /* function call. very kludgy and fragile */
223 63a68686 2008-11-03 jas static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE };
224 63a68686 2008-11-03 jas int i, ncall, ndef;
226 63a68686 2008-11-03 jas Cell *args[NARGS], *oargs[NARGS]; /* BUG: fixed size arrays */
227 63a68686 2008-11-03 jas Cell *y, *z, *fcn;
230 63a68686 2008-11-03 jas fcn = execute(a[0]); /* the function itself */
231 63a68686 2008-11-03 jas s = fcn->nval;
232 63a68686 2008-11-03 jas if (!isfcn(fcn))
233 63a68686 2008-11-03 jas FATAL("calling undefined function %s", s);
234 63a68686 2008-11-03 jas if (frame == NULL) {
235 63a68686 2008-11-03 jas fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
236 63a68686 2008-11-03 jas if (frame == NULL)
237 63a68686 2008-11-03 jas FATAL("out of space for stack frames calling %s", s);
239 63a68686 2008-11-03 jas for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */
241 63a68686 2008-11-03 jas ndef = (int) fcn->fval; /* args in defn */
242 63a68686 2008-11-03 jas dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) );
243 63a68686 2008-11-03 jas if (ncall > ndef)
244 63a68686 2008-11-03 jas WARNING("function %s called with %d args, uses only %d",
245 63a68686 2008-11-03 jas s, ncall, ndef);
246 63a68686 2008-11-03 jas if (ncall + ndef > NARGS)
247 63a68686 2008-11-03 jas FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS);
248 63a68686 2008-11-03 jas for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */
249 63a68686 2008-11-03 jas dprintf( ("evaluate args[%d], fp=%d:\n", i, (int) (fp-frame)) );
250 63a68686 2008-11-03 jas y = execute(x);
251 63a68686 2008-11-03 jas oargs[i] = y;
252 63a68686 2008-11-03 jas dprintf( ("args[%d]: %s %f <%s>, t=%o\n",
253 63a68686 2008-11-03 jas i, y->nval, y->fval, isarr(y) ? "(array)" : y->sval, y->tval) );
254 63a68686 2008-11-03 jas if (isfcn(y))
255 63a68686 2008-11-03 jas FATAL("can't use function %s as argument in %s", y->nval, s);
256 63a68686 2008-11-03 jas if (isarr(y))
257 63a68686 2008-11-03 jas args[i] = y; /* arrays by ref */
259 63a68686 2008-11-03 jas args[i] = copycell(y);
260 63a68686 2008-11-03 jas tempfree(y);
262 63a68686 2008-11-03 jas for ( ; i < ndef; i++) { /* add null args for ones not provided */
263 63a68686 2008-11-03 jas args[i] = gettemp();
264 63a68686 2008-11-03 jas *args[i] = newcopycell;
266 63a68686 2008-11-03 jas fp++; /* now ok to up frame */
267 63a68686 2008-11-03 jas if (fp >= frame + nframe) {
268 63a68686 2008-11-03 jas int dfp = fp - frame; /* old index */
269 63a68686 2008-11-03 jas frame = (struct Frame *)
270 63a68686 2008-11-03 jas realloc((char *) frame, (nframe += 100) * sizeof(struct Frame));
271 63a68686 2008-11-03 jas if (frame == NULL)
272 63a68686 2008-11-03 jas FATAL("out of space for stack frames in %s", s);
273 63a68686 2008-11-03 jas fp = frame + dfp;
275 63a68686 2008-11-03 jas fp->fcncell = fcn;
276 63a68686 2008-11-03 jas fp->args = args;
277 63a68686 2008-11-03 jas fp->nargs = ndef; /* number defined with (excess are locals) */
278 63a68686 2008-11-03 jas fp->retval = gettemp();
280 63a68686 2008-11-03 jas dprintf( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) );
281 63a68686 2008-11-03 jas y = execute((Node *)(fcn->sval)); /* execute body */
282 63a68686 2008-11-03 jas dprintf( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) );
284 63a68686 2008-11-03 jas for (i = 0; i < ndef; i++) {
285 63a68686 2008-11-03 jas Cell *t = fp->args[i];
286 63a68686 2008-11-03 jas if (isarr(t)) {
287 63a68686 2008-11-03 jas if (t->csub == CCOPY) {
288 63a68686 2008-11-03 jas if (i >= ncall) {
289 63a68686 2008-11-03 jas freesymtab(t);
290 63a68686 2008-11-03 jas t->csub = CTEMP;
291 63a68686 2008-11-03 jas tempfree(t);
293 63a68686 2008-11-03 jas oargs[i]->tval = t->tval;
294 63a68686 2008-11-03 jas oargs[i]->tval &= ~(STR|NUM|DONTFREE);
295 63a68686 2008-11-03 jas oargs[i]->sval = t->sval;
296 63a68686 2008-11-03 jas tempfree(t);
299 63a68686 2008-11-03 jas } else if (t != y) { /* kludge to prevent freeing twice */
300 63a68686 2008-11-03 jas t->csub = CTEMP;
301 63a68686 2008-11-03 jas tempfree(t);
304 63a68686 2008-11-03 jas tempfree(fcn);
305 63a68686 2008-11-03 jas if (isexit(y) || isnext(y) || isnextfile(y))
307 63a68686 2008-11-03 jas tempfree(y); /* this can free twice! */
308 63a68686 2008-11-03 jas z = fp->retval; /* return value */
309 63a68686 2008-11-03 jas dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );
314 63a68686 2008-11-03 jas Cell *copycell(Cell *x) /* make a copy of a cell in a temp */
318 63a68686 2008-11-03 jas y = gettemp();
319 63a68686 2008-11-03 jas y->csub = CCOPY; /* prevents freeing until call is over */
320 63a68686 2008-11-03 jas y->nval = x->nval; /* BUG? */
321 63a68686 2008-11-03 jas y->sval = x->sval ? tostring(x->sval) : NULL;
322 63a68686 2008-11-03 jas y->fval = x->fval;
323 63a68686 2008-11-03 jas y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */
324 63a68686 2008-11-03 jas /* is DONTFREE right? */
328 63a68686 2008-11-03 jas Cell *arg(Node **a, int n) /* nth argument of a function */
331 63a68686 2008-11-03 jas n = ptoi(a[0]); /* argument number, counting from 0 */
332 63a68686 2008-11-03 jas dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );
333 63a68686 2008-11-03 jas if (n+1 > fp->nargs)
334 63a68686 2008-11-03 jas FATAL("argument #%d of function %s was not supplied",
335 63a68686 2008-11-03 jas n+1, fp->fcncell->nval);
336 63a68686 2008-11-03 jas return fp->args[n];
339 63a68686 2008-11-03 jas Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */
343 63a68686 2008-11-03 jas switch (n) {
345 63a68686 2008-11-03 jas if (a[0] != NULL) {
346 63a68686 2008-11-03 jas y = execute(a[0]);
347 63a68686 2008-11-03 jas errorflag = (int) getfval(y);
348 63a68686 2008-11-03 jas tempfree(y);
350 63a68686 2008-11-03 jas longjmp(env, 1);
351 63a68686 2008-11-03 jas case RETURN:
352 63a68686 2008-11-03 jas if (a[0] != NULL) {
353 63a68686 2008-11-03 jas y = execute(a[0]);
354 63a68686 2008-11-03 jas if ((y->tval & (STR|NUM)) == (STR|NUM)) {
355 63a68686 2008-11-03 jas setsval(fp->retval, getsval(y));
356 63a68686 2008-11-03 jas fp->retval->fval = getfval(y);
357 63a68686 2008-11-03 jas fp->retval->tval |= NUM;
359 63a68686 2008-11-03 jas else if (y->tval & STR)
360 63a68686 2008-11-03 jas setsval(fp->retval, getsval(y));
361 63a68686 2008-11-03 jas else if (y->tval & NUM)
362 63a68686 2008-11-03 jas setfval(fp->retval, getfval(y));
363 63a68686 2008-11-03 jas else /* can't happen */
364 63a68686 2008-11-03 jas FATAL("bad type variable %d", y->tval);
365 63a68686 2008-11-03 jas tempfree(y);
367 63a68686 2008-11-03 jas return(jret);
369 63a68686 2008-11-03 jas return(jnext);
370 63a68686 2008-11-03 jas case NEXTFILE:
372 63a68686 2008-11-03 jas return(jnextfile);
374 63a68686 2008-11-03 jas return(jbreak);
375 63a68686 2008-11-03 jas case CONTINUE:
376 63a68686 2008-11-03 jas return(jcont);
377 63a68686 2008-11-03 jas default: /* can't happen */
378 63a68686 2008-11-03 jas FATAL("illegal jump type %d", n);
380 63a68686 2008-11-03 jas return 0; /* not reached */
383 63a68686 2008-11-03 jas Cell *getline(Node **a, int n) /* get next line from specific input */
384 63a68686 2008-11-03 jas { /* a[0] is variable, a[1] is operator, a[2] is filename */
385 63a68686 2008-11-03 jas Cell *r, *x;
386 63a68686 2008-11-03 jas extern Cell **fldtab;
389 63a68686 2008-11-03 jas int bufsize = recsize;
392 63a68686 2008-11-03 jas if ((buf = (char *) malloc(bufsize)) == NULL)
393 63a68686 2008-11-03 jas FATAL("out of memory in getline");
395 63a68686 2008-11-03 jas fflush(stdout); /* in case someone is waiting for a prompt */
396 63a68686 2008-11-03 jas r = gettemp();
397 63a68686 2008-11-03 jas if (a[1] != NULL) { /* getline < file */
398 63a68686 2008-11-03 jas x = execute(a[2]); /* filename */
399 63a68686 2008-11-03 jas mode = ptoi(a[1]);
400 63a68686 2008-11-03 jas if (mode == '|') /* input pipe */
401 63a68686 2008-11-03 jas mode = LE; /* arbitrary flag */
402 63a68686 2008-11-03 jas fp = openfile(mode, getsval(x));
403 63a68686 2008-11-03 jas tempfree(x);
404 63a68686 2008-11-03 jas if (fp == NULL)
407 63a68686 2008-11-03 jas n = readrec(&buf, &bufsize, fp);
408 63a68686 2008-11-03 jas if (n <= 0) {
410 63a68686 2008-11-03 jas } else if (a[0] != NULL) { /* getline var <file */
411 63a68686 2008-11-03 jas x = execute(a[0]);
412 63a68686 2008-11-03 jas setsval(x, buf);
413 63a68686 2008-11-03 jas tempfree(x);
414 63a68686 2008-11-03 jas } else { /* getline <file */
415 63a68686 2008-11-03 jas setsval(fldtab[0], buf);
416 63a68686 2008-11-03 jas if (is_number(fldtab[0]->sval)) {
417 63a68686 2008-11-03 jas fldtab[0]->fval = atof(fldtab[0]->sval);
418 63a68686 2008-11-03 jas fldtab[0]->tval |= NUM;
421 63a68686 2008-11-03 jas } else { /* bare getline; use current input */
422 63a68686 2008-11-03 jas if (a[0] == NULL) /* getline */
423 63a68686 2008-11-03 jas n = getrec(&record, &recsize, 1);
424 63a68686 2008-11-03 jas else { /* getline var */
425 63a68686 2008-11-03 jas n = getrec(&buf, &bufsize, 0);
426 63a68686 2008-11-03 jas x = execute(a[0]);
427 63a68686 2008-11-03 jas setsval(x, buf);
428 63a68686 2008-11-03 jas tempfree(x);
431 63a68686 2008-11-03 jas setfval(r, (Awkfloat) n);
436 63a68686 2008-11-03 jas Cell *getnf(Node **a, int n) /* get NF */
438 63a68686 2008-11-03 jas if (donefld == 0)
440 63a68686 2008-11-03 jas return (Cell *) a[0];
443 63a68686 2008-11-03 jas Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
445 63a68686 2008-11-03 jas Cell *x, *y, *z;
449 63a68686 2008-11-03 jas int bufsz = recsize;
450 63a68686 2008-11-03 jas int nsub = strlen(*SUBSEP);
452 63a68686 2008-11-03 jas if ((buf = (char *) malloc(bufsz)) == NULL)
453 63a68686 2008-11-03 jas FATAL("out of memory in array");
455 63a68686 2008-11-03 jas x = execute(a[0]); /* Cell* for symbol table */
457 63a68686 2008-11-03 jas for (np = a[1]; np; np = np->nnext) {
458 63a68686 2008-11-03 jas y = execute(np); /* subscript */
459 63a68686 2008-11-03 jas s = getsval(y);
460 63a68686 2008-11-03 jas if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))
461 63a68686 2008-11-03 jas FATAL("out of memory for %s[%s...]", x->nval, buf);
462 63a68686 2008-11-03 jas strcat(buf, s);
463 63a68686 2008-11-03 jas if (np->nnext)
464 63a68686 2008-11-03 jas strcat(buf, *SUBSEP);
465 63a68686 2008-11-03 jas tempfree(y);
467 63a68686 2008-11-03 jas if (!isarr(x)) {
468 63a68686 2008-11-03 jas dprintf( ("making %s into an array\n", x->nval) );
469 63a68686 2008-11-03 jas if (freeable(x))
470 63a68686 2008-11-03 jas xfree(x->sval);
471 63a68686 2008-11-03 jas x->tval &= ~(STR|NUM|DONTFREE);
472 63a68686 2008-11-03 jas x->tval |= ARR;
473 63a68686 2008-11-03 jas x->sval = (char *) makesymtab(NSYMTAB);
475 63a68686 2008-11-03 jas z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
476 63a68686 2008-11-03 jas z->ctype = OCELL;
477 63a68686 2008-11-03 jas z->csub = CVAR;
478 63a68686 2008-11-03 jas tempfree(x);
483 63a68686 2008-11-03 jas Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
485 63a68686 2008-11-03 jas Cell *x, *y;
488 63a68686 2008-11-03 jas int nsub = strlen(*SUBSEP);
490 63a68686 2008-11-03 jas x = execute(a[0]); /* Cell* for symbol table */
491 63a68686 2008-11-03 jas if (!isarr(x))
492 63a68686 2008-11-03 jas return True;
493 63a68686 2008-11-03 jas if (a[1] == 0) { /* delete the elements, not the table */
494 63a68686 2008-11-03 jas freesymtab(x);
495 63a68686 2008-11-03 jas x->tval &= ~STR;
496 63a68686 2008-11-03 jas x->tval |= ARR;
497 63a68686 2008-11-03 jas x->sval = (char *) makesymtab(NSYMTAB);
499 63a68686 2008-11-03 jas int bufsz = recsize;
501 63a68686 2008-11-03 jas if ((buf = (char *) malloc(bufsz)) == NULL)
502 63a68686 2008-11-03 jas FATAL("out of memory in adelete");
504 63a68686 2008-11-03 jas for (np = a[1]; np; np = np->nnext) {
505 63a68686 2008-11-03 jas y = execute(np); /* subscript */
506 63a68686 2008-11-03 jas s = getsval(y);
507 63a68686 2008-11-03 jas if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))
508 63a68686 2008-11-03 jas FATAL("out of memory deleting %s[%s...]", x->nval, buf);
509 63a68686 2008-11-03 jas strcat(buf, s);
510 63a68686 2008-11-03 jas if (np->nnext)
511 63a68686 2008-11-03 jas strcat(buf, *SUBSEP);
512 63a68686 2008-11-03 jas tempfree(y);
514 63a68686 2008-11-03 jas freeelem(x, buf);
517 63a68686 2008-11-03 jas tempfree(x);
518 63a68686 2008-11-03 jas return True;
521 63a68686 2008-11-03 jas Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
523 63a68686 2008-11-03 jas Cell *x, *ap, *k;
527 63a68686 2008-11-03 jas int bufsz = recsize;
528 63a68686 2008-11-03 jas int nsub = strlen(*SUBSEP);
530 63a68686 2008-11-03 jas ap = execute(a[1]); /* array name */
531 63a68686 2008-11-03 jas if (!isarr(ap)) {
532 63a68686 2008-11-03 jas dprintf( ("making %s into an array\n", ap->nval) );
533 63a68686 2008-11-03 jas if (freeable(ap))
534 63a68686 2008-11-03 jas xfree(ap->sval);
535 63a68686 2008-11-03 jas ap->tval &= ~(STR|NUM|DONTFREE);
536 63a68686 2008-11-03 jas ap->tval |= ARR;
537 63a68686 2008-11-03 jas ap->sval = (char *) makesymtab(NSYMTAB);
539 63a68686 2008-11-03 jas if ((buf = (char *) malloc(bufsz)) == NULL) {
540 63a68686 2008-11-03 jas FATAL("out of memory in intest");
543 63a68686 2008-11-03 jas for (p = a[0]; p; p = p->nnext) {
544 63a68686 2008-11-03 jas x = execute(p); /* expr */
545 63a68686 2008-11-03 jas s = getsval(x);
546 63a68686 2008-11-03 jas if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))
547 63a68686 2008-11-03 jas FATAL("out of memory deleting %s[%s...]", x->nval, buf);
548 63a68686 2008-11-03 jas strcat(buf, s);
549 63a68686 2008-11-03 jas tempfree(x);
550 63a68686 2008-11-03 jas if (p->nnext)
551 63a68686 2008-11-03 jas strcat(buf, *SUBSEP);
553 63a68686 2008-11-03 jas k = lookup(buf, (Array *) ap->sval);
554 63a68686 2008-11-03 jas tempfree(ap);
556 63a68686 2008-11-03 jas if (k == NULL)
557 63a68686 2008-11-03 jas return(False);
559 63a68686 2008-11-03 jas return(True);
563 63a68686 2008-11-03 jas Cell *matchop(Node **a, int n) /* ~ and match() */
565 63a68686 2008-11-03 jas Cell *x, *y;
566 63a68686 2008-11-03 jas char *s, *t;
570 63a68686 2008-11-03 jas x = execute(a[1]); /* a[1] = target text */
571 63a68686 2008-11-03 jas s = getsval(x);
572 63a68686 2008-11-03 jas if (a[0] == 0) /* a[1] == 0: already-compiled reg expr */
573 63a68686 2008-11-03 jas p = (void *) a[2];
575 63a68686 2008-11-03 jas y = execute(a[2]); /* a[2] = regular expr */
576 63a68686 2008-11-03 jas t = getsval(y);
577 63a68686 2008-11-03 jas p = compre(t);
578 63a68686 2008-11-03 jas tempfree(y);
580 63a68686 2008-11-03 jas if (n == MATCHFCN)
581 63a68686 2008-11-03 jas i = pmatch(p, s, s);
583 63a68686 2008-11-03 jas i = match(p, s, s);
584 63a68686 2008-11-03 jas tempfree(x);
585 63a68686 2008-11-03 jas if (n == MATCHFCN) {
586 63a68686 2008-11-03 jas int start = countposn(s, patbeg-s)+1;
587 63a68686 2008-11-03 jas if (patlen < 0)
589 63a68686 2008-11-03 jas setfval(rstartloc, (Awkfloat) start);
590 63a68686 2008-11-03 jas setfval(rlengthloc, (Awkfloat) countposn(patbeg, patlen));
591 63a68686 2008-11-03 jas x = gettemp();
592 63a68686 2008-11-03 jas x->tval = NUM;
593 63a68686 2008-11-03 jas x->fval = start;
595 63a68686 2008-11-03 jas } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
596 63a68686 2008-11-03 jas return(True);
598 63a68686 2008-11-03 jas return(False);
602 63a68686 2008-11-03 jas Cell *boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */
604 63a68686 2008-11-03 jas Cell *x, *y;
607 63a68686 2008-11-03 jas x = execute(a[0]);
608 63a68686 2008-11-03 jas i = istrue(x);
609 63a68686 2008-11-03 jas tempfree(x);
610 63a68686 2008-11-03 jas switch (n) {
612 63a68686 2008-11-03 jas if (i) return(True);
613 63a68686 2008-11-03 jas y = execute(a[1]);
614 63a68686 2008-11-03 jas i = istrue(y);
615 63a68686 2008-11-03 jas tempfree(y);
616 63a68686 2008-11-03 jas if (i) return(True);
617 63a68686 2008-11-03 jas else return(False);
619 63a68686 2008-11-03 jas if ( !i ) return(False);
620 63a68686 2008-11-03 jas y = execute(a[1]);
621 63a68686 2008-11-03 jas i = istrue(y);
622 63a68686 2008-11-03 jas tempfree(y);
623 63a68686 2008-11-03 jas if (i) return(True);
624 63a68686 2008-11-03 jas else return(False);
626 63a68686 2008-11-03 jas if (i) return(False);
627 63a68686 2008-11-03 jas else return(True);
628 63a68686 2008-11-03 jas default: /* can't happen */
629 63a68686 2008-11-03 jas FATAL("unknown boolean operator %d", n);
631 63a68686 2008-11-03 jas return 0; /*NOTREACHED*/
634 63a68686 2008-11-03 jas Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */
637 63a68686 2008-11-03 jas Cell *x, *y;
640 63a68686 2008-11-03 jas x = execute(a[0]);
641 63a68686 2008-11-03 jas y = execute(a[1]);
642 63a68686 2008-11-03 jas if (x->tval&NUM && y->tval&NUM) {
643 63a68686 2008-11-03 jas j = x->fval - y->fval;
644 63a68686 2008-11-03 jas i = j<0? -1: (j>0? 1: 0);
646 63a68686 2008-11-03 jas i = strcmp(getsval(x), getsval(y));
648 63a68686 2008-11-03 jas tempfree(x);
649 63a68686 2008-11-03 jas tempfree(y);
650 63a68686 2008-11-03 jas switch (n) {
651 63a68686 2008-11-03 jas case LT: if (i<0) return(True);
652 63a68686 2008-11-03 jas else return(False);
653 63a68686 2008-11-03 jas case LE: if (i<=0) return(True);
654 63a68686 2008-11-03 jas else return(False);
655 63a68686 2008-11-03 jas case NE: if (i!=0) return(True);
656 63a68686 2008-11-03 jas else return(False);
657 63a68686 2008-11-03 jas case EQ: if (i == 0) return(True);
658 63a68686 2008-11-03 jas else return(False);
659 63a68686 2008-11-03 jas case GE: if (i>=0) return(True);
660 63a68686 2008-11-03 jas else return(False);
661 63a68686 2008-11-03 jas case GT: if (i>0) return(True);
662 63a68686 2008-11-03 jas else return(False);
663 63a68686 2008-11-03 jas default: /* can't happen */
664 63a68686 2008-11-03 jas FATAL("unknown relational operator %d", n);
666 63a68686 2008-11-03 jas return 0; /*NOTREACHED*/
669 63a68686 2008-11-03 jas void tfree(Cell *a) /* free a tempcell */
671 63a68686 2008-11-03 jas if (freeable(a)) {
672 63a68686 2008-11-03 jas dprintf( ("freeing %s %s %o\n", a->nval, a->sval, a->tval) );
673 63a68686 2008-11-03 jas xfree(a->sval);
675 63a68686 2008-11-03 jas if (a == tmps)
676 63a68686 2008-11-03 jas FATAL("tempcell list is curdled");
677 63a68686 2008-11-03 jas a->cnext = tmps;
681 63a68686 2008-11-03 jas Cell *gettemp(void) /* get a tempcell */
685 63a68686 2008-11-03 jas if (!tmps) {
686 63a68686 2008-11-03 jas tmps = (Cell *) calloc(100, sizeof(Cell));
688 63a68686 2008-11-03 jas FATAL("out of space for temporaries");
689 63a68686 2008-11-03 jas for(i = 1; i < 100; i++)
690 63a68686 2008-11-03 jas tmps[i-1].cnext = &tmps[i];
691 63a68686 2008-11-03 jas tmps[i-1].cnext = 0;
694 63a68686 2008-11-03 jas tmps = x->cnext;
695 63a68686 2008-11-03 jas *x = tempcell;
699 63a68686 2008-11-03 jas Cell *indirect(Node **a, int n) /* $( a[0] ) */
705 63a68686 2008-11-03 jas x = execute(a[0]);
706 63a68686 2008-11-03 jas m = (int) getfval(x);
707 63a68686 2008-11-03 jas if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */
708 63a68686 2008-11-03 jas FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
709 63a68686 2008-11-03 jas /* BUG: can x->nval ever be null??? */
710 63a68686 2008-11-03 jas tempfree(x);
711 63a68686 2008-11-03 jas x = fieldadr(m);
712 63a68686 2008-11-03 jas x->ctype = OCELL; /* BUG? why are these needed? */
713 63a68686 2008-11-03 jas x->csub = CFLD;
717 63a68686 2008-11-03 jas Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */
719 63a68686 2008-11-03 jas int k, m, n;
720 63a68686 2008-11-03 jas char *s, *p;
722 63a68686 2008-11-03 jas Cell *x, *y, *z = 0;
724 63a68686 2008-11-03 jas x = execute(a[0]);
725 63a68686 2008-11-03 jas y = execute(a[1]);
726 63a68686 2008-11-03 jas if (a[2] != 0)
727 63a68686 2008-11-03 jas z = execute(a[2]);
728 63a68686 2008-11-03 jas s = getsval(x);
729 63a68686 2008-11-03 jas k = countposn(s, strlen(s)) + 1;
730 63a68686 2008-11-03 jas if (k <= 1) {
731 63a68686 2008-11-03 jas tempfree(x);
732 63a68686 2008-11-03 jas tempfree(y);
733 63a68686 2008-11-03 jas if (a[2] != 0)
734 63a68686 2008-11-03 jas tempfree(z);
735 63a68686 2008-11-03 jas x = gettemp();
736 63a68686 2008-11-03 jas setsval(x, "");
739 63a68686 2008-11-03 jas m = (int) getfval(y);
742 63a68686 2008-11-03 jas else if (m > k)
744 63a68686 2008-11-03 jas tempfree(y);
745 63a68686 2008-11-03 jas if (a[2] != 0) {
746 63a68686 2008-11-03 jas n = (int) getfval(z);
747 63a68686 2008-11-03 jas tempfree(z);
752 63a68686 2008-11-03 jas else if (n > k - m)
754 63a68686 2008-11-03 jas dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) );
755 63a68686 2008-11-03 jas y = gettemp();
756 63a68686 2008-11-03 jas while (*s && --m)
757 63a68686 2008-11-03 jas s += mblen(s, k);
758 63a68686 2008-11-03 jas for (p = s; *p && n--; p += mblen(p, k))
760 63a68686 2008-11-03 jas temp = *p; /* with thanks to John Linderman */
762 63a68686 2008-11-03 jas setsval(y, s);
764 63a68686 2008-11-03 jas tempfree(x);
768 63a68686 2008-11-03 jas Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */
770 63a68686 2008-11-03 jas Cell *x, *y, *z;
771 63a68686 2008-11-03 jas char *s1, *s2, *p1, *p2, *q;
772 63a68686 2008-11-03 jas Awkfloat v = 0.0;
774 63a68686 2008-11-03 jas x = execute(a[0]);
775 63a68686 2008-11-03 jas s1 = getsval(x);
776 63a68686 2008-11-03 jas y = execute(a[1]);
777 63a68686 2008-11-03 jas s2 = getsval(y);
779 63a68686 2008-11-03 jas z = gettemp();
780 63a68686 2008-11-03 jas for (p1 = s1; *p1 != '\0'; p1++) {
781 63a68686 2008-11-03 jas for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
783 63a68686 2008-11-03 jas if (*p2 == '\0') {
784 63a68686 2008-11-03 jas v = (Awkfloat) countposn(s1, p1-s1) + 1; /* origin 1 */
788 63a68686 2008-11-03 jas tempfree(x);
789 63a68686 2008-11-03 jas tempfree(y);
790 63a68686 2008-11-03 jas setfval(z, v);
794 63a68686 2008-11-03 jas #define MAXNUMSIZE 50
796 63a68686 2008-11-03 jas int format(char **pbuf, int *pbufsize, char *s, Node *a) /* printf-like conversions */
799 63a68686 2008-11-03 jas char *p, *t, *os;
801 63a68686 2008-11-03 jas int flag = 0, n;
802 63a68686 2008-11-03 jas int fmtwd; /* format width */
803 63a68686 2008-11-03 jas int fmtsz = recsize;
804 63a68686 2008-11-03 jas char *buf = *pbuf;
805 63a68686 2008-11-03 jas int bufsize = *pbufsize;
809 63a68686 2008-11-03 jas if ((fmt = (char *) malloc(fmtsz)) == NULL)
810 63a68686 2008-11-03 jas FATAL("out of memory in format()");
811 63a68686 2008-11-03 jas while (*s) {
812 63a68686 2008-11-03 jas adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format");
813 63a68686 2008-11-03 jas if (*s != '%') {
814 63a68686 2008-11-03 jas *p++ = *s++;
817 63a68686 2008-11-03 jas if (*(s+1) == '%') {
822 63a68686 2008-11-03 jas /* have to be real careful in case this is a huge number, eg, %100000d */
823 63a68686 2008-11-03 jas fmtwd = atoi(s+1);
824 63a68686 2008-11-03 jas if (fmtwd < 0)
825 63a68686 2008-11-03 jas fmtwd = -fmtwd;
826 63a68686 2008-11-03 jas adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
827 63a68686 2008-11-03 jas for (t = fmt; (*t++ = *s) != '\0'; s++) {
828 63a68686 2008-11-03 jas if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, 0))
829 63a68686 2008-11-03 jas FATAL("format item %.30s... ran format() out of memory", os);
830 63a68686 2008-11-03 jas if (isalpha(*s) && *s != 'l' && *s != 'h' && *s != 'L')
831 63a68686 2008-11-03 jas break; /* the ansi panoply */
832 63a68686 2008-11-03 jas if (*s == '*') {
833 63a68686 2008-11-03 jas x = execute(a);
834 63a68686 2008-11-03 jas a = a->nnext;
835 63a68686 2008-11-03 jas sprintf(t-1, "%d", fmtwd=(int) getfval(x));
836 63a68686 2008-11-03 jas if (fmtwd < 0)
837 63a68686 2008-11-03 jas fmtwd = -fmtwd;
838 63a68686 2008-11-03 jas adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
839 63a68686 2008-11-03 jas t = fmt + strlen(fmt);
840 63a68686 2008-11-03 jas tempfree(x);
844 63a68686 2008-11-03 jas if (fmtwd < 0)
845 63a68686 2008-11-03 jas fmtwd = -fmtwd;
846 63a68686 2008-11-03 jas adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
848 63a68686 2008-11-03 jas switch (*s) {
849 63a68686 2008-11-03 jas case 'f': case 'e': case 'g': case 'E': case 'G':
852 63a68686 2008-11-03 jas case 'd': case 'i':
854 63a68686 2008-11-03 jas if(*(s-1) == 'l') break;
855 63a68686 2008-11-03 jas *(t-1) = 'l';
857 63a68686 2008-11-03 jas *++t = '\0';
859 63a68686 2008-11-03 jas case 'o': case 'x': case 'X': case 'u':
860 63a68686 2008-11-03 jas flag = *(s-1) == 'l' ? 2 : 3;
869 63a68686 2008-11-03 jas WARNING("weird printf conversion %s", fmt);
873 63a68686 2008-11-03 jas if (a == NULL)
874 63a68686 2008-11-03 jas FATAL("not enough args in printf(%s)", os);
875 63a68686 2008-11-03 jas x = execute(a);
876 63a68686 2008-11-03 jas a = a->nnext;
877 63a68686 2008-11-03 jas n = MAXNUMSIZE;
878 63a68686 2008-11-03 jas if (fmtwd > n)
880 63a68686 2008-11-03 jas adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format");
881 63a68686 2008-11-03 jas switch (flag) {
882 63a68686 2008-11-03 jas case 0: sprintf(p, "%s", fmt); /* unknown, so dump it too */
883 63a68686 2008-11-03 jas t = getsval(x);
884 63a68686 2008-11-03 jas n = strlen(t);
885 63a68686 2008-11-03 jas if (fmtwd > n)
887 63a68686 2008-11-03 jas adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format");
888 63a68686 2008-11-03 jas p += strlen(p);
889 63a68686 2008-11-03 jas sprintf(p, "%s", t);
891 63a68686 2008-11-03 jas case 1: sprintf(p, fmt, getfval(x)); break;
892 63a68686 2008-11-03 jas case 2: sprintf(p, fmt, (long) getfval(x)); break;
893 63a68686 2008-11-03 jas case 3: sprintf(p, fmt, (int) getfval(x)); break;
895 63a68686 2008-11-03 jas t = getsval(x);
896 63a68686 2008-11-03 jas n = strlen(t);
897 63a68686 2008-11-03 jas if (fmtwd > n)
899 63a68686 2008-11-03 jas if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, 0))
900 63a68686 2008-11-03 jas FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t);
901 63a68686 2008-11-03 jas sprintf(p, fmt, t);
904 63a68686 2008-11-03 jas if (isnum(x)) {
905 63a68686 2008-11-03 jas if (getfval(x))
906 63a68686 2008-11-03 jas sprintf(p, fmt, (int) getfval(x));
908 63a68686 2008-11-03 jas *p++ = '\0';
912 63a68686 2008-11-03 jas sprintf(p, fmt, getsval(x)[0]);
915 63a68686 2008-11-03 jas tempfree(x);
916 63a68686 2008-11-03 jas p += strlen(p);
921 63a68686 2008-11-03 jas for ( ; a; a = a->nnext) /* evaluate any remaining args */
923 63a68686 2008-11-03 jas *pbuf = buf;
924 63a68686 2008-11-03 jas *pbufsize = bufsize;
925 63a68686 2008-11-03 jas return p - buf;
928 63a68686 2008-11-03 jas Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */
933 63a68686 2008-11-03 jas int bufsz=3*recsize;
935 63a68686 2008-11-03 jas if ((buf = (char *) malloc(bufsz)) == NULL)
936 63a68686 2008-11-03 jas FATAL("out of memory in awksprintf");
937 63a68686 2008-11-03 jas y = a[0]->nnext;
938 63a68686 2008-11-03 jas x = execute(a[0]);
939 63a68686 2008-11-03 jas if (format(&buf, &bufsz, getsval(x), y) == -1)
940 63a68686 2008-11-03 jas FATAL("sprintf string %.30s... too long. can't happen.", buf);
941 63a68686 2008-11-03 jas tempfree(x);
942 63a68686 2008-11-03 jas x = gettemp();
943 63a68686 2008-11-03 jas x->sval = buf;
944 63a68686 2008-11-03 jas x->tval = STR;
948 63a68686 2008-11-03 jas Cell *awkprintf(Node **a, int n) /* printf */
949 63a68686 2008-11-03 jas { /* a[0] is list of args, starting with format string */
950 63a68686 2008-11-03 jas /* a[1] is redirection operator, a[2] is redirection file */
956 63a68686 2008-11-03 jas int bufsz=3*recsize;
958 63a68686 2008-11-03 jas if ((buf = (char *) malloc(bufsz)) == NULL)
959 63a68686 2008-11-03 jas FATAL("out of memory in awkprintf");
960 63a68686 2008-11-03 jas y = a[0]->nnext;
961 63a68686 2008-11-03 jas x = execute(a[0]);
962 63a68686 2008-11-03 jas if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
963 63a68686 2008-11-03 jas FATAL("printf string %.30s... too long. can't happen.", buf);
964 63a68686 2008-11-03 jas tempfree(x);
965 63a68686 2008-11-03 jas if (a[1] == NULL) {
966 63a68686 2008-11-03 jas /* fputs(buf, stdout); */
967 63a68686 2008-11-03 jas fwrite(buf, len, 1, stdout);
968 63a68686 2008-11-03 jas if (ferror(stdout))
969 63a68686 2008-11-03 jas FATAL("write error on stdout");
971 63a68686 2008-11-03 jas fp = redirect(ptoi(a[1]), a[2]);
972 63a68686 2008-11-03 jas /* fputs(buf, fp); */
973 63a68686 2008-11-03 jas fwrite(buf, len, 1, fp);
975 63a68686 2008-11-03 jas if (ferror(fp))
976 63a68686 2008-11-03 jas FATAL("write error on %s", filename(fp));
979 63a68686 2008-11-03 jas return(True);
982 63a68686 2008-11-03 jas Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */
984 63a68686 2008-11-03 jas Awkfloat i, j = 0;
986 63a68686 2008-11-03 jas Cell *x, *y, *z;
988 63a68686 2008-11-03 jas x = execute(a[0]);
989 63a68686 2008-11-03 jas i = getfval(x);
990 63a68686 2008-11-03 jas tempfree(x);
991 63a68686 2008-11-03 jas if (n != UMINUS) {
992 63a68686 2008-11-03 jas y = execute(a[1]);
993 63a68686 2008-11-03 jas j = getfval(y);
994 63a68686 2008-11-03 jas tempfree(y);
996 63a68686 2008-11-03 jas z = gettemp();
997 63a68686 2008-11-03 jas switch (n) {
1001 63a68686 2008-11-03 jas case MINUS:
1007 63a68686 2008-11-03 jas case DIVIDE:
1008 63a68686 2008-11-03 jas if (j == 0)
1009 63a68686 2008-11-03 jas FATAL("division by zero");
1013 63a68686 2008-11-03 jas if (j == 0)
1014 63a68686 2008-11-03 jas FATAL("division by zero in mod");
1015 63a68686 2008-11-03 jas modf(i/j, &v);
1016 63a68686 2008-11-03 jas i = i - j * v;
1018 63a68686 2008-11-03 jas case UMINUS:
1021 63a68686 2008-11-03 jas case POWER:
1022 63a68686 2008-11-03 jas if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
1023 63a68686 2008-11-03 jas i = ipow(i, (int) j);
1025 63a68686 2008-11-03 jas i = errcheck(pow(i, j), "pow");
1027 63a68686 2008-11-03 jas default: /* can't happen */
1028 63a68686 2008-11-03 jas FATAL("illegal arithmetic operator %d", n);
1030 63a68686 2008-11-03 jas setfval(z, i);
1034 63a68686 2008-11-03 jas double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */
1038 63a68686 2008-11-03 jas if (n <= 0)
1040 63a68686 2008-11-03 jas v = ipow(x, n/2);
1041 63a68686 2008-11-03 jas if (n % 2 == 0)
1042 63a68686 2008-11-03 jas return v * v;
1044 63a68686 2008-11-03 jas return x * v * v;
1047 63a68686 2008-11-03 jas Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */
1049 63a68686 2008-11-03 jas Cell *x, *z;
1051 63a68686 2008-11-03 jas Awkfloat xf;
1053 63a68686 2008-11-03 jas x = execute(a[0]);
1054 63a68686 2008-11-03 jas xf = getfval(x);
1055 63a68686 2008-11-03 jas k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
1056 63a68686 2008-11-03 jas if (n == PREINCR || n == PREDECR) {
1057 63a68686 2008-11-03 jas setfval(x, xf + k);
1060 63a68686 2008-11-03 jas z = gettemp();
1061 63a68686 2008-11-03 jas setfval(z, xf);
1062 63a68686 2008-11-03 jas setfval(x, xf + k);
1063 63a68686 2008-11-03 jas tempfree(x);
1067 63a68686 2008-11-03 jas Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */
1068 63a68686 2008-11-03 jas { /* this is subtle; don't muck with it. */
1069 63a68686 2008-11-03 jas Cell *x, *y;
1070 63a68686 2008-11-03 jas Awkfloat xf, yf;
1073 63a68686 2008-11-03 jas y = execute(a[1]);
1074 63a68686 2008-11-03 jas x = execute(a[0]);
1075 63a68686 2008-11-03 jas if (n == ASSIGN) { /* ordinary assignment */
1076 63a68686 2008-11-03 jas if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: */
1077 63a68686 2008-11-03 jas ; /* leave alone unless it's a field */
1078 63a68686 2008-11-03 jas else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
1079 63a68686 2008-11-03 jas setsval(x, getsval(y));
1080 63a68686 2008-11-03 jas x->fval = getfval(y);
1081 63a68686 2008-11-03 jas x->tval |= NUM;
1083 63a68686 2008-11-03 jas else if (isstr(y))
1084 63a68686 2008-11-03 jas setsval(x, getsval(y));
1085 63a68686 2008-11-03 jas else if (isnum(y))
1086 63a68686 2008-11-03 jas setfval(x, getfval(y));
1088 63a68686 2008-11-03 jas funnyvar(y, "read value of");
1089 63a68686 2008-11-03 jas tempfree(y);
1092 63a68686 2008-11-03 jas xf = getfval(x);
1093 63a68686 2008-11-03 jas yf = getfval(y);
1094 63a68686 2008-11-03 jas switch (n) {
1095 63a68686 2008-11-03 jas case ADDEQ:
1098 63a68686 2008-11-03 jas case SUBEQ:
1101 63a68686 2008-11-03 jas case MULTEQ:
1104 63a68686 2008-11-03 jas case DIVEQ:
1105 63a68686 2008-11-03 jas if (yf == 0)
1106 63a68686 2008-11-03 jas FATAL("division by zero in /=");
1109 63a68686 2008-11-03 jas case MODEQ:
1110 63a68686 2008-11-03 jas if (yf == 0)
1111 63a68686 2008-11-03 jas FATAL("division by zero in %%=");
1112 63a68686 2008-11-03 jas modf(xf/yf, &v);
1113 63a68686 2008-11-03 jas xf = xf - yf * v;
1115 63a68686 2008-11-03 jas case POWEQ:
1116 63a68686 2008-11-03 jas if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */
1117 63a68686 2008-11-03 jas xf = ipow(xf, (int) yf);
1119 63a68686 2008-11-03 jas xf = errcheck(pow(xf, yf), "pow");
1122 63a68686 2008-11-03 jas FATAL("illegal assignment operator %d", n);
1125 63a68686 2008-11-03 jas tempfree(y);
1126 63a68686 2008-11-03 jas setfval(x, xf);
1130 63a68686 2008-11-03 jas Cell *cat(Node **a, int q) /* a[0] cat a[1] */
1132 63a68686 2008-11-03 jas Cell *x, *y, *z;
1133 63a68686 2008-11-03 jas int n1, n2;
1136 63a68686 2008-11-03 jas x = execute(a[0]);
1137 63a68686 2008-11-03 jas y = execute(a[1]);
1138 63a68686 2008-11-03 jas getsval(x);
1139 63a68686 2008-11-03 jas getsval(y);
1140 63a68686 2008-11-03 jas n1 = strlen(x->sval);
1141 63a68686 2008-11-03 jas n2 = strlen(y->sval);
1142 63a68686 2008-11-03 jas s = (char *) malloc(n1 + n2 + 1);
1143 63a68686 2008-11-03 jas if (s == NULL)
1144 63a68686 2008-11-03 jas FATAL("out of space concatenating %.15s... and %.15s...",
1145 63a68686 2008-11-03 jas x->sval, y->sval);
1146 63a68686 2008-11-03 jas strcpy(s, x->sval);
1147 63a68686 2008-11-03 jas strcpy(s+n1, y->sval);
1148 63a68686 2008-11-03 jas tempfree(y);
1149 63a68686 2008-11-03 jas z = gettemp();
1150 63a68686 2008-11-03 jas z->sval = s;
1151 63a68686 2008-11-03 jas z->tval = STR;
1152 63a68686 2008-11-03 jas tempfree(x);
1156 63a68686 2008-11-03 jas Cell *pastat(Node **a, int n) /* a[0] { a[1] } */
1160 63a68686 2008-11-03 jas if (a[0] == 0)
1161 63a68686 2008-11-03 jas x = execute(a[1]);
1163 63a68686 2008-11-03 jas x = execute(a[0]);
1164 63a68686 2008-11-03 jas if (istrue(x)) {
1165 63a68686 2008-11-03 jas tempfree(x);
1166 63a68686 2008-11-03 jas x = execute(a[1]);
1172 63a68686 2008-11-03 jas Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */
1177 63a68686 2008-11-03 jas pair = ptoi(a[3]);
1178 63a68686 2008-11-03 jas if (pairstack[pair] == 0) {
1179 63a68686 2008-11-03 jas x = execute(a[0]);
1180 63a68686 2008-11-03 jas if (istrue(x))
1181 63a68686 2008-11-03 jas pairstack[pair] = 1;
1182 63a68686 2008-11-03 jas tempfree(x);
1184 63a68686 2008-11-03 jas if (pairstack[pair] == 1) {
1185 63a68686 2008-11-03 jas x = execute(a[1]);
1186 63a68686 2008-11-03 jas if (istrue(x))
1187 63a68686 2008-11-03 jas pairstack[pair] = 0;
1188 63a68686 2008-11-03 jas tempfree(x);
1189 63a68686 2008-11-03 jas x = execute(a[2]);
1192 63a68686 2008-11-03 jas return(False);
1195 63a68686 2008-11-03 jas Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
1197 63a68686 2008-11-03 jas Cell *x = 0, *y, *ap;
1198 5a8bc789 2009-08-12 mt4swm char *s, *t, *fs = 0;
1199 5a8bc789 2009-08-12 mt4swm char temp, num[50];
1200 5a8bc789 2009-08-12 mt4swm int n, nb, sep, arg3type;
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 */
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/) */
1213 63a68686 2008-11-03 jas FATAL("illegal type of split");
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);
1223 63a68686 2008-11-03 jas if ((*s != '\0' && strlen(fs) > 1) || arg3type == REGEXPR) { /* reg expr */
1225 63a68686 2008-11-03 jas if (arg3type == REGEXPR) { /* it's ready already */
1226 63a68686 2008-11-03 jas p = (void *) a[2];
1228 63a68686 2008-11-03 jas p = compre(fs);
1231 63a68686 2008-11-03 jas if (nematch(p,s,t)) {
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);
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) {
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;
1249 63a68686 2008-11-03 jas } while (nematch(p,s,t));
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);
1256 63a68686 2008-11-03 jas setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
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')
1263 63a68686 2008-11-03 jas if (*s == 0)
1269 63a68686 2008-11-03 jas while (*s!=' ' && *s!='\t' && *s!='\n' && *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);
1276 63a68686 2008-11-03 jas setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1278 63a68686 2008-11-03 jas if (*s != 0)
1281 63a68686 2008-11-03 jas } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */
1282 5a8bc789 2009-08-12 mt4swm for (n = 0; *s != 0; s += nb) {
1284 5a8bc789 2009-08-12 mt4swm char buf[UTFmax+1];
1287 5a8bc789 2009-08-12 mt4swm snprintf(num, sizeof num, "%d", n);
1288 5a8bc789 2009-08-12 mt4swm nb = chartorune(&r, s);
1289 5a8bc789 2009-08-12 mt4swm memmove(buf, s, nb);
1290 5a8bc789 2009-08-12 mt4swm buf[nb] = '\0';
1291 63a68686 2008-11-03 jas if (isdigit(buf[0]))
1292 63a68686 2008-11-03 jas setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval);
1294 63a68686 2008-11-03 jas setsymtab(num, buf, 0.0, STR, (Array *) ap->sval);
1296 63a68686 2008-11-03 jas } else if (*s != 0) {
1300 63a68686 2008-11-03 jas while (*s != sep && *s != '\n' && *s != '\0')
1304 63a68686 2008-11-03 jas sprintf(num, "%d", n);
1305 63a68686 2008-11-03 jas if (is_number(t))
1306 63a68686 2008-11-03 jas setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1308 63a68686 2008-11-03 jas setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1310 63a68686 2008-11-03 jas if (*s++ == 0)
1314 63a68686 2008-11-03 jas tempfree(ap);
1315 63a68686 2008-11-03 jas tempfree(y);
1316 63a68686 2008-11-03 jas if (a[2] != 0 && arg3type == STRING)
1317 63a68686 2008-11-03 jas tempfree(x);
1318 63a68686 2008-11-03 jas x = gettemp();
1319 63a68686 2008-11-03 jas x->tval = NUM;
1320 63a68686 2008-11-03 jas x->fval = n;
1324 63a68686 2008-11-03 jas Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */
1328 63a68686 2008-11-03 jas x = execute(a[0]);
1329 63a68686 2008-11-03 jas if (istrue(x)) {
1330 63a68686 2008-11-03 jas tempfree(x);
1331 63a68686 2008-11-03 jas x = execute(a[1]);
1333 63a68686 2008-11-03 jas tempfree(x);
1334 63a68686 2008-11-03 jas x = execute(a[2]);
1339 63a68686 2008-11-03 jas Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */
1343 63a68686 2008-11-03 jas x = execute(a[0]);
1344 63a68686 2008-11-03 jas if (istrue(x)) {
1345 63a68686 2008-11-03 jas tempfree(x);
1346 63a68686 2008-11-03 jas x = execute(a[1]);
1347 63a68686 2008-11-03 jas } else if (a[2] != 0) {
1348 63a68686 2008-11-03 jas tempfree(x);
1349 63a68686 2008-11-03 jas x = execute(a[2]);
1354 63a68686 2008-11-03 jas Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */
1359 63a68686 2008-11-03 jas x = execute(a[0]);
1360 63a68686 2008-11-03 jas if (!istrue(x))
1362 63a68686 2008-11-03 jas tempfree(x);
1363 63a68686 2008-11-03 jas x = execute(a[1]);
1364 63a68686 2008-11-03 jas if (isbreak(x)) {
1368 63a68686 2008-11-03 jas if (isnext(x) || isexit(x) || isret(x))
1370 63a68686 2008-11-03 jas tempfree(x);
1374 63a68686 2008-11-03 jas Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */
1379 63a68686 2008-11-03 jas x = execute(a[0]);
1380 63a68686 2008-11-03 jas if (isbreak(x))
1381 63a68686 2008-11-03 jas return True;
1382 63a68686 2008-11-03 jas if (isnext(x) || isnextfile(x) || isexit(x) || isret(x))
1384 63a68686 2008-11-03 jas tempfree(x);
1385 63a68686 2008-11-03 jas x = execute(a[1]);
1386 63a68686 2008-11-03 jas if (!istrue(x))
1388 63a68686 2008-11-03 jas tempfree(x);
1392 63a68686 2008-11-03 jas Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */
1396 63a68686 2008-11-03 jas x = execute(a[0]);
1397 63a68686 2008-11-03 jas tempfree(x);
1399 63a68686 2008-11-03 jas if (a[1]!=0) {
1400 63a68686 2008-11-03 jas x = execute(a[1]);
1401 63a68686 2008-11-03 jas if (!istrue(x)) return(x);
1402 63a68686 2008-11-03 jas else tempfree(x);
1404 63a68686 2008-11-03 jas x = execute(a[3]);
1405 63a68686 2008-11-03 jas if (isbreak(x)) /* turn off break */
1406 63a68686 2008-11-03 jas return True;
1407 63a68686 2008-11-03 jas if (isnext(x) || isexit(x) || isret(x))
1409 63a68686 2008-11-03 jas tempfree(x);
1410 63a68686 2008-11-03 jas x = execute(a[2]);
1411 63a68686 2008-11-03 jas tempfree(x);
1415 63a68686 2008-11-03 jas Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */
1417 63a68686 2008-11-03 jas Cell *x, *vp, *arrayp, *cp, *ncp;
1421 63a68686 2008-11-03 jas vp = execute(a[0]);
1422 63a68686 2008-11-03 jas arrayp = execute(a[1]);
1423 63a68686 2008-11-03 jas if (!isarr(arrayp)) {
1424 63a68686 2008-11-03 jas return True;
1426 63a68686 2008-11-03 jas tp = (Array *) arrayp->sval;
1427 63a68686 2008-11-03 jas tempfree(arrayp);
1428 63a68686 2008-11-03 jas for (i = 0; i < tp->size; i++) { /* this routine knows too much */
1429 63a68686 2008-11-03 jas for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1430 63a68686 2008-11-03 jas setsval(vp, cp->nval);
1431 63a68686 2008-11-03 jas ncp = cp->cnext;
1432 63a68686 2008-11-03 jas x = execute(a[2]);
1433 63a68686 2008-11-03 jas if (isbreak(x)) {
1434 63a68686 2008-11-03 jas tempfree(vp);
1435 63a68686 2008-11-03 jas return True;
1437 63a68686 2008-11-03 jas if (isnext(x) || isexit(x) || isret(x)) {
1438 63a68686 2008-11-03 jas tempfree(vp);
1441 63a68686 2008-11-03 jas tempfree(x);
1444 63a68686 2008-11-03 jas return True;
1447 63a68686 2008-11-03 jas Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */
1449 63a68686 2008-11-03 jas Cell *x, *y;
1450 63a68686 2008-11-03 jas Awkfloat u;
1452 63a68686 2008-11-03 jas wchar_t wc;
1453 63a68686 2008-11-03 jas char *p, *buf;
1454 63a68686 2008-11-03 jas char mbc[50];
1455 63a68686 2008-11-03 jas Node *nextarg;
1457 5a8bc789 2009-08-12 mt4swm void flush_all(void);
1459 63a68686 2008-11-03 jas t = ptoi(a[0]);
1460 63a68686 2008-11-03 jas x = execute(a[1]);
1461 63a68686 2008-11-03 jas nextarg = a[1]->nnext;
1462 63a68686 2008-11-03 jas switch (t) {
1463 63a68686 2008-11-03 jas case FLENGTH:
1464 5a8bc789 2009-08-12 mt4swm if (isarr(x))
1465 5a8bc789 2009-08-12 mt4swm u = ((Array *) x->sval)->nelem; /* GROT. should be function*/
1467 5a8bc789 2009-08-12 mt4swm p = getsval(x);
1468 5a8bc789 2009-08-12 mt4swm u = (Awkfloat) countposn(p, strlen(p));
1472 63a68686 2008-11-03 jas u = errcheck(log(getfval(x)), "log"); break;
1474 63a68686 2008-11-03 jas modf(getfval(x), &u); break;
1476 63a68686 2008-11-03 jas u = errcheck(exp(getfval(x)), "exp"); break;
1477 63a68686 2008-11-03 jas case FSQRT:
1478 63a68686 2008-11-03 jas u = errcheck(sqrt(getfval(x)), "sqrt"); break;
1480 63a68686 2008-11-03 jas u = sin(getfval(x)); break;
1482 63a68686 2008-11-03 jas u = cos(getfval(x)); break;
1483 63a68686 2008-11-03 jas case FATAN:
1484 63a68686 2008-11-03 jas if (nextarg == 0) {
1485 63a68686 2008-11-03 jas WARNING("atan2 requires two arguments; returning 1.0");
1488 63a68686 2008-11-03 jas y = execute(a[1]->nnext);
1489 63a68686 2008-11-03 jas u = atan2(getfval(x), getfval(y));
1490 63a68686 2008-11-03 jas tempfree(y);
1491 63a68686 2008-11-03 jas nextarg = nextarg->nnext;
1494 63a68686 2008-11-03 jas case FSYSTEM:
1495 63a68686 2008-11-03 jas fflush(stdout); /* in case something is buffered already */
1496 63a68686 2008-11-03 jas u = (Awkfloat) system(getsval(x)) / 256; /* 256 is unix-dep */
1498 63a68686 2008-11-03 jas case FRAND:
1499 63a68686 2008-11-03 jas /* in principle, rand() returns something in 0..RAND_MAX */
1500 63a68686 2008-11-03 jas u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX;
1502 63a68686 2008-11-03 jas case FSRAND:
1503 63a68686 2008-11-03 jas if (isrec(x)) /* no argument provided */
1504 63a68686 2008-11-03 jas u = time((time_t *)0);
1506 63a68686 2008-11-03 jas u = getfval(x);
1507 63a68686 2008-11-03 jas srand((unsigned int) u);
1509 63a68686 2008-11-03 jas case FTOUPPER:
1510 63a68686 2008-11-03 jas case FTOLOWER:
1511 63a68686 2008-11-03 jas buf = tostring(getsval(x));
1512 63a68686 2008-11-03 jas if (t == FTOUPPER) {
1513 63a68686 2008-11-03 jas for (p = buf; *p; p++)
1514 63a68686 2008-11-03 jas if (islower(*p))
1515 63a68686 2008-11-03 jas *p = toupper(*p);
1517 63a68686 2008-11-03 jas for (p = buf; *p; p++)
1518 63a68686 2008-11-03 jas if (isupper(*p))
1519 63a68686 2008-11-03 jas *p = tolower(*p);
1521 63a68686 2008-11-03 jas tempfree(x);
1522 63a68686 2008-11-03 jas x = gettemp();
1523 63a68686 2008-11-03 jas setsval(x, buf);
1526 63a68686 2008-11-03 jas case FFLUSH:
1527 5a8bc789 2009-08-12 mt4swm if (isrec(x) || strlen(getsval(x)) == 0) {
1528 5a8bc789 2009-08-12 mt4swm flush_all(); /* fflush() or fflush("") -> all */
1530 5a8bc789 2009-08-12 mt4swm } else if ((fp = openfile(FFLUSH, getsval(x))) == NULL)
1533 63a68686 2008-11-03 jas u = fflush(fp);
1536 63a68686 2008-11-03 jas wc = (int)getfval(x);
1537 63a68686 2008-11-03 jas mbc[wctomb(mbc, wc)] = 0;
1538 63a68686 2008-11-03 jas tempfree(x);
1539 63a68686 2008-11-03 jas x = gettemp();
1540 63a68686 2008-11-03 jas setsval(x, mbc);
1542 63a68686 2008-11-03 jas default: /* can't happen */
1543 63a68686 2008-11-03 jas FATAL("illegal function type %d", t);
1544 0cfb3760 2012-10-21 rsc return(NULL);
1546 63a68686 2008-11-03 jas tempfree(x);
1547 63a68686 2008-11-03 jas x = gettemp();
1548 63a68686 2008-11-03 jas setfval(x, u);
1549 63a68686 2008-11-03 jas if (nextarg != 0) {
1550 63a68686 2008-11-03 jas WARNING("warning: function has too many arguments");
1551 63a68686 2008-11-03 jas for ( ; nextarg; nextarg = nextarg->nnext)
1552 63a68686 2008-11-03 jas execute(nextarg);
1557 63a68686 2008-11-03 jas Cell *printstat(Node **a, int n) /* print a[0] */
1564 63a68686 2008-11-03 jas if (a[1] == 0) /* a[1] is redirection operator, a[2] is file */
1565 63a68686 2008-11-03 jas fp = stdout;
1567 63a68686 2008-11-03 jas fp = redirect(ptoi(a[1]), a[2]);
1568 63a68686 2008-11-03 jas for (x = a[0]; x != NULL; x = x->nnext) {
1569 63a68686 2008-11-03 jas y = execute(x);
1570 63a68686 2008-11-03 jas fputs(getsval(y), fp);
1571 63a68686 2008-11-03 jas tempfree(y);
1572 63a68686 2008-11-03 jas if (x->nnext == NULL)
1573 63a68686 2008-11-03 jas r = fputs(*ORS, fp);
1575 63a68686 2008-11-03 jas r = fputs(*OFS, fp);
1576 63a68686 2008-11-03 jas if (r == EOF)
1577 63a68686 2008-11-03 jas FATAL("write error on %s", filename(fp));
1579 63a68686 2008-11-03 jas if (a[1] != 0)
1580 63a68686 2008-11-03 jas if (fflush(fp) == EOF)
1581 63a68686 2008-11-03 jas FATAL("write error on %s", filename(fp));
1582 63a68686 2008-11-03 jas return(True);
1585 63a68686 2008-11-03 jas Cell *nullproc(Node **a, int n)
1591 63a68686 2008-11-03 jas FILE *redirect(int a, Node *b) /* set up all i/o redirections */
1595 63a68686 2008-11-03 jas char *fname;
1597 63a68686 2008-11-03 jas x = execute(b);
1598 63a68686 2008-11-03 jas fname = getsval(x);
1599 63a68686 2008-11-03 jas fp = openfile(a, fname);
1600 63a68686 2008-11-03 jas if (fp == NULL)
1601 63a68686 2008-11-03 jas FATAL("can't open file %s", fname);
1602 63a68686 2008-11-03 jas tempfree(x);
1606 63a68686 2008-11-03 jas struct files {
1608 63a68686 2008-11-03 jas char *fname;
1609 63a68686 2008-11-03 jas int mode; /* '|', 'a', 'w' => LE/LT, GT */
1610 63a68686 2008-11-03 jas } files[FOPEN_MAX] ={
1611 63a68686 2008-11-03 jas { NULL, "/dev/stdin", LT }, /* watch out: don't free this! */
1612 63a68686 2008-11-03 jas { NULL, "/dev/stdout", GT },
1613 63a68686 2008-11-03 jas { NULL, "/dev/stderr", GT }
1616 63a68686 2008-11-03 jas void stdinit(void) /* in case stdin, etc., are not constants */
1618 63a68686 2008-11-03 jas files[0].fp = stdin;
1619 63a68686 2008-11-03 jas files[1].fp = stdout;
1620 63a68686 2008-11-03 jas files[2].fp = stderr;
1623 63a68686 2008-11-03 jas FILE *openfile(int a, char *us)
1625 63a68686 2008-11-03 jas char *s = us;
1627 63a68686 2008-11-03 jas FILE *fp = 0;
1629 63a68686 2008-11-03 jas if (*s == '\0')
1630 63a68686 2008-11-03 jas FATAL("null file name in print or getline");
1631 63a68686 2008-11-03 jas for (i=0; i < FOPEN_MAX; i++)
1632 63a68686 2008-11-03 jas if (files[i].fname && strcmp(s, files[i].fname) == 0) {
1633 63a68686 2008-11-03 jas if (a == files[i].mode || (a==APPEND && files[i].mode==GT))
1634 63a68686 2008-11-03 jas return files[i].fp;
1635 63a68686 2008-11-03 jas if (a == FFLUSH)
1636 63a68686 2008-11-03 jas return files[i].fp;
1638 63a68686 2008-11-03 jas if (a == FFLUSH) /* didn't find it, so don't create it! */
1639 63a68686 2008-11-03 jas return NULL;
1641 63a68686 2008-11-03 jas for (i=0; i < FOPEN_MAX; i++)
1642 63a68686 2008-11-03 jas if (files[i].fp == 0)
1644 63a68686 2008-11-03 jas if (i >= FOPEN_MAX)
1645 63a68686 2008-11-03 jas FATAL("%s makes too many open files", s);
1646 63a68686 2008-11-03 jas fflush(stdout); /* force a semblance of order */
1648 63a68686 2008-11-03 jas if (a == GT) {
1649 63a68686 2008-11-03 jas fp = fopen(s, "w");
1650 63a68686 2008-11-03 jas } else if (a == APPEND) {
1651 63a68686 2008-11-03 jas fp = fopen(s, "a");
1652 63a68686 2008-11-03 jas m = GT; /* so can mix > and >> */
1653 63a68686 2008-11-03 jas } else if (a == '|') { /* output pipe */
1654 63a68686 2008-11-03 jas fp = popen(s, "w");
1655 63a68686 2008-11-03 jas } else if (a == LE) { /* input pipe */
1656 63a68686 2008-11-03 jas fp = popen(s, "r");
1657 63a68686 2008-11-03 jas } else if (a == LT) { /* getline <file */
1658 63a68686 2008-11-03 jas fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */
1659 63a68686 2008-11-03 jas } else /* can't happen */
1660 63a68686 2008-11-03 jas FATAL("illegal redirection %d", a);
1661 63a68686 2008-11-03 jas if (fp != NULL) {
1662 63a68686 2008-11-03 jas files[i].fname = tostring(s);
1663 63a68686 2008-11-03 jas files[i].fp = fp;
1664 63a68686 2008-11-03 jas files[i].mode = m;
1669 63a68686 2008-11-03 jas char *filename(FILE *fp)
1673 63a68686 2008-11-03 jas for (i = 0; i < FOPEN_MAX; i++)
1674 63a68686 2008-11-03 jas if (fp == files[i].fp)
1675 63a68686 2008-11-03 jas return files[i].fname;
1676 63a68686 2008-11-03 jas return "???";
1679 63a68686 2008-11-03 jas Cell *closefile(Node **a, int n)
1682 63a68686 2008-11-03 jas int i, stat;
1684 63a68686 2008-11-03 jas x = execute(a[0]);
1685 63a68686 2008-11-03 jas getsval(x);
1686 63a68686 2008-11-03 jas for (i = 0; i < FOPEN_MAX; i++)
1687 63a68686 2008-11-03 jas if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) {
1688 63a68686 2008-11-03 jas if (ferror(files[i].fp))
1689 63a68686 2008-11-03 jas WARNING( "i/o error occurred on %s", files[i].fname );
1690 63a68686 2008-11-03 jas if (files[i].mode == '|' || files[i].mode == LE)
1691 63a68686 2008-11-03 jas stat = pclose(files[i].fp);
1693 63a68686 2008-11-03 jas stat = fclose(files[i].fp);
1694 63a68686 2008-11-03 jas if (stat == EOF)
1695 63a68686 2008-11-03 jas WARNING( "i/o error occurred closing %s", files[i].fname );
1696 63a68686 2008-11-03 jas if (i > 2) /* don't do /dev/std... */
1697 63a68686 2008-11-03 jas xfree(files[i].fname);
1698 63a68686 2008-11-03 jas files[i].fname = NULL; /* watch out for ref thru this */
1699 63a68686 2008-11-03 jas files[i].fp = NULL;
1701 63a68686 2008-11-03 jas tempfree(x);
1702 63a68686 2008-11-03 jas return(True);
1705 63a68686 2008-11-03 jas void closeall(void)
1707 63a68686 2008-11-03 jas int i, stat;
1709 63a68686 2008-11-03 jas for (i = 0; i < FOPEN_MAX; i++)
1710 63a68686 2008-11-03 jas if (files[i].fp) {
1711 63a68686 2008-11-03 jas if (ferror(files[i].fp))
1712 63a68686 2008-11-03 jas WARNING( "i/o error occurred on %s", files[i].fname );
1713 63a68686 2008-11-03 jas if (files[i].mode == '|' || files[i].mode == LE)
1714 63a68686 2008-11-03 jas stat = pclose(files[i].fp);
1716 63a68686 2008-11-03 jas stat = fclose(files[i].fp);
1717 63a68686 2008-11-03 jas if (stat == EOF)
1718 63a68686 2008-11-03 jas WARNING( "i/o error occurred while closing %s", files[i].fname );
1722 5a8bc789 2009-08-12 mt4swm void flush_all(void)
1726 5a8bc789 2009-08-12 mt4swm for (i = 0; i < FOPEN_MAX; i++)
1727 5a8bc789 2009-08-12 mt4swm if (files[i].fp)
1728 5a8bc789 2009-08-12 mt4swm fflush(files[i].fp);
1731 63a68686 2008-11-03 jas void backsub(char **pb_ptr, char **sptr_ptr);
1733 63a68686 2008-11-03 jas Cell *sub(Node **a, int nnn) /* substitute command */
1735 63a68686 2008-11-03 jas char *sptr, *pb, *q;
1736 63a68686 2008-11-03 jas Cell *x, *y, *result;
1737 63a68686 2008-11-03 jas char *t, *buf;
1739 63a68686 2008-11-03 jas int bufsz = recsize;
1741 63a68686 2008-11-03 jas if ((buf = (char *) malloc(bufsz)) == NULL)
1742 63a68686 2008-11-03 jas FATAL("out of memory in sub");
1743 63a68686 2008-11-03 jas x = execute(a[3]); /* target string */
1744 63a68686 2008-11-03 jas t = getsval(x);
1745 63a68686 2008-11-03 jas if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1746 63a68686 2008-11-03 jas p = (void *) a[1]; /* regular expression */
1748 63a68686 2008-11-03 jas y = execute(a[1]);
1749 63a68686 2008-11-03 jas p = compre(getsval(y));
1750 63a68686 2008-11-03 jas tempfree(y);
1752 63a68686 2008-11-03 jas y = execute(a[2]); /* replacement string */
1753 63a68686 2008-11-03 jas result = False;
1754 63a68686 2008-11-03 jas if (pmatch(p, t, t)) {
1756 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub");
1758 63a68686 2008-11-03 jas while (sptr < patbeg)
1759 63a68686 2008-11-03 jas *pb++ = *sptr++;
1760 63a68686 2008-11-03 jas sptr = getsval(y);
1761 63a68686 2008-11-03 jas while (*sptr != 0) {
1762 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub");
1763 63a68686 2008-11-03 jas if (*sptr == '\\') {
1764 63a68686 2008-11-03 jas backsub(&pb, &sptr);
1765 63a68686 2008-11-03 jas } else if (*sptr == '&') {
1767 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub");
1768 63a68686 2008-11-03 jas for (q = patbeg; q < patbeg+patlen; )
1769 63a68686 2008-11-03 jas *pb++ = *q++;
1771 63a68686 2008-11-03 jas *pb++ = *sptr++;
1773 63a68686 2008-11-03 jas *pb = '\0';
1774 63a68686 2008-11-03 jas if (pb > buf + bufsz)
1775 63a68686 2008-11-03 jas FATAL("sub result1 %.30s too big; can't happen", buf);
1776 63a68686 2008-11-03 jas sptr = patbeg + patlen;
1777 63a68686 2008-11-03 jas if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
1778 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
1779 63a68686 2008-11-03 jas while ((*pb++ = *sptr++) != 0)
1782 63a68686 2008-11-03 jas if (pb > buf + bufsz)
1783 63a68686 2008-11-03 jas FATAL("sub result2 %.30s too big; can't happen", buf);
1784 63a68686 2008-11-03 jas setsval(x, buf); /* BUG: should be able to avoid copy */
1785 63a68686 2008-11-03 jas result = True;;
1787 63a68686 2008-11-03 jas tempfree(x);
1788 63a68686 2008-11-03 jas tempfree(y);
1790 63a68686 2008-11-03 jas return result;
1793 63a68686 2008-11-03 jas Cell *gsub(Node **a, int nnn) /* global substitute */
1795 63a68686 2008-11-03 jas Cell *x, *y;
1796 63a68686 2008-11-03 jas char *rptr, *sptr, *t, *pb, *c;
1799 63a68686 2008-11-03 jas int mflag, num;
1800 63a68686 2008-11-03 jas int bufsz = recsize;
1802 63a68686 2008-11-03 jas if ((buf = (char *)malloc(bufsz)) == NULL)
1803 63a68686 2008-11-03 jas FATAL("out of memory in gsub");
1804 63a68686 2008-11-03 jas mflag = 0; /* if mflag == 0, can replace empty string */
1806 63a68686 2008-11-03 jas x = execute(a[3]); /* target string */
1807 63a68686 2008-11-03 jas c = t = getsval(x);
1808 63a68686 2008-11-03 jas if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1809 63a68686 2008-11-03 jas p = (void *) a[1]; /* regular expression */
1811 63a68686 2008-11-03 jas y = execute(a[1]);
1812 63a68686 2008-11-03 jas p = compre(getsval(y));
1813 63a68686 2008-11-03 jas tempfree(y);
1815 63a68686 2008-11-03 jas y = execute(a[2]); /* replacement string */
1816 63a68686 2008-11-03 jas if (pmatch(p, t, c)) {
1818 63a68686 2008-11-03 jas rptr = getsval(y);
1820 63a68686 2008-11-03 jas if (patlen == 0 && *patbeg != 0) { /* matched empty string */
1821 63a68686 2008-11-03 jas if (mflag == 0) { /* can replace empty */
1823 63a68686 2008-11-03 jas sptr = rptr;
1824 63a68686 2008-11-03 jas while (*sptr != 0) {
1825 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1826 63a68686 2008-11-03 jas if (*sptr == '\\') {
1827 63a68686 2008-11-03 jas backsub(&pb, &sptr);
1828 63a68686 2008-11-03 jas } else if (*sptr == '&') {
1831 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1832 63a68686 2008-11-03 jas for (q = patbeg; q < patbeg+patlen; )
1833 63a68686 2008-11-03 jas *pb++ = *q++;
1835 63a68686 2008-11-03 jas *pb++ = *sptr++;
1838 63a68686 2008-11-03 jas if (*c == 0) /* at end */
1840 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
1841 63a68686 2008-11-03 jas *pb++ = *c++;
1842 63a68686 2008-11-03 jas if (pb > buf + bufsz) /* BUG: not sure of this test */
1843 63a68686 2008-11-03 jas FATAL("gsub result0 %.30s too big; can't happen", buf);
1846 63a68686 2008-11-03 jas else { /* matched nonempty string */
1849 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub");
1850 63a68686 2008-11-03 jas while (sptr < patbeg)
1851 63a68686 2008-11-03 jas *pb++ = *sptr++;
1852 63a68686 2008-11-03 jas sptr = rptr;
1853 63a68686 2008-11-03 jas while (*sptr != 0) {
1854 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1855 63a68686 2008-11-03 jas if (*sptr == '\\') {
1856 63a68686 2008-11-03 jas backsub(&pb, &sptr);
1857 63a68686 2008-11-03 jas } else if (*sptr == '&') {
1860 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1861 63a68686 2008-11-03 jas for (q = patbeg; q < patbeg+patlen; )
1862 63a68686 2008-11-03 jas *pb++ = *q++;
1864 63a68686 2008-11-03 jas *pb++ = *sptr++;
1866 63a68686 2008-11-03 jas c = patbeg + patlen;
1867 63a68686 2008-11-03 jas if ((c[-1] == 0) || (*c == 0))
1869 63a68686 2008-11-03 jas if (pb > buf + bufsz)
1870 63a68686 2008-11-03 jas FATAL("gsub result1 %.30s too big; can't happen", buf);
1873 63a68686 2008-11-03 jas } while (pmatch(p, t, c));
1875 63a68686 2008-11-03 jas adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
1876 63a68686 2008-11-03 jas while ((*pb++ = *sptr++) != 0)
1878 63a68686 2008-11-03 jas done: if (pb > buf + bufsz)
1879 63a68686 2008-11-03 jas FATAL("gsub result2 %.30s too big; can't happen", buf);
1880 63a68686 2008-11-03 jas *pb = '\0';
1881 63a68686 2008-11-03 jas setsval(x, buf); /* BUG: should be able to avoid copy + free */
1883 63a68686 2008-11-03 jas tempfree(x);
1884 63a68686 2008-11-03 jas tempfree(y);
1885 63a68686 2008-11-03 jas x = gettemp();
1886 63a68686 2008-11-03 jas x->tval = NUM;
1887 63a68686 2008-11-03 jas x->fval = num;
1892 63a68686 2008-11-03 jas void backsub(char **pb_ptr, char **sptr_ptr) /* handle \\& variations */
1893 63a68686 2008-11-03 jas { /* sptr[0] == '\\' */
1894 63a68686 2008-11-03 jas char *pb = *pb_ptr, *sptr = *sptr_ptr;
1896 63a68686 2008-11-03 jas if (sptr[1] == '\\') {
1897 63a68686 2008-11-03 jas if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
1898 63a68686 2008-11-03 jas *pb++ = '\\';
1899 63a68686 2008-11-03 jas *pb++ = '&';
1901 63a68686 2008-11-03 jas } else if (sptr[2] == '&') { /* \\& -> \ + matched */
1902 63a68686 2008-11-03 jas *pb++ = '\\';
1904 63a68686 2008-11-03 jas } else { /* \\x -> \\x */
1905 63a68686 2008-11-03 jas *pb++ = *sptr++;
1906 63a68686 2008-11-03 jas *pb++ = *sptr++;
1908 63a68686 2008-11-03 jas } else if (sptr[1] == '&') { /* literal & */
1910 63a68686 2008-11-03 jas *pb++ = *sptr++;
1911 63a68686 2008-11-03 jas } else /* literal \ */
1912 63a68686 2008-11-03 jas *pb++ = *sptr++;
1914 63a68686 2008-11-03 jas *pb_ptr = pb;
1915 63a68686 2008-11-03 jas *sptr_ptr = sptr;