diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/editfns.c | 96 |
1 files changed, 41 insertions, 55 deletions
diff --git a/src/editfns.c b/src/editfns.c index 96bb271b2d6..3a34dd0980b 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -4563,32 +4563,30 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4563 | and with pM inserted for integer formats. | 4563 | and with pM inserted for integer formats. |
| 4564 | At most two flags F can be specified at once. */ | 4564 | At most two flags F can be specified at once. */ |
| 4565 | char convspec[sizeof "%FF.*d" + max (INT_AS_LDBL, pMlen)]; | 4565 | char convspec[sizeof "%FF.*d" + max (INT_AS_LDBL, pMlen)]; |
| 4566 | { | 4566 | char *f = convspec; |
| 4567 | char *f = convspec; | 4567 | *f++ = '%'; |
| 4568 | *f++ = '%'; | 4568 | /* MINUS_FLAG and ZERO_FLAG are dealt with later. */ |
| 4569 | /* MINUS_FLAG and ZERO_FLAG are dealt with later. */ | 4569 | *f = '+'; f += plus_flag; |
| 4570 | *f = '+'; f += plus_flag; | 4570 | *f = ' '; f += space_flag; |
| 4571 | *f = ' '; f += space_flag; | 4571 | *f = '#'; f += sharp_flag; |
| 4572 | *f = '#'; f += sharp_flag; | 4572 | *f++ = '.'; |
| 4573 | *f++ = '.'; | 4573 | *f++ = '*'; |
| 4574 | *f++ = '*'; | 4574 | if (float_conversion) |
| 4575 | if (float_conversion) | 4575 | { |
| 4576 | { | 4576 | if (INT_AS_LDBL) |
| 4577 | if (INT_AS_LDBL) | 4577 | { |
| 4578 | { | 4578 | *f = 'L'; |
| 4579 | *f = 'L'; | 4579 | f += INTEGERP (arg); |
| 4580 | f += INTEGERP (arg); | 4580 | } |
| 4581 | } | 4581 | } |
| 4582 | } | 4582 | else if (conversion != 'c') |
| 4583 | else if (conversion != 'c') | 4583 | { |
| 4584 | { | 4584 | memcpy (f, pMd, pMlen); |
| 4585 | memcpy (f, pMd, pMlen); | 4585 | f += pMlen; |
| 4586 | f += pMlen; | 4586 | zero_flag &= ! precision_given; |
| 4587 | zero_flag &= ! precision_given; | 4587 | } |
| 4588 | } | 4588 | *f++ = conversion; |
| 4589 | *f++ = conversion; | 4589 | *f = '\0'; |
| 4590 | *f = '\0'; | ||
| 4591 | } | ||
| 4592 | 4590 | ||
| 4593 | int prec = -1; | 4591 | int prec = -1; |
| 4594 | if (precision_given) | 4592 | if (precision_given) |
| @@ -4630,29 +4628,20 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4630 | } | 4628 | } |
| 4631 | else if (conversion == 'd' || conversion == 'i') | 4629 | else if (conversion == 'd' || conversion == 'i') |
| 4632 | { | 4630 | { |
| 4633 | /* For float, maybe we should use "%1.0f" | ||
| 4634 | instead so it also works for values outside | ||
| 4635 | the integer range. */ | ||
| 4636 | printmax_t x; | ||
| 4637 | if (INTEGERP (arg)) | 4631 | if (INTEGERP (arg)) |
| 4638 | x = XINT (arg); | 4632 | { |
| 4633 | printmax_t x = XINT (arg); | ||
| 4634 | sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x); | ||
| 4635 | } | ||
| 4639 | else | 4636 | else |
| 4640 | { | 4637 | { |
| 4641 | double d = XFLOAT_DATA (arg); | 4638 | strcpy (f - pMlen - 1, "f"); |
| 4642 | if (d < 0) | 4639 | double x = XFLOAT_DATA (arg); |
| 4643 | { | 4640 | sprintf_bytes = sprintf (sprintf_buf, convspec, 0, x); |
| 4644 | x = TYPE_MINIMUM (printmax_t); | 4641 | char c0 = sprintf_buf[0]; |
| 4645 | if (x < d) | 4642 | bool signedp = ! ('0' <= c0 && c0 <= '9'); |
| 4646 | x = d; | 4643 | prec = min (precision, sprintf_bytes - signedp); |
| 4647 | } | ||
| 4648 | else | ||
| 4649 | { | ||
| 4650 | x = TYPE_MAXIMUM (printmax_t); | ||
| 4651 | if (d < x) | ||
| 4652 | x = d; | ||
| 4653 | } | ||
| 4654 | } | 4644 | } |
| 4655 | sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x); | ||
| 4656 | } | 4645 | } |
| 4657 | else | 4646 | else |
| 4658 | { | 4647 | { |
| @@ -4663,22 +4652,19 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4663 | else | 4652 | else |
| 4664 | { | 4653 | { |
| 4665 | double d = XFLOAT_DATA (arg); | 4654 | double d = XFLOAT_DATA (arg); |
| 4666 | if (d < 0) | 4655 | double uprintmax = TYPE_MAXIMUM (uprintmax_t); |
| 4667 | x = 0; | 4656 | if (! (0 <= d && d < uprintmax + 1)) |
| 4668 | else | 4657 | xsignal1 (Qoverflow_error, arg); |
| 4669 | { | 4658 | x = d; |
| 4670 | x = TYPE_MAXIMUM (uprintmax_t); | ||
| 4671 | if (d < x) | ||
| 4672 | x = d; | ||
| 4673 | } | ||
| 4674 | } | 4659 | } |
| 4675 | sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x); | 4660 | sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x); |
| 4676 | } | 4661 | } |
| 4677 | 4662 | ||
| 4678 | /* Now the length of the formatted item is known, except it omits | 4663 | /* Now the length of the formatted item is known, except it omits |
| 4679 | padding and excess precision. Deal with excess precision | 4664 | padding and excess precision. Deal with excess precision |
| 4680 | first. This happens only when the format specifies | 4665 | first. This happens when the format specifies ridiculously |
| 4681 | ridiculously large precision. */ | 4666 | large precision, or when %d or %i formats a float that would |
| 4667 | ordinarily need fewer digits than a specified precision. */ | ||
| 4682 | ptrdiff_t excess_precision | 4668 | ptrdiff_t excess_precision |
| 4683 | = precision_given ? precision - prec : 0; | 4669 | = precision_given ? precision - prec : 0; |
| 4684 | ptrdiff_t leading_zeros = 0, trailing_zeros = 0; | 4670 | ptrdiff_t leading_zeros = 0, trailing_zeros = 0; |