From c0d534f5ad00683d9c08196192baff13c26fc45f Mon Sep 17 00:00:00 2001 From: Sylvie <35663410+Rangi42@users.noreply.github.com> Date: Thu, 22 Feb 2024 16:22:37 -0500 Subject: [PATCH] No more flexible array members (not standard C++) (#1307) * Replace FAMs with `std::vector`s (or one `std::string`) in four `struct`s * Anonymous types declared in an anonymous union are also non-standard Only Clang complains about this (-Wnested-anon-types) --- include/asm/fstack.hpp | 7 +-- include/asm/macro.hpp | 2 +- include/asm/symbol.hpp | 20 +++---- include/link/main.hpp | 11 ++-- src/asm/charmap.cpp | 59 +++++++------------ src/asm/fstack.cpp | 130 +++++++++++++++++++---------------------- src/asm/lexer.cpp | 28 +++++---- src/asm/macro.cpp | 79 ++++++++++--------------- src/asm/output.cpp | 8 +-- src/asm/parser.y | 17 ++++-- src/link/sdas_obj.cpp | 2 +- test/asm/unique-id.asm | 10 ++-- 12 files changed, 170 insertions(+), 203 deletions(-) diff --git a/include/asm/fstack.hpp b/include/asm/fstack.hpp index 342664d7..efb8b253 100644 --- a/include/asm/fstack.hpp +++ b/include/asm/fstack.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "asm/lexer.hpp" @@ -28,14 +29,12 @@ struct FileStackNode { struct FileStackReptNode { // NODE_REPT struct FileStackNode node; - uint32_t reptDepth; - // WARNING: if changing this type, change overflow check in `fstk_Init` - uint32_t iters[]; // REPT iteration counts since last named node, in reverse depth order + std::vector *iters; // REPT iteration counts since last named node, in reverse depth order }; struct FileStackNamedNode { // NODE_FILE, NODE_MACRO struct FileStackNode node; - char name[]; // File name for files, file::macro name for macros + std::string *name; // File name for files, file::macro name for macros }; #define DEFAULT_MAX_DEPTH 64 diff --git a/include/asm/macro.hpp b/include/asm/macro.hpp index bed0aad9..7e2247b2 100644 --- a/include/asm/macro.hpp +++ b/include/asm/macro.hpp @@ -15,7 +15,7 @@ struct MacroArgs; struct MacroArgs *macro_GetCurrentArgs(void); struct MacroArgs *macro_NewArgs(void); -void macro_AppendArg(struct MacroArgs **args, char *s); +void macro_AppendArg(struct MacroArgs *args, char *s); void macro_UseNewArgs(struct MacroArgs *args); void macro_FreeArgs(struct MacroArgs *args); char const *macro_GetArg(uint32_t i); diff --git a/include/asm/symbol.hpp b/include/asm/symbol.hpp index 5e2b8a4a..8ea1073f 100644 --- a/include/asm/symbol.hpp +++ b/include/asm/symbol.hpp @@ -23,6 +23,12 @@ enum SymbolType { SYM_REF // Forward reference to a label }; +// Only used in an anonymous union by `struct Symbol` +struct strValue { + size_t size; + char *value; +}; + struct Symbol { char name[MAXSYMLEN + 1]; enum SymbolType type; @@ -36,18 +42,12 @@ struct Symbol { union { // If sym_IsNumeric int32_t value; - int32_t (*numCallback)(void); + int32_t (*numCallback)(void); // If hasCallback // For SYM_MACRO - struct { - size_t size; - char *value; - } macro; + struct strValue macro; // For SYM_EQUS - struct { - size_t size; - char *value; - } equs; - char const *(*strCallback)(void); + struct strValue equs; + char const *(*strCallback)(void); // If hasCallback }; uint32_t ID; // ID of the symbol in the object file (-1 if none) diff --git a/include/link/main.hpp b/include/link/main.hpp index a9b9b844..5cefb68a 100644 --- a/include/link/main.hpp +++ b/include/link/main.hpp @@ -28,6 +28,12 @@ extern bool beVerbose; extern bool isWRA0Mode; extern bool disablePadding; +// Only used in an anonymous union by `struct FileStackNode` +struct reptNodeData { + uint32_t depth; + uint32_t *iters; +}; + struct FileStackNode { struct FileStackNode *parent; // Line at which the parent context was exited; meaningless for the root level @@ -36,10 +42,7 @@ struct FileStackNode { enum FileStackNodeType type; union { char *name; // NODE_FILE, NODE_MACRO - struct { // NODE_REPT - uint32_t depth; - uint32_t *iters; - } rept; + struct reptNodeData rept; // NODE_REPT }; }; diff --git a/src/asm/charmap.cpp b/src/asm/charmap.cpp index e3cff375..7a049168 100644 --- a/src/asm/charmap.cpp +++ b/src/asm/charmap.cpp @@ -1,11 +1,13 @@ /* SPDX-License-Identifier: MIT */ #include +#include #include #include #include #include #include +#include #include "asm/charmap.hpp" #include "asm/main.hpp" @@ -25,13 +27,9 @@ struct Charnode { size_t next[255]; // Indexes of where to go next, 0 = nowhere }; -#define INITIAL_CAPACITY 32 - struct Charmap { char *name; - size_t usedNodes; // How many nodes are being used - size_t capacity; // How many nodes have been allocated - struct Charnode nodes[]; // first node is reserved for the root node + std::vector *nodes; // first node is reserved for the root node }; static HashMap charmaps; @@ -52,16 +50,6 @@ static struct Charmap *charmap_Get(char const *name) return (struct Charmap *)hash_GetElement(charmaps, name); } -static void resizeCharmap(struct Charmap **map, size_t capacity) -{ - *map = (struct Charmap *)realloc(*map, sizeof(**map) + sizeof(*(*map)->nodes) * capacity); - - if (!*map) - fatalerror("Failed to %s charmap: %s\n", - *map ? "create" : "resize", strerror(errno)); - (**map).capacity = capacity; -} - static void initNode(struct Charnode *node) { node->isTerminal = false; @@ -87,15 +75,17 @@ struct Charmap *charmap_New(char const *name, char const *baseName) } // Init the new charmap's fields - if (base) { - resizeCharmap(&charmap, base->capacity); - charmap->usedNodes = base->usedNodes; + charmap = (struct Charmap *)malloc(sizeof(*charmap)); + if (charmap) + charmap->nodes = new(std::nothrow) std::vector(); + if (!charmap || !charmap->nodes) + fatalerror("Failed to create charmap: %s\n", strerror(errno)); - memcpy(charmap->nodes, base->nodes, sizeof(base->nodes[0]) * charmap->usedNodes); + if (base) { + *charmap->nodes = *base->nodes; // Copies `base->nodes` } else { - resizeCharmap(&charmap, INITIAL_CAPACITY); - charmap->usedNodes = 1; - initNode(&charmap->nodes[0]); // Init the root node + charmap->nodes->emplace_back(); + initNode(&charmap->nodes->back()); // Init the root node } charmap->name = strdup(name); @@ -109,6 +99,7 @@ static void freeCharmap(void *_charmap, void *) struct Charmap *charmap = (struct Charmap *)_charmap; free(charmap->name); + delete charmap->nodes; free(charmap); } @@ -157,25 +148,19 @@ void charmap_Pop(void) void charmap_Add(char *mapping, uint8_t value) { struct Charmap *charmap = *currentCharmap; - struct Charnode *node = &charmap->nodes[0]; + struct Charnode *node = &charmap->nodes->front(); for (uint8_t c; *mapping; mapping++) { c = *mapping - 1; if (node->next[c]) { - node = &charmap->nodes[node->next[c]]; + node = &(*charmap->nodes)[node->next[c]]; } else { // Register next available node - node->next[c] = charmap->usedNodes; - // If no more nodes are available, get new ones - if (charmap->usedNodes == charmap->capacity) { - charmap->capacity *= 2; - resizeCharmap(currentCharmap, charmap->capacity); - charmap = *currentCharmap; - } + node->next[c] = charmap->nodes->size(); // Switch to and init new node - node = &charmap->nodes[charmap->usedNodes++]; + node = &charmap->nodes->emplace_back(); initNode(node); } } @@ -190,14 +175,14 @@ void charmap_Add(char *mapping, uint8_t value) bool charmap_HasChar(char const *input) { struct Charmap const *charmap = *currentCharmap; - struct Charnode const *node = &charmap->nodes[0]; + struct Charnode const *node = &charmap->nodes->front(); for (; *input; input++) { size_t next = node->next[(uint8_t)*input - 1]; if (!next) return false; - node = &charmap->nodes[next]; + node = &(*charmap->nodes)[next]; } return node->isTerminal; @@ -220,7 +205,7 @@ size_t charmap_ConvertNext(char const **input, uint8_t **output) // If that would lead to a dead end, rewind characters until the last match, and output. // If no match, read a UTF-8 codepoint and output that. struct Charmap const *charmap = *currentCharmap; - struct Charnode const *node = &charmap->nodes[0]; + struct Charnode const *node = &charmap->nodes->front(); struct Charnode const *match = NULL; size_t rewindDistance = 0; @@ -233,7 +218,7 @@ size_t charmap_ConvertNext(char const **input, uint8_t **output) rewindDistance++; // Advance to next node (index starts at 1) - node = &charmap->nodes[node->next[c]]; + node = &(*charmap->nodes)[node->next[c]]; if (node->isTerminal) { // This node matches, register it match = node; @@ -265,7 +250,7 @@ size_t charmap_ConvertNext(char const **input, uint8_t **output) *output += codepointLen; // Warn if this character is not mapped but any others are - if (charmap->usedNodes > 1) + if (charmap->nodes->size() > 1) warning(WARNING_UNMAPPED_CHAR_1, "Unmapped character %s\n", printChar(firstChar)); else if (strcmp(charmap->name, DEFAULT_CHARMAP_NAME)) diff --git a/src/asm/fstack.cpp b/src/asm/fstack.cpp index 979dea2e..f9ee636b 100644 --- a/src/asm/fstack.cpp +++ b/src/asm/fstack.cpp @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: MIT */ #include +#include #include #include #include @@ -9,6 +10,7 @@ #include #include #include +#include #include "asm/fstack.hpp" #include "asm/macro.hpp" @@ -51,10 +53,10 @@ static const char *dumpNodeAndParents(struct FileStackNode const *node) name = dumpNodeAndParents(node->parent); fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, name); - for (uint32_t i = reptInfo->reptDepth; i--; ) - fprintf(stderr, "::REPT~%" PRIu32, reptInfo->iters[i]); + for (uint32_t i = reptInfo->iters->size(); i--; ) + fprintf(stderr, "::REPT~%" PRIu32, (*reptInfo->iters)[i]); } else { - name = ((struct FileStackNamedNode const *)node)->name; + name = ((struct FileStackNamedNode const *)node)->name->c_str(); if (node->parent) { dumpNodeAndParents(node->parent); fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, name); @@ -103,7 +105,7 @@ char const *fstk_GetFileName(void) while (node->type != NODE_FILE) node = node->parent; - return ((struct FileStackNamedNode const *)node)->name; + return ((struct FileStackNamedNode const *)node)->name->c_str(); } void fstk_AddIncludePath(char const *path) @@ -199,13 +201,16 @@ bool yywrap(void) // If the node is referenced, we can't edit it; duplicate it if (contextStack->fileInfo->referenced) { - size_t size = sizeof(*fileInfo) + sizeof(fileInfo->iters[0]) * fileInfo->reptDepth; - struct FileStackReptNode *copy = (struct FileStackReptNode *)malloc(size); + struct FileStackReptNode *copy = (struct FileStackReptNode *)malloc(sizeof(*copy)); - if (!copy) - fatalerror("Failed to duplicate REPT file node: %s\n", strerror(errno)); // Copy all info but the referencing - memcpy(copy, fileInfo, size); + if (copy) { + memcpy(copy, fileInfo, sizeof(*copy)); + copy->iters = new(std::nothrow) std::vector(); + } + if (!copy || !copy->iters) + fatalerror("Failed to duplicate REPT file node: %s\n", strerror(errno)); + *copy->iters = *fileInfo->iters; // Copies `fileInfo->iters` copy->node.next = NULL; copy->node.referenced = false; @@ -214,7 +219,7 @@ bool yywrap(void) } // If this is a FOR, update the symbol value - if (contextStack->forName && fileInfo->iters[0] <= contextStack->nbReptIters) { + if (contextStack->forName && fileInfo->iters->front() <= contextStack->nbReptIters) { // Avoid arithmetic overflow runtime error uint32_t forValue = (uint32_t)contextStack->forValue + (uint32_t)contextStack->forStep; @@ -228,9 +233,9 @@ bool yywrap(void) fatalerror("Failed to update FOR symbol value\n"); } // Advance to the next iteration - fileInfo->iters[0]++; + fileInfo->iters->front()++; // If this wasn't the last iteration, wrap instead of popping - if (fileInfo->iters[0] <= contextStack->nbReptIters) { + if (fileInfo->iters->front() <= contextStack->nbReptIters) { lexer_RestartRept(contextStack->fileInfo->lineNo); contextStack->uniqueID = macro_UseNewUniqueID(); return false; @@ -252,8 +257,13 @@ bool yywrap(void) macro_UseNewArgs(contextStack->macroArgs); } // Free the file stack node - if (!context->fileInfo->referenced) + if (!context->fileInfo->referenced) { + if (context->fileInfo->type == NODE_REPT) + delete ((struct FileStackReptNode *)context->fileInfo)->iters; + else + delete ((struct FileStackNamedNode *)context->fileInfo)->name; free(context->fileInfo); + } // Free the FOR symbol name free(context->forName); // Free the entry and make its parent the current entry @@ -309,19 +319,17 @@ void fstk_RunInclude(char const *path) return; } - struct FileStackNamedNode *fileInfo = - (struct FileStackNamedNode *)malloc(sizeof(*fileInfo) + fullPath->length() + 1); + struct FileStackNamedNode *fileInfo = (struct FileStackNamedNode *)malloc(sizeof(*fileInfo)); if (!fileInfo) { error("Failed to alloc file info for INCLUDE: %s\n", strerror(errno)); return; } fileInfo->node.type = NODE_FILE; - strcpy(fileInfo->name, fullPath->c_str()); - delete fullPath; + fileInfo->name = fullPath; // `fullPath` is already `new`-allocated, so just point to it newContext((struct FileStackNode *)fileInfo); - contextStack->lexerState = lexer_OpenFile(fileInfo->name); + contextStack->lexerState = lexer_OpenFile(fileInfo->name->c_str()); if (!contextStack->lexerState) fatalerror("Failed to set up lexer for file include\n"); lexer_SetStateAtEOL(contextStack->lexerState); @@ -345,19 +353,17 @@ static void runPreIncludeFile(void) return; } - struct FileStackNamedNode *fileInfo = - (struct FileStackNamedNode *)malloc(sizeof(*fileInfo) + fullPath->length() + 1); + struct FileStackNamedNode *fileInfo = (struct FileStackNamedNode *)malloc(sizeof(*fileInfo)); if (!fileInfo) { error("Failed to alloc file info for pre-include: %s\n", strerror(errno)); return; } fileInfo->node.type = NODE_FILE; - strcpy(fileInfo->name, fullPath->c_str()); - delete fullPath; + fileInfo->name = fullPath; // `fullPath` is already `new`-allocated, so just point to it newContext((struct FileStackNode *)fileInfo); - contextStack->lexerState = lexer_OpenFile(fileInfo->name); + contextStack->lexerState = lexer_OpenFile(fileInfo->name->c_str()); if (!contextStack->lexerState) fatalerror("Failed to set up lexer for file include\n"); lexer_SetState(contextStack->lexerState); @@ -387,43 +393,41 @@ void fstk_RunMacro(char const *macroName, struct MacroArgs *args) struct FileStackReptNode const *reptNode = (struct FileStackReptNode const *)node; // 4294967295 = 2^32 - 1, aka UINT32_MAX - reptNameLen += reptNode->reptDepth * strlen("::REPT~4294967295"); + reptNameLen += reptNode->iters->size() * strlen("::REPT~4294967295"); // Look for next named node do { node = node->parent; } while (node->type == NODE_REPT); } - struct FileStackNamedNode const *baseNode = (struct FileStackNamedNode const *)node; - size_t baseLen = strlen(baseNode->name); - size_t macroNameLen = strlen(macro->name); - struct FileStackNamedNode *fileInfo = (struct FileStackNamedNode *)malloc(sizeof(*fileInfo) + - baseLen + reptNameLen + 2 + macroNameLen + 1); - if (!fileInfo) { + struct FileStackNamedNode const *baseNode = (struct FileStackNamedNode const *)node; + struct FileStackNamedNode *fileInfo = (struct FileStackNamedNode *)malloc(sizeof(*fileInfo)); + + if (fileInfo) + fileInfo->name = new(std::nothrow) std::string(); + if (!fileInfo || !fileInfo->name) { error("Failed to alloc file info for \"%s\": %s\n", macro->name, strerror(errno)); return; } fileInfo->node.type = NODE_MACRO; - // Print the name... - char *dest = fileInfo->name; - memcpy(dest, baseNode->name, baseLen); - dest += baseLen; + // Print the name... + fileInfo->name->reserve(baseNode->name->length() + reptNameLen + 2 + strlen(macro->name)); + fileInfo->name->append(*baseNode->name); if (node->type == NODE_REPT) { struct FileStackReptNode const *reptNode = (struct FileStackReptNode const *)node; - for (uint32_t i = reptNode->reptDepth; i--; ) { - int nbChars = sprintf(dest, "::REPT~%" PRIu32, reptNode->iters[i]); + for (uint32_t i = reptNode->iters->size(); i--; ) { + char buf[sizeof("::REPT~4294967295")]; // UINT32_MAX - if (nbChars < 0) + if (sprintf(buf, "::REPT~%" PRIu32, (*reptNode->iters)[i]) < 0) fatalerror("Failed to write macro invocation info: %s\n", strerror(errno)); - dest += nbChars; + fileInfo->name->append(buf); } } - *dest++ = ':'; - *dest++ = ':'; - memcpy(dest, macro->name, macroNameLen + 1); + fileInfo->name->append("::"); + fileInfo->name->append(macro->name); newContext((struct FileStackNode *)fileInfo); contextStack->lexerState = lexer_OpenFileView("MACRO", macro->macro.value, macro->macro.size, @@ -438,23 +442,22 @@ void fstk_RunMacro(char const *macroName, struct MacroArgs *args) static bool newReptContext(int32_t reptLineNo, char *body, size_t size) { uint32_t reptDepth = contextStack->fileInfo->type == NODE_REPT - ? ((struct FileStackReptNode *)contextStack->fileInfo)->reptDepth + ? ((struct FileStackReptNode *)contextStack->fileInfo)->iters->size() : 0; - struct FileStackReptNode *fileInfo = (struct FileStackReptNode *)malloc(sizeof(*fileInfo) - + (reptDepth + 1) * sizeof(fileInfo->iters[0])); + struct FileStackReptNode *fileInfo = (struct FileStackReptNode *)malloc(sizeof(*fileInfo)); - if (!fileInfo) { + if (fileInfo) + fileInfo->iters = new std::vector(); + if (!fileInfo || !fileInfo->iters) { error("Failed to alloc file info for REPT: %s\n", strerror(errno)); return false; } fileInfo->node.type = NODE_REPT; - fileInfo->reptDepth = reptDepth + 1; - fileInfo->iters[0] = 1; - if (reptDepth) + if (reptDepth) { // Copy all parent iter counts - memcpy(&fileInfo->iters[1], - ((struct FileStackReptNode *)contextStack->fileInfo)->iters, - reptDepth * sizeof(fileInfo->iters[0])); + *fileInfo->iters = *((struct FileStackReptNode *)contextStack->fileInfo)->iters; + } + fileInfo->iters->insert(fileInfo->iters->begin(), 1); newContext((struct FileStackNode *)fileInfo); // Correct our line number, which currently points to the `ENDR` line @@ -545,23 +548,22 @@ void fstk_Init(char const *mainPath, size_t maxDepth) fatalerror("Failed to open main file\n"); lexer_SetState(state); char const *fileName = lexer_GetFileName(); - size_t len = strlen(fileName); struct Context *context = (struct Context *)malloc(sizeof(*contextStack)); - struct FileStackNamedNode *fileInfo = - (struct FileStackNamedNode *)malloc(sizeof(*fileInfo) + len + 1); + struct FileStackNamedNode *fileInfo = (struct FileStackNamedNode *)malloc(sizeof(*fileInfo)); if (!context) fatalerror("Failed to allocate memory for main context: %s\n", strerror(errno)); - if (!fileInfo) + if (fileInfo) + fileInfo->name = new(std::nothrow) std::string(fileName); + if (!fileInfo || !fileInfo->name) fatalerror("Failed to allocate memory for main file info: %s\n", strerror(errno)); context->fileInfo = (struct FileStackNode *)fileInfo; - // lineNo and reptIter are unused on the top-level context + // lineNo and nbReptIters are unused on the top-level context context->fileInfo->parent = NULL; context->fileInfo->lineNo = 0; // This still gets written to the object file, so init it context->fileInfo->referenced = false; context->fileInfo->type = NODE_FILE; - memcpy(fileInfo->name, fileName, len + 1); context->parent = NULL; context->lexerState = state; @@ -574,19 +576,7 @@ void fstk_Init(char const *mainPath, size_t maxDepth) // Now that it's set up properly, register the context contextStack = context; - // Check that max recursion depth won't allow overflowing node `malloc`s - // This assumes that the rept node is larger -#define DEPTH_LIMIT ((SIZE_MAX - sizeof(struct FileStackReptNode)) / sizeof(uint32_t)) - if (maxDepth > DEPTH_LIMIT) { - error("Recursion depth may not be higher than %zu, defaulting to " - EXPAND_AND_STR(DEFAULT_MAX_DEPTH) "\n", DEPTH_LIMIT); - maxRecursionDepth = DEFAULT_MAX_DEPTH; - } else { - maxRecursionDepth = maxDepth; - } - // Make sure that the default of 64 is OK, though - assert(DEPTH_LIMIT >= DEFAULT_MAX_DEPTH); -#undef DEPTH_LIMIT + maxRecursionDepth = maxDepth; runPreIncludeFile(); } diff --git a/src/asm/lexer.cpp b/src/asm/lexer.cpp index db8a130f..53d88b8e 100644 --- a/src/asm/lexer.cpp +++ b/src/asm/lexer.cpp @@ -308,24 +308,28 @@ struct IfStack { bool reachedElseBlock; // Whether an ELSE block ran already }; +struct MmappedLexerState { + char *ptr; // Technically `const` during the lexer's execution + size_t size; + size_t offset; + bool isReferenced; // If a macro in this file requires not unmapping it +}; + +struct BufferedLexerState { + int fd; + size_t index; // Read index into the buffer + char buf[LEXER_BUF_SIZE]; // Circular buffer + size_t nbChars; // Number of "fresh" chars in the buffer +}; + struct LexerState { char const *path; // mmap()-dependent IO state bool isMmapped; union { - struct { // If mmap()ed - char *ptr; // Technically `const` during the lexer's execution - size_t size; - size_t offset; - bool isReferenced; // If a macro in this file requires not unmapping it - } mmap; - struct { // Otherwise - int fd; - size_t index; // Read index into the buffer - char buf[LEXER_BUF_SIZE]; // Circular buffer - size_t nbChars; // Number of "fresh" chars in the buffer - } cbuf; + struct MmappedLexerState mmap; // If mmap()ed + struct BufferedLexerState cbuf; // Otherwise }; // Common state diff --git a/src/asm/macro.cpp b/src/asm/macro.cpp index c0b07821..80776491 100644 --- a/src/asm/macro.cpp +++ b/src/asm/macro.cpp @@ -1,33 +1,24 @@ /* SPDX-License-Identifier: MIT */ #include +#include #include #include #include #include #include +#include #include "asm/macro.hpp" #include "asm/warning.hpp" #define MAXMACROARGS 99999 -// Your average macro invocation does not go past the tens, but some go further -// This ensures that sane and slightly insane invocations suffer no penalties, -// and the rest is insane and thus will assume responsibility. -// Additionally, ~300 bytes (on x64) of memory per level of nesting has been -// deemed reasonable. (Halve that on x86.) -#define INITIAL_ARG_SIZE 32 struct MacroArgs { - unsigned int nbArgs; unsigned int shift; - unsigned int capacity; - char *args[]; + std::vector *args; }; -#define SIZEOF_ARGS(nbArgs) (sizeof(struct MacroArgs) + \ - sizeof(((struct MacroArgs *)0)->args[0]) * (nbArgs)) - static struct MacroArgs *macroArgs = NULL; static uint32_t uniqueID = 0; static uint32_t maxUniqueID = 0; @@ -44,35 +35,24 @@ struct MacroArgs *macro_GetCurrentArgs(void) struct MacroArgs *macro_NewArgs(void) { - struct MacroArgs *args = (struct MacroArgs *)malloc(SIZEOF_ARGS(INITIAL_ARG_SIZE)); + struct MacroArgs *args = (struct MacroArgs *)malloc(sizeof(*args)); - if (!args) + if (args) + args->args = new(std::nothrow) std::vector(); + if (!args || !args->args) fatalerror("Unable to register macro arguments: %s\n", strerror(errno)); - args->nbArgs = 0; args->shift = 0; - args->capacity = INITIAL_ARG_SIZE; return args; } -void macro_AppendArg(struct MacroArgs **argPtr, char *s) +void macro_AppendArg(struct MacroArgs *args, char *s) { -#define macArgs (*argPtr) if (s[0] == '\0') warning(WARNING_EMPTY_MACRO_ARG, "Empty macro argument\n"); - if (macArgs->nbArgs == MAXMACROARGS) + if (args->args->size() == MAXMACROARGS) error("A maximum of " EXPAND_AND_STR(MAXMACROARGS) " arguments is allowed\n"); - if (macArgs->nbArgs >= macArgs->capacity) { - macArgs->capacity *= 2; - // Check that overflow didn't roll us back - if (macArgs->capacity <= macArgs->nbArgs) - fatalerror("Failed to add new macro argument: capacity overflow\n"); - macArgs = (struct MacroArgs *)realloc(macArgs, SIZEOF_ARGS(macArgs->capacity)); - if (!macArgs) - fatalerror("Error adding new macro argument: %s\n", strerror(errno)); - } - macArgs->args[macArgs->nbArgs++] = s; -#undef macArgs + args->args->push_back(s); } void macro_UseNewArgs(struct MacroArgs *args) @@ -82,8 +62,9 @@ void macro_UseNewArgs(struct MacroArgs *args) void macro_FreeArgs(struct MacroArgs *args) { - for (uint32_t i = 0; i < macroArgs->nbArgs; i++) - free(args->args[i]); + for (char *arg : *macroArgs->args) + free(arg); + delete args->args; } char const *macro_GetArg(uint32_t i) @@ -93,8 +74,7 @@ char const *macro_GetArg(uint32_t i) uint32_t realIndex = i + macroArgs->shift - 1; - return realIndex >= macroArgs->nbArgs ? NULL - : macroArgs->args[realIndex]; + return realIndex >= macroArgs->args->size() ? NULL : (*macroArgs->args)[realIndex]; } char const *macro_GetAllArgs(void) @@ -102,13 +82,15 @@ char const *macro_GetAllArgs(void) if (!macroArgs) return NULL; - if (macroArgs->shift >= macroArgs->nbArgs) + size_t nbArgs = macroArgs->args->size(); + + if (macroArgs->shift >= nbArgs) return ""; size_t len = 0; - for (uint32_t i = macroArgs->shift; i < macroArgs->nbArgs; i++) - len += strlen(macroArgs->args[i]) + 1; // 1 for comma + for (uint32_t i = macroArgs->shift; i < nbArgs; i++) + len += strlen((*macroArgs->args)[i]) + 1; // 1 for comma char *str = (char *)malloc(len + 1); // 1 for '\0' char *ptr = str; @@ -116,14 +98,15 @@ char const *macro_GetAllArgs(void) if (!str) fatalerror("Failed to allocate memory for expanding '\\#': %s\n", strerror(errno)); - for (uint32_t i = macroArgs->shift; i < macroArgs->nbArgs; i++) { - size_t n = strlen(macroArgs->args[i]); + for (uint32_t i = macroArgs->shift; i < nbArgs; i++) { + char *arg = (*macroArgs->args)[i]; + size_t n = strlen(arg); - memcpy(ptr, macroArgs->args[i], n); + memcpy(ptr, arg, n); ptr += n; // Commas go between args and after a last empty arg - if (i < macroArgs->nbArgs - 1 || n == 0) + if (i < nbArgs - 1 || n == 0) *ptr++ = ','; // no space after comma } *ptr = '\0'; @@ -176,14 +159,12 @@ void macro_ShiftCurrentArgs(int32_t count) { if (!macroArgs) { error("Cannot shift macro arguments outside of a macro\n"); - } else if (count > 0 && ((uint32_t)count > macroArgs->nbArgs - || macroArgs->shift > macroArgs->nbArgs - count)) { - warning(WARNING_MACRO_SHIFT, - "Cannot shift macro arguments past their end\n"); - macroArgs->shift = macroArgs->nbArgs; + } else if (size_t nbArgs = macroArgs->args->size(); + count > 0 && ((uint32_t)count > nbArgs || macroArgs->shift > nbArgs - count)) { + warning(WARNING_MACRO_SHIFT, "Cannot shift macro arguments past their end\n"); + macroArgs->shift = nbArgs; } else if (count < 0 && macroArgs->shift < (uint32_t)-count) { - warning(WARNING_MACRO_SHIFT, - "Cannot shift macro arguments past their beginning\n"); + warning(WARNING_MACRO_SHIFT, "Cannot shift macro arguments past their beginning\n"); macroArgs->shift = 0; } else { macroArgs->shift += count; @@ -192,5 +173,5 @@ void macro_ShiftCurrentArgs(int32_t count) uint32_t macro_NbArgs(void) { - return macroArgs->nbArgs - macroArgs->shift; + return macroArgs->args->size() - macroArgs->shift; } diff --git a/src/asm/output.cpp b/src/asm/output.cpp index 838e4ad2..9865e5a9 100644 --- a/src/asm/output.cpp +++ b/src/asm/output.cpp @@ -457,14 +457,14 @@ static void writeFileStackNode(struct FileStackNode const *node, FILE *f) putlong(node->lineNo, f); putc(node->type, f); if (node->type != NODE_REPT) { - putstring(((struct FileStackNamedNode const *)node)->name, f); + putstring(((struct FileStackNamedNode const *)node)->name->c_str(), f); } else { struct FileStackReptNode const *reptNode = (struct FileStackReptNode const *)node; - putlong(reptNode->reptDepth, f); + putlong(reptNode->iters->size(), f); // Iters are stored by decreasing depth, so reverse the order for output - for (uint32_t i = reptNode->reptDepth; i--; ) - putlong(reptNode->iters[i], f); + for (uint32_t i = reptNode->iters->size(); i--; ) + putlong((*reptNode->iters)[i], f); } } diff --git a/src/asm/parser.y b/src/asm/parser.y index 97e6e549..1ed52d7f 100644 --- a/src/asm/parser.y +++ b/src/asm/parser.y @@ -492,6 +492,15 @@ enum { %} +%code requires { + // Only used in the %union + struct ForArgs { + int32_t start; + int32_t stop; + int32_t step; + }; +} + %union { char symName[MAXSYMLEN + 1]; @@ -506,11 +515,7 @@ enum { struct AlignmentSpec alignSpec; struct DsArgList dsArgs; struct PurgeArgList purgeArgs; - struct { - int32_t start; - int32_t stop; - int32_t step; - } forArgs; + struct ForArgs forArgs; struct StrFmtArgList strfmtArgs; bool captureTerminated; } @@ -885,7 +890,7 @@ macroargs : %empty { $$ = macro_NewArgs(); } | macroargs T_STRING { - macro_AppendArg(&($$), strdup($2)); + macro_AppendArg($$, strdup($2)); } ; diff --git a/src/link/sdas_obj.cpp b/src/link/sdas_obj.cpp index 6d08f3c2..93d32bec 100644 --- a/src/link/sdas_obj.cpp +++ b/src/link/sdas_obj.cpp @@ -416,7 +416,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file) { // definition is in a floating section if ((other->section && !other->section->isAddressFixed) || (symbol->section && !symbol->section->isAddressFixed)) { - sym_AddSymbol(symbol); // This will error out + sym_AddSymbol(symbol); // This will error out } else if (other->value != symbol->value) { error(where, lineNo, "Definition of \"%s\" conflicts with definition in %s (%" PRId32 " != %" PRId32 ")", diff --git a/test/asm/unique-id.asm b/test/asm/unique-id.asm index f5c84419..a689686b 100644 --- a/test/asm/unique-id.asm +++ b/test/asm/unique-id.asm @@ -1,11 +1,11 @@ DEF warn_unique EQUS "WARN \"\\@!\"" macro m - warn_unique - REPT 2 - warn_unique - ENDR - warn_unique + warn_unique + REPT 2 + warn_unique + ENDR + warn_unique endm ; TODO: Ideally we'd test now as well, but it'd cause a fatal error ;warn_unique