1 /*****************************************************************************/
5 /* Small scanner for input from a StrBuf */
9 /* (C) 2002-2009, 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 /*****************************************************************************/
45 #include "scanstrbuf.h"
49 /*****************************************************************************/
50 /* Helper functions */
51 /*****************************************************************************/
55 static int ParseChar (StrBuf* B)
56 /* Parse a character. Converts \n into EOL, etc. */
62 /* Check for escape chars */
63 if ((C = SB_Get (B)) == '\\') {
64 switch (SB_Peek (B)) {
111 /* Hex character constant */
113 C = HexVal (SB_Get (B)) << 4;
114 C |= HexVal (SB_Get (B));
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');
132 Error ("Character constant out of range");
137 Error ("Illegal character constant 0x%02X", SB_Get (B));
143 /* Return the character */
149 /*****************************************************************************/
151 /*****************************************************************************/
155 void SB_SkipWhite (StrBuf* B)
156 /* Skip whitespace in the string buffer */
158 while (IsBlank (SB_Peek (B))) {
165 int SB_GetSym (StrBuf* B, StrBuf* Ident, const char* SpecialChars)
166 /* Get a symbol from the string buffer. If SpecialChars is not NULL, it
167 * points to a string that contains characters allowed within the string in
168 * addition to letters, digits and the underline. Note: The identifier must
169 * still begin with a letter.
170 * Returns 1 if a symbol was found and 0 otherwise but doesn't output any
174 /* Handle a NULL argument for SpecialChars transparently */
175 if (SpecialChars == 0) {
182 if (IsIdent (SB_Peek (B))) {
183 char C = SB_Peek (B);
185 SB_AppendChar (Ident, C);
188 } while (IsIdent (C) || IsDigit (C) || strchr (SpecialChars, C) != 0);
189 SB_Terminate (Ident);
198 int SB_GetString (StrBuf* B, StrBuf* S)
199 /* Get a string from the string buffer. Returns 1 if a string was found and 0
200 * otherwise. Errors are only output in case of invalid strings (missing end
209 /* A string starts with quote marks */
210 if (SB_Peek (B) == '\"') {
212 /* String follows, be sure to concatenate strings */
213 while (SB_Peek (B) == '\"') {
215 /* Skip the quote char */
218 /* Read the actual string contents */
219 while ((C = SB_Peek (B)) != '\"') {
221 Error ("Unexpected end of string");
224 SB_AppendChar (S, ParseChar (B));
227 /* Skip the closing quote char if there was one */
230 /* Skip white space, read new input */
234 /* Terminate the string */
250 int SB_GetNumber (StrBuf* B, long* Val)
251 /* Get a number from the string buffer. Accepted formats are decimal, octal,
252 * hex and character constants. Numeric constants may be preceeded by a
253 * minus or plus sign. The function returns 1 if a number was found and
254 * zero otherwise. Errors are only output for invalid numbers.
266 /* Handle character constants */
267 if (SB_Peek (B) == '\'') {
269 /* Character constant */
271 *Val = SignExtendChar (TgtTranslateChar (ParseChar (B)));
272 if (SB_Peek (B) != '\'') {
273 Error ("`\'' expected");
282 /* Check for a sign. A sign must be followed by a digit, otherwise it's
286 switch (SB_Peek (B)) {
291 if (!IsDigit (SB_LookAt (B, SB_GetIndex (B) + 1))) {
298 /* We must have a digit now, otherwise its not a number */
304 /* Determine the base */
308 if (tolower (SB_Peek (B)) == 'x') {
311 if (!IsXDigit (SB_Peek (B))) {
312 Error ("Invalid hexadecimal number");
322 /* Read the number */
323 while (IsXDigit (C = SB_Peek (B)) && (DigitVal = HexVal (C)) < Base) {
324 *Val = (*Val * Base) + DigitVal;
328 /* Allow optional 'U' and 'L' modifiers */
330 if (C == 'u' || C == 'U') {
333 if (C == 'l' || C == 'L') {
336 } else if (C == 'l' || C == 'L') {
339 if (C == 'u' || C == 'U') {
344 /* Success, value read is in Val */