git: 9front

Download patch

ref: fdb503349c9e8007902b26211170cdc8dfa745af
parent: 767cceeba3e9dfc47c1633f98f2de833cc12582a
author: qwx <qwx@sciops.net>
date: Sun Oct 26 20:06:15 EDT 2025

awk: use constant for empty strings

avoids useless strdups and cleans up using DONTFREE.
use nfloc instead of looking up NF, which was already
preallocated during initialization.

--- a/sys/src/cmd/awk/awk.h
+++ b/sys/src/cmd/awk/awk.h
@@ -48,6 +48,8 @@
 extern int	donerec;	/* 1 if record is valid (no fld has changed */
 extern char	inputFS[];	/* FS at time of input, for field splitting */
 
+extern char	EMPTY[];
+
 extern int	dbg;
 
 extern	char	*patbeg;	/* beginning of pattern matched */
--- a/sys/src/cmd/awk/lex.c
+++ b/sys/src/cmd/awk/lex.c
@@ -306,7 +306,7 @@
 					unputstr("(NF)");
 					RET(INDIRECT);
 				}
-				yylval.cp = setsymtab(buf, "", 0.0, STR|NUM, symtab);
+				yylval.cp = setsymtab(buf, EMPTY, 0.0, STR|NUM, symtab);
 				RET(IVAR);
 			} else {
 				unputstr(buf);
@@ -467,7 +467,7 @@
 				SYNTAX( "return not in function" );
 			RET(kp->type);
 		case VARNF:
-			yylval.cp = setsymtab("NF", "", 0.0, NUM, symtab);
+			yylval.cp = nfloc;
 			RET(VARNF);
 		default:
 			RET(kp->type);
@@ -478,7 +478,7 @@
 		yylval.i = n;
 		RET(ARG);
 	} else {
-		yylval.cp = setsymtab(w, "", 0.0, STR|NUM|DONTFREE, symtab);
+		yylval.cp = setsymtab(w, EMPTY, 0.0, STR|NUM|DONTFREE, symtab);
 		if (c == '(') {
 			RET(CALL);
 		} else {
--- a/sys/src/cmd/awk/lib.c
+++ b/sys/src/cmd/awk/lib.c
@@ -30,7 +30,7 @@
 #include "y.tab.h"
 
 Biobuf	*infile;
-char	*file	= "";
+char	*file	= EMPTY;
 char	*record;
 int	recsize	= RECSIZE;
 char	*fields;
@@ -49,8 +49,8 @@
 int	argno	= 1;	/* current input argument number */
 extern	Awkfloat *AARGC;
 
-static Cell dollar0 = { OCELL, CFLD, REC|STR|DONTFREE, nil, "", 0.0 };
-static Cell dollar1 = { OCELL, CFLD, FLD|STR|DONTFREE, nil, "", 0.0 };
+static Cell dollar0 = { OCELL, CFLD, REC|STR|DONTFREE, nil, EMPTY, 0.0 };
+static Cell dollar1 = { OCELL, CFLD, FLD|STR|DONTFREE, nil, EMPTY, 0.0 };
 
 void recinit(unsigned int n)
 {
@@ -220,7 +220,7 @@
 	extern Array *ARGVtab;
 
 	sprint(temp, "%d", n);
-	x = setsymtab(temp, "", 0.0, STR, ARGVtab);
+	x = setsymtab(temp, EMPTY, 0.0, STR, ARGVtab);
 	s = getsval(x);
 	dprint( ("getargv(%d) returns |%s|\n", n, s) );
 	return s;
@@ -352,7 +352,7 @@
 		p = fldtab[i];
 		if (freeable(p))
 			xfree(p->sval);
-		p->sval = "";
+		p->sval = EMPTY;
 		p->tval = FLD | STR | DONTFREE;
 	}
 }
--- a/sys/src/cmd/awk/parse.c
+++ b/sys/src/cmd/awk/parse.c
@@ -190,7 +190,8 @@
 		if (isfcn(cp))
 			SYNTAX( "%s is a function, not an array", cp->nval );
 		else if (!isarr(cp)) {
-			xfree(cp->sval);
+			if (freeable(cp))
+				xfree(cp->sval);
 			cp->sval = (char *) makesymtab(NSYMTAB);
 			cp->tval = ARR;
 		}
--- a/sys/src/cmd/awk/run.c
+++ b/sys/src/cmd/awk/run.c
@@ -52,7 +52,7 @@
 Cell	*jexit	= &exitcell;
 static Cell	retcell		={ OJUMP, JRET, NUM, 0, 0, 0.0 };
 Cell	*jret	= &retcell;
-static Cell	tempcell	={ OCELL, CTEMP, NUM|STR|DONTFREE, 0, "", 0.0 };
+static Cell	tempcell	={ OCELL, CTEMP, NUM|STR|DONTFREE, 0, EMPTY, 0.0 };
 
 Node	*curnode = nil;	/* the node being executed, for debugging */
 
@@ -224,7 +224,7 @@
 
 Cell *call(Node **a, int)	/* function call.  very kludgy and fragile */
 {
-	static Cell newcopycell = { OCELL, CCOPY, NUM|STR|DONTFREE, 0, "", 0.0 };
+	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 */
@@ -328,10 +328,11 @@
 	y = gettemp();
 	y->csub = CCOPY;	/* prevents freeing until call is over */
 	y->nval = x->nval;	/* BUG? */
-	y->sval = x->sval ? tostring(x->sval) : nil;
+	y->sval = x->sval != nil && x->sval != EMPTY ? tostring(x->sval) : EMPTY;
 	y->fval = x->fval;
 	y->tval = x->tval & ~(CON|FLD|REC|DONTFREE);	/* copy is not constant or field */
-							/* is DONTFREE right? */
+	if (y->sval == EMPTY)
+		y->tval |= DONTFREE;
 	return y;
 }
 
@@ -354,7 +355,7 @@
 	case EXIT:
 		if (a[0] != nil) {
 			y = execute(a[0]);
-			if((y->tval & (NUM|STR)) == STR) {
+			if ((y->tval & (NUM|STR)) == STR) {
 				exitstatus = getsval(y);
 			} else if((int) getfval(y) != 0) {
 				exitstatus = "error";
@@ -492,7 +493,7 @@
 		x->tval |= ARR;
 		x->sval = (char *) makesymtab(NSYMTAB);
 	}
-	z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
+	z = setsymtab(buf, EMPTY, 0.0, STR|NUM, (Array *) x->sval);
 	z->ctype = OCELL;
 	z->csub = CVAR;
 	if (istemp(x))
@@ -771,7 +772,7 @@
 				tfree(z);
 		}
 		x = gettemp();
-		setsval(x, "");
+		setsval(x, EMPTY);
 		return(x);
 	}
 	m = (int) getfval(y);
@@ -1312,7 +1313,7 @@
 				if (t[-1] == 0 || *t == 0) {
 					n++;
 					sprint(num, "%d", n);
-					setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
+					setsymtab(num, EMPTY, 0.0, STR, (Array *) ap->sval);
 					goto spdone;
 				}
 			} while (nematch(p,s,t));
