]> git.sur5r.net Git - cc65/blobdiff - src/ca65/pseudo.c
More fixes for Watcom C / C89.
[cc65] / src / ca65 / pseudo.c
index 4d6d945cb7be0868d0e1d7b5609252b1891a0f49..0c9a2fa111eaf443def235a7945755e94c427af4 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2003 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       */
@@ -53,6 +53,7 @@
 #include "asserts.h"
 #include "condasm.h"
 #include "dbginfo.h"
+#include "enum.h"
 #include "error.h"
 #include "expr.h"
 #include "feature.h"
 #include "pseudo.h"
 #include "repeat.h"
 #include "segment.h"
+#include "sizeof.h"
 #include "spool.h"
+#include "struct.h"
+#include "symbol.h"
 #include "symtab.h"
 
 
@@ -80,7 +84,7 @@
 
 
 /* Keyword we're about to handle */
-static char Keyword [sizeof (SVal)+1] = ".";
+static StrBuf Keyword = STATIC_STRBUF_INITIALIZER;
 
 /* Segment stack */
 #define MAX_PUSHED_SEGMENTS     16
@@ -161,6 +165,33 @@ static void SetBoolOption (unsigned char* Flag)
 
 
 
+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 */
@@ -177,7 +208,7 @@ static void ExportImport (void (*Func) (SymEntry*, unsigned char, unsigned),
        }
 
         /* Find the symbol table entry, allocate a new one if necessary */
-        Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW);
+        Sym = SymFind (CurrentScope, &SVal, SYM_ALLOC_NEW);
 
         /* Skip the name */
         NextTok ();
@@ -207,7 +238,7 @@ static long IntArg (long Min, long Max)
  * and return -1 in this case.
  */
 {
-    if (Tok == TOK_IDENT && strcmp (SVal, "unlimited") == 0) {
+    if (Tok == TOK_IDENT && SB_CompareStr (&SVal, "unlimited") == 0) {
        NextTok ();
        return -1;
     } else {
@@ -222,7 +253,7 @@ static long IntArg (long Min, long Max)
 
 
 
-static void ConDes (const char* Name, unsigned Type)
+static void ConDes (const StrBuf* Name, unsigned Type)
 /* Parse remaining line for constructor/destructor of the remaining type */
 {
     long Prio;
@@ -265,7 +296,7 @@ static void DoA16 (void)
        Error ("Command is only valid in 65816 mode");
     } else {
                /* Immidiate mode has two extension bytes */
-       ExtBytes [AMI_IMM_ACCU] = 2;
+       ExtBytes [AM65I_IMM_ACCU] = 2;
     }
 }
 
@@ -278,7 +309,7 @@ static void DoA8 (void)
        Error ("Command is only valid in 65816 mode");
     } else {
        /* Immidiate mode has one extension byte */
-       ExtBytes [AMI_IMM_ACCU] = 1;
+       ExtBytes [AM65I_IMM_ACCU] = 1;
     }
 }
 
@@ -345,8 +376,6 @@ static void DoAlign (void)
 static void DoASCIIZ (void)
 /* Define text with a zero terminator */
 {
-    unsigned Len;
-
     while (1) {
        /* Must have a string constant */
        if (Tok != TOK_STRCON) {
@@ -354,12 +383,9 @@ static void DoASCIIZ (void)
            return;
        }
 
-       /* Get the length of the string constant */
-       Len = strlen (SVal);
-
        /* Translate into target charset and emit */
-       TgtTranslateBuf (SVal, Len);
-               EmitData ((unsigned char*) SVal, Len);
+               TgtTranslateStrBuf (&SVal);
+               EmitStrBuf (&SVal);
        NextTok ();
        if (Tok == TOK_COMMA) {
            NextTok ();
@@ -380,8 +406,8 @@ static void DoAssert (void)
         "ERROR"
     };
 
-    int Action;
-
+    int      Action;
+    unsigned Msg;
 
     /* First we have the expression that has to evaluated */
     ExprNode* Expr = Expression ();
@@ -410,15 +436,36 @@ static void DoAssert (void)
             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);
 }
 
 
