2005-01-08 20:16:57 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* asminc.c */
|
|
|
|
/* */
|
|
|
|
/* Read an assembler include file containing symbols */
|
|
|
|
/* */
|
|
|
|
/* */
|
|
|
|
/* */
|
2008-03-31 20:54:45 +00:00
|
|
|
/* (C) 2005-2008 Ullrich von Bassewitz */
|
|
|
|
/* Roemerstrasse 52 */
|
2005-01-08 20:16:57 +00:00
|
|
|
/* 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"
|
2006-01-29 19:00:22 +00:00
|
|
|
#include "comments.h"
|
2005-01-08 20:16:57 +00:00
|
|
|
#include "error.h"
|
2006-01-29 19:00:22 +00:00
|
|
|
#include "labels.h"
|
2005-01-08 20:16:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2013-05-09 11:56:54 +00:00
|
|
|
/* Code */
|
2005-01-08 20:16:57 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
2005-02-16 23:30:05 +00:00
|
|
|
const char* Comment;
|
2005-01-08 20:16:57 +00:00
|
|
|
unsigned Line;
|
2013-05-09 11:56:54 +00:00
|
|
|
unsigned Len;
|
2005-01-08 20:16:57 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-05-09 11:56:54 +00:00
|
|
|
/* Remove trailing whitespace */
|
|
|
|
Len = strlen (L);
|
|
|
|
while (Len > 0 && IsSpace (L[Len-1])) {
|
|
|
|
--Len;
|
|
|
|
}
|
|
|
|
L[Len] = '\0';
|
2005-01-08 20:16:57 +00:00
|
|
|
|
|
|
|
/* 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) {
|
2021-05-10 08:56:40 +00:00
|
|
|
Error ("%s:%u: Syntax error", Filename, Line);
|
2005-01-08 20:16:57 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Ignore white space */
|
|
|
|
L = SkipWhitespace (L);
|
|
|
|
|
|
|
|
/* Check for := or = */
|
|
|
|
if (*L == '=') {
|
|
|
|
++L;
|
|
|
|
} else if (*L == ':' && *++L == '=') {
|
|
|
|
++L;
|
|
|
|
} else {
|
2013-05-09 11:56:54 +00:00
|
|
|
if (!IgnoreUnknown) {
|
2021-05-10 08:56:40 +00:00
|
|
|
Error ("%s:%u: Missing '='", Filename, Line);
|
2013-05-09 11:56:54 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2005-01-08 20:16:57 +00:00
|
|
|
|
|
|
|
/* 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
|
2014-06-30 09:10:35 +00:00
|
|
|
** hex and binary numbers respectively.
|
|
|
|
*/
|
2005-01-08 20:16:57 +00:00
|
|
|
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) {
|
2021-05-10 08:56:40 +00:00
|
|
|
Error ("%s:%u: Error in number format", Filename, Line);
|
2005-01-08 20:16:57 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Skip whitespace again */
|
|
|
|
L = SkipWhitespace (L);
|
|
|
|
|
2005-02-16 23:30:05 +00:00
|
|
|
/* Check for a comment */
|
|
|
|
if (*L == CommentStart) {
|
|
|
|
Comment = SkipWhitespace (L+1);
|
|
|
|
if (*Comment == '\0') {
|
|
|
|
Comment = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Comment = 0;
|
|
|
|
}
|
|
|
|
|
2005-01-08 20:16:57 +00:00
|
|
|
/* Check for a comment character or end of line */
|
|
|
|
if (*L != CommentStart && *L != '\0') {
|
|
|
|
if (!IgnoreUnknown) {
|
2021-05-10 08:56:40 +00:00
|
|
|
Error ("%s:%u: Trailing garbage", Filename, Line);
|
2005-01-08 20:16:57 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Apply the sign */
|
|
|
|
Val *= Sign;
|
|
|
|
|
2006-01-29 19:00:22 +00:00
|
|
|
/* Define the symbol and the comment */
|
|
|
|
AddExtLabel (Val, SB_GetConstBuf (&Ident));
|
|
|
|
SetComment (Val, Comment);
|
2005-01-08 20:16:57 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Delete the string buffer contents */
|
2008-03-31 20:54:45 +00:00
|
|
|
SB_Done (&Ident);
|
2005-01-08 20:16:57 +00:00
|
|
|
|
|
|
|
/* Close the include file ignoring errors (we were just reading). */
|
|
|
|
(void) fclose (F);
|
|
|
|
}
|