diff options
| author | Paul Eggert | 2015-08-27 08:50:22 -0700 |
|---|---|---|
| committer | Paul Eggert | 2015-08-27 08:52:02 -0700 |
| commit | 6dbe056b9beec0b9ff6c84331a49c568408dbbaa (patch) | |
| tree | 32a6e13fcb20634d9986324e9dc973713cd7be96 /src | |
| parent | f33c164123e2bc46c4d06853b1a32130126d54c8 (diff) | |
| download | emacs-6dbe056b9beec0b9ff6c84331a49c568408dbbaa.tar.gz emacs-6dbe056b9beec0b9ff6c84331a49c568408dbbaa.zip | |
Add test case for ‘format’ bug and refactor
* src/editfns.c (styled_format): Refactor internally, mostly by
moving declarations closer to uses. This should not affect behavior.
* test/automated/textprop-tests.el (textprop-tests-format): New test.
Diffstat (limited to 'src')
| -rw-r--r-- | src/editfns.c | 237 |
1 files changed, 103 insertions, 134 deletions
diff --git a/src/editfns.c b/src/editfns.c index bbb139f2980..a85c9e79d4e 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -3861,68 +3861,59 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 3861 | ptrdiff_t max_bufsize = STRING_BYTES_BOUND + 1; | 3861 | ptrdiff_t max_bufsize = STRING_BYTES_BOUND + 1; |
| 3862 | char *p; | 3862 | char *p; |
| 3863 | ptrdiff_t buf_save_value_index IF_LINT (= 0); | 3863 | ptrdiff_t buf_save_value_index IF_LINT (= 0); |
| 3864 | char *format, *end, *format_start; | 3864 | char *format, *end; |
| 3865 | ptrdiff_t formatlen, nchars; | 3865 | ptrdiff_t nchars; |
| 3866 | /* True if the format is multibyte. */ | ||
| 3867 | bool multibyte_format = 0; | ||
| 3868 | /* True if the output should be a multibyte string, | ||
| 3869 | which is true if any of the inputs is one. */ | ||
| 3870 | bool multibyte = 0; | ||
| 3871 | /* When we make a multibyte string, we must pay attention to the | 3866 | /* When we make a multibyte string, we must pay attention to the |
| 3872 | byte combining problem, i.e., a byte may be combined with a | 3867 | byte combining problem, i.e., a byte may be combined with a |
| 3873 | multibyte character of the previous string. This flag tells if we | 3868 | multibyte character of the previous string. This flag tells if we |
| 3874 | must consider such a situation or not. */ | 3869 | must consider such a situation or not. */ |
| 3875 | bool maybe_combine_byte; | 3870 | bool maybe_combine_byte; |
| 3876 | Lisp_Object val; | 3871 | bool arg_intervals = false; |
| 3877 | bool arg_intervals = 0; | ||
| 3878 | USE_SAFE_ALLOCA; | 3872 | USE_SAFE_ALLOCA; |
| 3879 | 3873 | ||
| 3880 | /* discarded[I] is 1 if byte I of the format | ||
| 3881 | string was not copied into the output. | ||
| 3882 | It is 2 if byte I was not the first byte of its character. */ | ||
| 3883 | char *discarded; | ||
| 3884 | |||
| 3885 | /* Each element records, for one argument, | 3874 | /* Each element records, for one argument, |
| 3886 | the start and end bytepos in the output string, | 3875 | the start and end bytepos in the output string, |
| 3887 | whether the argument has been converted to string (e.g., due to "%S"), | 3876 | whether the argument has been converted to string (e.g., due to "%S"), |
| 3888 | and whether the argument is a string with intervals. | 3877 | and whether the argument is a string with intervals. */ |
| 3889 | info[0] is unused. Unused elements have -1 for start. */ | ||
| 3890 | struct info | 3878 | struct info |
| 3891 | { | 3879 | { |
| 3892 | ptrdiff_t start, end; | 3880 | ptrdiff_t start, end; |
| 3893 | bool_bf converted_to_string : 1; | 3881 | bool_bf converted_to_string : 1; |
| 3894 | bool_bf intervals : 1; | 3882 | bool_bf intervals : 1; |
| 3895 | } *info = 0; | 3883 | } *info; |
| 3896 | 3884 | ||
| 3897 | CHECK_STRING (args[0]); | 3885 | CHECK_STRING (args[0]); |
| 3898 | format_start = SSDATA (args[0]); | 3886 | char *format_start = SSDATA (args[0]); |
| 3899 | formatlen = SBYTES (args[0]); | 3887 | ptrdiff_t formatlen = SBYTES (args[0]); |
| 3900 | 3888 | ||
| 3901 | /* Allocate the info and discarded tables. */ | 3889 | /* Allocate the info and discarded tables. */ |
| 3902 | { | 3890 | if ((SIZE_MAX - formatlen) / sizeof (struct info) <= nargs) |
| 3903 | ptrdiff_t i; | 3891 | memory_full (SIZE_MAX); |
| 3904 | if ((SIZE_MAX - formatlen) / sizeof (struct info) <= nargs) | 3892 | size_t alloca_size = (nargs + 1) * sizeof *info + formatlen; |
| 3905 | memory_full (SIZE_MAX); | 3893 | /* info[0] is unused. Unused elements have -1 for start. */ |
| 3906 | info = SAFE_ALLOCA ((nargs + 1) * sizeof *info + formatlen); | 3894 | info = SAFE_ALLOCA (alloca_size); |
| 3907 | discarded = (char *) &info[nargs + 1]; | 3895 | memset (info, 0, alloca_size); |
| 3908 | for (i = 0; i < nargs + 1; i++) | 3896 | for (ptrdiff_t i = 0; i < nargs + 1; i++) |
| 3909 | { | 3897 | info[i].start = -1; |
| 3910 | info[i].start = -1; | 3898 | /* discarded[I] is 1 if byte I of the format |
| 3911 | info[i].intervals = info[i].converted_to_string = 0; | 3899 | string was not copied into the output. |
| 3912 | } | 3900 | It is 2 if byte I was not the first byte of its character. */ |
| 3913 | memset (discarded, 0, formatlen); | 3901 | char *discarded = (char *) &info[nargs + 1]; |
| 3914 | } | ||
| 3915 | 3902 | ||
| 3916 | /* Try to determine whether the result should be multibyte. | 3903 | /* Try to determine whether the result should be multibyte. |
| 3917 | This is not always right; sometimes the result needs to be multibyte | 3904 | This is not always right; sometimes the result needs to be multibyte |
| 3918 | because of an object that we will pass through prin1. | 3905 | because of an object that we will pass through prin1. |
| 3919 | or because a grave accent or apostrophe is requoted, | 3906 | or because a grave accent or apostrophe is requoted, |
| 3920 | and in that case, we won't know it here. */ | 3907 | and in that case, we won't know it here. */ |
| 3921 | multibyte_format = STRING_MULTIBYTE (args[0]); | 3908 | |
| 3922 | multibyte = multibyte_format; | 3909 | /* True if the format is multibyte. */ |
| 3923 | for (n = 1; !multibyte && n < nargs; n++) | 3910 | bool multibyte_format = STRING_MULTIBYTE (args[0]); |
| 3924 | if (STRINGP (args[n]) && STRING_MULTIBYTE (args[n])) | 3911 | /* True if the output should be a multibyte string, |
| 3925 | multibyte = 1; | 3912 | which is true if any of the inputs is one. */ |
| 3913 | bool multibyte = multibyte_format; | ||
| 3914 | for (ptrdiff_t i = 1; !multibyte && i < nargs; i++) | ||
| 3915 | if (STRINGP (args[i]) && STRING_MULTIBYTE (args[i])) | ||
| 3916 | multibyte = true; | ||
| 3926 | 3917 | ||
| 3927 | int quoting_style = message ? text_quoting_style () : -1; | 3918 | int quoting_style = message ? text_quoting_style () : -1; |
| 3928 | 3919 | ||
| @@ -3937,7 +3928,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 3937 | /* Scan the format and store result in BUF. */ | 3928 | /* Scan the format and store result in BUF. */ |
| 3938 | format = format_start; | 3929 | format = format_start; |
| 3939 | end = format + formatlen; | 3930 | end = format + formatlen; |
| 3940 | maybe_combine_byte = 0; | 3931 | maybe_combine_byte = false; |
| 3941 | 3932 | ||
| 3942 | while (format != end) | 3933 | while (format != end) |
| 3943 | { | 3934 | { |
| @@ -3975,11 +3966,6 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 3975 | bool space_flag = false; | 3966 | bool space_flag = false; |
| 3976 | bool sharp_flag = false; | 3967 | bool sharp_flag = false; |
| 3977 | bool zero_flag = false; | 3968 | bool zero_flag = false; |
| 3978 | ptrdiff_t field_width; | ||
| 3979 | bool precision_given; | ||
| 3980 | uintmax_t precision = UINTMAX_MAX; | ||
| 3981 | char *num_end; | ||
| 3982 | char conversion; | ||
| 3983 | 3969 | ||
| 3984 | for (; ; format++) | 3970 | for (; ; format++) |
| 3985 | { | 3971 | { |
| @@ -3998,29 +3984,26 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 3998 | space_flag &= ~ plus_flag; | 3984 | space_flag &= ~ plus_flag; |
| 3999 | zero_flag &= ~ minus_flag; | 3985 | zero_flag &= ~ minus_flag; |
| 4000 | 3986 | ||
| 4001 | { | 3987 | char *num_end; |
| 4002 | uintmax_t w = strtoumax (format, &num_end, 10); | 3988 | uintmax_t raw_field_width = strtoumax (format, &num_end, 10); |
| 4003 | if (max_bufsize <= w) | 3989 | if (max_bufsize <= raw_field_width) |
| 4004 | string_overflow (); | 3990 | string_overflow (); |
| 4005 | field_width = w; | 3991 | ptrdiff_t field_width = raw_field_width; |
| 4006 | } | 3992 | |
| 4007 | precision_given = *num_end == '.'; | 3993 | bool precision_given = *num_end == '.'; |
| 4008 | if (precision_given) | 3994 | uintmax_t precision = (precision_given |
| 4009 | precision = strtoumax (num_end + 1, &num_end, 10); | 3995 | ? strtoumax (num_end + 1, &num_end, 10) |
| 3996 | : UINTMAX_MAX); | ||
| 4010 | format = num_end; | 3997 | format = num_end; |
| 4011 | 3998 | ||
| 4012 | if (format == end) | 3999 | if (format == end) |
| 4013 | error ("Format string ends in middle of format specifier"); | 4000 | error ("Format string ends in middle of format specifier"); |
| 4014 | 4001 | ||
| 4015 | memset (&discarded[format0 - format_start], 1, format - format0); | 4002 | char conversion = *format++; |
| 4016 | conversion = *format; | 4003 | memset (&discarded[format0 - format_start], 1, |
| 4004 | format - format0 - (conversion == '%')); | ||
| 4017 | if (conversion == '%') | 4005 | if (conversion == '%') |
| 4018 | { | 4006 | goto copy_char; |
| 4019 | format++; | ||
| 4020 | goto copy_char; | ||
| 4021 | } | ||
| 4022 | discarded[format - format_start] = 1; | ||
| 4023 | format++; | ||
| 4024 | 4007 | ||
| 4025 | ++n; | 4008 | ++n; |
| 4026 | if (! (n < nargs)) | 4009 | if (! (n < nargs)) |
| @@ -4038,10 +4021,10 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4038 | { | 4021 | { |
| 4039 | Lisp_Object noescape = conversion == 'S' ? Qnil : Qt; | 4022 | Lisp_Object noescape = conversion == 'S' ? Qnil : Qt; |
| 4040 | args[n] = Fprin1_to_string (args[n], noescape); | 4023 | args[n] = Fprin1_to_string (args[n], noescape); |
| 4041 | info[n].converted_to_string = 1; | 4024 | info[n].converted_to_string = true; |
| 4042 | if (STRING_MULTIBYTE (args[n]) && ! multibyte) | 4025 | if (STRING_MULTIBYTE (args[n]) && ! multibyte) |
| 4043 | { | 4026 | { |
| 4044 | multibyte = 1; | 4027 | multibyte = true; |
| 4045 | goto retry; | 4028 | goto retry; |
| 4046 | } | 4029 | } |
| 4047 | } | 4030 | } |
| @@ -4059,16 +4042,16 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4059 | { | 4042 | { |
| 4060 | if (!multibyte) | 4043 | if (!multibyte) |
| 4061 | { | 4044 | { |
| 4062 | multibyte = 1; | 4045 | multibyte = true; |
| 4063 | goto retry; | 4046 | goto retry; |
| 4064 | } | 4047 | } |
| 4065 | args[n] = Fchar_to_string (args[n]); | 4048 | args[n] = Fchar_to_string (args[n]); |
| 4066 | info[n].converted_to_string = 1; | 4049 | info[n].converted_to_string = true; |
| 4067 | } | 4050 | } |
| 4068 | 4051 | ||
| 4069 | if (info[n].converted_to_string) | 4052 | if (info[n].converted_to_string) |
| 4070 | conversion = 's'; | 4053 | conversion = 's'; |
| 4071 | zero_flag = 0; | 4054 | zero_flag = false; |
| 4072 | } | 4055 | } |
| 4073 | 4056 | ||
| 4074 | if (SYMBOLP (args[n])) | 4057 | if (SYMBOLP (args[n])) |
| @@ -4076,7 +4059,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4076 | args[n] = SYMBOL_NAME (args[n]); | 4059 | args[n] = SYMBOL_NAME (args[n]); |
| 4077 | if (STRING_MULTIBYTE (args[n]) && ! multibyte) | 4060 | if (STRING_MULTIBYTE (args[n]) && ! multibyte) |
| 4078 | { | 4061 | { |
| 4079 | multibyte = 1; | 4062 | multibyte = true; |
| 4080 | goto retry; | 4063 | goto retry; |
| 4081 | } | 4064 | } |
| 4082 | } | 4065 | } |
| @@ -4085,9 +4068,6 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4085 | { | 4068 | { |
| 4086 | /* handle case (precision[n] >= 0) */ | 4069 | /* handle case (precision[n] >= 0) */ |
| 4087 | 4070 | ||
| 4088 | ptrdiff_t width, padding, nbytes; | ||
| 4089 | ptrdiff_t nchars_string; | ||
| 4090 | |||
| 4091 | ptrdiff_t prec = -1; | 4071 | ptrdiff_t prec = -1; |
| 4092 | if (precision_given && precision <= TYPE_MAXIMUM (ptrdiff_t)) | 4072 | if (precision_given && precision <= TYPE_MAXIMUM (ptrdiff_t)) |
| 4093 | prec = precision; | 4073 | prec = precision; |
| @@ -4098,6 +4078,8 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4098 | lisp_string_width is the right thing, and will be | 4078 | lisp_string_width is the right thing, and will be |
| 4099 | done, but meanwhile we work with it. */ | 4079 | done, but meanwhile we work with it. */ |
| 4100 | 4080 | ||
| 4081 | ptrdiff_t width, nbytes; | ||
| 4082 | ptrdiff_t nchars_string; | ||
| 4101 | if (prec == 0) | 4083 | if (prec == 0) |
| 4102 | width = nchars_string = nbytes = 0; | 4084 | width = nchars_string = nbytes = 0; |
| 4103 | else | 4085 | else |
| @@ -4120,7 +4102,8 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4120 | if (convbytes && multibyte && ! STRING_MULTIBYTE (args[n])) | 4102 | if (convbytes && multibyte && ! STRING_MULTIBYTE (args[n])) |
| 4121 | convbytes = count_size_as_multibyte (SDATA (args[n]), nbytes); | 4103 | convbytes = count_size_as_multibyte (SDATA (args[n]), nbytes); |
| 4122 | 4104 | ||
| 4123 | padding = width < field_width ? field_width - width : 0; | 4105 | ptrdiff_t padding |
| 4106 | = width < field_width ? field_width - width : 0; | ||
| 4124 | 4107 | ||
| 4125 | if (max_bufsize - padding <= convbytes) | 4108 | if (max_bufsize - padding <= convbytes) |
| 4126 | string_overflow (); | 4109 | string_overflow (); |
| @@ -4139,7 +4122,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4139 | && !ASCII_CHAR_P (*((unsigned char *) p - 1)) | 4122 | && !ASCII_CHAR_P (*((unsigned char *) p - 1)) |
| 4140 | && STRING_MULTIBYTE (args[n]) | 4123 | && STRING_MULTIBYTE (args[n]) |
| 4141 | && !CHAR_HEAD_P (SREF (args[n], 0))) | 4124 | && !CHAR_HEAD_P (SREF (args[n], 0))) |
| 4142 | maybe_combine_byte = 1; | 4125 | maybe_combine_byte = true; |
| 4143 | 4126 | ||
| 4144 | p += copy_text (SDATA (args[n]), (unsigned char *) p, | 4127 | p += copy_text (SDATA (args[n]), (unsigned char *) p, |
| 4145 | nbytes, | 4128 | nbytes, |
| @@ -4159,7 +4142,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4159 | /* If this argument has text properties, record where | 4142 | /* If this argument has text properties, record where |
| 4160 | in the result string it appears. */ | 4143 | in the result string it appears. */ |
| 4161 | if (string_intervals (args[n])) | 4144 | if (string_intervals (args[n])) |
| 4162 | info[n].intervals = arg_intervals = 1; | 4145 | info[n].intervals = arg_intervals = true; |
| 4163 | 4146 | ||
| 4164 | continue; | 4147 | continue; |
| 4165 | } | 4148 | } |
| @@ -4198,24 +4181,15 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4198 | }; | 4181 | }; |
| 4199 | verify (USEFUL_PRECISION_MAX > 0); | 4182 | verify (USEFUL_PRECISION_MAX > 0); |
| 4200 | 4183 | ||
| 4201 | int prec; | ||
| 4202 | ptrdiff_t padding, sprintf_bytes; | ||
| 4203 | uintmax_t excess_precision, numwidth; | ||
| 4204 | uintmax_t leading_zeros = 0, trailing_zeros = 0; | ||
| 4205 | |||
| 4206 | char sprintf_buf[SPRINTF_BUFSIZE]; | ||
| 4207 | |||
| 4208 | /* Copy of conversion specification, modified somewhat. | ||
| 4209 | At most three flags F can be specified at once. */ | ||
| 4210 | char convspec[sizeof "%FFF.*d" + pMlen]; | ||
| 4211 | |||
| 4212 | /* Avoid undefined behavior in underlying sprintf. */ | 4184 | /* Avoid undefined behavior in underlying sprintf. */ |
| 4213 | if (conversion == 'd' || conversion == 'i') | 4185 | if (conversion == 'd' || conversion == 'i') |
| 4214 | sharp_flag = 0; | 4186 | sharp_flag = false; |
| 4215 | 4187 | ||
| 4216 | /* Create the copy of the conversion specification, with | 4188 | /* Create the copy of the conversion specification, with |
| 4217 | any width and precision removed, with ".*" inserted, | 4189 | any width and precision removed, with ".*" inserted, |
| 4218 | and with pM inserted for integer formats. */ | 4190 | and with pM inserted for integer formats. |
| 4191 | At most three flags F can be specified at once. */ | ||
| 4192 | char convspec[sizeof "%FFF.*d" + pMlen]; | ||
| 4219 | { | 4193 | { |
| 4220 | char *f = convspec; | 4194 | char *f = convspec; |
| 4221 | *f++ = '%'; | 4195 | *f++ = '%'; |
| @@ -4238,7 +4212,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4238 | *f = '\0'; | 4212 | *f = '\0'; |
| 4239 | } | 4213 | } |
| 4240 | 4214 | ||
| 4241 | prec = -1; | 4215 | int prec = -1; |
| 4242 | if (precision_given) | 4216 | if (precision_given) |
| 4243 | prec = min (precision, USEFUL_PRECISION_MAX); | 4217 | prec = min (precision, USEFUL_PRECISION_MAX); |
| 4244 | 4218 | ||
| @@ -4253,6 +4227,8 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4253 | careful about integer overflow, NaNs, infinities, and | 4227 | careful about integer overflow, NaNs, infinities, and |
| 4254 | conversions; for example, the min and max macros are | 4228 | conversions; for example, the min and max macros are |
| 4255 | not suitable here. */ | 4229 | not suitable here. */ |
| 4230 | char sprintf_buf[SPRINTF_BUFSIZE]; | ||
| 4231 | ptrdiff_t sprintf_bytes; | ||
| 4256 | if (conversion == 'e' || conversion == 'f' || conversion == 'g') | 4232 | if (conversion == 'e' || conversion == 'f' || conversion == 'g') |
| 4257 | { | 4233 | { |
| 4258 | double x = (INTEGERP (args[n]) | 4234 | double x = (INTEGERP (args[n]) |
| @@ -4317,7 +4293,8 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4317 | padding and excess precision. Deal with excess precision | 4293 | padding and excess precision. Deal with excess precision |
| 4318 | first. This happens only when the format specifies | 4294 | first. This happens only when the format specifies |
| 4319 | ridiculously large precision. */ | 4295 | ridiculously large precision. */ |
| 4320 | excess_precision = precision - prec; | 4296 | uintmax_t excess_precision = precision - prec; |
| 4297 | uintmax_t leading_zeros = 0, trailing_zeros = 0; | ||
| 4321 | if (excess_precision) | 4298 | if (excess_precision) |
| 4322 | { | 4299 | { |
| 4323 | if (conversion == 'e' || conversion == 'f' | 4300 | if (conversion == 'e' || conversion == 'f' |
| @@ -4344,8 +4321,9 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4344 | 4321 | ||
| 4345 | /* Compute the total bytes needed for this item, including | 4322 | /* Compute the total bytes needed for this item, including |
| 4346 | excess precision and padding. */ | 4323 | excess precision and padding. */ |
| 4347 | numwidth = sprintf_bytes + excess_precision; | 4324 | uintmax_t numwidth = sprintf_bytes + excess_precision; |
| 4348 | padding = numwidth < field_width ? field_width - numwidth : 0; | 4325 | ptrdiff_t padding |
| 4326 | = numwidth < field_width ? field_width - numwidth : 0; | ||
| 4349 | if (max_bufsize - sprintf_bytes <= excess_precision | 4327 | if (max_bufsize - sprintf_bytes <= excess_precision |
| 4350 | || max_bufsize - padding <= numwidth) | 4328 | || max_bufsize - padding <= numwidth) |
| 4351 | string_overflow (); | 4329 | string_overflow (); |
| @@ -4360,7 +4338,6 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4360 | char src0 = src[0]; | 4338 | char src0 = src[0]; |
| 4361 | int exponent_bytes = 0; | 4339 | int exponent_bytes = 0; |
| 4362 | bool signedp = src0 == '-' || src0 == '+' || src0 == ' '; | 4340 | bool signedp = src0 == '-' || src0 == '+' || src0 == ' '; |
| 4363 | int significand_bytes; | ||
| 4364 | if (zero_flag | 4341 | if (zero_flag |
| 4365 | && ((src[signedp] >= '0' && src[signedp] <= '9') | 4342 | && ((src[signedp] >= '0' && src[signedp] <= '9') |
| 4366 | || (src[signedp] >= 'a' && src[signedp] <= 'f') | 4343 | || (src[signedp] >= 'a' && src[signedp] <= 'f') |
| @@ -4390,7 +4367,8 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4390 | p += signedp; | 4367 | p += signedp; |
| 4391 | memset (p, '0', leading_zeros); | 4368 | memset (p, '0', leading_zeros); |
| 4392 | p += leading_zeros; | 4369 | p += leading_zeros; |
| 4393 | significand_bytes = sprintf_bytes - signedp - exponent_bytes; | 4370 | int significand_bytes |
| 4371 | = sprintf_bytes - signedp - exponent_bytes; | ||
| 4394 | memcpy (p, src, significand_bytes); | 4372 | memcpy (p, src, significand_bytes); |
| 4395 | p += significand_bytes; | 4373 | p += significand_bytes; |
| 4396 | src += significand_bytes; | 4374 | src += significand_bytes; |
| @@ -4460,7 +4438,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4460 | if (p > buf | 4438 | if (p > buf |
| 4461 | && !ASCII_CHAR_P (*((unsigned char *) p - 1)) | 4439 | && !ASCII_CHAR_P (*((unsigned char *) p - 1)) |
| 4462 | && !CHAR_HEAD_P (format_char)) | 4440 | && !CHAR_HEAD_P (format_char)) |
| 4463 | maybe_combine_byte = 1; | 4441 | maybe_combine_byte = true; |
| 4464 | 4442 | ||
| 4465 | while (! CHAR_HEAD_P (*format)) | 4443 | while (! CHAR_HEAD_P (*format)) |
| 4466 | format++; | 4444 | format++; |
| @@ -4490,31 +4468,28 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4490 | /* There wasn't enough room to store this conversion or single | 4468 | /* There wasn't enough room to store this conversion or single |
| 4491 | character. CONVBYTES says how much room is needed. Allocate | 4469 | character. CONVBYTES says how much room is needed. Allocate |
| 4492 | enough room (and then some) and do it again. */ | 4470 | enough room (and then some) and do it again. */ |
| 4493 | { | ||
| 4494 | ptrdiff_t used = p - buf; | ||
| 4495 | |||
| 4496 | if (max_bufsize - used < convbytes) | ||
| 4497 | string_overflow (); | ||
| 4498 | bufsize = used + convbytes; | ||
| 4499 | bufsize = bufsize < max_bufsize / 2 ? bufsize * 2 : max_bufsize; | ||
| 4500 | 4471 | ||
| 4501 | if (buf == initial_buffer) | 4472 | ptrdiff_t used = p - buf; |
| 4502 | { | 4473 | if (max_bufsize - used < convbytes) |
| 4503 | buf = xmalloc (bufsize); | 4474 | string_overflow (); |
| 4504 | sa_must_free = true; | 4475 | bufsize = used + convbytes; |
| 4505 | buf_save_value_index = SPECPDL_INDEX (); | 4476 | bufsize = bufsize < max_bufsize / 2 ? bufsize * 2 : max_bufsize; |
| 4506 | record_unwind_protect_ptr (xfree, buf); | ||
| 4507 | memcpy (buf, initial_buffer, used); | ||
| 4508 | } | ||
| 4509 | else | ||
| 4510 | { | ||
| 4511 | buf = xrealloc (buf, bufsize); | ||
| 4512 | set_unwind_protect_ptr (buf_save_value_index, xfree, buf); | ||
| 4513 | } | ||
| 4514 | 4477 | ||
| 4515 | p = buf + used; | 4478 | if (buf == initial_buffer) |
| 4516 | } | 4479 | { |
| 4480 | buf = xmalloc (bufsize); | ||
| 4481 | sa_must_free = true; | ||
| 4482 | buf_save_value_index = SPECPDL_INDEX (); | ||
| 4483 | record_unwind_protect_ptr (xfree, buf); | ||
| 4484 | memcpy (buf, initial_buffer, used); | ||
| 4485 | } | ||
| 4486 | else | ||
| 4487 | { | ||
| 4488 | buf = xrealloc (buf, bufsize); | ||
| 4489 | set_unwind_protect_ptr (buf_save_value_index, xfree, buf); | ||
| 4490 | } | ||
| 4517 | 4491 | ||
| 4492 | p = buf + used; | ||
| 4518 | format = format0; | 4493 | format = format0; |
| 4519 | n = n0; | 4494 | n = n0; |
| 4520 | } | 4495 | } |
| @@ -4524,7 +4499,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4524 | 4499 | ||
| 4525 | if (maybe_combine_byte) | 4500 | if (maybe_combine_byte) |
| 4526 | nchars = multibyte_chars_in_text ((unsigned char *) buf, p - buf); | 4501 | nchars = multibyte_chars_in_text ((unsigned char *) buf, p - buf); |
| 4527 | val = make_specified_string (buf, nchars, p - buf, multibyte); | 4502 | Lisp_Object val = make_specified_string (buf, nchars, p - buf, multibyte); |
| 4528 | 4503 | ||
| 4529 | /* If the format string has text properties, or any of the string | 4504 | /* If the format string has text properties, or any of the string |
| 4530 | arguments has text properties, set up text properties of the | 4505 | arguments has text properties, set up text properties of the |
| @@ -4532,17 +4507,14 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4532 | 4507 | ||
| 4533 | if (string_intervals (args[0]) || arg_intervals) | 4508 | if (string_intervals (args[0]) || arg_intervals) |
| 4534 | { | 4509 | { |
| 4535 | Lisp_Object len, new_len, props; | ||
| 4536 | |||
| 4537 | /* Add text properties from the format string. */ | 4510 | /* Add text properties from the format string. */ |
| 4538 | len = make_number (SCHARS (args[0])); | 4511 | Lisp_Object len = make_number (SCHARS (args[0])); |
| 4539 | props = text_property_list (args[0], make_number (0), len, Qnil); | 4512 | Lisp_Object props = text_property_list (args[0], make_number (0), |
| 4540 | 4513 | len, Qnil); | |
| 4541 | if (CONSP (props)) | 4514 | if (CONSP (props)) |
| 4542 | { | 4515 | { |
| 4543 | ptrdiff_t bytepos = 0, position = 0, translated = 0; | 4516 | ptrdiff_t bytepos = 0, position = 0, translated = 0; |
| 4544 | ptrdiff_t argn = 1; | 4517 | ptrdiff_t argn = 1; |
| 4545 | Lisp_Object list; | ||
| 4546 | 4518 | ||
| 4547 | /* Adjust the bounds of each text property | 4519 | /* Adjust the bounds of each text property |
| 4548 | to the proper start and end in the output string. */ | 4520 | to the proper start and end in the output string. */ |
| @@ -4556,15 +4528,12 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4556 | POSITION is the untranslated char position in it, | 4528 | POSITION is the untranslated char position in it, |
| 4557 | TRANSLATED is the translated char position in BUF, | 4529 | TRANSLATED is the translated char position in BUF, |
| 4558 | and ARGN is the number of the next arg we will come to. */ | 4530 | and ARGN is the number of the next arg we will come to. */ |
| 4559 | for (list = props; CONSP (list); list = XCDR (list)) | 4531 | for (Lisp_Object list = props; CONSP (list); list = XCDR (list)) |
| 4560 | { | 4532 | { |
| 4561 | Lisp_Object item; | 4533 | Lisp_Object item = XCAR (list); |
| 4562 | ptrdiff_t pos; | ||
| 4563 | |||
| 4564 | item = XCAR (list); | ||
| 4565 | 4534 | ||
| 4566 | /* First adjust the property start position. */ | 4535 | /* First adjust the property start position. */ |
| 4567 | pos = XINT (XCAR (item)); | 4536 | ptrdiff_t pos = XINT (XCAR (item)); |
| 4568 | 4537 | ||
| 4569 | /* Advance BYTEPOS, POSITION, TRANSLATED and ARGN | 4538 | /* Advance BYTEPOS, POSITION, TRANSLATED and ARGN |
| 4570 | up to this position. */ | 4539 | up to this position. */ |
| @@ -4611,19 +4580,19 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4611 | 4580 | ||
| 4612 | /* Add text properties from arguments. */ | 4581 | /* Add text properties from arguments. */ |
| 4613 | if (arg_intervals) | 4582 | if (arg_intervals) |
| 4614 | for (n = 1; n < nargs; ++n) | 4583 | for (ptrdiff_t i = 1; i < nargs; i++) |
| 4615 | if (info[n].intervals) | 4584 | if (info[i].intervals) |
| 4616 | { | 4585 | { |
| 4617 | len = make_number (SCHARS (args[n])); | 4586 | len = make_number (SCHARS (args[i])); |
| 4618 | new_len = make_number (info[n].end - info[n].start); | 4587 | Lisp_Object new_len = make_number (info[i].end - info[i].start); |
| 4619 | props = text_property_list (args[n], make_number (0), len, Qnil); | 4588 | props = text_property_list (args[i], make_number (0), len, Qnil); |
| 4620 | props = extend_property_ranges (props, new_len); | 4589 | props = extend_property_ranges (props, new_len); |
| 4621 | /* If successive arguments have properties, be sure that | 4590 | /* If successive arguments have properties, be sure that |
| 4622 | the value of `composition' property be the copy. */ | 4591 | the value of `composition' property be the copy. */ |
| 4623 | if (n > 1 && info[n - 1].end) | 4592 | if (1 < i && info[i - 1].end) |
| 4624 | make_composition_value_copy (props); | 4593 | make_composition_value_copy (props); |
| 4625 | add_text_properties_from_list (val, props, | 4594 | add_text_properties_from_list (val, props, |
| 4626 | make_number (info[n].start)); | 4595 | make_number (info[i].start)); |
| 4627 | } | 4596 | } |
| 4628 | } | 4597 | } |
| 4629 | 4598 | ||