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