Merge pull request #2777 from kugelfuhr/kugelfuhr/ca65-errors
Improve error handling for ca65
This commit is contained in:
@@ -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 ();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -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. */
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
119
src/ca65/macro.c
119
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
304
src/ca65/token.c
304
src/ca65/token.c
@@ -33,30 +33,261 @@
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
147
src/ca65/token.h
147
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 */
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
|
||||
.macpack cpu
|
||||
|
||||
; step 1: try to assemble an instruction that's exclusive to this set
|
||||
; (when possible)
|
||||
|
||||
|
||||
1
test/asm/listing/120-errormsg.s
Normal file
1
test/asm/listing/120-errormsg.s
Normal file
@@ -0,0 +1 @@
|
||||
0:
|
||||
1
test/asm/listing/121-errormsg.s
Normal file
1
test/asm/listing/121-errormsg.s
Normal file
@@ -0,0 +1 @@
|
||||
foo
|
||||
3
test/asm/listing/122-errormsg.s
Normal file
3
test/asm/listing/122-errormsg.s
Normal file
@@ -0,0 +1,3 @@
|
||||
.struct x
|
||||
.word
|
||||
.endstruct
|
||||
1
test/asm/listing/123-errormsg.s
Normal file
1
test/asm/listing/123-errormsg.s
Normal file
@@ -0,0 +1 @@
|
||||
lda #$00 foo
|
||||
1
test/asm/listing/124-errormsg.s
Normal file
1
test/asm/listing/124-errormsg.s
Normal file
@@ -0,0 +1 @@
|
||||
lda ($00),a
|
||||
1
test/asm/listing/125-errormsg.s
Normal file
1
test/asm/listing/125-errormsg.s
Normal file
@@ -0,0 +1 @@
|
||||
lda ($00,a)
|
||||
3
test/asm/listing/126-errormsg.s
Normal file
3
test/asm/listing/126-errormsg.s
Normal file
@@ -0,0 +1,3 @@
|
||||
.struct foo
|
||||
bar
|
||||
.endstruct
|
||||
1
test/asm/listing/127-errormsg.s
Normal file
1
test/asm/listing/127-errormsg.s
Normal file
@@ -0,0 +1 @@
|
||||
127
|
||||
1
test/asm/listing/128-errormsg.s
Normal file
1
test/asm/listing/128-errormsg.s
Normal file
@@ -0,0 +1 @@
|
||||
.fileopt author
|
||||
1
test/asm/listing/129-errormsg.s
Normal file
1
test/asm/listing/129-errormsg.s
Normal file
@@ -0,0 +1 @@
|
||||
.assert 1
|
||||
2
test/asm/listing/130-errormsg.s
Normal file
2
test/asm/listing/130-errormsg.s
Normal file
@@ -0,0 +1,2 @@
|
||||
lda |
|
||||
|
||||
1
test/asm/listing/131-errormsg.s
Normal file
1
test/asm/listing/131-errormsg.s
Normal file
@@ -0,0 +1 @@
|
||||
.byte 0 1
|
||||
1
test/asm/listing/132-errormsg.s
Normal file
1
test/asm/listing/132-errormsg.s
Normal file
@@ -0,0 +1 @@
|
||||
.define debug(x) .out x
|
||||
3
test/asm/listing/133-errormsg.s
Normal file
3
test/asm/listing/133-errormsg.s
Normal file
@@ -0,0 +1,3 @@
|
||||
.repeat 10
|
||||
.byte $00
|
||||
|
||||
4
test/asm/listing/134-errormsg.s
Normal file
4
test/asm/listing/134-errormsg.s
Normal file
@@ -0,0 +1,4 @@
|
||||
.import foo
|
||||
|
||||
foo = 3
|
||||
|
||||
5
test/asm/listing/135-errormsg.s
Normal file
5
test/asm/listing/135-errormsg.s
Normal file
@@ -0,0 +1,5 @@
|
||||
foo = 3
|
||||
|
||||
|
||||
foo = 2
|
||||
|
||||
5
test/asm/listing/136-errormsg.s
Normal file
5
test/asm/listing/136-errormsg.s
Normal file
@@ -0,0 +1,5 @@
|
||||
.macro mac
|
||||
|
||||
lda #$00
|
||||
.byte 3
|
||||
|
||||
5
test/asm/listing/137-errormsg.s
Normal file
5
test/asm/listing/137-errormsg.s
Normal file
@@ -0,0 +1,5 @@
|
||||
.mac lda, val
|
||||
ldx #val
|
||||
txa
|
||||
|
||||
|
||||
4
test/asm/listing/138-errormsg.s
Normal file
4
test/asm/listing/138-errormsg.s
Normal file
@@ -0,0 +1,4 @@
|
||||
.macro mac
|
||||
.local .endmacro
|
||||
.endmacro
|
||||
mac
|
||||
6
test/asm/listing/139-errormsg.s
Normal file
6
test/asm/listing/139-errormsg.s
Normal file
@@ -0,0 +1,6 @@
|
||||
.macro mac val
|
||||
lda #val
|
||||
.endmacro
|
||||
.macro mac val
|
||||
lda #val
|
||||
.endmacro
|
||||
5
test/asm/listing/140-errormsg.s
Normal file
5
test/asm/listing/140-errormsg.s
Normal file
@@ -0,0 +1,5 @@
|
||||
.macro foo a1, a2
|
||||
.byte a1, a2
|
||||
.endmacro
|
||||
|
||||
foo 1, 2, 3
|
||||
7
test/asm/listing/141-errormsg.s
Normal file
7
test/asm/listing/141-errormsg.s
Normal file
@@ -0,0 +1,7 @@
|
||||
.macro mac1
|
||||
.delmac mac2
|
||||
.endmacro
|
||||
.macro mac2
|
||||
mac1
|
||||
.endmacro
|
||||
mac2
|
||||
6
test/asm/listing/142-errormsg.s
Normal file
6
test/asm/listing/142-errormsg.s
Normal file
@@ -0,0 +1,6 @@
|
||||
.macro mac
|
||||
.define endmac .endmacro
|
||||
.endmacro
|
||||
.macro mac
|
||||
.define endmac .endmacro
|
||||
.endmacro
|
||||
0
test/asm/listing/control/120-errormsg.err
Normal file
0
test/asm/listing/control/120-errormsg.err
Normal file
0
test/asm/listing/control/121-errormsg.err
Normal file
0
test/asm/listing/control/121-errormsg.err
Normal file
0
test/asm/listing/control/122-errormsg.err
Normal file
0
test/asm/listing/control/122-errormsg.err
Normal file
0
test/asm/listing/control/123-errormsg.err
Normal file
0
test/asm/listing/control/123-errormsg.err
Normal file
0
test/asm/listing/control/124-errormsg.err
Normal file
0
test/asm/listing/control/124-errormsg.err
Normal file
0
test/asm/listing/control/125-errormsg.err
Normal file
0
test/asm/listing/control/125-errormsg.err
Normal file
0
test/asm/listing/control/126-errormsg.err
Normal file
0
test/asm/listing/control/126-errormsg.err
Normal file
0
test/asm/listing/control/127-errormsg.err
Normal file
0
test/asm/listing/control/127-errormsg.err
Normal file
0
test/asm/listing/control/128-errormsg.err
Normal file
0
test/asm/listing/control/128-errormsg.err
Normal file
0
test/asm/listing/control/129-errormsg.err
Normal file
0
test/asm/listing/control/129-errormsg.err
Normal file
0
test/asm/listing/control/130-errormsg.err
Normal file
0
test/asm/listing/control/130-errormsg.err
Normal file
0
test/asm/listing/control/131-errormsg.err
Normal file
0
test/asm/listing/control/131-errormsg.err
Normal file
0
test/asm/listing/control/132-errormsg.err
Normal file
0
test/asm/listing/control/132-errormsg.err
Normal file
0
test/asm/listing/control/133-errormsg.err
Normal file
0
test/asm/listing/control/133-errormsg.err
Normal file
0
test/asm/listing/control/134-errormsg.err
Normal file
0
test/asm/listing/control/134-errormsg.err
Normal file
0
test/asm/listing/control/135-errormsg.err
Normal file
0
test/asm/listing/control/135-errormsg.err
Normal file
0
test/asm/listing/control/136-errormsg.err
Normal file
0
test/asm/listing/control/136-errormsg.err
Normal file
0
test/asm/listing/control/137-errormsg.err
Normal file
0
test/asm/listing/control/137-errormsg.err
Normal file
0
test/asm/listing/control/138-errormsg.err
Normal file
0
test/asm/listing/control/138-errormsg.err
Normal file
0
test/asm/listing/control/139-errormsg.err
Normal file
0
test/asm/listing/control/139-errormsg.err
Normal file
0
test/asm/listing/control/140-errormsg.err
Normal file
0
test/asm/listing/control/140-errormsg.err
Normal file
0
test/asm/listing/control/141-errormsg.err
Normal file
0
test/asm/listing/control/141-errormsg.err
Normal file
0
test/asm/listing/control/142-errormsg.err
Normal file
0
test/asm/listing/control/142-errormsg.err
Normal file
@@ -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'
|
||||
|
||||
1
test/asm/listing/ref/120-errormsg.err2-ref
Normal file
1
test/asm/listing/ref/120-errormsg.err2-ref
Normal file
@@ -0,0 +1 @@
|
||||
120-errormsg.s:1: Error: Expected a mnemonic but found '0'
|
||||
1
test/asm/listing/ref/121-errormsg.err2-ref
Normal file
1
test/asm/listing/ref/121-errormsg.err2-ref
Normal file
@@ -0,0 +1 @@
|
||||
121-errormsg.s:1: Error: Expected ':' after identifier to form a label but found 'end-of-line'
|
||||
1
test/asm/listing/ref/122-errormsg.err2-ref
Normal file
1
test/asm/listing/ref/122-errormsg.err2-ref
Normal file
@@ -0,0 +1 @@
|
||||
122-errormsg.s:1: Error: Expected a struct/union name but found 'X'
|
||||
1
test/asm/listing/ref/123-errormsg.err2-ref
Normal file
1
test/asm/listing/ref/123-errormsg.err2-ref
Normal file
@@ -0,0 +1 @@
|
||||
123-errormsg.s:1: Error: Expected 'end-of-line' but found 'foo'
|
||||
1
test/asm/listing/ref/124-errormsg.err2-ref
Normal file
1
test/asm/listing/ref/124-errormsg.err2-ref
Normal file
@@ -0,0 +1 @@
|
||||
124-errormsg.s:1: Error: Expected 'Y' but found 'A'
|
||||
2
test/asm/listing/ref/125-errormsg.err2-ref
Normal file
2
test/asm/listing/ref/125-errormsg.err2-ref
Normal file
@@ -0,0 +1,2 @@
|
||||
125-errormsg.s:1: Error: Expected 'X' or 'S' but found 'A'
|
||||
125-errormsg.s:1: Error: Illegal addressing mode
|
||||
1
test/asm/listing/ref/126-errormsg.err2-ref
Normal file
1
test/asm/listing/ref/126-errormsg.err2-ref
Normal file
@@ -0,0 +1 @@
|
||||
126-errormsg.s:2: Error: Expected a storage allocator after the field name but found 'end-of-line'
|
||||
1
test/asm/listing/ref/127-errormsg.err2-ref
Normal file
1
test/asm/listing/ref/127-errormsg.err2-ref
Normal file
@@ -0,0 +1 @@
|
||||
127-errormsg.s:1: Error: Expected a mnemonic but found '127'
|
||||
1
test/asm/listing/ref/128-errormsg.err2-ref
Normal file
1
test/asm/listing/ref/128-errormsg.err2-ref
Normal file
@@ -0,0 +1 @@
|
||||
128-errormsg.s:1: Error: Expected ',' but found 'end-of-line'
|
||||
1
test/asm/listing/ref/129-errormsg.err2-ref
Normal file
1
test/asm/listing/ref/129-errormsg.err2-ref
Normal file
@@ -0,0 +1 @@
|
||||
129-errormsg.s:1: Error: Expected ',' but found 'end-of-line'
|
||||
2
test/asm/listing/ref/130-errormsg.err2-ref
Normal file
2
test/asm/listing/ref/130-errormsg.err2-ref
Normal file
@@ -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'
|
||||
1
test/asm/listing/ref/131-errormsg.err2-ref
Normal file
1
test/asm/listing/ref/131-errormsg.err2-ref
Normal file
@@ -0,0 +1 @@
|
||||
131-errormsg.s:1: Error: Expected 'end-of-line' but found '1'
|
||||
2
test/asm/listing/ref/132-errormsg.err2-ref
Normal file
2
test/asm/listing/ref/132-errormsg.err2-ref
Normal file
@@ -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'
|
||||
2
test/asm/listing/ref/133-errormsg.err2-ref
Normal file
2
test/asm/listing/ref/133-errormsg.err2-ref
Normal file
@@ -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
|
||||
2
test/asm/listing/ref/134-errormsg.err2-ref
Normal file
2
test/asm/listing/ref/134-errormsg.err2-ref
Normal file
@@ -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
|
||||
2
test/asm/listing/ref/135-errormsg.err2-ref
Normal file
2
test/asm/listing/ref/135-errormsg.err2-ref
Normal file
@@ -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
|
||||
2
test/asm/listing/ref/136-errormsg.err2-ref
Normal file
2
test/asm/listing/ref/136-errormsg.err2-ref
Normal file
@@ -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
|
||||
3
test/asm/listing/ref/137-errormsg.err2-ref
Normal file
3
test/asm/listing/ref/137-errormsg.err2-ref
Normal file
@@ -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
|
||||
3
test/asm/listing/ref/138-errormsg.err2-ref
Normal file
3
test/asm/listing/ref/138-errormsg.err2-ref
Normal file
@@ -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
|
||||
2
test/asm/listing/ref/139-errormsg.err2-ref
Normal file
2
test/asm/listing/ref/139-errormsg.err2-ref
Normal file
@@ -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
|
||||
2
test/asm/listing/ref/140-errormsg.err2-ref
Normal file
2
test/asm/listing/ref/140-errormsg.err2-ref
Normal file
@@ -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
|
||||
3
test/asm/listing/ref/141-errormsg.err2-ref
Normal file
3
test/asm/listing/ref/141-errormsg.err2-ref
Normal file
@@ -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
|
||||
2
test/asm/listing/ref/142-errormsg.err2-ref
Normal file
2
test/asm/listing/ref/142-errormsg.err2-ref
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user