/* */
/* */
/* */
-/* (C) 2000-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 2000-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
#include <stdio.h>
#include <string.h>
-/* common */
-#include "xsprintf.h"
-
/* ca65 */
#include "anonname.h"
-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);
}
/* */
/* */
/* */
-/* (C) 2000-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 2000-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
+/* 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
/* */
/* */
/* */
-/* (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 */
/* */
/* */
/* 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 */
/* */
#include <string.h>
+/* common */
+#include "strbuf.h"
+
/* ca65 */
#include "error.h"
#include "expr.h"
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;
ErrorSkip ("String constant expected");
return;
}
- strcpy (Name, SVal);
+ SB_Copy (&Name, &SVal);
NextTok ();
/* Comma expected */
MTime = ConstExpression ();
/* Insert the file into the table */
- AddFile (Name, Size, MTime);
+ AddFile (&Name, Size, MTime);
+
+ /* Free memory used for Name */
+ SB_Done (&Name);
}
}
/* Get the index in the file table for the name */
- Index = GetFileIndex (SVal);
+ Index = GetFileIndex (&SVal);
/* Skip the name */
NextTok ();
/* */
/* */
/* */
-/* (C) 2003 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* (C) 2003-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
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 ();
}
}
/* 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 ();
/* */
/* */
/* */
-/* (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 */
/* */
#include <stdlib.h>
#include <stdarg.h>
+/* common */
+#include "strbuf.h"
+
/* ca65 */
+#include "error.h"
#include "filetab.h"
#include "nexttok.h"
-#include "error.h"
/* 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);
}
}
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);
}
/* 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);
}
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);
}
/* */
/* */
/* */
-/* (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 */
/* */
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. */
/* 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. */
/* */
/* */
/* */
-/* (C) 1998-2007 Ullrich von Bassewitz */
+/* (C) 1998-2008 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
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;
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 ();
}
/* 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
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);
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 */
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);
} else {
/* Get the length of the string */
- Len = strlen (SVal);
+ Len = SB_GetLen (&SVal);
/* Skip the string */
NextTok ();
break;
case TOK_LOCAL_IDENT:
- N = Symbol (SymFindLocal (SymLast, SVal, SYM_ALLOC_NEW));
+ N = Symbol (SymFindLocal (SymLast, &SVal, SYM_ALLOC_NEW));
NextTok ();
break;
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");
/* */
/* */
/* */
-/* (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 */
/* */
-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.
*/
/* 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;
}
-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.
/* */
/* */
/* */
-/* (C) 2000-2007 Ullrich von Bassewitz */
+/* (C) 2000-2008 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
+/* common */
+#include "strbuf.h"
+
+
+
/*****************************************************************************/
/* Data */
/*****************************************************************************/
-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.
/* */
/* */
/* */
-/* (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 */
/* */
-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) {
*/
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;
-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;
-
+
/* */
/* */
/* */
-/* (C) 2000-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 2000-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
+/* 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.
*/
/* */
/* */
/* */
-/* (C) 1998-2006, Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 1998-2008, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
-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.
*/
/* 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.
*/
/* 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';
/*****************************************************************************/
/* */
-/* 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 */
/* */
/* common */
#include "cpu.h"
+#include "strbuf.h"
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.
*/
+
/* */
/* */
/* */
-/* (C) 2000-2007 Ullrich von Bassewitz */
+/* (C) 2000-2008 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* 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;
/* */
/* */
/* */
-/* (C) 1998-2005, Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 1998-2008, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
-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.
*/
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;
}
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)) {
/* */
/* */
/* */
-/* (C) 1998-2005, Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 1998-2008, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
+/* common */
+#include "strbuf.h"
+
+
+
/*****************************************************************************/
/* Data */
/*****************************************************************************/
-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.
*/
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.
/* */
/* */
/* */
-/* (C) 1998-2007 Ullrich von Bassewitz */
+/* (C) 1998-2008 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
typedef struct IdDesc IdDesc;
struct IdDesc {
IdDesc* Next; /* Linked list */
- char Id [1]; /* Identifier, dynamically allocated */
+ StrBuf Id; /* Identifier, dynamically allocated */
};
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 */
static unsigned HT_GenHash (const void* Key)
/* Generate the hash over a key. */
{
- return HashStr (Key);
+ return HashBuf (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;
}
* than zero if Key1 is greater then Key2.
*/
{
- return strcmp (Key1, Key2);
+ return SB_Compare (Key1, 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;
-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);
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;
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.
*/
}
/* 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 ();
* 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) {
-
- /* 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;
+ while (Tok == TOK_IDENT) {
+
+ /* 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 (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) {
}
/* 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;
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;
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 */
/* 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 */
-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);
-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);
-
-
-
/* */
/* */
/* */
-/* (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 */
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);
/* */
/* */
/* */
-/* (C) 1998-2007, Ullrich von Bassewitz */
+/* (C) 1998-2008, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
#include "cmdline.h"
#include "mmodel.h"
#include "print.h"
+#include "strbuf.h"
#include "target.h"
#include "tgttrans.h"
#include "version.h"
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);
}
{
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)) {
/* Mark the symbol as defined */
SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_NONE);
+
+ /* Free string buffer memory */
+ SB_Done (&SymBuf);
}
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 != '=') {
}
/* Define the new symbol */
- NewSymbol (SymName, Val);
+ NewSymbol (SB_GetConstBuf (&SymName), Val);
+
+ /* Release string memory */
+ SB_Done (&SymName);
}
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);
}
}
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));
}
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);
}
}
/* 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 ();
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);
}
}
}
/* 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)) {
{ "--version", 0, OptVersion },
};
+ /* Name of the global name space */
+ static const StrBuf GlobalNameSpace = STATIC_STRBUF_INITIALIZER;
+
unsigned I;
/* Initialize the cmdline module */
/* 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;
/* */
/* */
/* */
-/* (C) 2000-2007 Ullrich von Bassewitz */
+/* (C) 2000-2008 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
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 ();
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 ();
}
}
- /* Terminate the string */
- *B = '\0';
-
/* We expect a closing parenthesis, but will not skip it but replace it
* by the string token just created.
*/
Error ("`)' expected");
} else {
Tok = TOK_STRCON;
- strcpy (SVal, Buf);
+ SB_Copy (&SVal, &Buf);
}
+
+ /* Free the string buffer */
+ SB_Done (&Buf);
}
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 */
/* 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);
}
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 */
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;
}
/* 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':
* 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 */
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 */
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 */
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);
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);
}
static void FuncString (void)
/* Handle the .STRING function */
{
- char Buf[MAX_STR_LEN+1];
+ StrBuf Buf = STATIC_STRBUF_INITIALIZER;
/* Skip it */
NextTok ();
/* 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
Error ("`)' expected");
} else {
Tok = TOK_STRCON;
- strcpy (SVal, Buf);
+ SB_Copy (&SVal, &Buf);
}
+
+ /* Free string memory */
+ SB_Done (&Buf);
}
/* */
/* */
/* */
-/* (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 */
/* */
-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);
}
+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 */
{
/* */
/* */
/* */
-/* (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 */
/* */
/* ca65 */
#include "expr.h"
+#include "strbuf.h"
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 */
+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 */
{
/* common */
#include "filepos.h"
+#include "strbuf.h"
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 */
/* */
/* */
/* */
-/* (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 */
-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));
}
+
/* */
/* */
/* */
-/* (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 */
-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);
void WriteOptions (void);
/* Write the options to the object file */
-
+
/* End of options.h */
/* */
/* */
/* */
-/* (C) 1998-2007, Ullrich von Bassewitz */
+/* (C) 1998-2008, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* 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
}
/* 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 ();
* 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 {
-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;
static void DoASCIIZ (void)
/* Define text with a zero terminator */
{
- unsigned Len;
-
while (1) {
/* Must have a string constant */
if (Tok != TOK_STRCON) {
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 ();
/* Translate the message into a string id. We can then skip the input
* string.
*/
- Msg = GetStringId (SVal);
+ Msg = GetStrBufId (&SVal);
NextTok ();
} else {
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 ());
"DESTRUCTOR",
"INTERRUPTOR",
};
- char Name [sizeof (SVal)];
+ StrBuf Name = STATIC_STRBUF_INITIALIZER;
long Type;
/* Symbol name follows */
ErrorSkip ("Identifier expected");
return;
}
- strcpy (Name, SVal);
+ SB_Copy (&Name, &SVal);
NextTok ();
/* Type follows. May be encoded as identifier or numerical */
/* Check if we got a valid keyword */
if (Type < 0) {
- Error ("Syntax error");
- SkipUntilSep ();
- return;
+ ErrorSkip ("Syntax error");
+ goto ExitPoint;
}
} else {
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);
}
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);
}
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);
}
if (Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
- Error ("User error: %s", SVal);
+ Error ("User error: %m%p", &SVal);
SkipUntilSep ();
}
}
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 */
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:
}
/* Insert the option */
- OptStr ((unsigned char) OptNum, SVal);
+ OptStr ((unsigned char) OptNum, &SVal);
/* Done */
NextTok ();
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;
ErrorSkip ("String constant expected");
return;
}
- strcpy (Name, SVal);
+ SB_Copy (&Name, &SVal);
+ SB_Terminate (&Name);
NextTok ();
/* A starting offset may follow */
}
/* 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 */
/* If we had an error before, bail out now */
if (F == 0) {
- return;
+ goto ExitPoint;
}
}
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;
}
Done:
/* Close the file, ignore errors since it's r/o */
(void) fclose (F);
+
+ExitPoint:
+ /* Free string memory */
+ SB_Done (&Name);
}
/* Name must follow */
if (Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
- } else {
- NewInputFile (SVal);
+ } else {
+ SB_Terminate (&SVal);
+ NewInputFile (SB_GetConstBuf (&SVal));
}
}
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);
}
* an error in the assembler itself, while DoInvalid is.
*/
{
- Internal ("Unexpected token: %s", Keyword);
+ Internal ("Unexpected token: %m%p", &Keyword);
}
}
/* Search for the macro package name */
- Package = MacPackFind (SVal);
+ LocaseSVal ();
+ Package = MacPackFind (&SVal);
if (Package < 0) {
/* Not found */
ErrorSkip ("Invalid macro package");
/* 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 ();
}
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) {
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 ();
/* 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);
}
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");
}
AddrSize = OptionalAddrSize ();
/* Enter the new scope */
- SymEnterLevel (Name, ST_SCOPE, AddrSize);
+ SymEnterLevel (&Name, ST_SCOPE, AddrSize);
+ /* Free memory for Name */
+ SB_Done (&Name);
}
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);
}
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);
static void DoUnexpected (void)
/* Got an unexpected keyword */
{
- Error ("Unexpected `%s'", Keyword);
+ Error ("Unexpected `%m%p'", &Keyword);
SkipUntilSep ();
}
if (Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
- Warning (0, "User warning: %s", SVal);
+ Warning (0, "User warning: %m%p", &SVal);
SkipUntilSep ();
}
}
/* Remember the instruction, then skip it if needed */
if ((D->Flags & ccKeepToken) == 0) {
- strcpy (Keyword, SVal);
+ SB_Copy (&Keyword, &SVal);
NextTok ();
}
/* */
/* */
/* */
-/* (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 */
/* */
/* */
/* */
/* */
-/* (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 */
* 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;
ErrorSkip ("Identifier expected");
} else {
/* Remember the name and skip it */
- Name = xstrdup (SVal);
+ SB_Terminate (&SVal);
+ Name = xstrdup (SB_GetConstBuf (&SVal));
NextTok ();
}
}
/* */
/* */
/* */
-/* (C) 1998-2007 Ullrich von Bassewitz */
+/* (C) 1998-2008 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
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 */
/* check again if we do now have an open file */
if (F != 0) {
+ StrBuf NameBuf;
unsigned FileIdx;
CharSource* S;
}
/* 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));
void LocaseSVal (void)
/* Make SVal lower case */
{
- unsigned I = 0;
- while (SVal [I]) {
- SVal [I] = tolower (SVal [I]);
- ++I;
- }
+ SB_ToLower (&SVal);
}
void UpcaseSVal (void)
/* Make SVal upper case */
{
- unsigned I = 0;
- while (SVal [I]) {
- SVal [I] = toupper (SVal [I]);
- ++I;
- }
+ SB_ToUpper (&SVal);
}
* 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 */
-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) {
-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;
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 ();
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.
*/
unsigned RegNum;
char Check;
- if (Ident[0] != 'r' && Ident[0] != 'R') {
+ if (SB_GetLen (Id) < 2) {
+ return -1;
+ }
+ if (toupper (SB_AtUnchecked (Id, 0)) != 'R') {
return -1;
}
- if (!IsDigit (Ident[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;
}
/* 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 ();
} else {
/* Read the remainder of the identifier */
- SVal[0] = '.';
- ReadIdent (1);
+ SB_AppendChar (&SVal, '.');
+ ReadIdent ();
/* Dot keyword, search for it */
Tok = FindDotKeyword ();
/* 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;
/* 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;
}
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 == ':') {
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;
}
/* Check for define style macro */
- if (IsDefine (SVal)) {
+ if (IsDefine (&SVal)) {
/* Macro - expand it */
MacExpandStart ();
goto Restart;
* 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;
case '\\':
/* Line continuation? */
if (LineCont) {
- NextChar ();
- if (C == '\n') {
+ NextChar ();
+ if (C == '\n') {
/* Handle as white space */
NextChar ();
C = ' ';
/* 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;
}
/* common */
#include "filepos.h"
+#include "strbuf.h"
/* ca65 */
#include "token.h"
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 */
-
+
/* */
/* */
/* */
-/* (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 */
/* 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 */
/*****************************************************************************/
* 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);
}
* does not exist.
*/
{
- return SymFindLocal (Sym, SizeEntryName, SYM_ALLOC_NEW);
+ return SymFindLocal (Sym, &SizeEntryName, SYM_ALLOC_NEW);
}
/* */
/* */
/* */
-/* (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 */
#ifndef SIZEOF_H
#define SIZEOF_H
+
+
+
+/* common */
+#include "strbuf.h"
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+extern const StrBuf SizeEntryName; /* Contains name of symbol with size */
+
+
+
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void WriteStrPool (void)
/* Write the string pool to the object file */
-{
+{
unsigned I;
/* Get the number of strings in the string pool */
/* 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 */
+#if defined(HAVE_INLINE)
+INLINE unsigned GetStrBufId (const StrBuf* S)
+/* Return the id of the given string buffer */
+{
+ return SP_Add (&StrPool, S);
+}
+#else
+# define GetStringId(S) SP_Add (&StrPool, (S))
+#endif
+
#if defined(HAVE_INLINE)
INLINE unsigned GetStringId (const char* S)
/* Return the id of the given string */
{
- return SP_Add (&StrPool, S);
+ return SP_AddStr (&StrPool, S);
}
#else
# define GetStringId(S) SP_Add (&StrPool, (S))
#endif
#if defined(HAVE_INLINE)
-INLINE const char* GetString (unsigned Index)
+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);
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;
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);
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;
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 {
/* */
/* */
/* */
-/* (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 */
/* */
-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) {
} 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.
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;
}
/* 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. */
/* 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
*/
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 ();
}
}
* 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.
* 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
* 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;
}
* 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
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;
}
/* */
/* */
/* */
-/* (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 */
/* */
-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);
/* */
/* 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 */
-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;
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;
-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,
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) {
{
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
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));
}
/* 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;
}
*/
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));
}
}
/* 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;
}
*/
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;
}
*/
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;
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));
}
{
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;
}
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;
}
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;
*/
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;
}
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));
}
/* 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;
}
*/
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;
}
/* 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));
}
}
*/
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;
/* */
/* */
/* */
-/* (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 */
/* */
#include "coll.h"
#include "filepos.h"
#include "inline.h"
+#include "strbuf.h"
/* ca65 */
#include "spool.h"
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 */
};
-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,
*/
#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)
/* */
/* */
/* */
-/* (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 */
/* */
-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 */
S->TableSlots = Slots;
S->TableEntries = 0;
S->Parent = Parent;
- S->Name = GetStringId (Name);
+ S->Name = GetStrBufId (Name);
while (Slots--) {
S->Table[Slots] = 0;
}
} 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;
}
} else {
/* Duplicate scope name */
- Internal ("Duplicate scope name: `%s'", Name);
+ Internal ("Duplicate scope name: `%m%p'", 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 */
/* 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 {
-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) {
-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* 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.
-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* 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);
-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.
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.
/* 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 {
}
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));
}
}
/* 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 */
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));
}
}
}
/* 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));
}
}
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++;
} 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));
}
}
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));
}
/* 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" : "---",
+
+
/* */
/* */
/* */
-/* (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 */
/* */
-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.
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);
}
/* */
/* */
/* */
-/* (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 */
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;
void FreeTokNode (TokNode* T)
/* Free the given token node */
{
+ SB_Done (&T->SVal);
xfree (T);
}
Tok = T->Tok;
WS = T->WS;
IVal = T->IVal;
- strcpy (SVal, T->SVal);
+ SB_Copy (&SVal, &T->SVal);
}
/* 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)) {
/* */
/* */
/* */
-/* (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 */
+/* common */
+#include "strbuf.h"
+
+/* ca65 */
#include "scanner.h"
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 */
/* */
/* */
/* */
-/* (C) 2001-2004 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 2001-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@musoftware.de */
/* */
Done:
/* Call the string buf destructors */
- DoneStrBuf (&S);
- DoneStrBuf (&T);
+ SB_Done (&S);
+ SB_Done (&T);
}
/* */
/* */
/* */
-/* (C) 2001-2006, Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 2001-2008, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
}
/* Cleanup the string buffer */
- DoneStrBuf (&Buf);
+ SB_Done (&Buf);
}
/* */
/* */
/* */
-/* (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 */
/* */
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);
xfree (CollAtUnchecked (&M->FormalArgs, I));
}
DoneCollection (&M->FormalArgs);
- DoneStrBuf (&M->Replacement);
+ SB_Done (&M->Replacement);
xfree (M);
}
/* */
/* */
/* */
-/* (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 */
/* */
}
/* Call the string buf destructor */
- DoneStrBuf (&S);
+ SB_Done (&S);
}
g_segname (Seg);
/* Call the string buf destructor */
- DoneStrBuf (&S);
+ SB_Done (&S);
}
FlagPragma (&B, &WarnDisable);
break;
- case PR_ZPSYM:
+ case PR_ZPSYM:
StringPragma (&B, MakeZPSym);
break;
}
/* Release the StrBuf */
- DoneStrBuf (&B);
+ SB_Done (&B);
}
/* */
/* */
/* */
-/* (C) 1998-2007, Ullrich von Bassewitz */
+/* (C) 1998-2008, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* Initialize a MacroExp structure */
{
InitCollection (&E->ActualArgs);
- InitStrBuf (&E->Replacement);
+ SB_Init (&E->Replacement);
E->M = M;
return E;
}
FreeStrBuf (CollAtUnchecked (&E->ActualArgs, I));
}
DoneCollection (&E->ActualArgs);
- DoneStrBuf (&E->Replacement);
+ SB_Done (&E->Replacement);
}
}
/* Deallocate string buf resources */
- DoneStrBuf (&Arg);
+ SB_Done (&Arg);
}
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)
/* */
/* */
/* */
-/* (C) 1998-2004 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 1998-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
{
unsigned Base; /* Temporary number base */
unsigned Prefix; /* Base according to prefix */
- StrBuf S;
+ StrBuf S = STATIC_STRBUF_INITIALIZER;
int IsFloat;
char C;
unsigned DigitVal;
* 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 ();
}
/* We don't need the string buffer any longer */
- DoneStrBuf (&S);
+ SB_Done (&S);
/* Distinguish between integer and floating point constants */
if (!IsFloat) {
/* */
/* */
/* */
-/* (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 */
+/* common */
+#include "hashstr.h"
+
+
+
/*****************************************************************************/
/* Code */
/*****************************************************************************/
+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;
+}
+
+
+
/*****************************************************************************/
/* */
-/* 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 */
+/* common */
#include "attrib.h"
+#include "strbuf.h"
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 */
/* */
/* */
/* */
-/* (C) 2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 2003-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
#define InitHashNode(N, E) \
(N)->Next = 0, \
(N)->Owner = 0, \
- (N)->Entry = (E)
+ (N)->Entry = (E)
#endif
#if defined(HAVE_INLINE)
/* */
/* */
/* */
-/* (C) 2000-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 2000-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
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;
}
}
/* Not found */
- DoneStrBuf (&PathName);
+ SB_Done (&PathName);
return 0;
}
-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);
+ }
}
StrBuf* B = xmalloc (sizeof (StrBuf));
/* Initialize the struct... */
- InitStrBuf (B);
+ SB_Init (B);
/* ...and return it */
return B;
void FreeStrBuf (StrBuf* B)
/* Free a string buffer */
{
- DoneStrBuf (B);
+ SB_Done (B);
xfree (B);
}
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;
}
/* 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;
*/
{
/* Free the target string */
- if (Target->Buf) {
+ if (Target->Allocated) {
xfree (Target->Buf);
}
*Target = *Source;
/* Clear Source */
- InitStrBuf (Source);
+ SB_Init (Source);
}
+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
/* 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);
}
/*****************************************************************************/
-/* 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;
/* 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);
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
/* */
/* */
/* */
-/* (C) 2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 2003-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* 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.
*/
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 */
};
-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;
/* 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);
-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]));
/* 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;
}
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;
+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;
+}
+
+
+
/* */
/* */
/* */
-/* (C) 2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 2003-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* common */
+#include "attrib.h"
#include "coll.h"
#include "inline.h"
#include "strbuf.h"
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.
*/
/* */
/* */
/* */
-/* (C) 2000-2004 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 2000-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
#include <string.h>
+/* common */
#include "abend.h"
#include "check.h"
#include "target.h"
+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 */
{
/* */
/* */
/* */
-/* (C) 2000-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 2000-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
#ifndef TGTTRANS_H
-#define TGTTRANS_H
+#define TGTTRANS_H
+
+
+
+/* common */
+#include "strbuf.h"
* 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 */
/* */
/* */
/* */
-/* (C) 2005 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 2005-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
}
/* Delete the string buffer contents */
- DoneStrBuf (&Ident);
+ SB_Done (&Ident);
/* Close the include file ignoring errors (we were just reading). */
(void) fclose (F);
/* */
/* */
/* */
-/* (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 */
/* */
/* */
/* */
-/* (C) 1999-2005 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 1999-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
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 */
};
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);
+
/* */
/* */
/* */
-/* (C) 2005, Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 2005-2008, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
{
/* If the type is a string, we must delete the string buffer */
if (E->Type == ceString) {
- DoneStrBuf (&E->SVal);
+ SB_Done (&E->SVal);
}
}
/* */
/* */
/* */
-/* (C) 2000-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 2000-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
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 */
/* */
/* */
/* */
-/* (C) 1998-2005 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 1998-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
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));
}
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);
}
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);
}
/* 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 */
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) {
/* */
/* */
/* */
-/* (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 */
/* */
/* */
/* */
/* */
-/* (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 */
/* */
/* */
/* */
/* */
-/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 1998-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
-
+
/* common */
#include "cmdline.h"
+#include "strbuf.h"
/* ld65 */
#include "error.h"
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);
}
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);
}
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);
}
-
+
/* */
/* */
/* */
-/* (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 */
/* */
/* 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);
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));
}
/* 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' : ' ',
/* */
/* */
/* */
-/* (C) 1999-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 1999-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* */
/* */
-/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 1998-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
*/
{
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;
/* */
/* */
/* */
-/* (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 */
va_end (ap);
Warning ("%s(%u): %s", CfgGetName(), CfgErrorLine, SB_GetConstBuf (&Buf));
- DoneStrBuf (&Buf);
+ SB_Done (&Buf);
}
va_end (ap);
Error ("%s(%u): %s", CfgGetName(), CfgErrorLine, SB_GetConstBuf (&Buf));
- DoneStrBuf (&Buf);
+ SB_Done (&Buf);
}
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>");
}
-
+
/* */
/* */
/* */
-/* (C) 2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 2003-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
+#if defined(HAVE_INLINE)
+INLINE unsigned GetStrBufId (const StrBuf* S)
+/* Return the id of the given string buffer */
+{
+ return SP_Add (&StrPool, S);
+}
+#else
+# define GetStringId(S) SP_Add (&StrPool, (S))
+#endif
+
#if defined(HAVE_INLINE)
INLINE unsigned GetStringId (const char* S)
/* Return the id of the given string */
{
- return SP_Add (&StrPool, S);
+ return SP_AddStr (&StrPool, S);
}
#else
# define GetStringId(S) SP_Add (&StrPool, (S))
#endif
#if defined(HAVE_INLINE)
-INLINE const char* GetString (unsigned Index)
+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);