shithub: rgbds

Download patch

ref: 30fb6bde5e89504162a8471e674d9a2bdac1e9ad
parent: cc4d455b8a827e03ea73554a6058a7888bf9e736
parent: 4f842a1248be75cc9ca0c23e7a4e1b00e59cc6a5
author: Eldred Habert <eldredhabert0@gmail.com>
date: Wed Nov 25 10:17:34 EST 2020

Merge pull request #615 from ISSOtm/find-sym

Create specialized symbol finder functions

--- a/include/asm/rpn.h
+++ b/include/asm/rpn.h
@@ -46,7 +46,7 @@
 	return expr->isSymbol;
 }
 
-void rpn_Symbol(struct Expression *expr, char *tzSym);
+void rpn_Symbol(struct Expression *expr, char const *tzSym);
 void rpn_Number(struct Expression *expr, uint32_t i);
 void rpn_LOGNOT(struct Expression *expr, const struct Expression *src);
 struct Symbol const *rpn_SymbolOf(struct Expression const *expr);
--- a/include/asm/symbol.h
+++ b/include/asm/symbol.h
@@ -121,7 +121,19 @@
 uint32_t sym_GetPCValue(void);
 uint32_t sym_GetConstantSymValue(struct Symbol const *sym);
 uint32_t sym_GetConstantValue(char const *s);
-struct Symbol *sym_FindSymbol(char const *symName);
+/*
+ * Find a symbol by exact name, bypassing expansion checks
+ */
+struct Symbol *sym_FindExactSymbol(char const *name);
+/*
+ * Find a symbol by exact name; may not be scoped, produces an error if it is
+ */
+struct Symbol *sym_FindUnscopedSymbol(char const *name);
+/*
+ * Find a symbol, possibly scoped, by name
+ */
+struct Symbol *sym_FindScopedSymbol(char const *name);
+struct Symbol const *sym_GetPC(void);
 struct Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char *body, size_t size);
 struct Symbol *sym_Ref(char const *symName);
 struct Symbol *sym_AddString(char const *symName, char const *value);
