]> git.sur5r.net Git - cc65/blobdiff - src/da65/config.c
Encode option strings in the string pool
[cc65] / src / da65 / config.c
index 7d284d24240aaf53023c7afb74434803cc938730..f6fefab7f9acf656f7e76ea309291aebb91da41e 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                                config.c                                  */
+/*                                config.c                                  */
 /*                                                                           */
 /*                Disassembler configuration file handling                  */
 /*                                                                           */
@@ -33,6 +33,8 @@
 
 
 
+#include <stdio.h>
+#include <string.h>
 #if defined(_MSC_VER)
 /* Microsoft compiler */
 #  include <io.h>
@@ -45,6 +47,8 @@
 #include "xmalloc.h"
 
 /* da65 */
+#include "attrtab.h"
+#include "error.h"
 #include "global.h"
 #include "scanner.h"
 #include "config.h"
@@ -64,6 +68,7 @@ static void GlobalSection (void)
                {   "INPUTNAME",        CFGTOK_INPUTNAME        },
        {   "OUTPUTNAME",       CFGTOK_OUTPUTNAME       },
        {   "PAGELENGTH",       CFGTOK_PAGELENGTH       },
+       {   "STARTADDR",        CFGTOK_STARTADDR        },
     };
 
     /* Skip the token */
@@ -110,6 +115,15 @@ static void GlobalSection (void)
                PageLength = CfgIVal;
                CfgNextTok ();
                break;
+
+           case CFGTOK_STARTADDR:
+               CfgNextTok ();
+               CfgAssureInt ();
+               CfgRangeCheck (0x0000, 0xFFFF);
+               StartAddr = CfgIVal;
+               CfgNextTok ();
+               break;
+
        }
 
        /* Directive is followed by a semicolon */
@@ -127,11 +141,36 @@ static void RangeSection (void)
 /* Parse a range section */
 {
     static const IdentTok RangeDefs[] = {
-               {   "START",            CFGTOK_START    },
-       {   "END",              CFGTOK_END      },
+               {   "START",            CFGTOK_START    },
+       {   "END",              CFGTOK_END      },
        {   "TYPE",             CFGTOK_TYPE     },
     };
 
+    static const IdentTok TypeDefs[] = {
+       {   "CODE",             CFGTOK_CODE     },
+       {   "BYTETABLE",        CFGTOK_BYTETAB  },
+       {   "WORDTABLE",        CFGTOK_WORDTAB  },
+       {   "DWORDTABLE",       CFGTOK_DWORDTAB },
+       {   "ADDRTABLE",        CFGTOK_ADDRTAB  },
+       {   "RTSTABLE",         CFGTOK_RTSTAB   },
+       {   "TEXTTABLE",        CFGTOK_TEXTTAB  },
+    };
+
+
+    /* Which values did we get? */
+    enum {
+       tNone   = 0x00,
+       tStart  = 0x01,
+       tEnd    = 0x02,
+       tType   = 0x04,
+       tAll    = 0x07
+    } Needed = tNone;
+
+    /* Locals - initialize to avoid gcc warnings */
+    unsigned Start     = 0;
+    unsigned End       = 0;
+    unsigned char Type = 0;
+
     /* Skip the token */
     CfgNextTok ();
 
@@ -141,9 +180,65 @@ static void RangeSection (void)
     /* Look for section tokens */
     while (CfgTok != CFGTOK_RCURLY) {
 
+       /* Convert to special token */
+               CfgSpecialToken (RangeDefs, ENTRY_COUNT (RangeDefs), "Range directive");
+
+       /* Look at the token */
+       switch (CfgTok) {
 
+           case CFGTOK_START:
+               CfgNextTok ();
+               CfgAssureInt ();
+               CfgRangeCheck (0x0000, 0xFFFF);
+               Start = CfgIVal;
+               Needed |= tStart;
+               CfgNextTok ();
+               break;
+
+           case CFGTOK_END:
+               CfgNextTok ();
+               CfgAssureInt ();
+               CfgRangeCheck (0x0000, 0xFFFF);
+               End = CfgIVal;
+               Needed |= tEnd;
+               CfgNextTok ();
+               break;
+
+           case CFGTOK_TYPE:
+               CfgNextTok ();
+               CfgSpecialToken (TypeDefs, ENTRY_COUNT (TypeDefs), "Type");
+               switch (CfgTok) {
+                   case CFGTOK_CODE:           Type = atCode;          break;
+                   case CFGTOK_BYTETAB:        Type = atByteTab;       break;
+                   case CFGTOK_WORDTAB:        Type = atWordTab;       break;
+                   case CFGTOK_DWORDTAB:       Type = atDWordTab;      break;
+                   case CFGTOK_ADDRTAB:        Type = atAddrTab;       break;
+                           case CFGTOK_RTSTAB:         Type = atRtsTab;        break;
+                   case CFGTOK_TEXTTAB:        Type = atTextTab;       break;
+               }
+               Needed |= tType;
+               CfgNextTok ();
+               break;
+       }
+
+       /* Directive is followed by a semicolon */
+       CfgConsumeSemi ();
+
+    }
+
+    /* Did we get all required values? */
+    if (Needed != tAll) {
+       CfgError ("Required values missing from this section");
     }
 
+    /* Start must be less than end */
+    if (Start > End) {
+       CfgError ("Start value must not be greater than end value");
+    }
+
+    /* Set the range */
+    MarkRange (Start, End, Type);
+
     /* Consume the closing brace */
     CfgConsumeRCurly ();
 }
