1 /*****************************************************************************/
5 /* Handle the .REPEAT pseudo instruction */
9 /* (C) 2000-2011, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
50 /*****************************************************************************/
52 /*****************************************************************************/
56 static TokList* CollectRepeatTokens (void)
57 /* Collect all tokens inside the .REPEAT body in a token list and return
58 * this list. In case of errors, NULL is returned.
61 /* Create the token list */
62 TokList* List = NewTokList ();
64 /* Read the token list */
66 while (Repeats != 0 || CurTok.Tok != TOK_ENDREP) {
68 /* Check for end of input */
69 if (CurTok.Tok == TOK_EOF) {
70 Error ("Unexpected end of file");
75 /* Collect all tokens in the list */
78 /* Check for and count nested .REPEATs */
79 if (CurTok.Tok == TOK_REPEAT) {
81 } else if (CurTok.Tok == TOK_ENDREP) {
85 /* Get the next token */
89 /* Eat the closing .ENDREP */
92 /* Return the list of collected tokens */
98 static void RepeatTokenCheck (TokList* L)
99 /* Called each time a token from a repeat token list is set. Is used to check
100 * for and replace identifiers that are the repeat counter.
103 if (CurTok.Tok == TOK_IDENT &&
105 SB_CompareStr (&CurTok.SVal, L->Data) == 0) {
106 /* Must replace by the repeat counter */
107 CurTok.Tok = TOK_INTCON;
108 CurTok.IVal = L->RepCount;
114 void ParseRepeat (void)
115 /* Parse and handle the .REPEAT statement */
120 /* Repeat count follows */
121 long RepCount = ConstExpression ();
123 Error ("Range error");
127 /* Optional there is a comma and a counter variable */
129 if (CurTok.Tok == TOK_COMMA) {
134 /* Check for an identifier */
135 if (CurTok.Tok != TOK_IDENT) {
136 ErrorSkip ("Identifier expected");
138 /* Remember the name and skip it */
139 SB_Terminate (&CurTok.SVal);
140 Name = xstrdup (SB_GetConstBuf (&CurTok.SVal));
145 /* Switch to raw token mode, then skip the separator */
146 EnterRawTokenMode ();
149 /* Read the token list */
150 List = CollectRepeatTokens ();
152 /* If we had an error, bail out */
158 /* Update the token list for replay */
159 List->RepMax = (unsigned) RepCount;
161 List->Check = RepeatTokenCheck;
163 /* If the list is empty, or repeat count zero, there is nothing
166 if (List->Count == 0 || RepCount == 0) {
171 /* Read input from the repeat descriptor */
172 PushTokList (List, ".REPEAT");
175 /* Switch out of raw token mode */
176 LeaveRawTokenMode ();