--- a/src/asm/fstack.c
+++ b/src/asm/fstack.c
@@ -317,7 +317,7 @@
 {
 	dbgPrint("Running macro \"%s\"\n", macroName);
 
-	struct Symbol *macro = sym_FindSymbol(macroName);
+	struct Symbol *macro = sym_FindExactSymbol(macroName);
 
 	if (!macro) {
 		error("Macro \"%s\" not defined\n", macroName);
--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -1311,7 +1311,7 @@
 	}
 	symName[i] = '\0';
 
-	struct Symbol const *sym = sym_FindSymbol(symName);
+	struct Symbol const *sym = sym_FindScopedSymbol(symName);
 
 	if (!sym) {
 		error("Interpolated symbol \"%s\" does not exist\n", symName);
@@ -1691,9 +1691,10 @@
 				if (tokenType != T_ID && tokenType != T_LOCAL_ID)
 					return tokenType;
 
-				if (lexerState->expandStrings) {
+				/* Local symbols cannot be string expansions */
+				if (tokenType == T_ID && lexerState->expandStrings) {
 					/* Attempt string expansion */
-					struct Symbol const *sym = sym_FindSymbol(yylval.tzSym);
+					struct Symbol const *sym = sym_FindExactSymbol(yylval.tzSym);
 
 					if (sym && sym->type == SYM_EQUS) {
 						char const *s = sym_GetStringValue(sym);
--- a/src/asm/output.c
+++ b/src/asm/output.c
@@ -296,6 +296,11 @@
 		uint8_t rpndata = popbyte();
 
 		switch (rpndata) {
+			struct Symbol *sym;
+			uint32_t value;
+			uint8_t b;
+			size_t i;
+
 		case RPN_CONST:
 			writebyte(RPN_CONST);
 			writebyte(popbyte());
@@ -303,13 +308,15 @@
 			writebyte(popbyte());
 			writebyte(popbyte());
 			break;
+
 		case RPN_SYM:
-		{
-			for (unsigned int i = -1; (tzSym[++i] = popbyte()); )
-				;
-			struct Symbol *sym = sym_FindSymbol(tzSym);
-			uint32_t value;
+			i = 0;
+			do {
+				tzSym[i] = popbyte();
+			} while (tzSym[i++]);
 
+			// The symbol name is always written expanded
+			sym = sym_FindExactSymbol(tzSym);
 			if (sym_IsConstant(sym)) {
 				writebyte(RPN_CONST);
 				value = sym_GetConstantValue(tzSym);
@@ -317,19 +324,23 @@
 				writebyte(RPN_SYM);
 				value = getSymbolID(sym);
 			}
+
 			writebyte(value & 0xFF);
 			writebyte(value >> 8);
 			writebyte(value >> 16);
 			writebyte(value >> 24);
 			break;
-		}
+
 		case RPN_BANK_SYM:
-		{
-			for (unsigned int i = -1; (tzSym[++i] = popbyte()); )
-				;
-			struct Symbol *sym = sym_FindSymbol(tzSym);
-			uint32_t value = getSymbolID(sym);
+			i = 0;
+			do {
+				tzSym[i] = popbyte();
+			} while (tzSym[i++]);
 
+			// The symbol name is always written expanded
+			sym = sym_FindExactSymbol(tzSym);
+			value = getSymbolID(sym);
+
 			writebyte(RPN_BANK_SYM);
 			writebyte(value & 0xFF);
 			writebyte(value >> 8);
@@ -336,11 +347,8 @@
 			writebyte(value >> 16);
 			writebyte(value >> 24);
 			break;
-		}
-		case RPN_BANK_SECT:
-		{
-			uint8_t b;
 
+		case RPN_BANK_SECT:
 			writebyte(RPN_BANK_SECT);
 			do {
 				b = popbyte();
@@ -347,7 +355,7 @@
 				writebyte(b);
 			} while (b != 0);
 			break;
-		}
+
 		default:
 			writebyte(rpndata);
 			break;
--- a/src/asm/parser.y
+++ b/src/asm/parser.y
@@ -932,7 +932,7 @@
 		| T_OP_DEF {
 			lexer_ToggleStringExpansion(false);
 		} '(' scoped_id ')' {
-			struct Symbol const *sym = sym_FindSymbol($4);
+			struct Symbol const *sym = sym_FindScopedSymbol($4);
 
 			rpn_Number(&$$, !!sym);
 
--- a/src/asm/rpn.c
+++ b/src/asm/rpn.c
@@ -104,9 +104,9 @@
 	expr->nVal = i;
 }
 
-void rpn_Symbol(struct Expression *expr, char *tzSym)
+void rpn_Symbol(struct Expression *expr, char const *tzSym)
 {
-	struct Symbol *sym = sym_FindSymbol(tzSym);
+	struct Symbol *sym = sym_FindScopedSymbol(tzSym);
 
 	if (sym_IsPC(sym) && !sect_GetSymbolSection()) {
 		error("PC has no value outside a section\n");
@@ -115,15 +115,15 @@
 		rpn_Init(expr);
 		expr->isSymbol = true;
 
-		sym_Ref(tzSym);
 		makeUnknown(expr, sym_IsPC(sym) ? "PC is not constant at assembly time"
 						: "'%s' is not constant at assembly time", tzSym);
+		sym = sym_Ref(tzSym);
 		expr->nRPNPatchSize += 5; /* 1-byte opcode + 4-byte symbol ID */
 
-		size_t nameLen = strlen(tzSym) + 1; /* Don't forget NUL! */
+		size_t nameLen = strlen(sym->name) + 1; /* Don't forget NUL! */
 		uint8_t *ptr = reserveSpace(expr, nameLen + 1);
 		*ptr++ = RPN_SYM;
-		memcpy(ptr, tzSym, nameLen);
+		memcpy(ptr, sym->name, nameLen);
 
 		/* RGBLINK assumes PC is at the byte being computed... */
 		if (sym_IsPC(sym) && nPCOffset) {
@@ -157,7 +157,7 @@
 
 void rpn_BankSymbol(struct Expression *expr, char const *tzSym)
 {
-	struct Symbol const *sym = sym_FindSymbol(tzSym);
+	struct Symbol const *sym = sym_FindScopedSymbol(tzSym);
 
 	/* The @ symbol is treated differently. */
 	if (sym_IsPC(sym)) {
@@ -169,10 +169,8 @@
 	if (sym && !sym_IsLabel(sym)) {
 		error("BANK argument must be a label\n");
 	} else {
-		sym_Ref(tzSym);
-		if (!sym)
-			/* If the symbol didn't exist, `sym_Ref` created it */
-			sym = sym_FindSymbol(tzSym);
+		sym = sym_Ref(tzSym);
+		assert(sym); // If the symbol didn't exist, it should have been created
 
 		if (sym_GetSection(sym) && sym_GetSection(sym)->bank != -1) {
 			/* Symbol's section is known and bank is fixed */
@@ -181,10 +179,10 @@
 			makeUnknown(expr, "\"%s\"'s bank is not known", tzSym);
 			expr->nRPNPatchSize += 5; /* opcode + 4-byte sect ID */
 
-			size_t nameLen = strlen(tzSym) + 1; /* Room for NUL! */
+			size_t nameLen = strlen(sym->name) + 1; /* Room for NUL! */
 			uint8_t *ptr = reserveSpace(expr, nameLen + 1);
 			*ptr++ = RPN_BANK_SYM;
-			memcpy(ptr, tzSym, nameLen);
+			memcpy(ptr, sym->name, nameLen);
 		}
 	}
 }
@@ -298,7 +296,7 @@
 {
 	if (!rpn_isSymbol(expr))
 		return NULL;
-	return sym_FindSymbol((char *)expr->tRPN + 1);
+	return sym_FindScopedSymbol((char *)expr->tRPN + 1);
 }
 
 bool rpn_IsDiffConstant(struct Expression const *src, struct Symbol const *sym)
--- a/src/asm/section.c
+++ b/src/asm/section.c
@@ -620,7 +620,7 @@
 {
 	checkcodesection();
 	reserveSpace(1);
-	struct Symbol const *pc = sym_FindSymbol("@");
+	struct Symbol const *pc = sym_GetPC();
 
 	if (!rpn_IsDiffConstant(expr, pc)) {
 		createPatch(PATCHTYPE_JR, expr);
--- a/src/asm/symbol.c
+++ b/src/asm/symbol.c
@@ -222,32 +222,42 @@
 		fatalerror("Symbol name is too long: '%s%s'\n", scopeName, localName);
 }
 
-/*
- * Find a symbol by name and scope
- */
-static struct Symbol *findsymbol(char const *s, char const *scope)
+struct Symbol *sym_FindExactSymbol(char const *name)
 {
-	char fullname[MAXSYMLEN + 1];
+	return hash_GetElement(symbols, name);
+}
 
-	if (s[0] == '.' && scope) {
-		fullSymbolName(fullname, sizeof(fullname), s, scope);
-		s = fullname;
+struct Symbol *sym_FindUnscopedSymbol(char const *name)
+{
+	if (strchr(name, '.')) {
+		error("Expected non-scoped symbol name, not \"%s\"\n", name);
+		return NULL;
 	}
+	return sym_FindExactSymbol(name);
+}
 
-	char const *separator = strchr(s, '.');
+struct Symbol *sym_FindScopedSymbol(char const *name)
+{
+	char const *dotPtr = strchr(name, '.');
 
-	if (separator && strchr(separator + 1, '.'))
-		fatalerror("'%s' is a nonsensical reference to a nested local symbol\n", s);
+	if (dotPtr) {
+		if (strchr(dotPtr + 1, '.'))
+			fatalerror("'%s' is a nonsensical reference to a nested local symbol\n",
+				   name);
+		/* If auto-scoped local label, expand the name */
+		if (dotPtr == name) { /* Meaning, the name begins with the dot */
+			char fullname[MAXSYMLEN + 1];
 
-	return hash_GetElement(symbols, s);
+			fullSymbolName(fullname, sizeof(fullname), name, labelScope);
+			return sym_FindExactSymbol(fullname);
+		}
+	}
+	return sym_FindExactSymbol(name);
 }
 
-/*
- * Find a symbol by name, with automatically determined scope
- */
-struct Symbol *sym_FindSymbol(char const *symName)
+struct Symbol const *sym_GetPC(void)
 {
-	return findsymbol(symName, symName[0] == '.' ? labelScope : NULL);
+	return PCSymbol;
 }
 
 static inline bool isReferenced(struct Symbol const *sym)
@@ -260,7 +270,7 @@
  */
 void sym_Purge(char const *symName)
 {
-	struct Symbol *symbol = sym_FindSymbol(symName);
+	struct Symbol *symbol = sym_FindScopedSymbol(symName);
 
 	if (!symbol) {
 		error("'%s' not defined\n", symName);
@@ -312,7 +322,7 @@
  */
 uint32_t sym_GetConstantValue(char const *s)
 {
-	struct Symbol const *sym = sym_FindSymbol(s);
+	struct Symbol const *sym = sym_FindScopedSymbol(s);
 
 	if (sym == NULL)
 		error("'%s' not defined\n", s);
@@ -339,11 +349,11 @@
  */
 static struct Symbol *createNonrelocSymbol(char const *symbolName)
 {
-	struct Symbol *symbol = findsymbol(symbolName, NULL);
+	struct Symbol *symbol = sym_FindExactSymbol(symbolName);
 
-	if (!symbol)
+	if (!symbol) {
 		symbol = createsymbol(symbolName);
-	else if (sym_IsDefined(symbol)) {
+	} else if (sym_IsDefined(symbol)) {
 		error("'%s' already defined at ", symbolName);
 		dumpFilename(symbol);
 		putc('\n', stderr);
@@ -400,7 +410,7 @@
  */
 struct Symbol *sym_AddSet(char const *symName, int32_t value)
 {
-	struct Symbol *sym = findsymbol(symName, NULL);
+	struct Symbol *sym = sym_FindExactSymbol(symName);
 
 	if (sym == NULL) {
 		sym = createsymbol(symName);
@@ -411,7 +421,6 @@
 		putc('\n', stderr);
 		return sym;
 	} else {
-		/* TODO: can the scope be incorrect when taking over refs? */
 		updateSymbolFilename(sym);
 	}
 
@@ -429,7 +438,7 @@
 static struct Symbol *addLabel(char const *name)
 {
 	assert(name[0] != '.'); /* The symbol name must have been expanded prior */
-	struct Symbol *sym = findsymbol(name, NULL); /* Due to this, don't look for expansions */
+	struct Symbol *sym = sym_FindExactSymbol(name);
 
 	if (!sym) {
 		sym = createsymbol(name);
@@ -511,7 +520,7 @@
  */
 void sym_Export(char const *symName)
 {
-	struct Symbol *sym = sym_FindSymbol(symName);
+	struct Symbol *sym = sym_FindScopedSymbol(symName);
 
 	/* If the symbol doesn't exist, create a ref that can be purged */
 	if (!sym)
@@ -545,7 +554,7 @@
  */
 struct Symbol *sym_Ref(char const *symName)
 {
-	struct Symbol *nsym = sym_FindSymbol(symName);
+	struct Symbol *nsym = sym_FindScopedSymbol(symName);
 
 	if (nsym == NULL) {
 		char fullname[MAXSYMLEN + 1];