?? c-lex.c
字號:
case '_': letter: p = token_buffer; while (isalnum (c) || c == '_' || c == '$' || c == '@') { /* Make sure this char really belongs in an identifier. */ if (c == '@' && ! doing_objc_thang) break; if (c == '$' && ! dollars_in_ident) break; if (p >= token_buffer + maxtoken) p = extend_token_buffer (p); *p++ = c; c = getc (finput); } *p = 0; nextchar = c; value = IDENTIFIER; yylval.itype = 0; /* Try to recognize a keyword. Uses minimum-perfect hash function */ { register struct resword *ptr; if (ptr = is_reserved_word (token_buffer, p - token_buffer)) { if (ptr->rid) yylval.ttype = ridpointers[(int) ptr->rid]; value = (int) ptr->token; /* Only return OBJECTNAME if it is a typedef. */ if (doing_objc_thang && value == OBJECTNAME) { lastiddecl = lookup_name(yylval.ttype); if (lastiddecl == NULL_TREE || TREE_CODE (lastiddecl) != TYPE_DECL) value = IDENTIFIER; } /* Even if we decided to recognize asm, still perhaps warn. */ if (pedantic && (value == ASM_KEYWORD || value == TYPEOF || ptr->rid == RID_INLINE) && token_buffer[0] != '_') pedwarn ("ANSI does not permit the keyword `%s'", token_buffer); } } /* If we did not find a keyword, look for an identifier (or a typename). */ if (value == IDENTIFIER) { if (token_buffer[0] == '@') error("invalid identifier `%s'", token_buffer); yylval.ttype = get_identifier (token_buffer); lastiddecl = lookup_name (yylval.ttype); if (lastiddecl != 0 && TREE_CODE (lastiddecl) == TYPE_DECL) value = TYPENAME; /* A user-invisible read-only initialized variable should be replaced by its value. We handle only strings since that's the only case used in C. */ else if (lastiddecl != 0 && TREE_CODE (lastiddecl) == VAR_DECL && DECL_IGNORED_P (lastiddecl) && TREE_READONLY (lastiddecl) && DECL_INITIAL (lastiddecl) != 0 && TREE_CODE (DECL_INITIAL (lastiddecl)) == STRING_CST) { tree stringval = DECL_INITIAL (lastiddecl); /* Copy the string value so that we won't clobber anything if we put something in the TREE_CHAIN of this one. */ yylval.ttype = build_string (TREE_STRING_LENGTH (stringval), TREE_STRING_POINTER (stringval)); value = STRING; } else if (doing_objc_thang) { tree objc_interface_decl = is_class_name (yylval.ttype); if (objc_interface_decl) { value = CLASSNAME; yylval.ttype = objc_interface_decl; } } } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': { int base = 10; int count = 0; int largest_digit = 0; int numdigits = 0; /* for multi-precision arithmetic, we actually store only HOST_BITS_PER_CHAR bits in each part. The number of parts is chosen so as to be sufficient to hold the enough bits to fit into the two HOST_WIDE_INTs that contain the integer value (this is always at least as many bits as are in a target `long long' value, but may be wider). */#define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2 + 2) int parts[TOTAL_PARTS]; int overflow = 0; enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag = NOT_FLOAT; for (count = 0; count < TOTAL_PARTS; count++) parts[count] = 0; p = token_buffer; *p++ = c; if (c == '0') { *p++ = (c = getc (finput)); if ((c == 'x') || (c == 'X')) { base = 16; *p++ = (c = getc (finput)); } /* Leading 0 forces octal unless the 0 is the only digit. */ else if (c >= '0' && c <= '9') { base = 8; numdigits++; } else numdigits++; } /* Read all the digits-and-decimal-points. */ while (c == '.' || (isalnum (c) && c != 'l' && c != 'L' && c != 'u' && c != 'U' && c != 'i' && c != 'I' && c != 'j' && c != 'J' && (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F'))))) { if (c == '.') { if (base == 16) error ("floating constant may not be in radix 16"); if (floatflag == TOO_MANY_POINTS) /* We have already emitted an error. Don't need another. */ ; else if (floatflag == AFTER_POINT) { error ("malformed floating constant"); floatflag = TOO_MANY_POINTS; /* Avoid another error from atof by forcing all characters from here on to be ignored. */ p[-1] = '\0'; } else floatflag = AFTER_POINT; base = 10; *p++ = c = getc (finput); /* Accept '.' as the start of a floating-point number only when it is followed by a digit. Otherwise, unread the following non-digit and use the '.' as a structural token. */ if (p == token_buffer + 2 && !isdigit (c)) { if (c == '.') { c = getc (finput); if (c == '.') { *p++ = c; *p = 0; return ELLIPSIS; } error ("parse error at `..'"); } ungetc (c, finput); token_buffer[1] = 0; value = '.'; goto done; } } else { /* It is not a decimal point. It should be a digit (perhaps a hex digit). */ if (isdigit (c)) { c = c - '0'; } else if (base <= 10) { if (c == 'e' || c == 'E') { base = 10; floatflag = AFTER_POINT; break; /* start of exponent */ } error ("nondigits in number and not hexadecimal"); c = 0; } else if (c >= 'a') { c = c - 'a' + 10; } else { c = c - 'A' + 10; } if (c >= largest_digit) largest_digit = c; numdigits++; for (count = 0; count < TOTAL_PARTS; count++) { parts[count] *= base; if (count) { parts[count] += (parts[count-1] >> HOST_BITS_PER_CHAR); parts[count-1] &= (1 << HOST_BITS_PER_CHAR) - 1; } else parts[0] += c; } /* If the extra highest-order part ever gets anything in it, the number is certainly too big. */ if (parts[TOTAL_PARTS - 1] != 0) overflow = 1; if (p >= token_buffer + maxtoken - 3) p = extend_token_buffer (p); *p++ = (c = getc (finput)); } } if (numdigits == 0) error ("numeric constant with no digits"); if (largest_digit >= base) error ("numeric constant contains digits beyond the radix"); /* Remove terminating char from the token buffer and delimit the string */ *--p = 0; if (floatflag != NOT_FLOAT) { tree type = double_type_node; int garbage_chars = 0, exceeds_double = 0; int imag = 0; REAL_VALUE_TYPE value; jmp_buf handler; /* Read explicit exponent if any, and put it in tokenbuf. */ if ((c == 'e') || (c == 'E')) { if (p >= token_buffer + maxtoken - 3) p = extend_token_buffer (p); *p++ = c; c = getc (finput); if ((c == '+') || (c == '-')) { *p++ = c; c = getc (finput); } if (! isdigit (c)) error ("floating constant exponent has no digits"); while (isdigit (c)) { if (p >= token_buffer + maxtoken - 3) p = extend_token_buffer (p); *p++ = c; c = getc (finput); } } *p = 0; errno = 0; /* Convert string to a double, checking for overflow. */ if (setjmp (handler)) { error ("floating constant out of range"); value = dconst0; } else { int fflag = 0, lflag = 0; /* Copy token_buffer now, while it has just the number and not the suffixes; once we add `f' or `i', REAL_VALUE_ATOF may not work any more. */ char *copy = (char *) alloca (p - token_buffer + 1); bcopy (token_buffer, copy, p - token_buffer + 1); set_float_handler (handler); while (1) { int lose = 0; /* Read the suffixes to choose a data type. */ switch (c) { case 'f': case 'F': if (fflag) error ("more than one `f' in numeric constant"); fflag = 1; break; case 'l': case 'L': if (lflag) error ("more than one `l' in numeric constant"); lflag = 1; break; case 'i': case 'I': if (imag) error ("more than one `i' or `j' in numeric constant"); else if (pedantic) pedwarn ("ANSI C forbids imaginary numeric constants"); imag = 1; break; default: lose = 1; } if (lose) break; if (p >= token_buffer + maxtoken - 3) p = extend_token_buffer (p); *p++ = c; *p = 0; c = getc (finput); } /* The second argument, machine_mode, of REAL_VALUE_ATOF tells the desired precision of the binary result of decimal-to-binary conversion. */ if (fflag) { if (lflag) error ("both `f' and `l' in floating constant"); type = float_type_node; value = REAL_VALUE_ATOF (copy, TYPE_MODE (type)); /* A diagnostic is required here by some ANSI C testsuites. This is not pedwarn, become some people don't want an error for this. */ if (REAL_VALUE_ISINF (value) && pedantic) warning ("floating point number exceeds range of `float'"); } else if (lflag) { type = long_double_type_node; value = REAL_VALUE_ATOF (copy, TYPE_MODE (type)); if (REAL_VALUE_ISINF (value) && pedantic) warning ("floating point number exceeds range of `long double'"); } else { value = REAL_VALUE_ATOF (copy, TYPE_MODE (type)); if (REAL_VALUE_ISINF (value) && pedantic) warning ("floating point number exceeds range of `double'"); } set_float_handler (NULL_PTR); }#ifdef ERANGE if (errno == ERANGE && !flag_traditional && pedantic) { /* ERANGE is also reported for underflow, so test the value to distinguish overflow from that. */ if (REAL_VALUES_LESS (dconst1, value) || REAL_VALUES_LESS (value, dconstm1)) { warning ("floating point number exceeds range of `double'"); exceeds_double = 1; } }#endif garbage_chars = 0; while (isalnum (c) || c == '.' || c == '_' || (!flag_traditional && (c == '+' || c == '-') && (p[-1] == 'e' || p[-1] == 'E'))) { if (p >= token_buffer + maxtoken - 3) p = extend_token_buffer (p); *p++ = c; c = getc (finput); garbage_chars++; } if (garbage_chars > 0) error ("garbage at end of number"); /* If the result is not a number, assume it must have been due to some error message above, so silently convert it to a zero. */ if (REAL_VALUE_ISNAN (value)) value = dconst0; /* Create a node with determined type and value. */ if (imag) yylval.ttype = build_complex (convert (type, integer_zero_node), build_real (type, value)); else yylval.ttype = build_real (type, value); ungetc (c, finput); *p = 0; } else { tree traditional_type, ansi_type, type; HOST_WIDE_INT high, low; int spec_unsigned = 0; int spec_long = 0; int spec_long_long = 0; int spec_imag = 0; int bytes, warn, i; while (1) { if (c == 'u' || c == 'U') { if (spec_unsigned) error ("two `u's in integer constant"); spec_unsigned = 1; } else if (c == 'l' || c == 'L') { if (spec_long) { if (spec_long_long) error ("three `l's in integer constant"); else if (pedantic) pedwarn ("ANSI C forbids long long integer constants"); spec_long_long = 1; } spec_long = 1; } else if (c == 'i' || c == 'j' || c == 'I' || c == 'J') { if (spec_imag) error ("more than one `i' or `j' in numeric constant"); else if (pedantic) pedwarn ("ANSI C forbids imaginary numeric constants"); spec_imag = 1; } else { if (isalnum (c) || c == '.' || c == '_' || (!flag_traditional && (c == '+' || c == '-') && (p[-1] == 'e' || p[-1] == 'E'))) { error ("garbage at end of number"); while (isalnum (c) || c == '.' || c == '_' || (!flag_traditional && (c == '+' || c == '-') && (p[-1] == 'e' || p[-1] == 'E'))) { 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)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -