mirror of
https://github.com/cc65/cc65.git
synced 2025-04-07 11:38:02 +00:00
Make much more usage of dynamic strings (StrBufs) instead of char* and
friends. Since names and other strings are now StrBufs in many places, code for output had to be changed. Added support for string literals to StrBuf. git-svn-id: svn://svn.cc65.org/cc65/trunk@3825 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
6a7e844500
commit
9174f65e54
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 2000-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -36,9 +36,6 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* common */
|
||||
#include "xsprintf.h"
|
||||
|
||||
/* ca65 */
|
||||
#include "anonname.h"
|
||||
|
||||
@ -60,23 +57,27 @@ static const char AnonTag[] = "$anon";
|
||||
|
||||
|
||||
|
||||
char* AnonName (char* Buf, unsigned Size, const char* Spec)
|
||||
StrBuf* AnonName (StrBuf* Buf, const char* Spec)
|
||||
/* Get a name for an anonymous scope, variable or type. Size is the size of
|
||||
* the buffer passed to the function, Spec will be used as part of the
|
||||
* identifier if given. A pointer to the buffer is returned.
|
||||
*/
|
||||
{
|
||||
static unsigned ACount = 0;
|
||||
xsprintf (Buf, Size, "%s-%s-%04X", AnonTag, Spec, ++ACount);
|
||||
SB_Printf (Buf, "%s-%s-%04X", AnonTag, Spec, ++ACount);
|
||||
return Buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int IsAnonName (const char* Name)
|
||||
int IsAnonName (const StrBuf* Name)
|
||||
/* Check if the given symbol name is that of an anonymous symbol */
|
||||
{
|
||||
return (strncmp (Name, AnonTag, sizeof (AnonTag) - 1) == 0);
|
||||
{
|
||||
if (SB_GetLen (Name) < sizeof (AnonTag) - 1) {
|
||||
/* Too short */
|
||||
return 0;
|
||||
}
|
||||
return (strncmp (SB_GetConstBuf (Name), AnonTag, sizeof (AnonTag) - 1) == 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 2000-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -38,22 +38,27 @@
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "strbuf.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
char* AnonName (char* Buf, unsigned Size, const char* Spec);
|
||||
StrBuf* AnonName (StrBuf* Buf, const char* Spec);
|
||||
/* Get a name for an anonymous scope, variable or type. Size is the size of
|
||||
* the buffer passed to the function, Spec will be used as part of the
|
||||
* identifier if given. A pointer to the buffer is returned.
|
||||
*/
|
||||
|
||||
int IsAnonName (const char* Name);
|
||||
int IsAnonName (const StrBuf* Name);
|
||||
/* Check if the given symbol name is that of an anonymous symbol */
|
||||
|
||||
|
||||
|
||||
|
||||
/* End of anonname.h */
|
||||
#endif
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003-2005, Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 2003-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
|
@ -2,12 +2,12 @@
|
||||
/* */
|
||||
/* dbginfo.c */
|
||||
/* */
|
||||
/* Handle the .dbg commands */
|
||||
/* Handle the .dbg commands */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2003 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 2000-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -35,6 +35,9 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* common */
|
||||
#include "strbuf.h"
|
||||
|
||||
/* ca65 */
|
||||
#include "error.h"
|
||||
#include "expr.h"
|
||||
@ -54,7 +57,7 @@
|
||||
void DbgInfoFile (void)
|
||||
/* Parse and handle FILE subcommand of the .dbg pseudo instruction */
|
||||
{
|
||||
char Name [sizeof (SVal)];
|
||||
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
||||
unsigned long Size;
|
||||
unsigned long MTime;
|
||||
|
||||
@ -66,7 +69,7 @@ void DbgInfoFile (void)
|
||||
ErrorSkip ("String constant expected");
|
||||
return;
|
||||
}
|
||||
strcpy (Name, SVal);
|
||||
SB_Copy (&Name, &SVal);
|
||||
NextTok ();
|
||||
|
||||
/* Comma expected */
|
||||
@ -82,7 +85,10 @@ void DbgInfoFile (void)
|
||||
MTime = ConstExpression ();
|
||||
|
||||
/* Insert the file into the table */
|
||||
AddFile (Name, Size, MTime);
|
||||
AddFile (&Name, Size, MTime);
|
||||
|
||||
/* Free memory used for Name */
|
||||
SB_Done (&Name);
|
||||
}
|
||||
|
||||
|
||||
@ -111,7 +117,7 @@ void DbgInfoLine (void)
|
||||
}
|
||||
|
||||
/* Get the index in the file table for the name */
|
||||
Index = GetFileIndex (SVal);
|
||||
Index = GetFileIndex (&SVal);
|
||||
|
||||
/* Skip the name */
|
||||
NextTok ();
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 2003-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -65,7 +65,7 @@ void DoEnum (void)
|
||||
int Anon = (Tok != TOK_IDENT);
|
||||
if (!Anon) {
|
||||
/* Enter a new scope, then skip the name */
|
||||
SymEnterLevel (SVal, ST_ENUM, ADDR_SIZE_ABS);
|
||||
SymEnterLevel (&SVal, ST_ENUM, ADDR_SIZE_ABS);
|
||||
NextTok ();
|
||||
}
|
||||
|
||||
@ -94,7 +94,7 @@ void DoEnum (void)
|
||||
}
|
||||
|
||||
/* We have an identifier, generate a symbol */
|
||||
Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW);
|
||||
Sym = SymFind (CurrentScope, &SVal, SYM_ALLOC_NEW);
|
||||
|
||||
/* Skip the member name */
|
||||
NextTok ();
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -37,10 +37,13 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* common */
|
||||
#include "strbuf.h"
|
||||
|
||||
/* ca65 */
|
||||
#include "error.h"
|
||||
#include "filetab.h"
|
||||
#include "nexttok.h"
|
||||
#include "error.h"
|
||||
|
||||
|
||||
|
||||
@ -69,11 +72,18 @@ void WarningMsg (const FilePos* Pos, unsigned Level, const char* Format, va_list
|
||||
/* Print warning message. */
|
||||
{
|
||||
if (Level <= WarnLevel) {
|
||||
fprintf (stderr, "%s(%lu): Warning: ",
|
||||
GetFileName (Pos->Name), Pos->Line);
|
||||
vfprintf (stderr, Format, ap);
|
||||
fprintf (stderr, "\n");
|
||||
|
||||
StrBuf S = STATIC_STRBUF_INITIALIZER;
|
||||
SB_VPrintf (&S, Format, ap);
|
||||
SB_Terminate (&S);
|
||||
|
||||
fprintf (stderr, "%s(%lu): Warning: %s\n",
|
||||
SB_GetConstBuf (GetFileName (Pos->Name)),
|
||||
Pos->Line,
|
||||
SB_GetConstBuf (&S));
|
||||
++WarningCount;
|
||||
|
||||
SB_Done (&S);
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,11 +120,17 @@ void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...)
|
||||
void ErrorMsg (const FilePos* Pos, const char* Format, va_list ap)
|
||||
/* Print an error message */
|
||||
{
|
||||
fprintf (stderr, "%s(%lu): Error: ",
|
||||
GetFileName (Pos->Name), Pos->Line);
|
||||
vfprintf (stderr, Format, ap);
|
||||
fprintf (stderr, "\n");
|
||||
StrBuf S = STATIC_STRBUF_INITIALIZER;
|
||||
SB_VPrintf (&S, Format, ap);
|
||||
SB_Terminate (&S);
|
||||
|
||||
fprintf (stderr, "%s(%lu): Error: %s\n",
|
||||
SB_GetConstBuf (GetFileName (Pos->Name)),
|
||||
Pos->Line,
|
||||
SB_GetConstBuf (&S));
|
||||
++ErrorCount;
|
||||
|
||||
SB_Done (&S);
|
||||
}
|
||||
|
||||
|
||||
@ -164,13 +180,17 @@ void Fatal (const char* Format, ...)
|
||||
/* Print a message about a fatal error and die */
|
||||
{
|
||||
va_list ap;
|
||||
StrBuf S = STATIC_STRBUF_INITIALIZER;
|
||||
|
||||
va_start (ap, Format);
|
||||
fprintf (stderr, "Fatal error: ");
|
||||
vfprintf (stderr, Format, ap);
|
||||
fprintf (stderr, "\n");
|
||||
SB_VPrintf (&S, Format, ap);
|
||||
SB_Terminate (&S);
|
||||
va_end (ap);
|
||||
|
||||
fprintf (stderr, "Fatal error: %s\n", SB_GetConstBuf (&S));
|
||||
|
||||
SB_Done (&S);
|
||||
|
||||
/* And die... */
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
@ -178,14 +198,19 @@ void Fatal (const char* Format, ...)
|
||||
|
||||
|
||||
void Internal (const char* Format, ...)
|
||||
/* Print a message about an internal compiler error and die. */
|
||||
/* Print a message about an internal assembler error and die. */
|
||||
{
|
||||
va_list ap;
|
||||
StrBuf S = STATIC_STRBUF_INITIALIZER;
|
||||
|
||||
va_start (ap, Format);
|
||||
fprintf (stderr, "Internal assembler error:\n");
|
||||
vfprintf (stderr, Format, ap);
|
||||
SB_VPrintf (&S, Format, ap);
|
||||
SB_Terminate (&S);
|
||||
va_end (ap);
|
||||
fprintf (stderr, "\n");
|
||||
|
||||
fprintf (stderr, "Internal assembler error: %s\n", SB_GetConstBuf (&S));
|
||||
|
||||
SB_Done (&S);
|
||||
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -73,7 +73,7 @@ void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...) attr
|
||||
|
||||
void Error (const char* Format, ...) attribute ((format (printf, 1, 2)));
|
||||
/* Print an error message */
|
||||
|
||||
|
||||
void PError (const FilePos* Pos, const char* Format, ...) attribute ((format (printf, 2, 3)));
|
||||
/* Print an error message giving an explicit file and position. */
|
||||
|
||||
@ -84,7 +84,7 @@ void Fatal (const char* Format, ...) attribute((noreturn, format(printf,1,2)));
|
||||
/* Print a message about a fatal error and die */
|
||||
|
||||
void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2)));
|
||||
/* Print a message about an internal compiler error and die. */
|
||||
/* Print a message about an internal assembler error and die. */
|
||||
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2007 Ullrich von Bassewitz */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -550,8 +550,8 @@ static ExprNode* FuncReferenced (void)
|
||||
static ExprNode* FuncSizeOf (void)
|
||||
/* Handle the .SIZEOF function */
|
||||
{
|
||||
StrBuf ScopeName = AUTO_STRBUF_INITIALIZER;
|
||||
char Name[sizeof (SVal)];
|
||||
StrBuf ScopeName = STATIC_STRBUF_INITIALIZER;
|
||||
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
||||
SymTable* Scope;
|
||||
SymEntry* Sym;
|
||||
SymEntry* SizeSym;
|
||||
@ -566,27 +566,28 @@ static ExprNode* FuncSizeOf (void)
|
||||
if (Tok == TOK_LOCAL_IDENT) {
|
||||
|
||||
/* Cheap local symbol */
|
||||
Sym = SymFindLocal (SymLast, SVal, SYM_FIND_EXISTING);
|
||||
Sym = SymFindLocal (SymLast, &SVal, SYM_FIND_EXISTING);
|
||||
if (Sym == 0) {
|
||||
Error ("Unknown symbol or scope: `%s'", SVal);
|
||||
Error ("Unknown symbol or scope: `%m%p'", &SVal);
|
||||
} else {
|
||||
SizeSym = GetSizeOfSymbol (Sym);
|
||||
}
|
||||
|
||||
/* Remember and skip SVal, terminate ScopeName so it is empty */
|
||||
strcpy (Name, SVal);
|
||||
SB_Copy (&Name, &SVal);
|
||||
NextTok ();
|
||||
SB_Terminate (&ScopeName);
|
||||
|
||||
} else {
|
||||
|
||||
/* Parse the scope and the name */
|
||||
SymTable* ParentScope = ParseScopedIdent (Name, &ScopeName);
|
||||
SymTable* ParentScope = ParseScopedIdent (&Name, &ScopeName);
|
||||
|
||||
/* Check if the parent scope is valid */
|
||||
if (ParentScope == 0) {
|
||||
/* No such scope */
|
||||
DoneStrBuf (&ScopeName);
|
||||
SB_Done (&ScopeName);
|
||||
SB_Done (&Name);
|
||||
return GenLiteral0 ();
|
||||
}
|
||||
|
||||
@ -597,9 +598,9 @@ static ExprNode* FuncSizeOf (void)
|
||||
|
||||
/* First search for a scope with the given name */
|
||||
if (NoScope) {
|
||||
Scope = SymFindAnyScope (ParentScope, Name);
|
||||
Scope = SymFindAnyScope (ParentScope, &Name);
|
||||
} else {
|
||||
Scope = SymFindScope (ParentScope, Name, SYM_FIND_EXISTING);
|
||||
Scope = SymFindScope (ParentScope, &Name, SYM_FIND_EXISTING);
|
||||
}
|
||||
|
||||
/* If we did find a scope with the name, read the symbol defining the
|
||||
@ -610,29 +611,30 @@ static ExprNode* FuncSizeOf (void)
|
||||
SizeSym = GetSizeOfScope (Scope);
|
||||
} else {
|
||||
if (NoScope) {
|
||||
Sym = SymFindAny (ParentScope, Name);
|
||||
Sym = SymFindAny (ParentScope, &Name);
|
||||
} else {
|
||||
Sym = SymFind (ParentScope, Name, SYM_FIND_EXISTING);
|
||||
Sym = SymFind (ParentScope, &Name, SYM_FIND_EXISTING);
|
||||
}
|
||||
|
||||
/* If we found the symbol retrieve the size, otherwise complain */
|
||||
if (Sym) {
|
||||
SizeSym = GetSizeOfSymbol (Sym);
|
||||
} else {
|
||||
Error ("Unknown symbol or scope: `%s%s'",
|
||||
SB_GetConstBuf (&ScopeName), Name);
|
||||
Error ("Unknown symbol or scope: `%m%p%m%p'",
|
||||
&ScopeName, &Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we have a size */
|
||||
if (SizeSym == 0 || !SymIsConst (SizeSym, &Size)) {
|
||||
Error ("Size of `%s%s' is unknown", SB_GetConstBuf (&ScopeName), Name);
|
||||
Error ("Size of `%m%p%m%p' is unknown", &ScopeName, &Name);
|
||||
Size = 0;
|
||||
}
|
||||
|
||||
/* Free the scope name */
|
||||
DoneStrBuf (&ScopeName);
|
||||
/* Free the string buffers */
|
||||
SB_Done (&ScopeName);
|
||||
SB_Done (&Name);
|
||||
|
||||
/* Return the size */
|
||||
return GenLiteralExpr (Size);
|
||||
@ -643,19 +645,19 @@ static ExprNode* FuncSizeOf (void)
|
||||
static ExprNode* FuncStrAt (void)
|
||||
/* Handle the .STRAT function */
|
||||
{
|
||||
char Str [sizeof(SVal)];
|
||||
StrBuf Str = STATIC_STRBUF_INITIALIZER;
|
||||
long Index;
|
||||
unsigned char C;
|
||||
unsigned char C = 0;
|
||||
|
||||
/* String constant expected */
|
||||
if (Tok != TOK_STRCON) {
|
||||
Error ("String constant expected");
|
||||
NextTok ();
|
||||
return GenLiteral0 ();
|
||||
goto ExitPoint;
|
||||
}
|
||||
|
||||
/* Remember the string and skip it */
|
||||
strcpy (Str, SVal);
|
||||
SB_Copy (&Str, &SVal);
|
||||
NextTok ();
|
||||
|
||||
/* Comma must follow */
|
||||
@ -665,15 +667,19 @@ static ExprNode* FuncStrAt (void)
|
||||
Index = ConstExpression ();
|
||||
|
||||
/* Must be a valid index */
|
||||
if (Index >= (long) strlen (Str)) {
|
||||
if (Index >= (long) SB_GetLen (&Str)) {
|
||||
Error ("Range error");
|
||||
return GenLiteral0 ();
|
||||
goto ExitPoint;
|
||||
}
|
||||
|
||||
/* Get the char, handle as unsigned. Be sure to translate it into
|
||||
* the target character set.
|
||||
*/
|
||||
C = TgtTranslateChar (Str [(size_t)Index]);
|
||||
C = TgtTranslateChar (SB_At (&Str, (unsigned)Index));
|
||||
|
||||
ExitPoint:
|
||||
/* Free string buffer memory */
|
||||
SB_Done (&Str);
|
||||
|
||||
/* Return the char expression */
|
||||
return GenLiteralExpr (C);
|
||||
@ -699,7 +705,7 @@ static ExprNode* FuncStrLen (void)
|
||||
} else {
|
||||
|
||||
/* Get the length of the string */
|
||||
Len = strlen (SVal);
|
||||
Len = SB_GetLen (&SVal);
|
||||
|
||||
/* Skip the string */
|
||||
NextTok ();
|
||||
@ -807,7 +813,7 @@ static ExprNode* Factor (void)
|
||||
break;
|
||||
|
||||
case TOK_LOCAL_IDENT:
|
||||
N = Symbol (SymFindLocal (SymLast, SVal, SYM_ALLOC_NEW));
|
||||
N = Symbol (SymFindLocal (SymLast, &SVal, SYM_ALLOC_NEW));
|
||||
NextTok ();
|
||||
break;
|
||||
|
||||
@ -948,9 +954,9 @@ static ExprNode* Factor (void)
|
||||
break;
|
||||
|
||||
default:
|
||||
if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
|
||||
if (LooseCharTerm && Tok == TOK_STRCON && SB_GetLen (&SVal) == 1) {
|
||||
/* A character constant */
|
||||
N = GenLiteralExpr (TgtTranslateChar (SVal[0]));
|
||||
N = GenLiteralExpr (TgtTranslateChar (SB_At (&SVal, 0)));
|
||||
} else {
|
||||
N = GenLiteral0 (); /* Dummy */
|
||||
Error ("Syntax error");
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2004 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 2000-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -70,7 +70,7 @@ static const char* FeatureKeys[FEAT_COUNT] = {
|
||||
|
||||
|
||||
|
||||
feature_t FindFeature (const char* Key)
|
||||
feature_t FindFeature (const StrBuf* Key)
|
||||
/* Find the feature in a table and return the corresponding enum value. If the
|
||||
* feature is invalid, return FEAT_UNKNOWN.
|
||||
*/
|
||||
@ -79,7 +79,7 @@ feature_t FindFeature (const char* Key)
|
||||
|
||||
/* This is not time critical, so do a linear search */
|
||||
for (F = (feature_t) 0; F < FEAT_COUNT; ++F) {
|
||||
if (strcmp (Key, FeatureKeys[F]) == 0) {
|
||||
if (SB_CompareStr (Key, FeatureKeys[F]) == 0) {
|
||||
/* Found, index is enum value */
|
||||
return F;
|
||||
}
|
||||
@ -91,7 +91,7 @@ feature_t FindFeature (const char* Key)
|
||||
|
||||
|
||||
|
||||
feature_t SetFeature (const char* Key)
|
||||
feature_t SetFeature (const StrBuf* Key)
|
||||
/* Find the feature and set the corresponding flag if the feature is known.
|
||||
* In any case, return the feature found. An invalid Key will return
|
||||
* FEAT_UNKNOWN.
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2007 Ullrich von Bassewitz */
|
||||
/* (C) 2000-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -38,6 +38,11 @@
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "strbuf.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
@ -70,12 +75,12 @@ typedef enum {
|
||||
|
||||
|
||||
|
||||
feature_t FindFeature (const char* Key);
|
||||
feature_t FindFeature (const StrBuf* Key);
|
||||
/* Find the feature in a table and return the corresponding enum value. If the
|
||||
* feature is invalid, return FEAT_UNKNOWN.
|
||||
*/
|
||||
|
||||
feature_t SetFeature (const char* Key);
|
||||
feature_t SetFeature (const StrBuf* Key);
|
||||
/* Find the feature and set the corresponding flag if the feature is known.
|
||||
* In any case, return the feature found. An invalid Key will return
|
||||
* FEAT_UNKNOWN.
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2003 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 2000-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -180,9 +180,11 @@ static FileEntry* NewFileEntry (unsigned Name, unsigned long Size, unsigned long
|
||||
|
||||
|
||||
|
||||
const char* GetFileName (unsigned Name)
|
||||
const StrBuf* GetFileName (unsigned Name)
|
||||
/* Get the name of a file where the name index is known */
|
||||
{
|
||||
static StrBuf ErrorMsg = LIT_STRBUF_INITIALIZER ("(outside file scope)");
|
||||
|
||||
const FileEntry* F;
|
||||
|
||||
if (Name == 0) {
|
||||
@ -192,30 +194,30 @@ const char* GetFileName (unsigned Name)
|
||||
*/
|
||||
if (CollCount (&FileTab) == 0) {
|
||||
/* No files defined until now */
|
||||
return "(outside file scope)";
|
||||
return &ErrorMsg;
|
||||
} else {
|
||||
F = CollConstAt (&FileTab, 0);
|
||||
}
|
||||
} else {
|
||||
F = CollConstAt (&FileTab, Name-1);
|
||||
}
|
||||
return GetString (F->Name);
|
||||
return GetStrBuf (F->Name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned GetFileIndex (const char* Name)
|
||||
unsigned GetFileIndex (const StrBuf* Name)
|
||||
/* Return the file index for the given file name. */
|
||||
{
|
||||
/* Get the string pool index from the name */
|
||||
unsigned NameIdx = GetStringId (Name);
|
||||
unsigned NameIdx = GetStrBufId (Name);
|
||||
|
||||
/* Search in the hash table for the name */
|
||||
FileEntry* F = HT_FindEntry (&HashTab, &NameIdx);
|
||||
|
||||
/* If we don't have this index, print a diagnostic and use the main file */
|
||||
if (F == 0) {
|
||||
Error ("File name `%s' not found in file table", Name);
|
||||
Error ("File name `%m%p' not found in file table", Name);
|
||||
return 0;
|
||||
} else {
|
||||
return F->Index;
|
||||
@ -224,13 +226,13 @@ unsigned GetFileIndex (const char* Name)
|
||||
|
||||
|
||||
|
||||
unsigned AddFile (const char* Name, unsigned long Size, unsigned long MTime)
|
||||
unsigned AddFile (const StrBuf* Name, unsigned long Size, unsigned long MTime)
|
||||
/* Add a new file to the list of input files. Return the index of the file in
|
||||
* the table.
|
||||
*/
|
||||
{
|
||||
/* Create a new file entry and insert it into the tables */
|
||||
FileEntry* F = NewFileEntry (GetStringId (Name), Size, MTime);
|
||||
FileEntry* F = NewFileEntry (GetStrBufId (Name), Size, MTime);
|
||||
|
||||
/* Return the index */
|
||||
return F->Index;
|
||||
@ -265,4 +267,4 @@ void WriteFiles (void)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 2000-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -38,19 +38,24 @@
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "strbuf.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
const char* GetFileName (unsigned Name);
|
||||
const StrBuf* GetFileName (unsigned Name);
|
||||
/* Get the name of a file where the name index is known */
|
||||
|
||||
unsigned GetFileIndex (const char* Name);
|
||||
unsigned GetFileIndex (const StrBuf* Name);
|
||||
/* Return the file index for the given file name. */
|
||||
|
||||
unsigned AddFile (const char* Name, unsigned long Size, unsigned long MTime);
|
||||
unsigned AddFile (const StrBuf* Name, unsigned long Size, unsigned long MTime);
|
||||
/* Add a new file to the list of input files. Return the index of the file in
|
||||
* the table.
|
||||
*/
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2006, Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 1998-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -1453,7 +1453,7 @@ cpu_t GetCPU (void)
|
||||
|
||||
|
||||
|
||||
int FindInstruction (const char* Ident)
|
||||
int FindInstruction (const StrBuf* Ident)
|
||||
/* Check if Ident is a valid mnemonic. If so, return the index in the
|
||||
* instruction table. If not, return -1.
|
||||
*/
|
||||
@ -1472,7 +1472,7 @@ int FindInstruction (const char* Ident)
|
||||
|
||||
/* Make a copy, and uppercase that copy */
|
||||
I = 0;
|
||||
while (Ident[I] != '\0') {
|
||||
while (I < SB_GetLen (Ident)) {
|
||||
/* If the identifier is longer than the longest mnemonic, it cannot
|
||||
* be one.
|
||||
*/
|
||||
@ -1480,7 +1480,7 @@ int FindInstruction (const char* Ident)
|
||||
/* Not found, no need for further action */
|
||||
return -1;
|
||||
}
|
||||
Key[I] = toupper ((unsigned char)Ident[I]);
|
||||
Key[I] = toupper ((unsigned char)SB_AtUnchecked (Ident, I));
|
||||
++I;
|
||||
}
|
||||
Key[I] = '\0';
|
||||
|
@ -1,13 +1,13 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* instr.h */
|
||||
/* instr.h */
|
||||
/* */
|
||||
/* Instruction encoding for the ca65 macroassembler */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2005, Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 1998-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -40,6 +40,7 @@
|
||||
|
||||
/* common */
|
||||
#include "cpu.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
|
||||
|
||||
@ -152,7 +153,7 @@ void SetCPU (cpu_t NewCPU);
|
||||
cpu_t GetCPU (void);
|
||||
/* Return the current CPU */
|
||||
|
||||
int FindInstruction (const char* Ident);
|
||||
int FindInstruction (const StrBuf* Ident);
|
||||
/* Check if Ident is a valid mnemonic. If so, return the index in the
|
||||
* instruction table. If not, return -1.
|
||||
*/
|
||||
@ -169,3 +170,4 @@ void HandleInstruction (unsigned Index);
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2007 Ullrich von Bassewitz */
|
||||
/* (C) 2000-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -218,17 +218,20 @@ static void PrintPageHeader (FILE* F, const ListLine* L)
|
||||
/* Print the header for a new page. It is assumed that the given line is the
|
||||
* last line of the previous page.
|
||||
*/
|
||||
{
|
||||
{
|
||||
/* Gte a pointer to the current input file */
|
||||
const StrBuf* CurFile = GetFileName (L->File);
|
||||
|
||||
/* Print the header on the new page */
|
||||
fprintf (F,
|
||||
"ca65 V%u.%u.%u - %s\n"
|
||||
"Main file : %s\n"
|
||||
"Current file: %s\n"
|
||||
"Current file: %.*s\n"
|
||||
"\n",
|
||||
VER_MAJOR, VER_MINOR, VER_PATCH,
|
||||
Copyright,
|
||||
InFile,
|
||||
GetFileName (L->File));
|
||||
SB_GetLen (CurFile), SB_GetConstBuf (CurFile));
|
||||
|
||||
/* Count pages, reset lines */
|
||||
++PageNumber;
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2005, Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 1998-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -82,7 +82,7 @@ static StrBuf MacPackDir = STATIC_STRBUF_INITIALIZER;
|
||||
|
||||
|
||||
|
||||
int MacPackFind (const char* Name)
|
||||
int MacPackFind (const StrBuf* Name)
|
||||
/* Find a macro package by name. The function will either return the id or
|
||||
* -1 if the package name was not found.
|
||||
*/
|
||||
@ -90,7 +90,7 @@ int MacPackFind (const char* Name)
|
||||
int I;
|
||||
|
||||
for (I = 0; I < MAC_COUNT; ++I) {
|
||||
if (StrCaseCmp (Name, MacPackages[I].Name) == 0) {
|
||||
if (SB_CompareStr (Name, MacPackages[I].Name) == 0) {
|
||||
/* Found */
|
||||
return I;
|
||||
}
|
||||
@ -130,21 +130,21 @@ void MacPackInsert (int Id)
|
||||
NewInputFile (SB_GetConstBuf (&Filename));
|
||||
|
||||
/* Destroy the contents of Filename */
|
||||
DoneStrBuf (&Filename);
|
||||
SB_Done (&Filename);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MacPackSetDir (const char* Dir)
|
||||
void MacPackSetDir (const StrBuf* Dir)
|
||||
/* Set a directory where files for macro packages can be found. Standard is
|
||||
* to use the builtin packages. For debugging macro packages, external files
|
||||
* can be used.
|
||||
*/
|
||||
{
|
||||
/* Copy the directory name to the buffer */
|
||||
SB_CopyStr (&MacPackDir, Dir);
|
||||
SB_Copy (&MacPackDir, Dir);
|
||||
|
||||
/* Make sure that the last character is a path delimiter */
|
||||
if (SB_NotEmpty (&MacPackDir)) {
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2005, Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 1998-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -38,6 +38,11 @@
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "strbuf.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
@ -64,7 +69,7 @@ enum {
|
||||
|
||||
|
||||
|
||||
int MacPackFind (const char* Name);
|
||||
int MacPackFind (const StrBuf* Name);
|
||||
/* Find a macro package by name. The function will either return the id or
|
||||
* -1 if the package name was not found.
|
||||
*/
|
||||
@ -72,7 +77,7 @@ int MacPackFind (const char* Name);
|
||||
void MacPackInsert (int Id);
|
||||
/* Insert the macro package with the given id in the input stream */
|
||||
|
||||
void MacPackSetDir (const char* Dir);
|
||||
void MacPackSetDir (const StrBuf* Dir);
|
||||
/* Set a directory where files for macro packages can be found. Standard is
|
||||
* to use the builtin packages. For debugging macro packages, external files
|
||||
* can be used.
|
||||
|
122
src/ca65/macro.c
122
src/ca65/macro.c
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2007 Ullrich von Bassewitz */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -88,7 +88,7 @@ static int HT_Compare (const void* Key1, const void* Key2);
|
||||
typedef struct IdDesc IdDesc;
|
||||
struct IdDesc {
|
||||
IdDesc* Next; /* Linked list */
|
||||
char Id [1]; /* Identifier, dynamically allocated */
|
||||
StrBuf Id; /* Identifier, dynamically allocated */
|
||||
};
|
||||
|
||||
|
||||
@ -106,7 +106,7 @@ struct Macro {
|
||||
TokNode* TokRoot; /* Root of token list */
|
||||
TokNode* TokLast; /* Pointer to last token in list */
|
||||
unsigned char Style; /* Macro style */
|
||||
char Name [1]; /* Macro name, dynamically allocated */
|
||||
StrBuf Name; /* Macro name, dynamically allocated */
|
||||
};
|
||||
|
||||
/* Hash table functions */
|
||||
@ -157,7 +157,7 @@ static unsigned LocalName = 0;
|
||||
static unsigned HT_GenHash (const void* Key)
|
||||
/* Generate the hash over a key. */
|
||||
{
|
||||
return HashStr (Key);
|
||||
return HashBuf (Key);
|
||||
}
|
||||
|
||||
|
||||
@ -165,7 +165,7 @@ static unsigned HT_GenHash (const void* Key)
|
||||
static const void* HT_GetKey (void* Entry)
|
||||
/* Given a pointer to the user entry data, return a pointer to the index */
|
||||
{
|
||||
return ((Macro*) Entry)->Name;
|
||||
return &((Macro*) Entry)->Name;
|
||||
}
|
||||
|
||||
|
||||
@ -184,7 +184,7 @@ static int HT_Compare (const void* Key1, const void* Key2)
|
||||
* than zero if Key1 is greater then Key2.
|
||||
*/
|
||||
{
|
||||
return strcmp (Key1, Key2);
|
||||
return SB_Compare (Key1, Key2);
|
||||
}
|
||||
|
||||
|
||||
@ -195,17 +195,16 @@ static int HT_Compare (const void* Key1, const void* Key2)
|
||||
|
||||
|
||||
|
||||
static IdDesc* NewIdDesc (const char* Id)
|
||||
static IdDesc* NewIdDesc (const StrBuf* Id)
|
||||
/* Create a new IdDesc, initialize and return it */
|
||||
{
|
||||
/* Allocate memory */
|
||||
unsigned Len = strlen (Id);
|
||||
IdDesc* I = xmalloc (sizeof (IdDesc) + Len);
|
||||
IdDesc* I = xmalloc (sizeof (IdDesc));
|
||||
|
||||
/* Initialize the struct */
|
||||
I->Next = 0;
|
||||
memcpy (I->Id, Id, Len);
|
||||
I->Id [Len] = '\0';
|
||||
I->Id = AUTO_STRBUF_INITIALIZER;
|
||||
SB_Copy (&I->Id, Id);
|
||||
|
||||
/* Return the new struct */
|
||||
return I;
|
||||
@ -213,12 +212,11 @@ static IdDesc* NewIdDesc (const char* Id)
|
||||
|
||||
|
||||
|
||||
static Macro* NewMacro (const char* Name, unsigned char Style)
|
||||
static Macro* NewMacro (const StrBuf* Name, unsigned char Style)
|
||||
/* Generate a new macro entry, initialize and return it */
|
||||
{
|
||||
/* Allocate memory */
|
||||
unsigned Len = strlen (Name);
|
||||
Macro* M = xmalloc (sizeof (Macro) + Len);
|
||||
Macro* M = xmalloc (sizeof (Macro));
|
||||
|
||||
/* Initialize the macro struct */
|
||||
InitHashNode (&M->Node, M);
|
||||
@ -230,7 +228,8 @@ static Macro* NewMacro (const char* Name, unsigned char Style)
|
||||
M->TokRoot = 0;
|
||||
M->TokLast = 0;
|
||||
M->Style = Style;
|
||||
memcpy (M->Name, Name, Len+1);
|
||||
M->Name = AUTO_STRBUF_INITIALIZER;
|
||||
SB_Copy (&M->Name, Name);
|
||||
|
||||
/* Insert the macro into the global macro list */
|
||||
M->List = MacroRoot;
|
||||
@ -340,7 +339,7 @@ void MacDef (unsigned Style)
|
||||
Error ("Identifier expected");
|
||||
MacSkipDef (Style);
|
||||
return;
|
||||
} else if (!UbiquitousIdents && FindInstruction (SVal) >= 0) {
|
||||
} else if (!UbiquitousIdents && FindInstruction (&SVal) >= 0) {
|
||||
/* The identifier is a name of a 6502 instruction, which is not
|
||||
* allowed if not explicitly enabled.
|
||||
*/
|
||||
@ -350,16 +349,16 @@ void MacDef (unsigned Style)
|
||||
}
|
||||
|
||||
/* Did we already define that macro? */
|
||||
if (HT_Find (&MacroTab, SVal) != 0) {
|
||||
if (HT_Find (&MacroTab, &SVal) != 0) {
|
||||
/* Macro is already defined */
|
||||
Error ("A macro named `%s' is already defined", SVal);
|
||||
Error ("A macro named `%m%p' is already defined", &SVal);
|
||||
/* Skip tokens until we reach the final .endmacro */
|
||||
MacSkipDef (Style);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Define the macro */
|
||||
M = NewMacro (SVal, Style);
|
||||
M = NewMacro (&SVal, Style);
|
||||
|
||||
/* Switch to raw token mode and skip the macro name */
|
||||
EnterRawTokenMode ();
|
||||
@ -369,45 +368,45 @@ void MacDef (unsigned Style)
|
||||
* otherwise we may have parameters without braces.
|
||||
*/
|
||||
if (Style == MAC_STYLE_CLASSIC) {
|
||||
HaveParams = 1;
|
||||
HaveParams = 1;
|
||||
} else {
|
||||
if (Tok == TOK_LPAREN) {
|
||||
HaveParams = 1;
|
||||
NextTok ();
|
||||
} else {
|
||||
HaveParams = 0;
|
||||
}
|
||||
if (Tok == TOK_LPAREN) {
|
||||
HaveParams = 1;
|
||||
NextTok ();
|
||||
} else {
|
||||
HaveParams = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the parameter list */
|
||||
if (HaveParams) {
|
||||
|
||||
while (Tok == TOK_IDENT) {
|
||||
while (Tok == TOK_IDENT) {
|
||||
|
||||
/* Create a struct holding the identifier */
|
||||
IdDesc* I = NewIdDesc (SVal);
|
||||
/* Create a struct holding the identifier */
|
||||
IdDesc* I = NewIdDesc (&SVal);
|
||||
|
||||
/* Insert the struct into the list, checking for duplicate idents */
|
||||
if (M->ParamCount == 0) {
|
||||
M->Params = I;
|
||||
} else {
|
||||
IdDesc* List = M->Params;
|
||||
while (1) {
|
||||
if (strcmp (List->Id, SVal) == 0) {
|
||||
Error ("Duplicate symbol `%s'", SVal);
|
||||
}
|
||||
if (List->Next == 0) {
|
||||
break;
|
||||
} else {
|
||||
List = List->Next;
|
||||
}
|
||||
}
|
||||
List->Next = I;
|
||||
}
|
||||
++M->ParamCount;
|
||||
/* Insert the struct into the list, checking for duplicate idents */
|
||||
if (M->ParamCount == 0) {
|
||||
M->Params = I;
|
||||
} else {
|
||||
IdDesc* List = M->Params;
|
||||
while (1) {
|
||||
if (SB_Compare (&List->Id, &SVal) == 0) {
|
||||
Error ("Duplicate symbol `%m%p'", &SVal);
|
||||
}
|
||||
if (List->Next == 0) {
|
||||
break;
|
||||
} else {
|
||||
List = List->Next;
|
||||
}
|
||||
}
|
||||
List->Next = I;
|
||||
}
|
||||
++M->ParamCount;
|
||||
|
||||
/* Skip the name */
|
||||
NextTok ();
|
||||
NextTok ();
|
||||
|
||||
/* Maybe there are more params... */
|
||||
if (Tok == TOK_COMMA) {
|
||||
@ -471,7 +470,7 @@ void MacDef (unsigned Style)
|
||||
}
|
||||
|
||||
/* Put the identifier into the locals list and skip it */
|
||||
I = NewIdDesc (SVal);
|
||||
I = NewIdDesc (&SVal);
|
||||
I->Next = M->Locals;
|
||||
M->Locals = I;
|
||||
++M->LocalCount;
|
||||
@ -497,7 +496,7 @@ void MacDef (unsigned Style)
|
||||
unsigned Count = 0;
|
||||
IdDesc* I = M->Params;
|
||||
while (I) {
|
||||
if (strcmp (I->Id, SVal) == 0) {
|
||||
if (SB_Compare (&I->Id, &SVal) == 0) {
|
||||
/* Local param name, replace it */
|
||||
T->Tok = TOK_MACPARAM;
|
||||
T->IVal = Count;
|
||||
@ -607,15 +606,21 @@ static int MacExpand (void* Data)
|
||||
unsigned Index = 0;
|
||||
IdDesc* I = Mac->M->Locals;
|
||||
while (I) {
|
||||
if (strcmp (SVal, I->Id) == 0) {
|
||||
if (SB_Compare (&SVal, &I->Id) == 0) {
|
||||
/* This is in fact a local symbol, change the name. Be sure
|
||||
* to generate a local label name if the original name was
|
||||
* a local label, and also generate a name that cannot be
|
||||
* generated by a user.
|
||||
*/
|
||||
unsigned PrefixLen = (I->Id[0] == LocalStart);
|
||||
sprintf (SVal, "%.*sLOCAL-MACRO-SYMBOL-%04X", PrefixLen,
|
||||
I->Id, Mac->LocalStart + Index);
|
||||
if (SB_At (&I->Id, 0) == LocalStart) {
|
||||
/* Must generate a local symbol */
|
||||
SB_Printf (&SVal, "%cLOCAL-MACRO_SYMBOL-%04X",
|
||||
LocalStart, Mac->LocalStart + Index);
|
||||
} else {
|
||||
/* Global symbol */
|
||||
SB_Printf (&SVal, "LOCAL-MACRO_SYMBOL-%04X",
|
||||
Mac->LocalStart + Index);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Next symbol */
|
||||
@ -836,7 +841,7 @@ void MacExpandStart (void)
|
||||
/* Start expanding the macro in SVal */
|
||||
{
|
||||
/* Search for the macro */
|
||||
Macro* M = HT_FindEntry (&MacroTab, SVal);
|
||||
Macro* M = HT_FindEntry (&MacroTab, &SVal);
|
||||
CHECK (M != 0);
|
||||
|
||||
/* Call the apropriate subroutine */
|
||||
@ -861,7 +866,7 @@ void MacAbort (void)
|
||||
|
||||
|
||||
|
||||
int IsMacro (const char* Name)
|
||||
int IsMacro (const StrBuf* Name)
|
||||
/* Return true if the given name is the name of a macro */
|
||||
{
|
||||
return (HT_Find (&MacroTab, Name) != 0);
|
||||
@ -869,7 +874,7 @@ int IsMacro (const char* Name)
|
||||
|
||||
|
||||
|
||||
int IsDefine (const char* Name)
|
||||
int IsDefine (const StrBuf* Name)
|
||||
/* Return true if the given name is the name of a define style macro */
|
||||
{
|
||||
Macro* M = HT_FindEntry (&MacroTab, Name);
|
||||
@ -886,6 +891,3 @@ int InMacExpansion (void)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2000 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -65,10 +65,10 @@ void MacExpandStart (void);
|
||||
void MacAbort (void);
|
||||
/* Abort the current macro expansion */
|
||||
|
||||
int IsMacro (const char* Name);
|
||||
int IsMacro (const StrBuf* Name);
|
||||
/* Return true if the given name is the name of a macro */
|
||||
|
||||
int IsDefine (const char* Name);
|
||||
int IsDefine (const StrBuf* Name);
|
||||
/* Return true if the given name is the name of a define style macro */
|
||||
|
||||
int InMacExpansion (void);
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2007, Ullrich von Bassewitz */
|
||||
/* (C) 1998-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -44,6 +44,7 @@
|
||||
#include "cmdline.h"
|
||||
#include "mmodel.h"
|
||||
#include "print.h"
|
||||
#include "strbuf.h"
|
||||
#include "target.h"
|
||||
#include "tgttrans.h"
|
||||
#include "version.h"
|
||||
@ -127,14 +128,17 @@ static void Usage (void)
|
||||
static void SetOptions (void)
|
||||
/* Set the option for the translator */
|
||||
{
|
||||
char Buf [256];
|
||||
StrBuf Buf = STATIC_STRBUF_INITIALIZER;
|
||||
|
||||
/* Set the translator */
|
||||
sprintf (Buf, "ca65 V%u.%u.%u", VER_MAJOR, VER_MINOR, VER_PATCH);
|
||||
OptTranslator (Buf);
|
||||
SB_Printf (&Buf, "ca65 V%u.%u.%u", VER_MAJOR, VER_MINOR, VER_PATCH);
|
||||
OptTranslator (&Buf);
|
||||
|
||||
/* Set date and time */
|
||||
OptDateTime ((unsigned long) time(0));
|
||||
|
||||
/* Release memory for the string */
|
||||
SB_Done (&Buf);
|
||||
}
|
||||
|
||||
|
||||
@ -144,8 +148,12 @@ static void NewSymbol (const char* SymName, long Val)
|
||||
{
|
||||
ExprNode* Expr;
|
||||
|
||||
/* Convert the name to a string buffer */
|
||||
StrBuf SymBuf = STATIC_STRBUF_INITIALIZER;
|
||||
SB_CopyStr (&SymBuf, SymName);
|
||||
|
||||
/* Search for the symbol, allocate a new one if it doesn't exist */
|
||||
SymEntry* Sym = SymFind (CurrentScope, SymName, SYM_ALLOC_NEW);
|
||||
SymEntry* Sym = SymFind (CurrentScope, &SymBuf, SYM_ALLOC_NEW);
|
||||
|
||||
/* Check if have already a symbol with this name */
|
||||
if (SymIsDef (Sym)) {
|
||||
@ -157,6 +165,9 @@ static void NewSymbol (const char* SymName, long Val)
|
||||
|
||||
/* Mark the symbol as defined */
|
||||
SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_NONE);
|
||||
|
||||
/* Free string buffer memory */
|
||||
SB_Done (&SymBuf);
|
||||
}
|
||||
|
||||
|
||||
@ -276,24 +287,21 @@ static void DefineSymbol (const char* Def)
|
||||
const char* P;
|
||||
unsigned I;
|
||||
long Val;
|
||||
char SymName [MAX_STR_LEN+1];
|
||||
StrBuf SymName = AUTO_STRBUF_INITIALIZER;
|
||||
|
||||
|
||||
/* The symbol must start with a character or underline */
|
||||
if (Def [0] != '_' && !IsAlpha (Def [0])) {
|
||||
if (!IsIdStart (Def [0])) {
|
||||
InvDef (Def);
|
||||
}
|
||||
P = Def;
|
||||
|
||||
|
||||
/* Copy the symbol, checking the rest */
|
||||
I = 0;
|
||||
while (IsAlNum (*P) || *P == '_') {
|
||||
if (I <= MAX_STR_LEN) {
|
||||
SymName [I++] = *P;
|
||||
}
|
||||
++P;
|
||||
while (IsIdChar (*P)) {
|
||||
SB_AppendChar (&SymName, *P++);
|
||||
}
|
||||
SymName [I] = '\0';
|
||||
SB_Terminate (&SymName);
|
||||
|
||||
/* Do we have a value given? */
|
||||
if (*P != '=') {
|
||||
@ -317,7 +325,10 @@ static void DefineSymbol (const char* Def)
|
||||
}
|
||||
|
||||
/* Define the new symbol */
|
||||
NewSymbol (SymName, Val);
|
||||
NewSymbol (SB_GetConstBuf (&SymName), Val);
|
||||
|
||||
/* Release string memory */
|
||||
SB_Done (&SymName);
|
||||
}
|
||||
|
||||
|
||||
@ -356,8 +367,11 @@ static void OptDebugInfo (const char* Opt attribute ((unused)),
|
||||
static void OptFeature (const char* Opt attribute ((unused)), const char* Arg)
|
||||
/* Set an emulation feature */
|
||||
{
|
||||
/* Make a string buffer from Arg */
|
||||
StrBuf Feature;
|
||||
|
||||
/* Set the feature, check for errors */
|
||||
if (SetFeature (Arg) == FEAT_UNKNOWN) {
|
||||
if (SetFeature (SB_InitFromString (&Feature, Arg)) == FEAT_UNKNOWN) {
|
||||
AbEnd ("Illegal emulation feature: `%s'", Arg);
|
||||
}
|
||||
}
|
||||
@ -425,8 +439,11 @@ static void OptListing (const char* Opt attribute ((unused)),
|
||||
static void OptMacPackDir (const char* Opt attribute ((unused)), const char* Arg)
|
||||
/* Set a macro package directory */
|
||||
{
|
||||
/* Make a string buffer from Arg */
|
||||
StrBuf Dir;
|
||||
|
||||
/* Use the directory */
|
||||
MacPackSetDir (Arg);
|
||||
MacPackSetDir (SB_InitFromString (&Dir, Arg));
|
||||
}
|
||||
|
||||
|
||||
@ -545,13 +562,13 @@ static void OneLine (void)
|
||||
if (Tok == TOK_IDENT) {
|
||||
if (!UbiquitousIdents) {
|
||||
/* Macros and symbols cannot use instruction names */
|
||||
Instr = FindInstruction (SVal);
|
||||
Instr = FindInstruction (&SVal);
|
||||
if (Instr < 0) {
|
||||
Macro = IsMacro (SVal);
|
||||
Macro = IsMacro (&SVal);
|
||||
}
|
||||
} else {
|
||||
/* Macros and symbols may use the names of instructions */
|
||||
Macro = IsMacro (SVal);
|
||||
Macro = IsMacro (&SVal);
|
||||
}
|
||||
}
|
||||
|
||||
@ -563,9 +580,9 @@ static void OneLine (void)
|
||||
|
||||
/* Generate the symbol table entry, then skip the name */
|
||||
if (Tok == TOK_IDENT) {
|
||||
Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW);
|
||||
Sym = SymFind (CurrentScope, &SVal, SYM_ALLOC_NEW);
|
||||
} else {
|
||||
Sym = SymFindLocal (SymLast, SVal, SYM_ALLOC_NEW);
|
||||
Sym = SymFindLocal (SymLast, &SVal, SYM_ALLOC_NEW);
|
||||
}
|
||||
NextTok ();
|
||||
|
||||
@ -640,13 +657,13 @@ static void OneLine (void)
|
||||
if (Tok == TOK_IDENT) {
|
||||
if (!UbiquitousIdents) {
|
||||
/* Macros and symbols cannot use instruction names */
|
||||
Instr = FindInstruction (SVal);
|
||||
Instr = FindInstruction (&SVal);
|
||||
if (Instr < 0) {
|
||||
Macro = IsMacro (SVal);
|
||||
Macro = IsMacro (&SVal);
|
||||
}
|
||||
} else {
|
||||
/* Macros and symbols may use the names of instructions */
|
||||
Macro = IsMacro (SVal);
|
||||
Macro = IsMacro (&SVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -660,7 +677,7 @@ static void OneLine (void)
|
||||
/* A macro expansion */
|
||||
MacExpandStart ();
|
||||
} else if (Instr >= 0 ||
|
||||
(UbiquitousIdents && ((Instr = FindInstruction (SVal)) >= 0))) {
|
||||
(UbiquitousIdents && ((Instr = FindInstruction (&SVal)) >= 0))) {
|
||||
/* A mnemonic - assemble one instruction */
|
||||
HandleInstruction (Instr);
|
||||
} else if (PCAssignment && (Tok == TOK_STAR || Tok == TOK_PC)) {
|
||||
@ -774,6 +791,9 @@ int main (int argc, char* argv [])
|
||||
{ "--version", 0, OptVersion },
|
||||
};
|
||||
|
||||
/* Name of the global name space */
|
||||
static const StrBuf GlobalNameSpace = STATIC_STRBUF_INITIALIZER;
|
||||
|
||||
unsigned I;
|
||||
|
||||
/* Initialize the cmdline module */
|
||||
@ -782,7 +802,7 @@ int main (int argc, char* argv [])
|
||||
/* Enter the base lexical level. We must do that here, since we may
|
||||
* define symbols using -D.
|
||||
*/
|
||||
SymEnterLevel ("", ST_GLOBAL, ADDR_SIZE_DEFAULT);
|
||||
SymEnterLevel (&GlobalNameSpace, ST_GLOBAL, ADDR_SIZE_DEFAULT);
|
||||
|
||||
/* Check the parameters */
|
||||
I = 1;
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2007 Ullrich von Bassewitz */
|
||||
/* (C) 2000-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -142,10 +142,7 @@ static TokList* CollectTokens (unsigned Start, unsigned Count)
|
||||
static void FuncConcat (void)
|
||||
/* Handle the .CONCAT function */
|
||||
{
|
||||
char Buf[MAX_STR_LEN+1];
|
||||
char* B;
|
||||
unsigned Length;
|
||||
unsigned L;
|
||||
StrBuf Buf = STATIC_STRBUF_INITIALIZER;
|
||||
|
||||
/* Skip it */
|
||||
NextTok ();
|
||||
@ -154,29 +151,16 @@ static void FuncConcat (void)
|
||||
ConsumeLParen ();
|
||||
|
||||
/* Concatenate any number of strings */
|
||||
B = Buf;
|
||||
B[0] = '\0';
|
||||
Length = 0;
|
||||
while (1) {
|
||||
|
||||
/* Next token must be a string */
|
||||
if (!LookAtStrCon ()) {
|
||||
SB_Done (&Buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the length of the string const and check total length */
|
||||
L = strlen (SVal);
|
||||
if (Length + L > MAX_STR_LEN) {
|
||||
Error ("String is too long");
|
||||
/* Try to recover */
|
||||
SkipUntilSep ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add the new string */
|
||||
memcpy (B, SVal, L);
|
||||
Length += L;
|
||||
B += L;
|
||||
/* Append the string */
|
||||
SB_Append (&Buf, &SVal);
|
||||
|
||||
/* Skip the string token */
|
||||
NextTok ();
|
||||
@ -190,9 +174,6 @@ static void FuncConcat (void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate the string */
|
||||
*B = '\0';
|
||||
|
||||
/* We expect a closing parenthesis, but will not skip it but replace it
|
||||
* by the string token just created.
|
||||
*/
|
||||
@ -200,8 +181,11 @@ static void FuncConcat (void)
|
||||
Error ("`)' expected");
|
||||
} else {
|
||||
Tok = TOK_STRCON;
|
||||
strcpy (SVal, Buf);
|
||||
SB_Copy (&SVal, &Buf);
|
||||
}
|
||||
|
||||
/* Free the string buffer */
|
||||
SB_Done (&Buf);
|
||||
}
|
||||
|
||||
|
||||
@ -218,9 +202,8 @@ static void NoIdent (void)
|
||||
static void FuncIdent (void)
|
||||
/* Handle the .IDENT function */
|
||||
{
|
||||
char Buf[sizeof(SVal)];
|
||||
StrBuf Buf = STATIC_STRBUF_INITIALIZER;
|
||||
Token Id;
|
||||
unsigned Len;
|
||||
unsigned I;
|
||||
|
||||
/* Skip it */
|
||||
@ -237,49 +220,45 @@ static void FuncIdent (void)
|
||||
/* Check that the string contains a valid identifier. While doing so,
|
||||
* determine if it is a cheap local, or global one.
|
||||
*/
|
||||
Len = strlen (SVal);
|
||||
if (Len == 0) {
|
||||
NoIdent ();
|
||||
return;
|
||||
}
|
||||
I = 0;
|
||||
if (SVal[0] == LocalStart) {
|
||||
if (Len < 2) {
|
||||
NoIdent ();
|
||||
return;
|
||||
}
|
||||
I = 1;
|
||||
SB_Reset (&SVal);
|
||||
|
||||
/* Check for a cheap local symbol */
|
||||
if (SB_Peek (&SVal) == LocalStart) {
|
||||
SB_Skip (&SVal);
|
||||
Id = TOK_LOCAL_IDENT;
|
||||
} else {
|
||||
Id = TOK_IDENT;
|
||||
}
|
||||
if (!IsIdStart (SVal[I])) {
|
||||
|
||||
/* Next character must be a valid identifier start */
|
||||
if (!IsIdStart (SB_Get (&SVal))) {
|
||||
NoIdent ();
|
||||
return;
|
||||
}
|
||||
while (I < Len) {
|
||||
if (!IsIdChar (SVal[I])) {
|
||||
for (I = SB_GetIndex (&SVal); I < SB_GetLen (&SVal); ++I) {
|
||||
if (!IsIdChar (SB_AtUnchecked (&SVal, I))) {
|
||||
NoIdent ();
|
||||
return;
|
||||
}
|
||||
++I;
|
||||
}
|
||||
if (IgnoreCase) {
|
||||
UpcaseSVal ();
|
||||
}
|
||||
|
||||
/* If anything is ok, save and skip the string. Check that the next token
|
||||
* is a right paren, in which case SVal is untouched. Replace the token by
|
||||
* a identifier token.
|
||||
* is a right paren, then replace the token by an identifier token.
|
||||
*/
|
||||
memcpy (Buf, SVal, Len+1);
|
||||
SB_Copy (&Buf, &SVal);
|
||||
NextTok ();
|
||||
if (Tok != TOK_RPAREN) {
|
||||
Error ("`)' expected");
|
||||
} else {
|
||||
Tok = Id;
|
||||
memcpy (SVal, Buf, Len+1);
|
||||
SB_Copy (&SVal, &Buf);
|
||||
}
|
||||
|
||||
/* Free buffer memory */
|
||||
SB_Done (&Buf);
|
||||
}
|
||||
|
||||
|
||||
@ -443,11 +422,11 @@ static void InvalidFormatString (void)
|
||||
static void FuncSPrintF (void)
|
||||
/* Handle the .SPRINTF function */
|
||||
{
|
||||
char Format[sizeof (SVal)]; /* User given format */
|
||||
const char* F = Format; /* User format pointer */
|
||||
StrBuf R = AUTO_STRBUF_INITIALIZER; /* Result string */
|
||||
StrBuf F1 = AUTO_STRBUF_INITIALIZER; /* One format spec from F */
|
||||
StrBuf R1 = AUTO_STRBUF_INITIALIZER; /* One result */
|
||||
StrBuf Format = STATIC_STRBUF_INITIALIZER; /* User supplied format */
|
||||
StrBuf R = STATIC_STRBUF_INITIALIZER; /* Result string */
|
||||
StrBuf F1 = STATIC_STRBUF_INITIALIZER; /* One format spec from F */
|
||||
StrBuf R1 = STATIC_STRBUF_INITIALIZER; /* One result */
|
||||
char C;
|
||||
int Done;
|
||||
long IVal; /* Integer value */
|
||||
|
||||
@ -463,30 +442,31 @@ static void FuncSPrintF (void)
|
||||
if (!LookAtStrCon ()) {
|
||||
return;
|
||||
}
|
||||
strcpy (Format, SVal);
|
||||
SB_Copy (&Format, &SVal);
|
||||
NextTok ();
|
||||
|
||||
/* Walk over the format string, generating the function result in R */
|
||||
while (1) {
|
||||
|
||||
/* Get the next char from the format string and check for EOS */
|
||||
if (*F == '\0') {
|
||||
if (SB_Peek (&Format) == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check for a format specifier */
|
||||
if (*F != '%') {
|
||||
if (SB_Peek (&Format) != '%') {
|
||||
/* No format specifier, just copy */
|
||||
SB_AppendChar (&R, *F++);
|
||||
SB_AppendChar (&R, SB_Get (&Format));
|
||||
continue;
|
||||
}
|
||||
if (*++F == '%') {
|
||||
SB_Skip (&Format);
|
||||
if (SB_Peek (&Format) == '%') {
|
||||
/* %% */
|
||||
SB_AppendChar (&R, '%');
|
||||
++F;
|
||||
SB_Skip (&Format);
|
||||
continue;
|
||||
}
|
||||
if (*F == '\0') {
|
||||
if (SB_Peek (&Format) == '\0') {
|
||||
InvalidFormatString ();
|
||||
break;
|
||||
}
|
||||
@ -505,32 +485,32 @@ static void FuncSPrintF (void)
|
||||
|
||||
/* Check for flags */
|
||||
Done = 0;
|
||||
while (*F != '\0' && !Done) {
|
||||
switch (*F) {
|
||||
while ((C = SB_Peek (&Format)) != '\0' && !Done) {
|
||||
switch (C) {
|
||||
case '-': /* FALLTHROUGH */
|
||||
case '+': /* FALLTHROUGH */
|
||||
case ' ': /* FALLTHROUGH */
|
||||
case '#': /* FALLTHROUGH */
|
||||
case '0': SB_AppendChar (&F1, *F++); break;
|
||||
default: Done = 1; break;
|
||||
case '0': SB_AppendChar (&F1, SB_Get (&Format)); break;
|
||||
default: Done = 1; break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We do only support a numerical width field */
|
||||
while (IsDigit (*F)) {
|
||||
SB_AppendChar (&F1, *F++);
|
||||
while (IsDigit (SB_Peek (&Format))) {
|
||||
SB_AppendChar (&F1, SB_Get (&Format));
|
||||
}
|
||||
|
||||
/* Precision - only positive numerical fields supported */
|
||||
if (*F == '.') {
|
||||
SB_AppendChar (&F1, *F++);
|
||||
while (IsDigit (*F)) {
|
||||
SB_AppendChar (&F1, *F++);
|
||||
if (SB_Peek (&Format) == '.') {
|
||||
SB_AppendChar (&F1, SB_Get (&Format));
|
||||
while (IsDigit (SB_Peek (&Format))) {
|
||||
SB_AppendChar (&F1, SB_Get (&Format));
|
||||
}
|
||||
}
|
||||
|
||||
/* Length modifiers aren't supported, so read the conversion specs */
|
||||
switch (*F) {
|
||||
switch (SB_Peek (&Format)) {
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
@ -542,7 +522,7 @@ static void FuncSPrintF (void)
|
||||
* calling xsprintf later. Terminate the format string.
|
||||
*/
|
||||
SB_AppendChar (&F1, 'l');
|
||||
SB_AppendChar (&F1, *F++);
|
||||
SB_AppendChar (&F1, SB_Get (&Format));
|
||||
SB_Terminate (&F1);
|
||||
|
||||
/* The argument must be a constant expression */
|
||||
@ -558,13 +538,13 @@ static void FuncSPrintF (void)
|
||||
|
||||
case 's':
|
||||
/* Add the format spec and terminate the format */
|
||||
SB_AppendChar (&F1, *F++);
|
||||
SB_AppendChar (&F1, SB_Get (&Format));
|
||||
SB_Terminate (&F1);
|
||||
|
||||
/* The argument must be a string constant */
|
||||
if (!LookAtStrCon ()) {
|
||||
/* Make it one */
|
||||
strcpy (SVal, "**undefined**");
|
||||
SB_CopyStr (&SVal, "**undefined**");
|
||||
}
|
||||
|
||||
/* Format this argument according to the spec */
|
||||
@ -580,7 +560,7 @@ static void FuncSPrintF (void)
|
||||
|
||||
case 'c':
|
||||
/* Add the format spec and terminate the format */
|
||||
SB_AppendChar (&F1, *F++);
|
||||
SB_AppendChar (&F1, SB_Get (&Format));
|
||||
SB_Terminate (&F1);
|
||||
|
||||
/* The argument must be a constant expression */
|
||||
@ -604,21 +584,12 @@ static void FuncSPrintF (void)
|
||||
|
||||
default:
|
||||
Error ("Invalid format string");
|
||||
if (*F) {
|
||||
/* Don't skip beyond end of string */
|
||||
++F;
|
||||
}
|
||||
SB_Skip (&Format);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* The length of the final result may not exceed the size of a string */
|
||||
if (SB_GetLen (&R) >= sizeof (SVal)) {
|
||||
Error ("Resulting string is too long");
|
||||
SB_Cut (&R, sizeof (SVal) - 1);
|
||||
}
|
||||
|
||||
/* Terminate the result string */
|
||||
SB_Terminate (&R);
|
||||
|
||||
@ -629,14 +600,15 @@ static void FuncSPrintF (void)
|
||||
Error ("`)' expected");
|
||||
} else {
|
||||
Tok = TOK_STRCON;
|
||||
memcpy (SVal, SB_GetConstBuf (&R), SB_GetLen (&R) + 1);
|
||||
SB_Copy (&SVal, &R);
|
||||
}
|
||||
|
||||
|
||||
/* Delete the string buffers */
|
||||
DoneStrBuf (&R);
|
||||
DoneStrBuf (&F1);
|
||||
DoneStrBuf (&R1);
|
||||
SB_Done (&Format);
|
||||
SB_Done (&R);
|
||||
SB_Done (&F1);
|
||||
SB_Done (&R1);
|
||||
}
|
||||
|
||||
|
||||
@ -644,7 +616,7 @@ static void FuncSPrintF (void)
|
||||
static void FuncString (void)
|
||||
/* Handle the .STRING function */
|
||||
{
|
||||
char Buf[MAX_STR_LEN+1];
|
||||
StrBuf Buf = STATIC_STRBUF_INITIALIZER;
|
||||
|
||||
/* Skip it */
|
||||
NextTok ();
|
||||
@ -655,12 +627,12 @@ static void FuncString (void)
|
||||
/* Accept identifiers or numeric expressions */
|
||||
if (Tok == TOK_IDENT || Tok == TOK_LOCAL_IDENT) {
|
||||
/* Save the identifier, then skip it */
|
||||
strcpy (Buf, SVal);
|
||||
SB_Copy (&Buf, &SVal);
|
||||
NextTok ();
|
||||
} else {
|
||||
/* Numeric expression */
|
||||
long Val = ConstExpression ();
|
||||
sprintf (Buf, "%ld", Val);
|
||||
SB_Printf (&Buf, "%ld", Val);
|
||||
}
|
||||
|
||||
/* We expect a closing parenthesis, but will not skip it but replace it
|
||||
@ -670,8 +642,11 @@ static void FuncString (void)
|
||||
Error ("`)' expected");
|
||||
} else {
|
||||
Tok = TOK_STRCON;
|
||||
strcpy (SVal, Buf);
|
||||
SB_Copy (&SVal, &Buf);
|
||||
}
|
||||
|
||||
/* Free string memory */
|
||||
SB_Done (&Buf);
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -104,15 +104,18 @@ void EmitPCRel (unsigned char OPC, ExprNode* Expr, unsigned Size)
|
||||
|
||||
|
||||
|
||||
void EmitData (const unsigned char* Data, unsigned Size)
|
||||
void EmitData (const void* D, unsigned Size)
|
||||
/* Emit data into the current segment */
|
||||
{
|
||||
/* Make a useful pointer from Data */
|
||||
const unsigned char* Data = D;
|
||||
|
||||
/* Create lots of fragments for the data */
|
||||
while (Size) {
|
||||
Fragment* F;
|
||||
Fragment* F;
|
||||
|
||||
/* Determine the length of the next fragment */
|
||||
unsigned Len = Size;
|
||||
/* Determine the length of the next fragment */
|
||||
unsigned Len = Size;
|
||||
if (Len > sizeof (F->V.Data)) {
|
||||
Len = sizeof (F->V.Data);
|
||||
}
|
||||
@ -132,6 +135,15 @@ void EmitData (const unsigned char* Data, unsigned Size)
|
||||
|
||||
|
||||
|
||||
void EmitStrBuf (const StrBuf* Data)
|
||||
/* Emit a string into the current segment */
|
||||
{
|
||||
/* Use EmitData to output the data */
|
||||
EmitData (SB_GetConstBuf (Data), SB_GetLen (Data));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void EmitByte (ExprNode* Expr)
|
||||
/* Emit one byte */
|
||||
{
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -40,6 +40,7 @@
|
||||
|
||||
/* ca65 */
|
||||
#include "expr.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
|
||||
|
||||
@ -67,9 +68,12 @@ void EmitSigned (ExprNode* Expr, unsigned Size);
|
||||
void EmitPCRel (unsigned char OPC, ExprNode* Expr, unsigned Size);
|
||||
/* Emit an opcode with a PC relative argument of one or two bytes */
|
||||
|
||||
void EmitData (const unsigned char* Data, unsigned Size);
|
||||
void EmitData (const void* Data, unsigned Size);
|
||||
/* Emit data into the current segment */
|
||||
|
||||
void EmitStrBuf (const StrBuf* Data);
|
||||
/* Emit a string into the current segment */
|
||||
|
||||
void EmitByte (ExprNode* Expr);
|
||||
/* Emit one byte */
|
||||
|
||||
|
@ -296,6 +296,19 @@ void ObjWriteStr (const char* S)
|
||||
|
||||
|
||||
|
||||
void ObjWriteBuf (const StrBuf* S)
|
||||
/* Write a string to the object file */
|
||||
{
|
||||
/* Write the string with the length preceeded (this is easier for
|
||||
* the reading routine than the C format since the length is known in
|
||||
* advance).
|
||||
*/
|
||||
ObjWriteVar (SB_GetLen (S));
|
||||
ObjWriteData (SB_GetConstBuf (S), SB_GetLen (S));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ObjWriteData (const void* Data, unsigned Size)
|
||||
/* Write literal data to the file */
|
||||
{
|
||||
|
@ -40,6 +40,7 @@
|
||||
|
||||
/* common */
|
||||
#include "filepos.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
|
||||
|
||||
@ -79,6 +80,9 @@ void ObjWriteVar (unsigned long V);
|
||||
void ObjWriteStr (const char* S);
|
||||
/* Write a string to the object file */
|
||||
|
||||
void ObjWriteBuf (const StrBuf* S);
|
||||
/* Write a string to the object file */
|
||||
|
||||
void ObjWriteData (const void* Data, unsigned Size);
|
||||
/* Write literal data to the file */
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2000 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 1998-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -96,50 +96,50 @@ static Option* NewOption (unsigned char Type, unsigned long Val)
|
||||
|
||||
|
||||
|
||||
void OptStr (unsigned char Type, const char* Text)
|
||||
void OptStr (unsigned char Type, const StrBuf* Text)
|
||||
/* Add a string option */
|
||||
{
|
||||
NewOption (Type, GetStringId (Text));
|
||||
NewOption (Type, GetStrBufId (Text));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OptComment (const char* Comment)
|
||||
void OptComment (const StrBuf* Comment)
|
||||
/* Add a comment */
|
||||
{
|
||||
NewOption (OPT_COMMENT, GetStringId (Comment));
|
||||
NewOption (OPT_COMMENT, GetStrBufId (Comment));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OptAuthor (const char* Author)
|
||||
void OptAuthor (const StrBuf* Author)
|
||||
/* Add an author statement */
|
||||
{
|
||||
NewOption (OPT_AUTHOR, GetStringId (Author));
|
||||
NewOption (OPT_AUTHOR, GetStrBufId (Author));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OptTranslator (const char* Translator)
|
||||
void OptTranslator (const StrBuf* Translator)
|
||||
/* Add a translator option */
|
||||
{
|
||||
NewOption (OPT_TRANSLATOR, GetStringId (Translator));
|
||||
NewOption (OPT_TRANSLATOR, GetStrBufId (Translator));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OptCompiler (const char* Compiler)
|
||||
void OptCompiler (const StrBuf* Compiler)
|
||||
/* Add a compiler option */
|
||||
{
|
||||
NewOption (OPT_COMPILER, GetStringId (Compiler));
|
||||
NewOption (OPT_COMPILER, GetStrBufId (Compiler));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OptOS (const char* OS)
|
||||
void OptOS (const StrBuf* OS)
|
||||
/* Add an operating system option */
|
||||
{
|
||||
NewOption (OPT_OS, GetStringId (OS));
|
||||
NewOption (OPT_OS, GetStrBufId (OS));
|
||||
}
|
||||
|
||||
|
||||
@ -182,3 +182,4 @@ void WriteOptions (void)
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 1998-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -44,22 +44,22 @@
|
||||
|
||||
|
||||
|
||||
void OptStr (unsigned char Type, const char* Text);
|
||||
void OptStr (unsigned char Type, const StrBuf* Text);
|
||||
/* Add a string option */
|
||||
|
||||
void OptComment (const char* Comment);
|
||||
void OptComment (const StrBuf* Comment);
|
||||
/* Add a comment */
|
||||
|
||||
void OptAuthor (const char* Author);
|
||||
void OptAuthor (const StrBuf* Author);
|
||||
/* Add an author statement */
|
||||
|
||||
void OptTranslator (const char* Translator);
|
||||
void OptTranslator (const StrBuf* Translator);
|
||||
/* Add a translator option */
|
||||
|
||||
void OptCompiler (const char* Compiler);
|
||||
void OptCompiler (const StrBuf* Compiler);
|
||||
/* Add a compiler option */
|
||||
|
||||
void OptOS (const char* OS);
|
||||
void OptOS (const StrBuf* OS);
|
||||
/* Add an operating system option */
|
||||
|
||||
void OptDateTime (unsigned long DateTime);
|
||||
@ -68,7 +68,7 @@ void OptDateTime (unsigned long DateTime);
|
||||
void WriteOptions (void);
|
||||
/* Write the options to the object file */
|
||||
|
||||
|
||||
|
||||
|
||||
/* End of options.h */
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2007, Ullrich von Bassewitz */
|
||||
/* (C) 1998-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -84,7 +84,7 @@
|
||||
|
||||
|
||||
/* Keyword we're about to handle */
|
||||
static char Keyword [sizeof (SVal)+1];
|
||||
static StrBuf Keyword = STATIC_STRBUF_INITIALIZER;
|
||||
|
||||
/* Segment stack */
|
||||
#define MAX_PUSHED_SEGMENTS 16
|
||||
@ -208,7 +208,7 @@ static void ExportImport (void (*Func) (SymEntry*, unsigned char, unsigned),
|
||||
}
|
||||
|
||||
/* Find the symbol table entry, allocate a new one if necessary */
|
||||
Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW);
|
||||
Sym = SymFind (CurrentScope, &SVal, SYM_ALLOC_NEW);
|
||||
|
||||
/* Skip the name */
|
||||
NextTok ();
|
||||
@ -238,7 +238,7 @@ static long IntArg (long Min, long Max)
|
||||
* and return -1 in this case.
|
||||
*/
|
||||
{
|
||||
if (Tok == TOK_IDENT && strcmp (SVal, "unlimited") == 0) {
|
||||
if (Tok == TOK_IDENT && SB_CompareStr (&SVal, "unlimited") == 0) {
|
||||
NextTok ();
|
||||
return -1;
|
||||
} else {
|
||||
@ -253,7 +253,7 @@ static long IntArg (long Min, long Max)
|
||||
|
||||
|
||||
|
||||
static void ConDes (const char* Name, unsigned Type)
|
||||
static void ConDes (const StrBuf* Name, unsigned Type)
|
||||
/* Parse remaining line for constructor/destructor of the remaining type */
|
||||
{
|
||||
long Prio;
|
||||
@ -376,8 +376,6 @@ static void DoAlign (void)
|
||||
static void DoASCIIZ (void)
|
||||
/* Define text with a zero terminator */
|
||||
{
|
||||
unsigned Len;
|
||||
|
||||
while (1) {
|
||||
/* Must have a string constant */
|
||||
if (Tok != TOK_STRCON) {
|
||||
@ -385,12 +383,9 @@ static void DoASCIIZ (void)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the length of the string constant */
|
||||
Len = strlen (SVal);
|
||||
|
||||
/* Translate into target charset and emit */
|
||||
TgtTranslateBuf (SVal, Len);
|
||||
EmitData ((unsigned char*) SVal, Len);
|
||||
TgtTranslateStrBuf (&SVal);
|
||||
EmitStrBuf (&SVal);
|
||||
NextTok ();
|
||||
if (Tok == TOK_COMMA) {
|
||||
NextTok ();
|
||||
@ -459,7 +454,7 @@ static void DoAssert (void)
|
||||
/* Translate the message into a string id. We can then skip the input
|
||||
* string.
|
||||
*/
|
||||
Msg = GetStringId (SVal);
|
||||
Msg = GetStrBufId (&SVal);
|
||||
NextTok ();
|
||||
|
||||
} else {
|
||||
@ -497,9 +492,8 @@ static void DoByte (void)
|
||||
while (1) {
|
||||
if (Tok == TOK_STRCON) {
|
||||
/* A string, translate into target charset and emit */
|
||||
unsigned Len = strlen (SVal);
|
||||
TgtTranslateBuf (SVal, Len);
|
||||
EmitData ((unsigned char*) SVal, Len);
|
||||
TgtTranslateStrBuf (&SVal);
|
||||
EmitStrBuf (&SVal);
|
||||
NextTok ();
|
||||
} else {
|
||||
EmitByte (Expression ());
|
||||
@ -575,7 +569,7 @@ static void DoConDes (void)
|
||||
"DESTRUCTOR",
|
||||
"INTERRUPTOR",
|
||||
};
|
||||
char Name [sizeof (SVal)];
|
||||
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
||||
long Type;
|
||||
|
||||
/* Symbol name follows */
|
||||
@ -583,7 +577,7 @@ static void DoConDes (void)
|
||||
ErrorSkip ("Identifier expected");
|
||||
return;
|
||||
}
|
||||
strcpy (Name, SVal);
|
||||
SB_Copy (&Name, &SVal);
|
||||
NextTok ();
|
||||
|
||||
/* Type follows. May be encoded as identifier or numerical */
|
||||
@ -596,9 +590,8 @@ static void DoConDes (void)
|
||||
|
||||
/* Check if we got a valid keyword */
|
||||
if (Type < 0) {
|
||||
Error ("Syntax error");
|
||||
SkipUntilSep ();
|
||||
return;
|
||||
ErrorSkip ("Syntax error");
|
||||
goto ExitPoint;
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -607,14 +600,18 @@ static void DoConDes (void)
|
||||
Type = ConstExpression ();
|
||||
if (Type < CD_TYPE_MIN || Type > CD_TYPE_MAX) {
|
||||
/* Value out of range */
|
||||
Error ("Range error");
|
||||
return;
|
||||
ErrorSkip ("Range error");
|
||||
goto ExitPoint;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Parse the remainder of the line and export the symbol */
|
||||
ConDes (Name, (unsigned) Type);
|
||||
ConDes (&Name, (unsigned) Type);
|
||||
|
||||
ExitPoint:
|
||||
/* Free string memory */
|
||||
SB_Done (&Name);
|
||||
}
|
||||
|
||||
|
||||
@ -622,18 +619,21 @@ static void DoConDes (void)
|
||||
static void DoConstructor (void)
|
||||
/* Export a symbol as constructor */
|
||||
{
|
||||
char Name [sizeof (SVal)];
|
||||
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
||||
|
||||
/* Symbol name follows */
|
||||
if (Tok != TOK_IDENT) {
|
||||
ErrorSkip ("Identifier expected");
|
||||
return;
|
||||
}
|
||||
strcpy (Name, SVal);
|
||||
SB_Copy (&Name, &SVal);
|
||||
NextTok ();
|
||||
|
||||
/* Parse the remainder of the line and export the symbol */
|
||||
ConDes (Name, CD_TYPE_CON);
|
||||
ConDes (&Name, CD_TYPE_CON);
|
||||
|
||||
/* Free string memory */
|
||||
SB_Done (&Name);
|
||||
}
|
||||
|
||||
|
||||
@ -714,18 +714,21 @@ static void DoDefine (void)
|
||||
static void DoDestructor (void)
|
||||
/* Export a symbol as destructor */
|
||||
{
|
||||
char Name [sizeof (SVal)];
|
||||
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
||||
|
||||
/* Symbol name follows */
|
||||
if (Tok != TOK_IDENT) {
|
||||
ErrorSkip ("Identifier expected");
|
||||
return;
|
||||
}
|
||||
strcpy (Name, SVal);
|
||||
SB_Copy (&Name, &SVal);
|
||||
NextTok ();
|
||||
|
||||
/* Parse the remainder of the line and export the symbol */
|
||||
ConDes (Name, CD_TYPE_DES);
|
||||
ConDes (&Name, CD_TYPE_DES);
|
||||
|
||||
/* Free string memory */
|
||||
SB_Done (&Name);
|
||||
}
|
||||
|
||||
|
||||
@ -786,7 +789,7 @@ static void DoError (void)
|
||||
if (Tok != TOK_STRCON) {
|
||||
ErrorSkip ("String constant expected");
|
||||
} else {
|
||||
Error ("User error: %s", SVal);
|
||||
Error ("User error: %m%p", &SVal);
|
||||
SkipUntilSep ();
|
||||
}
|
||||
}
|
||||
@ -853,9 +856,9 @@ static void DoFeature (void)
|
||||
LocaseSVal ();
|
||||
|
||||
/* Set the feature and check for errors */
|
||||
if (SetFeature (SVal) == FEAT_UNKNOWN) {
|
||||
if (SetFeature (&SVal) == FEAT_UNKNOWN) {
|
||||
/* Not found */
|
||||
ErrorSkip ("Invalid feature: `%s'", SVal);
|
||||
ErrorSkip ("Invalid feature: `%m%p'", &SVal);
|
||||
return;
|
||||
} else {
|
||||
/* Skip the keyword */
|
||||
@ -911,17 +914,17 @@ static void DoFileOpt (void)
|
||||
|
||||
case 0:
|
||||
/* Author */
|
||||
OptAuthor (SVal);
|
||||
OptAuthor (&SVal);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
/* Comment */
|
||||
OptComment (SVal);
|
||||
OptComment (&SVal);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* Compiler */
|
||||
OptCompiler (SVal);
|
||||
OptCompiler (&SVal);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -951,7 +954,7 @@ static void DoFileOpt (void)
|
||||
}
|
||||
|
||||
/* Insert the option */
|
||||
OptStr ((unsigned char) OptNum, SVal);
|
||||
OptStr ((unsigned char) OptNum, &SVal);
|
||||
|
||||
/* Done */
|
||||
NextTok ();
|
||||
@ -1029,7 +1032,7 @@ static void DoImportZP (void)
|
||||
static void DoIncBin (void)
|
||||
/* Include a binary file */
|
||||
{
|
||||
char Name [sizeof (SVal)];
|
||||
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
||||
long Start = 0L;
|
||||
long Count = -1L;
|
||||
long Size;
|
||||
@ -1040,7 +1043,8 @@ static void DoIncBin (void)
|
||||
ErrorSkip ("String constant expected");
|
||||
return;
|
||||
}
|
||||
strcpy (Name, SVal);
|
||||
SB_Copy (&Name, &SVal);
|
||||
SB_Terminate (&Name);
|
||||
NextTok ();
|
||||
|
||||
/* A starting offset may follow */
|
||||
@ -1057,14 +1061,14 @@ static void DoIncBin (void)
|
||||
}
|
||||
|
||||
/* Try to open the file */
|
||||
F = fopen (Name, "rb");
|
||||
F = fopen (SB_GetConstBuf (&Name), "rb");
|
||||
if (F == 0) {
|
||||
|
||||
/* Search for the file in the include directories. */
|
||||
char* PathName = FindInclude (Name);
|
||||
char* PathName = FindInclude (SB_GetConstBuf (&Name));
|
||||
if (PathName == 0 || (F = fopen (PathName, "r")) == 0) {
|
||||
/* Not found or cannot open, print an error and bail out */
|
||||
ErrorSkip ("Cannot open include file `%s': %s", Name, strerror (errno));
|
||||
ErrorSkip ("Cannot open include file `%m%p': %s", &Name, strerror (errno));
|
||||
}
|
||||
|
||||
/* Free the allocated memory */
|
||||
@ -1072,7 +1076,7 @@ static void DoIncBin (void)
|
||||
|
||||
/* If we had an error before, bail out now */
|
||||
if (F == 0) {
|
||||
return;
|
||||
goto ExitPoint;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1111,8 +1115,8 @@ 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 `%s': %s",
|
||||
Name, strerror (errno));
|
||||
ErrorSkip ("Cannot read from include file `%m%p': %s",
|
||||
&Name, strerror (errno));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1126,6 +1130,10 @@ static void DoIncBin (void)
|
||||
Done:
|
||||
/* Close the file, ignore errors since it's r/o */
|
||||
(void) fclose (F);
|
||||
|
||||
ExitPoint:
|
||||
/* Free string memory */
|
||||
SB_Done (&Name);
|
||||
}
|
||||
|
||||
|
||||
@ -1136,8 +1144,9 @@ static void DoInclude (void)
|
||||
/* Name must follow */
|
||||
if (Tok != TOK_STRCON) {
|
||||
ErrorSkip ("String constant expected");
|
||||
} else {
|
||||
NewInputFile (SVal);
|
||||
} else {
|
||||
SB_Terminate (&SVal);
|
||||
NewInputFile (SB_GetConstBuf (&SVal));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1146,18 +1155,21 @@ static void DoInclude (void)
|
||||
static void DoInterruptor (void)
|
||||
/* Export a symbol as interruptor */
|
||||
{
|
||||
char Name [sizeof (SVal)];
|
||||
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
||||
|
||||
/* Symbol name follows */
|
||||
if (Tok != TOK_IDENT) {
|
||||
ErrorSkip ("Identifier expected");
|
||||
return;
|
||||
}
|
||||
strcpy (Name, SVal);
|
||||
SB_Copy (&Name, &SVal);
|
||||
NextTok ();
|
||||
|
||||
/* Parse the remainder of the line and export the symbol */
|
||||
ConDes (Name, CD_TYPE_INT);
|
||||
ConDes (&Name, CD_TYPE_INT);
|
||||
|
||||
/* Free string memory */
|
||||
SB_Done (&Name);
|
||||
}
|
||||
|
||||
|
||||
@ -1171,7 +1183,7 @@ static void DoInvalid (void)
|
||||
* an error in the assembler itself, while DoInvalid is.
|
||||
*/
|
||||
{
|
||||
Internal ("Unexpected token: %s", Keyword);
|
||||
Internal ("Unexpected token: %m%p", &Keyword);
|
||||
}
|
||||
|
||||
|
||||
@ -1238,7 +1250,8 @@ static void DoMacPack (void)
|
||||
}
|
||||
|
||||
/* Search for the macro package name */
|
||||
Package = MacPackFind (SVal);
|
||||
LocaseSVal ();
|
||||
Package = MacPackFind (&SVal);
|
||||
if (Package < 0) {
|
||||
/* Not found */
|
||||
ErrorSkip ("Invalid macro package");
|
||||
@ -1289,7 +1302,7 @@ static void DoOut (void)
|
||||
/* 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.
|
||||
*/
|
||||
printf ("%s\n", SVal);
|
||||
printf ("%m%p\n", &SVal);
|
||||
fflush (stdout);
|
||||
NextTok ();
|
||||
}
|
||||
@ -1355,7 +1368,7 @@ static void DoPopSeg (void)
|
||||
static void DoProc (void)
|
||||
/* Start a new lexical scope */
|
||||
{
|
||||
char Name[sizeof(SVal)];
|
||||
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
||||
unsigned char AddrSize;
|
||||
|
||||
if (Tok == TOK_IDENT) {
|
||||
@ -1363,10 +1376,10 @@ static void DoProc (void)
|
||||
SymEntry* Sym;
|
||||
|
||||
/* The new scope has a name. Remember it. */
|
||||
strcpy (Name, SVal);
|
||||
SB_Copy (&Name, &SVal);
|
||||
|
||||
/* Search for the symbol, generate a new one if needed */
|
||||
Sym = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
|
||||
Sym = SymFind (CurrentScope, &Name, SYM_ALLOC_NEW);
|
||||
|
||||
/* Skip the scope name */
|
||||
NextTok ();
|
||||
@ -1381,13 +1394,16 @@ static void DoProc (void)
|
||||
|
||||
/* A .PROC statement without a name */
|
||||
Warning (1, "Unnamed .PROCs are deprecated, please use .SCOPE");
|
||||
AnonName (Name, sizeof (Name), "PROC");
|
||||
AnonName (&Name, "PROC");
|
||||
AddrSize = ADDR_SIZE_DEFAULT;
|
||||
|
||||
}
|
||||
|
||||
/* Enter a new scope */
|
||||
SymEnterLevel (Name, ST_PROC, AddrSize);
|
||||
SymEnterLevel (&Name, ST_PROC, AddrSize);
|
||||
|
||||
/* Free memory for Name */
|
||||
SB_Done (&Name);
|
||||
}
|
||||
|
||||
|
||||
@ -1475,20 +1491,20 @@ static void DoROData (void)
|
||||
static void DoScope (void)
|
||||
/* Start a local scope */
|
||||
{
|
||||
char Name[sizeof (SVal)];
|
||||
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
||||
unsigned char AddrSize;
|
||||
|
||||
|
||||
if (Tok == TOK_IDENT) {
|
||||
|
||||
/* The new scope has a name. Remember and skip it. */
|
||||
strcpy (Name, SVal);
|
||||
SB_Copy (&Name, &SVal);
|
||||
NextTok ();
|
||||
|
||||
} else {
|
||||
|
||||
/* An unnamed scope */
|
||||
AnonName (Name, sizeof (Name), "SCOPE");
|
||||
AnonName (&Name, "SCOPE");
|
||||
|
||||
}
|
||||
|
||||
@ -1496,8 +1512,10 @@ static void DoScope (void)
|
||||
AddrSize = OptionalAddrSize ();
|
||||
|
||||
/* Enter the new scope */
|
||||
SymEnterLevel (Name, ST_SCOPE, AddrSize);
|
||||
SymEnterLevel (&Name, ST_SCOPE, AddrSize);
|
||||
|
||||
/* Free memory for Name */
|
||||
SB_Done (&Name);
|
||||
}
|
||||
|
||||
|
||||
@ -1505,24 +1523,30 @@ static void DoScope (void)
|
||||
static void DoSegment (void)
|
||||
/* Switch to another segment */
|
||||
{
|
||||
char Name [sizeof (SVal)];
|
||||
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
||||
SegDef Def;
|
||||
Def.Name = Name;
|
||||
|
||||
if (Tok != TOK_STRCON) {
|
||||
ErrorSkip ("String constant expected");
|
||||
} else {
|
||||
|
||||
/* Save the name of the segment and skip it */
|
||||
strcpy (Name, SVal);
|
||||
SB_Copy (&Name, &SVal);
|
||||
NextTok ();
|
||||
|
||||
/* Use the name for the segment definition */
|
||||
SB_Terminate (&Name);
|
||||
Def.Name = SB_GetBuf (&Name);
|
||||
|
||||
/* Check for an optional address size modifier */
|
||||
Def.AddrSize = OptionalAddrSize ();
|
||||
|
||||
/* Set the segment */
|
||||
UseSeg (&Def);
|
||||
}
|
||||
|
||||
/* Free memory for Name */
|
||||
SB_Done (&Name);
|
||||
}
|
||||
|
||||
|
||||
@ -1535,7 +1559,8 @@ static void DoSetCPU (void)
|
||||
ErrorSkip ("String constant expected");
|
||||
} else {
|
||||
/* Try to find the CPU */
|
||||
cpu_t CPU = FindCPU (SVal);
|
||||
SB_Terminate (&SVal);
|
||||
cpu_t CPU = FindCPU (SB_GetConstBuf (&SVal));
|
||||
|
||||
/* Switch to the new CPU */
|
||||
SetCPU (CPU);
|
||||
@ -1615,7 +1640,7 @@ static void DoTag (void)
|
||||
static void DoUnexpected (void)
|
||||
/* Got an unexpected keyword */
|
||||
{
|
||||
Error ("Unexpected `%s'", Keyword);
|
||||
Error ("Unexpected `%m%p'", &Keyword);
|
||||
SkipUntilSep ();
|
||||
}
|
||||
|
||||
@ -1627,7 +1652,7 @@ static void DoWarning (void)
|
||||
if (Tok != TOK_STRCON) {
|
||||
ErrorSkip ("String constant expected");
|
||||
} else {
|
||||
Warning (0, "User warning: %s", SVal);
|
||||
Warning (0, "User warning: %m%p", &SVal);
|
||||
SkipUntilSep ();
|
||||
}
|
||||
}
|
||||
@ -1832,7 +1857,7 @@ void HandlePseudo (void)
|
||||
|
||||
/* Remember the instruction, then skip it if needed */
|
||||
if ((D->Flags & ccKeepToken) == 0) {
|
||||
strcpy (Keyword, SVal);
|
||||
SB_Copy (&Keyword, &SVal);
|
||||
NextTok ();
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 2000-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -109,7 +109,7 @@ static void RepeatTokenCheck (TokList* L)
|
||||
* for and replace identifiers that are the repeat counter.
|
||||
*/
|
||||
{
|
||||
if (Tok == TOK_IDENT && L->Data != 0 && strcmp (SVal, L->Data) == 0) {
|
||||
if (Tok == TOK_IDENT && L->Data != 0 && SB_CompareStr (&SVal, L->Data) == 0) {
|
||||
/* Must replace by the repeat counter */
|
||||
Tok = TOK_INTCON;
|
||||
IVal = L->RepCount;
|
||||
@ -143,7 +143,8 @@ void ParseRepeat (void)
|
||||
ErrorSkip ("Identifier expected");
|
||||
} else {
|
||||
/* Remember the name and skip it */
|
||||
Name = xstrdup (SVal);
|
||||
SB_Terminate (&SVal);
|
||||
Name = xstrdup (SB_GetConstBuf (&SVal));
|
||||
NextTok ();
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2007 Ullrich von Bassewitz */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -73,7 +73,7 @@
|
||||
Token Tok = TOK_NONE; /* Current token */
|
||||
int WS; /* Flag: Whitespace before token */
|
||||
long IVal; /* Integer token attribute */
|
||||
char SVal[MAX_STR_LEN+1]; /* String token attribute */
|
||||
StrBuf SVal = STATIC_STRBUF_INITIALIZER;/* String token attribute */
|
||||
|
||||
FilePos CurPos = { 0, 0, 0 }; /* Name and position in current file */
|
||||
|
||||
@ -459,6 +459,7 @@ void NewInputFile (const char* Name)
|
||||
/* check again if we do now have an open file */
|
||||
if (F != 0) {
|
||||
|
||||
StrBuf NameBuf;
|
||||
unsigned FileIdx;
|
||||
CharSource* S;
|
||||
|
||||
@ -476,7 +477,7 @@ void NewInputFile (const char* Name)
|
||||
}
|
||||
|
||||
/* Add the file to the input file table and remember the index */
|
||||
FileIdx = AddFile (Name, Buf.st_size, Buf.st_mtime);
|
||||
FileIdx = AddFile (SB_InitFromString (&NameBuf, Name), Buf.st_size, Buf.st_mtime);
|
||||
|
||||
/* Create a new input source variable and initialize it */
|
||||
S = xmalloc (sizeof (*S));
|
||||
@ -619,11 +620,7 @@ static void NextChar (void)
|
||||
void LocaseSVal (void)
|
||||
/* Make SVal lower case */
|
||||
{
|
||||
unsigned I = 0;
|
||||
while (SVal [I]) {
|
||||
SVal [I] = tolower (SVal [I]);
|
||||
++I;
|
||||
}
|
||||
SB_ToLower (&SVal);
|
||||
}
|
||||
|
||||
|
||||
@ -631,11 +628,7 @@ void LocaseSVal (void)
|
||||
void UpcaseSVal (void)
|
||||
/* Make SVal upper case */
|
||||
{
|
||||
unsigned I = 0;
|
||||
while (SVal [I]) {
|
||||
SVal [I] = toupper (SVal [I]);
|
||||
++I;
|
||||
}
|
||||
SB_ToUpper (&SVal);
|
||||
}
|
||||
|
||||
|
||||
@ -653,7 +646,7 @@ static unsigned char FindDotKeyword (void)
|
||||
* return TOK_NONE if not found.
|
||||
*/
|
||||
{
|
||||
static const struct DotKeyword K = { SVal, 0 };
|
||||
struct DotKeyword K = { SB_GetConstBuf (&SVal), 0 };
|
||||
struct DotKeyword* R;
|
||||
|
||||
/* If we aren't in ignore case mode, we have to uppercase the keyword */
|
||||
@ -673,20 +666,19 @@ static unsigned char FindDotKeyword (void)
|
||||
|
||||
|
||||
|
||||
static void ReadIdent (unsigned Index)
|
||||
static void ReadIdent (void)
|
||||
/* Read an identifier from the current input position into Ident. Filling SVal
|
||||
* starts at Index with the current character in C. It is assumed that any
|
||||
* characters already filled in are ok, and the character in C is checked.
|
||||
* starts at the current position with the next character in C. It is assumed
|
||||
* that any characters already filled in are ok, and the character in C is
|
||||
* checked.
|
||||
*/
|
||||
{
|
||||
/* Read the identifier */
|
||||
do {
|
||||
if (Index < MAX_STR_LEN) {
|
||||
SVal [Index++] = C;
|
||||
}
|
||||
NextChar ();
|
||||
SB_AppendChar (&SVal, C);
|
||||
NextChar ();
|
||||
} while (IsIdChar (C));
|
||||
SVal [Index] = '\0';
|
||||
SB_Terminate (&SVal);
|
||||
|
||||
/* If we should ignore case, convert the identifier to upper case */
|
||||
if (IgnoreCase) {
|
||||
@ -696,18 +688,13 @@ static void ReadIdent (unsigned Index)
|
||||
|
||||
|
||||
|
||||
static unsigned ReadStringConst (int StringTerm)
|
||||
/* Read a string constant into SVal. Check for maximum string length and all
|
||||
* other stuff. The length of the string is returned.
|
||||
*/
|
||||
static void ReadStringConst (int StringTerm)
|
||||
/* Read a string constant into SVal. */
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
/* Skip the leading string terminator */
|
||||
NextChar ();
|
||||
|
||||
/* Read the string */
|
||||
I = 0;
|
||||
while (1) {
|
||||
if (C == StringTerm) {
|
||||
break;
|
||||
@ -717,13 +704,8 @@ static unsigned ReadStringConst (int StringTerm)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check for string length, print an error message once */
|
||||
if (I == MAX_STR_LEN) {
|
||||
Error ("Maximum string size exceeded");
|
||||
} else if (I < MAX_STR_LEN) {
|
||||
SVal [I] = C;
|
||||
}
|
||||
++I;
|
||||
/* Append the char to the string */
|
||||
SB_AppendChar (&SVal, C);
|
||||
|
||||
/* Skip the character */
|
||||
NextChar ();
|
||||
@ -733,18 +715,12 @@ static unsigned ReadStringConst (int StringTerm)
|
||||
NextChar ();
|
||||
|
||||
/* Terminate the string */
|
||||
if (I >= MAX_STR_LEN) {
|
||||
I = MAX_STR_LEN;
|
||||
}
|
||||
SVal [I] = '\0';
|
||||
|
||||
/* Return the length of the string */
|
||||
return I;
|
||||
SB_Terminate (&SVal);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int Sweet16Reg (const char* Ident)
|
||||
static int Sweet16Reg (const StrBuf* Id)
|
||||
/* Check if the given identifier is a sweet16 register. Return -1 if this is
|
||||
* not the case, return the register number otherwise.
|
||||
*/
|
||||
@ -752,14 +728,17 @@ static int Sweet16Reg (const char* Ident)
|
||||
unsigned RegNum;
|
||||
char Check;
|
||||
|
||||
if (Ident[0] != 'r' && Ident[0] != 'R') {
|
||||
if (SB_GetLen (Id) < 2) {
|
||||
return -1;
|
||||
}
|
||||
if (!IsDigit (Ident[1])) {
|
||||
if (toupper (SB_AtUnchecked (Id, 0)) != 'R') {
|
||||
return -1;
|
||||
}
|
||||
if (!IsDigit (SB_AtUnchecked (Id, 1))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sscanf (Ident+1, "%u%c", &RegNum, &Check) != 1 || RegNum > 15) {
|
||||
if (sscanf (SB_GetConstBuf (Id)+1, "%u%c", &RegNum, &Check) != 1 || RegNum > 15) {
|
||||
/* Invalid register */
|
||||
return -1;
|
||||
}
|
||||
@ -796,6 +775,9 @@ Again:
|
||||
/* Mark the file position of the next token */
|
||||
Source->Func->MarkStart (Source);
|
||||
|
||||
/* Clear the string attribute */
|
||||
SB_Clear (&SVal);
|
||||
|
||||
/* Hex number or PC symbol? */
|
||||
if (C == '$') {
|
||||
NextChar ();
|
||||
@ -928,8 +910,8 @@ Again:
|
||||
} else {
|
||||
|
||||
/* Read the remainder of the identifier */
|
||||
SVal[0] = '.';
|
||||
ReadIdent (1);
|
||||
SB_AppendChar (&SVal, '.');
|
||||
ReadIdent ();
|
||||
|
||||
/* Dot keyword, search for it */
|
||||
Tok = FindDotKeyword ();
|
||||
@ -938,14 +920,14 @@ Again:
|
||||
/* Not found */
|
||||
if (!LeadingDotInIdents) {
|
||||
/* Invalid pseudo instruction */
|
||||
Error ("`%s' is not a recognized control command", SVal);
|
||||
Error ("`%m%p' is not a recognized control command", &SVal);
|
||||
goto Again;
|
||||
}
|
||||
|
||||
/* An identifier with a dot. Check if it's a define style
|
||||
* macro.
|
||||
*/
|
||||
if (IsDefine (SVal)) {
|
||||
if (IsDefine (&SVal)) {
|
||||
/* This is a define style macro - expand it */
|
||||
MacExpandStart ();
|
||||
goto Restart;
|
||||
@ -971,11 +953,11 @@ Again:
|
||||
/* Local symbol? */
|
||||
if (C == LocalStart) {
|
||||
|
||||
/* Read the identifier */
|
||||
ReadIdent (0);
|
||||
/* Read the identifier. */
|
||||
ReadIdent ();
|
||||
|
||||
/* Start character alone is not enough */
|
||||
if (SVal [1] == '\0') {
|
||||
if (SB_GetLen (&SVal) == 1) {
|
||||
Error ("Invalid cheap local symbol");
|
||||
goto Again;
|
||||
}
|
||||
@ -990,13 +972,13 @@ Again:
|
||||
if (IsIdStart (C)) {
|
||||
|
||||
/* Read the identifier */
|
||||
ReadIdent (0);
|
||||
ReadIdent ();
|
||||
|
||||
/* Check for special names. Bail out if we have identified the type of
|
||||
* the token. Go on if the token is an identifier.
|
||||
*/
|
||||
if (SVal[1] == '\0') {
|
||||
switch (toupper (SVal [0])) {
|
||||
if (SB_GetLen (&SVal) == 1) {
|
||||
switch (toupper (SB_AtUnchecked (&SVal, 0))) {
|
||||
|
||||
case 'A':
|
||||
if (C == ':') {
|
||||
@ -1039,7 +1021,7 @@ Again:
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (CPU == CPU_SWEET16 && (IVal = Sweet16Reg (SVal)) >= 0) {
|
||||
} else if (CPU == CPU_SWEET16 && (IVal = Sweet16Reg (&SVal)) >= 0) {
|
||||
|
||||
/* A sweet16 register number in sweet16 mode */
|
||||
Tok = TOK_REG;
|
||||
@ -1048,7 +1030,7 @@ Again:
|
||||
}
|
||||
|
||||
/* Check for define style macro */
|
||||
if (IsDefine (SVal)) {
|
||||
if (IsDefine (&SVal)) {
|
||||
/* Macro - expand it */
|
||||
MacExpandStart ();
|
||||
goto Restart;
|
||||
@ -1243,8 +1225,9 @@ CharAgain:
|
||||
* string later.
|
||||
*/
|
||||
if (LooseStringTerm) {
|
||||
if (ReadStringConst ('\'') == 1) {
|
||||
IVal = SVal[0];
|
||||
ReadStringConst ('\'');
|
||||
if (SB_GetLen (&SVal) == 1) {
|
||||
IVal = SB_AtUnchecked (&SVal, 0);
|
||||
Tok = TOK_CHARCON;
|
||||
} else {
|
||||
Tok = TOK_STRCON;
|
||||
@ -1277,8 +1260,8 @@ CharAgain:
|
||||
case '\\':
|
||||
/* Line continuation? */
|
||||
if (LineCont) {
|
||||
NextChar ();
|
||||
if (C == '\n') {
|
||||
NextChar ();
|
||||
if (C == '\n') {
|
||||
/* Handle as white space */
|
||||
NextChar ();
|
||||
C = ' ';
|
||||
@ -1333,7 +1316,7 @@ int GetSubKey (const char** Keys, unsigned Count)
|
||||
|
||||
/* Do a linear search (a binary search is not worth the effort) */
|
||||
for (I = 0; I < Count; ++I) {
|
||||
if (strcmp (SVal, Keys [I]) == 0) {
|
||||
if (SB_CompareStr (&SVal, Keys [I]) == 0) {
|
||||
/* Found it */
|
||||
return I;
|
||||
}
|
||||
|
@ -40,6 +40,7 @@
|
||||
|
||||
/* common */
|
||||
#include "filepos.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
/* ca65 */
|
||||
#include "token.h"
|
||||
@ -58,7 +59,7 @@
|
||||
extern Token Tok; /* Current token */
|
||||
extern int WS; /* Flag: Whitespace before token */
|
||||
extern long IVal; /* Integer token attribute */
|
||||
extern char SVal[MAX_STR_LEN+1]; /* String token attribute */
|
||||
extern StrBuf SVal; /* String token attribute */
|
||||
|
||||
extern FilePos CurPos; /* Name and position in file */
|
||||
extern int ForcedEnd; /* Force end of assembly */
|
||||
@ -119,4 +120,4 @@ void DoneScanner (void);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 2003-2008, Ullrich von Bassewit */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -52,13 +52,12 @@
|
||||
/* The name of the symbol used to encode the size. The name of this entry is
|
||||
* choosen so that it cannot be accessed by the user.
|
||||
*/
|
||||
static const char SizeEntryName[] = ".size";
|
||||
|
||||
const StrBuf SizeEntryName = LIT_STRBUF_INITIALIZER (".size");
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@ -68,7 +67,7 @@ SymEntry* GetSizeOfScope (SymTable* Scope)
|
||||
* encodes the size, and will create a new entry if it does not exist.
|
||||
*/
|
||||
{
|
||||
return SymFind (Scope, SizeEntryName, SYM_ALLOC_NEW);
|
||||
return SymFind (Scope, &SizeEntryName, SYM_ALLOC_NEW);
|
||||
}
|
||||
|
||||
|
||||
@ -79,7 +78,7 @@ SymEntry* GetSizeOfSymbol (SymEntry* Sym)
|
||||
* does not exist.
|
||||
*/
|
||||
{
|
||||
return SymFindLocal (Sym, SizeEntryName, SYM_ALLOC_NEW);
|
||||
return SymFindLocal (Sym, &SizeEntryName, SYM_ALLOC_NEW);
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 2003-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -35,6 +35,11 @@
|
||||
|
||||
#ifndef SIZEOF_H
|
||||
#define SIZEOF_H
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "strbuf.h"
|
||||
|
||||
|
||||
|
||||
@ -49,6 +54,16 @@ struct SymTable;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
extern const StrBuf SizeEntryName; /* Contains name of symbol with size */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
@ -57,7 +57,7 @@ StringPool StrPool = STATIC_STRINGPOOL_INITIALIZER;
|
||||
|
||||
void WriteStrPool (void)
|
||||
/* Write the string pool to the object file */
|
||||
{
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
/* Get the number of strings in the string pool */
|
||||
@ -71,7 +71,7 @@ void WriteStrPool (void)
|
||||
|
||||
/* Write the strings in id order */
|
||||
for (I = 0; I < Count; ++I) {
|
||||
ObjWriteStr (SP_Get (&StrPool, I));
|
||||
ObjWriteBuf (SP_Get (&StrPool, I));
|
||||
}
|
||||
|
||||
/* Done writing the string pool */
|
||||
|
@ -60,8 +60,8 @@ extern StringPool StrPool;
|
||||
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned GetStringId (const char* S)
|
||||
/* Return the id of the given string */
|
||||
INLINE unsigned GetStrBufId (const StrBuf* S)
|
||||
/* Return the id of the given string buffer */
|
||||
{
|
||||
return SP_Add (&StrPool, S);
|
||||
}
|
||||
@ -70,13 +70,33 @@ INLINE unsigned GetStringId (const char* S)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE const char* GetString (unsigned Index)
|
||||
INLINE unsigned GetStringId (const char* S)
|
||||
/* Return the id of the given string */
|
||||
{
|
||||
return SP_AddStr (&StrPool, S);
|
||||
}
|
||||
#else
|
||||
# define GetStringId(S) SP_Add (&StrPool, (S))
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE const StrBuf* GetStrBuf (unsigned Index)
|
||||
/* Convert a string index into a string */
|
||||
{
|
||||
return SP_Get (&StrPool, Index);
|
||||
}
|
||||
#else
|
||||
# define GetString(Index) SP_Get (&StrPool, (Index))
|
||||
# define GetStrBuf(Index) SP_Get (&StrPool, (Index))
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
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);
|
||||
|
@ -106,7 +106,7 @@ static long DoStructInternal (long Offs, unsigned Type)
|
||||
int Anon = (Tok != TOK_IDENT);
|
||||
if (!Anon) {
|
||||
/* Enter a new scope, then skip the name */
|
||||
SymEnterLevel (SVal, ST_STRUCT, ADDR_SIZE_ABS);
|
||||
SymEnterLevel (&SVal, ST_STRUCT, ADDR_SIZE_ABS);
|
||||
NextTok ();
|
||||
/* Start at zero offset in the new scope */
|
||||
Offs = 0;
|
||||
@ -132,7 +132,7 @@ static long DoStructInternal (long Offs, unsigned Type)
|
||||
Sym = 0;
|
||||
if (Tok == TOK_IDENT) {
|
||||
/* We have an identifier, generate a symbol */
|
||||
Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW);
|
||||
Sym = SymFind (CurrentScope, &SVal, SYM_ALLOC_NEW);
|
||||
|
||||
/* Assign the symbol the offset of the current member */
|
||||
SymDef (Sym, GenLiteralExpr (Offs), ADDR_SIZE_DEFAULT, SF_NONE);
|
||||
@ -261,7 +261,7 @@ static long DoStructInternal (long Offs, unsigned Type)
|
||||
long GetStructSize (SymTable* Struct)
|
||||
/* Get the size of a struct or union */
|
||||
{
|
||||
SymEntry* Sym = SymFind (Struct, ".size", SYM_FIND_EXISTING);
|
||||
SymEntry* Sym = SymFind (Struct, &SizeEntryName, SYM_FIND_EXISTING);
|
||||
if (Sym == 0) {
|
||||
Error ("Size of struct/union is unknown");
|
||||
return 0;
|
||||
|
@ -511,7 +511,7 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D)
|
||||
DumpExpr (Expr, SymResolve);
|
||||
}
|
||||
PError (GetSymPos (Sym),
|
||||
"Circular reference in definition of symbol `%s'",
|
||||
"Circular reference in definition of symbol `%m%p'",
|
||||
GetSymName (Sym));
|
||||
ED_Invalidate (D);
|
||||
} else {
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -53,17 +53,19 @@
|
||||
|
||||
|
||||
|
||||
SymTable* ParseScopedIdent (char* Name, StrBuf* ScopeName)
|
||||
/* Parse a (possibly scoped) identifer. Name must point to a buffer big enough
|
||||
* to hold such an identifier. The scope of the name must exist and is returned
|
||||
* as function result, while the last part (the identifier) which may be either
|
||||
* a symbol or a scope depending on the context is returned in Name. ScopeName
|
||||
* is a string buffer that is used to store the name of the scope, the
|
||||
* identifier lives in. It does contain anything but the identifier itself, so
|
||||
* if ScopeName is empty on return, no explicit scope was specified. The full
|
||||
* name of the identifier (including the scope) is ScopeName+Name.
|
||||
SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
|
||||
/* Parse a (possibly scoped) identifer. The scope of the name must exist and
|
||||
* is returned as function result, while the last part (the identifier) which
|
||||
* may be either a symbol or a scope depending on the context is returned in
|
||||
* Name. FullName is a string buffer that is used to store the full name of
|
||||
* the identifier including the scope. It is used internally and may be used
|
||||
* by the caller for error messages or similar.
|
||||
*/
|
||||
{
|
||||
/* Clear both passed string buffers */
|
||||
SB_Clear (Name);
|
||||
SB_Clear (FullName);
|
||||
|
||||
/* Get the starting table */
|
||||
SymTable* Scope;
|
||||
if (Tok == TOK_NAMESPACE) {
|
||||
@ -74,17 +76,17 @@ SymTable* ParseScopedIdent (char* Name, StrBuf* ScopeName)
|
||||
} else if (Tok == TOK_IDENT) {
|
||||
|
||||
/* Remember the name and skip it */
|
||||
strcpy (Name, SVal);
|
||||
SB_Copy (Name, &SVal);
|
||||
NextTok ();
|
||||
|
||||
/* If no namespace symbol follows, we're already done */
|
||||
if (Tok != TOK_NAMESPACE) {
|
||||
SB_Terminate (ScopeName);
|
||||
SB_Terminate (FullName);
|
||||
return CurrentScope;
|
||||
}
|
||||
|
||||
/* Pass the scope back to the caller */
|
||||
SB_AppendStr (ScopeName, Name);
|
||||
SB_Append (FullName, Name);
|
||||
|
||||
/* The scope must exist, so search for it starting with the current
|
||||
* scope.
|
||||
@ -92,8 +94,8 @@ SymTable* ParseScopedIdent (char* Name, StrBuf* ScopeName)
|
||||
Scope = SymFindAnyScope (CurrentScope, Name);
|
||||
if (Scope == 0) {
|
||||
/* Scope not found */
|
||||
SB_Terminate (ScopeName);
|
||||
Error ("No such scope: `%s'", SB_GetConstBuf (ScopeName));
|
||||
SB_Terminate (FullName);
|
||||
Error ("No such scope: `%m%p'", FullName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -101,14 +103,12 @@ SymTable* ParseScopedIdent (char* Name, StrBuf* ScopeName)
|
||||
|
||||
/* Invalid token */
|
||||
Error ("Identifier expected");
|
||||
SB_Terminate (ScopeName);
|
||||
Name[0] = '\0';
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* Skip the namespace token that follows */
|
||||
SB_AppendStr (ScopeName, "::");
|
||||
SB_AppendStr (FullName, "::");
|
||||
NextTok ();
|
||||
|
||||
/* Resolve scopes. */
|
||||
@ -117,13 +117,11 @@ SymTable* ParseScopedIdent (char* Name, StrBuf* ScopeName)
|
||||
/* Next token must be an identifier. */
|
||||
if (Tok != TOK_IDENT) {
|
||||
Error ("Identifier expected");
|
||||
SB_Terminate (ScopeName);
|
||||
Name[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Remember and skip the identifier */
|
||||
strcpy (Name, SVal);
|
||||
SB_Copy (Name, &SVal);
|
||||
NextTok ();
|
||||
|
||||
/* If a namespace token follows, we search for another scope, otherwise
|
||||
@ -131,24 +129,22 @@ SymTable* ParseScopedIdent (char* Name, StrBuf* ScopeName)
|
||||
*/
|
||||
if (Tok != TOK_NAMESPACE) {
|
||||
/* Symbol */
|
||||
SB_Terminate (ScopeName);
|
||||
return Scope;
|
||||
}
|
||||
|
||||
/* Pass the scope back to the caller */
|
||||
SB_AppendStr (ScopeName, Name);
|
||||
SB_Append (FullName, Name);
|
||||
|
||||
/* Search for the child scope */
|
||||
Scope = SymFindScope (Scope, Name, SYM_FIND_EXISTING);
|
||||
if (Scope == 0) {
|
||||
/* Scope not found */
|
||||
SB_Terminate (ScopeName);
|
||||
Error ("No such scope: `%s'", SB_GetConstBuf (ScopeName));
|
||||
Error ("No such scope: `%m%p'", FullName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Skip the namespace token that follows */
|
||||
SB_AppendStr (ScopeName, "::");
|
||||
SB_AppendStr (FullName, "::");
|
||||
NextTok ();
|
||||
}
|
||||
}
|
||||
@ -160,19 +156,19 @@ SymEntry* ParseScopedSymName (int AllocNew)
|
||||
* and return the symbol table entry.
|
||||
*/
|
||||
{
|
||||
StrBuf ScopeName = AUTO_STRBUF_INITIALIZER;
|
||||
char Ident[sizeof (SVal)];
|
||||
StrBuf ScopeName = STATIC_STRBUF_INITIALIZER;
|
||||
StrBuf Ident = STATIC_STRBUF_INITIALIZER;
|
||||
int NoScope;
|
||||
SymEntry* Sym;
|
||||
|
||||
/* Parse the scoped symbol name */
|
||||
SymTable* Scope = ParseScopedIdent (Ident, &ScopeName);
|
||||
SymTable* Scope = ParseScopedIdent (&Ident, &ScopeName);
|
||||
|
||||
/* If ScopeName is empty, no scope was specified */
|
||||
NoScope = SB_IsEmpty (&ScopeName);
|
||||
|
||||
/* We don't need ScopeName any longer */
|
||||
DoneStrBuf (&ScopeName);
|
||||
SB_Done (&ScopeName);
|
||||
|
||||
/* Check if the scope is valid. Errors have already been diagnosed by
|
||||
* the routine, so just exit.
|
||||
@ -182,9 +178,9 @@ SymEntry* ParseScopedSymName (int AllocNew)
|
||||
* search also in the upper levels.
|
||||
*/
|
||||
if (NoScope && !AllocNew) {
|
||||
Sym = SymFindAny (Scope, Ident);
|
||||
Sym = SymFindAny (Scope, &Ident);
|
||||
} else {
|
||||
Sym = SymFind (Scope, Ident, AllocNew);
|
||||
Sym = SymFind (Scope, &Ident, AllocNew);
|
||||
}
|
||||
} else {
|
||||
/* No scope ==> no symbol. To avoid errors in the calling routine that
|
||||
@ -192,12 +188,15 @@ SymEntry* ParseScopedSymName (int AllocNew)
|
||||
* symbol.
|
||||
*/
|
||||
if (AllocNew) {
|
||||
Sym = NewSymEntry (Ident, SF_NONE);
|
||||
Sym = NewSymEntry (&Ident, SF_NONE);
|
||||
} else {
|
||||
Sym = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Deallocate memory for ident */
|
||||
SB_Done (&Ident);
|
||||
|
||||
/* Return the symbol found */
|
||||
return Sym;
|
||||
}
|
||||
@ -209,19 +208,19 @@ SymTable* ParseScopedSymTable (void)
|
||||
* symbol space and return the symbol table struct.
|
||||
*/
|
||||
{
|
||||
StrBuf ScopeName = AUTO_STRBUF_INITIALIZER;
|
||||
char Name[sizeof (SVal)];
|
||||
StrBuf ScopeName = STATIC_STRBUF_INITIALIZER;
|
||||
StrBuf Name = STATIC_STRBUF_INITIALIZER;
|
||||
int NoScope;
|
||||
|
||||
|
||||
/* Parse the scoped symbol name */
|
||||
SymTable* Scope = ParseScopedIdent (Name, &ScopeName);
|
||||
SymTable* Scope = ParseScopedIdent (&Name, &ScopeName);
|
||||
|
||||
/* If ScopeName is empty, no scope was specified */
|
||||
NoScope = SB_IsEmpty (&ScopeName);
|
||||
|
||||
/* We don't need FullName any longer */
|
||||
DoneStrBuf (&ScopeName);
|
||||
SB_Done (&ScopeName);
|
||||
|
||||
/* If we got no error, search for the child scope withint the enclosing one.
|
||||
* Beware: If no explicit parent scope was specified, search in all upper
|
||||
@ -230,11 +229,16 @@ SymTable* ParseScopedSymTable (void)
|
||||
if (Scope) {
|
||||
/* Search for the last scope */
|
||||
if (NoScope) {
|
||||
Scope = SymFindAnyScope (Scope, Name);
|
||||
Scope = SymFindAnyScope (Scope, &Name);
|
||||
} else {
|
||||
Scope = SymFindScope (Scope, Name, SYM_FIND_EXISTING);
|
||||
Scope = SymFindScope (Scope, &Name, SYM_FIND_EXISTING);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free memory for name */
|
||||
SB_Done (&Name);
|
||||
|
||||
/* Return the scope found */
|
||||
return Scope;
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -55,14 +55,13 @@ struct SymTable;
|
||||
|
||||
|
||||
|
||||
struct SymTable* ParseScopedIdent (char* Name, struct StrBuf* FullName);
|
||||
/* Parse a (possibly scoped) identifer. Name must point to a buffer big enough
|
||||
* to hold such an identifier. The scope of the name must exist and is returned
|
||||
* as function result, while the last part (the identifier) which may be either
|
||||
* a symbol or a scope depending on the context is returned in Name. FullName
|
||||
* is a string buffer that is used to store the full name of the identifier
|
||||
* including the scope. It is used internally and may be used by the caller
|
||||
* for error messages or similar.
|
||||
struct SymTable* ParseScopedIdent (struct StrBuf* Name, struct StrBuf* FullName);
|
||||
/* Parse a (possibly scoped) identifer. The scope of the name must exist and
|
||||
* is returned as function result, while the last part (the identifier) which
|
||||
* may be either a symbol or a scope depending on the context is returned in
|
||||
* Name. FullName is a string buffer that is used to store the full name of
|
||||
* the identifier including the scope. It is used internally and may be used
|
||||
* by the caller for error messages or similar.
|
||||
*/
|
||||
|
||||
struct SymEntry* ParseScopedSymName (int AllowNew);
|
||||
|
@ -2,11 +2,11 @@
|
||||
/* */
|
||||
/* symentry.c */
|
||||
/* */
|
||||
/* Symbol table entry forward for the ca65 macroassembler */
|
||||
/* Symbol table entry for the ca65 macroassembler */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2007 Ullrich von Bassewitz */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -72,7 +72,7 @@ SymEntry* SymLast = 0;
|
||||
|
||||
|
||||
|
||||
SymEntry* NewSymEntry (const char* Name, unsigned Flags)
|
||||
SymEntry* NewSymEntry (const StrBuf* Name, unsigned Flags)
|
||||
/* Allocate a symbol table entry, initialize and return it */
|
||||
{
|
||||
unsigned I;
|
||||
@ -95,7 +95,7 @@ SymEntry* NewSymEntry (const char* Name, unsigned Flags)
|
||||
S->ExportSize = ADDR_SIZE_DEFAULT;
|
||||
S->AddrSize = ADDR_SIZE_DEFAULT;
|
||||
memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio));
|
||||
S->Name = GetStringId (Name);
|
||||
S->Name = GetStrBufId (Name);
|
||||
|
||||
/* Insert it into the list of all entries */
|
||||
S->List = SymList;
|
||||
@ -107,7 +107,7 @@ SymEntry* NewSymEntry (const char* Name, unsigned Flags)
|
||||
|
||||
|
||||
|
||||
int SymSearchTree (SymEntry* T, const char* Name, SymEntry** E)
|
||||
int SymSearchTree (SymEntry* T, const StrBuf* Name, SymEntry** E)
|
||||
/* Search in the given tree for a name. If we find the symbol, the function
|
||||
* will return 0 and put the entry pointer into E. If we did not find the
|
||||
* symbol, and the tree is empty, E is set to NULL. If the tree is not empty,
|
||||
@ -126,10 +126,10 @@ int SymSearchTree (SymEntry* T, const char* Name, SymEntry** E)
|
||||
while (1) {
|
||||
|
||||
/* Get the symbol name */
|
||||
const char* SymName = GetString (T->Name);
|
||||
const StrBuf* SymName = GetStrBuf (T->Name);
|
||||
|
||||
/* Choose next entry */
|
||||
int Cmp = strcmp (Name, SymName);
|
||||
int Cmp = SB_Compare (Name, SymName);
|
||||
if (Cmp < 0 && T->Left) {
|
||||
T = T->Left;
|
||||
} else if (Cmp > 0&& T->Right) {
|
||||
@ -216,24 +216,24 @@ 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 `%s' is already an import", GetSymName (S));
|
||||
Error ("Symbol `%m%p' is already an import", GetSymName (S));
|
||||
return;
|
||||
}
|
||||
if ((Flags & SF_VAR) != 0 && (S->Flags & (SF_EXPORT | SF_GLOBAL))) {
|
||||
/* Variable symbols cannot be exports or globals */
|
||||
Error ("Var symbol `%s' 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 `%s' is already defined", GetSymName (S));
|
||||
Error ("Symbol `%m%p' is already defined", GetSymName (S));
|
||||
S->Flags |= SF_MULTDEF;
|
||||
return;
|
||||
} else {
|
||||
/* Redefinition must also be a variable symbol */
|
||||
if ((Flags & SF_VAR) == 0) {
|
||||
Error ("Symbol `%s' 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
|
||||
@ -284,7 +284,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 */
|
||||
PWarning (GetSymPos (S), 1, "Symbol `%s' is %s but exported %s",
|
||||
PWarning (GetSymPos (S), 1, "Symbol `%m%p' is %s but exported %s",
|
||||
GetSymName (S), AddrSizeToStr (S->AddrSize),
|
||||
AddrSizeToStr (S->ExportSize));
|
||||
}
|
||||
@ -302,13 +302,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 `%s' 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 `%s'", GetSymName (S));
|
||||
Error ("Cannot import exported symbol `%m%p'", GetSymName (S));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -324,16 +324,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 `%s'", GetSymName (S));
|
||||
Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
|
||||
}
|
||||
if (AddrSize != S->AddrSize) {
|
||||
Error ("Address size mismatch for symbol `%s'", 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 `%s'", GetSymName (S));
|
||||
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
|
||||
}
|
||||
}
|
||||
|
||||
@ -350,12 +350,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 `%s' 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 `%s' cannot be exported", GetSymName (S));
|
||||
Error ("Var symbol `%m%p' cannot be exported", GetSymName (S));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -364,7 +364,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 `%s'", GetSymName (S));
|
||||
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
|
||||
}
|
||||
S->Flags &= ~SF_GLOBAL;
|
||||
}
|
||||
@ -374,7 +374,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 `%s'", GetSymName (S));
|
||||
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
|
||||
}
|
||||
}
|
||||
S->ExportSize = AddrSize;
|
||||
@ -388,7 +388,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 `%s' is %s but exported %s",
|
||||
Warning (1, "Symbol `%m%p' is %s but exported %s",
|
||||
GetSymName (S), AddrSizeToStr (S->AddrSize),
|
||||
AddrSizeToStr (S->ExportSize));
|
||||
}
|
||||
@ -407,7 +407,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 `%s' cannot be made global", GetSymName (S));
|
||||
Error ("Var symbol `%m%p' cannot be made global", GetSymName (S));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -420,7 +420,7 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
|
||||
AddrSize = GetCurrentSegAddrSize ();
|
||||
}
|
||||
if (AddrSize != S->AddrSize) {
|
||||
Error ("Address size mismatch for symbol `%s'", GetSymName (S));
|
||||
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -432,12 +432,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 `%s'", 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 `%s'", GetSymName (S));
|
||||
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -449,7 +449,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 `%s'", GetSymName (S));
|
||||
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -467,7 +467,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 `%s' is %s but exported %s",
|
||||
Warning (1, "Symbol `%m%p' is %s but exported %s",
|
||||
GetSymName (S), AddrSizeToStr (S->AddrSize),
|
||||
AddrSizeToStr (S->ExportSize));
|
||||
}
|
||||
@ -505,12 +505,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 `%s' 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 `%s' cannot be exported", GetSymName (S));
|
||||
Error ("Var symbol `%m%p' cannot be exported", GetSymName (S));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -520,7 +520,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 `%s'", GetSymName (S));
|
||||
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
|
||||
}
|
||||
S->Flags &= ~SF_GLOBAL;
|
||||
}
|
||||
@ -534,7 +534,7 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri
|
||||
/* Use the real size of the symbol */
|
||||
S->ExportSize = S->AddrSize;
|
||||
} else if (S->AddrSize != S->ExportSize) {
|
||||
Error ("Address size mismatch for symbol `%s'", GetSymName (S));
|
||||
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
|
||||
}
|
||||
}
|
||||
|
||||
@ -543,7 +543,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 `%s'", GetSymName (S));
|
||||
Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
|
||||
}
|
||||
}
|
||||
S->ConDesPrio[Type] = Prio;
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2006 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -43,6 +43,7 @@
|
||||
#include "coll.h"
|
||||
#include "filepos.h"
|
||||
#include "inline.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
/* ca65 */
|
||||
#include "spool.h"
|
||||
@ -97,7 +98,7 @@ struct SymEntry {
|
||||
unsigned char ExportSize; /* Export address size */
|
||||
unsigned char AddrSize; /* Address size of label */
|
||||
unsigned char ConDesPrio[CD_TYPE_COUNT]; /* ConDes priorities... */
|
||||
/* ...actually value+1 (used as flag) */
|
||||
/* ...actually value+1 (used as flag) */
|
||||
unsigned Name; /* Name index in global string pool */
|
||||
};
|
||||
|
||||
@ -115,10 +116,10 @@ extern SymEntry* SymLast;
|
||||
|
||||
|
||||
|
||||
SymEntry* NewSymEntry (const char* Name, unsigned Flags);
|
||||
SymEntry* NewSymEntry (const StrBuf* Name, unsigned Flags);
|
||||
/* Allocate a symbol table entry, initialize and return it */
|
||||
|
||||
int SymSearchTree (SymEntry* T, const char* Name, SymEntry** E);
|
||||
int SymSearchTree (SymEntry* T, const StrBuf* Name, SymEntry** E);
|
||||
/* Search in the given tree for a name. If we find the symbol, the function
|
||||
* will return 0 and put the entry pointer into E. If we did not find the
|
||||
* symbol, and the tree is empty, E is set to NULL. If the tree is not empty,
|
||||
@ -305,10 +306,10 @@ const struct ExprNode* SymResolve (const SymEntry* Sym);
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE const char* GetSymName (const SymEntry* S)
|
||||
INLINE const StrBuf* GetSymName (const SymEntry* S)
|
||||
/* Return the name of the symbol */
|
||||
{
|
||||
return GetString (S->Name);
|
||||
return GetStrBuf (S->Name);
|
||||
}
|
||||
#else
|
||||
# define GetSymName(S) GetString ((S)->Name)
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2006 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -97,7 +97,7 @@ static unsigned ScopeTableSize (unsigned Level)
|
||||
|
||||
|
||||
|
||||
static SymTable* NewSymTable (SymTable* Parent, const char* Name)
|
||||
static SymTable* NewSymTable (SymTable* Parent, const StrBuf* Name)
|
||||
/* Allocate a symbol table on the heap and return it */
|
||||
{
|
||||
/* Determine the lexical level and the number of table slots */
|
||||
@ -119,7 +119,7 @@ static SymTable* NewSymTable (SymTable* Parent, const char* Name)
|
||||
S->TableSlots = Slots;
|
||||
S->TableEntries = 0;
|
||||
S->Parent = Parent;
|
||||
S->Name = GetStringId (Name);
|
||||
S->Name = GetStrBufId (Name);
|
||||
while (Slots--) {
|
||||
S->Table[Slots] = 0;
|
||||
}
|
||||
@ -133,7 +133,7 @@ static SymTable* NewSymTable (SymTable* Parent, const char* Name)
|
||||
} else {
|
||||
while (1) {
|
||||
/* Choose next entry */
|
||||
int Cmp = strcmp (Name, GetString (T->Name));
|
||||
int Cmp = SB_Compare (Name, GetStrBuf (T->Name));
|
||||
if (Cmp < 0) {
|
||||
if (T->Left) {
|
||||
T = T->Left;
|
||||
@ -150,7 +150,7 @@ static SymTable* NewSymTable (SymTable* Parent, const char* Name)
|
||||
}
|
||||
} else {
|
||||
/* Duplicate scope name */
|
||||
Internal ("Duplicate scope name: `%s'", Name);
|
||||
Internal ("Duplicate scope name: `%m%p'", Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -163,12 +163,12 @@ static SymTable* NewSymTable (SymTable* Parent, const char* Name)
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
void SymEnterLevel (const char* ScopeName, unsigned char Type, unsigned char AddrSize)
|
||||
void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type, unsigned char AddrSize)
|
||||
/* Enter a new lexical level */
|
||||
{
|
||||
/* Map a default address size to something real */
|
||||
@ -187,7 +187,7 @@ void SymEnterLevel (const char* ScopeName, unsigned char Type, unsigned char Add
|
||||
|
||||
/* Check if the scope has been defined before */
|
||||
if (CurrentScope->Flags & ST_DEFINED) {
|
||||
Error ("Duplicate scope `%s'", ScopeName);
|
||||
Error ("Duplicate scope `%m%p'", ScopeName);
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -235,12 +235,12 @@ void SymLeaveLevel (void)
|
||||
|
||||
|
||||
|
||||
SymTable* SymFindScope (SymTable* Parent, const char* Name, int AllocNew)
|
||||
SymTable* SymFindScope (SymTable* Parent, const StrBuf* Name, int AllocNew)
|
||||
/* Find a scope in the given enclosing scope */
|
||||
{
|
||||
SymTable** T = &Parent->Childs;
|
||||
while (*T) {
|
||||
int Cmp = strcmp (Name, GetString ((*T)->Name));
|
||||
int Cmp = SB_Compare (Name, GetStrBuf ((*T)->Name));
|
||||
if (Cmp < 0) {
|
||||
T = &(*T)->Left;
|
||||
} else if (Cmp > 0) {
|
||||
@ -262,7 +262,7 @@ SymTable* SymFindScope (SymTable* Parent, const char* Name, int AllocNew)
|
||||
|
||||
|
||||
|
||||
SymTable* SymFindAnyScope (SymTable* Parent, const char* Name)
|
||||
SymTable* SymFindAnyScope (SymTable* Parent, const StrBuf* Name)
|
||||
/* Find a scope in the given or any of its parent scopes. The function will
|
||||
* never create a new symbol, since this can only be done in one specific
|
||||
* scope.
|
||||
@ -283,7 +283,7 @@ SymTable* SymFindAnyScope (SymTable* Parent, const char* Name)
|
||||
|
||||
|
||||
|
||||
SymEntry* SymFindLocal (SymEntry* Parent, const char* Name, int AllocNew)
|
||||
SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* Name, int AllocNew)
|
||||
/* Find a cheap local symbol. If AllocNew is given and the entry is not
|
||||
* found, create a new one. Return the entry found, or the new entry created,
|
||||
* or - in case AllocNew is zero - return 0.
|
||||
@ -331,7 +331,7 @@ SymEntry* SymFindLocal (SymEntry* Parent, const char* Name, int AllocNew)
|
||||
|
||||
|
||||
|
||||
SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew)
|
||||
SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, int AllocNew)
|
||||
/* Find a new symbol table entry in the given table. If AllocNew is given and
|
||||
* the entry is not found, create a new one. Return the entry found, or the
|
||||
* new entry created, or - in case AllocNew is zero - return 0.
|
||||
@ -340,7 +340,7 @@ SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew)
|
||||
SymEntry* S;
|
||||
|
||||
/* Global symbol: Get the hash value for the name */
|
||||
unsigned Hash = HashStr (Name) % Scope->TableSlots;
|
||||
unsigned Hash = HashBuf (Name) % Scope->TableSlots;
|
||||
|
||||
/* Search for the entry */
|
||||
int Cmp = SymSearchTree (Scope->Table[Hash], Name, &S);
|
||||
@ -373,7 +373,7 @@ SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew)
|
||||
|
||||
|
||||
|
||||
SymEntry* SymFindAny (SymTable* Scope, const char* Name)
|
||||
SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name)
|
||||
/* Find a symbol in the given or any of its parent scopes. The function will
|
||||
* never create a new symbol, since this can only be done in one specific
|
||||
* scope.
|
||||
@ -424,7 +424,7 @@ static void SymCheckUndefined (SymEntry* S)
|
||||
SymEntry* Sym = 0;
|
||||
SymTable* Tab = GetSymParentScope (S);
|
||||
while (Tab) {
|
||||
Sym = SymFind (Tab, GetString (S->Name), SYM_FIND_EXISTING);
|
||||
Sym = SymFind (Tab, GetStrBuf (S->Name), SYM_FIND_EXISTING);
|
||||
if (Sym && (Sym->Flags & (SF_DEFINED | SF_IMPORT)) != 0) {
|
||||
/* We've found a symbol in a higher level that is
|
||||
* either defined in the source, or an import.
|
||||
@ -451,8 +451,9 @@ static void SymCheckUndefined (SymEntry* S)
|
||||
/* The symbol is already marked as an export. */
|
||||
if (Sym->AddrSize > S->ExportSize) {
|
||||
/* We're exporting a symbol smaller than it actually is */
|
||||
PWarning (&S->Pos, 1, "Symbol `%s' is %s but exported %s",
|
||||
GetSymName (Sym), AddrSizeToStr (Sym->AddrSize),
|
||||
PWarning (&S->Pos, 1, "Symbol `%m%p' is %s but exported %s",
|
||||
GetSymName (Sym),
|
||||
AddrSizeToStr (Sym->AddrSize),
|
||||
AddrSizeToStr (S->ExportSize));
|
||||
}
|
||||
} else {
|
||||
@ -465,8 +466,9 @@ static void SymCheckUndefined (SymEntry* S)
|
||||
}
|
||||
if (Sym->AddrSize > Sym->ExportSize) {
|
||||
/* We're exporting a symbol smaller than it actually is */
|
||||
PWarning (&S->Pos, 1, "Symbol `%s' is %s but exported %s",
|
||||
GetSymName (Sym), AddrSizeToStr (Sym->AddrSize),
|
||||
PWarning (&S->Pos, 1, "Symbol `%m%p' is %s but exported %s",
|
||||
GetSymName (Sym),
|
||||
AddrSizeToStr (Sym->AddrSize),
|
||||
AddrSizeToStr (Sym->ExportSize));
|
||||
}
|
||||
}
|
||||
@ -483,8 +485,8 @@ static void SymCheckUndefined (SymEntry* S)
|
||||
/* The symbol is definitely undefined */
|
||||
if (S->Flags & SF_EXPORT) {
|
||||
/* We will not auto-import an export */
|
||||
PError (&S->Pos, "Exported symbol `%s' was never defined",
|
||||
GetString (S->Name));
|
||||
PError (&S->Pos, "Exported symbol `%m%p' was never defined",
|
||||
GetSymName (S));
|
||||
} else {
|
||||
if (AutoImport) {
|
||||
/* Mark as import, will be indexed later */
|
||||
@ -493,7 +495,7 @@ static void SymCheckUndefined (SymEntry* S)
|
||||
S->AddrSize = CodeAddrSize;
|
||||
} else {
|
||||
/* Error */
|
||||
PError (&S->Pos, "Symbol `%s' is undefined", GetString (S->Name));
|
||||
PError (&S->Pos, "Symbol `%m%p' is undefined", GetSymName (S));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -549,11 +551,11 @@ void SymCheck (void)
|
||||
|
||||
/* Check for defined symbols that were never referenced */
|
||||
if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
|
||||
const char* Name = GetString (S->Name);
|
||||
if (Name[0] != '.') { /* Ignore internals */
|
||||
const StrBuf* Name = GetStrBuf (S->Name);
|
||||
if (SB_At (Name, 0) != '.') { /* Ignore internals */
|
||||
PWarning (&S->Pos, 2,
|
||||
"Symbol `%s' is defined but never used",
|
||||
GetString (S->Name));
|
||||
"Symbol `%m%p' is defined but never used",
|
||||
GetSymName (S));
|
||||
}
|
||||
}
|
||||
|
||||
@ -562,8 +564,8 @@ void SymCheck (void)
|
||||
if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) {
|
||||
/* Imported symbol is not referenced */
|
||||
PWarning (&S->Pos, 2,
|
||||
"Symbol `%s' is imported but never used",
|
||||
GetString (S->Name));
|
||||
"Symbol `%m%p' is imported but never used",
|
||||
GetSymName (S));
|
||||
} else {
|
||||
/* Give the import an index, count imports */
|
||||
S->Index = ImportCount++;
|
||||
@ -593,8 +595,9 @@ void SymCheck (void)
|
||||
} else if (S->AddrSize > S->ExportSize) {
|
||||
/* We're exporting a symbol smaller than it actually is */
|
||||
PWarning (&S->Pos, 1,
|
||||
"Symbol `%s' is %s but exported %s",
|
||||
GetSymName (S), AddrSizeToStr (S->AddrSize),
|
||||
"Symbol `%m%p' is %s but exported %s",
|
||||
GetSymName (S),
|
||||
AddrSizeToStr (S->AddrSize),
|
||||
AddrSizeToStr (S->ExportSize));
|
||||
}
|
||||
}
|
||||
@ -612,7 +615,7 @@ void SymCheck (void)
|
||||
const FilePos* P = S->GuessedUse[S->AddrSize - 1];
|
||||
if (P) {
|
||||
PWarning (P, 0,
|
||||
"Didn't use %s addressing for `%s'",
|
||||
"Didn't use %s addressing for `%m%p'",
|
||||
AddrSizeToStr (S->AddrSize),
|
||||
GetSymName (S));
|
||||
}
|
||||
@ -637,8 +640,8 @@ void SymDump (FILE* F)
|
||||
/* Ignore unused symbols */
|
||||
if ((S->Flags & SF_UNUSED) != 0) {
|
||||
fprintf (F,
|
||||
"%-24s %s %s %s %s %s\n",
|
||||
GetString (S->Name),
|
||||
"%m%-24p %s %s %s %s %s\n",
|
||||
GetSymName (S),
|
||||
(S->Flags & SF_DEFINED)? "DEF" : "---",
|
||||
(S->Flags & SF_REFERENCED)? "REF" : "---",
|
||||
(S->Flags & SF_IMPORT)? "IMP" : "---",
|
||||
@ -842,3 +845,5 @@ void WriteScopes (void)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -101,34 +101,34 @@ extern SymTable* RootScope; /* Root symbol table */
|
||||
|
||||
|
||||
|
||||
void SymEnterLevel (const char* ScopeName, unsigned char Type, unsigned char AddrSize);
|
||||
void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type, unsigned char AddrSize);
|
||||
/* Enter a new lexical level */
|
||||
|
||||
void SymLeaveLevel (void);
|
||||
/* Leave the current lexical level */
|
||||
|
||||
SymTable* SymFindScope (SymTable* Parent, const char* Name, int AllocNew);
|
||||
SymTable* SymFindScope (SymTable* Parent, const StrBuf* Name, int AllocNew);
|
||||
/* Find a scope in the given enclosing scope */
|
||||
|
||||
SymTable* SymFindAnyScope (SymTable* Parent, const char* Name);
|
||||
SymTable* SymFindAnyScope (SymTable* Parent, const StrBuf* Name);
|
||||
/* Find a scope in the given or any of its parent scopes. The function will
|
||||
* never create a new symbol, since this can only be done in one specific
|
||||
* scope.
|
||||
*/
|
||||
|
||||
SymEntry* SymFindLocal (SymEntry* Parent, const char* Name, int AllocNew);
|
||||
SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* StrBuf, int AllocNew);
|
||||
/* Find a cheap local symbol. If AllocNew is given and the entry is not
|
||||
* found, create a new one. Return the entry found, or the new entry created,
|
||||
* or - in case AllocNew is zero - return 0.
|
||||
*/
|
||||
|
||||
SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew);
|
||||
SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, int AllocNew);
|
||||
/* Find a new symbol table entry in the given table. If AllocNew is given and
|
||||
* the entry is not found, create a new one. Return the entry found, or the
|
||||
* new entry created, or - in case AllocNew is zero - return 0.
|
||||
*/
|
||||
|
||||
SymEntry* SymFindAny (SymTable* Scope, const char* Name);
|
||||
SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name);
|
||||
/* Find a symbol in the given or any of its parent scopes. The function will
|
||||
* never create a new symbol, since this can only be done in one specific
|
||||
* scope.
|
||||
|
@ -47,7 +47,7 @@
|
||||
int TokHasSVal (Token Tok)
|
||||
/* Return true if the given token has an attached SVal */
|
||||
{
|
||||
return (Tok == TOK_IDENT || TOK_LOCAL_IDENT || Tok == TOK_STRCON);
|
||||
return (Tok == TOK_IDENT || Tok == TOK_LOCAL_IDENT || Tok == TOK_STRCON);
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 1998-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -60,16 +60,15 @@ TokNode* NewTokNode (void)
|
||||
TokNode* T;
|
||||
|
||||
/* Allocate memory */
|
||||
unsigned Len = TokHasSVal (Tok)? strlen (SVal) : 0;
|
||||
T = xmalloc (sizeof (TokNode) + Len);
|
||||
T = xmalloc (sizeof (TokNode));
|
||||
|
||||
/* Initialize the token contents */
|
||||
T->Next = 0;
|
||||
T->Tok = Tok;
|
||||
T->WS = WS;
|
||||
T->IVal = IVal;
|
||||
memcpy (T->SVal, SVal, Len);
|
||||
T->SVal [Len] = '\0';
|
||||
T->SVal = AUTO_STRBUF_INITIALIZER;
|
||||
SB_Copy (&T->SVal, &SVal);
|
||||
|
||||
/* Return the node */
|
||||
return T;
|
||||
@ -80,6 +79,7 @@ TokNode* NewTokNode (void)
|
||||
void FreeTokNode (TokNode* T)
|
||||
/* Free the given token node */
|
||||
{
|
||||
SB_Done (&T->SVal);
|
||||
xfree (T);
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ void TokSet (TokNode* T)
|
||||
Tok = T->Tok;
|
||||
WS = T->WS;
|
||||
IVal = T->IVal;
|
||||
strcpy (SVal, T->SVal);
|
||||
SB_Copy (&SVal, &T->SVal);
|
||||
}
|
||||
|
||||
|
||||
@ -107,7 +107,7 @@ enum TC TokCmp (const TokNode* T)
|
||||
|
||||
/* If the token has string attribute, check it */
|
||||
if (TokHasSVal (T->Tok)) {
|
||||
if (strcmp (T->SVal, SVal) != 0) {
|
||||
if (SB_Compare (&SVal, &T->SVal) != 0) {
|
||||
return tcSameToken;
|
||||
}
|
||||
} else if (TokHasIVal (T->Tok)) {
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2007 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 2000-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -38,6 +38,10 @@
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "strbuf.h"
|
||||
|
||||
/* ca65 */
|
||||
#include "scanner.h"
|
||||
|
||||
|
||||
@ -55,7 +59,7 @@ struct TokNode {
|
||||
Token Tok; /* Token value */
|
||||
int WS; /* Whitespace before token? */
|
||||
long IVal; /* Integer token attribute */
|
||||
char SVal [1]; /* String attribute, dyn. allocated */
|
||||
StrBuf SVal; /* String attribute, dyn. allocated */
|
||||
};
|
||||
|
||||
/* Struct holding a token list */
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2001-2004 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 2001-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* */
|
||||
@ -415,8 +415,8 @@ static void ParseAsm (void)
|
||||
|
||||
Done:
|
||||
/* Call the string buf destructors */
|
||||
DoneStrBuf (&S);
|
||||
DoneStrBuf (&T);
|
||||
SB_Done (&S);
|
||||
SB_Done (&T);
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2001-2006, Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 2001-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -541,7 +541,7 @@ void CS_AddVLine (CodeSeg* S, LineInfo* LI, const char* Format, va_list ap)
|
||||
}
|
||||
|
||||
/* Cleanup the string buffer */
|
||||
DoneStrBuf (&Buf);
|
||||
SB_Done (&Buf);
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2005, Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 2000-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -81,7 +81,7 @@ Macro* NewMacro (const char* Name)
|
||||
M->ArgCount = -1; /* Flag: Not a function like macro */
|
||||
M->MaxArgs = 0;
|
||||
InitCollection (&M->FormalArgs);
|
||||
InitStrBuf (&M->Replacement);
|
||||
SB_Init (&M->Replacement);
|
||||
M->Variadic = 0;
|
||||
memcpy (M->Name, Name, Len+1);
|
||||
|
||||
@ -102,7 +102,7 @@ void FreeMacro (Macro* M)
|
||||
xfree (CollAtUnchecked (&M->FormalArgs, I));
|
||||
}
|
||||
DoneCollection (&M->FormalArgs);
|
||||
DoneStrBuf (&M->Replacement);
|
||||
SB_Done (&M->Replacement);
|
||||
xfree (M);
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2004 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -153,7 +153,7 @@ static void StringPragma (StrBuf* B, void (*Func) (const char*))
|
||||
}
|
||||
|
||||
/* Call the string buf destructor */
|
||||
DoneStrBuf (&S);
|
||||
SB_Done (&S);
|
||||
}
|
||||
|
||||
|
||||
@ -223,7 +223,7 @@ static void SegNamePragma (StrBuf* B, segment_t Seg)
|
||||
g_segname (Seg);
|
||||
|
||||
/* Call the string buf destructor */
|
||||
DoneStrBuf (&S);
|
||||
SB_Done (&S);
|
||||
}
|
||||
|
||||
|
||||
@ -494,7 +494,7 @@ static void ParsePragma (void)
|
||||
FlagPragma (&B, &WarnDisable);
|
||||
break;
|
||||
|
||||
case PR_ZPSYM:
|
||||
case PR_ZPSYM:
|
||||
StringPragma (&B, MakeZPSym);
|
||||
break;
|
||||
|
||||
@ -522,7 +522,7 @@ static void ParsePragma (void)
|
||||
}
|
||||
|
||||
/* Release the StrBuf */
|
||||
DoneStrBuf (&B);
|
||||
SB_Done (&B);
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2007, Ullrich von Bassewitz */
|
||||
/* (C) 1998-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -189,7 +189,7 @@ static MacroExp* InitMacroExp (MacroExp* E, Macro* M)
|
||||
/* Initialize a MacroExp structure */
|
||||
{
|
||||
InitCollection (&E->ActualArgs);
|
||||
InitStrBuf (&E->Replacement);
|
||||
SB_Init (&E->Replacement);
|
||||
E->M = M;
|
||||
return E;
|
||||
}
|
||||
@ -206,7 +206,7 @@ static void DoneMacroExp (MacroExp* E)
|
||||
FreeStrBuf (CollAtUnchecked (&E->ActualArgs, I));
|
||||
}
|
||||
DoneCollection (&E->ActualArgs);
|
||||
DoneStrBuf (&E->Replacement);
|
||||
SB_Done (&E->Replacement);
|
||||
}
|
||||
|
||||
|
||||
@ -488,7 +488,7 @@ static void ReadMacroArgs (MacroExp* E)
|
||||
}
|
||||
|
||||
/* Deallocate string buf resources */
|
||||
DoneStrBuf (&Arg);
|
||||
SB_Done (&Arg);
|
||||
}
|
||||
|
||||
|
||||
@ -1145,7 +1145,7 @@ static void DoInclude (void)
|
||||
|
||||
Done:
|
||||
/* Free the allocated filename data */
|
||||
DoneStrBuf (&Filename);
|
||||
SB_Done (&Filename);
|
||||
|
||||
/* Clear the remaining line so the next input will come from the new
|
||||
* file (if open)
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2004 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -442,7 +442,7 @@ static void NumericConst (void)
|
||||
{
|
||||
unsigned Base; /* Temporary number base */
|
||||
unsigned Prefix; /* Base according to prefix */
|
||||
StrBuf S;
|
||||
StrBuf S = STATIC_STRBUF_INITIALIZER;
|
||||
int IsFloat;
|
||||
char C;
|
||||
unsigned DigitVal;
|
||||
@ -470,7 +470,6 @@ static void NumericConst (void)
|
||||
* before converting it, so we can determine if it's a float or an
|
||||
* integer.
|
||||
*/
|
||||
InitStrBuf (&S);
|
||||
while (IsXDigit (CurC) && HexVal (CurC) < Base) {
|
||||
SB_AppendChar (&S, CurC);
|
||||
NextChar ();
|
||||
@ -506,7 +505,7 @@ static void NumericConst (void)
|
||||
}
|
||||
|
||||
/* We don't need the string buffer any longer */
|
||||
DoneStrBuf (&S);
|
||||
SB_Done (&S);
|
||||
|
||||
/* Distinguish between integer and floating point constants */
|
||||
if (!IsFloat) {
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -33,6 +33,11 @@
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "hashstr.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
@ -54,3 +59,18 @@ unsigned HashStr (const char* S)
|
||||
|
||||
|
||||
|
||||
unsigned HashBuf (const StrBuf* S)
|
||||
/* Return a hash value for the given string buffer */
|
||||
{
|
||||
unsigned I, L, H;
|
||||
|
||||
/* Do the hash */
|
||||
H = L = 0;
|
||||
for (I = 0; I < SB_GetLen (S); ++I) {
|
||||
H = ((H << 3) ^ ((unsigned char) SB_AtUnchecked (S, I))) + L++;
|
||||
}
|
||||
return H;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,15 +1,15 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* hashstr.h */
|
||||
/* hashstr.h */
|
||||
/* */
|
||||
/* Hash function for strings */
|
||||
/* Hash function for strings */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -38,7 +38,9 @@
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "attrib.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
|
||||
|
||||
@ -51,6 +53,9 @@
|
||||
unsigned HashStr (const char* S) attribute ((const));
|
||||
/* Return a hash value for the given string */
|
||||
|
||||
unsigned HashBuf (const StrBuf* S) attribute ((const));
|
||||
/* Return a hash value for the given string buffer */
|
||||
|
||||
|
||||
|
||||
/* End of hashstr.h */
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 2003-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -112,7 +112,7 @@ INLINE void InitHashNode (HashNode* N, void* Entry)
|
||||
#define InitHashNode(N, E) \
|
||||
(N)->Next = 0, \
|
||||
(N)->Owner = 0, \
|
||||
(N)->Entry = (E)
|
||||
(N)->Entry = (E)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 2000-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -138,7 +138,7 @@ static char* Find (const char* Path, const char* File)
|
||||
if (access (SB_GetBuf (&PathName), 0) == 0) {
|
||||
/* The file exists, return its name */
|
||||
char* Name = xstrdup (SB_GetBuf (&PathName));
|
||||
DoneStrBuf (&PathName);
|
||||
SB_Done (&PathName);
|
||||
return Name;
|
||||
}
|
||||
|
||||
@ -149,7 +149,7 @@ static char* Find (const char* Path, const char* File)
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
DoneStrBuf (&PathName);
|
||||
SB_Done (&PathName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -62,22 +62,37 @@ const StrBuf EmptyStrBuf = STATIC_STRBUF_INITIALIZER;
|
||||
|
||||
|
||||
|
||||
StrBuf* InitStrBuf (StrBuf* B)
|
||||
#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.
|
||||
*/
|
||||
{
|
||||
B->Allocated = 0;
|
||||
B->Len = 0;
|
||||
B->Len = strlen (S);
|
||||
B->Index = 0;
|
||||
B->Buf = 0;
|
||||
B->Buf = (char*) S;
|
||||
return B;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DoneStrBuf (StrBuf* B)
|
||||
void SB_Done (StrBuf* B)
|
||||
/* Free the data of a string buffer (but not the struct itself) */
|
||||
{
|
||||
xfree (B->Buf);
|
||||
if (B->Allocated) {
|
||||
xfree (B->Buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -89,7 +104,7 @@ StrBuf* NewStrBuf (void)
|
||||
StrBuf* B = xmalloc (sizeof (StrBuf));
|
||||
|
||||
/* Initialize the struct... */
|
||||
InitStrBuf (B);
|
||||
SB_Init (B);
|
||||
|
||||
/* ...and return it */
|
||||
return B;
|
||||
@ -100,7 +115,7 @@ StrBuf* NewStrBuf (void)
|
||||
void FreeStrBuf (StrBuf* B)
|
||||
/* Free a string buffer */
|
||||
{
|
||||
DoneStrBuf (B);
|
||||
SB_Done (B);
|
||||
xfree (B);
|
||||
}
|
||||
|
||||
@ -122,8 +137,50 @@ void SB_Realloc (StrBuf* B, unsigned NewSize)
|
||||
NewAllocated *= 2;
|
||||
}
|
||||
|
||||
/* Reallocate the buffer */
|
||||
B->Buf = xrealloc (B->Buf, NewAllocated);
|
||||
/* Reallocate the buffer. Beware: The allocated size may be zero while the
|
||||
* length is not. This means that we have a buffer that wasn't allocated
|
||||
* on the heap.
|
||||
*/
|
||||
if (B->Allocated) {
|
||||
/* Just reallocate the block */
|
||||
B->Buf = xrealloc (B->Buf, NewAllocated);
|
||||
} else {
|
||||
/* Allocate a new block and copy */
|
||||
B->Buf = memcpy (xmalloc (NewAllocated), B->Buf, B->Len);
|
||||
}
|
||||
|
||||
/* Remember the new block size */
|
||||
B->Allocated = NewAllocated;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void SB_CheapRealloc (StrBuf* B, unsigned NewSize)
|
||||
/* Reallocate the string buffer space, make sure at least NewSize bytes are
|
||||
* available. This function won't copy the old buffer contents over to the new
|
||||
* buffer and may be used if the old contents are overwritten later.
|
||||
*/
|
||||
{
|
||||
/* Get the current size, use a minimum of 8 bytes */
|
||||
unsigned NewAllocated = B->Allocated;
|
||||
if (NewAllocated == 0) {
|
||||
NewAllocated = 8;
|
||||
}
|
||||
|
||||
/* Round up to the next power of two */
|
||||
while (NewAllocated < NewSize) {
|
||||
NewAllocated *= 2;
|
||||
}
|
||||
|
||||
/* Free the old buffer if there is one */
|
||||
if (B->Allocated) {
|
||||
xfree (B->Buf);
|
||||
}
|
||||
|
||||
/* Allocate a fresh block */
|
||||
B->Buf = xmalloc (NewAllocated);
|
||||
|
||||
/* Remember the new block size */
|
||||
B->Allocated = NewAllocated;
|
||||
}
|
||||
|
||||
@ -170,7 +227,7 @@ void SB_CopyBuf (StrBuf* Target, const char* Buf, unsigned Size)
|
||||
/* Copy Buf to Target, discarding the old contents of Target */
|
||||
{
|
||||
if (Target->Allocated < Size) {
|
||||
SB_Realloc (Target, Size);
|
||||
SB_CheapRealloc (Target, Size);
|
||||
}
|
||||
memcpy (Target->Buf, Buf, Size);
|
||||
Target->Len = Size;
|
||||
@ -294,7 +351,7 @@ void SB_Move (StrBuf* Target, StrBuf* Source)
|
||||
*/
|
||||
{
|
||||
/* Free the target string */
|
||||
if (Target->Buf) {
|
||||
if (Target->Allocated) {
|
||||
xfree (Target->Buf);
|
||||
}
|
||||
|
||||
@ -302,7 +359,7 @@ void SB_Move (StrBuf* Target, StrBuf* Source)
|
||||
*Target = *Source;
|
||||
|
||||
/* Clear Source */
|
||||
InitStrBuf (Source);
|
||||
SB_Init (Source);
|
||||
}
|
||||
|
||||
|
||||
@ -359,6 +416,31 @@ int SB_Compare (const StrBuf* S1, const StrBuf* S2)
|
||||
|
||||
|
||||
|
||||
int SB_CompareStr (const StrBuf* S1, const char* S2)
|
||||
/* Do a lexical compare of S1 and S2. See strcmp for result codes. */
|
||||
{
|
||||
int Result;
|
||||
unsigned S2Len = strlen (S2);
|
||||
if (S1->Len < S2Len) {
|
||||
Result = memcmp (S1->Buf, S2, S1->Len);
|
||||
if (Result == 0) {
|
||||
/* S1 considered lesser because it's shorter */
|
||||
Result = -1;
|
||||
}
|
||||
} else if (S1->Len > S2Len) {
|
||||
Result = memcmp (S1->Buf, S2, S2Len);
|
||||
if (Result == 0) {
|
||||
/* S2 considered lesser because it's shorter */
|
||||
Result = 1;
|
||||
}
|
||||
} else {
|
||||
Result = memcmp (S1->Buf, S2, S1->Len);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SB_VPrintf (StrBuf* S, const char* Format, va_list ap)
|
||||
/* printf function with S as target. The function is safe, which means that
|
||||
* the current contents of S are discarded, and are allocated again with
|
||||
@ -382,10 +464,8 @@ void SB_VPrintf (StrBuf* S, const char* Format, va_list ap)
|
||||
|
||||
/* Check if we must reallocate */
|
||||
if ((unsigned) SizeNeeded >= S->Allocated) {
|
||||
/* Must retry. Don't use Realloc to avoid copying */
|
||||
xfree (S->Buf);
|
||||
S->Allocated = SizeNeeded + 1; /* Account for '\0' */
|
||||
S->Buf = xmalloc (S->Allocated);
|
||||
/* Must retry. Use CheapRealloc to avoid copying */
|
||||
SB_CheapRealloc (S, SizeNeeded + 1); /* Account for '\0' */
|
||||
(void) xvsnprintf (S->Buf, S->Allocated, Format, ap);
|
||||
}
|
||||
|
||||
|
@ -49,18 +49,18 @@
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
typedef struct StrBuf StrBuf;
|
||||
struct StrBuf {
|
||||
unsigned Allocated; /* Size of allocated memory */
|
||||
char* Buf; /* Pointer to buffer */
|
||||
unsigned Len; /* Length of the string */
|
||||
unsigned Index; /* Used for reading (Get and friends) */
|
||||
char* Buf; /* Pointer to buffer */
|
||||
};
|
||||
unsigned Allocated; /* Size of allocated memory */
|
||||
};
|
||||
|
||||
/* An empty string buf */
|
||||
extern const StrBuf EmptyStrBuf;
|
||||
@ -71,18 +71,36 @@ extern const StrBuf EmptyStrBuf;
|
||||
/* Initializer for auto string bufs */
|
||||
#define AUTO_STRBUF_INITIALIZER EmptyStrBuf
|
||||
|
||||
/* Initialize with a string literal (beware: evaluates str twice!) */
|
||||
#define LIT_STRBUF_INITIALIZER(str) { (char*)str, sizeof(str)-1, 0, 0 }
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
StrBuf* InitStrBuf (StrBuf* B);
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE StrBuf* SB_Init (StrBuf* B)
|
||||
/* Initialize a string buffer */
|
||||
{
|
||||
*B = EmptyStrBuf;
|
||||
return B;
|
||||
}
|
||||
#else
|
||||
StrBuf* SB_Init (StrBuf* B);
|
||||
#endif
|
||||
|
||||
void DoneStrBuf (StrBuf* B);
|
||||
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. A buffer initialized with
|
||||
* this routine may be "forgotten" without calling SB_Done, since no memory
|
||||
* has been allocated.
|
||||
*/
|
||||
|
||||
void SB_Done (StrBuf* B);
|
||||
/* Free the data of a string buffer (but not the struct itself) */
|
||||
|
||||
StrBuf* NewStrBuf (void);
|
||||
@ -358,14 +376,17 @@ void SB_ToUpper (StrBuf* S);
|
||||
int SB_Compare (const StrBuf* S1, const StrBuf* S2);
|
||||
/* Do a lexical compare of S1 and S2. See strcmp for result codes. */
|
||||
|
||||
void SB_VPrintf (StrBuf* S, const char* Format, va_list ap);
|
||||
int SB_CompareStr (const StrBuf* S1, const char* S2);
|
||||
/* Do a lexical compare of S1 and S2. See strcmp for result codes. */
|
||||
|
||||
void SB_VPrintf (StrBuf* S, const char* Format, va_list ap) attribute ((format (printf, 2, 0)));
|
||||
/* printf function with S as target. The function is safe, which means that
|
||||
* the current contents of S are discarded, and are allocated again with
|
||||
* a matching size for the output. The function will call FAIL when problems
|
||||
* are detected (anything that let xsnprintf return -1).
|
||||
*/
|
||||
|
||||
void SB_Printf (StrBuf* S, const char* Format, ...);
|
||||
void SB_Printf (StrBuf* S, const char* Format, ...) attribute ((format (printf, 2, 3)));
|
||||
/* vprintf function with S as target. The function is safe, which means that
|
||||
* the current contents of S are discarded, and are allocated again with
|
||||
* a matching size for the output. The function will call FAIL when problems
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 2003-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -35,7 +35,7 @@
|
||||
|
||||
/* A string pool is used to store identifiers and other strings. Each string
|
||||
* stored in the pool has a unique id, which may be used to access the string
|
||||
* in the pool. Identical strings are only stored once in the pool and have
|
||||
* in the pool. Identical strings are stored only once in the pool and have
|
||||
* identical ids. This means that instead of comparing strings, just the
|
||||
* string pool ids must be compared.
|
||||
*/
|
||||
@ -64,8 +64,7 @@ struct StringPoolEntry {
|
||||
StringPoolEntry* Next; /* Pointer to next entry in hash chain */
|
||||
unsigned Hash; /* Full hash value */
|
||||
unsigned Id; /* The numeric string id */
|
||||
unsigned Len; /* Length of the string (excluding terminator) */
|
||||
char S[1]; /* The string itself */
|
||||
StrBuf Buf; /* The string itself */
|
||||
};
|
||||
|
||||
|
||||
@ -76,21 +75,21 @@ struct StringPoolEntry {
|
||||
|
||||
|
||||
|
||||
static StringPoolEntry* NewStringPoolEntry (const char* S, unsigned Hash, unsigned Id)
|
||||
static StringPoolEntry* NewStringPoolEntry (const StrBuf* S, unsigned Hash, unsigned Id)
|
||||
/* Create a new string pool entry and return it. */
|
||||
{
|
||||
/* Get the length of the string */
|
||||
unsigned Len = strlen (S);
|
||||
|
||||
/* Allocate memory */
|
||||
StringPoolEntry* E = xmalloc (sizeof (StringPoolEntry) + Len);
|
||||
StringPoolEntry* E = xmalloc (sizeof (StringPoolEntry));
|
||||
|
||||
/* Initialize the fields */
|
||||
E->Next = 0;
|
||||
E->Hash = Hash;
|
||||
E->Id = Id;
|
||||
E->Len = Len;
|
||||
memcpy (E->S, S, Len+1);
|
||||
E->Buf = AUTO_STRBUF_INITIALIZER;
|
||||
SB_Copy (&E->Buf, S);
|
||||
|
||||
/* Always zero terminate the string */
|
||||
SB_Terminate (&E->Buf);
|
||||
|
||||
/* Return the new entry */
|
||||
return E;
|
||||
@ -129,7 +128,15 @@ void DoneStringPool (StringPool* P)
|
||||
|
||||
/* Free all entries and clear the entry collection */
|
||||
for (I = 0; I < CollCount (&P->Entries); ++I) {
|
||||
xfree (CollAtUnchecked (&P->Entries, I));
|
||||
|
||||
/* Get a pointer to the entry */
|
||||
StringPoolEntry* E = CollAtUnchecked (&P->Entries, I);
|
||||
|
||||
/* Free string buffer memory */
|
||||
SB_Done (&E->Buf);
|
||||
|
||||
/* Free the memory for the entry itself */
|
||||
xfree (E);
|
||||
}
|
||||
CollDeleteAll (&P->Entries);
|
||||
|
||||
@ -165,25 +172,26 @@ void FreeStringPool (StringPool* P)
|
||||
|
||||
|
||||
|
||||
const char* SP_Get (const StringPool* P, unsigned Index)
|
||||
const StrBuf* SP_Get (const StringPool* P, unsigned Index)
|
||||
/* Return a string from the pool. Index must exist, otherwise FAIL is called. */
|
||||
{
|
||||
/* Get the collection entry */
|
||||
const StringPoolEntry* E = CollConstAt (&P->Entries, Index);
|
||||
|
||||
/* Return the string from the entry */
|
||||
return E->S;
|
||||
return &E->Buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned SP_Add (StringPool* P, const char* S)
|
||||
/* Add a string to the buffer and return the index. If the string does already
|
||||
* exist in the pool, SP_Add will just return the index of the existing string.
|
||||
unsigned SP_Add (StringPool* P, const StrBuf* S)
|
||||
/* Add a string buffer to the buffer and return the index. If the string does
|
||||
* already exist in the pool, SP_AddBuf will just return the index of the
|
||||
* existing string.
|
||||
*/
|
||||
{
|
||||
/* Calculate the string hash */
|
||||
unsigned Hash = HashStr (S);
|
||||
unsigned Hash = HashBuf (S);
|
||||
|
||||
/* Calculate the reduced string hash */
|
||||
unsigned RHash = Hash % (sizeof (P->Tab)/sizeof (P->Tab[0]));
|
||||
@ -191,7 +199,7 @@ unsigned SP_Add (StringPool* P, const char* S)
|
||||
/* Search for an existing entry */
|
||||
StringPoolEntry* E = P->Tab[RHash];
|
||||
while (E) {
|
||||
if (E->Hash == Hash && strcmp (E->S, S) == 0) {
|
||||
if (E->Hash == Hash && SB_Compare (&E->Buf, S) == 0) {
|
||||
/* Found, return the id of the existing string */
|
||||
return E->Id;
|
||||
}
|
||||
@ -208,8 +216,8 @@ unsigned SP_Add (StringPool* P, const char* S)
|
||||
E->Next = P->Tab[RHash];
|
||||
P->Tab[RHash] = E;
|
||||
|
||||
/* Add up the string size (plus terminator) */
|
||||
P->TotalSize += E->Len + 1;
|
||||
/* Add up the string size */
|
||||
P->TotalSize += SB_GetLen (&E->Buf);
|
||||
|
||||
/* Return the id of the entry */
|
||||
return E->Id;
|
||||
@ -217,3 +225,22 @@ unsigned SP_Add (StringPool* P, const char* S)
|
||||
|
||||
|
||||
|
||||
unsigned SP_AddStr (StringPool* P, const char* S)
|
||||
/* Add a string to the buffer and return the index. If the string does already
|
||||
* exist in the pool, SP_Add will just return the index of the existing string.
|
||||
*/
|
||||
{
|
||||
unsigned Id;
|
||||
|
||||
/* First make a string buffer, then add it. This is some overhead, but the
|
||||
* routine will probably go.
|
||||
*/
|
||||
StrBuf Buf;
|
||||
Id = SP_Add (P, SB_InitFromString (&Buf, S));
|
||||
|
||||
/* Return the id of the new entry */
|
||||
return Id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 2003-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -48,6 +48,7 @@
|
||||
|
||||
|
||||
/* common */
|
||||
#include "attrib.h"
|
||||
#include "coll.h"
|
||||
#include "inline.h"
|
||||
#include "strbuf.h"
|
||||
@ -100,10 +101,16 @@ StringPool* NewStringPool (void);
|
||||
void FreeStringPool (StringPool* P);
|
||||
/* Free a string pool */
|
||||
|
||||
const char* SP_Get (const StringPool* P, unsigned Index);
|
||||
const StrBuf* SP_Get (const StringPool* P, unsigned Index);
|
||||
/* Return a string from the pool. Index must exist, otherwise FAIL is called. */
|
||||
|
||||
unsigned SP_Add (StringPool* P, const char* S);
|
||||
unsigned SP_Add (StringPool* P, const StrBuf* S);
|
||||
/* Add a string buffer to the buffer and return the index. If the string does
|
||||
* already exist in the pool, SP_AddBuf will just return the index of the
|
||||
* existing string.
|
||||
*/
|
||||
|
||||
unsigned SP_AddStr (StringPool* P, const char* S);
|
||||
/* Add a string to the buffer and return the index. If the string does already
|
||||
* exist in the pool, SP_Add will just return the index of the existing string.
|
||||
*/
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2004 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 2000-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -35,6 +35,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* common */
|
||||
#include "abend.h"
|
||||
#include "check.h"
|
||||
#include "target.h"
|
||||
@ -212,6 +213,16 @@ void TgtTranslateBuf (void* Buf, unsigned Len)
|
||||
|
||||
|
||||
|
||||
void TgtTranslateStrBuf (StrBuf* Buf)
|
||||
/* Translate a string buffer from the source character set into the target
|
||||
* system character set.
|
||||
*/
|
||||
{
|
||||
TgtTranslateBuf (SB_GetBuf (Buf), SB_GetLen (Buf));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void TgtTranslateSet (unsigned Index, unsigned char C)
|
||||
/* Set the translation code for the given character */
|
||||
{
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 2000-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -34,7 +34,12 @@
|
||||
|
||||
|
||||
#ifndef TGTTRANS_H
|
||||
#define TGTTRANS_H
|
||||
#define TGTTRANS_H
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "strbuf.h"
|
||||
|
||||
|
||||
|
||||
@ -62,6 +67,11 @@ void TgtTranslateBuf (void* Buf, unsigned Len);
|
||||
* the target system character set.
|
||||
*/
|
||||
|
||||
void TgtTranslateStrBuf (StrBuf* Buf);
|
||||
/* Translate a string buffer from the source character set into the target
|
||||
* system character set.
|
||||
*/
|
||||
|
||||
void TgtTranslateSet (unsigned Index, unsigned char C);
|
||||
/* Set the translation code for the given character */
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2005 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 2005-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -228,7 +228,7 @@ void AsmInc (const char* Filename, char CommentStart, int IgnoreUnknown)
|
||||
}
|
||||
|
||||
/* Delete the string buffer contents */
|
||||
DoneStrBuf (&Ident);
|
||||
SB_Done (&Ident);
|
||||
|
||||
/* Close the include file ignoring errors (we were just reading). */
|
||||
(void) fclose (F);
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 2003-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1999-2005 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 1999-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -62,9 +62,9 @@
|
||||
|
||||
|
||||
struct BinDesc {
|
||||
unsigned Undef; /* Count of undefined externals */
|
||||
FILE* F; /* Output file */
|
||||
const char* Filename; /* Name of output file */
|
||||
unsigned Undef; /* Count of undefined externals */
|
||||
FILE* F; /* Output file */
|
||||
const char* Filename; /* Name of output file */
|
||||
};
|
||||
|
||||
|
||||
@ -148,9 +148,9 @@ static void BinWriteMem (BinDesc* D, Memory* M)
|
||||
Print (stdout, 1, " Writing `%s'\n", GetString (S->Name));
|
||||
|
||||
/* Writes do only occur in the load area and not for BSS segments */
|
||||
DoWrite = (S->Flags & SF_BSS) == 0 && /* No BSS segment */
|
||||
S->Load == M && /* LOAD segment */
|
||||
S->Seg->Dumped == 0; /* Not already written */
|
||||
DoWrite = (S->Flags & SF_BSS) == 0 && /* No BSS segment */
|
||||
S->Load == M && /* LOAD segment */
|
||||
S->Seg->Dumped == 0; /* Not already written */
|
||||
|
||||
/* Output debugging stuff */
|
||||
PrintBoolVal ("bss", S->Flags & SF_BSS);
|
||||
@ -315,3 +315,4 @@ void BinWriteTarget (BinDesc* D, struct File* F)
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2005, Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 2005-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -91,7 +91,7 @@ static void CE_Done (CfgExpr* E)
|
||||
{
|
||||
/* If the type is a string, we must delete the string buffer */
|
||||
if (E->Type == ceString) {
|
||||
DoneStrBuf (&E->SVal);
|
||||
SB_Done (&E->SVal);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 2000-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -112,7 +112,7 @@ static int ConDesCompare (void* Data, const void* E1, const void* E2)
|
||||
Cmp = 1;
|
||||
} else {
|
||||
/* Use the name in this case */
|
||||
Cmp = strcmp (GetString (Exp1->Name), GetString (Exp2->Name));
|
||||
Cmp = SB_Compare (GetStrBuf (Exp1->Name), GetStrBuf (Exp2->Name));
|
||||
}
|
||||
|
||||
/* Reverse the result for decreasing order */
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2005 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -203,7 +203,7 @@ static Memory* CfgFindMemory (unsigned Name)
|
||||
static Memory* CfgGetMemory (unsigned Name)
|
||||
/* Find the memory are with the given name. Print an error on an invalid name */
|
||||
{
|
||||
Memory* M = CfgFindMemory (Name);
|
||||
Memory* M = CfgFindMemory (Name);
|
||||
if (M == 0) {
|
||||
CfgError ("Invalid memory area `%s'", GetString (Name));
|
||||
}
|
||||
@ -1557,13 +1557,14 @@ void CfgRead (void)
|
||||
static void CreateRunDefines (SegDesc* S, unsigned long SegAddr)
|
||||
/* Create the defines for a RUN segment */
|
||||
{
|
||||
char Buf [256];
|
||||
StrBuf Buf = STATIC_STRBUF_INITIALIZER;
|
||||
|
||||
xsprintf (Buf, sizeof (Buf), "__%s_RUN__", GetString (S->Name));
|
||||
CreateMemoryExport (GetStringId (Buf), S->Run, SegAddr - S->Run->Start);
|
||||
xsprintf (Buf, sizeof (Buf), "__%s_SIZE__", GetString (S->Name));
|
||||
CreateConstExport (GetStringId (Buf), S->Seg->Size);
|
||||
SB_Printf (&Buf, "__%s_RUN__", GetString (S->Name));
|
||||
CreateMemoryExport (GetStrBufId (&Buf), S->Run, SegAddr - S->Run->Start);
|
||||
SB_Printf (&Buf, "__%s_SIZE__", GetString (S->Name));
|
||||
CreateConstExport (GetStrBufId (&Buf), S->Seg->Size);
|
||||
S->Flags |= SF_RUN_DEF;
|
||||
SB_Done (&Buf);
|
||||
}
|
||||
|
||||
|
||||
@ -1571,11 +1572,12 @@ static void CreateRunDefines (SegDesc* S, unsigned long SegAddr)
|
||||
static void CreateLoadDefines (SegDesc* S, unsigned long SegAddr)
|
||||
/* Create the defines for a LOAD segment */
|
||||
{
|
||||
char Buf [256];
|
||||
StrBuf Buf = STATIC_STRBUF_INITIALIZER;
|
||||
|
||||
xsprintf (Buf, sizeof (Buf), "__%s_LOAD__", GetString (S->Name));
|
||||
CreateMemoryExport (GetStringId (Buf), S->Load, SegAddr - S->Load->Start);
|
||||
SB_Printf (&Buf, "__%s_LOAD__", GetString (S->Name));
|
||||
CreateMemoryExport (GetStrBufId (&Buf), S->Load, SegAddr - S->Load->Start);
|
||||
S->Flags |= SF_LOAD_DEF;
|
||||
SB_Done (&Buf);
|
||||
}
|
||||
|
||||
|
||||
@ -1697,13 +1699,14 @@ unsigned CfgAssignSegments (void)
|
||||
|
||||
/* If requested, define symbols for start and size of the memory area */
|
||||
if (M->Flags & MF_DEFINE) {
|
||||
char Buf [256];
|
||||
sprintf (Buf, "__%s_START__", GetString (M->Name));
|
||||
CreateMemoryExport (GetStringId (Buf), M, 0);
|
||||
sprintf (Buf, "__%s_SIZE__", GetString (M->Name));
|
||||
CreateConstExport (GetStringId (Buf), M->Size);
|
||||
sprintf (Buf, "__%s_LAST__", GetString (M->Name));
|
||||
CreateMemoryExport (GetStringId (Buf), M, M->FillLevel);
|
||||
StrBuf Buf = STATIC_STRBUF_INITIALIZER;
|
||||
SB_Printf (&Buf, "__%s_START__", GetString (M->Name));
|
||||
CreateMemoryExport (GetStrBufId (&Buf), M, 0);
|
||||
SB_Printf (&Buf, "__%s_SIZE__", GetString (M->Name));
|
||||
CreateConstExport (GetStrBufId (&Buf), M->Size);
|
||||
SB_Printf (&Buf, "__%s_LAST__", GetString (M->Name));
|
||||
CreateMemoryExport (GetStrBufId (&Buf), M, M->FillLevel);
|
||||
SB_Done (&Buf);
|
||||
}
|
||||
|
||||
/* Next memory area */
|
||||
@ -1728,7 +1731,7 @@ void CfgWriteTarget (void)
|
||||
if (F->MemList) {
|
||||
|
||||
/* Is there an output file? */
|
||||
if (strlen (GetString (F->Name)) > 0) {
|
||||
if (SB_GetLen (GetStrBuf (F->Name)) > 0) {
|
||||
|
||||
/* Assign a proper binary format */
|
||||
if (F->Format == BINFMT_DEFAULT) {
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2001-2003 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 2001-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -36,9 +36,10 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
/* common */
|
||||
#include "cmdline.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
/* ld65 */
|
||||
#include "error.h"
|
||||
@ -54,12 +55,17 @@
|
||||
void Warning (const char* Format, ...)
|
||||
/* Print a warning message */
|
||||
{
|
||||
StrBuf S = STATIC_STRBUF_INITIALIZER;
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, Format);
|
||||
fprintf (stderr, "%s: Warning: ", ProgName);
|
||||
vfprintf (stderr, Format, ap);
|
||||
putc ('\n', stderr);
|
||||
SB_VPrintf (&S, Format, ap);
|
||||
va_end (ap);
|
||||
SB_Terminate (&S);
|
||||
|
||||
fprintf (stderr, "%s: Warning: %s\n", ProgName, SB_GetConstBuf (&S));
|
||||
|
||||
SB_Done (&S);
|
||||
}
|
||||
|
||||
|
||||
@ -67,12 +73,18 @@ void Warning (const char* Format, ...)
|
||||
void Error (const char* Format, ...)
|
||||
/* Print an error message and die */
|
||||
{
|
||||
StrBuf S = STATIC_STRBUF_INITIALIZER;
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, Format);
|
||||
fprintf (stderr, "%s: Error: ", ProgName);
|
||||
vfprintf (stderr, Format, ap);
|
||||
putc ('\n', stderr);
|
||||
SB_VPrintf (&S, Format, ap);
|
||||
va_end (ap);
|
||||
SB_Terminate (&S);
|
||||
|
||||
fprintf (stderr, "%s: Error: %s\n", ProgName, SB_GetConstBuf (&S));
|
||||
|
||||
SB_Done (&S);
|
||||
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@ -81,14 +93,20 @@ void Error (const char* Format, ...)
|
||||
void Internal (const char* Format, ...)
|
||||
/* Print an internal error message and die */
|
||||
{
|
||||
StrBuf S = STATIC_STRBUF_INITIALIZER;
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, Format);
|
||||
fprintf (stderr, "%s: Internal error: ", ProgName);
|
||||
vfprintf (stderr, Format, ap);
|
||||
putc ('\n', stderr);
|
||||
SB_VPrintf (&S, Format, ap);
|
||||
va_end (ap);
|
||||
SB_Terminate (&S);
|
||||
|
||||
fprintf (stderr, "%s: Internal Error: %s\n", ProgName, SB_GetConstBuf (&S));
|
||||
|
||||
SB_Done (&S);
|
||||
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2005 Ullrich von Bassewitz */
|
||||
/* Römerstraße 52 */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -620,7 +620,7 @@ static void PrintUnresolved (ExpCheckFunc F, void* Data)
|
||||
/* Unresolved external */
|
||||
Import* Imp = E->ImpList;
|
||||
fprintf (stderr,
|
||||
"Unresolved external `%s' referenced in:\n",
|
||||
"Unresolved external `%s' referenced in:\n",
|
||||
GetString (E->Name));
|
||||
while (Imp) {
|
||||
const char* Name = GetSourceFileName (Imp->Obj, Imp->Pos.Name);
|
||||
@ -636,8 +636,8 @@ static void PrintUnresolved (ExpCheckFunc F, void* Data)
|
||||
static int CmpExpName (const void* K1, const void* K2)
|
||||
/* Compare function for qsort */
|
||||
{
|
||||
return strcmp (GetString ((*(Export**)K1)->Name),
|
||||
GetString ((*(Export**)K2)->Name));
|
||||
return SB_Compare (GetStrBuf ((*(Export**)K1)->Name),
|
||||
GetStrBuf ((*(Export**)K2)->Name));
|
||||
}
|
||||
|
||||
|
||||
@ -728,7 +728,7 @@ void PrintExportMap (FILE* F)
|
||||
/* Print unreferenced symbols only if explictly requested */
|
||||
if (VerboseMap || E->ImpCount > 0 || IS_EXP_CONDES (E->Type)) {
|
||||
fprintf (F,
|
||||
"%-25s %06lX %c%c%c%c ",
|
||||
"%-25s %06lX %c%c%c%c ",
|
||||
GetString (E->Name),
|
||||
GetExportVal (E),
|
||||
E->ImpCount? 'R' : ' ',
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1999-2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 1999-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -283,34 +283,23 @@ unsigned ReadStr (FILE* F)
|
||||
*/
|
||||
{
|
||||
unsigned Id;
|
||||
char* B;
|
||||
char Buf[256];
|
||||
StrBuf Buf = STATIC_STRBUF_INITIALIZER;
|
||||
|
||||
/* Read the length */
|
||||
unsigned Len = ReadVar (F);
|
||||
|
||||
/* If the string is short enough, use our buffer on the stack, otherwise
|
||||
* allocate space on the heap.
|
||||
*/
|
||||
if (Len < sizeof (Buf)) {
|
||||
B = Buf;
|
||||
} else {
|
||||
B = xmalloc (Len + 1);
|
||||
}
|
||||
/* Expand the string buffer memory */
|
||||
SB_Realloc (&Buf, Len);
|
||||
|
||||
/* Read the string */
|
||||
ReadData (F, B, Len);
|
||||
|
||||
/* Terminate the string */
|
||||
B[Len] = '\0';
|
||||
ReadData (F, SB_GetBuf (&Buf), Len);
|
||||
Buf.Len = Len;
|
||||
|
||||
/* Insert it into the string pool and remember the id */
|
||||
Id = GetStringId (B);
|
||||
Id = GetStrBufId (&Buf);
|
||||
|
||||
/* If we had allocated memory before, free it now */
|
||||
if (B != Buf) {
|
||||
xfree (B);
|
||||
}
|
||||
/* Free the memory buffer */
|
||||
SB_Done (&Buf);
|
||||
|
||||
/* Return the string id */
|
||||
return Id;
|
||||
|
@ -6,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2000 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 1998-2008, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -95,7 +95,7 @@ void CfgWarning (const char* Format, ...)
|
||||
va_end (ap);
|
||||
|
||||
Warning ("%s(%u): %s", CfgGetName(), CfgErrorLine, SB_GetConstBuf (&Buf));
|
||||
DoneStrBuf (&Buf);
|
||||
SB_Done (&Buf);
|
||||
}
|
||||
|
||||
|
||||
@ -111,7 +111,7 @@ void CfgError (const char* Format, ...)
|
||||
va_end (ap);
|
||||
|
||||
Error ("%s(%u): %s", CfgGetName(), CfgErrorLine, SB_GetConstBuf (&Buf));
|
||||
DoneStrBuf (&Buf);
|
||||
SB_Done (&Buf);
|
||||
}
|
||||
|
||||
|
||||
|
@ -57,12 +57,12 @@ StringPool StrPool = STATIC_STRINGPOOL_INITIALIZER;
|
||||
void InitStrPool (void)
|
||||
/* Initialize the string pool */
|
||||
{
|
||||
/* We insert a first string here, which will have id zero. This means
|
||||
/* We insert a first string here, which will have id zero. This means
|
||||
* that we can treat index zero later as invalid.
|
||||
*/
|
||||
SP_Add (&StrPool, "<invalid message #0>");
|
||||
*/
|
||||
SP_AddStr (&StrPool, "<invalid message #0>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* (C) 2003-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -64,8 +64,8 @@ extern StringPool StrPool;
|
||||
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned GetStringId (const char* S)
|
||||
/* Return the id of the given string */
|
||||
INLINE unsigned GetStrBufId (const StrBuf* S)
|
||||
/* Return the id of the given string buffer */
|
||||
{
|
||||
return SP_Add (&StrPool, S);
|
||||
}
|
||||
@ -74,13 +74,33 @@ INLINE unsigned GetStringId (const char* S)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE const char* GetString (unsigned Index)
|
||||
INLINE unsigned GetStringId (const char* S)
|
||||
/* Return the id of the given string */
|
||||
{
|
||||
return SP_AddStr (&StrPool, S);
|
||||
}
|
||||
#else
|
||||
# define GetStringId(S) SP_Add (&StrPool, (S))
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE const StrBuf* GetStrBuf (unsigned Index)
|
||||
/* Convert a string index into a string */
|
||||
{
|
||||
return SP_Get (&StrPool, Index);
|
||||
}
|
||||
#else
|
||||
# define GetString(Index) SP_Get (&StrPool, (Index))
|
||||
# define GetStrBuf(Index) SP_Get (&StrPool, (Index))
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user