ref: fd02ffb7bd6e41d310dd1c6f0652fcee82152437
parent: 62ecdce0b0db976894f88336f1fa7f257a77e950
author: ISSOtm <eldredhabert0@gmail.com>
date: Sun Aug 16 09:33:06 EDT 2020
Implement __FILE__ symbol Also clean up built-in symbol creation This is not great, but currently okay. Should be fixed later, like the rest...
--- a/include/asm/fstack.h
+++ b/include/asm/fstack.h
@@ -58,6 +58,7 @@
void fstk_Dump(void);
char *fstk_DumpToStr(void);
+char const *fstk_GetFileName(void);
uint32_t fstk_GetLine(void);
void fstk_Init(char *mainPath, uint32_t maxRecursionDepth);
--- a/include/asm/symbol.h
+++ b/include/asm/symbol.h
@@ -38,15 +38,20 @@
char fileName[_MAX_PATH + 1]; /* File where the symbol was defined. */
uint32_t fileLine; /* Line where the symbol was defined. */
+ bool hasCallback;
union {
- struct { /* If sym_IsNumeric */
+ union { /* Otherwise */
+ /* If sym_IsNumeric */
int32_t value;
- int32_t (*callback)(void);
+ int32_t (*numCallback)(void);
+ /* For SYM_MACRO */
+ struct {
+ size_t macroSize;
+ char *macro;
+ };
+ /* For SYM_EQUS, TODO: separate "base" fields from SYM_MACRO */
+ char const *(*strCallback)(void); /* For SYM_EQUS */
};
- struct { /* For SYM_MACRO */
- size_t macroSize;
- char *macro;
- };
};
uint32_t ID; /* ID of the symbol in the object file (-1 if none) */
@@ -101,6 +106,8 @@
*/
static inline char const *sym_GetStringValue(struct Symbol const *sym)
{
+ if (sym->hasCallback)
+ return sym->strCallback();
return sym->macro;
}
--- a/src/asm/fstack.c
+++ b/src/asm/fstack.c
@@ -229,8 +229,8 @@
newContext(0);
/* Line minus 1 because buffer begins with a newline */
- contextStack->lexerState = lexer_OpenFileView(macro->macro,
- macro->macroSize, macro->fileLine - 1);
+ contextStack->lexerState = lexer_OpenFileView(macro->macro, macro->macroSize,
+ macro->fileLine - 1);
if (!contextStack->lexerState)
fatalerror("Failed to set up lexer for macro invocation\n");
lexer_SetStateAtEOL(contextStack->lexerState);
@@ -305,6 +305,11 @@
dumpToStream(stream);
fclose(stream);
return str;
+}
+
+char const *fstk_GetFileName(void)
+{
+ return contextStack->fileName;
}
uint32_t fstk_GetLine(void)
--- a/src/asm/symbol.c
+++ b/src/asm/symbol.c
@@ -85,6 +85,45 @@
return lexer_GetLineNo();
}
+static char const *Callback__FILE__(void)
+{
+ /*
+ * FIXME: this is dangerous, and here's why this is CURRENTLY okay. It's still bad, fix it.
+ * There are only two call sites for this; one copies the contents directly, the other is
+ * EQUS expansions, which cannot straddle file boundaries. So this should be fine.
+ */
+ static char *buf = NULL;
+ static size_t bufsize = 0;
+ char const *fileName = fstk_GetFileName();
+ size_t j = 1;
+
+ /* TODO: is there a way for a file name to be empty? */
+ assert(strlen(fileName) != 0);
+ /* The assertion above ensures the loop runs at least once */
+ for (size_t i = 0; fileName[i]; i++, j++) {
+ /* Account for the extra backslash inserted below */
+ if (fileName[i] == '"')
+ j++;
+ /* Ensure there will be enough room; DO NOT PRINT ANYTHING ABOVE THIS!! */
+ if (j + 2 >= bufsize) { /* Always keep room for 2 tail chars */
+ bufsize = bufsize ? bufsize * 2 : 64;
+ buf = realloc(buf, bufsize);
+ if (!buf)
+ fatalerror("Failed to grow buffer for file name: %s\n",
+ strerror(errno));
+ }
+ /* Escape quotes, since we're returning a string */
+ if (fileName[i] == '"')
+ buf[j - 1] = '\\';
+ buf[j] = fileName[i];
+ }
+ /* Write everything after the loop, to ensure everything has been allocated */
+ buf[0] = '"';
+ buf[j++] = '"';
+ buf[j] = '\0';
+ return buf;
+}
+
static int32_t CallbackPC(void)
{
struct Section const *section = sect_GetSymbolSection();
@@ -97,8 +136,8 @@
*/
int32_t sym_GetValue(struct Symbol const *sym)
{
- if (sym_IsNumeric(sym) && sym->callback)
- return sym->callback();
+ if (sym_IsNumeric(sym) && sym->hasCallback)
+ return sym->numCallback();
if (sym->type == SYM_LABEL)
/* TODO: do not use section's org directly */
@@ -113,9 +152,8 @@
static void updateSymbolFilename(struct Symbol *sym)
{
if (snprintf(sym->fileName, _MAX_PATH + 1, "%s",
- lexer_GetFileName()) > _MAX_PATH)
- fatalerror("%s: File name is too long: '%s'\n", __func__,
- lexer_GetFileName());
+ fstk_GetFileName()) > _MAX_PATH)
+ fatalerror("%s: File name is too long: '%s'\n", __func__, fstk_GetFileName());
sym->fileLine = fstk_GetLine();
}
@@ -134,6 +172,7 @@
symbol->isExported = false;
symbol->isBuiltin = false;
+ symbol->hasCallback = false;
symbol->section = NULL;
updateSymbolFilename(symbol);
symbol->ID = -1;
@@ -310,7 +349,6 @@
struct Symbol *sym = createNonrelocSymbol(symName);
sym->type = SYM_EQU;
- sym->callback = NULL;
sym->value = value;
return sym;
@@ -364,7 +402,6 @@
updateSymbolFilename(sym);
sym->type = SYM_SET;
- sym->callback = NULL;
sym->value = value;
return sym;
@@ -375,7 +412,7 @@
* @param name The label's full name (so `.name` is invalid)
* @return The created symbol
*/
-static struct Symbol *addSectionlessLabel(char const *name)
+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 */
@@ -389,7 +426,6 @@
}
/* If the symbol already exists as a ref, just "take over" it */
sym->type = SYM_LABEL;
- sym->callback = NULL;
sym->value = sect_GetSymbolOffset();
if (exportall)
sym->isExported = true;
@@ -396,13 +432,6 @@
sym->section = sect_GetSymbolSection();
updateSymbolFilename(sym);
- return sym;
-}
-
-static struct Symbol *addLabel(char const *name)
-{
- struct Symbol *sym = addSectionlessLabel(name);
-
if (sym && !sym->section)
error("Label \"%s\" created outside of a SECTION\n", name);
return sym;
@@ -538,21 +567,35 @@
return ptr;
}
+static inline struct Symbol *createBuiltinSymbol(char const *name)
+{
+ struct Symbol *sym = createsymbol(name);
+
+ sym->isBuiltin = true;
+ sym->hasCallback = true;
+ strcpy(sym->fileName, "<builtin>");
+ sym->fileLine = 0;
+ return sym;
+}
/*
* Initialize the symboltable
*/
void sym_Init(void)
{
- struct Symbol *_NARGSymbol = sym_AddEqu("_NARG", 0);
- struct Symbol *__LINE__Symbol = sym_AddEqu("__LINE__", 0);
+ PCSymbol = createBuiltinSymbol("@");
+ struct Symbol *_NARGSymbol = createBuiltinSymbol("_NARG");
+ struct Symbol *__LINE__Symbol = createBuiltinSymbol("__LINE__");
+ struct Symbol *__FILE__Symbol = createBuiltinSymbol("__FILE__");
- PCSymbol = addSectionlessLabel("@");
- PCSymbol->isBuiltin = true;
- PCSymbol->callback = CallbackPC;
- _NARGSymbol->isBuiltin = true;
- _NARGSymbol->callback = Callback_NARG;
- __LINE__Symbol->isBuiltin = true;
- __LINE__Symbol->callback = Callback__LINE__;
+ PCSymbol->type = SYM_LABEL;
+ PCSymbol->section = NULL;
+ PCSymbol->numCallback = CallbackPC;
+ _NARGSymbol->type = SYM_EQU;
+ _NARGSymbol->numCallback = Callback_NARG;
+ __LINE__Symbol->type = SYM_EQU;
+ __LINE__Symbol->numCallback = Callback__LINE__;
+ __FILE__Symbol->type = SYM_EQUS;
+ __FILE__Symbol->strCallback = Callback__FILE__;
sym_AddSet("_RS", 0)->isBuiltin = true;
sym_AddEqu("__RGBDS_MAJOR__", PACKAGE_VERSION_MAJOR)->isBuiltin = true;
--- a/test/asm/file-sym.out
+++ b/test/asm/file-sym.out
@@ -1,1 +1,1 @@
-"test/asm/file-sym.asm"
+"file-sym.asm"