ref: 8bb135cdcb5ce7490ee88512f6f7e65c9e184250
parent: 642cd5f2f3f252cbe54a448c14b84c071729231b
author: qwx <qwx@sciops.net>
date: Mon Nov 3 04:13:01 EST 2025
add awk-cinapfixes: function call and empty string allocation fixes (pending)
--- /dev/null
+++ b/awk-cinapfixes
@@ -1,0 +1,176 @@
+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))
+
--
⑨