]> git.sur5r.net Git - cc65/blob - src/ca65/nexttok.c
72c80708a22777dd6076c05ec94e8ce4c9be4326
[cc65] / src / ca65 / nexttok.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 nexttok.c                                 */
4 /*                                                                           */
5 /*              Get next token and handle token level functions              */
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 #include <stdio.h>
37
38 #include "error.h"
39 #include "expr.h"
40 #include "scanner.h"
41 #include "toklist.h"
42 #include "nexttok.h"
43
44
45
46 /*****************************************************************************/
47 /*                                   Code                                    */
48 /*****************************************************************************/
49
50
51
52 static TokList* CollectTokens (unsigned Start, unsigned Count)
53 /* Read a list of tokens that is terminated by a right paren. For all tokens
54  * starting at the one with index Start, and ending at (Start+Count-1), place
55  * them into a token list, and return this token list.
56  */
57 {
58     /* Create the token list */
59     TokList* List = NewTokList ();
60
61     /* Read the token list */
62     unsigned Current = 0;
63     unsigned Parens  = 0;
64     while (Parens != 0 || Tok != TOK_RPAREN) {
65
66         /* Check for end of line or end of input */
67         if (Tok == TOK_SEP || Tok == TOK_EOF) {
68             Error (ERR_UNEXPECTED_EOL);
69             return List;
70         }
71
72         /* Collect tokens in the given range */
73         if (Current >= Start && Current < Start+Count) {
74             /* Add the current token to the list */
75             AddCurTok (List);
76         }
77
78         /* Check for and count parenthesii */
79         if (Tok == TOK_LPAREN) {
80             ++Parens;
81         } else if (Tok == TOK_RPAREN) {
82             --Parens;
83         }
84
85         /* Get the next token */
86         ++Current;
87         NextTok ();
88     }
89
90     /* Eat the closing paren */
91     ConsumeRParen ();
92
93     /* Return the list of collected tokens */
94     return List;
95 }
96
97
98
99 static void FuncConcat (void)
100 /* Handle the .CONCAT function */
101 {
102     char        Buf[MAX_STR_LEN+1];
103     char*       B;
104     unsigned    Length;
105     unsigned    L;
106
107     /* Skip it */
108     NextTok ();
109
110     /* Left paren expected */
111     ConsumeLParen ();
112
113     /* Concatenate any number of strings */
114     B = Buf;
115     B[0] = '\0';
116     Length = 0;
117     while (1) {
118
119         /* Next token must be a string */
120         if (Tok != TOK_STRCON) {
121             Error (ERR_STRCON_EXPECTED);
122             SkipUntilSep ();
123             return;
124         }
125
126         /* Get the length of the string const and check total length */
127         L = strlen (SVal);
128         if (Length + L > MAX_STR_LEN) {
129             Error (ERR_STRING_TOO_LONG);
130             /* Try to recover */
131             SkipUntilSep ();
132             return;
133         }
134
135         /* Add the new string */
136         memcpy (B, SVal, L);
137         Length += L;
138         B      += L;
139
140         /* Skip the string token */
141         NextTok ();
142
143         /* Comma means another argument */
144         if (Tok == TOK_COMMA) {
145             NextTok ();
146         } else {
147             /* Done */
148             break;
149         }
150     }
151
152     /* Terminate the string */
153     *B = '\0';
154
155     /* We expect a closing parenthesis, but will not skip it but replace it
156      * by the string token just created.
157      */
158     if (Tok != TOK_RPAREN) {
159         Error (ERR_RPAREN_EXPECTED);
160     } else {
161         Tok = TOK_STRCON;
162         strcpy (SVal, Buf);
163     }
164 }
165
166
167
168 static void FuncMid (void)
169 /* Handle the .MID function */
170 {
171     long        Start;
172     long        Count;
173     TokList*    List;
174
175     /* Skip it */
176     NextTok ();
177
178     /* Left paren expected */
179     ConsumeLParen ();
180
181     /* Start argument */
182     Start = ConstExpression ();
183     if (Start < 0 || Start > 100) {
184         Error (ERR_RANGE);
185         Start = 0;
186     }
187     ConsumeComma ();
188
189     /* Count argument */
190     Count = ConstExpression ();
191     if (Count < 0 || Count > 100) {
192         Error (ERR_RANGE);
193         Count = 1;
194     }
195     ConsumeComma ();
196
197     /* Read the token list */
198     List = CollectTokens ((unsigned) Start, (unsigned) Count);
199
200     /* Insert it into the scanner feed */
201     PushTokList (List, ".MID");
202 }
203
204
205
206 static void FuncString (void)
207 /* Handle the .STRING function */
208 {
209     char Buf[MAX_STR_LEN+1];
210
211     /* Skip it */
212     NextTok ();
213
214     /* Left paren expected */
215     ConsumeLParen ();
216
217     /* Accept identifiers or numeric expressions */
218     if (Tok == TOK_IDENT) {
219         /* Save the identifier, then skip it */
220         strcpy (Buf, SVal);
221         NextTok ();
222     } else {
223         /* Numeric expression */
224         long Val = ConstExpression ();
225         sprintf (Buf, "%ld", Val);
226     }
227
228     /* We expect a closing parenthesis, but will not skip it but replace it
229      * by the string token just created.
230      */
231     if (Tok != TOK_RPAREN) {
232         Error (ERR_RPAREN_EXPECTED);
233     } else {
234         Tok = TOK_STRCON;
235         strcpy (SVal, Buf);
236     }
237 }
238
239
240
241 void NextTok (void)
242 /* Get next token and handle token level functions */
243 {
244     /* Get the next raw token */
245     NextRawTok ();
246
247     /* Check for token handling functions */
248     switch (Tok) {
249
250         case TOK_CONCAT:
251             FuncConcat ();
252             break;
253
254         case TOK_MID:
255             FuncMid ();
256             break;
257
258         case TOK_STRING:
259             FuncString ();
260             break;
261
262         default:
263             /* Quiet down gcc */
264             break;
265
266     }
267 }
268
269
270
271 void Consume (enum Token Expected, unsigned ErrMsg)
272 /* Consume Expected, print an error if we don't find it */
273 {
274     if (Tok == Expected) {
275         NextTok ();
276     } else {
277         Error (ErrMsg);
278     }
279 }
280
281
282
283 void ConsumeSep (void)
284 /* Consume a separator token */
285 {
286     /* Accept an EOF as separator */
287     if (Tok != TOK_EOF) {
288         if (Tok != TOK_SEP) {
289             Error (ERR_TOO_MANY_CHARS);
290             SkipUntilSep ();
291         } else {
292             NextTok ();
293         }
294     }
295 }
296
297
298
299 void ConsumeLParen (void)
300 /* Consume a left paren */
301 {
302     Consume (TOK_LPAREN, ERR_LPAREN_EXPECTED);
303 }
304
305
306
307 void ConsumeRParen (void)
308 /* Consume a right paren */
309 {
310     Consume (TOK_RPAREN, ERR_RPAREN_EXPECTED);
311 }
312
313
314
315 void ConsumeComma (void)
316 /* Consume a comma */
317 {
318     Consume (TOK_COMMA, ERR_COMMA_EXPECTED);
319 }
320
321
322
323 void SkipUntilSep (void)
324 /* Skip tokens until we reach a line separator */
325 {
326     while (Tok != TOK_SEP && Tok != TOK_EOF) {
327         NextTok ();
328     }
329 }
330
331
332