diff --git a/include/asm/asm.h b/include/asm/asm.h index 609de1c0..1bf97e79 100644 --- a/include/asm/asm.h +++ b/include/asm/asm.h @@ -23,6 +23,7 @@ extern ULONG nTotalLines; extern ULONG nPC; extern ULONG nPass; extern ULONG nIFDepth; +extern bool skipElif; extern char tzCurrentFileName[_MAX_PATH + 1]; extern struct Section *pCurrentSection; extern struct sSymbol *tHashedSymbols[HASHSIZE]; diff --git a/src/asm/asmy.y b/src/asm/asmy.y index 1af450ae..aff6737c 100644 --- a/src/asm/asmy.y +++ b/src/asm/asmy.y @@ -289,70 +289,75 @@ void copymacro( void ) yyskipbytes( ulNewMacroSize+4 ); } -ULONG isIf( char *s ) +ULONG isIf(char *s) { - return( (strncasecmp(s,"If",2)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[2]) ); + return((strncasecmp(s,"If",2) == 0) && isWhiteSpace(s[-1]) && isWhiteSpace(s[2])); } -ULONG isElse( char *s ) +ULONG isElif(char *s) { - return( (strncasecmp(s,"Else",4)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[4]) ); + return((strncasecmp(s,"Elif",4) == 0) && isWhiteSpace(s[-1]) && isWhiteSpace(s[4])); } -ULONG isEndc( char *s ) +ULONG isElse(char *s) { - return( (strncasecmp(s,"Endc",4)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[4]) ); + return((strncasecmp(s,"Else",4) == 0) && isWhiteSpace(s[-1]) && isWhiteSpace(s[4])); } -void if_skip_to_else( void ) +ULONG isEndc(char *s) { - SLONG level=1, len, instring=0; - char *src=pCurrentBuffer->pBuffer; + return((strncasecmp(s,"Endc",4) == 0) && isWhiteSpace(s[-1]) && isWhiteSpace(s[4])); +} - while( *src && level ) - { - if( *src=='\n' ) - nLineNo+=1; +void if_skip_to_else() +{ + SLONG level = 1; + bool inString = false; + char *src=pCurrentBuffer->pBuffer; - if( instring==0 ) - { - if( isIf(src) ) - { - level+=1; - src+=2; - } - else if( level==1 && isElse(src) ) - { - level-=1; - src+=4; - } - else if( isEndc(src) ) - { - level-=1; - if( level!=0 ) - src+=4; - } - else - { - if( *src=='\"' ) - instring=1; - src+=1; - } + while (*src && level) { + if (*src == '\n') { + nLineNo++; } - else - { - if( *src=='\\' ) - { - src+=2; + + if (!inString) { + if (isIf(src)) { + level++; + src += 2; + + } else if (level == 1 && isElif(src)) { + level--; + skipElif = false; + + } else if (level == 1 && isElse(src)) { + level--; + src += 4; + + } else if (isEndc(src)) { + level--; + if (level != 0) { + src += 4; + } + + } else { + if (*src=='\"') { + inString = true; + } + src++; } - else if( *src=='\"' ) - { - src+=1; - instring=0; - } - else - { - src+=1; + } else { + switch (*src) { + case '\\': + src += 2; + break; + + case '\"': + src++; + inString = false; + + default: + src++; + break; } } } @@ -361,57 +366,56 @@ void if_skip_to_else( void ) fatalerror("Unterminated IF construct"); } - len=src-pCurrentBuffer->pBuffer; + SLONG len = src - pCurrentBuffer->pBuffer; - yyskipbytes( len ); - yyunput( '\n' ); - nLineNo-=1; + yyskipbytes(len); + yyunput('\n'); + nLineNo--; } -void if_skip_to_endc( void ) +void if_skip_to_endc() { - SLONG level=1, len, instring=0; - char *src=pCurrentBuffer->pBuffer; + SLONG level = 1; + bool inString = false; + char *src=pCurrentBuffer->pBuffer; - while( *src && level ) - { - if( *src=='\n' ) - nLineNo+=1; + while (*src && level) { + if (*src == '\n') { + nLineNo++; + } - if( instring==0 ) - { - if( isIf(src) ) - { - level+=1; - src+=2; - } - else if( isEndc(src) ) - { - level-=1; - if( level!=0 ) - src+=4; - } - else - { - if( *src=='\"' ) - instring=1; - src+=1; + if (!inString) { + if (isIf(src)) { + level++; + src += 2; + + } else if (isEndc(src)) { + level--; + if (level != 0) { + src += 4; + } + + } else { + if (*src=='\"') { + inString = true; + } + src++; } } - else - { - if( *src=='\\' ) - { - src+=2; - } - else if( *src=='\"' ) - { - src+=1; - instring=0; - } - else - { - src+=1; + else { + switch (*src) { + case '\\': + src += 2; + break; + + case '\"': + src++; + inString = false; + break; + + default: + src++; + break; } } } @@ -420,11 +424,11 @@ void if_skip_to_endc( void ) fatalerror("Unterminated IF construct"); } - len=src-pCurrentBuffer->pBuffer; + SLONG len = src - pCurrentBuffer->pBuffer; - yyskipbytes( len ); - yyunput( '\n' ); - nLineNo-=1; + yyskipbytes(len); + yyunput('\n'); + nLineNo--; } %} @@ -492,7 +496,7 @@ void if_skip_to_endc( void ) %token T_POP_SET %token T_POP_EQUS -%token T_POP_INCLUDE T_POP_PRINTF T_POP_PRINTT T_POP_PRINTV T_POP_IF T_POP_ELSE T_POP_ENDC +%token T_POP_INCLUDE T_POP_PRINTF T_POP_PRINTT T_POP_PRINTV T_POP_IF T_POP_ELIF T_POP_ELSE T_POP_ENDC %token T_POP_IMPORT T_POP_EXPORT T_POP_GLOBAL %token T_POP_DB T_POP_DS T_POP_DW T_POP_DL %token T_POP_SECTION @@ -627,6 +631,7 @@ simple_pseudoop : include | printt | printv | if + | elif | else | endc | import @@ -867,26 +872,47 @@ printf : T_POP_PRINTF const } ; -if : T_POP_IF const - { - nIFDepth+=1; - if( !$2 ) - { - if_skip_to_else(); /* will continue parsing just after ELSE or just at ENDC keyword */ +if : T_POP_IF const { + nIFDepth++; + if (!$2) { + if_skip_to_else(); // Continue parsing after ELSE, or at ELIF or ENDC keyword } - } + }; -else : T_POP_ELSE - { - if_skip_to_endc(); /* will continue parsing just at ENDC keyword */ - } -; +elif : T_POP_ELIF const { + if (nIFDepth <= 0) { + fatalerror("Found ELIF outside an IF construct"); + } -endc : T_POP_ENDC - { - nIFDepth-=1; - } -; + if (skipElif) { + // This is for when ELIF is reached at the end of an IF or ELIF block for which the condition was true. + if_skip_to_endc(); // Continue parsing at ENDC keyword + + } else { + // This is for when ELIF is skipped to because the condition of the previous IF or ELIF block was false. + skipElif = true; + + if (!$2) { + if_skip_to_else(); // Continue parsing after ELSE, or at ELIF or ENDC keyword + } + } + }; + +else : T_POP_ELSE { + if (nIFDepth <= 0) { + fatalerror("Found ELSE outside an IF construct"); + } + + if_skip_to_endc(); // Continue parsing at ENDC keyword + }; + +endc : T_POP_ENDC { + if (nIFDepth <= 0) { + fatalerror("Found ENDC outside an IF construct"); + } + + nIFDepth--; + }; const_3bit : const { diff --git a/src/asm/globlex.c b/src/asm/globlex.c index ee7420d3..6cc74ebd 100644 --- a/src/asm/globlex.c +++ b/src/asm/globlex.c @@ -329,6 +329,7 @@ struct sLexInitString staticstrings[] = { {"if", T_POP_IF}, {"else", T_POP_ELSE}, + {"elif", T_POP_ELIF}, {"endc", T_POP_ENDC}, {"wram0", T_SECT_WRAM0}, diff --git a/src/asm/main.c b/src/asm/main.c index e21c1544..e54b25fc 100644 --- a/src/asm/main.c +++ b/src/asm/main.c @@ -23,6 +23,7 @@ char **cldefines; clock_t nStartClock, nEndClock; SLONG nLineNo; ULONG nTotalLines, nPass, nPC, nIFDepth, nErrors; +bool skipElif; extern int yydebug; @@ -414,6 +415,7 @@ main(int argc, char *argv[]) nLineNo = 1; nTotalLines = 0; nIFDepth = 0; + skipElif = true; nPC = 0; nPass = 1; nErrors = 0; @@ -440,6 +442,7 @@ main(int argc, char *argv[]) nTotalLines = 0; nLineNo = 1; nIFDepth = 0; + skipElif = true; nPC = 0; nPass = 2; nErrors = 0;