@@ -445,14 +492,13 @@ static void DoByte (void)
     while (1) {
        if (Tok == TOK_STRCON) {
            /* A string, translate into target charset and emit */
-           unsigned Len = strlen (SVal);
-           TgtTranslateBuf (SVal, Len);
-           EmitData ((unsigned char*) SVal, Len);
+                   TgtTranslateStrBuf (&SVal);
+           EmitStrBuf (&SVal);
            NextTok ();
        } else {
            EmitByte (Expression ());
        }
-       if (Tok != TOK_COMMA) {
+       if (Tok != TOK_COMMA) {
            break;
        } else {
            NextTok ();
@@ -484,7 +530,7 @@ static void DoCharMap (void)
 
     /* 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;
@@ -495,10 +541,10 @@ static void DoCharMap (void)
 
     /* 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 */
@@ -521,8 +567,9 @@ static void DoConDes (void)
     static const char* Keys[] = {
                "CONSTRUCTOR",
        "DESTRUCTOR",
+        "INTERRUPTOR",
     };
-    char Name [sizeof (SVal)];
+    StrBuf Name = STATIC_STRBUF_INITIALIZER;
     long Type;
 
     /* Symbol name follows */
@@ -530,7 +577,7 @@ static void DoConDes (void)
        ErrorSkip ("Identifier expected");
        return;
     }
-    strcpy (Name, SVal);
+    SB_Copy (&Name, &SVal);
     NextTok ();
 
     /* Type follows. May be encoded as identifier or numerical */
@@ -543,9 +590,8 @@ static void DoConDes (void)
 
        /* Check if we got a valid keyword */
        if (Type < 0) {
-           Error ("Syntax error");
-           SkipUntilSep ();
-           return;
+                   ErrorSkip ("Syntax error");
+           goto ExitPoint;
        }
 
     } else {
@@ -554,14 +600,18 @@ static void DoConDes (void)
                Type = ConstExpression ();
        if (Type < CD_TYPE_MIN || Type > CD_TYPE_MAX) {
            /* Value out of range */
-           Error ("Range error");
-           return;
+                   ErrorSkip ("Range error");
+           goto ExitPoint;
        }
 
     }
 
     /* Parse the remainder of the line and export the symbol */
-    ConDes (Name, (unsigned) Type);
+    ConDes (&Name, (unsigned) Type);
+
+ExitPoint:
+    /* Free string memory */
+    SB_Done (&Name);
 }
 
 
@@ -569,18 +619,21 @@ static void DoConDes (void)
 static void DoConstructor (void)
 /* Export a symbol as constructor */
 {
-    char Name [sizeof (SVal)];
+    StrBuf Name = STATIC_STRBUF_INITIALIZER;
 
     /* Symbol name follows */
     if (Tok != TOK_IDENT) {
        ErrorSkip ("Identifier expected");
        return;
     }
-    strcpy (Name, SVal);
+    SB_Copy (&Name, &SVal);
     NextTok ();
 
     /* Parse the remainder of the line and export the symbol */
-    ConDes (Name, CD_TYPE_CON);
+    ConDes (&Name, CD_TYPE_CON);
+
+    /* Free string memory */
+    SB_Done (&Name);
 }
 
 
@@ -661,18 +714,21 @@ static void DoDefine (void)
 static void DoDestructor (void)
 /* Export a symbol as destructor */
 {
-    char Name [sizeof (SVal)];
+    StrBuf Name = STATIC_STRBUF_INITIALIZER;
 
     /* Symbol name follows */
     if (Tok != TOK_IDENT) {
        ErrorSkip ("Identifier expected");
        return;
     }
-    strcpy (Name, SVal);
+    SB_Copy (&Name, &SVal);
     NextTok ();
 
     /* Parse the remainder of the line and export the symbol */
-    ConDes (Name, CD_TYPE_DES);
+    ConDes (&Name, CD_TYPE_DES);
+
+    /* Free string memory */
+    SB_Done (&Name);
 }
 
 
