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:
Rangi
2021-01-08 16:28:51 -05:00
committed by Eldred Habert
parent 62bea23c49
commit cab9cb06a3
12 changed files with 64 additions and 21 deletions

View File

@@ -25,7 +25,6 @@
#define MAXINCPATHS 128 #define MAXINCPATHS 128
extern uint32_t nTotalLines; extern uint32_t nTotalLines;
extern uint32_t nIFDepth;
extern struct Section *pCurrentSection; extern struct Section *pCurrentSection;
#endif /* RGBDS_ASM_ASM_H */ #endif /* RGBDS_ASM_ASM_H */

View File

@@ -53,6 +53,9 @@ extern size_t nMaxRecursionDepth;
struct MacroArgs; 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_Dump(struct FileStackNode const *node, uint32_t lineNo);
void fstk_DumpCurrent(void); void fstk_DumpCurrent(void);
struct FileStackNode *fstk_GetFileStack(void); struct FileStackNode *fstk_GetFileStack(void);

View File

@@ -31,6 +31,7 @@ struct Context {
struct Context *parent; struct Context *parent;
struct FileStackNode *fileInfo; struct FileStackNode *fileInfo;
struct LexerState *lexerState; struct LexerState *lexerState;
uint32_t nIFDepth;
uint32_t uniqueID; uint32_t uniqueID;
struct MacroArgs *macroArgs; /* Macro args are *saved* here */ struct MacroArgs *macroArgs; /* Macro args are *saved* here */
uint32_t nbReptIters; uint32_t nbReptIters;
@@ -47,7 +48,22 @@ size_t nMaxRecursionDepth;
static unsigned int nbIncPaths = 0; static unsigned int nbIncPaths = 0;
static char const *includePaths[MAXINCPATHS]; 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; char const *name;
@@ -200,6 +216,10 @@ bool fstk_FindFile(char const *path, char **fullPath, size_t *size)
bool yywrap(void) 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 */ if (contextStack->fileInfo->type == NODE_REPT) { /* The context is a REPT block, which may loop */
struct FileStackReptNode *fileInfo = (struct FileStackReptNode *)contextStack->fileInfo; struct FileStackReptNode *fileInfo = (struct FileStackReptNode *)contextStack->fileInfo;
@@ -283,6 +303,7 @@ static void newContext(struct FileStackNode *fileInfo)
fileInfo->referenced = false; fileInfo->referenced = false;
fileInfo->lineNo = lexer_GetLineNo(); fileInfo->lineNo = lexer_GetLineNo();
context->fileInfo = fileInfo; context->fileInfo = fileInfo;
context->nIFDepth = 0;
context->forName = NULL; context->forName = NULL;
/* /*
* Link new entry to its parent so it's reachable later * 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); contextStack->lexerState = lexer_OpenFileView(body, size, reptLineNo);
if (!contextStack->lexerState) 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); lexer_SetStateAtEOL(contextStack->lexerState);
contextStack->uniqueID = macro_UseNewUniqueID(); contextStack->uniqueID = macro_UseNewUniqueID();
return true; return true;
@@ -521,6 +542,7 @@ void fstk_Init(char const *mainPath, size_t maxRecursionDepth)
context->parent = NULL; context->parent = NULL;
context->lexerState = state; context->lexerState = state;
context->nIFDepth = 0;
context->uniqueID = 0; context->uniqueID = 0;
macro_SetUniqueID(0); macro_SetUniqueID(0);
context->nbReptIters = 0; context->nbReptIters = 0;

View File

@@ -1966,7 +1966,7 @@ static int skipIfBlock(bool toEndc)
{ {
dbgPrint("Skipping IF block (toEndc = %s)\n", toEndc ? "true" : "false"); dbgPrint("Skipping IF block (toEndc = %s)\n", toEndc ? "true" : "false");
lexer_SetMode(LEXER_NORMAL); lexer_SetMode(LEXER_NORMAL);
int startingDepth = nIFDepth; int startingDepth = fstk_GetIFDepth();
int token; int token;
bool atLineStart = lexerState->atLineStart; bool atLineStart = lexerState->atLineStart;
@@ -1990,7 +1990,7 @@ static int skipIfBlock(bool toEndc)
token = readIdentifier(c); token = readIdentifier(c);
switch (token) { switch (token) {
case T_POP_IF: case T_POP_IF:
nIFDepth++; fstk_IncIFDepth();
break; break;
case T_POP_ELIF: case T_POP_ELIF:
@@ -1999,10 +1999,10 @@ static int skipIfBlock(bool toEndc)
break; break;
/* fallthrough */ /* fallthrough */
case T_POP_ENDC: case T_POP_ENDC:
if (nIFDepth == startingDepth) if (fstk_GetIFDepth() == startingDepth)
goto finish; goto finish;
if (token == T_POP_ENDC) if (token == T_POP_ENDC)
nIFDepth--; fstk_DecIFDepth();
} }
} }
atLineStart = false; atLineStart = false;
@@ -2087,11 +2087,11 @@ static int yylex_SKIP_TO_ENDR(void)
break; break;
case T_POP_IF: case T_POP_IF:
nIFDepth++; fstk_IncIFDepth();
break; break;
case T_POP_ENDC: case T_POP_ENDC:
nIFDepth--; fstk_DecIFDepth();
} }
} }
atLineStart = false; atLineStart = false;

