aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2017-06-01 16:03:12 -0700
committerPaul Eggert2017-06-01 16:06:38 -0700
commit8de2581a64dac3785fc3877f7cd87c4164fd2936 (patch)
treeaf8885c43a57dee86b17c05118a78d6f1d0361ac
parent178d0cb5f530e6d7eb36eb9987ff405c854ccdb3 (diff)
downloademacs-8de2581a64dac3785fc3877f7cd87c4164fd2936.tar.gz
emacs-8de2581a64dac3785fc3877f7cd87c4164fd2936.zip
Limit format fields to more POSIX-like spec
* doc/lispref/strings.texi (Formatting Strings): Don’t allow mixing numbered with unnumbered format specs. * src/editfns.c (styled_format): Don’t bother checking for field 0, since it doesn’t crash and the behavior is not specified. * test/src/editfns-tests.el (format-with-field): Adjust tests to match current doc. Add more tests for out-of-range fields.
-rw-r--r--doc/lispref/strings.texi13
-rw-r--r--src/editfns.c8
-rw-r--r--test/src/editfns-tests.el28
3 files changed, 31 insertions, 18 deletions
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi
index 4d33e55b018..e80e778bece 100644
--- a/doc/lispref/strings.texi
+++ b/doc/lispref/strings.texi
@@ -965,16 +965,13 @@ extra values to be formatted are ignored.
965decimal number immediately after the initial @samp{%}, followed by a 965decimal number immediately after the initial @samp{%}, followed by a
966literal dollar sign @samp{$}. It causes the format specification to 966literal dollar sign @samp{$}. It causes the format specification to
967convert the argument with the given number instead of the next 967convert the argument with the given number instead of the next
968argument. Argument 1 is the argument just after the format. 968argument. Field numbers start at 1. A format can contain either
969 969numbered or unnumbered format specifications but not both, except that
970 You can mix specifications with and without field numbers. A 970@samp{%%} can be mixed with numbered specifications.
971specification without a field number that follows a specification with
972a field number will convert the argument after the one specified by
973the field number:
974 971
975@example 972@example
976(format "Argument %2$s, then %s, then %1$s" "x" "y" "z") 973(format "%2$s, %3$s, %%, %1$s" "x" "y" "z")
977 @result{} "Argument y, then z, then x" 974 @result{} "y, z, %, x"
978@end example 975@end example
979 976
980@cindex flags in format specifications 977@cindex flags in format specifications
diff --git a/src/editfns.c b/src/editfns.c
index 1dbae8f5d4b..29af25aab4f 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -3900,8 +3900,10 @@ where field is [0-9]+ followed by a literal dollar "$", flags is
3900[+ #-0]+, width is [0-9]+, and precision is a literal period "." 3900[+ #-0]+, width is [0-9]+, and precision is a literal period "."
3901followed by [0-9]+. 3901followed by [0-9]+.
3902 3902
3903If field is given, it must be a one-based argument number; the given 3903If a %-sequence is numbered with a field with positive value N, the
3904argument is substituted instead of the next one. 3904Nth argument is substituted instead of the next one. A format can
3905contain either numbered or unnumbered %-sequences but not both, except
3906that %% can be mixed with numbered %-sequences.
3905 3907
3906The + flag character inserts a + before any positive number, while a 3908The + flag character inserts a + before any positive number, while a
3907space inserts a space before any positive number; these flags only 3909space inserts a space before any positive number; these flags only
@@ -4081,8 +4083,6 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4081 num = str2num (format, &num_end); 4083 num = str2num (format, &num_end);
4082 if (*num_end == '$') 4084 if (*num_end == '$')
4083 { 4085 {
4084 if (num == 0)
4085 error ("Invalid format field number 0");
4086 n = num - 1; 4086 n = num - 1;
4087 format = num_end + 1; 4087 format = num_end + 1;
4088 } 4088 }
diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el
index c5923aaafb1..54fb743e192 100644
--- a/test/src/editfns-tests.el
+++ b/test/src/editfns-tests.el
@@ -178,17 +178,33 @@
178 (concat (make-string 2048 ?X) "0"))))) 178 (concat (make-string 2048 ?X) "0")))))
179 179
180(ert-deftest format-with-field () 180(ert-deftest format-with-field ()
181 (should (equal (format "First argument %2$s, then %s, then %1$s" 1 2 3) 181 (should (equal (format "First argument %2$s, then %3$s, then %1$s" 1 2 3)
182 "First argument 2, then 3, then 1")) 182 "First argument 2, then 3, then 1"))
183 (should (equal (format "a %2$s %d %1$d %2$S %d %d b" 11 "22" 33 44) 183 (should (equal (format "a %2$s %3$d %1$d %2$S %3$d %4$d b" 11 "22" 33 44)
184 "a 22 33 11 \"22\" 33 44 b")) 184 "a 22 33 11 \"22\" 33 44 b"))
185 (should (equal (format "a %08$s %s b" 1 2 3 4 5 6 7 8 9) "a 8 9 b")) 185 (should (equal (format "a %08$s %0000000000000000009$s b" 1 2 3 4 5 6 7 8 9)
186 "a 8 9 b"))
186 (should (equal (should-error (format "a %999999$s b" 11)) 187 (should (equal (should-error (format "a %999999$s b" 11))
187 '(error "Not enough arguments for format string"))) 188 '(error "Not enough arguments for format string")))
189 (should (equal (should-error (format "a %2147483647$s b"))
190 '(error "Not enough arguments for format string")))
191 (should (equal (should-error (format "a %9223372036854775807$s b"))
192 '(error "Not enough arguments for format string")))
193 (should (equal (should-error (format "a %9223372036854775808$s b"))
194 '(error "Not enough arguments for format string")))
195 (should (equal (should-error (format "a %18446744073709551615$s b"))
196 '(error "Not enough arguments for format string")))
197 (should (equal (should-error (format "a %18446744073709551616$s b"))
198 '(error "Not enough arguments for format string")))
199 (should (equal (should-error
200 (format (format "a %%%d$d b" most-positive-fixnum)))
201 '(error "Not enough arguments for format string")))
202 (should (equal (should-error
203 (format (format "a %%%d$d b" (+ 1.0 most-positive-fixnum))))
204 '(error "Not enough arguments for format string")))
188 (should (equal (should-error (format "a %$s b" 11)) 205 (should (equal (should-error (format "a %$s b" 11))
189 '(error "Invalid format operation %$"))) 206 '(error "Invalid format operation %$")))
190 (should (equal (should-error (format "a %0$s b" 11)) 207 (should (equal (should-error (format "a %-1$s b" 11))
191 '(error "Invalid format field number 0"))) 208 '(error "Invalid format operation %$"))))
192 (should (equal (format "a %1$% %s b" 11) "a % 11 b")))
193 209
194;;; editfns-tests.el ends here 210;;; editfns-tests.el ends here