1 /* printf - format and print data
2 Copyright (C) 1990-2022 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Usage: printf format [argument...]
19 A front end to the printf function that lets it be used from the shell.
27 \c = produce no further output
34 \ooo = octal number (ooo is 1 to 3 digits)
35 \xhh = hexadecimal number (hhh is 1 to 2 digits)
36 \uhhhh = 16-bit Unicode character (hhhh is 4 digits)
37 \Uhhhhhhhh = 32-bit Unicode character (hhhhhhhh is 8 digits)
41 %b = print an argument string, interpreting backslash escapes,
42 except that octal escapes are of the form \0 or \0ooo.
44 %q = print an argument string in a format that can be
45 reused as shell input. Escaped characters used the proposed
46 POSIX $'' syntax supported by most shells.
48 The 'format' argument is re-used as many times as necessary
49 to convert all of the given arguments.
51 David MacKenzie <djm@gnu.ai.mit.edu> */
55 #include <sys/types.h>
58 #include "cl-strtod.h"
62 #include "unicodeio.h"
65 /* The official name of this program (e.g., no 'g' prefix). */
66 #define PROGRAM_NAME "printf"
68 #define AUTHORS proper_name ("David MacKenzie")
70 #define isodigit(c) ((c) >= '0' && (c) <= '7')
71 #define hextobin(c) ((c) >= 'a' && (c) <= 'f' ? (c) - 'a' + 10 : \
72 (c) >= 'A' && (c) <= 'F' ? (c) - 'A' + 10 : (c) - '0')
73 #define octtobin(c) ((c) - '0')
75 /* The value to return to the calling program. */
76 static int exit_status
;
78 /* True if the POSIXLY_CORRECT environment variable is set. */
79 static bool posixly_correct
;
81 /* This message appears in N_() here rather than just in _() below because
82 the sole use would have been in a #define. */
83 static char const *const cfcc_msg
=
84 N_("warning: %s: character(s) following character constant have been ignored");
89 if (status
!= EXIT_SUCCESS
)
94 Usage: %s FORMAT [ARGUMENT]...\n\
97 program_name
, program_name
);
99 Print ARGUMENT(s) according to FORMAT, or execute according to OPTION:\n\
102 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
103 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
106 FORMAT controls the output as in C printf. Interpreted sequences are:\n\
114 \\c produce no further output\n\
118 \\r carriage return\n\
119 \\t horizontal tab\n\
123 \\NNN byte with octal value NNN (1 to 3 digits)\n\
124 \\xHH byte with hexadecimal value HH (1 to 2 digits)\n\
125 \\uHHHH Unicode (ISO/IEC 10646) character with hex value HHHH (4 digits)\n\
126 \\UHHHHHHHH Unicode character with hex value HHHHHHHH (8 digits)\n\
130 %b ARGUMENT as a string with '\\' escapes interpreted,\n\
131 except that octal escapes are of the form \\0 or \\0NNN\n\
132 %q ARGUMENT is printed in a format that can be reused as shell input,\n\
133 escaping non-printable characters with the proposed POSIX $'' syntax.\
135 and all C format specifications ending with one of diouxXfeEgGcs, with\n\
136 ARGUMENTs converted to proper type first. Variable widths are handled.\n\
138 printf (USAGE_BUILTIN_WARNING
, PROGRAM_NAME
);
139 emit_ancillary_info (PROGRAM_NAME
);
145 verify_numeric (char const *s
, char const *end
)
149 error (0, errno
, "%s", quote (s
));
150 exit_status
= EXIT_FAILURE
;
155 error (0, 0, _("%s: expected a numeric value"), quote (s
));
157 error (0, 0, _("%s: value not completely converted"), quote (s
));
158 exit_status
= EXIT_FAILURE
;
162 #define STRTOX(TYPE, FUNC_NAME, LIB_FUNC_EXPR) \
164 FUNC_NAME (char const *s) \
169 if ((*s == '\"' || *s == '\'') && *(s + 1)) \
171 unsigned char ch = *++s; \
173 /* If POSIXLY_CORRECT is not set, then give a warning that there \
174 are characters following the character constant and that GNU \
175 printf is ignoring those characters. If POSIXLY_CORRECT *is* \
176 set, then don't give the warning. */ \
177 if (*++s != 0 && !posixly_correct) \
178 error (0, 0, _(cfcc_msg), s); \
183 val = (LIB_FUNC_EXPR); \
184 verify_numeric (s, end); \
189 STRTOX (intmax_t, vstrtoimax, strtoimax (s, &end, 0))
190 STRTOX (uintmax_t, vstrtoumax
, strtoumax (s
, &end
, 0))
191 STRTOX (long double, vstrtold
, cl_strtold (s
, &end
))
193 /* Output a single-character \ escape. */
196 print_esc_char (char c
)
200 case 'a': /* Alert. */
203 case 'b': /* Backspace. */
206 case 'c': /* Cancel the rest of the output. */
209 case 'e': /* Escape. */
212 case 'f': /* Form feed. */
215 case 'n': /* New line. */
218 case 'r': /* Carriage return. */
221 case 't': /* Horizontal tab. */
224 case 'v': /* Vertical tab. */
233 /* Print a \ escape sequence starting at ESCSTART.
234 Return the number of characters in the escape sequence
235 besides the backslash.
236 If OCTAL_0 is nonzero, octal escapes are of the form \0ooo, where o
237 is an octal digit; otherwise they are of the form \ooo. */
240 print_esc (char const *escstart
, bool octal_0
)
242 char const *p
= escstart
+ 1;
243 int esc_value
= 0; /* Value of \nnn escape. */
244 int esc_length
; /* Length of \nnn escape. */
248 /* A hexadecimal \xhh escape sequence must have 1 or 2 hex. digits. */
249 for (esc_length
= 0, ++p
;
250 esc_length
< 2 && isxdigit (to_uchar (*p
));
252 esc_value
= esc_value
* 16 + hextobin (*p
);
254 die (EXIT_FAILURE
, 0, _("missing hexadecimal number in escape"));
257 else if (isodigit (*p
))
259 /* Parse \0ooo (if octal_0 && *p == '0') or \ooo (otherwise).
260 Allow \ooo if octal_0 && *p != '0'; this is an undocumented
261 extension to POSIX that is compatible with Bash 2.05b. */
262 for (esc_length
= 0, p
+= octal_0
&& *p
== '0';
263 esc_length
< 3 && isodigit (*p
);
265 esc_value
= esc_value
* 8 + octtobin (*p
);
268 else if (*p
&& strchr ("\"\\abcefnrtv", *p
))
269 print_esc_char (*p
++);
270 else if (*p
== 'u' || *p
== 'U')
273 unsigned int uni_value
;
276 for (esc_length
= (esc_char
== 'u' ? 4 : 8), ++p
;
280 if (! isxdigit (to_uchar (*p
)))
281 die (EXIT_FAILURE
, 0, _("missing hexadecimal number in escape"));
282 uni_value
= uni_value
* 16 + hextobin (*p
);
285 /* A universal character name shall not specify a character short
286 identifier in the range 00000000 through 00000020, 0000007F through
287 0000009F, or 0000D800 through 0000DFFF inclusive. A universal
288 character name shall not designate a character in the required
290 if ((uni_value
<= 0x9f
291 && uni_value
!= 0x24 && uni_value
!= 0x40 && uni_value
!= 0x60)
292 || (uni_value
>= 0xd800 && uni_value
<= 0xdfff))
293 die (EXIT_FAILURE
, 0, _("invalid universal character name \\%c%0*x"),
294 esc_char
, (esc_char
== 'u' ? 4 : 8), uni_value
);
296 print_unicode_char (stdout
, uni_value
, 0);
307 return p
- escstart
- 1;
310 /* Print string STR, evaluating \ escapes. */
313 print_esc_string (char const *str
)
317 str
+= print_esc (str
, true);
322 /* Evaluate a printf conversion specification. START is the start of
323 the directive, LENGTH is its length, and CONVERSION specifies the
324 type of conversion. LENGTH does not include any length modifier or
325 the conversion specifier itself. FIELD_WIDTH and PRECISION are the
326 field width and precision for '*' values, if HAVE_FIELD_WIDTH and
327 HAVE_PRECISION are true, respectively. ARGUMENT is the argument to
331 print_direc (char const *start
, size_t length
, char conversion
,
332 bool have_field_width
, int field_width
,
333 bool have_precision
, int precision
,
334 char const *argument
)
336 char *p
; /* Null-terminated copy of % directive. */
338 /* Create a null-terminated copy of the % directive, with an
339 intmax_t-wide length modifier substituted for any existing
340 integer length modifier. */
343 char const *length_modifier
;
344 size_t length_modifier_len
;
348 case 'd': case 'i': case 'o': case 'u': case 'x': case 'X':
349 length_modifier
= PRIdMAX
;
350 length_modifier_len
= sizeof PRIdMAX
- 2;
353 case 'a': case 'e': case 'f': case 'g':
354 case 'A': case 'E': case 'F': case 'G':
355 length_modifier
= "L";
356 length_modifier_len
= 1;
360 length_modifier
= start
; /* Any valid pointer will do. */
361 length_modifier_len
= 0;
365 p
= xmalloc (length
+ length_modifier_len
+ 2);
366 q
= mempcpy (p
, start
, length
);
367 q
= mempcpy (q
, length_modifier
, length_modifier_len
);
377 intmax_t arg
= vstrtoimax (argument
);
378 if (!have_field_width
)
383 xprintf (p
, precision
, arg
);
388 xprintf (p
, field_width
, arg
);
390 xprintf (p
, field_width
, precision
, arg
);
400 uintmax_t arg
= vstrtoumax (argument
);
401 if (!have_field_width
)
406 xprintf (p
, precision
, arg
);
411 xprintf (p
, field_width
, arg
);
413 xprintf (p
, field_width
, precision
, arg
);
427 long double arg
= vstrtold (argument
);
428 if (!have_field_width
)
433 xprintf (p
, precision
, arg
);
438 xprintf (p
, field_width
, arg
);
440 xprintf (p
, field_width
, precision
, arg
);
446 if (!have_field_width
)
447 xprintf (p
, *argument
);
449 xprintf (p
, field_width
, *argument
);
453 if (!have_field_width
)
456 xprintf (p
, argument
);
458 xprintf (p
, precision
, argument
);
463 xprintf (p
, field_width
, argument
);
465 xprintf (p
, field_width
, precision
, argument
);
473 /* Print the text in FORMAT, using ARGV (with ARGC elements) for
474 arguments to any '%' directives.
475 Return the number of elements of ARGV used. */
478 print_formatted (char const *format
, int argc
, char **argv
)
480 int save_argc
= argc
; /* Preserve original value. */
481 char const *f
; /* Pointer into 'format'. */
482 char const *direc_start
; /* Start of % directive. */
483 size_t direc_length
; /* Length of % directive. */
484 bool have_field_width
; /* True if FIELD_WIDTH is valid. */
485 int field_width
= 0; /* Arg to first '*'. */
486 bool have_precision
; /* True if PRECISION is valid. */
487 int precision
= 0; /* Arg to second '*'. */
488 char ok
[UCHAR_MAX
+ 1]; /* ok['x'] is true if %x is allowed. */
490 for (f
= format
; *f
; ++f
)
497 have_field_width
= have_precision
= false;
505 /* FIXME: Field width and precision are not supported
506 for %b, even though POSIX requires it. */
509 print_esc_string (*argv
);
520 fputs (quotearg_style (shell_escape_quoting_style
, *argv
),
528 memset (ok
, 0, sizeof ok
);
529 ok
['a'] = ok
['A'] = ok
['c'] = ok
['d'] = ok
['e'] = ok
['E'] =
530 ok
['f'] = ok
['F'] = ok
['g'] = ok
['G'] = ok
['i'] = ok
['o'] =
531 ok
['s'] = ok
['u'] = ok
['x'] = ok
['X'] = 1;
533 for (;; f
++, direc_length
++)
536 #if (__GLIBC__ == 2 && 2 <= __GLIBC_MINOR__) || 3 <= __GLIBC__
540 ok
['a'] = ok
['A'] = ok
['c'] = ok
['e'] = ok
['E'] =
541 ok
['o'] = ok
['s'] = ok
['x'] = ok
['X'] = 0;
543 case '-': case '+': case ' ':
546 ok
['c'] = ok
['d'] = ok
['i'] = ok
['s'] = ok
['u'] = 0;
549 ok
['c'] = ok
['s'] = 0;
552 goto no_more_flag_characters
;
554 no_more_flag_characters
:
562 intmax_t width
= vstrtoimax (*argv
);
563 if (INT_MIN
<= width
&& width
<= INT_MAX
)
566 die (EXIT_FAILURE
, 0, _("invalid field width: %s"),
573 have_field_width
= true;
592 intmax_t prec
= vstrtoimax (*argv
);
595 /* A negative precision is taken as if the
596 precision were omitted, so -1 is safe
597 here even if prec < INT_MIN. */
600 else if (INT_MAX
< prec
)
601 die (EXIT_FAILURE
, 0, _("invalid precision: %s"),
610 have_precision
= true;
620 while (*f
== 'l' || *f
== 'L' || *f
== 'h'
621 || *f
== 'j' || *f
== 't' || *f
== 'z')
625 unsigned char conversion
= *f
;
626 if (! ok
[conversion
])
627 die (EXIT_FAILURE
, 0,
628 _("%.*s: invalid conversion specification"),
629 (int) (f
+ 1 - direc_start
), direc_start
);
632 print_direc (direc_start
, direc_length
, *f
,
633 have_field_width
, field_width
,
634 have_precision
, precision
,
635 (argc
<= 0 ? "" : (argc
--, *argv
++)));
639 f
+= print_esc (f
, false);
647 return save_argc
- argc
;
651 main (int argc
, char **argv
)
656 initialize_main (&argc
, &argv
);
657 set_program_name (argv
[0]);
658 setlocale (LC_ALL
, "");
659 bindtextdomain (PACKAGE
, LOCALEDIR
);
660 textdomain (PACKAGE
);
662 atexit (close_stdout
);
664 exit_status
= EXIT_SUCCESS
;
666 posixly_correct
= (getenv ("POSIXLY_CORRECT") != NULL
);
668 /* We directly parse options, rather than use parse_long_options, in
669 order to avoid accepting abbreviations. */
672 if (STREQ (argv
[1], "--help"))
673 usage (EXIT_SUCCESS
);
675 if (STREQ (argv
[1], "--version"))
677 version_etc (stdout
, PROGRAM_NAME
, PACKAGE_NAME
, Version
, AUTHORS
,
683 /* The above handles --help and --version.
684 Since there is no other invocation of getopt, handle '--' here. */
685 if (1 < argc
&& STREQ (argv
[1], "--"))
693 error (0, 0, _("missing operand"));
694 usage (EXIT_FAILURE
);
703 args_used
= print_formatted (format
, argc
, argv
);
707 while (args_used
> 0 && argc
> 0);
711 _("warning: ignoring excess arguments, starting with %s"),