@@ -704,7 +760,7 @@ static void DoEnd (void)
 static void DoEndProc (void)
 /* Leave a lexical level */
 {
-    if (CurrentScope == RootScope || GetCurrentSymTabType () != ST_PROC) {
+    if (GetCurrentSymTabType () != ST_PROC) {
         /* No local scope */
         ErrorSkip ("No open .PROC");
     } else {
@@ -717,7 +773,7 @@ static void DoEndProc (void)
 static void DoEndScope (void)
 /* Leave a lexical level */
 {
-    if (CurrentScope == RootScope || GetCurrentSymTabType () != ST_SCOPE) {
+    if ( GetCurrentSymTabType () != ST_SCOPE) {
         /* No local scope */
         ErrorSkip ("No open .SCOPE");
     } else {
@@ -733,7 +789,7 @@ static void DoError (void)
     if (Tok != TOK_STRCON) {
        ErrorSkip ("String constant expected");
     } else {
-               Error ("User error: %s", SVal);
+               Error ("User error: %m%p", &SVal);
        SkipUntilSep ();
     }
 }
@@ -756,7 +812,7 @@ static void DoExitMacro (void)
 static void DoExport (void)
 /* Export a symbol */
 {
-    ExportImport (SymExport, ADDR_SIZE_DEFAULT, SF_NONE);
+    ExportImport (ExportWithAssign, ADDR_SIZE_DEFAULT, SF_NONE);
 }
 
 
@@ -764,7 +820,7 @@ static void DoExport (void)
 static void DoExportZP (void)
 /* Export a zeropage symbol */
 {
-    ExportImport (SymExport, ADDR_SIZE_ZP, SF_NONE);
+    ExportImport (ExportWithAssign, ADDR_SIZE_ZP, SF_NONE);
 }
 
 
@@ -800,9 +856,9 @@ static void DoFeature (void)
        LocaseSVal ();
 
        /* Set the feature and check for errors */
-       if (SetFeature (SVal) == FEAT_UNKNOWN) {
+       if (SetFeature (&SVal) == FEAT_UNKNOWN) {
            /* Not found */
-           ErrorSkip ("Invalid feature: `%s'", SVal);
+           ErrorSkip ("Invalid feature: `%m%p'", &SVal);
            return;
        } else {
            /* Skip the keyword */
@@ -858,17 +914,17 @@ static void DoFileOpt (void)
 
            case 0:
                /* Author */
-               OptAuthor (SVal);
+               OptAuthor (&SVal);
                break;
 
            case 1:
                /* Comment */
-               OptComment (SVal);
+               OptComment (&SVal);
                break;
 
            case 2:
                /* Compiler */
-               OptCompiler (SVal);
+               OptCompiler (&SVal);
                break;
 
            default:
@@ -898,7 +954,7 @@ static void DoFileOpt (void)
        }
 
        /* Insert the option */
-       OptStr ((unsigned char) OptNum, SVal);
+       OptStr ((unsigned char) OptNum, &SVal);
 
        /* Done */
        NextTok ();
@@ -938,7 +994,7 @@ static void DoI16 (void)
        Error ("Command is only valid in 65816 mode");
     } else {
                /* Immidiate mode has two extension bytes */
-       ExtBytes [AMI_IMM_INDEX] = 2;
+       ExtBytes [AM65I_IMM_INDEX] = 2;
     }
 }
 
@@ -951,7 +1007,7 @@ static void DoI8 (void)
        Error ("Command is only valid in 65816 mode");
     } else {
        /* Immidiate mode has one extension byte */
-       ExtBytes [AMI_IMM_INDEX] = 1;
+       ExtBytes [AM65I_IMM_INDEX] = 1;
     }
 }
 
@@ -976,7 +1032,7 @@ static void DoImportZP (void)
 static void DoIncBin (void)
 /* Include a binary file */
 {
-    char Name [sizeof (SVal)];
+    StrBuf Name = STATIC_STRBUF_INITIALIZER;
     long Start = 0L;
     long Count = -1L;
     long Size;
@@ -987,7 +1043,8 @@ static void DoIncBin (void)
        ErrorSkip ("String constant expected");
        return;
     }
-    strcpy (Name, SVal);
+    SB_Copy (&Name, &SVal);
+    SB_Terminate (&Name);
     NextTok ();
 
     /* A starting offset may follow */
@@ -1004,14 +1061,14 @@ static void DoIncBin (void)
     }
 
     /* Try to open the file */
-    F = fopen (Name, "rb");
+    F = fopen (SB_GetConstBuf (&Name), "rb");
     if (F == 0) {
 
                /* Search for the file in the include directories. */
-       char* PathName = FindInclude (Name);
+       char* PathName = FindInclude (SB_GetConstBuf (&Name));
                if (PathName == 0 || (F = fopen (PathName, "r")) == 0) {
            /* Not found or cannot open, print an error and bail out */
-                   ErrorSkip ("Cannot open include file `%s': %s", Name, strerror (errno));
+                   ErrorSkip ("Cannot open include file `%m%p': %s", &Name, strerror (errno));
        }
 
        /* Free the allocated memory */
@@ -1019,7 +1076,7 @@ static void DoIncBin (void)
 
         /* If we had an error before, bail out now */
         if (F == 0) {
-            return;
+            goto ExitPoint;
         }
     }
 
@@ -1058,8 +1115,8 @@ static void DoIncBin (void)
        size_t BytesRead = fread (Buf, 1, BytesToRead, F);
        if (BytesToRead != BytesRead) {
            /* Some sort of error */
-           ErrorSkip ("Cannot read from include file `%s': %s",
-                       Name, strerror (errno));
+           ErrorSkip ("Cannot read from include file `%m%p': %s",
+                       &Name, strerror (errno));
            break;
        }
 
@@ -1073,6 +1130,10 @@ static void DoIncBin (void)
 Done:
     /* Close the file, ignore errors since it's r/o */
     (void) fclose (F);
+
+ExitPoint:
+    /* Free string memory */
+    SB_Done (&Name);
 }
 
 
