/* */
/* */
/* */
-/* (C) 1998-2004 Ullrich von Bassewitz */
-/* Römerstraße 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (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 */
/* 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
+static void ExportWithAssign (SymEntry* Sym, unsigned char AddrSize, unsigned Flags)
+/* Allow to assign the value of an export in an .export statement */
+{
+ /* The name and optional address size spec may be followed by an assignment
+ * or equal token.
+ */
+ if (Tok == TOK_ASSIGN || Tok == TOK_EQ) {
+
+ /* Assignment means the symbol is a label */
+ if (Tok == TOK_ASSIGN) {
+ Flags |= SF_LABEL;
+ }
+
+ /* Skip the assignment token */
+ NextTok ();
+
+ /* Define the symbol with the expression following the '=' */
+ SymDef (Sym, Expression(), ADDR_SIZE_DEFAULT, Flags);
+
+ }
+
+ /* Now export the symbol */
+ SymExport (Sym, AddrSize, Flags);
+}
+
+
+
static void ExportImport (void (*Func) (SymEntry*, unsigned char, unsigned),
unsigned char DefAddrSize, unsigned Flags)
/* Export or import symbols */
}
/* 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 ();
"ERROR"
};
- int Action;
-
+ int Action;
+ unsigned Msg;
/* First we have the expression that has to evaluated */
ExprNode* Expr = Expression ();
Error ("Illegal assert action specifier");
}
NextTok ();
- ConsumeComma ();
- /* Read the message */
- if (Tok != TOK_STRCON) {
- ErrorSkip ("String constant expected");
- } else {
- AddAssertion (Expr, Action, GetStringId (SVal));
+ /* We can have an optional message. If no message is present, use
+ * "Assertion failed".
+ */
+ if (Tok == TOK_COMMA) {
+
+ /* Skip the comma */
+ NextTok ();
+
+ /* Read the message */
+ if (Tok != TOK_STRCON) {
+ ErrorSkip ("String constant expected");
+ return;
+ }
+
+ /* Translate the message into a string id. We can then skip the input
+ * string.
+ */
+ Msg = GetStrBufId (&SVal);
NextTok ();
+
+ } else {
+
+ /* Use "Assertion failed" */
+ Msg = GetStringId ("Assertion failed");
+
}
+
+ /* Remember the assertion */
+ AddAssertion (Expr, Action, Msg);
}
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 ());
}
- if (Tok != TOK_COMMA) {
+ if (Tok != TOK_COMMA) {
break;
} else {
NextTok ();
/* Read the index as numerical value */
Index = ConstExpression ();
- if (Index < 1 || Index > 255) {
+ if (Index < 0 || Index > 255) {
/* Value out of range */
ErrorSkip ("Range error");
return;
/* Read the character code */
Code = ConstExpression ();
- if (Code < 1 || Code > 255) {
- /* Value out of range */
+ if (Code < 0 || Code > 255) {
+ /* Value out of range */
ErrorSkip ("Range error");
- return;
+ return;
}
/* Set the character translation */
"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 ();
}
}
static void DoExport (void)
/* Export a symbol */
{
- ExportImport (SymExport, ADDR_SIZE_DEFAULT, SF_NONE);
+ ExportImport (ExportWithAssign, ADDR_SIZE_DEFAULT, SF_NONE);
}
static void DoExportZP (void)
/* Export a zeropage symbol */
{
- ExportImport (SymExport, ADDR_SIZE_ZP, SF_NONE);
+ ExportImport (ExportWithAssign, ADDR_SIZE_ZP, SF_NONE);
}
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);
}
static void DoInclude (void)
/* Include another file */
{
- char Name [MAX_STR_LEN+1];
-
/* Name must follow */
if (Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
- strcpy (Name, SVal);
- NextTok ();
- NewInputFile (Name);
+ 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);
}
static void DoMacPack (void)
/* Insert a macro package */
{
- /* Macro package names */
- static const char* Keys [] = {
- "GENERIC",
- "LONGBRANCH",
- "CBM",
- "CPU"
- };
-
int Package;
/* We expect an identifier */
return;
}
- /* Map the keyword to a number */
- Package = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
+ /* Search for the macro package name */
+ LocaseSVal ();
+ Package = MacPackFind (&SVal);
if (Package < 0) {
/* Not found */
ErrorSkip ("Invalid macro package");
return;
}
- /* Skip the package name */
- NextTok ();
-
/* Insert the package */
- InsertMacPack (Package);
+ MacPackInsert (Package);
}
Error ("Range error");
return;
}
- SetAbsPC (PC);
+ EnterAbsoluteMode (PC);
}
/* 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 DoReloc (void)
/* Enter relocatable mode */
{
- RelocMode = 1;
+ EnterRelocMode ();
}
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);
}
if (Tok != TOK_STRCON) {
ErrorSkip ("String constant expected");
} else {
+ cpu_t CPU;
+
/* Try to find the CPU */
- cpu_t CPU = FindCPU (SVal);
+ SB_Terminate (&SVal);
+ 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 ();
}
}
{ ccNone, DoUnexpected }, /* .HIWORD */
{ ccNone, DoI16 },
{ ccNone, DoI8 },
+ { ccNone, DoUnexpected }, /* .IDENT */
{ ccKeepToken, DoConditionals }, /* .IF */
{ ccKeepToken, DoConditionals }, /* .IFBLANK */
{ ccKeepToken, DoConditionals }, /* .IFCONST */
{ ccNone, DoROData },
{ ccNone, DoScope },
{ ccNone, DoSegment },
+ { ccNone, DoUnexpected }, /* .SET */
{ ccNone, DoSetCPU },
{ ccNone, DoUnexpected }, /* .SIZEOF */
{ ccNone, DoSmart },
+ { ccNone, DoUnexpected }, /* .SPRINTF */
{ ccNone, DoUnexpected }, /* .STRAT */
{ ccNone, DoUnexpected }, /* .STRING */
{ ccNone, DoUnexpected }, /* .STRLEN */
/* Remember the instruction, then skip it if needed */
if ((D->Flags & ccKeepToken) == 0) {
- strcpy (Keyword, SVal);
+ SB_Copy (&Keyword, &SVal);
NextTok ();
}