diff options
Diffstat (limited to 'src/data.c')
| -rw-r--r-- | src/data.c | 121 |
1 files changed, 99 insertions, 22 deletions
diff --git a/src/data.c b/src/data.c index 78bd454056d..a41ffe7a1f6 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -2326,33 +2326,110 @@ DEFUN ("zerop", Fzerop, Szerop, 1, 1, 0, | |||
| 2326 | return Qnil; | 2326 | return Qnil; |
| 2327 | } | 2327 | } |
| 2328 | 2328 | ||
| 2329 | /* Convert between long values and pairs of Lisp integers. | 2329 | /* Convert the cons-of-integers, integer, or float value C to an |
| 2330 | Note that long_to_cons returns a single Lisp integer | 2330 | unsigned value with maximum value MAX. Signal an error if C does not |
| 2331 | when the value fits in one. */ | 2331 | have a valid format or is out of range. */ |
| 2332 | uintmax_t | ||
| 2333 | cons_to_unsigned (Lisp_Object c, uintmax_t max) | ||
| 2334 | { | ||
| 2335 | int valid = 0; | ||
| 2336 | uintmax_t val IF_LINT (= 0); | ||
| 2337 | if (INTEGERP (c)) | ||
| 2338 | { | ||
| 2339 | valid = 0 <= XINT (c); | ||
| 2340 | val = XINT (c); | ||
| 2341 | } | ||
| 2342 | else if (FLOATP (c)) | ||
| 2343 | { | ||
| 2344 | double d = XFLOAT_DATA (c); | ||
| 2345 | if (0 <= d | ||
| 2346 | && d < (max == UINTMAX_MAX ? (double) UINTMAX_MAX + 1 : max + 1)) | ||
| 2347 | { | ||
| 2348 | val = d; | ||
| 2349 | valid = 1; | ||
| 2350 | } | ||
| 2351 | } | ||
| 2352 | else if (CONSP (c) && NATNUMP (XCAR (c))) | ||
| 2353 | { | ||
| 2354 | uintmax_t top = XFASTINT (XCAR (c)); | ||
| 2355 | Lisp_Object rest = XCDR (c); | ||
| 2356 | if (top <= UINTMAX_MAX >> 24 >> 16 | ||
| 2357 | && CONSP (rest) | ||
| 2358 | && NATNUMP (XCAR (rest)) && XFASTINT (XCAR (rest)) < 1 << 24 | ||
| 2359 | && NATNUMP (XCDR (rest)) && XFASTINT (XCDR (rest)) < 1 << 16) | ||
| 2360 | { | ||
| 2361 | uintmax_t mid = XFASTINT (XCAR (rest)); | ||
| 2362 | val = top << 24 << 16 | mid << 16 | XFASTINT (XCDR (rest)); | ||
| 2363 | valid = 1; | ||
| 2364 | } | ||
| 2365 | else if (top <= UINTMAX_MAX >> 16) | ||
| 2366 | { | ||
| 2367 | if (CONSP (rest)) | ||
| 2368 | rest = XCAR (rest); | ||
| 2369 | if (NATNUMP (rest) && XFASTINT (rest) < 1 << 16) | ||
| 2370 | { | ||
| 2371 | val = top << 16 | XFASTINT (rest); | ||
| 2372 | valid = 1; | ||
| 2373 | } | ||
| 2374 | } | ||
| 2375 | } | ||
| 2332 | 2376 | ||
| 2333 | Lisp_Object | 2377 | if (! (valid && val <= max)) |
| 2334 | long_to_cons (long unsigned int i) | 2378 | error ("Not an in-range integer, float, or cons of integers"); |
| 2335 | { | 2379 | return val; |
| 2336 | unsigned long top = i >> 16; | ||
| 2337 | unsigned int bot = i & 0xFFFF; | ||
| 2338 | if (top == 0) | ||
| 2339 | return make_number (bot); | ||
| 2340 | if (top == (unsigned long)-1 >> 16) | ||
| 2341 | return Fcons (make_number (-1), make_number (bot)); | ||
| 2342 | return Fcons (make_number (top), make_number (bot)); | ||
| 2343 | } | 2380 | } |
| 2344 | 2381 | ||
| 2345 | unsigned long | 2382 | /* Convert the cons-of-integers, integer, or float value C to a signed |
| 2346 | cons_to_long (Lisp_Object c) | 2383 | value with extrema MIN and MAX. Signal an error if C does not have |
| 2384 | a valid format or is out of range. */ | ||
| 2385 | intmax_t | ||
| 2386 | cons_to_signed (Lisp_Object c, intmax_t min, intmax_t max) | ||
| 2347 | { | 2387 | { |
| 2348 | Lisp_Object top, bot; | 2388 | int valid = 0; |
| 2389 | intmax_t val IF_LINT (= 0); | ||
| 2349 | if (INTEGERP (c)) | 2390 | if (INTEGERP (c)) |
| 2350 | return XINT (c); | 2391 | { |
| 2351 | top = XCAR (c); | 2392 | val = XINT (c); |
| 2352 | bot = XCDR (c); | 2393 | valid = 1; |
| 2353 | if (CONSP (bot)) | 2394 | } |
| 2354 | bot = XCAR (bot); | 2395 | else if (FLOATP (c)) |
| 2355 | return ((XINT (top) << 16) | XINT (bot)); | 2396 | { |
| 2397 | double d = XFLOAT_DATA (c); | ||
| 2398 | if (min <= d | ||
| 2399 | && d < (max == INTMAX_MAX ? (double) INTMAX_MAX + 1 : max + 1)) | ||
| 2400 | { | ||
| 2401 | val = d; | ||
| 2402 | valid = 1; | ||
| 2403 | } | ||
| 2404 | } | ||
| 2405 | else if (CONSP (c) && INTEGERP (XCAR (c))) | ||
| 2406 | { | ||
| 2407 | intmax_t top = XINT (XCAR (c)); | ||
| 2408 | Lisp_Object rest = XCDR (c); | ||
| 2409 | if (INTMAX_MIN >> 24 >> 16 <= top && top <= INTMAX_MAX >> 24 >> 16 | ||
| 2410 | && CONSP (rest) | ||
| 2411 | && NATNUMP (XCAR (rest)) && XFASTINT (XCAR (rest)) < 1 << 24 | ||
| 2412 | && NATNUMP (XCDR (rest)) && XFASTINT (XCDR (rest)) < 1 << 16) | ||
| 2413 | { | ||
| 2414 | intmax_t mid = XFASTINT (XCAR (rest)); | ||
| 2415 | val = top << 24 << 16 | mid << 16 | XFASTINT (XCDR (rest)); | ||
| 2416 | valid = 1; | ||
| 2417 | } | ||
| 2418 | else if (INTMAX_MIN >> 16 <= top && top <= INTMAX_MAX >> 16) | ||
| 2419 | { | ||
| 2420 | if (CONSP (rest)) | ||
| 2421 | rest = XCAR (rest); | ||
| 2422 | if (NATNUMP (rest) && XFASTINT (rest) < 1 << 16) | ||
| 2423 | { | ||
| 2424 | val = top << 16 | XFASTINT (rest); | ||
| 2425 | valid = 1; | ||
| 2426 | } | ||
| 2427 | } | ||
| 2428 | } | ||
| 2429 | |||
| 2430 | if (! (valid && min <= val && val <= max)) | ||
| 2431 | error ("Not an in-range integer, float, or cons of integers"); | ||
| 2432 | return val; | ||
| 2356 | } | 2433 | } |
| 2357 | 2434 | ||
| 2358 | DEFUN ("number-to-string", Fnumber_to_string, Snumber_to_string, 1, 1, 0, | 2435 | DEFUN ("number-to-string", Fnumber_to_string, Snumber_to_string, 1, 1, 0, |