mirror of
https://github.com/cc65/cc65.git
synced 2024-12-25 17:29:50 +00:00
Added a more generic way to push sources that deliver a token stream
independent of the actual input from the file. Change macro handling to use the new input stack. Fixed an error in FreeIf: If an unexpected .ENDIF was reached, the assembler started an endless loop printing error messages. git-svn-id: svn://svn.cc65.org/cc65/trunk@24 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
5e561a0f40
commit
522c7e8c46
@ -35,7 +35,7 @@
|
||||
|
||||
#include "error.h"
|
||||
#include "expr.h"
|
||||
#include "scanner.h"
|
||||
#include "nexttok.h"
|
||||
#include "symtab.h"
|
||||
#include "condasm.h"
|
||||
|
||||
@ -124,6 +124,7 @@ static void FreeIf (void)
|
||||
IfDesc* D = GetCurrentIf();
|
||||
if (D == 0) {
|
||||
Error (ERR_UNEXPECTED, ".ENDIF");
|
||||
Done = 1;
|
||||
} else {
|
||||
Done = (D->Flags & ifNeedTerm) != 0;
|
||||
--IfCount;
|
||||
@ -416,3 +417,21 @@ void CheckOpenIfs (void)
|
||||
|
||||
|
||||
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -52,6 +52,12 @@ void CheckOpenIfs (void);
|
||||
* 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 */
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include "error.h"
|
||||
#include "expr.h"
|
||||
#include "instr.h"
|
||||
#include "scanner.h"
|
||||
#include "nexttok.h"
|
||||
#include "ea.h"
|
||||
|
||||
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "scanner.h"
|
||||
#include "nexttok.h"
|
||||
#include "error.h"
|
||||
|
||||
|
||||
@ -190,6 +190,7 @@ void ErrorMsg (const FilePos* Pos, unsigned ErrNum, va_list ap)
|
||||
"CPU not supported",
|
||||
"Counter underflow",
|
||||
"Undefined label",
|
||||
"Open `%s´",
|
||||
};
|
||||
|
||||
fprintf (stderr, "%s(%lu): Error #%u: ",
|
||||
@ -257,7 +258,7 @@ void Fatal (unsigned FatNum, ...)
|
||||
"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;
|
||||
|
@ -123,6 +123,7 @@ enum Errors {
|
||||
ERR_CPU_NOT_SUPPORTED,
|
||||
ERR_COUNTER_UNDERFLOW,
|
||||
ERR_UNDEFINED_LABEL,
|
||||
ERR_OPEN_STMT,
|
||||
ERR_COUNT /* Error count */
|
||||
};
|
||||
|
||||
@ -140,7 +141,7 @@ enum Fatals {
|
||||
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 */
|
||||
};
|
||||
|
@ -39,11 +39,11 @@
|
||||
#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"
|
||||
|
||||
|
@ -43,8 +43,8 @@
|
||||
#include "error.h"
|
||||
#include "expr.h"
|
||||
#include "global.h"
|
||||
#include "nexttok.h"
|
||||
#include "objcode.h"
|
||||
#include "scanner.h"
|
||||
#include "instr.h"
|
||||
|
||||
|
||||
|
149
src/ca65/istack.c
Normal file
149
src/ca65/istack.c
Normal file
@ -0,0 +1,149 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
71
src/ca65/istack.h
Normal file
71
src/ca65/istack.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* 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
|
||||
|
||||
|
||||
|
||||
|
300
src/ca65/macro.c
300
src/ca65/macro.c
@ -38,11 +38,13 @@
|
||||
|
||||
#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"
|
||||
|
||||
|
||||
@ -90,6 +92,7 @@ typedef struct MacExp_ MacExp;
|
||||
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 */
|
||||
@ -98,10 +101,13 @@ struct MacExp_ {
|
||||
TokNode* ParamExp; /* Node for expanding parameters */
|
||||
};
|
||||
|
||||
/* Data for macro expansions */
|
||||
#define MAX_MACRO_EXPANSIONS 255
|
||||
static unsigned MacroNesting = 0;
|
||||
static MacExp* CurMac = 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;
|
||||
|
||||
|
||||
@ -172,6 +178,7 @@ static MacExp* NewMacExp (Macro* M)
|
||||
|
||||
/* Initialize the data */
|
||||
E->M = M;
|
||||
E->IfSP = GetIfStack ();
|
||||
E->Exp = M->TokRoot;
|
||||
E->Final = 0;
|
||||
E->LocalStart = LocalName;
|
||||
@ -183,44 +190,34 @@ static MacExp* NewMacExp (Macro* M)
|
||||
E->Params [I] = 0;
|
||||
}
|
||||
|
||||
/* And return it... */
|
||||
/* One macro expansion more */
|
||||
++MacExpansions;
|
||||
|
||||
/* Return the new macro expansion */
|
||||
return E;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void MacInsertExp (MacExp* E)
|
||||
/* Insert a macro expansion into the list */
|
||||
{
|
||||
E->Next = CurMac;
|
||||
CurMac = E;
|
||||
++MacroNesting;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
@ -461,6 +458,123 @@ void MacDef (unsigned Style)
|
||||
|
||||
|
||||
|
||||
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 */
|
||||
{
|
||||
@ -522,8 +636,8 @@ static void StartExpClassic (Macro* M)
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert the newly created structure into the expansion list */
|
||||
MacInsertExp (E);
|
||||
/* Insert a new token input function */
|
||||
PushInput (MacExpand, E, ".MACRO");
|
||||
}
|
||||
|
||||
|
||||
@ -596,8 +710,8 @@ static void StartExpDefine (Macro* M)
|
||||
*/
|
||||
E->Final = NewTokNode ();
|
||||
|
||||
/* Insert the newly created structure into the expansion list */
|
||||
MacInsertExp (E);
|
||||
/* Insert a new token input function */
|
||||
PushInput (MacExpand, E, ".DEFINE");
|
||||
}
|
||||
|
||||
|
||||
@ -605,15 +719,8 @@ static void StartExpDefine (Macro* M)
|
||||
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 */
|
||||
@ -626,115 +733,14 @@ void MacExpandStart (void)
|
||||
|
||||
|
||||
|
||||
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 ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MacAbort (void)
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
@ -759,7 +765,7 @@ int IsDefine (const char* Name)
|
||||
int InMacExpansion (void)
|
||||
/* Return true if we're currently expanding a macro */
|
||||
{
|
||||
return MacroNesting != 0;
|
||||
return (MacExpansions > 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -62,12 +62,6 @@ void MacDef (unsigned Style);
|
||||
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 */
|
||||
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "listing.h"
|
||||
#include "macro.h"
|
||||
#include "mem.h"
|
||||
#include "nexttok.h"
|
||||
#include "objcode.h"
|
||||
#include "objfile.h"
|
||||
#include "options.h"
|
||||
|
@ -15,11 +15,13 @@ OBJS = condasm.o \
|
||||
global.o \
|
||||
incpath.o \
|
||||
instr.o \
|
||||
istack.o \
|
||||
listing.o \
|
||||
macpack.o \
|
||||
macro.o \
|
||||
main.o \
|
||||
mem.o \
|
||||
nexttok.o \
|
||||
objcode.o \
|
||||
objfile.o \
|
||||
options.o \
|
||||
@ -27,7 +29,7 @@ OBJS = condasm.o \
|
||||
scanner.o \
|
||||
strexpr.o \
|
||||
symtab.o \
|
||||
toknode.o \
|
||||
toklist.o \
|
||||
ulabel.o
|
||||
|
||||
LIBS = ../common/common.a
|
||||
@ -62,3 +64,4 @@ depend dep: $(OBJS:.o=.c)
|
||||
@echo "Creating dependency information"
|
||||
$(CC) -MM $^ > .depend
|
||||
|
||||
|
||||
|
@ -72,11 +72,13 @@ OBJS = condasm.obj \
|
||||
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 \
|
||||
@ -84,7 +86,7 @@ OBJS = condasm.obj \
|
||||
scanner.obj \
|
||||
strexpr.obj \
|
||||
symtab.obj \
|
||||
toknode.obj \
|
||||
toklist.obj \
|
||||
ulabel.obj
|
||||
|
||||
LIBS = ..\common\common.lib
|
||||
@ -116,11 +118,13 @@ FILE fragment.obj
|
||||
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
|
||||
@ -128,7 +132,7 @@ FILE pseudo.obj
|
||||
FILE scanner.obj
|
||||
FILE strexpr.obj
|
||||
FILE symtab.obj
|
||||
FILE toknode.obj
|
||||
FILE toklist.obj
|
||||
FILE ulabel.obj
|
||||
LIBRARY ..\common\common.lib
|
||||
|
|
||||
|
219
src/ca65/nexttok.c
Normal file
219
src/ca65/nexttok.c
Normal file
@ -0,0 +1,219 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* 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 ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
80
src/ca65/nexttok.h
Normal file
80
src/ca65/nexttok.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* 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
|
||||
|
||||
|
||||
|
||||
|
@ -49,9 +49,9 @@
|
||||
#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"
|
||||
@ -789,6 +789,16 @@ static void DoMacro (void)
|
||||
|
||||
|
||||
|
||||
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 */
|
||||
{
|
||||
@ -1119,6 +1129,7 @@ static CtrlDesc CtrlCmdTab [] = {
|
||||
{ ccNone, DoMacPack },
|
||||
{ ccNone, DoMacro },
|
||||
{ ccNone, DoUnexpected }, /* .MATCH */
|
||||
{ ccNone, DoMid },
|
||||
{ ccNone, DoNull },
|
||||
{ ccNone, DoOrg },
|
||||
{ ccNone, DoOut },
|
||||
|
@ -46,10 +46,12 @@
|
||||
#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"
|
||||
|
||||
|
||||
@ -104,10 +106,10 @@ static struct {
|
||||
static unsigned FileCount = 0;
|
||||
|
||||
/* Current input variables */
|
||||
static InputFile* IFile = 0;
|
||||
static InputData* IData = 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;
|
||||
static int C = 0; /* Current input character */
|
||||
|
||||
/* Force end of assembly */
|
||||
int ForcedEnd = 0;
|
||||
@ -189,6 +191,7 @@ struct DotKeyword {
|
||||
{ "MACPACK", TOK_MACPACK },
|
||||
{ "MACRO", TOK_MACRO },
|
||||
{ "MATCH", TOK_MATCH },
|
||||
{ "MID", TOK_MID },
|
||||
{ "MOD", TOK_MOD },
|
||||
{ "NOT", TOK_BNOT },
|
||||
{ "NULL", TOK_NULL },
|
||||
@ -627,7 +630,7 @@ static unsigned ReadStringConst (int StringTerm)
|
||||
|
||||
|
||||
|
||||
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 */
|
||||
@ -636,8 +639,9 @@ void NextTok (void)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -813,9 +817,7 @@ Again:
|
||||
} 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;
|
||||
@ -1042,6 +1044,8 @@ CharAgain:
|
||||
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.
|
||||
@ -1065,68 +1069,6 @@ CharAgain:
|
||||
|
||||
|
||||
|
||||
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 */
|
||||
{
|
||||
|
@ -168,6 +168,7 @@ enum Token {
|
||||
TOK_MACPACK,
|
||||
TOK_MACRO,
|
||||
TOK_MATCH,
|
||||
TOK_MID,
|
||||
TOK_NULL,
|
||||
TOK_ORG,
|
||||
TOK_OUT,
|
||||
@ -230,26 +231,8 @@ void NewInputData (const char* Data, int Malloced);
|
||||
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 */
|
||||
|
@ -1,8 +1,8 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* toknode.c */
|
||||
/* toklist.c */
|
||||
/* */
|
||||
/* Token list node for the ca65 macroassembler */
|
||||
/* Token list for the ca65 macroassembler */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
@ -37,7 +37,7 @@
|
||||
|
||||
#include "mem.h"
|
||||
#include "scanner.h"
|
||||
#include "toknode.h"
|
||||
#include "toklist.h"
|
||||
|
||||
|
||||
|
||||
@ -115,3 +115,71 @@ enum TC TokCmp (const TokNode* T)
|
||||
|
||||
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* toknode.h */
|
||||
/* toklist.h */
|
||||
/* */
|
||||
/* Token list node for the ca65 macroassembler */
|
||||
/* Token list for the ca65 macroassembler */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998 Ullrich von Bassewitz */
|
||||
/* (C) 2000 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
@ -33,8 +33,8 @@
|
||||
|
||||
|
||||
|
||||
#ifndef TOKNODE_H
|
||||
#define TOKNODE_H
|
||||
#ifndef TOKLIST_H
|
||||
#define TOKLIST_H
|
||||
|
||||
|
||||
|
||||
@ -45,8 +45,8 @@
|
||||
|
||||
|
||||
/* Struct holding a token */
|
||||
typedef struct TokNode_ TokNode;
|
||||
struct TokNode_ {
|
||||
typedef struct TokNode TokNode;
|
||||
struct TokNode {
|
||||
TokNode* Next; /* For single linked list */
|
||||
enum Token Tok; /* Token value */
|
||||
int WS; /* Whitespace before token? */
|
||||
@ -54,6 +54,16 @@ struct TokNode_ {
|
||||
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 */
|
||||
@ -83,9 +93,21 @@ void TokSet (TokNode* T);
|
||||
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 toknode.h */
|
||||
|
||||
/* End of toklist.h */
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user