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