comparison src/message.c @ 10038:7cf4e210cf3c v7.4.2291

commit https://github.com/vim/vim/commit/04186095346daa60e82e981dad114de2b641d672 Author: Bram Moolenaar <Bram@vim.org> Date: Mon Aug 29 21:55:35 2016 +0200 patch 7.4.2291 Problem: printf() handles floats wrong when there is a sign. Solution: Fix placing the sign. Add tests. (Dominique Pelle)
author Christian Brabandt <cb@256bit.org>
date Mon, 29 Aug 2016 22:00:07 +0200
parents ab6320d74331
children 48f70e0c696a
comparison
equal deleted inserted replaced
10037:f359ee3f123e 10038:7cf4e210cf3c
4028 * This snprintf() only supports the following conversion specifiers: 4028 * This snprintf() only supports the following conversion specifiers:
4029 * s, c, d, u, o, x, X, p (and synonyms: i, D, U, O - see below) 4029 * s, c, d, u, o, x, X, p (and synonyms: i, D, U, O - see below)
4030 * with flags: '-', '+', ' ', '0' and '#'. 4030 * with flags: '-', '+', ' ', '0' and '#'.
4031 * An asterisk is supported for field width as well as precision. 4031 * An asterisk is supported for field width as well as precision.
4032 * 4032 *
4033 * Limited support for floating point was added: 'f', 'e', 'E', 'g', 'G'. 4033 * Limited support for floating point was added: 'f', 'F', 'e', 'E', 'g', 'G'.
4034 * 4034 *
4035 * Length modifiers 'h' (short int) and 'l' (long int) and 'll' (long long int) 4035 * Length modifiers 'h' (short int) and 'l' (long int) and 'll' (long long int)
4036 * are supported. 4036 * are supported.
4037 * 4037 *
4038 * The locale is not used, the string is used as a byte string. This is only 4038 * The locale is not used, the string is used as a byte string. This is only
4284 { 4284 {
4285 case 'i': fmt_spec = 'd'; break; 4285 case 'i': fmt_spec = 'd'; break;
4286 case 'D': fmt_spec = 'd'; length_modifier = 'l'; break; 4286 case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
4287 case 'U': fmt_spec = 'u'; length_modifier = 'l'; break; 4287 case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
4288 case 'O': fmt_spec = 'o'; length_modifier = 'l'; break; 4288 case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
4289 case 'F': fmt_spec = 'f'; break;
4290 default: break; 4289 default: break;
4291 } 4290 }
4292 4291
4293 # if defined(FEAT_EVAL) && defined(FEAT_NUM64) 4292 # if defined(FEAT_EVAL) && defined(FEAT_NUM64)
4294 switch (fmt_spec) 4293 switch (fmt_spec)
4713 break; 4712 break;
4714 } 4713 }
4715 4714
4716 # ifdef FEAT_FLOAT 4715 # ifdef FEAT_FLOAT
4717 case 'f': 4716 case 'f':
4717 case 'F':
4718 case 'e': 4718 case 'e':
4719 case 'E': 4719 case 'E':
4720 case 'g': 4720 case 'g':
4721 case 'G': 4721 case 'G':
4722 { 4722 {
4738 { 4738 {
4739 /* Would be nice to use %g directly, but it prints 4739 /* Would be nice to use %g directly, but it prints
4740 * "1.0" as "1", we don't want that. */ 4740 * "1.0" as "1", we don't want that. */
4741 if ((abs_f >= 0.001 && abs_f < 10000000.0) 4741 if ((abs_f >= 0.001 && abs_f < 10000000.0)
4742 || abs_f == 0.0) 4742 || abs_f == 0.0)
4743 fmt_spec = 'f'; 4743 fmt_spec = ASCII_ISUPPER(fmt_spec) ? 'F' : 'f';
4744 else 4744 else
4745 fmt_spec = fmt_spec == 'g' ? 'e' : 'E'; 4745 fmt_spec = fmt_spec == 'g' ? 'e' : 'E';
4746 remove_trailing_zeroes = TRUE; 4746 remove_trailing_zeroes = TRUE;
4747 } 4747 }
4748 4748
4749 if (fmt_spec == 'f' && 4749 if ((fmt_spec == 'f' || fmt_spec == 'F') &&
4750 # ifdef VAX 4750 # ifdef VAX
4751 abs_f > 1.0e38 4751 abs_f > 1.0e38
4752 # else 4752 # else
4753 abs_f > 1.0e307 4753 abs_f > 1.0e307
4754 # endif 4754 # endif
4760 str_arg_l = STRLEN(tmp); 4760 str_arg_l = STRLEN(tmp);
4761 zero_padding = 0; 4761 zero_padding = 0;
4762 } 4762 }
4763 else 4763 else
4764 { 4764 {
4765 format[0] = '%';
4766 l = 1;
4767 if (precision_specified)
4768 {
4769 size_t max_prec = TMP_LEN - 10;
4770
4771 /* Make sure we don't get more digits than we
4772 * have room for. */
4773 if (fmt_spec == 'f' && abs_f > 1.0)
4774 max_prec -= (size_t)log10(abs_f);
4775 if (precision > max_prec)
4776 precision = max_prec;
4777 l += sprintf(format + 1, ".%d", (int)precision);
4778 }
4779 format[l] = fmt_spec;
4780 format[l + 1] = NUL;
4781
4782 if (isnan(f)) 4765 if (isnan(f))
4783 { 4766 {
4784 /* Not a number: nan or NAN */ 4767 /* Not a number: nan or NAN */
4785 STRCPY(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" 4768 STRCPY(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN"
4786 : "nan"); 4769 : "nan");
4793 force_sign, space_for_positive)); 4776 force_sign, space_for_positive));
4794 str_arg_l = STRLEN(tmp); 4777 str_arg_l = STRLEN(tmp);
4795 zero_padding = 0; 4778 zero_padding = 0;
4796 } 4779 }
4797 else 4780 else
4781 {
4798 /* Regular float number */ 4782 /* Regular float number */
4783 format[0] = '%';
4784 l = 1;
4785 if (force_sign)
4786 format[l++] = space_for_positive ? ' ' : '+';
4787 if (precision_specified)
4788 {
4789 size_t max_prec = TMP_LEN - 10;
4790
4791 /* Make sure we don't get more digits than we
4792 * have room for. */
4793 if ((fmt_spec == 'f' || fmt_spec == 'F')
4794 && abs_f > 1.0)
4795 max_prec -= (size_t)log10(abs_f);
4796 if (precision > max_prec)
4797 precision = max_prec;
4798 l += sprintf(format + l, ".%d", (int)precision);
4799 }
4800 format[l] = fmt_spec;
4801 format[l + 1] = NUL;
4802
4799 str_arg_l = sprintf(tmp, format, f); 4803 str_arg_l = sprintf(tmp, format, f);
4804 }
4800 4805
4801 if (remove_trailing_zeroes) 4806 if (remove_trailing_zeroes)
4802 { 4807 {
4803 int i; 4808 int i;
4804 char *tp; 4809 char *tp;
4805 4810
4806 /* Using %g or %G: remove superfluous zeroes. */ 4811 /* Using %g or %G: remove superfluous zeroes. */
4807 if (fmt_spec == 'f') 4812 if (fmt_spec == 'f' || fmt_spec == 'F')
4808 tp = tmp + str_arg_l - 1; 4813 tp = tmp + str_arg_l - 1;
4809 else 4814 else
4810 { 4815 {
4811 tp = (char *)vim_strchr((char_u *)tmp, 4816 tp = (char *)vim_strchr((char_u *)tmp,
4812 fmt_spec == 'e' ? 'e' : 'E'); 4817 fmt_spec == 'e' ? 'e' : 'E');
4859 STRMOVE(tp + 2, tp + 3); 4864 STRMOVE(tp + 2, tp + 3);
4860 --str_arg_l; 4865 --str_arg_l;
4861 } 4866 }
4862 } 4867 }
4863 } 4868 }
4869 if (zero_padding && min_field_width > str_arg_l
4870 && (tmp[0] == '-' || force_sign))
4871 {
4872 /* padding 0's should be inserted after the sign */
4873 number_of_zeros_to_pad = min_field_width - str_arg_l;
4874 zero_padding_insertion_ind = 1;
4875 }
4864 str_arg = tmp; 4876 str_arg = tmp;
4865 break; 4877 break;
4866 } 4878 }
4867 # endif 4879 # endif
4868 4880