@@ -1080,20 +1141,39 @@ Done:
 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 */
+{
+    StrBuf Name = STATIC_STRBUF_INITIALIZER;
+
+    /* Symbol name follows */
+    if (Tok != TOK_IDENT) {
+       ErrorSkip ("Identifier expected");
+       return;
+    }
+    SB_Copy (&Name, &SVal);
+    NextTok ();
+
+    /* Parse the remainder of the line and export the symbol */
+    ConDes (&Name, CD_TYPE_INT);
+
+    /* Free string memory */
+    SB_Done (&Name);
+}
+
+
+
 static void DoInvalid (void)
 /* Handle a token that is invalid here, since it should have been handled on
  * a much lower level of the expression hierarchy. Getting this sort of token
@@ -1103,7 +1183,7 @@ static void DoInvalid (void)
  * an error in the assembler itself, while DoInvalid is.
  */
 {
-    Internal ("Unexpected token: %s", Keyword);
+    Internal ("Unexpected token: %m%p", &Keyword);
 }
 
 
@@ -1161,14 +1241,6 @@ static void DoLocalChar (void)
 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 */
@@ -1177,19 +1249,17 @@ static void DoMacPack (void)
        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);
 }
 
 
@@ -1218,7 +1288,7 @@ static void DoOrg (void)
        Error ("Range error");
        return;
     }
-    SetAbsPC (PC);
+    EnterAbsoluteMode (PC);
 }
 
 
@@ -1232,7 +1302,7 @@ static void DoOut (void)
        /* Output the string and be sure to flush the output to keep it in
         * sync with any error messages if the output is redirected to a file.
         */
