Use std::stack for unions

This commit is contained in:
Rangi42
2024-02-21 12:12:48 -05:00
committed by Sylvie
parent 8083ef605f
commit 2ea6de7195

View File

@@ -6,6 +6,7 @@
#include <errno.h> #include <errno.h>
#include <inttypes.h> #include <inttypes.h>
#include <new> #include <new>
#include <stack>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string> #include <string>
@@ -28,8 +29,7 @@ uint8_t fillByte;
struct UnionStackEntry { struct UnionStackEntry {
uint32_t start; uint32_t start;
uint32_t size; uint32_t size;
struct UnionStackEntry *next; };
} *unionStack = NULL;
struct SectionStackEntry { struct SectionStackEntry {
struct Section *section; struct Section *section;
@@ -37,10 +37,11 @@ struct SectionStackEntry {
char const *scope; // Section's symbol scope char const *scope; // Section's symbol scope
uint32_t offset; uint32_t offset;
int32_t loadOffset; int32_t loadOffset;
struct UnionStackEntry *unionStack; std::stack<struct UnionStackEntry> *unionStack;
struct SectionStackEntry *next; struct SectionStackEntry *next;
}; };
std::stack<struct UnionStackEntry> *currentUnionStack = NULL;
struct SectionStackEntry *sectionStack; struct SectionStackEntry *sectionStack;
uint32_t curOffset; // Offset into the current section (see sect_GetSymbolOffset) uint32_t curOffset; // Offset into the current section (see sect_GetSymbolOffset)
struct Section *currentSection = NULL; struct Section *currentSection = NULL;
@@ -381,7 +382,7 @@ static struct Section *getSection(char const *name, enum SectionType type, uint3
// Set the current section // Set the current section
static void changeSection(void) static void changeSection(void)
{ {
if (unionStack) if (currentUnionStack && !currentUnionStack->empty())
fatalerror("Cannot change the section within a UNION\n"); fatalerror("Cannot change the section within a UNION\n");
sym_SetCurrentSymbolScope(NULL); sym_SetCurrentSymbolScope(NULL);
@@ -574,28 +575,28 @@ void sect_StartUnion(void)
error("Cannot use UNION inside of ROM0 or ROMX sections\n"); error("Cannot use UNION inside of ROM0 or ROMX sections\n");
return; return;
} }
struct UnionStackEntry *entry = (struct UnionStackEntry *)malloc(sizeof(*entry));
if (!entry) if (!currentUnionStack)
fatalerror("Failed to allocate new union stack entry: %s\n", strerror(errno)); currentUnionStack = new(std::nothrow) std::stack<struct UnionStackEntry>();
entry->start = curOffset; if (!currentUnionStack)
entry->size = 0; fatalerror("No memory for union stack: %s\n", strerror(errno));
entry->next = unionStack;
unionStack = entry; currentUnionStack->push({ .start = curOffset, .size = 0 });
} }
static void endUnionMember(void) static void endUnionMember(void)
{ {
uint32_t memberSize = curOffset - unionStack->start; struct UnionStackEntry &member = currentUnionStack->top();
uint32_t memberSize = curOffset - member.start;
if (memberSize > unionStack->size) if (memberSize > member.size)
unionStack->size = memberSize; member.size = memberSize;
curOffset = unionStack->start; curOffset = member.start;
} }
void sect_NextUnionMember(void) void sect_NextUnionMember(void)
{ {
if (!unionStack) { if (!currentUnionStack || currentUnionStack->empty()) {
error("Found NEXTU outside of a UNION construct\n"); error("Found NEXTU outside of a UNION construct\n");
return; return;
} }
@@ -604,22 +605,21 @@ void sect_NextUnionMember(void)
void sect_EndUnion(void) void sect_EndUnion(void)
{ {
if (!unionStack) { if (!currentUnionStack || currentUnionStack->empty()) {
error("Found ENDU outside of a UNION construct\n"); error("Found ENDU outside of a UNION construct\n");
return; return;
} }
endUnionMember(); endUnionMember();
curOffset += unionStack->size; curOffset += currentUnionStack->top().size;
struct UnionStackEntry *next = unionStack->next; currentUnionStack->pop();
free(unionStack);
unionStack = next;
} }
void sect_CheckUnionClosed(void) void sect_CheckUnionClosed(void)
{ {
if (unionStack) if (currentUnionStack && !currentUnionStack->empty())
error("Unterminated UNION construct\n"); error("Unterminated UNION construct\n");
if (currentUnionStack)
delete currentUnionStack;
} }
// Output an absolute byte // Output an absolute byte
@@ -951,7 +951,7 @@ void sect_PushSection(void)
entry->scope = sym_GetCurrentSymbolScope(); entry->scope = sym_GetCurrentSymbolScope();
entry->offset = curOffset; entry->offset = curOffset;
entry->loadOffset = loadOffset; entry->loadOffset = loadOffset;
entry->unionStack = unionStack; entry->unionStack = currentUnionStack;
entry->next = sectionStack; entry->next = sectionStack;
sectionStack = entry; sectionStack = entry;
@@ -959,7 +959,7 @@ void sect_PushSection(void)
currentSection = NULL; currentSection = NULL;
currentLoadSection = NULL; currentLoadSection = NULL;
sym_SetCurrentSymbolScope(NULL); sym_SetCurrentSymbolScope(NULL);
unionStack = NULL; currentUnionStack = NULL;
} }
void sect_PopSection(void) void sect_PopSection(void)
@@ -978,7 +978,8 @@ void sect_PopSection(void)
sym_SetCurrentSymbolScope(entry->scope); sym_SetCurrentSymbolScope(entry->scope);
curOffset = entry->offset; curOffset = entry->offset;
loadOffset = entry->loadOffset; loadOffset = entry->loadOffset;
unionStack = entry->unionStack; delete currentUnionStack;
currentUnionStack = entry->unionStack;
sectionStack = entry->next; sectionStack = entry->next;
free(entry); free(entry);
@@ -992,7 +993,7 @@ void sect_EndSection(void)
if (currentLoadSection) if (currentLoadSection)
fatalerror("Cannot end the section within a `LOAD` block\n"); fatalerror("Cannot end the section within a `LOAD` block\n");
if (unionStack) if (currentUnionStack && !currentUnionStack->empty())
fatalerror("Cannot end the section within a UNION\n"); fatalerror("Cannot end the section within a UNION\n");
// Reset the section scope // Reset the section scope