fix tty inheritance
[unix-history] / usr / src / old / awk / run.c
CommitLineData
2791ff57
KB
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.proprietary.c%
6 */
7
b803c326 8#ifndef lint
2791ff57
KB
9static char sccsid[] = "@(#)run.c 4.9 (Berkeley) %G%";
10#endif /* not lint */
059b34c5 11
ddec95fa 12#include "sys/param.h"
059b34c5 13#include "awk.def"
28e13bf4 14#include "math.h"
059b34c5
KM
15#include "awk.h"
16#include "stdio.h"
28e13bf4 17#include "fcntl.h"
c01fc283 18#define RECSIZE BUFSIZ
059b34c5 19
ddec95fa 20#define FILENUM NOFILE
059b34c5
KM
21struct
22{
23 FILE *fp;
1d8dcd58 24 int type;
059b34c5
KM
25 char *fname;
26} files[FILENUM];
27FILE *popen();
28
29extern obj execute(), nodetoobj(), fieldel(), dopa2(), gettemp();
30#define PA2NUM 29
31int pairstack[PA2NUM], paircnt;
32node *winner = (node *)NULL;
33#define MAXTMP 20
34cell tmps[MAXTMP];
c48090b0 35static cell nullval ={EMPTY,EMPTY,0.0,NUM,0};
059b34c5
KM
36obj true ={ OBOOL, BTRUE, 0 };
37obj false ={ OBOOL, BFALSE, 0 };
38
39run()
40{
1d8dcd58
RC
41 register int i;
42
059b34c5 43 execute(winner);
1d8dcd58
RC
44
45 /* Wait for children to complete if output to a pipe. */
46 for (i=0; i<FILENUM; i++)
47 if (files[i].fp && files[i].type == '|')
48 pclose(files[i].fp);
059b34c5
KM
49}
50
51obj execute(u) node *u;
52{
53 register obj (*proc)();
54 obj x;
55 node *a;
56 extern char *printname[];
57
58 if (u==(node *)NULL)
59 return(true);
60 for (a = u; ; a = a->nnext) {
61 if (cantexec(a))
62 return(nodetoobj(a));
63 if (a->ntype==NPA2)
64 proc=dopa2;
65 else {
66 if (notlegal(a->nobj))
67 error(FATAL, "illegal statement %o", a);
68 proc = proctab[a->nobj-FIRSTTOKEN];
69 }
70 x = (*proc)(a->narg,a->nobj);
71 if (isfld(x)) fldbld();
72 if (isexpr(a))
73 return(x);
74 /* a statement, goto next statement */
75 if (isjump(x))
76 return(x);
77 if (a->nnext == (node *)NULL)
78 return(x);
79 tempfree(x);
80 }
81}
82
83obj program(a, n) node **a;
84{
85 obj x;
86
87 if (a[0] != NULL) {
88 x = execute(a[0]);
89 if (isexit(x))
90 return(true);
91 if (isjump(x))
92 error(FATAL, "unexpected break, continue or next");
93 tempfree(x);
94 }
95 while (getrec()) {
96 x = execute(a[1]);
97 if (isexit(x)) break;
98 tempfree(x);
99 }
100 tempfree(x);
101 if (a[2] != NULL) {
102 x = execute(a[2]);
103 if (isbreak(x) || isnext(x) || iscont(x))
104 error(FATAL, "unexpected break, continue or next");
105 tempfree(x);
106 }
107 return(true);
108}
109
110obj getline()
111{
112 obj x;
113
114 x = gettemp();
115 setfval(x.optr, (awkfloat) getrec());
116 return(x);
117}
118
119obj array(a,n) node **a;
120{
121 obj x, y;
122 extern obj arrayel();
123
124 x = execute(a[1]);
125 y = arrayel(a[0], x);
126 tempfree(x);
127 return(y);
128}
129
130obj arrayel(a,b) node *a; obj b;
131{
132 char *s;
133 cell *x;
134 int i;
135 obj y;
136
137 s = getsval(b.optr);
138 x = (cell *) a;
139 if (!(x->tval&ARR)) {
c48090b0 140 strfree(x->sval);
059b34c5
KM
141 x->tval &= ~STR;
142 x->tval |= ARR;
143 x->sval = (char *) makesymtab();
144 }
145 y.optr = setsymtab(s, tostring(""), 0.0, STR|NUM, x->sval);
146 y.otype = OCELL;
147 y.osub = CVAR;
148 return(y);
149}
150
151obj matchop(a,n) node **a;
152{
153 obj x;
154 char *s;
155 int i;
156
157 x = execute(a[0]);
158 if (isstr(x)) s = x.optr->sval;
159 else s = getsval(x.optr);
160 tempfree(x);
161 i = match(a[1], s);
162 if (n==MATCH && i==1 || n==NOTMATCH && i==0)
163 return(true);
164 else
165 return(false);
166}
167
168obj boolop(a,n) node **a;
169{
170 obj x, y;
171 int i;
172
173 x = execute(a[0]);
174 i = istrue(x);
175 tempfree(x);
176 switch (n) {
177 default:
178 error(FATAL, "unknown boolean operator %d", n);
179 case BOR:
180 if (i) return(true);
181 y = execute(a[1]);
182 i = istrue(y);
183 tempfree(y);
184 if (i) return(true);
185 else return(false);
186 case AND:
187 if ( !i ) return(false);
188 y = execute(a[1]);
189 i = istrue(y);
190 tempfree(y);
191 if (i) return(true);
192 else return(false);
193 case NOT:
194 if (i) return(false);
195 else return(true);
196 }
197}
198
199obj relop(a,n) node **a;
200{
201 int i;
202 obj x, y;
203 awkfloat j;
204
205 x = execute(a[0]);
206 y = execute(a[1]);
207 if (x.optr->tval&NUM && y.optr->tval&NUM) {
208 j = x.optr->fval - y.optr->fval;
209 i = j<0? -1: (j>0? 1: 0);
210 } else {
211 i = strcmp(getsval(x.optr), getsval(y.optr));
212 }
213 tempfree(x);
214 tempfree(y);
215 switch (n) {
216 default:
217 error(FATAL, "unknown relational operator %d", n);
218 case LT: if (i<0) return(true);
219 else return(false);
220 case LE: if (i<=0) return(true);
221 else return(false);
222 case NE: if (i!=0) return(true);
223 else return(false);
224 case EQ: if (i==0) return(true);
225 else return(false);
226 case GE: if (i>=0) return(true);
227 else return(false);
228 case GT: if (i>0) return(true);
229 else return(false);
230 }
231}
232
233tempfree(a) obj a;
234{
235 if (!istemp(a)) return;
c48090b0 236 strfree(a.optr->sval);
059b34c5
KM
237 a.optr->tval = 0;
238}
239
240obj gettemp()
241{
242 int i;
243 obj x;
244
245 for (i=0; i<MAXTMP; i++)
246 if (tmps[i].tval==0)
247 break;
248 if (i==MAXTMP)
249 error(FATAL, "out of temporaries in gettemp");
250 x.optr = &tmps[i];
251 tmps[i] = nullval;
252 x.otype = OCELL;
253 x.osub = CTEMP;
254 return(x);
255}
256
257obj indirect(a,n) node **a;
258{
259 obj x;
260 int m;
261 cell *fieldadr();
262
263 x = execute(a[0]);
264 m = getfval(x.optr);
265 tempfree(x);
266 x.optr = fieldadr(m);
267 x.otype = OCELL;
268 x.osub = CFLD;
269 return(x);
270}
271
272obj substr(a, nnn) node **a;
273{
274 char *s, temp;
275 obj x;
276 int k, m, n;
277
278 x = execute(a[0]);
279 s = getsval(x.optr);
280 k = strlen(s) + 1;
281 tempfree(x);
282 x = execute(a[1]);
283 m = getfval(x.optr);
284 if (m <= 0)
285 m = 1;
286 else if (m > k)
287 m = k;
288 tempfree(x);
289 if (a[2] != nullstat) {
290 x = execute(a[2]);
291 n = getfval(x.optr);
292 tempfree(x);
293 }
294 else
295 n = k - 1;
296 if (n < 0)
297 n = 0;
298 else if (n > k - m)
299 n = k - m;
300 dprintf("substr: m=%d, n=%d, s=%s\n", m, n, s);
301 x = gettemp();
302 temp = s[n+m-1]; /* with thanks to John Linderman */
303 s[n+m-1] = '\0';
304 setsval(x.optr, s + m - 1);
305 s[n+m-1] = temp;
306 return(x);
307}
308
309obj sindex(a, nnn) node **a;
310{
311 obj x;
312 char *s1, *s2, *p1, *p2, *q;
313
314 x = execute(a[0]);
315 s1 = getsval(x.optr);
316 tempfree(x);
317 x = execute(a[1]);
318 s2 = getsval(x.optr);
319 tempfree(x);
320
321 x = gettemp();
322 for (p1 = s1; *p1 != '\0'; p1++) {
323 for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
324 ;
325 if (*p2 == '\0') {
326 setfval(x.optr, (awkfloat) (p1 - s1 + 1)); /* origin 1 */
327 return(x);
328 }
329 }
330 setfval(x.optr, 0.0);
331 return(x);
332}
333
334char *format(s,a) char *s; node *a;
335{
336 char *buf, *p, fmt[200], *t, *os;
337 obj x;
338 int flag = 0;
339 awkfloat xf;
340
341 os = s;
342 p = buf = (char *)malloc(RECSIZE);
343 while (*s) {
344 if (*s != '%') {
345 *p++ = *s++;
346 continue;
347 }
348 if (*(s+1) == '%') {
349 *p++ = '%';
350 s += 2;
351 continue;
352 }
353 for (t=fmt; (*t++ = *s) != '\0'; s++)
354 if (*s >= 'a' && *s <= 'z' && *s != 'l')
355 break;
356 *t = '\0';
357 if (t >= fmt + sizeof(fmt))
358 error(FATAL, "format item %.20s... too long", os);
359 switch (*s) {
360 case 'f': case 'e': case 'g':
361 flag = 1;
362 break;
363 case 'd':
364 flag = 2;
365 if(*(s-1) == 'l') break;
366 *(t-1) = 'l';
367 *t = 'd';
368 *++t = '\0';
369 break;
370 case 'o': case 'x':
371 flag = *(s-1)=='l' ? 2 : 3;
372 break;
373 case 'c':
374 flag = 3;
375 break;
376 case 's':
377 flag = 4;
378 break;
379 default:
380 flag = 0;
381 break;
382 }
383 if (flag == 0) {
6521d648 384 (void)sprintf(p, "%s", fmt);
059b34c5
KM
385 p += strlen(p);
386 continue;
387 }
388 if (a == NULL)
389 error(FATAL, "not enough arguments in printf(%s)", os);
390 x = execute(a);
391 a = a->nnext;
392 if (flag != 4) /* watch out for converting to numbers! */
393 xf = getfval(x.optr);
6521d648
KB
394 if (flag==1) (void)sprintf(p, fmt, xf);
395 else if (flag==2) (void)sprintf(p, fmt, (long)xf);
396 else if (flag==3) (void)sprintf(p, fmt, (int)xf);
397 else if (flag==4) (void)sprintf(p, fmt, x.optr->sval==NULL ? "" : getsval(x.optr));
059b34c5
KM
398 tempfree(x);
399 p += strlen(p);
400 s++;
401 }
402 *p = '\0';
403 return(buf);
404}
405
406obj asprintf(a,n) node **a;
407{
408 obj x;
409 node *y;
410 char *s;
411
412 y = a[0]->nnext;
413 x = execute(a[0]);
414 s = format(getsval(x.optr), y);
415 tempfree(x);
416 x = gettemp();
417 x.optr->sval = s;
418 x.optr->tval = STR;
419 return(x);
420}
421
422obj arith(a,n) node **a;
423{
424 awkfloat i,j;
425 obj x,y,z;
426
427 x = execute(a[0]);
428 i = getfval(x.optr);
429 tempfree(x);
430 if (n != UMINUS) {
431 y = execute(a[1]);
432 j = getfval(y.optr);
433 tempfree(y);
434 }
435 z = gettemp();
436 switch (n) {
437 default:
438 error(FATAL, "illegal arithmetic operator %d", n);
439 case ADD:
440 i += j;
441 break;
442 case MINUS:
443 i -= j;
444 break;
445 case MULT:
446 i *= j;
447 break;
448 case DIVIDE:
449 if (j == 0)
450 error(FATAL, "division by zero");
451 i /= j;
452 break;
453 case MOD:
454 if (j == 0)
455 error(FATAL, "division by zero");
456 i = i - j*(long)(i/j);
457 break;
458 case UMINUS:
459 i = -i;
460 break;
461 }
462 setfval(z.optr, i);
463 return(z);
464}
465
466obj incrdecr(a, n) node **a;
467{
468 obj x, z;
469 int k;
470 awkfloat xf;
471
472 x = execute(a[0]);
473 xf = getfval(x.optr);
474 k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
475 if (n == PREINCR || n == PREDECR) {
476 setfval(x.optr, xf + k);
477 return(x);
478 }
479 z = gettemp();
480 setfval(z.optr, xf);
481 setfval(x.optr, xf + k);
482 tempfree(x);
483 return(z);
484}
485
486
487obj assign(a,n) node **a;
488{
489 obj x, y;
490 awkfloat xf, yf;
491
492 x = execute(a[0]);
493 y = execute(a[1]);
494 if (n == ASSIGN) { /* ordinary assignment */
495 if ((y.optr->tval & (STR|NUM)) == (STR|NUM)) {
496 setsval(x.optr, y.optr->sval);
497 x.optr->fval = y.optr->fval;
498 x.optr->tval |= NUM;
499 }
500 else if (y.optr->tval & STR)
501 setsval(x.optr, y.optr->sval);
502 else if (y.optr->tval & NUM)
503 setfval(x.optr, y.optr->fval);
504 tempfree(y);
505 return(x);
506 }
507 xf = getfval(x.optr);
508 yf = getfval(y.optr);
509 switch (n) {
510 case ADDEQ:
511 xf += yf;
512 break;
513 case SUBEQ:
514 xf -= yf;
515 break;
516 case MULTEQ:
517 xf *= yf;
518 break;
519 case DIVEQ:
520 if (yf == 0)
521 error(FATAL, "division by zero");
522 xf /= yf;
523 break;
524 case MODEQ:
525 if (yf == 0)
526 error(FATAL, "division by zero");
527 xf = xf - yf*(long)(xf/yf);
528 break;
529 default:
530 error(FATAL, "illegal assignment operator %d", n);
531 break;
532 }
533 tempfree(y);
534 setfval(x.optr, xf);
535 return(x);
536}
537
538obj cat(a,q) node **a;
539{
540 obj x,y,z;
541 int n1, n2;
542 char *s;
543
544 x = execute(a[0]);
545 y = execute(a[1]);
546 getsval(x.optr);
547 getsval(y.optr);
548 n1 = strlen(x.optr->sval);
549 n2 = strlen(y.optr->sval);
550 s = (char *) malloc(n1 + n2 + 1);
551 strcpy(s, x.optr->sval);
552 strcpy(s+n1, y.optr->sval);
553 tempfree(y);
554 z = gettemp();
555 z.optr->sval = s;
556 z.optr->tval = STR;
557 tempfree(x);
558 return(z);
559}
560
561obj pastat(a,n) node **a;
562{
563 obj x;
564
565 if (a[0]==nullstat)
566 x = true;
567 else
568 x = execute(a[0]);
569 if (istrue(x)) {
570 tempfree(x);
571 x = execute(a[1]);
572 }
573 return(x);
574}
575
576obj dopa2(a,n) node **a;
577{
578 obj x;
579
580 if (pairstack[n]==0) {
581 x = execute(a[0]);
582 if (istrue(x))
583 pairstack[n] = 1;
584 tempfree(x);
585 }
586 if (pairstack[n] == 1) {
587 x = execute(a[1]);
588 if (istrue(x))
589 pairstack[n] = 0;
590 tempfree(x);
591 x = execute(a[2]);
592 return(x);
593 }
594 return(false);
595}
596
597obj aprintf(a,n) node **a;
598{
599 obj x;
600
601 x = asprintf(a,n);
602 if (a[1]==NULL) {
603 printf("%s", x.optr->sval);
604 tempfree(x);
605 return(true);
606 }
607 redirprint(x.optr->sval, (int)a[1], a[2]);
608 return(x);
609}
610
611obj split(a,nnn) node **a;
612{
613 obj x;
614 cell *ap;
615 register char *s, *p;
616 char *t, temp, num[5];
617 register int sep;
618 int n, flag;
619
620 x = execute(a[0]);
621 s = getsval(x.optr);
622 tempfree(x);
623 if (a[2] == nullstat)
624 sep = **FS;
625 else {
626 x = execute(a[2]);
627 sep = getsval(x.optr)[0];
628 tempfree(x);
629 }
630 ap = (cell *) a[1];
631 freesymtab(ap);
632 dprintf("split: s=|%s|, a=%s, sep=|%c|\n", s, ap->nval, sep);
633 ap->tval &= ~STR;
634 ap->tval |= ARR;
635 ap->sval = (char *) makesymtab();
636
637 n = 0;
638 if (sep == ' ')
639 for (n = 0; ; ) {
640 while (*s == ' ' || *s == '\t' || *s == '\n')
641 s++;
642 if (*s == 0)
643 break;
644 n++;
645 t = s;
646 do
647 s++;
648 while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
649 temp = *s;
650 *s = '\0';
6521d648 651 (void)sprintf(num, "%d", n);
059b34c5
KM
652 if (isnumber(t))
653 setsymtab(num, tostring(t), atof(t), STR|NUM, ap->sval);
654 else
655 setsymtab(num, tostring(t), 0.0, STR, ap->sval);
656 *s = temp;
657 if (*s != 0)
658 s++;
659 }
660 else if (*s != 0)
661 for (;;) {
662 n++;
663 t = s;
664 while (*s != sep && *s != '\n' && *s != '\0')
665 s++;
666 temp = *s;
667 *s = '\0';
6521d648 668 (void)sprintf(num, "%d", n);
059b34c5
KM
669 if (isnumber(t))
670 setsymtab(num, tostring(t), atof(t), STR|NUM, ap->sval);
671 else
672 setsymtab(num, tostring(t), 0.0, STR, ap->sval);
673 *s = temp;
674 if (*s++ == 0)
675 break;
676 }
677 x = gettemp();
678 x.optr->tval = NUM;
679 x.optr->fval = n;
680 return(x);
681}
682
683obj ifstat(a,n) node **a;
684{
685 obj x;
686
687 x = execute(a[0]);
688 if (istrue(x)) {
689 tempfree(x);
690 x = execute(a[1]);
691 }
692 else if (a[2] != nullstat) {
693 tempfree(x);
694 x = execute(a[2]);
695 }
696 return(x);
697}
698
699obj whilestat(a,n) node **a;
700{
701 obj x;
702
703 for (;;) {
704 x = execute(a[0]);
705 if (!istrue(x)) return(x);
706 tempfree(x);
707 x = execute(a[1]);
708 if (isbreak(x)) {
709 x = true;
710 return(x);
711 }
712 if (isnext(x) || isexit(x))
713 return(x);
714 tempfree(x);
715 }
716}
717
718obj forstat(a,n) node **a;
719{
720 obj x;
721
722 tempfree(execute(a[0]));
723 for (;;) {
724 if (a[1]!=nullstat) {
725 x = execute(a[1]);
726 if (!istrue(x)) return(x);
727 else tempfree(x);
728 }
729 x = execute(a[3]);
730 if (isbreak(x)) { /* turn off break */
731 x = true;
732 return(x);
733 }
734 if (isnext(x) || isexit(x))
735 return(x);
736 tempfree(x);
737 tempfree(execute(a[2]));
738 }
739}
740
741obj instat(a, n) node **a;
742{
743 cell *vp, *arrayp, *cp, **tp;
744 obj x;
745 int i;
746
747 vp = (cell *) a[0];
748 arrayp = (cell *) a[1];
749 if (!(arrayp->tval & ARR))
750 error(FATAL, "%s is not an array", arrayp->nval);
751 tp = (cell **) arrayp->sval;
752 for (i = 0; i < MAXSYM; i++) { /* this routine knows too much */
753 for (cp = tp[i]; cp != NULL; cp = cp->nextval) {
754 setsval(vp, cp->nval);
755 x = execute(a[2]);
756 if (isbreak(x)) {
757 x = true;
758 return(x);
759 }
760 if (isnext(x) || isexit(x))
761 return(x);
762 tempfree(x);
763 }
764 }
c01fc283 765 return (true);
059b34c5
KM
766}
767
768obj jump(a,n) node **a;
769{
770 obj x, y;
771
772 x.otype = OJUMP;
773 switch (n) {
774 default:
775 error(FATAL, "illegal jump type %d", n);
776 break;
777 case EXIT:
778 if (a[0] != 0) {
779 y = execute(a[0]);
780 errorflag = getfval(y.optr);
781 }
782 x.osub = JEXIT;
783 break;
784 case NEXT:
785 x.osub = JNEXT;
786 break;
787 case BREAK:
788 x.osub = JBREAK;
789 break;
790 case CONTINUE:
791 x.osub = JCONT;
792 break;
793 }
794 return(x);
795}
796
797obj fncn(a,n) node **a;
798{
799 obj x;
800 awkfloat u;
801 int t;
802
803 t = (int) a[0];
804 x = execute(a[1]);
805 if (t == FLENGTH)
806 u = (awkfloat) strlen(getsval(x.optr));
807 else if (t == FLOG)
808 u = log(getfval(x.optr));
809 else if (t == FINT)
810 u = (awkfloat) (long) getfval(x.optr);
811 else if (t == FEXP)
812 u = exp(getfval(x.optr));
813 else if (t == FSQRT)
814 u = sqrt(getfval(x.optr));
815 else
816 error(FATAL, "illegal function type %d", t);
817 tempfree(x);
818 x = gettemp();
819 setfval(x.optr, u);
820 return(x);
821}
822
823obj print(a,n) node **a;
824{
825 register node *x;
826 obj y;
827 char s[RECSIZE];
828
829 s[0] = '\0';
830 for (x=a[0]; x!=NULL; x=x->nnext) {
831 y = execute(x);
832 strcat(s, getsval(y.optr));
833 tempfree(y);
834 if (x->nnext==NULL)
835 strcat(s, *ORS);
836 else
837 strcat(s, *OFS);
838 }
839 if (strlen(s) >= RECSIZE)
840 error(FATAL, "string %.20s ... too long to print", s);
841 if (a[1]==nullstat) {
842 printf("%s", s);
843 return(true);
844 }
845 redirprint(s, (int)a[1], a[2]);
846 return(false);
847}
848
849obj nullproc() {}
850
851obj nodetoobj(a) node *a;
852{
853 obj x;
854
855 x.optr = (cell *) a->nobj;
856 x.otype = OCELL;
857 x.osub = a->subtype;
858 if (isfld(x)) fldbld();
859 return(x);
860}
861
862redirprint(s, a, b) char *s; node *b;
863{
864 register int i;
865 obj x;
866
867 x = execute(b);
868 getsval(x.optr);
869 for (i=0; i<FILENUM; i++)
870 if (files[i].fp && strcmp(x.optr->sval, files[i].fname) == 0)
871 goto doit;
872 for (i=0; i<FILENUM; i++)
873 if (files[i].fp == 0)
874 break;
875 if (i >= FILENUM)
876 error(FATAL, "too many output files %d", i);
877 if (a == '|') /* a pipe! */
878 files[i].fp = popen(x.optr->sval, "w");
879 else if (a == APPEND)
880 files[i].fp = fopen(x.optr->sval, "a");
881 else
882 files[i].fp = fopen(x.optr->sval, "w");
883 if (files[i].fp == NULL)
884 error(FATAL, "can't open file %s", x.optr->sval);
28e13bf4
KB
885 if (fcntl(fileno(files[i].fp), F_SETFD, 1) < 0)
886 error(FATAL, "close on exec failure");
059b34c5 887 files[i].fname = tostring(x.optr->sval);
1d8dcd58 888 files[i].type = a;
059b34c5
KM
889doit:
890 fprintf(files[i].fp, "%s", s);
891#ifndef gcos
892 fflush(files[i].fp); /* in case someone is waiting for the output */
893#endif
894 tempfree(x);
895}