]> git.sur5r.net Git - cc65/blob - src/ca65/repeat.c
Renamed EXP_INITIALIZER
[cc65] / src / ca65 / repeat.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 repeat.c                                  */
4 /*                                                                           */
5 /*                   Handle the .REPEAT pseudo instruction                   */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2000     Ullrich von Bassewitz                                        */
10 /*              Wacholderweg 14                                              */
11 /*              D-70597 Stuttgart                                            */
12 /* EMail:       uz@musoftware.de                                             */
13 /*                                                                           */
14 /*                                                                           */
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.                                    */
18 /*                                                                           */
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:                            */
22 /*                                                                           */
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              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 /* common */
37 #include "xmalloc.h"
38
39 /* ca65 */
40 #include "error.h"
41 #include "expr.h"
42 #include "nexttok.h"
43 #include "toklist.h"
44 #include "repeat.h"
45
46
47
48 /*****************************************************************************/
49 /*                                   Code                                    */
50 /*****************************************************************************/
51
52
53
54 static TokList* CollectRepeatTokens (void)
55 /* Collect all tokens inside the .REPEAT body in a token list and return
56  * this list. In case of errors, NULL is returned.
57  */
58 {
59     /* Create the token list */
60     TokList* List = NewTokList ();
61
62     /* Read the token list */
63     unsigned Repeats = 0;
64     while (Repeats != 0 || Tok != TOK_ENDREP) {
65
66         /* Check for end of input */
67         if (Tok == TOK_EOF) {
68             Error (ERR_UNEXPECTED_EOF);
69             FreeTokList (List);
70             return 0;
71         }
72
73         /* If we find a token that is equal to the repeat counter name,
74          * replace it by a REPCOUNTER token. This way we have to do strcmps
75          * only once for each identifier, and not for each expansion.
76          * Note: This will fail for nested repeats using the same repeat
77          * counter name, but
78          */
79
80
81
82         /* Collect all tokens in the list */
83         AddCurTok (List);
84
85         /* Check for and count nested .REPEATs */
86         if (Tok == TOK_REPEAT) {
87             ++Repeats;
88         } else if (Tok == TOK_ENDREP) {
89             --Repeats;
90         }
91
92         /* Get the next token */
93         NextTok ();
94     }
95
96     /* Eat the closing .ENDREP */
97     NextTok ();
98
99     /* Return the list of collected tokens */
100     return List;
101 }
102
103
104
105 static void RepeatTokenCheck (TokList* L)
106 /* Called each time a token from a repeat token list is set. Is used to check
107  * for and replace identifiers that are the repeat counter.
108  */
109 {                 
110     if (Tok == TOK_IDENT && L->Data != 0 && strcmp (SVal, L->Data) == 0) {
111         /* Must replace by the repeat counter */
112         Tok  = TOK_INTCON;
113         IVal = L->RepCount;
114     }
115 }
116
117
118
119 void ParseRepeat (void)
120 /* Parse and handle the .REPEAT statement */
121 {
122     char* Name;
123     TokList* List;
124
125     /* Repeat count follows */
126     long RepCount = ConstExpression ();
127     if (RepCount < 0) {
128         Error (ERR_RANGE);
129         RepCount = 0;
130     }
131
132     /* Optional there is a comma and a counter variable */
133     Name = 0;
134     if (Tok == TOK_COMMA) {
135
136         /* Skip the comma */
137         NextTok ();
138
139         /* Check for an identifier */
140         if (Tok != TOK_IDENT) {
141             ErrorSkip (ERR_IDENT_EXPECTED);
142         } else {
143             /* Remember the name and skip it */
144             Name = xstrdup (SVal);
145             NextTok ();
146         }
147     }
148
149     /* Separator */
150     ConsumeSep ();
151
152     /* Read the token list */
153     List = CollectRepeatTokens ();
154
155     /* If we had an error, bail out */
156     if (List == 0) {
157         xfree (Name);
158         return;
159     }
160
161     /* Update the token list for replay */
162     List->RepMax = (unsigned) RepCount;
163     List->Data   = Name;
164     List->Check  = RepeatTokenCheck;
165
166     /* If the list is empty, or repeat count zero, there is nothing
167      * to repeat.
168      */
169     if (List->Count == 0 || RepCount == 0) {
170         FreeTokList (List);
171         return;
172     }
173
174     /* Read input from the repeat descriptor */
175     PushTokList (List, ".REPEAT");
176 }
177
178
179