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:
parent
0c85406f52
commit
fbe694bca3
@ -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 */
|
||||
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -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. */
|
||||
|
||||
|
||||
|
||||
|
@ -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 },
|
||||
|
@ -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 },
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user