]> git.sur5r.net Git - cc65/blobdiff - src/ca65/pseudo.c
New module strstack
[cc65] / src / ca65 / pseudo.c
index 90409ca8b97e9e3bb672f20bf7d4db01b39db2dc..1388cdadc72dd32dc8acc986edb8788dda8ede56 100644 (file)
@@ -7,7 +7,7 @@
 /*                                                                           */
 /*                                                                           */
 /* (C) 1998-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
+/*               Römerstraße 52                                              */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
@@ -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 char Keyword [sizeof (SVal)+1];
 
 /* Segment stack */
 #define MAX_PUSHED_SEGMENTS     16
@@ -114,7 +118,7 @@ static void DoInvalid (void);
 
 
 
-static unsigned OptionalAddrSize (void)
+static unsigned char OptionalAddrSize (void)
 /* If a colon follows, parse an optional address size spec and return it.
  * Otherwise return ADDR_SIZE_DEFAULT.
  */
@@ -148,7 +152,7 @@ static void SetBoolOption (unsigned char* Flag)
                /* Map the keyword to a number */
                switch (GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]))) {
            case 0:     *Flag = 0; NextTok ();                  break;
-           case 1:     *Flag = 1; NextTok ();                  break;  
+           case 1:     *Flag = 1; NextTok ();                  break;
            default:    ErrorSkip ("`on' or `off' expected");   break;
        }
     } else if (TokIsSep (Tok)) {
@@ -161,12 +165,12 @@ static void SetBoolOption (unsigned char* Flag)
 
 
 
-static void ExportImport (void (*Func) (SymEntry*, unsigned, unsigned),
-                          unsigned DefAddrSize, unsigned Flags)
+static void ExportImport (void (*Func) (SymEntry*, unsigned char, unsigned),
+                          unsigned char DefAddrSize, unsigned Flags)
 /* Export or import symbols */
 {
     SymEntry* Sym;
-    unsigned  AddrSize;
+    unsigned char AddrSize;
 
     while (1) {
 
@@ -227,6 +231,10 @@ static void ConDes (const char* Name, unsigned Type)
 {
     long Prio;
 
+
+    /* Find the symbol table entry, allocate a new one if necessary */
+    SymEntry* Sym = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
+
     /* Optional constructor priority */
     if (Tok == TOK_COMMA) {
        /* Priority value follows */
@@ -243,7 +251,7 @@ static void ConDes (const char* Name, unsigned Type)
     }
 
     /* Define the symbol */
-    SymConDes (Name, Type, (unsigned) Prio);
+    SymConDes (Sym, ADDR_SIZE_DEFAULT, Type, (unsigned) Prio);
 }
 
 
@@ -256,7 +264,7 @@ static void ConDes (const char* Name, unsigned Type)
 
 static void DoA16 (void)
 /* Switch the accu to 16 bit mode (assembler only) */
-{              
+{
     if (GetCPU() != CPU_65816) {
        Error ("Command is only valid in 65816 mode");
     } else {
@@ -410,7 +418,7 @@ static void DoAssert (void)
 
     /* Read the message */
     if (Tok != TOK_STRCON) {
-       ErrorSkip ("String constant expected");           
+       ErrorSkip ("String constant expected");
     } else {
         AddAssertion (Expr, Action, GetStringId (SVal));
         NextTok ();
@@ -700,11 +708,24 @@ static void DoEnd (void)
 static void DoEndProc (void)
 /* Leave a lexical level */
 {
-    if (CurrentScope != RootScope) {
-        SymLeaveLevel ();
+    if (GetCurrentSymTabType () != ST_PROC) {
+        /* No local scope */
+        ErrorSkip ("No open .PROC");
     } else {
+        SymLeaveLevel ();
+    }
+}
+
+
+
+static void DoEndScope (void)
+/* Leave a lexical level */
+{
+    if ( GetCurrentSymTabType () != ST_SCOPE) {
         /* No local scope */
-        ErrorSkip ("No open lexical level");
+        ErrorSkip ("No open .SCOPE");
+    } else {
+        SymLeaveLevel ();
     }
 }
 
@@ -792,7 +813,7 @@ static void DoFeature (void)
            NextTok ();
        }
 
-       /* Allow more than one keyword */           
+       /* Allow more than one keyword */
        if (Tok == TOK_COMMA) {
            NextTok ();
        } else {
@@ -1041,7 +1062,7 @@ static void DoIncBin (void)
        size_t BytesRead = fread (Buf, 1, BytesToRead, F);
        if (BytesToRead != BytesRead) {
            /* Some sort of error */
-           ErrorSkip ("Cannot read from include file `%s': %s", 
+           ErrorSkip ("Cannot read from include file `%s': %s",
                        Name, strerror (errno));
            break;
        }
@@ -1281,16 +1302,18 @@ static void DoPopSeg (void)
 static void DoProc (void)
 /* Start a new lexical scope */
 {
+    char Name[sizeof(SVal)];
+    unsigned char AddrSize;
+
     if (Tok == TOK_IDENT) {
 
-        unsigned AddrSize;
+        SymEntry* Sym;
 
        /* The new scope has a name. Remember it. */
-        char Name[sizeof(SVal)];
         strcpy (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 ();
@@ -1301,17 +1324,17 @@ static void DoProc (void)
         /* Mark the symbol as defined */
        SymDef (Sym, GenCurrentPC (), AddrSize, SF_LABEL);
 
-        /* Enter a new scope with the given name */
-        SymEnterLevel (Name, AddrSize);
-
     } else {
 
         /* A .PROC statement without a name */
-        char Buf[sizeof (SVal)];
-        SymEnterLevel (AnonName (Buf, sizeof (Buf), "Scope"), ADDR_SIZE_DEFAULT);
         Warning (1, "Unnamed .PROCs are deprecated, please use .SCOPE");
+        AnonName (Name, sizeof (Name), "PROC");
+        AddrSize = ADDR_SIZE_DEFAULT;
 
     }
+
+    /* Enter a new scope */
+    SymEnterLevel (Name, ST_PROC, AddrSize);
 }
 
 
@@ -1396,6 +1419,36 @@ static void DoROData (void)
 
 
 
+static void DoScope (void)
+/* Start a local scope */
+{
+    char Name[sizeof (SVal)];
+    unsigned char AddrSize;
+
+
+    if (Tok == TOK_IDENT) {
+
+       /* The new scope has a name. Remember and skip it. */
+        strcpy (Name, SVal);
+        NextTok ();
+
+    } else {
+
+        /* An unnamed scope */
+        AnonName (Name, sizeof (Name), "SCOPE");
+
+    }
+
+    /* Read an optional address size specifier */
+    AddrSize = OptionalAddrSize ();
+
+    /* Enter the new scope */
+    SymEnterLevel (Name, ST_SCOPE, AddrSize);
+
+}
+
+
+
 static void DoSegment (void)
 /* Switch to another segment */
 {
@@ -1447,14 +1500,6 @@ static void DoSmart (void)
 
 
 
-static void DoStruct (void)
-/* Struct definition */
-{
-    Error ("Not implemented");
-}
-
-
-
 static void DoSunPlus (void)
 /* Switch to the SUNPLUS CPU */
 {
@@ -1463,10 +1508,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);
 }
 
 
@@ -1544,6 +1628,7 @@ static CtrlDesc CtrlCmdTab [] = {
     { ccNone,          DoASCIIZ        },
     { ccNone,           DoAssert        },
     { ccNone,          DoAutoImport    },
+    { ccNone,          DoUnexpected    },      /* .BANKBYTE */
     { ccNone,          DoUnexpected    },      /* .BLANK */
     { ccNone,          DoBss           },
     { ccNone,          DoByte          },
@@ -1566,11 +1651,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        },
@@ -1582,6 +1671,8 @@ static CtrlDesc CtrlCmdTab [] = {
     { ccNone,          DoUnexpected    },      /* .FORCEWORD */
     { ccNone,          DoGlobal        },
     { ccNone,          DoGlobalZP      },
+    { ccNone,          DoUnexpected    },      /* .HIBYTE */
+    { ccNone,          DoUnexpected    },      /* .HIWORD */
     { ccNone,          DoI16           },
     { ccNone,          DoI8            },
     { ccKeepToken,     DoConditionals  },      /* .IF */
@@ -1605,8 +1696,10 @@ static CtrlDesc CtrlCmdTab [] = {
     { ccNone,          DoLineCont      },
     { ccNone,          DoList          },
     { ccNone,                  DoListBytes     },
+    { ccNone,          DoUnexpected    },      /* .LOBYTE */
     { ccNone,          DoUnexpected    },      /* .LOCAL */
     { ccNone,          DoLocalChar     },
+    { ccNone,          DoUnexpected    },      /* .LOWORD */
     { ccNone,          DoMacPack       },
     { ccNone,          DoMacro         },
     { ccNone,                  DoUnexpected    },      /* .MATCH */
@@ -1617,53 +1710,47 @@ static CtrlDesc CtrlCmdTab [] = {
     { ccNone,          DoP02           },
     { ccNone,          DoP816          },
     { ccNone,                  DoPageLength    },
-    { ccNone,          DoUnexpected    },      /* .PARAMCOUNT */
+    { ccNone,          DoUnexpected    },      /* .PARAMCOUNT */
     { ccNone,          DoPC02          },
     { ccNone,           DoPopSeg        },
     { ccNone,          DoProc          },
     { ccNone,                  DoPSC02         },
     { ccNone,           DoPushSeg       },
-    { ccNone,          DoUnexpected    },      /* .REFERENCED */
+    { ccNone,          DoUnexpected    },      /* .REFERENCED */
     { ccNone,          DoReloc         },
     { ccNone,          DoRepeat        },
     { ccNone,          DoRes           },
     { ccNone,          DoInvalid       },      /* .RIGHT */
     { ccNone,          DoROData        },
+    { ccNone,           DoScope         },
     { ccNone,          DoSegment       },
     { ccNone,                  DoSetCPU        },
+    { ccNone,           DoUnexpected    },      /* .SIZEOF */
     { ccNone,          DoSmart         },
-    { ccNone,          DoUnexpected    },      /* .STRAT */
-    { ccNone,                  DoUnexpected    },      /* .STRING */
-    { ccNone,          DoUnexpected    },      /* .STRLEN */
+    { ccNone,          DoUnexpected    },      /* .STRAT */
+    { ccNone,                  DoUnexpected    },      /* .STRING */
+    { ccNone,          DoUnexpected    },      /* .STRLEN */
     { ccNone,           DoStruct        },
     { ccNone,          DoSunPlus       },
-    { ccNone,           DoUnexpected    },      /* .TAG */
-    { ccNone,          DoUnexpected    },      /* .TCOUNT */
-    { ccNone,                  DoUnexpected    },      /* .TIME */
+    { ccNone,           DoTag           },
+    { ccNone,          DoUnexpected    },      /* .TCOUNT */
+    { ccNone,                  DoUnexpected    },      /* .TIME */
     { ccNone,           DoUnion         },
     { ccNone,           DoUnexpected    },      /* .VERSION */
     { ccNone,          DoWarning       },
     { ccNone,          DoWord          },
-    { ccNone,                  DoUnexpected    },      /* .XMATCH */
+    { ccNone,                  DoUnexpected    },      /* .XMATCH */
     { ccNone,          DoZeropage      },
 };
 
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                                          Code                                    */
 /*****************************************************************************/
 
 
 
-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 */
 {
@@ -1684,7 +1771,7 @@ void HandlePseudo (void)
 
     /* Remember the instruction, then skip it if needed */
     if ((D->Flags & ccKeepToken) == 0) {
-       strcpy (Keyword+1, SVal);
+       strcpy (Keyword, SVal);
        NextTok ();
     }