-       printf ("%s\n", SVal);
+       printf ("%m%p\n", &SVal);
        fflush (stdout);
        NextTok ();
     }
@@ -1298,16 +1368,18 @@ static void DoPopSeg (void)
 static void DoProc (void)
 /* Start a new lexical scope */
 {
-    char Name[sizeof(SVal)];
+    StrBuf Name = STATIC_STRBUF_INITIALIZER;
     unsigned char AddrSize;
 
     if (Tok == TOK_IDENT) {
 
+        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 */
-       SymEntry* Sym = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
+               Sym = SymFind (CurrentScope, &Name, SYM_ALLOC_NEW);
 
         /* Skip the scope name */
         NextTok ();
@@ -1322,13 +1394,16 @@ static void DoProc (void)
 
         /* A .PROC statement without a name */
         Warning (1, "Unnamed .PROCs are deprecated, please use .SCOPE");
-        AnonName (Name, sizeof (Name), "PROC");
+        AnonName (&Name, "PROC");
         AddrSize = ADDR_SIZE_DEFAULT;
 
     }
 
     /* Enter a new scope */
-    SymEnterLevel (Name, ST_PROC, AddrSize);
+    SymEnterLevel (&Name, ST_PROC, AddrSize);
+
+    /* Free memory for Name */
+    SB_Done (&Name);
 }
 
 
@@ -1359,7 +1434,7 @@ static void DoPushSeg (void)
 static void DoReloc (void)
 /* Enter relocatable mode */
 {
-    RelocMode = 1;
+    EnterRelocMode ();
 }
 
 
@@ -1416,20 +1491,20 @@ static void DoROData (void)
 static void DoScope (void)
 /* Start a local scope */
 {
-    char Name[sizeof (SVal)];
+    StrBuf Name = STATIC_STRBUF_INITIALIZER;
     unsigned char AddrSize;
 
 
     if (Tok == TOK_IDENT) {
 
        /* The new scope has a name. Remember and skip it. */
-        strcpy (Name, SVal);
+        SB_Copy (&Name, &SVal);
         NextTok ();
 
     } else {
 
         /* An unnamed scope */
-        AnonName (Name, sizeof (Name), "SCOPE");
+        AnonName (&Name, "SCOPE");
 
     }
 
@@ -1437,8 +1512,10 @@ static void DoScope (void)
     AddrSize = OptionalAddrSize ();
 
     /* Enter the new scope */
-    SymEnterLevel (Name, ST_SCOPE, AddrSize);
+    SymEnterLevel (&Name, ST_SCOPE, AddrSize);
 
+    /* Free memory for Name */
+    SB_Done (&Name);
 }
 
 
@@ -1446,24 +1523,30 @@ static void DoScope (void)
 static void DoSegment (void)
 /* Switch to another segment */
 {
-    char Name [sizeof (SVal)];
+    StrBuf Name = STATIC_STRBUF_INITIALIZER;
     SegDef Def;
-    Def.Name = Name;
 
     if (Tok != TOK_STRCON) {
        ErrorSkip ("String constant expected");
     } else {
 
        /* Save the name of the segment and skip it */
-       strcpy (Name, SVal);
+       SB_Copy (&Name, &SVal);
        NextTok ();
 
+        /* Use the name for the segment definition */
+        SB_Terminate (&Name);
+        Def.Name = SB_GetBuf (&Name);
+
        /* Check for an optional address size modifier */
         Def.AddrSize = OptionalAddrSize ();
 
        /* Set the segment */
        UseSeg (&Def);
     }
+
+    /* Free memory for Name */
+    SB_Done (&Name);
 }
 
 
