From bcd29de443f41e770d18e6e7256306f269a5accc Mon Sep 17 00:00:00 2001 From: Kugel Fuhr <98353208+kugelfuhr@users.noreply.github.com> Date: Fri, 4 Jul 2025 17:11:34 +0200 Subject: [PATCH] Much improved error messages for ca65. For most errors it will now say what was expected and what was found instead. Also improved error recovery in a few places. --- src/ca65/condasm.c | 32 +- src/ca65/dbginfo.c | 18 +- src/ca65/ea65.c | 36 ++- src/ca65/easw16.c | 2 +- src/ca65/enum.c | 11 +- src/ca65/expr.c | 20 +- src/ca65/instr.c | 4 +- src/ca65/macro.c | 18 +- src/ca65/main.c | 39 ++- src/ca65/nexttok.c | 112 +++++-- src/ca65/nexttok.h | 61 +++- src/ca65/pseudo.c | 210 ++++++------ src/ca65/repeat.c | 6 +- src/ca65/scanner.c | 12 +- src/ca65/struct.c | 34 +- src/ca65/studyexpr.c | 3 +- src/ca65/symbol.c | 5 +- src/ca65/token.c | 304 +++++++++++++++++- src/ca65/token.h | 147 +++++---- src/ca65/ulabel.c | 4 +- test/asm/cpudetect/cpudetect.s | 2 - test/asm/listing/120-errormsg.s | 1 + test/asm/listing/121-errormsg.s | 1 + test/asm/listing/122-errormsg.s | 3 + test/asm/listing/123-errormsg.s | 1 + test/asm/listing/124-errormsg.s | 1 + test/asm/listing/125-errormsg.s | 1 + test/asm/listing/126-errormsg.s | 3 + test/asm/listing/127-errormsg.s | 1 + test/asm/listing/128-errormsg.s | 1 + test/asm/listing/129-errormsg.s | 1 + test/asm/listing/130-errormsg.s | 2 + test/asm/listing/131-errormsg.s | 1 + .../asm/listing/ref/110-capabilities.err2-ref | 10 +- test/asm/listing/ref/120-errormsg.err2 | 1 + test/asm/listing/ref/121-errormsg.err2 | 1 + test/asm/listing/ref/122-errormsg.err2 | 1 + test/asm/listing/ref/123-errormsg.err2 | 1 + test/asm/listing/ref/124-errormsg.err2 | 1 + test/asm/listing/ref/125-errormsg.err2 | 2 + test/asm/listing/ref/126-errormsg.err2 | 1 + test/asm/listing/ref/127-errormsg.err2 | 1 + test/asm/listing/ref/128-errormsg.err2 | 1 + test/asm/listing/ref/129-errormsg.err2 | 1 + test/asm/listing/ref/130-errormsg.err2 | 2 + test/asm/listing/ref/131-errormsg.err2 | 1 + 46 files changed, 779 insertions(+), 342 deletions(-) create mode 100644 test/asm/listing/120-errormsg.s create mode 100644 test/asm/listing/121-errormsg.s create mode 100644 test/asm/listing/122-errormsg.s create mode 100644 test/asm/listing/123-errormsg.s create mode 100644 test/asm/listing/124-errormsg.s create mode 100644 test/asm/listing/125-errormsg.s create mode 100644 test/asm/listing/126-errormsg.s create mode 100644 test/asm/listing/127-errormsg.s create mode 100644 test/asm/listing/128-errormsg.s create mode 100644 test/asm/listing/129-errormsg.s create mode 100644 test/asm/listing/130-errormsg.s create mode 100644 test/asm/listing/131-errormsg.s create mode 100644 test/asm/listing/ref/120-errormsg.err2 create mode 100644 test/asm/listing/ref/121-errormsg.err2 create mode 100644 test/asm/listing/ref/122-errormsg.err2 create mode 100644 test/asm/listing/ref/123-errormsg.err2 create mode 100644 test/asm/listing/ref/124-errormsg.err2 create mode 100644 test/asm/listing/ref/125-errormsg.err2 create mode 100644 test/asm/listing/ref/126-errormsg.err2 create mode 100644 test/asm/listing/ref/127-errormsg.err2 create mode 100644 test/asm/listing/ref/128-errormsg.err2 create mode 100644 test/asm/listing/ref/129-errormsg.err2 create mode 100644 test/asm/listing/ref/130-errormsg.err2 create mode 100644 test/asm/listing/ref/131-errormsg.err2 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/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..845efec5a 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -406,11 +406,11 @@ void MacDef (unsigned Style) Pos = CurTok.Pos; /* We expect a macro name here */ - if (CurTok.Tok != TOK_IDENT) { - Error ("Identifier expected"); + if (!Expect (TOK_IDENT, "Expected an identifier")) { MacSkipDef (Style); 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. */ @@ -439,7 +439,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 +451,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); @@ -533,7 +533,7 @@ 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 (); break; } @@ -591,7 +591,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 (); @@ -938,10 +938,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"); } } } diff --git a/src/ca65/main.c b/src/ca65/main.c index 60f342567..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 { @@ -859,7 +857,8 @@ static void OneLine (void) */ if (CurTok.Tok != TOK_COLON) { if (HadWS || !NoColonLabels) { - ErrorSkip ("Expected ':' after identifier to form a label"); + ErrorExpect ("Expected ':' after identifier to form a label"); + SkipUntilSep (); goto Done; } } else { @@ -903,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) { - ErrorSkip ("'=' expected"); + if (!ExpectSkip (TOK_EQ, "Expected '='")) { goto Done; - } else { - /* Skip the equal sign */ - NextTok (); - /* Enter absolute mode */ - DoPCAssign (); } + /* 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. @@ -1233,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..08e9eda81 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 the 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 + * the 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 the 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..4f4975dd8 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 the 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 + * the 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 the 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..54e8fda4b 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 (); } diff --git a/src/ca65/repeat.c b/src/ca65/repeat.c index 90aa894f7..6a518cb37 100644 --- a/src/ca65/repeat.c +++ b/src/ca65/repeat.c @@ -120,7 +120,7 @@ void ParseRepeat (void) /* Repeat count follows */ long RepCount = ConstExpression (); if (RepCount < 0) { - Error ("Range error"); + Error ("Repeat count must be positive or zero"); RepCount = 0; } @@ -132,9 +132,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)); 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/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 b40534d79..d713a6ee1 100644 --- a/src/ca65/token.h +++ b/src/ca65/token.h @@ -53,76 +53,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, @@ -284,9 +288,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; @@ -318,11 +322,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 TokHasIVal(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 #if defined(HAVE_INLINE) INLINE int TokIsSep (enum token_t T) @@ -339,6 +359,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..6cabad9f0 --- /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..5256198b6 --- /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/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 b/test/asm/listing/ref/120-errormsg.err2 new file mode 100644 index 000000000..ac78914e0 --- /dev/null +++ b/test/asm/listing/ref/120-errormsg.err2 @@ -0,0 +1 @@ +120-errormsg.s:1: Error: Expected 'end-of-line' but found '0' diff --git a/test/asm/listing/ref/121-errormsg.err2 b/test/asm/listing/ref/121-errormsg.err2 new file mode 100644 index 000000000..abc16d4d5 --- /dev/null +++ b/test/asm/listing/ref/121-errormsg.err2 @@ -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 b/test/asm/listing/ref/122-errormsg.err2 new file mode 100644 index 000000000..692ac0cc6 --- /dev/null +++ b/test/asm/listing/ref/122-errormsg.err2 @@ -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 b/test/asm/listing/ref/123-errormsg.err2 new file mode 100644 index 000000000..f7db86f47 --- /dev/null +++ b/test/asm/listing/ref/123-errormsg.err2 @@ -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 b/test/asm/listing/ref/124-errormsg.err2 new file mode 100644 index 000000000..b96690f68 --- /dev/null +++ b/test/asm/listing/ref/124-errormsg.err2 @@ -0,0 +1 @@ +124-errormsg.s:1: Error: Expected 'Y' but found 'A' diff --git a/test/asm/listing/ref/125-errormsg.err2 b/test/asm/listing/ref/125-errormsg.err2 new file mode 100644 index 000000000..4640ed3d5 --- /dev/null +++ b/test/asm/listing/ref/125-errormsg.err2 @@ -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 b/test/asm/listing/ref/126-errormsg.err2 new file mode 100644 index 000000000..ba42cc0bb --- /dev/null +++ b/test/asm/listing/ref/126-errormsg.err2 @@ -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 b/test/asm/listing/ref/127-errormsg.err2 new file mode 100644 index 000000000..cdc5eada7 --- /dev/null +++ b/test/asm/listing/ref/127-errormsg.err2 @@ -0,0 +1 @@ +127-errormsg.s:1: Error: Expected a mnemonic but found '127' diff --git a/test/asm/listing/ref/128-errormsg.err2 b/test/asm/listing/ref/128-errormsg.err2 new file mode 100644 index 000000000..28982e479 --- /dev/null +++ b/test/asm/listing/ref/128-errormsg.err2 @@ -0,0 +1 @@ +128-errormsg.s:1: Error: Expected ',' but found 'end-of-line' diff --git a/test/asm/listing/ref/129-errormsg.err2 b/test/asm/listing/ref/129-errormsg.err2 new file mode 100644 index 000000000..4b35ded67 --- /dev/null +++ b/test/asm/listing/ref/129-errormsg.err2 @@ -0,0 +1 @@ +129-errormsg.s:1: Error: Expected ',' but found 'end-of-line' diff --git a/test/asm/listing/ref/130-errormsg.err2 b/test/asm/listing/ref/130-errormsg.err2 new file mode 100644 index 000000000..79b40a915 --- /dev/null +++ b/test/asm/listing/ref/130-errormsg.err2 @@ -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 b/test/asm/listing/ref/131-errormsg.err2 new file mode 100644 index 000000000..46cc77c62 --- /dev/null +++ b/test/asm/listing/ref/131-errormsg.err2 @@ -0,0 +1 @@ +131-errormsg.s:1: Error: Expected 'end-of-line' but found '1'