Merge branch 'master' into macexpand
This commit is contained in:
@@ -57,7 +57,7 @@ ifdef QUIET
|
||||
PQ = "QUIET=1"
|
||||
PD = --no-print-directory
|
||||
ifndef CMD_EXE
|
||||
CATERR = 2> ../wrk/common/$$@.errlog || (cat ../wrk/common/$$@.errlog && false)
|
||||
CATERR = 2> $@.errlog || (cat $@.errlog && false)
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@
|
||||
<ClInclude Include="ca65\easw16.h" />
|
||||
<ClInclude Include="ca65\enum.h" />
|
||||
<ClInclude Include="ca65\error.h" />
|
||||
<ClInclude Include="ca65\expect.h" />
|
||||
<ClInclude Include="ca65\expr.h" />
|
||||
<ClInclude Include="ca65\feature.h" />
|
||||
<ClInclude Include="ca65\filetab.h" />
|
||||
@@ -132,6 +133,7 @@
|
||||
<ClCompile Include="ca65\easw16.c" />
|
||||
<ClCompile Include="ca65\enum.c" />
|
||||
<ClCompile Include="ca65\error.c" />
|
||||
<ClCompile Include="ca65\expect.c" />
|
||||
<ClCompile Include="ca65\expr.c" />
|
||||
<ClCompile Include="ca65\feature.c" />
|
||||
<ClCompile Include="ca65\filetab.c" />
|
||||
@@ -168,4 +170,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
222
src/ca65/error.c
222
src/ca65/error.c
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
116
src/ca65/expect.c
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,12 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* inline.h */
|
||||
/* expect.h */
|
||||
/* */
|
||||
/* Definitions to use the inline compiler feature */
|
||||
/* Print errors about expected tokens */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2001-2005 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 2025, Kugelfuhr */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@@ -33,24 +30,54 @@
|
||||
|
||||
|
||||
|
||||
#ifndef INLINE_H
|
||||
#define INLINE_H
|
||||
#ifndef EXPECT_H
|
||||
#define EXPECT_H
|
||||
|
||||
|
||||
|
||||
/* ca65 */
|
||||
#include "token.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Defines */
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#if defined(__GNUC__) && !defined(DISABLE_INLINE)
|
||||
# define HAVE_INLINE 1
|
||||
# define INLINE static __inline__
|
||||
#endif
|
||||
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 inline.h */
|
||||
/* End of expect.h */
|
||||
|
||||
#endif
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,7 +304,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));
|
||||
}
|
||||
|
||||
124
src/ca65/macro.c
124
src/ca65/macro.c
@@ -45,6 +45,7 @@
|
||||
/* ca65 */
|
||||
#include "condasm.h"
|
||||
#include "error.h"
|
||||
#include "expect.h"
|
||||
#include "global.h"
|
||||
#include "instr.h"
|
||||
#include "istack.h"
|
||||
@@ -104,10 +105,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 */
|
||||
@@ -235,7 +238,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 */
|
||||
@@ -250,11 +253,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);
|
||||
@@ -368,19 +374,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 ();
|
||||
@@ -392,48 +407,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 ();
|
||||
@@ -443,7 +459,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;
|
||||
@@ -455,7 +471,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);
|
||||
|
||||
@@ -467,7 +483,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;
|
||||
@@ -517,7 +534,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 {
|
||||
@@ -537,8 +557,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;
|
||||
}
|
||||
|
||||
@@ -557,7 +578,10 @@ void MacDef (unsigned Style)
|
||||
}
|
||||
|
||||
/* We need end of line after the locals */
|
||||
ConsumeSep ();
|
||||
if (!ExpectSep ()) {
|
||||
M->HasError = 1;
|
||||
}
|
||||
NextTok ();
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -595,7 +619,7 @@ void MacDef (unsigned Style)
|
||||
/* Save if last token was a separator to know if .endmacro is at
|
||||
** the start of a line
|
||||
*/
|
||||
LastTokWasSep = TokIsSep(CurTok.Tok);
|
||||
LastTokWasSep = TokIsSep (CurTok.Tok);
|
||||
|
||||
/* Read the next token */
|
||||
NextTok ();
|
||||
@@ -626,11 +650,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;
|
||||
}
|
||||
|
||||
@@ -846,7 +871,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;
|
||||
}
|
||||
|
||||
@@ -860,7 +889,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;
|
||||
}
|
||||
@@ -971,10 +1000,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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1005,9 +1032,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;
|
||||
}
|
||||
|
||||
@@ -1015,7 +1054,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
@@ -126,12 +129,14 @@ 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"
|
||||
" --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);
|
||||
}
|
||||
|
||||
|
||||
@@ -738,7 +768,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);
|
||||
}
|
||||
@@ -783,7 +813,7 @@ static void OneLine (void)
|
||||
if (CurTok.Tok == TOK_COLON) {
|
||||
NextTok ();
|
||||
} else if (CurTok.WS || !NoColonLabels) {
|
||||
Error ("':' expected");
|
||||
Error ("`:' expected");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -832,11 +862,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) {
|
||||
|
||||
@@ -854,8 +883,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 {
|
||||
|
||||
@@ -865,26 +893,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.
|
||||
*/
|
||||
@@ -918,17 +944,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.
|
||||
@@ -950,6 +982,7 @@ static void OneLine (void)
|
||||
}
|
||||
}
|
||||
|
||||
Done:
|
||||
/* Line separator must come here */
|
||||
ConsumeSep ();
|
||||
}
|
||||
@@ -1023,6 +1056,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 },
|
||||
@@ -1037,6 +1071,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 },
|
||||
{ "--smart", 0, OptSmart },
|
||||
@@ -1051,6 +1086,9 @@ int main (int argc, char* argv [])
|
||||
|
||||
unsigned I;
|
||||
|
||||
/* Initialize console output */
|
||||
CP_Init ();
|
||||
|
||||
/* Initialize the cmdline module */
|
||||
InitCmdLine (&argc, &argv, "ca65");
|
||||
|
||||
@@ -1253,7 +1291,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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
/* ca65 */
|
||||
#include "condasm.h"
|
||||
#include "error.h"
|
||||
#include "expect.h"
|
||||
#include "filetab.h"
|
||||
#include "global.h"
|
||||
#include "incpath.h"
|
||||
@@ -556,7 +557,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
|
||||
@@ -565,7 +566,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;
|
||||
}
|
||||
|
||||
@@ -582,7 +583,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 */
|
||||
@@ -829,7 +830,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;
|
||||
}
|
||||
@@ -912,12 +913,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");
|
||||
@@ -1207,7 +1208,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;
|
||||
}
|
||||
|
||||
@@ -1598,8 +1599,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;
|
||||
}
|
||||
@@ -1697,14 +1698,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
/* common */
|
||||
#include "coll.h"
|
||||
#include "fragdefs.h"
|
||||
#include "inline.h"
|
||||
|
||||
/* ca65 */
|
||||
#include "fragment.h"
|
||||
@@ -99,35 +98,23 @@ Fragment* GenFragment (unsigned char Type, unsigned short Len);
|
||||
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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
304
src/ca65/token.c
304
src/ca65/token.c
@@ -33,30 +33,261 @@
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* ca65 */
|
||||
#include "token.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
int TokHasSVal (token_t Tok)
|
||||
/* Return true if the given token has an attached SVal */
|
||||
{
|
||||
return (Tok == TOK_IDENT || Tok == TOK_LOCAL_IDENT || Tok == TOK_STRCON);
|
||||
}
|
||||
/* Use a struct so we can extend it if required */
|
||||
typedef struct TokDescEntry TokDescEntry;
|
||||
struct TokDescEntry {
|
||||
const char* Desc;
|
||||
};
|
||||
|
||||
static const TokDescEntry TokDesc[] = {
|
||||
{ "none", },
|
||||
{ "end-of-file", },
|
||||
{ "end-of-line", },
|
||||
{ "{s}", },
|
||||
{ "{s}", },
|
||||
|
||||
{ "{i}", },
|
||||
{ "'{c}'", },
|
||||
{ "\"{s}\"", },
|
||||
|
||||
{ "A", },
|
||||
{ "Q", },
|
||||
{ "S", },
|
||||
{ "X", },
|
||||
{ "Y", },
|
||||
{ "Z", },
|
||||
{ "R{i}", },
|
||||
|
||||
{ ":=", },
|
||||
{ "unnamed label", },
|
||||
|
||||
{ "=", },
|
||||
{ "<>", },
|
||||
{ "<", },
|
||||
{ ">", },
|
||||
{ "<=", },
|
||||
{ ">=", },
|
||||
|
||||
{ ".AND", },
|
||||
{ ".OR", },
|
||||
{ ".XOR", },
|
||||
{ ".NOT", },
|
||||
|
||||
{ "+", },
|
||||
{ "-", },
|
||||
{ "*", },
|
||||
{ "/", },
|
||||
{ "!", },
|
||||
{ "|", },
|
||||
{ "^", },
|
||||
{ "&", },
|
||||
{ "<<", },
|
||||
{ ">>", },
|
||||
{ "~", },
|
||||
|
||||
{ "$", },
|
||||
{ "::", },
|
||||
{ ".", },
|
||||
{ ",", },
|
||||
{ "#", },
|
||||
{ ":", },
|
||||
{ "(", },
|
||||
{ ")", },
|
||||
{ "[", },
|
||||
{ "]", },
|
||||
{ "{", },
|
||||
{ "}", },
|
||||
{ "@", },
|
||||
|
||||
{ "z:", },
|
||||
{ "a:", },
|
||||
{ "f:", },
|
||||
|
||||
{ "macro parameter", },
|
||||
{ "repeat counter", },
|
||||
|
||||
{ ".A16" },
|
||||
{ ".A8" },
|
||||
{ ".ADDR" },
|
||||
{ ".ADDRSIZE" },
|
||||
{ ".ALIGN" },
|
||||
{ ".ASCIIZ" },
|
||||
{ ".ASIZE" },
|
||||
{ ".ASSERT" },
|
||||
{ ".AUTOIMPORT" },
|
||||
{ ".BANK" },
|
||||
{ ".BANKBYTE" },
|
||||
{ ".BANKBYTES" },
|
||||
{ ".BLANK" },
|
||||
{ ".BSS" },
|
||||
{ ".BYTE" },
|
||||
{ ".CAP" },
|
||||
{ ".CASE" },
|
||||
{ ".CHARMAP" },
|
||||
{ ".CODE" },
|
||||
{ ".CONCAT" },
|
||||
{ ".CONDES" },
|
||||
{ ".CONST" },
|
||||
{ ".CONSTRUCTOR" },
|
||||
{ ".CPU" },
|
||||
{ ".DATA" },
|
||||
{ ".DBG" },
|
||||
{ ".DBYT" },
|
||||
{ ".DEBUGINFO" },
|
||||
{ ".DEFINE" },
|
||||
{ ".DEFINED" },
|
||||
{ ".DEFINEDMACRO" },
|
||||
{ ".DELMAC" },
|
||||
{ ".DESTRUCTOR" },
|
||||
{ ".DWORD" },
|
||||
{ ".ELSE" },
|
||||
{ ".ELSEIF" },
|
||||
{ ".END" },
|
||||
{ ".ENDENUM" },
|
||||
{ ".ENDIF" },
|
||||
{ ".ENDMACRO" },
|
||||
{ ".ENDPROC" },
|
||||
{ ".ENDREP" },
|
||||
{ ".ENDSCOPE" },
|
||||
{ ".ENDSTRUCT" },
|
||||
{ ".ENDUNION" },
|
||||
{ ".ENUM" },
|
||||
{ ".ERROR" },
|
||||
{ ".EXITMACRO" },
|
||||
{ ".EXPORT" },
|
||||
{ ".EXPORTZP" },
|
||||
{ ".FARADDR" },
|
||||
{ ".FATAL" },
|
||||
{ ".FEATURE" },
|
||||
{ ".FILEOPT" },
|
||||
{ ".FORCEIMPORT" },
|
||||
{ ".FORCEWORD" },
|
||||
{ ".GLOBAL" },
|
||||
{ ".GLOBALZP" },
|
||||
{ ".HIBYTE" },
|
||||
{ ".HIBYTES" },
|
||||
{ ".HIWORD" },
|
||||
{ ".I16" },
|
||||
{ ".I8" },
|
||||
{ ".MAKEIDENT" },
|
||||
{ ".IF" },
|
||||
{ ".IFBLANK" },
|
||||
{ ".IFCONST" },
|
||||
{ ".IFDEF" },
|
||||
{ ".IFNBLANK" },
|
||||
{ ".IFNCONST" },
|
||||
{ ".IFNDEF" },
|
||||
{ ".IFNREF" },
|
||||
{ ".IFP02" },
|
||||
{ ".IFP02X" },
|
||||
{ ".IFP4510" },
|
||||
{ ".IFP45GS02" },
|
||||
{ ".IFP6280" },
|
||||
{ ".IFP816" },
|
||||
{ ".IFPC02" },
|
||||
{ ".IFPCE02" },
|
||||
{ ".IFPDTV" },
|
||||
{ ".IFPM740" },
|
||||
{ ".IFPSC02" },
|
||||
{ ".IFPSWEET16" },
|
||||
{ ".IFPWC02" },
|
||||
{ ".IFREF" },
|
||||
{ ".IMPORT" },
|
||||
{ ".IMPORTZP" },
|
||||
{ ".INCBIN" },
|
||||
{ ".INCLUDE" },
|
||||
{ ".INTERRUPTOR" },
|
||||
{ ".ISIZE" },
|
||||
{ ".ISMNEMONIC" },
|
||||
{ ".LEFT" },
|
||||
{ ".LINECONT" },
|
||||
{ ".LIST" },
|
||||
{ ".LISTBYTES" },
|
||||
{ ".LITERAL" },
|
||||
{ ".LOBYTE" },
|
||||
{ ".LOBYTES" },
|
||||
{ ".LOCAL" },
|
||||
{ ".LOCALCHAR" },
|
||||
{ ".LOWORD" },
|
||||
{ ".MACPACK" },
|
||||
{ ".MACRO" },
|
||||
{ ".MATCH" },
|
||||
{ ".MAX" },
|
||||
{ ".MID" },
|
||||
{ ".MIN" },
|
||||
{ ".NULL" },
|
||||
{ ".ORG" },
|
||||
{ ".OUT" },
|
||||
{ ".P02" },
|
||||
{ ".P02X" },
|
||||
{ ".P4510" },
|
||||
{ ".P45GS02" },
|
||||
{ ".P6280" },
|
||||
{ ".P816" },
|
||||
{ ".PAGELENGTH" },
|
||||
{ ".PARAMCOUNT" },
|
||||
{ ".PC02" },
|
||||
{ ".PCE02" },
|
||||
{ ".PDTV" },
|
||||
{ ".PM740" },
|
||||
{ ".POPCHARMAP" },
|
||||
{ ".POPCPU" },
|
||||
{ ".POPSEG" },
|
||||
{ ".PROC" },
|
||||
{ ".PSC02" },
|
||||
{ ".PSWEET16" },
|
||||
{ ".PUSHCHARMAP" },
|
||||
{ ".PUSHCPU" },
|
||||
{ ".PUSHSEG" },
|
||||
{ ".PWC02" },
|
||||
{ ".REFERENCED" },
|
||||
{ ".REFERTO" },
|
||||
{ ".RELOC" },
|
||||
{ ".REPEAT" },
|
||||
{ ".RES" },
|
||||
{ ".RIGHT" },
|
||||
{ ".RODATA" },
|
||||
{ ".SCOPE" },
|
||||
{ ".SEGMENT" },
|
||||
{ ".SET" },
|
||||
{ ".SETCPU" },
|
||||
{ ".SIZEOF" },
|
||||
{ ".SMART" },
|
||||
{ ".SPRINTF" },
|
||||
{ ".STRAT" },
|
||||
{ ".STRING" },
|
||||
{ ".STRLEN" },
|
||||
{ ".STRUCT" },
|
||||
{ ".TAG" },
|
||||
{ ".TCOUNT" },
|
||||
{ ".TIME" },
|
||||
{ ".UNDEF" },
|
||||
{ ".UNION" },
|
||||
{ ".VERSION" },
|
||||
{ ".WARNING" },
|
||||
{ ".WORD" },
|
||||
{ ".XMATCH" },
|
||||
{ ".ZEROPAGE" },
|
||||
};
|
||||
|
||||
|
||||
|
||||
int TokHasIVal (token_t Tok)
|
||||
/* Return true if the given token has an attached IVal */
|
||||
{
|
||||
return (Tok == TOK_INTCON || Tok == TOK_CHARCON || Tok == TOK_REG);
|
||||
}
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
@@ -72,3 +303,54 @@ void CopyToken (Token* Dst, const Token* Src)
|
||||
SB_Copy (&Dst->SVal, &Src->SVal);
|
||||
Dst->Pos = Src->Pos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
StrBuf* TokenDesc (const Token* T, StrBuf* S)
|
||||
/* Place a textual description of the given token into S. */
|
||||
{
|
||||
PRECONDITION (sizeof (TokDesc) / sizeof (TokDesc[0]) == TOK_COUNT);
|
||||
|
||||
/* Clear the target buffer */
|
||||
SB_Clear (S);
|
||||
|
||||
/* Get the description for the token */
|
||||
const char* Desc = TokDesc[T->Tok].Desc;
|
||||
|
||||
/* Repeatedly replace {c}, {i} and {s} */
|
||||
size_t Start = 0;
|
||||
while (1) {
|
||||
const char* P = strchr (Desc + Start, '{');
|
||||
if (P) {
|
||||
/* Check if this is really {c}, {i} or {s} */
|
||||
if ((P[1] != 'c' &&
|
||||
P[1] != 'i' &&
|
||||
P[1] != 's') ||
|
||||
P[2] != '}') {
|
||||
++Start;
|
||||
continue;
|
||||
}
|
||||
/* Append the text before the replacement token */
|
||||
SB_AppendBuf (S, Desc + Start, P - (Desc + Start));
|
||||
Start += P - (Desc + Start) + 3;
|
||||
/* Append the replacement text */
|
||||
if (P[1] == 'c') {
|
||||
SB_AppendChar (S, (char)T->IVal);
|
||||
} else if (P[1] == 'i') {
|
||||
char Buf[64];
|
||||
snprintf (Buf, sizeof (Buf), "%ld", T->IVal);
|
||||
SB_AppendStr (S, Buf);
|
||||
} else {
|
||||
SB_Append (S, &T->SVal);
|
||||
}
|
||||
} else {
|
||||
/* No more replacements found, append remainder */
|
||||
SB_AppendStr (S, Desc + Start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Zero-terminate the buffer and return it */
|
||||
SB_Terminate (S);
|
||||
return S;
|
||||
}
|
||||
|
||||
156
src/ca65/token.h
156
src/ca65/token.h
@@ -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 */
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -70,45 +70,29 @@ CaseNode* NewCaseNode (unsigned char Value);
|
||||
void FreeCaseNode (CaseNode* N);
|
||||
/* Delete a case node plus all sub nodes */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE CaseNode* CN_GetSubNode (CaseNode* N, unsigned Index)
|
||||
static inline CaseNode* CN_GetSubNode (CaseNode* N, unsigned Index)
|
||||
/* Get a sub node of the given node */
|
||||
{
|
||||
return CollAt (N->Nodes, Index);
|
||||
}
|
||||
#else
|
||||
# define CN_GetSubNode(N, Index) CollAt (&(N)->Nodes, Index)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned char CN_GetValue (const CaseNode* N)
|
||||
static inline unsigned char CN_GetValue (const CaseNode* N)
|
||||
/* Return the value for a case node */
|
||||
{
|
||||
return N->Value;
|
||||
}
|
||||
#else
|
||||
# define CN_GetValue(N) ((N)->Value)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned CN_GetLabel (const CaseNode* N)
|
||||
static inline unsigned CN_GetLabel (const CaseNode* N)
|
||||
/* Return the label for a case node */
|
||||
{
|
||||
return N->Label;
|
||||
}
|
||||
#else
|
||||
# define CN_GetLabel(N) ((N)->Label)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int CN_IsLeafNode (const CaseNode* N)
|
||||
static inline int CN_IsLeafNode (const CaseNode* N)
|
||||
/* Return true if this is a leaf node */
|
||||
{
|
||||
return (N->Nodes == 0);
|
||||
}
|
||||
#else
|
||||
# define CN_IsLeafNode(N) ((N)->Nodes == 0)
|
||||
#endif
|
||||
|
||||
void FreeCaseNodeColl (Collection* Nodes);
|
||||
/* Free a collection of case nodes */
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
|
||||
/* common */
|
||||
#include "coll.h"
|
||||
#include "inline.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "codelab.h"
|
||||
@@ -150,88 +149,56 @@ void CE_ClearJumpTo (CodeEntry* E);
|
||||
** so use it with care.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int CE_HasLabel (const CodeEntry* E)
|
||||
static inline int CE_HasLabel (const CodeEntry* E)
|
||||
/* Check if the given code entry has labels attached */
|
||||
{
|
||||
return (CollCount (&E->Labels) > 0);
|
||||
}
|
||||
#else
|
||||
# define CE_HasLabel(E) (CollCount (&(E)->Labels) > 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned CE_GetLabelCount (const CodeEntry* E)
|
||||
static inline unsigned CE_GetLabelCount (const CodeEntry* E)
|
||||
/* Get the number of labels attached to this entry */
|
||||
{
|
||||
return CollCount (&E->Labels);
|
||||
}
|
||||
#else
|
||||
# define CE_GetLabelCount(E) CollCount (&(E)->Labels)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE CodeLabel* CE_GetLabel (CodeEntry* E, unsigned Index)
|
||||
static inline CodeLabel* CE_GetLabel (CodeEntry* E, unsigned Index)
|
||||
/* Get a label from this code entry */
|
||||
{
|
||||
return CollAt (&E->Labels, Index);
|
||||
}
|
||||
#else
|
||||
# define CE_GetLabel(E, Index) CollAt (&(E)->Labels, (Index))
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void CE_ReplaceLabel (CodeEntry* E, CodeLabel* L, unsigned Index)
|
||||
static inline void CE_ReplaceLabel (CodeEntry* E, CodeLabel* L, unsigned Index)
|
||||
/* Replace the code label at the specified index with L */
|
||||
{
|
||||
CollReplace (&E->Labels, L, Index);
|
||||
}
|
||||
#else
|
||||
# define CE_ReplaceLabel(E, L, Index) CollReplace (&(E)->Labels, (L), (Index))
|
||||
#endif
|
||||
|
||||
void CE_MoveLabel (CodeLabel* L, CodeEntry* E);
|
||||
/* Move the code label L from it's former owner to the code entry E. */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int CE_HasMark (const CodeEntry* E)
|
||||
static inline int CE_HasMark (const CodeEntry* E)
|
||||
/* Return true if the given code entry has the CEF_USERMARK flag set */
|
||||
{
|
||||
return (E->Flags & CEF_USERMARK) != 0;
|
||||
}
|
||||
#else
|
||||
# define CE_HasMark(E) (((E)->Flags & CEF_USERMARK) != 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void CE_SetMark (CodeEntry* E)
|
||||
static inline void CE_SetMark (CodeEntry* E)
|
||||
/* Set the CEF_USERMARK flag for the given entry */
|
||||
{
|
||||
E->Flags |= CEF_USERMARK;
|
||||
}
|
||||
#else
|
||||
# define CE_SetMark(E) ((E)->Flags |= CEF_USERMARK)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void CE_ResetMark (CodeEntry* E)
|
||||
static inline void CE_ResetMark (CodeEntry* E)
|
||||
/* Reset the CEF_USERMARK flag for the given entry */
|
||||
{
|
||||
E->Flags &= ~CEF_USERMARK;
|
||||
}
|
||||
#else
|
||||
# define CE_ResetMark(E) ((E)->Flags &= ~CEF_USERMARK)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int CE_HasNumArg (const CodeEntry* E)
|
||||
static inline int CE_HasNumArg (const CodeEntry* E)
|
||||
/* Return true if the instruction has a numeric argument */
|
||||
{
|
||||
return (E->Flags & CEF_NUMARG) != 0;
|
||||
}
|
||||
#else
|
||||
# define CE_HasNumArg(E) (((E)->Flags & CEF_NUMARG) != 0)
|
||||
#endif
|
||||
|
||||
void CE_SetArg (CodeEntry* E, const char* Arg);
|
||||
/* Replace the argument by the new one. */
|
||||
@@ -271,15 +238,11 @@ int CE_IsKnownImm (const CodeEntry* E, unsigned long Num);
|
||||
** equal to Num.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int CE_IsCallTo (const CodeEntry* E, const char* Name)
|
||||
static inline int CE_IsCallTo (const CodeEntry* E, const char* Name)
|
||||
/* Check if this is a call to the given function */
|
||||
{
|
||||
return (E->OPC == OP65_JSR && strcmp (E->Arg, Name) == 0);
|
||||
}
|
||||
#else
|
||||
# define CE_IsCallTo(E, Name) ((E)->OPC == OP65_JSR && strcmp ((E)->Arg, (Name)) == 0)
|
||||
#endif
|
||||
|
||||
int CE_UseLoadFlags (CodeEntry* E);
|
||||
/* Return true if the instruction uses any flags that are set by a load of
|
||||
|
||||
@@ -83,25 +83,17 @@ CodeLabel* NewCodeLabel (const char* Name, unsigned Hash);
|
||||
void FreeCodeLabel (CodeLabel* L);
|
||||
/* Free the given code label */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned CL_GetRefCount (const CodeLabel* L)
|
||||
static inline unsigned CL_GetRefCount (const CodeLabel* L)
|
||||
/* Get the number of references for this label */
|
||||
{
|
||||
return CollCount (&L->JumpFrom);
|
||||
}
|
||||
#else
|
||||
# define CL_GetRefCount(L) CollCount (&(L)->JumpFrom)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE struct CodeEntry* CL_GetRef (CodeLabel* L, unsigned Index)
|
||||
static inline struct CodeEntry* CL_GetRef (CodeLabel* L, unsigned Index)
|
||||
/* Get a code entry referencing this label */
|
||||
{
|
||||
return CollAt (&L->JumpFrom, Index);
|
||||
}
|
||||
#else
|
||||
# define CL_GetRef(L, Index) CollAt (&(L)->JumpFrom, (Index))
|
||||
#endif
|
||||
|
||||
void CL_AddRef (CodeLabel* L, struct CodeEntry* E);
|
||||
/* Let the CodeEntry E reference the label L */
|
||||
|
||||
@@ -113,6 +113,8 @@ static OptFunc DOptAdd3 = { OptAdd3, "OptAdd3", 65, 0,
|
||||
static OptFunc DOptAdd4 = { OptAdd4, "OptAdd4", 90, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptAdd5 = { OptAdd5, "OptAdd5", 100, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptAdd6 = { OptAdd6, "OptAdd6", 40, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptAXLoad = { OptAXLoad, "OptAXLoad", 50, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptAXOps = { OptAXOps, "OptAXOps", 50, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptBNegA1 = { OptBNegA1, "OptBNegA1", 100, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptBNegA2 = { OptBNegA2, "OptBNegA2", 100, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptBNegAX1 = { OptBNegAX1, "OptBNegAX1", 100, 0, 0, 0, 0, 0 };
|
||||
@@ -236,6 +238,7 @@ static OptFunc* OptFuncs[] = {
|
||||
&DOptAdd4,
|
||||
&DOptAdd5,
|
||||
&DOptAdd6,
|
||||
&DOptAXOps,
|
||||
&DOptBNegA1,
|
||||
&DOptBNegA2,
|
||||
&DOptBNegAX1,
|
||||
@@ -629,6 +632,7 @@ static unsigned RunOptGroup1 (CodeSeg* S)
|
||||
|
||||
Changes += RunOptFunc (S, &DOptGotoSPAdj, 1);
|
||||
Changes += RunOptFunc (S, &DOptStackPtrOps, 5);
|
||||
Changes += RunOptFunc (S, &DOptAXOps, 5);
|
||||
Changes += RunOptFunc (S, &DOptAdd3, 1); /* Before OptPtrLoad5! */
|
||||
Changes += RunOptFunc (S, &DOptPtrStore1, 1);
|
||||
Changes += RunOptFunc (S, &DOptPtrStore2, 1);
|
||||
@@ -871,6 +875,7 @@ static unsigned RunOptGroup7 (CodeSeg* S)
|
||||
** may have opened new oportunities.
|
||||
*/
|
||||
Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
|
||||
Changes += RunOptFunc (S, &DOptAXLoad, 5);
|
||||
Changes += RunOptFunc (S, &DOptUnusedStores, 1);
|
||||
Changes += RunOptFunc (S, &DOptJumpTarget1, 5);
|
||||
Changes += RunOptFunc (S, &DOptStore5, 1);
|
||||
@@ -907,6 +912,11 @@ static unsigned RunOptGroup7 (CodeSeg* S)
|
||||
between branches */
|
||||
C += RunOptFunc (S, &DOptBranchDist, 3);
|
||||
|
||||
/* Re-optimize inc/decsp that may now be grouped */
|
||||
C += RunOptFunc (S, &DOptStackPtrOps, 5);
|
||||
/* Re-optimize JSR/RTS that may now be grouped */
|
||||
C += RunOptFunc (S, &DOptRTS, 1);
|
||||
|
||||
Changes += C;
|
||||
/* If we had changes, we must run dead code elimination again,
|
||||
** since the changes may have introduced dead code.
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
/* common */
|
||||
#include "attrib.h"
|
||||
#include "coll.h"
|
||||
#include "inline.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "codelab.h"
|
||||
@@ -106,15 +105,11 @@ void CS_AddVLine (CodeSeg* S, LineInfo* LI, const char* Format, va_list ap) attr
|
||||
void CS_AddLine (CodeSeg* S, LineInfo* LI, const char* Format, ...) attribute ((format(printf,3,4)));
|
||||
/* Add a line to the given code segment */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned CS_GetEntryCount (const CodeSeg* S)
|
||||
static inline unsigned CS_GetEntryCount (const CodeSeg* S)
|
||||
/* Return the number of entries for the given code segment */
|
||||
{
|
||||
return CollCount (&S->Entries);
|
||||
}
|
||||
#else
|
||||
# define CS_GetEntryCount(S) CollCount (&(S)->Entries)
|
||||
#endif
|
||||
|
||||
void CS_InsertEntry (CodeSeg* S, struct CodeEntry* E, unsigned Index);
|
||||
/* Insert the code entry at the index given. Following code entries will be
|
||||
@@ -145,27 +140,19 @@ void CS_MoveEntries (CodeSeg* S, unsigned Start, unsigned Count, unsigned NewPos
|
||||
** current code end)
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void CS_MoveEntry (CodeSeg* S, unsigned OldPos, unsigned NewPos)
|
||||
static inline void CS_MoveEntry (CodeSeg* S, unsigned OldPos, unsigned NewPos)
|
||||
/* Move an entry from one position to another. OldPos is the current position
|
||||
** of the entry, NewPos is the new position of the entry.
|
||||
*/
|
||||
{
|
||||
CollMove (&S->Entries, OldPos, NewPos);
|
||||
}
|
||||
#else
|
||||
# define CS_MoveEntry(S, OldPos, NewPos) CollMove (&(S)->Entries, OldPos, NewPos)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE struct CodeEntry* CS_GetEntry (CodeSeg* S, unsigned Index)
|
||||
static inline struct CodeEntry* CS_GetEntry (CodeSeg* S, unsigned Index)
|
||||
/* Get an entry from the given code segment */
|
||||
{
|
||||
return CollAt (&S->Entries, Index);
|
||||
}
|
||||
#else
|
||||
# define CS_GetEntry(S, Index) ((struct CodeEntry*) CollAt(&(S)->Entries, (Index)))
|
||||
#endif
|
||||
|
||||
struct CodeEntry* CS_GetPrevEntry (CodeSeg* S, unsigned Index);
|
||||
/* Get the code entry preceeding the one with the index Index. If there is no
|
||||
@@ -192,17 +179,13 @@ int CS_RangeHasLabel (CodeSeg* S, unsigned Start, unsigned Count);
|
||||
** possible span instead.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int CS_HavePendingLabel (const CodeSeg* S)
|
||||
static inline int CS_HavePendingLabel (const CodeSeg* S)
|
||||
/* Return true if there are open labels that will get attached to the next
|
||||
** instruction that is added.
|
||||
*/
|
||||
{
|
||||
return (CollCount (&S->Labels) > 0);
|
||||
}
|
||||
#else
|
||||
# define CS_HavePendingLabel(S) (CollCount (&(S)->Labels) > 0)
|
||||
#endif
|
||||
|
||||
CodeLabel* CS_AddLabel (CodeSeg* S, const char* Name);
|
||||
/* Add a code label for the next instruction to follow */
|
||||
@@ -253,18 +236,13 @@ void CS_DelCodeAfter (CodeSeg* S, unsigned Last);
|
||||
void CS_ResetMarks (CodeSeg* S, unsigned First, unsigned Last);
|
||||
/* Remove all user marks from the entries in the given range */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void CS_ResetAllMarks (CodeSeg* S)
|
||||
static inline void CS_ResetAllMarks (CodeSeg* S)
|
||||
/* Remove all user marks from the code segment */
|
||||
{
|
||||
if (CS_GetEntryCount (S) > 0) {
|
||||
CS_ResetMarks (S, 0, CS_GetEntryCount (S));
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define CS_ResetAllMarks(S) \
|
||||
((CS_GetEntryCount (S) > 0)? CS_ResetMarks (S, 0, CS_GetEntryCount (S)) : (void) 0)
|
||||
#endif
|
||||
|
||||
int CS_IsBasicBlock (CodeSeg* S, unsigned First, unsigned Last);
|
||||
/* Check if the given code segment range is a basic block. That is, check if
|
||||
|
||||
@@ -380,28 +380,37 @@ unsigned OptIndLoads2 (CodeSeg* S)
|
||||
|
||||
|
||||
|
||||
static unsigned IsDecSP (const CodeEntry* E)
|
||||
/* Check if this is an insn that decrements the stack pointer. If so, return
|
||||
** the decrement. If not, return zero.
|
||||
** The function expects E to be a subroutine call.
|
||||
static signed IsShift (const CodeEntry* E, const char* dec, const char* inc, const char* sub, const char* add)
|
||||
/* Check if this is an insn that increments/decrements the stack pointer or AX.
|
||||
** If so, return the value (negative for dec, positive for inc). If not, return zero.
|
||||
*/
|
||||
{
|
||||
if (strncmp (E->Arg, "decsp", 5) == 0) {
|
||||
if (E->OPC != OP65_JSR && E->OPC != OP65_JMP) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strncmp (E->Arg, dec, 5) == 0) {
|
||||
if (E->Arg[5] >= '1' && E->Arg[5] <= '8') {
|
||||
return -(E->Arg[5] - '0');
|
||||
}
|
||||
} else if (strcmp (E->Arg, sub) == 0 && RegValIsKnown (E->RI->In.RegY)) {
|
||||
return -(E->RI->In.RegY);
|
||||
} else if (strncmp (E->Arg, inc, 5) == 0) {
|
||||
if (E->Arg[5] >= '1' && E->Arg[5] <= '8') {
|
||||
return (E->Arg[5] - '0');
|
||||
}
|
||||
} else if (strcmp (E->Arg, "subysp") == 0 && RegValIsKnown (E->RI->In.RegY)) {
|
||||
return E->RI->In.RegY;
|
||||
} else if (strcmp (E->Arg, add) == 0 && RegValIsKnown (E->RI->In.RegY)) {
|
||||
return (E->RI->In.RegY);
|
||||
}
|
||||
|
||||
/* If we come here, it's not a decsp op */
|
||||
/* If we come here, it's not a dec/inc op */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned OptStackPtrOps (CodeSeg* S)
|
||||
/* Merge adjacent calls to decsp into one. NOTE: This function won't merge all
|
||||
static unsigned OptIncDecOps (CodeSeg* S, const char* dec, const char* inc, const char* sub, const char* add)
|
||||
/* Merge adjacent calls to inc/dec/add/sub into one. NOTE: This function won't merge all
|
||||
** known cases!
|
||||
*/
|
||||
{
|
||||
@@ -412,38 +421,116 @@ unsigned OptStackPtrOps (CodeSeg* S)
|
||||
I = 0;
|
||||
while (I < CS_GetEntryCount (S)) {
|
||||
|
||||
unsigned Dec1;
|
||||
unsigned Dec2;
|
||||
signed Val1;
|
||||
signed Val2;
|
||||
const CodeEntry* N;
|
||||
|
||||
/* Get the next entry */
|
||||
const CodeEntry* E = CS_GetEntry (S, I);
|
||||
|
||||
/* Check for decspn or subysp */
|
||||
if (E->OPC == OP65_JSR &&
|
||||
(Dec1 = IsDecSP (E)) > 0 &&
|
||||
(N = CS_GetNextEntry (S, I)) != 0 &&
|
||||
(Dec2 = IsDecSP (N)) > 0 &&
|
||||
(Dec1 += Dec2) <= 255 &&
|
||||
/* Check for decspn, incspn, subysp or addysp */
|
||||
if (E->OPC == OP65_JSR &&
|
||||
(Val1 = IsShift (E, dec, inc, sub, add)) != 0 &&
|
||||
(N = CS_GetNextEntry (S, I)) != 0 &&
|
||||
(N->OPC == OP65_JSR || N->OPC == OP65_JMP) &&
|
||||
(Val2 = IsShift (N, dec, inc, sub, add)) != 0 &&
|
||||
abs(Val1 += Val2) <= 255 &&
|
||||
!CE_HasLabel (N)) {
|
||||
|
||||
CodeEntry* X;
|
||||
char Buf[20];
|
||||
|
||||
/* We can combine the two */
|
||||
if (Dec1 <= 8) {
|
||||
/* Insert a call to decsp */
|
||||
xsprintf (Buf, sizeof (Buf), "decsp%u", Dec1);
|
||||
X = NewCodeEntry (OP65_JSR, AM65_ABS, Buf, 0, N->LI);
|
||||
CS_InsertEntry (S, X, I+2);
|
||||
} else {
|
||||
/* Insert a call to subysp */
|
||||
const char* Arg = MakeHexArg (Dec1);
|
||||
X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, N->LI);
|
||||
CS_InsertEntry (S, X, I+2);
|
||||
X = NewCodeEntry (OP65_JSR, AM65_ABS, "subysp", 0, N->LI);
|
||||
CS_InsertEntry (S, X, I+3);
|
||||
}
|
||||
if (Val1 != 0) {
|
||||
/* We can combine the two */
|
||||
if (abs(Val1) <= 8) {
|
||||
/* Insert a call to inc/dec using the last OPC */
|
||||
xsprintf (Buf, sizeof (Buf), "%s%u", Val1 < 0 ? dec:inc, abs(Val1));
|
||||
X = NewCodeEntry (N->OPC, AM65_ABS, Buf, 0, N->LI);
|
||||
CS_InsertEntry (S, X, I+2);
|
||||
} else {
|
||||
/* Insert a call to add/sub */
|
||||
const char* Arg = MakeHexArg (abs(Val1));
|
||||
X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, N->LI);
|
||||
CS_InsertEntry (S, X, I+2);
|
||||
if (Val1 < 0) {
|
||||
X = NewCodeEntry (N->OPC, AM65_ABS, sub, 0, N->LI);
|
||||
} else {
|
||||
X = NewCodeEntry (N->OPC, AM65_ABS, add, 0, N->LI);
|
||||
}
|
||||
CS_InsertEntry (S, X, I+3);
|
||||
}
|
||||
} /* If total shift == 0, just drop the old code. */
|
||||
|
||||
/* Delete the old code */
|
||||
CS_DelEntries (S, I, 2);
|
||||
|
||||
/* Regenerate register info */
|
||||
CS_GenRegInfo (S);
|
||||
|
||||
/* Remember we had changes */
|
||||
++Changes;
|
||||
|
||||
} else {
|
||||
|
||||
/* Next entry */
|
||||
++I;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Return the number of changes made */
|
||||
return Changes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned OptStackPtrOps (CodeSeg* S)
|
||||
{
|
||||
return OptIncDecOps(S, "decsp", "incsp", "subysp", "addysp");
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned OptAXOps (CodeSeg* S)
|
||||
{
|
||||
return OptIncDecOps(S, "decax", "incax", "decaxy", "incaxy");
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned OptAXLoad (CodeSeg* S)
|
||||
/* Merge jsr incax/jsr ldaxi into ldy/jsr ldaxidx */
|
||||
{
|
||||
unsigned Changes = 0;
|
||||
unsigned I;
|
||||
|
||||
/* Walk over the entries */
|
||||
I = 0;
|
||||
while (I < CS_GetEntryCount (S)) {
|
||||
|
||||
signed Val;
|
||||
const CodeEntry* N;
|
||||
|
||||
/* Get the next entry */
|
||||
const CodeEntry* E = CS_GetEntry (S, I);
|
||||
|
||||
/* Check for incax followed by jsr/jmp ldaxi */
|
||||
if (E->OPC == OP65_JSR &&
|
||||
strncmp (E->Arg, "incax", 5) == 0 &&
|
||||
(N = CS_GetNextEntry (S, I)) != 0 &&
|
||||
(N->OPC == OP65_JSR || N->OPC == OP65_JMP) &&
|
||||
strcmp (N->Arg, "ldaxi") == 0 &&
|
||||
!CE_HasLabel (N)) {
|
||||
|
||||
CodeEntry* X;
|
||||
const char* Arg;
|
||||
|
||||
Val = E->Arg[5] - '0';
|
||||
Arg = MakeHexArg (Val + 1);
|
||||
X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, N->LI);
|
||||
CS_InsertEntry (S, X, I+2);
|
||||
X = NewCodeEntry (N->OPC, AM65_ABS, "ldaxidx", 0, N->LI);
|
||||
CS_InsertEntry (S, X, I+3);
|
||||
|
||||
/* Delete the old code */
|
||||
CS_DelEntries (S, I, 2);
|
||||
|
||||
@@ -92,10 +92,18 @@ unsigned OptIndLoads2 (CodeSeg* S);
|
||||
*/
|
||||
|
||||
unsigned OptStackPtrOps (CodeSeg* S);
|
||||
/* Merge adjacent calls to decsp into one. NOTE: This function won't merge all
|
||||
/* Merge adjacent calls to decsp/incax into one. NOTE: This function won't merge all
|
||||
** known cases!
|
||||
*/
|
||||
|
||||
unsigned OptAXOps (CodeSeg* S);
|
||||
/* Merge adjacent calls to decax/incax into one. NOTE: This function won't merge all
|
||||
** known cases!
|
||||
*/
|
||||
|
||||
unsigned OptAXLoad (CodeSeg* S);
|
||||
/* Merge adjacent calls to incax/ldaxi into ldy/ldaxidx */
|
||||
|
||||
unsigned OptGotoSPAdj (CodeSeg* S);
|
||||
/* Optimize SP adjustment for forward 'goto' */
|
||||
|
||||
|
||||
@@ -878,16 +878,6 @@ int IsTypeFragBitField (const Type* T)
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
int IsTypeFuncLike (const Type* T)
|
||||
/* Return true if this is a function or a function pointer */
|
||||
{
|
||||
return IsTypeFunc (T) || IsTypeFuncPtr (T);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
int IsObjectType (const Type* T)
|
||||
/* Return true if this is a fully described object type */
|
||||
{
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
|
||||
/* common */
|
||||
#include "attrib.h"
|
||||
#include "inline.h"
|
||||
#include "mmodel.h"
|
||||
|
||||
/* cc65 */
|
||||
@@ -258,15 +257,11 @@ Type* TypeAlloc (unsigned Len);
|
||||
void TypeFree (Type* T);
|
||||
/* Free a type string */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void CopyTypeAttr (const Type* Src, Type* Dest)
|
||||
static inline void CopyTypeAttr (const Type* Src, Type* Dest)
|
||||
/* Copy attribute data from Src to Dest */
|
||||
{
|
||||
Dest->A = Src->A;
|
||||
}
|
||||
#else
|
||||
# define CopyTypeAttr(Src, Dest) ((Dest)->A = (Src)->A)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -316,104 +311,68 @@ unsigned CheckedPSizeOf (const Type* T);
|
||||
** the rest of the compiler doesn't have to work with invalid sizes).
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode GetQualifier (const Type* T)
|
||||
static inline TypeCode GetQualifier (const Type* T)
|
||||
/* Get the qualifier from the given type. This doesn't have a "raw" version
|
||||
** since an underlying type can never be qualified.
|
||||
*/
|
||||
{
|
||||
return (T->C & T_MASK_QUAL);
|
||||
}
|
||||
#else
|
||||
# define GetQualifier(T) ((T)->C & T_MASK_QUAL)
|
||||
#endif
|
||||
|
||||
TypeCode GetUnderlyingTypeCode (const Type* Type);
|
||||
/* Get the type code of the unqualified underlying type of Type.
|
||||
** Return GetUnqualRawTypeCode (Type) if Type is not scalar.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode GetUnqualRawTypeCode (const Type* T)
|
||||
static inline TypeCode GetUnqualRawTypeCode (const Type* T)
|
||||
/* Return the unqualified raw type code */
|
||||
{
|
||||
return (T->C & ~T_MASK_QUAL);
|
||||
}
|
||||
#else
|
||||
# define GetUnqualRawTypeCode(T) ((T)->C & ~T_MASK_QUAL)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode GetTypeClass (const Type* T)
|
||||
static inline TypeCode GetTypeClass (const Type* T)
|
||||
/* Get the class of a type. This doesn't have a "raw" version since an
|
||||
** underlying type can never be in a different class.
|
||||
*/
|
||||
{
|
||||
return (T->C & T_MASK_CLASS);
|
||||
}
|
||||
#else
|
||||
# define GetTypeClass(T) ((T)->C & T_MASK_CLASS)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode GetTypeRank (const Type* T)
|
||||
static inline TypeCode GetTypeRank (const Type* T)
|
||||
/* Get the type rank of a type */
|
||||
{
|
||||
return (GetUnderlyingTypeCode (T) & T_MASK_RANK);
|
||||
}
|
||||
#else
|
||||
# define GetTypeRank(T) (GetUnderlyingTypeCode (T) & T_MASK_RANK)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode GetSignedness (const Type* T)
|
||||
static inline TypeCode GetSignedness (const Type* T)
|
||||
/* Get the signedness of a type */
|
||||
{
|
||||
return (GetUnderlyingTypeCode (T) & T_MASK_SIGN);
|
||||
}
|
||||
#else
|
||||
# define GetSignedness(T) (GetUnderlyingTypeCode (T) & T_MASK_SIGN)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode GetSizeModifier (const Type* T)
|
||||
static inline TypeCode GetSizeModifier (const Type* T)
|
||||
/* Get the size modifier of a type */
|
||||
{
|
||||
return (GetUnderlyingTypeCode (T) & T_MASK_SIZE);
|
||||
}
|
||||
#else
|
||||
# define GetSizeModifier(T) (GetUnderlyingTypeCode (T) & T_MASK_SIZE)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode GetRawTypeRank (const Type* T)
|
||||
static inline TypeCode GetRawTypeRank (const Type* T)
|
||||
/* Get the raw type rank of a type */
|
||||
{
|
||||
return (T->C & T_MASK_RANK);
|
||||
}
|
||||
#else
|
||||
# define GetRawTypeRank(T) ((T)->C & T_MASK_RANK)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode GetRawSignedness (const Type* T)
|
||||
static inline TypeCode GetRawSignedness (const Type* T)
|
||||
/* Get the raw signedness of a type */
|
||||
{
|
||||
return (T->C & T_MASK_SIGN);
|
||||
}
|
||||
#else
|
||||
# define GetRawSignedness(T) ((T)->C & T_MASK_SIGN)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode GetRawSizeModifier (const Type* T)
|
||||
static inline TypeCode GetRawSizeModifier (const Type* T)
|
||||
/* Get the raw size modifier of a type */
|
||||
{
|
||||
return (T->C & T_MASK_SIZE);
|
||||
}
|
||||
#else
|
||||
# define GetRawSizeModifier(T) ((T)->C & T_MASK_SIZE)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -498,263 +457,162 @@ const Type* GetBitFieldChunkType (const Type* Type);
|
||||
|
||||
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsRankChar (const Type* T)
|
||||
static inline int IsRankChar (const Type* T)
|
||||
/* Return true if this is a character type */
|
||||
{
|
||||
return (GetTypeRank (T) == T_RANK_CHAR);
|
||||
}
|
||||
#else
|
||||
# define IsRankChar(T) (GetTypeRank (T) == T_RANK_CHAR)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsRankShort (const Type* T)
|
||||
static inline int IsRankShort (const Type* T)
|
||||
/* Return true if this is a short type (signed or unsigned) */
|
||||
{
|
||||
return (GetTypeRank (T) == T_RANK_SHORT);
|
||||
}
|
||||
#else
|
||||
# define IsRankShort(T) (GetTypeRank (T) == T_RANK_SHORT)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsRankInt (const Type* T)
|
||||
static inline int IsRankInt (const Type* T)
|
||||
/* Return true if this is an int type (signed or unsigned) */
|
||||
{
|
||||
return (GetTypeRank (T) == T_RANK_INT);
|
||||
}
|
||||
#else
|
||||
# define IsRankInt(T) (GetTypeRank (T) == T_RANK_INT)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsRankLong (const Type* T)
|
||||
static inline int IsRankLong (const Type* T)
|
||||
/* Return true if this is a long int type (signed or unsigned) */
|
||||
{
|
||||
return (GetTypeRank (T) == T_RANK_LONG);
|
||||
}
|
||||
#else
|
||||
# define IsRankLong(T) (GetTypeRank (T) == T_RANK_LONG)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsDeclTypeChar (const Type* T)
|
||||
static inline int IsDeclTypeChar (const Type* T)
|
||||
/* Return true if this is declared as a char type (without signed/unsigned).
|
||||
** This function is to exclude enums whose underlying type is char.
|
||||
*/
|
||||
{
|
||||
return (GetUnqualRawTypeCode (T) == T_CHAR);
|
||||
}
|
||||
#else
|
||||
# define IsDeclTypeChar(T) (GetUnqualRawTypeCode (T) == T_CHAR)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsDeclRankChar (const Type* T)
|
||||
static inline int IsDeclRankChar (const Type* T)
|
||||
/* Return true if this is declared as a character type (including signed/unsigned).
|
||||
** This function is to exclude enums whose underlying types are character types.
|
||||
*/
|
||||
{
|
||||
return (GetRawTypeRank (T) == T_RANK_CHAR);
|
||||
}
|
||||
#else
|
||||
# define IsDeclRankChar(T) (GetRawTypeRank (T) == T_RANK_CHAR)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeFloat (const Type* T)
|
||||
static inline int IsTypeFloat (const Type* T)
|
||||
/* Return true if this is a float type */
|
||||
{
|
||||
return (GetRawTypeRank (T) == T_RANK_FLOAT);
|
||||
}
|
||||
#else
|
||||
# define IsTypeFloat(T) (GetRawTypeRank (T) == T_RANK_FLOAT)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeDouble (const Type* T)
|
||||
static inline int IsTypeDouble (const Type* T)
|
||||
/* Return true if this is a double type */
|
||||
{
|
||||
return (GetRawTypeRank (T) == T_RANK_DOUBLE);
|
||||
}
|
||||
#else
|
||||
# define IsTypeDouble(T) (GetRawTypeRank (T) == T_RANK_DOUBLE)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypePtr (const Type* T)
|
||||
static inline int IsTypePtr (const Type* T)
|
||||
/* Return true if this is a pointer type */
|
||||
{
|
||||
return (GetRawTypeRank (T) == T_RANK_PTR);
|
||||
}
|
||||
#else
|
||||
# define IsTypePtr(T) (GetRawTypeRank (T) == T_RANK_PTR)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeEnum (const Type* T)
|
||||
static inline int IsTypeEnum (const Type* T)
|
||||
/* Return true if this is an enum type */
|
||||
{
|
||||
return (GetRawTypeRank (T) == T_RANK_ENUM);
|
||||
}
|
||||
#else
|
||||
# define IsTypeEnum(T) (GetRawTypeRank (T) == T_RANK_ENUM)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeSignedBitField (const Type* T)
|
||||
static inline int IsTypeSignedBitField (const Type* T)
|
||||
/* Return true if this is a signed bit-field */
|
||||
{
|
||||
return (GetUnqualRawTypeCode (T) == T_SBITFIELD);
|
||||
}
|
||||
#else
|
||||
# define IsTypeSignedBitField(T) (GetUnqualRawTypeCode (T) == T_SBITFIELD)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeUnsignedBitField (const Type* T)
|
||||
static inline int IsTypeUnsignedBitField (const Type* T)
|
||||
/* Return true if this is an unsigned bit-field */
|
||||
{
|
||||
return (GetUnqualRawTypeCode (T) == T_UBITFIELD);
|
||||
}
|
||||
#else
|
||||
# define IsTypeUnsignedBitField(T) (GetUnqualRawTypeCode (T) == T_UBITFIELD)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeBitField (const Type* T)
|
||||
static inline int IsTypeBitField (const Type* T)
|
||||
/* Return true if this is a bit-field (either signed or unsigned) */
|
||||
{
|
||||
return IsTypeSignedBitField (T) || IsTypeUnsignedBitField (T);
|
||||
}
|
||||
#else
|
||||
# define IsTypeBitField(T) (IsTypeSignedBitField (T) || IsTypeUnsignedBitField (T))
|
||||
#endif
|
||||
|
||||
int IsTypeFragBitField (const Type* T);
|
||||
/* Return true if this is a bit-field that shares byte space with other fields */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeStruct (const Type* T)
|
||||
static inline int IsTypeStruct (const Type* T)
|
||||
/* Return true if this is a struct type */
|
||||
{
|
||||
return (GetRawTypeRank (T) == T_RANK_STRUCT);
|
||||
}
|
||||
#else
|
||||
# define IsTypeStruct(T) (GetRawTypeRank (T) == T_RANK_STRUCT)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeUnion (const Type* T)
|
||||
static inline int IsTypeUnion (const Type* T)
|
||||
/* Return true if this is a union type */
|
||||
{
|
||||
return (GetRawTypeRank (T) == T_RANK_UNION);
|
||||
}
|
||||
#else
|
||||
# define IsTypeUnion(T) (GetRawTypeRank (T) == T_RANK_UNION)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeArray (const Type* T)
|
||||
static inline int IsTypeArray (const Type* T)
|
||||
/* Return true if this is an array type */
|
||||
{
|
||||
return (GetRawTypeRank (T) == T_RANK_ARRAY);
|
||||
}
|
||||
#else
|
||||
# define IsTypeArray(T) (GetRawTypeRank (T) == T_RANK_ARRAY)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeVoid (const Type* T)
|
||||
static inline int IsTypeVoid (const Type* T)
|
||||
/* Return true if this is a void type */
|
||||
{
|
||||
return (GetRawTypeRank (T) == T_RANK_VOID);
|
||||
}
|
||||
#else
|
||||
# define IsTypeVoid(T) (GetRawTypeRank (T) == T_RANK_VOID)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeFunc (const Type* T)
|
||||
static inline int IsTypeFunc (const Type* T)
|
||||
/* Return true if this is a function type */
|
||||
{
|
||||
return (GetRawTypeRank (T) == T_RANK_FUNC);
|
||||
}
|
||||
#else
|
||||
# define IsTypeFunc(T) (GetRawTypeRank (T) == T_RANK_FUNC)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeFuncPtr (const Type* T)
|
||||
static inline int IsTypeFuncPtr (const Type* T)
|
||||
/* Return true if this is a function pointer type */
|
||||
{
|
||||
return (IsTypePtr (T) && IsTypeFunc (T+1));
|
||||
}
|
||||
#else
|
||||
# define IsTypeFuncPtr(T) (IsTypePtr (T) && IsTypeFunc (T+1))
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsTypeFuncLike (const Type* T)
|
||||
static inline int IsTypeFuncLike (const Type* T)
|
||||
/* Return true if this is a function or a function pointer */
|
||||
{
|
||||
return IsTypeFunc (T) || IsTypeFuncPtr (T);
|
||||
}
|
||||
#else
|
||||
int IsTypeFuncLike (const Type* T);
|
||||
/* Return true if this is a function or a function pointer */
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsClassInt (const Type* T)
|
||||
static inline int IsClassInt (const Type* T)
|
||||
/* Return true if this is an integer type */
|
||||
{
|
||||
return (GetTypeClass (T) == T_CLASS_INT);
|
||||
}
|
||||
#else
|
||||
# define IsClassInt(T) (GetTypeClass (T) == T_CLASS_INT)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsClassFloat (const Type* T)
|
||||
static inline int IsClassFloat (const Type* T)
|
||||
/* Return true if this is a floating type */
|
||||
{
|
||||
return (GetTypeClass (T) == T_CLASS_FLOAT);
|
||||
}
|
||||
#else
|
||||
# define IsClassFloat(T) (GetTypeClass (T) == T_CLASS_FLOAT)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsClassPtr (const Type* T)
|
||||
static inline int IsClassPtr (const Type* T)
|
||||
/* Return true if this is a pointer or array type */
|
||||
{
|
||||
return (GetTypeClass (T) == T_CLASS_PTR);
|
||||
}
|
||||
#else
|
||||
# define IsClassPtr(T) (GetTypeClass (T) == T_CLASS_PTR)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsClassStruct (const Type* T)
|
||||
static inline int IsClassStruct (const Type* T)
|
||||
/* Return true if this is a struct or union type */
|
||||
{
|
||||
return (GetTypeClass (T) == T_CLASS_STRUCT);
|
||||
}
|
||||
#else
|
||||
# define IsClassStruct(T) (GetTypeClass (T) == T_CLASS_STRUCT)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsClassFunc (const Type* T)
|
||||
static inline int IsClassFunc (const Type* T)
|
||||
/* Return true if this is a function type */
|
||||
{
|
||||
return (GetTypeClass (T) == T_CLASS_FUNC);
|
||||
}
|
||||
#else
|
||||
# define IsClassFunc(T) (GetTypeClass (T) == T_CLASS_FUNC)
|
||||
#endif
|
||||
|
||||
int IsObjectType (const Type* T);
|
||||
/* Return true if this is a fully described object type */
|
||||
@@ -813,45 +671,29 @@ int HasUnknownSize (const Type* T);
|
||||
int TypeHasAttrData (const Type* T);
|
||||
/* Return true if the given type has attribute data */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsRawSignUnsigned (const Type* T)
|
||||
static inline int IsRawSignUnsigned (const Type* T)
|
||||
/* Return true if this is an unsigned raw type */
|
||||
{
|
||||
return (GetRawSignedness (T) == T_SIGN_UNSIGNED);
|
||||
}
|
||||
#else
|
||||
# define IsRawSignUnsigned(T) (GetRawSignedness (T) == T_SIGN_UNSIGNED)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsSignUnsigned (const Type* T)
|
||||
static inline int IsSignUnsigned (const Type* T)
|
||||
/* Return true if this is an unsigned type */
|
||||
{
|
||||
return (GetSignedness (T) == T_SIGN_UNSIGNED);
|
||||
}
|
||||
#else
|
||||
# define IsSignUnsigned(T) (GetSignedness (T) == T_SIGN_UNSIGNED)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsRawSignSigned (const Type* T)
|
||||
static inline int IsRawSignSigned (const Type* T)
|
||||
/* Return true if this is a signed raw type */
|
||||
{
|
||||
return (GetRawSignedness (T) == T_SIGN_SIGNED);
|
||||
}
|
||||
#else
|
||||
# define IsRawSignSigned(T) (GetRawSignedness (T) == T_SIGN_SIGNED)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsSignSigned (const Type* T)
|
||||
static inline int IsSignSigned (const Type* T)
|
||||
/* Return true if this is a signed type */
|
||||
{
|
||||
return (GetSignedness (T) == T_SIGN_SIGNED);
|
||||
}
|
||||
#else
|
||||
# define IsSignSigned(T) (GetSignedness (T) == T_SIGN_SIGNED)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -861,108 +703,68 @@ INLINE int IsSignSigned (const Type* T)
|
||||
|
||||
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsQualConst (const Type* T)
|
||||
static inline int IsQualConst (const Type* T)
|
||||
/* Return true if the given type has a const memory image */
|
||||
{
|
||||
return (T->C & T_QUAL_CONST) != 0;
|
||||
}
|
||||
#else
|
||||
# define IsQualConst(T) (((T)->C & T_QUAL_CONST) != 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsQualVolatile (const Type* T)
|
||||
static inline int IsQualVolatile (const Type* T)
|
||||
/* Return true if the given type has a volatile type qualifier */
|
||||
{
|
||||
return (T->C & T_QUAL_VOLATILE) != 0;
|
||||
}
|
||||
#else
|
||||
# define IsQualVolatile(T) (((T)->C & T_QUAL_VOLATILE) != 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsQualRestrict (const Type* T)
|
||||
static inline int IsQualRestrict (const Type* T)
|
||||
/* Return true if the given type has a restrict qualifier */
|
||||
{
|
||||
return (T->C & T_QUAL_RESTRICT) != 0;
|
||||
}
|
||||
#else
|
||||
# define IsQualRestrict(T) (((T)->C & T_QUAL_RESTRICT) != 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsQualNear (const Type* T)
|
||||
static inline int IsQualNear (const Type* T)
|
||||
/* Return true if the given type has a near qualifier */
|
||||
{
|
||||
return (T->C & T_QUAL_NEAR) != 0;
|
||||
}
|
||||
#else
|
||||
# define IsQualNear(T) (((T)->C & T_QUAL_NEAR) != 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsQualFar (const Type* T)
|
||||
static inline int IsQualFar (const Type* T)
|
||||
/* Return true if the given type has a far qualifier */
|
||||
{
|
||||
return (T->C & T_QUAL_FAR) != 0;
|
||||
}
|
||||
#else
|
||||
# define IsQualFar(T) (((T)->C & T_QUAL_FAR) != 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsQualFastcall (const Type* T)
|
||||
static inline int IsQualFastcall (const Type* T)
|
||||
/* Return true if the given type has a fastcall qualifier */
|
||||
{
|
||||
return (T->C & T_QUAL_FASTCALL) != 0;
|
||||
}
|
||||
#else
|
||||
# define IsQualFastcall(T) (((T)->C & T_QUAL_FASTCALL) != 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsQualCDecl (const Type* T)
|
||||
static inline int IsQualCDecl (const Type* T)
|
||||
/* Return true if the given type has a cdecl qualifier */
|
||||
{
|
||||
return (T->C & T_QUAL_CDECL) != 0;
|
||||
}
|
||||
#else
|
||||
# define IsQualCDecl(T) (((T)->C & T_QUAL_CDECL) != 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsQualCConv (const Type* T)
|
||||
static inline int IsQualCConv (const Type* T)
|
||||
/* Return true if the given type has a calling convention qualifier */
|
||||
{
|
||||
return (T->C & T_QUAL_CCONV) != 0;
|
||||
}
|
||||
#else
|
||||
# define IsQualCConv(T) (((T)->C & T_QUAL_CCONV) != 0)
|
||||
#endif
|
||||
|
||||
TypeCode AddrSizeQualifier (unsigned AddrSize);
|
||||
/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the address size */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode CodeAddrSizeQualifier (void)
|
||||
static inline TypeCode CodeAddrSizeQualifier (void)
|
||||
/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the code address size */
|
||||
{
|
||||
return AddrSizeQualifier (CodeAddrSize);
|
||||
}
|
||||
#else
|
||||
# define CodeAddrSizeQualifier() (AddrSizeQualifier (CodeAddrSize))
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE TypeCode DataAddrSizeQualifier (void)
|
||||
static inline TypeCode DataAddrSizeQualifier (void)
|
||||
/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the data address size */
|
||||
{
|
||||
return AddrSizeQualifier (DataAddrSize);
|
||||
}
|
||||
#else
|
||||
# define DataAddrSizeQualifier() (AddrSizeQualifier (DataAddrSize))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -155,18 +155,6 @@ int ED_GetStackOffs (const ExprDesc* Expr, int Offs)
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
int ED_IsLocQuasiConst (const ExprDesc* Expr)
|
||||
/* Return true if the expression is a constant location of some sort or on the
|
||||
** stack.
|
||||
*/
|
||||
{
|
||||
return ED_IsLocConst (Expr) || ED_IsLocStack (Expr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
int ED_IsLocZP (const ExprDesc* Expr)
|
||||
/* Return true if the expression is in a location on a zeropage */
|
||||
{
|
||||
@@ -178,27 +166,6 @@ int ED_IsLocZP (const ExprDesc* Expr)
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr)
|
||||
/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */
|
||||
{
|
||||
return ED_IsLocPrimary (Expr) || ED_IsLocExpr (Expr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
int ED_IsIndExpr (const ExprDesc* Expr)
|
||||
/* Check if the expression is a reference to its value */
|
||||
{
|
||||
return (Expr->Flags & E_ADDRESS_OF) == 0 &&
|
||||
!ED_IsLocNone (Expr) && !ED_IsLocPrimary (Expr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
int ED_YetToLoad (const ExprDesc* Expr)
|
||||
/* Check if the expression needs to be loaded somehow. */
|
||||
{
|
||||
@@ -209,29 +176,6 @@ int ED_YetToLoad (const ExprDesc* Expr)
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
int ED_IsAbs (const ExprDesc* Expr)
|
||||
/* Return true if the expression denotes a numeric value or address. */
|
||||
{
|
||||
return (Expr->Flags & (E_MASK_LOC)) == (E_LOC_NONE) ||
|
||||
(Expr->Flags & (E_MASK_LOC|E_ADDRESS_OF)) == (E_LOC_ABS|E_ADDRESS_OF);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
int ED_IsConstAbs (const ExprDesc* Expr)
|
||||
/* Return true if the expression denotes a constant absolute value. This can be
|
||||
** a numeric constant, cast to any type.
|
||||
*/
|
||||
{
|
||||
return ED_IsRVal (Expr) && ED_IsAbs (Expr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
int ED_IsConstAbsInt (const ExprDesc* Expr)
|
||||
/* Return true if the expression is a constant (numeric) integer. */
|
||||
{
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
|
||||
/* common */
|
||||
#include "fp.h"
|
||||
#include "inline.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "asmcode.h"
|
||||
@@ -235,25 +234,17 @@ ExprDesc* ED_Init (ExprDesc* Expr);
|
||||
|
||||
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_GetLoc (const ExprDesc* Expr)
|
||||
static inline int ED_GetLoc (const ExprDesc* Expr)
|
||||
/* Return the location flags from the expression */
|
||||
{
|
||||
return (Expr->Flags & E_MASK_LOC);
|
||||
}
|
||||
#else
|
||||
# define ED_GetLoc(Expr) ((Expr)->Flags & E_MASK_LOC)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_GetNeeds (const ExprDesc* Expr)
|
||||
static inline int ED_GetNeeds (const ExprDesc* Expr)
|
||||
/* Get flags about what the expression needs. */
|
||||
{
|
||||
return (Expr->Flags & E_MASK_NEED);
|
||||
}
|
||||
#else
|
||||
# define ED_GetNeeds(Expr) ((Expr)->Flags & E_MASK_NEED)
|
||||
#endif
|
||||
|
||||
const char* ED_GetLabelName (const ExprDesc* Expr, long Offs);
|
||||
/* Return the assembler label name of the given expression. Beware: This
|
||||
@@ -274,269 +265,164 @@ int ED_GetStackOffs (const ExprDesc* Expr, int Offs);
|
||||
|
||||
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsLocNone (const ExprDesc* Expr)
|
||||
static inline int ED_IsLocNone (const ExprDesc* Expr)
|
||||
/* Return true if the expression is an absolute value */
|
||||
{
|
||||
return (Expr->Flags & E_MASK_LOC) == E_LOC_NONE;
|
||||
}
|
||||
#else
|
||||
# define ED_IsLocNone(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_NONE)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsLocAbs (const ExprDesc* Expr)
|
||||
static inline int ED_IsLocAbs (const ExprDesc* Expr)
|
||||
/* Return true if the expression is referenced with an absolute address */
|
||||
{
|
||||
return (Expr->Flags & E_MASK_LOC) == E_LOC_ABS;
|
||||
}
|
||||
#else
|
||||
# define ED_IsLocAbs(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_ABS)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsLocRegister (const ExprDesc* Expr)
|
||||
static inline int ED_IsLocRegister (const ExprDesc* Expr)
|
||||
/* Return true if the expression is located in a register */
|
||||
{
|
||||
return (Expr->Flags & E_MASK_LOC) == E_LOC_REGISTER;
|
||||
}
|
||||
#else
|
||||
# define ED_IsLocRegister(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_REGISTER)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsLocStack (const ExprDesc* Expr)
|
||||
static inline int ED_IsLocStack (const ExprDesc* Expr)
|
||||
/* Return true if the expression is located on the stack */
|
||||
{
|
||||
return (Expr->Flags & E_MASK_LOC) == E_LOC_STACK;
|
||||
}
|
||||
#else
|
||||
# define ED_IsLocStack(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_STACK)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsLocPrimary (const ExprDesc* Expr)
|
||||
static inline int ED_IsLocPrimary (const ExprDesc* Expr)
|
||||
/* Return true if the expression is an expression in the primary */
|
||||
{
|
||||
return (Expr->Flags & E_MASK_LOC) == E_LOC_PRIMARY;
|
||||
}
|
||||
#else
|
||||
# define ED_IsLocPrimary(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_PRIMARY)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsLocExpr (const ExprDesc* Expr)
|
||||
static inline int ED_IsLocExpr (const ExprDesc* Expr)
|
||||
/* Return true if the expression is an expression referenced in the primary */
|
||||
{
|
||||
return (Expr->Flags & E_MASK_LOC) == E_LOC_EXPR;
|
||||
}
|
||||
#else
|
||||
# define ED_IsLocExpr(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_EXPR)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsLocLiteral (const ExprDesc* Expr)
|
||||
static inline int ED_IsLocLiteral (const ExprDesc* Expr)
|
||||
/* Return true if the expression is a string from the literal pool */
|
||||
{
|
||||
return (Expr->Flags & E_MASK_LOC) == E_LOC_LITERAL;
|
||||
}
|
||||
#else
|
||||
# define ED_IsLocLiteral(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_LITERAL)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsLocConst (const ExprDesc* Expr)
|
||||
static inline int ED_IsLocConst (const ExprDesc* Expr)
|
||||
/* Return true if the expression is a constant location of some sort */
|
||||
{
|
||||
return ((Expr)->Flags & E_MASK_LOC & ~E_LOC_CONST) == 0;
|
||||
}
|
||||
#else
|
||||
# define ED_IsLocConst(Expr) (((Expr)->Flags & E_MASK_LOC & ~E_LOC_CONST) == 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsLocQuasiConst (const ExprDesc* Expr)
|
||||
static inline int ED_IsLocQuasiConst (const ExprDesc* Expr)
|
||||
/* Return true if the expression is a constant location of some sort or on the
|
||||
** stack.
|
||||
*/
|
||||
{
|
||||
return ED_IsLocConst (Expr) || ED_IsLocStack (Expr);
|
||||
}
|
||||
#else
|
||||
int ED_IsLocQuasiConst (const ExprDesc* Expr);
|
||||
/* Return true if the expression denotes a constant address of some sort. This
|
||||
** can be the address of a global variable (maybe with offset) or similar.
|
||||
*/
|
||||
#endif
|
||||
|
||||
int ED_IsLocZP (const ExprDesc* Expr);
|
||||
/* Return true if the expression is in a location on a zeropage */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr)
|
||||
static inline int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr)
|
||||
/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */
|
||||
{
|
||||
return ED_IsLocPrimary (Expr) || ED_IsLocExpr (Expr);
|
||||
}
|
||||
#else
|
||||
int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr);
|
||||
/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_NeedsPrimary (const ExprDesc* Expr)
|
||||
static inline int ED_NeedsPrimary (const ExprDesc* Expr)
|
||||
/* Check if the expression needs to be in Primary. */
|
||||
{
|
||||
return (Expr->Flags & E_MASK_NEED) == E_NEED_EAX;
|
||||
}
|
||||
#else
|
||||
# define ED_NeedsPrimary(Expr) (((Expr)->Flags & E_MASK_NEED) == E_NEED_EAX)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_NeedsTest (const ExprDesc* Expr)
|
||||
static inline int ED_NeedsTest (const ExprDesc* Expr)
|
||||
/* Check if the expression needs a test. */
|
||||
{
|
||||
return (Expr->Flags & E_NEED_TEST) != 0;
|
||||
}
|
||||
#else
|
||||
# define ED_NeedsTest(Expr) (((Expr)->Flags & E_NEED_TEST) != 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsTested (const ExprDesc* Expr)
|
||||
static inline int ED_IsTested (const ExprDesc* Expr)
|
||||
/* Check if the expression has set the condition codes. */
|
||||
{
|
||||
return (Expr->Flags & E_CC_SET) != 0;
|
||||
}
|
||||
#else
|
||||
# define ED_IsTested(Expr) (((Expr)->Flags & E_CC_SET) != 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_YetToTest (const ExprDesc* Expr)
|
||||
static inline int ED_YetToTest (const ExprDesc* Expr)
|
||||
/* Check if the expression needs to be tested but not yet. */
|
||||
{
|
||||
return ((Expr)->Flags & (E_NEED_TEST | E_CC_SET)) == E_NEED_TEST;
|
||||
}
|
||||
#else
|
||||
# define ED_YetToTest(Expr) (((Expr)->Flags & (E_NEED_TEST | E_CC_SET)) == E_NEED_TEST)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsLoaded (const ExprDesc* Expr)
|
||||
static inline int ED_IsLoaded (const ExprDesc* Expr)
|
||||
/* Check if the expression is loaded.
|
||||
** NOTE: This is currently unused and not working due to code complexity.
|
||||
*/
|
||||
{
|
||||
return (Expr->Flags & E_LOADED) != 0;
|
||||
}
|
||||
#else
|
||||
# define ED_IsLoaded(Expr) (((Expr)->Flags & E_LOADED) != 0)
|
||||
#endif
|
||||
|
||||
int ED_YetToLoad (const ExprDesc* Expr);
|
||||
/* Check if the expression is yet to be loaded somehow. */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_NeedsConst (const ExprDesc* Expr)
|
||||
static inline int ED_NeedsConst (const ExprDesc* Expr)
|
||||
/* Check if the expression need be immutable */
|
||||
{
|
||||
return (Expr->Flags & E_EVAL_IMMUTABLE_RESULT) == E_EVAL_IMMUTABLE_RESULT;
|
||||
}
|
||||
#else
|
||||
# define ED_NeedsConst(Expr) (((Expr)->Flags & E_EVAL_IMMUTABLE_RESULT) == E_EVAL_IMMUTABLE_RESULT)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsUneval (const ExprDesc* Expr)
|
||||
static inline int ED_IsUneval (const ExprDesc* Expr)
|
||||
/* Check if the expression is not to be evaluated */
|
||||
{
|
||||
return (Expr->Flags & E_EVAL_UNEVAL) == E_EVAL_UNEVAL;
|
||||
}
|
||||
#else
|
||||
# define ED_IsUneval(Expr) (((Expr)->Flags & E_EVAL_UNEVAL) == E_EVAL_UNEVAL)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_MayHaveNoEffect (const ExprDesc* Expr)
|
||||
static inline int ED_MayHaveNoEffect (const ExprDesc* Expr)
|
||||
/* Check if the expression may be present without effects */
|
||||
{
|
||||
return (Expr->Flags & E_EVAL_MAYBE_UNUSED) == E_EVAL_MAYBE_UNUSED;
|
||||
}
|
||||
#else
|
||||
# define ED_MayHaveNoEffect(Expr) (((Expr)->Flags & E_EVAL_MAYBE_UNUSED) == E_EVAL_MAYBE_UNUSED)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsAddrExpr (const ExprDesc* Expr)
|
||||
static inline int ED_IsAddrExpr (const ExprDesc* Expr)
|
||||
/* Check if the expression is taken address of instead of its value.
|
||||
*/
|
||||
{
|
||||
return (Expr->Flags & E_ADDRESS_OF) != 0;
|
||||
}
|
||||
#else
|
||||
# define ED_IsAddrExpr(Expr) (((Expr)->Flags & E_ADDRESS_OF) != 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsIndExpr (const ExprDesc* Expr)
|
||||
static inline int ED_IsIndExpr (const ExprDesc* Expr)
|
||||
/* Check if the expression is a reference to its value */
|
||||
{
|
||||
return (Expr->Flags & E_ADDRESS_OF) == 0 &&
|
||||
!ED_IsLocNone (Expr) && !ED_IsLocPrimary (Expr);
|
||||
}
|
||||
#else
|
||||
int ED_IsIndExpr (const ExprDesc* Expr);
|
||||
/* Check if the expression is a reference to its value */
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsLVal (const ExprDesc* Expr)
|
||||
static inline int ED_IsLVal (const ExprDesc* Expr)
|
||||
/* Return true if the expression is a reference */
|
||||
{
|
||||
return ((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_LVAL;
|
||||
}
|
||||
#else
|
||||
# define ED_IsLVal(Expr) (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_LVAL)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsRVal (const ExprDesc* Expr)
|
||||
static inline int ED_IsRVal (const ExprDesc* Expr)
|
||||
/* Return true if the expression is an rvalue */
|
||||
{
|
||||
return ((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL;
|
||||
}
|
||||
#else
|
||||
# define ED_IsRVal(Expr) (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsAbs (const ExprDesc* Expr)
|
||||
static inline int ED_IsAbs (const ExprDesc* Expr)
|
||||
/* Return true if the expression denotes a numeric value or address. */
|
||||
{
|
||||
return (Expr->Flags & (E_MASK_LOC)) == (E_LOC_NONE) ||
|
||||
(Expr->Flags & (E_MASK_LOC|E_ADDRESS_OF)) == (E_LOC_ABS|E_ADDRESS_OF);
|
||||
}
|
||||
#else
|
||||
int ED_IsAbs (const ExprDesc* Expr);
|
||||
/* Return true if the expression denotes a numeric value or address. */
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsConstAbs (const ExprDesc* Expr)
|
||||
static inline int ED_IsConstAbs (const ExprDesc* Expr)
|
||||
/* Return true if the expression denotes a constant absolute value. This can be
|
||||
** a numeric constant, cast to any type.
|
||||
*/
|
||||
{
|
||||
return ED_IsRVal (Expr) && ED_IsAbs (Expr);
|
||||
}
|
||||
#else
|
||||
int ED_IsConstAbs (const ExprDesc* Expr);
|
||||
/* Return true if the expression denotes a constant absolute value. This can be
|
||||
** a numeric constant, cast to any type.
|
||||
*/
|
||||
#endif
|
||||
|
||||
int ED_IsConstAbsInt (const ExprDesc* Expr);
|
||||
/* Return true if the expression is a constant (numeric) integer. */
|
||||
@@ -623,8 +509,7 @@ ExprDesc* ED_MakeConstBool (ExprDesc* Expr, long Value);
|
||||
ExprDesc* ED_FinalizeRValLoad (ExprDesc* Expr);
|
||||
/* Finalize the result of LoadExpr to be an rvalue in the primary register */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void ED_MarkExprAsLVal (ExprDesc* Expr)
|
||||
static inline void ED_MarkExprAsLVal (ExprDesc* Expr)
|
||||
/* Mark the expression as an lvalue.
|
||||
** HINT: Consider using ED_IndExpr instead of this, unless you know what
|
||||
** consequence there will be, as there are both a big part in the code
|
||||
@@ -633,12 +518,8 @@ INLINE void ED_MarkExprAsLVal (ExprDesc* Expr)
|
||||
{
|
||||
Expr->Flags |= E_RTYPE_LVAL;
|
||||
}
|
||||
#else
|
||||
# define ED_MarkExprAsLVal(Expr) do { (Expr)->Flags |= E_RTYPE_LVAL; } while (0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void ED_MarkExprAsRVal (ExprDesc* Expr)
|
||||
static inline void ED_MarkExprAsRVal (ExprDesc* Expr)
|
||||
/* Mark the expression as an rvalue.
|
||||
** HINT: Consider using ED_AddrExpr instead of this, unless you know what
|
||||
** consequence there will be, as there are both a big part in the code
|
||||
@@ -647,9 +528,6 @@ INLINE void ED_MarkExprAsRVal (ExprDesc* Expr)
|
||||
{
|
||||
Expr->Flags &= ~E_RTYPE_LVAL;
|
||||
}
|
||||
#else
|
||||
# define ED_MarkExprAsRVal(Expr) do { (Expr)->Flags &= ~E_RTYPE_LVAL; } while (0)
|
||||
#endif
|
||||
|
||||
void ED_AddrExpr (ExprDesc* Expr);
|
||||
/* Take address of Expr */
|
||||
@@ -657,59 +535,38 @@ void ED_AddrExpr (ExprDesc* Expr);
|
||||
void ED_IndExpr (ExprDesc* Expr);
|
||||
/* Dereference Expr */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void ED_RequireTest (ExprDesc* Expr)
|
||||
static inline void ED_RequireTest (ExprDesc* Expr)
|
||||
/* Mark the expression for a test. */
|
||||
{
|
||||
Expr->Flags |= E_NEED_TEST;
|
||||
}
|
||||
#else
|
||||
# define ED_RequireTest(Expr) do { (Expr)->Flags |= E_NEED_TEST; } while (0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void ED_RequireNoTest (ExprDesc* Expr)
|
||||
static inline void ED_RequireNoTest (ExprDesc* Expr)
|
||||
/* Mark the expression not for a test. */
|
||||
{
|
||||
Expr->Flags &= ~E_NEED_TEST;
|
||||
}
|
||||
#else
|
||||
# define ED_RequireNoTest(Expr) do { (Expr)->Flags &= ~E_NEED_TEST; } while (0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void ED_TestDone (ExprDesc* Expr)
|
||||
static inline void ED_TestDone (ExprDesc* Expr)
|
||||
/* Mark the expression as tested and condition codes set. */
|
||||
{
|
||||
Expr->Flags |= E_CC_SET;
|
||||
}
|
||||
#else
|
||||
# define ED_TestDone(Expr) \
|
||||
do { (Expr)->Flags |= E_CC_SET; } while (0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void ED_MarkAsUntested (ExprDesc* Expr)
|
||||
static inline void ED_MarkAsUntested (ExprDesc* Expr)
|
||||
/* Mark the expression as not tested (condition codes not set). */
|
||||
{
|
||||
Expr->Flags &= ~E_CC_SET;
|
||||
}
|
||||
#else
|
||||
# define ED_MarkAsUntested(Expr) do { (Expr)->Flags &= ~E_CC_SET; } while (0)
|
||||
#endif
|
||||
|
||||
void ED_MarkForUneval (ExprDesc* Expr);
|
||||
/* Mark the expression as not to be evaluated */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void ED_PropagateFrom (ExprDesc* Expr, const ExprDesc* SubExpr)
|
||||
static inline void ED_PropagateFrom (ExprDesc* Expr, const ExprDesc* SubExpr)
|
||||
/* Propagate viral flags from subexpression */
|
||||
{
|
||||
Expr->Flags |= SubExpr->Flags & E_MASK_VIRAL;
|
||||
}
|
||||
#else
|
||||
# define ED_PropagateFrom(Expr, SubExpr) (void)((Expr)->Flags |= (SubExpr)->Flags & E_MASK_VIRAL)
|
||||
#endif
|
||||
|
||||
const Type* ReplaceType (ExprDesc* Expr, const Type* NewType);
|
||||
/* Replace the type of Expr by a copy of Newtype and return the old type string */
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
|
||||
/* common */
|
||||
#include "coll.h"
|
||||
#include "inline.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
|
||||
@@ -109,15 +108,11 @@ void FreeUndefinedMacros (void);
|
||||
Macro* FindMacro (const char* Name);
|
||||
/* Find a macro with the given name. Return the macro definition or NULL */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsMacro (const char* Name)
|
||||
static inline int IsMacro (const char* Name)
|
||||
/* Return true if the given name is the name of a macro, return false otherwise */
|
||||
{
|
||||
return FindMacro (Name) != 0;
|
||||
}
|
||||
#else
|
||||
# define IsMacro(Name) (FindMacro (Name) != 0)
|
||||
#endif
|
||||
|
||||
int FindMacroParam (const Macro* M, const char* Param);
|
||||
/* Search for a macro parameter. If found, return the index of the parameter.
|
||||
|
||||
@@ -38,11 +38,6 @@
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "inline.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
@@ -216,27 +211,19 @@ const OPCDesc* FindOP65 (const char* OPC);
|
||||
unsigned GetInsnSize (opc_t OPC, am_t AM);
|
||||
/* Return the size of the given instruction */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE const OPCDesc* GetOPCDesc (opc_t OPC)
|
||||
static inline const OPCDesc* GetOPCDesc (opc_t OPC)
|
||||
/* Get an opcode description */
|
||||
{
|
||||
/* Return the description */
|
||||
return &OPCTable [OPC];
|
||||
}
|
||||
#else
|
||||
# define GetOPCDesc(OPC) (&OPCTable [(OPC)])
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned GetOPCInfo (opc_t OPC)
|
||||
static inline unsigned GetOPCInfo (opc_t OPC)
|
||||
/* Get opcode information */
|
||||
{
|
||||
/* Return the info */
|
||||
return OPCTable[OPC].Info;
|
||||
}
|
||||
#else
|
||||
# define GetOPCInfo(OPC) (OPCTable[(OPC)].Info)
|
||||
#endif
|
||||
|
||||
unsigned char GetAMUseInfo (am_t AM);
|
||||
/* Get usage info for the given addressing mode (addressing modes that use
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
/* common */
|
||||
#include "chartype.h"
|
||||
#include "check.h"
|
||||
#include "inline.h"
|
||||
#include "print.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
|
||||
@@ -111,44 +111,6 @@ void RC_Dump (FILE* F, const RegContents* RC)
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
int PStatesAreKnown (unsigned short PFlags, unsigned WhatStates)
|
||||
/* Return true if all queried processor states are known.
|
||||
** Note: WhatStates takes PSTATE_* rather than PFVAL_*.
|
||||
*/
|
||||
{
|
||||
return ((PFlags << (PSTATE_BITS_SHIFT - 8)) & WhatStates & PSTATE_BITS_MASK) == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
int PStatesAreSet (unsigned short PFlags, unsigned WhatStates)
|
||||
/* Return true if all queried processor states are known to be set.
|
||||
** Note: WhatStates takes PSTATE_* rather than PFVAL_*.
|
||||
*/
|
||||
{
|
||||
return (PFlags & (WhatStates >> (PSTATE_BITS_SHIFT - 8))) == 0 &&
|
||||
(PFlags & (WhatStates >> PSTATE_BITS_SHIFT)) == WhatStates >> PSTATE_BITS_SHIFT;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
int PStatesAreClear (unsigned short PFlags, unsigned WhatStates)
|
||||
/* Return true if all queried processor states are known to be cleared.
|
||||
** Note: WhatStates takes PSTATE_* rather than PFVAL_*.
|
||||
*/
|
||||
{
|
||||
return (PFlags & (WhatStates >> (PSTATE_BITS_SHIFT - 8))) == 0 &&
|
||||
(PFlags & (WhatStates >> PSTATE_BITS_SHIFT)) == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
RegInfo* NewRegInfo (const RegContents* RC)
|
||||
/* Allocate a new register info, initialize and return it. If RC is not
|
||||
** a NULL pointer, it is used to initialize both, the input and output
|
||||
|
||||
@@ -40,9 +40,6 @@
|
||||
|
||||
#include <stdio.h> /* ### */
|
||||
|
||||
/* common */
|
||||
#include "inline.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -160,52 +157,35 @@ void RC_InvalidatePS (RegContents* C);
|
||||
void RC_Dump (FILE* F, const RegContents* RC);
|
||||
/* Dump the contents of the given RegContents struct */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int RegValIsKnown (short Val)
|
||||
static inline int RegValIsKnown (short Val)
|
||||
/* Return true if the register value is known */
|
||||
{
|
||||
return (Val >= 0);
|
||||
}
|
||||
#else
|
||||
# define RegValIsKnown(S) ((S) >= 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int RegValIsUnknown (short Val)
|
||||
static inline int RegValIsUnknown (short Val)
|
||||
/* Return true if the register value is not known */
|
||||
{
|
||||
return (Val < 0);
|
||||
}
|
||||
#else
|
||||
# define RegValIsUnknown(S) ((S) < 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int PStatesAreKnown (unsigned short PFlags, unsigned WhatStates)
|
||||
static inline int PStatesAreKnown (unsigned short PFlags, unsigned WhatStates)
|
||||
/* Return true if all queried processor states are known.
|
||||
** Note: WhatStates takes PSTATE_* rather than PFVAL_*.
|
||||
*/
|
||||
{
|
||||
return ((PFlags << (PSTATE_BITS_SHIFT - 8)) & WhatStates & PSTATE_BITS_MASK) == 0;
|
||||
}
|
||||
#else
|
||||
int PStatesAreKnown (unsigned short PFlags, unsigned WhatStates);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int PStatesAreUnknown (unsigned short PFlags, unsigned WhatStates)
|
||||
static inline int PStatesAreUnknown (unsigned short PFlags, unsigned WhatStates)
|
||||
/* Return true if any queried processor states are unknown.
|
||||
** Note: WhatStates takes PSTATE_* rather than PFVAL_*.
|
||||
*/
|
||||
{
|
||||
return !PStatesAreKnown (PFlags, WhatStates);
|
||||
}
|
||||
#else
|
||||
# define PStatesAreUnknown(V, B) (!PStatesAreKnown (V, B))
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int PStatesAreSet (unsigned short PFlags, unsigned WhatStates)
|
||||
static inline int PStatesAreSet (unsigned short PFlags, unsigned WhatStates)
|
||||
/* Return true if all queried processor states are known to be set.
|
||||
** Note: WhatStates takes PSTATE_* rather than PFVAL_*.
|
||||
*/
|
||||
@@ -213,12 +193,8 @@ INLINE int PStatesAreSet (unsigned short PFlags, unsigned WhatStates)
|
||||
return (PFlags & (WhatStates >> (PSTATE_BITS_SHIFT - 8))) == 0 &&
|
||||
(PFlags & (WhatStates >> PSTATE_BITS_SHIFT)) == WhatStates >> PSTATE_BITS_SHIFT;
|
||||
}
|
||||
#else
|
||||
int PStatesAreSet (unsigned short PFlags, unsigned WhatStates);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int PStatesAreClear (unsigned short PFlags, unsigned WhatStates)
|
||||
static inline int PStatesAreClear (unsigned short PFlags, unsigned WhatStates)
|
||||
/* Return true if the queried processor states are known to be cleared.
|
||||
** Note: WhatStates takes PSTATE_* rather than PFVAL_*.
|
||||
*/
|
||||
@@ -226,9 +202,6 @@ INLINE int PStatesAreClear (unsigned short PFlags, unsigned WhatStates)
|
||||
return (PFlags & (WhatStates >> (PSTATE_BITS_SHIFT - 8))) == 0 &&
|
||||
(PFlags & (WhatStates >> PSTATE_BITS_SHIFT)) == 0;
|
||||
}
|
||||
#else
|
||||
int PStatesAreClear (unsigned short PFlags, unsigned WhatStates);
|
||||
#endif
|
||||
|
||||
RegInfo* NewRegInfo (const RegContents* RC);
|
||||
/* Allocate a new register info, initialize and return it. If RC is not
|
||||
|
||||
@@ -235,47 +235,29 @@ extern unsigned InPragmaParser; /* Depth of pragma parser calling */
|
||||
|
||||
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int TokIsPunc (const Token* T)
|
||||
static inline int TokIsPunc (const Token* T)
|
||||
/* Return true if the token is a punctuator */
|
||||
{
|
||||
return (T->Tok >= TOK_FIRST_PUNC && T->Tok <= TOK_LAST_PUNC);
|
||||
}
|
||||
#else
|
||||
# define TokIsPunc(T) \
|
||||
((T)->Tok >= TOK_FIRST_PUNC && (T)->Tok <= TOK_LAST_PUNC)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int TokIsStorageClass (const Token* T)
|
||||
static inline int TokIsStorageClass (const Token* T)
|
||||
/* Return true if the token is a storage class specifier */
|
||||
{
|
||||
return (T->Tok >= TOK_FIRST_STORAGE_CLASS && T->Tok <= TOK_LAST_STORAGE_CLASS);
|
||||
}
|
||||
#else
|
||||
# define TokIsStorageClass(T) \
|
||||
((T)->Tok >= TOK_FIRST_STORAGE_CLASS && (T)->Tok <= TOK_LAST_STORAGE_CLASS)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int TokIsType (const Token* T)
|
||||
static inline int TokIsType (const Token* T)
|
||||
/* Return true if the token is a type */
|
||||
{
|
||||
return (T->Tok >= TOK_FIRST_TYPE && T->Tok <= TOK_LAST_TYPE);
|
||||
}
|
||||
#else
|
||||
# define TokIsType(T) ((T)->Tok >= TOK_FIRST_TYPE && (T)->Tok <= TOK_LAST_TYPE)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int TokIsTypeQual (const Token* T)
|
||||
static inline int TokIsTypeQual (const Token* T)
|
||||
/* Return true if the token is a type qualifier */
|
||||
{
|
||||
return (T->Tok >= TOK_FIRST_TYPEQUAL && T->Tok <= TOK_LAST_TYPEQUAL);
|
||||
}
|
||||
#else
|
||||
# define TokIsTypeQual(T) ((T)->Tok >= TOK_FIRST_TYPEQUAL && (T)->Tok <= TOK_LAST_TYPEQUAL)
|
||||
#endif
|
||||
|
||||
int TokIsFuncSpec (const Token* T);
|
||||
/* Return true if the token is a function specifier */
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
|
||||
/* common */
|
||||
#include "coll.h"
|
||||
#include "inline.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "datatype.h"
|
||||
@@ -262,118 +261,74 @@ void DumpSymEntry (FILE* F, const SymEntry* E);
|
||||
int SymIsOutputFunc (const SymEntry* Sym);
|
||||
/* Return true if this is a function that must be output */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SymIsArray (const SymEntry* Sym)
|
||||
static inline int SymIsArray (const SymEntry* Sym)
|
||||
/* Return true if the given entry is an array entry */
|
||||
{
|
||||
return ((Sym->Flags & SC_TYPEMASK) == SC_ARRAY);
|
||||
}
|
||||
#else
|
||||
# define SymIsArray(Sym) (((Sym)->Flags & SC_TYPEMASK) == SC_ARRAY)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SymIsBitField (const SymEntry* Sym)
|
||||
static inline int SymIsBitField (const SymEntry* Sym)
|
||||
/* Return true if the given entry is a bit-field entry */
|
||||
{
|
||||
return ((Sym->Flags & SC_TYPEMASK) == SC_BITFIELD);
|
||||
}
|
||||
#else
|
||||
# define SymIsBitField(Sym) (((Sym)->Flags & SC_TYPEMASK) == SC_BITFIELD)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SymIsLabel (const SymEntry* Sym)
|
||||
static inline int SymIsLabel (const SymEntry* Sym)
|
||||
/* Return true if the given entry is a label entry */
|
||||
{
|
||||
return ((Sym)->Flags & SC_TYPEMASK) == SC_LABEL;
|
||||
}
|
||||
#else
|
||||
# define SymIsLabel(Sym) (((Sym)->Flags & SC_TYPEMASK) == SC_LABEL)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SymIsTypeDef (const SymEntry* Sym)
|
||||
static inline int SymIsTypeDef (const SymEntry* Sym)
|
||||
/* Return true if the given entry is a typedef entry */
|
||||
{
|
||||
return ((Sym->Flags & SC_TYPEMASK) == SC_TYPEDEF);
|
||||
}
|
||||
#else
|
||||
# define SymIsTypeDef(Sym) (((Sym)->Flags & SC_TYPEMASK) == SC_TYPEDEF)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SymIsDef (const SymEntry* Sym)
|
||||
static inline int SymIsDef (const SymEntry* Sym)
|
||||
/* Return true if the given entry is defined */
|
||||
{
|
||||
return ((Sym->Flags & SC_DEF) == SC_DEF);
|
||||
}
|
||||
#else
|
||||
# define SymIsDef(Sym) (((Sym)->Flags & SC_DEF) == SC_DEF)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SymIsRef (const SymEntry* Sym)
|
||||
static inline int SymIsRef (const SymEntry* Sym)
|
||||
/* Return true if the given entry is referenced */
|
||||
{
|
||||
return ((Sym->Flags & SC_REF) == SC_REF);
|
||||
}
|
||||
#else
|
||||
# define SymIsRef(Sym) (((Sym)->Flags & SC_REF) == SC_REF)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SymIsRegVar (const SymEntry* Sym)
|
||||
static inline int SymIsRegVar (const SymEntry* Sym)
|
||||
/* Return true if the given entry is a register variable */
|
||||
{
|
||||
return ((Sym->Flags & (SC_STORAGEMASK | SC_TYPEMASK)) == (SC_REGISTER | SC_NONE));
|
||||
}
|
||||
#else
|
||||
# define SymIsRegVar(Sym) (((Sym)->Flags & (SC_STORAGEMASK | SC_TYPEMASK)) == (SC_REGISTER | SC_NONE))
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SymHasFlexibleArrayMember (const SymEntry* Sym)
|
||||
static inline int SymHasFlexibleArrayMember (const SymEntry* Sym)
|
||||
/* Return true if the given entry has a flexible array member */
|
||||
{
|
||||
return ((Sym->Flags & SC_HAVEFAM) == SC_HAVEFAM);
|
||||
}
|
||||
#else
|
||||
# define SymHasFlexibleArrayMember(Sym) (((Sym)->Flags & SC_HAVEFAM) == SC_HAVEFAM)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SymHasConstMember (const SymEntry* Sym)
|
||||
static inline int SymHasConstMember (const SymEntry* Sym)
|
||||
/* Return true if the given entry has a const member */
|
||||
{
|
||||
return ((Sym->Flags & SC_HAVECONST) == SC_HAVECONST);
|
||||
}
|
||||
#else
|
||||
# define SymHasConstMember(Sym) (((Sym)->Flags & SC_HAVECONST) == SC_HAVECONST)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE const char* SymGetAsmName (const SymEntry* Sym)
|
||||
static inline const char* SymGetAsmName (const SymEntry* Sym)
|
||||
/* Return the assembler label name for the symbol (beware: may be NULL!) */
|
||||
{
|
||||
return Sym->AsmName;
|
||||
}
|
||||
#else
|
||||
# define SymGetAsmName(Sym) ((Sym)->AsmName)
|
||||
#endif
|
||||
|
||||
const DeclAttr* SymGetAttr (const SymEntry* Sym, DeclAttrType AttrType);
|
||||
/* Return an attribute for this symbol or NULL if the attribute does not exist */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SymHasAttr (const SymEntry* Sym, DeclAttrType A)
|
||||
static inline int SymHasAttr (const SymEntry* Sym, DeclAttrType A)
|
||||
/* Return true if the symbol has the given attribute */
|
||||
{
|
||||
return (SymGetAttr (Sym, A) != 0);
|
||||
}
|
||||
#else
|
||||
# define SymHasAttr(Sym, A) (SymGetAttr (Sym, A) != 0)
|
||||
#endif
|
||||
|
||||
void SymUseAttr (SymEntry* Sym, struct Declarator* D);
|
||||
/* Use the attributes from the declarator for this symbol */
|
||||
|
||||
@@ -86,6 +86,7 @@
|
||||
<ClInclude Include="common\check.h" />
|
||||
<ClInclude Include="common\cmdline.h" />
|
||||
<ClInclude Include="common\coll.h" />
|
||||
<ClInclude Include="common\consprop.h" />
|
||||
<ClInclude Include="common\cpu.h" />
|
||||
<ClInclude Include="common\debugflag.h" />
|
||||
<ClInclude Include="common\exprdefs.h" />
|
||||
@@ -139,6 +140,7 @@
|
||||
<ClCompile Include="common\check.c" />
|
||||
<ClCompile Include="common\cmdline.c" />
|
||||
<ClCompile Include="common\coll.c" />
|
||||
<ClCompile Include="common\consprop.c" />
|
||||
<ClCompile Include="common\cpu.c" />
|
||||
<ClCompile Include="common\debugflag.c" />
|
||||
<ClCompile Include="common\exprdefs.c" />
|
||||
|
||||
@@ -38,11 +38,6 @@
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "inline.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2026, Kugelfuhr */
|
||||
/* (C) 2025, Kugelfuhr */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
|
||||
@@ -40,8 +40,6 @@
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
/* common */
|
||||
#include "inline.h"
|
||||
|
||||
|
||||
/* This module contains replacements for functions in ctype.h besides other
|
||||
@@ -73,15 +71,11 @@ int IsAscii (char C);
|
||||
int IsBlank (char C);
|
||||
/* Check for a space or tab */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IsControl (char C)
|
||||
static inline int IsControl (char C)
|
||||
/* Check for control chars */
|
||||
{
|
||||
return iscntrl ((unsigned char) C);
|
||||
}
|
||||
#else
|
||||
# define IsControl(C) iscntrl (C)
|
||||
#endif
|
||||
|
||||
int IsSpace (char C);
|
||||
/* Check for any white space characters */
|
||||
|
||||
@@ -155,89 +155,6 @@ void CollInsert (Collection* C, void* Item, unsigned Index)
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
void CollAppend (Collection* C, void* Item)
|
||||
/* Append an item to the end of the collection */
|
||||
{
|
||||
/* Insert the item at the end of the current list */
|
||||
CollInsert (C, Item, C->Count);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
void* CollAt (const Collection* C, unsigned Index)
|
||||
/* Return the item at the given index */
|
||||
{
|
||||
/* Check the index */
|
||||
PRECONDITION (Index < C->Count);
|
||||
|
||||
/* Return the element */
|
||||
return C->Items[Index];
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
const void* CollConstAt (const Collection* C, unsigned Index)
|
||||
/* Return the item at the given index */
|
||||
{
|
||||
/* Check the index */
|
||||
PRECONDITION (Index < C->Count);
|
||||
|
||||
/* Return the element */
|
||||
return C->Items[Index];
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
void* CollLast (Collection* C)
|
||||
/* Return the last item in a collection */
|
||||
{
|
||||
/* We must have at least one entry */
|
||||
PRECONDITION (C->Count > 0);
|
||||
|
||||
/* Return the element */
|
||||
return C->Items[C->Count-1];
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
const void* CollConstLast (const Collection* C)
|
||||
/* Return the last item in a collection */
|
||||
{
|
||||
/* We must have at least one entry */
|
||||
PRECONDITION (C->Count > 0);
|
||||
|
||||
/* Return the element */
|
||||
return C->Items[C->Count-1];
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
void* CollPop (Collection* C)
|
||||
/* Remove the last segment from the stack and return it. Calls FAIL if the
|
||||
** collection is empty.
|
||||
*/
|
||||
{
|
||||
/* We must have at least one entry */
|
||||
PRECONDITION (C->Count > 0);
|
||||
|
||||
/* Return the element */
|
||||
return C->Items[--C->Count];
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
int CollIndex (Collection* C, const void* Item)
|
||||
/* Return the index of the given item in the collection. Return -1 if the
|
||||
** item was not found in the collection.
|
||||
@@ -290,22 +207,6 @@ void CollDeleteItem (Collection* C, const void* Item)
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
void CollReplace (Collection* C, void* Item, unsigned Index)
|
||||
/* Replace the item at the given position. The old item will not be freed,
|
||||
** just the pointer will get replaced.
|
||||
*/
|
||||
{
|
||||
/* Check the index */
|
||||
PRECONDITION (Index < C->Count);
|
||||
|
||||
/* Replace the item pointer */
|
||||
C->Items[Index] = Item;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void CollReplaceExpand (Collection* C, void* Item, unsigned Index)
|
||||
/* If Index is a valid index for the collection, replace the item at this
|
||||
** position by the one passed. If the collection is too small, expand it,
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
/* common */
|
||||
#include "attrib.h"
|
||||
#include "check.h"
|
||||
#include "inline.h"
|
||||
|
||||
|
||||
|
||||
@@ -96,33 +95,23 @@ void CollGrow (Collection* C, unsigned Size);
|
||||
** of items to be placed in the collection is known in advance.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned CollCount (const Collection* C)
|
||||
static inline unsigned CollCount (const Collection* C)
|
||||
/* Return the number of items in the collection */
|
||||
{
|
||||
return C->Count;
|
||||
}
|
||||
#else
|
||||
# define CollCount(C) (C)->Count
|
||||
#endif
|
||||
|
||||
void CollInsert (Collection* C, void* Item, unsigned Index);
|
||||
/* Insert the data at the given position in the collection */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void CollAppend (Collection* C, void* Item)
|
||||
static inline void CollAppend (Collection* C, void* Item)
|
||||
/* Append an item to the end of the collection */
|
||||
{
|
||||
/* Insert the item at the end of the current list */
|
||||
CollInsert (C, Item, C->Count);
|
||||
}
|
||||
#else
|
||||
void CollAppend (Collection* C, void* Item);
|
||||
/* Append an item to the end of the collection */
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void* CollAt (const Collection* C, unsigned Index)
|
||||
static inline void* CollAt (const Collection* C, unsigned Index)
|
||||
/* Return the item at the given index */
|
||||
{
|
||||
/* Check the index */
|
||||
@@ -131,24 +120,15 @@ INLINE void* CollAt (const Collection* C, unsigned Index)
|
||||
/* Return the element */
|
||||
return C->Items[Index];
|
||||
}
|
||||
#else
|
||||
void* CollAt (const Collection* C, unsigned Index);
|
||||
/* Return the item at the given index */
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void* CollAtUnchecked (const Collection* C, unsigned Index)
|
||||
static inline void* CollAtUnchecked (const Collection* C, unsigned Index)
|
||||
/* Return the item at the given index */
|
||||
{
|
||||
/* Return the element */
|
||||
return C->Items[Index];
|
||||
}
|
||||
#else
|
||||
# define CollAtUnchecked(C, Index) ((C)->Items[(Index)])
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE const void* CollConstAt (const Collection* C, unsigned Index)
|
||||
static inline const void* CollConstAt (const Collection* C, unsigned Index)
|
||||
/* Return the item at the given index */
|
||||
{
|
||||
/* Check the index */
|
||||
@@ -157,13 +137,8 @@ INLINE const void* CollConstAt (const Collection* C, unsigned Index)
|
||||
/* Return the element */
|
||||
return C->Items[Index];
|
||||
}
|
||||
#else
|
||||
const void* CollConstAt (const Collection* C, unsigned Index);
|
||||
/* Return the item at the given index */
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void* CollLast (Collection* C)
|
||||
static inline void* CollLast (Collection* C)
|
||||
/* Return the last item in a collection */
|
||||
{
|
||||
/* We must have at least one entry */
|
||||
@@ -172,13 +147,8 @@ INLINE void* CollLast (Collection* C)
|
||||
/* Return the element */
|
||||
return C->Items[C->Count-1];
|
||||
}
|
||||
#else
|
||||
void* CollLast (Collection* C);
|
||||
/* Return the last item in a collection */
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE const void* CollConstLast (const Collection* C)
|
||||
static inline const void* CollConstLast (const Collection* C)
|
||||
/* Return the last item in a collection */
|
||||
{
|
||||
/* We must have at least one entry */
|
||||
@@ -187,13 +157,8 @@ INLINE const void* CollConstLast (const Collection* C)
|
||||
/* Return the element */
|
||||
return C->Items[C->Count-1];
|
||||
}
|
||||
#else
|
||||
const void* CollConstLast (const Collection* C);
|
||||
/* Return the last item in a collection */
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void* CollPop (Collection* C)
|
||||
static inline void* CollPop (Collection* C)
|
||||
/* Remove the last segment from the stack and return it. Calls FAIL if the
|
||||
** collection is empty.
|
||||
*/
|
||||
@@ -204,12 +169,6 @@ INLINE void* CollPop (Collection* C)
|
||||
/* Return the element */
|
||||
return C->Items[--C->Count];
|
||||
}
|
||||
#else
|
||||
void* CollPop (Collection* C);
|
||||
/* Remove the last segment from the stack and return it. Calls FAIL if the
|
||||
** collection is empty.
|
||||
*/
|
||||
#endif
|
||||
|
||||
int CollIndex (Collection* C, const void* Item);
|
||||
/* Return the index of the given item in the collection. Return -1 if the
|
||||
@@ -227,8 +186,7 @@ void CollDeleteItem (Collection* C, const void* Item);
|
||||
** collection, otherwise FAIL will be called.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void CollDeleteAll (Collection* C)
|
||||
static inline void CollDeleteAll (Collection* C)
|
||||
/* Delete all items from the given collection. This will not free the items
|
||||
** itself, it will only remove the pointers.
|
||||
*/
|
||||
@@ -236,12 +194,8 @@ INLINE void CollDeleteAll (Collection* C)
|
||||
/* This one is easy... */
|
||||
C->Count = 0;
|
||||
}
|
||||
#else
|
||||
# define CollDeleteAll(C) ((C)->Count = 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void CollReplace (Collection* C, void* Item, unsigned Index)
|
||||
static inline void CollReplace (Collection* C, void* Item, unsigned Index)
|
||||
/* Replace the item at the given position. The old item will not be freed,
|
||||
** just the pointer will get replaced.
|
||||
*/
|
||||
@@ -252,12 +206,6 @@ INLINE void CollReplace (Collection* C, void* Item, unsigned Index)
|
||||
/* Replace the item pointer */
|
||||
C->Items[Index] = Item;
|
||||
}
|
||||
#else
|
||||
void CollReplace (Collection* C, void* Item, unsigned Index);
|
||||
/* Replace the item at the given position. The old item will not be freed,
|
||||
** just the pointer will get replaced.
|
||||
*/
|
||||
#endif
|
||||
|
||||
void CollReplaceExpand (Collection* C, void* Item, unsigned Index);
|
||||
/* If Index is a valid index for the collection, replace the item at this
|
||||
|
||||
213
src/common/consprop.c
Normal file
213
src/common/consprop.c
Normal file
@@ -0,0 +1,213 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* consprop.c */
|
||||
/* */
|
||||
/* Console properties */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (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. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#if !defined(_WIN32)
|
||||
# include <unistd.h>
|
||||
#else
|
||||
# include <windows.h>
|
||||
# include <io.h>
|
||||
# define isatty _isatty
|
||||
# define STDOUT_FILENO 1
|
||||
# define STDERR_FILENO 2
|
||||
#endif
|
||||
|
||||
/* common */
|
||||
#include "consprop.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
static unsigned CodePage; /* Windows code page on startup */
|
||||
#endif
|
||||
|
||||
/* State variables */
|
||||
static int IsTTY = 1; /* True if console is a tty */
|
||||
static int IsUTF8 = 1; /* True if console is in UTF-8 mode */
|
||||
static int Color = 0; /* True if we should use color */
|
||||
static ColorMode CMode = CM_AUTO; /* Current color mode */
|
||||
|
||||
/* ANSI escape sequences for color */
|
||||
const char CP_ColorSeq[CC_COUNT][2][8] = {
|
||||
{ "", "\x1b[30m", }, /* Black */
|
||||
{ "", "\x1b[31m", }, /* Red */
|
||||
{ "", "\x1b[32m", }, /* Green */
|
||||
{ "", "\x1b[33m", }, /* Brown */
|
||||
{ "", "\x1b[34m", }, /* Blue */
|
||||
{ "", "\x1b[35m", }, /* Magenta */
|
||||
{ "", "\x1b[36m", }, /* Cyan */
|
||||
{ "", "\x1b[37m", }, /* LightGray */
|
||||
{ "", "\x1b[90m", }, /* Gray */
|
||||
{ "", "\x1b[91m", }, /* BrightRed */
|
||||
{ "", "\x1b[92m", }, /* BrightGreen */
|
||||
{ "", "\x1b[93m", }, /* Yellow */
|
||||
{ "", "\x1b[94m", }, /* BrightBlue */
|
||||
{ "", "\x1b[95m", }, /* BrightMagenta */
|
||||
{ "", "\x1b[96m", }, /* BrightCyan */
|
||||
{ "", "\x1b[97m", }, /* White */
|
||||
};
|
||||
|
||||
/* Box drawing sequences */
|
||||
const char CP_BoxDrawingSeq[BD_COUNT][2][4] = {
|
||||
{ "-", "\xE2\x94\x80", }, /* "─" - Horizontal */
|
||||
{ "|", "\xE2\x94\x82", }, /* "│" - Vertical */
|
||||
{ "+", "\xE2\x94\x8C", }, /* "┌" - ULCorner */
|
||||
{ "+", "\xE2\x94\x94", }, /* "└" - LLCorner */
|
||||
{ "+", "\xE2\x94\x90", }, /* "┐" - URCorner */
|
||||
{ "+", "\xE2\x94\x98", }, /* "┘" - LRCorner */
|
||||
{ "+", "\xE2\x94\x9C", }, /* "├" - VerticalRight */
|
||||
{ "+", "\xE2\x94\xA4", }, /* "┤" - VerticalLeft */
|
||||
{ "+", "\xE2\x94\xAC", }, /* "┬" - HorizontalDown */
|
||||
{ "+", "\xE2\x94\xB4", }, /* "┴" - HorizontalUp */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Helpers */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
static void Cleanup (void)
|
||||
/* Cleanup on program exit */
|
||||
{
|
||||
SetConsoleOutputCP (CodePage);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
void CP_Init (void)
|
||||
/* Init console properties. Must be called before using any other function or
|
||||
** data from this module.
|
||||
*/
|
||||
{
|
||||
IsTTY = (isatty (STDOUT_FILENO) && isatty (STDERR_FILENO));
|
||||
CP_SetColorMode (CMode);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (IsTTY) {
|
||||
CodePage = GetConsoleOutputCP ();
|
||||
IsUTF8 = (int) SetConsoleOutputCP (CP_UTF8);
|
||||
if (IsUTF8) {
|
||||
/* Switch the code page back on exit */
|
||||
atexit (Cleanup);
|
||||
}
|
||||
if (Color) {
|
||||
HANDLE StdOut = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||
if (StdOut != INVALID_HANDLE_VALUE) {
|
||||
DWORD Mode;
|
||||
if (GetConsoleMode (StdOut, &Mode)) {
|
||||
Mode |= ENABLE_PROCESSED_OUTPUT |
|
||||
ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
SetConsoleMode (StdOut, Mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
int CP_IsTTY (void)
|
||||
/* Return true if console output goes to a tty */
|
||||
{
|
||||
return IsTTY;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int CP_IsUTF8 (void)
|
||||
/* Return true if the console supports UTF-8 */
|
||||
{
|
||||
return IsUTF8;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int CP_HasColor (void)
|
||||
/* Return true if the console supports color and it should be used */
|
||||
{
|
||||
return Color;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ColorMode CP_GetColorMode (void)
|
||||
/* Return the current color mode */
|
||||
{
|
||||
return CMode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CP_SetColorMode (ColorMode M)
|
||||
/* Set the color mode */
|
||||
{
|
||||
CMode = M;
|
||||
switch (CMode) {
|
||||
case CM_AUTO: Color = IsTTY; break;
|
||||
case CM_ON: Color = 1; break;
|
||||
default: Color = 0; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CP_DisableUTF8 (void)
|
||||
/* Disable UTF-8 support */
|
||||
{
|
||||
IsUTF8 = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CP_EnableUTF8 (void)
|
||||
/* Enable UTF-8 support */
|
||||
{
|
||||
IsUTF8 = 1;
|
||||
}
|
||||
174
src/common/consprop.h
Normal file
174
src/common/consprop.h
Normal file
@@ -0,0 +1,174 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* consprop.h */
|
||||
/* */
|
||||
/* Console properties */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (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 CONSPROP_H
|
||||
#define CONSPROP_H
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "check.h"
|
||||
#include "consprop.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Color mode for the program */
|
||||
enum ColorMode { CM_OFF, CM_AUTO, CM_ON };
|
||||
typedef enum ColorMode ColorMode;
|
||||
|
||||
/* Colors */
|
||||
enum ConsoleColor {
|
||||
CC_BLACK, CC_RED, CC_GREEN, CC_BROWN,
|
||||
CC_BLUE, CC_MAGENTA, CC_CYAN, CC_LIGHTGRAY,
|
||||
CC_GRAY, CC_BRIGHTRED, CC_BRIGHTGREEN, CC_YELLOW,
|
||||
CC_BRIGHTBLUE, CC_BRIGHTMAGENTA, CC_BRIGHTCYAN, CC_WHITE,
|
||||
CC_COUNT, /* Number of colors */
|
||||
};
|
||||
typedef enum ConsoleColor ConsoleColor;
|
||||
|
||||
/* Box drawing characters */
|
||||
enum BoxDrawing {
|
||||
BD_HORIZONTAL,
|
||||
BD_VERTICAL,
|
||||
BD_ULCORNER,
|
||||
BD_LLCORNER,
|
||||
BD_URCORNER,
|
||||
BD_LRCORNER,
|
||||
BD_RVERTICAL,
|
||||
BD_LVERTICAL,
|
||||
BD_DHORIZONTAL,
|
||||
BD_UHORIZONTAL,
|
||||
BD_COUNT, /* Number of available box drawing chars */
|
||||
};
|
||||
typedef enum BoxDrawing BoxDrawing;
|
||||
|
||||
/* ANSI escape sequences for color - don't use directly */
|
||||
extern const char CP_ColorSeq[CC_COUNT][2][8];
|
||||
|
||||
/* Box drawing characters - don't use directly */
|
||||
extern const char CP_BoxDrawingSeq[BD_COUNT][2][4];
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
void CP_Init (void);
|
||||
/* Init console properties. Must be called before using any other function or
|
||||
** data from this module.
|
||||
**/
|
||||
|
||||
int CP_IsTTY (void);
|
||||
/* Return true if console output goes to a tty */
|
||||
|
||||
int CP_IsUTF8 (void);
|
||||
/* Return true if the console supports UTF-8 */
|
||||
|
||||
int CP_HasColor (void);
|
||||
/* Return true if the console supports color and it should be used */
|
||||
|
||||
ColorMode CP_GetColorMode (void);
|
||||
/* Return the current color mode */
|
||||
|
||||
void CP_SetColorMode (ColorMode M);
|
||||
/* Set the color mode */
|
||||
|
||||
void CP_DisableUTF8 (void);
|
||||
/* Disable UTF-8 support */
|
||||
|
||||
void CP_EnableUTF8 (void);
|
||||
/* Enable UTF-8 support */
|
||||
|
||||
static inline const char* CP_Color (ConsoleColor C)
|
||||
/* Return the ANSI escape sequence for a specific color or an empty string */
|
||||
{
|
||||
PRECONDITION (C >= 0 && C < CC_COUNT);
|
||||
return CP_ColorSeq[C][CP_HasColor ()];
|
||||
}
|
||||
|
||||
static inline const char* CP_Reset (void)
|
||||
/* Return the ANSI escape sequence to reset the colors or an empty string */
|
||||
{
|
||||
return CP_HasColor () ? "\x1b[0m" : "";
|
||||
}
|
||||
|
||||
/* Return specific colors */
|
||||
static inline const char* CP_Black (void) { return CP_Color (CC_BLACK); }
|
||||
static inline const char* CP_Red (void) { return CP_Color (CC_RED); }
|
||||
static inline const char* CP_Green (void) { return CP_Color (CC_GREEN); }
|
||||
static inline const char* CP_Brown (void) { return CP_Color (CC_BROWN); }
|
||||
static inline const char* CP_Blue (void) { return CP_Color (CC_BLUE); }
|
||||
static inline const char* CP_Magenta (void) { return CP_Color (CC_MAGENTA); }
|
||||
static inline const char* CP_Cyan (void) { return CP_Color (CC_CYAN); }
|
||||
static inline const char* CP_LightGray (void) { return CP_Color (CC_LIGHTGRAY); }
|
||||
static inline const char* CP_Gray (void) { return CP_Color (CC_GRAY); }
|
||||
static inline const char* CP_BrightRed (void) { return CP_Color (CC_BRIGHTRED); }
|
||||
static inline const char* CP_BrightGreen (void) { return CP_Color (CC_BRIGHTGREEN); }
|
||||
static inline const char* CP_Yellow (void) { return CP_Color (CC_YELLOW); }
|
||||
static inline const char* CP_BrightBlue (void) { return CP_Color (CC_BRIGHTBLUE); }
|
||||
static inline const char* CP_BrightMagenta (void) { return CP_Color (CC_BRIGHTMAGENTA); }
|
||||
static inline const char* CP_BrightCyan (void) { return CP_Color (CC_BRIGHTCYAN); }
|
||||
static inline const char* CP_White (void) { return CP_Color (CC_WHITE); }
|
||||
|
||||
static inline const char* CP_BoxDrawing (BoxDrawing B)
|
||||
/* Return the UTF-8 sequence for the box drawing characters */
|
||||
{
|
||||
PRECONDITION (B >= 0 && B < BD_COUNT);
|
||||
return CP_BoxDrawingSeq[B][CP_IsUTF8 ()];
|
||||
}
|
||||
|
||||
/* Return specific box drawing character sequences */
|
||||
static inline const char* CP_Horizontal (void) { return CP_BoxDrawing (BD_HORIZONTAL); }
|
||||
static inline const char* CP_Vertical (void) { return CP_BoxDrawing (BD_VERTICAL); }
|
||||
static inline const char* CP_ULCorner (void) { return CP_BoxDrawing (BD_ULCORNER); }
|
||||
static inline const char* CP_LLCorner (void) { return CP_BoxDrawing (BD_LLCORNER); }
|
||||
static inline const char* CP_URCorner (void) { return CP_BoxDrawing (BD_URCORNER); }
|
||||
static inline const char* CP_LRCorner (void) { return CP_BoxDrawing (BD_LRCORNER); }
|
||||
static inline const char* CP_VerticalRight (void) { return CP_BoxDrawing (BD_RVERTICAL); }
|
||||
static inline const char* CP_VerticalLeft (void) { return CP_BoxDrawing (BD_LVERTICAL); }
|
||||
static inline const char* CP_HorizontalDown (void) { return CP_BoxDrawing (BD_DHORIZONTAL); }
|
||||
static inline const char* CP_HorizontalUp (void) { return CP_BoxDrawing (BD_UHORIZONTAL); }
|
||||
|
||||
|
||||
|
||||
/* End of consprop.h */
|
||||
|
||||
#endif
|
||||
@@ -39,7 +39,6 @@
|
||||
|
||||
|
||||
/* common */
|
||||
#include "inline.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
|
||||
@@ -99,15 +98,11 @@ struct HashTable {
|
||||
|
||||
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void InitHashNode (HashNode* N)
|
||||
static inline void InitHashNode (HashNode* N)
|
||||
/* Initialize a hash node. */
|
||||
{
|
||||
N->Next = 0;
|
||||
}
|
||||
#else
|
||||
#define InitHashNode(N) do { (N)->Next = 0; } while (0)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -125,29 +120,21 @@ void DoneHashTable (HashTable* T);
|
||||
** in the table!
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE HashTable* NewHashTable (unsigned Slots, const HashFunctions* Func)
|
||||
static inline HashTable* NewHashTable (unsigned Slots, const HashFunctions* Func)
|
||||
/* Create a new hash table and return it. */
|
||||
{
|
||||
/* Allocate memory, initialize and return it */
|
||||
return InitHashTable (xmalloc (sizeof (HashTable)), Slots, Func);
|
||||
}
|
||||
#else
|
||||
#define NewHashTable(Slots, Func) InitHashTable(xmalloc (sizeof (HashTable)), Slots, Func)
|
||||
#endif
|
||||
|
||||
void FreeHashTable (HashTable* T);
|
||||
/* Free a hash table. Note: This will not free the entries in the table! */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned HT_GetCount (const HashTable* T)
|
||||
static inline unsigned HT_GetCount (const HashTable* T)
|
||||
/* Return the number of items in the table. */
|
||||
{
|
||||
return T->Count;
|
||||
}
|
||||
#else
|
||||
#define HT_GetCount(T) ((T)->Count)
|
||||
#endif
|
||||
|
||||
HashNode* HT_FindHash (const HashTable* T, const void* Key, unsigned Hash);
|
||||
/* Find the node with the given key. Differs from HT_Find in that the hash
|
||||
|
||||
@@ -35,10 +35,6 @@
|
||||
|
||||
|
||||
|
||||
#include "inline.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
@@ -56,10 +52,16 @@ struct IntPtrStack {
|
||||
};
|
||||
|
||||
/* An initializer for an empty int stack */
|
||||
#define STATIC_INTPTRSTACK_INITIALIZER { 0, { 0, 0 }, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} } }
|
||||
#define STATIC_INTPTRSTACK_INITIALIZER { \
|
||||
0, \
|
||||
{ 0, 0 }, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} } \
|
||||
}
|
||||
|
||||
/* Declare an int stack with the given value as first element */
|
||||
#define INTPTRSTACK(Val, Ptr) { 1, { {Val, Ptr}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} } }
|
||||
#define INTPTRSTACK(Val, Ptr) { \
|
||||
1, \
|
||||
{ {Val, Ptr}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} } \
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -69,35 +71,23 @@ struct IntPtrStack {
|
||||
|
||||
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IPS_IsFull (const IntPtrStack* S)
|
||||
static inline int IPS_IsFull (const IntPtrStack* S)
|
||||
/* Return true if there is no space left on the given int stack */
|
||||
{
|
||||
return (S->Count >= sizeof (S->Stack) / sizeof (S->Stack[0]));
|
||||
}
|
||||
#else
|
||||
# define IPS_IsFull(S) ((S)->Count >= sizeof ((S)->Stack) / sizeof ((S)->Stack[0]))
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IPS_IsEmpty (const IntPtrStack* S)
|
||||
static inline int IPS_IsEmpty (const IntPtrStack* S)
|
||||
/* Return true if there are no values on the given int stack */
|
||||
{
|
||||
return (S->Count == 0);
|
||||
}
|
||||
#else
|
||||
# define IPS_IsEmpty(S) ((S)->Count == 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned IPS_GetCount (const IntPtrStack* S)
|
||||
static inline unsigned IPS_GetCount (const IntPtrStack* S)
|
||||
/* Return the number of elements on the given int stack */
|
||||
{
|
||||
return S->Count;
|
||||
}
|
||||
#else
|
||||
# define IPS_GetCount(S) (S)->Count
|
||||
#endif
|
||||
|
||||
void IPS_Get (const IntPtrStack* S, long *Val, void **Ptr);
|
||||
/* Get the value on top of an int stack */
|
||||
|
||||
@@ -38,10 +38,6 @@
|
||||
|
||||
|
||||
|
||||
#include "inline.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
@@ -68,35 +64,23 @@ struct IntStack {
|
||||
|
||||
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IS_IsFull (const IntStack* S)
|
||||
static inline int IS_IsFull (const IntStack* S)
|
||||
/* Return true if there is no space left on the given int stack */
|
||||
{
|
||||
return (S->Count >= sizeof (S->Stack) / sizeof (S->Stack[0]));
|
||||
}
|
||||
#else
|
||||
# define IS_IsFull(S) ((S)->Count >= sizeof ((S)->Stack) / sizeof ((S)->Stack[0]))
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int IS_IsEmpty (const IntStack* S)
|
||||
static inline int IS_IsEmpty (const IntStack* S)
|
||||
/* Return true if there are no values on the given int stack */
|
||||
{
|
||||
return (S->Count == 0);
|
||||
}
|
||||
#else
|
||||
# define IS_IsEmpty(S) ((S)->Count == 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned IS_GetCount (const IntStack* S)
|
||||
static inline unsigned IS_GetCount (const IntStack* S)
|
||||
/* Return the number of elements on the given int stack */
|
||||
{
|
||||
return S->Count;
|
||||
}
|
||||
#else
|
||||
# define IS_GetCount(S) (S)->Count
|
||||
#endif
|
||||
|
||||
long IS_Get (const IntStack* S);
|
||||
/* Get the value on top of an int stack */
|
||||
|
||||
@@ -62,17 +62,6 @@ const StrBuf EmptyStrBuf = STATIC_STRBUF_INITIALIZER;
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
StrBuf* SB_Init (StrBuf* B)
|
||||
/* Initialize a string buffer */
|
||||
{
|
||||
*B = EmptyStrBuf;
|
||||
return B;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
StrBuf* SB_InitFromString (StrBuf* B, const char* S)
|
||||
/* Initialize a string buffer from a literal string. Beware: The buffer won't
|
||||
** store a copy but a pointer to the actual string.
|
||||
@@ -195,17 +184,6 @@ static void SB_CheapRealloc (StrBuf* B, unsigned NewSize)
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
char SB_At (const StrBuf* B, unsigned Index)
|
||||
/* Get a character from the buffer */
|
||||
{
|
||||
PRECONDITION (Index < B->Len);
|
||||
return B->Buf[Index];
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void SB_Drop (StrBuf* B, unsigned Count)
|
||||
/* Drop characters from the end of the string. */
|
||||
{
|
||||
@@ -263,27 +241,6 @@ void SB_CopyBufCooked (StrBuf* Target, const char* Buf, const char* Cooked, unsi
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
void SB_CopyStr (StrBuf* Target, const char* S)
|
||||
/* Copy S to Target, discarding the old contents of Target */
|
||||
{
|
||||
SB_CopyBuf (Target, S, strlen (S));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
void SB_Copy (StrBuf* Target, const StrBuf* Source)
|
||||
/* Copy Source to Target, discarding the old contents of Target */
|
||||
{
|
||||
SB_CopyBufCooked (Target, Source->Buf, Source->Cooked, Source->Len);
|
||||
Target->Index = Source->Index;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void SB_AppendChar (StrBuf* B, int C)
|
||||
/* Append a character to a string buffer */
|
||||
{
|
||||
@@ -326,46 +283,6 @@ void SB_AppendBuf (StrBuf* B, const char* S, unsigned Size)
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
void SB_AppendStr (StrBuf* B, const char* S)
|
||||
/* Append a string to the end of the string buffer */
|
||||
{
|
||||
SB_AppendBuf (B, S, strlen (S));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
void SB_Append (StrBuf* Target, const StrBuf* Source)
|
||||
/* Append the contents of Source to Target */
|
||||
{
|
||||
unsigned NewLen = Target->Len + Source->Len;
|
||||
if (NewLen > Target->Allocated) {
|
||||
SB_Realloc (Target, NewLen);
|
||||
}
|
||||
memcpy (Target->Buf + Target->Len, Source->Buf, Source->Len);
|
||||
memcpy (Target->Cooked + Target->Len, Source->Cooked, Source->Len);
|
||||
Target->Len = NewLen;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if !defined(HAVE_INLINE)
|
||||
void SB_Cut (StrBuf* B, unsigned Len)
|
||||
/* Cut the contents of B at the given length. If the current length of the
|
||||
** buffer is smaller than Len, nothing will happen.
|
||||
*/
|
||||
{
|
||||
if (Len < B->Len) {
|
||||
B->Len = Len;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void SB_Slice (StrBuf* Target, const StrBuf* Source, unsigned Start, unsigned Len)
|
||||
/* Copy a slice from Source into Target. The current contents of Target are
|
||||
** destroyed. If Start is greater than the length of Source, or if Len
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
/* common */
|
||||
#include "attrib.h"
|
||||
#include "check.h"
|
||||
#include "inline.h"
|
||||
|
||||
|
||||
|
||||
@@ -89,16 +88,12 @@ extern const StrBuf EmptyStrBuf;
|
||||
|
||||
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE StrBuf* SB_Init (StrBuf* B)
|
||||
static inline StrBuf* SB_Init (StrBuf* B)
|
||||
/* Initialize a string buffer */
|
||||
{
|
||||
*B = EmptyStrBuf;
|
||||
return B;
|
||||
}
|
||||
#else
|
||||
StrBuf* SB_Init (StrBuf* B);
|
||||
#endif
|
||||
|
||||
StrBuf* SB_InitFromString (StrBuf* B, const char* S);
|
||||
/* Initialize a string buffer from a literal string. Beware: The buffer won't
|
||||
@@ -121,200 +116,126 @@ void SB_Realloc (StrBuf* B, unsigned NewSize);
|
||||
** available.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned SB_GetLen (const StrBuf* B)
|
||||
static inline unsigned SB_GetLen (const StrBuf* B)
|
||||
/* Return the length of the buffer contents */
|
||||
{
|
||||
return B->Len;
|
||||
}
|
||||
#else
|
||||
# define SB_GetLen(B) (B)->Len
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned SB_GetIndex (const StrBuf* B)
|
||||
static inline unsigned SB_GetIndex (const StrBuf* B)
|
||||
/* Return the user index of the string buffer */
|
||||
{
|
||||
return B->Index;
|
||||
}
|
||||
#else
|
||||
# define SB_GetIndex(B) (B)->Index
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void SB_SetIndex (StrBuf* B, unsigned Index)
|
||||
static inline void SB_SetIndex (StrBuf* B, unsigned Index)
|
||||
/* Set the user index of the string buffer */
|
||||
{
|
||||
B->Index = Index;
|
||||
}
|
||||
#else
|
||||
# define SB_SetIndex(B, Idx) ((B)->Index = (Idx))
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE const char* SB_GetConstBuf (const StrBuf* B)
|
||||
static inline const char* SB_GetConstBuf (const StrBuf* B)
|
||||
/* Return a buffer pointer */
|
||||
{
|
||||
return B->Buf;
|
||||
}
|
||||
#else
|
||||
# define SB_GetConstBuf(B) (B)->Buf
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE char* SB_GetBuf (StrBuf* B)
|
||||
static inline char* SB_GetBuf (StrBuf* B)
|
||||
/* Return a buffer pointer */
|
||||
{
|
||||
return B->Buf;
|
||||
}
|
||||
#else
|
||||
# define SB_GetBuf(B) (B)->Buf
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE char* SB_GetCooked (StrBuf* B)
|
||||
static inline char* SB_GetCooked (StrBuf* B)
|
||||
/* Return a cooked pointer */
|
||||
{
|
||||
return B->Cooked;
|
||||
}
|
||||
#else
|
||||
# define SB_GetCooked(B) (B)->Cooked
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE char SB_At (const StrBuf* B, unsigned Index)
|
||||
static inline char SB_At (const StrBuf* B, unsigned Index)
|
||||
/* Get a character from the buffer */
|
||||
{
|
||||
PRECONDITION (Index < B->Len);
|
||||
return B->Buf[Index];
|
||||
}
|
||||
#else
|
||||
char SB_At (const StrBuf* B, unsigned Index);
|
||||
/* Get a character from the buffer */
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE char SB_AtUnchecked (const StrBuf* B, unsigned Index)
|
||||
static inline char SB_AtUnchecked (const StrBuf* B, unsigned Index)
|
||||
/* Get a character from the buffer */
|
||||
{
|
||||
return B->Buf[Index];
|
||||
}
|
||||
#else
|
||||
# define SB_AtUnchecked(B, Index) ((B)->Buf[Index])
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SB_IsEmpty (const StrBuf* B)
|
||||
static inline int SB_IsEmpty (const StrBuf* B)
|
||||
/* Return true if the string buffer is empty */
|
||||
{
|
||||
return (B->Len == 0);
|
||||
}
|
||||
#else
|
||||
# define SB_IsEmpty(B) ((B)->Len == 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SB_NotEmpty (const StrBuf* B)
|
||||
static inline int SB_NotEmpty (const StrBuf* B)
|
||||
/* Return true if the string buffer is not empty */
|
||||
{
|
||||
return (B->Len > 0);
|
||||
}
|
||||
#else
|
||||
# define SB_NotEmpty(B) ((B)->Len > 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void SB_Clear (StrBuf* B)
|
||||
static inline void SB_Clear (StrBuf* B)
|
||||
/* Clear the string buffer (make it empty) */
|
||||
{
|
||||
B->Len = B->Index = 0;
|
||||
}
|
||||
#else
|
||||
# define SB_Clear(B) ((B)->Len = (B)->Index = 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void SB_Reset (StrBuf* B)
|
||||
static inline void SB_Reset (StrBuf* B)
|
||||
/* Reset the string buffer index to zero */
|
||||
{
|
||||
B->Index = 0;
|
||||
}
|
||||
#else
|
||||
# define SB_Reset(B) ((B)->Index = 0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE char SB_Get (StrBuf* B)
|
||||
static inline char SB_Get (StrBuf* B)
|
||||
/* Return the next character from the string incrementing Index. Returns NUL
|
||||
** if the end of the string is reached.
|
||||
*/
|
||||
{
|
||||
return (B->Index < B->Len)? B->Buf[B->Index++] : '\0';
|
||||
}
|
||||
#else
|
||||
# define SB_Get(B) (((B)->Index < (B)->Len)? (B)->Buf[(B)->Index++] : '\0')
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE char SB_Peek (const StrBuf* B)
|
||||
static inline char SB_Peek (const StrBuf* B)
|
||||
/* Look at the next character from the string without incrementing Index.
|
||||
** Returns NUL if the end of the string is reached.
|
||||
*/
|
||||
{
|
||||
return (B->Index < B->Len)? B->Buf[B->Index] : '\0';
|
||||
}
|
||||
#else
|
||||
# define SB_Peek(B) (((B)->Index < (B)->Len)? (B)->Buf[(B)->Index] : '\0')
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE char SB_LookAt (const StrBuf* B, unsigned Index)
|
||||
static inline char SB_LookAt (const StrBuf* B, unsigned Index)
|
||||
/* Look at a specific character from the string. Returns NUL if the given
|
||||
** index is greater than the size of the string.
|
||||
*/
|
||||
{
|
||||
return (Index < B->Len)? B->Buf[Index] : '\0';
|
||||
}
|
||||
#else
|
||||
# define SB_LookAt(B,Index) (((Index) < (B)->Len)? (B)->Buf[(Index)] : '\0')
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE char SB_LookAtLast (const StrBuf* B)
|
||||
static inline char SB_LookAtLast (const StrBuf* B)
|
||||
/* Look at the last character from the string. Returns NUL if the string buffer
|
||||
** is empty.
|
||||
*/
|
||||
{
|
||||
return (B->Len > 0)? B->Buf[B->Len-1] : '\0';
|
||||
}
|
||||
#else
|
||||
# define SB_LookAtLast(B) (((B)->Len > 0)? (B)->Buf[(B)->Len-1] : '\0')
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void SB_Skip (StrBuf* B)
|
||||
static inline void SB_Skip (StrBuf* B)
|
||||
/* Skip the next character in the string buffer if this is possible. */
|
||||
{
|
||||
if (B->Index < B->Len) {
|
||||
++B->Index;
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define SB_Skip(B) do { if ((B)->Index < (B)->Len) ++(B)->Index; } while (0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void SB_SkipMultiple (StrBuf* B, unsigned Count)
|
||||
static inline void SB_SkipMultiple (StrBuf* B, unsigned Count)
|
||||
/* Skip a number of characters in the string buffer if this is possible. */
|
||||
{
|
||||
if ((B->Index += Count) > B->Len) {
|
||||
B->Index = B->Len;
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define SB_SkipMultiple(B, Count) \
|
||||
do { if (((B)->Index += (Count)) > (B)->Len) (B)->Index = (B)->Len; } while (0)
|
||||
#endif
|
||||
|
||||
void SB_Drop (StrBuf* B, unsigned Count);
|
||||
/* Drop characters from the end of the string. */
|
||||
@@ -330,28 +251,18 @@ void SB_CopyBuf (StrBuf* Target, const char* Buf, unsigned Size);
|
||||
void SB_CopyBufCooked (StrBuf* Target, const char* Buf, const char *Cooked, unsigned Size);
|
||||
/* Copy Buf and Cooked to Target, discarding the old contents of Target */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void SB_CopyStr (StrBuf* Target, const char* S)
|
||||
static inline void SB_CopyStr (StrBuf* Target, const char* S)
|
||||
/* Copy S to Target, discarding the old contents of Target */
|
||||
{
|
||||
SB_CopyBuf (Target, S, strlen (S));
|
||||
SB_CopyBuf (Target, S, (unsigned)strlen (S));
|
||||
}
|
||||
#else
|
||||
void SB_CopyStr (StrBuf* Target, const char* S);
|
||||
/* Copy S to Target, discarding the old contents of Target */
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void SB_Copy (StrBuf* Target, const StrBuf* Source)
|
||||
static inline void SB_Copy (StrBuf* Target, const StrBuf* Source)
|
||||
/* Copy Source to Target, discarding the old contents of Target */
|
||||
{
|
||||
SB_CopyBufCooked (Target, Source->Buf, Source->Cooked, Source->Len);
|
||||
Target->Index = Source->Index;
|
||||
}
|
||||
#else
|
||||
void SB_Copy (StrBuf* Target, const StrBuf* Source);
|
||||
/* Copy Source to Target, discarding the old contents of Target */
|
||||
#endif
|
||||
|
||||
void SB_AppendChar (StrBuf* B, int C);
|
||||
/* Append a character to a string buffer */
|
||||
@@ -362,19 +273,13 @@ void SB_AppendCharCooked (StrBuf* B, int C, int Cooked);
|
||||
void SB_AppendBuf (StrBuf* B, const char* S, unsigned Size);
|
||||
/* Append a character buffer to the end of the string buffer */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void SB_AppendStr (StrBuf* B, const char* S)
|
||||
static inline void SB_AppendStr (StrBuf* B, const char* S)
|
||||
/* Append a string to the end of the string buffer */
|
||||
{
|
||||
SB_AppendBuf (B, S, strlen (S));
|
||||
SB_AppendBuf (B, S, (unsigned)strlen (S));
|
||||
}
|
||||
#else
|
||||
void SB_AppendStr (StrBuf* B, const char* S);
|
||||
/* Append a string to the end of the string buffer */
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void SB_Append (StrBuf* Target, const StrBuf* Source)
|
||||
static inline void SB_Append (StrBuf* Target, const StrBuf* Source)
|
||||
/* Append the contents of Source to Target */
|
||||
{
|
||||
unsigned NewLen = Target->Len + Source->Len;
|
||||
@@ -385,13 +290,8 @@ INLINE void SB_Append (StrBuf* Target, const StrBuf* Source)
|
||||
memcpy (Target->Cooked + Target->Len, Source->Cooked, Source->Len);
|
||||
Target->Len = NewLen;
|
||||
}
|
||||
#else
|
||||
void SB_Append (StrBuf* Target, const StrBuf* Source);
|
||||
/* Append the contents of Source to Target */
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void SB_Cut (StrBuf* B, unsigned Len)
|
||||
static inline void SB_Cut (StrBuf* B, unsigned Len)
|
||||
/* Cut the contents of B at the given length. If the current length of the
|
||||
** buffer is smaller than Len, nothing will happen.
|
||||
*/
|
||||
@@ -400,12 +300,6 @@ INLINE void SB_Cut (StrBuf* B, unsigned Len)
|
||||
B->Len = Len;
|
||||
}
|
||||
}
|
||||
#else
|
||||
void SB_Cut (StrBuf* B, unsigned Len);
|
||||
/* Cut the contents of B at the given length. If the current length of the
|
||||
** buffer is smaller than Len, nothing will happen.
|
||||
*/
|
||||
#endif
|
||||
|
||||
void SB_Slice (StrBuf* Target, const StrBuf* Source, unsigned Start, unsigned Len);
|
||||
/* Copy a slice from Source into Target. The current contents of Target are
|
||||
|
||||
@@ -38,10 +38,6 @@
|
||||
|
||||
|
||||
|
||||
#include "inline.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
@@ -65,25 +61,17 @@ struct StrStack {
|
||||
|
||||
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int SS_IsFull (const StrStack* S)
|
||||
static inline int SS_IsFull (const StrStack* S)
|
||||
/* Return true if there is no space left on the given string stack */
|
||||
{
|
||||
return (S->Count >= sizeof (S->Stack) / sizeof (S->Stack[0]));
|
||||
}
|
||||
#else
|
||||
# define SS_IsFull(S) ((S)->Count >= sizeof ((S)->Stack) / sizeof ((S)->Stack[0]))
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned SS_GetCount (const StrStack* S)
|
||||
static inline unsigned SS_GetCount (const StrStack* S)
|
||||
/* Return the number of elements on the given string stack */
|
||||
{
|
||||
return S->Count;
|
||||
}
|
||||
#else
|
||||
# define SS_GetCount(S) (S)->Count
|
||||
#endif
|
||||
|
||||
const char* SS_Get (const StrStack* S);
|
||||
/* Get the value on top of a string stack */
|
||||
|
||||
@@ -243,7 +243,7 @@ static const TargetProperties PropertyTable[TGT_COUNT] = {
|
||||
{ "pce", CPU_HUC6280, BINFMT_BINARY, CTNone },
|
||||
{ "gamate", CPU_6502, BINFMT_BINARY, CTNone },
|
||||
{ "c65", CPU_4510, BINFMT_BINARY, CTPET },
|
||||
{ "cx16", CPU_65C02, BINFMT_BINARY, CTPET },
|
||||
{ "cx16", CPU_W65C02, BINFMT_BINARY, CTPET },
|
||||
{ "sym1", CPU_6502, BINFMT_BINARY, CTNone },
|
||||
{ "mega65", CPU_45GS02, BINFMT_BINARY, CTPET },
|
||||
{ "kim1", CPU_6502, BINFMT_BINARY, CTNone },
|
||||
|
||||
@@ -87,25 +87,17 @@ struct Fragment {
|
||||
Fragment* NewFragment (unsigned char Type, unsigned Size, struct Section* S);
|
||||
/* Create a new fragment and insert it into the section S */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE const char* GetFragmentSourceName (const Fragment* F)
|
||||
static inline const char* GetFragmentSourceName (const Fragment* F)
|
||||
/* Return the name of the source file for this fragment */
|
||||
{
|
||||
return GetSourceNameFromList (&F->LineInfos);
|
||||
}
|
||||
#else
|
||||
# define GetFragmentSourceName(F) GetSourceNameFromList (&(F)->LineInfos)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned GetFragmentSourceLine (const Fragment* F)
|
||||
static inline unsigned GetFragmentSourceLine (const Fragment* F)
|
||||
/* Return the source file line for this fragment */
|
||||
{
|
||||
return GetSourceLineFromList (&F->LineInfos);
|
||||
}
|
||||
#else
|
||||
# define GetFragmentSourceLine(F) GetSourceLineFromList (&(F)->LineInfos)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -110,69 +110,43 @@ const LineInfo* GetAsmLineInfo (const Collection* LineInfos);
|
||||
** and return it. Return NULL if no such line info was found.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE const FilePos* GetSourcePos (const LineInfo* LI)
|
||||
static inline const FilePos* GetSourcePos (const LineInfo* LI)
|
||||
/* Return the source file position from the given line info */
|
||||
{
|
||||
return &LI->Pos;
|
||||
}
|
||||
#else
|
||||
# define GetSourcePos(LI) (&(LI)->Pos)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE const char* GetSourceName (const LineInfo* LI)
|
||||
static inline const char* GetSourceName (const LineInfo* LI)
|
||||
/* Return the name of a source file from the given line info */
|
||||
{
|
||||
return GetString (LI->Pos.Name);
|
||||
}
|
||||
#else
|
||||
# define GetSourceName(LI) (GetString ((LI)->Pos.Name))
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned GetSourceLine (const LineInfo* LI)
|
||||
static inline unsigned GetSourceLine (const LineInfo* LI)
|
||||
/* Return the source file line from the given line info */
|
||||
{
|
||||
return LI->Pos.Line;
|
||||
}
|
||||
#else
|
||||
# define GetSourceLine(LI) ((LI)->Pos.Line)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned GetSourceCol (const LineInfo* LI)
|
||||
static inline unsigned GetSourceCol (const LineInfo* LI)
|
||||
/* Return the source file column from the given line info */
|
||||
{
|
||||
return LI->Pos.Col;
|
||||
}
|
||||
#else
|
||||
# define GetSourceCol(LI) ((LI)->Pos.Col)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE const char* GetSourceNameFromList (const Collection* LineInfos)
|
||||
static inline const char* GetSourceNameFromList (const Collection* LineInfos)
|
||||
/* Return the name of a source file from a list of line infos */
|
||||
{
|
||||
/* The relevant entry is in slot zero */
|
||||
return GetSourceName (CollConstAt (LineInfos, 0));
|
||||
}
|
||||
#else
|
||||
# define GetSourceNameFromList(LineInfos) \
|
||||
GetSourceName ((const LineInfo*) CollConstAt ((LineInfos), 0))
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned GetSourceLineFromList (const Collection* LineInfos)
|
||||
static inline unsigned GetSourceLineFromList (const Collection* LineInfos)
|
||||
/* Return the source file line from a list of line infos */
|
||||
{
|
||||
/* The relevant entry is in slot zero */
|
||||
return GetSourceLine (CollConstAt (LineInfos, 0));
|
||||
}
|
||||
#else
|
||||
# define GetSourceLineFromList(LineInfos) \
|
||||
GetSourceLine ((const LineInfo*) CollConstAt ((LineInfos), 0))
|
||||
#endif
|
||||
|
||||
unsigned LineInfoCount (void);
|
||||
/* Return the total number of line infos */
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
|
||||
/* common */
|
||||
#include "coll.h"
|
||||
#include "inline.h"
|
||||
#include "objdefs.h"
|
||||
|
||||
|
||||
@@ -136,15 +135,11 @@ const char* GetObjFileName (const ObjData* O);
|
||||
** file is NULL.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ObjHasFiles (const ObjData* O)
|
||||
static inline int ObjHasFiles (const ObjData* O)
|
||||
/* Return true if the files list does exist */
|
||||
{
|
||||
return (O != 0 && CollCount (&O->Files) != 0);
|
||||
}
|
||||
#else
|
||||
# define ObjHasFiles(O) ((O) != 0 && CollCount (&(O)->Files) != 0)
|
||||
#endif
|
||||
|
||||
const struct StrBuf* GetObjString (const ObjData* Obj, unsigned Id);
|
||||
/* Get a string from an object file checking for an invalid index */
|
||||
|
||||
@@ -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 InitStrPool (void);
|
||||
/* Initialize the string pool */
|
||||
|
||||
@@ -65,35 +65,23 @@ extern StringPool* TypePool;
|
||||
|
||||
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned GetTypeId (const StrBuf* Type)
|
||||
static inline unsigned GetTypeId (const StrBuf* Type)
|
||||
/* Return the id of the given generic type */
|
||||
{
|
||||
return SP_Add (TypePool, Type);
|
||||
}
|
||||
#else
|
||||
# define GetTypeId(Type) SP_Add (TypePool, (Type))
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE const StrBuf* GetType (unsigned Index)
|
||||
static inline const StrBuf* GetType (unsigned Index)
|
||||
/* Convert a type index into a type string */
|
||||
{
|
||||
return SP_Get (TypePool, Index);
|
||||
}
|
||||
#else
|
||||
# define GetType(Index) SP_Get (TypePool, (Index))
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned TypeCount (void)
|
||||
static inline unsigned TypeCount (void)
|
||||
/* Return the number of types in the pool */
|
||||
{
|
||||
return SP_GetCount (TypePool);
|
||||
}
|
||||
#else
|
||||
# define TypeCount() SP_GetCount (TypePool)
|
||||
#endif
|
||||
|
||||
void PrintDbgTypes (FILE* F);
|
||||
/* Output the types to a debug info file */
|
||||
|
||||
Reference in New Issue
Block a user