X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fca65%2Fcondasm.c;h=8be5cb687851c9b51f5b2ede272847ad7169399e;hb=361da29e51c2eb2a944a0fbfca854a040dd88fdc;hp=5b2bf8ef09e42dbd728547977d640aa44e0c5292;hpb=5ef1f65c9bd9f83ecbb8c66c6d8f8da0dec85e47;p=cc65 diff --git a/src/ca65/condasm.c b/src/ca65/condasm.c index 5b2bf8ef0..8be5cb687 100644 --- a/src/ca65/condasm.c +++ b/src/ca65/condasm.c @@ -1,15 +1,15 @@ /*****************************************************************************/ /* */ -/* condasm.c */ +/* condasm.c */ /* */ -/* Conditional assembly support for ca65 */ +/* Conditional assembly support for ca65 */ /* */ /* */ /* */ -/* (C) 2000-2003 Ullrich von Bassewitz */ -/* Römerstraße 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2000-2011, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -37,6 +37,7 @@ #include "error.h" #include "expr.h" #include "instr.h" +#include "lineinfo.h" #include "nexttok.h" #include "symbol.h" #include "symtab.h" @@ -45,26 +46,30 @@ /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ /* Maximum count of nested .ifs */ -#define MAX_IFS 256 +#define MAX_IFS 256 /* Set of bitmapped flags for the if descriptor */ enum { - ifNone = 0x0000, /* No flag */ - ifCond = 0x0001, /* IF condition was true */ - ifElse = 0x0002, /* We had a .ELSE branch */ - ifNeedTerm = 0x0004 /* Need .ENDIF termination */ + ifNone = 0x0000, /* No flag */ + ifCond = 0x0001, /* IF condition was true */ + ifParentCond= 0x0002, /* IF condition of parent */ + ifElse = 0x0004, /* We had a .ELSE branch */ + ifNeedTerm = 0x0008, /* Need .ENDIF termination */ }; +/* The overall .IF condition */ +int IfCond = 1; + /*****************************************************************************/ -/* struct IfDesc */ +/* struct IfDesc */ /*****************************************************************************/ @@ -72,9 +77,9 @@ enum { /* One .IF descriptor */ typedef struct IfDesc IfDesc; struct IfDesc { - unsigned Flags; /* Bitmapped flags, see above */ - FilePos Pos; /* File position of the .IF */ - const char* Name; /* Name of the directive */ + unsigned Flags; /* Bitmapped flags, see above */ + Collection LineInfos; /* File position of the .IF */ + const char* Name; /* Name of the directive */ }; /* The .IF stack */ @@ -83,70 +88,35 @@ static unsigned IfCount = 0; -static IfDesc* AllocIf (const char* Directive, int NeedTerm) -/* Alloc a new element from the .IF stack */ -{ - IfDesc* ID; - - /* Check for stack overflow */ - if (IfCount >= MAX_IFS) { - Fatal ("Too many nested .IFs"); - } - - /* Alloc one element */ - ID = &IfStack [IfCount++]; - - /* Initialize elements */ - ID->Flags = NeedTerm? ifNeedTerm : ifNone; - ID->Pos = CurPos; - ID->Name = Directive; - - /* Return the result */ - return ID; -} - - - static IfDesc* GetCurrentIf (void) /* Return the current .IF descriptor */ { if (IfCount == 0) { - return 0; + return 0; } else { - return &IfStack [IfCount-1]; + return &IfStack[IfCount-1]; } } -static void FreeIf (void) -/* Free all .IF descriptors until we reach one with the NeedTerm bit set */ +static int GetOverallIfCond (void) +/* Get the overall condition based on all conditions on the stack. */ { - int Done = 0; - do { - IfDesc* D = GetCurrentIf(); - if (D == 0) { - Error (" Unexpected .ENDIF"); - Done = 1; - } else { - Done = (D->Flags & ifNeedTerm) != 0; - --IfCount; - } - } while (!Done); + /* Since the last entry contains the overall condition of the parent, we + * must check it in combination of the current condition. If there is no + * last entry, the overall condition is true. + */ + return (IfCount == 0) || + ((IfStack[IfCount-1].Flags & (ifCond | ifParentCond)) == (ifCond | ifParentCond)); } -static int GetCurrentIfCond (void) -/* Return the current condition based on all conditions on the stack */ +static void CalcOverallIfCond (void) +/* Caclulate the overall condition based on all conditions on the stack. */ { - unsigned Count; - for (Count = 0; Count < IfCount; ++Count) { - if ((IfStack[Count].Flags & ifCond) == 0) { - return 0; - } - } - return 1; + IfCond = GetOverallIfCond (); } @@ -155,44 +125,90 @@ static void SetIfCond (IfDesc* ID, int C) /* Set the .IF condition */ { if (C) { - ID->Flags |= ifCond; + ID->Flags |= ifCond; } else { - ID->Flags &= ~ifCond; + ID->Flags &= ~ifCond; } } -static void InvertIfCond (IfDesc* ID) -/* Invert the current condition */ +static void ElseClause (IfDesc* ID, const char* Directive) +/* Enter an .ELSE clause */ { + /* Check if we have an open .IF - otherwise .ELSE is not allowed */ + if (ID == 0) { + Error ("Unexpected %s", Directive); + return; + } + + /* Check for a duplicate else, then remember that we had one */ + if (ID->Flags & ifElse) { + /* We already had a .ELSE ! */ + Error ("Duplicate .ELSE"); + } + ID->Flags |= ifElse; + + /* Condition is inverted now */ ID->Flags ^= ifCond; } -static int GetElse (const IfDesc* ID) -/* Return true if we had a .ELSE */ +static IfDesc* AllocIf (const char* Directive, int NeedTerm) +/* Alloc a new element from the .IF stack */ { - return (ID->Flags & ifElse) != 0; + IfDesc* ID; + + /* Check for stack overflow */ + if (IfCount >= MAX_IFS) { + Fatal ("Too many nested .IFs"); + } + + /* Get the next element */ + ID = &IfStack[IfCount]; + + /* Initialize elements */ + ID->Flags = NeedTerm? ifNeedTerm : ifNone; + if (GetOverallIfCond ()) { + /* The parents .IF condition is true */ + ID->Flags |= ifParentCond; + } + ID->LineInfos = EmptyCollection; + GetFullLineInfo (&ID->LineInfos); + ID->Name = Directive; + + /* One more slot allocated */ + ++IfCount; + + /* Return the result */ + return ID; } -static void SetElse (IfDesc* ID, int E) -/* Set the .ELSE flag */ +static void FreeIf (void) +/* Free all .IF descriptors until we reach one with the NeedTerm bit set */ { - if (E) { - ID->Flags |= ifElse; - } else { - ID->Flags &= ~ifElse; - } + int Done; + do { + IfDesc* ID = GetCurrentIf(); + if (ID == 0) { + Error (" Unexpected .ENDIF"); + Done = 1; + } else { + Done = (ID->Flags & ifNeedTerm) != 0; + ReleaseFullLineInfo (&ID->LineInfos); + DoneCollection (&ID->LineInfos); + --IfCount; + } + } while (!Done); } /*****************************************************************************/ -/* Code */ +/* Code */ /*****************************************************************************/ @@ -202,213 +218,222 @@ void DoConditionals (void) { IfDesc* D; - int IfCond = GetCurrentIfCond (); do { - switch (Tok) { - - case TOK_ELSE: - D = GetCurrentIf (); - if (D == 0) { - Error ("Unexpected .ELSE"); - } else if (GetElse(D)) { - /* We already had a .ELSE ! */ - Error ("Duplicate .ELSE"); - } else { - /* Allow an .ELSE */ - InvertIfCond (D); - SetElse (D, 1); - D->Pos = CurPos; - D->Name = ".ELSE"; - IfCond = GetCurrentIfCond (); - } - NextTok (); - break; - - case TOK_ELSEIF: - D = GetCurrentIf (); - if (D == 0) { - Error ("Unexpected .ELSEIF"); - } else if (GetElse(D)) { - /* We already had a .ELSE */ - Error ("Duplicate .ELSE"); - } else { - /* Handle as if there was an .ELSE first */ - InvertIfCond (D); - SetElse (D, 1); - - /* Allocate and prepare a new descriptor */ - D = AllocIf (".ELSEIF", 0); - NextTok (); - - /* Ignore the new condition if we are inside a false .ELSE - * branch. This way we won't get any errors about undefined - * symbols or similar... - */ - if (IfCond == 0) { - SetIfCond (D, ConstExpression ()); - } - - /* Get the new overall condition */ - IfCond = GetCurrentIfCond (); - } - break; - - case TOK_ENDIF: - /* We're done with this .IF.. - remove the descriptor(s) */ - FreeIf (); - - /* Be sure not to read the next token until the .IF stack - * has been cleanup up, since we may be at end of file. - */ - NextTok (); - - /* Get the new overall condition */ - IfCond = GetCurrentIfCond (); - break; - - case TOK_IF: - D = AllocIf (".IF", 1); - NextTok (); - if (IfCond) { - SetIfCond (D, ConstExpression ()); - } - IfCond = GetCurrentIfCond (); - break; - - case TOK_IFBLANK: - D = AllocIf (".IFBLANK", 1); - NextTok (); - if (IfCond) { - if (TokIsSep (Tok)) { + switch (CurTok.Tok) { + + case TOK_ELSE: + D = GetCurrentIf (); + + /* Allow an .ELSE */ + ElseClause (D, ".ELSE"); + + /* Remember the data for the .ELSE */ + if (D) { + ReleaseFullLineInfo (&D->LineInfos); + GetFullLineInfo (&D->LineInfos); + D->Name = ".ELSE"; + } + + /* Calculate the new overall condition */ + CalcOverallIfCond (); + + /* Skip .ELSE */ + NextTok (); + ExpectSep (); + break; + + case TOK_ELSEIF: + D = GetCurrentIf (); + /* Handle as if there was an .ELSE first */ + ElseClause (D, ".ELSEIF"); + + /* Calculate the new overall if condition */ + CalcOverallIfCond (); + + /* Allocate and prepare a new descriptor */ + D = AllocIf (".ELSEIF", 0); + NextTok (); + + /* Ignore the new condition if we are inside a false .ELSE + * branch. This way we won't get any errors about undefined + * symbols or similar... + */ + if (IfCond) { + SetIfCond (D, ConstExpression ()); + ExpectSep (); + } + + /* Get the new overall condition */ + CalcOverallIfCond (); + break; + + case TOK_ENDIF: + /* We're done with this .IF.. - remove the descriptor(s) */ + FreeIf (); + + /* Be sure not to read the next token until the .IF stack + * has been cleanup up, since we may be at end of file. + */ + NextTok (); + ExpectSep (); + + /* Get the new overall condition */ + CalcOverallIfCond (); + break; + + case TOK_IF: + D = AllocIf (".IF", 1); + NextTok (); + if (IfCond) { + SetIfCond (D, ConstExpression ()); + ExpectSep (); + } + CalcOverallIfCond (); + break; + + case TOK_IFBLANK: + D = AllocIf (".IFBLANK", 1); + NextTok (); + if (IfCond) { + if (TokIsSep (CurTok.Tok)) { SetIfCond (D, 1); } else { - SetIfCond (D, 0); + SetIfCond (D, 0); SkipUntilSep (); } - } - IfCond = GetCurrentIfCond (); - break; - - case TOK_IFCONST: - D = AllocIf (".IFCONST", 1); - NextTok (); - if (IfCond) { - ExprNode* Expr = Expression(); - SetIfCond (D, IsConstExpr (Expr, 0)); - FreeExpr (Expr); - } - IfCond = GetCurrentIfCond (); - break; - - case TOK_IFDEF: - D = AllocIf (".IFDEF", 1); - NextTok (); - if (IfCond) { - SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING); - SetIfCond (D, Sym != 0 && SymIsDef (Sym)); - } - IfCond = GetCurrentIfCond (); - break; - - case TOK_IFNBLANK: - D = AllocIf (".IFNBLANK", 1); - NextTok (); - if (IfCond) { - if (TokIsSep (Tok)) { + } + CalcOverallIfCond (); + break; + + case TOK_IFCONST: + D = AllocIf (".IFCONST", 1); + NextTok (); + if (IfCond) { + ExprNode* Expr = Expression(); + SetIfCond (D, IsConstExpr (Expr, 0)); + FreeExpr (Expr); + ExpectSep (); + } + CalcOverallIfCond (); + break; + + case TOK_IFDEF: + D = AllocIf (".IFDEF", 1); + NextTok (); + if (IfCond) { + SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING); + SetIfCond (D, Sym != 0 && SymIsDef (Sym)); + } + CalcOverallIfCond (); + break; + + case TOK_IFNBLANK: + D = AllocIf (".IFNBLANK", 1); + NextTok (); + if (IfCond) { + if (TokIsSep (CurTok.Tok)) { SetIfCond (D, 0); } else { - SetIfCond (D, 1); + SetIfCond (D, 1); SkipUntilSep (); } - } - IfCond = GetCurrentIfCond (); - break; - - case TOK_IFNCONST: - D = AllocIf (".IFNCONST", 1); - NextTok (); - if (IfCond) { - ExprNode* Expr = Expression(); - SetIfCond (D, !IsConstExpr (Expr, 0)); - FreeExpr (Expr); - } - IfCond = GetCurrentIfCond (); - break; - - case TOK_IFNDEF: - D = AllocIf (".IFNDEF", 1); - NextTok (); - if (IfCond) { - SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING); - SetIfCond (D, Sym == 0 || !SymIsDef (Sym)); - } - IfCond = GetCurrentIfCond (); - break; - - case TOK_IFNREF: - D = AllocIf (".IFNREF", 1); - NextTok (); - if (IfCond) { - SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING); - SetIfCond (D, Sym == 0 || !SymIsRef (Sym)); - } - IfCond = GetCurrentIfCond (); - break; - - case TOK_IFP02: - D = AllocIf (".IFP02", 1); - NextTok (); - if (IfCond) { - SetIfCond (D, GetCPU() == CPU_6502); - } - IfCond = GetCurrentIfCond (); - break; - - case TOK_IFP816: - D = AllocIf (".IFP816", 1); - NextTok (); - if (IfCond) { - SetIfCond (D, GetCPU() == CPU_65816); - } - IfCond = GetCurrentIfCond (); - break; - - case TOK_IFPC02: - D = AllocIf (".IFPC02", 1); - NextTok (); - if (IfCond) { - SetIfCond (D, GetCPU() == CPU_65C02); - } - IfCond = GetCurrentIfCond (); - break; - - case TOK_IFPSC02: - D = AllocIf (".IFPSC02", 1); - NextTok (); - if (IfCond) { - SetIfCond (D, GetCPU() == CPU_65SC02); - } - IfCond = GetCurrentIfCond (); - break; - - case TOK_IFREF: - D = AllocIf (".IFREF", 1); - NextTok (); - if (IfCond) { - SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING); - SetIfCond (D, Sym != 0 && SymIsRef (Sym)); - } - IfCond = GetCurrentIfCond (); - break; - - default: - /* Skip tokens */ - NextTok (); - - } - - } while (IfCond == 0 && Tok != TOK_EOF); + } + CalcOverallIfCond (); + break; + + case TOK_IFNCONST: + D = AllocIf (".IFNCONST", 1); + NextTok (); + if (IfCond) { + ExprNode* Expr = Expression(); + SetIfCond (D, !IsConstExpr (Expr, 0)); + FreeExpr (Expr); + ExpectSep (); + } + CalcOverallIfCond (); + break; + + case TOK_IFNDEF: + D = AllocIf (".IFNDEF", 1); + NextTok (); + if (IfCond) { + SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING); + SetIfCond (D, Sym == 0 || !SymIsDef (Sym)); + ExpectSep (); + } + CalcOverallIfCond (); + break; + + case TOK_IFNREF: + D = AllocIf (".IFNREF", 1); + NextTok (); + if (IfCond) { + SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING); + SetIfCond (D, Sym == 0 || !SymIsRef (Sym)); + ExpectSep (); + } + CalcOverallIfCond (); + break; + + case TOK_IFP02: + D = AllocIf (".IFP02", 1); + NextTok (); + if (IfCond) { + SetIfCond (D, GetCPU() == CPU_6502); + } + ExpectSep (); + CalcOverallIfCond (); + break; + + case TOK_IFP816: + D = AllocIf (".IFP816", 1); + NextTok (); + if (IfCond) { + SetIfCond (D, GetCPU() == CPU_65816); + } + ExpectSep (); + CalcOverallIfCond (); + break; + + case TOK_IFPC02: + D = AllocIf (".IFPC02", 1); + NextTok (); + if (IfCond) { + SetIfCond (D, GetCPU() == CPU_65C02); + } + ExpectSep (); + CalcOverallIfCond (); + break; + + case TOK_IFPSC02: + D = AllocIf (".IFPSC02", 1); + NextTok (); + if (IfCond) { + SetIfCond (D, GetCPU() == CPU_65SC02); + } + ExpectSep (); + CalcOverallIfCond (); + break; + + case TOK_IFREF: + D = AllocIf (".IFREF", 1); + NextTok (); + if (IfCond) { + SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING); + SetIfCond (D, Sym != 0 && SymIsRef (Sym)); + ExpectSep (); + } + CalcOverallIfCond (); + break; + + default: + /* Skip tokens */ + NextTok (); + + } + + } while (IfCond == 0 && CurTok.Tok != TOK_EOF); } @@ -419,7 +444,7 @@ int CheckConditionals (void) * return false otherwise. */ { - switch (Tok) { + switch (CurTok.Tok) { case TOK_ELSE: case TOK_ELSEIF: case TOK_ENDIF: @@ -451,25 +476,31 @@ void CheckOpenIfs (void) * open .ifs in this file. */ { + const LineInfo* LI; + while (1) { - /* Get the current file number and check if the topmost entry on the - * .IF stack was inserted with this file number - */ - IfDesc* D = GetCurrentIf (); - if (D == 0) { - /* There are no open .IFs */ - break; - } - - if (D->Pos.Name != CurPos.Name) { - /* The .if is from another file, bail out */ - break; - } - - /* Start of .if is in the file we're about to leave */ - PError (&D->Pos, "Conditional assembly branch was never closed"); - FreeIf (); + /* Get the current file number and check if the topmost entry on the + * .IF stack was inserted with this file number + */ + IfDesc* D = GetCurrentIf (); + if (D == 0) { + /* There are no open .IFs */ + break; + } + + LI = CollConstAt (&D->LineInfos, 0); + if (GetSourcePos (LI)->Name != CurTok.Pos.Name) { + /* The .if is from another file, bail out */ + break; + } + + /* Start of .if is in the file we're about to leave */ + LIError (&D->LineInfos, "Conditional assembly branch was never closed"); + FreeIf (); } + + /* Calculate the new overall .IF condition */ + CalcOverallIfCond (); } @@ -486,9 +517,13 @@ void CleanupIfStack (unsigned SP) /* Cleanup the .IF stack, remove anything above the given stack pointer */ { while (IfCount > SP) { - FreeIf (); + FreeIf (); } + + /* Calculate the new overall .IF condition */ + CalcOverallIfCond (); } +