1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-25 17:29:50 +00:00

Added/finished .MID, .LEFT, .RIGHT

git-svn-id: svn://svn.cc65.org/cc65/trunk@136 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2000-07-08 14:01:43 +00:00
parent 0c85406f52
commit fbe694bca3
8 changed files with 273 additions and 77 deletions

View File

@ -290,6 +290,9 @@ void MacDef (unsigned Style)
/* Define the macro */ /* Define the macro */
M = NewMacro (SVal, HashVal, Style); M = NewMacro (SVal, HashVal, Style);
/* Switch to raw token mode and skip the macro name */
EnterRawTokenMode ();
NextTok (); NextTok ();
/* If we have a DEFINE style macro, we may have parameters in braces, /* If we have a DEFINE style macro, we may have parameters in braces,
@ -371,7 +374,7 @@ void MacDef (unsigned Style)
/* May not have end of file in a macro definition */ /* May not have end of file in a macro definition */
if (Tok == TOK_EOF) { if (Tok == TOK_EOF) {
Error (ERR_ENDMACRO_EXPECTED); Error (ERR_ENDMACRO_EXPECTED);
return; goto Done;
} }
} else { } else {
/* Accept a newline or end of file for new style macros */ /* Accept a newline or end of file for new style macros */
@ -454,6 +457,10 @@ void MacDef (unsigned Style)
if (Style == MAC_STYLE_CLASSIC) { if (Style == MAC_STYLE_CLASSIC) {
NextTok (); NextTok ();
} }
Done:
/* Switch out of raw token mode */
LeaveRawTokenMode ();
} }
@ -650,7 +657,7 @@ static void StartExpDefine (Macro* M)
/* A define style macro must be called with as many actual parameters /* A define style macro must be called with as many actual parameters
* as there are formal ones. Get the parameter count. * as there are formal ones. Get the parameter count.
*/ */
unsigned Count = M->ParamCount; unsigned Count = M->ParamCount;
/* Skip the current token */ /* Skip the current token */

View File

@ -328,33 +328,31 @@ static void OneLine (void)
* is no colon, it's an assignment. * is no colon, it's an assignment.
*/ */
if (Tok == TOK_EQ) { if (Tok == TOK_EQ) {
/* Skip the '=' */ /* Skip the '=' */
NextTok (); NextTok ();
/* Define the symbol with the expression following the /* Define the symbol with the expression following the '=' */
* '=' SymDef (Ident, Expression (), 0);
*/ /* Don't allow anything after a symbol definition */
SymDef (Ident, Expression (), 0); Done = 1;
/* Don't allow anything after a symbol definition */
Done = 1;
} else { } else {
/* Define a label */ /* Define a label */
SymDef (Ident, CurrentPC (), IsZPSeg ()); SymDef (Ident, CurrentPC (), IsZPSeg ());
/* Skip the colon. If NoColonLabels is enabled, allow labels /* Skip the colon. If NoColonLabels is enabled, allow labels
* without a colon if there is no whitespace before the * without a colon if there is no whitespace before the
* identifier. * identifier.
*/ */
if (Tok != TOK_COLON) { if (Tok != TOK_COLON) {
if (HadWS || !NoColonLabels) { if (HadWS || !NoColonLabels) {
Error (ERR_COLON_EXPECTED); Error (ERR_COLON_EXPECTED);
} }
if (Tok == TOK_NAMESPACE) { if (Tok == TOK_NAMESPACE) {
/* Smart :: handling */ /* Smart :: handling */
NextTok (); NextTok ();
} }
} else { } else {
/* Skip the colon */ /* Skip the colon */
NextTok (); NextTok ();
} }
} }
} }
} }

View File

