Merge pull request #2777 from kugelfuhr/kugelfuhr/ca65-errors
Improve error handling for ca65
This commit is contained in:
@@ -238,8 +238,7 @@ void DbgInfoFunc (void)
|
|||||||
ConsumeComma ();
|
ConsumeComma ();
|
||||||
|
|
||||||
/* Type */
|
/* Type */
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
|
||||||
ErrorSkip ("String constant expected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Type = ValidateType (&CurTok.SVal);
|
Type = ValidateType (&CurTok.SVal);
|
||||||
@@ -267,8 +266,7 @@ void DbgInfoFunc (void)
|
|||||||
ConsumeComma ();
|
ConsumeComma ();
|
||||||
|
|
||||||
/* Assembler name follows */
|
/* Assembler name follows */
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
|
||||||
ErrorSkip ("String constant expected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AsmName = GetStrBufId (&CurTok.SVal);
|
AsmName = GetStrBufId (&CurTok.SVal);
|
||||||
@@ -321,8 +319,7 @@ void DbgInfoLine (void)
|
|||||||
ConsumeComma ();
|
ConsumeComma ();
|
||||||
|
|
||||||
/* The name of the file follows */
|
/* The name of the file follows */
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
|
||||||
ErrorSkip ("String constant expected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,8 +368,7 @@ void DbgInfoSym (void)
|
|||||||
ConsumeComma ();
|
ConsumeComma ();
|
||||||
|
|
||||||
/* Name */
|
/* Name */
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
|
||||||
ErrorSkip ("String constant expected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Name = GetStrBufId (&CurTok.SVal);
|
Name = GetStrBufId (&CurTok.SVal);
|
||||||
@@ -382,8 +378,7 @@ void DbgInfoSym (void)
|
|||||||
ConsumeComma ();
|
ConsumeComma ();
|
||||||
|
|
||||||
/* Type */
|
/* Type */
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
|
||||||
ErrorSkip ("String constant expected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Type = ValidateType (&CurTok.SVal);
|
Type = ValidateType (&CurTok.SVal);
|
||||||
@@ -418,8 +413,7 @@ void DbgInfoSym (void)
|
|||||||
Offs = ConstExpression ();
|
Offs = ConstExpression ();
|
||||||
} else {
|
} else {
|
||||||
/* Register, extern or static: Assembler name follows */
|
/* Register, extern or static: Assembler name follows */
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
|
||||||
ErrorSkip ("String constant expected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AsmName = GetStrBufId (&CurTok.SVal);
|
AsmName = GetStrBufId (&CurTok.SVal);
|
||||||
|
|||||||
@@ -62,11 +62,11 @@ void GetEA (EffAddr* A)
|
|||||||
if (BracketAsIndirect) {
|
if (BracketAsIndirect) {
|
||||||
IndirectEnter = TOK_LBRACK;
|
IndirectEnter = TOK_LBRACK;
|
||||||
IndirectLeave = TOK_RBRACK;
|
IndirectLeave = TOK_RBRACK;
|
||||||
IndirectExpect = "']' expected";
|
IndirectExpect = "Expected ']'";
|
||||||
} else {
|
} else {
|
||||||
IndirectEnter = TOK_LPAREN;
|
IndirectEnter = TOK_LPAREN;
|
||||||
IndirectLeave = TOK_RPAREN;
|
IndirectLeave = TOK_RPAREN;
|
||||||
IndirectExpect = "')' expected";
|
IndirectExpect = "Expected ')'";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear the output struct */
|
/* Clear the output struct */
|
||||||
@@ -136,16 +136,22 @@ void GetEA (EffAddr* A)
|
|||||||
/* (adr,x) */
|
/* (adr,x) */
|
||||||
NextTok ();
|
NextTok ();
|
||||||
A->AddrModeSet = AM65_ABS_X_IND | AM65_DIR_X_IND;
|
A->AddrModeSet = AM65_ABS_X_IND | AM65_DIR_X_IND;
|
||||||
Consume (IndirectLeave, IndirectExpect);
|
if (!Consume (IndirectLeave, IndirectExpect)) {
|
||||||
|
SkipUntilSep ();
|
||||||
|
}
|
||||||
} else if (CurTok.Tok == TOK_S) {
|
} else if (CurTok.Tok == TOK_S) {
|
||||||
/* (rel,s),y */
|
/* (rel,s),y */
|
||||||
NextTok ();
|
NextTok ();
|
||||||
A->AddrModeSet = AM65_STACK_REL_IND_Y;
|
A->AddrModeSet = AM65_STACK_REL_IND_Y;
|
||||||
Consume (IndirectLeave, IndirectExpect);
|
if (!Consume (IndirectLeave, IndirectExpect) ||
|
||||||
ConsumeComma ();
|
!ConsumeComma () ||
|
||||||
Consume (TOK_Y, "'Y' expected");
|
!Consume (TOK_Y, "Expected 'Y'")) {
|
||||||
|
/* In case of errors skip anything else on the line */
|
||||||
|
SkipUntilSep ();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Error ("Syntax error");
|
ErrorExpect ("Expected 'X' or 'S'");
|
||||||
|
SkipUntilSep ();
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -162,7 +168,9 @@ void GetEA (EffAddr* A)
|
|||||||
A->AddrModeSet = AM65_DIR_IND;
|
A->AddrModeSet = AM65_DIR_IND;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Consume (TOK_Y, "'Y' expected");
|
if (!Consume (TOK_Y, "Expected 'Y'")) {
|
||||||
|
SkipUntilSep ();
|
||||||
|
}
|
||||||
A->AddrModeSet = AM65_DIR_IND_Y;
|
A->AddrModeSet = AM65_DIR_IND_Y;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -190,16 +198,22 @@ void GetEA (EffAddr* A)
|
|||||||
/* [dir] or [dir],y */
|
/* [dir] or [dir],y */
|
||||||
NextTok ();
|
NextTok ();
|
||||||
A->Expr = Expression ();
|
A->Expr = Expression ();
|
||||||
Consume (TOK_RBRACK, "']' expected");
|
if (!Consume (TOK_RBRACK, "Expected ']'")) {
|
||||||
|
SkipUntilSep ();
|
||||||
|
}
|
||||||
if (CurTok.Tok == TOK_COMMA) {
|
if (CurTok.Tok == TOK_COMMA) {
|
||||||
/* [dir],y */
|
/* [dir],y */
|
||||||
NextTok ();
|
NextTok ();
|
||||||
if (GetCPU () == CPU_45GS02) {
|
if (GetCPU () == CPU_45GS02) {
|
||||||
Consume (TOK_Z, "'Z' expected");
|
if (!Consume (TOK_Z, "Expected 'Z'")) {
|
||||||
|
SkipUntilSep ();
|
||||||
|
}
|
||||||
A->AddrModeSet = AM65_32BIT_BASE_IND_Z;
|
A->AddrModeSet = AM65_32BIT_BASE_IND_Z;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Consume (TOK_Y, "'Y' expected");
|
if (!Consume (TOK_Y, "Expected 'Y'")) {
|
||||||
|
SkipUntilSep ();
|
||||||
|
}
|
||||||
A->AddrModeSet = AM65_DIR_IND_LONG_Y;
|
A->AddrModeSet = AM65_DIR_IND_LONG_Y;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ void GetSweet16EA (EffAddr* A)
|
|||||||
/* Register number */
|
/* Register number */
|
||||||
A->Reg = (unsigned) Reg;
|
A->Reg = (unsigned) Reg;
|
||||||
} else {
|
} else {
|
||||||
ErrorSkip ("Register or register number expected");
|
ErrorExpect ("Expected register or register number");
|
||||||
A->Reg = 0;
|
A->Reg = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,12 +87,13 @@ void DoEnum (void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The format is "identifier [ = value ]" */
|
/* Allow conditionals within an enum */
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
if (CheckConditionals ()) {
|
||||||
/* Maybe it's a conditional? */
|
continue;
|
||||||
if (!CheckConditionals ()) {
|
|
||||||
ErrorSkip ("Identifier expected");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The format is "identifier [ = value ]" */
|
||||||
|
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
|
||||||
continue;
|
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)
|
static void AddNotifications (const Collection* LineInfos)
|
||||||
/* Output additional notifications for an error or warning */
|
/* 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 */
|
/* Output until an upper limit of messages is reached */
|
||||||
if (Msg) {
|
if (Msg) {
|
||||||
if (Output < MAX_NOTES) {
|
if (Output < MAX_NOTES) {
|
||||||
PrintMsg (GetSourcePos (LI), "Note", "%s", Msg);
|
PNotification (GetSourcePos (LI), "%s", Msg);
|
||||||
++Output;
|
++Output;
|
||||||
} else {
|
} else {
|
||||||
++Skipped;
|
++Skipped;
|
||||||
@@ -176,13 +164,31 @@ static void AddNotifications (const Collection* LineInfos)
|
|||||||
/* Add a note if we have more stuff that we won't output */
|
/* Add a note if we have more stuff that we won't output */
|
||||||
if (Skipped > 0) {
|
if (Skipped > 0) {
|
||||||
const LineInfo* LI = CollConstAt (LineInfos, 0);
|
const LineInfo* LI = CollConstAt (LineInfos, 0);
|
||||||
PrintMsg (GetSourcePos (LI), "Note",
|
PNotification (GetSourcePos (LI), "Dropping %u additional line infos",
|
||||||
"Dropping %u additional line infos", Skipped);
|
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 */
|
/* 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)));
|
void Warning (unsigned Level, const char* Format, ...) attribute ((format (printf, 2, 3)));
|
||||||
/* Print warning message. */
|
/* Print warning message. */
|
||||||
|
|
||||||
|
|||||||
@@ -421,8 +421,7 @@ static ExprNode* FuncCapability (void)
|
|||||||
capability_t Cap;
|
capability_t Cap;
|
||||||
|
|
||||||
/* We must have an identifier */
|
/* We must have an identifier */
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
if (!Expect (TOK_IDENT, "Expected a capability name")) {
|
||||||
Error ("Arguments to .CAPABILITY must be identifiers");
|
|
||||||
/* Skip tokens until closing paren or end of line */
|
/* Skip tokens until closing paren or end of line */
|
||||||
while (CurTok.Tok != TOK_RPAREN && !TokIsSep (CurTok.Tok)) {
|
while (CurTok.Tok != TOK_RPAREN && !TokIsSep (CurTok.Tok)) {
|
||||||
NextTok ();
|
NextTok ();
|
||||||
@@ -942,8 +941,7 @@ static ExprNode* FuncStrAt (void)
|
|||||||
unsigned char C = 0;
|
unsigned char C = 0;
|
||||||
|
|
||||||
/* String constant expected */
|
/* String constant expected */
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
if (!Expect (TOK_STRCON, "Expected a string constant")) {
|
||||||
Error ("String constant expected");
|
|
||||||
NextTok ();
|
NextTok ();
|
||||||
goto ExitPoint;
|
goto ExitPoint;
|
||||||
}
|
}
|
||||||
@@ -985,9 +983,8 @@ static ExprNode* FuncStrLen (void)
|
|||||||
int Len;
|
int Len;
|
||||||
|
|
||||||
/* String constant expected */
|
/* String constant expected */
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
if (!Expect (TOK_STRCON, "Expected a string constant")) {
|
||||||
|
|
||||||
Error ("String constant expected");
|
|
||||||
/* Smart error recovery */
|
/* Smart error recovery */
|
||||||
if (CurTok.Tok != TOK_RPAREN) {
|
if (CurTok.Tok != TOK_RPAREN) {
|
||||||
NextTok ();
|
NextTok ();
|
||||||
@@ -1062,9 +1059,7 @@ static ExprNode* Function (ExprNode* (*F) (void))
|
|||||||
NextTok ();
|
NextTok ();
|
||||||
|
|
||||||
/* Expression must be enclosed in braces */
|
/* Expression must be enclosed in braces */
|
||||||
if (CurTok.Tok != TOK_LPAREN) {
|
if (!ExpectSkip (TOK_LPAREN, "Expected '('")) {
|
||||||
Error ("'(' expected");
|
|
||||||
SkipUntilSep ();
|
|
||||||
return GenLiteral0 ();
|
return GenLiteral0 ();
|
||||||
}
|
}
|
||||||
NextTok ();
|
NextTok ();
|
||||||
@@ -1296,7 +1291,7 @@ static ExprNode* Factor (void)
|
|||||||
NextTok ();
|
NextTok ();
|
||||||
} else {
|
} else {
|
||||||
N = GenLiteral0 (); /* Dummy */
|
N = GenLiteral0 (); /* Dummy */
|
||||||
Error ("Syntax error");
|
ErrorExpect ("Expected an expression");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1957,8 +1952,7 @@ ExprNode* GenNearAddrExpr (ExprNode* Expr)
|
|||||||
if (IsEasyConst (Expr, &Val)) {
|
if (IsEasyConst (Expr, &Val)) {
|
||||||
FreeExpr (Expr);
|
FreeExpr (Expr);
|
||||||
Expr = GenLiteralExpr (Val & 0xFFFF);
|
Expr = GenLiteralExpr (Val & 0xFFFF);
|
||||||
if (Val > 0xFFFF)
|
if (Val > 0xFFFF) {
|
||||||
{
|
|
||||||
Error ("Range error: constant too large for assumed near address.");
|
Error ("Range error: constant too large for assumed near address.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
117
src/ca65/macro.c
117
src/ca65/macro.c
@@ -102,10 +102,12 @@ struct Macro {
|
|||||||
unsigned TokCount; /* Number of tokens for this macro */
|
unsigned TokCount; /* Number of tokens for this macro */
|
||||||
TokNode* TokRoot; /* Root of token list */
|
TokNode* TokRoot; /* Root of token list */
|
||||||
TokNode* TokLast; /* Pointer to last token in list */
|
TokNode* TokLast; /* Pointer to last token in list */
|
||||||
|
FilePos DefPos; /* Position of definition */
|
||||||
StrBuf Name; /* Macro name, dynamically allocated */
|
StrBuf Name; /* Macro name, dynamically allocated */
|
||||||
unsigned Expansions; /* Number of active macro expansions */
|
unsigned Expansions; /* Number of active macro expansions */
|
||||||
unsigned char Style; /* Macro style */
|
unsigned char Style; /* Macro style */
|
||||||
unsigned char Incomplete; /* Macro is currently built */
|
unsigned char Incomplete; /* Macro is currently built */
|
||||||
|
unsigned char HasError; /* Macro has errors */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Hash table functions */
|
/* 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 */
|
/* Generate a new macro entry, initialize and return it */
|
||||||
{
|
{
|
||||||
/* Allocate memory */
|
/* Allocate memory */
|
||||||
@@ -247,11 +249,14 @@ static Macro* NewMacro (const StrBuf* Name, unsigned char Style)
|
|||||||
M->TokCount = 0;
|
M->TokCount = 0;
|
||||||
M->TokRoot = 0;
|
M->TokRoot = 0;
|
||||||
M->TokLast = 0;
|
M->TokLast = 0;
|
||||||
|
M->DefPos = *P;
|
||||||
SB_Init (&M->Name);
|
SB_Init (&M->Name);
|
||||||
SB_Copy (&M->Name, Name);
|
SB_Copy (&M->Name, Name);
|
||||||
|
SB_Terminate (&M->Name); /* So the name can be used with %s */
|
||||||
M->Expansions = 0;
|
M->Expansions = 0;
|
||||||
M->Style = Style;
|
M->Style = Style;
|
||||||
M->Incomplete = 1;
|
M->Incomplete = 1;
|
||||||
|
M->HasError = 0;
|
||||||
|
|
||||||
/* Insert the macro into the hash table */
|
/* Insert the macro into the hash table */
|
||||||
HT_Insert (&MacroTab, &M->Node);
|
HT_Insert (&MacroTab, &M->Node);
|
||||||
@@ -364,18 +369,27 @@ static void FreeMacExp (MacExp* E)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void MacSkipDef (unsigned Style)
|
static void MacSkipDef (unsigned Style, const FilePos* StartPos)
|
||||||
/* Skip a macro definition */
|
/* Skip a macro definition */
|
||||||
{
|
{
|
||||||
if (Style == MAC_STYLE_CLASSIC) {
|
if (Style == MAC_STYLE_CLASSIC) {
|
||||||
/* Skip tokens until we reach the final .endmacro */
|
/* Skip tokens until we reach the final .endmacro. Implement the same
|
||||||
while (CurTok.Tok != TOK_ENDMACRO && CurTok.Tok != TOK_EOF) {
|
** behavior as when parsing the macro regularily: .endmacro needs to
|
||||||
NextTok ();
|
** 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_EOF) {
|
if (CurTok.Tok == TOK_ENDMACRO && LastWasSep) {
|
||||||
SkipUntilSep ();
|
NextTok ();
|
||||||
} else {
|
break;
|
||||||
Error ("'.ENDMACRO' expected");
|
}
|
||||||
|
LastWasSep = (CurTok.Tok == TOK_SEP);
|
||||||
|
NextTok ();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Skip until end of line */
|
/* Skip until end of line */
|
||||||
@@ -388,48 +402,49 @@ static void MacSkipDef (unsigned Style)
|
|||||||
void MacDef (unsigned Style)
|
void MacDef (unsigned Style)
|
||||||
/* Parse a macro definition */
|
/* Parse a macro definition */
|
||||||
{
|
{
|
||||||
|
Macro* Existing;
|
||||||
Macro* M;
|
Macro* M;
|
||||||
TokNode* N;
|
TokNode* N;
|
||||||
FilePos Pos;
|
|
||||||
int HaveParams;
|
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.
|
/* 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
|
** If the macro name and parameters pass our checks then we will be on a
|
||||||
** new line, so set it now
|
** new line, so set it now
|
||||||
*/
|
*/
|
||||||
LastTokWasSep = 1;
|
int 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;
|
|
||||||
|
|
||||||
/* We expect a macro name here */
|
/* We expect a macro name here */
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
if (!Expect (TOK_IDENT, "Expected an identifier")) {
|
||||||
Error ("Identifier expected");
|
MacSkipDef (Style, &StartPos);
|
||||||
MacSkipDef (Style);
|
|
||||||
return;
|
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
|
/* The identifier is a name of a 6502 instruction, which is not
|
||||||
** allowed if not explicitly enabled.
|
** allowed if not explicitly enabled.
|
||||||
*/
|
*/
|
||||||
Error ("Cannot use an instruction as macro name");
|
Error ("Cannot use an instruction as macro name");
|
||||||
MacSkipDef (Style);
|
MacSkipDef (Style, &StartPos);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Did we already define that macro? */
|
/* 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 */
|
/* Macro is already defined */
|
||||||
Error ("A macro named '%m%p' is already defined", &CurTok.SVal);
|
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 */
|
/* Skip tokens until we reach the final .endmacro */
|
||||||
MacSkipDef (Style);
|
MacSkipDef (Style, &StartPos);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Define the macro */
|
/* Define the macro */
|
||||||
M = NewMacro (&CurTok.SVal, Style);
|
M = NewMacro (&CurTok.SVal, &StartPos, Style);
|
||||||
|
|
||||||
/* Switch to raw token mode and skip the macro name */
|
/* Switch to raw token mode and skip the macro name */
|
||||||
EnterRawTokenMode ();
|
EnterRawTokenMode ();
|
||||||
@@ -439,7 +454,7 @@ void MacDef (unsigned Style)
|
|||||||
** otherwise, we may have parameters without parentheses.
|
** otherwise, we may have parameters without parentheses.
|
||||||
*/
|
*/
|
||||||
if (Style == MAC_STYLE_CLASSIC) {
|
if (Style == MAC_STYLE_CLASSIC) {
|
||||||
HaveParams = 1;
|
HaveParams = (CurTok.Tok != TOK_SEP);
|
||||||
} else {
|
} else {
|
||||||
if (CurTok.Tok == TOK_LPAREN) {
|
if (CurTok.Tok == TOK_LPAREN) {
|
||||||
HaveParams = 1;
|
HaveParams = 1;
|
||||||
@@ -451,7 +466,7 @@ void MacDef (unsigned Style)
|
|||||||
|
|
||||||
/* Parse the parameter list */
|
/* Parse the parameter list */
|
||||||
if (HaveParams) {
|
if (HaveParams) {
|
||||||
while (CurTok.Tok == TOK_IDENT) {
|
while (Expect (TOK_IDENT, "Expected a parameter name")) {
|
||||||
/* Create a struct holding the identifier */
|
/* Create a struct holding the identifier */
|
||||||
IdDesc* I = NewIdDesc (&CurTok.SVal);
|
IdDesc* I = NewIdDesc (&CurTok.SVal);
|
||||||
|
|
||||||
@@ -463,7 +478,8 @@ void MacDef (unsigned Style)
|
|||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (SB_Compare (&List->Id, &CurTok.SVal) == 0) {
|
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) {
|
if (List->Next == 0) {
|
||||||
break;
|
break;
|
||||||
@@ -513,7 +529,10 @@ void MacDef (unsigned Style)
|
|||||||
}
|
}
|
||||||
/* May not have end of file in a macro definition */
|
/* May not have end of file in a macro definition */
|
||||||
if (CurTok.Tok == TOK_EOF) {
|
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;
|
goto Done;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -533,8 +552,9 @@ void MacDef (unsigned Style)
|
|||||||
|
|
||||||
/* Need an identifer */
|
/* Need an identifer */
|
||||||
if (CurTok.Tok != TOK_IDENT && CurTok.Tok != TOK_LOCAL_IDENT) {
|
if (CurTok.Tok != TOK_IDENT && CurTok.Tok != TOK_LOCAL_IDENT) {
|
||||||
Error ("Identifier expected");
|
ErrorExpect ("Expected an identifier");
|
||||||
SkipUntilSep ();
|
SkipUntilSep ();
|
||||||
|
M->HasError = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,7 +573,10 @@ void MacDef (unsigned Style)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* We need end of line after the locals */
|
/* We need end of line after the locals */
|
||||||
ConsumeSep ();
|
if (!ExpectSep ()) {
|
||||||
|
M->HasError = 1;
|
||||||
|
}
|
||||||
|
NextTok ();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,7 +649,8 @@ void MacUndef (const StrBuf* Name, unsigned char Style)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (M->Expansions > 0) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -813,7 +837,11 @@ static void StartExpClassic (MacExp* E)
|
|||||||
|
|
||||||
/* Check for maximum parameter count */
|
/* Check for maximum parameter count */
|
||||||
if (E->ParamCount >= E->M->ParamCount) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -827,7 +855,7 @@ static void StartExpClassic (MacExp* E)
|
|||||||
|
|
||||||
/* Check for end of file */
|
/* Check for end of file */
|
||||||
if (CurTok.Tok == TOK_EOF) {
|
if (CurTok.Tok == TOK_EOF) {
|
||||||
Error ("Unexpected end of file");
|
Error ("Unexpected end of file in macro parameter list");
|
||||||
FreeMacExp (E);
|
FreeMacExp (E);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -938,10 +966,8 @@ static void StartExpDefine (MacExp* E)
|
|||||||
|
|
||||||
/* Check for a comma */
|
/* Check for a comma */
|
||||||
if (Count > 0) {
|
if (Count > 0) {
|
||||||
if (CurTok.Tok == TOK_COMMA) {
|
if (Expect (TOK_COMMA, "Expected ','")) {
|
||||||
NextTok ();
|
NextTok ();
|
||||||
} else {
|
|
||||||
Error ("',' expected");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -972,9 +998,21 @@ void MacExpandStart (Macro* M)
|
|||||||
Pos = CurTok.Pos;
|
Pos = CurTok.Pos;
|
||||||
NextTok ();
|
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 */
|
/* We cannot expand an incomplete macro */
|
||||||
if (M->Incomplete) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -982,7 +1020,8 @@ void MacExpandStart (Macro* M)
|
|||||||
** to force an endless loop and assembler crash.
|
** to force an endless loop and assembler crash.
|
||||||
*/
|
*/
|
||||||
if (MacExpansions >= MAX_MACEXPANSIONS) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -727,7 +727,7 @@ static void DoPCAssign (void)
|
|||||||
{
|
{
|
||||||
long PC = ConstExpression ();
|
long PC = ConstExpression ();
|
||||||
if (PC < 0 || PC > 0xFFFFFF) {
|
if (PC < 0 || PC > 0xFFFFFF) {
|
||||||
Error ("Range error");
|
Error ("Program counter value is out of valid range");
|
||||||
} else {
|
} else {
|
||||||
EnterAbsoluteMode (PC);
|
EnterAbsoluteMode (PC);
|
||||||
}
|
}
|
||||||
@@ -823,8 +823,7 @@ static void OneLine (void)
|
|||||||
SymDef (Sym, Expression (), ADDR_SIZE_DEFAULT, Flags);
|
SymDef (Sym, Expression (), ADDR_SIZE_DEFAULT, Flags);
|
||||||
|
|
||||||
/* Don't allow anything after a symbol definition */
|
/* Don't allow anything after a symbol definition */
|
||||||
ConsumeSep ();
|
goto Done;
|
||||||
return;
|
|
||||||
|
|
||||||
} else if (CurTok.Tok == TOK_SET) {
|
} else if (CurTok.Tok == TOK_SET) {
|
||||||
|
|
||||||
@@ -842,8 +841,7 @@ static void OneLine (void)
|
|||||||
SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_VAR);
|
SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_VAR);
|
||||||
|
|
||||||
/* Don't allow anything after a symbol definition */
|
/* Don't allow anything after a symbol definition */
|
||||||
ConsumeSep ();
|
goto Done;
|
||||||
return;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@@ -853,26 +851,24 @@ static void OneLine (void)
|
|||||||
Seg = ActiveSeg;
|
Seg = ActiveSeg;
|
||||||
PC = GetPC ();
|
PC = GetPC ();
|
||||||
|
|
||||||
/* Define the label */
|
|
||||||
SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL);
|
|
||||||
|
|
||||||
/* Skip the colon. If NoColonLabels is enabled, allow labels
|
/* Skip the colon. If NoColonLabels is enabled, allow labels
|
||||||
** without a colon if there is no whitespace before the
|
** without a colon if there is no whitespace before the
|
||||||
** identifier.
|
** identifier.
|
||||||
*/
|
*/
|
||||||
if (CurTok.Tok != TOK_COLON) {
|
if (CurTok.Tok != TOK_COLON) {
|
||||||
if (HadWS || !NoColonLabels) {
|
if (HadWS || !NoColonLabels) {
|
||||||
Error ("':' expected");
|
ErrorExpect ("Expected ':' after identifier to form a label");
|
||||||
/* Try some smart error recovery */
|
SkipUntilSep ();
|
||||||
if (CurTok.Tok == TOK_NAMESPACE) {
|
goto Done;
|
||||||
NextTok ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Skip the colon */
|
/* Skip the colon */
|
||||||
NextTok ();
|
NextTok ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Define the label */
|
||||||
|
SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL);
|
||||||
|
|
||||||
/* If we come here, a new identifier may be waiting, which may
|
/* If we come here, a new identifier may be waiting, which may
|
||||||
** be a macro or instruction.
|
** be a macro or instruction.
|
||||||
*/
|
*/
|
||||||
@@ -906,16 +902,22 @@ static void OneLine (void)
|
|||||||
HandleInstruction (Instr);
|
HandleInstruction (Instr);
|
||||||
} else if (PCAssignment && (CurTok.Tok == TOK_STAR || CurTok.Tok == TOK_PC)) {
|
} else if (PCAssignment && (CurTok.Tok == TOK_STAR || CurTok.Tok == TOK_PC)) {
|
||||||
NextTok ();
|
NextTok ();
|
||||||
if (CurTok.Tok != TOK_EQ) {
|
if (!ExpectSkip (TOK_EQ, "Expected '='")) {
|
||||||
Error ("'=' expected");
|
goto Done;
|
||||||
SkipUntilSep ();
|
}
|
||||||
} else {
|
|
||||||
/* Skip the equal sign */
|
/* Skip the equal sign */
|
||||||
NextTok ();
|
NextTok ();
|
||||||
/* Enter absolute mode */
|
/* Enter absolute mode */
|
||||||
DoPCAssign ();
|
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
|
/* 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
|
** a symbol assignment, but in this case Done is false, so we don't
|
||||||
@@ -938,6 +940,7 @@ static void OneLine (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Done:
|
||||||
/* Line separator must come here */
|
/* Line separator must come here */
|
||||||
ConsumeSep ();
|
ConsumeSep ();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -725,52 +725,118 @@ void NextTok (void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Consume (token_t Expected, const char* ErrMsg)
|
void ErrorExpect (const char* Msg)
|
||||||
/* Consume Expected, print an error if we don't find it */
|
/* 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) {
|
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 ();
|
NextTok ();
|
||||||
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
Error ("%s", ErrMsg);
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ConsumeSep (void)
|
int ConsumeSep (void)
|
||||||
/* Consume a separator token */
|
/* Consume a separator token. Return true if the token was found and false
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
/* We expect a separator token */
|
/* We expect a separator token */
|
||||||
ExpectSep ();
|
int Found = ExpectSep ();
|
||||||
|
|
||||||
/* If we are at end of line, skip it */
|
/* If we are at end of line, skip it */
|
||||||
if (CurTok.Tok == TOK_SEP) {
|
if (CurTok.Tok == TOK_SEP) {
|
||||||
NextTok ();
|
NextTok ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ConsumeLParen (void)
|
int ConsumeLParen (void)
|
||||||
/* Consume a left paren */
|
/* 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)
|
int ConsumeRParen (void)
|
||||||
/* Consume a right paren */
|
/* 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)
|
int ConsumeComma (void)
|
||||||
/* Consume a comma */
|
/* 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)
|
int ExpectSep (void)
|
||||||
/* Check if we've reached a line separator, and output an error if not. Do
|
/* Check if we've reached a line separator. If so, return true. If not, output
|
||||||
** not skip the line separator.
|
** an error and skip all tokens until the line separator is reached. Then
|
||||||
|
** return false.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
if (!TokIsSep (CurTok.Tok)) {
|
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);
|
void NextTok (void);
|
||||||
/* Get next token and handle token level functions */
|
/* Get next token and handle token level functions */
|
||||||
|
|
||||||
void Consume (token_t Expected, const char* ErrMsg);
|
void ErrorExpect (const char* Msg);
|
||||||
/* Consume Token, print an error if we don't find it */
|
/* 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);
|
int Expect (token_t Expected, const char* Msg);
|
||||||
/* Consume a separator token */
|
/* 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);
|
int ExpectSkip (token_t Expected, const char* Msg);
|
||||||
/* Consume a left paren */
|
/* 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);
|
int Consume (token_t Expected, const char* ErrMsg);
|
||||||
/* Consume a right paren */
|
/* Consume Token, print an error if we don't find it. Return true if the token
|
||||||
|
** was found and false otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
void ConsumeComma (void);
|
int ConsumeSep (void);
|
||||||
/* Consume a comma */
|
/* 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);
|
void SkipUntilSep (void);
|
||||||
/* Skip tokens until we reach a line separator or end of file */
|
/* Skip tokens until we reach a line separator or end of file */
|
||||||
|
|
||||||
void ExpectSep (void);
|
int ExpectSep (void);
|
||||||
/* Check if we've reached a line separator, and output an error if not. Do
|
/* Check if we've reached a line separator. If so, return true. If not, output
|
||||||
** not skip the line separator.
|
** an error and skip all tokens until the line separator is reached. Then
|
||||||
|
** return false.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void EnterRawTokenMode (void);
|
void EnterRawTokenMode (void);
|
||||||
|
|||||||
@@ -167,13 +167,17 @@ static void SetBoolOption (unsigned char* Flag)
|
|||||||
switch (GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]))) {
|
switch (GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]))) {
|
||||||
case 0: *Flag = 0; NextTok (); break;
|
case 0: *Flag = 0; NextTok (); break;
|
||||||
case 1: *Flag = 1; 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)) {
|
} else if (TokIsSep (CurTok.Tok)) {
|
||||||
/* Without anything assume switch on */
|
/* Without anything assume switch on */
|
||||||
*Flag = 1;
|
*Flag = 1;
|
||||||
} else {
|
} 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) {
|
while (1) {
|
||||||
|
|
||||||
/* We need an identifier here */
|
/* We need an identifier here */
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
|
||||||
ErrorSkip ("Identifier expected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,7 +286,7 @@ static void ConDes (const StrBuf* Name, unsigned Type)
|
|||||||
Prio = ConstExpression ();
|
Prio = ConstExpression ();
|
||||||
if (Prio < CD_PRIO_MIN || Prio > CD_PRIO_MAX) {
|
if (Prio < CD_PRIO_MIN || Prio > CD_PRIO_MAX) {
|
||||||
/* Value out of range */
|
/* Value out of range */
|
||||||
Error ("Range error");
|
Error ("Given priority is out of range");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -400,7 +403,7 @@ static void DoAlign (void)
|
|||||||
/* Read the alignment value */
|
/* Read the alignment value */
|
||||||
Alignment = ConstExpression ();
|
Alignment = ConstExpression ();
|
||||||
if (Alignment <= 0 || (unsigned long) Alignment > MAX_ALIGNMENT) {
|
if (Alignment <= 0 || (unsigned long) Alignment > MAX_ALIGNMENT) {
|
||||||
ErrorSkip ("Range error");
|
ErrorSkip ("Alignment is out of range");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,7 +413,7 @@ static void DoAlign (void)
|
|||||||
FillVal = ConstExpression ();
|
FillVal = ConstExpression ();
|
||||||
/* We need a byte value here */
|
/* We need a byte value here */
|
||||||
if (!IsByteRange (FillVal)) {
|
if (!IsByteRange (FillVal)) {
|
||||||
ErrorSkip ("Range error");
|
ErrorSkip ("Fill value is not in byte range");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -428,8 +431,7 @@ static void DoASCIIZ (void)
|
|||||||
{
|
{
|
||||||
while (1) {
|
while (1) {
|
||||||
/* Must have a string constant */
|
/* Must have a string constant */
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
|
||||||
ErrorSkip ("String constant expected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,11 +465,10 @@ static void DoAssert (void)
|
|||||||
|
|
||||||
/* First we have the expression that has to evaluated */
|
/* First we have the expression that has to evaluated */
|
||||||
ExprNode* Expr = Expression ();
|
ExprNode* Expr = Expression ();
|
||||||
ConsumeComma ();
|
|
||||||
|
|
||||||
/* Action follows */
|
/* Followed by comma and action */
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
if (!ConsumeComma () || !Expect (TOK_IDENT, "Expected an identifier")) {
|
||||||
ErrorSkip ("Identifier expected");
|
SkipUntilSep ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (GetSubKey (ActionTab, sizeof (ActionTab) / sizeof (ActionTab[0]))) {
|
switch (GetSubKey (ActionTab, sizeof (ActionTab) / sizeof (ActionTab[0]))) {
|
||||||
@@ -496,9 +497,8 @@ static void DoAssert (void)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
Error ("Illegal assert action specifier");
|
Error ("Illegal assert action specifier");
|
||||||
/* Use lderror - there won't be an .o file anyway */
|
SkipUntilSep ();
|
||||||
Action = ASSERT_ACT_LDERROR;
|
return;
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
NextTok ();
|
NextTok ();
|
||||||
@@ -512,8 +512,7 @@ static void DoAssert (void)
|
|||||||
NextTok ();
|
NextTok ();
|
||||||
|
|
||||||
/* Read the message */
|
/* Read the message */
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
|
||||||
ErrorSkip ("String constant expected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -642,20 +641,23 @@ static void DoCharMap (void)
|
|||||||
|
|
||||||
/* Read the index as numerical value */
|
/* Read the index as numerical value */
|
||||||
Index = ConstExpression ();
|
Index = ConstExpression ();
|
||||||
if (Index < 0 || Index > 255) {
|
if (IsByteRange (Index)) {
|
||||||
/* Value out of range */
|
/* Value out of range */
|
||||||
ErrorSkip ("Index range error");
|
ErrorSkip ("Index must be in byte range");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Comma follows */
|
/* Comma follows */
|
||||||
ConsumeComma ();
|
if (!ConsumeComma ()) {
|
||||||
|
SkipUntilSep ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read the character code */
|
/* Read the character code */
|
||||||
Code = ConstExpression ();
|
Code = ConstExpression ();
|
||||||
if (Code < 0 || Code > 255) {
|
if (!IsByteRange (Code)) {
|
||||||
/* Value out of range */
|
/* Value out of range */
|
||||||
ErrorSkip ("Code range error");
|
ErrorSkip ("Replacement character code must be in byte range");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -685,15 +687,17 @@ static void DoConDes (void)
|
|||||||
long Type;
|
long Type;
|
||||||
|
|
||||||
/* Symbol name follows */
|
/* Symbol name follows */
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
|
||||||
ErrorSkip ("Identifier expected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SB_Copy (&Name, &CurTok.SVal);
|
SB_Copy (&Name, &CurTok.SVal);
|
||||||
NextTok ();
|
NextTok ();
|
||||||
|
|
||||||
/* Type follows. May be encoded as identifier or numerical */
|
/* Type follows. May be encoded as identifier or numerical */
|
||||||
ConsumeComma ();
|
if (!ConsumeComma ()) {
|
||||||
|
SkipUntilSep ();
|
||||||
|
goto ExitPoint;
|
||||||
|
}
|
||||||
if (CurTok.Tok == TOK_IDENT) {
|
if (CurTok.Tok == TOK_IDENT) {
|
||||||
|
|
||||||
/* Map the following keyword to a number, then skip it */
|
/* 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 */
|
/* Check if we got a valid keyword */
|
||||||
if (Type < 0) {
|
if (Type < 0) {
|
||||||
ErrorSkip ("Syntax error");
|
ErrorExpect ("Expected CONSTRUCTOR, DESTRUCTOR or INTERRUPTOR");
|
||||||
|
SkipUntilSep ();
|
||||||
goto ExitPoint;
|
goto ExitPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -712,7 +717,7 @@ static void DoConDes (void)
|
|||||||
Type = ConstExpression ();
|
Type = ConstExpression ();
|
||||||
if (Type < CD_TYPE_MIN || Type > CD_TYPE_MAX) {
|
if (Type < CD_TYPE_MIN || Type > CD_TYPE_MAX) {
|
||||||
/* Value out of range */
|
/* Value out of range */
|
||||||
ErrorSkip ("Range error");
|
ErrorSkip ("Numeric condes type is out of range");
|
||||||
goto ExitPoint;
|
goto ExitPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -734,8 +739,7 @@ static void DoConstructor (void)
|
|||||||
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
||||||
|
|
||||||
/* Symbol name follows */
|
/* Symbol name follows */
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
|
||||||
ErrorSkip ("Identifier expected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SB_Copy (&Name, &CurTok.SVal);
|
SB_Copy (&Name, &CurTok.SVal);
|
||||||
@@ -771,8 +775,7 @@ static void DoDbg (void)
|
|||||||
|
|
||||||
|
|
||||||
/* We expect a subkey */
|
/* We expect a subkey */
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
|
||||||
ErrorSkip ("Identifier expected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -788,7 +791,10 @@ static void DoDbg (void)
|
|||||||
case 1: DbgInfoFunc (); break;
|
case 1: DbgInfoFunc (); break;
|
||||||
case 2: DbgInfoLine (); break;
|
case 2: DbgInfoLine (); break;
|
||||||
case 3: DbgInfoSym (); 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 */
|
/* Delete a classic macro */
|
||||||
{
|
{
|
||||||
/* We expect an identifier */
|
/* We expect an identifier */
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
if (ExpectSkip (TOK_IDENT, "Expected an identifier")) {
|
||||||
ErrorSkip ("Identifier expected");
|
|
||||||
} else {
|
|
||||||
MacUndef (&CurTok.SVal, MAC_STYLE_CLASSIC);
|
MacUndef (&CurTok.SVal, MAC_STYLE_CLASSIC);
|
||||||
NextTok ();
|
NextTok ();
|
||||||
}
|
}
|
||||||
@@ -869,8 +873,7 @@ static void DoDestructor (void)
|
|||||||
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
||||||
|
|
||||||
/* Symbol name follows */
|
/* Symbol name follows */
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
|
||||||
ErrorSkip ("Identifier expected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SB_Copy (&Name, &CurTok.SVal);
|
SB_Copy (&Name, &CurTok.SVal);
|
||||||
@@ -938,9 +941,7 @@ static void DoEndScope (void)
|
|||||||
static void DoError (void)
|
static void DoError (void)
|
||||||
/* User error */
|
/* User error */
|
||||||
{
|
{
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
|
||||||
ErrorSkip ("String constant expected");
|
|
||||||
} else {
|
|
||||||
Error ("User error: %m%p", &CurTok.SVal);
|
Error ("User error: %m%p", &CurTok.SVal);
|
||||||
SkipUntilSep ();
|
SkipUntilSep ();
|
||||||
}
|
}
|
||||||
@@ -1010,9 +1011,7 @@ static void DoFarAddr (void)
|
|||||||
static void DoFatal (void)
|
static void DoFatal (void)
|
||||||
/* Fatal user error */
|
/* Fatal user error */
|
||||||
{
|
{
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
|
||||||
ErrorSkip ("String constant expected");
|
|
||||||
} else {
|
|
||||||
Fatal ("User error: %m%p", &CurTok.SVal);
|
Fatal ("User error: %m%p", &CurTok.SVal);
|
||||||
SkipUntilSep ();
|
SkipUntilSep ();
|
||||||
}
|
}
|
||||||
@@ -1030,8 +1029,7 @@ static void DoFeature (void)
|
|||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
/* We expect an identifier */
|
/* We expect an identifier */
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
|
||||||
ErrorSkip ("Identifier expected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1045,7 +1043,8 @@ static void DoFeature (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Feature == FEAT_ADDRSIZE) {
|
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 ();
|
NextTok ();
|
||||||
@@ -1087,19 +1086,17 @@ static void DoFileOpt (void)
|
|||||||
OptNum = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
|
OptNum = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
|
||||||
if (OptNum < 0) {
|
if (OptNum < 0) {
|
||||||
/* Not found */
|
/* Not found */
|
||||||
ErrorSkip ("File option keyword expected");
|
ErrorExpect ("Expected a file option keyword");
|
||||||
|
SkipUntilSep ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip the keyword */
|
/* Skip the keyword */
|
||||||
NextTok ();
|
NextTok ();
|
||||||
|
|
||||||
/* Must be followed by a comma */
|
/* Must be followed by a comma and a string option */
|
||||||
ConsumeComma ();
|
if (!ConsumeComma () || !Expect (TOK_STRCON, "Expected a string constant")) {
|
||||||
|
SkipUntilSep ();
|
||||||
/* We accept only string options for now */
|
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
|
||||||
ErrorSkip ("String constant expected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1134,16 +1131,13 @@ static void DoFileOpt (void)
|
|||||||
/* Option given as number */
|
/* Option given as number */
|
||||||
OptNum = ConstExpression ();
|
OptNum = ConstExpression ();
|
||||||
if (!IsByteRange (OptNum)) {
|
if (!IsByteRange (OptNum)) {
|
||||||
ErrorSkip ("Range error");
|
ErrorSkip ("Option number must be in byte range");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Must be followed by a comma */
|
/* Must be followed by a comma plus a string constant */
|
||||||
ConsumeComma ();
|
if (!ConsumeComma () || !Expect (TOK_STRCON, "Expected a string constant")) {
|
||||||
|
SkipUntilSep ();
|
||||||
/* We accept only string options for now */
|
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
|
||||||
ErrorSkip ("String constant expected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1248,8 +1242,7 @@ static void DoIncBin (void)
|
|||||||
FILE* F;
|
FILE* F;
|
||||||
|
|
||||||
/* Name must follow */
|
/* Name must follow */
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
|
||||||
ErrorSkip ("String constant expected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SB_Copy (&Name, &CurTok.SVal);
|
SB_Copy (&Name, &CurTok.SVal);
|
||||||
@@ -1314,13 +1307,16 @@ static void DoIncBin (void)
|
|||||||
Count = Size - Start;
|
Count = Size - Start;
|
||||||
if (Count < 0) {
|
if (Count < 0) {
|
||||||
/* Nothing to read - flag this as a range error */
|
/* Nothing to read - flag this as a range error */
|
||||||
ErrorSkip ("Range error");
|
ErrorSkip ("Start offset is larger than file size");
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Count was given, check if it is valid */
|
/* Count was given, check if it is valid */
|
||||||
if (Start + Count > Size) {
|
if (Start > Size) {
|
||||||
ErrorSkip ("Range error");
|
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;
|
goto Done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1367,9 +1363,7 @@ static void DoInclude (void)
|
|||||||
/* Include another file */
|
/* Include another file */
|
||||||
{
|
{
|
||||||
/* Name must follow */
|
/* Name must follow */
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
|
||||||
ErrorSkip ("String constant expected");
|
|
||||||
} else {
|
|
||||||
SB_Terminate (&CurTok.SVal);
|
SB_Terminate (&CurTok.SVal);
|
||||||
if (NewInputFile (SB_GetConstBuf (&CurTok.SVal)) == 0) {
|
if (NewInputFile (SB_GetConstBuf (&CurTok.SVal)) == 0) {
|
||||||
/* Error opening the file, skip remainder of line */
|
/* Error opening the file, skip remainder of line */
|
||||||
@@ -1386,8 +1380,7 @@ static void DoInterruptor (void)
|
|||||||
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
||||||
|
|
||||||
/* Symbol name follows */
|
/* Symbol name follows */
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
|
||||||
ErrorSkip ("Identifier expected");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SB_Copy (&Name, &CurTok.SVal);
|
SB_Copy (&Name, &CurTok.SVal);
|
||||||
@@ -1474,9 +1467,7 @@ static void DoListBytes (void)
|
|||||||
static void DoLocalChar (void)
|
static void DoLocalChar (void)
|
||||||
/* Define the character that starts local labels */
|
/* Define the character that starts local labels */
|
||||||
{
|
{
|
||||||
if (CurTok.Tok != TOK_CHARCON) {
|
if (ExpectSkip (TOK_CHARCON, "Expected a character constant")) {
|
||||||
ErrorSkip ("Character constant expected");
|
|
||||||
} else {
|
|
||||||
if (CurTok.IVal != '@' && CurTok.IVal != '?') {
|
if (CurTok.IVal != '@' && CurTok.IVal != '?') {
|
||||||
Error ("Invalid start character for locals");
|
Error ("Invalid start character for locals");
|
||||||
} else {
|
} else {
|
||||||
@@ -1492,9 +1483,9 @@ static void DoMacPack (void)
|
|||||||
/* Insert a macro package */
|
/* Insert a macro package */
|
||||||
{
|
{
|
||||||
/* We expect an identifier */
|
/* We expect an identifier */
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
|
||||||
ErrorSkip ("Identifier expected");
|
return;
|
||||||
} else {
|
}
|
||||||
SB_AppendStr (&CurTok.SVal, ".mac");
|
SB_AppendStr (&CurTok.SVal, ".mac");
|
||||||
SB_Terminate (&CurTok.SVal);
|
SB_Terminate (&CurTok.SVal);
|
||||||
if (NewInputFile (SB_GetConstBuf (&CurTok.SVal)) == 0) {
|
if (NewInputFile (SB_GetConstBuf (&CurTok.SVal)) == 0) {
|
||||||
@@ -1502,7 +1493,6 @@ static void DoMacPack (void)
|
|||||||
SkipUntilSep ();
|
SkipUntilSep ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1538,11 +1528,9 @@ static void DoOrg (void)
|
|||||||
static void DoOut (void)
|
static void DoOut (void)
|
||||||
/* Output a string */
|
/* Output a string */
|
||||||
{
|
{
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
|
||||||
ErrorSkip ("String constant expected");
|
|
||||||
} else {
|
|
||||||
/* Output the string and be sure to flush the output to keep it in
|
/* 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",
|
printf ("%.*s\n",
|
||||||
(int) SB_GetLen (&CurTok.SVal),
|
(int) SB_GetLen (&CurTok.SVal),
|
||||||
@@ -1835,7 +1823,7 @@ static void DoRes (void)
|
|||||||
|
|
||||||
Count = ConstExpression ();
|
Count = ConstExpression ();
|
||||||
if (Count > 0xFFFF || Count < 0) {
|
if (Count > 0xFFFF || Count < 0) {
|
||||||
ErrorSkip ("Range error");
|
ErrorSkip ("Invalid number of bytes specified");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (CurTok.Tok == TOK_COMMA) {
|
if (CurTok.Tok == TOK_COMMA) {
|
||||||
@@ -1843,7 +1831,7 @@ static void DoRes (void)
|
|||||||
Val = ConstExpression ();
|
Val = ConstExpression ();
|
||||||
/* We need a byte value here */
|
/* We need a byte value here */
|
||||||
if (!IsByteRange (Val)) {
|
if (!IsByteRange (Val)) {
|
||||||
ErrorSkip ("Range error");
|
ErrorSkip ("Fill value is not in byte range");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1903,12 +1891,10 @@ static void DoScope (void)
|
|||||||
static void DoSegment (void)
|
static void DoSegment (void)
|
||||||
/* Switch to another segment */
|
/* Switch to another segment */
|
||||||
{
|
{
|
||||||
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
|
||||||
SegDef Def;
|
|
||||||
|
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
SegDef Def;
|
||||||
ErrorSkip ("String constant expected");
|
StrBuf Name = AUTO_STRBUF_INITIALIZER;
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Save the name of the segment and skip it */
|
/* Save the name of the segment and skip it */
|
||||||
SB_Copy (&Name, &CurTok.SVal);
|
SB_Copy (&Name, &CurTok.SVal);
|
||||||
@@ -1923,11 +1909,11 @@ static void DoSegment (void)
|
|||||||
|
|
||||||
/* Set the segment */
|
/* Set the segment */
|
||||||
UseSeg (&Def);
|
UseSeg (&Def);
|
||||||
}
|
|
||||||
|
|
||||||
/* Free memory for Name */
|
/* Free memory for Name */
|
||||||
SB_Done (&Name);
|
SB_Done (&Name);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1935,9 +1921,7 @@ static void DoSetCPU (void)
|
|||||||
/* Switch the CPU instruction set */
|
/* Switch the CPU instruction set */
|
||||||
{
|
{
|
||||||
/* We expect an identifier */
|
/* We expect an identifier */
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
|
||||||
ErrorSkip ("String constant expected");
|
|
||||||
} else {
|
|
||||||
cpu_t CPU;
|
cpu_t CPU;
|
||||||
|
|
||||||
/* Try to find the CPU */
|
/* Try to find the CPU */
|
||||||
@@ -1948,7 +1932,7 @@ static void DoSetCPU (void)
|
|||||||
SetCPU (CPU);
|
SetCPU (CPU);
|
||||||
|
|
||||||
/* Skip the identifier. If the CPU switch was successful, the scanner
|
/* 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 ();
|
NextTok ();
|
||||||
}
|
}
|
||||||
@@ -2024,9 +2008,7 @@ static void DoUnDef (void)
|
|||||||
EnableDefineStyleMacros ();
|
EnableDefineStyleMacros ();
|
||||||
|
|
||||||
/* We expect an identifier */
|
/* We expect an identifier */
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
if (ExpectSkip (TOK_IDENT, "Expected an identifier")) {
|
||||||
ErrorSkip ("Identifier expected");
|
|
||||||
} else {
|
|
||||||
MacUndef (&CurTok.SVal, MAC_STYLE_DEFINE);
|
MacUndef (&CurTok.SVal, MAC_STYLE_DEFINE);
|
||||||
NextTok ();
|
NextTok ();
|
||||||
}
|
}
|
||||||
@@ -2046,9 +2028,7 @@ static void DoUnexpected (void)
|
|||||||
static void DoWarning (void)
|
static void DoWarning (void)
|
||||||
/* User warning */
|
/* User warning */
|
||||||
{
|
{
|
||||||
if (CurTok.Tok != TOK_STRCON) {
|
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
|
||||||
ErrorSkip ("String constant expected");
|
|
||||||
} else {
|
|
||||||
Warning (0, "User warning: %m%p", &CurTok.SVal);
|
Warning (0, "User warning: %m%p", &CurTok.SVal);
|
||||||
SkipUntilSep ();
|
SkipUntilSep ();
|
||||||
}
|
}
|
||||||
@@ -2255,7 +2235,7 @@ static CtrlDesc CtrlCmdTab [] = {
|
|||||||
{ ccNone, DoUnexpected }, /* .REF, .REFERENCED */
|
{ ccNone, DoUnexpected }, /* .REF, .REFERENCED */
|
||||||
{ ccNone, DoReferTo }, /* .REFTO, .REFERTO */
|
{ ccNone, DoReferTo }, /* .REFTO, .REFERTO */
|
||||||
{ ccNone, DoReloc }, /* .RELOC */
|
{ ccNone, DoReloc }, /* .RELOC */
|
||||||
{ ccNone, DoRepeat }, /* .REPEAT */
|
{ ccKeepToken, DoRepeat }, /* .REPEAT */
|
||||||
{ ccNone, DoRes }, /* .RES */
|
{ ccNone, DoRes }, /* .RES */
|
||||||
{ ccNone, DoInvalid }, /* .RIGHT */
|
{ ccNone, DoInvalid }, /* .RIGHT */
|
||||||
{ ccNone, DoROData }, /* .RODATA */
|
{ 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
|
/* Collect all tokens inside the .REPEAT body in a token list and return
|
||||||
** this list. In case of errors, NULL is returned.
|
** this list. In case of errors, NULL is returned.
|
||||||
*/
|
*/
|
||||||
@@ -67,7 +67,8 @@ static TokList* CollectRepeatTokens (void)
|
|||||||
|
|
||||||
/* Check for end of input */
|
/* Check for end of input */
|
||||||
if (CurTok.Tok == TOK_EOF) {
|
if (CurTok.Tok == TOK_EOF) {
|
||||||
Error ("Unexpected end of file");
|
ErrorExpect ("Expected '.ENDREPEAT'");
|
||||||
|
PNotification (StartPos, "For this '.REPEAT' command");
|
||||||
FreeTokList (List);
|
FreeTokList (List);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -117,10 +118,14 @@ void ParseRepeat (void)
|
|||||||
char* Name;
|
char* Name;
|
||||||
TokList* List;
|
TokList* List;
|
||||||
|
|
||||||
|
/* Remember the position of the .REPEAT token, then skip it */
|
||||||
|
FilePos StartPos = CurTok.Pos;
|
||||||
|
NextTok ();
|
||||||
|
|
||||||
/* Repeat count follows */
|
/* Repeat count follows */
|
||||||
long RepCount = ConstExpression ();
|
long RepCount = ConstExpression ();
|
||||||
if (RepCount < 0) {
|
if (RepCount < 0) {
|
||||||
Error ("Range error");
|
Error ("Repeat count must be positive or zero");
|
||||||
RepCount = 0;
|
RepCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,9 +137,7 @@ void ParseRepeat (void)
|
|||||||
NextTok ();
|
NextTok ();
|
||||||
|
|
||||||
/* Check for an identifier */
|
/* Check for an identifier */
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
if (ExpectSkip (TOK_IDENT, "Expected an identifier")) {
|
||||||
ErrorSkip ("Identifier expected");
|
|
||||||
} else {
|
|
||||||
/* Remember the name and skip it */
|
/* Remember the name and skip it */
|
||||||
SB_Terminate (&CurTok.SVal);
|
SB_Terminate (&CurTok.SVal);
|
||||||
Name = xstrdup (SB_GetConstBuf (&CurTok.SVal));
|
Name = xstrdup (SB_GetConstBuf (&CurTok.SVal));
|
||||||
@@ -147,7 +150,7 @@ void ParseRepeat (void)
|
|||||||
ConsumeSep ();
|
ConsumeSep ();
|
||||||
|
|
||||||
/* Read the token list */
|
/* Read the token list */
|
||||||
List = CollectRepeatTokens ();
|
List = CollectRepeatTokens (&StartPos);
|
||||||
|
|
||||||
/* If we had an error, bail out */
|
/* If we had an error, bail out */
|
||||||
if (List == 0) {
|
if (List == 0) {
|
||||||
|
|||||||
@@ -105,14 +105,21 @@ static long DoStructInternal (long Offs, unsigned Type)
|
|||||||
** union, the struct may be anonymous; in which case, no new lexical level
|
** union, the struct may be anonymous; in which case, no new lexical level
|
||||||
** is started.
|
** is started.
|
||||||
*/
|
*/
|
||||||
int Anon = (CurTok.Tok != TOK_IDENT);
|
int Anon = (CurTok.Tok == TOK_SEP);
|
||||||
|
|
||||||
if (!Anon) {
|
if (!Anon) {
|
||||||
|
/* 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 */
|
/* Enter a new scope, then skip the name */
|
||||||
SymEnterLevel (&CurTok.SVal, SCOPE_STRUCT, ADDR_SIZE_ABS, 0);
|
SymEnterLevel (&CurTok.SVal, SCOPE_STRUCT, ADDR_SIZE_ABS, 0);
|
||||||
NextTok ();
|
NextTok ();
|
||||||
/* Start at zero offset in the new scope */
|
/* Start at zero offset in the new scope */
|
||||||
Offs = 0;
|
Offs = 0;
|
||||||
|
} else {
|
||||||
|
/* Skip the junk on the line before proceeding */
|
||||||
|
SkipUntilSep ();
|
||||||
|
Anon = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test for end of line */
|
/* Test for end of line */
|
||||||
@@ -183,7 +190,7 @@ static long DoStructInternal (long Offs, unsigned Type)
|
|||||||
case TOK_RES:
|
case TOK_RES:
|
||||||
NextTok ();
|
NextTok ();
|
||||||
if (CurTok.Tok == TOK_SEP) {
|
if (CurTok.Tok == TOK_SEP) {
|
||||||
ErrorSkip ("Size is missing");
|
ErrorExpect ("Expected a byte count");
|
||||||
} else {
|
} else {
|
||||||
MemberSize = Member (1);
|
MemberSize = Member (1);
|
||||||
}
|
}
|
||||||
@@ -192,7 +199,7 @@ static long DoStructInternal (long Offs, unsigned Type)
|
|||||||
case TOK_ORG:
|
case TOK_ORG:
|
||||||
NextTok ();
|
NextTok ();
|
||||||
if (CurTok.Tok == TOK_SEP) {
|
if (CurTok.Tok == TOK_SEP) {
|
||||||
ErrorSkip ("Address is missing");
|
ErrorExpect ("Expected an address");
|
||||||
} else {
|
} else {
|
||||||
Offs = ConstExpression ();
|
Offs = ConstExpression ();
|
||||||
|
|
||||||
@@ -233,7 +240,12 @@ static long DoStructInternal (long Offs, unsigned Type)
|
|||||||
default:
|
default:
|
||||||
if (!CheckConditionals ()) {
|
if (!CheckConditionals ()) {
|
||||||
/* Not a conditional directive */
|
/* 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 */
|
/* End of struct/union definition */
|
||||||
if (Type == STRUCT) {
|
if (Type == STRUCT) {
|
||||||
Consume (TOK_ENDSTRUCT, "'.ENDSTRUCT' expected");
|
Consume (TOK_ENDSTRUCT, "Expected '.ENDSTRUCT'");
|
||||||
} else {
|
} else {
|
||||||
Consume (TOK_ENDUNION, "'.ENDUNION' expected");
|
Consume (TOK_ENDUNION, "Expected '.ENDUNION'");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the size of the struct */
|
/* Return the size of the struct */
|
||||||
|
|||||||
@@ -1359,8 +1359,7 @@ static void StudyNearAddr (ExprNode* Expr, ExprDesc* D)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Promote to absolute if smaller. */
|
/* Promote to absolute if smaller. */
|
||||||
if (D->AddrSize < ADDR_SIZE_ABS)
|
if (D->AddrSize < ADDR_SIZE_ABS) {
|
||||||
{
|
|
||||||
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 */
|
/* Start from the root scope */
|
||||||
Scope = RootScope;
|
Scope = RootScope;
|
||||||
|
|
||||||
} else if (CurTok.Tok == TOK_IDENT) {
|
} else if (Expect (TOK_IDENT, "Expected an identifier")) {
|
||||||
|
|
||||||
/* Remember the name and skip it */
|
/* Remember the name and skip it */
|
||||||
SB_Copy (Name, &CurTok.SVal);
|
SB_Copy (Name, &CurTok.SVal);
|
||||||
@@ -115,8 +115,7 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
|
|||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
/* Next token must be an identifier. */
|
/* Next token must be an identifier. */
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
if (!Expect (TOK_IDENT, "Expected an identifier")) {
|
||||||
Error ("Identifier expected");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -216,6 +216,10 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags
|
|||||||
if (S->Flags & SF_IMPORT) {
|
if (S->Flags & SF_IMPORT) {
|
||||||
/* Defined symbol is marked as imported external symbol */
|
/* Defined symbol is marked as imported external symbol */
|
||||||
Error ("Symbol '%m%p' is already an import", GetSymName (S));
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if ((Flags & SF_VAR) != 0 && (S->Flags & (SF_EXPORT | SF_GLOBAL))) {
|
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. */
|
/* Multiple definition. In case of a variable, this is legal. */
|
||||||
if ((S->Flags & SF_VAR) == 0) {
|
if ((S->Flags & SF_VAR) == 0) {
|
||||||
Error ("Symbol '%m%p' is already defined", GetSymName (S));
|
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;
|
S->Flags |= SF_MULTDEF;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
304
src/ca65/token.c
304
src/ca65/token.c
@@ -33,30 +33,261 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
/* ca65 */
|
/* ca65 */
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Data */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int TokHasSVal (token_t Tok)
|
/* Use a struct so we can extend it if required */
|
||||||
/* Return true if the given token has an attached SVal */
|
typedef struct TokDescEntry TokDescEntry;
|
||||||
{
|
struct TokDescEntry {
|
||||||
return (Tok == TOK_IDENT || Tok == TOK_LOCAL_IDENT || Tok == TOK_STRCON);
|
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 */
|
/* Code */
|
||||||
{
|
/*****************************************************************************/
|
||||||
return (Tok == TOK_INTCON || Tok == TOK_CHARCON || Tok == TOK_REG);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -72,3 +303,54 @@ void CopyToken (Token* Dst, const Token* Src)
|
|||||||
SB_Copy (&Dst->SVal, &Src->SVal);
|
SB_Copy (&Dst->SVal, &Src->SVal);
|
||||||
Dst->Pos = Src->Pos;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -62,18 +62,21 @@ typedef enum token_t {
|
|||||||
TOK_CHARCON, /* Character constant */
|
TOK_CHARCON, /* Character constant */
|
||||||
TOK_STRCON, /* String constant */
|
TOK_STRCON, /* String constant */
|
||||||
|
|
||||||
TOK_A, /* A)ccumulator */
|
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_X, /* X register */
|
||||||
TOK_Y, /* Y register */
|
TOK_Y, /* Y register */
|
||||||
TOK_Z, /* Z register */
|
TOK_Z, /* Z register */
|
||||||
TOK_S, /* S register */
|
|
||||||
TOK_Q, /* Q pseudo register */
|
|
||||||
TOK_REG, /* Sweet16 R.. register (in sweet16 mode) */
|
TOK_REG, /* Sweet16 R.. register (in sweet16 mode) */
|
||||||
|
TOK_LASTREG = TOK_REG, /* Last register name token */
|
||||||
|
|
||||||
TOK_ASSIGN, /* := */
|
TOK_ASSIGN, /* := */
|
||||||
TOK_ULABEL, /* An unnamed label */
|
TOK_ULABEL, /* An unnamed label */
|
||||||
|
|
||||||
TOK_EQ, /* = */
|
TOK_FIRSTOP, /* First operator token */
|
||||||
|
TOK_EQ = TOK_FIRSTOP, /* = */
|
||||||
TOK_NE, /* <> */
|
TOK_NE, /* <> */
|
||||||
TOK_LT, /* < */
|
TOK_LT, /* < */
|
||||||
TOK_GT, /* > */
|
TOK_GT, /* > */
|
||||||
@@ -97,6 +100,7 @@ typedef enum token_t {
|
|||||||
TOK_SHL, /* << */
|
TOK_SHL, /* << */
|
||||||
TOK_SHR, /* >> */
|
TOK_SHR, /* >> */
|
||||||
TOK_NOT, /* ~ */
|
TOK_NOT, /* ~ */
|
||||||
|
TOK_LASTOP = TOK_NOT, /* Last operator token */
|
||||||
|
|
||||||
TOK_PC, /* $ if enabled */
|
TOK_PC, /* $ if enabled */
|
||||||
TOK_NAMESPACE, /* :: */
|
TOK_NAMESPACE, /* :: */
|
||||||
@@ -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 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 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)
|
static inline int TokIsSep (enum token_t T)
|
||||||
/* Return true if this is a separator token */
|
/* Return true if this is a separator token */
|
||||||
@@ -334,6 +354,9 @@ void CopyToken (Token* Dst, const Token* Src);
|
|||||||
** initialized.
|
** initialized.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
StrBuf* TokenDesc (const Token* T, StrBuf* S);
|
||||||
|
/* Place a textual description of the given token into S. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* End of token.h */
|
/* End of token.h */
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
|
|
||||||
.macpack cpu
|
|
||||||
|
|
||||||
; step 1: try to assemble an instruction that's exclusive to this set
|
; step 1: try to assemble an instruction that's exclusive to this set
|
||||||
; (when possible)
|
; (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:3: Error: Expected a capability name but found ')'
|
||||||
110-capabilities.s:8: Error: Arguments to .CAPABILITY must be identifiers
|
110-capabilities.s:8: Error: Expected a capability name but found 'end-of-line'
|
||||||
110-capabilities.s:8: Error: ')' expected
|
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:12: Error: Not a valid capability name: CPU_HAS_BR
|
||||||
110-capabilities.s:17: Error: ')' expected
|
110-capabilities.s:17: Error: Expected ')' but found 'cpu_has_bra8'
|
||||||
110-capabilities.s:17: Error: Unexpected trailing garbage characters
|
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