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
extern uint32_t nTotalLines;
extern uint32_t nIFDepth;
extern struct Section *pCurrentSection;
#endif /* RGBDS_ASM_ASM_H */

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}
;

View File

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

View File

@@ -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

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