Color SvgParser::GetColor(const String& text_) { String text = ToLower(text_); if(text == "none" || text.IsEmpty()) return Null; else if(*text == '#') { const char *b = ~text + 1; while(*b && !IsXDigit(*b)) b++; const char *s = b; while(IsXDigit(*s)) s++; int col = ScanInt(b, NULL, 16); if(s - b <= 3) { col = (col & 0xf) | ((col & 0xf0) << 4) | ((col & 0xf00) << 8); col |= col << 4; } return Color((col >> 16) & 255, (col >> 8) & 255, col & 255); } else { try {
unsigned HexVal (int C) /* Convert a hex digit into a value. The function will emit an error for * invalid hex digits. */ { if (!IsXDigit (C)) { Error ("Invalid hexadecimal digit: `%c'", C); } if (IsDigit (C)) { return C - '0'; } else { return toupper (C) - 'A' + 10; } }
static int GetEncodedChar (char* Buf, unsigned* IPtr, unsigned Size) { char Decoded = 0; int Count; if (C == EOF) { return -1; } else if (C != '\\') { Decoded = C; NextChar (); goto Store; } NextChar (); /* consume '\\' */ if (C == EOF) { return -1; } else if (IsODigit (C)) { Count = 3; do { Decoded = Decoded * 8 + DigitVal (C); NextChar (); --Count; } while (Count > 0 && C != EOF && IsODigit (C)); } else if (C == 'x') { NextChar (); /* consume 'x' */ Count = 2; while (Count > 0 && C != EOF && IsXDigit (C)) { Decoded = Decoded * 16 + DigitVal (C); NextChar (); --Count; } } else { switch (C) { case '"': case '\'': case '\\': Decoded = C; break; case 't': Decoded = '\t'; break; case 'r': Decoded = '\r'; break; case 'n': Decoded = '\n'; break; default: return -1; } NextChar (); } Store: if (*IPtr < Size - 1) { Buf [(*IPtr)++] = Decoded; } Buf [*IPtr] = 0; return 0; }
static int try_parse_v6_netmask(const char *text, struct irc_ssaddr *addr, int *b) { const char *p; char c; int d[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; int dp = 0; int nyble = 4; int finsert = -1; int bits = 128; int deficit = 0; short dc[8]; struct sockaddr_in6 *v6 = (struct sockaddr_in6*) addr; for (p = text; (c = *p); p++) if (IsXDigit(c)) { if (nyble == 0) return HM_HOST; DigitParse(c); d[dp] |= c << (4 * --nyble); } else if (c == ':') { if (p > text && *(p - 1) == ':') { if (finsert >= 0) return HM_HOST; finsert = dp; } else { /* If there were less than 4 hex digits, e.g. :ABC: shift right * so we don't interpret it as ABC0 -A1kmm */ d[dp] = d[dp] >> 4 * nyble; nyble = 4; if (++dp >= 8) return HM_HOST; } } else if (c == '*')
static int exec(FILE* fp, ENC_INFO* einfo) { #define NCOL 8 int c, val, enc; enc = einfo->num; fprintf(fp, "static const unsigned short Enc%s_CtypeTable[256] = {\n", einfo->name); for (c = 0; c < 256; c++) { val = 0; if (IsNewline(enc, c)) val |= BIT_CTYPE_NEWLINE; if (IsAlpha (enc, c)) val |= (BIT_CTYPE_ALPHA | BIT_CTYPE_ALNUM); if (IsBlank (enc, c)) val |= BIT_CTYPE_BLANK; if (IsCntrl (enc, c)) val |= BIT_CTYPE_CNTRL; if (IsDigit (enc, c)) val |= (BIT_CTYPE_DIGIT | BIT_CTYPE_ALNUM); if (IsGraph (enc, c)) val |= BIT_CTYPE_GRAPH; if (IsLower (enc, c)) val |= BIT_CTYPE_LOWER; if (IsPrint (enc, c)) val |= BIT_CTYPE_PRINT; if (IsPunct (enc, c)) val |= BIT_CTYPE_PUNCT; if (IsSpace (enc, c)) val |= BIT_CTYPE_SPACE; if (IsUpper (enc, c)) val |= BIT_CTYPE_UPPER; if (IsXDigit(enc, c)) val |= BIT_CTYPE_XDIGIT; if (IsWord (enc, c)) val |= BIT_CTYPE_WORD; if (IsAscii (enc, c)) val |= BIT_CTYPE_ASCII; if (c % NCOL == 0) fputs(" ", fp); fprintf(fp, "0x%04x", val); if (c != 255) fputs(",", fp); if (c != 0 && c % NCOL == (NCOL-1)) fputs("\n", fp); else fputs(" ", fp); } fprintf(fp, "};\n"); return 0; }
static int ValidateType (StrBuf* Type) /* Check if the given type is valid and if so, return a string id for it. If ** the type isn't valid, return -1. Type is overwritten when checking. */ { unsigned I; const char* A; char* B; /* The length must not be zero and divideable by two */ unsigned Length = SB_GetLen (Type); if (Length < 2 || (Length & 0x01) != 0) { ErrorSkip ("Type value has invalid length"); return -1; } /* The string must consist completely of hex digit chars */ A = SB_GetConstBuf (Type); for (I = 0; I < Length; ++I) { if (!IsXDigit (A[I])) { ErrorSkip ("Type value contains invalid characters"); return -1; } } /* Convert the type to binary */ B = SB_GetBuf (Type); while (A < SB_GetConstBuf (Type) + Length) { /* Since we know, there are only hex digits, there can't be any errors */ *B++ = (HexValue (A[0]) << 4) | HexValue (A[1]); A += 2; } Type->Len = (Length /= 2); /* Allocate the type and return it */ return GetStrBufId (Type); }
void AsmInc (const char* Filename, char CommentStart, int IgnoreUnknown) /* Read an assembler include file */ { char Buf[1024]; char* L; const char* Comment; unsigned Line; unsigned Len; long Val; unsigned DVal; int Sign; unsigned Base; unsigned Digits; StrBuf Ident = STATIC_STRBUF_INITIALIZER; /* Try to open the file for reading */ FILE* F = fopen (Filename, "r"); if (F == 0) { Error ("Cannot open asm include file \"%s\": %s", Filename, strerror (errno)); } /* Read line by line, check for NAME = VALUE lines */ Line = 0; while ((L = fgets (Buf, sizeof (Buf), F)) != 0) { /* One more line read */ ++Line; /* Ignore leading white space */ while (IsBlank (*L)) { ++L; } /* Remove trailing whitespace */ Len = strlen (L); while (Len > 0 && IsSpace (L[Len-1])) { --Len; } L[Len] = '\0'; /* If the line is empty or starts with a comment char, ignore it */ if (*L == '\0' || *L == CommentStart) { continue; } /* Read an identifier */ SB_Clear (&Ident); if (IsAlpha (*L) || *L == '_') { SB_AppendChar (&Ident, *L++); while (IsAlNum (*L) || *L == '_') { SB_AppendChar (&Ident, *L++); } SB_Terminate (&Ident); } else { if (!IgnoreUnknown) { Error ("%s(%u): Syntax error", Filename, Line); } continue; } /* Ignore white space */ L = SkipWhitespace (L); /* Check for := or = */ if (*L == '=') { ++L; } else if (*L == ':' && *++L == '=') { ++L; } else { if (!IgnoreUnknown) { Error ("%s(%u): Missing `='", Filename, Line); } continue; } /* Allow white space once again */ L = SkipWhitespace (L); /* A number follows. Read the sign. */ if (*L == '-') { Sign = -1; ++L; } else { Sign = 1; if (*L == '+') { ++L; } } /* Determine the base of the number. Allow $ and % as prefixes for * hex and binary numbers respectively. */ if (*L == '$') { Base = 16; ++L; } else if (*L == '%') { Base = 2; ++L; } else { Base = 10; } /* Decode the number */ Digits = 0; Val = 0; while (IsXDigit (*L) && (DVal = DigitVal (*L)) < Base) { Val = (Val * Base) + DVal; ++Digits; ++L; } /* Must have at least one digit */ if (Digits == 0) { if (!IgnoreUnknown) { Error ("%s(%u): Error in number format", Filename, Line); } continue; } /* Skip whitespace again */ L = SkipWhitespace (L); /* Check for a comment */ if (*L == CommentStart) { Comment = SkipWhitespace (L+1); if (*Comment == '\0') { Comment = 0; } } else { Comment = 0; } /* Check for a comment character or end of line */ if (*L != CommentStart && *L != '\0') { if (!IgnoreUnknown) { Error ("%s(%u): Trailing garbage", Filename, Line); } continue; } /* Apply the sign */ Val *= Sign; /* Define the symbol and the comment */ AddExtLabel (Val, SB_GetConstBuf (&Ident)); SetComment (Val, Comment); } /* Delete the string buffer contents */ SB_Done (&Ident); /* Close the include file ignoring errors (we were just reading). */ (void) fclose (F); }
/* Fixed so ::/0 (any IPv6 address) is valid Also a bug in DigitParse above. -Gozem 2002-07-19 [email protected] */ static int try_parse_v6_netmask(const char *text, struct irc_ssaddr *addr, int *b) { char c; int d[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; int dp = 0; int nyble = 4; int finsert = -1; int bits = 128; int deficit = 0; short dc[8]; struct sockaddr_in6 *const v6 = (struct sockaddr_in6 *)addr; for (const char *p = text; (c = *p); ++p) { if (IsXDigit(c)) { if (nyble == 0) return HM_HOST; DigitParse(c); d[dp] |= c << (4 * --nyble); } else if (c == ':') { if (p > text && *(p - 1) == ':') { if (finsert >= 0) return HM_HOST; finsert = dp; } else { /* If there were less than 4 hex digits, e.g. :ABC: shift right * so we don't interpret it as ABC0 -A1kmm */ d[dp] = d[dp] >> 4 * nyble; nyble = 4; if (++dp >= 8) return HM_HOST; } } else if (c == '*') { /* * must be last, and * is ambiguous if there is a ::... -A1kmm */ if (finsert >= 0 || *(p + 1) || dp == 0 || *(p - 1) != ':') return HM_HOST; bits = dp * 16; } else if (c == '/') { char *after; d[dp] = d[dp] >> 4 * nyble; ++dp; bits = strtoul(p + 1, &after, 10); if (bits < 0 || *after) return HM_HOST; if (bits > dp * 4 && !(finsert >= 0 && bits <= 128)) return HM_HOST; break; }
void NextRawTok (void) /* Read the next raw token from the input stream */ { Macro* M; /* If we've a forced end of assembly, don't read further */ if (ForcedEnd) { CurTok.Tok = TOK_EOF; return; } Restart: /* Check if we have tokens from another input source */ if (InputFromStack ()) { if (CurTok.Tok == TOK_IDENT && (M = FindDefine (&CurTok.SVal)) != 0) { /* This is a define style macro - expand it */ MacExpandStart (M); goto Restart; } return; } Again: /* Skip whitespace, remember if we had some */ if ((CurTok.WS = IsBlank (C)) != 0) { do { NextChar (); } while (IsBlank (C)); } /* Mark the file position of the next token */ Source->Func->MarkStart (Source); /* Clear the string attribute */ SB_Clear (&CurTok.SVal); /* Generate line info for the current token */ NewAsmLine (); /* Hex number or PC symbol? */ if (C == '$') { NextChar (); /* Hex digit must follow or DollarIsPC must be enabled */ if (!IsXDigit (C)) { if (DollarIsPC) { CurTok.Tok = TOK_PC; return; } else { Error ("Hexadecimal digit expected"); } } /* Read the number */ CurTok.IVal = 0; while (1) { if (UnderlineInNumbers && C == '_') { while (C == '_') { NextChar (); } if (!IsXDigit (C)) { Error ("Number may not end with underline"); } } if (IsXDigit (C)) { if (CurTok.IVal & 0xF0000000) { Error ("Overflow in hexadecimal number"); CurTok.IVal = 0; } CurTok.IVal = (CurTok.IVal << 4) + DigitVal (C); NextChar (); } else { break; } } /* This is an integer constant */ CurTok.Tok = TOK_INTCON; return; } /* Binary number? */ if (C == '%') { NextChar (); /* 0 or 1 must follow */ if (!IsBDigit (C)) { Error ("Binary digit expected"); } /* Read the number */ CurTok.IVal = 0; while (1) { if (UnderlineInNumbers && C == '_') { while (C == '_') { NextChar (); } if (!IsBDigit (C)) { Error ("Number may not end with underline"); } } if (IsBDigit (C)) { if (CurTok.IVal & 0x80000000) { Error ("Overflow in binary number"); CurTok.IVal = 0; } CurTok.IVal = (CurTok.IVal << 1) + DigitVal (C); NextChar (); } else { break; } } /* This is an integer constant */ CurTok.Tok = TOK_INTCON; return; } /* Number? */ if (IsDigit (C)) { char Buf[16]; unsigned Digits; unsigned Base; unsigned I; long Max; unsigned DVal; /* Ignore leading zeros */ while (C == '0') { NextChar (); } /* Read the number into Buf counting the digits */ Digits = 0; while (1) { if (UnderlineInNumbers && C == '_') { while (C == '_') { NextChar (); } if (!IsXDigit (C)) { Error ("Number may not end with underline"); } } if (IsXDigit (C)) { /* Buf is big enough to allow any decimal and hex number to ** overflow, so ignore excess digits here, they will be detected ** when we convert the value. */ if (Digits < sizeof (Buf)) { Buf[Digits++] = C; } NextChar (); } else { break; } } /* Allow zilog/intel style hex numbers with a 'h' suffix */ if (C == 'h' || C == 'H') { NextChar (); Base = 16; Max = 0xFFFFFFFFUL / 16; } else { Base = 10; Max = 0xFFFFFFFFUL / 10; } /* Convert the number using the given base */ CurTok.IVal = 0; for (I = 0; I < Digits; ++I) { if (CurTok.IVal > Max) { Error ("Number out of range"); CurTok.IVal = 0; break; } DVal = DigitVal (Buf[I]); if (DVal >= Base) { Error ("Invalid digits in number"); CurTok.IVal = 0; break; } CurTok.IVal = (CurTok.IVal * Base) + DVal; } /* This is an integer constant */ CurTok.Tok = TOK_INTCON; return; } /* Control command? */ if (C == '.') { /* Remember and skip the dot */ NextChar (); /* Check if it's just a dot */ if (!IsIdStart (C)) { /* Just a dot */ CurTok.Tok = TOK_DOT; } else { /* Read the remainder of the identifier */ SB_AppendChar (&CurTok.SVal, '.'); ReadIdent (); /* Dot keyword, search for it */ CurTok.Tok = FindDotKeyword (); if (CurTok.Tok == TOK_NONE) { /* Not found */ if (!LeadingDotInIdents) { /* Invalid pseudo instruction */ Error ("'%m%p' is not a recognized control command", &CurTok.SVal); goto Again; } /* An identifier with a dot. Check if it's a define style ** macro. */ if ((M = FindDefine (&CurTok.SVal)) != 0) { /* This is a define style macro - expand it */ MacExpandStart (M); goto Restart; } /* Just an identifier with a dot */ CurTok.Tok = TOK_IDENT; } } return; } /* Indirect op for sweet16 cpu. Must check this before checking for local ** symbols, because these may also use the '@' symbol. */ if (CPU == CPU_SWEET16 && C == '@') { NextChar (); CurTok.Tok = TOK_AT; return; } /* Local symbol? */ if (C == LocalStart) { /* Read the identifier. */ ReadIdent (); /* Start character alone is not enough */ if (SB_GetLen (&CurTok.SVal) == 1) { Error ("Invalid cheap local symbol"); goto Again; } /* A local identifier */ CurTok.Tok = TOK_LOCAL_IDENT; return; } /* Identifier or keyword? */ if (IsIdStart (C)) { /* Read the identifier */ ReadIdent (); /* Check for special names. Bail out if we have identified the type of ** the token. Go on if the token is an identifier. */ switch (SB_GetLen (&CurTok.SVal)) { case 1: switch (toupper (SB_AtUnchecked (&CurTok.SVal, 0))) { case 'A': if (C == ':') { NextChar (); CurTok.Tok = TOK_OVERRIDE_ABS; } else { CurTok.Tok = TOK_A; } return; case 'F': if (C == ':') { NextChar (); CurTok.Tok = TOK_OVERRIDE_FAR; return; } break; case 'S': if ((CPU == CPU_4510) || (CPU == CPU_65816)) { CurTok.Tok = TOK_S; return; } break; case 'X': CurTok.Tok = TOK_X; return; case 'Y': CurTok.Tok = TOK_Y; return; case 'Z': if (C == ':') { NextChar (); CurTok.Tok = TOK_OVERRIDE_ZP; return; } else { if (CPU == CPU_4510) { CurTok.Tok = TOK_Z; return; } } break; default: break; } break; case 2: if ((CPU == CPU_4510) && (toupper (SB_AtUnchecked (&CurTok.SVal, 0)) == 'S') && (toupper (SB_AtUnchecked (&CurTok.SVal, 1)) == 'P')) { CurTok.Tok = TOK_S; return; } /* FALL THROUGH */ default: if (CPU == CPU_SWEET16 && (CurTok.IVal = Sweet16Reg (&CurTok.SVal)) >= 0) { /* A sweet16 register number in sweet16 mode */ CurTok.Tok = TOK_REG; return; } } /* Check for define style macro */ if ((M = FindDefine (&CurTok.SVal)) != 0) { /* Macro - expand it */ MacExpandStart (M); goto Restart; } else { /* An identifier */ CurTok.Tok = TOK_IDENT; } return; } /* Ok, let's do the switch */ CharAgain: switch (C) { case '+': NextChar (); CurTok.Tok = TOK_PLUS; return; case '-': NextChar (); CurTok.Tok = TOK_MINUS; return; case '/': NextChar (); if (C != '*') { CurTok.Tok = TOK_DIV; } else if (CComments) { /* Remember the position, then skip the '*' */ Collection LineInfos = STATIC_COLLECTION_INITIALIZER; GetFullLineInfo (&LineInfos); NextChar (); do { while (C != '*') { if (C == EOF) { LIError (&LineInfos, "Unterminated comment"); ReleaseFullLineInfo (&LineInfos); DoneCollection (&LineInfos); goto CharAgain; } NextChar (); } NextChar (); } while (C != '/'); NextChar (); ReleaseFullLineInfo (&LineInfos); DoneCollection (&LineInfos); goto Again; } return; case '*': NextChar (); CurTok.Tok = TOK_MUL; return; case '^': NextChar (); CurTok.Tok = TOK_XOR; return; case '&': NextChar (); if (C == '&') { NextChar (); CurTok.Tok = TOK_BOOLAND; } else { CurTok.Tok = TOK_AND; } return; case '|': NextChar (); if (C == '|') { NextChar (); CurTok.Tok = TOK_BOOLOR; } else { CurTok.Tok = TOK_OR; } return; case ':': NextChar (); switch (C) { case ':': NextChar (); CurTok.Tok = TOK_NAMESPACE; break; case '-': CurTok.IVal = 0; do { --CurTok.IVal; NextChar (); } while (C == '-'); CurTok.Tok = TOK_ULABEL; break; case '+': CurTok.IVal = 0; do { ++CurTok.IVal; NextChar (); } while (C == '+'); CurTok.Tok = TOK_ULABEL; break; case '=': NextChar (); CurTok.Tok = TOK_ASSIGN; break; default: CurTok.Tok = TOK_COLON; break; } return; case ',': NextChar (); CurTok.Tok = TOK_COMMA; return; case ';': NextChar (); while (C != '\n' && C != EOF) { NextChar (); } goto CharAgain; case '#': NextChar (); CurTok.Tok = TOK_HASH; return; case '(': NextChar (); CurTok.Tok = TOK_LPAREN; return; case ')': NextChar (); CurTok.Tok = TOK_RPAREN; return; case '[': NextChar (); CurTok.Tok = TOK_LBRACK; return; case ']': NextChar (); CurTok.Tok = TOK_RBRACK; return; case '{': NextChar (); CurTok.Tok = TOK_LCURLY; return; case '}': NextChar (); CurTok.Tok = TOK_RCURLY; return; case '<': NextChar (); if (C == '=') { NextChar (); CurTok.Tok = TOK_LE; } else if (C == '<') { NextChar (); CurTok.Tok = TOK_SHL; } else if (C == '>') { NextChar (); CurTok.Tok = TOK_NE; } else { CurTok.Tok = TOK_LT; } return; case '=': NextChar (); CurTok.Tok = TOK_EQ; return; case '!': NextChar (); CurTok.Tok = TOK_BOOLNOT; return; case '>': NextChar (); if (C == '=') { NextChar (); CurTok.Tok = TOK_GE; } else if (C == '>') { NextChar (); CurTok.Tok = TOK_SHR; } else { CurTok.Tok = TOK_GT; } return; case '~': NextChar (); CurTok.Tok = TOK_NOT; return; case '\'': /* Hack: If we allow ' as terminating character for strings, read ** the following stuff as a string, and check for a one character ** string later. */ if (LooseStringTerm) { ReadStringConst ('\''); if (SB_GetLen (&CurTok.SVal) == 1) { CurTok.IVal = SB_AtUnchecked (&CurTok.SVal, 0); CurTok.Tok = TOK_CHARCON; } else { CurTok.Tok = TOK_STRCON; } } else { /* Always a character constant */ NextChar (); if (C == EOF || IsControl (C)) { Error ("Illegal character constant"); goto CharAgain; } CurTok.IVal = C; CurTok.Tok = TOK_CHARCON; NextChar (); if (C != '\'') { if (!MissingCharTerm) { Error ("Illegal character constant"); } } else { NextChar (); } } return; case '\"': ReadStringConst ('\"'); CurTok.Tok = TOK_STRCON; return; case '\\': /* Line continuation? */ if (LineCont) { NextChar (); /* Next char should be a LF, if not, will result in an error later */ if (C == '\n') { /* Ignore the '\n' */ NextChar (); goto Again; } else { /* Make it clear what the problem is: */ Error ("EOL expected."); } } break; case '\n': NextChar (); CurTok.Tok = TOK_SEP; return; case EOF: CheckInputStack (); /* In case of the main file, do not close it, but return EOF. */ if (Source && Source->Next) { DoneCharSource (); goto Again; } else { CurTok.Tok = TOK_EOF; } return; } /* If we go here, we could not identify the current character. Skip it ** and try again. */ Error ("Invalid input character: 0x%02X", C & 0xFF); NextChar (); goto Again; }
static void ReadStringConst (int StringTerm) /* Read a string constant into SVal. */ { /* Skip the leading string terminator */ NextChar (); /* Read the string */ while (1) { if (C == StringTerm) { break; } if (C == '\n' || C == EOF) { Error ("Newline in string constant"); break; } if (C == '\\' && StringEscapes) { NextChar (); switch (C) { case EOF: Error ("Unterminated escape sequence in string constant"); break; case '\\': case '\'': case '"': break; case 't': C = '\x09'; break; case 'r': C = '\x0D'; break; case 'n': C = '\x0A'; break; case 'x': NextChar (); if (IsXDigit (C)) { char high_nibble = DigitVal (C) << 4; NextChar (); if (IsXDigit (C)) { C = high_nibble | DigitVal (C); break; } } /* otherwise, fall through */ default: Error ("Unsupported escape sequence in string constant"); break; } } /* Append the char to the string */ SB_AppendChar (&CurTok.SVal, C); /* Skip the character */ NextChar (); } /* Skip the trailing terminator */ NextChar (); /* Terminate the string */ SB_Terminate (&CurTok.SVal); }
static void NumericConst (void) /* Parse a numeric constant */ { unsigned Base; /* Temporary number base */ unsigned Prefix; /* Base according to prefix */ StrBuf S = STATIC_STRBUF_INITIALIZER; int IsFloat; char C; unsigned DigitVal; unsigned long IVal; /* Value */ /* Check for a leading hex or octal prefix and determine the possible ** integer types. */ if (CurC == '0') { /* Gobble 0 and examine next char */ NextChar (); if (toupper (CurC) == 'X') { Base = Prefix = 16; NextChar (); /* gobble "x" */ } else { Base = 10; /* Assume 10 for now - see below */ Prefix = 8; /* Actual prefix says octal */ } } else { Base = Prefix = 10; } /* Because floating point numbers don't have octal prefixes (a number ** with a leading zero is decimal), we first have to read the number ** before converting it, so we can determine if it's a float or an ** integer. */ while (IsXDigit (CurC) && HexVal (CurC) < Base) { SB_AppendChar (&S, CurC); NextChar (); } SB_Terminate (&S); /* The following character tells us if we have an integer or floating ** point constant. Note: Hexadecimal floating point constants aren't ** supported in C89. */ IsFloat = (CurC == '.' || (Base == 10 && toupper (CurC) == 'E') || (Base == 16 && toupper (CurC) == 'P' && IS_Get (&Standard) >= STD_C99)); /* If we don't have a floating point type, an octal prefix results in an ** octal base. */ if (!IsFloat && Prefix == 8) { Base = 8; } /* Since we do now know the correct base, convert the remembered input ** into a number. */ SB_Reset (&S); IVal = 0; while ((C = SB_Get (&S)) != '\0') { DigitVal = HexVal (C); if (DigitVal >= Base) { Error ("Numeric constant contains digits beyond the radix"); } IVal = (IVal * Base) + DigitVal; } /* We don't need the string buffer any longer */ SB_Done (&S); /* Distinguish between integer and floating point constants */ if (!IsFloat) { unsigned Types; int HaveSuffix; /* Check for a suffix and determine the possible types */ HaveSuffix = 1; if (toupper (CurC) == 'U') { /* Unsigned type */ NextChar (); if (toupper (CurC) != 'L') { Types = IT_UINT | IT_ULONG; } else { NextChar (); Types = IT_ULONG; } } else if (toupper (CurC) == 'L') { /* Long type */ NextChar (); if (toupper (CurC) != 'U') { Types = IT_LONG | IT_ULONG; } else { NextChar (); Types = IT_ULONG; } } else { HaveSuffix = 0; if (Prefix == 10) { /* Decimal constants are of any type but uint */ Types = IT_INT | IT_LONG | IT_ULONG; } else { /* Octal or hex constants are of any type */ Types = IT_INT | IT_UINT | IT_LONG | IT_ULONG; } } /* Check the range to determine the type */ if (IVal > 0x7FFF) { /* Out of range for int */ Types &= ~IT_INT; /* If the value is in the range 0x8000..0xFFFF, unsigned int is not ** allowed, and we don't have a type specifying suffix, emit a ** warning, because the constant is of type long. */ if (IVal <= 0xFFFF && (Types & IT_UINT) == 0 && !HaveSuffix) { Warning ("Constant is long"); } } if (IVal > 0xFFFF) { /* Out of range for unsigned int */ Types &= ~IT_UINT; } if (IVal > 0x7FFFFFFF) { /* Out of range for long int */ Types &= ~IT_LONG; } /* Now set the type string to the smallest type in types */ if (Types & IT_INT) { NextTok.Type = type_int; } else if (Types & IT_UINT) { NextTok.Type = type_uint; } else if (Types & IT_LONG) { NextTok.Type = type_long; } else { NextTok.Type = type_ulong; } /* Set the value and the token */ NextTok.IVal = IVal; NextTok.Tok = TOK_ICONST; } else { /* Float constant */ Double FVal = FP_D_FromInt (IVal); /* Convert to double */ /* Check for a fractional part and read it */ if (CurC == '.') { Double Scale; /* Skip the dot */ NextChar (); /* Read fractional digits */ Scale = FP_D_Make (1.0); while (IsXDigit (CurC) && (DigitVal = HexVal (CurC)) < Base) { /* Get the value of this digit */ Double FracVal = FP_D_Div (FP_D_FromInt (DigitVal * Base), Scale); /* Add it to the float value */ FVal = FP_D_Add (FVal, FracVal); /* Scale base */ Scale = FP_D_Mul (Scale, FP_D_FromInt (DigitVal)); /* Skip the digit */ NextChar (); } } /* Check for an exponent and read it */ if ((Base == 16 && toupper (CurC) == 'F') || (Base == 10 && toupper (CurC) == 'E')) { unsigned Digits; unsigned Exp; /* Skip the exponent notifier */ NextChar (); /* Read an optional sign */ if (CurC == '-') { NextChar (); } else if (CurC == '+') { NextChar (); } /* Read exponent digits. Since we support only 32 bit floats ** with a maximum exponent of +-/127, we read the exponent ** part as integer with up to 3 digits and drop the remainder. ** This avoids an overflow of Exp. The exponent is always ** decimal, even for hex float consts. */ Digits = 0; Exp = 0; while (IsDigit (CurC)) { if (++Digits <= 3) { Exp = Exp * 10 + HexVal (CurC); } NextChar (); } /* Check for errors: We must have exponent digits, and not more ** than three. */ if (Digits == 0) { Error ("Floating constant exponent has no digits"); } else if (Digits > 3) { Warning ("Floating constant exponent is too large"); } /* Scale the exponent and adjust the value accordingly */ if (Exp) { FVal = FP_D_Mul (FVal, FP_D_Make (pow (10, Exp))); } } /* Check for a suffix and determine the type of the constant */ if (toupper (CurC) == 'F') { NextChar (); NextTok.Type = type_float; } else { NextTok.Type = type_double; } /* Set the value and the token */ NextTok.FVal = FVal; NextTok.Tok = TOK_FCONST; } }
static int ParseChar (void) /* Parse a character. Converts escape chars into character codes. */ { int C; int HadError; int Count; /* Check for escape chars */ if (CurC == '\\') { NextChar (); switch (CurC) { case '?': C = '\?'; break; case 'a': C = '\a'; break; case 'b': C = '\b'; break; case 'f': C = '\f'; break; case 'r': C = '\r'; break; case 'n': C = '\n'; break; case 't': C = '\t'; break; case 'v': C = '\v'; break; case '\"': C = '\"'; break; case '\'': C = '\''; break; case '\\': C = '\\'; break; case 'x': case 'X': /* Hex character constant */ if (!IsXDigit (NextC)) { Error ("\\x used with no following hex digits"); C = ' '; } else { HadError = 0; C = 0; while (IsXDigit (NextC)) { if ((C << 4) >= 256) { if (!HadError) { Error ("Hex character constant out of range"); HadError = 1; } } else { C = (C << 4) | HexVal (NextC); } NextChar (); } } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': /* Octal constant */ Count = 1; C = HexVal (CurC); while (IsODigit (NextC) && Count++ < 3) { C = (C << 3) | HexVal (NextC); NextChar (); } if (C >= 256) Error ("Octal character constant out of range"); break; default: C = CurC; Error ("Illegal escaped character: 0x%02X", CurC); break; } } else { C = CurC; } /* Skip the character read */ NextChar (); /* Do correct sign extension */ return SignExtendChar (C); }
void InfoNextTok (void) /* Read the next token from the input stream */ { unsigned I; char DecodeBuf [2]; Again: /* Skip whitespace */ SkipBlanks (0); /* Remember the current position */ InfoErrorLine = InputLine; InfoErrorCol = InputCol; /* Identifier? */ if (C == '_' || IsAlpha (C)) { /* Read the identifier */ I = 0; while (C == '_' || IsAlNum (C)) { if (I < CFG_MAX_IDENT_LEN) { InfoSVal [I++] = C; } NextChar (); } InfoSVal [I] = '\0'; InfoTok = INFOTOK_IDENT; return; } /* Hex number? */ if (C == '$') { NextChar (); if (!IsXDigit (C)) { InfoError ("Hex digit expected"); } InfoIVal = 0; while (IsXDigit (C)) { InfoIVal = InfoIVal * 16 + DigitVal (C); NextChar (); } InfoTok = INFOTOK_INTCON; return; } /* Decimal number? */ if (IsDigit (C)) { InfoIVal = GetDecimalToken (); InfoTok = INFOTOK_INTCON; return; } /* Other characters */ switch (C) { case '{': NextChar (); InfoTok = INFOTOK_LCURLY; break; case '}': NextChar (); InfoTok = INFOTOK_RCURLY; break; case ';': NextChar (); InfoTok = INFOTOK_SEMI; break; case '.': NextChar (); InfoTok = INFOTOK_DOT; break; case ',': NextChar (); InfoTok = INFOTOK_COMMA; break; case '=': NextChar (); InfoTok = INFOTOK_EQ; break; case ':': NextChar (); InfoTok = INFOTOK_COLON; break; case '\"': NextChar (); I = 0; InfoSVal[0] = '\0'; while (C != EOF && C != '\"') { if (GetEncodedChar (InfoSVal, &I, sizeof InfoSVal) < 0) { if (C == EOF) { InfoError ("Unterminated string"); } else { InfoError ("Invalid escape char: %c", C); } } } if (C != '\"') { InfoError ("Unterminated string"); } NextChar (); InfoTok = INFOTOK_STRCON; break; case '\'': NextChar (); if (C == EOF || IsControl (C) || C == '\'') { InfoError ("Invalid character constant"); } if (GetEncodedChar (DecodeBuf, &I, sizeof DecodeBuf) < 0 || I != 1) { InfoError ("Invalid character constant"); } InfoIVal = DecodeBuf [0]; if (C != '\'') { InfoError ("Unterminated character constant"); } NextChar (); InfoTok = INFOTOK_CHARCON; break; case '#': /* # lineno "sourcefile" or # comment */ if (SyncLines && InputCol == 1) { LineMarkerOrComment (); } else { do { NextChar (); } while (C != EOF && C != '\n'); NextChar (); } if (C != EOF) { goto Again; } InfoTok = INFOTOK_EOF; break; case '/': /* C++ style comment */ NextChar (); if (C != '/') { InfoError ("Invalid token '/'"); } do { NextChar (); } while (C != '\n' && C != EOF); if (C != EOF) { goto Again; } InfoTok = INFOTOK_EOF; break; case EOF: InfoTok = INFOTOK_EOF; break; default: InfoError ("Invalid character '%c'", C); } }
int SB_GetNumber (StrBuf* B, long* Val) /* Get a number from the string buffer. Accepted formats are decimal, octal, ** hex and character constants. Numeric constants may be preceeded by a ** minus or plus sign. The function returns 1 if a number was found and ** zero otherwise. Errors are only output for invalid numbers. */ { int Sign; char C; unsigned Base; unsigned DigitVal; /* Initialize Val */ *Val = 0; /* Handle character constants */ if (SB_Peek (B) == '\'') { /* Character constant */ SB_Skip (B); *Val = SignExtendChar (TgtTranslateChar (ParseChar (B))); if (SB_Peek (B) != '\'') { Error ("`\'' expected"); return 0; } else { /* Skip the quote */ SB_Skip (B); return 1; } } /* Check for a sign. A sign must be followed by a digit, otherwise it's ** not a number */ Sign = 1; switch (SB_Peek (B)) { case '-': Sign = -1; /* FALLTHROUGH */ case '+': if (!IsDigit (SB_LookAt (B, SB_GetIndex (B) + 1))) { return 0; } SB_Skip (B); break; } /* We must have a digit now, otherwise its not a number */ C = SB_Peek (B); if (!IsDigit (C)) { return 0; } /* Determine the base */ if (C == '0') { /* Hex or octal */ SB_Skip (B); if (tolower (SB_Peek (B)) == 'x') { SB_Skip (B); Base = 16; if (!IsXDigit (SB_Peek (B))) { Error ("Invalid hexadecimal number"); return 0; } } else { Base = 8; } } else { Base = 10; } /* Read the number */ while (IsXDigit (C = SB_Peek (B)) && (DigitVal = HexVal (C)) < Base) { *Val = (*Val * Base) + DigitVal; SB_Skip (B); } /* Allow optional 'U' and 'L' modifiers */ C = SB_Peek (B); if (C == 'u' || C == 'U') { SB_Skip (B); C = SB_Peek (B); if (C == 'l' || C == 'L') { SB_Skip (B); } } else if (C == 'l' || C == 'L') { SB_Skip (B); C = SB_Peek (B); if (C == 'u' || C == 'U') { SB_Skip (B); } } /* Success, value read is in Val */ *Val *= Sign; return 1; }