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