5172 tftpd service is not registered by default and its manual is giving misleading...
[unleashed.git] / usr / src / cmd / oawk / run.c
blob88d666e5faa729c56d9c29f58dbcfd113db7c5b6
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
29 #define DEBUG
30 #define tempfree(a) {if (istemp(a)) {xfree(a->sval); a->tval = 0; }}
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>
41 #define RECSIZE BUFSIZ
43 #define FILENUM 10
44 struct
46 FILE *fp;
47 int type;
48 wchar_t *fname;
49 } files[FILENUM];
50 FILE *popen();
52 extern CELL *execute(), *nodetoobj(), *fieldel(), *dopa2(), *gettemp();
54 #define PA2NUM 29
55 int pairstack[PA2NUM], paircnt;
56 NODE *winner = NULL;
57 #define MAXTMP 20
58 CELL tmps[MAXTMP];
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 };
74 static void redirprint(wchar_t *s, int a, NODE *b);
76 void freesymtab(CELL *ap);
77 void fldbld(void);
79 void
80 run(NODE *a)
82 int i;
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);
92 CELL *
93 execute(NODE *u)
95 CELL *(*proc)();
96 CELL *x;
97 NODE *a;
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);
124 CELL *
125 program(NODE **a, int n)
127 CELL *x;
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);
137 while (getrec()) {
138 x = execute(a[1]);
139 if (isexit(x)) {
140 tempfree(x);
141 break;
143 tempfree(x);
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);
151 return (true);
157 CELL *
158 getaline(void)
160 CELL *x;
162 x = gettemp();
163 setfval(x, (awkfloat) getrec());
164 return (x);
170 CELL *
171 array(NODE **a, int n)
173 CELL *x, *y;
174 extern CELL *arrayel();
176 x = execute(a[1]);
177 y = arrayel(a[0], x);
178 tempfree(x);
179 return (y);
185 CELL *
186 arrayel(NODE *a, CELL *b)
188 wchar_t *s;
189 CELL *x;
190 int i;
191 CELL *y;
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();
201 y = setsymtab(s, tostring(L_NULL), 0.0, STR|NUM, x->sval);
202 y->ctype = OCELL;
203 y->csub = CVAR;
204 return (y);
207 CELL *
208 matchop(NODE **a, int n)
210 CELL *x;
211 wchar_t *s;
212 int i;
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);
227 CELL *
228 boolop(NODE **a, int n)
230 CELL *x, *y;
231 int i;
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);
260 return (false);
266 CELL *
267 relop(NODE **a, int n)
269 int i;
270 CELL *x, *y;
271 awkfloat j;
272 wchar_t *xs, *ys;
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);
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);
308 return (false);
318 CELL *
319 gettemp(void)
321 int i;
322 CELL *x;
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);
340 CELL *
341 indirect(NODE **a, int n)
343 CELL *x;
344 int m;
345 CELL *fieldadr();
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);
359 CELL *
360 substr(NODE **a, int nnn)
362 int k, m, n;
363 wchar_t *s, temp;
364 CELL *x, *y;
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);
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);
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);
405 CELL *
406 sindex(NODE **a, int nnn)
408 CELL *x;
409 wchar_t *s1, *s2, *p1, *p2, *q;
411 x = execute(a[0]);
412 s1 = getsval(x);
413 tempfree(x);
414 x = execute(a[1]);
415 s2 = getsval(x);
416 tempfree(x);
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++)
422 if (*p2 == (wchar_t)0x0) {
423 setfval(x, (awkfloat) (p1 - s1 + 1)); /* origin 1 */
424 return (x);
427 setfval(x, 0.0);
428 return (x);
434 wchar_t *
435 format(wchar_t *s, NODE *a)
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;
447 os = s;
448 p = buf= (wchar_t *)malloc(RECSIZE * sizeof (wchar_t));
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;
458 if (*(s+1) == '%') {
459 *p++ = '%';
460 s += 2;
461 continue;
463 for (t=fmt; *s != '\0'; s++)
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);
476 x = execute(a);
477 a = a->nnext;
478 sprintf(t-1, "%d", (int) getfval(x));
479 t = fmt + strlen(fmt);
480 tempfree(x);
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;
511 if (flag == 0) {
512 wsprintf(p, "%s", fmt);
513 p += wslen(p);
514 continue;
516 if (a == NULL) {
517 error(FATAL,
518 "not enough arguments in printf(%ws) or sprintf(%ws)", os, os);
520 x = execute(a);
521 a = a->nnext;
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.
528 if (flag == 4) { /* watch out for converting to numbers! */
529 str = getsval(x);
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;
542 * If string overruns the buffer, reallocate;
543 * consider length of format string
545 if (p + wslen(str) + wslen(s) + 1 >= ep) {
546 int newlen, oldlen;
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;
557 /* Transfer string to buffer */
558 if (flag == 4)
559 wsprintf(p, fmt, str);
560 else
561 wscpy(p, str);
563 tempfree(x);
564 p += wslen(p);
565 if (p >= ep)
566 error(FATAL, "formatted string too long");
567 s++;
569 *p = '\0';
570 return (buf);
574 CELL *
575 a_sprintf(NODE **a, int n)
577 CELL *x;
578 NODE *y;
579 wchar_t *s;
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);
592 CELL *
593 arith(NODE **a, int n)
595 awkfloat i, j;
596 CELL *x, *y, *z;
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);
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);
633 setfval(z, i);
634 return (z);
640 CELL *
641 incrdecr(NODE **a, int n)
643 CELL *x, *z;
644 int k;
645 awkfloat xf;
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);
654 z = gettemp();
655 setfval(z, xf);
656 setfval(x, xf + k);
657 tempfree(x);
658 return (z);
663 CELL *
664 assign(NODE **a, int n)
666 CELL *x, *y;
667 awkfloat xf, yf;
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;
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);
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;
713 tempfree(y);
714 setfval(x, xf);
715 return (x);
721 CELL *
722 cat(NODE **a, int q)
724 CELL *x, *y, *z;
725 int n1, n2;
726 wchar_t *s;
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);
752 CELL *
753 pastat(NODE **a, int n)
755 CELL *x;
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]);
768 return (x);
774 CELL *
775 dopa2(NODE **a, int n)
777 CELL *x;
778 int pair;
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);
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);
798 return (false);
804 CELL *
805 aprintf(NODE **a, int n)
807 CELL *x;
812 x = a_sprintf(a, n);
813 if (a[1] == NULL) {
814 printf("%ws", x->sval);
815 tempfree(x);
816 return (true);
818 redirprint(x->sval, (int)a[1], a[2]);
819 return (x);
825 CELL *
826 split(NODE **a, int nnn)
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;
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);
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();
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;
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++;
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;
902 x = gettemp();
903 x->tval = NUM;
904 x->fval = n;
905 return (x);
911 CELL *
912 ifstat(NODE **a, int n)
914 CELL *x;
919 x = execute(a[0]);
920 if (istrue(x)) {
921 tempfree(x);
922 x = execute(a[1]);
924 } else if (a[2] != 0) {
925 tempfree(x);
926 x = execute(a[2]);
928 return (x);
934 CELL *
935 whilestat(NODE **a, int n)
937 CELL *x;
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);
951 if (isnext(x) || isexit(x))
952 return (x);
953 tempfree(x);
960 CELL *
961 forstat(NODE **a, int n)
963 CELL *x;
964 CELL *z;
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);
977 x = execute(a[3]);
978 if (isbreak(x)) { /* turn off break */
979 x = true;
980 return (x);
982 if (isnext(x) || isexit(x))
983 return (x);
984 tempfree(x);
985 z = execute(a[2]);
986 tempfree(z);
993 CELL *
994 instat(NODE **a, int n)
996 CELL *vp, *arrayp, *cp, **tp;
997 CELL *x;
998 int i;
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);
1016 if (isnext(x) || isexit(x))
1017 return (x);
1018 tempfree(x);
1021 return (true);
1027 CELL *
1028 jump(NODE **a, int n)
1030 CELL *y;
1035 switch (n) {
1036 case EXIT:
1037 if (a[0] != 0) {
1038 y = execute(a[0]);
1039 errorflag = getfval(y);
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);
1051 return (NULL);
1057 CELL *
1058 fncn(NODE **a, int n)
1060 CELL *x;
1061 awkfloat u;
1062 int t;
1063 wchar_t *wp;
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);
1088 CELL *
1089 print(NODE **a, int n)
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;
1097 s[0] = '\0';
1098 bp = s;
1099 ep = s + RECSIZE;
1101 blen = 0;
1102 orslen = wcslen(*ORS);
1103 ofslen = wcslen(*OFS);
1105 for (x = a[0]; x != NULL; x = x->nnext) {
1106 y = execute(x);
1107 ss = getsval(y);
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;
1118 newlen = blen + sslen + oslen;
1120 /* allocate larger buffer if needed */
1121 if (ep < (bp + newlen + 1)) {
1122 wchar_t *oldbp = bp;
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);
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';
1139 if (a[1] == NULL) {
1140 (void) printf("%ws", bp);
1141 if (bp != s)
1142 free(bp);
1143 return (true);
1146 redirprint(bp, (int)a[1], a[2]);
1147 if (bp != s)
1148 free(bp);
1149 return (false);
1154 CELL *
1155 nullproc(void)
1157 return (NULL);
1162 CELL *
1163 nodetoobj(NODE *a)
1165 CELL *x;
1167 x= (CELL *) a->nobj;
1168 x->ctype = OCELL;
1169 x->csub = a->subtype;
1170 if (isfld(x))
1171 fldbld();
1172 return (x);
1175 static void
1176 redirprint(wchar_t *s, int a, NODE *b)
1178 int i;
1179 CELL *x;
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);