?? c-lex.c
字號:
spec_long = 1; } else { if (isalnum (c)) { error ("garbage at end of number"); while (isalnum (c)) { if (p >= token_buffer + maxtoken - 3) p = extend_token_buffer (p); *p++ = c; c = getc (finput); } } break; } if (p >= token_buffer + maxtoken - 3) p = extend_token_buffer (p); *p++ = c; c = getc (finput); } ungetc (c, finput); /* If the constant is not long long and it won't fit in an unsigned long, or if the constant is long long and won't fit in an unsigned long long, then warn that the constant is out of range. */ /* ??? This assumes that long long and long integer types are a multiple of 8 bits. This better than the original code though which assumed that long was exactly 32 bits and long long was exactly 64 bits. */ if (spec_long_long) bytes = TYPE_PRECISION (long_long_integer_type_node) / 8; else bytes = TYPE_PRECISION (long_integer_type_node) / 8; warn = overflow; for (i = bytes; i < TOTAL_PARTS; i++) if (parts[i]) warn = 1; if (warn) pedwarn ("integer constant out of range"); /* This is simplified by the fact that our constant is always positive. */ high = low = 0; for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; i++) { high |= ((HOST_WIDE_INT) parts[i + (HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR)] << (i * HOST_BITS_PER_CHAR)); low |= (HOST_WIDE_INT) parts[i] << (i * HOST_BITS_PER_CHAR); } yylval.ttype = build_int_2 (low, high); TREE_TYPE (yylval.ttype) = long_long_unsigned_type_node; /* If warn_traditional, calculate both the ANSI type and the traditional type, then see if they disagree. Otherwise, calculate only the type for the dialect in use. */ if (warn_traditional || flag_traditional) { /* Calculate the traditional type. */ /* Traditionally, any constant is signed; but if unsigned is specified explicitly, obey that. Use the smallest size with the right number of bits, except for one special case with decimal constants. */ if (! spec_long && base != 10 && int_fits_type_p (yylval.ttype, unsigned_type_node)) traditional_type = (spec_unsigned ? unsigned_type_node : integer_type_node); /* A decimal constant must be long if it does not fit in type int. I think this is independent of whether the constant is signed. */ else if (! spec_long && base == 10 && int_fits_type_p (yylval.ttype, integer_type_node)) traditional_type = (spec_unsigned ? unsigned_type_node : integer_type_node); else if (! spec_long_long) traditional_type = (spec_unsigned ? long_unsigned_type_node : long_integer_type_node); else traditional_type = (spec_unsigned ? long_long_unsigned_type_node : long_long_integer_type_node); } if (warn_traditional || ! flag_traditional) { /* Calculate the ANSI type. */ if (! spec_long && ! spec_unsigned && int_fits_type_p (yylval.ttype, integer_type_node)) ansi_type = integer_type_node; else if (! spec_long && (base != 10 || spec_unsigned) && int_fits_type_p (yylval.ttype, unsigned_type_node)) ansi_type = unsigned_type_node; else if (! spec_unsigned && !spec_long_long && int_fits_type_p (yylval.ttype, long_integer_type_node)) ansi_type = long_integer_type_node; else if (! spec_long_long) ansi_type = long_unsigned_type_node; else if (! spec_unsigned /* Verify value does not overflow into sign bit. */ && TREE_INT_CST_HIGH (yylval.ttype) >= 0 && int_fits_type_p (yylval.ttype, long_long_integer_type_node)) ansi_type = long_long_integer_type_node; else ansi_type = long_long_unsigned_type_node; } type = flag_traditional ? traditional_type : ansi_type; if (warn_traditional && traditional_type != ansi_type) { if (TYPE_PRECISION (traditional_type) != TYPE_PRECISION (ansi_type)) warning ("width of integer constant changes with -traditional"); else if (TREE_UNSIGNED (traditional_type) != TREE_UNSIGNED (ansi_type)) warning ("integer constant is unsigned in ANSI C, signed with -traditional"); else warning ("width of integer constant may change on other systems with -traditional"); } if (!flag_traditional && !int_fits_type_p (yylval.ttype, type) && !warn) pedwarn ("integer constant out of range"); if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type)) warning ("integer constant is so large that it is unsigned"); if (flag_traditional && !int_fits_type_p (yylval.ttype, type)) /* The traditional constant 0x80000000 is signed but doesn't fit in the range of int. This will change it to -0x80000000, which does fit. */ { TREE_TYPE (yylval.ttype) = unsigned_type (type); yylval.ttype = convert (type, yylval.ttype); } else TREE_TYPE (yylval.ttype) = type; *p = 0; } value = CONSTANT; break; } case '\'': char_constant: { register int result = 0; register int num_chars = 0; unsigned width = TYPE_PRECISION (char_type_node); int max_chars; if (wide_flag) { width = WCHAR_TYPE_SIZE;#ifdef MULTIBYTE_CHARS max_chars = MB_CUR_MAX;#else max_chars = 1;#endif } else max_chars = TYPE_PRECISION (integer_type_node) / width; while (1) { tryagain: c = getc (finput); if (c == '\'' || c == EOF) break; if (c == '\\') { int ignore = 0; c = readescape (&ignore); if (ignore) goto tryagain; if (width < HOST_BITS_PER_INT && (unsigned) c >= (1 << width)) pedwarn ("escape sequence out of range for character"); } else if (c == '\n') { if (pedantic) pedwarn ("ANSI C forbids newline in character constant"); lineno++; } num_chars++; if (num_chars > maxtoken - 4) extend_token_buffer (token_buffer); token_buffer[num_chars] = c; /* Merge character into result; ignore excess chars. */ if (num_chars < max_chars + 1) { if (width < HOST_BITS_PER_INT) result = (result << width) | (c & ((1 << width) - 1)); else result = c; } } token_buffer[num_chars + 1] = '\''; token_buffer[num_chars + 2] = 0; if (c != '\'') error ("malformatted character constant"); else if (num_chars == 0) error ("empty character constant"); else if (num_chars > max_chars) { num_chars = max_chars; error ("character constant too long"); } else if (num_chars != 1 && ! flag_traditional) warning ("multi-character character constant"); /* If char type is signed, sign-extend the constant. */ if (! wide_flag) { int num_bits = num_chars * width; if (TREE_UNSIGNED (char_type_node) || ((result >> (num_bits - 1)) & 1) == 0) yylval.ttype = build_int_2 (result & ((unsigned HOST_WIDE_INT) ~0 >> (HOST_BITS_PER_WIDE_INT - num_bits)), 0); else yylval.ttype = build_int_2 (result | ~((unsigned HOST_WIDE_INT) ~0 >> (HOST_BITS_PER_WIDE_INT - num_bits)), -1); } else {#ifdef MULTIBYTE_CHARS /* Set the initial shift state and convert the next sequence. */ result = 0; /* In all locales L'\0' is zero and mbtowc will return zero, so don't use it. */ if (num_chars > 1 || (num_chars == 1 && token_buffer[1] != '\0')) { wchar_t wc; (void) mbtowc (NULL_PTR, NULL_PTR, 0); if (mbtowc (& wc, token_buffer + 1, num_chars) == num_chars) result = wc; else warning ("Ignoring invalid multibyte character"); }#endif yylval.ttype = build_int_2 (result, 0); } TREE_TYPE (yylval.ttype) = integer_type_node; value = CONSTANT; break; } case '"': string_constant: { c = getc (finput); p = token_buffer + 1; while (c != '"' && c >= 0) { /* ignore_escape_flag is set for reading the filename in #line. */ if (!ignore_escape_flag && c == '\\') { int ignore = 0; c = readescape (&ignore); if (ignore) goto skipnewline; if (!wide_flag && TYPE_PRECISION (char_type_node) < HOST_BITS_PER_INT && c >= (1 << TYPE_PRECISION (char_type_node))) pedwarn ("escape sequence out of range for character"); } else if (c == '\n') { if (pedantic) pedwarn ("ANSI C forbids newline in string constant"); lineno++; } if (p == token_buffer + maxtoken) p = extend_token_buffer (p); *p++ = c; skipnewline: c = getc (finput); } *p = 0; /* We have read the entire constant. Construct a STRING_CST for the result. */ if (wide_flag) { /* If this is a L"..." wide-string, convert the multibyte string to a wide character string. */ char *widep = (char *) alloca ((p - token_buffer) * WCHAR_BYTES); int len;#ifdef MULTIBYTE_CHARS len = mbstowcs ((wchar_t *) widep, token_buffer + 1, p - token_buffer); if ((unsigned) len >= (p - token_buffer)) { warning ("Ignoring invalid multibyte string"); len = 0; } bzero (widep + (len * WCHAR_BYTES), WCHAR_BYTES);#else { union { long l; char c[sizeof (long)]; } u; int big_endian; char *wp, *cp; /* Determine whether host is little or big endian. */ u.l = 1; big_endian = u.c[sizeof (long) - 1]; wp = widep + (big_endian ? WCHAR_BYTES - 1 : 0); bzero (widep, (p - token_buffer) * WCHAR_BYTES); for (cp = token_buffer + 1; cp < p; cp++) *wp = *cp, wp += WCHAR_BYTES; len = p - token_buffer - 1; }#endif yylval.ttype = build_string ((len + 1) * WCHAR_BYTES, widep); TREE_TYPE (yylval.ttype) = wchar_array_type_node; } else { yylval.ttype = build_string (p - token_buffer, token_buffer + 1); TREE_TYPE (yylval.ttype) = char_array_type_node; } *p++ = '"'; *p = 0; value = STRING; break; } case '+': case '-': case '&': case '|': case '<': case '>': case '*': case '/': case '%': case '^': case '!': case '=': { register int c1; combine: switch (c) { case '+': yylval.code = PLUS_EXPR; break; case '-': yylval.code = MINUS_EXPR; break; case '&': yylval.code = BIT_AND_EXPR; break; case '|': yylval.code = BIT_IOR_EXPR; break; case '*': yylval.code = MULT_EXPR; break; case '/': yylval.code = TRUNC_DIV_EXPR; break; case '%': yylval.code = TRUNC_MOD_EXPR; break; case '^': yylval.code = BIT_XOR_EXPR; break; case LSHIFT: yylval.code = LSHIFT_EXPR; break; case RSHIFT: yylval.code = RSHIFT_EXPR; break; case '<': yylval.code = LT_EXPR; break; case '>': yylval.code = GT_EXPR; break; } token_buffer[1] = c1 = getc (finput); token_buffer[2] = 0; if (c1 == '=') { switch (c) { case '<': value = ARITHCOMPARE; yylval.code = LE_EXPR; goto done; case '>': value = ARITHCOMPARE; yylval.code = GE_EXPR; goto done; case '!': value = EQCOMPARE; yylval.code = NE_EXPR; goto done; case '=': value = EQCOMPARE; yylval.code = EQ_EXPR; goto done; } value = ASSIGN; goto done; } else if (c == c1) switch (c) { case '+': value = PLUSPLUS; goto done; case '-': value = MINUSMINUS; goto done; case '&': value = ANDAND; goto done; case '|': value = OROR; goto done; case '<': c = LSHIFT; goto combine; case '>': c = RSHIFT; goto combine; } else if ((c == '-') && (c1 == '>')) { value = POINTSAT; goto done; } ungetc (c1, finput); token_buffer[1] = 0; if ((c == '<') || (c == '>')) value = ARITHCOMPARE; else value = c; goto done; } case 0: /* Don't make yyparse think this is eof. */ value = 1; break; default: value = c; }done:/* yylloc.last_line = lineno; */ return value;}/* Sets the value of the 'yydebug' variable to VALUE. This is a function so we don't have to have YYDEBUG defined in order to build the compiler. */voidset_yydebug (value) int value;{#if YYDEBUG != 0 yydebug = value;#else warning ("YYDEBUG not defined.");#endif}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -