aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2015-08-27 08:50:22 -0700
committerPaul Eggert2015-08-27 08:52:02 -0700
commit6dbe056b9beec0b9ff6c84331a49c568408dbbaa (patch)
tree32a6e13fcb20634d9986324e9dc973713cd7be96 /src
parentf33c164123e2bc46c4d06853b1a32130126d54c8 (diff)
downloademacs-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.c237
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