diff --git a/src/ca65/condasm.c b/src/ca65/condasm.c index 7cd3310b3..5f542ad87 100644 --- a/src/ca65/condasm.c +++ b/src/ca65/condasm.c @@ -194,7 +194,7 @@ static void FreeIf (void) { int Done; do { - IfDesc* ID = GetCurrentIf(); + IfDesc* ID = GetCurrentIf (); if (ID == 0) { Error (" Unexpected .ENDIF"); Done = 1; @@ -318,7 +318,7 @@ void DoConditionals (void) D = AllocIf (".IFCONST", 1); NextTok (); if (IfCond) { - ExprNode* Expr = Expression(); + ExprNode* Expr = Expression (); SetIfCond (D, IsConstExpr (Expr, 0)); FreeExpr (Expr); ExpectSep (); @@ -354,7 +354,7 @@ void DoConditionals (void) D = AllocIf (".IFNCONST", 1); NextTok (); if (IfCond) { - ExprNode* Expr = Expression(); + ExprNode* Expr = Expression (); SetIfCond (D, !IsConstExpr (Expr, 0)); FreeExpr (Expr); ExpectSep (); @@ -388,7 +388,7 @@ void DoConditionals (void) D = AllocIf (".IFP02", 1); NextTok (); if (IfCond) { - SetIfCond (D, GetCPU() == CPU_6502); + SetIfCond (D, GetCPU () == CPU_6502); } ExpectSep (); CalcOverallIfCond (); @@ -398,7 +398,7 @@ void DoConditionals (void) D = AllocIf (".IFP02X", 1); NextTok (); if (IfCond) { - SetIfCond (D, GetCPU() == CPU_6502X); + SetIfCond (D, GetCPU () == CPU_6502X); } ExpectSep (); CalcOverallIfCond (); @@ -408,7 +408,7 @@ void DoConditionals (void) D = AllocIf (".IFP4510", 1); NextTok (); if (IfCond) { - SetIfCond (D, GetCPU() == CPU_4510); + SetIfCond (D, GetCPU () == CPU_4510); } ExpectSep (); CalcOverallIfCond (); @@ -418,7 +418,7 @@ void DoConditionals (void) D = AllocIf (".IFP45GS02", 1); NextTok (); if (IfCond) { - SetIfCond (D, GetCPU() == CPU_45GS02); + SetIfCond (D, GetCPU () == CPU_45GS02); } ExpectSep (); CalcOverallIfCond (); @@ -428,7 +428,7 @@ void DoConditionals (void) D = AllocIf (".IFP6280", 1); NextTok (); if (IfCond) { - SetIfCond (D, GetCPU() == CPU_HUC6280); + SetIfCond (D, GetCPU () == CPU_HUC6280); } ExpectSep (); CalcOverallIfCond (); @@ -438,7 +438,7 @@ void DoConditionals (void) D = AllocIf (".IFP816", 1); NextTok (); if (IfCond) { - SetIfCond (D, GetCPU() == CPU_65816); + SetIfCond (D, GetCPU () == CPU_65816); } ExpectSep (); CalcOverallIfCond (); @@ -448,7 +448,7 @@ void DoConditionals (void) D = AllocIf (".IFPC02", 1); NextTok (); if (IfCond) { - SetIfCond (D, GetCPU() == CPU_65C02); + SetIfCond (D, GetCPU () == CPU_65C02); } ExpectSep (); CalcOverallIfCond (); @@ -458,7 +458,7 @@ void DoConditionals (void) D = AllocIf (".IFPCE02", 1); NextTok (); if (IfCond) { - SetIfCond (D, GetCPU() == CPU_65CE02); + SetIfCond (D, GetCPU () == CPU_65CE02); } ExpectSep (); CalcOverallIfCond (); @@ -468,7 +468,7 @@ void DoConditionals (void) D = AllocIf (".IFPDTV", 1); NextTok (); if (IfCond) { - SetIfCond (D, GetCPU() == CPU_6502DTV); + SetIfCond (D, GetCPU () == CPU_6502DTV); } ExpectSep (); CalcOverallIfCond (); @@ -478,7 +478,7 @@ void DoConditionals (void) D = AllocIf (".IFPM740", 1); NextTok (); if (IfCond) { - SetIfCond (D, GetCPU() == CPU_M740); + SetIfCond (D, GetCPU () == CPU_M740); } ExpectSep (); CalcOverallIfCond (); @@ -488,7 +488,7 @@ void DoConditionals (void) D = AllocIf (".IFPSC02", 1); NextTok (); if (IfCond) { - SetIfCond (D, GetCPU() == CPU_65SC02); + SetIfCond (D, GetCPU () == CPU_65SC02); } ExpectSep (); CalcOverallIfCond (); @@ -498,7 +498,7 @@ void DoConditionals (void) D = AllocIf (".IFPSWEET16", 1); NextTok (); if (IfCond) { - SetIfCond (D, GetCPU() == CPU_SWEET16); + SetIfCond (D, GetCPU () == CPU_SWEET16); } ExpectSep (); CalcOverallIfCond (); @@ -508,7 +508,7 @@ void DoConditionals (void) D = AllocIf (".IFPWC02", 1); NextTok (); if (IfCond) { - SetIfCond (D, GetCPU() == CPU_W65C02); + SetIfCond (D, GetCPU () == CPU_W65C02); } ExpectSep (); CalcOverallIfCond (); diff --git a/src/ca65/dbginfo.c b/src/ca65/dbginfo.c index c9dd7ab6d..efc685eb6 100644 --- a/src/ca65/dbginfo.c +++ b/src/ca65/dbginfo.c @@ -238,8 +238,7 @@ void DbgInfoFunc (void) ConsumeComma (); /* Type */ - if (CurTok.Tok != TOK_STRCON) { - ErrorSkip ("String constant expected"); + if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) { return; } Type = ValidateType (&CurTok.SVal); @@ -267,8 +266,7 @@ void DbgInfoFunc (void) ConsumeComma (); /* Assembler name follows */ - if (CurTok.Tok != TOK_STRCON) { - ErrorSkip ("String constant expected"); + if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) { return; } AsmName = GetStrBufId (&CurTok.SVal); @@ -321,8 +319,7 @@ void DbgInfoLine (void) ConsumeComma (); /* The name of the file follows */ - if (CurTok.Tok != TOK_STRCON) { - ErrorSkip ("String constant expected"); + if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) { return; } @@ -371,8 +368,7 @@ void DbgInfoSym (void) ConsumeComma (); /* Name */ - if (CurTok.Tok != TOK_STRCON) { - ErrorSkip ("String constant expected"); + if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) { return; } Name = GetStrBufId (&CurTok.SVal); @@ -382,8 +378,7 @@ void DbgInfoSym (void) ConsumeComma (); /* Type */ - if (CurTok.Tok != TOK_STRCON) { - ErrorSkip ("String constant expected"); + if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) { return; } Type = ValidateType (&CurTok.SVal); @@ -418,8 +413,7 @@ void DbgInfoSym (void) Offs = ConstExpression (); } else { /* Register, extern or static: Assembler name follows */ - if (CurTok.Tok != TOK_STRCON) { - ErrorSkip ("String constant expected"); + if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) { return; } AsmName = GetStrBufId (&CurTok.SVal); diff --git a/src/ca65/ea65.c b/src/ca65/ea65.c index 898b344ca..50a0f6de1 100644 --- a/src/ca65/ea65.c +++ b/src/ca65/ea65.c @@ -62,11 +62,11 @@ void GetEA (EffAddr* A) if (BracketAsIndirect) { IndirectEnter = TOK_LBRACK; IndirectLeave = TOK_RBRACK; - IndirectExpect = "']' expected"; + IndirectExpect = "Expected ']'"; } else { IndirectEnter = TOK_LPAREN; IndirectLeave = TOK_RPAREN; - IndirectExpect = "')' expected"; + IndirectExpect = "Expected ')'"; } /* Clear the output struct */ @@ -136,16 +136,22 @@ void GetEA (EffAddr* A) /* (adr,x) */ NextTok (); A->AddrModeSet = AM65_ABS_X_IND | AM65_DIR_X_IND; - Consume (IndirectLeave, IndirectExpect); + if (!Consume (IndirectLeave, IndirectExpect)) { + SkipUntilSep (); + } } else if (CurTok.Tok == TOK_S) { /* (rel,s),y */ NextTok (); A->AddrModeSet = AM65_STACK_REL_IND_Y; - Consume (IndirectLeave, IndirectExpect); - ConsumeComma (); - Consume (TOK_Y, "'Y' expected"); + if (!Consume (IndirectLeave, IndirectExpect) || + !ConsumeComma () || + !Consume (TOK_Y, "Expected 'Y'")) { + /* In case of errors skip anything else on the line */ + SkipUntilSep (); + } } else { - Error ("Syntax error"); + ErrorExpect ("Expected 'X' or 'S'"); + SkipUntilSep (); } } else { @@ -162,7 +168,9 @@ void GetEA (EffAddr* A) A->AddrModeSet = AM65_DIR_IND; break; default: - Consume (TOK_Y, "'Y' expected"); + if (!Consume (TOK_Y, "Expected 'Y'")) { + SkipUntilSep (); + } A->AddrModeSet = AM65_DIR_IND_Y; break; } @@ -190,16 +198,22 @@ void GetEA (EffAddr* A) /* [dir] or [dir],y */ NextTok (); A->Expr = Expression (); - Consume (TOK_RBRACK, "']' expected"); + if (!Consume (TOK_RBRACK, "Expected ']'")) { + SkipUntilSep (); + } if (CurTok.Tok == TOK_COMMA) { /* [dir],y */ NextTok (); if (GetCPU () == CPU_45GS02) { - Consume (TOK_Z, "'Z' expected"); + if (!Consume (TOK_Z, "Expected 'Z'")) { + SkipUntilSep (); + } A->AddrModeSet = AM65_32BIT_BASE_IND_Z; } else { - Consume (TOK_Y, "'Y' expected"); + if (!Consume (TOK_Y, "Expected 'Y'")) { + SkipUntilSep (); + } A->AddrModeSet = AM65_DIR_IND_LONG_Y; } } else { diff --git a/src/ca65/easw16.c b/src/ca65/easw16.c index 081828991..aea52f034 100644 --- a/src/ca65/easw16.c +++ b/src/ca65/easw16.c @@ -96,7 +96,7 @@ void GetSweet16EA (EffAddr* A) /* Register number */ A->Reg = (unsigned) Reg; } else { - ErrorSkip ("Register or register number expected"); + ErrorExpect ("Expected register or register number"); A->Reg = 0; } diff --git a/src/ca65/enum.c b/src/ca65/enum.c index 339b3230f..586d9b67f 100644 --- a/src/ca65/enum.c +++ b/src/ca65/enum.c @@ -87,12 +87,13 @@ void DoEnum (void) continue; } + /* Allow conditionals within an enum */ + if (CheckConditionals ()) { + continue; + } + /* The format is "identifier [ = value ]" */ - if (CurTok.Tok != TOK_IDENT) { - /* Maybe it's a conditional? */ - if (!CheckConditionals ()) { - ErrorSkip ("Identifier expected"); - } + if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) { continue; } diff --git a/src/ca65/error.c b/src/ca65/error.c index 78941b5c2..28ff6aa59 100644 --- a/src/ca65/error.c +++ b/src/ca65/error.c @@ -108,18 +108,6 @@ static void VPrintMsg (const FilePos* Pos, const char* Desc, -static void PrintMsg (const FilePos* Pos, const char* Desc, - const char* Format, ...) -/* Format and output an error/warning message. */ -{ - va_list ap; - va_start (ap, Format); - VPrintMsg (Pos, Desc, Format, ap); - va_end (ap); -} - - - static void AddNotifications (const Collection* LineInfos) /* Output additional notifications for an error or warning */ { @@ -165,7 +153,7 @@ static void AddNotifications (const Collection* LineInfos) /* Output until an upper limit of messages is reached */ if (Msg) { if (Output < MAX_NOTES) { - PrintMsg (GetSourcePos (LI), "Note", "%s", Msg); + PNotification (GetSourcePos (LI), "%s", Msg); ++Output; } else { ++Skipped; @@ -176,13 +164,31 @@ static void AddNotifications (const Collection* LineInfos) /* Add a note if we have more stuff that we won't output */ if (Skipped > 0) { const LineInfo* LI = CollConstAt (LineInfos, 0); - PrintMsg (GetSourcePos (LI), "Note", - "Dropping %u additional line infos", Skipped); + PNotification (GetSourcePos (LI), "Dropping %u additional line infos", + Skipped); } } +/*****************************************************************************/ +/* Notifications */ +/*****************************************************************************/ + + + +void PNotification (const FilePos* Pos, const char* Format, ...) +/* Print a notification message. */ +{ + /* Output the message */ + va_list ap; + va_start (ap, Format); + VPrintMsg (Pos, "Note", Format, ap); + va_end (ap); +} + + + /*****************************************************************************/ /* Warnings */ /*****************************************************************************/ diff --git a/src/ca65/error.h b/src/ca65/error.h index c6fb4f44e..a55ceb8e4 100644 --- a/src/ca65/error.h +++ b/src/ca65/error.h @@ -72,6 +72,9 @@ extern unsigned WarningCount; +void PNotification (const FilePos* Pos, const char* Format, ...) attribute ((format (printf, 2, 3))); +/* Print a notification message. */ + void Warning (unsigned Level, const char* Format, ...) attribute ((format (printf, 2, 3))); /* Print warning message. */ diff --git a/src/ca65/expr.c b/src/ca65/expr.c index 33984610d..6b1b9fa12 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -421,8 +421,7 @@ static ExprNode* FuncCapability (void) capability_t Cap; /* We must have an identifier */ - if (CurTok.Tok != TOK_IDENT) { - Error ("Arguments to .CAPABILITY must be identifiers"); + if (!Expect (TOK_IDENT, "Expected a capability name")) { /* Skip tokens until closing paren or end of line */ while (CurTok.Tok != TOK_RPAREN && !TokIsSep (CurTok.Tok)) { NextTok (); @@ -942,8 +941,7 @@ static ExprNode* FuncStrAt (void) unsigned char C = 0; /* String constant expected */ - if (CurTok.Tok != TOK_STRCON) { - Error ("String constant expected"); + if (!Expect (TOK_STRCON, "Expected a string constant")) { NextTok (); goto ExitPoint; } @@ -985,9 +983,8 @@ static ExprNode* FuncStrLen (void) int Len; /* String constant expected */ - if (CurTok.Tok != TOK_STRCON) { + if (!Expect (TOK_STRCON, "Expected a string constant")) { - Error ("String constant expected"); /* Smart error recovery */ if (CurTok.Tok != TOK_RPAREN) { NextTok (); @@ -1062,9 +1059,7 @@ static ExprNode* Function (ExprNode* (*F) (void)) NextTok (); /* Expression must be enclosed in braces */ - if (CurTok.Tok != TOK_LPAREN) { - Error ("'(' expected"); - SkipUntilSep (); + if (!ExpectSkip (TOK_LPAREN, "Expected '('")) { return GenLiteral0 (); } NextTok (); @@ -1296,7 +1291,7 @@ static ExprNode* Factor (void) NextTok (); } else { N = GenLiteral0 (); /* Dummy */ - Error ("Syntax error"); + ErrorExpect ("Expected an expression"); } break; } @@ -1957,9 +1952,8 @@ ExprNode* GenNearAddrExpr (ExprNode* Expr) if (IsEasyConst (Expr, &Val)) { FreeExpr (Expr); Expr = GenLiteralExpr (Val & 0xFFFF); - if (Val > 0xFFFF) - { - Error("Range error: constant too large for assumed near address."); + if (Val > 0xFFFF) { + Error ("Range error: constant too large for assumed near address."); } } else { ExprNode* Operand = Expr; diff --git a/src/ca65/instr.c b/src/ca65/instr.c index d38a42843..5bf1418c5 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -2091,7 +2091,7 @@ static void PutBitBranch_m740 (const InsDesc* Ins) EffAddr A; /* Evaluate the addressing mode used */ - GetEA(&A); + GetEA (&A); /* From the possible addressing modes, remove the ones that are invalid ** for this instruction or CPU. @@ -2375,7 +2375,7 @@ static void PutJSR_m740 (const InsDesc* Ins) /* direct page */ A.Opcode = 0x22; Emit0 (A.Opcode); - EmitByte(GenByteExpr(A.Expr)); + EmitByte (GenByteExpr (A.Expr)); return; } } diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 904c80756..55b718957 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -102,10 +102,12 @@ struct Macro { unsigned TokCount; /* Number of tokens for this macro */ TokNode* TokRoot; /* Root of token list */ TokNode* TokLast; /* Pointer to last token in list */ + FilePos DefPos; /* Position of definition */ StrBuf Name; /* Macro name, dynamically allocated */ unsigned Expansions; /* Number of active macro expansions */ unsigned char Style; /* Macro style */ unsigned char Incomplete; /* Macro is currently built */ + unsigned char HasError; /* Macro has errors */ }; /* Hash table functions */ @@ -232,7 +234,7 @@ static void FreeIdDescList (IdDesc* ID) -static Macro* NewMacro (const StrBuf* Name, unsigned char Style) +static Macro* NewMacro (const StrBuf* Name, const FilePos* P, unsigned char Style) /* Generate a new macro entry, initialize and return it */ { /* Allocate memory */ @@ -247,11 +249,14 @@ static Macro* NewMacro (const StrBuf* Name, unsigned char Style) M->TokCount = 0; M->TokRoot = 0; M->TokLast = 0; + M->DefPos = *P; SB_Init (&M->Name); SB_Copy (&M->Name, Name); + SB_Terminate (&M->Name); /* So the name can be used with %s */ M->Expansions = 0; M->Style = Style; M->Incomplete = 1; + M->HasError = 0; /* Insert the macro into the hash table */ HT_Insert (&MacroTab, &M->Node); @@ -364,19 +369,28 @@ static void FreeMacExp (MacExp* E) -static void MacSkipDef (unsigned Style) +static void MacSkipDef (unsigned Style, const FilePos* StartPos) /* Skip a macro definition */ { if (Style == MAC_STYLE_CLASSIC) { - /* Skip tokens until we reach the final .endmacro */ - while (CurTok.Tok != TOK_ENDMACRO && CurTok.Tok != TOK_EOF) { + /* Skip tokens until we reach the final .endmacro. Implement the same + ** behavior as when parsing the macro regularily: .endmacro needs to + ** be at the start of the line to end the macro definition. + */ + int LastWasSep = 0; + while (1) { + if (CurTok.Tok == TOK_EOF) { + ErrorExpect ("Expected '.ENDMACRO'"); + PNotification (StartPos, "Macro definition started here"); + break; + } + if (CurTok.Tok == TOK_ENDMACRO && LastWasSep) { + NextTok (); + break; + } + LastWasSep = (CurTok.Tok == TOK_SEP); NextTok (); } - if (CurTok.Tok != TOK_EOF) { - SkipUntilSep (); - } else { - Error ("'.ENDMACRO' expected"); - } } else { /* Skip until end of line */ SkipUntilSep (); @@ -388,48 +402,49 @@ static void MacSkipDef (unsigned Style) void MacDef (unsigned Style) /* Parse a macro definition */ { + Macro* Existing; Macro* M; TokNode* N; - FilePos Pos; int HaveParams; - int LastTokWasSep; + + /* Remember the current file position */ + FilePos StartPos = CurTok.Pos; /* For classic macros, remember if we are at the beginning of the line. ** If the macro name and parameters pass our checks then we will be on a ** new line, so set it now */ - LastTokWasSep = 1; - - /* Save the position of the start of the macro definition to allow - ** using Perror to display the error if .endmacro isn't found - */ - Pos = CurTok.Pos; + int LastTokWasSep = 1; /* We expect a macro name here */ - if (CurTok.Tok != TOK_IDENT) { - Error ("Identifier expected"); - MacSkipDef (Style); + if (!Expect (TOK_IDENT, "Expected an identifier")) { + MacSkipDef (Style, &StartPos); return; - } else if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) { + } + if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) { /* The identifier is a name of a 6502 instruction, which is not ** allowed if not explicitly enabled. */ Error ("Cannot use an instruction as macro name"); - MacSkipDef (Style); + MacSkipDef (Style, &StartPos); return; } /* Did we already define that macro? */ - if (HT_Find (&MacroTab, &CurTok.SVal) != 0) { + Existing = HT_Find (&MacroTab, &CurTok.SVal); + if (Existing != 0) { /* Macro is already defined */ Error ("A macro named '%m%p' is already defined", &CurTok.SVal); + PNotification (&Existing->DefPos, + "Previous definition of macro '%s' was here", + SB_GetConstBuf (&Existing->Name)); /* Skip tokens until we reach the final .endmacro */ - MacSkipDef (Style); + MacSkipDef (Style, &StartPos); return; } /* Define the macro */ - M = NewMacro (&CurTok.SVal, Style); + M = NewMacro (&CurTok.SVal, &StartPos, Style); /* Switch to raw token mode and skip the macro name */ EnterRawTokenMode (); @@ -439,7 +454,7 @@ void MacDef (unsigned Style) ** otherwise, we may have parameters without parentheses. */ if (Style == MAC_STYLE_CLASSIC) { - HaveParams = 1; + HaveParams = (CurTok.Tok != TOK_SEP); } else { if (CurTok.Tok == TOK_LPAREN) { HaveParams = 1; @@ -451,7 +466,7 @@ void MacDef (unsigned Style) /* Parse the parameter list */ if (HaveParams) { - while (CurTok.Tok == TOK_IDENT) { + while (Expect (TOK_IDENT, "Expected a parameter name")) { /* Create a struct holding the identifier */ IdDesc* I = NewIdDesc (&CurTok.SVal); @@ -463,7 +478,8 @@ void MacDef (unsigned Style) while (1) { if (SB_Compare (&List->Id, &CurTok.SVal) == 0) { - Error ("Duplicate symbol '%m%p'", &CurTok.SVal); + Error ("Duplicate macro parameter '%m%p'", &CurTok.SVal); + M->HasError = 1; } if (List->Next == 0) { break; @@ -513,7 +529,10 @@ void MacDef (unsigned Style) } /* May not have end of file in a macro definition */ if (CurTok.Tok == TOK_EOF) { - PError (&Pos, "'.ENDMACRO' expected for macro '%m%p'", &M->Name); + Error ("Missing '.ENDMACRO' for definition of macro '%s'", + SB_GetConstBuf (&M->Name)); + PNotification (&StartPos, "Macro definition started here"); + M->HasError = 1; goto Done; } } else { @@ -533,8 +552,9 @@ void MacDef (unsigned Style) /* Need an identifer */ if (CurTok.Tok != TOK_IDENT && CurTok.Tok != TOK_LOCAL_IDENT) { - Error ("Identifier expected"); + ErrorExpect ("Expected an identifier"); SkipUntilSep (); + M->HasError = 1; break; } @@ -553,7 +573,10 @@ void MacDef (unsigned Style) } /* We need end of line after the locals */ - ConsumeSep (); + if (!ExpectSep ()) { + M->HasError = 1; + } + NextTok (); continue; } @@ -591,7 +614,7 @@ void MacDef (unsigned Style) /* Save if last token was a separator to know if .endmacro is at ** the start of a line */ - LastTokWasSep = TokIsSep(CurTok.Tok); + LastTokWasSep = TokIsSep (CurTok.Tok); /* Read the next token */ NextTok (); @@ -626,7 +649,8 @@ void MacUndef (const StrBuf* Name, unsigned char Style) return; } if (M->Expansions > 0) { - Error ("Cannot delete a macro that is currently expanded"); + Error ("Cannot delete macro '%s' which is currently expanded", + SB_GetConstBuf (&M->Name)); return; } @@ -813,7 +837,11 @@ static void StartExpClassic (MacExp* E) /* Check for maximum parameter count */ if (E->ParamCount >= E->M->ParamCount) { - ErrorSkip ("Too many macro parameters"); + ErrorSkip ("Too many parameters for macro '%s'", + SB_GetConstBuf (&E->M->Name)); + PNotification (&E->M->DefPos, + "See definition of macro '%s' which was here", + SB_GetConstBuf (&E->M->Name)); break; } @@ -827,7 +855,7 @@ static void StartExpClassic (MacExp* E) /* Check for end of file */ if (CurTok.Tok == TOK_EOF) { - Error ("Unexpected end of file"); + Error ("Unexpected end of file in macro parameter list"); FreeMacExp (E); return; } @@ -938,10 +966,8 @@ static void StartExpDefine (MacExp* E) /* Check for a comma */ if (Count > 0) { - if (CurTok.Tok == TOK_COMMA) { + if (Expect (TOK_COMMA, "Expected ','")) { NextTok (); - } else { - Error ("',' expected"); } } } @@ -972,9 +998,21 @@ void MacExpandStart (Macro* M) Pos = CurTok.Pos; NextTok (); + /* We cannot expand a macro with errors */ + if (M->HasError) { + PError (&Pos, "Macro '%s' contains errors and cannot be expanded", + SB_GetConstBuf (&M->Name)); + PNotification (&M->DefPos, "Definition of macro '%s' was here", + SB_GetConstBuf (&M->Name)); + return; + } + /* We cannot expand an incomplete macro */ if (M->Incomplete) { - PError (&Pos, "Cannot expand an incomplete macro"); + PError (&Pos, "Macro '%s' is incomplete and cannot be expanded", + SB_GetConstBuf (&M->Name)); + PNotification (&M->DefPos, "Definition of macro '%s' was here", + SB_GetConstBuf (&M->Name)); return; } @@ -982,7 +1020,8 @@ void MacExpandStart (Macro* M) ** to force an endless loop and assembler crash. */ if (MacExpansions >= MAX_MACEXPANSIONS) { - PError (&Pos, "Too many nested macro expansions"); + PError (&Pos, "Too many nested macro expansions for macro '%s'", + SB_GetConstBuf (&M->Name)); return; } diff --git a/src/ca65/main.c b/src/ca65/main.c index e9b36ee5d..9c8cb0e96 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -145,7 +145,7 @@ static void SetOptions (void) OptTranslator (&Buf); /* Set date and time */ - OptDateTime ((unsigned long) time(0)); + OptDateTime ((unsigned long) time (0)); /* Release memory for the string */ SB_Done (&Buf); @@ -708,7 +708,7 @@ static void OptVersion (const char* Opt attribute ((unused)), /* Print the assembler version */ { fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ()); - exit(EXIT_SUCCESS); + exit (EXIT_SUCCESS); } @@ -727,7 +727,7 @@ static void DoPCAssign (void) { long PC = ConstExpression (); if (PC < 0 || PC > 0xFFFFFF) { - Error ("Range error"); + Error ("Program counter value is out of valid range"); } else { EnterAbsoluteMode (PC); } @@ -820,11 +820,10 @@ static void OneLine (void) NextTok (); /* Define the symbol with the expression following the '=' */ - SymDef (Sym, Expression(), ADDR_SIZE_DEFAULT, Flags); + SymDef (Sym, Expression (), ADDR_SIZE_DEFAULT, Flags); /* Don't allow anything after a symbol definition */ - ConsumeSep (); - return; + goto Done; } else if (CurTok.Tok == TOK_SET) { @@ -842,8 +841,7 @@ static void OneLine (void) SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_VAR); /* Don't allow anything after a symbol definition */ - ConsumeSep (); - return; + goto Done; } else { @@ -853,26 +851,24 @@ static void OneLine (void) Seg = ActiveSeg; PC = GetPC (); - /* Define the label */ - SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL); - /* Skip the colon. If NoColonLabels is enabled, allow labels ** without a colon if there is no whitespace before the ** identifier. */ if (CurTok.Tok != TOK_COLON) { if (HadWS || !NoColonLabels) { - Error ("':' expected"); - /* Try some smart error recovery */ - if (CurTok.Tok == TOK_NAMESPACE) { - NextTok (); - } + ErrorExpect ("Expected ':' after identifier to form a label"); + SkipUntilSep (); + goto Done; } } else { /* Skip the colon */ NextTok (); } + /* Define the label */ + SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL); + /* If we come here, a new identifier may be waiting, which may ** be a macro or instruction. */ @@ -906,17 +902,23 @@ static void OneLine (void) HandleInstruction (Instr); } else if (PCAssignment && (CurTok.Tok == TOK_STAR || CurTok.Tok == TOK_PC)) { NextTok (); - if (CurTok.Tok != TOK_EQ) { - Error ("'=' expected"); - SkipUntilSep (); - } else { - /* Skip the equal sign */ - NextTok (); - /* Enter absolute mode */ - DoPCAssign (); + if (!ExpectSkip (TOK_EQ, "Expected '='")) { + goto Done; } + /* Skip the equal sign */ + NextTok (); + /* Enter absolute mode */ + DoPCAssign (); + } else if ((CurTok.Tok >= TOK_FIRSTOP && CurTok.Tok <= TOK_LASTOP) || + (CurTok.Tok >= TOK_FIRSTREG && CurTok.Tok <= TOK_LASTREG) || + CurTok.Tok == TOK_INTCON || CurTok.Tok == TOK_CHARCON || + CurTok.Tok == TOK_STRCON) { + ErrorExpect ("Expected a mnemonic"); + SkipUntilSep (); + goto Done; } + /* If we have defined a label, remember its size. Sym is also set by ** a symbol assignment, but in this case Done is false, so we don't ** come here. @@ -938,6 +940,7 @@ static void OneLine (void) } } +Done: /* Line separator must come here */ ConsumeSep (); } @@ -1235,7 +1238,7 @@ int main (int argc, char* argv []) } if (WarningCount > 0 && WarningsAsErrors) { - Error("Warnings as errors"); + Error ("Warnings as errors"); } /* If we didn't have an errors, finish off the line infos */ diff --git a/src/ca65/nexttok.c b/src/ca65/nexttok.c index 54733740e..36cb9def1 100644 --- a/src/ca65/nexttok.c +++ b/src/ca65/nexttok.c @@ -725,52 +725,118 @@ void NextTok (void) -void Consume (token_t Expected, const char* ErrMsg) -/* Consume Expected, print an error if we don't find it */ +void ErrorExpect (const char* Msg) +/* Output an error message about some expected token using Msg and the + * description of the following token. This means that Msg should contain + * something like "xyz expected". The actual error message would then be + * "xyz expected but found zyx". + */ +{ + StrBuf S = AUTO_STRBUF_INITIALIZER; + TokenDesc (&CurTok, &S); + Error ("%s but found '%s'", Msg, SB_GetConstBuf (&S)); + SB_Done (&S); +} + + + +int Expect (token_t Expected, const char* Msg) +/* Check if the next token is the expected one. If not, print Msg plus some + * information about the token that was actually found. This means that Msg + * should contain something like "xyz expected". The actual error message would + * then be "xyz expected but found zyx". + * Returns true if the token was found, otherwise false. + */ { if (CurTok.Tok == Expected) { + return 1; + } + + ErrorExpect (Msg); + return 0; +} + + + +int ExpectSkip (token_t Expected, const char* Msg) +/* Check if the next token is the expected one. If not, print Msg plus some + * information about the token that was actually found and skip the remainder + * of the line. This means that Msg should contain something like "xyz + * expected". The actual error message would then be "xyz expected but found + * zyx". + * Returns true if the token was found, otherwise false. + */ +{ + if (CurTok.Tok == Expected) { + return 1; + } + + ErrorExpect (Msg); + SkipUntilSep (); + return 0; +} + + + +int Consume (token_t Expected, const char* ErrMsg) +/* Consume Token, print an error if we don't find it. Return true if the token +** was found and false otherwise. +*/ +{ + if (Expect (Expected, ErrMsg)) { NextTok (); + return 1; } else { - Error ("%s", ErrMsg); + return 0; } } -void ConsumeSep (void) -/* Consume a separator token */ +int ConsumeSep (void) +/* Consume a separator token. Return true if the token was found and false + * otherwise. + */ { /* We expect a separator token */ - ExpectSep (); + int Found = ExpectSep (); /* If we are at end of line, skip it */ if (CurTok.Tok == TOK_SEP) { NextTok (); } + + return Found; } -void ConsumeLParen (void) -/* Consume a left paren */ +int ConsumeLParen (void) +/* Consume a left paren. Return true if the token was found and false +** otherwise. +*/ { - Consume (TOK_LPAREN, "'(' expected"); + return Consume (TOK_LPAREN, "Expected '('"); } -void ConsumeRParen (void) -/* Consume a right paren */ +int ConsumeRParen (void) +/* Consume a right paren. Return true if the token was found and false +** otherwise. +*/ { - Consume (TOK_RPAREN, "')' expected"); + return Consume (TOK_RPAREN, "Expected ')'"); } -void ConsumeComma (void) -/* Consume a comma */ +int ConsumeComma (void) +/* Consume a comma. Return true if the token was found and false +** otherwise. +*/ { - Consume (TOK_COMMA, "',' expected"); + return Consume (TOK_COMMA, "Expected ','"); } @@ -785,13 +851,21 @@ void SkipUntilSep (void) -void ExpectSep (void) -/* Check if we've reached a line separator, and output an error if not. Do -** not skip the line separator. +int ExpectSep (void) +/* Check if we've reached a line separator. If so, return true. If not, output +** an error and skip all tokens until the line separator is reached. Then +** return false. */ { if (!TokIsSep (CurTok.Tok)) { - ErrorSkip ("Unexpected trailing garbage characters"); + /* Try to be helpful by giving information about the token that was + * unexpected. + */ + ErrorExpect ("Expected 'end-of-line'"); + SkipUntilSep (); + return 0; + } else { + return 1; } } diff --git a/src/ca65/nexttok.h b/src/ca65/nexttok.h index 68a371a0b..3902db518 100644 --- a/src/ca65/nexttok.h +++ b/src/ca65/nexttok.h @@ -51,27 +51,62 @@ void NextTok (void); /* Get next token and handle token level functions */ -void Consume (token_t Expected, const char* ErrMsg); -/* Consume Token, print an error if we don't find it */ +void ErrorExpect (const char* Msg); +/* Output an error message about some expected token using Msg and the + * description of the following token. This means that Msg should contain + * something like "xyz expected". The actual error message would then be + * "xyz expected but found zyx". + */ -void ConsumeSep (void); -/* Consume a separator token */ +int Expect (token_t Expected, const char* Msg); +/* Check if the next token is the expected one. If not, print Msg plus some + * information about the token that was actually found. This means that Msg + * should contain something like "xyz expected". The actual error message would + * then be "xyz expected but found zyx". + * Returns true if the token was found, otherwise false. + */ -void ConsumeLParen (void); -/* Consume a left paren */ +int ExpectSkip (token_t Expected, const char* Msg); +/* Check if the next token is the expected one. If not, print Msg plus some + * information about the token that was actually found and skip the remainder + * of the line. This means that Msg should contain something like "xyz + * expected". The actual error message would then be "xyz expected but found + * zyx". + * Returns true if the token was found, otherwise false. + */ -void ConsumeRParen (void); -/* Consume a right paren */ +int Consume (token_t Expected, const char* ErrMsg); +/* Consume Token, print an error if we don't find it. Return true if the token +** was found and false otherwise. +*/ -void ConsumeComma (void); -/* Consume a comma */ +int ConsumeSep (void); +/* Consume a separator token. Return true if the token was found and false + * otherwise. + */ + +int ConsumeLParen (void); +/* Consume a left paren. Return true if the token was found and false +** otherwise. +*/ + +int ConsumeRParen (void); +/* Consume a right paren. Return true if the token was found and false +** otherwise. +*/ + +int ConsumeComma (void); +/* Consume a comma. Return true if the token was found and false +** otherwise. +*/ void SkipUntilSep (void); /* Skip tokens until we reach a line separator or end of file */ -void ExpectSep (void); -/* Check if we've reached a line separator, and output an error if not. Do -** not skip the line separator. +int ExpectSep (void); +/* Check if we've reached a line separator. If so, return true. If not, output +** an error and skip all tokens until the line separator is reached. Then +** return false. */ void EnterRawTokenMode (void); diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index 301129583..145eb4963 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -167,13 +167,17 @@ static void SetBoolOption (unsigned char* Flag) switch (GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]))) { case 0: *Flag = 0; NextTok (); break; case 1: *Flag = 1; NextTok (); break; - default: ErrorSkip ("'on' or 'off' expected"); break; + default: + ErrorExpect ("Expected ON or OFF"); + SkipUntilSep (); + break; } } else if (TokIsSep (CurTok.Tok)) { /* Without anything assume switch on */ *Flag = 1; } else { - ErrorSkip ("'on' or 'off' expected"); + ErrorExpect ("Expected ON or OFF"); + SkipUntilSep (); } } @@ -216,8 +220,7 @@ static void ExportImport (void (*Func) (SymEntry*, unsigned char, unsigned), while (1) { /* We need an identifier here */ - if (CurTok.Tok != TOK_IDENT) { - ErrorSkip ("Identifier expected"); + if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) { return; } @@ -283,7 +286,7 @@ static void ConDes (const StrBuf* Name, unsigned Type) Prio = ConstExpression (); if (Prio < CD_PRIO_MIN || Prio > CD_PRIO_MAX) { /* Value out of range */ - Error ("Range error"); + Error ("Given priority is out of range"); return; } } else { @@ -333,7 +336,7 @@ static StrBuf* GenArrayType (StrBuf* Type, unsigned SpanSize, static void DoA16 (void) /* Switch the accu to 16 bit mode (assembler only) */ { - if (GetCPU() != CPU_65816) { + if (GetCPU () != CPU_65816) { Error ("Command is only valid in 65816 mode"); } else { /* Immidiate mode has two extension bytes */ @@ -346,7 +349,7 @@ static void DoA16 (void) static void DoA8 (void) /* Switch the accu to 8 bit mode (assembler only) */ { - if (GetCPU() != CPU_65816) { + if (GetCPU () != CPU_65816) { Error ("Command is only valid in 65816 mode"); } else { /* Immidiate mode has one extension byte */ @@ -400,7 +403,7 @@ static void DoAlign (void) /* Read the alignment value */ Alignment = ConstExpression (); if (Alignment <= 0 || (unsigned long) Alignment > MAX_ALIGNMENT) { - ErrorSkip ("Range error"); + ErrorSkip ("Alignment is out of range"); return; } @@ -410,7 +413,7 @@ static void DoAlign (void) FillVal = ConstExpression (); /* We need a byte value here */ if (!IsByteRange (FillVal)) { - ErrorSkip ("Range error"); + ErrorSkip ("Fill value is not in byte range"); return; } } else { @@ -428,8 +431,7 @@ static void DoASCIIZ (void) { while (1) { /* Must have a string constant */ - if (CurTok.Tok != TOK_STRCON) { - ErrorSkip ("String constant expected"); + if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) { return; } @@ -463,11 +465,10 @@ static void DoAssert (void) /* First we have the expression that has to evaluated */ ExprNode* Expr = Expression (); - ConsumeComma (); - /* Action follows */ - if (CurTok.Tok != TOK_IDENT) { - ErrorSkip ("Identifier expected"); + /* Followed by comma and action */ + if (!ConsumeComma () || !Expect (TOK_IDENT, "Expected an identifier")) { + SkipUntilSep (); return; } switch (GetSubKey (ActionTab, sizeof (ActionTab) / sizeof (ActionTab[0]))) { @@ -496,9 +497,8 @@ static void DoAssert (void) default: Error ("Illegal assert action specifier"); - /* Use lderror - there won't be an .o file anyway */ - Action = ASSERT_ACT_LDERROR; - break; + SkipUntilSep (); + return; } NextTok (); @@ -512,8 +512,7 @@ static void DoAssert (void) NextTok (); /* Read the message */ - if (CurTok.Tok != TOK_STRCON) { - ErrorSkip ("String constant expected"); + if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) { return; } @@ -642,20 +641,23 @@ static void DoCharMap (void) /* Read the index as numerical value */ Index = ConstExpression (); - if (Index < 0 || Index > 255) { + if (IsByteRange (Index)) { /* Value out of range */ - ErrorSkip ("Index range error"); + ErrorSkip ("Index must be in byte range"); return; } /* Comma follows */ - ConsumeComma (); + if (!ConsumeComma ()) { + SkipUntilSep (); + return; + } /* Read the character code */ Code = ConstExpression (); - if (Code < 0 || Code > 255) { + if (!IsByteRange (Code)) { /* Value out of range */ - ErrorSkip ("Code range error"); + ErrorSkip ("Replacement character code must be in byte range"); return; } @@ -685,15 +687,17 @@ static void DoConDes (void) long Type; /* Symbol name follows */ - if (CurTok.Tok != TOK_IDENT) { - ErrorSkip ("Identifier expected"); + if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) { return; } SB_Copy (&Name, &CurTok.SVal); NextTok (); /* Type follows. May be encoded as identifier or numerical */ - ConsumeComma (); + if (!ConsumeComma ()) { + SkipUntilSep (); + goto ExitPoint; + } if (CurTok.Tok == TOK_IDENT) { /* Map the following keyword to a number, then skip it */ @@ -702,7 +706,8 @@ static void DoConDes (void) /* Check if we got a valid keyword */ if (Type < 0) { - ErrorSkip ("Syntax error"); + ErrorExpect ("Expected CONSTRUCTOR, DESTRUCTOR or INTERRUPTOR"); + SkipUntilSep (); goto ExitPoint; } @@ -712,7 +717,7 @@ static void DoConDes (void) Type = ConstExpression (); if (Type < CD_TYPE_MIN || Type > CD_TYPE_MAX) { /* Value out of range */ - ErrorSkip ("Range error"); + ErrorSkip ("Numeric condes type is out of range"); goto ExitPoint; } @@ -734,8 +739,7 @@ static void DoConstructor (void) StrBuf Name = STATIC_STRBUF_INITIALIZER; /* Symbol name follows */ - if (CurTok.Tok != TOK_IDENT) { - ErrorSkip ("Identifier expected"); + if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) { return; } SB_Copy (&Name, &CurTok.SVal); @@ -771,8 +775,7 @@ static void DoDbg (void) /* We expect a subkey */ - if (CurTok.Tok != TOK_IDENT) { - ErrorSkip ("Identifier expected"); + if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) { return; } @@ -788,7 +791,10 @@ static void DoDbg (void) case 1: DbgInfoFunc (); break; case 2: DbgInfoLine (); break; case 3: DbgInfoSym (); break; - default: ErrorSkip ("Syntax error"); break; + default: + ErrorExpect ("Expected FILE, FUNC, LINE or SYM"); + SkipUntilSep (); + break; } } @@ -853,9 +859,7 @@ static void DoDelMac (void) /* Delete a classic macro */ { /* We expect an identifier */ - if (CurTok.Tok != TOK_IDENT) { - ErrorSkip ("Identifier expected"); - } else { + if (ExpectSkip (TOK_IDENT, "Expected an identifier")) { MacUndef (&CurTok.SVal, MAC_STYLE_CLASSIC); NextTok (); } @@ -869,8 +873,7 @@ static void DoDestructor (void) StrBuf Name = STATIC_STRBUF_INITIALIZER; /* Symbol name follows */ - if (CurTok.Tok != TOK_IDENT) { - ErrorSkip ("Identifier expected"); + if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) { return; } SB_Copy (&Name, &CurTok.SVal); @@ -938,9 +941,7 @@ static void DoEndScope (void) static void DoError (void) /* User error */ { - if (CurTok.Tok != TOK_STRCON) { - ErrorSkip ("String constant expected"); - } else { + if (ExpectSkip (TOK_STRCON, "Expected a string constant")) { Error ("User error: %m%p", &CurTok.SVal); SkipUntilSep (); } @@ -1010,9 +1011,7 @@ static void DoFarAddr (void) static void DoFatal (void) /* Fatal user error */ { - if (CurTok.Tok != TOK_STRCON) { - ErrorSkip ("String constant expected"); - } else { + if (ExpectSkip (TOK_STRCON, "Expected a string constant")) { Fatal ("User error: %m%p", &CurTok.SVal); SkipUntilSep (); } @@ -1030,14 +1029,13 @@ static void DoFeature (void) while (1) { /* We expect an identifier */ - if (CurTok.Tok != TOK_IDENT) { - ErrorSkip ("Identifier expected"); + if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) { return; } /* Make the string attribute lower case */ LocaseSVal (); - Feature = FindFeature(&CurTok.SVal); + Feature = FindFeature (&CurTok.SVal); if (Feature == FEAT_UNKNOWN) { /* Not found */ ErrorSkip ("Invalid feature: '%m%p'", &CurTok.SVal); @@ -1045,7 +1043,8 @@ static void DoFeature (void) } if (Feature == FEAT_ADDRSIZE) { - Warning (1, "Deprecated feature: '.feature addrsize'. Pseudo function .addrsize is always available."); + Warning (1, "Deprecated feature: '.feature addrsize'. " + "Pseudo function .addrsize is always available."); } NextTok (); @@ -1053,7 +1052,7 @@ static void DoFeature (void) /* Optional +/- or ON/OFF */ On = 1; if (CurTok.Tok != TOK_COMMA && !TokIsSep (CurTok.Tok)) { - SetBoolOption(&On); + SetBoolOption (&On); } /* Apply feature setting. */ @@ -1087,19 +1086,17 @@ static void DoFileOpt (void) OptNum = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0])); if (OptNum < 0) { /* Not found */ - ErrorSkip ("File option keyword expected"); + ErrorExpect ("Expected a file option keyword"); + SkipUntilSep (); return; } /* Skip the keyword */ NextTok (); - /* Must be followed by a comma */ - ConsumeComma (); - - /* We accept only string options for now */ - if (CurTok.Tok != TOK_STRCON) { - ErrorSkip ("String constant expected"); + /* Must be followed by a comma and a string option */ + if (!ConsumeComma () || !Expect (TOK_STRCON, "Expected a string constant")) { + SkipUntilSep (); return; } @@ -1134,16 +1131,13 @@ static void DoFileOpt (void) /* Option given as number */ OptNum = ConstExpression (); if (!IsByteRange (OptNum)) { - ErrorSkip ("Range error"); + ErrorSkip ("Option number must be in byte range"); return; } - /* Must be followed by a comma */ - ConsumeComma (); - - /* We accept only string options for now */ - if (CurTok.Tok != TOK_STRCON) { - ErrorSkip ("String constant expected"); + /* Must be followed by a comma plus a string constant */ + if (!ConsumeComma () || !Expect (TOK_STRCON, "Expected a string constant")) { + SkipUntilSep (); return; } @@ -1198,7 +1192,7 @@ static void DoHiBytes (void) static void DoI16 (void) /* Switch the index registers to 16 bit mode (assembler only) */ { - if (GetCPU() != CPU_65816) { + if (GetCPU () != CPU_65816) { Error ("Command is only valid in 65816 mode"); } else { /* Immidiate mode has two extension bytes */ @@ -1211,7 +1205,7 @@ static void DoI16 (void) static void DoI8 (void) /* Switch the index registers to 16 bit mode (assembler only) */ { - if (GetCPU() != CPU_65816) { + if (GetCPU () != CPU_65816) { Error ("Command is only valid in 65816 mode"); } else { /* Immidiate mode has one extension byte */ @@ -1248,8 +1242,7 @@ static void DoIncBin (void) FILE* F; /* Name must follow */ - if (CurTok.Tok != TOK_STRCON) { - ErrorSkip ("String constant expected"); + if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) { return; } SB_Copy (&Name, &CurTok.SVal); @@ -1314,13 +1307,16 @@ static void DoIncBin (void) Count = Size - Start; if (Count < 0) { /* Nothing to read - flag this as a range error */ - ErrorSkip ("Range error"); + ErrorSkip ("Start offset is larger than file size"); goto Done; } } else { /* Count was given, check if it is valid */ - if (Start + Count > Size) { - ErrorSkip ("Range error"); + if (Start > Size) { + ErrorSkip ("Start offset is larger than file size"); + goto Done; + } else if (Start + Count > Size) { + ErrorSkip ("Not enough bytes left in file at offset %ld", Start); goto Done; } } @@ -1367,9 +1363,7 @@ static void DoInclude (void) /* Include another file */ { /* Name must follow */ - if (CurTok.Tok != TOK_STRCON) { - ErrorSkip ("String constant expected"); - } else { + if (ExpectSkip (TOK_STRCON, "Expected a string constant")) { SB_Terminate (&CurTok.SVal); if (NewInputFile (SB_GetConstBuf (&CurTok.SVal)) == 0) { /* Error opening the file, skip remainder of line */ @@ -1386,8 +1380,7 @@ static void DoInterruptor (void) StrBuf Name = STATIC_STRBUF_INITIALIZER; /* Symbol name follows */ - if (CurTok.Tok != TOK_IDENT) { - ErrorSkip ("Identifier expected"); + if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) { return; } SB_Copy (&Name, &CurTok.SVal); @@ -1474,9 +1467,7 @@ static void DoListBytes (void) static void DoLocalChar (void) /* Define the character that starts local labels */ { - if (CurTok.Tok != TOK_CHARCON) { - ErrorSkip ("Character constant expected"); - } else { + if (ExpectSkip (TOK_CHARCON, "Expected a character constant")) { if (CurTok.IVal != '@' && CurTok.IVal != '?') { Error ("Invalid start character for locals"); } else { @@ -1492,15 +1483,14 @@ static void DoMacPack (void) /* Insert a macro package */ { /* We expect an identifier */ - if (CurTok.Tok != TOK_IDENT) { - ErrorSkip ("Identifier expected"); - } else { - SB_AppendStr (&CurTok.SVal, ".mac"); - SB_Terminate (&CurTok.SVal); - if (NewInputFile (SB_GetConstBuf (&CurTok.SVal)) == 0) { - /* Error opening the file, skip remainder of line */ - SkipUntilSep (); - } + if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) { + return; + } + SB_AppendStr (&CurTok.SVal, ".mac"); + SB_Terminate (&CurTok.SVal); + if (NewInputFile (SB_GetConstBuf (&CurTok.SVal)) == 0) { + /* Error opening the file, skip remainder of line */ + SkipUntilSep (); } } @@ -1538,12 +1528,10 @@ static void DoOrg (void) static void DoOut (void) /* Output a string */ { - if (CurTok.Tok != TOK_STRCON) { - ErrorSkip ("String constant expected"); - } else { + if (ExpectSkip (TOK_STRCON, "Expected a string constant")) { /* Output the string and be sure to flush the output to keep it in - ** sync with any error messages if the output is redirected to a file. - */ + * sync with any error messages if the output is redirected to a file. + */ printf ("%.*s\n", (int) SB_GetLen (&CurTok.SVal), SB_GetConstBuf (&CurTok.SVal)); @@ -1835,7 +1823,7 @@ static void DoRes (void) Count = ConstExpression (); if (Count > 0xFFFF || Count < 0) { - ErrorSkip ("Range error"); + ErrorSkip ("Invalid number of bytes specified"); return; } if (CurTok.Tok == TOK_COMMA) { @@ -1843,7 +1831,7 @@ static void DoRes (void) Val = ConstExpression (); /* We need a byte value here */ if (!IsByteRange (Val)) { - ErrorSkip ("Range error"); + ErrorSkip ("Fill value is not in byte range"); return; } @@ -1903,12 +1891,10 @@ static void DoScope (void) static void DoSegment (void) /* Switch to another segment */ { - StrBuf Name = STATIC_STRBUF_INITIALIZER; - SegDef Def; + if (ExpectSkip (TOK_STRCON, "Expected a string constant")) { - if (CurTok.Tok != TOK_STRCON) { - ErrorSkip ("String constant expected"); - } else { + SegDef Def; + StrBuf Name = AUTO_STRBUF_INITIALIZER; /* Save the name of the segment and skip it */ SB_Copy (&Name, &CurTok.SVal); @@ -1923,10 +1909,10 @@ static void DoSegment (void) /* Set the segment */ UseSeg (&Def); - } - /* Free memory for Name */ - SB_Done (&Name); + /* Free memory for Name */ + SB_Done (&Name); + } } @@ -1935,9 +1921,7 @@ static void DoSetCPU (void) /* Switch the CPU instruction set */ { /* We expect an identifier */ - if (CurTok.Tok != TOK_STRCON) { - ErrorSkip ("String constant expected"); - } else { + if (ExpectSkip (TOK_STRCON, "Expected a string constant")) { cpu_t CPU; /* Try to find the CPU */ @@ -1948,8 +1932,8 @@ static void DoSetCPU (void) SetCPU (CPU); /* Skip the identifier. If the CPU switch was successful, the scanner - ** will treat the input now correctly for the new CPU. - */ + * will treat the input now correctly for the new CPU. + */ NextTok (); } } @@ -2024,9 +2008,7 @@ static void DoUnDef (void) EnableDefineStyleMacros (); /* We expect an identifier */ - if (CurTok.Tok != TOK_IDENT) { - ErrorSkip ("Identifier expected"); - } else { + if (ExpectSkip (TOK_IDENT, "Expected an identifier")) { MacUndef (&CurTok.SVal, MAC_STYLE_DEFINE); NextTok (); } @@ -2046,9 +2028,7 @@ static void DoUnexpected (void) static void DoWarning (void) /* User warning */ { - if (CurTok.Tok != TOK_STRCON) { - ErrorSkip ("String constant expected"); - } else { + if (ExpectSkip (TOK_STRCON, "Expected a string constant")) { Warning (0, "User warning: %m%p", &CurTok.SVal); SkipUntilSep (); } @@ -2255,7 +2235,7 @@ static CtrlDesc CtrlCmdTab [] = { { ccNone, DoUnexpected }, /* .REF, .REFERENCED */ { ccNone, DoReferTo }, /* .REFTO, .REFERTO */ { ccNone, DoReloc }, /* .RELOC */ - { ccNone, DoRepeat }, /* .REPEAT */ + { ccKeepToken, DoRepeat }, /* .REPEAT */ { ccNone, DoRes }, /* .RES */ { ccNone, DoInvalid }, /* .RIGHT */ { ccNone, DoROData }, /* .RODATA */ diff --git a/src/ca65/repeat.c b/src/ca65/repeat.c index 90aa894f7..c2fb7d9fa 100644 --- a/src/ca65/repeat.c +++ b/src/ca65/repeat.c @@ -53,7 +53,7 @@ -static TokList* CollectRepeatTokens (void) +static TokList* CollectRepeatTokens (const FilePos* StartPos) /* Collect all tokens inside the .REPEAT body in a token list and return ** this list. In case of errors, NULL is returned. */ @@ -67,7 +67,8 @@ static TokList* CollectRepeatTokens (void) /* Check for end of input */ if (CurTok.Tok == TOK_EOF) { - Error ("Unexpected end of file"); + ErrorExpect ("Expected '.ENDREPEAT'"); + PNotification (StartPos, "For this '.REPEAT' command"); FreeTokList (List); return 0; } @@ -117,10 +118,14 @@ void ParseRepeat (void) char* Name; TokList* List; + /* Remember the position of the .REPEAT token, then skip it */ + FilePos StartPos = CurTok.Pos; + NextTok (); + /* Repeat count follows */ long RepCount = ConstExpression (); if (RepCount < 0) { - Error ("Range error"); + Error ("Repeat count must be positive or zero"); RepCount = 0; } @@ -132,9 +137,7 @@ void ParseRepeat (void) NextTok (); /* Check for an identifier */ - if (CurTok.Tok != TOK_IDENT) { - ErrorSkip ("Identifier expected"); - } else { + if (ExpectSkip (TOK_IDENT, "Expected an identifier")) { /* Remember the name and skip it */ SB_Terminate (&CurTok.SVal); Name = xstrdup (SB_GetConstBuf (&CurTok.SVal)); @@ -147,7 +150,7 @@ void ParseRepeat (void) ConsumeSep (); /* Read the token list */ - List = CollectRepeatTokens (); + List = CollectRepeatTokens (&StartPos); /* If we had an error, bail out */ if (List == 0) { diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index a2a72a149..b56b17401 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -818,7 +818,7 @@ static void ReadStringConst (int StringTerm) int Cooked = 1; NeedNext = 1; - if (StringTerm == 0 && SB_GetLen(&CurTok.SVal) == 1) { + if (StringTerm == 0 && SB_GetLen (&CurTok.SVal) == 1) { if (C == '\'') { break; } @@ -901,12 +901,12 @@ static void ReadStringConst (int StringTerm) case '7': { /* brace needed for scoping */ int Count = 1; - int Final = DigitVal(C); + int Final = DigitVal (C); Cooked = 0; NextChar (); while (IsODigit (C) && Count++ < 3) { - Final = (Final << 3) | DigitVal(C); - NextChar(); + Final = (Final << 3) | DigitVal (C); + NextChar (); } if (C >= 256) Error ("Octal character constant out of range"); @@ -1587,8 +1587,8 @@ CharAgain: /* Always a character constant ** Hack: Pass 0 to ReadStringConst for special handling. */ - ReadStringConst(0); - if (SB_GetLen(&CurTok.SVal) != 1) { + ReadStringConst (0); + if (SB_GetLen (&CurTok.SVal) != 1) { Error ("Illegal character constant"); goto CharAgain; } diff --git a/src/ca65/struct.c b/src/ca65/struct.c index ecbaa2a71..0ec4ae916 100644 --- a/src/ca65/struct.c +++ b/src/ca65/struct.c @@ -105,14 +105,21 @@ static long DoStructInternal (long Offs, unsigned Type) ** union, the struct may be anonymous; in which case, no new lexical level ** is started. */ - int Anon = (CurTok.Tok != TOK_IDENT); + int Anon = (CurTok.Tok == TOK_SEP); if (!Anon) { - /* Enter a new scope, then skip the name */ - SymEnterLevel (&CurTok.SVal, SCOPE_STRUCT, ADDR_SIZE_ABS, 0); - NextTok (); - /* Start at zero offset in the new scope */ - Offs = 0; + /* Non anonymous structs must have an identifier as name */ + if (Expect (TOK_IDENT, "Expected a struct/union name")) { + /* Enter a new scope, then skip the name */ + SymEnterLevel (&CurTok.SVal, SCOPE_STRUCT, ADDR_SIZE_ABS, 0); + NextTok (); + /* Start at zero offset in the new scope */ + Offs = 0; + } else { + /* Skip the junk on the line before proceeding */ + SkipUntilSep (); + Anon = 1; + } } /* Test for end of line */ @@ -183,7 +190,7 @@ static long DoStructInternal (long Offs, unsigned Type) case TOK_RES: NextTok (); if (CurTok.Tok == TOK_SEP) { - ErrorSkip ("Size is missing"); + ErrorExpect ("Expected a byte count"); } else { MemberSize = Member (1); } @@ -192,7 +199,7 @@ static long DoStructInternal (long Offs, unsigned Type) case TOK_ORG: NextTok (); if (CurTok.Tok == TOK_SEP) { - ErrorSkip ("Address is missing"); + ErrorExpect ("Expected an address"); } else { Offs = ConstExpression (); @@ -233,7 +240,12 @@ static long DoStructInternal (long Offs, unsigned Type) default: if (!CheckConditionals ()) { /* Not a conditional directive */ - ErrorSkip ("Invalid storage allocator in struct/union"); + if (Sym) { + ErrorExpect ("Expected a storage allocator after the field name"); + } else { + ErrorExpect ("Expected a storage allocator"); + } + SkipUntilSep (); } } @@ -275,9 +287,9 @@ static long DoStructInternal (long Offs, unsigned Type) /* End of struct/union definition */ if (Type == STRUCT) { - Consume (TOK_ENDSTRUCT, "'.ENDSTRUCT' expected"); + Consume (TOK_ENDSTRUCT, "Expected '.ENDSTRUCT'"); } else { - Consume (TOK_ENDUNION, "'.ENDUNION' expected"); + Consume (TOK_ENDUNION, "Expected '.ENDUNION'"); } /* Return the size of the struct */ diff --git a/src/ca65/studyexpr.c b/src/ca65/studyexpr.c index f4376e221..6c297f4df 100644 --- a/src/ca65/studyexpr.c +++ b/src/ca65/studyexpr.c @@ -1359,8 +1359,7 @@ static void StudyNearAddr (ExprNode* Expr, ExprDesc* D) } /* Promote to absolute if smaller. */ - if (D->AddrSize < ADDR_SIZE_ABS) - { + if (D->AddrSize < ADDR_SIZE_ABS) { D->AddrSize = ADDR_SIZE_ABS; } } diff --git a/src/ca65/symbol.c b/src/ca65/symbol.c index f1c259082..974323d7c 100644 --- a/src/ca65/symbol.c +++ b/src/ca65/symbol.c @@ -73,7 +73,7 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName) /* Start from the root scope */ Scope = RootScope; - } else if (CurTok.Tok == TOK_IDENT) { + } else if (Expect (TOK_IDENT, "Expected an identifier")) { /* Remember the name and skip it */ SB_Copy (Name, &CurTok.SVal); @@ -115,8 +115,7 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName) while (1) { /* Next token must be an identifier. */ - if (CurTok.Tok != TOK_IDENT) { - Error ("Identifier expected"); + if (!Expect (TOK_IDENT, "Expected an identifier")) { return 0; } diff --git a/src/ca65/symentry.c b/src/ca65/symentry.c index c57fcff2a..dd18fc765 100644 --- a/src/ca65/symentry.c +++ b/src/ca65/symentry.c @@ -216,6 +216,10 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags if (S->Flags & SF_IMPORT) { /* Defined symbol is marked as imported external symbol */ Error ("Symbol '%m%p' is already an import", GetSymName (S)); + if (CollCount (&S->DefLines) > 0) { + PNotification (GetSourcePos (CollAt(&S->DefLines, 0)), + "The symbol was previously imported here"); + } return; } if ((Flags & SF_VAR) != 0 && (S->Flags & (SF_EXPORT | SF_GLOBAL))) { @@ -227,6 +231,10 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags /* Multiple definition. In case of a variable, this is legal. */ if ((S->Flags & SF_VAR) == 0) { Error ("Symbol '%m%p' is already defined", GetSymName (S)); + if (CollCount (&S->DefLines) > 0) { + PNotification (GetSourcePos (CollAt(&S->DefLines, 0)), + "The symbol was previously defined here"); + } S->Flags |= SF_MULTDEF; return; } else { diff --git a/src/ca65/token.c b/src/ca65/token.c index db2a63fc7..48ffdff80 100644 --- a/src/ca65/token.c +++ b/src/ca65/token.c @@ -33,30 +33,261 @@ +#include + /* ca65 */ #include "token.h" /*****************************************************************************/ -/* Code */ +/* Data */ /*****************************************************************************/ -int TokHasSVal (token_t Tok) -/* Return true if the given token has an attached SVal */ -{ - return (Tok == TOK_IDENT || Tok == TOK_LOCAL_IDENT || Tok == TOK_STRCON); -} +/* Use a struct so we can extend it if required */ +typedef struct TokDescEntry TokDescEntry; +struct TokDescEntry { + const char* Desc; +}; + +static const TokDescEntry TokDesc[] = { + { "none", }, + { "end-of-file", }, + { "end-of-line", }, + { "{s}", }, + { "{s}", }, + + { "{i}", }, + { "'{c}'", }, + { "\"{s}\"", }, + + { "A", }, + { "Q", }, + { "S", }, + { "X", }, + { "Y", }, + { "Z", }, + { "R{i}", }, + + { ":=", }, + { "unnamed label", }, + + { "=", }, + { "<>", }, + { "<", }, + { ">", }, + { "<=", }, + { ">=", }, + + { ".AND", }, + { ".OR", }, + { ".XOR", }, + { ".NOT", }, + + { "+", }, + { "-", }, + { "*", }, + { "/", }, + { "!", }, + { "|", }, + { "^", }, + { "&", }, + { "<<", }, + { ">>", }, + { "~", }, + + { "$", }, + { "::", }, + { ".", }, + { ",", }, + { "#", }, + { ":", }, + { "(", }, + { ")", }, + { "[", }, + { "]", }, + { "{", }, + { "}", }, + { "@", }, + + { "z:", }, + { "a:", }, + { "f:", }, + + { "macro parameter", }, + { "repeat counter", }, + + { ".A16" }, + { ".A8" }, + { ".ADDR" }, + { ".ADDRSIZE" }, + { ".ALIGN" }, + { ".ASCIIZ" }, + { ".ASIZE" }, + { ".ASSERT" }, + { ".AUTOIMPORT" }, + { ".BANK" }, + { ".BANKBYTE" }, + { ".BANKBYTES" }, + { ".BLANK" }, + { ".BSS" }, + { ".BYTE" }, + { ".CAP" }, + { ".CASE" }, + { ".CHARMAP" }, + { ".CODE" }, + { ".CONCAT" }, + { ".CONDES" }, + { ".CONST" }, + { ".CONSTRUCTOR" }, + { ".CPU" }, + { ".DATA" }, + { ".DBG" }, + { ".DBYT" }, + { ".DEBUGINFO" }, + { ".DEFINE" }, + { ".DEFINED" }, + { ".DEFINEDMACRO" }, + { ".DELMAC" }, + { ".DESTRUCTOR" }, + { ".DWORD" }, + { ".ELSE" }, + { ".ELSEIF" }, + { ".END" }, + { ".ENDENUM" }, + { ".ENDIF" }, + { ".ENDMACRO" }, + { ".ENDPROC" }, + { ".ENDREP" }, + { ".ENDSCOPE" }, + { ".ENDSTRUCT" }, + { ".ENDUNION" }, + { ".ENUM" }, + { ".ERROR" }, + { ".EXITMACRO" }, + { ".EXPORT" }, + { ".EXPORTZP" }, + { ".FARADDR" }, + { ".FATAL" }, + { ".FEATURE" }, + { ".FILEOPT" }, + { ".FORCEIMPORT" }, + { ".FORCEWORD" }, + { ".GLOBAL" }, + { ".GLOBALZP" }, + { ".HIBYTE" }, + { ".HIBYTES" }, + { ".HIWORD" }, + { ".I16" }, + { ".I8" }, + { ".MAKEIDENT" }, + { ".IF" }, + { ".IFBLANK" }, + { ".IFCONST" }, + { ".IFDEF" }, + { ".IFNBLANK" }, + { ".IFNCONST" }, + { ".IFNDEF" }, + { ".IFNREF" }, + { ".IFP02" }, + { ".IFP02X" }, + { ".IFP4510" }, + { ".IFP45GS02" }, + { ".IFP6280" }, + { ".IFP816" }, + { ".IFPC02" }, + { ".IFPCE02" }, + { ".IFPDTV" }, + { ".IFPM740" }, + { ".IFPSC02" }, + { ".IFPSWEET16" }, + { ".IFPWC02" }, + { ".IFREF" }, + { ".IMPORT" }, + { ".IMPORTZP" }, + { ".INCBIN" }, + { ".INCLUDE" }, + { ".INTERRUPTOR" }, + { ".ISIZE" }, + { ".ISMNEMONIC" }, + { ".LEFT" }, + { ".LINECONT" }, + { ".LIST" }, + { ".LISTBYTES" }, + { ".LITERAL" }, + { ".LOBYTE" }, + { ".LOBYTES" }, + { ".LOCAL" }, + { ".LOCALCHAR" }, + { ".LOWORD" }, + { ".MACPACK" }, + { ".MACRO" }, + { ".MATCH" }, + { ".MAX" }, + { ".MID" }, + { ".MIN" }, + { ".NULL" }, + { ".ORG" }, + { ".OUT" }, + { ".P02" }, + { ".P02X" }, + { ".P4510" }, + { ".P45GS02" }, + { ".P6280" }, + { ".P816" }, + { ".PAGELENGTH" }, + { ".PARAMCOUNT" }, + { ".PC02" }, + { ".PCE02" }, + { ".PDTV" }, + { ".PM740" }, + { ".POPCHARMAP" }, + { ".POPCPU" }, + { ".POPSEG" }, + { ".PROC" }, + { ".PSC02" }, + { ".PSWEET16" }, + { ".PUSHCHARMAP" }, + { ".PUSHCPU" }, + { ".PUSHSEG" }, + { ".PWC02" }, + { ".REFERENCED" }, + { ".REFERTO" }, + { ".RELOC" }, + { ".REPEAT" }, + { ".RES" }, + { ".RIGHT" }, + { ".RODATA" }, + { ".SCOPE" }, + { ".SEGMENT" }, + { ".SET" }, + { ".SETCPU" }, + { ".SIZEOF" }, + { ".SMART" }, + { ".SPRINTF" }, + { ".STRAT" }, + { ".STRING" }, + { ".STRLEN" }, + { ".STRUCT" }, + { ".TAG" }, + { ".TCOUNT" }, + { ".TIME" }, + { ".UNDEF" }, + { ".UNION" }, + { ".VERSION" }, + { ".WARNING" }, + { ".WORD" }, + { ".XMATCH" }, + { ".ZEROPAGE" }, +}; -int TokHasIVal (token_t Tok) -/* Return true if the given token has an attached IVal */ -{ - return (Tok == TOK_INTCON || Tok == TOK_CHARCON || Tok == TOK_REG); -} +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ @@ -72,3 +303,54 @@ void CopyToken (Token* Dst, const Token* Src) SB_Copy (&Dst->SVal, &Src->SVal); Dst->Pos = Src->Pos; } + + + +StrBuf* TokenDesc (const Token* T, StrBuf* S) +/* Place a textual description of the given token into S. */ +{ + PRECONDITION (sizeof (TokDesc) / sizeof (TokDesc[0]) == TOK_COUNT); + + /* Clear the target buffer */ + SB_Clear (S); + + /* Get the description for the token */ + const char* Desc = TokDesc[T->Tok].Desc; + + /* Repeatedly replace {c}, {i} and {s} */ + size_t Start = 0; + while (1) { + const char* P = strchr (Desc + Start, '{'); + if (P) { + /* Check if this is really {c}, {i} or {s} */ + if ((P[1] != 'c' && + P[1] != 'i' && + P[1] != 's') || + P[2] != '}') { + ++Start; + continue; + } + /* Append the text before the replacement token */ + SB_AppendBuf (S, Desc + Start, P - (Desc + Start)); + Start += P - (Desc + Start) + 3; + /* Append the replacement text */ + if (P[1] == 'c') { + SB_AppendChar (S, (char)T->IVal); + } else if (P[1] == 'i') { + char Buf[64]; + snprintf (Buf, sizeof (Buf), "%ld", T->IVal); + SB_AppendStr (S, Buf); + } else { + SB_Append (S, &T->SVal); + } + } else { + /* No more replacements found, append remainder */ + SB_AppendStr (S, Desc + Start); + break; + } + } + + /* Zero-terminate the buffer and return it */ + SB_Terminate (S); + return S; +} diff --git a/src/ca65/token.h b/src/ca65/token.h index 39a4d0980..34706fad5 100644 --- a/src/ca65/token.h +++ b/src/ca65/token.h @@ -52,76 +52,80 @@ /* Tokens */ typedef enum token_t { - TOK_NONE, /* Start value, invalid */ - TOK_EOF, /* End of input file */ - TOK_SEP, /* Separator (usually newline) */ - TOK_IDENT, /* An identifier */ - TOK_LOCAL_IDENT, /* A cheap local identifier */ + TOK_NONE, /* Start value, invalid */ + TOK_EOF, /* End of input file */ + TOK_SEP, /* Separator (usually newline) */ + TOK_IDENT, /* An identifier */ + TOK_LOCAL_IDENT, /* A cheap local identifier */ - TOK_INTCON, /* Integer constant */ - TOK_CHARCON, /* Character constant */ - TOK_STRCON, /* String constant */ + TOK_INTCON, /* Integer constant */ + TOK_CHARCON, /* Character constant */ + TOK_STRCON, /* String constant */ - TOK_A, /* A)ccumulator */ - TOK_X, /* X register */ - TOK_Y, /* Y register */ - TOK_Z, /* Z register */ - TOK_S, /* S register */ - TOK_Q, /* Q pseudo register */ - TOK_REG, /* Sweet16 R.. register (in sweet16 mode) */ + TOK_FIRSTREG, /* First register name token */ + TOK_A = TOK_FIRSTREG, /* A)ccumulator */ + TOK_Q, /* Q pseudo register */ + TOK_S, /* S register */ + TOK_X, /* X register */ + TOK_Y, /* Y register */ + TOK_Z, /* Z register */ + TOK_REG, /* Sweet16 R.. register (in sweet16 mode) */ + TOK_LASTREG = TOK_REG, /* Last register name token */ - TOK_ASSIGN, /* := */ - TOK_ULABEL, /* An unnamed label */ + TOK_ASSIGN, /* := */ + TOK_ULABEL, /* An unnamed label */ - TOK_EQ, /* = */ - TOK_NE, /* <> */ - TOK_LT, /* < */ - TOK_GT, /* > */ - TOK_LE, /* <= */ - TOK_GE, /* >= */ + TOK_FIRSTOP, /* First operator token */ + TOK_EQ = TOK_FIRSTOP, /* = */ + TOK_NE, /* <> */ + TOK_LT, /* < */ + TOK_GT, /* > */ + TOK_LE, /* <= */ + TOK_GE, /* >= */ - TOK_BOOLAND, /* .and */ - TOK_BOOLOR, /* .or */ - TOK_BOOLXOR, /* .xor */ - TOK_BOOLNOT, /* .not */ + TOK_BOOLAND, /* .and */ + TOK_BOOLOR, /* .or */ + TOK_BOOLXOR, /* .xor */ + TOK_BOOLNOT, /* .not */ - TOK_PLUS, /* + */ - TOK_MINUS, /* - */ - TOK_MUL, /* * */ - TOK_STAR = TOK_MUL, /* Alias */ - TOK_DIV, /* / */ - TOK_MOD, /* ! */ - TOK_OR, /* | */ - TOK_XOR, /* ^ */ - TOK_AND, /* & */ - TOK_SHL, /* << */ - TOK_SHR, /* >> */ - TOK_NOT, /* ~ */ + TOK_PLUS, /* + */ + TOK_MINUS, /* - */ + TOK_MUL, /* * */ + TOK_STAR = TOK_MUL, /* Alias */ + TOK_DIV, /* / */ + TOK_MOD, /* ! */ + TOK_OR, /* | */ + TOK_XOR, /* ^ */ + TOK_AND, /* & */ + TOK_SHL, /* << */ + TOK_SHR, /* >> */ + TOK_NOT, /* ~ */ + TOK_LASTOP = TOK_NOT, /* Last operator token */ - TOK_PC, /* $ if enabled */ - TOK_NAMESPACE, /* :: */ - TOK_DOT, /* . */ - TOK_COMMA, /* , */ - TOK_HASH, /* # */ - TOK_COLON, /* : */ - TOK_LPAREN, /* ( */ - TOK_RPAREN, /* ) */ - TOK_LBRACK, /* [ */ - TOK_RBRACK, /* ] */ - TOK_LCURLY, /* { */ - TOK_RCURLY, /* } */ - TOK_AT, /* @ - in Sweet16 mode */ + TOK_PC, /* $ if enabled */ + TOK_NAMESPACE, /* :: */ + TOK_DOT, /* . */ + TOK_COMMA, /* , */ + TOK_HASH, /* # */ + TOK_COLON, /* : */ + TOK_LPAREN, /* ( */ + TOK_RPAREN, /* ) */ + TOK_LBRACK, /* [ */ + TOK_RBRACK, /* ] */ + TOK_LCURLY, /* { */ + TOK_RCURLY, /* } */ + TOK_AT, /* @ - in Sweet16 mode */ - TOK_OVERRIDE_ZP, /* z: */ - TOK_OVERRIDE_ABS, /* a: */ - TOK_OVERRIDE_FAR, /* f: */ + TOK_OVERRIDE_ZP, /* z: */ + TOK_OVERRIDE_ABS, /* a: */ + TOK_OVERRIDE_FAR, /* f: */ - TOK_MACPARAM, /* Macro parameter, not generated by scanner */ - TOK_REPCOUNTER, /* Repeat counter, not generated by scanner */ + TOK_MACPARAM, /* Macro parameter, not generated by scanner */ + TOK_REPCOUNTER, /* Repeat counter, not generated by scanner */ /* The next ones are tokens for the pseudo instructions. Keep together! */ TOK_FIRSTPSEUDO, - TOK_A16 = TOK_FIRSTPSEUDO, + TOK_A16 = TOK_FIRSTPSEUDO, TOK_A8, TOK_ADDR, TOK_ADDRSIZE, @@ -283,9 +287,9 @@ typedef enum token_t { TOK_WORD, TOK_XMATCH, TOK_ZEROPAGE, - TOK_LASTPSEUDO = TOK_ZEROPAGE, + TOK_LASTPSEUDO = TOK_ZEROPAGE, - TOK_COUNT /* Count of tokens */ + TOK_COUNT /* Count of tokens */ } token_t; @@ -317,11 +321,27 @@ struct Token { -int TokHasSVal (token_t Tok); +#if defined(HAVE_INLINE) +INLINE int TokHasSVal (token_t Tok) /* Return true if the given token has an attached SVal */ +{ + return (Tok == TOK_IDENT || Tok == TOK_LOCAL_IDENT || Tok == TOK_STRCON); +} +#else +# define TokHasSVal(T) \ + ((T) == TOK_IDENT || (T) == TOK_LOCAL_IDENT || (T) == TOK_STRCON) +#endif -int TokHasIVal (token_t Tok); +#if defined(HAVE_INLINE) +INLINE int TokHasIVal (token_t Tok) /* Return true if the given token has an attached IVal */ +{ + return (Tok == TOK_INTCON || Tok == TOK_CHARCON || Tok == TOK_REG); +} +#else +# define TokHasIVal(T) \ + ((T) == TOK_INTCON || (T) == TOK_CHARCON || (T) == TOK_REG) +#endif static inline int TokIsSep (enum token_t T) /* Return true if this is a separator token */ @@ -334,6 +354,9 @@ void CopyToken (Token* Dst, const Token* Src); ** initialized. */ +StrBuf* TokenDesc (const Token* T, StrBuf* S); +/* Place a textual description of the given token into S. */ + /* End of token.h */ diff --git a/src/ca65/ulabel.c b/src/ca65/ulabel.c index 19bec0671..43ba8f815 100644 --- a/src/ca65/ulabel.c +++ b/src/ca65/ulabel.c @@ -111,7 +111,7 @@ ExprNode* ULabRef (int Which) if (Which == 0) { Error ("Invalid unnamed label reference"); /* We must return something valid */ - return GenCurrentPC(); + return GenCurrentPC (); } /* Get the index of the referenced label */ @@ -125,7 +125,7 @@ ExprNode* ULabRef (int Which) /* Label does not exist */ Error ("Undefined label"); /* We must return something valid */ - return GenCurrentPC(); + return GenCurrentPC (); } /* Check if the label exists. If not, generate enough forward labels. */ diff --git a/test/asm/cpudetect/cpudetect.s b/test/asm/cpudetect/cpudetect.s index 3022038a2..0febfc3e5 100644 --- a/test/asm/cpudetect/cpudetect.s +++ b/test/asm/cpudetect/cpudetect.s @@ -1,6 +1,4 @@ -.macpack cpu - ; step 1: try to assemble an instruction that's exclusive to this set ; (when possible) diff --git a/test/asm/listing/120-errormsg.s b/test/asm/listing/120-errormsg.s new file mode 100644 index 000000000..2fa679e6f --- /dev/null +++ b/test/asm/listing/120-errormsg.s @@ -0,0 +1 @@ +0: diff --git a/test/asm/listing/121-errormsg.s b/test/asm/listing/121-errormsg.s new file mode 100644 index 000000000..257cc5642 --- /dev/null +++ b/test/asm/listing/121-errormsg.s @@ -0,0 +1 @@ +foo diff --git a/test/asm/listing/122-errormsg.s b/test/asm/listing/122-errormsg.s new file mode 100644 index 000000000..8df3ea0f3 --- /dev/null +++ b/test/asm/listing/122-errormsg.s @@ -0,0 +1,3 @@ +.struct x + .word +.endstruct diff --git a/test/asm/listing/123-errormsg.s b/test/asm/listing/123-errormsg.s new file mode 100644 index 000000000..383fe0236 --- /dev/null +++ b/test/asm/listing/123-errormsg.s @@ -0,0 +1 @@ + lda #$00 foo diff --git a/test/asm/listing/124-errormsg.s b/test/asm/listing/124-errormsg.s new file mode 100644 index 000000000..66ef83635 --- /dev/null +++ b/test/asm/listing/124-errormsg.s @@ -0,0 +1 @@ + lda ($00),a diff --git a/test/asm/listing/125-errormsg.s b/test/asm/listing/125-errormsg.s new file mode 100644 index 000000000..69e6a77ea --- /dev/null +++ b/test/asm/listing/125-errormsg.s @@ -0,0 +1 @@ + lda ($00,a) diff --git a/test/asm/listing/126-errormsg.s b/test/asm/listing/126-errormsg.s new file mode 100644 index 000000000..17a69ef45 --- /dev/null +++ b/test/asm/listing/126-errormsg.s @@ -0,0 +1,3 @@ +.struct foo + bar +.endstruct diff --git a/test/asm/listing/127-errormsg.s b/test/asm/listing/127-errormsg.s new file mode 100644 index 000000000..fb41ded23 --- /dev/null +++ b/test/asm/listing/127-errormsg.s @@ -0,0 +1 @@ + 127 diff --git a/test/asm/listing/128-errormsg.s b/test/asm/listing/128-errormsg.s new file mode 100644 index 000000000..c96f6c160 --- /dev/null +++ b/test/asm/listing/128-errormsg.s @@ -0,0 +1 @@ + .fileopt author diff --git a/test/asm/listing/129-errormsg.s b/test/asm/listing/129-errormsg.s new file mode 100644 index 000000000..5a8fb7b5f --- /dev/null +++ b/test/asm/listing/129-errormsg.s @@ -0,0 +1 @@ + .assert 1 diff --git a/test/asm/listing/130-errormsg.s b/test/asm/listing/130-errormsg.s new file mode 100644 index 000000000..eb85bc0e1 --- /dev/null +++ b/test/asm/listing/130-errormsg.s @@ -0,0 +1,2 @@ + lda | + diff --git a/test/asm/listing/131-errormsg.s b/test/asm/listing/131-errormsg.s new file mode 100644 index 000000000..3dccb45dd --- /dev/null +++ b/test/asm/listing/131-errormsg.s @@ -0,0 +1 @@ + .byte 0 1 diff --git a/test/asm/listing/132-errormsg.s b/test/asm/listing/132-errormsg.s new file mode 100644 index 000000000..648cf21bd --- /dev/null +++ b/test/asm/listing/132-errormsg.s @@ -0,0 +1 @@ +.define debug(x) .out x diff --git a/test/asm/listing/133-errormsg.s b/test/asm/listing/133-errormsg.s new file mode 100644 index 000000000..8bc4bae9f --- /dev/null +++ b/test/asm/listing/133-errormsg.s @@ -0,0 +1,3 @@ +.repeat 10 + .byte $00 + diff --git a/test/asm/listing/134-errormsg.s b/test/asm/listing/134-errormsg.s new file mode 100644 index 000000000..fa2abff13 --- /dev/null +++ b/test/asm/listing/134-errormsg.s @@ -0,0 +1,4 @@ + .import foo + + foo = 3 + diff --git a/test/asm/listing/135-errormsg.s b/test/asm/listing/135-errormsg.s new file mode 100644 index 000000000..f05adbb55 --- /dev/null +++ b/test/asm/listing/135-errormsg.s @@ -0,0 +1,5 @@ + foo = 3 + + + foo = 2 + diff --git a/test/asm/listing/136-errormsg.s b/test/asm/listing/136-errormsg.s new file mode 100644 index 000000000..0ef06dd17 --- /dev/null +++ b/test/asm/listing/136-errormsg.s @@ -0,0 +1,5 @@ +.macro mac + + lda #$00 + .byte 3 + diff --git a/test/asm/listing/137-errormsg.s b/test/asm/listing/137-errormsg.s new file mode 100644 index 000000000..4b5a4ddbf --- /dev/null +++ b/test/asm/listing/137-errormsg.s @@ -0,0 +1,5 @@ +.mac lda, val + ldx #val + txa + + diff --git a/test/asm/listing/138-errormsg.s b/test/asm/listing/138-errormsg.s new file mode 100644 index 000000000..4ca62b741 --- /dev/null +++ b/test/asm/listing/138-errormsg.s @@ -0,0 +1,4 @@ +.macro mac + .local .endmacro +.endmacro +mac diff --git a/test/asm/listing/139-errormsg.s b/test/asm/listing/139-errormsg.s new file mode 100644 index 000000000..d55cd7df9 --- /dev/null +++ b/test/asm/listing/139-errormsg.s @@ -0,0 +1,6 @@ +.macro mac val + lda #val +.endmacro +.macro mac val + lda #val +.endmacro diff --git a/test/asm/listing/140-errormsg.s b/test/asm/listing/140-errormsg.s new file mode 100644 index 000000000..b467dee11 --- /dev/null +++ b/test/asm/listing/140-errormsg.s @@ -0,0 +1,5 @@ +.macro foo a1, a2 + .byte a1, a2 +.endmacro + +foo 1, 2, 3 diff --git a/test/asm/listing/141-errormsg.s b/test/asm/listing/141-errormsg.s new file mode 100644 index 000000000..60d4748b4 --- /dev/null +++ b/test/asm/listing/141-errormsg.s @@ -0,0 +1,7 @@ +.macro mac1 + .delmac mac2 +.endmacro +.macro mac2 + mac1 +.endmacro +mac2 diff --git a/test/asm/listing/142-errormsg.s b/test/asm/listing/142-errormsg.s new file mode 100644 index 000000000..9c99304f3 --- /dev/null +++ b/test/asm/listing/142-errormsg.s @@ -0,0 +1,6 @@ +.macro mac + .define endmac .endmacro +.endmacro +.macro mac + .define endmac .endmacro +.endmacro diff --git a/test/asm/listing/control/120-errormsg.err b/test/asm/listing/control/120-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/121-errormsg.err b/test/asm/listing/control/121-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/122-errormsg.err b/test/asm/listing/control/122-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/123-errormsg.err b/test/asm/listing/control/123-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/124-errormsg.err b/test/asm/listing/control/124-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/125-errormsg.err b/test/asm/listing/control/125-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/126-errormsg.err b/test/asm/listing/control/126-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/127-errormsg.err b/test/asm/listing/control/127-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/128-errormsg.err b/test/asm/listing/control/128-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/129-errormsg.err b/test/asm/listing/control/129-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/130-errormsg.err b/test/asm/listing/control/130-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/131-errormsg.err b/test/asm/listing/control/131-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/132-errormsg.err b/test/asm/listing/control/132-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/133-errormsg.err b/test/asm/listing/control/133-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/134-errormsg.err b/test/asm/listing/control/134-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/135-errormsg.err b/test/asm/listing/control/135-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/136-errormsg.err b/test/asm/listing/control/136-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/137-errormsg.err b/test/asm/listing/control/137-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/138-errormsg.err b/test/asm/listing/control/138-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/139-errormsg.err b/test/asm/listing/control/139-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/140-errormsg.err b/test/asm/listing/control/140-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/141-errormsg.err b/test/asm/listing/control/141-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/control/142-errormsg.err b/test/asm/listing/control/142-errormsg.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/ref/110-capabilities.err2-ref b/test/asm/listing/ref/110-capabilities.err2-ref index e00e60e17..c6999d4c0 100644 --- a/test/asm/listing/ref/110-capabilities.err2-ref +++ b/test/asm/listing/ref/110-capabilities.err2-ref @@ -1,6 +1,6 @@ -110-capabilities.s:3: Error: Arguments to .CAPABILITY must be identifiers -110-capabilities.s:8: Error: Arguments to .CAPABILITY must be identifiers -110-capabilities.s:8: Error: ')' expected +110-capabilities.s:3: Error: Expected a capability name but found ')' +110-capabilities.s:8: Error: Expected a capability name but found 'end-of-line' +110-capabilities.s:8: Error: Expected ')' but found 'end-of-line' 110-capabilities.s:12: Error: Not a valid capability name: CPU_HAS_BR -110-capabilities.s:17: Error: ')' expected -110-capabilities.s:17: Error: Unexpected trailing garbage characters +110-capabilities.s:17: Error: Expected ')' but found 'cpu_has_bra8' +110-capabilities.s:17: Error: Expected 'end-of-line' but found 'cpu_has_bra8' diff --git a/test/asm/listing/ref/120-errormsg.err2-ref b/test/asm/listing/ref/120-errormsg.err2-ref new file mode 100644 index 000000000..80595d97d --- /dev/null +++ b/test/asm/listing/ref/120-errormsg.err2-ref @@ -0,0 +1 @@ +120-errormsg.s:1: Error: Expected a mnemonic but found '0' diff --git a/test/asm/listing/ref/121-errormsg.err2-ref b/test/asm/listing/ref/121-errormsg.err2-ref new file mode 100644 index 000000000..abc16d4d5 --- /dev/null +++ b/test/asm/listing/ref/121-errormsg.err2-ref @@ -0,0 +1 @@ +121-errormsg.s:1: Error: Expected ':' after identifier to form a label but found 'end-of-line' diff --git a/test/asm/listing/ref/122-errormsg.err2-ref b/test/asm/listing/ref/122-errormsg.err2-ref new file mode 100644 index 000000000..692ac0cc6 --- /dev/null +++ b/test/asm/listing/ref/122-errormsg.err2-ref @@ -0,0 +1 @@ +122-errormsg.s:1: Error: Expected a struct/union name but found 'X' diff --git a/test/asm/listing/ref/123-errormsg.err2-ref b/test/asm/listing/ref/123-errormsg.err2-ref new file mode 100644 index 000000000..f7db86f47 --- /dev/null +++ b/test/asm/listing/ref/123-errormsg.err2-ref @@ -0,0 +1 @@ +123-errormsg.s:1: Error: Expected 'end-of-line' but found 'foo' diff --git a/test/asm/listing/ref/124-errormsg.err2-ref b/test/asm/listing/ref/124-errormsg.err2-ref new file mode 100644 index 000000000..b96690f68 --- /dev/null +++ b/test/asm/listing/ref/124-errormsg.err2-ref @@ -0,0 +1 @@ +124-errormsg.s:1: Error: Expected 'Y' but found 'A' diff --git a/test/asm/listing/ref/125-errormsg.err2-ref b/test/asm/listing/ref/125-errormsg.err2-ref new file mode 100644 index 000000000..4640ed3d5 --- /dev/null +++ b/test/asm/listing/ref/125-errormsg.err2-ref @@ -0,0 +1,2 @@ +125-errormsg.s:1: Error: Expected 'X' or 'S' but found 'A' +125-errormsg.s:1: Error: Illegal addressing mode diff --git a/test/asm/listing/ref/126-errormsg.err2-ref b/test/asm/listing/ref/126-errormsg.err2-ref new file mode 100644 index 000000000..ba42cc0bb --- /dev/null +++ b/test/asm/listing/ref/126-errormsg.err2-ref @@ -0,0 +1 @@ +126-errormsg.s:2: Error: Expected a storage allocator after the field name but found 'end-of-line' diff --git a/test/asm/listing/ref/127-errormsg.err2-ref b/test/asm/listing/ref/127-errormsg.err2-ref new file mode 100644 index 000000000..cdc5eada7 --- /dev/null +++ b/test/asm/listing/ref/127-errormsg.err2-ref @@ -0,0 +1 @@ +127-errormsg.s:1: Error: Expected a mnemonic but found '127' diff --git a/test/asm/listing/ref/128-errormsg.err2-ref b/test/asm/listing/ref/128-errormsg.err2-ref new file mode 100644 index 000000000..28982e479 --- /dev/null +++ b/test/asm/listing/ref/128-errormsg.err2-ref @@ -0,0 +1 @@ +128-errormsg.s:1: Error: Expected ',' but found 'end-of-line' diff --git a/test/asm/listing/ref/129-errormsg.err2-ref b/test/asm/listing/ref/129-errormsg.err2-ref new file mode 100644 index 000000000..4b35ded67 --- /dev/null +++ b/test/asm/listing/ref/129-errormsg.err2-ref @@ -0,0 +1 @@ +129-errormsg.s:1: Error: Expected ',' but found 'end-of-line' diff --git a/test/asm/listing/ref/130-errormsg.err2-ref b/test/asm/listing/ref/130-errormsg.err2-ref new file mode 100644 index 000000000..79b40a915 --- /dev/null +++ b/test/asm/listing/ref/130-errormsg.err2-ref @@ -0,0 +1,2 @@ +130-errormsg.s:1: Error: Expected an expression but found '|' +130-errormsg.s:1: Error: Expected an expression but found 'end-of-line' diff --git a/test/asm/listing/ref/131-errormsg.err2-ref b/test/asm/listing/ref/131-errormsg.err2-ref new file mode 100644 index 000000000..46cc77c62 --- /dev/null +++ b/test/asm/listing/ref/131-errormsg.err2-ref @@ -0,0 +1 @@ +131-errormsg.s:1: Error: Expected 'end-of-line' but found '1' diff --git a/test/asm/listing/ref/132-errormsg.err2-ref b/test/asm/listing/ref/132-errormsg.err2-ref new file mode 100644 index 000000000..b8e73fdf8 --- /dev/null +++ b/test/asm/listing/ref/132-errormsg.err2-ref @@ -0,0 +1,2 @@ +132-errormsg.s:1: Error: Expected a parameter name but found 'X' +132-errormsg.s:1: Error: Expected ')' but found 'X' diff --git a/test/asm/listing/ref/133-errormsg.err2-ref b/test/asm/listing/ref/133-errormsg.err2-ref new file mode 100644 index 000000000..bfa637d67 --- /dev/null +++ b/test/asm/listing/ref/133-errormsg.err2-ref @@ -0,0 +1,2 @@ +133-errormsg.s:3: Error: Expected '.ENDREPEAT' but found 'end-of-file' +133-errormsg.s:1: Note: For this '.REPEAT' command diff --git a/test/asm/listing/ref/134-errormsg.err2-ref b/test/asm/listing/ref/134-errormsg.err2-ref new file mode 100644 index 000000000..7e674fdc3 --- /dev/null +++ b/test/asm/listing/ref/134-errormsg.err2-ref @@ -0,0 +1,2 @@ +134-errormsg.s:3: Error: Symbol 'foo' is already an import +134-errormsg.s:1: Note: The symbol was previously imported here diff --git a/test/asm/listing/ref/135-errormsg.err2-ref b/test/asm/listing/ref/135-errormsg.err2-ref new file mode 100644 index 000000000..8391770fa --- /dev/null +++ b/test/asm/listing/ref/135-errormsg.err2-ref @@ -0,0 +1,2 @@ +135-errormsg.s:4: Error: Symbol 'foo' is already defined +135-errormsg.s:1: Note: The symbol was previously defined here diff --git a/test/asm/listing/ref/136-errormsg.err2-ref b/test/asm/listing/ref/136-errormsg.err2-ref new file mode 100644 index 000000000..bed70989d --- /dev/null +++ b/test/asm/listing/ref/136-errormsg.err2-ref @@ -0,0 +1,2 @@ +136-errormsg.s:5: Error: Missing '.ENDMACRO' for definition of macro 'mac' +136-errormsg.s:1: Note: Macro definition started here diff --git a/test/asm/listing/ref/137-errormsg.err2-ref b/test/asm/listing/ref/137-errormsg.err2-ref new file mode 100644 index 000000000..81ca9cd69 --- /dev/null +++ b/test/asm/listing/ref/137-errormsg.err2-ref @@ -0,0 +1,3 @@ +137-errormsg.s:1: Error: Cannot use an instruction as macro name +137-errormsg.s:5: Error: Expected '.ENDMACRO' but found 'end-of-file' +137-errormsg.s:1: Note: Macro definition started here diff --git a/test/asm/listing/ref/138-errormsg.err2-ref b/test/asm/listing/ref/138-errormsg.err2-ref new file mode 100644 index 000000000..7a73e48fc --- /dev/null +++ b/test/asm/listing/ref/138-errormsg.err2-ref @@ -0,0 +1,3 @@ +138-errormsg.s:2: Error: Expected an identifier but found '.ENDMACRO' +138-errormsg.s:4: Error: Macro 'mac' contains errors and cannot be expanded +138-errormsg.s:1: Note: Definition of macro 'mac' was here diff --git a/test/asm/listing/ref/139-errormsg.err2-ref b/test/asm/listing/ref/139-errormsg.err2-ref new file mode 100644 index 000000000..370835210 --- /dev/null +++ b/test/asm/listing/ref/139-errormsg.err2-ref @@ -0,0 +1,2 @@ +139-errormsg.s:4: Error: A macro named 'mac' is already defined +139-errormsg.s:1: Note: Previous definition of macro 'mac' was here diff --git a/test/asm/listing/ref/140-errormsg.err2-ref b/test/asm/listing/ref/140-errormsg.err2-ref new file mode 100644 index 000000000..f9e9adace --- /dev/null +++ b/test/asm/listing/ref/140-errormsg.err2-ref @@ -0,0 +1,2 @@ +140-errormsg.s:5: Error: Too many parameters for macro 'foo' +140-errormsg.s:1: Note: See definition of macro 'foo' which was here diff --git a/test/asm/listing/ref/141-errormsg.err2-ref b/test/asm/listing/ref/141-errormsg.err2-ref new file mode 100644 index 000000000..b99e2d9fe --- /dev/null +++ b/test/asm/listing/ref/141-errormsg.err2-ref @@ -0,0 +1,3 @@ +141-errormsg.s:7: Error: Cannot delete macro 'mac2' which is currently expanded +141-errormsg.s:5: Note: Expanded from macro here +141-errormsg.s:2: Note: Expanded from macro here diff --git a/test/asm/listing/ref/142-errormsg.err2-ref b/test/asm/listing/ref/142-errormsg.err2-ref new file mode 100644 index 000000000..8d15ac44d --- /dev/null +++ b/test/asm/listing/ref/142-errormsg.err2-ref @@ -0,0 +1,2 @@ +142-errormsg.s:4: Error: A macro named 'mac' is already defined +142-errormsg.s:1: Note: Previous definition of macro 'mac' was here