@@ -153,12 +248,17 @@ static void RangeSection (void)
 static void LabelSection (void)
 /* Parse a label section */
 {
-    static const IdentTok Globals[] = {
-               {   "INPUTNAMEL",       CFGTOK_INPUTNAME        },
-       {   "OUTPUTNAME",       CFGTOK_OUTPUTNAME       },
-       {   "PAGELENGTH",       CFGTOK_PAGELENGTH       },
+    static const IdentTok LabelDefs[] = {
+               {   "NAME",     CFGTOK_NAME     },
+       {   "ADDR",     CFGTOK_ADDR     },
+               {   "SIZE",     CFGTOK_SIZE     },
     };
 
+    /* Locals - initialize to avoid gcc warnings */
+    char* Name = 0;
+    long Value = -1;
+    long Size  = -1;
+
     /* Skip the token */
     CfgNextTok ();
 
@@ -168,9 +268,100 @@ static void LabelSection (void)
     /* Look for section tokens */
     while (CfgTok != CFGTOK_RCURLY) {
 
+       /* Convert to special token */
+               CfgSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Label directive");
+
+       /* Look at the token */
+       switch (CfgTok) {
+
+           case CFGTOK_NAME:
+               CfgNextTok ();
+               if (Name) {
+                   CfgError ("Name already given");
+               }
+               CfgAssureStr ();
+               if (CfgSVal[0] == '\0') {
+                   CfgError ("Name may not be empty");
+               }
+               Name = xstrdup (CfgSVal);
+               CfgNextTok ();
+               break;
+
+           case CFGTOK_ADDR:
+               CfgNextTok ();
+               if (Value >= 0) {
+                   CfgError ("Value already given");
+               }
+               CfgAssureInt ();
+               CfgRangeCheck (0, 0xFFFF);
+               Value = CfgIVal;
+               CfgNextTok ();
+               break;
+
+           case CFGTOK_SIZE:
+               CfgNextTok ();
+               if (Size >= 0) {
+                   CfgError ("Size already given");
+               }
+               CfgAssureInt ();
+               CfgRangeCheck (1, 0x10000);
+               Size = CfgIVal;
+               CfgNextTok ();
+               break;
+
+       }
+
+       /* Directive is followed by a semicolon */
+       CfgConsumeSemi ();
+    }
+
+    /* Did we get the necessary data */
+    if (Name == 0) {
+       CfgError ("Label name is missing");
+    }
+    if (Value < 0) {
+       CfgError ("Label value is missing");
+    }
+    if (Size < 0) {
+       /* Use default */
+       Size = 1;
+    }
+    if (Value + Size > 0x10000) {
+       CfgError ("Invalid size (address out of range)");
+    }
+    if (HaveLabel ((unsigned) Value)) {
+       CfgError ("Label for address $%04lX already defined", Value);
+    }
 
+    /* Define the label */
+    AddLabel ((unsigned) Value, atExtLabel, Name);
+
+    /* Define dependent labels if necessary */
+    if (Size > 1) {
+       unsigned Offs;
+
+       /* Allocate memory for the dependent label names */
+       unsigned NameLen = strlen (Name);
+       char*    DepName = xmalloc (NameLen + 7);
+       char*    DepOffs = DepName + NameLen + 1;
+
+       /* Copy the original name into the buffer */
+       memcpy (DepName, Name, NameLen);
+       DepName[NameLen] = '+';
+
+       /* Define the labels */
+       for (Offs = 1; Offs < (unsigned) Size; ++Offs) {
+           sprintf (DepOffs, "%u", Offs);
+           AddLabel ((unsigned) Value+Offs, atDepLabel, DepName);
+       }
+
+       /* Free the name buffer */
+       xfree (DepName);
     }
 
+    /* Delete the dynamically allocated memory for Name */
+    xfree (Name);
+
     /* Consume the closing brace */
     CfgConsumeRCurly ();
 }
@@ -181,8 +372,8 @@ static void CfgParse (void)
 /* Parse the config file */
 {
     static const IdentTok Globals[] = {
-       {   "GLOBAL",   CFGTOK_GLOBAL   },
-       {   "RANGE",    CFGTOK_RANGE    },
+       {   "GLOBAL",   CFGTOK_GLOBAL   },
+       {   "RANGE",    CFGTOK_RANGE    },
        {   "LABEL",    CFGTOK_LABEL    },
     };