diff options
| author | Paul Eggert | 2017-06-01 16:03:12 -0700 |
|---|---|---|
| committer | Paul Eggert | 2017-06-01 16:06:38 -0700 |
| commit | 8de2581a64dac3785fc3877f7cd87c4164fd2936 (patch) | |
| tree | af8885c43a57dee86b17c05118a78d6f1d0361ac | |
| parent | 178d0cb5f530e6d7eb36eb9987ff405c854ccdb3 (diff) | |
| download | emacs-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.texi | 13 | ||||
| -rw-r--r-- | src/editfns.c | 8 | ||||
| -rw-r--r-- | test/src/editfns-tests.el | 28 |
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. | |||
| 965 | decimal number immediately after the initial @samp{%}, followed by a | 965 | decimal number immediately after the initial @samp{%}, followed by a |
| 966 | literal dollar sign @samp{$}. It causes the format specification to | 966 | literal dollar sign @samp{$}. It causes the format specification to |
| 967 | convert the argument with the given number instead of the next | 967 | convert the argument with the given number instead of the next |
| 968 | argument. Argument 1 is the argument just after the format. | 968 | argument. Field numbers start at 1. A format can contain either |
| 969 | 969 | numbered 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. |
| 971 | specification without a field number that follows a specification with | ||
| 972 | a field number will convert the argument after the one specified by | ||
| 973 | the 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 "." |
| 3901 | followed by [0-9]+. | 3901 | followed by [0-9]+. |
| 3902 | 3902 | ||
| 3903 | If field is given, it must be a one-based argument number; the given | 3903 | If a %-sequence is numbered with a field with positive value N, the |
| 3904 | argument is substituted instead of the next one. | 3904 | Nth argument is substituted instead of the next one. A format can |
| 3905 | contain either numbered or unnumbered %-sequences but not both, except | ||
| 3906 | that %% can be mixed with numbered %-sequences. | ||
| 3905 | 3907 | ||
| 3906 | The + flag character inserts a + before any positive number, while a | 3908 | The + flag character inserts a + before any positive number, while a |
| 3907 | space inserts a space before any positive number; these flags only | 3909 | space 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 |