Ejemplo n.º 1
0
static void ParseConfig (void)
/* Parse the config file */
{
    static const IdentTok BlockNames [] = {
	{   "MEMORY",  	CFGTOK_MEMORY	},
	{   "FILES",    CFGTOK_FILES    },
        {   "SEGMENTS", CFGTOK_SEGMENTS },
	{   "FORMATS", 	CFGTOK_FORMATS  },
	{   "FEATURES", CFGTOK_FEATURES	},
	{   "SYMBOLS",	CFGTOK_SYMBOLS 	},
    };
    cfgtok_t BlockTok;

    do {

	/* Read the block ident */
       	CfgSpecialToken (BlockNames, ENTRY_COUNT (BlockNames), "Block identifier");
	BlockTok = CfgTok;
	CfgNextTok ();

	/* Expected a curly brace */
	CfgConsume (CFGTOK_LCURLY, "`{' expected");

	/* Read the block */
	switch (BlockTok) {

	    case CFGTOK_MEMORY:
	     	ParseMemory ();
	     	break;

	    case CFGTOK_FILES:
	     	ParseFiles ();
	     	break;

	    case CFGTOK_SEGMENTS:
	     	ParseSegments ();
	     	break;

	    case CFGTOK_FORMATS:
	     	ParseFormats ();
	     	break;

	    case CFGTOK_FEATURES:
		ParseFeatures ();
		break;

	    case CFGTOK_SYMBOLS:
		ParseSymbols ();
		break;

	    default:
	     	FAIL ("Unexpected block token");

	}

	/* Skip closing brace */
	CfgConsume (CFGTOK_RCURLY, "`}' expected");

    } while (CfgTok != CFGTOK_EOF);
}
Ejemplo n.º 2
0
static void InfoParse (void)
/* Parse the config file */
{
    static const IdentTok Globals[] = {
        {   "ASMINC",   INFOTOK_ASMINC  },
        {   "GLOBAL",   INFOTOK_GLOBAL  },
        {   "LABEL",    INFOTOK_LABEL   },
        {   "RANGE",    INFOTOK_RANGE   },
        {   "SEGMENT",  INFOTOK_SEGMENT },
    };

    while (InfoTok != INFOTOK_EOF) {

        /* Convert an identifier into a token */
        InfoSpecialToken (Globals, ENTRY_COUNT (Globals), "Config directive");

        /* Check the token */
        switch (InfoTok) {

            case INFOTOK_ASMINC:
                AsmIncSection ();
                break;

            case INFOTOK_GLOBAL:
                GlobalSection ();
                break;

            case INFOTOK_LABEL:
                LabelSection ();
                break;

            case INFOTOK_RANGE:
                RangeSection ();
                break;

            case INFOTOK_SEGMENT:
                SegmentSection ();
                break;

            default:
                Internal ("Unexpected token: %u", InfoTok);
        }

        /* Semicolon expected */
        InfoConsumeSemi ();
    }
}
Ejemplo n.º 3
0
static void ParseFormats (void)
/* Parse a target format section */
{
    static const IdentTok Formats [] = {
       	{   "O65",     	CFGTOK_O65      },
       	{   "BIN",     	CFGTOK_BIN      },
       	{   "BINARY",   CFGTOK_BIN      },
    };

    while (CfgTok == CFGTOK_IDENT) {

	/* Map the identifier to a token */
	cfgtok_t FormatTok;
       	CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format");
	FormatTok = CfgTok;

	/* Skip the name and the following colon */
	CfgNextTok ();
	CfgConsumeColon ();

	/* Parse the format options */
	switch (FormatTok) {

	    case CFGTOK_O65:
		ParseO65 ();
		break;

	    case CFGTOK_BIN:
		/* No attribibutes available */
		break;

	    default:
		Error ("Unexpected format token");
	}

	/* Skip the semicolon */
	CfgConsumeSemi ();
    }


    /* Remember we had this section */
    SectionsEncountered |= SE_FORMATS;
}
Ejemplo n.º 4
0
static void ParseFeatures (void)
/* Parse a features section */
{
    static const IdentTok Features [] = {
       	{   "CONDES",  	    CFGTOK_CONDES	},
        {   "STARTADDRESS", CFGTOK_STARTADDRESS },
    };

    while (CfgTok == CFGTOK_IDENT) {

    	/* Map the identifier to a token */
    	cfgtok_t FeatureTok;
       	CfgSpecialToken (Features, ENTRY_COUNT (Features), "Feature");
       	FeatureTok = CfgTok;

    	/* Skip the name and the following colon */
    	CfgNextTok ();
    	CfgConsumeColon ();

    	/* Parse the format options */
    	switch (FeatureTok) {

    	    case CFGTOK_CONDES:
    	 	ParseConDes ();
    	 	break;

            case CFGTOK_STARTADDRESS:
                ParseStartAddress ();
                break;


    	    default:
       	       	FAIL ("Unexpected feature token");
    	}

    	/* Skip the semicolon */
    	CfgConsumeSemi ();
    }

    /* Remember we had this section */
    SectionsEncountered |= SE_FEATURES;
}
Ejemplo n.º 5
0
void CfgBoolToken (void)
/* Map an identifier or integer to a boolean token */
{
    static const IdentTok Booleans [] = {
       	{   "YES",     	CFGTOK_TRUE     },
	{   "NO",    	CFGTOK_FALSE    },
        {   "TRUE",     CFGTOK_TRUE     },
        {   "FALSE",    CFGTOK_FALSE    },
    };

    /* If we have an identifier, map it to a boolean token */
    if (CfgTok == CFGTOK_IDENT) {
	CfgSpecialToken (Booleans, ENTRY_COUNT (Booleans), "Boolean");
    } else {
	/* We expected an integer here */
	if (CfgTok != CFGTOK_INTCON) {
     	    CfgError ("Boolean value expected");
	}
	CfgTok = (CfgIVal == 0)? CFGTOK_FALSE : CFGTOK_TRUE;
    }
}
Ejemplo n.º 6
0
Archivo: scanner.c Proyecto: cc65/cc65
void InfoBoolToken (void)
/* Map an identifier or integer to a boolean token */
{
    static const IdentTok Booleans [] = {
        {   "YES",      INFOTOK_TRUE     },
        {   "NO",       INFOTOK_FALSE    },
        {   "TRUE",     INFOTOK_TRUE     },
        {   "FALSE",    INFOTOK_FALSE    },
        {   "ON",       INFOTOK_TRUE     },
        {   "OFF",      INFOTOK_FALSE    },
    };

    /* If we have an identifier, map it to a boolean token */
    if (InfoTok == INFOTOK_IDENT) {
        InfoSpecialToken (Booleans, ENTRY_COUNT (Booleans), "Boolean");
    } else {
        /* We expected an integer here */
        if (InfoTok != INFOTOK_INTCON) {
            InfoError ("Boolean value expected");
        }
        InfoTok = (InfoIVal == 0)? INFOTOK_FALSE : INFOTOK_TRUE;
    }
}
Ejemplo n.º 7
0
static void ParseO65 (void)
/* Parse the o65 format section */
{
    static const IdentTok Attributes [] = {
       	{   "EXPORT",   CFGTOK_EXPORT   	},
	{   "IMPORT",	CFGTOK_IMPORT		},
        {   "TYPE",     CFGTOK_TYPE     	},
       	{   "OS",      	CFGTOK_OS       	},
       	{   "ID",      	CFGTOK_ID       	},
       	{   "VERSION",  CFGTOK_VERSION          },
    };
    static const IdentTok Types [] = {
       	{   "SMALL",   	CFGTOK_SMALL    	},
       	{   "LARGE",   	CFGTOK_LARGE    	},
    };
    static const IdentTok OperatingSystems [] = {
       	{   "LUNIX",   	CFGTOK_LUNIX     	},
       	{   "OSA65",   	CFGTOK_OSA65    	},
        {   "CC65",     CFGTOK_CC65             },
        {   "OPENCBM",  CFGTOK_OPENCBM          },
    };

    /* 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 CfgSValId;
    unsigned OS = 0;            /* Initialize to keep gcc happy */
    unsigned Version = 0;

    /* Read the attributes */
    while (CfgTok == CFGTOK_IDENT) {

	/* Map the identifier to a token */
	cfgtok_t AttrTok;
       	CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
	AttrTok = CfgTok;

	/* An optional assignment follows */
	CfgNextTok ();
	CfgOptionalAssign ();

	/* Check which attribute was given */
	switch (AttrTok) {

	    case CFGTOK_EXPORT:
                /* Remember we had this token (maybe more than once) */
                AttrFlags |= atExport;
	      	/* We expect an identifier */
		CfgAssureIdent ();
                /* Convert the string into a string index */
                CfgSValId = GetStringId (CfgSVal);
	        /* Check if the export symbol is also defined as an import. */
	       	if (O65GetImport (O65FmtDesc, CfgSValId) != 0) {
		    CfgError ("Exported symbol `%s' cannot be an import", CfgSVal);
		}
      		/* Check if we have this symbol defined already. The entry
      	     	 * routine will check this also, but we get a more verbose
      		 * error message when checking it here.
      		 */
      	 	if (O65GetExport (O65FmtDesc, CfgSValId) != 0) {
      	  	    CfgError ("Duplicate exported symbol: `%s'", CfgSVal);
      	 	}
		/* Insert the symbol into the table */
	  	O65SetExport (O65FmtDesc, CfgSValId);
                /* Eat the identifier token */
                CfgNextTok ();
	    	break;

	    case CFGTOK_IMPORT:
                /* Remember we had this token (maybe more than once) */
                AttrFlags |= atImport;
	      	/* We expect an identifier */
		CfgAssureIdent ();
                /* Convert the string into a string index */
                CfgSValId = GetStringId (CfgSVal);
	        /* Check if the imported symbol is also defined as an export. */
	       	if (O65GetExport (O65FmtDesc, CfgSValId) != 0) {
		    CfgError ("Imported symbol `%s' cannot be an export", CfgSVal);
		}
      	    	/* Check if we have this symbol defined already. The entry
      	    	 * routine will check this also, but we get a more verbose
      	    	 * error message when checking it here.
      	    	 */
      	    	if (O65GetImport (O65FmtDesc, CfgSValId) != 0) {
      	    	    CfgError ("Duplicate imported symbol: `%s'", CfgSVal);
      	    	}
	    	/* Insert the symbol into the table */
	    	O65SetImport (O65FmtDesc, CfgSValId);
                /* Eat the identifier token */
                CfgNextTok ();
	    	break;

	    case CFGTOK_TYPE:
		/* Cannot have this attribute twice */
		FlagAttr (&AttrFlags, atType, "TYPE");
		/* Get the type of the executable */
		CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
		switch (CfgTok) {

		    case CFGTOK_SMALL:
		        O65SetSmallModel (O65FmtDesc);
		     	break;

		    case CFGTOK_LARGE:
		    	O65SetLargeModel (O65FmtDesc);
	    	     	break;

	    	    default:
	    	     	CfgError ("Unexpected type token");
	    	}
                /* Eat the attribute token */
                CfgNextTok ();
	     	break;

	    case CFGTOK_OS:
	     	/* Cannot use this attribute twice */
	     	FlagAttr (&AttrFlags, atOS, "OS");
	     	/* Get the operating system. It may be specified as name or
                 * as a number in the range 1..255.
                 */
		if (CfgTok == CFGTOK_INTCON) {
		    CfgRangeCheck (O65OS_MIN, O65OS_MAX);
		    OS = (unsigned) CfgIVal;
		} else {
                    CfgSpecialToken (OperatingSystems, ENTRY_COUNT (OperatingSystems), "OS type");
                    switch (CfgTok) {
                        case CFGTOK_LUNIX:    OS = O65OS_LUNIX;     break;
                        case CFGTOK_OSA65:    OS = O65OS_OSA65;     break;
                        case CFGTOK_CC65:     OS = O65OS_CC65;      break;
                        case CFGTOK_OPENCBM:  OS = O65OS_OPENCBM;   break;
                        default:              CfgError ("Unexpected OS token");
                    }
                }
                CfgNextTok ();
	     	break;

            case CFGTOK_ID:
                /* Cannot have this attribute twice */
                FlagAttr (&AttrFlags, atID, "ID");
                /* We're expecting a number in the 0..$FFFF range*/
                ModuleId = (unsigned) CfgCheckedIntExpr (0, 0xFFFF);
                break;

            case CFGTOK_VERSION:
                /* Cannot have this attribute twice */
                FlagAttr (&AttrFlags, atVersion, "VERSION");
                /* We're expecting a number in byte range */
                Version = (unsigned) CfgCheckedIntExpr (0, 0xFF);
                break;

	    default:
		FAIL ("Unexpected attribute token");

	}

	/* Skip an optional comma */
	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 && ModuleId < 0x8000) {
            CfgError ("OS type CC65 may not have imports or exports for ids < $8000");
        }
    } else {
        if (AttrFlags & atID) {
            CfgError ("Operating system does not support the ID attribute");
        }
    }

    /* Set the O65 operating system to use */
    O65SetOS (O65FmtDesc, OS, Version, ModuleId);
}
Ejemplo n.º 8
0
static void AsmIncSection (void)
/* Parse a asminc section */
{
    static const IdentTok LabelDefs[] = {
        {   "COMMENTSTART",     INFOTOK_COMMENTSTART    },
        {   "FILE",             INFOTOK_FILE            },
        {   "IGNOREUNKNOWN",    INFOTOK_IGNOREUNKNOWN   },
    };

    /* Locals - initialize to avoid gcc warnings */
    char* Name = 0;
    int CommentStart = EOF;
    int IgnoreUnknown = -1;

    /* Skip the token */
    InfoNextTok ();

    /* Expect the opening curly brace */
    InfoConsumeLCurly ();

    /* Look for section tokens */
    while (InfoTok != INFOTOK_RCURLY) {

        /* Convert to special token */
        InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Asminc directive");

        /* Look at the token */
        switch (InfoTok) {

            case INFOTOK_COMMENTSTART:
                InfoNextTok ();
                if (CommentStart != EOF) {
                    InfoError ("Commentstart already given");
                }
                InfoAssureChar ();
                CommentStart = (char) InfoIVal;
                InfoNextTok ();
                break;

            case INFOTOK_FILE:
                InfoNextTok ();
                if (Name) {
                    InfoError ("File name already given");
                }
                InfoAssureStr ();
                if (InfoSVal[0] == '\0') {
                    InfoError ("File name may not be empty");
                }
                Name = xstrdup (InfoSVal);
                InfoNextTok ();
                break;

            case INFOTOK_IGNOREUNKNOWN:
                InfoNextTok ();
                if (IgnoreUnknown != -1) {
                    InfoError ("Ignoreunknown already specified");
                }
                InfoBoolToken ();
                IgnoreUnknown = (InfoTok != INFOTOK_FALSE);
                InfoNextTok ();
                break;

            default:
                Internal ("Unexpected token: %u", InfoTok);
        }

        /* Directive is followed by a semicolon */
        InfoConsumeSemi ();
    }

    /* Check for the necessary data and assume defaults */
    if (Name == 0) {
        InfoError ("File name is missing");
    }
    if (CommentStart == EOF) {
        CommentStart = ';';
    }
    if (IgnoreUnknown == -1) {
        IgnoreUnknown = 0;
    }

    /* Open the file and read the symbol definitions */
    AsmInc (Name, CommentStart, IgnoreUnknown);

    /* Delete the dynamically allocated memory for Name */
    xfree (Name);

    /* Consume the closing brace */
    InfoConsumeRCurly ();
}
Ejemplo n.º 9
0
static void ParseStartAddress (void)
/* Parse the STARTADDRESS feature */
{
    static const IdentTok Attributes [] = {
       	{   "DEFAULT",  CFGTOK_DEFAULT },
    };


    /* Attribute values. */
    unsigned long DefStartAddr = 0;

    /* Bitmask to remember the attributes we got already */
    enum {
	atNone		= 0x0000,
       	atDefault       = 0x0001
    };
    unsigned AttrFlags = atNone;

    /* Parse the attributes */
    while (1) {

	/* Map the identifier to a token */
	cfgtok_t AttrTok;
       	CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
	AttrTok = CfgTok;

	/* An optional assignment follows */
	CfgNextTok ();
	CfgOptionalAssign ();

	/* Check which attribute was given */
	switch (AttrTok) {

	    case CFGTOK_DEFAULT:
	  	/* Don't allow this twice */
		FlagAttr (&AttrFlags, atDefault, "DEFAULT");
	      	/* We expect a numeric expression */
                DefStartAddr = CfgCheckedIntExpr (0, 0xFFFFFF);
	    	break;

	    default:
		FAIL ("Unexpected attribute token");

	}

	/* Semicolon ends the ConDes decl, otherwise accept an optional comma */
	if (CfgTok == CFGTOK_SEMI) {
	    break;
	} else if (CfgTok == CFGTOK_COMMA) {
	    CfgNextTok ();
	}
    }

    /* Check if we have all mandatory attributes */
    AttrCheck (AttrFlags, atDefault, "DEFAULT");

    /* If no start address was given on the command line, use the one given
     * here
     */
    if (!HaveStartAddr) {
        StartAddr = DefStartAddr;
    }
}
Ejemplo n.º 10
0
static void SegmentSection (void)
/* Parse a segment section */
{
    static const IdentTok LabelDefs[] = {
        {   "END",      INFOTOK_END     },
        {   "NAME",     INFOTOK_NAME    },
        {   "START",    INFOTOK_START   },
    };

    /* Locals - initialize to avoid gcc warnings */
    long End    = -1;
    long Start  = -1;
    char* Name  = 0;

    /* Skip the token */
    InfoNextTok ();

    /* Expect the opening curly brace */
    InfoConsumeLCurly ();

    /* Look for section tokens */
    while (InfoTok != INFOTOK_RCURLY) {

        /* Convert to special token */
        InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Segment attribute");

        /* Look at the token */
        switch (InfoTok) {

            case INFOTOK_END:
                InfoNextTok ();
                if (End >= 0) {
                    InfoError ("Value already given");
                }
                InfoAssureInt ();
                InfoRangeCheck (0, 0xFFFF);
                End = InfoIVal;
                InfoNextTok ();
                break;

            case INFOTOK_NAME:
                InfoNextTok ();
                if (Name) {
                    InfoError ("Name already given");
                }
                InfoAssureStr ();
                Name = xstrdup (InfoSVal);
                InfoNextTok ();
                break;

            case INFOTOK_START:
                InfoNextTok ();
                if (Start >= 0) {
                    InfoError ("Value already given");
                }
                InfoAssureInt ();
                InfoRangeCheck (0, 0xFFFF);
                Start = InfoIVal;
                InfoNextTok ();
                break;

            default:
                Internal ("Unexpected token: %u", InfoTok);
        }

        /* Directive is followed by a semicolon */
        InfoConsumeSemi ();
    }

    /* Did we get the necessary data, and is it correct? */
    if (Name == 0 || Name[0] == '\0') {
        InfoError ("Segment name is missing");
    }
    if (End < 0) {
        InfoError ("End address is missing");
    }
    if (Start < 0) {
        InfoError ("Start address is missing");
    }
    if (Start > End) {
        InfoError ("Start address of segment is greater than end address");
    }

    /* Check that segments do not overlap */
    if (SegmentDefined ((unsigned) Start, (unsigned) End)) {
        InfoError ("Segments must not overlap");
    }

    /* Remember the segment data */
    AddAbsSegment ((unsigned) Start, (unsigned) End, Name);

    /* Delete the dynamically allocated memory for Name */
    xfree (Name);

    /* Consume the closing brace */
    InfoConsumeRCurly ();
}
Ejemplo n.º 11
0
static void RangeSection (void)
/* Parse a range section */
{
    static const IdentTok RangeDefs[] = {
        {   "COMMENT",          INFOTOK_COMMENT },
        {   "END",              INFOTOK_END     },
        {   "NAME",             INFOTOK_NAME    },
        {   "START",            INFOTOK_START   },
        {   "TYPE",             INFOTOK_TYPE    },
    };

    static const IdentTok TypeDefs[] = {
        {   "ADDRTABLE",        INFOTOK_ADDRTAB  },
        {   "BYTETABLE",        INFOTOK_BYTETAB  },
        {   "CODE",             INFOTOK_CODE     },
        {   "DBYTETABLE",       INFOTOK_DBYTETAB },
        {   "DWORDTABLE",       INFOTOK_DWORDTAB },
        {   "RTSTABLE",         INFOTOK_RTSTAB   },
        {   "SKIP",             INFOTOK_SKIP     },
        {   "TEXTTABLE",        INFOTOK_TEXTTAB  },
        {   "WORDTABLE",        INFOTOK_WORDTAB  },
    };


    /* Which values did we get? */
    enum {
        tNone   = 0x00,
        tStart  = 0x01,
        tEnd    = 0x02,
        tType   = 0x04,
        tName   = 0x08,
        tComment= 0x10,
        tNeeded = (tStart | tEnd | tType)
    };
    unsigned Attributes = tNone;

    /* Locals - initialize to avoid gcc warnings */
    unsigned Start      = 0;
    unsigned End        = 0;
    unsigned char Type  = 0;
    char* Name          = 0;
    char* Comment       = 0;
    unsigned MemberSize = 0;


    /* Skip the token */
    InfoNextTok ();

    /* Expect the opening curly brace */
    InfoConsumeLCurly ();

    /* Look for section tokens */
    while (InfoTok != INFOTOK_RCURLY) {

        /* Convert to special token */
        InfoSpecialToken (RangeDefs, ENTRY_COUNT (RangeDefs), "Range attribute");

        /* Look at the token */
        switch (InfoTok) {

            case INFOTOK_COMMENT:
                AddAttr ("COMMENT", &Attributes, tComment);
                InfoNextTok ();
                InfoAssureStr ();
                if (InfoSVal[0] == '\0') {
                    InfoError ("Comment may not be empty");
                }
                Comment = xstrdup (InfoSVal);
                Attributes |= tComment;
                InfoNextTok ();
                break;

            case INFOTOK_END:
                AddAttr ("END", &Attributes, tEnd);
                InfoNextTok ();
                InfoAssureInt ();
                InfoRangeCheck (0x0000, 0xFFFF);
                End = InfoIVal;
                InfoNextTok ();
                break;

            case INFOTOK_NAME:
                AddAttr ("NAME", &Attributes, tName);
                InfoNextTok ();
                InfoAssureStr ();
                if (InfoSVal[0] == '\0') {
                    InfoError ("Name may not be empty");
                }
                Name = xstrdup (InfoSVal);
                Attributes |= tName;
                InfoNextTok ();
                break;

            case INFOTOK_START:
                AddAttr ("START", &Attributes, tStart);
                InfoNextTok ();
                InfoAssureInt ();
                InfoRangeCheck (0x0000, 0xFFFF);
                Start = InfoIVal;
                InfoNextTok ();
                break;

            case INFOTOK_TYPE:
                AddAttr ("TYPE", &Attributes, tType);
                InfoNextTok ();
                InfoSpecialToken (TypeDefs, ENTRY_COUNT (TypeDefs), "TYPE");
                switch (InfoTok) {
                    case INFOTOK_ADDRTAB:  Type = atAddrTab;  MemberSize = 2; break;
                    case INFOTOK_BYTETAB:  Type = atByteTab;  MemberSize = 1; break;
                    case INFOTOK_CODE:     Type = atCode;     MemberSize = 1; break;
                    case INFOTOK_DBYTETAB: Type = atDByteTab; MemberSize = 2; break;
                    case INFOTOK_DWORDTAB: Type = atDWordTab; MemberSize = 4; break;
                    case INFOTOK_RTSTAB:   Type = atRtsTab;   MemberSize = 2; break;
                    case INFOTOK_SKIP:     Type = atSkip;     MemberSize = 1; break;
                    case INFOTOK_TEXTTAB:  Type = atTextTab;  MemberSize = 1; break;
                    case INFOTOK_WORDTAB:  Type = atWordTab;  MemberSize = 2; break;
                }
                InfoNextTok ();
                break;

            default:
                Internal ("Unexpected token: %u", InfoTok);
        }

        /* Directive is followed by a semicolon */
        InfoConsumeSemi ();

    }

    /* Did we get all required values? */
    if ((Attributes & tNeeded) != tNeeded) {
        InfoError ("Required values missing from this section");
    }

    /* Start must be less than end */
    if (Start > End) {
        InfoError ("Start value must not be greater than end value");
    }

    /* Check the granularity */
    if (((End - Start + 1) % MemberSize) != 0) {
        InfoError ("Type of range needs a granularity of %u", MemberSize);
    }

    /* Set the range */
    MarkRange (Start, End, Type);

    /* Do we have a label? */
    if (Attributes & tName) {

        /* Define a label for the table */
        AddExtLabel (Start, Name);

        /* Set the comment if we have one */
        if (Comment) {
            SetComment (Start, Comment);
        }

        /* Delete name and comment */
        xfree (Name);
        xfree (Comment);
    }

    /* Consume the closing brace */
    InfoConsumeRCurly ();
}
Ejemplo n.º 12
0
static void LabelSection (void)
/* Parse a label section */
{
    static const IdentTok LabelDefs[] = {
        {   "COMMENT",  INFOTOK_COMMENT },
        {   "ADDR",     INFOTOK_ADDR    },
        {   "NAME",     INFOTOK_NAME    },
        {   "SIZE",     INFOTOK_SIZE    },
    };

    /* Locals - initialize to avoid gcc warnings */
    char* Name    = 0;
    char* Comment = 0;
    long Value    = -1;
    long Size     = -1;

    /* Skip the token */
    InfoNextTok ();

    /* Expect the opening curly brace */
    InfoConsumeLCurly ();

    /* Look for section tokens */
    while (InfoTok != INFOTOK_RCURLY) {

        /* Convert to special token */
        InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Label attribute");

        /* Look at the token */
        switch (InfoTok) {

            case INFOTOK_ADDR:
                InfoNextTok ();
                if (Value >= 0) {
                    InfoError ("Value already given");
                }
                InfoAssureInt ();
                InfoRangeCheck (0, 0xFFFF);
                Value = InfoIVal;
                InfoNextTok ();
                break;

            case INFOTOK_COMMENT:
                InfoNextTok ();
                if (Comment) {
                    InfoError ("Comment already given");
                }
                InfoAssureStr ();
                if (InfoSVal[0] == '\0') {
                    InfoError ("Comment may not be empty");
                }
                Comment = xstrdup (InfoSVal);
                InfoNextTok ();
                break;

            case INFOTOK_NAME:
                InfoNextTok ();
                if (Name) {
                    InfoError ("Name already given");
                }
                InfoAssureStr ();
                Name = xstrdup (InfoSVal);
                InfoNextTok ();
                break;

            case INFOTOK_SIZE:
                InfoNextTok ();
                if (Size >= 0) {
                    InfoError ("Size already given");
                }
                InfoAssureInt ();
                InfoRangeCheck (1, 0x10000);
                Size = InfoIVal;
                InfoNextTok ();
                break;

            default:
                Internal ("Unexpected token: %u", InfoTok);
        }

        /* Directive is followed by a semicolon */
        InfoConsumeSemi ();
    }

    /* Did we get the necessary data */
    if (Name == 0) {
        InfoError ("Label name is missing");
    }
    if (Name[0] == '\0' && Size > 1) {
        InfoError ("Unnamed labels must not have a size > 1");
    }
    if (Value < 0) {
        InfoError ("Label value is missing");
    }
    if (Size < 0) {
        /* Use default */
        Size = 1;
    }
    if (Value + Size > 0x10000) {
        InfoError ("Invalid size (address out of range)");
    }
    if (HaveLabel ((unsigned) Value)) {
        InfoError ("Label for address $%04lX already defined", Value);
    }

    /* Define the label(s) */
    if (Name[0] == '\0') {
        /* Size has already beed checked */
        AddUnnamedLabel (Value);
    } else {
        AddExtLabelRange ((unsigned) Value, Name, Size);
    }

    /* Define the comment */
    if (Comment) {
        SetComment (Value, Comment);
    }

    /* Delete the dynamically allocated memory for Name and Comment */
    xfree (Name);
    xfree (Comment);

    /* Consume the closing brace */
    InfoConsumeRCurly ();
}
Ejemplo n.º 13
0
static void GlobalSection (void)
/* Parse a global section */
{
    static const IdentTok GlobalDefs[] = {
        {   "ARGUMENTCOL",      INFOTOK_ARGUMENT_COLUMN },
        {   "ARGUMENTCOLUMN",   INFOTOK_ARGUMENT_COLUMN },
        {   "COMMENTCOL",       INFOTOK_COMMENT_COLUMN  },
        {   "COMMENTCOLUMN",    INFOTOK_COMMENT_COLUMN  },
        {   "COMMENTS",         INFOTOK_COMMENTS        },
        {   "CPU",              INFOTOK_CPU             },
        {   "HEXOFFS",          INFOTOK_HEXOFFS         },
        {   "INPUTNAME",        INFOTOK_INPUTNAME       },
        {   "INPUTOFFS",        INFOTOK_INPUTOFFS       },
        {   "INPUTSIZE",        INFOTOK_INPUTSIZE       },
        {   "LABELBREAK",       INFOTOK_LABELBREAK      },
        {   "MNEMONICCOL",      INFOTOK_MNEMONIC_COLUMN },
        {   "MNEMONICCOLUMN",   INFOTOK_MNEMONIC_COLUMN },
        {   "NEWLINEAFTERJMP",  INFOTOK_NL_AFTER_JMP    },
        {   "NEWLINEAFTERRTS",  INFOTOK_NL_AFTER_RTS    },
        {   "OUTPUTNAME",       INFOTOK_OUTPUTNAME      },
        {   "PAGELENGTH",       INFOTOK_PAGELENGTH      },
        {   "STARTADDR",        INFOTOK_STARTADDR       },
        {   "TEXTCOL",          INFOTOK_TEXT_COLUMN     },
        {   "TEXTCOLUMN",       INFOTOK_TEXT_COLUMN     },
    };

    /* Skip the token */
    InfoNextTok ();

    /* Expect the opening curly brace */
    InfoConsumeLCurly ();

    /* Look for section tokens */
    while (InfoTok != INFOTOK_RCURLY) {

        /* Convert to special token */
        InfoSpecialToken (GlobalDefs, ENTRY_COUNT (GlobalDefs), "Global directive");

        /* Look at the token */
        switch (InfoTok) {

            case INFOTOK_ARGUMENT_COLUMN:
                InfoNextTok ();
                InfoAssureInt ();
                InfoRangeCheck (MIN_ACOL, MAX_ACOL);
                ACol = InfoIVal;
                InfoNextTok ();
                break;

            case INFOTOK_COMMENT_COLUMN:
                InfoNextTok ();
                InfoAssureInt ();
                InfoRangeCheck (MIN_CCOL, MAX_CCOL);
                CCol = InfoIVal;
                InfoNextTok ();
                break;

            case INFOTOK_COMMENTS:
                InfoNextTok ();
                InfoAssureInt ();
                InfoRangeCheck (MIN_COMMENTS, MAX_COMMENTS);
                Comments = InfoIVal;
                InfoNextTok ();
                break;

            case INFOTOK_CPU:
                InfoNextTok ();
                InfoAssureStr ();
                if (CPU != CPU_UNKNOWN) {
                    InfoError ("CPU already specified");
                }
                CPU = FindCPU (InfoSVal);
                SetOpcTable (CPU);
                InfoNextTok ();
                break;

            case INFOTOK_HEXOFFS:
                InfoNextTok ();
                InfoBoolToken ();
                switch (InfoTok) {
                    case INFOTOK_FALSE: UseHexOffs = 0; break;
                    case INFOTOK_TRUE:  UseHexOffs = 1; break;
                }
                InfoNextTok ();
                break;

            case INFOTOK_INPUTNAME:
                InfoNextTok ();
                InfoAssureStr ();
                if (InFile) {
                    InfoError ("Input file name already given");
                }
                InFile = xstrdup (InfoSVal);
                InfoNextTok ();
                break;

            case INFOTOK_INPUTOFFS:
                InfoNextTok ();
                InfoAssureInt ();
                InputOffs = InfoIVal;
                InfoNextTok ();
                break;

            case INFOTOK_INPUTSIZE:
                InfoNextTok ();
                InfoAssureInt ();
                InfoRangeCheck (1, 0x10000);
                InputSize = InfoIVal;
                InfoNextTok ();
                break;

            case INFOTOK_LABELBREAK:
                InfoNextTok ();
                InfoAssureInt ();
                InfoRangeCheck (0, UCHAR_MAX);
                LBreak = (unsigned char) InfoIVal;
                InfoNextTok ();
                break;

            case INFOTOK_MNEMONIC_COLUMN:
                InfoNextTok ();
                InfoAssureInt ();
                InfoRangeCheck (MIN_MCOL, MAX_MCOL);
                MCol = InfoIVal;
                InfoNextTok ();
                break;

            case INFOTOK_NL_AFTER_JMP:
                InfoNextTok ();
                if (NewlineAfterJMP != -1) {
                    InfoError ("NLAfterJMP already specified");
                }
                InfoBoolToken ();
                NewlineAfterJMP = (InfoTok != INFOTOK_FALSE);
                InfoNextTok ();
                break;

            case INFOTOK_NL_AFTER_RTS:
                InfoNextTok ();
                InfoBoolToken ();
                if (NewlineAfterRTS != -1) {
                    InfoError ("NLAfterRTS already specified");
                }
                NewlineAfterRTS = (InfoTok != INFOTOK_FALSE);
                InfoNextTok ();
                break;

            case INFOTOK_OUTPUTNAME:
                InfoNextTok ();
                InfoAssureStr ();
                if (OutFile) {
                    InfoError ("Output file name already given");
                }
                OutFile = xstrdup (InfoSVal);
                InfoNextTok ();
                break;

            case INFOTOK_PAGELENGTH:
                InfoNextTok ();
                InfoAssureInt ();
                if (InfoIVal != 0) {
                    InfoRangeCheck (MIN_PAGE_LEN, MAX_PAGE_LEN);
                }
                PageLength = InfoIVal;
                InfoNextTok ();
                break;

            case INFOTOK_STARTADDR:
                InfoNextTok ();
                InfoAssureInt ();
                InfoRangeCheck (0x0000, 0xFFFF);
                StartAddr = InfoIVal;
                InfoNextTok ();
                break;

            case INFOTOK_TEXT_COLUMN:
                InfoNextTok ();
                InfoAssureInt ();
                InfoRangeCheck (MIN_TCOL, MAX_TCOL);
                TCol = InfoIVal;
                InfoNextTok ();
                break;

            default:
                Internal ("Unexpected token: %u", InfoTok);

        }

        /* Directive is followed by a semicolon */
        InfoConsumeSemi ();

    }

    /* Consume the closing brace */
    InfoConsumeRCurly ();
}
Ejemplo n.º 14
0
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		},
    };

    static const IdentTok Types [] = {
       	{   "CONSTRUCTOR",	CFGTOK_CONSTRUCTOR	},
	{   "DESTRUCTOR",      	CFGTOK_DESTRUCTOR	},
        {   "INTERRUPTOR",      CFGTOK_INTERRUPTOR      },
    };

    static const IdentTok Orders [] = {
	{   "DECREASING",      	CFGTOK_DECREASING	},
       	{   "INCREASING",      	CFGTOK_INCREASING	},
    };

    /* Attribute values. */
    unsigned SegName = INVALID_STRING_ID;
    unsigned Label   = INVALID_STRING_ID;
    unsigned Count   = INVALID_STRING_ID;
    /* Initialize to avoid gcc warnings: */
    int Type = -1;
    ConDesOrder Order = cdIncreasing;

    /* Bitmask to remember the attributes we got already */
    enum {
	atNone	   	= 0x0000,
	atSegName  	= 0x0001,
	atLabel	   	= 0x0002,
	atCount	   	= 0x0004,
	atType	   	= 0x0008,
	atOrder	   	= 0x0010
    };
    unsigned AttrFlags = atNone;

    /* Parse the attributes */
    while (1) {

	/* Map the identifier to a token */
	cfgtok_t AttrTok;
       	CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
	AttrTok = CfgTok;

	/* An optional assignment follows */
	CfgNextTok ();
	CfgOptionalAssign ();

	/* Check which attribute was given */
	switch (AttrTok) {

	    case CFGTOK_SEGMENT:
	  	/* Don't allow this twice */
		FlagAttr (&AttrFlags, atSegName, "SEGMENT");
	      	/* We expect an identifier */
		CfgAssureIdent ();
		/* Remember the value for later */
		SegName = GetStringId (CfgSVal);
	    	break;

	    case CFGTOK_LABEL:
	       	/* Don't allow this twice */
		FlagAttr (&AttrFlags, atLabel, "LABEL");
	      	/* We expect an identifier */
		CfgAssureIdent ();
		/* Remember the value for later */
		Label = GetStringId (CfgSVal);
		break;

	    case CFGTOK_COUNT:
	       	/* Don't allow this twice */
		FlagAttr (&AttrFlags, atCount, "COUNT");
	      	/* We expect an identifier */
		CfgAssureIdent ();
		/* Remember the value for later */
		Count = GetStringId (CfgSVal);
		break;

	    case CFGTOK_TYPE:
	  	/* Don't allow this twice */
		FlagAttr (&AttrFlags, atType, "TYPE");
		/* The type may be given as id or numerical */
		if (CfgTok == CFGTOK_INTCON) {
		    CfgRangeCheck (CD_TYPE_MIN, CD_TYPE_MAX);
		    Type = (int) CfgIVal;
		} else {
		    CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
		    switch (CfgTok) {
		     	case CFGTOK_CONSTRUCTOR: Type = CD_TYPE_CON;	break;
		     	case CFGTOK_DESTRUCTOR:	 Type = CD_TYPE_DES;	break;
                        case CFGTOK_INTERRUPTOR: Type = CD_TYPE_INT;    break;
	     	     	default: FAIL ("Unexpected type token");
		    }
		}
		break;

	    case CFGTOK_ORDER:
	       	/* Don't allow this twice */
		FlagAttr (&AttrFlags, atOrder, "ORDER");
		CfgSpecialToken (Orders, ENTRY_COUNT (Orders), "Order");
		switch (CfgTok) {
		    case CFGTOK_DECREASING: Order = cdDecreasing;	break;
		    case CFGTOK_INCREASING: Order = cdIncreasing;	break;
		    default: FAIL ("Unexpected order token");
		}
		break;

	    default:
		FAIL ("Unexpected attribute token");

	}

       	/* Skip the attribute value */
	CfgNextTok ();

	/* Semicolon ends the ConDes decl, otherwise accept an optional comma */
	if (CfgTok == CFGTOK_SEMI) {
	    break;
	} else if (CfgTok == CFGTOK_COMMA) {
	    CfgNextTok ();
	}
    }

    /* Check if we have all mandatory attributes */
    AttrCheck (AttrFlags, atSegName, "SEGMENT");
    AttrCheck (AttrFlags, atLabel, "LABEL");
    AttrCheck (AttrFlags, atType, "TYPE");

    /* Check if the condes has already attributes defined */
    if (ConDesHasSegName(Type) || ConDesHasLabel(Type)) {
	CfgError ("CONDES attributes for type %d are already defined", Type);
    }

    /* Define the attributes */
    ConDesSetSegName (Type, SegName);
    ConDesSetLabel (Type, Label);
    if (AttrFlags & atCount) {
	ConDesSetCountSym (Type, Count);
    }
    if (AttrFlags & atOrder) {
	ConDesSetOrder (Type, Order);
    }
}
Ejemplo n.º 15
0
static void ParseSegments (void)
/* Parse a SEGMENTS section */
{
    static const IdentTok Attributes [] = {
        {   "ALIGN",            CFGTOK_ALIGN            },
        {   "ALIGN_LOAD",       CFGTOK_ALIGN_LOAD       },
        {   "DEFINE",           CFGTOK_DEFINE           },
       	{   "LOAD",    	        CFGTOK_LOAD             },
	{   "OFFSET",  	        CFGTOK_OFFSET           },
        {   "OPTIONAL",         CFGTOK_OPTIONAL         },
	{   "RUN",     	        CFGTOK_RUN              },
	{   "START",   	        CFGTOK_START            },
        {   "TYPE",             CFGTOK_TYPE             },
    };
    static const IdentTok Types [] = {
       	{   "RO",      	        CFGTOK_RO               },
       	{   "RW",      	        CFGTOK_RW               },
       	{   "BSS",     	        CFGTOK_BSS              },
	{   "ZP",      	        CFGTOK_ZP	        },
    };

    unsigned Count;
    long     Val;

    /* The MEMORY section must preceed the SEGMENTS section */
    if ((SectionsEncountered & SE_MEMORY) == 0) {
        CfgError ("MEMORY must precede SEGMENTS");
    }

    while (CfgTok == CFGTOK_IDENT) {

	SegDesc* S;

	/* Create a new entry on the heap */
       	S = NewSegDesc (GetStringId (CfgSVal));

	/* Skip the name and the following colon */
	CfgNextTok ();
	CfgConsumeColon ();

       	/* Read the attributes */
	while (CfgTok == CFGTOK_IDENT) {

	    /* Map the identifier to a token */
	    cfgtok_t AttrTok;
	    CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
	    AttrTok = CfgTok;

	    /* An optional assignment follows */
	    CfgNextTok ();
	    CfgOptionalAssign ();

	    /* Check which attribute was given */
	    switch (AttrTok) {

	        case CFGTOK_ALIGN:
	    	    FlagAttr (&S->Attr, SA_ALIGN, "ALIGN");
	    	    Val = CfgCheckedIntExpr (1, 0x10000);
	    	    S->Align = BitFind (Val);
	    	    if ((0x01L << S->Align) != Val) {
	    	     	CfgError ("Alignment must be a power of 2");
	    	    }
	    	    S->Flags |= SF_ALIGN;
	    	    break;

                case CFGTOK_ALIGN_LOAD:
	    	    FlagAttr (&S->Attr, SA_ALIGN_LOAD, "ALIGN_LOAD");
	    	    Val = CfgCheckedIntExpr (1, 0x10000);
       	       	    S->AlignLoad = BitFind (Val);
	    	    if ((0x01L << S->AlignLoad) != Val) {
	    	     	CfgError ("Alignment must be a power of 2");
	    	    }
	    	    S->Flags |= SF_ALIGN_LOAD;
	    	    break;

	        case CFGTOK_DEFINE:
 	    	    FlagAttr (&S->Attr, SA_DEFINE, "DEFINE");
	    	    /* Map the token to a boolean */
	    	    CfgBoolToken ();
	    	    if (CfgTok == CFGTOK_TRUE) {
	    	     	S->Flags |= SF_DEFINE;
	    	    }
                    CfgNextTok ();
	    	    break;

	    	case CFGTOK_LOAD:
	      	    FlagAttr (&S->Attr, SA_LOAD, "LOAD");
	    	    S->Load = CfgGetMemory (GetStringId (CfgSVal));
                    CfgNextTok ();
	    	    break;

	        case CFGTOK_OFFSET:
	    	    FlagAttr (&S->Attr, SA_OFFSET, "OFFSET");
	    	    S->Addr   = CfgCheckedIntExpr (1, 0x1000000);
	    	    S->Flags |= SF_OFFSET;
	    	    break;

	        case CFGTOK_OPTIONAL:
	    	    FlagAttr (&S->Attr, SA_OPTIONAL, "OPTIONAL");
		    CfgBoolToken ();
		    if (CfgTok == CFGTOK_TRUE) {
	  	    	S->Flags |= SF_OPTIONAL;
		    }
                    CfgNextTok ();
	    	    break;

	    	case CFGTOK_RUN:
      	    	    FlagAttr (&S->Attr, SA_RUN, "RUN");
 	    	    S->Run = CfgGetMemory (GetStringId (CfgSVal));
                    CfgNextTok ();
	    	    break;

	        case CFGTOK_START:
	    	    FlagAttr (&S->Attr, SA_START, "START");
	    	    S->Addr   = CfgCheckedIntExpr (1, 0x1000000);
	    	    S->Flags |= SF_START;
	    	    break;

	    	case CFGTOK_TYPE:
 	    	    FlagAttr (&S->Attr, SA_TYPE, "TYPE");
       	    	    CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
	    	    switch (CfgTok) {
       	       	       	case CFGTOK_RO:	   S->Flags |= SF_RO;               break;
	    		case CFGTOK_RW:	   /* Default */		    break;
	    	     	case CFGTOK_BSS:   S->Flags |= SF_BSS;              break;
	    	     	case CFGTOK_ZP:	   S->Flags |= (SF_BSS | SF_ZP);    break;
	    	     	default:      	   Internal ("Unexpected token: %d", CfgTok);
	    	    }
                    CfgNextTok ();
	    	    break;

	    	default:
       	       	    FAIL ("Unexpected attribute token");

	    }

	    /* Skip an optional comma */
	    CfgOptionalComma ();
	}

	/* Check for mandatory parameters */
	AttrCheck (S->Attr, SA_LOAD, "LOAD");

 	/* Set defaults for stuff not given */
	if ((S->Attr & SA_RUN) == 0) {
	    S->Attr |= SA_RUN;
	    S->Run = S->Load;
	}

	/* If the segment is marked as BSS style, and if the segment exists
         * in any of the object file, check that there's no initialized data
         * in the segment.
	 */
	if ((S->Flags & SF_BSS) != 0 && S->Seg != 0 && !IsBSSType (S->Seg)) {
	    Warning ("%s(%u): Segment with type `bss' contains initialized data",
	    	     CfgGetName (), CfgErrorLine);
	}

        /* An attribute of ALIGN_LOAD doesn't make sense if there are no
         * separate run and load memory areas.
         */
        if ((S->Flags & SF_ALIGN_LOAD) != 0 && (S->Load == S->Run)) {
       	    Warning ("%s(%u): ALIGN_LOAD attribute specified, but no separate "
                     "LOAD and RUN memory areas assigned",
                     CfgGetName (), CfgErrorLine);
            /* Remove the flag */
            S->Flags &= ~SF_ALIGN_LOAD;
        }

        /* If the segment is marked as BSS style, it may not have separate
         * load and run memory areas, because it's is never written to disk.
         */
        if ((S->Flags & SF_BSS) != 0 && (S->Load != S->Run)) {
       	    Warning ("%s(%u): Segment with type `bss' has both LOAD and RUN "
                     "memory areas assigned", CfgGetName (), CfgErrorLine);
        }

      	/* Don't allow read/write data to be put into a readonly area */
      	if ((S->Flags & SF_RO) == 0) {
       	    if (S->Run->Flags & MF_RO) {
      	    	CfgError ("Cannot put r/w segment `%s' in r/o memory area `%s'",
      	    	     	  GetString (S->Name), GetString (S->Run->Name));
      	    }
      	}

      	/* Only one of ALIGN, START and OFFSET may be used */
       	Count = ((S->Flags & SF_ALIGN)  != 0) +
      	       	((S->Flags & SF_OFFSET) != 0) +
      	    	((S->Flags & SF_START)  != 0);
      	if (Count > 1) {
       	    CfgError ("Only one of ALIGN, START, OFFSET may be used");
      	}

      	/* If this segment does exist in any of the object files, insert the
      	 * descriptor into the list of segment descriptors. Otherwise print a
         * warning and discard it, because the segment pointer in the
         * descriptor is invalid.
      	 */
      	if (S->Seg != 0) {
	    /* Insert the descriptor into the list of all descriptors */
	    SegDescInsert (S);
      	    /* Insert the segment into the memory area list */
      	    MemoryInsert (S->Run, S);
      	    if (S->Load != S->Run) {
      	    	/* We have separate RUN and LOAD areas */
      	    	MemoryInsert (S->Load, S);
      	    }
      	} else {
            /* Print a warning if the segment is not optional */
            if ((S->Flags & SF_OPTIONAL) == 0) {
                CfgWarning ("Segment `%s' does not exist", GetString (S->Name));
            }
      	    /* Discard the descriptor */
      	    FreeSegDesc (S);
      	}

	/* Skip the semicolon */
	CfgConsumeSemi ();
    }

    /* Remember we had this section */
    SectionsEncountered |= SE_SEGMENTS;
}
Ejemplo n.º 16
0
static void ParseFiles (void)
/* Parse a FILES section */
{
    static const IdentTok Attributes [] = {
       	{   "FORMAT",  	CFGTOK_FORMAT   },
    };
    static const IdentTok Formats [] = {
       	{   "O65",     	CFGTOK_O65  	     },
       	{   "BIN",     	CFGTOK_BIN      },
       	{   "BINARY",   CFGTOK_BIN      },
    };


    /* The MEMORY section must preceed the FILES section */
    if ((SectionsEncountered & SE_MEMORY) == 0) {
        CfgError ("MEMORY must precede FILES");
    }

    /* Parse all files */
    while (CfgTok != CFGTOK_RCURLY) {

	File* F;

	/* We expect a string value here */
	CfgAssureStr ();

	/* Search for the file, it must exist */
       	F = FindFile (GetStringId (CfgSVal));
	if (F == 0) {
       	    CfgError ("File `%s' not found in MEMORY section", CfgSVal);
	}

	/* Skip the token and the following colon */
	CfgNextTok ();
	CfgConsumeColon ();

	/* Read the attributes */
	while (CfgTok == CFGTOK_IDENT) {

	    /* Map the identifier to a token */
	    cfgtok_t AttrTok;
	    CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
	    AttrTok = CfgTok;

	    /* An optional assignment follows */
	    CfgNextTok ();
	    CfgOptionalAssign ();

	    /* Check which attribute was given */
	    switch (AttrTok) {

	    	case CFGTOK_FORMAT:
	    	    if (F->Format != BINFMT_DEFAULT) {
	    	  	/* We've set the format already! */
		  	Error ("Cannot set a file format twice");
		    }
		    /* Read the format token */
		    CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format");
		    switch (CfgTok) {

			case CFGTOK_BIN:
			    F->Format = BINFMT_BINARY;
			    break;

			case CFGTOK_O65:
			    F->Format = BINFMT_O65;
			    break;

			default:
			    Error ("Unexpected format token");
		    }
      		    break;

	     	default:
	       	    FAIL ("Unexpected attribute token");

	    }

	    /* Skip the attribute value and an optional comma */
	    CfgNextTok ();
	    CfgOptionalComma ();
	}

	/* Skip the semicolon */
	CfgConsumeSemi ();

    }

    /* Remember we had this section */
    SectionsEncountered |= SE_FILES;
}
Ejemplo n.º 17
0
static void ParseMemory (void)
/* Parse a MEMORY section */
{
    static const IdentTok Attributes [] = {
       	{   "START",  	CFGTOK_START    },
	{   "SIZE", 	CFGTOK_SIZE     },
        {   "TYPE",     CFGTOK_TYPE     },
        {   "FILE",     CFGTOK_FILE     },
        {   "DEFINE",   CFGTOK_DEFINE   },
  	{   "FILL", 	CFGTOK_FILL     },
       	{   "FILLVAL", 	CFGTOK_FILLVAL  },
    };
    static const IdentTok Types [] = {
       	{   "RO",    	CFGTOK_RO       },
       	{   "RW",   	CFGTOK_RW       },
    };

    while (CfgTok == CFGTOK_IDENT) {

	/* Create a new entry on the heap */
       	Memory* M = NewMemory (GetStringId (CfgSVal));

	/* Skip the name and the following colon */
	CfgNextTok ();
	CfgConsumeColon ();

       	/* Read the attributes */
	while (CfgTok == CFGTOK_IDENT) {

	    /* Map the identifier to a token */
	    cfgtok_t AttrTok;
	    CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
	    AttrTok = CfgTok;

	    /* An optional assignment follows */
	    CfgNextTok ();
	    CfgOptionalAssign ();

	    /* Check which attribute was given */
	    switch (AttrTok) {

		case CFGTOK_START:
		    FlagAttr (&M->Attr, MA_START, "START");
                    M->Start = CfgIntExpr ();
		    break;

	      	case CFGTOK_SIZE:
	     	    FlagAttr (&M->Attr, MA_SIZE, "SIZE");
	      	    M->Size = CfgIntExpr ();
		    break;

		case CFGTOK_TYPE:
		    FlagAttr (&M->Attr, MA_TYPE, "TYPE");
      		    CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
		    if (CfgTok == CFGTOK_RO) {
		    	M->Flags |= MF_RO;
		    }
                    CfgNextTok ();
		    break;

	        case CFGTOK_FILE:
		    FlagAttr (&M->Attr, MA_FILE, "FILE");
		    CfgAssureStr ();
       	       	    /* Get the file entry and insert the memory area */
	    	    FileInsert (GetFile (GetStringId (CfgSVal)), M);
                    CfgNextTok ();
		    break;

	        case CFGTOK_DEFINE:
 		    FlagAttr (&M->Attr, MA_DEFINE, "DEFINE");
		    /* Map the token to a boolean */
		    CfgBoolToken ();
		    if (CfgTok == CFGTOK_TRUE) {
	  	    	M->Flags |= MF_DEFINE;
		    }
                    CfgNextTok ();
		    break;

	        case CFGTOK_FILL:
 		    FlagAttr (&M->Attr, MA_FILL, "FILL");
		    /* Map the token to a boolean */
		    CfgBoolToken ();
		    if (CfgTok == CFGTOK_TRUE) {
	  	    	M->Flags |= MF_FILL;
		    }
                    CfgNextTok ();
		    break;

	      	case CFGTOK_FILLVAL:
		    FlagAttr (&M->Attr, MA_FILLVAL, "FILLVAL");
	      	    M->FillVal = (unsigned char) CfgCheckedIntExpr (0, 0xFF);
		    break;

	     	default:
	       	    FAIL ("Unexpected attribute token");

	    }

	    /* Skip an optional comma */
	    CfgOptionalComma ();
	}

	/* Skip the semicolon */
	CfgConsumeSemi ();

	/* Check for mandatory parameters */
       	AttrCheck (M->Attr, MA_START, "START");
	AttrCheck (M->Attr, MA_SIZE, "SIZE");

	/* If we don't have a file name for output given, use the default
	 * file name.
	 */
	if ((M->Attr & MA_FILE) == 0) {
	    FileInsert (GetFile (GetStringId (OutputName)), M);
	}
    }

    /* Remember we had this section */
    SectionsEncountered |= SE_MEMORY;
}
Ejemplo n.º 18
0
static void ParseSymbols (void)
/* Parse a symbols section */
{
    static const IdentTok Attributes[] = {
       	{   "VALUE",   	CFGTOK_VALUE    },
        {   "WEAK",     CFGTOK_WEAK     },
    };

    while (CfgTok == CFGTOK_IDENT) {

	long Val = 0L;
        int  Weak = 0;
        Export* E;

	/* Remember the name */
	unsigned Name = GetStringId (CfgSVal);
	CfgNextTok ();

        /* Support both, old and new syntax here. New syntax is a colon
         * followed by an attribute list, old syntax is an optional equal
         * sign plus a value.
         */
        if (CfgTok != CFGTOK_COLON) {

            /* Old syntax */

            /* Allow an optional assignment */
            CfgOptionalAssign ();

            /* Make sure the next token is an integer expression, read and
             * skip it.
             */
            Val = CfgIntExpr ();

        } else {

            /* Bitmask to remember the attributes we got already */
            enum {
                atNone	     	= 0x0000,
                atValue         = 0x0001,
                atWeak          = 0x0002
            };
            unsigned AttrFlags = atNone;


            /* New syntax - skip the colon */
            CfgNextTok ();

            /* Parse the attributes */
            while (1) {

                /* Map the identifier to a token */
                cfgtok_t AttrTok;
                CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
                AttrTok = CfgTok;

                /* Skip the attribute name */
                CfgNextTok ();

                /* An optional assignment follows */
                CfgOptionalAssign ();

                /* Check which attribute was given */
                switch (AttrTok) {

                    case CFGTOK_VALUE:
                        /* Don't allow this twice */
                        FlagAttr (&AttrFlags, atValue, "VALUE");
                        /* We expect a numeric expression */
                        Val = CfgIntExpr ();
                        break;

                    case CFGTOK_WEAK:
                        /* Don't allow this twice */
                        FlagAttr (&AttrFlags, atWeak, "WEAK");
                        CfgBoolToken ();
                        Weak = (CfgTok == CFGTOK_TRUE);
                        CfgNextTok ();
                        break;

                    default:
                        FAIL ("Unexpected attribute token");

                }

                /* Semicolon ends the decl, otherwise accept an optional comma */
                if (CfgTok == CFGTOK_SEMI) {
                    break;
                } else if (CfgTok == CFGTOK_COMMA) {
                    CfgNextTok ();
                }
            }

            /* Check if we have all mandatory attributes */
            AttrCheck (AttrFlags, atValue, "VALUE");

            /* Weak is optional, the default are non weak symbols */
            if ((AttrFlags & atWeak) == 0) {
                Weak = 0;
            }

        }

        /* Check if the symbol is already defined */
        if ((E = FindExport (Name)) != 0 && !IsUnresolvedExport (E)) {
            /* If the symbol is not marked as weak, this is an error.
             * Otherwise ignore the symbol from the config.
             */
            if (!Weak) {
                CfgError ("Symbol `%s' is already defined", GetString (Name));
            }
        } else {
            /* The symbol is undefined, generate an export */
            CreateConstExport (Name, Val);
        }

    	/* Skip the semicolon */
    	CfgConsumeSemi ();
    }

    /* Remember we had this section */
    SectionsEncountered |= SE_SYMBOLS;
}