aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPhilipp Stephani2017-06-01 00:09:43 +0200
committerPhilipp Stephani2017-06-02 00:22:13 +0200
commit0dd1bbb0bb228acab21b8e16f2f2a0b5a17b19ab (patch)
tree279fbd070724c1d04945b69db32eb69957274e72 /src
parent404273aeacba39833ae3a38ce6764cc7a636e9d9 (diff)
downloademacs-0dd1bbb0bb228acab21b8e16f2f2a0b5a17b19ab.tar.gz
emacs-0dd1bbb0bb228acab21b8e16f2f2a0b5a17b19ab.zip
Implement field numbers in format strings
A field number explicitly specifies the argument to be formatted. This is especially important for potential localization work, since grammars of various languages dictate different word orders. * src/editfns.c (Fformat): Update documentation. (styled_format): Implement field numbers. * doc/lispref/strings.texi (Formatting Strings): Document field numbers. * lisp/emacs-lisp/bytecomp.el (byte-compile-format-warn): Adapt. * test/src/editfns-tests.el (format-with-field): New unit test.
Diffstat (limited to 'src')
-rw-r--r--src/editfns.c55
1 files changed, 47 insertions, 8 deletions
diff --git a/src/editfns.c b/src/editfns.c
index 89a67241044..44341cef2d3 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -48,6 +48,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
48#include <float.h> 48#include <float.h>
49#include <limits.h> 49#include <limits.h>
50 50
51#include <c-ctype.h>
51#include <intprops.h> 52#include <intprops.h>
52#include <stdlib.h> 53#include <stdlib.h>
53#include <strftime.h> 54#include <strftime.h>
@@ -3856,7 +3857,7 @@ The first argument is a format control string.
3856The other arguments are substituted into it to make the result, a string. 3857The other arguments are substituted into it to make the result, a string.
3857 3858
3858The format control string may contain %-sequences meaning to substitute 3859The format control string may contain %-sequences meaning to substitute
3859the next available argument: 3860the next available argument, or the argument explicitly specified:
3860 3861
3861%s means print a string argument. Actually, prints any object, with `princ'. 3862%s means print a string argument. Actually, prints any object, with `princ'.
3862%d means print as signed number in decimal. 3863%d means print as signed number in decimal.
@@ -3873,13 +3874,17 @@ the next available argument:
3873The argument used for %d, %o, %x, %e, %f, %g or %c must be a number. 3874The argument used for %d, %o, %x, %e, %f, %g or %c must be a number.
3874Use %% to put a single % into the output. 3875Use %% to put a single % into the output.
3875 3876
3876A %-sequence may contain optional flag, width, and precision 3877A %-sequence may contain optional field number, flag, width, and
3877specifiers, as follows: 3878precision specifiers, as follows:
3878 3879
3879 %<flags><width><precision>character 3880 %<field><flags><width><precision>character
3880 3881
3881where flags is [+ #-0]+, width is [0-9]+, and precision is a literal 3882where field is [0-9]+ followed by a literal dollar "$", flags is
3882period "." followed by [0-9]+ 3883[+ #-0]+, width is [0-9]+, and precision is a literal period "."
3884followed by [0-9]+.
3885
3886If field is given, it must be a one-based argument number; the given
3887argument is substituted instead of the next one.
3883 3888
3884The + flag character inserts a + before any positive number, while a 3889The + flag character inserts a + before any positive number, while a
3885space inserts a space before any positive number; these flags only 3890space inserts a space before any positive number; these flags only
@@ -4032,14 +4037,19 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4032 { 4037 {
4033 /* General format specifications look like 4038 /* General format specifications look like
4034 4039
4035 '%' [flags] [field-width] [precision] format 4040 '%' [field-number] [flags] [field-width] [precision] format
4036 4041
4037 where 4042 where
4038 4043
4044 field-number ::= [0-9]+ '$'
4039 flags ::= [-+0# ]+ 4045 flags ::= [-+0# ]+
4040 field-width ::= [0-9]+ 4046 field-width ::= [0-9]+
4041 precision ::= '.' [0-9]* 4047 precision ::= '.' [0-9]*
4042 4048
4049 If a field-number is specified, it specifies the argument
4050 number to substitute. Otherwise, the next argument is
4051 taken.
4052
4043 If a field-width is specified, it specifies to which width 4053 If a field-width is specified, it specifies to which width
4044 the output should be padded with blanks, if the output 4054 the output should be padded with blanks, if the output
4045 string is shorter than field-width. 4055 string is shorter than field-width.
@@ -4048,6 +4058,29 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4048 digits to print after the '.' for floats, or the max. 4058 digits to print after the '.' for floats, or the max.
4049 number of chars to print from a string. */ 4059 number of chars to print from a string. */
4050 4060
4061 char *field_end;
4062 uintmax_t raw_field = strtoumax (format, &field_end, 10);
4063 bool has_field = false;
4064 if (c_isdigit (*format) && *field_end == '$')
4065 {
4066 if (raw_field < 1 || raw_field >= PTRDIFF_MAX)
4067 {
4068 /* doprnt doesn't support %.*s, so we need to copy
4069 the field number string. */
4070 ptrdiff_t length = field_end - format;
4071 eassert (length > 0);
4072 eassert (length < PTRDIFF_MAX);
4073 char *field = SAFE_ALLOCA (length + 1);
4074 memcpy (field, format, length);
4075 field[length] = '\0';
4076 error ("Invalid field number `%s'", field);
4077 }
4078 has_field = true;
4079 /* n is incremented below. */
4080 n = raw_field - 1;
4081 format = field_end + 1;
4082 }
4083
4051 bool minus_flag = false; 4084 bool minus_flag = false;
4052 bool plus_flag = false; 4085 bool plus_flag = false;
4053 bool space_flag = false; 4086 bool space_flag = false;
@@ -4090,7 +4123,13 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4090 memset (&discarded[format0 - format_start], 1, 4123 memset (&discarded[format0 - format_start], 1,
4091 format - format0 - (conversion == '%')); 4124 format - format0 - (conversion == '%'));
4092 if (conversion == '%') 4125 if (conversion == '%')
4093 goto copy_char; 4126 {
4127 if (has_field)
4128 /* FIXME: `error' doesn't appear to support `%%'. */
4129 error ("Field number specified together with `%c' conversion",
4130 '%');
4131 goto copy_char;
4132 }
4094 4133
4095 ++n; 4134 ++n;
4096 if (! (n < nargs)) 4135 if (! (n < nargs))