1 /* printf - format and print data
2 Copyright (C) 1990-2023 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>
59 #include "cl-strtod.h"
61 #include "unicodeio.h"
64 /* The official name of this program (e.g., no 'g' prefix). */
65 #define PROGRAM_NAME "printf"
67 #define AUTHORS proper_name ("David MacKenzie")
69 #define isodigit(c) ((c) >= '0' && (c) <= '7')
70 #define hextobin(c) ((c) >= 'a' && (c) <= 'f' ? (c) - 'a' + 10 : \
71 (c) >= 'A' && (c) <= 'F' ? (c) - 'A' + 10 : (c) - '0')
72 #define octtobin(c) ((c) - '0')
74 /* The value to return to the calling program. */
75 static int exit_status
;
77 /* True if the POSIXLY_CORRECT environment variable is set. */
78 static bool posixly_correct
;
80 /* This message appears in N_() here rather than just in _() below because
81 the sole use would have been in a #define. */
82 static char const *const cfcc_msg
=
83 N_("warning: %s: character(s) following character constant have been ignored");
88 if (status
!= EXIT_SUCCESS
)
93 Usage: %s FORMAT [ARGUMENT]...\n\
96 program_name
, program_name
);
98 Print ARGUMENT(s) according to FORMAT, or execute according to OPTION:\n\
101 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
102 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
105 FORMAT controls the output as in C printf. Interpreted sequences are:\n\
113 \\c produce no further output\n\
117 \\r carriage return\n\
118 \\t horizontal tab\n\
122 \\NNN byte with octal value NNN (1 to 3 digits)\n\
123 \\xHH byte with hexadecimal value HH (1 to 2 digits)\n\
124 \\uHHHH Unicode (ISO/IEC 10646) character with hex value HHHH (4 digits)\n\
125 \\UHHHHHHHH Unicode character with hex value HHHHHHHH (8 digits)\n\
129 %b ARGUMENT as a string with '\\' escapes interpreted,\n\
130 except that octal escapes are of the form \\0 or \\0NNN\n\
131 %q ARGUMENT is printed in a format that can be reused as shell input,\n\
132 escaping non-printable characters with the proposed POSIX $'' syntax.\
134 and all C format specifications ending with one of diouxXfeEgGcs, with\n\
135 ARGUMENTs converted to proper type first. Variable widths are handled.\n\
137 printf (USAGE_BUILTIN_WARNING
, PROGRAM_NAME
);
138 emit_ancillary_info (PROGRAM_NAME
);
144 verify_numeric (char const *s
, char const *end
)
148 error (0, errno
, "%s", quote (s
));
149 exit_status
= EXIT_FAILURE
;
154 error (0, 0, _("%s: expected a numeric value"), quote (s
));
156 error (0, 0, _("%s: value not completely converted"), quote (s
));
157 exit_status
= EXIT_FAILURE
;
161 #define STRTOX(TYPE, FUNC_NAME, LIB_FUNC_EXPR) \
163 FUNC_NAME (char const *s) \
168 if ((*s == '\"' || *s == '\'') && *(s + 1)) \
170 unsigned char ch = *++s; \
173 if (MB_CUR_MAX > 1 && *(s + 1)) \
175 mbstate_t mbstate; mbszero (&mbstate); \
177 size_t slen = strlen (s); \
179 bytes = mbrtowc (&wc, s, slen, &mbstate); \
187 /* If POSIXLY_CORRECT is not set, then give a warning that there \
188 are characters following the character constant and that GNU \
189 printf is ignoring those characters. If POSIXLY_CORRECT *is* \
190 set, then don't give the warning. */ \
191 if (*++s != 0 && !posixly_correct) \
192 error (0, 0, _(cfcc_msg), s); \
197 val = (LIB_FUNC_EXPR); \
198 verify_numeric (s, end); \
203 STRTOX (intmax_t, vstrtoimax, strtoimax (s, &end, 0))
204 STRTOX (uintmax_t, vstrtoumax
, strtoumax (s
, &end
, 0))
205 STRTOX (long double, vstrtold
, cl_strtold (s
, &end
))
207 /* Output a single-character \ escape. */
210 print_esc_char (char c
)
214 case 'a': /* Alert. */
217 case 'b': /* Backspace. */
220 case 'c': /* Cancel the rest of the output. */
223 case 'e': /* Escape. */
226 case 'f': /* Form feed. */
229 case 'n': /* New line. */
232 case 'r': /* Carriage return. */
235 case 't': /* Horizontal tab. */
238 case 'v': /* Vertical tab. */
247 /* Print a \ escape sequence starting at ESCSTART.
248 Return the number of characters in the escape sequence
249 besides the backslash.
250 If OCTAL_0 is nonzero, octal escapes are of the form \0ooo, where o
251 is an octal digit; otherwise they are of the form \ooo. */
254 print_esc (char const *escstart
, bool octal_0
)
256 char const *p
= escstart
+ 1;
257 int esc_value
= 0; /* Value of \nnn escape. */
258 int esc_length
; /* Length of \nnn escape. */
262 /* A hexadecimal \xhh escape sequence must have 1 or 2 hex. digits. */
263 for (esc_length
= 0, ++p
;
264 esc_length
< 2 && isxdigit (to_uchar (*p
));
266 esc_value
= esc_value
* 16 + hextobin (*p
);
268 error (EXIT_FAILURE
, 0, _("missing hexadecimal number in escape"));
271 else if (isodigit (*p
))
273 /* Parse \0ooo (if octal_0 && *p == '0') or \ooo (otherwise).
274 Allow \ooo if octal_0 && *p != '0'; this is an undocumented
275 extension to POSIX that is compatible with Bash 2.05b. */
276 for (esc_length
= 0, p
+= octal_0
&& *p
== '0';
277 esc_length
< 3 && isodigit (*p
);
279 esc_value
= esc_value
* 8 + octtobin (*p
);
282 else if (*p
&& strchr ("\"\\abcefnrtv", *p
))
283 print_esc_char (*p
++);
284 else if (*p
== 'u' || *p
== 'U')
287 unsigned int uni_value
;
290 for (esc_length
= (esc_char
== 'u' ? 4 : 8), ++p
;
294 if (! isxdigit (to_uchar (*p
)))
295 error (EXIT_FAILURE
, 0, _("missing hexadecimal number in escape"));
296 uni_value
= uni_value
* 16 + hextobin (*p
);
299 /* Error for invalid code points 0000D800 through 0000DFFF inclusive.
300 Note print_unicode_char() would print the literal \u.. in this case. */
301 if (uni_value
>= 0xd800 && uni_value
<= 0xdfff)
302 error (EXIT_FAILURE
, 0, _("invalid universal character name \\%c%0*x"),
303 esc_char
, (esc_char
== 'u' ? 4 : 8), uni_value
);
305 print_unicode_char (stdout
, uni_value
, 0);
316 return p
- escstart
- 1;
319 /* Print string STR, evaluating \ escapes. */
322 print_esc_string (char const *str
)
326 str
+= print_esc (str
, true);
331 /* Evaluate a printf conversion specification. START is the start of
332 the directive, LENGTH is its length, and CONVERSION specifies the
333 type of conversion. LENGTH does not include any length modifier or
334 the conversion specifier itself. FIELD_WIDTH and PRECISION are the
335 field width and precision for '*' values, if HAVE_FIELD_WIDTH and
336 HAVE_PRECISION are true, respectively. ARGUMENT is the argument to
340 print_direc (char const *start
, size_t length
, char conversion
,
341 bool have_field_width
, int field_width
,
342 bool have_precision
, int precision
,
343 char const *argument
)
345 char *p
; /* Null-terminated copy of % directive. */
347 /* Create a null-terminated copy of the % directive, with an
348 intmax_t-wide length modifier substituted for any existing
349 integer length modifier. */
352 char const *length_modifier
;
353 size_t length_modifier_len
;
357 case 'd': case 'i': case 'o': case 'u': case 'x': case 'X':
358 length_modifier
= "j";
359 length_modifier_len
= 1;
362 case 'a': case 'e': case 'f': case 'g':
363 case 'A': case 'E': case 'F': case 'G':
364 length_modifier
= "L";
365 length_modifier_len
= 1;
369 length_modifier
= start
; /* Any valid pointer will do. */
370 length_modifier_len
= 0;
374 p
= xmalloc (length
+ length_modifier_len
+ 2);
375 q
= mempcpy (p
, start
, length
);
376 q
= mempcpy (q
, length_modifier
, length_modifier_len
);
386 intmax_t arg
= vstrtoimax (argument
);
387 if (!have_field_width
)
392 xprintf (p
, precision
, arg
);
397 xprintf (p
, field_width
, arg
);
399 xprintf (p
, field_width
, precision
, arg
);
409 uintmax_t arg
= vstrtoumax (argument
);
410 if (!have_field_width
)
415 xprintf (p
, precision
, arg
);
420 xprintf (p
, field_width
, arg
);
422 xprintf (p
, field_width
, precision
, arg
);
436 long double arg
= vstrtold (argument
);
437 if (!have_field_width
)
442 xprintf (p
, precision
, arg
);
447 xprintf (p
, field_width
, arg
);
449 xprintf (p
, field_width
, precision
, arg
);
455 if (!have_field_width
)
456 xprintf (p
, *argument
);
458 xprintf (p
, field_width
, *argument
);
462 if (!have_field_width
)
465 xprintf (p
, argument
);
467 xprintf (p
, precision
, argument
);
472 xprintf (p
, field_width
, argument
);
474 xprintf (p
, field_width
, precision
, argument
);
482 /* Print the text in FORMAT, using ARGV (with ARGC elements) for
483 arguments to any '%' directives.
484 Return the number of elements of ARGV used. */
487 print_formatted (char const *format
, int argc
, char **argv
)
489 int save_argc
= argc
; /* Preserve original value. */
490 char const *f
; /* Pointer into 'format'. */
491 char const *direc_start
; /* Start of % directive. */
492 size_t direc_length
; /* Length of % directive. */
493 bool have_field_width
; /* True if FIELD_WIDTH is valid. */
494 int field_width
= 0; /* Arg to first '*'. */
495 bool have_precision
; /* True if PRECISION is valid. */
496 int precision
= 0; /* Arg to second '*'. */
497 char ok
[UCHAR_MAX
+ 1]; /* ok['x'] is true if %x is allowed. */
499 for (f
= format
; *f
; ++f
)
506 have_field_width
= have_precision
= false;
514 /* FIXME: Field width and precision are not supported
515 for %b, even though POSIX requires it. */
518 print_esc_string (*argv
);
529 fputs (quotearg_style (shell_escape_quoting_style
, *argv
),
537 memset (ok
, 0, sizeof ok
);
538 ok
['a'] = ok
['A'] = ok
['c'] = ok
['d'] = ok
['e'] = ok
['E'] =
539 ok
['f'] = ok
['F'] = ok
['g'] = ok
['G'] = ok
['i'] = ok
['o'] =
540 ok
['s'] = ok
['u'] = ok
['x'] = ok
['X'] = 1;
542 for (;; f
++, direc_length
++)
545 #if (__GLIBC__ == 2 && 2 <= __GLIBC_MINOR__) || 3 <= __GLIBC__
549 ok
['a'] = ok
['A'] = ok
['c'] = ok
['e'] = ok
['E'] =
550 ok
['o'] = ok
['s'] = ok
['x'] = ok
['X'] = 0;
552 case '-': case '+': case ' ':
555 ok
['c'] = ok
['d'] = ok
['i'] = ok
['s'] = ok
['u'] = 0;
558 ok
['c'] = ok
['s'] = 0;
561 goto no_more_flag_characters
;
563 no_more_flag_characters
:
571 intmax_t width
= vstrtoimax (*argv
);
572 if (INT_MIN
<= width
&& width
<= INT_MAX
)
575 error (EXIT_FAILURE
, 0, _("invalid field width: %s"),
582 have_field_width
= true;
601 intmax_t prec
= vstrtoimax (*argv
);
604 /* A negative precision is taken as if the
605 precision were omitted, so -1 is safe
606 here even if prec < INT_MIN. */
609 else if (INT_MAX
< prec
)
610 error (EXIT_FAILURE
, 0, _("invalid precision: %s"),
619 have_precision
= true;
629 while (*f
== 'l' || *f
== 'L' || *f
== 'h'
630 || *f
== 'j' || *f
== 't' || *f
== 'z')
634 unsigned char conversion
= *f
;
635 int speclen
= MIN (f
+ 1 - direc_start
, INT_MAX
);
636 if (! ok
[conversion
])
637 error (EXIT_FAILURE
, 0,
638 _("%.*s: invalid conversion specification"),
639 speclen
, direc_start
);
642 print_direc (direc_start
, direc_length
, *f
,
643 have_field_width
, field_width
,
644 have_precision
, precision
,
645 (argc
<= 0 ? "" : (argc
--, *argv
++)));
649 f
+= print_esc (f
, false);
657 return save_argc
- argc
;
661 main (int argc
, char **argv
)
666 initialize_main (&argc
, &argv
);
667 set_program_name (argv
[0]);
668 setlocale (LC_ALL
, "");
669 bindtextdomain (PACKAGE
, LOCALEDIR
);
670 textdomain (PACKAGE
);
672 atexit (close_stdout
);
674 exit_status
= EXIT_SUCCESS
;
676 posixly_correct
= (getenv ("POSIXLY_CORRECT") != nullptr);
678 /* We directly parse options, rather than use parse_long_options, in
679 order to avoid accepting abbreviations. */
682 if (STREQ (argv
[1], "--help"))
683 usage (EXIT_SUCCESS
);
685 if (STREQ (argv
[1], "--version"))
687 version_etc (stdout
, PROGRAM_NAME
, PACKAGE_NAME
, Version
, AUTHORS
,
693 /* The above handles --help and --version.
694 Since there is no other invocation of getopt, handle '--' here. */
695 if (1 < argc
&& STREQ (argv
[1], "--"))
703 error (0, 0, _("missing operand"));
704 usage (EXIT_FAILURE
);
713 args_used
= print_formatted (format
, argc
, argv
);
717 while (args_used
> 0 && argc
> 0);
721 _("warning: ignoring excess arguments, starting with %s"),