View File

@@ -46,7 +46,7 @@ const size_t cldefine_entrysize = 2 * sizeof(void *);
char **cldefines; char **cldefines;
clock_t nStartClock, nEndClock; clock_t nStartClock, nEndClock;
uint32_t nTotalLines, nIFDepth; uint32_t nTotalLines;
#if defined(YYDEBUG) && YYDEBUG #if defined(YYDEBUG) && YYDEBUG
extern int yydebug; extern int yydebug;
@@ -488,7 +488,6 @@ int main(int argc, char *argv[])
nStartClock = clock(); nStartClock = clock();
nTotalLines = 0; nTotalLines = 0;
nIFDepth = 0;
sym_Init(now); sym_Init(now);
sym_SetExportAll(exportall); sym_SetExportAll(exportall);
@@ -502,10 +501,6 @@ int main(int argc, char *argv[])
if (dependfile) if (dependfile)
fclose(dependfile); fclose(dependfile);
if (nIFDepth != 0)
errx(1, "Unterminated IF construct (%" PRIu32 " levels)!",
nIFDepth);
sect_CheckUnionClosed(); sect_CheckUnionClosed();
double timespent; double timespent;

View File

@@ -563,7 +563,7 @@ conditional : if
; ;
if : T_POP_IF const T_NEWLINE { if : T_POP_IF const T_NEWLINE {
nIFDepth++; fstk_IncIFDepth();
executeElseBlock = !$2; executeElseBlock = !$2;
if (executeElseBlock) if (executeElseBlock)
lexer_SetMode(LEXER_SKIP_TO_ELIF); lexer_SetMode(LEXER_SKIP_TO_ELIF);
@@ -571,7 +571,7 @@ if : T_POP_IF const T_NEWLINE {
; ;
elif : T_POP_ELIF 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"); fatalerror("Found ELIF outside an IF construct\n");
if (!executeElseBlock) { if (!executeElseBlock) {
@@ -585,7 +585,7 @@ elif : T_POP_ELIF const T_NEWLINE {
; ;
else : T_POP_ELSE T_NEWLINE { else : T_POP_ELSE T_NEWLINE {
if (nIFDepth <= 0) if (fstk_GetIFDepth() == 0)
fatalerror("Found ELSE outside an IF construct\n"); fatalerror("Found ELSE outside an IF construct\n");
if (!executeElseBlock) if (!executeElseBlock)
@@ -594,10 +594,10 @@ else : T_POP_ELSE T_NEWLINE {
; ;
endc : T_POP_ENDC T_NEWLINE { endc : T_POP_ENDC T_NEWLINE {
if (nIFDepth <= 0) if (fstk_GetIFDepth() == 0)
fatalerror("Found ENDC outside an IF construct\n"); fatalerror("Found ENDC outside an IF construct\n");
nIFDepth--; fstk_DecIFDepth();
executeElseBlock = false; executeElseBlock = false;
} }
; ;

View File

@@ -20,3 +20,4 @@ rept 1
break break
no endc no endc
endr endr
println "done"

View File

@@ -2,4 +2,5 @@ warning: break.asm(9): [-Wuser]
done 5 done 5
warning: break.asm(17): [-Wuser] warning: break.asm(17): [-Wuser]
OK OK
error: Unterminated IF construct (1 levels)! FATAL: break.asm(18) -> break.asm::REPT~1(23):
Ended block with 1 unterminated IF construct

View File

@@ -0,0 +1,3 @@
if 1
println "inside include"
; no endc

View 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"

View File

@@ -0,0 +1,2 @@
FATAL: unterminated-if.asm(13) -> unterminated-if-include.inc(4):
Ended block with 1 unterminated IF construct

View File

@@ -0,0 +1,2 @@
B
inside include