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 if (n > 0) {
451 x = execute(a[0]);
452 setsval(x, buf);
453 if (is_number(x->sval, & result)) {
454 x->fval = result;
455 x->tval |= NUM;
456 }
457 tempfree(x);
458 }
459 }
460 }
461 setfval(r, (Awkfloat) n);
462 free(buf);
463 return r;
464 }
465
getnf(Node ** a,int n)466 Cell *getnf(Node **a, int n) /* get NF */
467 {
468 if (!donefld)
469 fldbld();
470 return (Cell *) a[0];
471 }
472
473 static char *
makearraystring(Node * p,const char * func)474 makearraystring(Node *p, const char *func)
475 {
476 char *buf;
477 int bufsz = recsize;
478 size_t blen;
479
480 if ((buf = (char *) malloc(bufsz)) == NULL) {
481 FATAL("%s: out of memory", func);
482 }
483
484 blen = 0;
485 buf[blen] = '\0';
486
487 for (; p; p = p->nnext) {
488 Cell *x = execute(p); /* expr */
489 char *s = getsval(x);
490 size_t seplen = strlen(getsval(subseploc));
491 size_t nsub = p->nnext ? seplen : 0;
492 size_t slen = strlen(s);
493 size_t tlen = blen + slen + nsub;
494
495 if (!adjbuf(&buf, &bufsz, tlen + 1, recsize, 0, func)) {
496 FATAL("%s: out of memory %s[%s...]",
497 func, x->nval, buf);
498 }
499 memcpy(buf + blen, s, slen);
500 if (nsub) {
501 memcpy(buf + blen + slen, *SUBSEP, nsub);
502 }
503 buf[tlen] = '\0';
504 blen = tlen;
505 tempfree(x);
506 }
507 return buf;
508 }
509
array(Node ** a,int n)510 Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
511 {
512 Cell *x, *z;
513 char *buf;
514
515 x = execute(a[0]); /* Cell* for symbol table */
516 buf = makearraystring(a[1], __func__);
517 if (!isarr(x)) {
518 DPRINTF("making %s into an array\n", NN(x->nval));
519 if (freeable(x))
520 xfree(x->sval);
521 x->tval &= ~(STR|NUM|DONTFREE);
522 x->tval |= ARR;
523 x->sval = (char *) makesymtab(NSYMTAB);
524 }
525 z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
526 z->ctype = OCELL;
527 z->csub = CVAR;
528 tempfree(x);
529 free(buf);
530 return(z);
531 }
532
awkdelete(Node ** a,int n)533 Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
534 {
535 Cell *x;
536
537 x = execute(a[0]); /* Cell* for symbol table */
538 if (x == symtabloc) {
539 FATAL("cannot delete SYMTAB or its elements");
540 }
541 if (!isarr(x))
542 return True;
543 if (a[1] == NULL) { /* delete the elements, not the table */
544 freesymtab(x);
545 x->tval &= ~STR;
546 x->tval |= ARR;
547 x->sval = (char *) makesymtab(NSYMTAB);
548 } else {
549 char *buf = makearraystring(a[1], __func__);
550 freeelem(x, buf);
551 free(buf);
552 }
553 tempfree(x);
554 return True;
555 }
556
intest(Node ** a,int n)557 Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
558 {
559 Cell *ap, *k;
560 char *buf;
561
562 ap = execute(a[1]); /* array name */
563 if (!isarr(ap)) {
564 DPRINTF("making %s into an array\n", ap->nval);
565 if (freeable(ap))
566 xfree(ap->sval);
567 ap->tval &= ~(STR|NUM|DONTFREE);
568 ap->tval |= ARR;
569 ap->sval = (char *) makesymtab(NSYMTAB);
570 }
571 buf = makearraystring(a[0], __func__);
572 k = lookup(buf, (Array *) ap->sval);
573 tempfree(ap);
574 free(buf);
575 if (k == NULL)
576 return(False);
577 else
578 return(True);
579 }
580
581
matchop(Node ** a,int n)582 Cell *matchop(Node **a, int n) /* ~ and match() */
583 {
584 Cell *x, *y;
585 char *s, *t;
586 int i;
587 fa *pfa;
588 int (*mf)(fa *, const char *) = match, mode = 0;
589
590 if (n == MATCHFCN) {
591 mf = pmatch;
592 mode = 1;
593 }
594 x = execute(a[1]); /* a[1] = target text */
595 s = getsval(x);
596 if (a[0] == NULL) /* a[1] == 0: already-compiled reg expr */
597 i = (*mf)((fa *) a[2], s);
598 else {
599 y = execute(a[2]); /* a[2] = regular expr */
600 t = getsval(y);
601 pfa = makedfa(t, mode);
602 i = (*mf)(pfa, s);
603 tempfree(y);
604 }
605 tempfree(x);
606 if (n == MATCHFCN) {
607 int start = patbeg - s + 1;
608 if (patlen < 0)
609 start = 0;
610 setfval(rstartloc, (Awkfloat) start);
611 setfval(rlengthloc, (Awkfloat) patlen);
612 x = gettemp();
613 x->tval = NUM;
614 x->fval = start;
615 return x;
616 } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
617 return(True);
618 else
619 return(False);
620 }
621
622
boolop(Node ** a,int n)623 Cell *boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */
624 {
625 Cell *x, *y;
626 int i;
627
628 x = execute(a[0]);
629 i = istrue(x);
630 tempfree(x);
631 switch (n) {
632 case BOR:
633 if (i) return(True);
634 y = execute(a[1]);
635 i = istrue(y);
636 tempfree(y);
637 if (i) return(True);
638 else return(False);
639 case AND:
640 if ( !i ) return(False);
641 y = execute(a[1]);
642 i = istrue(y);
643 tempfree(y);
644 if (i) return(True);
645 else return(False);
646 case NOT:
647 if (i) return(False);
648 else return(True);
649 default: /* can't happen */
650 FATAL("unknown boolean operator %d", n);
651 }
652 return 0; /*NOTREACHED*/
653 }
654
relop(Node ** a,int n)655 Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */
656 {
657 int i;
658 Cell *x, *y;
659 Awkfloat j;
660
661 x = execute(a[0]);
662 y = execute(a[1]);
663 if (x->tval&NUM && y->tval&NUM) {
664 j = x->fval - y->fval;
665 i = j<0? -1: (j>0? 1: 0);
666 } else {
667 i = strcmp(getsval(x), getsval(y));
668 }
669 tempfree(x);
670 tempfree(y);
671 switch (n) {
672 case LT: if (i<0) return(True);
673 else return(False);
674 case LE: if (i<=0) return(True);
675 else return(False);
676 case NE: if (i!=0) return(True);
677 else return(False);
678 case EQ: if (i == 0) return(True);
679 else return(False);
680 case GE: if (i>=0) return(True);
681 else return(False);
682 case GT: if (i>0) return(True);
683 else return(False);
684 default: /* can't happen */
685 FATAL("unknown relational operator %d", n);
686 }
687 return 0; /*NOTREACHED*/
688 }
689
tfree(Cell * a)690 void tfree(Cell *a) /* free a tempcell */
691 {
692 if (freeable(a)) {
693 DPRINTF("freeing %s %s %o\n", NN(a->nval), NN(a->sval), a->tval);
694 xfree(a->sval);
695 }
696 if (a == tmps)
697 FATAL("tempcell list is curdled");
698 a->cnext = tmps;
699 tmps = a;
700 }
701
gettemp(void)702 Cell *gettemp(void) /* get a tempcell */
703 { int i;
704 Cell *x;
705
706 if (!tmps) {
707 tmps = (Cell *) calloc(100, sizeof(*tmps));
708 if (!tmps)
709 FATAL("out of space for temporaries");
710 for (i = 1; i < 100; i++)
711 tmps[i-1].cnext = &tmps[i];
712 tmps[i-1].cnext = NULL;
713 }
714 x = tmps;
715 tmps = x->cnext;
716 *x = tempcell;
717 return(x);
718 }
719
indirect(Node ** a,int n)720 Cell *indirect(Node **a, int n) /* $( a[0] ) */
721 {
722 Awkfloat val;
723 Cell *x;
724 int m;
725 char *s;
726
727 x = execute(a[0]);
728 val = getfval(x); /* freebsd: defend against super large field numbers */
729 if ((Awkfloat)INT_MAX < val)
730 FATAL("trying to access out of range field %s", x->nval);
731 m = (int) val;
732 if (m == 0 && !is_number(s = getsval(x), NULL)) /* suspicion! */
733 FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
734 /* BUG: can x->nval ever be null??? */
735 tempfree(x);
736 x = fieldadr(m);
737 x->ctype = OCELL; /* BUG? why are these needed? */
738 x->csub = CFLD;
739 return(x);
740 }
741
substr(Node ** a,int nnn)742 Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */
743 {
744 int k, m, n;
745 char *s;
746 int temp;
747 Cell *x, *y, *z = NULL;
748
749 x = execute(a[0]);
750 y = execute(a[1]);
751 if (a[2] != NULL)
752 z = execute(a[2]);
753 s = getsval(x);
754 k = strlen(s) + 1;
755 if (k <= 1) {
756 tempfree(x);
757 tempfree(y);
758 if (a[2] != NULL) {
759 tempfree(z);
760 }
761 x = gettemp();
762 setsval(x, "");
763 return(x);
764 }
765 m = (int) getfval(y);
766 if (m <= 0)
767 m = 1;
768 else if (m > k)
769 m = k;
770 tempfree(y);
771 if (a[2] != NULL) {
772 n = (int) getfval(z);
773 tempfree(z);
774 } else
775 n = k - 1;
776 if (n < 0)
777 n = 0;
778 else if (n > k - m)
779 n = k - m;
780 DPRINTF("substr: m=%d, n=%d, s=%s\n", m, n, s);
781 y = gettemp();
782 temp = s[n+m-1]; /* with thanks to John Linderman */
783 s[n+m-1] = '\0';
784 setsval(y, s + m - 1);
785 s[n+m-1] = temp;
786 tempfree(x);
787 return(y);
788 }
789
sindex(Node ** a,int nnn)790 Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */
791 {
792 Cell *x, *y, *z;
793 char *s1, *s2, *p1, *p2, *q;
794 Awkfloat v = 0.0;
795
796 x = execute(a[0]);
797 s1 = getsval(x);
798 y = execute(a[1]);
799 s2 = getsval(y);
800
801 z = gettemp();
802 for (p1 = s1; *p1 != '\0'; p1++) {
803 for (q = p1, p2 = s2; *p2 != '\0' && *q == *p2; q++, p2++)
804 continue;
805 if (*p2 == '\0') {
806 v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */
807 break;
808 }
809 }
810 tempfree(x);
811 tempfree(y);
812 setfval(z, v);
813 return(z);
814 }
815
816 #define MAXNUMSIZE 50
817
format(char ** pbuf,int * pbufsize,const char * s,Node * a)818 int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like conversions */
819 {
820 char *fmt;
821 char *p, *t;
822 const char *os;
823 Cell *x;
824 int flag = 0, n;
825 int fmtwd; /* format width */
826 int fmtsz = recsize;
827 char *buf = *pbuf;
828 int bufsize = *pbufsize;
829 #define FMTSZ(a) (fmtsz - ((a) - fmt))
830 #define BUFSZ(a) (bufsize - ((a) - buf))
831
832 static bool first = true;
833 static bool have_a_format = false;
834
835 if (first) {
836 char xbuf[100];
837
838 snprintf(xbuf, sizeof(xbuf), "%a", 42.0);
839 have_a_format = (strcmp(xbuf, "0x1.5p+5") == 0);
840 first = false;
841 }
842
843 os = s;
844 p = buf;
845 if ((fmt = (char *) malloc(fmtsz)) == NULL)
846 FATAL("out of memory in format()");
847 while (*s) {
848 adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format1");
849 if (*s != '%') {
850 *p++ = *s++;
851 continue;
852 }
853 if (*(s+1) == '%') {
854 *p++ = '%';
855 s += 2;
856 continue;
857 }
858 /* have to be real careful in case this is a huge number, eg, %100000d */
859 fmtwd = atoi(s+1);
860 if (fmtwd < 0)
861 fmtwd = -fmtwd;
862 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format2");
863 for (t = fmt; (*t++ = *s) != '\0'; s++) {
864 if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3"))
865 FATAL("format item %.30s... ran format() out of memory", os);
866 /* Ignore size specifiers */
867 if (strchr("hjLlqtz", *s) != NULL) { /* the ansi panoply */
868 t--;
869 continue;
870 }
871 if (isalpha((uschar)*s))
872 break;
873 if (*s == '$') {
874 FATAL("'$' not permitted in awk formats");
875 }
876 if (*s == '*') {
877 if (a == NULL) {
878 FATAL("not enough args in printf(%s)", os);
879 }
880 x = execute(a);
881 a = a->nnext;
882 snprintf(t - 1, FMTSZ(t - 1),
883 "%d", fmtwd=(int) getfval(x));
884 if (fmtwd < 0)
885 fmtwd = -fmtwd;
886 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
887 t = fmt + strlen(fmt);
888 tempfree(x);
889 }
890 }
891 *t = '\0';
892 if (fmtwd < 0)
893 fmtwd = -fmtwd;
894 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format4");
895 switch (*s) {
896 case 'a': case 'A':
897 if (have_a_format)
898 flag = *s;
899 else
900 flag = 'f';
901 break;
902 case 'f': case 'e': case 'g': case 'E': case 'G':
903 flag = 'f';
904 break;
905 case 'd': case 'i': case 'o': case 'x': case 'X': case 'u':
906 flag = (*s == 'd' || *s == 'i') ? 'd' : 'u';
907 *(t-1) = 'j';
908 *t = *s;
909 *++t = '\0';
910 break;
911 case 's':
912 flag = 's';
913 break;
914 case 'c':
915 flag = 'c';
916 break;
917 default:
918 WARNING("weird printf conversion %s", fmt);
919 flag = '?';
920 break;
921 }
922 if (a == NULL)
923 FATAL("not enough args in printf(%s)", os);
924 x = execute(a);
925 a = a->nnext;
926 n = MAXNUMSIZE;
927 if (fmtwd > n)
928 n = fmtwd;
929 adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format5");
930 switch (flag) {
931 case '?': snprintf(p, BUFSZ(p), "%s", fmt); /* unknown, so dump it too */
932 t = getsval(x);
933 n = strlen(t);
934 if (fmtwd > n)
935 n = fmtwd;
936 adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format6");
937 p += strlen(p);
938 snprintf(p, BUFSZ(p), "%s", t);
939 break;
940 case 'a':
941 case 'A':
942 case 'f': snprintf(p, BUFSZ(p), fmt, getfval(x)); break;
943 case 'd': snprintf(p, BUFSZ(p), fmt, (intmax_t) getfval(x)); break;
944 case 'u': snprintf(p, BUFSZ(p), fmt, (uintmax_t) getfval(x)); break;
945 case 's':
946 t = getsval(x);
947 n = strlen(t);
948 if (fmtwd > n)
949 n = fmtwd;
950 if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format7"))
951 FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t);
952 snprintf(p, BUFSZ(p), fmt, t);
953 break;
954 case 'c':
955 if (isnum(x)) {
956 if ((int)getfval(x))
957 snprintf(p, BUFSZ(p), fmt, (int) getfval(x));
958 else {
959 *p++ = '\0'; /* explicit null byte */
960 *p = '\0'; /* next output will start here */
961 }
962 } else
963 snprintf(p, BUFSZ(p), fmt, getsval(x)[0]);
964 break;
965 default:
966 FATAL("can't happen: bad conversion %c in format()", flag);
967 }
968 tempfree(x);
969 p += strlen(p);
970 s++;
971 }
972 *p = '\0';
973 free(fmt);
974 for ( ; a; a = a->nnext) /* evaluate any remaining args */
975 execute(a);
976 *pbuf = buf;
977 *pbufsize = bufsize;
978 return p - buf;
979 }
980
awksprintf(Node ** a,int n)981 Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */
982 {
983 Cell *x;
984 Node *y;
985 char *buf;
986 int bufsz=3*recsize;
987
988 if ((buf = (char *) malloc(bufsz)) == NULL)
989 FATAL("out of memory in awksprintf");
990 y = a[0]->nnext;
991 x = execute(a[0]);
992 if (format(&buf, &bufsz, getsval(x), y) == -1)
993 FATAL("sprintf string %.30s... too long. can't happen.", buf);
994 tempfree(x);
995 x = gettemp();
996 x->sval = buf;
997 x->tval = STR;
998 return(x);
999 }
1000
awkprintf(Node ** a,int n)1001 Cell *awkprintf(Node **a, int n) /* printf */
1002 { /* a[0] is list of args, starting with format string */
1003 /* a[1] is redirection operator, a[2] is redirection file */
1004 FILE *fp;
1005 Cell *x;
1006 Node *y;
1007 char *buf;
1008 int len;
1009 int bufsz=3*recsize;
1010
1011 if ((buf = (char *) malloc(bufsz)) == NULL)
1012 FATAL("out of memory in awkprintf");
1013 y = a[0]->nnext;
1014 x = execute(a[0]);
1015 if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
1016 FATAL("printf string %.30s... too long. can't happen.", buf);
1017 tempfree(x);
1018 if (a[1] == NULL) {
1019 /* fputs(buf, stdout); */
1020 fwrite(buf, len, 1, stdout);
1021 if (ferror(stdout))
1022 FATAL("write error on stdout");
1023 } else {
1024 fp = redirect(ptoi(a[1]), a[2]);
1025 /* fputs(buf, fp); */
1026 fwrite(buf, len, 1, fp);
1027 fflush(fp);
1028 if (ferror(fp))
1029 FATAL("write error on %s", filename(fp));
1030 }
1031 free(buf);
1032 return(True);
1033 }
1034
arith(Node ** a,int n)1035 Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */
1036 {
1037 Awkfloat i, j = 0;
1038 double v;
1039 Cell *x, *y, *z;
1040
1041 x = execute(a[0]);
1042 i = getfval(x);
1043 tempfree(x);
1044 if (n != UMINUS && n != UPLUS) {
1045 y = execute(a[1]);
1046 j = getfval(y);
1047 tempfree(y);
1048 }
1049 z = gettemp();
1050 switch (n) {
1051 case ADD:
1052 i += j;
1053 break;
1054 case MINUS:
1055 i -= j;
1056 break;
1057 case MULT:
1058 i *= j;
1059 break;
1060 case DIVIDE:
1061 if (j == 0)
1062 FATAL("division by zero");
1063 i /= j;
1064 break;
1065 case MOD:
1066 if (j == 0)
1067 FATAL("division by zero in mod");
1068 modf(i/j, &v);
1069 i = i - j * v;
1070 break;
1071 case UMINUS:
1072 i = -i;
1073 break;
1074 case UPLUS: /* handled by getfval(), above */
1075 break;
1076 case POWER:
1077 if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
1078 i = ipow(i, (int) j);
1079 else {
1080 errno = 0;
1081 i = errcheck(pow(i, j), "pow");
1082 }
1083 break;
1084 default: /* can't happen */
1085 FATAL("illegal arithmetic operator %d", n);
1086 }
1087 setfval(z, i);
1088 return(z);
1089 }
1090
ipow(double x,int n)1091 double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */
1092 {
1093 double v;
1094
1095 if (n <= 0)
1096 return 1;
1097 v = ipow(x, n/2);
1098 if (n % 2 == 0)
1099 return v * v;
1100 else
1101 return x * v * v;
1102 }
1103
incrdecr(Node ** a,int n)1104 Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */
1105 {
1106 Cell *x, *z;
1107 int k;
1108 Awkfloat xf;
1109
1110 x = execute(a[0]);
1111 xf = getfval(x);
1112 k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
1113 if (n == PREINCR || n == PREDECR) {
1114 setfval(x, xf + k);
1115 return(x);
1116 }
1117 z = gettemp();
1118 setfval(z, xf);
1119 setfval(x, xf + k);
1120 tempfree(x);
1121 return(z);
1122 }
1123
assign(Node ** a,int n)1124 Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */
1125 { /* this is subtle; don't muck with it. */
1126 Cell *x, *y;
1127 Awkfloat xf, yf;
1128 double v;
1129
1130 y = execute(a[1]);
1131 x = execute(a[0]);
1132 if (n == ASSIGN) { /* ordinary assignment */
1133 if (x == y && !(x->tval & (FLD|REC)) && x != nfloc)
1134 ; /* self-assignment: leave alone unless it's a field or NF */
1135 else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
1136 setsval(x, getsval(y));
1137 x->fval = getfval(y);
1138 x->tval |= NUM;
1139 }
1140 else if (isstr(y))
1141 setsval(x, getsval(y));
1142 else if (isnum(y))
1143 setfval(x, getfval(y));
1144 else
1145 funnyvar(y, "read value of");
1146 tempfree(y);
1147 return(x);
1148 }
1149 xf = getfval(x);
1150 yf = getfval(y);
1151 switch (n) {
1152 case ADDEQ:
1153 xf += yf;
1154 break;
1155 case SUBEQ:
1156 xf -= yf;
1157 break;
1158 case MULTEQ:
1159 xf *= yf;
1160 break;
1161 case DIVEQ:
1162 if (yf == 0)
1163 FATAL("division by zero in /=");
1164 xf /= yf;
1165 break;
1166 case MODEQ:
1167 if (yf == 0)
1168 FATAL("division by zero in %%=");
1169 modf(xf/yf, &v);
1170 xf = xf - yf * v;
1171 break;
1172 case POWEQ:
1173 if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */
1174 xf = ipow(xf, (int) yf);
1175 else {
1176 errno = 0;
1177 xf = errcheck(pow(xf, yf), "pow");
1178 }
1179 break;
1180 default:
1181 FATAL("illegal assignment operator %d", n);
1182 break;
1183 }
1184 tempfree(y);
1185 setfval(x, xf);
1186 return(x);
1187 }
1188
cat(Node ** a,int q)1189 Cell *cat(Node **a, int q) /* a[0] cat a[1] */
1190 {
1191 Cell *x, *y, *z;
1192 int n1, n2;
1193 char *s = NULL;
1194 int ssz = 0;
1195
1196 x = execute(a[0]);
1197 n1 = strlen(getsval(x));
1198 adjbuf(&s, &ssz, n1, recsize, 0, "cat1");
1199 memcpy(s, x->sval, n1);
1200
1201 y = execute(a[1]);
1202 n2 = strlen(getsval(y));
1203 adjbuf(&s, &ssz, n1 + n2 + 1, recsize, 0, "cat2");
1204 memcpy(s + n1, y->sval, n2);
1205 s[n1 + n2] = '\0';
1206
1207 tempfree(x);
1208 tempfree(y);
1209
1210 z = gettemp();
1211 z->sval = s;
1212 z->tval = STR;
1213
1214 return(z);
1215 }
1216
pastat(Node ** a,int n)1217 Cell *pastat(Node **a, int n) /* a[0] { a[1] } */
1218 {
1219 Cell *x;
1220
1221 if (a[0] == NULL)
1222 x = execute(a[1]);
1223 else {
1224 x = execute(a[0]);
1225 if (istrue(x)) {
1226 tempfree(x);
1227 x = execute(a[1]);
1228 }
1229 }
1230 return x;
1231 }
1232
dopa2(Node ** a,int n)1233 Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */
1234 {
1235 Cell *x;
1236 int pair;
1237
1238 pair = ptoi(a[3]);
1239 if (pairstack[pair] == 0) {
1240 x = execute(a[0]);
1241 if (istrue(x))
1242 pairstack[pair] = 1;
1243 tempfree(x);
1244 }
1245 if (pairstack[pair] == 1) {
1246 x = execute(a[1]);
1247 if (istrue(x))
1248 pairstack[pair] = 0;
1249 tempfree(x);
1250 x = execute(a[2]);
1251 return(x);
1252 }
1253 return(False);
1254 }
1255
split(Node ** a,int nnn)1256 Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
1257 {
1258 Cell *x = NULL, *y, *ap;
1259 const char *s, *origs, *t;
1260 const char *fs = NULL;
1261 char *origfs = NULL;
1262 int sep;
1263 char temp, num[50];
1264 int n, tempstat, arg3type;
1265 double result;
1266
1267 y = execute(a[0]); /* source string */
1268 origs = s = strdup(getsval(y));
1269 arg3type = ptoi(a[3]);
1270 if (a[2] == NULL) /* fs string */
1271 fs = getsval(fsloc);
1272 else if (arg3type == STRING) { /* split(str,arr,"string") */
1273 x = execute(a[2]);
1274 fs = origfs = strdup(getsval(x));
1275 tempfree(x);
1276 } else if (arg3type == REGEXPR)
1277 fs = "(regexpr)"; /* split(str,arr,/regexpr/) */
1278 else
1279 FATAL("illegal type of split");
1280 sep = *fs;
1281 ap = execute(a[1]); /* array name */
1282 freesymtab(ap);
1283 DPRINTF("split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs);
1284 ap->tval &= ~STR;
1285 ap->tval |= ARR;
1286 ap->sval = (char *) makesymtab(NSYMTAB);
1287
1288 n = 0;
1289 if (arg3type == REGEXPR && strlen((char*)((fa*)a[2])->restr) == 0) {
1290 /* split(s, a, //); have to arrange that it looks like empty sep */
1291 arg3type = 0;
1292 fs = "";
1293 sep = 0;
1294 }
1295 if (*s != '\0' && (strlen(fs) > 1 || arg3type == REGEXPR)) { /* reg expr */
1296 fa *pfa;
1297 if (arg3type == REGEXPR) { /* it's ready already */
1298 pfa = (fa *) a[2];
1299 } else {
1300 pfa = makedfa(fs, 1);
1301 }
1302 if (nematch(pfa,s)) {
1303 tempstat = pfa->initstat;
1304 pfa->initstat = 2;
1305 do {
1306 n++;
1307 snprintf(num, sizeof(num), "%d", n);
1308 temp = *patbeg;
1309 setptr(patbeg, '\0');
1310 if (is_number(s, & result))
1311 setsymtab(num, s, result, STR|NUM, (Array *) ap->sval);
1312 else
1313 setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1314 setptr(patbeg, temp);
1315 s = patbeg + patlen;
1316 if (*(patbeg+patlen-1) == '\0' || *s == '\0') {
1317 n++;
1318 snprintf(num, sizeof(num), "%d", n);
1319 setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
1320 pfa->initstat = tempstat;
1321 goto spdone;
1322 }
1323 } while (nematch(pfa,s));
1324 pfa->initstat = tempstat; /* bwk: has to be here to reset */
1325 /* cf gsub and refldbld */
1326 }
1327 n++;
1328 snprintf(num, sizeof(num), "%d", n);
1329 if (is_number(s, & result))
1330 setsymtab(num, s, result, STR|NUM, (Array *) ap->sval);
1331 else
1332 setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1333 spdone:
1334 pfa = NULL;
1335 } else if (sep == ' ') {
1336 for (n = 0; ; ) {
1337 #define ISWS(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
1338 while (ISWS(*s))
1339 s++;
1340 if (*s == '\0')
1341 break;
1342 n++;
1343 t = s;
1344 do
1345 s++;
1346 while (*s != '\0' && !ISWS(*s));
1347 temp = *s;
1348 setptr(s, '\0');
1349 snprintf(num, sizeof(num), "%d", n);
1350 if (is_number(t, & result))
1351 setsymtab(num, t, result, STR|NUM, (Array *) ap->sval);
1352 else
1353 setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1354 setptr(s, temp);
1355 if (*s != '\0')
1356 s++;
1357 }
1358 } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */
1359 for (n = 0; *s != '\0'; s++) {
1360 char buf[2];
1361 n++;
1362 snprintf(num, sizeof(num), "%d", n);
1363 buf[0] = *s;
1364 buf[1] = '\0';
1365 if (isdigit((uschar)buf[0]))
1366 setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval);
1367 else
1368 setsymtab(num, buf, 0.0, STR, (Array *) ap->sval);
1369 }
1370 } else if (*s != '\0') {
1371 for (;;) {
1372 n++;
1373 t = s;
1374 while (*s != sep && *s != '\n' && *s != '\0')
1375 s++;
1376 temp = *s;
1377 setptr(s, '\0');
1378 snprintf(num, sizeof(num), "%d", n);
1379 if (is_number(t, & result))
1380 setsymtab(num, t, result, STR|NUM, (Array *) ap->sval);
1381 else
1382 setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1383 setptr(s, temp);
1384 if (*s++ == '\0')
1385 break;
1386 }
1387 }
1388 tempfree(ap);
1389 tempfree(y);
1390 xfree(origs);
1391 xfree(origfs);
1392 x = gettemp();
1393 x->tval = NUM;
1394 x->fval = n;
1395 return(x);
1396 }
1397
condexpr(Node ** a,int n)1398 Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */
1399 {
1400 Cell *x;
1401
1402 x = execute(a[0]);
1403 if (istrue(x)) {
1404 tempfree(x);
1405 x = execute(a[1]);
1406 } else {
1407 tempfree(x);
1408 x = execute(a[2]);
1409 }
1410 return(x);
1411 }
1412
ifstat(Node ** a,int n)1413 Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */
1414 {
1415 Cell *x;
1416
1417 x = execute(a[0]);
1418 if (istrue(x)) {
1419 tempfree(x);
1420 x = execute(a[1]);
1421 } else if (a[2] != NULL) {
1422 tempfree(x);
1423 x = execute(a[2]);
1424 }
1425 return(x);
1426 }
1427
whilestat(Node ** a,int n)1428 Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */
1429 {
1430 Cell *x;
1431
1432 for (;;) {
1433 x = execute(a[0]);
1434 if (!istrue(x))
1435 return(x);
1436 tempfree(x);
1437 x = execute(a[1]);
1438 if (isbreak(x)) {
1439 x = True;
1440 return(x);
1441 }
1442 if (isnext(x) || isexit(x) || isret(x))
1443 return(x);
1444 tempfree(x);
1445 }
1446 }
1447
dostat(Node ** a,int n)1448 Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */
1449 {
1450 Cell *x;
1451
1452 for (;;) {
1453 x = execute(a[0]);
1454 if (isbreak(x))
1455 return True;
1456 if (isnext(x) || isexit(x) || isret(x))
1457 return(x);
1458 tempfree(x);
1459 x = execute(a[1]);
1460 if (!istrue(x))
1461 return(x);
1462 tempfree(x);
1463 }
1464 }
1465
forstat(Node ** a,int n)1466 Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */
1467 {
1468 Cell *x;
1469
1470 x = execute(a[0]);
1471 tempfree(x);
1472 for (;;) {
1473 if (a[1]!=NULL) {
1474 x = execute(a[1]);
1475 if (!istrue(x)) return(x);
1476 else tempfree(x);
1477 }
1478 x = execute(a[3]);
1479 if (isbreak(x)) /* turn off break */
1480 return True;
1481 if (isnext(x) || isexit(x) || isret(x))
1482 return(x);
1483 tempfree(x);
1484 x = execute(a[2]);
1485 tempfree(x);
1486 }
1487 }
1488
instat(Node ** a,int n)1489 Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */
1490 {
1491 Cell *x, *vp, *arrayp, *cp, *ncp;
1492 Array *tp;
1493 int i;
1494
1495 vp = execute(a[0]);
1496 arrayp = execute(a[1]);
1497 if (!isarr(arrayp)) {
1498 return True;
1499 }
1500 tp = (Array *) arrayp->sval;
1501 tempfree(arrayp);
1502 for (i = 0; i < tp->size; i++) { /* this routine knows too much */
1503 for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1504 setsval(vp, cp->nval);
1505 ncp = cp->cnext;
1506 x = execute(a[2]);
1507 if (isbreak(x)) {
1508 tempfree(vp);
1509 return True;
1510 }
1511 if (isnext(x) || isexit(x) || isret(x)) {
1512 tempfree(vp);
1513 return(x);
1514 }
1515 tempfree(x);
1516 }
1517 }
1518 return True;
1519 }
1520
nawk_convert(const char * s,int (* fun_c)(int),wint_t (* fun_wc)(wint_t))1521 static char *nawk_convert(const char *s, int (*fun_c)(int),
1522 wint_t (*fun_wc)(wint_t))
1523 {
1524 char *buf = NULL;
1525 char *pbuf = NULL;
1526 const char *ps = NULL;
1527 size_t n = 0;
1528 wchar_t wc;
1529 size_t sz = MB_CUR_MAX;
1530
1531 if (sz == 1) {
1532 buf = tostring(s);
1533
1534 for (pbuf = buf; *pbuf; pbuf++)
1535 *pbuf = fun_c((uschar)*pbuf);
1536
1537 return buf;
1538 } else {
1539 /* upper/lower character may be shorter/longer */
1540 buf = tostringN(s, strlen(s) * sz + 1);
1541
1542 (void) mbtowc(NULL, NULL, 0); /* reset internal state */
1543 /*
1544 * Reset internal state here too.
1545 * Assign result to avoid a compiler warning. (Casting to void
1546 * doesn't work.)
1547 * Increment said variable to avoid a different warning.
1548 */
1549 int unused = wctomb(NULL, L'\0');
1550 unused++;
1551
1552 ps = s;
1553 pbuf = buf;
1554 while (n = mbtowc(&wc, ps, sz),
1555 n > 0 && n != (size_t)-1 && n != (size_t)-2)
1556 {
1557 ps += n;
1558
1559 n = wctomb(pbuf, fun_wc(wc));
1560 if (n == (size_t)-1)
1561 FATAL("illegal wide character %s", s);
1562
1563 pbuf += n;
1564 }
1565
1566 *pbuf = '\0';
1567
1568 if (n)
1569 FATAL("illegal byte sequence %s", s);
1570
1571 return buf;
1572 }
1573 }
1574
1575 #ifdef __DJGPP__
towupper(wint_t wc)1576 static wint_t towupper(wint_t wc)
1577 {
1578 if (wc >= 0 && wc < 256)
1579 return toupper(wc & 0xFF);
1580
1581 return wc;
1582 }
1583
towlower(wint_t wc)1584 static wint_t towlower(wint_t wc)
1585 {
1586 if (wc >= 0 && wc < 256)
1587 return tolower(wc & 0xFF);
1588
1589 return wc;
1590 }
1591 #endif
1592
nawk_toupper(const char * s)1593 static char *nawk_toupper(const char *s)
1594 {
1595 return nawk_convert(s, toupper, towupper);
1596 }
1597
nawk_tolower(const char * s)1598 static char *nawk_tolower(const char *s)
1599 {
1600 return nawk_convert(s, tolower, towlower);
1601 }
1602
bltin(Node ** a,int n)1603 Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */
1604 {
1605 Cell *x, *y;
1606 Awkfloat u;
1607 int t;
1608 Awkfloat tmp;
1609 char *buf;
1610 Node *nextarg;
1611 FILE *fp;
1612 int status = 0;
1613
1614 t = ptoi(a[0]);
1615 x = execute(a[1]);
1616 nextarg = a[1]->nnext;
1617 switch (t) {
1618 case FLENGTH:
1619 if (isarr(x))
1620 u = ((Array *) x->sval)->nelem; /* GROT. should be function*/
1621 else
1622 u = strlen(getsval(x));
1623 break;
1624 case FLOG:
1625 errno = 0;
1626 u = errcheck(log(getfval(x)), "log");
1627 break;
1628 case FINT:
1629 modf(getfval(x), &u); break;
1630 case FEXP:
1631 errno = 0;
1632 u = errcheck(exp(getfval(x)), "exp");
1633 break;
1634 case FSQRT:
1635 errno = 0;
1636 u = errcheck(sqrt(getfval(x)), "sqrt");
1637 break;
1638 case FSIN:
1639 u = sin(getfval(x)); break;
1640 case FCOS:
1641 u = cos(getfval(x)); break;
1642 case FATAN:
1643 if (nextarg == NULL) {
1644 WARNING("atan2 requires two arguments; returning 1.0");
1645 u = 1.0;
1646 } else {
1647 y = execute(a[1]->nnext);
1648 u = atan2(getfval(x), getfval(y));
1649 tempfree(y);
1650 nextarg = nextarg->nnext;
1651 }
1652 break;
1653 case FSYSTEM:
1654 fflush(stdout); /* in case something is buffered already */
1655 status = system(getsval(x));
1656 u = status;
1657 if (status != -1) {
1658 if (WIFEXITED(status)) {
1659 u = WEXITSTATUS(status);
1660 } else if (WIFSIGNALED(status)) {
1661 u = WTERMSIG(status) + 256;
1662 #ifdef WCOREDUMP
1663 if (WCOREDUMP(status))
1664 u += 256;
1665 #endif
1666 } else /* something else?!? */
1667 u = 0;
1668 }
1669 break;
1670 case FRAND:
1671 /* random() returns numbers in [0..2^31-1]
1672 * in order to get a number in [0, 1), divide it by 2^31
1673 */
1674 u = (Awkfloat) random() / (0x7fffffffL + 0x1UL);
1675 break;
1676 case FSRAND:
1677 if (isrec(x)) /* no argument provided */
1678 u = time((time_t *)0);
1679 else
1680 u = getfval(x);
1681 tmp = u;
1682 srandom((unsigned long) u);
1683 u = srand_seed;
1684 srand_seed = tmp;
1685 break;
1686 case FTOUPPER:
1687 case FTOLOWER:
1688 if (t == FTOUPPER)
1689 buf = nawk_toupper(getsval(x));
1690 else
1691 buf = nawk_tolower(getsval(x));
1692 tempfree(x);
1693 x = gettemp();
1694 setsval(x, buf);
1695 free(buf);
1696 return x;
1697 case FFLUSH:
1698 if (isrec(x) || strlen(getsval(x)) == 0) {
1699 flush_all(); /* fflush() or fflush("") -> all */
1700 u = 0;
1701 } else if ((fp = openfile(FFLUSH, getsval(x), NULL)) == NULL)
1702 u = EOF;
1703 else
1704 u = fflush(fp);
1705 break;
1706 default: /* can't happen */
1707 FATAL("illegal function type %d", t);
1708 break;
1709 }
1710 tempfree(x);
1711 x = gettemp();
1712 setfval(x, u);
1713 if (nextarg != NULL) {
1714 WARNING("warning: function has too many arguments");
1715 for ( ; nextarg; nextarg = nextarg->nnext)
1716 execute(nextarg);
1717 }
1718 return(x);
1719 }
1720
printstat(Node ** a,int n)1721 Cell *printstat(Node **a, int n) /* print a[0] */
1722 {
1723 Node *x;
1724 Cell *y;
1725 FILE *fp;
1726
1727 if (a[1] == NULL) /* a[1] is redirection operator, a[2] is file */
1728 fp = stdout;
1729 else
1730 fp = redirect(ptoi(a[1]), a[2]);
1731 for (x = a[0]; x != NULL; x = x->nnext) {
1732 y = execute(x);
1733 fputs(getpssval(y), fp);
1734 tempfree(y);
1735 if (x->nnext == NULL)
1736 fputs(getsval(orsloc), fp);
1737 else
1738 fputs(getsval(ofsloc), fp);
1739 }
1740 if (a[1] != NULL)
1741 fflush(fp);
1742 if (ferror(fp))
1743 FATAL("write error on %s", filename(fp));
1744 return(True);
1745 }
1746
nullproc(Node ** a,int n)1747 Cell *nullproc(Node **a, int n)
1748 {
1749 return 0;
1750 }
1751
1752
redirect(int a,Node * b)1753 FILE *redirect(int a, Node *b) /* set up all i/o redirections */
1754 {
1755 FILE *fp;
1756 Cell *x;
1757 char *fname;
1758
1759 x = execute(b);
1760 fname = getsval(x);
1761 fp = openfile(a, fname, NULL);
1762 if (fp == NULL)
1763 FATAL("can't open file %s", fname);
1764 tempfree(x);
1765 return fp;
1766 }
1767
1768 struct files {
1769 FILE *fp;
1770 const char *fname;
1771 int mode; /* '|', 'a', 'w' => LE/LT, GT */
1772 } *files;
1773
1774 size_t nfiles;
1775
stdinit(void)1776 static void stdinit(void) /* in case stdin, etc., are not constants */
1777 {
1778 nfiles = FOPEN_MAX;
1779 files = (struct files *) calloc(nfiles, sizeof(*files));
1780 if (files == NULL)
1781 FATAL("can't allocate file memory for %zu files", nfiles);
1782 files[0].fp = stdin;
1783 files[0].fname = "/dev/stdin";
1784 files[0].mode = LT;
1785 files[1].fp = stdout;
1786 files[1].fname = "/dev/stdout";
1787 files[1].mode = GT;
1788 files[2].fp = stderr;
1789 files[2].fname = "/dev/stderr";
1790 files[2].mode = GT;
1791 }
1792
openfile(int a,const char * us,bool * pnewflag)1793 FILE *openfile(int a, const char *us, bool *pnewflag)
1794 {
1795 const char *s = us;
1796 size_t i;
1797 int m;
1798 FILE *fp = NULL;
1799
1800 if (*s == '\0')
1801 FATAL("null file name in print or getline");
1802 for (i = 0; i < nfiles; i++)
1803 if (files[i].fname && strcmp(s, files[i].fname) == 0 &&
1804 (a == files[i].mode || (a==APPEND && files[i].mode==GT) ||
1805 a == FFLUSH)) {
1806 if (pnewflag)
1807 *pnewflag = false;
1808 return files[i].fp;
1809 }
1810 if (a == FFLUSH) /* didn't find it, so don't create it! */
1811 return NULL;
1812
1813 for (i = 0; i < nfiles; i++)
1814 if (files[i].fp == NULL)
1815 break;
1816 if (i >= nfiles) {
1817 struct files *nf;
1818 size_t nnf = nfiles + FOPEN_MAX;
1819 nf = (struct files *) realloc(files, nnf * sizeof(*nf));
1820 if (nf == NULL)
1821 FATAL("cannot grow files for %s and %zu files", s, nnf);
1822 memset(&nf[nfiles], 0, FOPEN_MAX * sizeof(*nf));
1823 nfiles = nnf;
1824 files = nf;
1825 }
1826 fflush(stdout); /* force a semblance of order */
1827 m = a;
1828 if (a == GT) {
1829 fp = fopen(s, "w");
1830 } else if (a == APPEND) {
1831 fp = fopen(s, "a");
1832 m = GT; /* so can mix > and >> */
1833 } else if (a == '|') { /* output pipe */
1834 fp = popen(s, "w");
1835 } else if (a == LE) { /* input pipe */
1836 fp = popen(s, "r");
1837 } else if (a == LT) { /* getline <file */
1838 fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */
1839 } else /* can't happen */
1840 FATAL("illegal redirection %d", a);
1841 if (fp != NULL) {
1842 files[i].fname = tostring(s);
1843 files[i].fp = fp;
1844 files[i].mode = m;
1845 if (pnewflag)
1846 *pnewflag = true;
1847 if (fp != stdin && fp != stdout && fp != stderr)
1848 (void) fcntl(fileno(fp), F_SETFD, FD_CLOEXEC);
1849 }
1850 return fp;
1851 }
1852
filename(FILE * fp)1853 const char *filename(FILE *fp)
1854 {
1855 size_t i;
1856
1857 for (i = 0; i < nfiles; i++)
1858 if (fp == files[i].fp)
1859 return files[i].fname;
1860 return "???";
1861 }
1862
closefile(Node ** a,int n)1863 Cell *closefile(Node **a, int n)
1864 {
1865 Cell *x;
1866 size_t i;
1867 bool stat;
1868
1869 x = execute(a[0]);
1870 getsval(x);
1871 stat = true;
1872 for (i = 0; i < nfiles; i++) {
1873 if (!files[i].fname || strcmp(x->sval, files[i].fname) != 0)
1874 continue;
1875 if (files[i].mode == GT || files[i].mode == '|')
1876 fflush(files[i].fp);
1877 if (ferror(files[i].fp)) {
1878 if ((files[i].mode == GT && files[i].fp != stderr)
1879 || files[i].mode == '|')
1880 FATAL("write error on %s", files[i].fname);
1881 else
1882 WARNING("i/o error occurred on %s", files[i].fname);
1883 }
1884 if (files[i].fp == stdin || files[i].fp == stdout ||
1885 files[i].fp == stderr)
1886 stat = freopen("/dev/null", "r+", files[i].fp) == NULL;
1887 else if (files[i].mode == '|' || files[i].mode == LE)
1888 stat = pclose(files[i].fp) == -1;
1889 else
1890 stat = fclose(files[i].fp) == EOF;
1891 if (stat)
1892 WARNING("i/o error occurred closing %s", files[i].fname);
1893 if (i > 2) /* don't do /dev/std... */
1894 xfree(files[i].fname);
1895 files[i].fname = NULL; /* watch out for ref thru this */
1896 files[i].fp = NULL;
1897 break;
1898 }
1899 tempfree(x);
1900 x = gettemp();
1901 setfval(x, (Awkfloat) (stat ? -1 : 0));
1902 return(x);
1903 }
1904
closeall(void)1905 void closeall(void)
1906 {
1907 size_t i;
1908 bool stat = false;
1909
1910 for (i = 0; i < nfiles; i++) {
1911 if (! files[i].fp)
1912 continue;
1913 if (files[i].mode == GT || files[i].mode == '|')
1914 fflush(files[i].fp);
1915 if (ferror(files[i].fp)) {
1916 if ((files[i].mode == GT && files[i].fp != stderr)
1917 || files[i].mode == '|')
1918 FATAL("write error on %s", files[i].fname);
1919 else
1920 WARNING("i/o error occurred on %s", files[i].fname);
1921 }
1922 if (files[i].fp == stdin || files[i].fp == stdout ||
1923 files[i].fp == stderr)
1924 continue;
1925 if (files[i].mode == '|' || files[i].mode == LE)
1926 stat = pclose(files[i].fp) == -1;
1927 else
1928 stat = fclose(files[i].fp) == EOF;
1929 if (stat)
1930 WARNING("i/o error occurred while closing %s", files[i].fname);
1931 }
1932 }
1933
flush_all(void)1934 static void flush_all(void)
1935 {
1936 size_t i;
1937
1938 for (i = 0; i < nfiles; i++)
1939 if (files[i].fp)
1940 fflush(files[i].fp);
1941 }
1942
1943 void backsub(char **pb_ptr, const char **sptr_ptr);
1944
sub(Node ** a,int nnn)1945 Cell *sub(Node **a, int nnn) /* substitute command */
1946 {
1947 const char *sptr, *q;
1948 Cell *x, *y, *result;
1949 char *t, *buf, *pb;
1950 fa *pfa;
1951 int bufsz = recsize;
1952
1953 if ((buf = (char *) malloc(bufsz)) == NULL)
1954 FATAL("out of memory in sub");
1955 x = execute(a[3]); /* target string */
1956 t = getsval(x);
1957 if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */
1958 pfa = (fa *) a[1]; /* regular expression */
1959 else {
1960 y = execute(a[1]);
1961 pfa = makedfa(getsval(y), 1);
1962 tempfree(y);
1963 }
1964 y = execute(a[2]); /* replacement string */
1965 result = False;
1966 if (pmatch(pfa, t)) {
1967 sptr = t;
1968 adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub");
1969 pb = buf;
1970 while (sptr < patbeg)
1971 *pb++ = *sptr++;
1972 sptr = getsval(y);
1973 while (*sptr != '\0') {
1974 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub");
1975 if (*sptr == '\\') {
1976 backsub(&pb, &sptr);
1977 } else if (*sptr == '&') {
1978 sptr++;
1979 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub");
1980 for (q = patbeg; q < patbeg+patlen; )
1981 *pb++ = *q++;
1982 } else
1983 *pb++ = *sptr++;
1984 }
1985 *pb = '\0';
1986 if (pb > buf + bufsz)
1987 FATAL("sub result1 %.30s too big; can't happen", buf);
1988 sptr = patbeg + patlen;
1989 if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
1990 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
1991 while ((*pb++ = *sptr++) != '\0')
1992 continue;
1993 }
1994 if (pb > buf + bufsz)
1995 FATAL("sub result2 %.30s too big; can't happen", buf);
1996 setsval(x, buf); /* BUG: should be able to avoid copy */
1997 result = True;
1998 }
1999 tempfree(x);
2000 tempfree(y);
2001 free(buf);
2002 return result;
2003 }
2004
gsub(Node ** a,int nnn)2005 Cell *gsub(Node **a, int nnn) /* global substitute */
2006 {
2007 Cell *x, *y;
2008 char *rptr, *pb;
2009 const char *q, *t, *sptr;
2010 char *buf;
2011 fa *pfa;
2012 int mflag, tempstat, num;
2013 int bufsz = recsize;
2014
2015 if ((buf = (char *) malloc(bufsz)) == NULL)
2016 FATAL("out of memory in gsub");
2017 mflag = 0; /* if mflag == 0, can replace empty string */
2018 num = 0;
2019 x = execute(a[3]); /* target string */
2020 t = getsval(x);
2021 if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */
2022 pfa = (fa *) a[1]; /* regular expression */
2023 else {
2024 y = execute(a[1]);
2025 pfa = makedfa(getsval(y), 1);
2026 tempfree(y);
2027 }
2028 y = execute(a[2]); /* replacement string */
2029 if (pmatch(pfa, t)) {
2030 tempstat = pfa->initstat;
2031 pfa->initstat = 2;
2032 pb = buf;
2033 rptr = getsval(y);
2034 do {
2035 if (patlen == 0 && *patbeg != '\0') { /* matched empty string */
2036 if (mflag == 0) { /* can replace empty */
2037 num++;
2038 sptr = rptr;
2039 while (*sptr != '\0') {
2040 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
2041 if (*sptr == '\\') {
2042 backsub(&pb, &sptr);
2043 } else if (*sptr == '&') {
2044 sptr++;
2045 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
2046 for (q = patbeg; q < patbeg+patlen; )
2047 *pb++ = *q++;
2048 } else
2049 *pb++ = *sptr++;
2050 }
2051 }
2052 if (*t == '\0') /* at end */
2053 goto done;
2054 adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
2055 *pb++ = *t++;
2056 if (pb > buf + bufsz) /* BUG: not sure of this test */
2057 FATAL("gsub result0 %.30s too big; can't happen", buf);
2058 mflag = 0;
2059 }
2060 else { /* matched nonempty string */
2061 num++;
2062 sptr = t;
2063 adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub");
2064 while (sptr < patbeg)
2065 *pb++ = *sptr++;
2066 sptr = rptr;
2067 while (*sptr != '\0') {
2068 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
2069 if (*sptr == '\\') {
2070 backsub(&pb, &sptr);
2071 } else if (*sptr == '&') {
2072 sptr++;
2073 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
2074 for (q = patbeg; q < patbeg+patlen; )
2075 *pb++ = *q++;
2076 } else
2077 *pb++ = *sptr++;
2078 }
2079 t = patbeg + patlen;
2080 if (patlen == 0 || *t == '\0' || *(t-1) == '\0')
2081 goto done;
2082 if (pb > buf + bufsz)
2083 FATAL("gsub result1 %.30s too big; can't happen", buf);
2084 mflag = 1;
2085 }
2086 } while (pmatch(pfa,t));
2087 sptr = t;
2088 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
2089 while ((*pb++ = *sptr++) != '\0')
2090 continue;
2091 done: if (pb < buf + bufsz)
2092 *pb = '\0';
2093 else if (*(pb-1) != '\0')
2094 FATAL("gsub result2 %.30s truncated; can't happen", buf);
2095 setsval(x, buf); /* BUG: should be able to avoid copy + free */
2096 pfa->initstat = tempstat;
2097 }
2098 tempfree(x);
2099 tempfree(y);
2100 x = gettemp();
2101 x->tval = NUM;
2102 x->fval = num;
2103 free(buf);
2104 return(x);
2105 }
2106
backsub(char ** pb_ptr,const char ** sptr_ptr)2107 void backsub(char **pb_ptr, const char **sptr_ptr) /* handle \\& variations */
2108 { /* sptr[0] == '\\' */
2109 char *pb = *pb_ptr;
2110 const char *sptr = *sptr_ptr;
2111 static bool first = true;
2112 static bool do_posix = false;
2113
2114 if (first) {
2115 first = false;
2116 do_posix = (getenv("POSIXLY_CORRECT") != NULL);
2117 }
2118
2119 if (sptr[1] == '\\') {
2120 if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
2121 *pb++ = '\\';
2122 *pb++ = '&';
2123 sptr += 4;
2124 } else if (sptr[2] == '&') { /* \\& -> \ + matched */
2125 *pb++ = '\\';
2126 sptr += 2;
2127 } else if (do_posix) { /* \\x -> \x */
2128 sptr++;
2129 *pb++ = *sptr++;
2130 } else { /* \\x -> \\x */
2131 *pb++ = *sptr++;
2132 *pb++ = *sptr++;
2133 }
2134 } else if (sptr[1] == '&') { /* literal & */
2135 sptr++;
2136 *pb++ = *sptr++;
2137 } else /* literal \ */
2138 *pb++ = *sptr++;
2139
2140 *pb_ptr = pb;
2141 *sptr_ptr = sptr;
2142 }
2143