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 */
M = NewMacro (SVal, HashVal, Style);
/* Switch to raw token mode and skip the macro name */
EnterRawTokenMode ();
NextTok ();
/* 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 */
if (Tok == TOK_EOF) {
Error (ERR_ENDMACRO_EXPECTED);
return;
goto Done;
}
} else {
/* Accept a newline or end of file for new style macros */
@ -454,6 +457,10 @@ void MacDef (unsigned Style)
if (Style == MAC_STYLE_CLASSIC) {
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
* as there are formal ones. Get the parameter count.
*/
*/
unsigned Count = M->ParamCount;
/* Skip the current token */

View File

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

View File

@ -43,6 +43,16 @@
/*****************************************************************************/
/* Data */
/*****************************************************************************/
static unsigned RawMode = 0; /* Raw token mode flag/counter */
/*****************************************************************************/
/* Code */
/*****************************************************************************/
@ -63,28 +73,28 @@ static TokList* CollectTokens (unsigned Start, unsigned Count)
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;
}
/* 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);
}
/* 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;
}
/* Check for and count parenthesii */
if (Tok == TOK_LPAREN) {
++Parens;
} else if (Tok == TOK_RPAREN) {
--Parens;
}
/* Get the next token */
++Current;
NextTok ();
/* Get the next token */
++Current;
NextTok ();
}
/* 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)
/* Handle the .MID function */
{
@ -181,7 +232,7 @@ static void FuncMid (void)
/* Start argument */
Start = ConstExpression ();
if (Start < 0 || Start > 100) {
Error (ERR_RANGE);
Error (ERR_RANGE);
Start = 0;
}
ConsumeComma ();
@ -189,16 +240,84 @@ static void FuncMid (void)
/* Count argument */
Count = ConstExpression ();
if (Count < 0 || Count > 100) {
Error (ERR_RANGE);
Count = 1;
Error (ERR_RANGE);
Count = 1;
}
ConsumeComma ();
/* Read the token list */
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 */
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 */
NextRawTok ();
/* Check for token handling functions */
switch (Tok) {
/* In raw mode, pass the token unchanged */
if (RawMode == 0) {
case TOK_CONCAT:
FuncConcat ();
break;
/* Execute token handling functions */
switch (Tok) {
case TOK_MID:
FuncMid ();
break;
case TOK_CONCAT:
FuncConcat ();
break;
case TOK_STRING:
FuncString ();
break;
case TOK_LEFT:
FuncLeft ();
break;
default:
/* Quiet down gcc */
break;
case TOK_MID:
FuncMid ();
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)
/* 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) {
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 */
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);
/* 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)
/* 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)
/* Switch to the NULL segment */
{
@ -1121,6 +1135,7 @@ static CtrlDesc CtrlCmdTab [] = {
{ ccNone, DoImportZP },
{ ccNone, DoIncBin },
{ ccNone, DoInclude },
{ ccNone, DoInvalid }, /* .LEFT */
{ ccNone, DoLineCont },
{ ccNone, DoList },
{ ccNone, DoListBytes },
@ -1129,7 +1144,7 @@ static CtrlDesc CtrlCmdTab [] = {
{ ccNone, DoMacPack },
{ ccNone, DoMacro },
{ ccNone, DoUnexpected }, /* .MATCH */
{ ccNone, DoMid },
{ ccNone, DoInvalid }, /* .MID */
{ ccNone, DoNull },
{ ccNone, DoOrg },
{ ccNone, DoOut },
@ -1143,6 +1158,7 @@ static CtrlDesc CtrlCmdTab [] = {
{ ccNone, DoReloc },
{ ccNone, DoRepeat },
{ ccNone, DoRes },
{ ccNone, DoInvalid }, /* .RIGHT */
{ ccNone, DoROData },
{ ccNone, DoSegment },
{ ccNone, DoSmart },

View File

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

View File

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

View File

@ -37,6 +37,7 @@
#include "../common/xmalloc.h"
#include "error.h"
#include "istack.h"
#include "scanner.h"
#include "toklist.h"
@ -191,9 +192,15 @@ static int ReplayTokList (void* List)
/* Cast the generic pointer to an actual 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 */
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
* zero, delete the list and remove the function from the stack.
*/