shithub: patch

ref: c2103276d324781df709f39564f54da596f302d8
dir: /awk-cinapfixes/

View raw version
diff f3ac883d0db6842870cdabd44ed938b92de87d71 uncommitted
--- a/sys/src/cmd/awk/run.c
+++ b/sys/src/cmd/awk/run.c
@@ -218,8 +218,6 @@
 
 #define	NARGS	50	/* max args in a call */
 
-struct Frame *frame = nil;	/* base of stack frames; dynamically allocated */
-int	nframe = 0;		/* number of frames allocated */
 struct Frame *fp = nil;	/* frame pointer. bottom level unused */
 
 Cell *call(Node **a, int)	/* function call.  very kludgy and fragile */
@@ -227,8 +225,9 @@
 	static Cell newcopycell = { OCELL, CCOPY, NUM|STR|DONTFREE, 0, EMPTY, 0.0 };
 	int i, ncall, ndef;
 	Node *x;
-	Cell *args[NARGS], *oargs[NARGS];	/* BUG: fixed size arrays */
+	Cell *args[NARGS], **oargs;
 	Cell *y, *z, *fcn;
+	struct Frame frame, *up;
 	char *s;
 
 	fcn = execute(a[0]);	/* the function itself */
@@ -235,79 +234,66 @@
 	s = fcn->nval;
 	if (!isfcn(fcn))
 		FATAL("calling undefined function %s", s);
-	if (frame == nil) {
-		fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
-		if (frame == nil)
-			FATAL("out of space for stack frames calling %s", s);
-	}
 	for (ncall = 0, x = a[1]; x != nil; x = x->nnext)	/* args in call */
 		ncall++;
 	ndef = (int) fcn->fval;			/* args in defn */
-	   dprint( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) );
-	if (ncall > ndef)
+	   dprint( ("calling %s, %d args (%d in defn)\n", s, ncall, ndef) );
+	if (ncall > ndef){
 		WARNING("function %s called with %d args, uses only %d",
 			s, ncall, ndef);
-	if (ncall + ndef > NARGS)
-		FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS);
-	for (i = 0, x = a[1]; x != nil; i++, x = x->nnext) {	/* get call args */
-		   dprint( ("evaluate args[%d], fp=%d:\n", i, (int) (fp-frame)) );
+		ncall = ndef;
+	}
+	if (ndef+ncall > NARGS)
+		FATAL("function %s has %d arguments, limit %d", s, ndef+ncall, NARGS);
+	oargs = args+ndef;
+	for (i = 0, x = a[1]; i < ncall && x != nil; i++, x = x->nnext) {	/* get call args */
+		   dprint( ("evaluate args[%d]:\n", i) );
 		y = execute(x);
-		oargs[i] = y;
 		   dprint( ("args[%d]: %s %f <%s>, t=%o\n",
 			   i, y->nval, y->fval, isarr(y) ? "(array)" : y->sval, y->tval) );
 		if (isfcn(y))
 			FATAL("can't use function %s as argument in %s", y->nval, s);
-		if (isarr(y))
+		if (isarr(y)) {
 			args[i] = y;	/* arrays by ref */
-		else
+			y = nil;
+		} else if (istemp(y)) {
+			y->csub = CCOPY;
+			args[i] = y;
+		} else
 			args[i] = copycell(y);
-			if (istemp(y))
-				tfree(y);
+		oargs[i] = y;	/* potential output arg for arrays */
 	}
 	for ( ; i < ndef; i++) {	/* add null args for ones not provided */
 		args[i] = gettemp();
 		*args[i] = newcopycell;
 	}
-	fp++;	/* now ok to up frame */
-	if (fp >= frame + nframe) {
-		int dfp = fp - frame;	/* old index */
-		frame = (struct Frame *)
-			realloc((char *) frame, (nframe += 100) * sizeof(struct Frame));
-		if (frame == nil)
-			FATAL("out of space for stack frames in %s", s);
-		fp = frame + dfp;
-	}
+	/* now ok to up frame */
+	up = fp;
+	fp = &frame;
 	fp->fcncell = fcn;
 	fp->args = args;
 	fp->nargs = ndef;	/* number defined with (excess are locals) */
 	fp->retval = gettemp();
 
-	dprint( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) );
+	dprint( ("start exec of %s\n", s) );
 	y = execute((Node *)(fcn->sval));	/* execute body */
-	dprint( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) );
+	dprint( ("finished exec of %s\n", s) );
 
 	for (i = 0; i < ndef; i++) {
-		Cell *t = fp->args[i];
+		Cell *t = args[i];
 		if (isarr(t)) {
 			if (t->csub == CCOPY) {
 				if (i >= ncall) {
 					freesymtab(t);
-					t->csub = CTEMP;
-				if (istemp(t))
 					tfree(t);
-				} else {
+				} else if(oargs[i] != nil) {
 					oargs[i]->tval = t->tval;
 					oargs[i]->tval &= ~(STR|NUM|DONTFREE);
 					oargs[i]->sval = t->sval;
-					if (istemp(t))
-						tfree(t);
 				}
 			}
-		} else if (t != y) {	/* kludge to prevent freeing twice */
-			t->csub = CTEMP;
-			if (istemp(t))
-				tfree(t);
-		}
+		} else if (t != y)	/* kludge to prevent freeing twice */
+			tfree(t);
 	}
 	if (istemp(fcn))
 		tfree(fcn);
@@ -317,7 +303,7 @@
 		tfree(y);		/* this can free twice! */
 	z = fp->retval;			/* return value */
 	   dprint( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );
-	fp--;
+	fp = up;
 	return(z);
 }
 
@@ -328,7 +314,7 @@
 	y = gettemp();
 	y->csub = CCOPY;	/* prevents freeing until call is over */
 	y->nval = x->nval;	/* BUG? */
-	y->sval = x->sval != nil && x->sval != EMPTY ? tostring(x->sval) : EMPTY;
+	y->sval = x->sval != nil && *x->sval ? tostring(x->sval) : EMPTY;
 	y->fval = x->fval;
 	y->tval = x->tval & ~(CON|FLD|REC|DONTFREE);	/* copy is not constant or field */
 	if (y->sval == EMPTY)
@@ -341,7 +327,7 @@
 
 	n = ptoi(a[0]);	/* argument number, counting from 0 */
 	   dprint( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );
-	if (n+1 > fp->nargs)
+	if (n >= fp->nargs)
 		FATAL("argument #%d of function %s was not supplied",
 			n+1, fp->fcncell->nval);
 	return fp->args[n];
--- a/sys/src/cmd/awk/tran.c
+++ b/sys/src/cmd/awk/tran.c
@@ -229,7 +229,7 @@
 		p->sval = (char *) ENVtab;
 		p->tval = ARR;
 	} else {
-		p->sval = s != nil && s != EMPTY ? tostring(s) : EMPTY;
+		p->sval = s && *s ? tostring(s) : EMPTY;
 		p->tval = t;
 		if (p->sval == EMPTY)
 			p->tval |= DONTFREE;
@@ -342,7 +342,7 @@
 		donefld = 0;	/* mark $1... invalid */
 		donerec = 1;
 	}
-	t = s != nil && s != EMPTY ? tostring(s) : EMPTY;	/* in case it's self-assign */
+	t = s && *s ? tostring(s) : EMPTY;	/* in case it's self-assign */
 	vp->tval &= ~NUM;
 	vp->tval |= STR;
 	if (freeable(vp))