?? c-lex.c
字號:
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 ("decimal constant is so large that it is unsigned"); if (spec_imag) { if (TYPE_PRECISION (type) <= TYPE_PRECISION (integer_type_node)) yylval.ttype = build_complex (integer_zero_node, convert (integer_type_node, yylval.ttype)); else error ("complex integer constant is too wide for `complex int'"); } else 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); TREE_OVERFLOW (yylval.ttype) = TREE_CONSTANT_OVERFLOW (yylval.ttype) = 0; } 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");#ifdef MAP_CHARACTER if (isprint (c)) c = MAP_CHARACTER (c);#endif } else if (c == '\n') { if (pedantic) pedwarn ("ANSI C forbids newline in character constant"); lineno++; }#ifdef MAP_CHARACTER else c = MAP_CHARACTER (c);#endif 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 (num_bits == 0) /* We already got an error; avoid invalid shift. */ yylval.ttype = build_int_2 (0, 0); else 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); TREE_TYPE (yylval.ttype) = integer_type_node; } 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) = wchar_type_node; } value = CONSTANT; break; } case '"': string_constant: { c = getc (finput); p = token_buffer + 1; while (c != '"' && c >= 0) { if (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; if (c < 0) error ("Unterminated string constant"); /* 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 (len < 0 || 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; value = STRING; } else if (objc_flag) { extern tree build_objc_string(); /* Return an Objective-C @"..." constant string object. */ yylval.ttype = build_objc_string (p - token_buffer, token_buffer + 1); TREE_TYPE (yylval.ttype) = char_array_type_node; value = OBJC_STRING; } else { yylval.ttype = build_string (p - token_buffer, token_buffer + 1); TREE_TYPE (yylval.ttype) = char_array_type_node; value = STRING; } *p++ = '"'; *p = 0; break; } case '+': 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 switch (c) { case '-': if (c1 == '>') { value = POINTSAT; goto done; } break; case ':': if (c1 == '>') { value = ']'; goto done; } break; case '<': if (c1 == '%') { value = '{'; goto done; } if (c1 == ':') { value = '['; goto done; } break; case '%': if (c1 == '>') { value = '}'; goto done; } break; } 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 + -