1
0
mirror of https://github.com/cc65/cc65.git synced 2024-08-07 11:29:03 +00:00
cc65/src/sim65/config.c

254 lines
6.8 KiB
C
Raw Normal View History

/*****************************************************************************/
/* */
/* config.c */
/* */
/* Configuration file parsing for the sim65 6502 simulator */
/* */
/* */
/* */
/* (C) 1998-2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/* common */
#include "check.h"
#include "bitops.h"
#include "print.h"
#include "xmalloc.h"
/* sim65 */
#include "cfgdata.h"
#include "chip.h"
#include "error.h"
#include "global.h"
#include "scanner.h"
#include "config.h"
/*****************************************************************************/
/* struct CfgData */
/*****************************************************************************/
static CfgData* NewCfgData (const char* Tok)
/* Create and intialize a new CfgData struct, then return it */
{
/* Allocate memory */
CfgData* D = xmalloc (sizeof (CfgData));
/* Initialize the fields */
D->Attr = xstrdup (Tok);
D->Type = Invalid;
/* Return the new struct */
return D;
}
/*****************************************************************************/
/* Data */
/*****************************************************************************/
static void FlagAttr (unsigned* Flags, unsigned Mask, const char* Name)
/* Check if the item is already defined. Print an error if so. If not, set
* the marker that we have a definition now.
*/
{
if (*Flags & Mask) {
CfgError ("%s is already defined", Name);
}
*Flags |= Mask;
}
static void AttrCheck (unsigned Attr, unsigned Mask, const char* Name)
/* Check that a mandatory attribute was given */
{
if ((Attr & Mask) == 0) {
CfgError ("%s attribute is missing", Name);
}
}
static void ParseChips (void)
/* Parse a CHIPS section */
{
static const IdentTok Attributes [] = {
{ "ADDR", CFGTOK_ADDR },
{ "RANGE", CFGTOK_RANGE },
};
/* Bits and stuff to remember which attributes we have read */
enum {
CA_ADDR = 0x01,
CA_RANGE = 0x02
};
unsigned Attr;
/* Attribute values. Initialize to make gcc happy. */
const Chip* C;
unsigned Addr = 0;
unsigned Range = 0;
while (CfgTok == CFGTOK_IDENT) {
/* Search the chip with the given name */
C = FindChip (CfgSVal);
if (C == 0) {
CfgError ("No such chip: `%s'", CfgSVal);
}
/* Skip the name plus the following colon */
CfgNextTok ();
CfgConsumeColon ();
/* Read the attributes */
Attr = 0;
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_ADDR:
CfgAssureInt ();
CfgRangeCheck (0, 0xFFFF);
FlagAttr (&Attr, CA_ADDR, "ADDR");
Addr = (unsigned) CfgIVal;
break;
case CFGTOK_RANGE:
CfgAssureInt ();
CfgRangeCheck (0, 0xFFFF);
FlagAttr (&Attr, CA_RANGE, "RANGE");
Range = (unsigned) CfgIVal;
break;
default:
FAIL ("Unexpected attribute token");
}
/* Skip the attribute value and an optional comma */
CfgNextTok ();
CfgOptionalComma ();
}
/* Skip the semicolon */
CfgConsumeSemi ();
/* Check for mandatory parameters */
AttrCheck (Attr, CA_ADDR, "ADDR");
AttrCheck (Attr, CA_RANGE, "RANGE");
/* Address + Range may not exceed 16 bits */
if (((unsigned long) Range) > 0x10000UL - Addr) {
CfgError ("Range error");
}
/* Create the chip ## */
}
}
static void ParseConfig (void)
/* Parse the config file */
{
static const IdentTok BlockNames [] = {
{ "CHIPS", CFGTOK_CHIPS },
};
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_CHIPS:
ParseChips ();
break;
default:
FAIL ("Unexpected block token");
}
/* Skip closing brace */
CfgConsume (CFGTOK_RCURLY, "`}' expected");
} while (CfgTok != CFGTOK_EOF);
}
void CfgRead (void)
/* Read the configuration */
{
/* If we have a config name given, open the file, otherwise we will read
* from a buffer.
*/
CfgOpenInput ();
/* Parse the file */
ParseConfig ();
/* Close the input file */
CfgCloseInput ();
}