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