From 3f9e7b56aeaad9c5ac679b19c7e69982cb45ab23 Mon Sep 17 00:00:00 2001 From: cuz Date: Sun, 21 Apr 2002 20:00:04 +0000 Subject: [PATCH] Support additional o65 attributes. Add a special ID for the cc65 operating system that is written to the OS field of the options header. git-svn-id: svn://svn.cc65.org/cc65/trunk@1254 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ld65/config.c | 108 ++++++++++++++++++++++++++++++--------------- src/ld65/o65.c | 24 +++++----- src/ld65/o65.h | 2 +- src/ld65/scanner.h | 2 + 4 files changed, 88 insertions(+), 48 deletions(-) diff --git a/src/ld65/config.c b/src/ld65/config.c index fb0a581de..657813ce1 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -104,17 +104,6 @@ unsigned SegDescCount; /* Number of entries in list */ static BinDesc* BinFmtDesc = 0; static O65Desc* O65FmtDesc = 0; -/* Attributes for the o65 format */ -static unsigned O65Attr = 0; -#define OA_OS 0x0001 -#define OA_TYPE 0x0002 -#define OA_VERSION 0x0004 -#define OA_OSVERSION 0x0008 -#define OA_TEXT 0x0010 -#define OA_DATA 0x0020 -#define OA_BSS 0x0040 -#define OA_ZP 0x0080 - /*****************************************************************************/ @@ -806,6 +795,8 @@ static void ParseO65 (void) { "IMPORT", CFGTOK_IMPORT }, { "TYPE", CFGTOK_TYPE }, { "OS", CFGTOK_OS }, + { "ID", CFGTOK_ID }, + { "VERSION", CFGTOK_VERSION }, }; static const IdentTok Types [] = { { "SMALL", CFGTOK_SMALL }, @@ -817,6 +808,25 @@ static void ParseO65 (void) { "CC65", CFGTOK_CC65 }, }; + /* Bitmask to remember the attributes we got already */ + enum { + atNone = 0x0000, + atOS = 0x0001, + atOSVersion = 0x0002, + atType = 0x0004, + atImport = 0x0008, + atExport = 0x0010, + atID = 0x0020, + atVersion = 0x0040 + }; + unsigned AttrFlags = atNone; + + /* Remember the attributes read */ + unsigned OS = 0; /* Initialize to keep gcc happy */ + unsigned ID = 0; /* Dito */ + unsigned Version = 0; + + /* Read the attributes */ while (CfgTok == CFGTOK_IDENT) { /* Map the identifier to a token */ @@ -832,6 +842,8 @@ static void ParseO65 (void) switch (AttrTok) { case CFGTOK_EXPORT: + /* Remember we had this token (maybe more than once) */ + AttrFlags |= atExport; /* We expect an identifier */ CfgAssureIdent (); /* Check if the export symbol is also defined as an import. */ @@ -843,13 +855,15 @@ static void ParseO65 (void) * error message when checking it here. */ if (O65GetExport (O65FmtDesc, CfgSVal) != 0) { - CfgError ("Duplicate exported symbol: `%s'", CfgSVal); + CfgError ("Duplicate exported symbol: `%s'", CfgSVal); } /* Insert the symbol into the table */ - O65SetExport (O65FmtDesc, CfgSVal); + O65SetExport (O65FmtDesc, CfgSVal); break; case CFGTOK_IMPORT: + /* Remember we had this token (maybe more than once) */ + AttrFlags |= atImport; /* We expect an identifier */ CfgAssureIdent (); /* Check if the imported symbol is also defined as an export. */ @@ -869,7 +883,7 @@ static void ParseO65 (void) case CFGTOK_TYPE: /* Cannot have this attribute twice */ - FlagAttr (&O65Attr, OA_TYPE, "TYPE"); + FlagAttr (&AttrFlags, atType, "TYPE"); /* Get the type of the executable */ CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); switch (CfgTok) { @@ -889,28 +903,35 @@ static void ParseO65 (void) case CFGTOK_OS: /* Cannot use this attribute twice */ - FlagAttr (&O65Attr, OA_OS, "OS"); + FlagAttr (&AttrFlags, atOS, "OS"); /* Get the operating system */ CfgSpecialToken (OperatingSystems, ENTRY_COUNT (OperatingSystems), "OS type"); switch (CfgTok) { - - case CFGTOK_LUNIX: - O65SetOS (O65FmtDesc, O65OS_LUNIX); - break; - - case CFGTOK_OSA65: - O65SetOS (O65FmtDesc, O65OS_OSA65); - break; - - case CFGTOK_CC65: - O65SetOS (O65FmtDesc, O65OS_CC65); - break; - - default: - CfgError ("Unexpected OS token"); + case CFGTOK_LUNIX: OS = O65OS_LUNIX; break; + case CFGTOK_OSA65: OS = O65OS_OSA65; break; + case CFGTOK_CC65: OS = O65OS_CC65; break; + default: CfgError ("Unexpected OS token"); } break; + case CFGTOK_ID: + /* Cannot have this attribute twice */ + FlagAttr (&AttrFlags, atID, "ID"); + /* We're expecting a number in the 0..$FFFF range*/ + CfgAssureInt (); + CfgRangeCheck (0, 0xFFFF); + ID = (unsigned) CfgIVal; + break; + + case CFGTOK_VERSION: + /* Cannot have this attribute twice */ + FlagAttr (&AttrFlags, atVersion, "VERSION"); + /* We're expecting a number in byte range */ + CfgAssureInt (); + CfgRangeCheck (0, 0xFF); + Version = (unsigned) CfgIVal; + break; + default: FAIL ("Unexpected attribute token"); @@ -920,6 +941,23 @@ static void ParseO65 (void) CfgNextTok (); CfgOptionalComma (); } + + /* Check if we have all mandatory attributes */ + AttrCheck (AttrFlags, atOS, "OS"); + + /* Check for attributes that may not be combined */ + if (OS == O65OS_CC65) { + if ((AttrFlags & (atImport | atExport)) != 0) { + CfgError ("OS type CC65 may not have imports or exports"); + } + } else { + if (AttrFlags & atID) { + CfgError ("Operating system does not support the ID attribute"); + } + } + + /* Set the O65 operating system to use */ + O65SetOS (O65FmtDesc, OS, Version, ID); } @@ -970,11 +1008,11 @@ static void ParseConDes (void) /* Parse the CONDES feature */ { static const IdentTok Attributes [] = { - { "SEGMENT", CFGTOK_SEGMENT }, - { "LABEL", CFGTOK_LABEL }, - { "COUNT", CFGTOK_COUNT }, - { "TYPE", CFGTOK_TYPE }, - { "ORDER", CFGTOK_ORDER }, + { "SEGMENT", CFGTOK_SEGMENT }, + { "LABEL", CFGTOK_LABEL }, + { "COUNT", CFGTOK_COUNT }, + { "TYPE", CFGTOK_TYPE }, + { "ORDER", CFGTOK_ORDER }, }; static const IdentTok Types [] = { diff --git a/src/ld65/o65.c b/src/ld65/o65.c index fc8265890..d14322880 100644 --- a/src/ld65/o65.c +++ b/src/ld65/o65.c @@ -1008,31 +1008,31 @@ void O65SetOption (O65Desc* D, unsigned Type, const void* Data, unsigned DataLen -void O65SetOS (O65Desc* D, unsigned OS) +void O65SetOS (O65Desc* D, unsigned OS, unsigned Version, unsigned Id) /* Set an option describing the target operating system */ { - static const unsigned char OSA65 [2] = { O65OS_OSA65, 0 }; - static const unsigned char Lunix [2] = { O65OS_LUNIX, 0 }; - static const unsigned char CC65 [4] = { O65OS_CC65, 0, 0, 0 }; + /* Setup the option data */ + unsigned char Opt[4]; + Opt[0] = OS; + Opt[1] = Version; - /* Write the correct option */ + /* Write the correct option length */ switch (OS) { - case O65OS_OSA65: - O65SetOption (D, O65OPT_OS, OSA65, sizeof (OSA65)); - break; - case O65OS_LUNIX: - O65SetOption (D, O65OPT_OS, Lunix, sizeof (Lunix)); + /* No id for these two */ + O65SetOption (D, O65OPT_OS, Opt, 2); break; case O65OS_CC65: - O65SetOption (D, O65OPT_OS, CC65, sizeof (CC65)); + /* Set the 16 bit id */ + Opt[2] = (unsigned char) Id; + Opt[3] = (unsigned char) (Id >> 8); + O65SetOption (D, O65OPT_OS, Opt, 4); break; default: Internal ("Trying to set invalid O65 operating system: %u", OS); - } } diff --git a/src/ld65/o65.h b/src/ld65/o65.h index 85f3c269d..aaeb2aced 100644 --- a/src/ld65/o65.h +++ b/src/ld65/o65.h @@ -98,7 +98,7 @@ void O65SetAlignment (O65Desc* D, unsigned Align); void O65SetOption (O65Desc* D, unsigned Type, const void* Data, unsigned DataLen); /* Set an o65 header option */ -void O65SetOS (O65Desc* D, unsigned OS); +void O65SetOS (O65Desc* D, unsigned OS, unsigned Version, unsigned Id); /* Set an option describing the target operating system */ ExtSym* O65GetImport (O65Desc* D, const char* Ident); diff --git a/src/ld65/scanner.h b/src/ld65/scanner.h index 5971c2be3..744abdb9a 100644 --- a/src/ld65/scanner.h +++ b/src/ld65/scanner.h @@ -77,6 +77,8 @@ typedef enum { CFGTOK_EXPORT, CFGTOK_IMPORT, CFGTOK_OS, + CFGTOK_ID, + CFGTOK_VERSION, CFGTOK_FORMAT, CFGTOK_LOAD, -- 2.39.5