1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28
29 #define DEBUG
30 #define tempfree(a) {if (istemp(a)) {xfree(a->sval); a->tval = 0; }}
31
32 #include "awk.def"
33 #include "math.h"
34 #include "awk.h"
35 #include "stdio.h"
36 #include "ctype.h"
37 #include "wctype.h"
38 #include "awktype.h"
39 #include <stdlib.h>
40
41 #define RECSIZE BUFSIZ
42
43 #define FILENUM 10
44 struct
45 {
46 FILE *fp;
47 int type;
48 wchar_t *fname;
49 } files[FILENUM];
50 FILE *popen();
51
52 extern CELL *execute(), *nodetoobj(), *fieldel(), *dopa2(), *gettemp();
53
54 #define PA2NUM 29
55 int pairstack[PA2NUM], paircnt;
56 NODE *winner = NULL;
57 #define MAXTMP 20
58 CELL tmps[MAXTMP];
59
60 static CELL truecell ={ OBOOL, BTRUE, 0, 0, 0.0, NUM, 0 };
61 CELL *true = &truecell;
62 static CELL falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM, 0 };
63 CELL *false = &falsecell;
64 static CELL breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM, 0 };
65 CELL *jbreak = &breakcell;
66 static CELL contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM, 0 };
67 CELL *jcont = &contcell;
68 static CELL nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM, 0 };
69 CELL *jnext = &nextcell;
70 static CELL exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM, 0 };
71 CELL *jexit = &exitcell;
72 static CELL tempcell ={ OCELL, CTEMP, 0, 0, 0.0, NUM, 0 };
73
74 static void redirprint(wchar_t *s, int a, NODE *b);
75
76 void freesymtab(CELL *ap);
77 void fldbld(void);
78
79 void
run(NODE * a)80 run(NODE *a)
81 {
82 int i;
83
84 execute(a);
85 /* Wait for children to complete if output to a pipe. */
86 for (i=0; i<FILENUM; i++)
87 if (files[i].fp && files[i].type == '|')
88 pclose(files[i].fp);
89 }
90
91
92 CELL *
execute(NODE * u)93 execute(NODE *u)
94 {
95 CELL *(*proc)();
96 CELL *x;
97 NODE *a;
98
99 if (u == NULL)
100 return (true);
101 for (a = u; /* dummy */; a = a->nnext) {
102 if (cantexec(a))
103 return (nodetoobj(a));
104 if (notlegal(a->nobj))
105 error(FATAL, "illegal statement %o", a);
106 proc = proctab[a->nobj-FIRSTTOKEN];
107 x = (*proc)(a->narg, a->nobj);
108 if (isfld(x))
109 fldbld();
110 if (isexpr(a))
111 return (x);
112 /* a statement, goto next statement */
113 if (isjump(x))
114 return (x);
115 if (a->nnext == (NODE *)NULL)
116 return (x);
117 tempfree(x);
118 }
119 }
120
121
122
123
124 CELL *
program(NODE ** a,int n)125 program(NODE **a, int n)
126 {
127 CELL *x;
128
129 if (a[0] != NULL) {
130 x = execute(a[0]);
131 if (isexit(x))
132 return (true);
133 if (isjump(x))
134 error(FATAL, "unexpected break, continue or next");
135 tempfree(x);
136 }
137 while (getrec()) {
138 x = execute(a[1]);
139 if (isexit(x)) {
140 tempfree(x);
141 break;
142 }
143 tempfree(x);
144 }
145 if (a[2] != NULL) {
146 x = execute(a[2]);
147 if (isbreak(x) || isnext(x) || iscont(x))
148 error(FATAL, "unexpected break, continue or next");
149 tempfree(x);
150 }
151 return (true);
152 }
153
154
155
156
157 CELL *
getaline(void)158 getaline(void)
159 {
160 CELL *x;
161
162 x = gettemp();
163 setfval(x, (awkfloat) getrec());
164 return (x);
165 }
166
167
168
169
170 CELL *
array(NODE ** a,int n)171 array(NODE **a, int n)
172 {
173 CELL *x, *y;
174 extern CELL *arrayel();
175
176 x = execute(a[1]);
177 y = arrayel(a[0], x);
178 tempfree(x);
179 return (y);
180 }
181
182
183
184
185 CELL *
arrayel(NODE * a,CELL * b)186 arrayel(NODE *a, CELL *b)
187 {
188 wchar_t *s;
189 CELL *x;
190 int i;
191 CELL *y;
192
193 s = getsval(b);
194 x = (CELL *) a;
195 if (!(x->tval&ARR)) {
196 xfree(x->sval);
197 x->tval &= ~STR;
198 x->tval |= ARR;
199 x->sval = (wchar_t *) makesymtab();
200 }
201 y = setsymtab(s, tostring(L_NULL), 0.0, STR|NUM, x->sval);
202 y->ctype = OCELL;
203 y->csub = CVAR;
204 return (y);
205 }
206
207 CELL *
matchop(NODE ** a,int n)208 matchop(NODE **a, int n)
209 {
210 CELL *x;
211 wchar_t *s;
212 int i;
213
214 x = execute(a[0]);
215 s = getsval(x);
216 tempfree(x);
217 i = match(a[1], s);
218 if (n == MATCH && i == 1 || n == NOTMATCH && i == 0)
219 return (true);
220 else
221 return (false);
222 }
223
224
225
226
227 CELL *
boolop(NODE ** a,int n)228 boolop(NODE **a, int n)
229 {
230 CELL *x, *y;
231 int i;
232
233
234
235
236 x = execute(a[0]);
237 i = istrue(x);
238 tempfree(x);
239 switch (n) {
240 case BOR:
241 if (i) return (true);
242 y = execute(a[1]);
243 i = istrue(y);
244 tempfree(y);
245 if (i) return (true);
246 else return (false);
247 case AND:
248 if (!i) return (false);
249 y = execute(a[1]);
250 i = istrue(y);
251 tempfree(y);
252 if (i) return (true);
253 else return (false);
254 case NOT:
255 if (i) return (false);
256 else return (true);
257 default:
258 error(FATAL, "unknown boolean operator %d", n);
259 }
260 return (false);
261 }
262
263
264
265
266 CELL *
relop(NODE ** a,int n)267 relop(NODE **a, int n)
268 {
269 int i;
270 CELL *x, *y;
271 awkfloat j;
272 wchar_t *xs, *ys;
273
274
275
276
277 x = execute(a[0]);
278 y = execute(a[1]);
279 if (x->tval&NUM && y->tval&NUM) {
280 j = x->fval - y->fval;
281 i = j<0? -1: (j>0? 1: 0);
282 } else {
283 xs = getsval(x);
284 ys = getsval(y);
285 if (xs && ys)
286 i = wscoll(xs, ys);
287 else
288 return (false);
289 }
290 tempfree(x);
291 tempfree(y);
292 switch (n) {
293 case LT: if (i<0) return (true);
294 else return (false);
295 case LE: if (i<=0) return (true);
296 else return (false);
297 case NE: if (i!=0) return (true);
298 else return (false);
299 case EQ: if (i == 0) return (true);
300 else return (false);
301 case GE: if (i>=0) return (true);
302 else return (false);
303 case GT: if (i>0) return (true);
304 else return (false);
305 default:
306 error(FATAL, "unknown relational operator %d", n);
307 }
308 return (false);
309 }
310
311
312
313
314
315
316
317
318 CELL *
gettemp(void)319 gettemp(void)
320 {
321 int i;
322 CELL *x;
323
324
325
326
327 for (i=0; i<MAXTMP; i++)
328 if (tmps[i].tval == 0)
329 break;
330 if (i == MAXTMP)
331 error(FATAL, "out of temporaries in gettemp");
332 tmps[i] = tempcell;
333 x = &tmps[i];
334 return (x);
335 }
336
337
338
339
340 CELL *
indirect(NODE ** a,int n)341 indirect(NODE **a, int n)
342 {
343 CELL *x;
344 int m;
345 CELL *fieldadr();
346
347 x = execute(a[0]);
348 m = getfval(x);
349 tempfree(x);
350 x = fieldadr(m);
351 x->ctype = OCELL;
352 x->csub = CFLD;
353 return (x);
354 }
355
356
357
358
359 CELL *
substr(NODE ** a,int nnn)360 substr(NODE **a, int nnn)
361 {
362 int k, m, n;
363 wchar_t *s, temp;
364 CELL *x, *y;
365
366 y = execute(a[0]);
367 s = getsval(y);
368 k = wslen(s) + 1;
369 if (k <= 1) {
370 x = gettemp();
371 setsval(x, L_NULL);
372 return (x);
373 }
374 x = execute(a[1]);
375 m = getfval(x);
376 if (m <= 0)
377 m = 1;
378 else if (m > k)
379 m = k;
380 tempfree(x);
381 if (a[2] != 0) {
382 x = execute(a[2]);
383 n = getfval(x);
384 tempfree(x);
385 }
386 else
387 n = k - 1;
388 if (n < 0)
389 n = 0;
390 else if (n > k - m)
391 n = k - m;
392 dprintf("substr: m=%d, n=%d, s=%ws\n", m, n, s);
393 x = gettemp();
394 temp = s[n+m-1];
395 s[n+m-1] = (wchar_t)0x0;
396 setsval(x, s + m - 1);
397 s[n+m-1] = temp;
398 tempfree(y);
399 return (x);
400 }
401
402
403
404
405 CELL *
sindex(NODE ** a,int nnn)406 sindex(NODE **a, int nnn)
407 {
408 CELL *x;
409 wchar_t *s1, *s2, *p1, *p2, *q;
410
411 x = execute(a[0]);
412 s1 = getsval(x);
413 tempfree(x);
414 x = execute(a[1]);
415 s2 = getsval(x);
416 tempfree(x);
417
418 x = gettemp();
419 for (p1 = s1; *p1 != (wchar_t)0x0; p1++) {
420 for (q=p1, p2=s2; *p2 != (wchar_t)0x0 && *q == *p2; q++, p2++)
421 ;
422 if (*p2 == (wchar_t)0x0) {
423 setfval(x, (awkfloat) (p1 - s1 + 1)); /* origin 1 */
424 return (x);
425 }
426 }
427 setfval(x, 0.0);
428 return (x);
429 }
430
431
432
433
434 wchar_t *
format(wchar_t * s,NODE * a)435 format(wchar_t *s, NODE *a)
436 {
437 wchar_t *buf, *ep, *str;
438 wchar_t *p;
439 char *t;
440 wchar_t *os;
441 wchar_t tbuf[2*RECSIZE];
442 char fmt[200];
443 CELL *x;
444 int flag = 0;
445 awkfloat xf;
446
447 os = s;
448 p = buf= (wchar_t *)malloc(RECSIZE * sizeof (wchar_t));
449
450 if (p == NULL)
451 error(FATAL, "out of space in format");
452 ep = p + RECSIZE;
453 while (*s) {
454 if (*s != '%') {
455 *p++ = *s++;
456 continue;
457 }
458 if (*(s+1) == '%') {
459 *p++ = '%';
460 s += 2;
461 continue;
462 }
463 for (t=fmt; *s != '\0'; s++)
464 {
465 if (*s == 's' || *s == 'c')
466 *t++ = 'w';
467 *t++ = *s;
468 if (*s >= 'a' && *s <= 'z' && *s != 'l')
469 break;
470 if (*s == '*') {
471 if (a == NULL) {
472 error(FATAL,
473 "not enough arguments in printf(%ws) or sprintf(%ws)",
474 os, os);
475 }
476 x = execute(a);
477 a = a->nnext;
478 sprintf(t-1, "%d", (int) getfval(x));
479 t = fmt + strlen(fmt);
480 tempfree(x);
481 }
482
483 }
484 *t = '\0';
485 if (t >= fmt + sizeof (fmt))
486 error(FATAL, "format item %.20ws... too long", os);
487 switch (*s) {
488 case 'f': case 'e': case 'g':
489 flag = 1;
490 break;
491 case 'd':
492 flag = 2;
493 if (*(s-1) == 'l') break;
494 *(t-1) = 'l';
495 *t = 'd';
496 *++t = '\0';
497 break;
498 case 'o': case 'x':
499 flag = *(s-1) == 'l' ? 2 : 3;
500 break;
501 case 'c':
502 flag = 3;
503 break;
504 case 's':
505 flag = 4;
506 break;
507 default:
508 flag = 0;
509 break;
510 }
511 if (flag == 0) {
512 wsprintf(p, "%s", fmt);
513 p += wslen(p);
514 continue;
515 }
516 if (a == NULL) {
517 error(FATAL,
518 "not enough arguments in printf(%ws) or sprintf(%ws)", os, os);
519 }
520 x = execute(a);
521 a = a->nnext;
522
523 /*
524 * Get the string to check length; %s is the usual problem;
525 * other conversions can cause overrun if they occur when
526 * the buffer is almost filled.
527 */
528 if (flag == 4) { /* watch out for converting to numbers! */
529 str = getsval(x);
530 }
531 else {
532 xf = getfval(x);
533 if (flag == 1) wsprintf(tbuf, fmt, xf);
534 else if (flag == 2) wsprintf(tbuf, fmt, (long)xf);
535 else if (flag == 3) wsprintf(tbuf, fmt, (int)xf);
536 if (wslen(tbuf) >= RECSIZE)
537 error(FATAL, "formatted item %s... too long",
538 tbuf);
539 str = tbuf;
540 }
541 /*
542 * If string overruns the buffer, reallocate;
543 * consider length of format string
544 */
545 if (p + wslen(str) + wslen(s) + 1 >= ep) {
546 int newlen, oldlen;
547
548 oldlen = p - buf;
549 /* Add RECSIZE for additional space */
550 newlen = oldlen + wslen(str) + RECSIZE;
551 buf = realloc(buf, (unsigned) newlen * sizeof(wchar_t));
552 if (buf == NULL)
553 error(FATAL, "out of format space");
554 p = buf + oldlen;
555 ep = buf + newlen;
556 }
557 /* Transfer string to buffer */
558 if (flag == 4)
559 wsprintf(p, fmt, str);
560 else
561 wscpy(p, str);
562
563 tempfree(x);
564 p += wslen(p);
565 if (p >= ep)
566 error(FATAL, "formatted string too long");
567 s++;
568 }
569 *p = '\0';
570 return (buf);
571 }
572
573
574 CELL *
a_sprintf(NODE ** a,int n)575 a_sprintf(NODE **a, int n)
576 {
577 CELL *x;
578 NODE *y;
579 wchar_t *s;
580
581 y = a[0]->nnext;
582 x = execute(a[0]);
583 s = format(getsval(x), y);
584 tempfree(x);
585 x = gettemp();
586 x->sval = s;
587 x->tval = STR;
588 return (x);
589 }
590
591
592 CELL *
arith(NODE ** a,int n)593 arith(NODE **a, int n)
594 {
595 awkfloat i, j;
596 CELL *x, *y, *z;
597
598 x = execute(a[0]);
599 i = getfval(x);
600 tempfree(x);
601 if (n != UMINUS) {
602 y = execute(a[1]);
603 j = getfval(y);
604 tempfree(y);
605 }
606 z = gettemp();
607 switch (n) {
608 case ADD:
609 i += j;
610 break;
611 case MINUS:
612 i -= j;
613 break;
614 case MULT:
615 i *= j;
616 break;
617 case DIVIDE:
618 if (j == 0)
619 error(FATAL, "division by zero");
620 i /= j;
621 break;
622 case MOD:
623 if (j == 0)
624 error(FATAL, "division by zero");
625 i = i - j*(long)(i/j);
626 break;
627 case UMINUS:
628 i = -i;
629 break;
630 default:
631 error(FATAL, "illegal arithmetic operator %d", n);
632 }
633 setfval(z, i);
634 return (z);
635 }
636
637
638
639
640 CELL *
incrdecr(NODE ** a,int n)641 incrdecr(NODE **a, int n)
642 {
643 CELL *x, *z;
644 int k;
645 awkfloat xf;
646
647 x = execute(a[0]);
648 xf = getfval(x);
649 k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
650 if (n == PREINCR || n == PREDECR) {
651 setfval(x, xf + k);
652 return (x);
653 }
654 z = gettemp();
655 setfval(z, xf);
656 setfval(x, xf + k);
657 tempfree(x);
658 return (z);
659 }
660
661
662
663 CELL *
assign(NODE ** a,int n)664 assign(NODE **a, int n)
665 {
666 CELL *x, *y;
667 awkfloat xf, yf;
668
669
670
671
672 x = execute(a[0]);
673 y = execute(a[1]);
674 if (n == ASSIGN) { /* ordinary assignment */
675 if ((y->tval & (STR|NUM)) == (STR|NUM)) {
676 setsval(x, y->sval);
677 x->fval = y->fval;
678 x->tval |= NUM;
679
680 } else if (y->tval & STR)
681 setsval(x, y->sval);
682 else if (y->tval & NUM)
683 setfval(x, y->fval);
684 tempfree(y);
685 return (x);
686 }
687 xf = getfval(x);
688 yf = getfval(y);
689 switch (n) {
690 case ADDEQ:
691 xf += yf;
692 break;
693 case SUBEQ:
694 xf -= yf;
695 break;
696 case MULTEQ:
697 xf *= yf;
698 break;
699 case DIVEQ:
700 if (yf == 0)
701 error(FATAL, "division by zero");
702 xf /= yf;
703 break;
704 case MODEQ:
705 if (yf == 0)
706 error(FATAL, "division by zero");
707 xf = xf - yf*(long)(xf/yf);
708 break;
709 default:
710 error(FATAL, "illegal assignment operator %d", n);
711 break;
712 }
713 tempfree(y);
714 setfval(x, xf);
715 return (x);
716 }
717
718
719
720
721 CELL *
cat(NODE ** a,int q)722 cat(NODE **a, int q)
723 {
724 CELL *x, *y, *z;
725 int n1, n2;
726 wchar_t *s;
727
728
729
730
731 x = execute(a[0]);
732 y = execute(a[1]);
733 getsval(x);
734 getsval(y);
735 n1 = wslen(x->sval);
736 n2 = wslen(y->sval);
737 if ((s = (wchar_t *) malloc((n1 + n2 + 1) * sizeof (wchar_t))) == NULL)
738 error(FATAL, "out of space in cat");
739 wscpy(s, x->sval);
740 wscpy(s+n1, y->sval);
741 tempfree(y);
742 z = gettemp();
743 z->sval = s;
744 z->tval = STR;
745 tempfree(x);
746 return (z);
747 }
748
749
750
751
752 CELL *
pastat(NODE ** a,int n)753 pastat(NODE **a, int n)
754 {
755 CELL *x;
756
757
758
759
760 if (a[0] == 0)
761 x = true;
762 else
763 x = execute(a[0]);
764 if (istrue(x)) {
765 tempfree(x);
766 x = execute(a[1]);
767 }
768 return (x);
769 }
770
771
772
773
774 CELL *
dopa2(NODE ** a,int n)775 dopa2(NODE **a, int n)
776 {
777 CELL *x;
778 int pair;
779
780
781
782
783 pair = (int) a[3];
784 if (pairstack[pair] == 0) {
785 x = execute(a[0]);
786 if (istrue(x))
787 pairstack[pair] = 1;
788 tempfree(x);
789 }
790 if (pairstack[pair] == 1) {
791 x = execute(a[1]);
792 if (istrue(x))
793 pairstack[pair] = 0;
794 tempfree(x);
795 x = execute(a[2]);
796 return (x);
797 }
798 return (false);
799 }
800
801
802
803
804 CELL *
aprintf(NODE ** a,int n)805 aprintf(NODE **a, int n)
806 {
807 CELL *x;
808
809
810
811
812 x = a_sprintf(a, n);
813 if (a[1] == NULL) {
814 printf("%ws", x->sval);
815 tempfree(x);
816 return (true);
817 }
818 redirprint(x->sval, (int)a[1], a[2]);
819 return (x);
820 }
821
822
823
824
825 CELL *
split(NODE ** a,int nnn)826 split(NODE **a, int nnn)
827 {
828 CELL *x;
829 CELL *ap;
830 wchar_t *s, *p, c;
831 wchar_t *t, temp, num[5];
832 wchar_t sep;
833 int n, flag;
834
835
836
837
838 x = execute(a[0]);
839 s = getsval(x);
840 tempfree(x);
841 if (a[2] == 0)
842 sep = **FS;
843 else {
844 x = execute(a[2]);
845 sep = getsval(x)[0];
846 tempfree(x);
847 }
848 ap = (CELL *) a[1];
849 freesymtab(ap);
850 dprintf("split: s=|%ws|, a=%ws, sep=|%wc|\n", s, ap->nval, sep);
851 ap->tval &= ~STR;
852 ap->tval |= ARR;
853 ap->sval = (wchar_t *) makesymtab();
854
855
856
857
858 n = 0;
859 if (sep == ' ')
860 for (n = 0; /* dummy */; /* dummy */) {
861 c = *s;
862 while (iswblank(c) || c == '\t' || c == '\n')
863 c = *(++s);
864 if (*s == 0)
865 break;
866 n++;
867 t = s;
868 do
869 c = *(++s);
870 while (! iswblank(c) && c != '\t' &&
871 c != '\n' && c != '\0');
872 temp = c;
873 *s = (wchar_t)0x0;
874 wsprintf(num, "%d", n);
875 if (isanumber(t))
876 setsymtab(num, tostring(t),
877 watof(t), STR|NUM, ap->sval);
878 else
879 setsymtab(num, tostring(t), 0.0, STR, ap->sval);
880 *s = temp;
881 if (*s != 0)
882 s++;
883
884 } else if (*s != 0)
885 for (;;) {
886 n++;
887 t = s;
888 while ((c = *s) != sep && c != '\n' && c != '\0')
889 s++;
890 temp = c;
891 *s = (wchar_t)0x0;
892 wsprintf(num, "%d", n);
893 if (isanumber(t))
894 setsymtab(num, tostring(t),
895 watof(t), STR|NUM, ap->sval);
896 else
897 setsymtab(num, tostring(t), 0.0, STR, ap->sval);
898 *s = temp;
899 if (*s++ == 0)
900 break;
901 }
902 x = gettemp();
903 x->tval = NUM;
904 x->fval = n;
905 return (x);
906 }
907
908
909
910
911 CELL *
ifstat(NODE ** a,int n)912 ifstat(NODE **a, int n)
913 {
914 CELL *x;
915
916
917
918
919 x = execute(a[0]);
920 if (istrue(x)) {
921 tempfree(x);
922 x = execute(a[1]);
923
924 } else if (a[2] != 0) {
925 tempfree(x);
926 x = execute(a[2]);
927 }
928 return (x);
929 }
930
931
932
933
934 CELL *
whilestat(NODE ** a,int n)935 whilestat(NODE **a, int n)
936 {
937 CELL *x;
938
939
940
941
942 for (;;) {
943 x = execute(a[0]);
944 if (!istrue(x)) return (x);
945 tempfree(x);
946 x = execute(a[1]);
947 if (isbreak(x)) {
948 x = true;
949 return (x);
950 }
951 if (isnext(x) || isexit(x))
952 return (x);
953 tempfree(x);
954 }
955 }
956
957
958
959
960 CELL *
forstat(NODE ** a,int n)961 forstat(NODE **a, int n)
962 {
963 CELL *x;
964 CELL *z;
965
966
967
968
969 z = execute(a[0]);
970 tempfree(z);
971 for (;;) {
972 if (a[1]!=0) {
973 x = execute(a[1]);
974 if (!istrue(x)) return (x);
975 else tempfree(x);
976 }
977 x = execute(a[3]);
978 if (isbreak(x)) { /* turn off break */
979 x = true;
980 return (x);
981 }
982 if (isnext(x) || isexit(x))
983 return (x);
984 tempfree(x);
985 z = execute(a[2]);
986 tempfree(z);
987 }
988 }
989
990
991
992
993 CELL *
instat(NODE ** a,int n)994 instat(NODE **a, int n)
995 {
996 CELL *vp, *arrayp, *cp, **tp;
997 CELL *x;
998 int i;
999
1000
1001
1002
1003 vp = (CELL *) a[0];
1004 arrayp = (CELL *) a[1];
1005 if (!(arrayp->tval & ARR))
1006 error(FATAL, "%ws is not an array", arrayp->nval);
1007 tp = (CELL **) arrayp->sval;
1008 for (i = 0; i < MAXSYM; i++) { /* this routine knows too much */
1009 for (cp = tp[i]; cp != NULL; cp = cp->nextval) {
1010 setsval(vp, cp->nval);
1011 x = execute(a[2]);
1012 if (isbreak(x)) {
1013 x = true;
1014 return (x);
1015 }
1016 if (isnext(x) || isexit(x))
1017 return (x);
1018 tempfree(x);
1019 }
1020 }
1021 return (true);
1022 }
1023
1024
1025
1026
1027 CELL *
jump(NODE ** a,int n)1028 jump(NODE **a, int n)
1029 {
1030 CELL *y;
1031
1032
1033
1034
1035 switch (n) {
1036 case EXIT:
1037 if (a[0] != 0) {
1038 y = execute(a[0]);
1039 errorflag = getfval(y);
1040 }
1041 return (jexit);
1042 case NEXT:
1043 return (jnext);
1044 case BREAK:
1045 return (jbreak);
1046 case CONTINUE:
1047 return (jcont);
1048 default:
1049 error(FATAL, "illegal jump type %d", n);
1050 }
1051 return (NULL);
1052 }
1053
1054
1055
1056
1057 CELL *
fncn(NODE ** a,int n)1058 fncn(NODE **a, int n)
1059 {
1060 CELL *x;
1061 awkfloat u;
1062 int t;
1063 wchar_t *wp;
1064
1065 t = (int) a[0];
1066 x = execute(a[1]);
1067 if (t == FLENGTH)
1068 u = (awkfloat) wslen(getsval(x));
1069 else if (t == FLOG)
1070 u = log(getfval(x));
1071 else if (t == FINT)
1072 u = (awkfloat) (long) getfval(x);
1073 else if (t == FEXP)
1074 u = exp(getfval(x));
1075 else if (t == FSQRT)
1076 u = sqrt(getfval(x));
1077 else
1078 error(FATAL, "illegal function type %d", t);
1079 tempfree(x);
1080 x = gettemp();
1081 setfval(x, u);
1082 return (x);
1083 }
1084
1085
1086
1087
1088 CELL *
print(NODE ** a,int n)1089 print(NODE **a, int n)
1090 {
1091 NODE *x;
1092 CELL *y;
1093 wchar_t s[RECSIZE];
1094 wchar_t *ss, *bp, *ep, *os;
1095 size_t blen, newlen, sslen, orslen, ofslen, oslen;
1096
1097 s[0] = '\0';
1098 bp = s;
1099 ep = s + RECSIZE;
1100
1101 blen = 0;
1102 orslen = wcslen(*ORS);
1103 ofslen = wcslen(*OFS);
1104
1105 for (x = a[0]; x != NULL; x = x->nnext) {
1106 y = execute(x);
1107 ss = getsval(y);
1108
1109 /* total new length will be */
1110 sslen = wcslen(ss);
1111 if (x->nnext == NULL) {
1112 os = *ORS;
1113 oslen = orslen;
1114 } else {
1115 os = *OFS;
1116 oslen = ofslen;
1117 }
1118 newlen = blen + sslen + oslen;
1119
1120 /* allocate larger buffer if needed */
1121 if (ep < (bp + newlen + 1)) {
1122 wchar_t *oldbp = bp;
1123
1124 if (oldbp == s)
1125 bp = NULL;
1126 bp = realloc(bp, sizeof (wchar_t) * (newlen + 1));
1127 if (bp == NULL)
1128 error(FATAL, "out of space in print");
1129 ep = bp + newlen + 1;
1130 if (oldbp == s)
1131 (void) wmemcpy(bp, oldbp, blen);
1132 }
1133 (void) wmemcpy(bp + blen, ss, sslen);
1134 (void) wmemcpy(bp + blen + sslen, os, oslen);
1135 tempfree(y);
1136 blen = newlen;
1137 bp[blen] = '\0';
1138 }
1139 if (a[1] == NULL) {
1140 (void) printf("%ws", bp);
1141 if (bp != s)
1142 free(bp);
1143 return (true);
1144 }
1145
1146 redirprint(bp, (int)a[1], a[2]);
1147 if (bp != s)
1148 free(bp);
1149 return (false);
1150 }
1151
1152
1153
1154 CELL *
nullproc(void)1155 nullproc(void)
1156 {
1157 return (NULL);
1158 }
1159
1160
1161
1162 CELL *
nodetoobj(NODE * a)1163 nodetoobj(NODE *a)
1164 {
1165 CELL *x;
1166
1167 x= (CELL *) a->nobj;
1168 x->ctype = OCELL;
1169 x->csub = a->subtype;
1170 if (isfld(x))
1171 fldbld();
1172 return (x);
1173 }
1174
1175 static void
redirprint(wchar_t * s,int a,NODE * b)1176 redirprint(wchar_t *s, int a, NODE *b)
1177 {
1178 int i;
1179 CELL *x;
1180
1181 x = execute(b);
1182 getsval(x);
1183 for (i=0; i<FILENUM; i++)
1184 if (files[i].fname && wscmp(x->sval, files[i].fname) == 0)
1185 goto doit;
1186 for (i=0; i<FILENUM; i++)
1187 if (files[i].fp == 0)
1188 break;
1189 if (i >= FILENUM)
1190 error(FATAL, "too many output files %d", i);
1191 if (a == '|') /* a pipe! */
1192 files[i].fp = popen(toeuccode(x->sval), "w");
1193 else if (a == APPEND)
1194 files[i].fp = fopen(toeuccode(x->sval), "a");
1195 else if (a == GT)
1196 files[i].fp = fopen(toeuccode(x->sval), "w");
1197 else
1198 error(FATAL, "illegal redirection near line %lld", lineno);
1199 if (files[i].fp == NULL)
1200 error(FATAL, "can't open file %ws", x->sval);
1201 files[i].fname = tostring(x->sval);
1202 files[i].type = a;
1203 doit:
1204 fprintf(files[i].fp, "%ws", s);
1205 #ifndef gcos
1206 fflush(files[i].fp); /* in case someone is waiting for the output */
1207 #endif
1208 tempfree(x);
1209 }
1210