1 /*
2 Changes by Gunnar Ritter, Freiburg i. Br., Germany, December 2002.
3
4 Sccsid @(#)run.c 1.33 (gritter) 12/25/06>
5 */
6 /* UNIX(R) Regular Expression Tools
7
8 Copyright (C) 2001 Caldera International, Inc.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to:
22 Free Software Foundation, Inc.
23 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25 /* copyright "%c%" */
26
27
28 /* from unixsrc:usr/src/common/cmd/awk/run.c /main/uw7_nj/1 */
29 /* from RCS Header: run.c 1.3 91/08/12 */
30
31 #define tempfree(x,s) if (istemp(x)) tfree(x,s); else
32
33 /* #define execute(p) (isvalue(p) ? (Cell *)((p)->narg[0]) : r_execute(p)) */
34 #define execute(p) r_execute((Node *)p)
35
36 #define DEBUG
37 #include <math.h>
38 #include <stdio.h>
39 #include <ctype.h>
40 #include <setjmp.h>
41 #include <pfmt.h>
42 #include <string.h>
43 #include <errno.h>
44 #include <wctype.h>
45 #include <inttypes.h>
46 #include <time.h>
47 #include "awk.h"
48 #include "y.tab.h"
49
50 jmp_buf env;
51
52 #define getfval(p) (((p)->tval & (ARR|FLD|REC|NUM)) == NUM ? (p)->fval : r_getfval(p))
53 #define getsval(p) (((p)->tval & (ARR|FLD|REC|STR)) == STR ? (p)->sval : r_getsval(p))
54
55 static void tfree(register Cell *a, char *s);
56
57 #define PA2NUM 29
58 int pairstack[PA2NUM];
59 long paircnt;
60 Node *winner = NULL;
61 Cell *tmps;
62
63 static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM };
64 Cell *true = &truecell;
65 static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM };
66 Cell *false = &falsecell;
67 static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM };
68 Cell *jbreak = &breakcell;
69 static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM };
70 Cell *jcont = &contcell;
71 static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM };
72 Cell *jnext = &nextcell;
73 static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM };
74 Cell *jexit = &exitcell;
75 static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM };
76 Cell *jret = &retcell;
77 static Cell tempcell ={ OCELL, CTEMP, 0, 0, 0.0, NUM };
78
79 Node *curnode = NULL; /* the node being executed, for debugging */
80
81 static const char
82 restoobig[] = ":40:%s() result %.20s too big",
83 notarray[] = ":41:%s is not an array",
84 ioerror[] = ":42:I/O error occurred on %s";
85 const char
86 illstat[] = ":43:Illegal statement";
87
88 extern const char readvofid[], readvof[], badopen[];
89
90 static int growsprintf(unsigned char **, unsigned char **,
91 int *, const char *, ...);
92 static void growbuf(unsigned char **buf, int *bufsize, int incr,
93 unsigned char **ptr, const char *fn);
94 static void closeall(void);
95 static void caseconv(unsigned char *s, wint_t (*conv)(wint_t));
96
run(Node * a)97 int run(Node *a)
98 {
99 execute(a);
100 closeall();
101 return 0;
102 }
103
r_execute(Node * u)104 Cell *r_execute(Node *u)
105 {
106 register Cell *(*proc)(Node **, int);
107 register Cell *x;
108 register Node *a;
109
110 if (u == NULL)
111 return(true);
112 for (a = u; ; a = a->nnext) {
113 curnode = a;
114 if (isvalue(a)) {
115 x = (Cell *) (a->narg[0]);
116 if ((x->tval & FLD) && !donefld)
117 fldbld();
118 else if ((x->tval & REC) && !donerec)
119 recbld();
120 return(x);
121 }
122 if (notlegal(a->nobj)) /* probably a Cell* but too risky to print */
123 error(MM_ERROR, illstat);
124 proc = proctab[a->nobj-FIRSTTOKEN];
125 x = (*proc)(a->narg, a->nobj);
126 if ((x->tval & FLD) && !donefld)
127 fldbld();
128 else if ((x->tval & REC) && !donerec)
129 recbld();
130 if (isexpr(a))
131 return(x);
132 /* a statement, goto next statement */
133 if (isjump(x))
134 return(x);
135 if (a->nnext == (Node *)NULL)
136 return(x);
137 tempfree(x, "execute");
138 }
139 }
140
141
program(register Node ** a,int n)142 Cell *program(register Node **a, int n)
143 {
144 register Cell *x = 0;
145
146 if (setjmp(env) != 0)
147 goto ex;
148 if (a[0]) { /* BEGIN */
149 x = execute(a[0]);
150 if (isexit(x))
151 return(true);
152 if (isjump(x))
153 error(MM_ERROR,
154 ":44:Illegal break, continue or next from BEGIN");
155 if(x != 0) { tempfree(x, ""); }
156 }
157 loop:
158 if (a[1] || a[2])
159 while (getrec(&record, &recsize) > 0) {
160 x = execute(a[1]);
161 if (isexit(x))
162 break;
163 if(x != 0) { tempfree(x, ""); }
164 }
165 ex:
166 if (setjmp(env) != 0)
167 goto ex1;
168 if (a[2]) { /* END */
169 x = execute(a[2]);
170 if (iscont(x)) /* read some more */
171 goto loop;
172 if (isbreak(x) || isnext(x))
173 error(MM_ERROR, ":45:Illegal break or next from END");
174 if(x != 0) { tempfree(x, ""); }
175 }
176 ex1:
177 return(true);
178 }
179
180 struct Frame {
181 int nargs; /* number of arguments in this call */
182 Cell *fcncell; /* pointer to Cell for function */
183 Cell **args; /* pointer to array of arguments after execute */
184 Cell *retval; /* return value */
185 };
186
187 #define NARGS 30
188
189 struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */
190 int nframe = 0; /* number of frames allocated */
191 struct Frame *fp = NULL; /* frame pointer. bottom level unused */
192
call(Node ** a,int n)193 Cell *call(Node **a, int n)
194 {
195 static Cell newcopycell = { OCELL, CCOPY, 0, (unsigned char *) "", 0.0, NUM|STR|DONTFREE };
196 int i, ncall, ndef;
197 Node *x;
198 Cell *args[NARGS], *oargs[NARGS], *y, *z, *fcn;
199 unsigned char *s;
200
201 fcn = execute(a[0]); /* the function itself */
202 s = fcn->nval;
203 if (!isfunc(fcn))
204 error(MM_ERROR, ":46:Calling undefined function %s", s);
205 if (frame == NULL) {
206 fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
207 if (frame == NULL)
208 error(MM_ERROR, ":47:Out of space for stack frames calling %s", s);
209 }
210 for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */
211 ncall++;
212 ndef = (int) fcn->fval; /* args in defn */
213 dprintf( ("calling %s, %d args (%d in defn), fp=%ld\n", s,
214 ncall, ndef, (long)(fp-frame)) );
215 if (ncall > ndef) {
216 if (ncall == 1)
217 error(MM_WARNING, ":48:Function %s called with 1 arg, uses only %d",
218 s, ndef);
219 else
220 error(MM_WARNING, ":49:Function %s called with %d args, uses only %d",
221 s, ncall, ndef);
222 }
223 if (ncall + ndef > NARGS)
224 error(MM_ERROR, ":50:Function %s has %d arguments, limit %d",
225 s, ncall+ndef, NARGS);
226 for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */
227 dprintf( ("evaluate args[%d], fp=%ld:\n", i,
228 (long)(fp-frame)) );
229 y = execute(x);
230 oargs[i] = y;
231 dprintf( ("args[%d]: %s %f <%s>, t=%o\n",
232 i, y->nval, y->fval, isarr(y) ?
233 "(array)" : (char*) y->sval, y->tval) );
234 if (isfunc(y))
235 error(MM_ERROR, ":51:Cannot use function %s as argument in %s",
236 y->nval, s);
237 if (isarr(y))
238 args[i] = y; /* arrays by ref */
239 else
240 args[i] = copycell(y);
241 tempfree(y, "callargs");
242 }
243 for ( ; i < ndef; i++) { /* add null args for ones not provided */
244 args[i] = gettemp("nullargs");
245 *args[i] = newcopycell;
246 }
247 fp++; /* now ok to up frame */
248 if (fp >= frame + nframe) {
249 int dfp = fp - frame; /* old index */
250 frame = (struct Frame *)
251 realloc(frame, (nframe += 100) * sizeof(struct Frame));
252 if (frame == NULL)
253 error(MM_ERROR, ":52:Out of space for stack frames in %s", s);
254 fp = frame + dfp;
255 }
256 fp->fcncell = fcn;
257 fp->args = args;
258 fp->nargs = ndef; /* number defined with (excess are locals) */
259 fp->retval = gettemp("retval");
260
261 dprintf( ("start exec of %s, fp=%ld\n", s, (long)(fp-frame)) );
262 y = execute((Node *)(fcn->sval)); /* execute body */
263 dprintf( ("finished exec of %s, fp=%ld\n", s, (long)(fp-frame)) );
264
265 for (i = 0; i < ndef; i++) {
266 Cell *t = fp->args[i];
267 if (isarr(t)) {
268 if (t->csub == CCOPY) {
269 if (i >= ncall) {
270 freesymtab(t);
271 t->csub = CTEMP;
272 } else {
273 oargs[i]->tval = t->tval;
274 oargs[i]->tval &= ~(STR|NUM|DONTFREE);
275 oargs[i]->sval = t->sval;
276 tempfree(t, "oargsarr");
277 }
278 }
279 } else if (t != y) { /* kludge to prevent freeing twice */
280 t->csub = CTEMP;
281 tempfree(t, "fp->args");
282 }
283 }
284 tempfree(fcn, "call.fcn");
285 if (isexit(y) || isnext(y))
286 return y;
287 tempfree(y, "fcn ret"); /* this can free twice! */
288 z = fp->retval; /* return value */
289 dprintf( ("%s returns %g |%s| %o\n", s, getfval(z),
290 getsval(z), z->tval) );
291 fp--;
292 return(z);
293 }
294
copycell(Cell * x)295 Cell *copycell(Cell *x) /* make a copy of a cell in a temp */
296 {
297 Cell *y;
298
299 y = gettemp("copycell");
300 y->csub = CCOPY; /* prevents freeing until call is over */
301 y->nval = x->nval;
302 y->sval = x->sval ? tostring(x->sval) : NULL;
303 y->fval = x->fval;
304 y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */
305 /* is DONTFREE right? */
306 return y;
307 }
308
309 /*ARGSUSED2*/
arg(Node ** a,int nnn)310 Cell *arg(Node **a, int nnn)
311 {
312 int n;
313
314 n = (intptr_t) a[0]; /* argument number, counting from 0 */
315 dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );
316 if (n+1 > fp->nargs)
317 error(MM_ERROR, ":53:Argument #%d of function %s was not supplied",
318 n+1, fp->fcncell->nval);
319 return fp->args[n];
320 }
321
322 static int in_loop = 0; /* Flag : are we in a [while|do|for] loop ? */
323
jump(Node ** a,int n)324 Cell *jump(Node **a, int n)
325 {
326 register Cell *y;
327
328 switch (n) {
329 case EXIT:
330 if (a[0] != NULL) {
331 y = execute(a[0]);
332 errorflag = getfval(y);
333 tempfree(y, "");
334 }
335 longjmp(env, 1);
336 case RETURN:
337 if (a[0] != NULL) {
338 y = execute(a[0]);
339 if ((y->tval & (STR|NUM)) == (STR|NUM)) {
340 setsval(fp->retval, getsval(y));
341 fp->retval->fval = getfval(y);
342 fp->retval->tval |= NUM;
343 }
344 else if (y->tval & STR)
345 setsval(fp->retval, getsval(y));
346 else if (y->tval & NUM)
347 setfval(fp->retval, getfval(y));
348 tempfree(y, "");
349 }
350 return(jret);
351 case NEXT:
352 return(jnext);
353 case BREAK:
354 if (posix && !in_loop)
355 error(MM_ERROR, ":101:break-statement outside of a loop");
356 return(jbreak);
357 case CONTINUE:
358 if (posix && !in_loop)
359 error(MM_ERROR, ":102:continue-statement outside of a loop");
360 return(jcont);
361 default: /* can't happen */
362 error(MM_ERROR, ":54:Illegal jump type %d", n);
363 /*NOTREACHED*/
364 return 0;
365 }
366 }
367
getline(Node ** a,int n)368 Cell *getline(Node **a, int n)
369 {
370 /* a[0] is variable, a[1] is operator, a[2] is filename */
371 register Cell *r, *x;
372 unsigned char *buf = NULL;
373 int bufsize = 0;
374 FILE *fp;
375
376 fflush(stdout); /* in case someone is waiting for a prompt */
377 r = gettemp("");
378 if (a[1] != NULL) { /* getline < file */
379 x = execute(a[2]); /* filename */
380 if ((intptr_t) a[1] == '|') /* input pipe */
381 a[1] = (Node *) LE; /* arbitrary flag */
382 fp = openfile((intptr_t) a[1], getsval(x));
383 tempfree(x, "");
384 if (fp == NULL)
385 n = -1;
386 else
387 n = readrec(&buf, &bufsize, fp);
388 if (n <= 0) {
389 ;
390 } else if (a[0] != NULL) { /* getline var <file */
391 setsval(execute(a[0]), buf);
392 } else { /* getline <file */
393 makerec(buf, bufsize);
394 }
395 } else { /* bare getline; use current input */
396 if (a[0] == NULL) /* getline */
397 n = getrec(&record, &recsize);
398 else { /* getline var */
399 n = getrec(&buf, &bufsize);
400 setsval(execute(a[0]), buf);
401 }
402 }
403 setfval(r, (Awkfloat) n);
404 if (bufsize)
405 free(buf);
406 return r;
407 }
408
getnf(register Node ** a,int n)409 Cell *getnf(register Node **a, int n)
410 {
411 if (donefld == 0)
412 fldbld();
413 return (Cell *) a[0];
414 }
415
array(register Node ** a,int n)416 Cell *array(register Node **a, int n)
417 {
418 register Cell *x, *y, *z;
419 register unsigned char *s;
420 register Node *np;
421 unsigned char *buf = NULL;
422 int bufsz = 0, subseplen, len = 1, l;
423
424 x = execute(a[0]); /* Cell* for symbol table */
425 subseplen = strlen((char *)*SUBSEP);
426 growbuf(&buf, &bufsz, CHUNK, NULL, "array");
427 buf[0] = 0;
428 for (np = a[1]; np; np = np->nnext) {
429 y = execute(np); /* subscript */
430 s = getsval(y);
431 len += (l = strlen((char *)s) + subseplen);
432 if (len >= bufsz)
433 growbuf(&buf, &bufsz, l, NULL, "array");
434 strcat((char*)buf, (char*)s);
435 if (np->nnext)
436 strcat((char*)buf, (char*)*SUBSEP);
437 tempfree(y, "");
438 }
439 if (!isarr(x)) {
440 dprintf( ("making %s into an array\n", x->nval) );
441 if (freeable(x))
442 xfree(x->sval);
443 x->tval &= ~(STR|NUM|DONTFREE);
444 x->tval |= ARR;
445 x->sval = (unsigned char *) makesymtab(NSYMTAB);
446 }
447 z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
448 z->ctype = OCELL;
449 z->csub = CVAR;
450 tempfree(x, "");
451 free(buf);
452 return(z);
453 }
454
delete(Node ** a,int n)455 Cell *delete(Node **a, int n)
456 {
457 Cell *x, *y;
458 Node *np;
459 unsigned char *buf = NULL, *s;
460 int bufsz = 0, subseplen, len = 1, l;
461
462 x = execute(a[0]); /* Cell* for symbol table */
463 if (!isarr(x))
464 return true;
465 subseplen = strlen((char *)*SUBSEP);
466 growbuf(&buf, &bufsz, CHUNK, NULL, "delete");
467 buf[0] = 0;
468 for (np = a[1]; np; np = np->nnext) {
469 y = execute(np); /* subscript */
470 s = getsval(y);
471 len += (l = strlen((char *)s) + subseplen);
472 if (len >= bufsz)
473 growbuf(&buf, &bufsz, l, NULL, "delete");
474 strcat((char*)buf, (char*)s);
475 if (np->nnext)
476 strcat((char*)buf, (char*)*SUBSEP);
477 tempfree(y, "");
478 }
479 freeelem(x, buf);
480 tempfree(x, "");
481 free(buf);
482 return true;
483 }
484
intest(Node ** a,int n)485 Cell *intest(Node **a, int n)
486 {
487 register Cell *x, *ap, *k;
488 Node *p;
489 unsigned char *s;
490 unsigned char *buf = NULL;
491 int bufsz = 0, subseplen, len = 1, l;
492
493 ap = execute(a[1]); /* array name */
494 if (!isarr(ap))
495 error(MM_ERROR, notarray, ap->nval);
496 subseplen = strlen((char *)*SUBSEP);
497 growbuf(&buf, &bufsz, CHUNK, NULL, "intest");
498 buf[0] = 0;
499 for (p = a[0]; p; p = p->nnext) {
500 x = execute(p); /* expr */
501 s = getsval(x);
502 len += (l = strlen((char *)s) + subseplen);
503 if (len >= bufsz)
504 growbuf(&buf, &bufsz, l, NULL, "array");
505 strcat((char *)buf, (char*)s);
506 tempfree(x, "");
507 if (p->nnext)
508 strcat((char *)buf, (char*)*SUBSEP);
509 }
510 k = lookup(buf, (Array *) ap->sval);
511 tempfree(ap, "");
512 free(buf);
513 if (k == NULL)
514 return(false);
515 else
516 return(true);
517 }
518
519
matchop(Node ** a,int n)520 Cell *matchop(Node **a, int n)
521 {
522 register Cell *x, *y;
523 register unsigned char *s, *t;
524 register int i;
525 fa *pfa;
526 int (*mf)(void *, unsigned char *) = match, mode = 0;
527
528 if (n == MATCHFCN) {
529 mf = pmatch;
530 mode = 1;
531 }
532 x = execute(a[1]);
533 s = getsval(x);
534 if (a[0] == 0)
535 i = (*mf)(a[2], s);
536 else {
537 y = execute(a[2]);
538 t = getsval(y);
539 pfa = makedfa(t, mode);
540 i = (*mf)(pfa, s);
541 tempfree(y, "");
542 }
543 tempfree(x, "");
544 if (n == MATCHFCN) {
545 int start, length;
546 if (patlen < 0) {
547 start = 0;
548 length = patlen;
549 } else {
550 start = chrdist(s, patbeg);
551 length = chrdist(patbeg, &patbeg[patlen - 1]);
552 }
553 setfval(rstartloc, (Awkfloat) start);
554 setfval(rlengthloc, (Awkfloat) length);
555 x = gettemp("");
556 x->tval = NUM;
557 x->fval = start;
558 return x;
559 } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
560 return(true);
561 else
562 return(false);
563 }
564
565
boolop(Node ** a,int n)566 Cell *boolop(Node **a, int n)
567 {
568 register Cell *x, *y;
569 register int i;
570
571 x = execute(a[0]);
572 i = istrue(x);
573 tempfree(x, "");
574 switch (n) {
575 case BOR:
576 if (i) return(true);
577 y = execute(a[1]);
578 i = istrue(y);
579 tempfree(y, "");
580 if (i) return(true);
581 else return(false);
582 case AND:
583 if ( !i ) return(false);
584 y = execute(a[1]);
585 i = istrue(y);
586 tempfree(y, "");
587 if (i) return(true);
588 else return(false);
589 case NOT:
590 if (i) return(false);
591 else return(true);
592 default: /* can't happen */
593 error(MM_ERROR, ":55:Unknown boolean operator %d", n);
594 }
595 /*NOTREACHED*/
596 return 0;
597 }
598
relop(Node ** a,int n)599 Cell *relop(Node **a, int n)
600 {
601 register int i;
602 register Cell *x, *y;
603 Awkfloat j;
604
605 x = execute(a[0]);
606 y = execute(a[1]);
607 if (x->tval&NUM && y->tval&NUM) {
608 j = x->fval - y->fval;
609 i = j<0? -1: (j>0? 1: 0);
610 } else {
611 i = strcoll((char*)getsval(x), (char*)getsval(y));
612 }
613 tempfree(x, "");
614 tempfree(y, "");
615 switch (n) {
616 case LT: if (i<0) return(true);
617 else return(false);
618 case LE: if (i<=0) return(true);
619 else return(false);
620 case NE: if (i!=0) return(true);
621 else return(false);
622 case EQ: if (i == 0) return(true);
623 else return(false);
624 case GE: if (i>=0) return(true);
625 else return(false);
626 case GT: if (i>0) return(true);
627 else return(false);
628 default: /* can't happen */
629 error(MM_ERROR, ":56:Unknown relational operator %d", n);
630 }
631 /*NOTREACHED*/
632 return 0;
633 }
634
tfree(register Cell * a,char * s)635 static void tfree(register Cell *a, char *s)
636 {
637 if (dbg>1) printf("## tfree %.8s %06lo %s\n",
638 s, (long)a, a->sval ? a->sval : (unsigned char *)"");
639 if (freeable(a))
640 xfree(a->sval);
641 if (a == tmps)
642 error(MM_ERROR, ":57:Tempcell list is curdled");
643 a->cnext = tmps;
644 tmps = a;
645 }
646
gettemp(const char * s)647 Cell *gettemp(const char *s)
648 { int i;
649 register Cell *x;
650
651 if (!tmps) {
652 tmps = (Cell *) calloc(100, sizeof(Cell));
653 if (!tmps)
654 error(MM_ERROR, ":58:No space for temporaries");
655 for(i = 1; i < 100; i++)
656 tmps[i-1].cnext = &tmps[i];
657 tmps[i-1].cnext = 0;
658 }
659 x = tmps;
660 tmps = x->cnext;
661 *x = tempcell;
662 if (dbg>1) printf("## gtemp %.8s %06lo\n", s, (long)x);
663 return(x);
664 }
665
indirect(Node ** a,int n)666 Cell *indirect(Node **a, int n)
667 {
668 register Cell *x;
669 register int m;
670 register unsigned char *s;
671
672 x = execute(a[0]);
673 m = getfval(x);
674 if (m == 0 && !is2number(s = getsval(x), 0)) /* suspicion! */
675 error(MM_ERROR, ":59:Illegal field $(%s)", s);
676 tempfree(x, "");
677 x = fieldadr(m);
678 x->ctype = OCELL;
679 x->csub = CFLD;
680 return(x);
681 }
682
substr(Node ** a,int nnn)683 Cell *substr(Node **a, int nnn)
684 {
685 register int k, m, n;
686 wchar_t wc;
687 register unsigned char *s, *sp, *sq;
688 int temp;
689 register Cell *x, *y, *z = 0;
690
691 x = execute(a[0]);
692 y = execute(a[1]);
693 if (a[2] != 0)
694 z = execute(a[2]);
695 s = getsval(x);
696 k = strlen((char*)s) + 1;
697 if (k <= 1) {
698 tempfree(x, "");
699 tempfree(y, "");
700 if (a[2] != 0) {
701 tempfree(z, "");
702 }
703 x = gettemp("");
704 setsval(x, (unsigned char *)"");
705 return(x);
706 }
707 m = getfval(y);
708 if (m <= 0)
709 m = 1;
710 else if (m > k)
711 m = k;
712 tempfree(y, "");
713 if (a[2] != 0) {
714 n = getfval(z);
715 tempfree(z, "");
716 } else
717 n = k - 1;
718 if (n < 0)
719 n = 0;
720 else if (n > k - m)
721 n = k - m;
722 dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) );
723 if (mb_cur_max > 1) {
724 for (sp = s; m > 1 && *sp; m--) {
725 next(wc, sp, k);
726 sp += k;
727 }
728 m = sp - s + 1;
729 for (sq = sp ; n > 0 && *sq; n--) {
730 next(wc, sq, k);
731 sq += k;
732 }
733 n = sq - sp;
734 dprintf( ("substr: multibyte: m=%d, n=%d, s=%s\n", m, n, s) );
735 }
736 y = gettemp("");
737 temp = s[n+m-1]; /* with thanks to John Linderman */
738 s[n+m-1] = '\0';
739 setsval(y, s + m - 1);
740 s[n+m-1] = temp;
741 tempfree(x, "");
742 return(y);
743 }
744
sindex(Node ** a,int nnn)745 Cell *sindex(Node **a, int nnn)
746 {
747 register Cell *x, *y, *z;
748 register unsigned char *s1, *s2, *p1, *p2, *q;
749 int n, nq, n2;
750 wchar_t wc, wq, w2;
751 Awkfloat v = 0.0;
752
753 x = execute(a[0]);
754 s1 = getsval(x);
755 y = execute(a[1]);
756 s2 = getsval(y);
757
758 z = gettemp("");
759 for (p1 = s1; next(wc, p1, n), wc != '\0'; p1 += n) {
760 for (q = p1, p2 = s2;
761 next(wq, q, nq),
762 next(w2, p2, n2),
763 w2 != '\0' && wq == w2;
764 q += nq, p2 += n2)
765 ;
766 if (w2 == '\0') {
767 v = (Awkfloat) chrdist(s1, p1);
768 break;
769 }
770 }
771 tempfree(x, "");
772 tempfree(y, "");
773 setfval(z, v);
774 return(z);
775 }
776
777
format(unsigned char ** buf,int * bufsize,const unsigned char * s,Node * a)778 int format(unsigned char **buf, int *bufsize, const unsigned char *s, Node *a)
779 {
780 unsigned char *fmt = NULL;
781 int fmtsz = 0;
782 unsigned char *p, *t;
783 const unsigned char *os;
784 register Cell *x;
785 int flag = 0;
786
787 os = s;
788 fmt = malloc(fmtsz = CHUNK);
789 if (*bufsize == 0)
790 *buf = malloc(*bufsize = CHUNK);
791 if (fmt == NULL || *buf == NULL)
792 error(MM_ERROR, outofspace, "format");
793 p = *buf;
794 while (*s) {
795 if (p >= &(*buf)[*bufsize])
796 growbuf(buf, bufsize, CHUNK, &p, "format");
797 if (*s != '%') {
798 *p++ = *s++;
799 continue;
800 }
801 if (*(s+1) == '%') {
802 *p++ = '%';
803 s += 2;
804 continue;
805 }
806 for (t=fmt; (*t++ = *s) != '\0'; s++) {
807 if (t >= &fmt[fmtsz])
808 growbuf(&fmt, &fmtsz, CHUNK, &t, "format");
809 if (isalpha(*s) && *s != 'l' && *s != 'h' && *s != 'L')
810 break; /* the ansi panoply */
811 if (*s == '*') {
812 x = execute(a);
813 a = a->nnext;
814 t--;
815 growsprintf(&fmt, &t, &fmtsz, "%d", (int) getfval(x));
816 tempfree(x, "");
817 }
818 }
819 *t = '\0';
820 switch (*s) {
821 case 'a': case 'A':
822 case 'e': case 'E':
823 case 'f': case 'F':
824 case 'g': case 'G':
825 flag = 1;
826 break;
827 case 'd': case 'i':
828 flag = 2;
829 if(*(s-1) == 'l') break;
830 *(t-1) = 'l';
831 *t = 'd';
832 *++t = '\0';
833 break;
834 case 'o': case 'x': case 'X': case 'u':
835 flag = *(s-1) == 'l' ? 12 : 13;
836 break;
837 case 's':
838 /*
839 * Note: If MB_CUR_MAX > 1, the precision is in
840 * bytes, not characters. This doesn't make much
841 * sense in awk context, but it seems to match
842 * what POSIX demands.
843 */
844 flag = 4;
845 break;
846 case 'c':
847 if (mb_cur_max > 1) {
848 *(t-1) = 'l';
849 *t = 'c';
850 *++t = '\0';
851 flag = 6;
852 } else
853 flag = 5;
854 break;
855 default:
856 flag = 0;
857 break;
858 }
859 if (flag == 0) {
860 growsprintf(buf, &p, bufsize, "%s", fmt);
861 continue;
862 }
863 if (a == NULL)
864 error(MM_ERROR, ":61:Not enough args in printf(%s)",
865 os);
866 x = execute(a);
867 a = a->nnext;
868 switch (flag) {
869 case 1: growsprintf(buf, &p, bufsize, (char *)fmt, getfval(x));
870 break;
871 case 2: growsprintf(buf, &p, bufsize, (char *)fmt,
872 (long) getfval(x));
873 break;
874 case 3: growsprintf(buf, &p, bufsize, (char *)fmt,
875 (int) getfval(x));
876 break;
877 case 12:growsprintf(buf, &p, bufsize, (char *)fmt,
878 (unsigned long) getfval(x));
879 break;
880 case 13:growsprintf(buf, &p, bufsize, (char *)fmt,
881 (unsigned int) getfval(x));
882 break;
883 case 4: growsprintf(buf, &p, bufsize, (char *)fmt, getsval(x));
884 break;
885 case 5: isnum(x) ? growsprintf(buf, &p, bufsize, (char *)fmt,
886 (int) getfval(x))
887 : growsprintf(buf, &p, bufsize, (char *)fmt,
888 getsval(x)[0]);
889 break;
890 case 6: isnum(x) ? growsprintf(buf, &p, bufsize, (char *)fmt,
891 (wint_t) getfval(x))
892 : growsprintf(buf, &p, bufsize, (char *)fmt,
893 (wint_t) getsval(x)[0]);
894 break;
895 }
896 tempfree(x, "");
897 s++;
898 }
899 *p = '\0';
900 for ( ; a; a = a->nnext) /* evaluate any remaining args */
901 execute(a);
902 xfree(fmt);
903 return 0;
904 }
905
awsprintf(Node ** a,int n)906 Cell *awsprintf(Node **a, int n)
907 {
908 register Cell *x;
909 register Node *y;
910 unsigned char *buf = NULL;
911 int bufsize = 0;
912
913 y = a[0]->nnext;
914 x = execute(a[0]);
915 if (format(&buf, &bufsize, getsval(x), y) == -1)
916 error(MM_ERROR, ":62:sprintf string %.40s ... too long", buf);
917 tempfree(x, "");
918 x = gettemp("");
919 x->sval = /*tostring(buf);*/ buf ? buf : tostring("");
920 x->tval = STR;
921 return(x);
922 }
923
aprintf(Node ** a,int n)924 Cell *aprintf(Node **a, int n)
925 {
926 FILE *fp;
927 register Cell *x;
928 register Node *y;
929 unsigned char *buf = NULL;
930 int bufsize = 0;
931
932 y = a[0]->nnext;
933 x = execute(a[0]);
934 if (format(&buf, &bufsize, getsval(x), y) == -1)
935 error(MM_ERROR, ":63:printf string %.40s ... too long", buf);
936 tempfree(x, "");
937 if (buf) {
938 if (a[1] == NULL)
939 fputs((char *)buf, stdout);
940 else {
941 fp = redirect((intptr_t)a[1], a[2]);
942 fputs((char *)buf, fp);
943 fflush(fp);
944 }
945 free(buf);
946 }
947 return(true);
948 }
949
arith(Node ** a,int n)950 Cell *arith(Node **a, int n)
951 {
952 Awkfloat i, j = 0;
953 double v;
954 register Cell *x, *y, *z;
955
956 x = execute(a[0]);
957 i = getfval(x);
958 tempfree(x, "");
959 if (n != UMINUS) {
960 y = execute(a[1]);
961 j = getfval(y);
962 tempfree(y, "");
963 }
964 z = gettemp("");
965 switch (n) {
966 case ADD:
967 i += j;
968 break;
969 case MINUS:
970 i -= j;
971 break;
972 case MULT:
973 i *= j;
974 break;
975 case DIVIDE:
976 if (j == 0)
977 error(MM_ERROR, ":64:Division by zero");
978 i /= j;
979 break;
980 case MOD:
981 if (j == 0)
982 error(MM_ERROR, ":65:Division by zero in mod");
983 modf(i/j, &v);
984 i = i - j * v;
985 break;
986 case UMINUS:
987 i = -i;
988 break;
989 case POWER:
990 if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
991 i = ipow(i, (int) j);
992 else
993 i = errcheck(pow(i, j), (unsigned char *)"pow");
994 break;
995 default: /* can't happen */
996 error(MM_ERROR, ":66:Illegal arithmetic operator %d", n);
997 }
998 setfval(z, i);
999 return(z);
1000 }
1001
ipow(double x,int n)1002 double ipow(double x, int n)
1003 {
1004 double v;
1005
1006 if (n <= 0)
1007 return 1;
1008 v = ipow(x, n/2);
1009 if (n % 2 == 0)
1010 return v * v;
1011 else
1012 return x * v * v;
1013 }
1014
incrdecr(Node ** a,int n)1015 Cell *incrdecr(Node **a, int n)
1016 {
1017 register Cell *x, *z;
1018 register int k;
1019 Awkfloat xf;
1020
1021 x = execute(a[0]);
1022 xf = getfval(x);
1023 k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
1024 if (n == PREINCR || n == PREDECR) {
1025 setfval(x, xf + k);
1026 return(x);
1027 }
1028 z = gettemp("");
1029 setfval(z, xf);
1030 setfval(x, xf + k);
1031 tempfree(x, "");
1032 return(z);
1033 }
1034
assign(Node ** a,int n)1035 Cell *assign(Node **a, int n)
1036 {
1037 register Cell *x, *y;
1038 Awkfloat xf, yf;
1039 double v;
1040
1041 y = execute(a[1]);
1042 x = execute(a[0]); /* order reversed from before... */
1043 if (n == ASSIGN) { /* ordinary assignment */
1044 if ((y->tval & (STR|NUM)) == (STR|NUM)) {
1045 setsval(x, getsval(y));
1046 x->fval = getfval(y);
1047 x->tval |= NUM;
1048 }
1049 else if (y->tval & STR)
1050 setsval(x, getsval(y));
1051 else if (y->tval & NUM)
1052 setfval(x, getfval(y));
1053 else
1054 funnyvar(y, (char *)gettxt(readvofid, readvof));
1055 tempfree(y, "");
1056 return(x);
1057 }
1058 xf = getfval(x);
1059 yf = getfval(y);
1060 switch (n) {
1061 case ADDEQ:
1062 xf += yf;
1063 break;
1064 case SUBEQ:
1065 xf -= yf;
1066 break;
1067 case MULTEQ:
1068 xf *= yf;
1069 break;
1070 case DIVEQ:
1071 if (yf == 0)
1072 error(MM_ERROR, ":67:Division by zero in /=");
1073 xf /= yf;
1074 break;
1075 case MODEQ:
1076 if (yf == 0)
1077 error(MM_ERROR, ":68:Division by zero in %%=");
1078 modf(xf/yf, &v);
1079 xf = xf - yf * v;
1080 break;
1081 case POWEQ:
1082 if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */
1083 xf = ipow(xf, (int) yf);
1084 else
1085 xf = errcheck(pow(xf, yf), (unsigned char *)"pow");
1086 break;
1087 default:
1088 error(MM_ERROR, ":69:Illegal assignment operator %d", n);
1089 break;
1090 }
1091 tempfree(y, "");
1092 setfval(x, xf);
1093 return(x);
1094 }
1095
cat(Node ** a,int q)1096 Cell *cat(Node **a, int q)
1097 {
1098 register Cell *x, *y, *z;
1099 register int n1, n2;
1100 register unsigned char *s;
1101
1102 x = execute(a[0]);
1103 y = execute(a[1]);
1104 getsval(x);
1105 getsval(y);
1106 n1 = (int)strlen((char*)x->sval);
1107 n2 = (int)strlen((char*)y->sval);
1108 s = (unsigned char *) malloc(n1 + n2 + 1);
1109 if (s == NULL)
1110 error(MM_ERROR, ":70:Out of space concatenating %.15s and %.15s",
1111 x->sval, y->sval);
1112 strcpy((char*)s, (char*)x->sval);
1113 strcpy((char*)s+n1, (char*)y->sval);
1114 tempfree(y, "");
1115 z = gettemp("");
1116 z->sval = s;
1117 z->tval = STR;
1118 tempfree(x, "");
1119 return(z);
1120 }
1121
pastat(Node ** a,int n)1122 Cell *pastat(Node **a, int n)
1123 {
1124 register Cell *x;
1125
1126 if (a[0] == 0)
1127 x = execute(a[1]);
1128 else {
1129 x = execute(a[0]);
1130 if (istrue(x)) {
1131 tempfree(x, "");
1132 x = execute(a[1]);
1133 }
1134 }
1135 return x;
1136 }
1137
dopa2(Node ** a,int n)1138 Cell *dopa2(Node **a, int n)
1139 {
1140 register Cell *x;
1141 register int pair;
1142
1143 pair = (intptr_t) a[3];
1144 if (pairstack[pair] == 0) {
1145 x = execute(a[0]);
1146 if (istrue(x))
1147 pairstack[pair] = 1;
1148 tempfree(x, "");
1149 }
1150 if (pairstack[pair] == 1) {
1151 x = execute(a[1]);
1152 if (istrue(x))
1153 pairstack[pair] = 0;
1154 tempfree(x, "");
1155 x = execute(a[2]);
1156 return(x);
1157 }
1158 return(false);
1159 }
1160
split(Node ** a,int nnn)1161 Cell *split(Node **a, int nnn)
1162 {
1163 Cell *x = 0, *y, *ap;
1164 register unsigned char *s;
1165 wchar_t sep, wc;
1166 unsigned char *t, temp, num[25], *fs = 0;
1167 int m, n, sepl;
1168
1169 y = execute(a[0]); /* source string */
1170 s = getsval(y);
1171 if (a[2] == 0) /* fs string */
1172 fs = *FS;
1173 else if ((intptr_t) a[3] == STRING) { /* split(str,arr,"string") */
1174 x = execute(a[2]);
1175 fs = getsval(x);
1176 } else if ((intptr_t) a[3] == REGEXPR)
1177 fs = (unsigned char*) "(regexpr)"; /* split(str,arr,/regexpr/) */
1178 else
1179 error(MM_ERROR, ":71:Illegal type of split()");
1180 next(sep, fs, sepl);
1181 ap = execute(a[1]); /* array name */
1182 freesymtab(ap);
1183 dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs) );
1184 ap->tval &= ~STR;
1185 ap->tval |= ARR;
1186 ap->sval = (unsigned char *) makesymtab(NSYMTAB);
1187
1188 n = 0;
1189 if ((*s != '\0' && sep != '\0' && fs[sepl] != '\0') ||
1190 ((intptr_t) a[3] == REGEXPR)) { /* reg expr */
1191 fa *pfa;
1192 if ((intptr_t) a[3] == REGEXPR) { /* it's ready already */
1193 pfa = (fa *) a[2];
1194 } else {
1195 pfa = makedfa(fs, 1);
1196 }
1197 pfa->notbol = 0;
1198 if (nematch(pfa,s)) {
1199 pfa->notbol = REG_NOTBOL;
1200 do {
1201 n++;
1202 snprintf((char *)num, sizeof num, "%d", n);
1203 temp = *patbeg;
1204 *patbeg = '\0';
1205 setsymtab(num, s, 0.0, STR|CANBENUM, (Array *)ap->sval);
1206 *patbeg = temp;
1207 s = patbeg + patlen;
1208 if (*(patbeg+patlen-1) == 0 || *s == 0) {
1209 n++;
1210 snprintf((char *)num, sizeof num, "%d", n);
1211 setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
1212 pfa->notbol = 0;
1213 goto spdone;
1214 }
1215 } while (nematch(pfa,s));
1216 }
1217 n++;
1218 snprintf((char *)num, sizeof num, "%d", n);
1219 setsymtab(num, s, 0.0, STR|CANBENUM, (Array *)ap->sval);
1220 spdone:
1221 pfa = NULL;
1222 } else if (sep == ' ') {
1223 for (n = 0; ; ) {
1224 while (*s == ' ' || *s == '\t' || *s == '\n')
1225 s++;
1226 if (*s == 0)
1227 break;
1228 n++;
1229 t = s;
1230 next(wc, s, m);
1231 do {
1232 s += m;
1233 next(wc, s, m);
1234 } while (wc!=' ' && wc!='\t' && wc!='\n' && wc!='\0');
1235 temp = *s;
1236 *s = '\0';
1237 snprintf((char *)num, sizeof num, "%d", n);
1238 setsymtab(num, t, 0.0, STR|CANBENUM, (Array *)ap->sval);
1239 *s = temp;
1240 if (*s != 0)
1241 s++;
1242 }
1243 } else if (*s != 0) {
1244 for (;;) {
1245 n++;
1246 t = s;
1247 while (next(wc, s, m),
1248 wc != sep && wc != '\n' && wc != '\0')
1249 s += m;
1250 temp = *s;
1251 *s = '\0';
1252 snprintf((char *)num, sizeof num, "%d", n);
1253 setsymtab(num, t, 0.0, STR|CANBENUM, (Array *)ap->sval);
1254 *s = temp;
1255 if (wc == '\0')
1256 break;
1257 s += m;
1258 }
1259 }
1260 tempfree(ap, "");
1261 tempfree(y, "");
1262 if (a[2] != 0 && (intptr_t) a[3] == STRING) {
1263 tempfree(x, "");
1264 }
1265 x = gettemp("");
1266 x->tval = NUM;
1267 x->fval = n;
1268 return(x);
1269 }
1270
condexpr(Node ** a,int n)1271 Cell *condexpr(Node **a, int n)
1272 {
1273 register Cell *x;
1274
1275 x = execute(a[0]);
1276 if (istrue(x)) {
1277 tempfree(x, "");
1278 x = execute(a[1]);
1279 } else {
1280 tempfree(x, "");
1281 x = execute(a[2]);
1282 }
1283 return(x);
1284 }
1285
ifstat(Node ** a,int n)1286 Cell *ifstat(Node **a, int n)
1287 {
1288 register Cell *x;
1289
1290 x = execute(a[0]);
1291 if (istrue(x)) {
1292 tempfree(x, "");
1293 x = execute(a[1]);
1294 } else if (a[2] != 0) {
1295 tempfree(x, "");
1296 x = execute(a[2]);
1297 }
1298 return(x);
1299 }
1300
whilestat(Node ** a,int n)1301 Cell *whilestat(Node **a, int n)
1302 {
1303 register Cell *x;
1304
1305 in_loop++;
1306 for (;;) {
1307 x = execute(a[0]);
1308 if (!istrue(x)) {
1309 in_loop--;
1310 return(x);
1311 }
1312 tempfree(x, "");
1313 x = execute(a[1]);
1314 if (isbreak(x)) {
1315 x = true;
1316 in_loop--;
1317 return(x);
1318 }
1319 if (isnext(x) || isexit(x) || isret(x)) {
1320 in_loop--;
1321 return(x);
1322 }
1323 tempfree(x, "");
1324 }
1325 /*in_loop--;*/
1326 }
1327
dostat(Node ** a,int n)1328 Cell *dostat(Node **a, int n)
1329 {
1330 register Cell *x;
1331
1332 in_loop++;
1333 for (;;) {
1334 x = execute(a[0]);
1335 if (isbreak(x)) {
1336 in_loop--;
1337 return true;
1338 }
1339 if (isnext(x) || isexit(x) || isret(x)) {
1340 in_loop--;
1341 return(x);
1342 }
1343 tempfree(x, "");
1344 x = execute(a[1]);
1345 if (!istrue(x)) {
1346 in_loop--;
1347 return(x);
1348 }
1349 tempfree(x, "");
1350 }
1351 /*in_loop--;*/
1352 }
1353
forstat(Node ** xa,int n)1354 Cell *forstat(Node **xa, int n)
1355 {
1356 char **a = (char **)xa;
1357 register Cell *x;
1358
1359 in_loop++;
1360 x = execute(a[0]);
1361 tempfree(x, "");
1362 for (;;) {
1363 if (a[1]!=0) {
1364 x = execute(a[1]);
1365 if (!istrue(x)) {
1366 in_loop--;
1367 return(x);
1368 }
1369 else tempfree(x, "");
1370 }
1371 x = execute(a[3]);
1372 if (isbreak(x)) { /* turn off break */
1373 in_loop--;
1374 return true;
1375 }
1376 if (isnext(x) || isexit(x) || isret(x)) {
1377 in_loop--;
1378 return(x);
1379 }
1380 tempfree(x, "");
1381 x = execute(a[2]);
1382 tempfree(x, "");
1383 }
1384 /*in_loop--;*/
1385 }
1386
instat(Node ** a,int n)1387 Cell *instat(Node **a, int n)
1388 {
1389 register Cell *x, *vp, *arrayp, *cp, *ncp;
1390 Array *tp;
1391 int i;
1392
1393 in_loop++;
1394 vp = execute(a[0]);
1395 arrayp = execute(a[1]);
1396 if (!isarr(arrayp))
1397 error(MM_ERROR, notarray, arrayp->nval);
1398 tp = (Array *) arrayp->sval;
1399 tempfree(arrayp, "");
1400 for (i = 0; i < tp->size; i++) { /* this routine knows too much */
1401 for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1402 setsval(vp, cp->nval);
1403 ncp = cp->cnext;
1404 x = execute(a[2]);
1405 if (isbreak(x)) {
1406 tempfree(vp, "");
1407 in_loop--;
1408 return true;
1409 }
1410 if (isnext(x) || isexit(x) || isret(x)) {
1411 tempfree(vp, "");
1412 in_loop--;
1413 return(x);
1414 }
1415 tempfree(x, "");
1416 }
1417 }
1418 in_loop--;
1419 return true;
1420 }
1421
1422 static int closefile(const char *a);
1423
bltin(Node ** a,int n)1424 Cell *bltin(Node **a, int n)
1425 {
1426 static unsigned saved_srand = 1;
1427 register Cell *x, *y;
1428 Awkfloat u;
1429 register int t;
1430 unsigned char *p, *buf;
1431 Node *nextarg;
1432
1433 t = (intptr_t) a[0];
1434 x = execute(a[1]);
1435 nextarg = a[1]->nnext;
1436 switch (t) {
1437 case FLENGTH:
1438 u = (Awkfloat) chrlen(getsval(x)); break;
1439 case FLOG:
1440 u = errcheck(log(getfval(x)), (unsigned char *)"log"); break;
1441 case FINT:
1442 modf(getfval(x), &u); break;
1443 case FEXP:
1444 u = errcheck(exp(getfval(x)), (unsigned char *)"exp"); break;
1445 case FSQRT:
1446 u = errcheck(sqrt(getfval(x)), (unsigned char *)"sqrt"); break;
1447 case FSIN:
1448 u = sin(getfval(x)); break;
1449 case FCOS:
1450 u = cos(getfval(x)); break;
1451 case FATAN:
1452 if (nextarg == 0) {
1453 error(MM_WARNING,
1454 ":72:atan2 requires two arguments; returning 1.0");
1455 u = 1.0;
1456 } else {
1457 y = execute(a[1]->nnext);
1458 u = atan2(getfval(x), getfval(y));
1459 tempfree(y, "");
1460 nextarg = nextarg->nnext;
1461 }
1462 break;
1463 case FSYSTEM:
1464 fflush(stdout); /* in case something is buffered already */
1465 u = (Awkfloat) system((char *)getsval(x)) / 256; /* 256 is unix-dep */
1466 break;
1467 case FRAND:
1468 u = (Awkfloat) (rand() % 32767) / 32767.0;
1469 break;
1470 case FSRAND:
1471 u = saved_srand; /* return previous seed */
1472 if (x->tval & REC) /* no argument provided */
1473 saved_srand = time(NULL);
1474 else
1475 saved_srand = getfval(x);
1476 srand((int) saved_srand);
1477 break;
1478 case FTOUPPER:
1479 case FTOLOWER:
1480 p = getsval(x);
1481 if ((buf = malloc(strlen((char *)p) + 1)) == 0)
1482 error(MM_ERROR, outofspace, "case-conversion");
1483 strcpy((char*)buf, (char*)getsval(x));
1484 if (t == FTOUPPER) {
1485 if (mb_cur_max == 1) {
1486 for (p = buf; *p; p++)
1487 if (islower(*p))
1488 *p = toupper(*p);
1489 } else
1490 caseconv(buf, towupper);
1491 } else {
1492 if (mb_cur_max == 1) {
1493 for (p = buf; *p; p++)
1494 if (isupper(*p))
1495 *p = tolower(*p);
1496 } else
1497 caseconv(buf, towlower);
1498 }
1499 tempfree(x, "");
1500 x = gettemp("");
1501 setsval(x, buf);
1502 free(buf);
1503 return x;
1504 case FCLOSE:
1505 u = (Awkfloat)closefile((char *)getsval(x));
1506 break;
1507 default: /* can't happen */
1508 error(MM_ERROR, ":73:Illegal function type %d", t);
1509 break;
1510 }
1511 tempfree(x, "");
1512 x = gettemp("");
1513 setfval(x, u);
1514 if (nextarg != 0) {
1515 error(MM_WARNING, ":74:Function has too many arguments");
1516 for ( ; nextarg; nextarg = nextarg->nnext)
1517 execute(nextarg);
1518 }
1519 return(x);
1520 }
1521
print(Node ** a,int n)1522 Cell *print(Node **a, int n)
1523 {
1524 register Node *x;
1525 register Cell *y;
1526 FILE *fp;
1527
1528 if (a[1] == 0)
1529 fp = stdout;
1530 else
1531 fp = redirect((intptr_t)a[1], a[2]);
1532 for (x = a[0]; x != NULL; x = x->nnext) {
1533 y = execute(x);
1534 /*
1535 * ALMOST getsval(). POSIX.2 requires that
1536 * numeric values be converted according to OFMT
1537 * (not CONVFMT) for print.
1538 */
1539 if (posix && (y->tval & (ARR|FLD|REC|STR)) == STR)
1540 fputs((char *)y->sval, fp);
1541 else if (!posix || (y->tval & (ARR|FLD|REC|NUM)) != NUM)
1542 fputs((char *)r_getsval(y), fp);
1543 else if ((long)y->fval == y->fval)
1544 fprintf(fp, "%ld", (long)y->fval);
1545 else
1546 fprintf(fp, (char *)*OFMT, y->fval);
1547 tempfree(y, "");
1548 if (x->nnext == NULL)
1549 fputs((char *)*ORS, fp);
1550 else
1551 fputs((char *)*OFS, fp);
1552 }
1553 if (a[1] != 0)
1554 fflush(fp);
1555 return(true);
1556 }
1557
1558 /*ARGSUSED*/
nullproc(Node ** a,int n)1559 Cell *nullproc(Node **a, int n) { return 0; }
1560
1561
1562 static struct afile
1563 {
1564 FILE *fp;
1565 unsigned char *fname;
1566 int mode; /* '|', 'a', 'w' */
1567 } *files;
1568 static int fopen_max;
1569
redirect(int a,Node * b)1570 FILE *redirect(int a, Node *b)
1571 {
1572 FILE *fp;
1573 Cell *x;
1574 unsigned char *fname;
1575
1576 x = execute(b);
1577 fname = getsval(x);
1578 fp = openfile(a, fname);
1579 if (fp == NULL)
1580 error(MM_ERROR, badopen, fname, strerror(errno));
1581 tempfree(x, "");
1582 return fp;
1583 }
1584
openfile(int a,unsigned char * s)1585 FILE *openfile(int a, unsigned char *s)
1586 {
1587 register int i, m;
1588 register FILE *fp = 0;
1589
1590 if (*s == '\0')
1591 error(MM_ERROR, ":75:Null file name in print or getline");
1592 for (i=0; i < fopen_max; i++)
1593 if (files[i].fname &&
1594 strcmp((char*)s, (char*)files[i].fname) == 0)
1595 if ((a == files[i].mode) || (a==APPEND && files[i].mode==GT))
1596 return files[i].fp;
1597 for (i=0; i < fopen_max; i++)
1598 if (files[i].fp == 0)
1599 break;
1600 if (i >= fopen_max) {
1601 if ((files = realloc(files, sizeof *files *
1602 (fopen_max = (i + 15))))==0)
1603 error(MM_ERROR, ":76:%s makes too many open files", s);
1604 memset(&files[i], 0, (fopen_max - i) * sizeof *files);
1605 }
1606 fflush(stdout); /* force a semblance of order */
1607 m = a;
1608 if (a == GT) {
1609 fp = fopen((char *)s, "w");
1610 } else if (a == APPEND) {
1611 fp = fopen((char *)s, "a");
1612 m = GT; /* so can mix > and >> */
1613 } else if (a == '|') { /* output pipe */
1614 fp = popen((char *)s, "w");
1615 } else if (a == LE) { /* input pipe */
1616 fp = popen((char *)s, "r");
1617 } else if (a == LT) { /* getline <file */
1618 fp = strcmp((char *)s, "-") == 0 ? stdin : fopen((char *)s, "r"); /* "-" is stdin */
1619 } else /* can't happen */
1620 error(MM_ERROR, ":77:Illegal redirection");
1621 if (fp != NULL) {
1622 files[i].fname = tostring(s);
1623 files[i].fp = fp;
1624 files[i].mode = m;
1625 }
1626 return fp;
1627 }
1628
endfile(struct afile * afp)1629 static int endfile(struct afile *afp)
1630 {
1631 int ret;
1632
1633 if (ferror(afp->fp)) {
1634 clearerr(afp->fp);
1635 error(MM_WARNING, ioerror, afp->fname);
1636 errorflag = 1;
1637 }
1638 if (afp->mode == '|' || afp->mode == LE)
1639 ret = pclose(afp->fp);
1640 else
1641 ret = fclose(afp->fp);
1642 if (ret == EOF) {
1643 error(MM_WARNING, ":79:I/O error occurred while closing %s",
1644 afp->fname);
1645 errorflag = 1;
1646 }
1647 if (afp->fp != stdout) {
1648 xfree(afp->fname);
1649 afp->fp = 0;
1650 }
1651 return ret;
1652 }
1653
closefile(const char * a)1654 static int closefile(const char *a)
1655 {
1656 int i, ret;
1657
1658 ret = EOF;
1659 for (i = 0; i < fopen_max; i++)
1660 if (files[i].fname && strcmp(a, (char*)files[i].fname) == 0)
1661 ret = endfile(&files[i]);
1662 return(ret);
1663 }
1664
closeall(void)1665 static void closeall(void)
1666 {
1667 struct afile std;
1668 int i;
1669
1670 for (i = 0; i < fopen_max; i++)
1671 if (files[i].fp)
1672 (void)endfile(&files[i]);
1673 std.fp = stdout;
1674 std.fname = (unsigned char *)"<stdout>";
1675 std.mode = GT;
1676 (void)endfile(&std);
1677 }
1678
sub(Node ** a,int nnn)1679 Cell *sub(Node **a, int nnn)
1680 {
1681 unsigned char *sptr, *pb, *q;
1682 register Cell *x, *y, *result;
1683 unsigned char *buf = NULL, *t;
1684 int bufsize = 0;
1685 fa *pfa;
1686
1687 x = execute(a[3]); /* target string */
1688 t = getsval(x);
1689 if (a[0] == 0)
1690 pfa = (fa *) a[1]; /* regular expression */
1691 else {
1692 y = execute(a[1]);
1693 pfa = makedfa(getsval(y), 1);
1694 tempfree(y, "");
1695 }
1696 y = execute(a[2]); /* replacement string */
1697 result = false;
1698 if (pmatch(pfa, t)) {
1699 growbuf(&buf, &bufsize, CHUNK, NULL, "sub");
1700 pb = buf;
1701 sptr = t;
1702 while (sptr < patbeg) {
1703 *pb++ = *sptr++;
1704 if (pb >= &buf[bufsize])
1705 growbuf(&buf, &bufsize, CHUNK, &pb, "sub");
1706 }
1707 sptr = getsval(y);
1708 while (*sptr != 0) {
1709 if (*sptr == '\\' && *(sptr+1) == '&') {
1710 sptr++; /* skip \, */
1711 *pb++ = *sptr++; /* add & */
1712 } else if (*sptr == '&') {
1713 sptr++;
1714 for (q = patbeg; q < patbeg+patlen; ) {
1715 *pb++ = *q++;
1716 growbuf(&buf, &bufsize, CHUNK,
1717 &pb, "sub");
1718 }
1719 } else
1720 *pb++ = *sptr++;
1721 if (pb >= &buf[bufsize])
1722 growbuf(&buf, &bufsize, CHUNK, &pb, "sub");
1723 }
1724 *pb = '\0';
1725 sptr = patbeg + patlen;
1726 if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1)))
1727 while ((*pb++ = *sptr++)) {
1728 if (pb >= &buf[bufsize])
1729 growbuf(&buf, &bufsize, CHUNK, &pb,
1730 "sub");
1731 }
1732 setsval(x, buf);
1733 result = true;;
1734 free(buf);
1735 }
1736 tempfree(x, "");
1737 tempfree(y, "");
1738 return result;
1739 }
1740
gsub(Node ** a,int nnn)1741 Cell *gsub(Node **a, int nnn)
1742 {
1743 register Cell *x, *y;
1744 unsigned char *rptr, *sptr, *t, *pb;
1745 unsigned char *buf = NULL;
1746 int bufsize = 0;
1747 register fa *pfa;
1748 int mflag, num;
1749
1750 mflag = 0; /* if mflag == 0, can replace empty string */
1751 num = 0;
1752 x = execute(a[3]); /* target string */
1753 t = getsval(x);
1754 if (a[0] == 0)
1755 pfa = (fa *) a[1]; /* regular expression */
1756 else {
1757 y = execute(a[1]);
1758 pfa = makedfa(getsval(y), 1);
1759 tempfree(y, "");
1760 }
1761 y = execute(a[2]); /* replacement string */
1762 pfa->notbol = 0;
1763 if (pmatch(pfa, t)) {
1764 pfa->notbol = REG_NOTBOL;
1765 growbuf(&buf, &bufsize, CHUNK, NULL, "gsub");
1766 pb = buf;
1767 rptr = getsval(y);
1768 do {
1769 /*
1770 unsigned char *p;
1771 int i;
1772 printf("target string: %s, *patbeg = %o, patlen = %d\n",
1773 t, *patbeg, patlen);
1774 printf(" match found: ");
1775 p=patbeg;
1776 for (i=0; i<patlen; i++)
1777 printf("%c", *p++);
1778 printf("\n");
1779 */
1780 if (patlen == 0 && *patbeg != 0) { /* matched empty string */
1781 if (mflag == 0) { /* can replace empty */
1782 num++;
1783 sptr = rptr;
1784 while (*sptr != 0) {
1785 if (*sptr == '\\' && *(sptr+1) == '&') {
1786 sptr++;
1787 *pb++ = *sptr++;
1788 } else if (*sptr == '&') {
1789 unsigned char *q;
1790 sptr++;
1791 for (q = patbeg; q < patbeg+patlen; ) {
1792 *pb++ = *q++;
1793 if (pb >= &buf[bufsize])
1794 growbuf(&buf,
1795 &bufsize, CHUNK,
1796 &pb, "gsub");
1797 }
1798 } else
1799 *pb++ = *sptr++;
1800 if (pb >= &buf[bufsize])
1801 growbuf(&buf,
1802 &bufsize, CHUNK,
1803 &pb, "gsub");
1804 }
1805 }
1806 if (*t == 0) /* at end */
1807 goto done;
1808 *pb++ = *t++;
1809 mflag = 0;
1810 }
1811 else { /* matched nonempty string */
1812 num++;
1813 sptr = t;
1814 while (sptr < patbeg) {
1815 if (pb >= &buf[bufsize])
1816 growbuf(&buf, &bufsize, CHUNK,
1817 &pb, "gsub");
1818 *pb++ = *sptr++;
1819 }
1820 sptr = rptr;
1821 while (*sptr != 0) {
1822 if (*sptr == '\\' && *(sptr+1) == '&') {
1823 sptr++;
1824 *pb++ = *sptr++;
1825 } else if (*sptr == '&') {
1826 unsigned char *q;
1827 sptr++;
1828 for (q = patbeg; q < patbeg+patlen; ) {
1829 *pb++ = *q++;
1830 if (pb >= &buf[bufsize])
1831 growbuf(&buf,
1832 &bufsize, CHUNK,
1833 &pb, "gsub");
1834 }
1835 } else
1836 *pb++ = *sptr++;
1837 if (pb >= &buf[bufsize])
1838 growbuf(&buf, &bufsize, CHUNK,
1839 &pb, "gsub");
1840 }
1841 t = patbeg + patlen;
1842 if ((*(t-1) == 0) || (*t == 0))
1843 goto done;
1844 mflag = 1;
1845 }
1846 } while (pmatch(pfa,t));
1847 sptr = t;
1848 while ((*pb++ = *sptr++)) {
1849 if (pb >= &buf[bufsize])
1850 growbuf(&buf, &bufsize, CHUNK, &pb, "gsub");
1851 }
1852 done: *pb = '\0';
1853 setsval(x, buf);
1854 pfa->notbol = 0;
1855 free(buf);
1856 }
1857 tempfree(x, "");
1858 tempfree(y, "");
1859 x = gettemp("");
1860 x->tval = NUM;
1861 x->fval = num;
1862 return(x);
1863 }
1864 #include <stdarg.h> /* MR ul92-34309a2 */
1865 static int
growsprintf(unsigned char ** whole,unsigned char ** target,int * size,const char * fmt,...)1866 growsprintf(unsigned char **whole, unsigned char **target, int *size,
1867 const char *fmt, ...)
1868 {
1869 va_list ap;
1870 int ret;
1871 size_t diff = 0, mx;
1872
1873 if (*size == 0) {
1874 if ((*whole = malloc(*size = CHUNK)) == NULL)
1875 goto oflo;
1876 *target = *whole;
1877 }
1878 diff = *target - *whole;
1879 again: va_start(ap, fmt);
1880
1881 mx = *size - diff - 8;
1882 ret = vsnprintf((char *)*target, mx, fmt, ap);
1883 va_end(ap);
1884
1885 if (ret < 0 || ret >= mx) {
1886 if (ret < 0) {
1887 char dummy[2];
1888 va_start(ap, fmt);
1889 ret = vsnprintf(dummy, sizeof dummy, fmt, ap);
1890 va_end(ap);
1891 if (ret < 0)
1892 goto oflo;
1893 }
1894 if ((*whole = realloc(*whole, *size = ret + 1 + diff + 8)) == 0)
1895 oflo: error(MM_ERROR,
1896 ":103:Formatted result would be too long: %.20s ...",
1897 fmt);
1898 *target = &(*whole)[diff];
1899 goto again;
1900 }
1901
1902 while (**target) /* NUL characters might have been printed; */
1903 (*target)++; /* don't skip past them. */
1904 return ret;
1905 }
1906
chrlen(const unsigned char * s)1907 int chrlen(const unsigned char *s)
1908 {
1909 wchar_t wc;
1910 int m = 0, n;
1911
1912 while (next(wc, s, n), wc != '\0') {
1913 s += n;
1914 m++;
1915 }
1916 return m;
1917 }
1918
chrdist(const unsigned char * s,const unsigned char * end)1919 int chrdist(const unsigned char *s, const unsigned char *end)
1920 {
1921 wchar_t wc;
1922 int m = 0, n;
1923
1924 while (next(wc, s, n), s <= end) {
1925 s += n;
1926 m++;
1927 }
1928 return m;
1929 }
1930
caseconv(unsigned char * s,wint_t (* conv)(wint_t))1931 static void caseconv(unsigned char *s, wint_t (*conv)(wint_t))
1932 {
1933 unsigned char *t = s;
1934 wchar_t wc;
1935 int len, nlen;
1936
1937 while (*s) {
1938 len = mbtowc(&wc, (char *)s, mb_cur_max);
1939 if (len < 0)
1940 *t++ = *s++;
1941 else {
1942 wc = conv(wc);
1943 if ((nlen = wctomb((char *)t, wc)) <= len) {
1944 t += nlen, s += len;
1945 } else
1946 *t++ = *s++;
1947 }
1948 }
1949 *t = '\0';
1950 }
1951
growbuf(unsigned char ** buf,int * bufsize,int incr,unsigned char ** ptr,const char * fn)1952 static void growbuf(unsigned char **buf, int *bufsize, int incr,
1953 unsigned char **ptr, const char *fn)
1954 {
1955 unsigned char *op;
1956
1957 op = *buf;
1958 if ((*buf = realloc(*buf, *bufsize += incr)) == NULL)
1959 error(MM_ERROR, outofspace, fn ? fn : "");
1960 if (ptr && *ptr)
1961 *ptr = &(*buf)[*ptr - op];
1962 }
1963