#include "error.h"
#include "expr.h"
-#include "scanner.h"
+#include "nexttok.h"
#include "symtab.h"
#include "condasm.h"
IfDesc* D = GetCurrentIf();
if (D == 0) {
Error (ERR_UNEXPECTED, ".ENDIF");
+ Done = 1;
} else {
Done = (D->Flags & ifNeedTerm) != 0;
--IfCount;
/* There are no open .IFs */
break;
}
-
+
if (D->Pos.Name != CurPos.Name) {
/* The .if is from another file, bail out */
break;
+unsigned GetIfStack (void)
+/* Get the current .IF stack pointer */
+{
+ return IfCount;
+}
+
+
+
+void CleanupIfStack (unsigned SP)
+/* Cleanup the .IF stack, remove anything above the given stack pointer */
+{
+ while (IfCount > SP) {
+ FreeIf ();
+ }
+}
+
+
+
* open .ifs in this file.
*/
+unsigned GetIfStack (void);
+/* Get the current .IF stack pointer */
+
+void CleanupIfStack (unsigned SP);
+/* Cleanup the .IF stack, remove anything above the given stack pointer */
+
/* End of condasm.h */
#include "error.h"
#include "expr.h"
#include "instr.h"
-#include "scanner.h"
+#include "nexttok.h"
#include "ea.h"
#include <stdlib.h>
#include <stdarg.h>
-#include "scanner.h"
+#include "nexttok.h"
#include "error.h"
"CPU not supported",
"Counter underflow",
"Undefined label",
+ "Open `%s´",
};
fprintf (stderr, "%s(%lu): Error #%u: ",
"Cannot open listing file: %s",
"Cannot write to listing file: %s",
"Cannot read from listing file: %s",
- "Macro nesting too deep",
+ "Too many nested constructs",
"Too many symbols",
};
va_list ap;
ERR_CPU_NOT_SUPPORTED,
ERR_COUNTER_UNDERFLOW,
ERR_UNDEFINED_LABEL,
+ ERR_OPEN_STMT,
ERR_COUNT /* Error count */
};
FAT_CANNOT_OPEN_LISTING,
FAT_CANNOT_WRITE_LISTING,
FAT_CANNOT_READ_LISTING,
- FAT_MACRO_NESTING,
+ FAT_NESTING,
FAT_TOO_MANY_SYMBOLS,
FAT_COUNT /* Fatal error count */
};
#include "global.h"
#include "instr.h"
#include "mem.h"
+#include "nexttok.h"
#include "objcode.h"
#include "objfile.h"
-#include "scanner.h"
#include "symtab.h"
-#include "toknode.h"
+#include "toklist.h"
#include "ulabel.h"
#include "expr.h"
#include "error.h"
#include "expr.h"
#include "global.h"
+#include "nexttok.h"
#include "objcode.h"
-#include "scanner.h"
#include "instr.h"
--- /dev/null
+/*****************************************************************************/
+/* */
+/* istack.c */
+/* */
+/* Input stack for the scanner */
+/* */
+/* */
+/* */
+/* (C) 2000 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 "error.h"
+#include "mem.h"
+#include "istack.h"
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+/* Size of the stack (== maximum nested macro or repeat count) */
+#define ISTACK_MAX 256
+
+/* Structure holding a stack element */
+typedef struct IElement IElement;
+struct IElement {
+ IElement* Next; /* Next stack element */
+ int (*Func)(void*); /* Function called for input */
+ void* Data; /* User data given as argument */
+ const char* Desc; /* Description */
+};
+
+/* The stack */
+static IElement* IStack = 0; /* Input stack pointer */
+static unsigned ICount = 0; /* Number of items on the stack */
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void PushInput (int (*Func) (void*), void* Data, const char* Desc)
+/* Push an input function onto the input stack */
+{
+ IElement* E;
+
+ /* Check for a stack overflow */
+ if (ICount > ISTACK_MAX) {
+ Fatal (FAT_NESTING);
+ }
+
+ /* Create a new stack element */
+ E = Xmalloc (sizeof (*E));
+
+ /* Initialize it */
+ E->Func = Func;
+ E->Data = Data;
+ E->Desc = Desc;
+
+ /* Push it */
+ E->Next = IStack;
+ IStack = E;
+}
+
+
+
+void PopInput (void)
+/* Pop the current input function from the input stack */
+{
+ IElement* E;
+
+ /* We cannot pop from an empty stack */
+ PRECONDITION (IStack != 0);
+
+ /* Remember the last element */
+ E = IStack;
+
+ /* Pop it */
+ IStack = IStack->Next;
+
+ /* And delete it */
+ Xfree (E);
+}
+
+
+
+int InputFromStack (void)
+/* Try to get input from the input stack. Return true if we had such input,
+ * return false otherwise.
+ */
+{
+ /* Repeatedly call the TOS routine until we have a token or if run out of
+ * routines.
+ */
+ while (IStack) {
+ if (IStack->Func (IStack->Data) != 0) {
+ /* We have a token */
+ return 1;
+ }
+ }
+
+ /* Nothing is on the stack */
+ return 0;
+}
+
+
+
+void CheckInputStack (void)
+/* Called from the scanner before closing an input file. Will check for any
+ * stuff on the input stack.
+ */
+{
+ if (IStack) {
+ Error (ERR_OPEN_STMT, IStack->Desc);
+ }
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* istack.h */
+/* */
+/* Input stack for the scanner */
+/* */
+/* */
+/* */
+/* (C) 2000 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. */
+/* */
+/*****************************************************************************/
+
+
+
+#ifndef ISTACK_H
+#define ISTACK_H
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void PushInput (int (*Func) (void*), void* Data, const char* Desc);
+/* Push an input function onto the input stack */
+
+void PopInput (void);
+/* Pop the current input function from the input stack */
+
+int InputFromStack (void);
+/* Try to get input from the input stack. Return true if we had such input,
+ * return false otherwise.
+ */
+
+void CheckInputStack (void);
+/* Called from the scanner before closing an input file. Will check for any
+ * stuff on the input stack.
+ */
+
+
+
+/* End of istack.h */
+
+#endif
+
+
+
+
#include "../common/hashstr.h"
-#include "mem.h"
+#include "condasm.h"
#include "error.h"
-#include "scanner.h"
-#include "toknode.h"
+#include "istack.h"
+#include "mem.h"
+#include "nexttok.h"
#include "pseudo.h"
+#include "toklist.h"
#include "macro.h"
struct MacExp_ {
MacExp* Next; /* Pointer to next expansion */
Macro* M; /* Which macro do we expand? */
+ unsigned IfSP; /* .IF stack pointer at start of expansion */
TokNode* Exp; /* Pointer to current token */
TokNode* Final; /* Pointer to final token */
unsigned LocalStart; /* Start of counter for local symbol names */
TokNode* ParamExp; /* Node for expanding parameters */
};
-/* Data for macro expansions */
-#define MAX_MACRO_EXPANSIONS 255
-static unsigned MacroNesting = 0;
-static MacExp* CurMac = 0;
-static unsigned LocalName = 0;
+/* Number of active macro expansions */
+static unsigned MacExpansions = 0;
+
+/* Flag if a macro expansion should get aborted */
+static int DoMacAbort = 0;
+
+/* Counter to create local names for symbols */
+static unsigned LocalName = 0;
/* Initialize the data */
E->M = M;
+ E->IfSP = GetIfStack ();
E->Exp = M->TokRoot;
E->Final = 0;
E->LocalStart = LocalName;
E->Params [I] = 0;
}
- /* And return it... */
- return E;
-}
+ /* One macro expansion more */
+ ++MacExpansions;
-
-
-static void MacInsertExp (MacExp* E)
-/* Insert a macro expansion into the list */
-{
- E->Next = CurMac;
- CurMac = E;
- ++MacroNesting;
+ /* Return the new macro expansion */
+ return E;
}
-static void FreeMacExp (void)
+static void FreeMacExp (MacExp* E)
/* Remove and free the current macro expansion */
{
unsigned I;
- MacExp* E;
+
+ /* One macro expansion less */
+ --MacExpansions;
/* Free the parameter list */
- for (I = 0; I < CurMac->ParamCount; ++I) {
- Xfree (CurMac->Params [I]);
+ for (I = 0; I < E->ParamCount; ++I) {
+ Xfree (E->Params [I]);
}
- Xfree (CurMac->Params);
+ Xfree (E->Params);
/* Free the final token if we have one */
- if (CurMac->Final) {
- FreeTokNode (CurMac->Final);
+ if (E->Final) {
+ FreeTokNode (E->Final);
}
- /* Reset the list pointer */
- E = CurMac;
- CurMac = E->Next;
- --MacroNesting;
-
/* Free the structure itself */
Xfree (E);
}
IdDesc* I;
- /* Skip .local or comma */
+ /* Skip .local or comma */
NextTok ();
/* Need an identifer */
+static int MacExpand (void* Data)
+/* If we're currently expanding a macro, set the the scanner token and
+ * attribute to the next value and return true. If we are not expanding
+ * a macro, return false.
+ */
+{
+ /* Cast the Data pointer to the actual data structure */
+ MacExp* Mac = (MacExp*) Data;
+
+ /* Check if we should abort this macro */
+ if (DoMacAbort) {
+
+ /* Reset the flag */
+ DoMacAbort = 0;
+
+ /* Abort any open .IF statements in this macro expansion */
+ CleanupIfStack (Mac->IfSP);
+
+ /* Terminate macro expansion */
+ goto MacEnd;
+ }
+
+ /* We're expanding a macro. Check if we are expanding one of the
+ * macro parameters.
+ */
+ if (Mac->ParamExp) {
+
+ /* Ok, use token from parameter list */
+ TokSet (Mac->ParamExp);
+
+ /* Set pointer to next token */
+ Mac->ParamExp = Mac->ParamExp->Next;
+
+ /* Done */
+ return 1;
+
+ }
+
+ /* We're not expanding macro parameters. Check if we have tokens left from
+ * the macro itself.
+ */
+ if (Mac->Exp) {
+
+ /* Use next macro token */
+ TokSet (Mac->Exp);
+
+ /* Set pointer to next token */
+ Mac->Exp = Mac->Exp->Next;
+
+ /* Is it a request for actual parameter count? */
+ if (Tok == TOK_PARAMCOUNT) {
+ Tok = TOK_INTCON;
+ IVal = Mac->ParamCount;
+ return 1;
+ }
+
+ /* Is it the name of a macro parameter? */
+ if (Tok == TOK_MACPARAM) {
+
+ /* Start to expand the parameter token list */
+ Mac->ParamExp = Mac->Params [IVal];
+
+ /* Recursive call to expand the parameter */
+ return MacExpand (Mac);
+ }
+
+ /* If it's an identifier, it may in fact be a local symbol */
+ if (Tok == TOK_IDENT && Mac->M->LocalCount) {
+ /* Search for the local symbol in the list */
+ unsigned Index = 0;
+ IdDesc* I = Mac->M->Locals;
+ while (I) {
+ if (strcmp (SVal, I->Id) == 0) {
+ /* This is in fact a local symbol, change the name */
+ sprintf (SVal, "___%04X__", Mac->LocalStart + Index);
+ break;
+ }
+ /* Next symbol */
+ ++Index;
+ I = I->Next;
+ }
+
+ /* Done */
+ return 1;
+ }
+
+ /* The token was successfully set */
+ return 1;
+
+ }
+
+ /* No more macro tokens. Do we have a final token? */
+ if (Mac->Final) {
+
+ /* Set the final token and remove it */
+ TokSet (Mac->Final);
+ FreeTokNode (Mac->Final);
+ Mac->Final = 0;
+
+ /* The token was successfully set */
+ return 1;
+
+ }
+
+MacEnd:
+ /* End of macro expansion */
+ FreeMacExp (Mac);
+
+ /* Pop the input function */
+ PopInput ();
+
+ /* No token available */
+ return 0;
+}
+
+
+
static void StartExpClassic (Macro* M)
/* Start expanding the classic macro M */
{
}
}
- /* Insert the newly created structure into the expansion list */
- MacInsertExp (E);
+ /* Insert a new token input function */
+ PushInput (MacExpand, E, ".MACRO");
}
*/
E->Final = NewTokNode ();
- /* Insert the newly created structure into the expansion list */
- MacInsertExp (E);
+ /* Insert a new token input function */
+ PushInput (MacExpand, E, ".DEFINE");
}
void MacExpandStart (void)
/* Start expanding the macro in SVal */
{
- Macro* M;
-
- /* Beware of runoff macros */
- if (MacroNesting == MAX_MACRO_EXPANSIONS) {
- Fatal (FAT_MACRO_NESTING);
- }
-
/* Search for the macro */
- M = MacFind (SVal, HashStr (SVal) % HASHTAB_SIZE);
+ Macro* M = MacFind (SVal, HashStr (SVal) % HASHTAB_SIZE);
CHECK (M != 0);
/* Call the apropriate subroutine */
switch (M->Style) {
case MAC_STYLE_CLASSIC: StartExpClassic (M); break;
case MAC_STYLE_DEFINE: StartExpDefine (M); break;
- default: Internal ("Invalid macro style: %d", M->Style);
- }
-}
-
-
-
-int MacExpand (void)
-/* If we're currently expanding a macro, set the the scanner token and
- * attribute to the next value and return true. If we are not expanding
- * a macro, return false.
- */
-{
- if (MacroNesting == 0) {
- /* Not expanding a macro */
- return 0;
- }
-
- /* We're expanding a macro. Check if we are expanding one of the
- * macro parameters.
- */
- if (CurMac->ParamExp) {
-
- /* Ok, use token from parameter list */
- TokSet (CurMac->ParamExp);
-
- /* Set pointer to next token */
- CurMac->ParamExp = CurMac->ParamExp->Next;
-
- /* Done */
- return 1;
-
- } else if (CurMac->Exp) {
-
- /* We're not expanding a parameter, use next macro token */
- TokSet (CurMac->Exp);
-
- /* Set pointer to next token */
- CurMac->Exp = CurMac->Exp->Next;
-
- /* Is it a request for actual parameter count? */
- if (Tok == TOK_PARAMCOUNT) {
- Tok = TOK_INTCON;
- IVal = CurMac->ParamCount;
- return 1;
- }
-
- /* Is it an .exitmacro command? */
- if (Tok == TOK_EXITMACRO) {
- /* Forced exit from macro expansion */
- FreeMacExp ();
- return MacExpand ();
- }
-
- /* Is it the name of a macro parameter? */
- if (Tok == TOK_MACPARAM) {
-
- /* Start to expand the parameter token list */
- CurMac->ParamExp = CurMac->Params [IVal];
-
- /* Recursive call to expand the parameter */
- return MacExpand ();
- }
-
- /* If it's an identifier, it may in fact be a local symbol */
- if (Tok == TOK_IDENT && CurMac->M->LocalCount) {
- /* Search for the local symbol in the list */
- unsigned Index = 0;
- IdDesc* I = CurMac->M->Locals;
- while (I) {
- if (strcmp (SVal, I->Id) == 0) {
- /* This is in fact a local symbol, change the name */
- sprintf (SVal, "___%04X__", CurMac->LocalStart + Index);
- break;
- }
- /* Next symbol */
- ++Index;
- I = I->Next;
- }
-
- /* Done */
- return 1;
- }
-
- /* The token was successfully set */
- return 1;
-
- } else if (CurMac->Final) {
-
- /* Set the final token and remove it */
- TokSet (CurMac->Final);
- FreeTokNode (CurMac->Final);
- CurMac->Final = 0;
-
- /* The token was successfully set */
- return 1;
-
- } else {
-
- /* End of macro expansion */
- FreeMacExp ();
- return MacExpand ();
-
+ default: Internal ("Invalid macro style: %d", M->Style);
}
}
/* Abort the current macro expansion */
{
/* Must have an expansion */
- CHECK (CurMac != 0);
+ CHECK (MacExpansions > 0);
- /* Free current structure */
- FreeMacExp ();
+ /* Set a flag so macro expansion will terminate on the next call */
+ DoMacAbort = 1;
}
int InMacExpansion (void)
/* Return true if we're currently expanding a macro */
{
- return MacroNesting != 0;
+ return (MacExpansions > 0);
}
void MacExpandStart (void);
/* Start expanding the macro in SVal */
-int MacExpand (void);
-/* If we're currently expanding a macro, set the the scanner token and
- * attribute to the next value and return true. If we are not expanding
- * a macro, return false.
- */
-
void MacAbort (void);
/* Abort the current macro expansion */
int IsDefine (const char* Name);
/* Return true if the given name is the name of a define style macro */
-int InMacExpansion (void);
+int InMacExpansion (void);
/* Return true if we're currently expanding a macro */
#include "listing.h"
#include "macro.h"
#include "mem.h"
+#include "nexttok.h"
#include "objcode.h"
#include "objfile.h"
#include "options.h"
OptIgnoreCase (Arg);
break;
- case 'l':
+ case 'l':
OptListing (Arg);
break;
global.o \
incpath.o \
instr.o \
+ istack.o \
listing.o \
macpack.o \
macro.o \
- main.o \
- mem.o \
+ main.o \
+ mem.o \
+ nexttok.o \
objcode.o \
objfile.o \
options.o \
scanner.o \
strexpr.o \
symtab.o \
- toknode.o \
+ toklist.o \
ulabel.o
LIBS = ../common/common.a
@echo "Creating dependency information"
$(CC) -MM $^ > .depend
+
global.obj \
incpath.obj \
instr.obj \
+ istack.obj \
listing.obj \
macpack.obj \
macro.obj \
main.obj \
mem.obj \
+ nexttok.obj \
objcode.obj \
objfile.obj \
options.obj \
scanner.obj \
strexpr.obj \
symtab.obj \
- toknode.obj \
+ toklist.obj \
ulabel.obj
LIBS = ..\common\common.lib
FILE global.obj
FILE incpath.obj
FILE instr.obj
+FILE istack.obj
FILE listing.obj
FILE macpack.obj
FILE macro.obj
FILE main.obj
FILE mem.obj
+FILE nexttok.obj
FILE objcode.obj
FILE objfile.obj
FILE options.obj
FILE scanner.obj
FILE strexpr.obj
FILE symtab.obj
-FILE toknode.obj
+FILE toklist.obj
FILE ulabel.obj
LIBRARY ..\common\common.lib
|
--- /dev/null
+/*****************************************************************************/
+/* */
+/* nexttok.c */
+/* */
+/* Get next token and handle token level functions */
+/* */
+/* */
+/* */
+/* (C) 2000 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 "error.h"
+#include "expr.h"
+#include "scanner.h"
+#include "toklist.h"
+#include "nexttok.h"
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+static TokList* CollectTokens (unsigned Start, unsigned Count)
+/* Read a list of tokens that is terminated by a right paren. For all tokens
+ * starting at the one with index Start, and ending at (Start+Count-1), place
+ * them into a token list, and return this token list.
+ */
+{
+ /* Create the token list */
+ TokList* List = NewTokList ();
+
+ /* Read the token list */
+ unsigned Current = 0;
+ unsigned Parens = 0;
+ while (Parens != 0 && Tok != TOK_RPAREN) {
+
+ /* Check for end of line or end of input */
+ if (Tok == TOK_SEP || Tok == TOK_EOF) {
+ Error (ERR_UNEXPECTED_EOL);
+ return List;
+ }
+
+ /* Collect tokens in the given range */
+ if (Current >= Start && Current < Start+Count) {
+ /* Add the current token to the list */
+ AddCurTok (List);
+ }
+
+ /* Check for and count parenthesii */
+ if (Tok == TOK_LPAREN) {
+ ++Parens;
+ } else if (Tok == TOK_RPAREN) {
+ --Parens;
+ }
+
+ /* Get the next token */
+ NextTok ();
+ }
+
+ /* Eat the closing paren */
+ ConsumeRParen ();
+
+ /* Return the list of collected tokens */
+ return List;
+}
+
+
+
+static void FuncMid (void)
+/* Handle the .MID function */
+{
+ long Start;
+ long Count;
+ TokList* List;
+
+ /* Skip it */
+ NextTok ();
+
+ /* Left paren expected */
+ ConsumeRParen ();
+
+ /* Start argument */
+ Start = ConstExpression ();
+ if (Start < 0 || Start > 100) {
+ Error (ERR_RANGE);
+ Start = 0;
+ }
+ ConsumeComma ();
+
+ /* Count argument */
+ Count = ConstExpression ();
+ if (Count > 100) {
+ Error (ERR_RANGE);
+ Count = 1;
+ }
+ ConsumeComma ();
+
+ /* Read the token list */
+ List = CollectTokens ((unsigned) Start, (unsigned) Count);
+
+ /* Insert it into the scanner feed */
+
+
+
+}
+
+
+
+void NextTok (void)
+/* Get next token and handle token level functions */
+{
+ /* Get the next raw token */
+ NextRawTok ();
+
+ /* Check for token handling functions */
+ switch (Tok) {
+
+ case TOK_MID:
+ FuncMid ();
+ break;
+
+ default:
+ /* Quiet down gcc */
+ break;
+
+ }
+}
+
+
+
+void Consume (enum Token Expected, unsigned ErrMsg)
+/* Consume Expected, print an error if we don't find it */
+{
+ if (Tok == Expected) {
+ NextTok ();
+ } else {
+ Error (ErrMsg);
+ }
+}
+
+
+
+void ConsumeSep (void)
+/* Consume a separator token */
+{
+ /* Accept an EOF as separator */
+ if (Tok != TOK_EOF) {
+ if (Tok != TOK_SEP) {
+ Error (ERR_TOO_MANY_CHARS);
+ SkipUntilSep ();
+ } else {
+ NextTok ();
+ }
+ }
+}
+
+
+
+void ConsumeLParen (void)
+/* Consume a left paren */
+{
+ Consume (TOK_LPAREN, ERR_LPAREN_EXPECTED);
+}
+
+
+
+void ConsumeRParen (void)
+/* Consume a right paren */
+{
+ Consume (TOK_RPAREN, ERR_RPAREN_EXPECTED);
+}
+
+
+
+void ConsumeComma (void)
+/* Consume a comma */
+{
+ Consume (TOK_COMMA, ERR_COMMA_EXPECTED);
+}
+
+
+
+void SkipUntilSep (void)
+/* Skip tokens until we reach a line separator */
+{
+ while (Tok != TOK_SEP && Tok != TOK_EOF) {
+ NextTok ();
+ }
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* nexttok.h */
+/* */
+/* Get next token and handle token level functions */
+/* */
+/* */
+/* */
+/* (C) 2000 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. */
+/* */
+/*****************************************************************************/
+
+
+
+#ifndef NEXTTOK_H
+#define NEXTTOK_H
+
+
+
+#include "scanner.h"
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void NextTok (void);
+/* Get next token and handle token level functions */
+
+void Consume (enum Token Expected, unsigned ErrMsg);
+/* Consume Token, print an error if we don't find it */
+
+void ConsumeSep (void);
+/* Consume a separator token */
+
+void ConsumeLParen (void);
+/* Consume a left paren */
+
+void ConsumeRParen (void);
+/* Consume a right paren */
+
+void ConsumeComma (void);
+/* Consume a comma */
+
+void SkipUntilSep (void);
+/* Skip tokens until we reach a line separator */
+
+
+
+/* End of nexttok.h */
+
+#endif
+
+
+
+
#include "listing.h"
#include "macpack.h"
#include "macro.h"
+#include "nexttok.h"
#include "objcode.h"
#include "options.h"
-#include "scanner.h"
#include "strexpr.h"
#include "symtab.h"
#include "pseudo.h"
+static void DoMid (void)
+/* Handle .MID - this should never happen, since the keyword is actually
+ * handled on a much lower level of the expression hierarchy.
+ */
+{
+ Internal ("Unexpected token: .MID");
+}
+
+
+
static void DoNull (void)
/* Switch to the NULL segment */
{
{ ccNone, DoMacPack },
{ ccNone, DoMacro },
{ ccNone, DoUnexpected }, /* .MATCH */
+ { ccNone, DoMid },
{ ccNone, DoNull },
{ ccNone, DoOrg },
{ ccNone, DoOut },
#include "global.h"
#include "incpath.h"
#include "instr.h"
+#include "istack.h"
#include "listing.h"
#include "macro.h"
#include "mem.h"
#include "objfile.h"
+#include "toklist.h"
#include "scanner.h"
static unsigned FileCount = 0;
/* Current input variables */
-static InputFile* IFile = 0;
-static InputData* IData = 0;
-static unsigned ICount = 0; /* Count of input files */
-static int C = 0;
+static InputFile* IFile = 0; /* Current input file */
+static InputData* IData = 0; /* Current input memory data */
+static unsigned ICount = 0; /* Count of input files */
+static int C = 0; /* Current input character */
/* Force end of assembly */
int ForcedEnd = 0;
{ "A8", TOK_A8 },
{ "ADDR", TOK_ADDR },
{ "ALIGN", TOK_ALIGN },
- { "AND", TOK_BAND },
+ { "AND", TOK_BAND },
{ "ASCIIZ", TOK_ASCIIZ },
{ "AUTOIMPORT", TOK_AUTOIMPORT },
{ "BITAND", TOK_AND },
{ "BLANK", TOK_BLANK },
{ "BSS", TOK_BSS },
{ "BYTE", TOK_BYTE },
- { "CASE", TOK_CASE },
+ { "CASE", TOK_CASE },
{ "CODE", TOK_CODE },
{ "CONST", TOK_CONST },
- { "CPU", TOK_CPU },
+ { "CPU", TOK_CPU },
{ "DATA", TOK_DATA },
{ "DBYT", TOK_DBYT },
{ "DEBUGINFO", TOK_DEBUGINFO },
{ "DEF", TOK_DEFINED },
- { "DEFINE", TOK_DEFINE },
+ { "DEFINE", TOK_DEFINE },
{ "DEFINED", TOK_DEFINED },
{ "DWORD", TOK_DWORD },
{ "ELSE", TOK_ELSE },
{ "MACPACK", TOK_MACPACK },
{ "MACRO", TOK_MACRO },
{ "MATCH", TOK_MATCH },
- { "MOD", TOK_MOD },
- { "NOT", TOK_BNOT },
+ { "MID", TOK_MID },
+ { "MOD", TOK_MOD },
+ { "NOT", TOK_BNOT },
{ "NULL", TOK_NULL },
- { "OR", TOK_BOR },
+ { "OR", TOK_BOR },
{ "ORG", TOK_ORG },
{ "OUT", TOK_OUT },
{ "P02", TOK_P02 },
{ "PARAMCOUNT", TOK_PARAMCOUNT },
{ "PC02", TOK_PC02 },
{ "PROC", TOK_PROC },
- { "REF", TOK_REFERENCED },
+ { "REF", TOK_REFERENCED },
{ "REFERENCED", TOK_REFERENCED },
{ "RELOC", TOK_RELOC },
{ "REPEAT", TOK_REPEAT },
{ "RES", TOK_RES },
{ "RODATA", TOK_RODATA },
{ "SEGMENT", TOK_SEGMENT },
- { "SHL", TOK_SHL },
- { "SHR", TOK_SHR },
+ { "SHL", TOK_SHL },
+ { "SHR", TOK_SHR },
{ "SMART", TOK_SMART },
{ "STRING", TOK_STRING },
{ "SUNPLUS", TOK_SUNPLUS },
/* End of file. Add an empty line to the listing. This is a
* small hack needed to keep the PC output in sync.
*/
- NewListingLine ("", IFile->Pos.Name, ICount);
+ NewListingLine ("", IFile->Pos.Name, ICount);
C = EOF;
return;
}
-void NextTok (void)
+void NextRawTok (void)
/* Read the next raw token from the input stream */
{
/* If we've a forced end of assembly, don't read further */
return;
}
- /* If we're expanding a macro, the tokens come from the macro expansion */
- if (MacExpand ()) {
+Restart:
+ /* Check if we have tokens from another input source */
+ if (InputFromStack ()) {
return;
}
} else if (IsDefine (SVal)) {
/* This is a define style macro - expand it */
MacExpandStart ();
- if (!MacExpand ()) {
- goto Again;
- }
+ goto Restart;
} else {
/* An identifier */
Tok = TOK_IDENT;
IVal = 0;
do {
++IVal;
- NextChar ();
- } while (C == '+');
+ NextChar ();
+ } while (C == '+');
Tok = TOK_ULABEL;
break;
/* Handle as white space */
NextChar ();
C = ' ';
- goto Again;
- }
+ goto Again;
+ }
}
break;
case EOF:
/* Check if we have any open .IFs in this file */
CheckOpenIfs ();
+ /* Check if we have any open token lists in this file */
+ CheckInputStack ();
/* If this was an include file, then close it and handle like a
* separator. Do not close the main file, but return EOF.
-void Consume (enum Token Expected, unsigned ErrMsg)
-/* Consume Expected, print an error if we don't find it */
-{
- if (Tok == Expected) {
- NextTok ();
- } else {
- Error (ErrMsg);
- }
-}
-
-
-
-void ConsumeSep (void)
-/* Consume a separator token */
-{
- /* Accept an EOF as separator */
- if (Tok != TOK_EOF) {
- if (Tok != TOK_SEP) {
- Error (ERR_TOO_MANY_CHARS);
- SkipUntilSep ();
- } else {
- NextTok ();
- }
- }
-}
-
-
-
-void ConsumeLParen (void)
-/* Consume a left paren */
-{
- Consume (TOK_LPAREN, ERR_LPAREN_EXPECTED);
-}
-
-
-
-void ConsumeRParen (void)
-/* Consume a right paren */
-{
- Consume (TOK_RPAREN, ERR_RPAREN_EXPECTED);
-}
-
-
-
-void ConsumeComma (void)
-/* Consume a comma */
-{
- Consume (TOK_COMMA, ERR_COMMA_EXPECTED);
-}
-
-
-
-void SkipUntilSep (void)
-/* Skip tokens until we reach a line separator */
-{
- while (Tok != TOK_SEP && Tok != TOK_EOF) {
- NextTok ();
- }
-}
-
-
-
int TokHasSVal (enum Token Tok)
/* Return true if the given token has an attached SVal */
{
TOK_MACPACK,
TOK_MACRO,
TOK_MATCH,
+ TOK_MID,
TOK_NULL,
TOK_ORG,
TOK_OUT,
void UpcaseSVal (void);
/* Make SVal upper case */
-void NextTok (void);
-/* Read the next token from the input stream */
-
-void Consume (enum Token Expected, unsigned ErrMsg);
-/* Consume Token, print an error if we don't find it */
-
-void ConsumeSep (void);
-/* Consume a separator token */
-
-void ConsumeLParen (void);
-/* Consume a left paren */
-
-void ConsumeRParen (void);
-/* Consume a right paren */
-
-void ConsumeComma (void);
-/* Consume a comma */
-
-void SkipUntilSep (void);
-/* Skip tokens until we reach a line separator */
+void NextRawTok (void);
+/* Read the next raw token from the input stream */
int TokHasSVal (enum Token Tok);
/* Return true if the given token has an attached SVal */
--- /dev/null
+/*****************************************************************************/
+/* */
+/* toklist.c */
+/* */
+/* Token list for the ca65 macroassembler */
+/* */
+/* */
+/* */
+/* (C) 1998 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 <string.h>
+
+#include "mem.h"
+#include "scanner.h"
+#include "toklist.h"
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+TokNode* NewTokNode (void)
+/* Create and return a token node with the current token value */
+{
+ TokNode* T;
+
+ /* Allocate memory */
+ unsigned Len = TokHasSVal (Tok)? strlen (SVal) : 0;
+ T = Xmalloc (sizeof (TokNode) + Len);
+
+ /* Initialize the token contents */
+ T->Next = 0;
+ T->Tok = Tok;
+ T->WS = WS;
+ T->IVal = IVal;
+ memcpy (T->SVal, SVal, Len);
+ T->SVal [Len] = '\0';
+
+ /* Return the node */
+ return T;
+}
+
+
+
+void FreeTokNode (TokNode* T)
+/* Free the given token node */
+{
+ Xfree (T);
+}
+
+
+
+void TokSet (TokNode* T)
+/* Set the scanner token from the given token node */
+{
+ /* Set the values */
+ Tok = T->Tok;
+ WS = T->WS;
+ IVal = T->IVal;
+ strcpy (SVal, T->SVal);
+}
+
+
+
+enum TC TokCmp (const TokNode* T)
+/* Compare the token given as parameter against the current token */
+{
+ if (T->Tok != Tok) {
+ /* Different token */
+ return tcDifferent;
+ }
+
+ /* If the token has string attribute, check it */
+ if (TokHasSVal (T->Tok)) {
+ if (strcmp (T->SVal, SVal) != 0) {
+ return tcSameToken;
+ }
+ } else if (TokHasIVal (T->Tok)) {
+ if (T->IVal != IVal) {
+ return tcSameToken;
+ }
+ }
+
+ /* Tokens are identical */
+ return tcIdentical;
+}
+
+
+
+void InitTokList (TokList* T)
+/* Initialize a token list structure for later use */
+{
+ /* Initialize the fields */
+ T->Next = 0;
+ T->Root = 0;
+ T->Last = 0;
+ T->Repeat = 1;
+ T->Count = 0;
+}
+
+
+
+TokList* NewTokList (void)
+/* Create a new, empty token list */
+{
+ /* Allocate memory for the list structure */
+ TokList* T = Xmalloc (sizeof (TokList));
+
+ /* Initialize the fields */
+ InitTokList (T);
+
+ /* Return the new list */
+ return T;
+}
+
+
+
+void FreeTokList (TokList* List)
+/* Delete the token list including all token nodes */
+{
+ /* Free the token list */
+ TokNode* T = List->Root;
+ while (T) {
+ TokNode* Tmp = T;
+ T = T->Next;
+ FreeTokNode (Tmp);
+ }
+
+ /* Free the list structure itself */
+ Xfree (List);
+}
+
+
+
+void AddCurTok (TokList* List)
+/* Add the current token to the token list */
+{
+ /* Create a token node with the current token value */
+ TokNode* T = NewTokNode ();
+
+ /* Insert the node into the list */
+ if (List->Root == 0) {
+ List->Root = T;
+ } else {
+ List->Last->Next = T;
+ }
+ List->Last = T;
+
+ /* Count nodes */
+ List->Count++;
+}
+
+
+
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* toklist.h */
+/* */
+/* Token list for the ca65 macroassembler */
+/* */
+/* */
+/* */
+/* (C) 2000 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. */
+/* */
+/*****************************************************************************/
+
+
+
+#ifndef TOKLIST_H
+#define TOKLIST_H
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+/* Struct holding a token */
+typedef struct TokNode TokNode;
+struct TokNode {
+ TokNode* Next; /* For single linked list */
+ enum Token Tok; /* Token value */
+ int WS; /* Whitespace before token? */
+ long IVal; /* Integer token attribute */
+ char SVal [1]; /* String attribute, dyn. allocated */
+};
+
+/* Struct holding a token list */
+typedef struct TokList TokList;
+struct TokList {
+ TokList* Next; /* Single linked list (for replay) */
+ TokNode* Root; /* First node in list */
+ TokNode* Last; /* Last node in list or replay */
+ unsigned Repeat; /* Repeat counter (used for replay) */
+ unsigned Count; /* Token count */
+};
+
+
+
+/* Return codes for TokCmp - higher numeric code means better match */
+enum TC {
+ tcDifferent, /* Different tokents */
+ tcSameToken, /* Same token, different attribute */
+ tcIdentical /* Identical (token + attribute) */
+};
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+TokNode* NewTokNode (void);
+/* Create and return a token node with the current token value */
+
+void FreeTokNode (TokNode* T);
+/* Free the given token node */
+
+void TokSet (TokNode* T);
+/* Set the scanner token from the given token node */
+
+enum TC TokCmp (const TokNode* T);
+/* Compare the token given as parameter against the current token */
+
+void InitTokList (TokList* T);
+/* Initialize a token list structure for later use */
+
+TokList* NewTokList (void);
+/* Create a new, empty token list */
+
+void FreeTokList (TokList* T);
+/* Delete the token list including all token nodes */
+
+void AddCurTok (TokList* T);
+/* Add the current token to the token list */
+
+
+
+/* End of toklist.h */
+
+#endif
+
+
+
+
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* toknode.c */
-/* */
-/* Token list node for the ca65 macroassembler */
-/* */
-/* */
-/* */
-/* (C) 1998 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 <string.h>
-
-#include "mem.h"
-#include "scanner.h"
-#include "toknode.h"
-
-
-
-/*****************************************************************************/
-/* Code */
-/*****************************************************************************/
-
-
-
-TokNode* NewTokNode (void)
-/* Create and return a token node with the current token value */
-{
- TokNode* T;
-
- /* Allocate memory */
- unsigned Len = TokHasSVal (Tok)? strlen (SVal) : 0;
- T = Xmalloc (sizeof (TokNode) + Len);
-
- /* Initialize the token contents */
- T->Next = 0;
- T->Tok = Tok;
- T->WS = WS;
- T->IVal = IVal;
- memcpy (T->SVal, SVal, Len);
- T->SVal [Len] = '\0';
-
- /* Return the node */
- return T;
-}
-
-
-
-void FreeTokNode (TokNode* T)
-/* Free the given token node */
-{
- Xfree (T);
-}
-
-
-
-void TokSet (TokNode* T)
-/* Set the scanner token from the given token node */
-{
- /* Set the values */
- Tok = T->Tok;
- WS = T->WS;
- IVal = T->IVal;
- strcpy (SVal, T->SVal);
-}
-
-
-
-enum TC TokCmp (const TokNode* T)
-/* Compare the token given as parameter against the current token */
-{
- if (T->Tok != Tok) {
- /* Different token */
- return tcDifferent;
- }
-
- /* If the token has string attribute, check it */
- if (TokHasSVal (T->Tok)) {
- if (strcmp (T->SVal, SVal) != 0) {
- return tcSameToken;
- }
- } else if (TokHasIVal (T->Tok)) {
- if (T->IVal != IVal) {
- return tcSameToken;
- }
- }
-
- /* Tokens are identical */
- return tcIdentical;
-}
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* toknode.h */
-/* */
-/* Token list node for the ca65 macroassembler */
-/* */
-/* */
-/* */
-/* (C) 1998 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. */
-/* */
-/*****************************************************************************/
-
-
-
-#ifndef TOKNODE_H
-#define TOKNODE_H
-
-
-
-/*****************************************************************************/
-/* Data */
-/*****************************************************************************/
-
-
-
-/* Struct holding a token */
-typedef struct TokNode_ TokNode;
-struct TokNode_ {
- TokNode* Next; /* For single linked list */
- enum Token Tok; /* Token value */
- int WS; /* Whitespace before token? */
- long IVal; /* Integer token attribute */
- char SVal [1]; /* String attribute, dyn. allocated */
-};
-
-
-
-/* Return codes for TokCmp - higher numeric code means better match */
-enum TC {
- tcDifferent, /* Different tokents */
- tcSameToken, /* Same token, different attribute */
- tcIdentical /* Identical (token + attribute) */
-};
-
-
-
-/*****************************************************************************/
-/* Code */
-/*****************************************************************************/
-
-
-
-TokNode* NewTokNode (void);
-/* Create and return a token node with the current token value */
-
-void FreeTokNode (TokNode* T);
-/* Free the given token node */
-
-void TokSet (TokNode* T);
-/* Set the scanner token from the given token node */
-
-enum TC TokCmp (const TokNode* T);
-/* Compare the token given as parameter against the current token */
-
-
-
-/* End of toknode.h */
-
-#endif
-
-
-
-