]> git.sur5r.net Git - cc65/blob - src/cc65/scanstrbuf.c
ValidSegName now defined in segnames.h
[cc65] / src / cc65 / scanstrbuf.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 scanstrbuf.c                              */
4 /*                                                                           */
5 /*                     Small scanner for input from a StrBuf                 */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2002      Ullrich von Bassewitz                                       */
10 /*               Wacholderweg 14                                             */
11 /*               D-70597 Stuttgart                                           */
12 /* EMail:        uz@cc65.org                                                 */
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 "chartype.h"
38 #include "tgttrans.h"
39
40 /* cc65 */
41 #include "datatype.h"
42 #include "error.h"
43 #include "hexval.h"
44 #include "ident.h"
45 #include "scanstrbuf.h"
46
47
48
49 /*****************************************************************************/
50 /*                               Helper functions                            */
51 /*****************************************************************************/
52
53
54
55 static char ParseChar (StrBuf* B)
56 /* Parse a character. Converts \n into EOL, etc. */
57 {
58     unsigned I;
59     int C;
60
61     /* Check for escape chars */
62     if ((C = SB_Get (B)) == '\\') {
63         switch (SB_Get (B)) {
64             case 'b':
65                 C = '\b';
66                 break;
67             case 'f':
68                 C = '\f';
69                 break;
70             case 'r':
71                 C = '\r';
72                 break;
73             case 'n':
74                 C = '\n';
75                 break;
76             case 't':
77                 C = '\t';
78                 break;
79             case '\"':
80                 C = '\"';
81                 break;
82             case '\'':
83                 C = '\'';
84                 break;
85             case '\\':
86                 C = '\\';
87                 break;
88             case 'x':
89             case 'X':
90                 /* Hex character constant */
91                 C = HexVal (SB_Get (B)) << 4;
92                 C |= HexVal (SB_Get (B));
93                 break;
94             case '0':
95                 /* Octal constant */
96                 C = 0;
97                 goto Octal;
98             case '1':
99                 /* Octal constant */
100                 C = 1;
101 Octal:          I = 0;
102                 while (SB_Peek (B) >= '0' && SB_Peek (B) <= '7' && I++ < 4) {
103                     C = (C << 3) | (SB_Get (B) - '0');
104                 }
105                 break;
106             default:
107                 Error ("Illegal character constant");
108                 C = ' ';
109                 break;
110         }
111     }
112
113     /* Return the character */
114     return C;
115 }
116
117
118
119
120
121
122
123 /*****************************************************************************/
124 /*                                   Code                                    */
125 /*****************************************************************************/
126
127
128
129 void SB_SkipWhite (StrBuf* B)
130 /* Skip whitespace in the string buffer */
131 {
132     while (IsBlank (SB_Peek (B))) {
133         SB_Skip (B);
134     }
135 }
136
137
138
139 int SB_GetSym (StrBuf* B, char* S)
140 /* Get a symbol from the string buffer. S must be able to hold MAX_IDENTLEN
141  * characters. Returns 1 if a symbol was found and 0 otherwise.
142  */
143 {
144     if (IsIdent (SB_Peek (B))) {
145         unsigned I = 0;
146         char C = SB_Peek (B);
147         do {
148             if (I < MAX_IDENTLEN) {
149                 ++I;
150                 *S++ = C;
151             }
152             SB_Skip (B);
153             C = SB_Peek (B);
154         } while (IsIdent (C) || IsDigit (C));
155         *S = '\0';
156         return 1;
157     } else {
158         return 0;
159     }
160 }
161
162
163
164 int SB_GetString (StrBuf* B, StrBuf* S)
165 /* Get a string from the string buffer. S will be initialized by the function
166  * and will return the correctly terminated string on return. The function
167  * returns 1 if a string was found and 0 otherwise.
168  */
169 {
170     char C;
171
172     /* Initialize S */
173     *S = AUTO_STRBUF_INITIALIZER;
174     if (SB_Peek (B) == '\"') {
175
176         /* String follows, be sure to concatenate strings */
177         while (SB_Peek (B) == '\"') {
178
179             /* Skip the quote char */
180             SB_Skip (B);
181
182             /* Read the actual string contents */
183             while ((C = SB_Peek (B)) != '\"') {
184                 if (C == '\0') {
185                     Error ("Unexpected end of string");
186                     break;
187                 }
188                 SB_AppendChar (S, ParseChar (B));
189             }
190
191             /* Skip the closing quote char if there was one */
192             SB_Skip (B);
193
194             /* Skip white space, read new input */
195             SB_SkipWhite (B);
196         }
197
198         /* Terminate the string */
199         SB_Terminate (S);
200
201         /* Success */
202         return 1;
203
204     } else {
205
206         /* Not a string */
207         SB_Terminate (S);
208         return 0;
209     }
210 }
211
212
213
214 int SB_GetNumber (StrBuf* B, long* Val)
215 /* Get a number from the string buffer. Accepted formats are decimal, octal,
216  * hex and character constants. Numeric constants may be preceeded by a
217  * minus or plus sign. The function returns 1 if a number was found and
218  * zero otherwise.
219  */
220 {
221     int      Sign;
222     char     C;
223     unsigned Base;
224     unsigned DigitVal;
225
226     /* Initialize Val */
227     *Val = 0;
228
229     /* Check for a sign */
230     Sign = 1;
231     switch (SB_Peek (B)) {
232         case '-':
233             Sign = -1;
234             /* FALLTHROUGH */
235         case '+':
236             SB_Skip (B);
237             SB_SkipWhite (B);
238             break;
239     }
240
241     /* Check for the different formats */
242     C = SB_Peek (B);
243     if (IsDigit (C)) {
244
245         if (C == '0') {
246             /* Hex or octal */
247             SB_Skip (B);
248             if (tolower (SB_Peek (B)) == 'x') {
249                 SB_Skip (B);
250                 Base = 16;
251                 if (!IsXDigit (SB_Peek (B))) {
252                     Error ("Invalid hexadecimal number");
253                     return 0;
254                 }
255             } else {
256                 Base = 8;
257             }
258         } else {
259             Base = 10;
260         }
261
262         /* Read the number */
263         while (IsXDigit (C = SB_Peek (B)) && (DigitVal = HexVal (C)) < Base) {
264             *Val = (*Val * Base) + DigitVal;
265             SB_Skip (B);
266         }
267
268         /* Allow optional 'U' and 'L' modifiers */
269         C = SB_Peek (B);
270         if (C == 'u' || C == 'U') {
271             SB_Skip (B);
272             C = SB_Peek (B);
273             if (C == 'l' || C == 'L') {
274                 SB_Skip (B);
275             }
276         } else if (C == 'l' || C == 'L') {
277             SB_Skip (B);
278             C = SB_Peek (B);
279             if (C == 'u' || C == 'U') {
280                 SB_Skip (B);
281             }
282         }
283
284     } else if (C == '\'') {
285
286         /* Character constant */
287         SB_Skip (B);
288         *Val = SignExtendChar (TgtTranslateChar (ParseChar (B)));
289         if (SB_Peek (B) != '\'') {
290             Error ("`\'' expected");
291             return 0;
292         } else {
293             /* Skip the quote */
294             SB_Skip (B);
295         }
296
297     } else {
298
299         /* Invalid number */
300         Error ("Numeric constant expected");
301         return 0;
302
303     }
304
305     /* Success, value read is in Val */
306     return 1;
307 }
308
309
310