diff options
Diffstat (limited to 'src/lread.c')
| -rw-r--r-- | src/lread.c | 149 |
1 files changed, 69 insertions, 80 deletions
diff --git a/src/lread.c b/src/lread.c index d32f0b6a7e2..776d4ced7f2 100644 --- a/src/lread.c +++ b/src/lread.c | |||
| @@ -3006,85 +3006,32 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list) | |||
| 3006 | if (!quoted && !uninterned_symbol) | 3006 | if (!quoted && !uninterned_symbol) |
| 3007 | { | 3007 | { |
| 3008 | register char *p1; | 3008 | register char *p1; |
| 3009 | Lisp_Object result; | ||
| 3009 | p1 = read_buffer; | 3010 | p1 = read_buffer; |
| 3010 | if (*p1 == '+' || *p1 == '-') p1++; | 3011 | if (*p1 == '+' || *p1 == '-') p1++; |
| 3011 | /* Is it an integer? */ | 3012 | /* Is it an integer? */ |
| 3012 | if (p1 != p) | 3013 | if ('0' <= *p1 && *p1 <= '9') |
| 3013 | { | 3014 | { |
| 3014 | while (p1 != p && (c = *p1) >= '0' && c <= '9') p1++; | 3015 | do |
| 3016 | p1++; | ||
| 3017 | while ('0' <= *p1 && *p1 <= '9'); | ||
| 3018 | |||
| 3015 | /* Integers can have trailing decimal points. */ | 3019 | /* Integers can have trailing decimal points. */ |
| 3016 | if (p1 > read_buffer && p1 < p && *p1 == '.') p1++; | 3020 | p1 += (*p1 == '.'); |
| 3017 | if (p1 == p) | 3021 | if (p1 == p) |
| 3018 | /* It is an integer. */ | ||
| 3019 | { | 3022 | { |
| 3020 | if (p1[-1] == '.') | 3023 | /* It is an integer. */ |
| 3021 | p1[-1] = '\0'; | 3024 | EMACS_INT n = strtol (read_buffer, NULL, 10); |
| 3022 | { | 3025 | if (FIXNUM_OVERFLOW_P (n)) |
| 3023 | /* EMACS_INT n = atol (read_buffer); */ | 3026 | xsignal (Qoverflow_error, |
| 3024 | char *endptr = NULL; | 3027 | list1 (build_string (read_buffer))); |
| 3025 | EMACS_INT n = (errno = 0, | 3028 | return make_number (n); |
| 3026 | strtol (read_buffer, &endptr, 10)); | ||
| 3027 | if (errno == ERANGE && endptr) | ||
| 3028 | { | ||
| 3029 | Lisp_Object args | ||
| 3030 | = Fcons (make_string (read_buffer, | ||
| 3031 | endptr - read_buffer), | ||
| 3032 | Qnil); | ||
| 3033 | xsignal (Qoverflow_error, args); | ||
| 3034 | } | ||
| 3035 | return make_fixnum_or_float (n); | ||
| 3036 | } | ||
| 3037 | } | 3029 | } |
| 3038 | } | 3030 | } |
| 3039 | if (isfloat_string (read_buffer, 0)) | ||
| 3040 | { | ||
| 3041 | /* Compute NaN and infinities using 0.0 in a variable, | ||
| 3042 | to cope with compilers that think they are smarter | ||
| 3043 | than we are. */ | ||
| 3044 | double zero = 0.0; | ||
| 3045 | |||
| 3046 | double value; | ||
| 3047 | |||
| 3048 | /* Negate the value ourselves. This treats 0, NaNs, | ||
| 3049 | and infinity properly on IEEE floating point hosts, | ||
| 3050 | and works around a common bug where atof ("-0.0") | ||
| 3051 | drops the sign. */ | ||
| 3052 | int negative = read_buffer[0] == '-'; | ||
| 3053 | |||
| 3054 | /* The only way p[-1] can be 'F' or 'N', after isfloat_string | ||
| 3055 | returns 1, is if the input ends in e+INF or e+NaN. */ | ||
| 3056 | switch (p[-1]) | ||
| 3057 | { | ||
| 3058 | case 'F': | ||
| 3059 | value = 1.0 / zero; | ||
| 3060 | break; | ||
| 3061 | case 'N': | ||
| 3062 | value = zero / zero; | ||
| 3063 | 3031 | ||
| 3064 | /* If that made a "negative" NaN, negate it. */ | 3032 | result = string_to_float (read_buffer, 0); |
| 3065 | 3033 | if (FLOATP (result)) | |
| 3066 | { | 3034 | return result; |
| 3067 | int i; | ||
| 3068 | union { double d; char c[sizeof (double)]; } u_data, u_minus_zero; | ||
| 3069 | |||
| 3070 | u_data.d = value; | ||
| 3071 | u_minus_zero.d = - 0.0; | ||
| 3072 | for (i = 0; i < sizeof (double); i++) | ||
| 3073 | if (u_data.c[i] & u_minus_zero.c[i]) | ||
| 3074 | { | ||
| 3075 | value = - value; | ||
| 3076 | break; | ||
| 3077 | } | ||
| 3078 | } | ||
| 3079 | /* Now VALUE is a positive NaN. */ | ||
| 3080 | break; | ||
| 3081 | default: | ||
| 3082 | value = atof (read_buffer + negative); | ||
| 3083 | break; | ||
| 3084 | } | ||
| 3085 | |||
| 3086 | return make_float (negative ? - value : value); | ||
| 3087 | } | ||
| 3088 | } | 3035 | } |
| 3089 | { | 3036 | { |
| 3090 | Lisp_Object name, result; | 3037 | Lisp_Object name, result; |
| @@ -3242,20 +3189,40 @@ substitute_in_interval (INTERVAL interval, Lisp_Object arg) | |||
| 3242 | } | 3189 | } |
| 3243 | 3190 | ||
| 3244 | 3191 | ||
| 3192 | /* Return the length of the floating-point number that is the prefix of CP, or | ||
| 3193 | zero if there is none. */ | ||
| 3194 | |||
| 3245 | #define LEAD_INT 1 | 3195 | #define LEAD_INT 1 |
| 3246 | #define DOT_CHAR 2 | 3196 | #define DOT_CHAR 2 |
| 3247 | #define TRAIL_INT 4 | 3197 | #define TRAIL_INT 4 |
| 3248 | #define E_CHAR 8 | 3198 | #define E_CHAR 8 |
| 3249 | #define EXP_INT 16 | 3199 | #define EXP_INT 16 |
| 3250 | 3200 | ||
| 3251 | int | 3201 | |
| 3252 | isfloat_string (const char *cp, int ignore_trailing) | 3202 | /* Convert CP to a floating point number. Return a non-float value if CP does |
| 3203 | not have valid floating point syntax. If IGNORE_TRAILING is nonzero, | ||
| 3204 | consider just the longest prefix of CP that has valid floating point | ||
| 3205 | syntax. */ | ||
| 3206 | |||
| 3207 | Lisp_Object | ||
| 3208 | string_to_float (char const *cp, int ignore_trailing) | ||
| 3253 | { | 3209 | { |
| 3254 | int state; | 3210 | int state; |
| 3255 | const char *start = cp; | 3211 | const char *start = cp; |
| 3256 | 3212 | ||
| 3213 | /* Compute NaN and infinities using a variable, to cope with compilers that | ||
| 3214 | think they are smarter than we are. */ | ||
| 3215 | double zero = 0; | ||
| 3216 | |||
| 3217 | /* Negate the value ourselves. This treats 0, NaNs, and infinity properly on | ||
| 3218 | IEEE floating point hosts, and works around a formerly-common bug where | ||
| 3219 | atof ("-0.0") drops the sign. */ | ||
| 3220 | int negative = *cp == '-'; | ||
| 3221 | |||
| 3222 | double value = 0; | ||
| 3223 | |||
| 3257 | state = 0; | 3224 | state = 0; |
| 3258 | if (*cp == '+' || *cp == '-') | 3225 | if (negative || *cp == '+') |
| 3259 | cp++; | 3226 | cp++; |
| 3260 | 3227 | ||
| 3261 | if (*cp >= '0' && *cp <= '9') | 3228 | if (*cp >= '0' && *cp <= '9') |
| @@ -3295,21 +3262,43 @@ isfloat_string (const char *cp, int ignore_trailing) | |||
| 3295 | { | 3262 | { |
| 3296 | state |= EXP_INT; | 3263 | state |= EXP_INT; |
| 3297 | cp += 3; | 3264 | cp += 3; |
| 3265 | value = 1.0 / zero; | ||
| 3298 | } | 3266 | } |
| 3299 | else if (cp[-1] == '+' && cp[0] == 'N' && cp[1] == 'a' && cp[2] == 'N') | 3267 | else if (cp[-1] == '+' && cp[0] == 'N' && cp[1] == 'a' && cp[2] == 'N') |
| 3300 | { | 3268 | { |
| 3301 | state |= EXP_INT; | 3269 | state |= EXP_INT; |
| 3302 | cp += 3; | 3270 | cp += 3; |
| 3271 | value = zero / zero; | ||
| 3272 | |||
| 3273 | /* If that made a "negative" NaN, negate it. */ | ||
| 3274 | { | ||
| 3275 | int i; | ||
| 3276 | union { double d; char c[sizeof (double)]; } u_data, u_minus_zero; | ||
| 3277 | |||
| 3278 | u_data.d = value; | ||
| 3279 | u_minus_zero.d = - 0.0; | ||
| 3280 | for (i = 0; i < sizeof (double); i++) | ||
| 3281 | if (u_data.c[i] & u_minus_zero.c[i]) | ||
| 3282 | { | ||
| 3283 | value = - value; | ||
| 3284 | break; | ||
| 3285 | } | ||
| 3286 | } | ||
| 3287 | /* Now VALUE is a positive NaN. */ | ||
| 3303 | } | 3288 | } |
| 3304 | 3289 | ||
| 3305 | return ((ignore_trailing | 3290 | if (! (state == (LEAD_INT|DOT_CHAR|TRAIL_INT) |
| 3306 | || *cp == 0 || *cp == ' ' || *cp == '\t' || *cp == '\n' | 3291 | || state == (DOT_CHAR|TRAIL_INT) |
| 3307 | || *cp == '\r' || *cp == '\f') | 3292 | || state == (LEAD_INT|E_CHAR|EXP_INT) |
| 3308 | && (state == (LEAD_INT|DOT_CHAR|TRAIL_INT) | 3293 | || state == (LEAD_INT|DOT_CHAR|TRAIL_INT|E_CHAR|EXP_INT) |
| 3309 | || state == (DOT_CHAR|TRAIL_INT) | 3294 | || state == (DOT_CHAR|TRAIL_INT|E_CHAR|EXP_INT))) |
| 3310 | || state == (LEAD_INT|E_CHAR|EXP_INT) | 3295 | return make_number (0); /* Any non-float value will do. */ |
| 3311 | || state == (LEAD_INT|DOT_CHAR|TRAIL_INT|E_CHAR|EXP_INT) | 3296 | |
| 3312 | || state == (DOT_CHAR|TRAIL_INT|E_CHAR|EXP_INT))); | 3297 | if (! value) |
| 3298 | value = atof (start + negative); | ||
| 3299 | if (negative) | ||
| 3300 | value = - value; | ||
| 3301 | return make_float (value); | ||
| 3313 | } | 3302 | } |
| 3314 | 3303 | ||
| 3315 | 3304 | ||