From 44a11218e1ee8193707b8a627b2407860bfd2eaa Mon Sep 17 00:00:00 2001 From: cuz Date: Fri, 28 Jul 2000 12:15:40 +0000 Subject: [PATCH] Added .REPEAT pseudo instruction git-svn-id: svn://svn.cc65.org/cc65/trunk@215 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ca65/listing.c | 41 ++++++--- src/ca65/main.c | 12 +-- src/ca65/make/gcc.mak | 29 ++++--- src/ca65/make/watcom.mak | 2 + src/ca65/pseudo.c | 9 +- src/ca65/repeat.c | 179 +++++++++++++++++++++++++++++++++++++++ src/ca65/repeat.h | 58 +++++++++++++ src/ca65/scanner.h | 3 +- src/ca65/toklist.c | 29 +++++-- src/ca65/toklist.h | 23 ++--- 10 files changed, 334 insertions(+), 51 deletions(-) create mode 100644 src/ca65/repeat.c create mode 100644 src/ca65/repeat.h diff --git a/src/ca65/listing.c b/src/ca65/listing.c index 05dc6c4ec..3f3fb3d79 100644 --- a/src/ca65/listing.c +++ b/src/ca65/listing.c @@ -37,11 +37,13 @@ #include #include -#include "../common/fname.h" -#include "../common/segdefs.h" -#include "../common/version.h" -#include "../common/xmalloc.h" +/* common */ +#include "fname.h" +#include "segdefs.h" +#include "version.h" +#include "xmalloc.h" +/* ca65 */ #include "error.h" #include "global.h" #include "objcode.h" @@ -50,7 +52,7 @@ /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ @@ -167,13 +169,28 @@ void InitListingLine (void) { if (Listing) { /* Make the last loaded line the current line */ - LineCur = LineLast; + /* ###### This code is a hack! We really need to do it right + * as soon as we know, how:-( + */ + if (LineCur && LineCur->Next && LineCur->Next != LineLast) { + ListLine* L = LineCur; + do { + L = L->Next; + /* Set the values for this line */ + CHECK (L != 0); + L->PC = GetPC (); + L->Reloc = RelocMode; + L->Output = (ListingEnabled > 0); + L->ListBytes = (unsigned char) ListBytes; + } while (L->Next != LineLast); + } + LineCur = LineLast; - /* Set the values for this line */ - CHECK (LineCur != 0); - LineCur->PC = GetPC (); - LineCur->Reloc = RelocMode; - LineCur->Output = (ListingEnabled > 0); + /* Set the values for this line */ + CHECK (LineCur != 0); + LineCur->PC = GetPC (); + LineCur->Reloc = RelocMode; + LineCur->Output = (ListingEnabled > 0); LineCur->ListBytes = (unsigned char) ListBytes; } } @@ -345,7 +362,7 @@ void CreateListing (void) break; case FRAG_EXPR: - case FRAG_SEXPR: + case FRAG_SEXPR: B = AddMult (B, 'r', Frag->Len*2); break; diff --git a/src/ca65/main.c b/src/ca65/main.c index f28224cb9..9f947f649 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -39,9 +39,11 @@ #include #include -#include "../common/cmdline.h" -#include "../common/version.h" - +/* common */ +#include "cmdline.h" +#include "version.h" + +/* ca65 */ #include "error.h" #include "expr.h" #include "global.h" @@ -301,11 +303,11 @@ static void OneLine (void) int Done = 0; /* Initialize the new listing line if we are actually reading from file - * and not from internally pushed input. + * and not from internally pushed input. */ if (!HavePushedInput ()) { InitListingLine (); - } + } if (Tok == TOK_COLON) { /* An unnamed label */ diff --git a/src/ca65/make/gcc.mak b/src/ca65/make/gcc.mak index 90494d084..807099892 100644 --- a/src/ca65/make/gcc.mak +++ b/src/ca65/make/gcc.mak @@ -1,8 +1,8 @@ # -# gcc Makefile for a65, link65 & libr65 +# gcc Makefile for ca65 # -CFLAGS = -g -O2 -Wall +CFLAGS = -g -O2 -Wall -I../common CC = gcc LDFLAGS = @@ -12,18 +12,19 @@ OBJS = condasm.o \ expr.o \ fragment.o \ global.o \ - incpath.o \ - instr.o \ - istack.o \ - listing.o \ - macpack.o \ - macro.o \ - main.o \ - nexttok.o \ - objcode.o \ - objfile.o \ - options.o \ - pseudo.o \ + incpath.o \ + instr.o \ + istack.o \ + listing.o \ + macpack.o \ + macro.o \ + main.o \ + nexttok.o \ + objcode.o \ + objfile.o \ + options.o \ + pseudo.o \ + repeat.o \ scanner.o \ symtab.o \ toklist.o \ diff --git a/src/ca65/make/watcom.mak b/src/ca65/make/watcom.mak index 430b964fb..bc9539964 100644 --- a/src/ca65/make/watcom.mak +++ b/src/ca65/make/watcom.mak @@ -81,6 +81,7 @@ OBJS = condasm.obj \ objfile.obj \ options.obj \ pseudo.obj \ + repeat.obj \ scanner.obj \ symtab.obj \ toklist.obj \ @@ -124,6 +125,7 @@ FILE objcode.obj FILE objfile.obj FILE options.obj FILE pseudo.obj +FILE repeat.obj FILE scanner.obj FILE symtab.obj FILE toklist.obj diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index fb2a6cee0..29befcea6 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -39,8 +39,10 @@ #include #include -#include "../common/bitops.h" +/* common */ +#include "bitops.h" +/* ca65 */ #include "condasm.h" #include "error.h" #include "expr.h" @@ -52,6 +54,7 @@ #include "nexttok.h" #include "objcode.h" #include "options.h" +#include "repeat.h" #include "symtab.h" #include "pseudo.h" @@ -906,7 +909,7 @@ static void DoReloc (void) static void DoRepeat (void) /* Repeat some instruction block */ { - ErrorSkip (ERR_NOT_IMPLEMENTED); + ParseRepeat (); } @@ -1043,7 +1046,7 @@ static void DoWarning (void) if (Tok != TOK_STRCON) { ErrorSkip (ERR_STRCON_EXPECTED); } else { - Error (WARN_USER, SVal); + Warning (WARN_USER, SVal); SkipUntilSep (); } } diff --git a/src/ca65/repeat.c b/src/ca65/repeat.c new file mode 100644 index 000000000..b442c165f --- /dev/null +++ b/src/ca65/repeat.c @@ -0,0 +1,179 @@ +/*****************************************************************************/ +/* */ +/* repeat.c */ +/* */ +/* Handle the .REPEAT pseudo instruction */ +/* */ +/* */ +/* */ +/* (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. */ +/* */ +/*****************************************************************************/ + + + +/* common */ +#include "xmalloc.h" + +/* ca65 */ +#include "error.h" +#include "expr.h" +#include "nexttok.h" +#include "toklist.h" +#include "repeat.h" + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +static TokList* CollectRepeatTokens (void) +/* Collect all tokens inside the .REPEAT body in a token list and return + * this list. In case of errors, NULL is returned. + */ +{ + /* Create the token list */ + TokList* List = NewTokList (); + + /* Read the token list */ + unsigned Repeats = 0; + while (Repeats != 0 || Tok != TOK_ENDREP) { + + /* Check for end of input */ + if (Tok == TOK_EOF) { + Error (ERR_UNEXPECTED_EOF); + FreeTokList (List); + return 0; + } + + /* If we find a token that is equal to the repeat counter name, + * replace it by a REPCOUNTER token. This way we have to do strcmps + * only once for each identifier, and not for each expansion. + * Note: This will fail for nested repeats using the same repeat + * counter name, but + */ + + + + /* Collect all tokens in the list */ + AddCurTok (List); + + /* Check for and count nested .REPEATs */ + if (Tok == TOK_REPEAT) { + ++Repeats; + } else if (Tok == TOK_ENDREP) { + --Repeats; + } + + /* Get the next token */ + NextTok (); + } + + /* Eat the closing .ENDREP */ + NextTok (); + + /* Return the list of collected tokens */ + return List; +} + + + +static void RepeatTokenCheck (TokList* L) +/* Called each time a token from a repeat token list is set. Is used to check + * for and replace identifiers that are the repeat counter. + */ +{ + if (Tok == TOK_IDENT && L->Data != 0 && strcmp (SVal, L->Data) == 0) { + /* Must replace by the repeat counter */ + Tok = TOK_INTCON; + IVal = L->RepCount; + } +} + + + +void ParseRepeat (void) +/* Parse and handle the .REPEAT statement */ +{ + char* Name; + TokList* List; + + /* Repeat count follows */ + long RepCount = ConstExpression (); + if (RepCount < 0) { + Error (ERR_RANGE); + RepCount = 0; + } + + /* Optional there is a comma and a counter variable */ + Name = 0; + if (Tok == TOK_COMMA) { + + /* Skip the comma */ + NextTok (); + + /* Check for an identifier */ + if (Tok != TOK_IDENT) { + ErrorSkip (ERR_IDENT_EXPECTED); + } else { + /* Remember the name and skip it */ + Name = xstrdup (SVal); + NextTok (); + } + } + + /* Separator */ + ConsumeSep (); + + /* Read the token list */ + List = CollectRepeatTokens (); + + /* If we had an error, bail out */ + if (List == 0) { + xfree (Name); + return; + } + + /* Update the token list for replay */ + List->RepMax = (unsigned) RepCount; + List->Data = Name; + List->Check = RepeatTokenCheck; + + /* If the list is empty, or repeat count zero, there is nothing + * to repeat. + */ + if (List->Count == 0 || RepCount == 0) { + FreeTokList (List); + return; + } + + /* Read input from the repeat descriptor */ + PushTokList (List, ".REPEAT"); +} + + + diff --git a/src/ca65/repeat.h b/src/ca65/repeat.h new file mode 100644 index 000000000..8bb5d3ec8 --- /dev/null +++ b/src/ca65/repeat.h @@ -0,0 +1,58 @@ +/*****************************************************************************/ +/* */ +/* repeat.h */ +/* */ +/* Handle the .REPEAT pseudo instruction */ +/* */ +/* */ +/* */ +/* (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 REPEAT_H +#define REPEAT_H + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +void ParseRepeat (void); +/* Parse and handle the .REPEAT statement */ + + + +/* End of repeat.h */ + +#endif + + + + diff --git a/src/ca65/scanner.h b/src/ca65/scanner.h index 4c43b6c85..952c6bab0 100644 --- a/src/ca65/scanner.h +++ b/src/ca65/scanner.h @@ -38,7 +38,8 @@ -#include "../common/filepos.h" +/* common */ +#include "filepos.h" diff --git a/src/ca65/toklist.c b/src/ca65/toklist.c index ab93a6766..82137f720 100644 --- a/src/ca65/toklist.c +++ b/src/ca65/toklist.c @@ -34,9 +34,11 @@ #include - -#include "../common/xmalloc.h" - + +/* common */ +#include "xmalloc.h" + +/* ca65 */ #include "error.h" #include "istack.h" #include "scanner.h" @@ -62,7 +64,7 @@ TokNode* NewTokNode (void) /* Initialize the token contents */ T->Next = 0; T->Tok = Tok; - T->WS = WS; + T->WS = WS; T->IVal = IVal; memcpy (T->SVal, SVal, Len); T->SVal [Len] = '\0'; @@ -125,8 +127,11 @@ void InitTokList (TokList* T) T->Next = 0; T->Root = 0; T->Last = 0; - T->Repeat = 1; + T->RepCount = 0; + T->RepMax = 1; T->Count = 0; + T->Check = 0; + T->Data = 0; } @@ -157,6 +162,11 @@ void FreeTokList (TokList* List) FreeTokNode (Tmp); } + /* If we have associated data, free it */ + if (List->Data) { + xfree (List->Data); + } + /* Free the list structure itself */ xfree (List); } @@ -198,6 +208,13 @@ static int ReplayTokList (void* List) /* Set the next token from the list */ TokSet (L->Last); + /* If a check function is defined, call it, so it may look at the token + * just set and changed it as apropriate. + */ + if (L->Check) { + L->Check (L); + } + /* Set the pointer to the next token */ L->Last = L->Last->Next; @@ -205,7 +222,7 @@ static int ReplayTokList (void* List) * zero, delete the list and remove the function from the stack. */ if (L->Last == 0) { - if (--L->Repeat == 0) { + if (++L->RepCount >= L->RepMax) { /* Done with this list */ FreeTokList (L); PopInput (); diff --git a/src/ca65/toklist.h b/src/ca65/toklist.h index 498631d83..9826724d4 100644 --- a/src/ca65/toklist.h +++ b/src/ca65/toklist.h @@ -47,21 +47,24 @@ /* 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 */ + 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 */ + TokList* Next; /* Single linked list (for replay) */ + TokNode* Root; /* First node in list */ + TokNode* Last; /* Last node in list or replay */ + unsigned RepCount; /* Repeat counter (used for replay) */ + unsigned RepMax; /* Maximum repeat count for replay */ + unsigned Count; /* Token count */ + void (*Check)(TokList*); /* Token check function */ + void* Data; /* Additional data for check */ }; -- 2.39.5