mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Use std::deque for expansions
This commit is contained in:
@@ -292,7 +292,6 @@ static_assert(LEXER_BUF_SIZE > 1, "Lexer buffer size is too small");
|
|||||||
static_assert(LEXER_BUF_SIZE <= SSIZE_MAX, "Lexer buffer size is too large");
|
static_assert(LEXER_BUF_SIZE <= SSIZE_MAX, "Lexer buffer size is too large");
|
||||||
|
|
||||||
struct Expansion {
|
struct Expansion {
|
||||||
struct Expansion *parent;
|
|
||||||
char *name;
|
char *name;
|
||||||
union {
|
union {
|
||||||
char const *unowned;
|
char const *unowned;
|
||||||
@@ -352,7 +351,7 @@ struct LexerState {
|
|||||||
bool disableInterpolation;
|
bool disableInterpolation;
|
||||||
size_t macroArgScanDistance; // Max distance already scanned for macro args
|
size_t macroArgScanDistance; // Max distance already scanned for macro args
|
||||||
bool expandStrings;
|
bool expandStrings;
|
||||||
struct Expansion *expansions; // Points to the innermost current expansion
|
std::deque<struct Expansion> *expansions; // Front is the innermost current expansion
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LexerState *lexerState = NULL;
|
struct LexerState *lexerState = NULL;
|
||||||
@@ -375,7 +374,10 @@ static void initState(struct LexerState *state)
|
|||||||
state->disableInterpolation = false;
|
state->disableInterpolation = false;
|
||||||
state->macroArgScanDistance = 0;
|
state->macroArgScanDistance = 0;
|
||||||
state->expandStrings = true;
|
state->expandStrings = true;
|
||||||
state->expansions = NULL;
|
|
||||||
|
state->expansions = new(std::nothrow) std::deque<struct Expansion>();
|
||||||
|
if (!state->expansions)
|
||||||
|
fatalerror("Unable to allocate new expansion stack: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nextLine(void)
|
static void nextLine(void)
|
||||||
@@ -544,6 +546,7 @@ void lexer_DeleteState(struct LexerState *state)
|
|||||||
else if (state->isFile && !state->mmap.isReferenced)
|
else if (state->isFile && !state->mmap.isReferenced)
|
||||||
munmap(state->mmap.ptr, state->mmap.size);
|
munmap(state->mmap.ptr, state->mmap.size);
|
||||||
delete state->ifStack;
|
delete state->ifStack;
|
||||||
|
delete state->expansions;
|
||||||
free(state);
|
free(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -642,37 +645,26 @@ static void beginExpansion(char const *str, bool owned, char const *name)
|
|||||||
if (name)
|
if (name)
|
||||||
lexer_CheckRecursionDepth();
|
lexer_CheckRecursionDepth();
|
||||||
|
|
||||||
struct Expansion *exp = (struct Expansion *)malloc(sizeof(*exp));
|
lexerState->expansions->push_front({
|
||||||
|
.name = name ? strdup(name) : NULL,
|
||||||
if (!exp)
|
.contents = { .unowned = str },
|
||||||
fatalerror("Unable to allocate new expansion: %s\n", strerror(errno));
|
.size = size,
|
||||||
|
.offset = 0,
|
||||||
exp->parent = lexerState->expansions;
|
.owned = owned,
|
||||||
exp->name = name ? strdup(name) : NULL;
|
});
|
||||||
exp->contents.unowned = str;
|
|
||||||
exp->size = size;
|
|
||||||
exp->offset = 0;
|
|
||||||
exp->owned = owned;
|
|
||||||
|
|
||||||
lexerState->expansions = exp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lexer_CheckRecursionDepth(void)
|
void lexer_CheckRecursionDepth(void)
|
||||||
{
|
{
|
||||||
size_t depth = 0;
|
if (lexerState->expansions->size() > maxRecursionDepth + 1)
|
||||||
|
|
||||||
for (struct Expansion *exp = lexerState->expansions; exp; exp = exp->parent) {
|
|
||||||
if (depth++ > maxRecursionDepth)
|
|
||||||
fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
|
fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void freeExpansion(struct Expansion *expansion)
|
static void freeExpansion(struct Expansion &expansion)
|
||||||
{
|
{
|
||||||
free(expansion->name);
|
free(expansion.name);
|
||||||
if (expansion->owned)
|
if (expansion.owned)
|
||||||
free(expansion->contents.owned);
|
free(expansion.contents.owned);
|
||||||
free(expansion);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isMacroChar(char c)
|
static bool isMacroChar(char c)
|
||||||
@@ -799,13 +791,13 @@ static size_t readInternal(size_t bufIndex, size_t nbChars)
|
|||||||
// We only need one character of lookahead, for macro arguments
|
// We only need one character of lookahead, for macro arguments
|
||||||
static int peekInternal(uint8_t distance)
|
static int peekInternal(uint8_t distance)
|
||||||
{
|
{
|
||||||
for (struct Expansion *exp = lexerState->expansions; exp; exp = exp->parent) {
|
for (struct Expansion &exp : *lexerState->expansions) {
|
||||||
// An expansion that has reached its end will have `exp->offset` == `exp->size`,
|
// An expansion that has reached its end will have `exp->offset` == `exp->size`,
|
||||||
// and `peekInternal` will continue with its parent
|
// and `peekInternal` will continue with its parent
|
||||||
assert(exp->offset <= exp->size);
|
assert(exp.offset <= exp.size);
|
||||||
if (distance < exp->size - exp->offset)
|
if (distance < exp.size - exp.offset)
|
||||||
return exp->contents.unowned[exp->offset + distance];
|
return exp.contents.unowned[exp.offset + distance];
|
||||||
distance -= exp->size - exp->offset;
|
distance -= exp.size - exp.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (distance >= LEXER_BUF_SIZE)
|
if (distance >= LEXER_BUF_SIZE)
|
||||||
@@ -918,17 +910,17 @@ static void shiftChar(void)
|
|||||||
lexerState->macroArgScanDistance--;
|
lexerState->macroArgScanDistance--;
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
if (lexerState->expansions) {
|
if (!lexerState->expansions->empty()) {
|
||||||
// Advance within the current expansion
|
// Advance within the current expansion
|
||||||
assert(lexerState->expansions->offset <= lexerState->expansions->size);
|
struct Expansion &expansion = lexerState->expansions->front();
|
||||||
lexerState->expansions->offset++;
|
|
||||||
if (lexerState->expansions->offset > lexerState->expansions->size) {
|
assert(expansion.offset <= expansion.size);
|
||||||
|
expansion.offset++;
|
||||||
|
if (expansion.offset > expansion.size) {
|
||||||
// When advancing would go past an expansion's end, free it,
|
// When advancing would go past an expansion's end, free it,
|
||||||
// move up to its parent, and try again to advance
|
// move up to its parent, and try again to advance
|
||||||
struct Expansion *exp = lexerState->expansions;
|
freeExpansion(expansion);
|
||||||
|
lexerState->expansions->pop_front();
|
||||||
lexerState->expansions = lexerState->expansions->parent;
|
|
||||||
freeExpansion(exp);
|
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -985,10 +977,10 @@ void lexer_DumpStringExpansions(void)
|
|||||||
if (!lexerState)
|
if (!lexerState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (struct Expansion *exp = lexerState->expansions; exp; exp = exp->parent) {
|
for (struct Expansion &exp : *lexerState->expansions) {
|
||||||
// Only register EQUS expansions, not string args
|
// Only register EQUS expansions, not string args
|
||||||
if (exp->name)
|
if (exp.name)
|
||||||
fprintf(stderr, "while expanding symbol \"%s\"\n", exp->name);
|
fprintf(stderr, "while expanding symbol \"%s\"\n", exp.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1009,7 +1001,7 @@ static void discardBlockComment(void)
|
|||||||
handleCRLF(c);
|
handleCRLF(c);
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case '\n':
|
case '\n':
|
||||||
if (!lexerState->expansions)
|
if (lexerState->expansions->empty())
|
||||||
nextLine();
|
nextLine();
|
||||||
continue;
|
continue;
|
||||||
case '/':
|
case '/':
|
||||||
@@ -1062,7 +1054,7 @@ static void readLineContinuation(void)
|
|||||||
shiftChar();
|
shiftChar();
|
||||||
// Handle CRLF before nextLine() since shiftChar updates colNo
|
// Handle CRLF before nextLine() since shiftChar updates colNo
|
||||||
handleCRLF(c);
|
handleCRLF(c);
|
||||||
if (!lexerState->expansions)
|
if (lexerState->expansions->empty())
|
||||||
nextLine();
|
nextLine();
|
||||||
break;
|
break;
|
||||||
} else if (c == ';') {
|
} else if (c == ';') {
|
||||||
@@ -2415,7 +2407,7 @@ int yylex(void)
|
|||||||
if (lexerState->lastToken == T_EOB && yywrap())
|
if (lexerState->lastToken == T_EOB && yywrap())
|
||||||
return T_EOF;
|
return T_EOF;
|
||||||
// Newlines read within an expansion should not increase the line count
|
// Newlines read within an expansion should not increase the line count
|
||||||
if (lexerState->atLineStart && !lexerState->expansions)
|
if (lexerState->atLineStart && lexerState->expansions->empty())
|
||||||
nextLine();
|
nextLine();
|
||||||
|
|
||||||
static int (* const lexerModeFuncs[NB_LEXER_MODES])(void) = {
|
static int (* const lexerModeFuncs[NB_LEXER_MODES])(void) = {
|
||||||
@@ -2446,7 +2438,7 @@ static void startCapture(struct CaptureBody *capture)
|
|||||||
|
|
||||||
capture->lineNo = lexer_GetLineNo();
|
capture->lineNo = lexer_GetLineNo();
|
||||||
|
|
||||||
if (lexerState->isMmapped && !lexerState->expansions) {
|
if (lexerState->isMmapped && lexerState->expansions->empty()) {
|
||||||
capture->body = &lexerState->mmap.ptr[lexerState->mmap.offset];
|
capture->body = &lexerState->mmap.ptr[lexerState->mmap.offset];
|
||||||
} else {
|
} else {
|
||||||
lexerState->captureCapacity = 128; // The initial size will be twice that
|
lexerState->captureCapacity = 128; // The initial size will be twice that
|
||||||
|
|||||||
Reference in New Issue
Block a user