shithub: kwa

Download patch

ref: 6d0ade9e0f10517872304e94c2c5d0e3a14c426d
parent: a288969bf6c2d73cb8e77ece798a6009ffb57d99
author: qwx <qwx@sciops.net>
date: Thu Sep 25 16:50:39 EDT 2025

allow a string value to be unset, use common constant

sval should never be nil.

--- a/awk.h
+++ b/awk.h
@@ -42,6 +42,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/lex.c
+++ b/lex.c
@@ -285,7 +285,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);
@@ -446,7 +446,7 @@
 				SYNTAX( "return not in function" );
 			RET(kp->type);
 		case VARNF:
-			yylval.cp = setsymtab("NF", "", 0.0, NUM, symtab);
+			yylval.cp = setsymtab("NF", EMPTY, 0.0, NUM, symtab);
 			RET(VARNF);
 		default:
 			RET(kp->type);
@@ -457,7 +457,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/lib.c
+++ b/lib.c
@@ -6,7 +6,7 @@
 #include "y.tab.h"
 
 Biobuf	*infile;
-char	*file	= "";
+char	*file	= EMPTY;
 char	*record;
 int	recsize	= RECSIZE;
 char	*fields;
@@ -25,8 +25,8 @@
 int	argno	= 1;	/* current input argument number */
 extern	Awkfloat *AARGC;
 
-static Cell dollar0 = { OCELL, CFLD, nil, "", 0.0, REC|STR|DONTFREE };
-static Cell dollar1 = { OCELL, CFLD, nil, "", 0.0, FLD|STR|DONTFREE };
+static Cell dollar0 = { OCELL, CFLD, nil, EMPTY, 0.0, REC|STR|DONTFREE };
+static Cell dollar1 = { OCELL, CFLD, nil, EMPTY, 0.0, FLD|STR|DONTFREE };
 
 void recinit(unsigned int n)
 {
@@ -194,7 +194,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;
@@ -322,7 +322,7 @@
 		p = fldtab[i];
 		if (freeable(p))
 			xfree(p->sval);
-		p->sval = "";
+		p->sval = EMPTY;
 		p->tval = FLD | STR | DONTFREE;
 	}
 }
--- a/parse.c
+++ b/parse.c
@@ -166,7 +166,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/run.c
+++ b/run.c
@@ -28,7 +28,7 @@
 Cell	*jexit	= &exitcell;
 static Cell	retcell		={ OJUMP, JRET, 0, 0, 0.0, NUM };
 Cell	*jret	= &retcell;
-static Cell	tempcell	={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE };
+static Cell	tempcell	={ OCELL, CTEMP, 0, EMPTY, 0.0, NUM|STR|DONTFREE };
 
 Node	*curnode = nil;	/* the node being executed, for debugging */
 
@@ -200,7 +200,7 @@
 
 Cell *call(Node **a, int)	/* function call.  very kludgy and fragile */
 {
-	static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE };
+	static Cell newcopycell = { OCELL, CCOPY, 0, EMPTY, 0.0, NUM|STR|DONTFREE };
 	int i, ncall, ndef;
 	Node *x;
 	Cell *args[NARGS], *oargs[NARGS];	/* BUG: fixed size arrays */
@@ -304,10 +304,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;
 }
 
@@ -466,7 +467,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))
@@ -747,7 +748,7 @@
 				tfree(z);
 		}
 		x = gettemp();
-		setsval(x, "");
+		setsval(x, EMPTY);
 		return(x);
 	}
 	m = (int) getfval(y);
@@ -1289,7 +1290,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/tran.c
+++ b/tran.c
@@ -8,6 +8,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 */
@@ -44,7 +46,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;
@@ -53,19 +55,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;
 }
 
@@ -76,8 +78,8 @@
 	char temp[50];
 	Awkfloat f;
 
-	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++) {
@@ -205,8 +207,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;
@@ -316,12 +320,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);
 }
--