mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Store IF depth relative to each fstack context
This disallows starting/ending an IF inside an INCLUDEd file or a macro expansion
This commit is contained in:
@@ -25,7 +25,6 @@
|
||||
#define MAXINCPATHS 128
|
||||
|
||||
extern uint32_t nTotalLines;
|
||||
extern uint32_t nIFDepth;
|
||||
extern struct Section *pCurrentSection;
|
||||
|
||||
#endif /* RGBDS_ASM_ASM_H */
|
||||
|
||||
@@ -53,6 +53,9 @@ extern size_t nMaxRecursionDepth;
|
||||
|
||||
struct MacroArgs;
|
||||
|
||||
uint32_t fstk_GetIFDepth(void);
|
||||
void fstk_IncIFDepth(void);
|
||||
void fstk_DecIFDepth(void);
|
||||
void fstk_Dump(struct FileStackNode const *node, uint32_t lineNo);
|
||||
void fstk_DumpCurrent(void);
|
||||
struct FileStackNode *fstk_GetFileStack(void);
|
||||
|
||||
@@ -31,6 +31,7 @@ struct Context {
|
||||
struct Context *parent;
|
||||
struct FileStackNode *fileInfo;
|
||||
struct LexerState *lexerState;
|
||||
uint32_t nIFDepth;
|
||||
uint32_t uniqueID;
|
||||
struct MacroArgs *macroArgs; /* Macro args are *saved* here */
|
||||
uint32_t nbReptIters;
|
||||
@@ -47,7 +48,22 @@ size_t nMaxRecursionDepth;
|
||||
static unsigned int nbIncPaths = 0;
|
||||
static char const *includePaths[MAXINCPATHS];
|
||||
|
||||
char const *dumpNodeAndParents(struct FileStackNode const *node)
|
||||
uint32_t fstk_GetIFDepth(void)
|
||||
{
|
||||
return contextStack->nIFDepth;
|
||||
}
|
||||
|
||||
void fstk_IncIFDepth(void)
|
||||
{
|
||||
contextStack->nIFDepth++;
|
||||
}
|
||||
|
||||
void fstk_DecIFDepth(void)
|
||||
{
|
||||
contextStack->nIFDepth--;
|
||||
}
|
||||
|
||||
static const char *dumpNodeAndParents(struct FileStackNode const *node)
|
||||
{
|
||||
char const *name;
|
||||
|
||||
@@ -200,6 +216,10 @@ bool fstk_FindFile(char const *path, char **fullPath, size_t *size)
|
||||
|
||||
bool yywrap(void)
|
||||
{
|
||||
if (contextStack->nIFDepth != 0)
|
||||
fatalerror("Ended block with %" PRIu32 " unterminated IF construct%s\n",
|
||||
contextStack->nIFDepth, contextStack->nIFDepth == 1 ? "" : "s");
|
||||
|
||||
if (contextStack->fileInfo->type == NODE_REPT) { /* The context is a REPT block, which may loop */
|
||||
struct FileStackReptNode *fileInfo = (struct FileStackReptNode *)contextStack->fileInfo;
|
||||
|
||||
@@ -283,6 +303,7 @@ static void newContext(struct FileStackNode *fileInfo)
|
||||
fileInfo->referenced = false;
|
||||
fileInfo->lineNo = lexer_GetLineNo();
|
||||
context->fileInfo = fileInfo;
|
||||
context->nIFDepth = 0;
|
||||
context->forName = NULL;
|
||||
/*
|
||||
* Link new entry to its parent so it's reachable later
|
||||
@@ -429,7 +450,7 @@ static bool newReptContext(int32_t reptLineNo, char *body, size_t size)
|
||||
|
||||
contextStack->lexerState = lexer_OpenFileView(body, size, reptLineNo);
|
||||
if (!contextStack->lexerState)
|
||||
fatalerror("Failed to set up lexer for rept block\n");
|
||||
fatalerror("Failed to set up lexer for REPT block\n");
|
||||
lexer_SetStateAtEOL(contextStack->lexerState);
|
||||
contextStack->uniqueID = macro_UseNewUniqueID();
|
||||
return true;
|
||||
@@ -521,6 +542,7 @@ void fstk_Init(char const *mainPath, size_t maxRecursionDepth)
|
||||
|
||||
context->parent = NULL;
|
||||
context->lexerState = state;
|
||||
context->nIFDepth = 0;
|
||||
context->uniqueID = 0;
|
||||
macro_SetUniqueID(0);
|
||||
context->nbReptIters = 0;
|
||||
|
||||
@@ -1966,7 +1966,7 @@ static int skipIfBlock(bool toEndc)
|
||||
{
|
||||
dbgPrint("Skipping IF block (toEndc = %s)\n", toEndc ? "true" : "false");
|
||||
lexer_SetMode(LEXER_NORMAL);
|
||||
int startingDepth = nIFDepth;
|
||||
int startingDepth = fstk_GetIFDepth();
|
||||
int token;
|
||||
bool atLineStart = lexerState->atLineStart;
|
||||
|
||||
@@ -1990,7 +1990,7 @@ static int skipIfBlock(bool toEndc)
|
||||
token = readIdentifier(c);
|
||||
switch (token) {
|
||||
case T_POP_IF:
|
||||
nIFDepth++;
|
||||
fstk_IncIFDepth();
|
||||
break;
|
||||
|
||||
case T_POP_ELIF:
|
||||
@@ -1999,10 +1999,10 @@ static int skipIfBlock(bool toEndc)
|
||||
break;
|
||||
/* fallthrough */
|
||||
case T_POP_ENDC:
|
||||
if (nIFDepth == startingDepth)
|
||||
if (fstk_GetIFDepth() == startingDepth)
|
||||
goto finish;
|
||||
if (token == T_POP_ENDC)
|
||||
nIFDepth--;
|
||||
fstk_DecIFDepth();
|
||||
}
|
||||
}
|
||||
atLineStart = false;
|
||||
@@ -2087,11 +2087,11 @@ static int yylex_SKIP_TO_ENDR(void)
|
||||
break;
|
||||
|
||||
case T_POP_IF:
|
||||
nIFDepth++;
|
||||
fstk_IncIFDepth();
|
||||
break;
|
||||
|
||||
case T_POP_ENDC:
|
||||
nIFDepth--;
|
||||
fstk_DecIFDepth();
|
||||
}
|
||||
}
|
||||
atLineStart = false;
|
||||
|
||||
@@ -46,7 +46,7 @@ const size_t cldefine_entrysize = 2 * sizeof(void *);
|
||||
char **cldefines;
|
||||
|
||||
clock_t nStartClock, nEndClock;
|
||||
uint32_t nTotalLines, nIFDepth;
|
||||
uint32_t nTotalLines;
|
||||
|
||||
#if defined(YYDEBUG) && YYDEBUG
|
||||
extern int yydebug;
|
||||
@@ -488,7 +488,6 @@ int main(int argc, char *argv[])
|
||||
nStartClock = clock();
|
||||
|
||||
nTotalLines = 0;
|
||||
nIFDepth = 0;
|
||||
sym_Init(now);
|
||||
sym_SetExportAll(exportall);
|
||||
|
||||
@@ -502,10 +501,6 @@ int main(int argc, char *argv[])
|
||||
if (dependfile)
|
||||
fclose(dependfile);
|
||||
|
||||
if (nIFDepth != 0)
|
||||
errx(1, "Unterminated IF construct (%" PRIu32 " levels)!",
|
||||
nIFDepth);
|
||||
|
||||
sect_CheckUnionClosed();
|
||||
|
||||
double timespent;
|
||||
|
||||
@@ -563,7 +563,7 @@ conditional : if
|
||||
;
|
||||
|
||||
if : T_POP_IF const T_NEWLINE {
|
||||
nIFDepth++;
|
||||
fstk_IncIFDepth();
|
||||
executeElseBlock = !$2;
|
||||
if (executeElseBlock)
|
||||
lexer_SetMode(LEXER_SKIP_TO_ELIF);
|
||||
@@ -571,7 +571,7 @@ if : T_POP_IF const T_NEWLINE {
|
||||
;
|
||||
|
||||
elif : T_POP_ELIF const T_NEWLINE {
|
||||
if (nIFDepth <= 0)
|
||||
if (fstk_GetIFDepth() == 0)
|
||||
fatalerror("Found ELIF outside an IF construct\n");
|
||||
|
||||
if (!executeElseBlock) {
|
||||
@@ -585,7 +585,7 @@ elif : T_POP_ELIF const T_NEWLINE {
|
||||
;
|
||||
|
||||
else : T_POP_ELSE T_NEWLINE {
|
||||
if (nIFDepth <= 0)
|
||||
if (fstk_GetIFDepth() == 0)
|
||||
fatalerror("Found ELSE outside an IF construct\n");
|
||||
|
||||
if (!executeElseBlock)
|
||||
@@ -594,10 +594,10 @@ else : T_POP_ELSE T_NEWLINE {
|
||||
;
|
||||
|
||||
endc : T_POP_ENDC T_NEWLINE {
|
||||
if (nIFDepth <= 0)
|
||||
if (fstk_GetIFDepth() == 0)
|
||||
fatalerror("Found ENDC outside an IF construct\n");
|
||||
|
||||
nIFDepth--;
|
||||
fstk_DecIFDepth();
|
||||
executeElseBlock = false;
|
||||
}
|
||||
;
|
||||
|
||||
@@ -20,3 +20,4 @@ rept 1
|
||||
break
|
||||
no endc
|
||||
endr
|
||||
println "done"
|
||||
|
||||
@@ -2,4 +2,5 @@ warning: break.asm(9): [-Wuser]
|
||||
done 5
|
||||
warning: break.asm(17): [-Wuser]
|
||||
OK
|
||||
error: Unterminated IF construct (1 levels)!
|
||||
FATAL: break.asm(18) -> break.asm::REPT~1(23):
|
||||
Ended block with 1 unterminated IF construct
|
||||
|
||||
3
test/asm/unterminated-if-include.inc
Normal file
3
test/asm/unterminated-if-include.inc
Normal file
@@ -0,0 +1,3 @@
|
||||
if 1
|
||||
println "inside include"
|
||||
; no endc
|
||||
15
test/asm/unterminated-if.asm
Normal file
15
test/asm/unterminated-if.asm
Normal file
@@ -0,0 +1,15 @@
|
||||
if 1
|
||||
if 0
|
||||
println "A"
|
||||
elif 1
|
||||
println "B"
|
||||
else
|
||||
println "C"
|
||||
endc
|
||||
else
|
||||
println "D"
|
||||
endc
|
||||
|
||||
INCLUDE "unterminated-if-include.inc"
|
||||
|
||||
println "done"
|
||||
2
test/asm/unterminated-if.err
Normal file
2
test/asm/unterminated-if.err
Normal file
@@ -0,0 +1,2 @@
|
||||
FATAL: unterminated-if.asm(13) -> unterminated-if-include.inc(4):
|
||||
Ended block with 1 unterminated IF construct
|
||||
2
test/asm/unterminated-if.out
Normal file
2
test/asm/unterminated-if.out
Normal file
@@ -0,0 +1,2 @@
|
||||
B
|
||||
inside include
|
||||
Reference in New Issue
Block a user