@@ -1475,12 +1558,19 @@ static void DoSetCPU (void)
     if (Tok != TOK_STRCON) {
        ErrorSkip ("String constant expected");
     } else {
-        /* Try to find the CPU, then skip the identifier */
-        cpu_t CPU = FindCPU (SVal);
-        NextTok ();
+        cpu_t CPU;
+
+        /* Try to find the CPU */
+        SB_Terminate (&SVal);
+        CPU = FindCPU (SB_GetConstBuf (&SVal));
 
         /* Switch to the new CPU */
         SetCPU (CPU);
+
+        /* Skip the identifier. If the CPU switch was successful, the scanner
+         * will treat the input now correctly for the new CPU.
+         */
+        NextTok ();
     }
 }
 
@@ -1494,14 +1584,6 @@ static void DoSmart (void)
 
 
 
-static void DoStruct (void)
-/* Struct definition */
-{
-    Error ("Not implemented");
-}
-
-
-
 static void DoSunPlus (void)
 /* Switch to the SUNPLUS CPU */
 {
@@ -1510,10 +1592,49 @@ static void DoSunPlus (void)
 
 
 
-static void DoUnion (void)
-/* Union definition */
+static void DoTag (void)
+/* Allocate space for a struct */
 {
-    Error ("Not implemented");
+    SymEntry* SizeSym;
+    long Size;
+
+    /* Read the struct name */
+    SymTable* Struct = ParseScopedSymTable ();
+
+    /* Check the supposed struct */
+    if (Struct == 0) {
+        ErrorSkip ("Unknown struct");
+        return;
+    }
+    if (GetSymTabType (Struct) != ST_STRUCT) {
+        ErrorSkip ("Not a struct");
+        return;
+    }
+
+    /* Get the symbol that defines the size of the struct */
+    SizeSym = GetSizeOfScope (Struct);
+
+    /* Check if it does exist and if its value is known */
+    if (SizeSym == 0 || !SymIsConst (SizeSym, &Size)) {
+        ErrorSkip ("Size of struct/union is unknown");
+        return;
+    }
+
+    /* Optional multiplicator may follow */
+    if (Tok == TOK_COMMA) {
+        long Multiplicator;
+        NextTok ();
+        Multiplicator = ConstExpression ();
+        /* Multiplicator must make sense */
+        if (Multiplicator <= 0) {
+            ErrorSkip ("Range error");
+            return;
+        }
+        Size *= Multiplicator;
+    }
+
+    /* Emit fill fragments */
+    EmitFill (Size);
 }
 
 
@@ -1521,7 +1642,7 @@ static void DoUnion (void)
 static void DoUnexpected (void)
 /* Got an unexpected keyword */
 {
-    Error ("Unexpected `%s'", Keyword);
+    Error ("Unexpected `%m%p'", &Keyword);
     SkipUntilSep ();
 }
 
@@ -1533,7 +1654,7 @@ static void DoWarning (void)
     if (Tok != TOK_STRCON) {
        ErrorSkip ("String constant expected");
     } else {
-               Warning (0, "User warning: %s", SVal);
+               Warning (0, "User warning: %m%p", &SVal);
        SkipUntilSep ();
     }
 }
