--- /dev/null
+/*****************************************************************************/
+/* */
+/* asminc.c */
+/* */
+/* Read an assembler include file containing symbols */
+/* */
+/* */
+/* */
+/* (C) 2005 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
+/* */
+/* */
+/* 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 <errno.h>
+
+/* common */
+#include "chartype.h"
+#include "strbuf.h"
+
+/* da65 */
+#include "asminc.h"
+#include "attrtab.h"
+#include "error.h"
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+static char* SkipWhitespace (char* L)
+/* Ignore white space in L */
+{
+ while (IsBlank (*L)) {
+ ++L;
+ }
+ return L;
+}
+
+
+
+unsigned DigitVal (unsigned char C)
+/* Return the value of the given digit */
+{
+ if (IsDigit (C)) {
+ return C - '0';
+ } else {
+ return tolower (C) - 'a' + 10;
+ }
+}
+
+
+
+void AsmInc (const char* Filename, char CommentStart, int IgnoreUnknown)
+/* Read an assembler include file */
+{
+ char Buf[1024];
+ char* L;
+ unsigned Line;
+ unsigned Len;
+ long Val;
+ unsigned DVal;
+ int Sign;
+ unsigned Base;
+ unsigned Digits;
+ StrBuf Ident = STATIC_STRBUF_INITIALIZER;
+
+ /* Try to open the file for reading */
+ FILE* F = fopen (Filename, "r");
+ if (F == 0) {
+ Error ("Cannot open asm include file \"%s\": %s",
+ Filename, strerror (errno));
+ }
+
+ /* Read line by line, check for NAME = VALUE lines */
+ Line = 0;
+ while ((L = fgets (Buf, sizeof (Buf), F)) != 0) {
+
+ /* One more line read */
+ ++Line;
+
+ /* Ignore leading white space */
+ while (IsBlank (*L)) {
+ ++L;
+ }
+
+ /* Remove trailing whitespace */
+ Len = strlen (L);
+ while (Len > 0 && IsSpace (L[Len-1])) {
+ --Len;
+ }
+ L[Len] = '\0';
+
+ /* If the line is empty or starts with a comment char, ignore it */
+ if (*L == '\0' || *L == CommentStart) {
+ continue;
+ }
+
+ /* Read an identifier */
+ SB_Clear (&Ident);
+ if (IsAlpha (*L) || *L == '_') {
+ SB_AppendChar (&Ident, *L++);
+ while (IsAlNum (*L) || *L == '_') {
+ SB_AppendChar (&Ident, *L++);
+ }
+ SB_Terminate (&Ident);
+ } else {
+ if (!IgnoreUnknown) {
+ Error ("%s(%u): Syntax error", Filename, Line);
+ }
+ continue;
+ }
+
+ /* Ignore white space */
+ L = SkipWhitespace (L);
+
+ /* Check for := or = */
+ if (*L == '=') {
+ ++L;
+ } else if (*L == ':' && *++L == '=') {
+ ++L;
+ } else {
+ if (!IgnoreUnknown) {
+ Error ("%s(%u): Missing `='", Filename, Line);
+ }
+ continue;
+ }
+
+ /* Allow white space once again */
+ L = SkipWhitespace (L);
+
+ /* A number follows. Read the sign. */
+ if (*L == '-') {
+ Sign = -1;
+ ++L;
+ } else {
+ Sign = 1;
+ if (*L == '+') {
+ ++L;
+ }
+ }
+
+ /* Determine the base of the number. Allow $ and % as prefixes for
+ * hex and binary numbers respectively.
+ */
+ if (*L == '$') {
+ Base = 16;
+ ++L;
+ } else if (*L == '%') {
+ Base = 2;
+ ++L;
+ } else {
+ Base = 10;
+ }
+
+ /* Decode the number */
+ Digits = 0;
+ Val = 0;
+ while (IsXDigit (*L) && (DVal = DigitVal (*L)) < Base) {
+ Val = (Val * Base) + DVal;
+ ++Digits;
+ ++L;
+ }
+
+ /* Must have at least one digit */
+ if (Digits == 0) {
+ if (!IgnoreUnknown) {
+ Error ("%s(%u): Error in number format", Filename, Line);
+ }
+ continue;
+ }
+
+ /* Skip whitespace again */
+ L = SkipWhitespace (L);
+
+ /* Check for a comment character or end of line */
+ if (*L != CommentStart && *L != '\0') {
+ if (!IgnoreUnknown) {
+ Error ("%s(%u): Trailing garbage", Filename, Line);
+ }
+ continue;
+ }
+
+ /* Apply the sign */
+ Val *= Sign;
+
+ /* Define the symbol */
+ AddExtLabelRange (Val, SB_GetConstBuf (&Ident), 1);
+
+ }
+
+ /* Delete the string buffer contents */
+ DoneStrBuf (&Ident);
+
+ /* Close the include file ignoring errors (we were just reading). */
+ (void) fclose (F);
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* asminc.h */
+/* */
+/* Read an assembler include file containing symbols */
+/* */
+/* */
+/* */
+/* (C) 2005 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
+/* */
+/* */
+/* 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. */
+/* */
+/*****************************************************************************/
+
+
+
+#ifndef ASMINC_H
+#define ASMINC_H
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void AsmInc (const char* Filename, char CommentStart, int IgnoreUnknown);
+/* Read an assembler include file */
+
+
+
+/* End of asminc.h */
+#endif
+
+
+
/* */
/* */
/* */
-/* (C) 2000-2004 Ullrich von Bassewitz */
+/* (C) 2000-2005 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
#include "xmalloc.h"
/* da65 */
+#include "asminc.h"
#include "attrtab.h"
#include "error.h"
#include "global.h"
Size = 1;
}
if (Value + Size > 0x10000) {
- InfoError ("Invalid size (address out of range)");
+ InfoError ("Invalid size (address out of range)");
}
if (HaveLabel ((unsigned) Value)) {
- InfoError ("Label for address $%04lX already defined", Value);
+ InfoError ("Label for address $%04lX already defined", Value);
}
/* Define the label(s) */
+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;
+ }
+
+ /* 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 ();
+}
+
+
+
static void InfoParse (void)
/* Parse the config file */
{
static const IdentTok Globals[] = {
- { "GLOBAL", INFOTOK_GLOBAL },
- { "RANGE", INFOTOK_RANGE },
- { "LABEL", INFOTOK_LABEL },
+ { "GLOBAL", INFOTOK_GLOBAL },
+ { "RANGE", INFOTOK_RANGE },
+ { "LABEL", INFOTOK_LABEL },
+ { "ASMINC", INFOTOK_ASMINC },
};
while (InfoTok != INFOTOK_EOF) {
LabelSection ();
break;
+ case INFOTOK_ASMINC:
+ AsmIncSection ();
+ break;
}
/* Semicolon expected */
EBIND=emxbind
LDFLAGS=
-OBJS = attrtab.o \
+OBJS = asminc.o \
+ attrtab.o \
code.o \
data.o \
error.o \
# ------------------------------------------------------------------------------
# All OBJ files
-OBJS = attrtab.obj \
+OBJS = asminc.obj \
+ attrtab.obj \
code.obj \
data.obj \
error.obj \
/* */
/* */
/* */
-/* (C) 2000-2003 Ullrich von Bassewitz */
+/* (C) 2000-2005 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
InfoTok = INFOTOK_STRCON;
break;
+ case '\'':
+ NextChar ();
+ if (C == EOF || IsControl (C)) {
+ InfoError ("Invalid character constant");
+ }
+ InfoIVal = C;
+ NextChar ();
+ if (C != '\'') {
+ InfoError ("Unterminated character constant");
+ }
+ NextChar ();
+ InfoTok = INFOTOK_CHARCON;
+ break;
+
case '#':
/* Comment */
while (C != '\n' && C != EOF) {
+void InfoAssureChar (void)
+/* Make sure the next token is a char constant */
+{
+ if (InfoTok != INFOTOK_STRCON) {
+ InfoError ("Character constant expected");
+ }
+}
+
+
+
void InfoAssureIdent (void)
/* Make sure the next token is an identifier */
{
{ "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 */
/* */
/* */
/* */
-/* (C) 2000-2003 Ullrich von Bassewitz */
+/* (C) 2000-2005 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
INFOTOK_NONE,
INFOTOK_INTCON,
INFOTOK_STRCON,
+ INFOTOK_CHARCON,
INFOTOK_IDENT,
INFOTOK_LCURLY,
INFOTOK_RCURLY,
INFOTOK_GLOBAL,
INFOTOK_RANGE,
INFOTOK_LABEL,
+ INFOTOK_ASMINC,
/* Global section */
INFOTOK_COMMENTS,
INFOTOK_ADDR,
INFOTOK_SIZE,
+ /* ASMINC section */
+ INFOTOK_FILE,
+ INFOTOK_COMMENTSTART,
+ INFOTOK_IGNOREUNKNOWN,
+
/* */
INFOTOK_TRUE,
INFOTOK_FALSE
/* Mapping table entry, special identifier --> token */
typedef struct IdentTok IdentTok;
struct IdentTok {
- const char* Ident; /* Identifier */
- token_t Tok; /* Token for identifier */
+ const char* Ident; /* Identifier */
+ token_t Tok; /* Token for identifier */
};
#define ENTRY_COUNT(s) (sizeof (s) / sizeof (s [0]))
/* Current token and attributes */
#define CFG_MAX_IDENT_LEN 255
-extern unsigned InfoTok;
-extern char InfoSVal [CFG_MAX_IDENT_LEN+1];
+extern unsigned InfoTok;
+extern char InfoSVal[CFG_MAX_IDENT_LEN+1];
extern long InfoIVal;
/* Error location */
void InfoAssureStr (void);
/* Make sure the next token is a string constant */
+void InfoAssureChar (void);
+/* Make sure the next token is a char constant */
+
void InfoAssureIdent (void);
/* Make sure the next token is an identifier */