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