@ -43,6 +43,16 @@
/*****************************************************************************/
/* Data */
/*****************************************************************************/
static unsigned RawMode = 0; /* Raw token mode flag/counter */
/*****************************************************************************/ /*****************************************************************************/
/* Code */ /* Code */
/*****************************************************************************/ /*****************************************************************************/
@ -63,28 +73,28 @@ static TokList* CollectTokens (unsigned Start, unsigned Count)
unsigned Parens = 0; unsigned Parens = 0;
while (Parens != 0 || Tok != TOK_RPAREN) { while (Parens != 0 || Tok != TOK_RPAREN) {
/* Check for end of line or end of input */ /* Check for end of line or end of input */
if (Tok == TOK_SEP || Tok == TOK_EOF) { if (Tok == TOK_SEP || Tok == TOK_EOF) {
Error (ERR_UNEXPECTED_EOL); Error (ERR_UNEXPECTED_EOL);
return List; return List;
} }
/* Collect tokens in the given range */ /* Collect tokens in the given range */
if (Current >= Start && Current < Start+Count) { if (Current >= Start && Current < Start+Count) {
/* Add the current token to the list */ /* Add the current token to the list */
AddCurTok (List); AddCurTok (List);
} }
/* Check for and count parenthesii */ /* Check for and count parenthesii */
if (Tok == TOK_LPAREN) { if (Tok == TOK_LPAREN) {
++Parens; ++Parens;
} else if (Tok == TOK_RPAREN) { } else if (Tok == TOK_RPAREN) {
--Parens; --Parens;
} }
/* Get the next token */ /* Get the next token */
++Current; ++Current;
NextTok (); NextTok ();
} }
/* Eat the closing paren */ /* Eat the closing paren */
@ -165,6 +175,47 @@ static void FuncConcat (void)
static void FuncLeft (void)
/* Handle the .LEFT function */
{
long Count;
TokList* List;
/* Skip it */
NextTok ();
/* Left paren expected */
ConsumeLParen ();
/* Count argument */
Count = ConstExpression ();
if (Count < 0 || Count > 100) {
Error (ERR_RANGE);
Count = 1;
}
ConsumeComma ();
/* Read the token list */
List = CollectTokens (0, (unsigned) Count);
/* Since we want to insert the list before the now current token, we have
* to save the current token in some way and then skip it. To do this, we
* will add the current token at the end of the token list (so the list
* will never be empty), push the token list, and then skip the current
* token. This will replace the current token by the first token from the
* list (which will be the old current token in case the list was empty).
*/
AddCurTok (List);
/* Insert it into the scanner feed */
PushTokList (List, ".LEFT");
/* Skip the current token */
NextTok ();
}
static void FuncMid (void) static void FuncMid (void)
/* Handle the .MID function */ /* Handle the .MID function */
{ {
@ -181,7 +232,7 @@ static void FuncMid (void)
/* Start argument */ /* Start argument */
Start = ConstExpression (); Start = ConstExpression ();
if (Start < 0 || Start > 100) { if (Start < 0 || Start > 100) {
Error (ERR_RANGE); Error (ERR_RANGE);
Start = 0; Start = 0;
} }
ConsumeComma (); ConsumeComma ();
@ -189,16 +240,84 @@ static void FuncMid (void)
/* Count argument */ /* Count argument */
Count = ConstExpression (); Count = ConstExpression ();
if (Count < 0 || Count > 100) { if (Count < 0 || Count > 100) {
Error (ERR_RANGE); Error (ERR_RANGE);
Count = 1; Count = 1;
} }
ConsumeComma (); ConsumeComma ();
/* Read the token list */ /* Read the token list */
List = CollectTokens ((unsigned) Start, (unsigned) Count); List = CollectTokens ((unsigned) Start, (unsigned) Count);
/* Since we want to insert the list before the now current token, we have
* to save the current token in some way and then skip it. To do this, we
* will add the current token at the end of the token list (so the list
* will never be empty), push the token list, and then skip the current
* token. This will replace the current token by the first token from the
* list (which will be the old current token in case the list was empty).
*/
AddCurTok (List);
/* Insert it into the scanner feed */ /* Insert it into the scanner feed */
PushTokList (List, ".MID"); PushTokList (List, ".MID");
/* Skip the current token */
NextTok ();
}
static void FuncRight (void)
/* Handle the .RIGHT function */
{
long Count;
TokList* List;
/* Skip it */
NextTok ();
/* Left paren expected */
ConsumeLParen ();
/* Count argument */
Count = ConstExpression ();
if (Count < 0 || Count > 100) {
Error (ERR_RANGE);
Count = 1;
}
ConsumeComma ();
/* Read the complete token list */
List = CollectTokens (0, 9999);
/* Delete tokens from the list until Count tokens are remaining */
while (List->Count > Count) {
/* Get the first node */
TokNode* T = List->Root;
/* Remove it from the list */
List->Root = List->Root->Next;
/* Free the node */
FreeTokNode (T);
/* Corrent the token counter */
List->Count--;
}
/* Since we want to insert the list before the now current token, we have
* to save the current token in some way and then skip it. To do this, we
* will add the current token at the end of the token list (so the list
* will never be empty), push the token list, and then skip the current
* token. This will replace the current token by the first token from the
* list (which will be the old current token in case the list was empty).
*/
AddCurTok (List);
/* Insert it into the scanner feed */
PushTokList (List, ".RIGHT");
/* Skip the current token */
NextTok ();
} }
@ -244,25 +363,37 @@ void NextTok (void)
/* Get the next raw token */ /* Get the next raw token */
NextRawTok (); NextRawTok ();
/* Check for token handling functions */ /* In raw mode, pass the token unchanged */
switch (Tok) { if (RawMode == 0) {
case TOK_CONCAT: /* Execute token handling functions */
FuncConcat (); switch (Tok) {
break;
case TOK_MID: case TOK_CONCAT:
FuncMid (); FuncConcat ();
break; break;
case TOK_STRING: case TOK_LEFT:
FuncString (); FuncLeft ();
break; break;
default: case TOK_MID:
/* Quiet down gcc */ FuncMid ();
break; break;
case TOK_RIGHT:
FuncRight ();
break;
case TOK_STRING:
FuncString ();
break;
default:
/* Quiet down gcc */
break;
}
} }
} }
@ -321,7 +452,7 @@ void ConsumeComma (void)
void SkipUntilSep (void) void SkipUntilSep (void)
/* Skip tokens until we reach a line separator */ /* Skip tokens until we reach a line separator or end of file */
{ {
while (Tok != TOK_SEP && Tok != TOK_EOF) { while (Tok != TOK_SEP && Tok != TOK_EOF) {
NextTok (); NextTok ();
@ -330,3 +461,25 @@ void SkipUntilSep (void)
void EnterRawTokenMode (void)
/* Enter raw token mode. In raw mode, token handling functions are not
* executed, but the function tokens are passed untouched to the upper
* layer. Raw token mode is used when storing macro tokens for later
* use.
* Calls to EnterRawTokenMode and LeaveRawTokenMode may be nested.
*/
{
++RawMode;
}
void LeaveRawTokenMode (void)
/* Leave raw token mode. */
{
PRECONDITION (RawMode > 0);
--RawMode;
}

View File

@ -67,7 +67,18 @@ void ConsumeComma (void);
/* Consume a comma */ /* Consume a comma */
void SkipUntilSep (void); void SkipUntilSep (void);
/* Skip tokens until we reach a line separator */ /* Skip tokens until we reach a line separator or end of file */
void EnterRawTokenMode (void);
/* Enter raw token mode. In raw mode, token handling functions are not
* executed, but the function tokens are passed untouched to the upper
* layer. Raw token mode is used when storing macro tokens for later
* use.
* Calls to EnterRawTokenMode and LeaveRawTokenMode may be nested.
*/
void LeaveRawTokenMode (void);
/* Leave raw token mode. */

View File

@ -75,6 +75,16 @@ static char Keyword [sizeof (SVal)+1] = ".";
static void DoUnexpected (void); static void DoUnexpected (void);
/* Got an unexpected keyword */
static void DoInvalid (void);
/* Handle a token that is invalid here, since it should have been handled on
* a much lower level of the expression hierarchy. Getting this sort of token
* means that the lower level code has bugs.
* This function differs to DoUnexpected in that the latter may be triggered
* by the user by using keywords in the wrong location. DoUnexpected is not
* an error in the assembler itself, while DoInvalid is.
*/
@ -696,6 +706,20 @@ static void DoInclude (void)
static void DoInvalid (void)
/* Handle a token that is invalid here, since it should have been handled on
* a much lower level of the expression hierarchy. Getting this sort of token
* means that the lower level code has bugs.
* This function differs to DoUnexpected in that the latter may be triggered
* by the user by using keywords in the wrong location. DoUnexpected is not
* an error in the assembler itself, while DoInvalid is.
*/
{
Internal ("Unexpected token: %s", Keyword);
}
static void DoLineCont (void) static void DoLineCont (void)
/* Switch the use of line continuations */ /* Switch the use of line continuations */
{ {
@ -788,16 +812,6 @@ 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) static void DoNull (void)
/* Switch to the NULL segment */ /* Switch to the NULL segment */
{ {
@ -1121,6 +1135,7 @@ static CtrlDesc CtrlCmdTab [] = {
{ ccNone, DoImportZP }, { ccNone, DoImportZP },
{ ccNone, DoIncBin }, { ccNone, DoIncBin },
{ ccNone, DoInclude }, { ccNone, DoInclude },
{ ccNone, DoInvalid }, /* .LEFT */
{ ccNone, DoLineCont }, { ccNone, DoLineCont },
{ ccNone, DoList }, { ccNone, DoList },
{ ccNone, DoListBytes }, { ccNone, DoListBytes },
@ -1129,7 +1144,7 @@ static CtrlDesc CtrlCmdTab [] = {
{ ccNone, DoMacPack }, { ccNone, DoMacPack },
{ ccNone, DoMacro }, { ccNone, DoMacro },
{ ccNone, DoUnexpected }, /* .MATCH */ { ccNone, DoUnexpected }, /* .MATCH */
{ ccNone, DoMid }, { ccNone, DoInvalid }, /* .MID */
{ ccNone, DoNull }, { ccNone, DoNull },
{ ccNone, DoOrg }, { ccNone, DoOrg },
{ ccNone, DoOut }, { ccNone, DoOut },
@ -1143,6 +1158,7 @@ static CtrlDesc CtrlCmdTab [] = {
{ ccNone, DoReloc }, { ccNone, DoReloc },
{ ccNone, DoRepeat }, { ccNone, DoRepeat },
{ ccNone, DoRes }, { ccNone, DoRes },
{ ccNone, DoInvalid }, /* .RIGHT */
{ ccNone, DoROData }, { ccNone, DoROData },
{ ccNone, DoSegment }, { ccNone, DoSegment },
{ ccNone, DoSmart }, { ccNone, DoSmart },

View File

@ -184,6 +184,7 @@ struct DotKeyword {
{ "IMPORTZP", TOK_IMPORTZP }, { "IMPORTZP", TOK_IMPORTZP },
{ "INCBIN", TOK_INCBIN }, { "INCBIN", TOK_INCBIN },
{ "INCLUDE", TOK_INCLUDE }, { "INCLUDE", TOK_INCLUDE },
{ "LEFT", TOK_LEFT },
{ "LINECONT", TOK_LINECONT }, { "LINECONT", TOK_LINECONT },
{ "LIST", TOK_LIST }, { "LIST", TOK_LIST },
{ "LISTBYTES", TOK_LISTBYTES }, { "LISTBYTES", TOK_LISTBYTES },
@ -212,6 +213,7 @@ struct DotKeyword {
{ "RELOC", TOK_RELOC }, { "RELOC", TOK_RELOC },
{ "REPEAT", TOK_REPEAT }, { "REPEAT", TOK_REPEAT },
{ "RES", TOK_RES }, { "RES", TOK_RES },
{ "RIGHT", TOK_RIGHT },
{ "RODATA", TOK_RODATA }, { "RODATA", TOK_RODATA },
{ "SEGMENT", TOK_SEGMENT }, { "SEGMENT", TOK_SEGMENT },
{ "SHL", TOK_SHL }, { "SHL", TOK_SHL },

View File

@ -161,6 +161,7 @@ enum Token {
TOK_IMPORTZP, TOK_IMPORTZP,
TOK_INCBIN, TOK_INCBIN,
TOK_INCLUDE, TOK_INCLUDE,
TOK_LEFT,
TOK_LINECONT, TOK_LINECONT,
TOK_LIST, TOK_LIST,
TOK_LISTBYTES, TOK_LISTBYTES,
@ -182,7 +183,8 @@ enum Token {
TOK_REFERENCED, TOK_REFERENCED,
TOK_RELOC, TOK_RELOC,
TOK_REPEAT, TOK_REPEAT,
TOK_RES, TOK_RES,
TOK_RIGHT,
TOK_RODATA, TOK_RODATA,
TOK_SEGMENT, TOK_SEGMENT,
TOK_SMART, TOK_SMART,

View File

@ -37,6 +37,7 @@
#include "../common/xmalloc.h" #include "../common/xmalloc.h"
#include "error.h"
#include "istack.h" #include "istack.h"
#include "scanner.h" #include "scanner.h"
#include "toklist.h" #include "toklist.h"
@ -191,9 +192,15 @@ static int ReplayTokList (void* List)
/* Cast the generic pointer to an actual list */ /* Cast the generic pointer to an actual list */
TokList* L = List; TokList* L = List;
/* Last may never be a NULL pointer, otherwise there's a bug in the code */
CHECK (L->Last != 0);
/* Set the next token from the list */ /* Set the next token from the list */
TokSet (L->Last); TokSet (L->Last);
/* Set the pointer to the next token */
L->Last = L->Last->Next;
/* If this was the last token, decrement the repeat counter. If it goes /* If this was the last token, decrement the repeat counter. If it goes
* zero, delete the list and remove the function from the stack. * zero, delete the list and remove the function from the stack.
*/ */