1 /* printf - format and print data
2 Copyright (C) 1990-2010 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 <http://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 The `format' argument is re-used as many times as necessary
45 to convert all of the given arguments.
47 David MacKenzie <djm@gnu.ai.mit.edu> */
51 #include <sys/types.h>
57 #include "unicodeio.h"
60 /* The official name of this program (e.g., no `g' prefix). */
61 #define PROGRAM_NAME "printf"
63 #define AUTHORS proper_name ("David MacKenzie")
65 #define isodigit(c) ((c) >= '0' && (c) <= '7')
66 #define hextobin(c) ((c) >= 'a' && (c) <= 'f' ? (c) - 'a' + 10 : \
67 (c) >= 'A' && (c) <= 'F' ? (c) - 'A' + 10 : (c) - '0')
68 #define octtobin(c) ((c) - '0')
70 /* The value to return to the calling program. */
71 static int exit_status
;
73 /* True if the POSIXLY_CORRECT environment variable is set. */
74 static bool posixly_correct
;
76 /* This message appears in N_() here rather than just in _() below because
77 the sole use would have been in a #define. */
78 static char const *const cfcc_msg
=
79 N_("warning: %s: character(s) following character constant have been ignored");
84 if (status
!= EXIT_SUCCESS
)
85 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
90 Usage: %s FORMAT [ARGUMENT]...\n\
93 program_name
, program_name
);
95 Print ARGUMENT(s) according to FORMAT, or execute according to OPTION:\n\
98 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
99 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
102 FORMAT controls the output as in C printf. Interpreted sequences are:\n\
110 \\c produce no further output\n\
114 \\r carriage return\n\
115 \\t horizontal tab\n\
119 \\NNN byte with octal value NNN (1 to 3 digits)\n\
120 \\xHH byte with hexadecimal value HH (1 to 2 digits)\n\
121 \\uHHHH Unicode (ISO/IEC 10646) character with hex value HHHH (4 digits)\n\
122 \\UHHHHHHHH Unicode character with hex value HHHHHHHH (8 digits)\n\
126 %b ARGUMENT as a string with `\\' escapes interpreted,\n\
127 except that octal escapes are of the form \\0 or \\0NNN\n\
129 and all C format specifications ending with one of diouxXfeEgGcs, with\n\
130 ARGUMENTs converted to proper type first. Variable widths are handled.\n\
132 printf (USAGE_BUILTIN_WARNING
, PROGRAM_NAME
);
133 emit_ancillary_info ();
139 verify_numeric (const char *s
, const char *end
)
143 error (0, errno
, "%s", s
);
144 exit_status
= EXIT_FAILURE
;
149 error (0, 0, _("%s: expected a numeric value"), s
);
151 error (0, 0, _("%s: value not completely converted"), s
);
152 exit_status
= EXIT_FAILURE
;
156 #define STRTOX(TYPE, FUNC_NAME, LIB_FUNC_EXPR) \
158 FUNC_NAME (char const *s) \
163 if (*s == '\"' || *s == '\'') \
165 unsigned char ch = *++s; \
167 /* If POSIXLY_CORRECT is not set, then give a warning that there \
168 are characters following the character constant and that GNU \
169 printf is ignoring those characters. If POSIXLY_CORRECT *is* \
170 set, then don't give the warning. */ \
171 if (*++s != 0 && !posixly_correct) \
172 error (0, 0, _(cfcc_msg), s); \
177 val = (LIB_FUNC_EXPR); \
178 verify_numeric (s, end); \
183 STRTOX (intmax_t, vstrtoimax, strtoimax (s, &end, 0))
184 STRTOX (uintmax_t, vstrtoumax
, strtoumax (s
, &end
, 0))
185 STRTOX (long double, vstrtold
, c_strtold (s
, &end
))
187 /* Output a single-character \ escape. */
190 print_esc_char (char c
)
194 case 'a': /* Alert. */
197 case 'b': /* Backspace. */
200 case 'c': /* Cancel the rest of the output. */
203 case 'e': /* Escape. */
206 case 'f': /* Form feed. */
209 case 'n': /* New line. */
212 case 'r': /* Carriage return. */
215 case 't': /* Horizontal tab. */
218 case 'v': /* Vertical tab. */
227 /* Print a \ escape sequence starting at ESCSTART.
228 Return the number of characters in the escape sequence
229 besides the backslash.
230 If OCTAL_0 is nonzero, octal escapes are of the form \0ooo, where o
231 is an octal digit; otherwise they are of the form \ooo. */
234 print_esc (const char *escstart
, bool octal_0
)
236 const char *p
= escstart
+ 1;
237 int esc_value
= 0; /* Value of \nnn escape. */
238 int esc_length
; /* Length of \nnn escape. */
242 /* A hexadecimal \xhh escape sequence must have 1 or 2 hex. digits. */
243 for (esc_length
= 0, ++p
;
244 esc_length
< 2 && isxdigit (to_uchar (*p
));
246 esc_value
= esc_value
* 16 + hextobin (*p
);
248 error (EXIT_FAILURE
, 0, _("missing hexadecimal number in escape"));
251 else if (isodigit (*p
))
253 /* Parse \0ooo (if octal_0 && *p == '0') or \ooo (otherwise).
254 Allow \ooo if octal_0 && *p != '0'; this is an undocumented
255 extension to POSIX that is compatible with Bash 2.05b. */
256 for (esc_length
= 0, p
+= octal_0
&& *p
== '0';
257 esc_length
< 3 && isodigit (*p
);
259 esc_value
= esc_value
* 8 + octtobin (*p
);
262 else if (*p
&& strchr ("\"\\abcefnrtv", *p
))
263 print_esc_char (*p
++);
264 else if (*p
== 'u' || *p
== 'U')
267 unsigned int uni_value
;
270 for (esc_length
= (esc_char
== 'u' ? 4 : 8), ++p
;
274 if (! isxdigit (to_uchar (*p
)))
275 error (EXIT_FAILURE
, 0, _("missing hexadecimal number in escape"));
276 uni_value
= uni_value
* 16 + hextobin (*p
);
279 /* A universal character name shall not specify a character short
280 identifier in the range 00000000 through 00000020, 0000007F through
281 0000009F, or 0000D800 through 0000DFFF inclusive. A universal
282 character name shall not designate a character in the required
284 if ((uni_value
<= 0x9f
285 && uni_value
!= 0x24 && uni_value
!= 0x40 && uni_value
!= 0x60)
286 || (uni_value
>= 0xd800 && uni_value
<= 0xdfff))
287 error (EXIT_FAILURE
, 0, _("invalid universal character name \\%c%0*x"),
288 esc_char
, (esc_char
== 'u' ? 4 : 8), uni_value
);
290 print_unicode_char (stdout
, uni_value
, 0);
301 return p
- escstart
- 1;
304 /* Print string STR, evaluating \ escapes. */
307 print_esc_string (const char *str
)
311 str
+= print_esc (str
, true);
316 /* Evaluate a printf conversion specification. START is the start of
317 the directive, LENGTH is its length, and CONVERSION specifies the
318 type of conversion. LENGTH does not include any length modifier or
319 the conversion specifier itself. FIELD_WIDTH and PRECISION are the
320 field width and precision for '*' values, if HAVE_FIELD_WIDTH and
321 HAVE_PRECISION are true, respectively. ARGUMENT is the argument to
325 print_direc (const char *start
, size_t length
, char conversion
,
326 bool have_field_width
, int field_width
,
327 bool have_precision
, int precision
,
328 char const *argument
)
330 char *p
; /* Null-terminated copy of % directive. */
332 /* Create a null-terminated copy of the % directive, with an
333 intmax_t-wide length modifier substituted for any existing
334 integer length modifier. */
337 char const *length_modifier
;
338 size_t length_modifier_len
;
342 case 'd': case 'i': case 'o': case 'u': case 'x': case 'X':
343 length_modifier
= PRIdMAX
;
344 length_modifier_len
= sizeof PRIdMAX
- 2;
347 case 'a': case 'e': case 'f': case 'g':
348 case 'A': case 'E': case 'F': case 'G':
349 length_modifier
= "L";
350 length_modifier_len
= 1;
354 length_modifier
= start
; /* Any valid pointer will do. */
355 length_modifier_len
= 0;
359 p
= xmalloc (length
+ length_modifier_len
+ 2);
360 q
= mempcpy (p
, start
, length
);
361 q
= mempcpy (q
, length_modifier
, length_modifier_len
);
371 intmax_t arg
= vstrtoimax (argument
);
372 if (!have_field_width
)
377 xprintf (p
, precision
, arg
);
382 xprintf (p
, field_width
, arg
);
384 xprintf (p
, field_width
, precision
, arg
);
394 uintmax_t arg
= vstrtoumax (argument
);
395 if (!have_field_width
)
400 xprintf (p
, precision
, arg
);
405 xprintf (p
, field_width
, arg
);
407 xprintf (p
, field_width
, precision
, arg
);
421 long double arg
= vstrtold (argument
);
422 if (!have_field_width
)
427 xprintf (p
, precision
, arg
);
432 xprintf (p
, field_width
, arg
);
434 xprintf (p
, field_width
, precision
, arg
);
440 if (!have_field_width
)
441 xprintf (p
, *argument
);
443 xprintf (p
, field_width
, *argument
);
447 if (!have_field_width
)
450 xprintf (p
, argument
);
452 xprintf (p
, precision
, argument
);
457 xprintf (p
, field_width
, argument
);
459 xprintf (p
, field_width
, precision
, argument
);
467 /* Print the text in FORMAT, using ARGV (with ARGC elements) for
468 arguments to any `%' directives.
469 Return the number of elements of ARGV used. */
472 print_formatted (const char *format
, int argc
, char **argv
)
474 int save_argc
= argc
; /* Preserve original value. */
475 const char *f
; /* Pointer into `format'. */
476 const char *direc_start
; /* Start of % directive. */
477 size_t direc_length
; /* Length of % directive. */
478 bool have_field_width
; /* True if FIELD_WIDTH is valid. */
479 int field_width
= 0; /* Arg to first '*'. */
480 bool have_precision
; /* True if PRECISION is valid. */
481 int precision
= 0; /* Arg to second '*'. */
482 char ok
[UCHAR_MAX
+ 1]; /* ok['x'] is true if %x is allowed. */
484 for (f
= format
; *f
; ++f
)
491 have_field_width
= have_precision
= false;
499 /* FIXME: Field width and precision are not supported
500 for %b, even though POSIX requires it. */
503 print_esc_string (*argv
);
510 memset (ok
, 0, sizeof ok
);
511 ok
['a'] = ok
['A'] = ok
['c'] = ok
['d'] = ok
['e'] = ok
['E'] =
512 ok
['f'] = ok
['F'] = ok
['g'] = ok
['G'] = ok
['i'] = ok
['o'] =
513 ok
['s'] = ok
['u'] = ok
['x'] = ok
['X'] = 1;
515 for (;; f
++, direc_length
++)
518 #if (__GLIBC__ == 2 && 2 <= __GLIBC_MINOR__) || 3 <= __GLIBC__
522 ok
['a'] = ok
['A'] = ok
['c'] = ok
['e'] = ok
['E'] =
523 ok
['o'] = ok
['s'] = ok
['x'] = ok
['X'] = 0;
525 case '-': case '+': case ' ':
528 ok
['c'] = ok
['d'] = ok
['i'] = ok
['s'] = ok
['u'] = 0;
531 ok
['c'] = ok
['s'] = 0;
534 goto no_more_flag_characters
;
536 no_more_flag_characters
:;
544 intmax_t width
= vstrtoimax (*argv
);
545 if (INT_MIN
<= width
&& width
<= INT_MAX
)
548 error (EXIT_FAILURE
, 0, _("invalid field width: %s"),
555 have_field_width
= true;
574 intmax_t prec
= vstrtoimax (*argv
);
577 /* A negative precision is taken as if the
578 precision were omitted, so -1 is safe
579 here even if prec < INT_MIN. */
582 else if (INT_MAX
< prec
)
583 error (EXIT_FAILURE
, 0, _("invalid precision: %s"),
592 have_precision
= true;
602 while (*f
== 'l' || *f
== 'L' || *f
== 'h'
603 || *f
== 'j' || *f
== 't' || *f
== 'z')
607 unsigned char conversion
= *f
;
608 if (! ok
[conversion
])
609 error (EXIT_FAILURE
, 0,
610 _("%.*s: invalid conversion specification"),
611 (int) (f
+ 1 - direc_start
), direc_start
);
614 print_direc (direc_start
, direc_length
, *f
,
615 have_field_width
, field_width
,
616 have_precision
, precision
,
617 (argc
<= 0 ? "" : (argc
--, *argv
++)));
621 f
+= print_esc (f
, false);
629 return save_argc
- argc
;
633 main (int argc
, char **argv
)
638 initialize_main (&argc
, &argv
);
639 set_program_name (argv
[0]);
640 setlocale (LC_ALL
, "");
641 bindtextdomain (PACKAGE
, LOCALEDIR
);
642 textdomain (PACKAGE
);
644 atexit (close_stdout
);
646 exit_status
= EXIT_SUCCESS
;
648 posixly_correct
= (getenv ("POSIXLY_CORRECT") != NULL
);
650 /* We directly parse options, rather than use parse_long_options, in
651 order to avoid accepting abbreviations. */
654 if (STREQ (argv
[1], "--help"))
655 usage (EXIT_SUCCESS
);
657 if (STREQ (argv
[1], "--version"))
659 version_etc (stdout
, PROGRAM_NAME
, PACKAGE_NAME
, Version
, AUTHORS
,
665 /* The above handles --help and --version.
666 Since there is no other invocation of getopt, handle `--' here. */
667 if (1 < argc
&& STREQ (argv
[1], "--"))
675 error (0, 0, _("missing operand"));
676 usage (EXIT_FAILURE
);
685 args_used
= print_formatted (format
, argc
, argv
);
689 while (args_used
> 0 && argc
> 0);
693 _("warning: ignoring excess arguments, starting with %s"),