--- a/sys/src/cmd/awk/tran.c
+++ b/sys/src/cmd/awk/tran.c
@@ -32,6 +32,8 @@
 #define	FULLTAB	2	/* rehash when table gets this x full */
 #define	GROWTAB 4	/* grow table by this factor */
 
+char	EMPTY[] = {'\0'};
+
 Array	*symtab;	/* main symbol table */
 
 char	**FS;		/* initial field sep */
@@ -68,7 +70,7 @@
 {
 	literal0 = setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab);
 	/* this is used for if(x)... tests: */
-	nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab);
+	nullloc = setsymtab("$zero&null", EMPTY, 0.0, NUM|STR|CON|DONTFREE, symtab);
 	nullnode = celltonode(nullloc, CCON);
 
 	FS = &setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab)->sval;
@@ -77,19 +79,19 @@
 	ORS = &setsymtab("ORS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
 	OFMT = &setsymtab("OFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
 	CONVFMT = &setsymtab("CONVFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
-	FILENAME = &setsymtab("FILENAME", "", 0.0, STR|DONTFREE, symtab)->sval;
-	nfloc = setsymtab("NF", "", 0.0, NUM, symtab);
+	FILENAME = &setsymtab("FILENAME", EMPTY, 0.0, STR|DONTFREE, symtab)->sval;
+	nfloc = setsymtab("NF", EMPTY, 0.0, NUM, symtab);
 	NF = &nfloc->fval;
-	nrloc = setsymtab("NR", "", 0.0, NUM, symtab);
+	nrloc = setsymtab("NR", EMPTY, 0.0, NUM, symtab);
 	NR = &nrloc->fval;
-	fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab);
+	fnrloc = setsymtab("FNR", EMPTY, 0.0, NUM, symtab);
 	FNR = &fnrloc->fval;
 	SUBSEP = &setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab)->sval;
-	rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab);
+	rstartloc = setsymtab("RSTART", EMPTY, 0.0, NUM, symtab);
 	RSTART = &rstartloc->fval;
-	rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab);
+	rlengthloc = setsymtab("RLENGTH", EMPTY, 0.0, NUM, symtab);
 	RLENGTH = &rlengthloc->fval;
-	symtabloc = setsymtab("SYMTAB", "", 0.0, ARR, symtab);
+	symtabloc = setsymtab("SYMTAB", EMPTY, 0.0, ARR, symtab);
 	symtabloc->sval = (char *) symtab;
 }
 
@@ -99,8 +101,8 @@
 	int i;
 	char temp[50];
 
-	AARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval;
-	cp = setsymtab("ARGV", "", 0.0, ARR, symtab);
+	AARGC = &setsymtab("ARGC", EMPTY, (Awkfloat) ac, NUM, symtab)->fval;
+	cp = setsymtab("ARGV", EMPTY, 0.0, ARR, symtab);
 	ARGVtab = makesymtab(NSYMTAB);	/* could be (int) ARGC as well */
 	cp->sval = (char *) ARGVtab;
 	for (i = 0; i < ac; i++) {
@@ -227,8 +229,10 @@
 		p->sval = (char *) ENVtab;
 		p->tval = ARR;
 	} else {
-		p->sval = s ? tostring(s) : tostring("");
+		p->sval = s != nil && s != EMPTY ? tostring(s) : EMPTY;
 		p->tval = t;
+		if (p->sval == EMPTY)
+			p->tval |= DONTFREE;
 	}
 	p->csub = CUNK;
 	p->ctype = OCELL;
@@ -338,12 +342,15 @@
 		donefld = 0;	/* mark $1... invalid */
 		donerec = 1;
 	}
-	t = tostring(s);	/* in case it's self-assign */
+	t = s != nil && s != EMPTY ? tostring(s) : EMPTY;	/* in case it's self-assign */
 	vp->tval &= ~NUM;
 	vp->tval |= STR;
 	if (freeable(vp))
 		xfree(vp->sval);
-	vp->tval &= ~DONTFREE;
+	if (t != EMPTY)
+		vp->tval &= ~DONTFREE;
+	else
+		vp->tval |= DONTFREE;
 	   dprint( ("setsval %p: %s = \"%s (%p)\", t=%o\n", vp, vp->nval, t,t, vp->tval) );
 	return(vp->sval = t);
 }
--