|
|
1.1 root 1: /*
2: Copyright (c) 1989 AT&T
3: All Rights Reserved
4:
5: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T.
6:
7: The copyright notice above does not evidence any
8: actual or intended publication of such source code.
9: */
10:
11: #define tempfree(x) if (istemp(x)) tfree(x); else
12:
13: /* #define execute(p) (isvalue(p) ? (Cell *)((p)->narg[0]) : r_execute(p)) */
14: #define execute(p) r_execute(p)
15:
16: #define DEBUG
17: #include <stdio.h>
18: #include <ctype.h>
19: #include <setjmp.h>
20: #include <math.h>
21: #include <string.h>
22: #include <stdlib.h>
23: #include <time.h>
24: #include "awk.h"
25: #include "y.tab.h"
26:
27: #ifdef _NFILE
28: #ifndef FOPEN_MAX
29: #define FOPEN_MAX _NFILE
30: #endif
31: #endif
32:
33: #ifndef FOPEN_MAX
34: #define FOPEN_MAX 40 /* max number of open files */
35: #endif
36:
37: #ifndef RAND_MAX
38: #define RAND_MAX 32767 /* all that ansi guarantees */
39: #endif
40:
41: jmp_buf env;
42:
43: #define getfval(p) (((p)->tval & (ARR|FLD|REC|NUM)) == NUM ? (p)->fval : r_getfval(p))
44: #define getsval(p) (((p)->tval & (ARR|FLD|REC|STR)) == STR ? (p)->sval : r_getsval(p))
45:
46:
47: #define PA2NUM 29
48: int pairstack[PA2NUM], paircnt;
49: Node *winner = NULL;
50: Cell *tmps;
51:
52: static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM };
53: Cell *true = &truecell;
54: static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM };
55: Cell *false = &falsecell;
56: static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM };
57: Cell *jbreak = &breakcell;
58: static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM };
59: Cell *jcont = &contcell;
60: static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM };
61: Cell *jnext = &nextcell;
62: static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM };
63: Cell *jexit = &exitcell;
64: static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM };
65: Cell *jret = &retcell;
66: static Cell tempcell ={ OCELL, CTEMP, 0, 0, 0.0, NUM };
67:
68: Node *curnode = NULL; /* the node being executed, for debugging */
69:
70: void run(Node *a)
71: {
72: execute(a);
73: closeall();
74: }
75:
76: Cell *r_execute(Node *u)
77: {
78: register Cell *(*proc)(Node **, int);
79: register Cell *x;
80: register Node *a;
81:
82: if (u == NULL)
83: return(true);
84: for (a = u; ; a = a->nnext) {
85: curnode = a;
86: if (isvalue(a)) {
87: x = (Cell *) (a->narg[0]);
88: if ((x->tval & FLD) && !donefld)
89: fldbld();
90: else if ((x->tval & REC) && !donerec)
91: recbld();
92: return(x);
93: }
94: if (notlegal(a->nobj)) /* probably a Cell* but too risky to print */
95: ERROR "illegal statement" FATAL;
96: proc = proctab[a->nobj-FIRSTTOKEN];
97: x = (*proc)(a->narg, a->nobj);
98: if ((x->tval & FLD) && !donefld)
99: fldbld();
100: else if ((x->tval & REC) && !donerec)
101: recbld();
102: if (isexpr(a))
103: return(x);
104: if (isjump(x))
105: return(x);
106: if (a->nnext == NULL)
107: return(x);
108: tempfree(x);
109: }
110: }
111:
112:
113: Cell *program(Node **a, int n)
114: {
115: register Cell *x;
116:
117: if (setjmp(env) != 0)
118: goto ex;
119: if (a[0]) { /* BEGIN */
120: x = execute(a[0]);
121: if (isexit(x))
122: return(true);
123: if (isjump(x))
124: ERROR "illegal break, continue or next from BEGIN" FATAL;
125: tempfree(x);
126: }
127: loop:
128: if (a[1] || a[2])
129: while (getrec(record) > 0) {
130: x = execute(a[1]);
131: if (isexit(x))
132: break;
133: tempfree(x);
134: }
135: ex:
136: if (setjmp(env) != 0) /* handles exit within END */
137: goto ex1;
138: if (a[2]) { /* END */
139: x = execute(a[2]);
140: if (isbreak(x) || isnext(x) || iscont(x))
141: ERROR "illegal break, next, or continue from END" FATAL;
142: tempfree(x);
143: }
144: ex1:
145: return(true);
146: }
147:
148: struct Frame {
149: int nargs; /* number of arguments in this call */
150: Cell *fcncell; /* pointer to Cell for function */
151: Cell **args; /* pointer to array of arguments after execute */
152: Cell *retval; /* return value */
153: };
154:
155: #define NARGS 30
156:
157: struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */
158: int nframe = 0; /* number of frames allocated */
159: struct Frame *fp = NULL; /* frame pointer. bottom level unused */
160:
161: Cell *call(Node **a, int n)
162: {
163: static Cell newcopycell = { OCELL, CCOPY, 0, (uchar *) "", 0.0, NUM|STR|DONTFREE };
164: int i, ncall, ndef;
165: Node *x;
166: Cell *args[NARGS], *oargs[NARGS], *y, *z, *fcn;
167: uchar *s;
168:
169: fcn = execute(a[0]); /* the function itself */
170: s = fcn->nval;
171: if (!isfunc(fcn))
172: ERROR "calling undefined function %s", s FATAL;
173: if (frame == NULL) {
174: fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
175: if (frame == NULL)
176: ERROR "out of space for stack frames calling %s", s FATAL;
177: }
178: for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */
179: ncall++;
180: ndef = (int) fcn->fval; /* args in defn */
181: dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, fp-frame) );
182: if (ncall > ndef)
183: ERROR "function %s called with %d args, uses only %d",
184: s, ncall, ndef WARNING;
185: if (ncall + ndef > NARGS)
186: ERROR "function %s has %d arguments, limit %d", s, ncall+ndef, NARGS FATAL;
187: for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */
188: dprintf( ("evaluate args[%d], fp=%d:\n", i, fp-frame) );
189: y = execute(x);
190: oargs[i] = y;
191: dprintf( ("args[%d]: %s %f <%s>, t=%o\n",
192: i, y->nval, y->fval, isarr(y) ? "(array)" : (char*) y->sval, y->tval) );
193: if (isfunc(y))
194: ERROR "can't use function %s as argument in %s", y->nval, s FATAL;
195: if (isarr(y))
196: args[i] = y; /* arrays by ref */
197: else
198: args[i] = copycell(y);
199: tempfree(y);
200: }
201: for ( ; i < ndef; i++) { /* add null args for ones not provided */
202: args[i] = gettemp();
203: *args[i] = newcopycell;
204: }
205: fp++; /* now ok to up frame */
206: if (fp >= frame + nframe) {
207: int dfp = fp - frame; /* old index */
208: frame = (struct Frame *)
209: realloc((char *) frame, (nframe += 100) * sizeof(struct Frame));
210: if (frame == NULL)
211: ERROR "out of space for stack frames in %s", s FATAL;
212: fp = frame + dfp;
213: }
214: fp->fcncell = fcn;
215: fp->args = args;
216: fp->nargs = ndef; /* number defined with (excess are locals) */
217: fp->retval = gettemp();
218:
219: dprintf( ("start exec of %s, fp=%d\n", s, fp-frame) );
220: y = execute((Node *)(fcn->sval)); /* execute body */
221: dprintf( ("finished exec of %s, fp=%d\n", s, fp-frame) );
222:
223: for (i = 0; i < ndef; i++) {
224: Cell *t = fp->args[i];
225: if (isarr(t)) {
226: if (t->csub == CCOPY) {
227: if (i >= ncall) {
228: freesymtab(t);
229: t->csub = CTEMP;
230: } else {
231: oargs[i]->tval = t->tval;
232: oargs[i]->tval &= ~(STR|NUM|DONTFREE);
233: oargs[i]->sval = t->sval;
234: tempfree(t);
235: }
236: }
237: } else if (t != y) { /* kludge to prevent freeing twice */
238: t->csub = CTEMP;
239: tempfree(t);
240: }
241: }
242: tempfree(fcn);
243: if (isexit(y) || isnext(y))
244: return y;
245: tempfree(y); /* this can free twice! */
246: z = fp->retval; /* return value */
247: dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );
248: fp--;
249: return(z);
250: }
251:
252: Cell *copycell(Cell *x) /* make a copy of a cell in a temp */
253: {
254: Cell *y;
255:
256: y = gettemp();
257: y->csub = CCOPY; /* prevents freeing until call is over */
258: y->nval = x->nval;
259: y->sval = x->sval ? tostring(x->sval) : NULL;
260: y->fval = x->fval;
261: y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */
262: /* is DONTFREE right? */
263: return y;
264: }
265:
266: Cell *arg(Node **a, int n)
267: {
268:
269: n = (int) a[0]; /* argument number, counting from 0 */
270: dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );
271: if (n+1 > fp->nargs)
272: ERROR "argument #%d of function %s was not supplied",
273: n+1, fp->fcncell->nval FATAL;
274: return fp->args[n];
275: }
276:
277: Cell *jump(Node **a, int n)
278: {
279: register Cell *y;
280:
281: switch (n) {
282: case EXIT:
283: if (a[0] != NULL) {
284: y = execute(a[0]);
285: errorflag = getfval(y);
286: tempfree(y);
287: }
288: longjmp(env, 1);
289: case RETURN:
290: if (a[0] != NULL) {
291: y = execute(a[0]);
292: if ((y->tval & (STR|NUM)) == (STR|NUM)) {
293: setsval(fp->retval, getsval(y));
294: fp->retval->fval = getfval(y);
295: fp->retval->tval |= NUM;
296: }
297: else if (y->tval & STR)
298: setsval(fp->retval, getsval(y));
299: else if (y->tval & NUM)
300: setfval(fp->retval, getfval(y));
301: else /* can't happen */
302: ERROR "bad type variable %d", y->tval FATAL;
303: tempfree(y);
304: }
305: return(jret);
306: case NEXT:
307: return(jnext);
308: case BREAK:
309: return(jbreak);
310: case CONTINUE:
311: return(jcont);
312: default: /* can't happen */
313: ERROR "illegal jump type %d", n FATAL;
314: }
315: return 0; /* not reached */
316: }
317:
318: Cell *getline(Node **a, int n)
319: {
320: /* a[0] is variable, a[1] is operator, a[2] is filename */
321: register Cell *r, *x;
322: uchar buf[RECSIZE];
323: FILE *fp;
324:
325: fflush(stdout); /* in case someone is waiting for a prompt */
326: r = gettemp();
327: if (a[1] != NULL) { /* getline < file */
328: x = execute(a[2]); /* filename */
329: if ((int) a[1] == '|') /* input pipe */
330: a[1] = (Node *) LE; /* arbitrary flag */
331: fp = openfile((int) a[1], getsval(x));
332: tempfree(x);
333: if (fp == NULL)
334: n = -1;
335: else
336: n = readrec(buf, sizeof(buf), fp);
337: if (n <= 0) {
338: ;
339: } else if (a[0] != NULL) { /* getline var <file */
340: setsval(execute(a[0]), buf);
341: } else { /* getline <file */
342: if (!(recloc->tval & DONTFREE))
343: xfree(recloc->sval);
344: strcpy(record, buf);
345: recloc->sval = record;
346: recloc->tval = REC | STR | DONTFREE;
347: if (isnumber(recloc->sval)) {
348: recloc->fval = atof(recloc->sval);
349: recloc->tval |= NUM;
350: }
351: donerec = 1; donefld = 0;
352: }
353: } else { /* bare getline; use current input */
354: if (a[0] == NULL) /* getline */
355: n = getrec(record);
356: else { /* getline var */
357: n = getrec(buf);
358: setsval(execute(a[0]), buf);
359: }
360: }
361: setfval(r, (Awkfloat) n);
362: return r;
363: }
364:
365: Cell *getnf(Node **a, int n)
366: {
367: if (donefld == 0)
368: fldbld();
369: return (Cell *) a[0];
370: }
371:
372: Cell *array(Node **a, int n)
373: {
374: register Cell *x, *y, *z;
375: register uchar *s;
376: register Node *np;
377: uchar buf[RECSIZE];
378:
379: x = execute(a[0]); /* Cell* for symbol table */
380: buf[0] = 0;
381: for (np = a[1]; np; np = np->nnext) {
382: y = execute(np); /* subscript */
383: s = getsval(y);
384: strcat(buf, s);
385: if (np->nnext)
386: strcat(buf, *SUBSEP);
387: tempfree(y);
388: }
389: if (!isarr(x)) {
390: dprintf( ("making %s into an array\n", x->nval) );
391: if (freeable(x))
392: xfree(x->sval);
393: x->tval &= ~(STR|NUM|DONTFREE);
394: x->tval |= ARR;
395: x->sval = (uchar *) makesymtab(NSYMTAB);
396: }
397: z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
398: z->ctype = OCELL;
399: z->csub = CVAR;
400: tempfree(x);
401: return(z);
402: }
403:
404: Cell *adelete(Node **a, int n)
405: {
406: Cell *x, *y;
407: Node *np;
408: uchar buf[RECSIZE], *s;
409:
410: x = execute(a[0]); /* Cell* for symbol table */
411: if (!isarr(x))
412: return true;
413: buf[0] = 0;
414: for (np = a[1]; np; np = np->nnext) {
415: y = execute(np); /* subscript */
416: s = getsval(y);
417: strcat(buf, s);
418: if (np->nnext)
419: strcat(buf, *SUBSEP);
420: tempfree(y);
421: }
422: freeelem(x, buf);
423: tempfree(x);
424: return true;
425: }
426:
427: Cell *intest(Node **a, int n)
428: {
429: register Cell *x, *ap, *k;
430: Node *p;
431: char buf[RECSIZE];
432: uchar *s;
433:
434: ap = execute(a[1]); /* array name */
435: /* if (!isarr(ap))
436: ERROR "%s is not an array", ap->nval FATAL; */
437: if (!isarr(ap)) {
438: dprintf( ("making %s into an array\n", ap->nval) );
439: if (freeable(ap))
440: xfree(ap->sval);
441: ap->tval &= ~(STR|NUM|DONTFREE);
442: ap->tval |= ARR;
443: ap->sval = (uchar *) makesymtab(NSYMTAB);
444: }
445: buf[0] = 0;
446: for (p = a[0]; p; p = p->nnext) {
447: x = execute(p); /* expr */
448: s = getsval(x);
449: strcat(buf, s);
450: tempfree(x);
451: if (p->nnext)
452: strcat(buf, *SUBSEP);
453: }
454: k = lookup(buf, (Array *) ap->sval);
455: tempfree(ap);
456: if (k == NULL)
457: return(false);
458: else
459: return(true);
460: }
461:
462:
463: Cell *matchop(Node **a, int n)
464: {
465: register Cell *x, *y;
466: register uchar *s, *t;
467: register int i;
468: fa *pfa;
469: int (*mf)(fa *, uchar *) = match, mode = 0;
470:
471: if (n == MATCHFCN) {
472: mf = pmatch;
473: mode = 1;
474: }
475: x = execute(a[1]);
476: s = getsval(x);
477: if (a[0] == 0)
478: i = (*mf)((fa *) a[2], s);
479: else {
480: y = execute(a[2]);
481: t = getsval(y);
482: pfa = makedfa(t, mode);
483: i = (*mf)(pfa, s);
484: tempfree(y);
485: }
486: tempfree(x);
487: if (n == MATCHFCN) {
488: int start = patbeg - s + 1;
489: if (patlen < 0)
490: start = 0;
491: setfval(rstartloc, (Awkfloat) start);
492: setfval(rlengthloc, (Awkfloat) patlen);
493: x = gettemp();
494: x->tval = NUM;
495: x->fval = start;
496: return x;
497: } else if (n == MATCH && i == 1 || n == NOTMATCH && i == 0)
498: return(true);
499: else
500: return(false);
501: }
502:
503:
504: Cell *boolop(Node **a, int n)
505: {
506: register Cell *x, *y;
507: register int i;
508:
509: x = execute(a[0]);
510: i = istrue(x);
511: tempfree(x);
512: switch (n) {
513: case BOR:
514: if (i) return(true);
515: y = execute(a[1]);
516: i = istrue(y);
517: tempfree(y);
518: if (i) return(true);
519: else return(false);
520: case AND:
521: if ( !i ) return(false);
522: y = execute(a[1]);
523: i = istrue(y);
524: tempfree(y);
525: if (i) return(true);
526: else return(false);
527: case NOT:
528: if (i) return(false);
529: else return(true);
530: default: /* can't happen */
531: ERROR "unknown boolean operator %d", n FATAL;
532: }
533: return 0; /*NOTREACHED*/
534: }
535:
536: Cell *relop(Node **a, int n)
537: {
538: register int i;
539: register Cell *x, *y;
540: Awkfloat j;
541:
542: x = execute(a[0]);
543: y = execute(a[1]);
544: if (x->tval&NUM && y->tval&NUM) {
545: j = x->fval - y->fval;
546: i = j<0? -1: (j>0? 1: 0);
547: } else {
548: i = strcmp(getsval(x), getsval(y));
549: }
550: tempfree(x);
551: tempfree(y);
552: switch (n) {
553: case LT: if (i<0) return(true);
554: else return(false);
555: case LE: if (i<=0) return(true);
556: else return(false);
557: case NE: if (i!=0) return(true);
558: else return(false);
559: case EQ: if (i == 0) return(true);
560: else return(false);
561: case GE: if (i>=0) return(true);
562: else return(false);
563: case GT: if (i>0) return(true);
564: else return(false);
565: default: /* can't happen */
566: ERROR "unknown relational operator %d", n FATAL;
567: }
568: return 0; /*NOTREACHED*/
569: }
570:
571: void tfree(Cell *a)
572: {
573: if (freeable(a))
574: xfree(a->sval);
575: if (a == tmps)
576: ERROR "tempcell list is curdled" FATAL;
577: a->cnext = tmps;
578: tmps = a;
579: }
580:
581: Cell *gettemp(void)
582: { int i;
583: register Cell *x;
584:
585: if (!tmps) {
586: tmps = (Cell *) calloc(100, sizeof(Cell));
587: if (!tmps)
588: ERROR "out of space for temporaries" FATAL;
589: for(i = 1; i < 100; i++)
590: tmps[i-1].cnext = &tmps[i];
591: tmps[i-1].cnext = 0;
592: }
593: x = tmps;
594: tmps = x->cnext;
595: *x = tempcell;
596: return(x);
597: }
598:
599: Cell *indirect(Node **a, int n)
600: {
601: register Cell *x;
602: register int m;
603: register uchar *s;
604:
605: x = execute(a[0]);
606: m = getfval(x);
607: if (m == 0 && !isnumber(s = getsval(x))) /* suspicion! */
608: ERROR "illegal field $(%s)", s FATAL;
609: tempfree(x);
610: x = fieldadr(m);
611: x->ctype = OCELL;
612: x->csub = CFLD;
613: return(x);
614: }
615:
616: Cell *substr(Node **a, int nnn)
617: {
618: register int k, m, n;
619: register uchar *s;
620: int temp;
621: register Cell *x, *y, *z;
622:
623: x = execute(a[0]);
624: y = execute(a[1]);
625: if (a[2] != 0)
626: z = execute(a[2]);
627: s = getsval(x);
628: k = strlen(s) + 1;
629: if (k <= 1) {
630: tempfree(x);
631: tempfree(y);
632: if (a[2] != 0)
633: tempfree(z);
634: x = gettemp();
635: setsval(x, "");
636: return(x);
637: }
638: m = getfval(y);
639: if (m <= 0)
640: m = 1;
641: else if (m > k)
642: m = k;
643: tempfree(y);
644: if (a[2] != 0) {
645: n = getfval(z);
646: tempfree(z);
647: } else
648: n = k - 1;
649: if (n < 0)
650: n = 0;
651: else if (n > k - m)
652: n = k - m;
653: dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) );
654: y = gettemp();
655: temp = s[n+m-1]; /* with thanks to John Linderman */
656: s[n+m-1] = '\0';
657: setsval(y, s + m - 1);
658: s[n+m-1] = temp;
659: tempfree(x);
660: return(y);
661: }
662:
663: Cell *sindex(Node **a, int nnn)
664: {
665: register Cell *x, *y, *z;
666: register uchar *s1, *s2, *p1, *p2, *q;
667: Awkfloat v = 0.0;
668:
669: x = execute(a[0]);
670: s1 = getsval(x);
671: y = execute(a[1]);
672: s2 = getsval(y);
673:
674: z = gettemp();
675: for (p1 = s1; *p1 != '\0'; p1++) {
676: for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
677: ;
678: if (*p2 == '\0') {
679: v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */
680: break;
681: }
682: }
683: tempfree(x);
684: tempfree(y);
685: setfval(z, v);
686: return(z);
687: }
688:
689: format(uchar *buf, int bufsize, uchar *s, Node *a)
690: {
691: uchar fmt[RECSIZE];
692: register uchar *p, *t, *os;
693: register Cell *x;
694: int flag = 0, n;
695:
696: os = s;
697: p = buf;
698: while (*s) {
699: if (p - buf >= bufsize)
700: return -1;
701: if (*s != '%') {
702: *p++ = *s++;
703: continue;
704: }
705: if (*(s+1) == '%') {
706: *p++ = '%';
707: s += 2;
708: continue;
709: }
710: for (t=fmt; (*t++ = *s) != '\0'; s++) {
711: if (isalpha(*s) && *s != 'l' && *s != 'h' && *s != 'L')
712: break; /* the ansi panoply */
713: if (*s == '*') {
714: x = execute(a);
715: a = a->nnext;
716: sprintf((char *)t-1, "%d", (int) getfval(x));
717: t = fmt + strlen(fmt);
718: tempfree(x);
719: }
720: }
721: *t = '\0';
722: if (t >= fmt + sizeof(fmt))
723: ERROR "format item %.20s... too long", os FATAL;
724: switch (*s) {
725: case 'f': case 'e': case 'g': case 'E': case 'G':
726: flag = 1;
727: break;
728: case 'd': case 'i':
729: flag = 2;
730: if(*(s-1) == 'l') break;
731: *(t-1) = 'l';
732: *t = 'd';
733: *++t = '\0';
734: break;
735: case 'o': case 'x': case 'X': case 'u':
736: flag = *(s-1) == 'l' ? 2 : 3;
737: break;
738: case 's':
739: flag = 4;
740: break;
741: case 'c':
742: flag = 5;
743: break;
744: default:
745: ERROR "weird printf conversion %s", fmt WARNING;
746: flag = 0;
747: break;
748: }
749: if (a == NULL)
750: ERROR "not enough args in printf(%s)", os FATAL;
751: x = execute(a);
752: a = a->nnext;
753: switch (flag) {
754: case 0: sprintf((char *)p, "%s", fmt); /* unknown, so dump it too */
755: p += strlen(p);
756: sprintf((char *)p, "%s", getsval(x));
757: break;
758: case 1: sprintf((char *)p, (char *)fmt, getfval(x)); break;
759: case 2: sprintf((char *)p, (char *)fmt, (long) getfval(x)); break;
760: case 3: sprintf((char *)p, (char *)fmt, (int) getfval(x)); break;
761: case 4:
762: t = getsval(x);
763: n = strlen(t);
764: if (n >= bufsize)
765: ERROR "huge string (%d chars) in printf %.30s...",
766: n, t FATAL;
767: sprintf((char *)p, (char *)fmt, t);
768: break;
769: case 5: isnum(x) ? sprintf((char *)p, (char *)fmt, (int) getfval(x))
770: : sprintf((char *)p, (char *)fmt, getsval(x)[0]);
771: break;
772: }
773: tempfree(x);
774: p += strlen(p);
775: s++;
776: }
777: *p = '\0';
778: for ( ; a; a = a->nnext) /* evaluate any remaining args */
779: execute(a);
780: return 0;
781: }
782:
783: Cell *asprintf(Node **a, int n)
784: {
785: register Cell *x;
786: register Node *y;
787: uchar buf[3*RECSIZE];
788:
789: y = a[0]->nnext;
790: x = execute(a[0]);
791: if (format(buf, sizeof buf, getsval(x), y) == -1)
792: ERROR "sprintf string %.40s... too long", buf FATAL;
793: tempfree(x);
794: x = gettemp();
795: x->sval = tostring(buf);
796: x->tval = STR;
797: return(x);
798: }
799:
800: Cell *aprintf(Node **a, int n)
801: {
802: FILE *fp;
803: register Cell *x;
804: register Node *y;
805: uchar buf[3*RECSIZE];
806:
807: y = a[0]->nnext;
808: x = execute(a[0]);
809: if (format(buf, sizeof buf, getsval(x), y) == -1)
810: ERROR "printf string %.40s... too long", buf FATAL;
811: tempfree(x);
812: if (a[1] == NULL) {
813: fputs((char *)buf, stdout);
814: if (ferror(stdout))
815: ERROR "write error on stdout" FATAL;
816: } else {
817: fp = redirect((int)a[1], a[2]);
818: fputs((char *)buf, fp);
819: fflush(fp);
820: if (ferror(fp))
821: ERROR "write error on %s", filename(fp) FATAL;
822: }
823: return(true);
824: }
825:
826: Cell *arith(Node **a, int n)
827: {
828: Awkfloat i, j;
829: double v;
830: register Cell *x, *y, *z;
831:
832: x = execute(a[0]);
833: i = getfval(x);
834: tempfree(x);
835: if (n != UMINUS) {
836: y = execute(a[1]);
837: j = getfval(y);
838: tempfree(y);
839: }
840: z = gettemp();
841: switch (n) {
842: case ADD:
843: i += j;
844: break;
845: case MINUS:
846: i -= j;
847: break;
848: case MULT:
849: i *= j;
850: break;
851: case DIVIDE:
852: if (j == 0)
853: ERROR "division by zero" FATAL;
854: i /= j;
855: break;
856: case MOD:
857: if (j == 0)
858: ERROR "division by zero in mod" FATAL;
859: modf(i/j, &v);
860: i = i - j * v;
861: break;
862: case UMINUS:
863: i = -i;
864: break;
865: case POWER:
866: if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
867: i = ipow(i, (int) j);
868: else
869: i = errcheck(pow(i, j), "pow");
870: break;
871: default: /* can't happen */
872: ERROR "illegal arithmetic operator %d", n FATAL;
873: }
874: setfval(z, i);
875: return(z);
876: }
877:
878: double ipow(double x, int n)
879: {
880: double v;
881:
882: if (n <= 0)
883: return 1;
884: v = ipow(x, n/2);
885: if (n % 2 == 0)
886: return v * v;
887: else
888: return x * v * v;
889: }
890:
891: Cell *incrdecr(Node **a, int n)
892: {
893: register Cell *x, *z;
894: register int k;
895: Awkfloat xf;
896:
897: x = execute(a[0]);
898: xf = getfval(x);
899: k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
900: if (n == PREINCR || n == PREDECR) {
901: setfval(x, xf + k);
902: return(x);
903: }
904: z = gettemp();
905: setfval(z, xf);
906: setfval(x, xf + k);
907: tempfree(x);
908: return(z);
909: }
910:
911: Cell *assign(Node **a, int n)
912: {
913: register Cell *x, *y;
914: Awkfloat xf, yf;
915: double v;
916:
917: y = execute(a[1]);
918: x = execute(a[0]);
919: if (n == ASSIGN) { /* ordinary assignment */
920: if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: leave alone! */
921: ; /* unless it's a field */
922: else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
923: setsval(x, getsval(y));
924: x->fval = getfval(y);
925: x->tval |= NUM;
926: }
927: else if (y->tval & STR)
928: setsval(x, getsval(y));
929: else if (y->tval & NUM)
930: setfval(x, getfval(y));
931: else
932: funnyvar(y, "read value of");
933: tempfree(y);
934: return(x);
935: }
936: xf = getfval(x);
937: yf = getfval(y);
938: switch (n) {
939: case ADDEQ:
940: xf += yf;
941: break;
942: case SUBEQ:
943: xf -= yf;
944: break;
945: case MULTEQ:
946: xf *= yf;
947: break;
948: case DIVEQ:
949: if (yf == 0)
950: ERROR "division by zero in /=" FATAL;
951: xf /= yf;
952: break;
953: case MODEQ:
954: if (yf == 0)
955: ERROR "division by zero in %%=" FATAL;
956: modf(xf/yf, &v);
957: xf = xf - yf * v;
958: break;
959: case POWEQ:
960: if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */
961: xf = ipow(xf, (int) yf);
962: else
963: xf = errcheck(pow(xf, yf), "pow");
964: break;
965: default:
966: ERROR "illegal assignment operator %d", n FATAL;
967: break;
968: }
969: tempfree(y);
970: setfval(x, xf);
971: return(x);
972: }
973:
974: Cell *cat(Node **a, int q)
975: {
976: register Cell *x, *y, *z;
977: register int n1, n2;
978: register uchar *s;
979:
980: x = execute(a[0]);
981: y = execute(a[1]);
982: getsval(x);
983: getsval(y);
984: n1 = strlen(x->sval);
985: n2 = strlen(y->sval);
986: s = (uchar *) malloc(n1 + n2 + 1);
987: if (s == NULL)
988: ERROR "out of space concatenating %.15s... and %.15s...",
989: x->sval, y->sval FATAL;
990: strcpy(s, x->sval);
991: strcpy(s+n1, y->sval);
992: tempfree(y);
993: z = gettemp();
994: z->sval = s;
995: z->tval = STR;
996: tempfree(x);
997: return(z);
998: }
999:
1000: Cell *pastat(Node **a, int n) /* a[0] { a[1] } */
1001: {
1002: register Cell *x;
1003:
1004: if (a[0] == 0)
1005: x = execute(a[1]);
1006: else {
1007: x = execute(a[0]);
1008: if (istrue(x)) {
1009: tempfree(x);
1010: x = execute(a[1]);
1011: }
1012: }
1013: return x;
1014: }
1015:
1016: Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */
1017: {
1018: register Cell *x;
1019: register int pair;
1020:
1021: pair = (int) a[3];
1022: if (pairstack[pair] == 0) {
1023: x = execute(a[0]);
1024: if (istrue(x))
1025: pairstack[pair] = 1;
1026: tempfree(x);
1027: }
1028: if (pairstack[pair] == 1) {
1029: x = execute(a[1]);
1030: if (istrue(x))
1031: pairstack[pair] = 0;
1032: tempfree(x);
1033: x = execute(a[2]);
1034: return(x);
1035: }
1036: return(false);
1037: }
1038:
1039: Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
1040: {
1041: Cell *x, *y, *ap;
1042: register uchar *s;
1043: register int sep;
1044: uchar *t, temp, num[10], *fs;
1045: int n, tempstat;
1046:
1047: y = execute(a[0]); /* source string */
1048: s = getsval(y);
1049: if (a[2] == 0) /* fs string */
1050: fs = *FS;
1051: else if ((int) a[3] == STRING) { /* split(str,arr,"string") */
1052: x = execute(a[2]);
1053: fs = getsval(x);
1054: } else if ((int) a[3] == REGEXPR)
1055: fs = (uchar*) "(regexpr)"; /* split(str,arr,/regexpr/) */
1056: else
1057: ERROR "illegal type of split()" FATAL;
1058: sep = *fs;
1059: ap = execute(a[1]); /* array name */
1060: freesymtab(ap);
1061: dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs) );
1062: ap->tval &= ~STR;
1063: ap->tval |= ARR;
1064: ap->sval = (uchar *) makesymtab(NSYMTAB);
1065:
1066: n = 0;
1067: if (*s != '\0' && strlen(fs) > 1 || (int) a[3] == REGEXPR) { /* reg expr */
1068: fa *pfa;
1069: if ((int) a[3] == REGEXPR) { /* it's ready already */
1070: pfa = (fa *) a[2];
1071: } else {
1072: pfa = makedfa(fs, 1);
1073: }
1074: if (nematch(pfa,s)) {
1075: tempstat = pfa->initstat;
1076: pfa->initstat = 2;
1077: do {
1078: n++;
1079: sprintf((char *)num, "%d", n);
1080: temp = *patbeg;
1081: *patbeg = '\0';
1082: if (isnumber(s))
1083: setsymtab(num, s, atof((char *)s), STR|NUM, (Array *) ap->sval);
1084: else
1085: setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1086: *patbeg = temp;
1087: s = patbeg + patlen;
1088: if (*(patbeg+patlen-1) == 0 || *s == 0) {
1089: n++;
1090: sprintf((char *)num, "%d", n);
1091: setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
1092: pfa->initstat = tempstat;
1093: goto spdone;
1094: }
1095: } while (nematch(pfa,s));
1096: }
1097: n++;
1098: sprintf((char *)num, "%d", n);
1099: if (isnumber(s))
1100: setsymtab(num, s, atof((char *)s), STR|NUM, (Array *) ap->sval);
1101: else
1102: setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1103: spdone:
1104: pfa = NULL;
1105: } else if (sep == ' ') {
1106: for (n = 0; ; ) {
1107: while (*s == ' ' || *s == '\t' || *s == '\n')
1108: s++;
1109: if (*s == 0)
1110: break;
1111: n++;
1112: t = s;
1113: do
1114: s++;
1115: while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
1116: temp = *s;
1117: *s = '\0';
1118: sprintf((char *)num, "%d", n);
1119: if (isnumber(t))
1120: setsymtab(num, t, atof((char *)t), STR|NUM, (Array *) ap->sval);
1121: else
1122: setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1123: *s = temp;
1124: if (*s != 0)
1125: s++;
1126: }
1127: } else if (*s != 0) {
1128: for (;;) {
1129: n++;
1130: t = s;
1131: while (*s != sep && *s != '\n' && *s != '\0')
1132: s++;
1133: temp = *s;
1134: *s = '\0';
1135: sprintf((char *)num, "%d", n);
1136: if (isnumber(t))
1137: setsymtab(num, t, atof((char *)t), STR|NUM, (Array *) ap->sval);
1138: else
1139: setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1140: *s = temp;
1141: if (*s++ == 0)
1142: break;
1143: }
1144: }
1145: tempfree(ap);
1146: tempfree(y);
1147: if (a[2] != 0 && (int) a[3] == STRING)
1148: tempfree(x);
1149: x = gettemp();
1150: x->tval = NUM;
1151: x->fval = n;
1152: return(x);
1153: }
1154:
1155: Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */
1156: {
1157: register Cell *x;
1158:
1159: x = execute(a[0]);
1160: if (istrue(x)) {
1161: tempfree(x);
1162: x = execute(a[1]);
1163: } else {
1164: tempfree(x);
1165: x = execute(a[2]);
1166: }
1167: return(x);
1168: }
1169:
1170: Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */
1171: {
1172: register Cell *x;
1173:
1174: x = execute(a[0]);
1175: if (istrue(x)) {
1176: tempfree(x);
1177: x = execute(a[1]);
1178: } else if (a[2] != 0) {
1179: tempfree(x);
1180: x = execute(a[2]);
1181: }
1182: return(x);
1183: }
1184:
1185: Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */
1186: {
1187: register Cell *x;
1188:
1189: for (;;) {
1190: x = execute(a[0]);
1191: if (!istrue(x))
1192: return(x);
1193: tempfree(x);
1194: x = execute(a[1]);
1195: if (isbreak(x)) {
1196: x = true;
1197: return(x);
1198: }
1199: if (isnext(x) || isexit(x) || isret(x))
1200: return(x);
1201: tempfree(x);
1202: }
1203: }
1204:
1205: Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */
1206: {
1207: register Cell *x;
1208:
1209: for (;;) {
1210: x = execute(a[0]);
1211: if (isbreak(x))
1212: return true;
1213: if (isnext(x) || isexit(x) || isret(x))
1214: return(x);
1215: tempfree(x);
1216: x = execute(a[1]);
1217: if (!istrue(x))
1218: return(x);
1219: tempfree(x);
1220: }
1221: }
1222:
1223: Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */
1224: {
1225: register Cell *x;
1226:
1227: x = execute(a[0]);
1228: tempfree(x);
1229: for (;;) {
1230: if (a[1]!=0) {
1231: x = execute(a[1]);
1232: if (!istrue(x)) return(x);
1233: else tempfree(x);
1234: }
1235: x = execute(a[3]);
1236: if (isbreak(x)) /* turn off break */
1237: return true;
1238: if (isnext(x) || isexit(x) || isret(x))
1239: return(x);
1240: tempfree(x);
1241: x = execute(a[2]);
1242: tempfree(x);
1243: }
1244: }
1245:
1246: Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */
1247: {
1248: register Cell *x, *vp, *arrayp, *cp, *ncp;
1249: Array *tp;
1250: int i;
1251:
1252: vp = execute(a[0]);
1253: arrayp = execute(a[1]);
1254: if (!isarr(arrayp)) {
1255: /* ERROR "%s is not an array", arrayp->nval FATAL; */
1256: return true;
1257: }
1258: tp = (Array *) arrayp->sval;
1259: tempfree(arrayp);
1260: for (i = 0; i < tp->size; i++) { /* this routine knows too much */
1261: for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1262: setsval(vp, cp->nval);
1263: ncp = cp->cnext;
1264: x = execute(a[2]);
1265: if (isbreak(x)) {
1266: tempfree(vp);
1267: return true;
1268: }
1269: if (isnext(x) || isexit(x) || isret(x)) {
1270: tempfree(vp);
1271: return(x);
1272: }
1273: tempfree(x);
1274: }
1275: }
1276: return true;
1277: }
1278:
1279: /* if someone ever wants to run over the arrays in sorted order: */
1280:
1281: /*
1282: *int qstrcmp(p, q)
1283: * uchar **p, **q;
1284: *{
1285: * return strcmp(*p, *q);
1286: *}
1287: */
1288:
1289: /*Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */
1290: /*{
1291: /* register Cell *x, *vp, *arrayp, *cp, *ncp, *ret;
1292: /* Array *tp;
1293: /* int i, ne;
1294: /*#define BIGENOUGH 1000
1295: /* uchar *elems[BIGENOUGH], **ep;
1296: /*
1297: /* vp = execute(a[0]);
1298: /* arrayp = execute(a[1]);
1299: /* if (!isarr(arrayp))
1300: /* ERROR "%s is not an array", arrayp->nval FATAL;
1301: /* tp = (Array *) arrayp->sval;
1302: /* tempfree(arrayp);
1303: /* ep = elems;
1304: /* ret = true;
1305: /* if (tp->nelem >= BIGENOUGH)
1306: /* ep = (uchar **) malloc(tp->nelem * sizeof(char *));
1307: /*
1308: /* for (i = ne = 0; i < tp->size; i++)
1309: /* for (cp = tp->tab[i]; cp != NULL; cp = cp->cnext)
1310: /* ep[ne++] = cp->nval;
1311: /* if (ne != tp->nelem)
1312: /* ERROR "can't happen: lost elems %d vs. %d", ne, tp->nelem FATAL;
1313: /* qsort(ep, ne, sizeof(char *), qstrcmp);
1314: /* for (i = 0; i < ne; i++) {
1315: /* setsval(vp, ep[i]);
1316: /* x = execute(a[2]);
1317: /* if (isbreak(x)) {
1318: /* tempfree(vp);
1319: /* break;
1320: /* }
1321: /* if (isnext(x) || isexit(x) || isret(x)) {
1322: /* tempfree(vp);
1323: /* ret = x;
1324: /* break;
1325: /* }
1326: /* tempfree(x);
1327: /* }
1328: /* if (ep != elems)
1329: /* free(ep);
1330: /* return ret;
1331: /*}
1332: */
1333:
1334:
1335: Cell *bltin(Node **a, int n)
1336: {
1337: register Cell *x, *y;
1338: Awkfloat u;
1339: register int t;
1340: uchar *p, buf[RECSIZE];
1341: Node *nextarg;
1342: FILE *fp;
1343:
1344: t = (int) a[0];
1345: x = execute(a[1]);
1346: nextarg = a[1]->nnext;
1347: switch (t) {
1348: case FLENGTH:
1349: u = (Awkfloat) strlen(getsval(x)); break;
1350: case FLOG:
1351: u = errcheck(log(getfval(x)), "log"); break;
1352: case FINT:
1353: modf(getfval(x), &u); break;
1354: case FEXP:
1355: u = errcheck(exp(getfval(x)), "exp"); break;
1356: case FSQRT:
1357: u = errcheck(sqrt(getfval(x)), "sqrt"); break;
1358: case FSIN:
1359: u = sin(getfval(x)); break;
1360: case FCOS:
1361: u = cos(getfval(x)); break;
1362: case FATAN:
1363: if (nextarg == 0) {
1364: ERROR "atan2 requires two arguments; returning 1.0" WARNING;
1365: u = 1.0;
1366: } else {
1367: y = execute(a[1]->nnext);
1368: u = atan2(getfval(x), getfval(y));
1369: tempfree(y);
1370: nextarg = nextarg->nnext;
1371: }
1372: break;
1373: case FSYSTEM:
1374: fflush(stdout); /* in case something is buffered already */
1375: u = (Awkfloat) system((char *)getsval(x)) / 256; /* 256 is unix-dep */
1376: break;
1377: case FRAND:
1378: /* in principle, rand() returns something in 0..RAND_MAX */
1379: u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX;
1380: break;
1381: case FSRAND:
1382: if (x->tval & REC) /* no argument provided */
1383: u = time((long *)0);
1384: else
1385: u = getfval(x);
1386: srand((int) u); u = (int) u;
1387: break;
1388: case FTOUPPER:
1389: case FTOLOWER:
1390: strcpy(buf, getsval(x));
1391: if (t == FTOUPPER) {
1392: for (p = buf; *p; p++)
1393: if (islower(*p))
1394: *p = toupper(*p);
1395: } else {
1396: for (p = buf; *p; p++)
1397: if (isupper(*p))
1398: *p = tolower(*p);
1399: }
1400: tempfree(x);
1401: x = gettemp();
1402: setsval(x, buf);
1403: return x;
1404: case FFLUSH:
1405: if ((fp = openfile(GT, getsval(x))) == NULL)
1406: u = EOF;
1407: else
1408: u = fflush(fp);
1409: break;
1410: default: /* can't happen */
1411: ERROR "illegal function type %d", t FATAL;
1412: break;
1413: }
1414: tempfree(x);
1415: x = gettemp();
1416: setfval(x, u);
1417: if (nextarg != 0) {
1418: ERROR "warning: function has too many arguments" WARNING;
1419: for ( ; nextarg; nextarg = nextarg->nnext)
1420: execute(nextarg);
1421: }
1422: return(x);
1423: }
1424:
1425: Cell *printstat(Node **a, int n)
1426: {
1427: register Node *x;
1428: register Cell *y;
1429: FILE *fp;
1430:
1431: if (a[1] == 0)
1432: fp = stdout;
1433: else
1434: fp = redirect((int)a[1], a[2]);
1435: for (x = a[0]; x != NULL; x = x->nnext) {
1436: y = execute(x);
1437: fputs((char *)getsval(y), fp);
1438: tempfree(y);
1439: if (x->nnext == NULL)
1440: fputs((char *)*ORS, fp);
1441: else
1442: fputs((char *)*OFS, fp);
1443: }
1444: if (a[1] != 0)
1445: fflush(fp);
1446: if (ferror(fp))
1447: ERROR "write error on %s", filename(fp) FATAL;
1448: return(true);
1449: }
1450:
1451: Cell *nullproc(Node **a, int n)
1452: {
1453: n;
1454: a;
1455: return 0;
1456: }
1457:
1458:
1459: FILE *redirect(int a, Node *b)
1460: {
1461: FILE *fp;
1462: Cell *x;
1463: uchar *fname;
1464:
1465: x = execute(b);
1466: fname = getsval(x);
1467: fp = openfile(a, fname);
1468: if (fp == NULL)
1469: ERROR "can't open file %s", fname FATAL;
1470: tempfree(x);
1471: return fp;
1472: }
1473:
1474: struct files {
1475: FILE *fp;
1476: uchar *fname;
1477: int mode; /* '|', 'a', 'w' => LE/LT, GT */
1478: } files[FOPEN_MAX] ={
1479: { stdin, "/dev/stdin", LT }, /* watch out: don't free this! */
1480: { stdout, "/dev/stdout", GT },
1481: { stderr, "/dev/stderr", GT }
1482: };
1483:
1484: FILE *openfile(int a, uchar *us)
1485: {
1486: char *s = us;
1487: register int i, m;
1488: register FILE *fp;
1489:
1490: if (*s == '\0')
1491: ERROR "null file name in print or getline" FATAL;
1492: for (i=0; i < FOPEN_MAX; i++)
1493: if (files[i].fname && strcmp(s, files[i].fname) == 0)
1494: if (a == files[i].mode || a==APPEND && files[i].mode==GT)
1495: return files[i].fp;
1496: for (i=0; i < FOPEN_MAX; i++)
1497: if (files[i].fp == 0)
1498: break;
1499: if (i >= FOPEN_MAX)
1500: ERROR "%s makes too many open files", s FATAL;
1501: fflush(stdout); /* force a semblance of order */
1502: m = a;
1503: if (a == GT) {
1504: fp = fopen(s, "w");
1505: } else if (a == APPEND) {
1506: fp = fopen(s, "a");
1507: m = GT; /* so can mix > and >> */
1508: } else if (a == '|') { /* output pipe */
1509: fp = popen(s, "w");
1510: } else if (a == LE) { /* input pipe */
1511: fp = popen(s, "r");
1512: } else if (a == LT) { /* getline <file */
1513: fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */
1514: } else /* can't happen */
1515: ERROR "illegal redirection %d", a FATAL;
1516: if (fp != NULL) {
1517: files[i].fname = tostring(s);
1518: files[i].fp = fp;
1519: files[i].mode = m;
1520: }
1521: return fp;
1522: }
1523:
1524: uchar *filename(FILE *fp)
1525: {
1526: int i;
1527:
1528: for (i = 0; i < FOPEN_MAX; i++)
1529: if (fp == files[i].fp)
1530: return files[i].fname;
1531: return "???";
1532: }
1533:
1534: Cell *closefile(Node **a, int n)
1535: {
1536: register Cell *x;
1537: int i, stat;
1538:
1539: n;
1540: x = execute(a[0]);
1541: getsval(x);
1542: for (i = 0; i < FOPEN_MAX; i++)
1543: if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) {
1544: if (ferror(files[i].fp))
1545: ERROR "i/o error occurred on %s", files[i].fname WARNING;
1546: if (files[i].mode == '|' || files[i].mode == LE)
1547: stat = pclose(files[i].fp);
1548: else
1549: stat = fclose(files[i].fp);
1550: if (stat == EOF)
1551: ERROR "i/o error occurred closing %s", files[i].fname WARNING;
1552: if (i > 2) /* don't do /dev/std... */
1553: xfree(files[i].fname);
1554: files[i].fname = NULL; /* watch out for ref thru this */
1555: files[i].fp = NULL;
1556: }
1557: tempfree(x);
1558: return(true);
1559: }
1560:
1561: void closeall(void)
1562: {
1563: int i, stat;
1564:
1565: for (i = 0; i < FOPEN_MAX; i++)
1566: if (files[i].fp) {
1567: if (ferror(files[i].fp))
1568: ERROR "i/o error occurred on %s", files[i].fname WARNING;
1569: if (files[i].mode == '|' || files[i].mode == LE)
1570: stat = pclose(files[i].fp);
1571: else
1572: stat = fclose(files[i].fp);
1573: if (stat == EOF)
1574: ERROR "i/o error occurred while closing %s", files[i].fname WARNING;
1575: }
1576: }
1577:
1578: #define SUBSIZE (20 * RECSIZE)
1579:
1580: Cell *sub(Node **a, int nnn)
1581: {
1582: register uchar *sptr, *pb, *q;
1583: register Cell *x, *y, *result;
1584: uchar buf[SUBSIZE], *t;
1585: fa *pfa;
1586:
1587: x = execute(a[3]); /* target string */
1588: t = getsval(x);
1589: if (a[0] == 0)
1590: pfa = (fa *) a[1]; /* regular expression */
1591: else {
1592: y = execute(a[1]);
1593: pfa = makedfa(getsval(y), 1);
1594: tempfree(y);
1595: }
1596: y = execute(a[2]); /* replacement string */
1597: result = false;
1598: if (pmatch(pfa, t)) {
1599: pb = buf;
1600: sptr = t;
1601: while (sptr < patbeg)
1602: *pb++ = *sptr++;
1603: sptr = getsval(y);
1604: while (*sptr != 0 && pb < buf + SUBSIZE - 1)
1605: if (*sptr == '\\' && *(sptr+1) == '&') {
1606: sptr++; /* skip \, */
1607: *pb++ = *sptr++; /* add & */
1608: } else if (*sptr == '&') {
1609: sptr++;
1610: for (q = patbeg; q < patbeg+patlen; )
1611: *pb++ = *q++;
1612: } else
1613: *pb++ = *sptr++;
1614: *pb = '\0';
1615: if (pb >= buf + SUBSIZE)
1616: ERROR "sub() result %.50s too big", buf FATAL;
1617: sptr = patbeg + patlen;
1618: if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1)))
1619: while (*pb++ = *sptr++)
1620: ;
1621: if (pb >= buf + SUBSIZE)
1622: ERROR "sub() result %.50s too big", buf FATAL;
1623: setsval(x, buf);
1624: result = true;;
1625: }
1626: tempfree(x);
1627: tempfree(y);
1628: return result;
1629: }
1630:
1631: Cell *gsub(Node **a, int nnn)
1632: {
1633: register Cell *x, *y;
1634: register uchar *rptr, *sptr, *t, *pb;
1635: uchar buf[SUBSIZE];
1636: register fa *pfa;
1637: int mflag, tempstat, num;
1638:
1639: mflag = 0; /* if mflag == 0, can replace empty string */
1640: num = 0;
1641: x = execute(a[3]); /* target string */
1642: t = getsval(x);
1643: if (a[0] == 0)
1644: pfa = (fa *) a[1]; /* regular expression */
1645: else {
1646: y = execute(a[1]);
1647: pfa = makedfa(getsval(y), 1);
1648: tempfree(y);
1649: }
1650: y = execute(a[2]); /* replacement string */
1651: if (pmatch(pfa, t)) {
1652: tempstat = pfa->initstat;
1653: pfa->initstat = 2;
1654: pb = buf;
1655: rptr = getsval(y);
1656: do {
1657: /*
1658: uchar *p;
1659: int i;
1660: printf("target string: %s, *patbeg = %o, patlen = %d\n",
1661: t, *patbeg, patlen);
1662: printf(" match found: ");
1663: p=patbeg;
1664: for (i=0; i<patlen; i++)
1665: printf("%c", *p++);
1666: printf("\n");
1667: */
1668: if (patlen == 0 && *patbeg != 0) { /* matched empty string */
1669: if (mflag == 0) { /* can replace empty */
1670: num++;
1671: sptr = rptr;
1672: while (*sptr != 0 && pb < buf + SUBSIZE-1)
1673: if (*sptr == '\\' && *(sptr+1) == '&') {
1674: sptr++;
1675: *pb++ = *sptr++;
1676: } else if (*sptr == '&') {
1677: uchar *q;
1678: sptr++;
1679: for (q = patbeg; q < patbeg+patlen; )
1680: *pb++ = *q++;
1681: } else
1682: *pb++ = *sptr++;
1683: }
1684: if (*t == 0) /* at end */
1685: goto done;
1686: *pb++ = *t++;
1687: if (pb >= buf + SUBSIZE-1)
1688: ERROR "gsub() result %.50s too big", buf FATAL;
1689: mflag = 0;
1690: }
1691: else { /* matched nonempty string */
1692: num++;
1693: sptr = t;
1694: while (sptr < patbeg && pb < buf + SUBSIZE-1)
1695: *pb++ = *sptr++;
1696: sptr = rptr;
1697: while (*sptr != 0 && pb < buf + SUBSIZE-1)
1698: if (*sptr == '\\' && *(sptr+1) == '&') {
1699: sptr++;
1700: *pb++ = *sptr++;
1701: } else if (*sptr == '&') {
1702: uchar *q;
1703: sptr++;
1704: for (q = patbeg; q < patbeg+patlen; )
1705: *pb++ = *q++;
1706: } else
1707: *pb++ = *sptr++;
1708: t = patbeg + patlen;
1709: if ((*(t-1) == 0) || (*t == 0))
1710: goto done;
1711: if (pb >= buf + SUBSIZE-1)
1712: ERROR "gsub() result %.50s too big", buf FATAL;
1713: mflag = 1;
1714: }
1715: } while (pmatch(pfa,t));
1716: sptr = t;
1717: while (*pb++ = *sptr++)
1718: ;
1719: done: if (pb >= buf + SUBSIZE-1)
1720: ERROR "gsub() result %.50s too big", buf FATAL;
1721: *pb = '\0';
1722: setsval(x, buf);
1723: pfa->initstat = tempstat;
1724: }
1725: tempfree(x);
1726: tempfree(y);
1727: x = gettemp();
1728: x->tval = NUM;
1729: x->fval = num;
1730: return(x);
1731: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.