Merge branch 'master' into seglist

This commit is contained in:
Bob Andrews
2025-07-10 20:48:28 +02:00
committed by GitHub
226 changed files with 2847 additions and 2118 deletions

View File

@@ -35,6 +35,7 @@
/* ca65 */
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "instr.h"
#include "lineinfo.h"
@@ -194,7 +195,7 @@ static void FreeIf (void)
{
int Done;
do {
IfDesc* ID = GetCurrentIf();
IfDesc* ID = GetCurrentIf ();
if (ID == 0) {
Error (" Unexpected .ENDIF");
Done = 1;
@@ -318,7 +319,7 @@ void DoConditionals (void)
D = AllocIf (".IFCONST", 1);
NextTok ();
if (IfCond) {
ExprNode* Expr = Expression();
ExprNode* Expr = Expression ();
SetIfCond (D, IsConstExpr (Expr, 0));
FreeExpr (Expr);
ExpectSep ();
@@ -354,7 +355,7 @@ void DoConditionals (void)
D = AllocIf (".IFNCONST", 1);
NextTok ();
if (IfCond) {
ExprNode* Expr = Expression();
ExprNode* Expr = Expression ();
SetIfCond (D, !IsConstExpr (Expr, 0));
FreeExpr (Expr);
ExpectSep ();
@@ -388,7 +389,7 @@ void DoConditionals (void)
D = AllocIf (".IFP02", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_6502);
SetIfCond (D, GetCPU () == CPU_6502);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -398,7 +399,7 @@ void DoConditionals (void)
D = AllocIf (".IFP02X", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_6502X);
SetIfCond (D, GetCPU () == CPU_6502X);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -408,7 +409,7 @@ void DoConditionals (void)
D = AllocIf (".IFP4510", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_4510);
SetIfCond (D, GetCPU () == CPU_4510);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -418,7 +419,7 @@ void DoConditionals (void)
D = AllocIf (".IFP45GS02", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_45GS02);
SetIfCond (D, GetCPU () == CPU_45GS02);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -428,7 +429,7 @@ void DoConditionals (void)
D = AllocIf (".IFP6280", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_HUC6280);
SetIfCond (D, GetCPU () == CPU_HUC6280);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -438,7 +439,7 @@ void DoConditionals (void)
D = AllocIf (".IFP816", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_65816);
SetIfCond (D, GetCPU () == CPU_65816);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -448,7 +449,7 @@ void DoConditionals (void)
D = AllocIf (".IFPC02", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_65C02);
SetIfCond (D, GetCPU () == CPU_65C02);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -458,7 +459,7 @@ void DoConditionals (void)
D = AllocIf (".IFPCE02", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_65CE02);
SetIfCond (D, GetCPU () == CPU_65CE02);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -468,7 +469,7 @@ void DoConditionals (void)
D = AllocIf (".IFPDTV", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_6502DTV);
SetIfCond (D, GetCPU () == CPU_6502DTV);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -478,7 +479,7 @@ void DoConditionals (void)
D = AllocIf (".IFPM740", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_M740);
SetIfCond (D, GetCPU () == CPU_M740);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -488,7 +489,7 @@ void DoConditionals (void)
D = AllocIf (".IFPSC02", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_65SC02);
SetIfCond (D, GetCPU () == CPU_65SC02);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -498,7 +499,7 @@ void DoConditionals (void)
D = AllocIf (".IFPSWEET16", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_SWEET16);
SetIfCond (D, GetCPU () == CPU_SWEET16);
}
ExpectSep ();
CalcOverallIfCond ();
@@ -508,7 +509,7 @@ void DoConditionals (void)
D = AllocIf (".IFPWC02", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_W65C02);
SetIfCond (D, GetCPU () == CPU_W65C02);
}
ExpectSep ();
CalcOverallIfCond ();

View File

@@ -46,6 +46,7 @@
/* ca65 */
#include "dbginfo.h"
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "filetab.h"
#include "global.h"
@@ -238,8 +239,7 @@ void DbgInfoFunc (void)
ConsumeComma ();
/* Type */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
return;
}
Type = ValidateType (&CurTok.SVal);
@@ -267,8 +267,7 @@ void DbgInfoFunc (void)
ConsumeComma ();
/* Assembler name follows */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
return;
}
AsmName = GetStrBufId (&CurTok.SVal);
@@ -321,8 +320,7 @@ void DbgInfoLine (void)
ConsumeComma ();
/* The name of the file follows */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
return;
}
@@ -371,8 +369,7 @@ void DbgInfoSym (void)
ConsumeComma ();
/* Name */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
return;
}
Name = GetStrBufId (&CurTok.SVal);
@@ -382,8 +379,7 @@ void DbgInfoSym (void)
ConsumeComma ();
/* Type */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
return;
}
Type = ValidateType (&CurTok.SVal);
@@ -418,8 +414,7 @@ void DbgInfoSym (void)
Offs = ConstExpression ();
} else {
/* Register, extern or static: Assembler name follows */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
return;
}
AsmName = GetStrBufId (&CurTok.SVal);
@@ -468,7 +463,7 @@ void DbgInfoCheck (void)
/* Search for the symbol name */
S->Sym = SymFindAny (S->Scope, GetStrBuf (S->AsmName));
if (S->Sym == 0) {
PError (&S->Pos, "Assembler symbol '%s' not found",
PError (&S->Pos, "Assembler symbol `%s' not found",
GetString (S->AsmName));
} else {
/* Set the backlink */

View File

@@ -37,6 +37,7 @@
#include "ea.h"
#include "ea65.h"
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "instr.h"
#include "nexttok.h"
@@ -62,11 +63,11 @@ void GetEA (EffAddr* A)
if (BracketAsIndirect) {
IndirectEnter = TOK_LBRACK;
IndirectLeave = TOK_RBRACK;
IndirectExpect = "']' expected";
IndirectExpect = "Expected `]'";
} else {
IndirectEnter = TOK_LPAREN;
IndirectLeave = TOK_RPAREN;
IndirectExpect = "')' expected";
IndirectExpect = "Expected `)'";
}
/* Clear the output struct */
@@ -136,16 +137,22 @@ void GetEA (EffAddr* A)
/* (adr,x) */
NextTok ();
A->AddrModeSet = AM65_ABS_X_IND | AM65_DIR_X_IND;
Consume (IndirectLeave, IndirectExpect);
if (!Consume (IndirectLeave, IndirectExpect)) {
SkipUntilSep ();
}
} else if (CurTok.Tok == TOK_S) {
/* (rel,s),y */
NextTok ();
A->AddrModeSet = AM65_STACK_REL_IND_Y;
Consume (IndirectLeave, IndirectExpect);
ConsumeComma ();
Consume (TOK_Y, "'Y' expected");
if (!Consume (IndirectLeave, IndirectExpect) ||
!ConsumeComma () ||
!Consume (TOK_Y, "Expected `Y'")) {
/* In case of errors skip anything else on the line */
SkipUntilSep ();
}
} else {
Error ("Syntax error");
ErrorExpect ("Expected `X' or `S'");
SkipUntilSep ();
}
} else {
@@ -162,7 +169,9 @@ void GetEA (EffAddr* A)
A->AddrModeSet = AM65_DIR_IND;
break;
default:
Consume (TOK_Y, "'Y' expected");
if (!Consume (TOK_Y, "Expected `Y'")) {
SkipUntilSep ();
}
A->AddrModeSet = AM65_DIR_IND_Y;
break;
}
@@ -190,16 +199,22 @@ void GetEA (EffAddr* A)
/* [dir] or [dir],y */
NextTok ();
A->Expr = Expression ();
Consume (TOK_RBRACK, "']' expected");
if (!Consume (TOK_RBRACK, "Expected `]'")) {
SkipUntilSep ();
}
if (CurTok.Tok == TOK_COMMA) {
/* [dir],y */
NextTok ();
if (GetCPU () == CPU_45GS02) {
Consume (TOK_Z, "'Z' expected");
if (!Consume (TOK_Z, "Expected `Z'")) {
SkipUntilSep ();
}
A->AddrModeSet = AM65_32BIT_BASE_IND_Z;
}
else {
Consume (TOK_Y, "'Y' expected");
if (!Consume (TOK_Y, "Expected `Y'")) {
SkipUntilSep ();
}
A->AddrModeSet = AM65_DIR_IND_LONG_Y;
}
} else {

View File

@@ -37,6 +37,7 @@
#include "ea.h"
#include "ea65.h"
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "instr.h"
#include "nexttok.h"
@@ -96,7 +97,7 @@ void GetSweet16EA (EffAddr* A)
/* Register number */
A->Reg = (unsigned) Reg;
} else {
ErrorSkip ("Register or register number expected");
ErrorExpect ("Expected register or register number");
A->Reg = 0;
}

View File

@@ -41,6 +41,7 @@
#include "condasm.h"
#include "enum.h"
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "macro.h"
#include "nexttok.h"
@@ -87,12 +88,13 @@ void DoEnum (void)
continue;
}
/* Allow conditionals within an enum */
if (CheckConditionals ()) {
continue;
}
/* The format is "identifier [ = value ]" */
if (CurTok.Tok != TOK_IDENT) {
/* Maybe it's a conditional? */
if (!CheckConditionals ()) {
ErrorSkip ("Identifier expected");
}
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
continue;
}
@@ -146,7 +148,7 @@ void DoEnum (void)
}
/* End of enum definition */
Consume (TOK_ENDENUM, "'.ENDENUM' expected");
Consume (TOK_ENDENUM, "`.ENDENUM' expected");
/* Free the base expression */
FreeExpr (BaseExpr);

View File