@@ -1591,6 +1712,7 @@ static CtrlDesc CtrlCmdTab [] = {
     { ccNone,          DoASCIIZ        },
     { ccNone,           DoAssert        },
     { ccNone,          DoAutoImport    },
+    { ccNone,          DoUnexpected    },      /* .BANKBYTE */
     { ccNone,          DoUnexpected    },      /* .BLANK */
     { ccNone,          DoBss           },
     { ccNone,          DoByte          },
@@ -1613,12 +1735,15 @@ static CtrlDesc CtrlCmdTab [] = {
     { ccKeepToken,     DoConditionals  },      /* .ELSE */
     { ccKeepToken,     DoConditionals  },      /* .ELSEIF */
     { ccKeepToken,             DoEnd           },
+    { ccNone,           DoUnexpected    },      /* .ENDENUM */
     { ccKeepToken,     DoConditionals  },      /* .ENDIF */
     { ccNone,          DoUnexpected    },      /* .ENDMACRO */
     { ccNone,          DoEndProc       },
     { ccNone,          DoUnexpected    },      /* .ENDREPEAT */
     { ccNone,           DoEndScope      },
     { ccNone,           DoUnexpected    },      /* .ENDSTRUCT */
+    { ccNone,           DoUnexpected    },      /* .ENDUNION */
+    { ccNone,           DoEnum          },
     { ccNone,          DoError         },
     { ccNone,          DoExitMacro     },
     { ccNone,          DoExport        },
@@ -1630,8 +1755,11 @@ static CtrlDesc CtrlCmdTab [] = {
     { ccNone,          DoUnexpected    },      /* .FORCEWORD */
     { ccNone,          DoGlobal        },
     { ccNone,          DoGlobalZP      },
+    { ccNone,          DoUnexpected    },      /* .HIBYTE */
+    { ccNone,          DoUnexpected    },      /* .HIWORD */
     { ccNone,          DoI16           },
     { ccNone,          DoI8            },
+    { ccNone,           DoUnexpected    },      /* .IDENT */
     { ccKeepToken,     DoConditionals  },      /* .IF */
     { ccKeepToken,     DoConditionals  },      /* .IFBLANK */
     { ccKeepToken,     DoConditionals  },      /* .IFCONST */
@@ -1649,12 +1777,15 @@ static CtrlDesc CtrlCmdTab [] = {
     { ccNone,          DoImportZP      },
     { ccNone,          DoIncBin        },
     { ccNone,          DoInclude       },
+    { ccNone,           DoInterruptor   },
     { ccNone,          DoInvalid       },      /* .LEFT */
     { ccNone,          DoLineCont      },
     { ccNone,          DoList          },
     { ccNone,                  DoListBytes     },
+    { ccNone,          DoUnexpected    },      /* .LOBYTE */
     { ccNone,          DoUnexpected    },      /* .LOCAL */
     { ccNone,          DoLocalChar     },
+    { ccNone,          DoUnexpected    },      /* .LOWORD */
     { ccNone,          DoMacPack       },
     { ccNone,          DoMacro         },
     { ccNone,                  DoUnexpected    },      /* .MATCH */
@@ -1679,14 +1810,17 @@ static CtrlDesc CtrlCmdTab [] = {
     { 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 */
     { ccNone,           DoStruct        },
     { ccNone,          DoSunPlus       },
-    { ccNone,           DoUnexpected    },      /* .TAG */
+    { ccNone,           DoTag           },
     { ccNone,          DoUnexpected    },      /* .TCOUNT */
     { ccNone,                  DoUnexpected    },      /* .TIME */
     { ccNone,           DoUnion         },
@@ -1705,14 +1839,6 @@ static CtrlDesc CtrlCmdTab [] = {
 
 
 
-int TokIsPseudo (unsigned Tok)
-/* Return true if the given token is a pseudo instruction token */
-{
-    return (Tok >= TOK_FIRSTPSEUDO && Tok <= TOK_LASTPSEUDO);
-}
-
-
-
 void HandlePseudo (void)
 /* Handle a pseudo instruction */
 {
@@ -1724,7 +1850,7 @@ void HandlePseudo (void)
     /* Safety check */
     if (PSEUDO_COUNT != (TOK_LASTPSEUDO - TOK_FIRSTPSEUDO + 1)) {
        Internal ("Pseudo mismatch: PSEUDO_COUNT = %u, actual count = %u\n",
-                 PSEUDO_COUNT, TOK_LASTPSEUDO - TOK_FIRSTPSEUDO + 1);
+                         (unsigned) PSEUDO_COUNT, TOK_LASTPSEUDO - TOK_FIRSTPSEUDO + 1);
     }
     CHECK (Index < PSEUDO_COUNT);
 
@@ -1733,7 +1859,7 @@ void HandlePseudo (void)
 
     /* Remember the instruction, then skip it if needed */
     if ((D->Flags & ccKeepToken) == 0) {
-       strcpy (Keyword+1, SVal);
+       SB_Copy (&Keyword, &SVal);
        NextTok ();
     }