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