@@ -38,6 +38,8 @@
#include <stdarg.h>
/* common */
#include "cmdline.h"
#include "consprop.h"
#include "strbuf.h"
/* ca65 */
@@ -45,6 +47,7 @@
#include "filetab.h"
#include "lineinfo.h"
#include "nexttok.h"
#include "spool.h"
@@ -64,6 +67,14 @@ unsigned WarningCount = 0;
/* Maximum number of additional notifications */
#define MAX_NOTES 8
/* Diagnostic category */
typedef enum { DC_NOTE, DC_WARN, DC_ERR, DC_FATAL, DC_COUNT } DiagCat;
/* Descriptions for diagnostic categories */
const char* DiagCatDesc[DC_COUNT] = {
"Note", "Warning", "Error", "Fatal error"
};
/*****************************************************************************/
@@ -72,27 +83,144 @@ unsigned WarningCount = 0;
static void VPrintMsg (const FilePos* Pos, const char* Desc,
const char* Format, va_list ap)
static void ReplaceQuotes (StrBuf* Msg)
/* Replace opening and closing single quotes in Msg by their typographically
** correct UTF-8 counterparts for better readbility. A closing quote will
** only get replaced if an opening quote has been seen before.
** To handle some special cases, the function will also treat \xF0 as
** opening and \xF1 as closing quote. These are replaced without the need for
** correct ordering (open/close).
** The function will change the quotes in place, so after the call Msg will
** contain the changed string. If UTF-8 is not available, the function will
** replace '`' by '\'' since that was the default behavior before. It will
** also replace \xF0 and \xF1 by '\''.
**/
{
/* UTF-8 characters for single quotes */
static const char QuoteStart[] = "\xE2\x80\x98";
static const char QuoteEnd[] = "\xE2\x80\x99";
/* ANSI color sequences */
const char* ColorStart = CP_BrightGreen ();
const char* ColorEnd = CP_White ();
/* Remember a few things */
int IsUTF8 = CP_IsUTF8 ();
/* We create a new string in T and will later copy it back to Msg */
StrBuf T = AUTO_STRBUF_INITIALIZER;
/* Parse the string and create a modified copy */
SB_Reset (Msg);
int InQuote = 0;
while (1) {
char C = SB_Get (Msg);
switch (C) {
case '`':
if (!InQuote) {
InQuote = 1;
if (IsUTF8) {
SB_AppendStr (&T, QuoteStart);
} else {
/* ca65 uses \' for opening and closing quotes */
SB_AppendChar (&T, '\'');
}
SB_AppendStr (&T, ColorStart);
} else {
/* Found two ` without closing quote - don't replace */
SB_AppendChar (&T, '`');
}
break;
case '\'':
if (InQuote) {
InQuote = 0;
SB_AppendStr (&T, ColorEnd);
if (IsUTF8) {
SB_AppendStr (&T, QuoteEnd);
} else {
SB_AppendChar (&T, C);
}
} else {
SB_AppendChar (&T, C);
}
break;
case '\xF0':
if (IsUTF8) {
SB_AppendStr (&T, QuoteStart);
} else {
SB_AppendChar (&T, '\'');
}
break;
case '\xF1':
if (IsUTF8) {
SB_AppendStr (&T, QuoteEnd);
} else {
SB_AppendChar (&T, '\'');
}
break;
case '\0':
goto Done;
default:
SB_AppendChar (&T, C);
break;
}
}
Done:
/* Copy the string back, then terminate it */
SB_Move (Msg, &T);
SB_Terminate (Msg);
}
static void VPrintMsg (const FilePos* Pos, DiagCat Cat, const char* Format,
va_list ap)
/* Format and output an error/warning message. */
{
StrBuf S = STATIC_STRBUF_INITIALIZER;
StrBuf S = AUTO_STRBUF_INITIALIZER;
StrBuf Msg = AUTO_STRBUF_INITIALIZER;
StrBuf Loc = AUTO_STRBUF_INITIALIZER;
/* Format the actual message */
StrBuf Msg = STATIC_STRBUF_INITIALIZER;
/* Determine the description for the category and its color */
const char* Desc = DiagCatDesc[Cat];
const char* Color;
switch (Cat) {
case DC_NOTE: Color = CP_Cyan (); break;
case DC_WARN: Color = CP_Yellow (); break;
case DC_ERR: Color = CP_BrightRed (); break;
case DC_FATAL: Color = CP_BrightRed (); break;
default: FAIL ("Unexpected Cat value"); break;
}
/* Format the actual message, then replace quotes */
SB_VPrintf (&Msg, Format, ap);
SB_Terminate (&Msg);
ReplaceQuotes (&Msg);
/* Format the message header */
SB_Printf (&S, "%s:%u: %s: ",
SB_GetConstBuf (GetFileName (Pos->Name)),
Pos->Line,
Desc);
/* Format the location. If the file position is valid, we use the file
** position, otherwise the program name. This allows to print fatal
** errors in the startup phase.
*/
if (Pos->Name == EMPTY_STRING_ID) {
SB_CopyStr (&Loc, ProgName);
} else {
SB_Printf (&Loc, "%s:%u", SB_GetConstBuf (GetFileName (Pos->Name)),
Pos->Line);
}
SB_Terminate (&Loc);
/* Append the message to the message header */
SB_Append (&S, &Msg);
/* Format the full message */
SB_Printf (&S, "%s%s: %s%s:%s %s%s",
CP_White (),
SB_GetConstBuf (&Loc),
Color,
Desc,
CP_White (),
SB_GetConstBuf (&Msg),
CP_Reset ());
/* Delete the formatted message */
/* Delete the formatted message and the location string */
SB_Done (&Loc);
SB_Done (&Msg);
/* Add a new line and terminate the generated full message */
@@ -108,18 +236,6 @@ static void VPrintMsg (const FilePos* Pos, const char* Desc,
static void PrintMsg (const FilePos* Pos, const char* Desc,
const char* Format, ...)
/* Format and output an error/warning message. */
{
va_list ap;
va_start (ap, Format);
VPrintMsg (Pos, Desc, Format, ap);
va_end (ap);
}
static void AddNotifications (const Collection* LineInfos)
/* Output additional notifications for an error or warning */
{
@@ -165,7 +281,7 @@ static void AddNotifications (const Collection* LineInfos)
/* Output until an upper limit of messages is reached */
if (Msg) {
if (Output < MAX_NOTES) {
PrintMsg (GetSourcePos (LI), "Note", "%s", Msg);
PNotification (GetSourcePos (LI), "%s", Msg);
++Output;
} else {
++Skipped;
@@ -176,13 +292,43 @@ static void AddNotifications (const Collection* LineInfos)
/* Add a note if we have more stuff that we won't output */
if (Skipped > 0) {
const LineInfo* LI = CollConstAt (LineInfos, 0);
PrintMsg (GetSourcePos (LI), "Note",
"Dropping %u additional line infos", Skipped);
PNotification (GetSourcePos (LI), "Dropping %u additional line infos",
Skipped);
}
}
/*****************************************************************************/
/* Notifications */
/*****************************************************************************/
void Notification (const char* Format, ...)
/* Print a notification message. */
{
/* Output the message */
va_list ap;
va_start (ap, Format);
VPrintMsg (&CurTok.Pos, DC_NOTE, Format, ap);
va_end (ap);
}
void PNotification (const FilePos* Pos, const char* Format, ...)
/* Print a notification message. */
{
/* Output the message */
va_list ap;
va_start (ap, Format);
VPrintMsg (Pos, DC_NOTE, Format, ap);
va_end (ap);
}
/*****************************************************************************/
/* Warnings */
/*****************************************************************************/
@@ -196,7 +342,7 @@ static void WarningMsg (const Collection* LineInfos, const char* Format, va_list
const LineInfo* LI = CollConstAt (LineInfos, 0);
/* Output a warning for this position */
VPrintMsg (GetSourcePos (LI), "Warning", Format, ap);
VPrintMsg (GetSourcePos (LI), DC_WARN, Format, ap);
/* Add additional notifications if necessary */
AddNotifications (LineInfos);
@@ -237,7 +383,7 @@ void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...)
if (Level <= WarnLevel) {
va_list ap;
va_start (ap, Format);
VPrintMsg (Pos, "Warning", Format, ap);
VPrintMsg (Pos, DC_WARN, Format, ap);
va_end (ap);
/* Count warnings */
@@ -274,7 +420,7 @@ void ErrorMsg (const Collection* LineInfos, const char* Format, va_list ap)
const LineInfo* LI = CollConstAt (LineInfos, 0);
/* Output an error for this position */
VPrintMsg (GetSourcePos (LI), "Error", Format, ap);
VPrintMsg (GetSourcePos (LI), DC_ERR, Format, ap);
/* Add additional notifications if necessary */
AddNotifications (LineInfos);
@@ -311,7 +457,7 @@ void PError (const FilePos* Pos, const char* Format, ...)
{
va_list ap;
va_start (ap, Format);
VPrintMsg (Pos, "Error", Format, ap);
VPrintMsg (Pos, DC_ERR, Format, ap);
va_end (ap);
/* Count errors */
@@ -365,18 +511,12 @@ void ErrorSkip (const char* Format, ...)
void Fatal (const char* Format, ...)
/* Print a message about a fatal error and die */
{
/* Output the message ... */
va_list ap;
StrBuf S = STATIC_STRBUF_INITIALIZER;
va_start (ap, Format);
SB_VPrintf (&S, Format, ap);
SB_Terminate (&S);
VPrintMsg (&CurTok.Pos, DC_FATAL, Format, ap);
va_end (ap);
fprintf (stderr, "Fatal error: %s\n", SB_GetConstBuf (&S));
SB_Done (&S);
/* And die... */
exit (EXIT_FAILURE);
}

View File

@@ -72,6 +72,12 @@ extern unsigned WarningCount;
void Notification (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Print a notification message. */
void PNotification (const FilePos* Pos, const char* Format, ...) attribute ((format (printf, 2, 3)));
/* Print a notification message. */
void Warning (unsigned Level, const char* Format, ...) attribute ((format (printf, 2, 3)));
/* Print warning message. */

116
src/ca65/expect.c Normal file
View File

@@ -0,0 +1,116 @@
/*****************************************************************************/
/* */
/* expect.c */
/* */
/* Print errors about expected tokens */
/* */
/* */
/* */
/* (C) 2025, Kugelfuhr */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
/* ca65 */
#include "error.h"
#include "expect.h"
#include "nexttok.h"
#include "scanner.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void ErrorExpect (const char* Msg)
/* Output an error message about some expected token using Msg and the
* description of the following token. This means that Msg should contain
* something like "xyz expected". The actual error message would then be
* "xyz expected but found zyx".
*/
{
StrBuf S = AUTO_STRBUF_INITIALIZER;
TokenDesc (&CurTok, &S);
Error ("%s but found `%s'", Msg, SB_GetConstBuf (&S));
SB_Done (&S);
}
int Expect (token_t Expected, const char* Msg)
/* Check if the next token is the expected one. If not, print Msg plus some
* information about the token that was actually found. This means that Msg
* should contain something like "xyz expected". The actual error message would
* then be "xyz expected but found zyx".
* Returns true if the token was found, otherwise false.
*/
{
if (CurTok.Tok == Expected) {
return 1;
}
ErrorExpect (Msg);
return 0;
}
int ExpectSkip (token_t Expected, const char* Msg)
/* Check if the next token is the expected one. If not, print Msg plus some
* information about the token that was actually found and skip the remainder
* of the line. This means that Msg should contain something like "xyz
* expected". The actual error message would then be "xyz expected but found
* zyx".
* Returns true if the token was found, otherwise false.
*/
{
if (CurTok.Tok == Expected) {
return 1;
}
ErrorExpect (Msg);
SkipUntilSep ();
return 0;
}
int ExpectSep (void)
/* Check if we've reached a line separator. If so, return true. If not, output
** an error and skip all tokens until the line separator is reached. Then
** return false.
*/
{
if (!TokIsSep (CurTok.Tok)) {
/* Try to be helpful by giving information about the token that was
* unexpected.
*/
ErrorExpect ("Expected `end-of-line'");
SkipUntilSep ();
return 0;
} else {
return 1;
}
}

83
src/ca65/expect.h Normal file
View File

@@ -0,0 +1,83 @@
/*****************************************************************************/
/* */
/* expect.h */
/* */
/* Print errors about expected tokens */
/* */
/* */
/* */
/* (C) 2025, Kugelfuhr */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef EXPECT_H
#define EXPECT_H
/* ca65 */
#include "token.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void ErrorExpect (const char* Msg);
/* Output an error message about some expected token using Msg and the
* description of the following token. This means that Msg should contain
* something like "xyz expected". The actual error message would then be
* "xyz expected but found zyx".
*/
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.
*/
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.
*/
int ExpectSep (void);
/* Check if we've reached a line separator. If so, return true. If not, output
** an error and skip all tokens until the line separator is reached. Then
** return false.
*/
/* End of expect.h */
#endif

View File

@@ -51,6 +51,7 @@
/* ca65 */
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "global.h"
#include "instr.h"
@@ -421,8 +422,7 @@ static ExprNode* FuncCapability (void)
capability_t Cap;
/* We must have an identifier */
if (CurTok.Tok != TOK_IDENT) {
Error ("Arguments to .CAPABILITY must be identifiers");
if (!Expect (TOK_IDENT, "Expected a capability name")) {
/* Skip tokens until closing paren or end of line */
while (CurTok.Tok != TOK_RPAREN && !TokIsSep (CurTok.Tok)) {
NextTok ();
@@ -779,7 +779,7 @@ static ExprNode* FuncAddrSize (void)
/* Cheap local symbol */
Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING);
if (Sym == 0) {
Error ("Unknown symbol or scope: '%m%p'", &CurTok.SVal);
Error ("Unknown symbol or scope: `%m%p'", &CurTok.SVal);
} else {
AddrSize = Sym->AddrSize;
}
@@ -819,13 +819,13 @@ static ExprNode* FuncAddrSize (void)
if (Sym) {
AddrSize = Sym->AddrSize;
} else {
Error ("Unknown symbol or scope: '%m%p%m%p'", &ScopeName, &Name);
Error ("Unknown symbol or scope: `%m%p%m%p'", &ScopeName, &Name);
}
}
if (AddrSize == 0) {
Warning (1, "Unknown address size: '%m%p%m%p'", &ScopeName, &Name);
Warning (1, "Unknown address size: `%m%p%m%p'", &ScopeName, &Name);
}
/* Free the string buffers */
@@ -860,7 +860,7 @@ static ExprNode* FuncSizeOf (void)
/* Cheap local symbol */
Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING);
if (Sym == 0) {
Error ("Unknown symbol or scope: '%m%p'", &CurTok.SVal);
Error ("Unknown symbol or scope: `%m%p'", &CurTok.SVal);
} else {
SizeSym = GetSizeOfSymbol (Sym);
}
@@ -912,7 +912,7 @@ static ExprNode* FuncSizeOf (void)
if (Sym) {
SizeSym = GetSizeOfSymbol (Sym);
} else {
Error ("Unknown symbol or scope: '%m%p%m%p'",
Error ("Unknown symbol or scope: `%m%p%m%p'",
&ScopeName, &Name);
}
}
@@ -920,7 +920,7 @@ static ExprNode* FuncSizeOf (void)
/* Check if we have a size */
if (SizeSym == 0 || !SymIsConst (SizeSym, &Size)) {
Error ("Size of '%m%p%m%p' is unknown", &ScopeName, &Name);
Error ("Size of `%m%p%m%p' is unknown", &ScopeName, &Name);
Size = 0;
}
@@ -942,8 +942,7 @@ static ExprNode* FuncStrAt (void)
unsigned char C = 0;
/* String constant expected */
if (CurTok.Tok != TOK_STRCON) {
Error ("String constant expected");
if (!Expect (TOK_STRCON, "Expected a string constant")) {
NextTok ();
goto ExitPoint;
}
@@ -985,9 +984,8 @@ static ExprNode* FuncStrLen (void)
int Len;
/* String constant expected */
if (CurTok.Tok != TOK_STRCON) {
if (!Expect (TOK_STRCON, "Expected a string constant")) {
Error ("String constant expected");
/* Smart error recovery */
if (CurTok.Tok != TOK_RPAREN) {
NextTok ();
@@ -1062,9 +1060,7 @@ static ExprNode* Function (ExprNode* (*F) (void))
NextTok ();
/* Expression must be enclosed in braces */
if (CurTok.Tok != TOK_LPAREN) {
Error ("'(' expected");
SkipUntilSep ();
if (!ExpectSkip (TOK_LPAREN, "Expected `('")) {
return GenLiteral0 ();
}
NextTok ();
@@ -1296,7 +1292,7 @@ static ExprNode* Factor (void)
NextTok ();
} else {
N = GenLiteral0 (); /* Dummy */
Error ("Syntax error");
ErrorExpect ("Expected an expression");
}
break;
}
@@ -1957,9 +1953,8 @@ ExprNode* GenNearAddrExpr (ExprNode* Expr)
if (IsEasyConst (Expr, &Val)) {
FreeExpr (Expr);
Expr = GenLiteralExpr (Val & 0xFFFF);
if (Val > 0xFFFF)
{
Error("Range error: constant too large for assumed near address.");
if (Val > 0xFFFF) {
Error ("Range error: constant too large for assumed near address.");
}
} else {
ExprNode* Operand = Expr;

View File

@@ -211,7 +211,7 @@ unsigned GetFileIndex (const StrBuf* Name)
/* If we don't have this index, print a diagnostic and use the main file */
if (F == 0) {
Error ("File name '%m%p' not found in file table", Name);
Error ("File name `%m%p' not found in file table", Name);
return 0;
} else {
return F->Index;
@@ -316,7 +316,7 @@ static void CreateDepFile (const char* Name, FileType Types)
/* Open the file */
FILE* F = fopen (Name, "w");
if (F == 0) {
Fatal ("Cannot open dependency file '%s': %s", Name, strerror (errno));
Fatal ("Cannot open dependency file `%s': %s", Name, strerror (errno));
}
/* Print the output file followed by a tab char */

View File

@@ -1961,7 +1961,7 @@ static void PutLDM_m740 (const InsDesc* Ins)
}
Emit0 (Ins->BaseCode);
EmitByte (A.Expr);
Consume (TOK_HASH, "'#' expected");
Consume (TOK_HASH, "`#' expected");
EmitByte (Expression ());
}
@@ -2091,7 +2091,7 @@ static void PutBitBranch_m740 (const InsDesc* Ins)
EffAddr A;
/* Evaluate the addressing mode used */
GetEA(&A);
GetEA (&A);
/* From the possible addressing modes, remove the ones that are invalid
** for this instruction or CPU.
@@ -2375,7 +2375,7 @@ static void PutJSR_m740 (const InsDesc* Ins)
/* direct page */
A.Opcode = 0x22;
Emit0 (A.Opcode);
EmitByte(GenByteExpr(A.Expr));
EmitByte (GenByteExpr (A.Expr));
return;
}
}

View File

@@ -316,7 +316,7 @@ void CreateListing (void)
/* Open the real listing file */
F = fopen (SB_GetConstBuf (&ListingName), "w");
if (F == 0) {
Fatal ("Cannot open listing file '%s': %s",
Fatal ("Cannot open listing file `%s': %s",
SB_GetConstBuf (&ListingName),
strerror (errno));
}

View File

@@ -45,6 +45,7 @@
/* ca65 */
#include "condasm.h"
#include "error.h"
#include "expect.h"
#include "global.h"
#include "instr.h"
#include "istack.h"
@@ -102,10 +103,12 @@ struct Macro {
unsigned TokCount; /* Number of tokens for this macro */
TokNode* TokRoot; /* Root of token list */
TokNode* TokLast; /* Pointer to last token in list */
FilePos DefPos; /* Position of definition */
StrBuf Name; /* Macro name, dynamically allocated */
unsigned Expansions; /* Number of active macro expansions */
unsigned char Style; /* Macro style */
unsigned char Incomplete; /* Macro is currently built */
unsigned char HasError; /* Macro has errors */
};
/* Hash table functions */
@@ -232,7 +235,7 @@ static void FreeIdDescList (IdDesc* ID)
static Macro* NewMacro (const StrBuf* Name, unsigned char Style)
static Macro* NewMacro (const StrBuf* Name, const FilePos* P, unsigned char Style)
/* Generate a new macro entry, initialize and return it */
{
/* Allocate memory */
@@ -247,11 +250,14 @@ static Macro* NewMacro (const StrBuf* Name, unsigned char Style)
M->TokCount = 0;
M->TokRoot = 0;
M->TokLast = 0;
M->DefPos = *P;
SB_Init (&M->Name);
SB_Copy (&M->Name, Name);
SB_Terminate (&M->Name); /* So the name can be used with %s */
M->Expansions = 0;
M->Style = Style;
M->Incomplete = 1;
M->HasError = 0;
/* Insert the macro into the hash table */
HT_Insert (&MacroTab, &M->Node);
@@ -364,19 +370,28 @@ static void FreeMacExp (MacExp* E)
static void MacSkipDef (unsigned Style)
static void MacSkipDef (unsigned Style, const FilePos* StartPos)
/* Skip a macro definition */
{
if (Style == MAC_STYLE_CLASSIC) {
/* Skip tokens until we reach the final .endmacro */
while (CurTok.Tok != TOK_ENDMACRO && CurTok.Tok != TOK_EOF) {
/* Skip tokens until we reach the final .endmacro. Implement the same
** behavior as when parsing the macro regularily: .endmacro needs to
** be at the start of the line to end the macro definition.
*/
int LastWasSep = 0;
while (1) {
if (CurTok.Tok == TOK_EOF) {
ErrorExpect ("Expected `.ENDMACRO'");
PNotification (StartPos, "Macro definition started here");
break;
}
if (CurTok.Tok == TOK_ENDMACRO && LastWasSep) {
NextTok ();
break;
}
LastWasSep = (CurTok.Tok == TOK_SEP);
NextTok ();
}
if (CurTok.Tok != TOK_EOF) {
SkipUntilSep ();
} else {
Error ("'.ENDMACRO' expected");
}
} else {
/* Skip until end of line */
SkipUntilSep ();
@@ -388,48 +403,49 @@ static void MacSkipDef (unsigned Style)
void MacDef (unsigned Style)
/* Parse a macro definition */
{
Macro* Existing;
Macro* M;
TokNode* N;
FilePos Pos;
int HaveParams;
int LastTokWasSep;
/* Remember the current file position */
FilePos StartPos = CurTok.Pos;
/* For classic macros, remember if we are at the beginning of the line.
** If the macro name and parameters pass our checks then we will be on a
** new line, so set it now
*/
LastTokWasSep = 1;
/* Save the position of the start of the macro definition to allow
** using Perror to display the error if .endmacro isn't found
*/
Pos = CurTok.Pos;
int LastTokWasSep = 1;
/* We expect a macro name here */
if (CurTok.Tok != TOK_IDENT) {
Error ("Identifier expected");
MacSkipDef (Style);
if (!Expect (TOK_IDENT, "Expected an identifier")) {
MacSkipDef (Style, &StartPos);
return;
} else if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) {
}
if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) {
/* The identifier is a name of a 6502 instruction, which is not
** allowed if not explicitly enabled.
*/
Error ("Cannot use an instruction as macro name");
MacSkipDef (Style);
MacSkipDef (Style, &StartPos);
return;
}
/* Did we already define that macro? */
if (HT_Find (&MacroTab, &CurTok.SVal) != 0) {
Existing = HT_Find (&MacroTab, &CurTok.SVal);
if (Existing != 0) {
/* Macro is already defined */
Error ("A macro named '%m%p' is already defined", &CurTok.SVal);
Error ("A macro named `%m%p' is already defined", &CurTok.SVal);
PNotification (&Existing->DefPos,
"Previous definition of macro `%s' was here",
SB_GetConstBuf (&Existing->Name));
/* Skip tokens until we reach the final .endmacro */
MacSkipDef (Style);
MacSkipDef (Style, &StartPos);
return;
}
/* Define the macro */
M = NewMacro (&CurTok.SVal, Style);
M = NewMacro (&CurTok.SVal, &StartPos, Style);
/* Switch to raw token mode and skip the macro name */
EnterRawTokenMode ();
@@ -439,7 +455,7 @@ void MacDef (unsigned Style)
** otherwise, we may have parameters without parentheses.
*/
if (Style == MAC_STYLE_CLASSIC) {
HaveParams = 1;
HaveParams = (CurTok.Tok != TOK_SEP);
} else {
if (CurTok.Tok == TOK_LPAREN) {
HaveParams = 1;
@@ -451,7 +467,7 @@ void MacDef (unsigned Style)
/* Parse the parameter list */
if (HaveParams) {
while (CurTok.Tok == TOK_IDENT) {
while (Expect (TOK_IDENT, "Expected a parameter name")) {
/* Create a struct holding the identifier */
IdDesc* I = NewIdDesc (&CurTok.SVal);
@@ -463,7 +479,8 @@ void MacDef (unsigned Style)
while (1) {
if (SB_Compare (&List->Id, &CurTok.SVal) == 0) {
Error ("Duplicate symbol '%m%p'", &CurTok.SVal);
Error ("Duplicate macro parameter `%m%p'", &CurTok.SVal);
M->HasError = 1;
}
if (List->Next == 0) {
break;
@@ -513,7 +530,10 @@ void MacDef (unsigned Style)
}
/* May not have end of file in a macro definition */
if (CurTok.Tok == TOK_EOF) {
PError (&Pos, "'.ENDMACRO' expected for macro '%m%p'", &M->Name);
Error ("Missing `.ENDMACRO' for definition of macro `%s'",
SB_GetConstBuf (&M->Name));
PNotification (&StartPos, "Macro definition started here");
M->HasError = 1;
goto Done;
}
} else {
@@ -533,8 +553,9 @@ void MacDef (unsigned Style)
/* Need an identifer */
if (CurTok.Tok != TOK_IDENT && CurTok.Tok != TOK_LOCAL_IDENT) {
Error ("Identifier expected");
ErrorExpect ("Expected an identifier");
SkipUntilSep ();
M->HasError = 1;
break;
}
@@ -553,7 +574,10 @@ void MacDef (unsigned Style)
}
/* We need end of line after the locals */
ConsumeSep ();
if (!ExpectSep ()) {
M->HasError = 1;
}
NextTok ();
continue;
}
@@ -591,7 +615,7 @@ void MacDef (unsigned Style)
/* Save if last token was a separator to know if .endmacro is at
** the start of a line
*/
LastTokWasSep = TokIsSep(CurTok.Tok);
LastTokWasSep = TokIsSep (CurTok.Tok);
/* Read the next token */
NextTok ();
@@ -622,11 +646,12 @@ void MacUndef (const StrBuf* Name, unsigned char Style)
/* Don't let the user kid with us */
if (M == 0 || M->Style != Style) {
Error ("No such macro: %m%p", Name);
Error ("No such macro: `%m%p'", Name);
return;
}
if (M->Expansions > 0) {
Error ("Cannot delete a macro that is currently expanded");
Error ("Cannot delete macro `%s' which is currently expanded",
SB_GetConstBuf (&M->Name));
return;
}
@@ -813,7 +838,11 @@ static void StartExpClassic (MacExp* E)
/* Check for maximum parameter count */
if (E->ParamCount >= E->M->ParamCount) {
ErrorSkip ("Too many macro parameters");
ErrorSkip ("Too many parameters for macro `%s'",
SB_GetConstBuf (&E->M->Name));
PNotification (&E->M->DefPos,
"See definition of macro `%s' which was here",
SB_GetConstBuf (&E->M->Name));
break;
}
@@ -827,7 +856,7 @@ static void StartExpClassic (MacExp* E)
/* Check for end of file */
if (CurTok.Tok == TOK_EOF) {
Error ("Unexpected end of file");
Error ("Unexpected end of file in macro parameter list");
FreeMacExp (E);
return;
}
@@ -938,10 +967,8 @@ static void StartExpDefine (MacExp* E)
/* Check for a comma */
if (Count > 0) {
if (CurTok.Tok == TOK_COMMA) {
if (Expect (TOK_COMMA, "Expected `,'")) {
NextTok ();
} else {
Error ("',' expected");
}
}
}
@@ -972,9 +999,21 @@ void MacExpandStart (Macro* M)
Pos = CurTok.Pos;
NextTok ();
/* We cannot expand a macro with errors */
if (M->HasError) {
PError (&Pos, "Macro `%s' contains errors and cannot be expanded",
SB_GetConstBuf (&M->Name));
PNotification (&M->DefPos, "Definition of macro `%s' was here",
SB_GetConstBuf (&M->Name));
return;
}
/* We cannot expand an incomplete macro */
if (M->Incomplete) {
PError (&Pos, "Cannot expand an incomplete macro");
PError (&Pos, "Macro `%s' is incomplete and cannot be expanded",
SB_GetConstBuf (&M->Name));
PNotification (&M->DefPos, "Definition of macro `%s' was here",
SB_GetConstBuf (&M->Name));
return;
}
@@ -982,7 +1021,8 @@ void MacExpandStart (Macro* M)
** to force an endless loop and assembler crash.
*/
if (MacExpansions >= MAX_MACEXPANSIONS) {
PError (&Pos, "Too many nested macro expansions");
PError (&Pos, "Too many nested macro expansions for macro `%s'",
SB_GetConstBuf (&M->Name));
return;
}

View File

@@ -42,6 +42,7 @@
#include "addrsize.h"
#include "chartype.h"
#include "cmdline.h"
#include "consprop.h"
#include "debugflag.h"
#include "mmodel.h"
#include "print.h"
@@ -56,6 +57,7 @@
#include "asserts.h"
#include "dbginfo.h"
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "feature.h"
#include "filetab.h"
@@ -112,6 +114,7 @@ static void Usage (void)
"Long options:\n"
" --auto-import\t\t\tMark unresolved symbols as import\n"
" --bin-include-dir dir\t\tSet a search path for binary includes\n"
" --color [on|auto|off]\t\tColor diagnostics (default: auto)\n"
" --cpu type\t\t\tSet cpu type\n"
" --create-dep name\t\tCreate a make dependency file\n"
" --create-full-dep name\tCreate a full make dependency file\n"
@@ -125,13 +128,15 @@ static void Usage (void)
" --listing name\t\tCreate a listing file if assembly was ok\n"
" --list-bytes n\t\tMaximum number of bytes per listing line\n"
" --memory-model model\t\tSet the memory model\n"
" --no-utf8\t\t\tDisable use of UTF-8 in diagnostics\n"
" --pagelength n\t\tSet the page length for the listing\n"
" --relax-checks\t\tRelax some checks (see docs)\n"
" --segment-list\t\tEnable segment offset listing\n"
" --smart\t\t\tEnable smart mode\n"
" --target sys\t\t\tSet the target system\n"
" --verbose\t\t\tIncrease verbosity\n"
" --version\t\t\tPrint the assembler version\n",
" --version\t\t\tPrint the assembler version\n"
" --warnings-as-errors\t\tTreat warnings as errors\n",
ProgName);
}
@@ -147,7 +152,7 @@ static void SetOptions (void)
OptTranslator (&Buf);
/* Set date and time */
OptDateTime ((unsigned long) time(0));
OptDateTime ((unsigned long) time (0));
/* Release memory for the string */
SB_Done (&Buf);
@@ -494,6 +499,22 @@ static void OptBinIncludeDir (const char* Opt attribute ((unused)), const char*
static void OptColor(const char* Opt, const char* Arg)
/* Handle the --color option */
{
if (strcmp (Arg, "off") == 0 || strcmp (Arg, "false") == 0) {
CP_SetColorMode (CM_OFF);
} else if (strcmp (Arg, "auto") == 0) {
CP_SetColorMode (CM_AUTO);
} else if (strcmp (Arg, "on") == 0 || strcmp (Arg, "true") == 0) {
CP_SetColorMode (CM_ON);
} else {
AbEnd ("Invalid argument to %s: %s", Opt, Arg);
}
}
static void OptCPU (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --cpu option */
{
@@ -624,7 +645,7 @@ static void OptListing (const char* Opt, const char* Arg)
** the filename is empty or begins with the option char.
*/
if (Arg == 0 || *Arg == '\0' || *Arg == '-') {
Fatal ("The meaning of '%s' has changed. It does now "
Fatal ("The meaning of `%s' has changed. It does now "
"expect a file name as argument.", Opt);
}
@@ -658,6 +679,15 @@ static void OptMemoryModel (const char* Opt, const char* Arg)
static void OptNoUtf8 (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Handle the --no-utf8 option */
{
CP_DisableUTF8 ();
}
static void OptPageLength (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --pagelength option */
{
@@ -710,7 +740,7 @@ static void OptVersion (const char* Opt attribute ((unused)),
/* Print the assembler version */
{
fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ());
exit(EXIT_SUCCESS);
exit (EXIT_SUCCESS);
}
static void OptSeglist (const char* Opt attribute ((unused)),
@@ -734,7 +764,7 @@ static void DoPCAssign (void)
{
long PC = ConstExpression ();
if (PC < 0 || PC > 0xFFFFFF) {
Error ("Range error");
Error ("Program counter value is out of valid range");
} else {
EnterAbsoluteMode (PC);
}
@@ -778,7 +808,7 @@ static void OneLine (void)
if (CurTok.Tok == TOK_COLON) {
NextTok ();
} else if (CurTok.WS || !NoColonLabels) {
Error ("':' expected");
Error ("`:' expected");
}
}
@@ -827,11 +857,10 @@ static void OneLine (void)
NextTok ();
/* Define the symbol with the expression following the '=' */
SymDef (Sym, Expression(), ADDR_SIZE_DEFAULT, Flags);
SymDef (Sym, Expression (), ADDR_SIZE_DEFAULT, Flags);
/* Don't allow anything after a symbol definition */
ConsumeSep ();
return;
goto Done;
} else if (CurTok.Tok == TOK_SET) {
@@ -849,8 +878,7 @@ static void OneLine (void)
SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_VAR);
/* Don't allow anything after a symbol definition */
ConsumeSep ();
return;
goto Done;
} else {
@@ -860,26 +888,24 @@ static void OneLine (void)
Seg = ActiveSeg;
PC = GetPC ();
/* Define the label */
SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL);
/* Skip the colon. If NoColonLabels is enabled, allow labels
** without a colon if there is no whitespace before the
** identifier.
*/
if (CurTok.Tok != TOK_COLON) {
if (HadWS || !NoColonLabels) {
Error ("':' expected");
/* Try some smart error recovery */
if (CurTok.Tok == TOK_NAMESPACE) {
NextTok ();
}
ErrorExpect ("Expected `:' after identifier to form a label");
SkipUntilSep ();
goto Done;
}
} else {
/* Skip the colon */
NextTok ();
}
/* Define the label */
SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL);
/* If we come here, a new identifier may be waiting, which may
** be a macro or instruction.
*/
@@ -913,17 +939,23 @@ static void OneLine (void)
HandleInstruction (Instr);
} else if (PCAssignment && (CurTok.Tok == TOK_STAR || CurTok.Tok == TOK_PC)) {
NextTok ();
if (CurTok.Tok != TOK_EQ) {
Error ("'=' expected");
SkipUntilSep ();
} else {
/* Skip the equal sign */
NextTok ();
/* Enter absolute mode */
DoPCAssign ();
if (!ExpectSkip (TOK_EQ, "Expected `='")) {
goto Done;
}
/* Skip the equal sign */
NextTok ();
/* Enter absolute mode */
DoPCAssign ();
} else if ((CurTok.Tok >= TOK_FIRSTOP && CurTok.Tok <= TOK_LASTOP) ||
(CurTok.Tok >= TOK_FIRSTREG && CurTok.Tok <= TOK_LASTREG) ||
CurTok.Tok == TOK_INTCON || CurTok.Tok == TOK_CHARCON ||
CurTok.Tok == TOK_STRCON) {
ErrorExpect ("Expected a mnemonic");
SkipUntilSep ();
goto Done;
}
/* If we have defined a label, remember its size. Sym is also set by
** a symbol assignment, but in this case Done is false, so we don't
** come here.
@@ -945,6 +977,7 @@ static void OneLine (void)
}
}
Done:
/* Line separator must come here */
ConsumeSep ();
}
@@ -1017,6 +1050,7 @@ int main (int argc, char* argv [])
static const LongOpt OptTab[] = {
{ "--auto-import", 0, OptAutoImport },
{ "--bin-include-dir", 1, OptBinIncludeDir },
{ "--color", 1, OptColor },
{ "--cpu", 1, OptCPU },
{ "--create-dep", 1, OptCreateDep },
{ "--create-full-dep", 1, OptCreateFullDep },
@@ -1030,6 +1064,7 @@ int main (int argc, char* argv [])
{ "--list-bytes", 1, OptListBytes },
{ "--listing", 1, OptListing },
{ "--memory-model", 1, OptMemoryModel },
{ "--no-utf8", 0, OptNoUtf8 },
{ "--pagelength", 1, OptPageLength },
{ "--relax-checks", 0, OptRelaxChecks },
{ "--segment-list", 0, OptSeglist },
@@ -1045,6 +1080,9 @@ int main (int argc, char* argv [])
unsigned I;
/* Initialize console output */
CP_Init ();
/* Initialize the cmdline module */
InitCmdLine (&argc, &argv, "ca65");
@@ -1247,7 +1285,7 @@ int main (int argc, char* argv [])
}
if (WarningCount > 0 && WarningsAsErrors) {
Error("Warnings as errors");
Error ("Warnings as errors");
}
/* If we didn't have an errors, finish off the line infos */

View File

@@ -44,6 +44,7 @@
/* ca65 */
#include "condasm.h"
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "global.h"
#include "scanner.h"
@@ -179,7 +180,7 @@ static void FuncConcat (void)
** by the string token just created.
*/
if (CurTok.Tok != TOK_RPAREN) {
Error ("')' expected");
Error ("`)' expected");
} else {
CurTok.Tok = TOK_STRCON;
SB_Copy (&CurTok.SVal, &Buf);
@@ -253,7 +254,7 @@ static void FuncIdent (void)
SB_Copy (&Buf, &CurTok.SVal);
NextTok ();
if (CurTok.Tok != TOK_RPAREN) {
Error ("')' expected");
Error ("`)' expected");
} else {
CurTok.Tok = Id;
SB_Copy (&CurTok.SVal, &Buf);
@@ -600,7 +601,7 @@ static void FuncSPrintF (void)
** by the string token just created.
*/
if (CurTok.Tok != TOK_RPAREN) {
Error ("')' expected");
Error ("`)' expected");
} else {
CurTok.Tok = TOK_STRCON;
SB_Copy (&CurTok.SVal, &R);
@@ -660,7 +661,7 @@ static void FuncString (void)
** by the string token just created.
*/
if (CurTok.Tok != TOK_RPAREN) {
Error ("')' expected");
Error ("`)' expected");
} else {
CurTok.Tok = TOK_STRCON;
SB_Copy (&CurTok.SVal, &Buf);
@@ -725,52 +726,65 @@ void NextTok (void)
void Consume (token_t Expected, const char* ErrMsg)
/* Consume Expected, print an error if we don't find it */
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 (CurTok.Tok == Expected) {
if (Expect (Expected, ErrMsg)) {
NextTok ();
return 1;
} else {
Error ("%s", ErrMsg);
return 0;
}
}
void ConsumeSep (void)
/* Consume a separator token */
int ConsumeSep (void)
/* Consume a separator token. Return true if the token was found and false
* otherwise.
*/
{
/* We expect a separator token */
ExpectSep ();
int Found = ExpectSep ();
/* If we are at end of line, skip it */
if (CurTok.Tok == TOK_SEP) {
NextTok ();
}
return Found;
}
void ConsumeLParen (void)
/* Consume a left paren */
int ConsumeLParen (void)
/* Consume a left paren. Return true if the token was found and false
** otherwise.
*/
{
Consume (TOK_LPAREN, "'(' expected");
return Consume (TOK_LPAREN, "Expected `('");
}
void ConsumeRParen (void)
/* Consume a right paren */
int ConsumeRParen (void)
/* Consume a right paren. Return true if the token was found and false
** otherwise.
*/
{
Consume (TOK_RPAREN, "')' expected");
return Consume (TOK_RPAREN, "Expected `)'");
}
void ConsumeComma (void)
/* Consume a comma */
int ConsumeComma (void)
/* Consume a comma. Return true if the token was found and false
** otherwise.
*/
{
Consume (TOK_COMMA, "',' expected");
return Consume (TOK_COMMA, "Expected `,'");
}
@@ -785,18 +799,6 @@ void SkipUntilSep (void)
void ExpectSep (void)
/* Check if we've reached a line separator, and output an error if not. Do
** not skip the line separator.
*/
{
if (!TokIsSep (CurTok.Tok)) {
ErrorSkip ("Unexpected trailing garbage characters");
}
}
void EnterRawTokenMode (void)
/* Enter raw token mode. In raw mode, token handling functions are not
** executed, but the function tokens are passed untouched to the upper

View File

@@ -51,29 +51,34 @@
void NextTok (void);
/* Get next token and handle token level functions */
void Consume (token_t Expected, const char* ErrMsg);
/* Consume Token, print an error if we don't find it */
int Consume (token_t Expected, const char* ErrMsg);
/* Consume Token, print an error if we don't find it. Return true if the token
** was found and false otherwise.
*/
void ConsumeSep (void);
/* Consume a separator token */
int ConsumeSep (void);
/* Consume a separator token. Return true if the token was found and false
* otherwise.
*/
void ConsumeLParen (void);
/* Consume a left paren */
int ConsumeLParen (void);
/* Consume a left paren. Return true if the token was found and false
** otherwise.
*/
void ConsumeRParen (void);
/* Consume a right paren */
int ConsumeRParen (void);
/* Consume a right paren. Return true if the token was found and false
** otherwise.
*/
void ConsumeComma (void);
/* Consume a comma */
int ConsumeComma (void);
/* Consume a comma. Return true if the token was found and false
** otherwise.
*/
void SkipUntilSep (void);
/* Skip tokens until we reach a line separator or end of file */
void ExpectSep (void);
/* Check if we've reached a line separator, and output an error if not. Do
** not skip the line separator.
*/
void EnterRawTokenMode (void);
/* Enter raw token mode. In raw mode, token handling functions are not
** executed, but the function tokens are passed untouched to the upper

View File

@@ -113,7 +113,7 @@ static void ObjWriteError (void)
remove (OutFile);
/* Now abort with a fatal error */
Fatal ("Cannot write to output file '%s': %s", OutFile, strerror (Error));
Fatal ("Cannot write to output file `%s': %s", OutFile, strerror (Error));
}
@@ -170,7 +170,7 @@ void ObjOpen (void)
/* Create the output file */
F = fopen (OutFile, "w+b");
if (F == 0) {
Fatal ("Cannot open output file '%s': %s", OutFile, strerror (errno));
Fatal ("Cannot open output file `%s': %s", OutFile, strerror (errno));
}
/* Write a dummy header */

View File

@@ -60,6 +60,7 @@
#include "dbginfo.h"
#include "enum.h"
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "feature.h"
#include "filetab.h"
@@ -167,13 +168,17 @@ static void SetBoolOption (unsigned char* Flag)
switch (GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]))) {
case 0: *Flag = 0; NextTok (); break;
case 1: *Flag = 1; NextTok (); break;
default: ErrorSkip ("'on' or 'off' expected"); break;
default:
ErrorExpect ("Expected ON or OFF");
SkipUntilSep ();
break;
}
} else if (TokIsSep (CurTok.Tok)) {
/* Without anything assume switch on */
*Flag = 1;
} else {
ErrorSkip ("'on' or 'off' expected");
ErrorExpect ("Expected ON or OFF");
SkipUntilSep ();
}
}
@@ -216,8 +221,7 @@ static void ExportImport (void (*Func) (SymEntry*, unsigned char, unsigned),
while (1) {
/* We need an identifier here */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
return;
}
@@ -283,7 +287,7 @@ static void ConDes (const StrBuf* Name, unsigned Type)
Prio = ConstExpression ();
if (Prio < CD_PRIO_MIN || Prio > CD_PRIO_MAX) {
/* Value out of range */
Error ("Range error");
Error ("Given priority is out of range");
return;
}
} else {
@@ -333,7 +337,7 @@ static StrBuf* GenArrayType (StrBuf* Type, unsigned SpanSize,
static void DoA16 (void)
/* Switch the accu to 16 bit mode (assembler only) */
{
if (GetCPU() != CPU_65816) {
if (GetCPU () != CPU_65816) {
Error ("Command is only valid in 65816 mode");
} else {
/* Immidiate mode has two extension bytes */
@@ -346,7 +350,7 @@ static void DoA16 (void)
static void DoA8 (void)
/* Switch the accu to 8 bit mode (assembler only) */
{
if (GetCPU() != CPU_65816) {
if (GetCPU () != CPU_65816) {
Error ("Command is only valid in 65816 mode");
} else {
/* Immidiate mode has one extension byte */
@@ -400,7 +404,7 @@ static void DoAlign (void)
/* Read the alignment value */
Alignment = ConstExpression ();
if (Alignment <= 0 || (unsigned long) Alignment > MAX_ALIGNMENT) {
ErrorSkip ("Range error");
ErrorSkip ("Alignment is out of range");
return;
}
@@ -410,7 +414,7 @@ static void DoAlign (void)
FillVal = ConstExpression ();
/* We need a byte value here */
if (!IsByteRange (FillVal)) {
ErrorSkip ("Range error");
ErrorSkip ("Fill value is not in byte range");
return;
}
} else {
@@ -428,8 +432,7 @@ static void DoASCIIZ (void)
{
while (1) {
/* Must have a string constant */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
return;
}
@@ -463,11 +466,10 @@ static void DoAssert (void)
/* First we have the expression that has to evaluated */
ExprNode* Expr = Expression ();
ConsumeComma ();
/* Action follows */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
/* Followed by comma and action */
if (!ConsumeComma () || !Expect (TOK_IDENT, "Expected an identifier")) {
SkipUntilSep ();
return;
}
switch (GetSubKey (ActionTab, sizeof (ActionTab) / sizeof (ActionTab[0]))) {
@@ -496,9 +498,8 @@ static void DoAssert (void)
default:
Error ("Illegal assert action specifier");
/* Use lderror - there won't be an .o file anyway */
Action = ASSERT_ACT_LDERROR;
break;
SkipUntilSep ();
return;
}
NextTok ();
@@ -512,8 +513,7 @@ static void DoAssert (void)
NextTok ();
/* Read the message */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
return;
}
@@ -642,20 +642,23 @@ static void DoCharMap (void)
/* Read the index as numerical value */
Index = ConstExpression ();
if (Index < 0 || Index > 255) {
if (IsByteRange (Index)) {
/* Value out of range */
ErrorSkip ("Index range error");
ErrorSkip ("Index must be in byte range");
return;
}
/* Comma follows */
ConsumeComma ();
if (!ConsumeComma ()) {
SkipUntilSep ();
return;
}
/* Read the character code */
Code = ConstExpression ();
if (Code < 0 || Code > 255) {
if (!IsByteRange (Code)) {
/* Value out of range */
ErrorSkip ("Code range error");
ErrorSkip ("Replacement character code must be in byte range");
return;
}
@@ -685,15 +688,17 @@ static void DoConDes (void)
long Type;
/* Symbol name follows */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
return;
}
SB_Copy (&Name, &CurTok.SVal);
NextTok ();
/* Type follows. May be encoded as identifier or numerical */
ConsumeComma ();
if (!ConsumeComma ()) {
SkipUntilSep ();
goto ExitPoint;
}
if (CurTok.Tok == TOK_IDENT) {
/* Map the following keyword to a number, then skip it */
@@ -702,7 +707,8 @@ static void DoConDes (void)
/* Check if we got a valid keyword */
if (Type < 0) {
ErrorSkip ("Syntax error");
ErrorExpect ("Expected CONSTRUCTOR, DESTRUCTOR or INTERRUPTOR");
SkipUntilSep ();
goto ExitPoint;
}
@@ -712,7 +718,7 @@ static void DoConDes (void)
Type = ConstExpression ();
if (Type < CD_TYPE_MIN || Type > CD_TYPE_MAX) {
/* Value out of range */
ErrorSkip ("Range error");
ErrorSkip ("Numeric condes type is out of range");
goto ExitPoint;
}
@@ -734,8 +740,7 @@ static void DoConstructor (void)
StrBuf Name = STATIC_STRBUF_INITIALIZER;
/* Symbol name follows */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
return;
}
SB_Copy (&Name, &CurTok.SVal);
@@ -771,8 +776,7 @@ static void DoDbg (void)
/* We expect a subkey */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
return;
}
@@ -788,7 +792,10 @@ static void DoDbg (void)
case 1: DbgInfoFunc (); break;
case 2: DbgInfoLine (); break;
case 3: DbgInfoSym (); break;
default: ErrorSkip ("Syntax error"); break;
default:
ErrorExpect ("Expected FILE, FUNC, LINE or SYM");
SkipUntilSep ();
break;
}
}
@@ -853,9 +860,7 @@ static void DoDelMac (void)
/* Delete a classic macro */
{
/* We expect an identifier */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
} else {
if (ExpectSkip (TOK_IDENT, "Expected an identifier")) {
MacUndef (&CurTok.SVal, MAC_STYLE_CLASSIC);
NextTok ();
}
@@ -869,8 +874,7 @@ static void DoDestructor (void)
StrBuf Name = STATIC_STRBUF_INITIALIZER;
/* Symbol name follows */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
return;
}
SB_Copy (&Name, &CurTok.SVal);
@@ -938,9 +942,7 @@ static void DoEndScope (void)
static void DoError (void)
/* User error */
{
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
Error ("User error: %m%p", &CurTok.SVal);
SkipUntilSep ();
}
@@ -1010,9 +1012,7 @@ static void DoFarAddr (void)
static void DoFatal (void)
/* Fatal user error */
{
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
Fatal ("User error: %m%p", &CurTok.SVal);
SkipUntilSep ();
}
@@ -1030,22 +1030,22 @@ static void DoFeature (void)
while (1) {
/* We expect an identifier */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
return;
}
/* Make the string attribute lower case */
LocaseSVal ();
Feature = FindFeature(&CurTok.SVal);
Feature = FindFeature (&CurTok.SVal);
if (Feature == FEAT_UNKNOWN) {
/* Not found */
ErrorSkip ("Invalid feature: '%m%p'", &CurTok.SVal);
ErrorSkip ("Invalid feature: `%m%p'", &CurTok.SVal);
return;
}
if (Feature == FEAT_ADDRSIZE) {
Warning (1, "Deprecated feature: '.feature addrsize'. Pseudo function .addrsize is always available.");
Warning (1, "Deprecated feature `addrsize'");
Notification ("Pseudo function `.addrsize' is always available");
}
NextTok ();
@@ -1053,7 +1053,7 @@ static void DoFeature (void)
/* Optional +/- or ON/OFF */
On = 1;
if (CurTok.Tok != TOK_COMMA && !TokIsSep (CurTok.Tok)) {
SetBoolOption(&On);
SetBoolOption (&On);
}
/* Apply feature setting. */
@@ -1087,19 +1087,17 @@ static void DoFileOpt (void)
OptNum = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
if (OptNum < 0) {
/* Not found */
ErrorSkip ("File option keyword expected");
ErrorExpect ("Expected a file option keyword");
SkipUntilSep ();
return;
}
/* Skip the keyword */
NextTok ();
/* Must be followed by a comma */
ConsumeComma ();
/* We accept only string options for now */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
/* Must be followed by a comma and a string option */
if (!ConsumeComma () || !Expect (TOK_STRCON, "Expected a string constant")) {
SkipUntilSep ();
return;
}
@@ -1134,16 +1132,13 @@ static void DoFileOpt (void)
/* Option given as number */
OptNum = ConstExpression ();
if (!IsByteRange (OptNum)) {
ErrorSkip ("Range error");
ErrorSkip ("Option number must be in byte range");
return;
}
/* Must be followed by a comma */
ConsumeComma ();
/* We accept only string options for now */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
/* Must be followed by a comma plus a string constant */
if (!ConsumeComma () || !Expect (TOK_STRCON, "Expected a string constant")) {
SkipUntilSep ();
return;
}
@@ -1198,7 +1193,7 @@ static void DoHiBytes (void)
static void DoI16 (void)
/* Switch the index registers to 16 bit mode (assembler only) */
{
if (GetCPU() != CPU_65816) {
if (GetCPU () != CPU_65816) {
Error ("Command is only valid in 65816 mode");
} else {
/* Immidiate mode has two extension bytes */
@@ -1211,7 +1206,7 @@ static void DoI16 (void)
static void DoI8 (void)
/* Switch the index registers to 16 bit mode (assembler only) */
{
if (GetCPU() != CPU_65816) {
if (GetCPU () != CPU_65816) {
Error ("Command is only valid in 65816 mode");
} else {
/* Immidiate mode has one extension byte */
@@ -1248,8 +1243,7 @@ static void DoIncBin (void)
FILE* F;
/* Name must follow */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
if (!ExpectSkip (TOK_STRCON, "Expected a string constant")) {
return;
}
SB_Copy (&Name, &CurTok.SVal);
@@ -1277,7 +1271,7 @@ static void DoIncBin (void)
char* PathName = SearchFile (BinSearchPath, SB_GetConstBuf (&Name));
if (PathName == 0 || (F = fopen (PathName, "rb")) == 0) {
/* Not found or cannot open, print an error and bail out */
ErrorSkip ("Cannot open include file '%m%p': %s", &Name, strerror (errno));
ErrorSkip ("Cannot open include file `%m%p': %s", &Name, strerror (errno));
xfree (PathName);
goto ExitPoint;
}
@@ -1303,7 +1297,7 @@ static void DoIncBin (void)
*/
SB_Terminate (&Name);
if (FileStat (SB_GetConstBuf (&Name), &StatBuf) != 0) {
Fatal ("Cannot stat input file '%m%p': %s", &Name, strerror (errno));
Fatal ("Cannot stat input file `%m%p': %s", &Name, strerror (errno));
}
/* Add the file to the input file table */
@@ -1314,13 +1308,16 @@ static void DoIncBin (void)
Count = Size - Start;
if (Count < 0) {
/* Nothing to read - flag this as a range error */
ErrorSkip ("Range error");
ErrorSkip ("Start offset is larger than file size");
goto Done;
}
} else {
/* Count was given, check if it is valid */
if (Start + Count > Size) {
ErrorSkip ("Range error");
if (Start > Size) {
ErrorSkip ("Start offset is larger than file size");
goto Done;
} else if (Start + Count > Size) {
ErrorSkip ("Not enough bytes left in file at offset %ld", Start);
goto Done;
}
}
@@ -1340,7 +1337,7 @@ static void DoIncBin (void)
size_t BytesRead = fread (Buf, 1, BytesToRead, F);
if (BytesToRead != BytesRead) {
/* Some sort of error */
ErrorSkip ("Cannot read from include file '%m%p': %s",
ErrorSkip ("Cannot read from include file `%m%p': %s",
&Name, strerror (errno));
break;
}
@@ -1367,9 +1364,7 @@ static void DoInclude (void)
/* Include another file */
{
/* Name must follow */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
SB_Terminate (&CurTok.SVal);
if (NewInputFile (SB_GetConstBuf (&CurTok.SVal)) == 0) {
/* Error opening the file, skip remainder of line */
@@ -1386,8 +1381,7 @@ static void DoInterruptor (void)
StrBuf Name = STATIC_STRBUF_INITIALIZER;
/* Symbol name follows */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
return;
}
SB_Copy (&Name, &CurTok.SVal);
@@ -1474,9 +1468,7 @@ static void DoListBytes (void)
static void DoLocalChar (void)
/* Define the character that starts local labels */
{
if (CurTok.Tok != TOK_CHARCON) {
ErrorSkip ("Character constant expected");
} else {
if (ExpectSkip (TOK_CHARCON, "Expected a character constant")) {
if (CurTok.IVal != '@' && CurTok.IVal != '?') {
Error ("Invalid start character for locals");
} else {
@@ -1492,15 +1484,14 @@ static void DoMacPack (void)
/* Insert a macro package */
{
/* We expect an identifier */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
} else {
SB_AppendStr (&CurTok.SVal, ".mac");
SB_Terminate (&CurTok.SVal);
if (NewInputFile (SB_GetConstBuf (&CurTok.SVal)) == 0) {
/* Error opening the file, skip remainder of line */
SkipUntilSep ();
}
if (!ExpectSkip (TOK_IDENT, "Expected an identifier")) {
return;
}
SB_AppendStr (&CurTok.SVal, ".mac");
SB_Terminate (&CurTok.SVal);
if (NewInputFile (SB_GetConstBuf (&CurTok.SVal)) == 0) {
/* Error opening the file, skip remainder of line */
SkipUntilSep ();
}
}
@@ -1538,12 +1529,10 @@ static void DoOrg (void)
static void DoOut (void)
/* Output a string */
{
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
/* Output the string and be sure to flush the output to keep it in
** sync with any error messages if the output is redirected to a file.
*/
* sync with any error messages if the output is redirected to a file.
*/
printf ("%.*s\n",
(int) SB_GetLen (&CurTok.SVal),
SB_GetConstBuf (&CurTok.SVal));
@@ -1835,7 +1824,7 @@ static void DoRes (void)
Count = ConstExpression ();
if (Count > 0xFFFF || Count < 0) {
ErrorSkip ("Range error");
ErrorSkip ("Invalid number of bytes specified");
return;
}
if (CurTok.Tok == TOK_COMMA) {
@@ -1843,7 +1832,7 @@ static void DoRes (void)
Val = ConstExpression ();
/* We need a byte value here */
if (!IsByteRange (Val)) {
ErrorSkip ("Range error");
ErrorSkip ("Fill value is not in byte range");
return;
}
@@ -1903,12 +1892,10 @@ static void DoScope (void)
static void DoSegment (void)
/* Switch to another segment */
{
StrBuf Name = STATIC_STRBUF_INITIALIZER;
SegDef Def;
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
SegDef Def;
StrBuf Name = AUTO_STRBUF_INITIALIZER;
/* Save the name of the segment and skip it */
SB_Copy (&Name, &CurTok.SVal);
@@ -1923,10 +1910,10 @@ static void DoSegment (void)
/* Set the segment */
UseSeg (&Def);
}
/* Free memory for Name */
SB_Done (&Name);
/* Free memory for Name */
SB_Done (&Name);
}
}
@@ -1935,9 +1922,7 @@ static void DoSetCPU (void)
/* Switch the CPU instruction set */
{
/* We expect an identifier */
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
cpu_t CPU;
/* Try to find the CPU */
@@ -1948,8 +1933,8 @@ static void DoSetCPU (void)
SetCPU (CPU);
/* Skip the identifier. If the CPU switch was successful, the scanner
** will treat the input now correctly for the new CPU.
*/
* will treat the input now correctly for the new CPU.
*/
NextTok ();
}
}
@@ -2024,9 +2009,7 @@ static void DoUnDef (void)
EnableDefineStyleMacros ();
/* We expect an identifier */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
} else {
if (ExpectSkip (TOK_IDENT, "Expected an identifier")) {
MacUndef (&CurTok.SVal, MAC_STYLE_DEFINE);
NextTok ();
}
@@ -2037,7 +2020,7 @@ static void DoUnDef (void)
static void DoUnexpected (void)
/* Got an unexpected keyword */
{
Error ("Unexpected '%m%p'", &Keyword);
Error ("Unexpected `%m%p'", &Keyword);
SkipUntilSep ();
}
@@ -2046,9 +2029,7 @@ static void DoUnexpected (void)
static void DoWarning (void)
/* User warning */
{
if (CurTok.Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
if (ExpectSkip (TOK_STRCON, "Expected a string constant")) {
Warning (0, "User warning: %m%p", &CurTok.SVal);
SkipUntilSep ();
}
@@ -2255,7 +2236,7 @@ static CtrlDesc CtrlCmdTab [] = {
{ ccNone, DoUnexpected }, /* .REF, .REFERENCED */
{ ccNone, DoReferTo }, /* .REFTO, .REFERTO */
{ ccNone, DoReloc }, /* .RELOC */
{ ccNone, DoRepeat }, /* .REPEAT */
{ ccKeepToken, DoRepeat }, /* .REPEAT */
{ ccNone, DoRes }, /* .RES */
{ ccNone, DoInvalid }, /* .RIGHT */
{ ccNone, DoROData }, /* .RODATA */

View File

@@ -40,6 +40,7 @@
/* ca65 */
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "nexttok.h"
#include "toklist.h"
@@ -53,7 +54,7 @@
static TokList* CollectRepeatTokens (void)
static TokList* CollectRepeatTokens (const FilePos* StartPos)
/* Collect all tokens inside the .REPEAT body in a token list and return
** this list. In case of errors, NULL is returned.
*/
@@ -67,7 +68,8 @@ static TokList* CollectRepeatTokens (void)
/* Check for end of input */
if (CurTok.Tok == TOK_EOF) {
Error ("Unexpected end of file");
ErrorExpect ("Expected `.ENDREPEAT'");
PNotification (StartPos, "For this `.REPEAT' command");
FreeTokList (List);
return 0;
}
@@ -117,10 +119,14 @@ void ParseRepeat (void)
char* Name;
TokList* List;
/* Remember the position of the .REPEAT token, then skip it */
FilePos StartPos = CurTok.Pos;
NextTok ();
/* Repeat count follows */
long RepCount = ConstExpression ();
if (RepCount < 0) {
Error ("Range error");
Error ("Repeat count must be positive or zero");
RepCount = 0;
}
@@ -132,9 +138,7 @@ void ParseRepeat (void)
NextTok ();
/* Check for an identifier */
if (CurTok.Tok != TOK_IDENT) {
ErrorSkip ("Identifier expected");
} else {
if (ExpectSkip (TOK_IDENT, "Expected an identifier")) {
/* Remember the name and skip it */
SB_Terminate (&CurTok.SVal);
Name = xstrdup (SB_GetConstBuf (&CurTok.SVal));
@@ -147,7 +151,7 @@ void ParseRepeat (void)
ConsumeSep ();
/* Read the token list */
List = CollectRepeatTokens ();
List = CollectRepeatTokens (&StartPos);
/* If we had an error, bail out */
if (List == 0) {

View File

@@ -52,6 +52,7 @@
/* ca65 */
#include "condasm.h"
#include "error.h"
#include "expect.h"
#include "filetab.h"
#include "global.h"
#include "incpath.h"
@@ -545,7 +546,7 @@ int NewInputFile (const char* Name)
/* Main file */
F = fopen (Name, "r");
if (F == 0) {
Fatal ("Cannot open input file '%s': %s", Name, strerror (errno));
Fatal ("Cannot open input file `%s': %s", Name, strerror (errno));
}
} else {
/* We are on include level. Search for the file in the include
@@ -554,7 +555,7 @@ int NewInputFile (const char* Name)
PathName = SearchFile (IncSearchPath, Name);
if (PathName == 0 || (F = fopen (PathName, "r")) == 0) {
/* Not found or cannot open, print an error and bail out */
Error ("Cannot open include file '%s': %s", Name, strerror (errno));
Error ("Cannot open include file `%s': %s", Name, strerror (errno));
goto ExitPoint;
}
@@ -571,7 +572,7 @@ int NewInputFile (const char* Name)
** here.
*/
if (FileStat (Name, &Buf) != 0) {
Fatal ("Cannot stat input file '%s': %s", Name, strerror (errno));
Fatal ("Cannot stat input file `%s': %s", Name, strerror (errno));
}
/* Add the file to the input file table and remember the index */
@@ -818,7 +819,7 @@ static void ReadStringConst (int StringTerm)
int Cooked = 1;
NeedNext = 1;
if (StringTerm == 0 && SB_GetLen(&CurTok.SVal) == 1) {
if (StringTerm == 0 && SB_GetLen (&CurTok.SVal) == 1) {
if (C == '\'') {
break;
}
@@ -901,12 +902,12 @@ static void ReadStringConst (int StringTerm)
case '7':
{ /* brace needed for scoping */
int Count = 1;
int Final = DigitVal(C);
int Final = DigitVal (C);
Cooked = 0;
NextChar ();
while (IsODigit (C) && Count++ < 3) {
Final = (Final << 3) | DigitVal(C);
NextChar();
Final = (Final << 3) | DigitVal (C);
NextChar ();
}
if (C >= 256)
Error ("Octal character constant out of range");
@@ -1196,7 +1197,7 @@ Again:
/* Not found */
if (!LeadingDotInIdents) {
/* Invalid pseudo instruction */
Error ("'%m%p' is not a recognized control command", &CurTok.SVal);
Error ("`%m%p' is not a recognized control command", &CurTok.SVal);
goto Again;
}
@@ -1587,8 +1588,8 @@ CharAgain:
/* Always a character constant
** Hack: Pass 0 to ReadStringConst for special handling.
*/
ReadStringConst(0);
if (SB_GetLen(&CurTok.SVal) != 1) {
ReadStringConst (0);
if (SB_GetLen (&CurTok.SVal) != 1) {
Error ("Illegal character constant");
goto CharAgain;
}
@@ -1686,14 +1687,14 @@ unsigned char ParseAddrSize (void)
/* Check for an identifier */
if (CurTok.Tok != TOK_IDENT) {
Error ("Address size specifier expected");
ErrorExpect ("Expected an address size specifier");
return ADDR_SIZE_DEFAULT;
}
/* Convert the attribute */
AddrSize = AddrSizeFromStr (SB_GetConstBuf (&CurTok.SVal));
if (AddrSize == ADDR_SIZE_INVALID) {
Error ("Address size specifier expected");
ErrorExpect ("Expected an address size specifier");
AddrSize = ADDR_SIZE_DEFAULT;
}

View File

@@ -134,7 +134,7 @@ static Segment* NewSegment (const char* Name, unsigned char AddrSize)
/* Check the segment name for invalid names */
if (!ValidSegName (Name)) {
Error ("Illegal segment name: '%s'", Name);
Error ("Illegal segment name: `%s'", Name);
}
/* Create a new segment and return it */

View File

@@ -41,7 +41,6 @@
/* common */
#include "coll.h"
#include "fragdefs.h"
#include "inline.h"
/* ca65 */
#include "fragment.h"
@@ -102,35 +101,23 @@ void ListSegments (FILE* destination);
void UseSeg (const SegDef* D);
/* Use the given segment */
#if defined(HAVE_INLINE)
INLINE const SegDef* GetCurrentSegDef (void)
static inline const SegDef* GetCurrentSegDef (void)
/* Get a pointer to the segment defininition of the current segment */
{
return ActiveSeg->Def;
}
#else
# define GetCurrentSegDef() (ActiveSeg->Def)
#endif
#if defined(HAVE_INLINE)
INLINE unsigned GetCurrentSegNum (void)
static inline unsigned GetCurrentSegNum (void)
/* Get the number of the current segment */
{
return ActiveSeg->Num;
}
#else
# define GetCurrentSegNum() (ActiveSeg->Num)
#endif
#if defined(HAVE_INLINE)
INLINE unsigned char GetCurrentSegAddrSize (void)
static inline unsigned char GetCurrentSegAddrSize (void)
/* Get the address size of the current segment */
{
return ActiveSeg->Def->AddrSize;
}
#else
# define GetCurrentSegAddrSize() (ActiveSeg->Def->AddrSize)
#endif
void SegAlign (unsigned long Alignment, int FillVal);
/* Align the PC segment to Alignment. If FillVal is -1, emit fill fragments

View File

@@ -42,7 +42,6 @@
#include "coll.h"
#include "gentype.h"
#include "hashtab.h"
#include "inline.h"
#include "strbuf.h"
@@ -75,15 +74,11 @@ struct Span{
#if defined(HAVE_INLINE)
INLINE unsigned long GetSpanSize (const Span* R)
static inline unsigned long GetSpanSize (const Span* R)
/* Return the span size in bytes */
{
return (R->End - R->Start);
}
#else
# define GetSpanSize(R) ((R)->End - (R)->Start)
#endif
void SetSpanType (Span* S, const StrBuf* Type);
/* Set the generic type of the span to Type */

View File

@@ -63,45 +63,29 @@ extern StringPool* StrPool;
#if defined(HAVE_INLINE)
INLINE unsigned GetStrBufId (const StrBuf* S)
static inline unsigned GetStrBufId (const StrBuf* S)
/* Return the id of the given string buffer */
{
return SP_Add (StrPool, S);
}
#else
# define GetStrBufId(S) SP_Add (StrPool, (S))
#endif
#if defined(HAVE_INLINE)
INLINE unsigned GetStringId (const char* S)
static inline unsigned GetStringId (const char* S)
/* Return the id of the given string */
{
return SP_AddStr (StrPool, S);
}
#else
# define GetStringId(S) SP_AddStr (StrPool, (S))
#endif
#if defined(HAVE_INLINE)
INLINE const StrBuf* GetStrBuf (unsigned Index)
static inline const StrBuf* GetStrBuf (unsigned Index)
/* Convert a string index into a string */
{
return SP_Get (StrPool, Index);
}
#else
# define GetStrBuf(Index) SP_Get (StrPool, (Index))
#endif
#if defined(HAVE_INLINE)
INLINE const char* GetString (unsigned Index)
static inline const char* GetString (unsigned Index)
/* Convert a string index into a string */
{
return SB_GetConstBuf (SP_Get (StrPool, Index));
}
#else
# define GetString(Index) SB_GetConstBuf (SP_Get (StrPool, (Index)))
#endif
void WriteStrPool (void);
/* Write the string pool to the object file */

View File

@@ -39,6 +39,7 @@
/* ca65 */
#include "condasm.h"
#include "error.h"
#include "expect.h"
#include "expr.h"
#include "macro.h"
#include "nexttok.h"
@@ -105,14 +106,21 @@ static long DoStructInternal (long Offs, unsigned Type)
** union, the struct may be anonymous; in which case, no new lexical level
** is started.
*/
int Anon = (CurTok.Tok != TOK_IDENT);
int Anon = (CurTok.Tok == TOK_SEP);
if (!Anon) {
/* Enter a new scope, then skip the name */
SymEnterLevel (&CurTok.SVal, SCOPE_STRUCT, ADDR_SIZE_ABS, 0);
NextTok ();
/* Start at zero offset in the new scope */
Offs = 0;
/* Non anonymous structs must have an identifier as name */
if (Expect (TOK_IDENT, "Expected a struct/union name")) {
/* Enter a new scope, then skip the name */
SymEnterLevel (&CurTok.SVal, SCOPE_STRUCT, ADDR_SIZE_ABS, 0);
NextTok ();
/* Start at zero offset in the new scope */
Offs = 0;
} else {
/* Skip the junk on the line before proceeding */
SkipUntilSep ();
Anon = 1;
}
}
/* Test for end of line */
@@ -183,7 +191,7 @@ static long DoStructInternal (long Offs, unsigned Type)
case TOK_RES:
NextTok ();
if (CurTok.Tok == TOK_SEP) {
ErrorSkip ("Size is missing");
ErrorExpect ("Expected a byte count");
} else {
MemberSize = Member (1);
}
@@ -192,7 +200,7 @@ static long DoStructInternal (long Offs, unsigned Type)
case TOK_ORG:
NextTok ();
if (CurTok.Tok == TOK_SEP) {
ErrorSkip ("Address is missing");
ErrorExpect ("Expected an address");
} else {
Offs = ConstExpression ();
@@ -233,7 +241,12 @@ static long DoStructInternal (long Offs, unsigned Type)
default:
if (!CheckConditionals ()) {
/* Not a conditional directive */
ErrorSkip ("Invalid storage allocator in struct/union");
if (Sym) {
ErrorExpect ("Expected a storage allocator after the field name");
} else {
ErrorExpect ("Expected a storage allocator");
}
SkipUntilSep ();
}
}
@@ -275,9 +288,9 @@ static long DoStructInternal (long Offs, unsigned Type)
/* End of struct/union definition */
if (Type == STRUCT) {
Consume (TOK_ENDSTRUCT, "'.ENDSTRUCT' expected");
Consume (TOK_ENDSTRUCT, "Expected `.ENDSTRUCT'");
} else {
Consume (TOK_ENDUNION, "'.ENDUNION' expected");
Consume (TOK_ENDUNION, "Expected `.ENDUNION'");
}
/* Return the size of the struct */

View File

@@ -593,7 +593,7 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D)
if (SymHasUserMark (Sym)) {
LIError (&Sym->DefLines,
"Circular reference in definition of symbol '%m%p'",
"Circular reference in definition of symbol `%m%p'",
GetSymName (Sym));
ED_SetError (D);
} else {
@@ -1359,8 +1359,7 @@ static void StudyNearAddr (ExprNode* Expr, ExprDesc* D)
}
/* Promote to absolute if smaller. */
if (D->AddrSize < ADDR_SIZE_ABS)
{
if (D->AddrSize < ADDR_SIZE_ABS) {
D->AddrSize = ADDR_SIZE_ABS;
}
}

View File

@@ -40,6 +40,7 @@
/* ca65 */
#include "error.h"
#include "expect.h"
#include "nexttok.h"
#include "scanner.h"
#include "symbol.h"
@@ -73,7 +74,7 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
/* Start from the root scope */
Scope = RootScope;
} else if (CurTok.Tok == TOK_IDENT) {
} else if (Expect (TOK_IDENT, "Expected an identifier")) {
/* Remember the name and skip it */
SB_Copy (Name, &CurTok.SVal);
@@ -95,7 +96,7 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
if (Scope == 0) {
/* Scope not found */
SB_Terminate (FullName);
Error ("No such scope: '%m%p'", FullName);
Error ("No such scope: `%m%p'", FullName);
return 0;
}
@@ -115,8 +116,7 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
while (1) {
/* Next token must be an identifier. */
if (CurTok.Tok != TOK_IDENT) {
Error ("Identifier expected");
if (!Expect (TOK_IDENT, "Expected an identifier")) {
return 0;
}
@@ -139,7 +139,7 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
Scope = SymFindScope (Scope, Name, SYM_FIND_EXISTING);
if (Scope == 0) {
/* Scope not found */
Error ("No such scope: '%m%p'", FullName);
Error ("No such scope: `%m%p'", FullName);
return 0;
}

View File

@@ -215,24 +215,32 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags
if (S->Flags & SF_IMPORT) {
/* Defined symbol is marked as imported external symbol */
Error ("Symbol '%m%p' is already an import", GetSymName (S));
Error ("Symbol `%m%p' is already an import", GetSymName (S));
if (CollCount (&S->DefLines) > 0) {
PNotification (GetSourcePos (CollAt(&S->DefLines, 0)),
"The symbol was previously imported here");
}
return;
}
if ((Flags & SF_VAR) != 0 && (S->Flags & (SF_EXPORT | SF_GLOBAL))) {
/* Variable symbols cannot be exports or globals */
Error ("Var symbol '%m%p' cannot be an export or global symbol", GetSymName (S));
Error ("Var symbol `%m%p' cannot be an export or global symbol", GetSymName (S));
return;
}
if (S->Flags & SF_DEFINED) {
/* Multiple definition. In case of a variable, this is legal. */
if ((S->Flags & SF_VAR) == 0) {
Error ("Symbol '%m%p' is already defined", GetSymName (S));
Error ("Symbol `%m%p' is already defined", GetSymName (S));
if (CollCount (&S->DefLines) > 0) {
PNotification (GetSourcePos (CollAt(&S->DefLines, 0)),
"The symbol was previously defined here");
}
S->Flags |= SF_MULTDEF;
return;
} else {
/* Redefinition must also be a variable symbol */
if ((Flags & SF_VAR) == 0) {
Error ("Symbol '%m%p' is already different kind", GetSymName (S));
Error ("Symbol `%m%p' is already different kind", GetSymName (S));
return;
}
/* Delete the current symbol expression, since it will get
@@ -288,7 +296,7 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags
S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) {
/* We're exporting a symbol smaller than it actually is */
Warning (1, "Symbol '%m%p' is %s but exported %s",
Warning (1, "Symbol `%m%p' is %s but exported %s",
GetSymName (S), AddrSizeToStr (S->AddrSize),
AddrSizeToStr (S->ExportSize));
}
@@ -320,13 +328,13 @@ void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
/* Mark the given symbol as an imported symbol */
{
if (S->Flags & SF_DEFINED) {
Error ("Symbol '%m%p' is already defined", GetSymName (S));
Error ("Symbol `%m%p' is already defined", GetSymName (S));
S->Flags |= SF_MULTDEF;
return;
}
if (S->Flags & SF_EXPORT) {
/* The symbol is already marked as exported symbol */
Error ("Cannot import exported symbol '%m%p'", GetSymName (S));
Error ("Cannot import exported symbol `%m%p'", GetSymName (S));
return;
}
@@ -342,16 +350,16 @@ void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
*/
if (S->Flags & SF_IMPORT) {
if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED)) {
Error ("Redeclaration mismatch for symbol '%m%p'", GetSymName (S));
Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
}
if (AddrSize != S->AddrSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
}
if (S->Flags & SF_GLOBAL) {
S->Flags &= ~SF_GLOBAL;
if (AddrSize != S->AddrSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
}
@@ -374,12 +382,12 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
/* Check if it's ok to export the symbol */
if (S->Flags & SF_IMPORT) {
/* The symbol is already 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));
return;
}
if (S->Flags & SF_VAR) {
/* Variable symbols cannot be exported */
Error ("Var symbol '%m%p' cannot be exported", GetSymName (S));
Error ("Var symbol `%m%p' cannot be exported", GetSymName (S));
return;
}
@@ -388,7 +396,7 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
*/
if (S->Flags & SF_GLOBAL) {
if (AddrSize != S->ExportSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
S->Flags &= ~SF_GLOBAL;
@@ -403,7 +411,7 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
*/
if ((S->Flags & (SF_EXPORT|SF_DEFINED)) == SF_EXPORT) {
if (S->ExportSize != AddrSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
}
S->ExportSize = AddrSize;
@@ -417,7 +425,7 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) {
/* We're exporting a symbol smaller than it actually is */
Warning (1, "Symbol '%m%p' is %s but exported %s",
Warning (1, "Symbol `%m%p' is %s but exported %s",
GetSymName (S), AddrSizeToStr (S->AddrSize),
AddrSizeToStr (S->ExportSize));
}
@@ -439,7 +447,7 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
{
if (S->Flags & SF_VAR) {
/* Variable symbols cannot be exported or imported */
Error ("Var symbol '%m%p' cannot be made global", GetSymName (S));
Error ("Var symbol `%m%p' cannot be made global", GetSymName (S));
return;
}
@@ -452,7 +460,7 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
AddrSize = GetCurrentSegAddrSize ();
}
if (AddrSize != S->AddrSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
return;
}
@@ -464,12 +472,12 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
if ((S->Flags & SF_DEFINED) == 0) {
/* Symbol is undefined */
if (AddrSize != S->ExportSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
} else if (AddrSize != ADDR_SIZE_DEFAULT) {
/* Symbol is defined and address size given */
if (AddrSize != S->ExportSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
}
return;
@@ -481,7 +489,7 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
*/
if (S->Flags & SF_GLOBAL) {
if (AddrSize != S->ExportSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
return;
}
@@ -499,7 +507,7 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) {
/* We're exporting a symbol smaller than it actually is */
Warning (1, "Symbol '%m%p' is %s but exported %s",
Warning (1, "Symbol `%m%p' is %s but exported %s",
GetSymName (S), AddrSizeToStr (S->AddrSize),
AddrSizeToStr (S->ExportSize));
}
@@ -542,12 +550,12 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri
/* Check for errors */
if (S->Flags & SF_IMPORT) {
/* The symbol is already 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));
return;
}
if (S->Flags & SF_VAR) {
/* Variable symbols cannot be exported or imported */
Error ("Var symbol '%m%p' cannot be exported", GetSymName (S));
Error ("Var symbol `%m%p' cannot be exported", GetSymName (S));
return;
}
@@ -559,7 +567,7 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri
/* Use the real size of the symbol */
AddrSize = S->AddrSize;
} else if (S->AddrSize != AddrSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
}
@@ -569,7 +577,7 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri
*/
if (S->Flags & (SF_EXPORT | SF_GLOBAL)) {
if (S->ExportSize != AddrSize) {
Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
S->Flags &= ~SF_GLOBAL;
}
@@ -580,7 +588,7 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri
*/
if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
if (S->ConDesPrio[Type] != Prio) {
Error ("Redeclaration mismatch for symbol '%m%p'", GetSymName (S));
Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
}
}
S->ConDesPrio[Type] = Prio;

View File

@@ -42,7 +42,6 @@
#include "cddefs.h"
#include "coll.h"
#include "filepos.h"
#include "inline.h"
#include "strbuf.h"
/* ca65 */
@@ -137,25 +136,17 @@ int SymSearchTree (SymEntry* T, const StrBuf* Name, SymEntry** E);
** inserted on the right side.
*/
#if defined(HAVE_INLINE)
INLINE void SymAddExprRef (SymEntry* Sym, struct ExprNode* Expr)
static inline void SymAddExprRef (SymEntry* Sym, struct ExprNode* Expr)
/* Add an expression reference to this symbol */
{
CollAppend (&Sym->ExprRefs, Expr);
}
#else
#define SymAddExprRef(Sym,Expr) CollAppend (&(Sym)->ExprRefs, Expr)
#endif
#if defined(HAVE_INLINE)
INLINE void SymDelExprRef (SymEntry* Sym, struct ExprNode* Expr)
static inline void SymDelExprRef (SymEntry* Sym, struct ExprNode* Expr)
/* Delete an expression reference to this symbol */
{
CollDeleteItem (&Sym->ExprRefs, Expr);
}
#else
#define SymDelExprRef(Sym,Expr) CollDeleteItem (&(Sym)->ExprRefs, Expr)
#endif
void SymTransferExprRefs (SymEntry* From, SymEntry* To);
/* Transfer all expression references from one symbol to another. */
@@ -199,107 +190,71 @@ void SymImportFromGlobal (SymEntry* S);
** into an import.
*/
#if defined(HAVE_INLINE)
INLINE int SymIsDef (const SymEntry* S)
static inline int SymIsDef (const SymEntry* S)
/* Return true if the given symbol is already defined */
{
return (S->Flags & SF_DEFINED) != 0;
}
#else
# define SymIsDef(S) (((S)->Flags & SF_DEFINED) != 0)
#endif
#if defined(HAVE_INLINE)
INLINE int SymIsRef (const SymEntry* S)
static inline int SymIsRef (const SymEntry* S)
/* Return true if the given symbol has been referenced */
{
return (S->Flags & SF_REFERENCED) != 0;
}
#else
# define SymIsRef(S) (((S)->Flags & SF_REFERENCED) != 0)
#endif
#if defined(HAVE_INLINE)
INLINE int SymIsImport (const SymEntry* S)
static inline int SymIsImport (const SymEntry* S)
/* Return true if the given symbol is marked as import */
{
/* Check the import flag */
return (S->Flags & SF_IMPORT) != 0;
}
#else
# define SymIsImport(S) (((S)->Flags & SF_IMPORT) != 0)
#endif
#if defined(HAVE_INLINE)
INLINE int SymIsExport (const SymEntry* S)
static inline int SymIsExport (const SymEntry* S)
/* Return true if the given symbol is marked as export */
{
/* Check the export flag */
return (S->Flags & SF_EXPORT) != 0;
}
#else
# define SymIsExport(S) (((S)->Flags & SF_EXPORT) != 0)
#endif
#if defined(HAVE_INLINE)
INLINE int SymIsVar (const SymEntry* S)
static inline int SymIsVar (const SymEntry* S)
/* Return true if the given symbol is marked as variable */
{
/* Check the variable flag */
return (S->Flags & SF_VAR) != 0;
}
#else
# define SymIsVar(S) (((S)->Flags & SF_VAR) != 0)
#endif
int SymIsConst (const SymEntry* Sym, long* Val);
/* Return true if the given symbol has a constant value. If Val is not NULL
** and the symbol has a constant value, store it's value there.
*/
#if defined(HAVE_INLINE)
INLINE int SymHasExpr (const SymEntry* S)
static inline int SymHasExpr (const SymEntry* S)
/* Return true if the given symbol has an associated expression */
{
/* Check the expression */
return ((S->Flags & (SF_DEFINED|SF_IMPORT)) == SF_DEFINED);
}
#else
# define SymHasExpr(S) (((S)->Flags & (SF_DEFINED|SF_IMPORT)) == SF_DEFINED)
#endif
#if defined(HAVE_INLINE)
INLINE void SymMarkUser (SymEntry* S)
static inline void SymMarkUser (SymEntry* S)
/* Set a user mark on the specified symbol */
{
/* Set the bit */
S->Flags |= SF_USER;
}
#else
# define SymMarkUser(S) ((S)->Flags |= SF_USER)
#endif
#if defined(HAVE_INLINE)
INLINE void SymUnmarkUser (SymEntry* S)
static inline void SymUnmarkUser (SymEntry* S)
/* Remove a user mark from the specified symbol */
{
/* Reset the bit */
S->Flags &= ~SF_USER;
}
#else
# define SymUnmarkUser(S) ((S)->Flags &= ~SF_USER)
#endif
#if defined(HAVE_INLINE)
INLINE int SymHasUserMark (SymEntry* S)
static inline int SymHasUserMark (SymEntry* S)
/* Return the state of the user mark for the specified symbol */
{
/* Check the bit */
return (S->Flags & SF_USER) != 0;
}
#else
# define SymHasUserMark(S) (((S)->Flags & SF_USER) != 0)
#endif
struct SymTable* GetSymParentScope (SymEntry* S);
/* Get the parent scope of the symbol (not the one it is defined in). Return
@@ -314,27 +269,19 @@ const struct ExprNode* SymResolve (const SymEntry* Sym);
** NULL. Do not call in other contexts!
*/
#if defined(HAVE_INLINE)
INLINE const StrBuf* GetSymName (const SymEntry* S)
static inline const StrBuf* GetSymName (const SymEntry* S)
/* Return the name of the symbol */
{
return GetStrBuf (S->Name);
}
#else
# define GetSymName(S) GetStrBuf ((S)->Name)
#endif
#if defined(HAVE_INLINE)
INLINE unsigned char GetSymAddrSize (const SymEntry* S)
static inline unsigned char GetSymAddrSize (const SymEntry* S)
/* Return the address size of the symbol. Beware: This function will just
** return the AddrSize member, it will not look at the expression!
*/
{
return S->AddrSize;
}
#else
# define GetSymAddrSize(S) ((S)->AddrSize)
#endif
long GetSymVal (SymEntry* Sym);
/* Return the value of a symbol assuming it's constant. FAIL will be called

View File

@@ -178,7 +178,7 @@ static SymTable* NewSymTable (SymTable* Parent, const StrBuf* Name)
}
} else {
/* Duplicate scope name */
Internal ("Duplicate scope name: '%m%p'", Name);
Internal ("Duplicate scope name: `%m%p'", Name);
}
}
}
@@ -216,7 +216,7 @@ void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type,
/* Check if the scope has been defined before */
if (CurrentScope->Flags & ST_DEFINED) {
Error ("Duplicate scope '%m%p'", ScopeName);
Error ("Duplicate scope `%m%p'", ScopeName);
}
} else {
@@ -502,7 +502,7 @@ static void SymCheckUndefined (SymEntry* S)
if (Sym->Flags & SF_IMPORT) {
/* The symbol is already marked as import */
LIError (&S->RefLines,
"Symbol '%s' is already an import",
"Symbol `%s' is already an import",
GetString (Sym->Name));
}
if ((Sym->Flags & SF_EXPORT) == 0) {
@@ -516,7 +516,7 @@ static void SymCheckUndefined (SymEntry* S)
if (Sym->AddrSize > Sym->ExportSize) {
/* We're exporting a symbol smaller than it actually is */
LIWarning (&Sym->DefLines, 1,
"Symbol '%m%p' is %s but exported %s",
"Symbol `%m%p' is %s but exported %s",
GetSymName (Sym),
AddrSizeToStr (Sym->AddrSize),
AddrSizeToStr (Sym->ExportSize));
@@ -541,7 +541,7 @@ static void SymCheckUndefined (SymEntry* S)
if (S->Flags & SF_EXPORT) {
/* We will not auto-import an export */
LIError (&S->RefLines,
"Exported symbol '%m%p' was never defined",
"Exported symbol `%m%p' was never defined",
GetSymName (S));
} else {
if (AutoImport) {
@@ -554,7 +554,7 @@ static void SymCheckUndefined (SymEntry* S)
} else {
/* Error */
LIError (&S->RefLines,
"Symbol '%m%p' is undefined",
"Symbol `%m%p' is undefined",
GetSymName (S));
}
}
@@ -573,13 +573,13 @@ void SymCheck (void)
if (CurrentScope->Label) {
/* proc has a label indicating the line it was opened. */
LIError (&CurrentScope->Label->DefLines,
"Local proc '%s' was not closed",
"Local proc `%s' was not closed",
GetString (CurrentScope->Name));
} else {
/* scope has no label to track a line number, uses end-of-document line instead.
** Anonymous scopes will reveal their internal automatic name.
*/
Error ("Local scope '%s' was not closed",
Error ("Local scope `%s' was not closed",
GetString (CurrentScope->Name));
}
}
@@ -627,7 +627,7 @@ void SymCheck (void)
ReleaseFullLineInfo (&S->RefLines);
} else if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
LIWarning (&S->DefLines, 2,
"Symbol '%m%p' is defined but never used",
"Symbol `%m%p' is defined but never used",
GetSymName (S));
}
@@ -636,7 +636,7 @@ void SymCheck (void)
if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) {
/* Imported symbol is not referenced */
LIWarning (&S->DefLines, 2,
"Symbol '%m%p' is imported but never used",
"Symbol `%m%p' is imported but never used",
GetSymName (S));
} else {
/* Give the import an id, count imports */
@@ -664,7 +664,7 @@ void SymCheck (void)
} else if (S->AddrSize > S->ExportSize) {
/* We're exporting a symbol smaller than it actually is */
LIWarning (&S->DefLines, 1,
"Symbol '%m%p' is %s but exported %s",
"Symbol `%m%p' is %s but exported %s",
GetSymName (S),
AddrSizeToStr (S->AddrSize),
AddrSizeToStr (S->ExportSize));
@@ -684,7 +684,7 @@ void SymCheck (void)
const FilePos* P = S->GuessedUse[S->AddrSize - 1];
if (P) {
PWarning (P, 0,
"Didn't use %s addressing for '%m%p'",
"Didn't use %s addressing for `%m%p'",
AddrSizeToStr (S->AddrSize),
GetSymName (S));
}

View File

@@ -42,7 +42,6 @@
/* common */
#include "exprdefs.h"
#include "inline.h"
/* ca65 */
#include "symentry.h"
@@ -135,25 +134,17 @@ SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name);
** scope.
*/
#if defined(HAVE_INLINE)
INLINE unsigned char GetSymTabType (const SymTable* S)
static inline unsigned char GetSymTabType (const SymTable* S)
/* Return the type of the given symbol table */
{
return S->Type;
}
#else
# define GetSymTabType(S) ((S)->Type)
#endif
#if defined(HAVE_INLINE)
INLINE int SymTabIsClosed (const SymTable* S)
static inline int SymTabIsClosed (const SymTable* S)
/* Return true if the symbol table has been closed */
{
return (S->Flags & ST_CLOSED) != 0;
}
#else
# define SymTabIsClosed(S) (((S)->Flags & ST_CLOSED) != 0)
#endif
void SymCheck (void);
/* Run through all symbols and check for anomalies and errors */

View File

@@ -33,30 +33,261 @@
#include <stdio.h>
/* ca65 */
#include "token.h"
/*****************************************************************************/
/* Code */
/* Data */
/*****************************************************************************/
int TokHasSVal (token_t Tok)
/* Return true if the given token has an attached SVal */
{
return (Tok == TOK_IDENT || Tok == TOK_LOCAL_IDENT || Tok == TOK_STRCON);
}
/* Use a struct so we can extend it if required */
typedef struct TokDescEntry TokDescEntry;
struct TokDescEntry {
const char* Desc;
};
static const TokDescEntry TokDesc[] = {
{ "none", },
{ "end-of-file", },
{ "end-of-line", },
{ "{s}", },
{ "{s}", },
{ "{i}", },
{ "'{c}'", },
{ "\"{s}\"", },
{ "A", },
{ "Q", },
{ "S", },
{ "X", },
{ "Y", },
{ "Z", },
{ "R{i}", },
{ ":=", },
{ "unnamed label", },
{ "=", },
{ "<>", },
{ "<", },
{ ">", },
{ "<=", },
{ ">=", },
{ ".AND", },
{ ".OR", },
{ ".XOR", },
{ ".NOT", },
{ "+", },
{ "-", },
{ "*", },
{ "/", },
{ "!", },
{ "|", },
{ "^", },
{ "&", },
{ "<<", },
{ ">>", },
{ "~", },
{ "$", },
{ "::", },
{ ".", },
{ ",", },
{ "#", },
{ ":", },
{ "(", },
{ ")", },
{ "[", },
{ "]", },
{ "{", },
{ "}", },
{ "@", },
{ "z:", },
{ "a:", },
{ "f:", },
{ "macro parameter", },
{ "repeat counter", },
{ ".A16" },
{ ".A8" },
{ ".ADDR" },
{ ".ADDRSIZE" },
{ ".ALIGN" },
{ ".ASCIIZ" },
{ ".ASIZE" },
{ ".ASSERT" },
{ ".AUTOIMPORT" },
{ ".BANK" },
{ ".BANKBYTE" },
{ ".BANKBYTES" },
{ ".BLANK" },
{ ".BSS" },
{ ".BYTE" },
{ ".CAP" },
{ ".CASE" },
{ ".CHARMAP" },
{ ".CODE" },
{ ".CONCAT" },
{ ".CONDES" },
{ ".CONST" },
{ ".CONSTRUCTOR" },
{ ".CPU" },
{ ".DATA" },
{ ".DBG" },
{ ".DBYT" },
{ ".DEBUGINFO" },
{ ".DEFINE" },
{ ".DEFINED" },
{ ".DEFINEDMACRO" },
{ ".DELMAC" },
{ ".DESTRUCTOR" },
{ ".DWORD" },
{ ".ELSE" },
{ ".ELSEIF" },
{ ".END" },
{ ".ENDENUM" },
{ ".ENDIF" },
{ ".ENDMACRO" },
{ ".ENDPROC" },
{ ".ENDREP" },
{ ".ENDSCOPE" },
{ ".ENDSTRUCT" },
{ ".ENDUNION" },
{ ".ENUM" },
{ ".ERROR" },
{ ".EXITMACRO" },
{ ".EXPORT" },
{ ".EXPORTZP" },
{ ".FARADDR" },
{ ".FATAL" },
{ ".FEATURE" },
{ ".FILEOPT" },
{ ".FORCEIMPORT" },
{ ".FORCEWORD" },
{ ".GLOBAL" },
{ ".GLOBALZP" },
{ ".HIBYTE" },
{ ".HIBYTES" },
{ ".HIWORD" },
{ ".I16" },
{ ".I8" },
{ ".MAKEIDENT" },
{ ".IF" },
{ ".IFBLANK" },
{ ".IFCONST" },
{ ".IFDEF" },
{ ".IFNBLANK" },
{ ".IFNCONST" },
{ ".IFNDEF" },
{ ".IFNREF" },
{ ".IFP02" },
{ ".IFP02X" },
{ ".IFP4510" },
{ ".IFP45GS02" },
{ ".IFP6280" },
{ ".IFP816" },
{ ".IFPC02" },
{ ".IFPCE02" },
{ ".IFPDTV" },
{ ".IFPM740" },
{ ".IFPSC02" },
{ ".IFPSWEET16" },
{ ".IFPWC02" },
{ ".IFREF" },
{ ".IMPORT" },
{ ".IMPORTZP" },
{ ".INCBIN" },
{ ".INCLUDE" },
{ ".INTERRUPTOR" },
{ ".ISIZE" },
{ ".ISMNEMONIC" },
{ ".LEFT" },
{ ".LINECONT" },
{ ".LIST" },
{ ".LISTBYTES" },
{ ".LITERAL" },
{ ".LOBYTE" },
{ ".LOBYTES" },
{ ".LOCAL" },
{ ".LOCALCHAR" },
{ ".LOWORD" },
{ ".MACPACK" },
{ ".MACRO" },
{ ".MATCH" },
{ ".MAX" },
{ ".MID" },
{ ".MIN" },
{ ".NULL" },
{ ".ORG" },
{ ".OUT" },
{ ".P02" },
{ ".P02X" },
{ ".P4510" },
{ ".P45GS02" },
{ ".P6280" },
{ ".P816" },
{ ".PAGELENGTH" },
{ ".PARAMCOUNT" },
{ ".PC02" },
{ ".PCE02" },
{ ".PDTV" },
{ ".PM740" },
{ ".POPCHARMAP" },
{ ".POPCPU" },
{ ".POPSEG" },
{ ".PROC" },
{ ".PSC02" },
{ ".PSWEET16" },
{ ".PUSHCHARMAP" },
{ ".PUSHCPU" },
{ ".PUSHSEG" },
{ ".PWC02" },
{ ".REFERENCED" },
{ ".REFERTO" },
{ ".RELOC" },
{ ".REPEAT" },
{ ".RES" },
{ ".RIGHT" },
{ ".RODATA" },
{ ".SCOPE" },
{ ".SEGMENT" },
{ ".SET" },
{ ".SETCPU" },
{ ".SIZEOF" },
{ ".SMART" },
{ ".SPRINTF" },
{ ".STRAT" },
{ ".STRING" },
{ ".STRLEN" },
{ ".STRUCT" },
{ ".TAG" },
{ ".TCOUNT" },
{ ".TIME" },
{ ".UNDEF" },
{ ".UNION" },
{ ".VERSION" },
{ ".WARNING" },
{ ".WORD" },
{ ".XMATCH" },
{ ".ZEROPAGE" },
};
int TokHasIVal (token_t Tok)
/* Return true if the given token has an attached IVal */
{
return (Tok == TOK_INTCON || Tok == TOK_CHARCON || Tok == TOK_REG);
}
/*****************************************************************************/
/* Code */
/*****************************************************************************/
@@ -72,3 +303,54 @@ void CopyToken (Token* Dst, const Token* Src)
SB_Copy (&Dst->SVal, &Src->SVal);
Dst->Pos = Src->Pos;
}
StrBuf* TokenDesc (const Token* T, StrBuf* S)
/* Place a textual description of the given token into S. */
{
PRECONDITION (sizeof (TokDesc) / sizeof (TokDesc[0]) == TOK_COUNT);
/* Clear the target buffer */
SB_Clear (S);
/* Get the description for the token */
const char* Desc = TokDesc[T->Tok].Desc;
/* Repeatedly replace {c}, {i} and {s} */
size_t Start = 0;
while (1) {
const char* P = strchr (Desc + Start, '{');
if (P) {
/* Check if this is really {c}, {i} or {s} */
if ((P[1] != 'c' &&
P[1] != 'i' &&
P[1] != 's') ||
P[2] != '}') {
++Start;
continue;
}
/* Append the text before the replacement token */
SB_AppendBuf (S, Desc + Start, P - (Desc + Start));
Start += P - (Desc + Start) + 3;
/* Append the replacement text */
if (P[1] == 'c') {
SB_AppendChar (S, (char)T->IVal);
} else if (P[1] == 'i') {
char Buf[64];
snprintf (Buf, sizeof (Buf), "%ld", T->IVal);
SB_AppendStr (S, Buf);
} else {
SB_Append (S, &T->SVal);
}
} else {
/* No more replacements found, append remainder */
SB_AppendStr (S, Desc + Start);
break;
}
}
/* Zero-terminate the buffer and return it */
SB_Terminate (S);
return S;
}

View File

@@ -40,7 +40,6 @@
/* common */
#include "filepos.h"
#include "inline.h"
#include "strbuf.h"
@@ -53,76 +52,80 @@
/* Tokens */
typedef enum token_t {
TOK_NONE, /* Start value, invalid */
TOK_EOF, /* End of input file */
TOK_SEP, /* Separator (usually newline) */
TOK_IDENT, /* An identifier */
TOK_LOCAL_IDENT, /* A cheap local identifier */
TOK_NONE, /* Start value, invalid */
TOK_EOF, /* End of input file */
TOK_SEP, /* Separator (usually newline) */
TOK_IDENT, /* An identifier */
TOK_LOCAL_IDENT, /* A cheap local identifier */
TOK_INTCON, /* Integer constant */
TOK_CHARCON, /* Character constant */
TOK_STRCON, /* String constant */
TOK_INTCON, /* Integer constant */
TOK_CHARCON, /* Character constant */
TOK_STRCON, /* String constant */
TOK_A, /* A)ccumulator */
TOK_X, /* X register */
TOK_Y, /* Y register */
TOK_Z, /* Z register */
TOK_S, /* S register */
TOK_Q, /* Q pseudo register */
TOK_REG, /* Sweet16 R.. register (in sweet16 mode) */
TOK_FIRSTREG, /* First register name token */
TOK_A = TOK_FIRSTREG, /* A)ccumulator */
TOK_Q, /* Q pseudo register */
TOK_S, /* S register */
TOK_X, /* X register */
TOK_Y, /* Y register */
TOK_Z, /* Z register */
TOK_REG, /* Sweet16 R.. register (in sweet16 mode) */
TOK_LASTREG = TOK_REG, /* Last register name token */
TOK_ASSIGN, /* := */
TOK_ULABEL, /* An unnamed label */
TOK_ASSIGN, /* := */
TOK_ULABEL, /* An unnamed label */
TOK_EQ, /* = */
TOK_NE, /* <> */
TOK_LT, /* < */
TOK_GT, /* > */
TOK_LE, /* <= */
TOK_GE, /* >= */
TOK_FIRSTOP, /* First operator token */
TOK_EQ = TOK_FIRSTOP, /* = */
TOK_NE, /* <> */
TOK_LT, /* < */
TOK_GT, /* > */
TOK_LE, /* <= */
TOK_GE, /* >= */
TOK_BOOLAND, /* .and */
TOK_BOOLOR, /* .or */
TOK_BOOLXOR, /* .xor */
TOK_BOOLNOT, /* .not */
TOK_BOOLAND, /* .and */
TOK_BOOLOR, /* .or */
TOK_BOOLXOR, /* .xor */
TOK_BOOLNOT, /* .not */
TOK_PLUS, /* + */
TOK_MINUS, /* - */
TOK_MUL, /* * */
TOK_STAR = TOK_MUL, /* Alias */
TOK_DIV, /* / */
TOK_MOD, /* ! */
TOK_OR, /* | */
TOK_XOR, /* ^ */
TOK_AND, /* & */
TOK_SHL, /* << */
TOK_SHR, /* >> */
TOK_NOT, /* ~ */
TOK_PLUS, /* + */
TOK_MINUS, /* - */
TOK_MUL, /* * */
TOK_STAR = TOK_MUL, /* Alias */
TOK_DIV, /* / */
TOK_MOD, /* ! */
TOK_OR, /* | */
TOK_XOR, /* ^ */
TOK_AND, /* & */
TOK_SHL, /* << */
TOK_SHR, /* >> */
TOK_NOT, /* ~ */
TOK_LASTOP = TOK_NOT, /* Last operator token */
TOK_PC, /* $ if enabled */
TOK_NAMESPACE, /* :: */
TOK_DOT, /* . */
TOK_COMMA, /* , */
TOK_HASH, /* # */
TOK_COLON, /* : */
TOK_LPAREN, /* ( */
TOK_RPAREN, /* ) */
TOK_LBRACK, /* [ */
TOK_RBRACK, /* ] */
TOK_LCURLY, /* { */
TOK_RCURLY, /* } */
TOK_AT, /* @ - in Sweet16 mode */
TOK_PC, /* $ if enabled */
TOK_NAMESPACE, /* :: */
TOK_DOT, /* . */
TOK_COMMA, /* , */
TOK_HASH, /* # */
TOK_COLON, /* : */
TOK_LPAREN, /* ( */
TOK_RPAREN, /* ) */
TOK_LBRACK, /* [ */
TOK_RBRACK, /* ] */
TOK_LCURLY, /* { */
TOK_RCURLY, /* } */
TOK_AT, /* @ - in Sweet16 mode */
TOK_OVERRIDE_ZP, /* z: */
TOK_OVERRIDE_ABS, /* a: */
TOK_OVERRIDE_FAR, /* f: */
TOK_OVERRIDE_ZP, /* z: */
TOK_OVERRIDE_ABS, /* a: */
TOK_OVERRIDE_FAR, /* f: */
TOK_MACPARAM, /* Macro parameter, not generated by scanner */
TOK_REPCOUNTER, /* Repeat counter, not generated by scanner */
TOK_MACPARAM, /* Macro parameter, not generated by scanner */
TOK_REPCOUNTER, /* Repeat counter, not generated by scanner */
/* The next ones are tokens for the pseudo instructions. Keep together! */
TOK_FIRSTPSEUDO,
TOK_A16 = TOK_FIRSTPSEUDO,
TOK_A16 = TOK_FIRSTPSEUDO,
TOK_A8,
TOK_ADDR,
TOK_ADDRSIZE,
@@ -284,9 +287,9 @@ typedef enum token_t {
TOK_WORD,
TOK_XMATCH,
TOK_ZEROPAGE,
TOK_LASTPSEUDO = TOK_ZEROPAGE,
TOK_LASTPSEUDO = TOK_ZEROPAGE,
TOK_COUNT /* Count of tokens */
TOK_COUNT /* Count of tokens */
} token_t;
@@ -318,27 +321,42 @@ 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 */
int TokHasIVal (token_t Tok);
/* Return true if the given token has an attached IVal */
{
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
#if defined(HAVE_INLINE)
INLINE int TokIsSep (enum token_t T)
INLINE int TokHasIVal (token_t Tok)
/* Return true if the given token has an attached IVal */
{
return (Tok == TOK_INTCON || Tok == TOK_CHARCON || Tok == TOK_REG);
}
#else
# define TokHasIVal(T) \
((T) == TOK_INTCON || (T) == TOK_CHARCON || (T) == TOK_REG)
#endif
static inline int TokIsSep (enum token_t T)
/* Return true if this is a separator token */
{
return (T == TOK_SEP || T == TOK_EOF);
}
#else
# define TokIsSep(T) ((T) == TOK_SEP || (T) == TOK_EOF)
#endif
void CopyToken (Token* Dst, const Token* Src);
/* Copy a token. The current value of Dst.SVal is free'd, so Dst must be
** initialized.
*/
StrBuf* TokenDesc (const Token* T, StrBuf* S);
/* Place a textual description of the given token into S. */
/* End of token.h */

View File

@@ -111,7 +111,7 @@ ExprNode* ULabRef (int Which)
if (Which == 0) {
Error ("Invalid unnamed label reference");
/* We must return something valid */
return GenCurrentPC();
return GenCurrentPC ();
}
/* Get the index of the referenced label */
@@ -125,7 +125,7 @@ ExprNode* ULabRef (int Which)
/* Label does not exist */
Error ("Undefined label");
/* We must return something valid */
return GenCurrentPC();
return GenCurrentPC ();
}
/* Check if the label exists. If not, generate enough forward labels. */