1 /* printf - format and print data
2 Copyright (C) 1990-2006 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 2, or (at your option)
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, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18 /* Usage: printf format [argument...]
20 A front end to the printf function that lets it be used from the shell.
28 \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 "long-options.h"
59 #include "unicodeio.h"
61 /* The official name of this program (e.g., no `g' prefix). */
62 #define PROGRAM_NAME "printf"
64 #define AUTHORS "David MacKenzie"
66 #define isodigit(c) ((c) >= '0' && (c) <= '7')
67 #define hextobin(c) ((c) >= 'a' && (c) <= 'f' ? (c) - 'a' + 10 : \
68 (c) >= 'A' && (c) <= 'F' ? (c) - 'A' + 10 : (c) - '0')
69 #define octtobin(c) ((c) - '0')
71 /* The value to return to the calling program. */
72 static int exit_status
;
74 /* True if the POSIXLY_CORRECT environment variable is set. */
75 static bool posixly_correct
;
77 /* This message appears in N_() here rather than just in _() below because
78 the sole use would have been in a #define. */
79 static char *const cfcc_msg
=
80 N_("warning: %s: character(s) following character constant have been ignored");
82 /* The name this program was run with. */
88 if (status
!= EXIT_SUCCESS
)
89 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
94 Usage: %s FORMAT [ARGUMENT]...\n\
97 program_name
, program_name
);
99 Print ARGUMENT(s) according to FORMAT.\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\
109 \\NNN character with octal value NNN (1 to 3 digits)\n\
115 \\c produce no further output\n\
120 \\r carriage return\n\
121 \\t horizontal tab\n\
125 \\xHH byte with hexadecimal value HH (1 to 2 digits)\n\
126 \\uHHHH Unicode (ISO/IEC 10646) character with hex value HHHH (4 digits)\n\
127 \\UHHHHHHHH Unicode character with hex value HHHHHHHH (8 digits)\n\
131 %b ARGUMENT as a string with `\\' escapes interpreted,\n\
132 except that octal escapes are of the form \\0 or \\0NNN\n\
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 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT
);
144 verify_numeric (const char *s
, const char *end
)
148 error (0, errno
, "%s", s
);
149 exit_status
= EXIT_FAILURE
;
154 error (0, 0, _("%s: expected a numeric value"), s
);
156 error (0, 0, _("%s: value not completely converted"), 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 == '\'') \
170 unsigned char ch = *++s; \
172 /* If POSIXLY_CORRECT is not set, then give a warning that there \
173 are characters following the character constant and that GNU \
174 printf is ignoring those characters. If POSIXLY_CORRECT *is* \
175 set, then don't give the warning. */ \
176 if (*++s != 0 && !posixly_correct) \
177 error (0, 0, _(cfcc_msg), s); \
182 val = (LIB_FUNC_EXPR); \
183 verify_numeric (s, end); \
188 STRTOX (intmax_t, vstrtoimax, strtoimax (s, &end, 0))
189 STRTOX (uintmax_t, vstrtoumax
, strtoumax (s
, &end
, 0))
190 STRTOX (long double, vstrtold
, c_strtold (s
, &end
))
192 /* Output a single-character \ escape. */
195 print_esc_char (char c
)
199 case 'a': /* Alert. */
202 case 'b': /* Backspace. */
205 case 'c': /* Cancel the rest of the output. */
208 case 'f': /* Form feed. */
211 case 'n': /* New line. */
214 case 'r': /* Carriage return. */
217 case 't': /* Horizontal tab. */
220 case 'v': /* Vertical tab. */
229 /* Print a \ escape sequence starting at ESCSTART.
230 Return the number of characters in the escape sequence
231 besides the backslash.
232 If OCTAL_0 is nonzero, octal escapes are of the form \0ooo, where o
233 is an octal digit; otherwise they are of the form \ooo. */
236 print_esc (const char *escstart
, bool octal_0
)
238 const char *p
= escstart
+ 1;
239 int esc_value
= 0; /* Value of \nnn escape. */
240 int esc_length
; /* Length of \nnn escape. */
244 /* A hexadecimal \xhh escape sequence must have 1 or 2 hex. digits. */
245 for (esc_length
= 0, ++p
;
246 esc_length
< 2 && isxdigit (to_uchar (*p
));
248 esc_value
= esc_value
* 16 + hextobin (*p
);
250 error (EXIT_FAILURE
, 0, _("missing hexadecimal number in escape"));
253 else if (isodigit (*p
))
255 /* Parse \0ooo (if octal_0 && *p == '0') or \ooo (otherwise).
256 Allow \ooo if octal_0 && *p != '0'; this is an undocumented
257 extension to POSIX that is compatible with Bash 2.05b. */
258 for (esc_length
= 0, p
+= octal_0
&& *p
== '0';
259 esc_length
< 3 && isodigit (*p
);
261 esc_value
= esc_value
* 8 + octtobin (*p
);
264 else if (*p
&& strchr ("\"\\abcfnrtv", *p
))
265 print_esc_char (*p
++);
266 else if (*p
== 'u' || *p
== 'U')
269 unsigned int uni_value
;
272 for (esc_length
= (esc_char
== 'u' ? 4 : 8), ++p
;
276 if (! isxdigit (to_uchar (*p
)))
277 error (EXIT_FAILURE
, 0, _("missing hexadecimal number in escape"));
278 uni_value
= uni_value
* 16 + hextobin (*p
);
281 /* A universal character name shall not specify a character short
282 identifier in the range 00000000 through 00000020, 0000007F through
283 0000009F, or 0000D800 through 0000DFFF inclusive. A universal
284 character name shall not designate a character in the required
286 if ((uni_value
<= 0x9f
287 && uni_value
!= 0x24 && uni_value
!= 0x40 && uni_value
!= 0x60)
288 || (uni_value
>= 0xd800 && uni_value
<= 0xdfff))
289 error (EXIT_FAILURE
, 0, _("invalid universal character name \\%c%0*x"),
290 esc_char
, (esc_char
== 'u' ? 4 : 8), uni_value
);
292 print_unicode_char (stdout
, uni_value
, 0);
303 return p
- escstart
- 1;
306 /* Print string STR, evaluating \ escapes. */
309 print_esc_string (const char *str
)
313 str
+= print_esc (str
, true);
318 /* Evaluate a printf conversion specification. START is the start of
319 the directive, LENGTH is its length, and CONVERSION specifies the
320 type of conversion. LENGTH does not include any length modifier or
321 the conversion specifier itself. FIELD_WIDTH and PRECISION are the
322 field width and precision for '*' values, if HAVE_FIELD_WIDTH and
323 HAVE_PRECISION are true, respectively. ARGUMENT is the argument to
327 print_direc (const char *start
, size_t length
, char conversion
,
328 bool have_field_width
, int field_width
,
329 bool have_precision
, int precision
,
330 char const *argument
)
332 char *p
; /* Null-terminated copy of % directive. */
334 /* Create a null-terminated copy of the % directive, with an
335 intmax_t-wide length modifier substituted for any existing
336 integer length modifier. */
339 char const *length_modifier
;
340 size_t length_modifier_len
;
344 case 'd': case 'i': case 'o': case 'u': case 'x': case 'X':
345 length_modifier
= PRIdMAX
;
346 length_modifier_len
= sizeof PRIdMAX
- 2;
349 case 'a': case 'e': case 'f': case 'g':
350 case 'A': case 'E': case 'F': case 'G':
351 length_modifier
= "L";
352 length_modifier_len
= 1;
356 length_modifier
= start
; /* Any valid pointer will do. */
357 length_modifier_len
= 0;
361 p
= xmalloc (length
+ length_modifier_len
+ 2);
362 q
= mempcpy (p
, start
, length
);
363 q
= mempcpy (q
, length_modifier
, length_modifier_len
);
373 intmax_t arg
= vstrtoimax (argument
);
374 if (!have_field_width
)
379 printf (p
, precision
, arg
);
384 printf (p
, field_width
, arg
);
386 printf (p
, field_width
, precision
, arg
);
396 uintmax_t arg
= vstrtoumax (argument
);
397 if (!have_field_width
)
402 printf (p
, precision
, arg
);
407 printf (p
, field_width
, arg
);
409 printf (p
, field_width
, precision
, arg
);
423 long double arg
= vstrtold (argument
);
424 if (!have_field_width
)
429 printf (p
, precision
, arg
);
434 printf (p
, field_width
, arg
);
436 printf (p
, field_width
, precision
, arg
);
442 if (!have_field_width
)
443 printf (p
, *argument
);
445 printf (p
, field_width
, *argument
);
449 if (!have_field_width
)
452 printf (p
, argument
);
454 printf (p
, precision
, argument
);
459 printf (p
, field_width
, argument
);
461 printf (p
, field_width
, precision
, argument
);
469 /* Print the text in FORMAT, using ARGV (with ARGC elements) for
470 arguments to any `%' directives.
471 Return the number of elements of ARGV used. */
474 print_formatted (const char *format
, int argc
, char **argv
)
476 int save_argc
= argc
; /* Preserve original value. */
477 const char *f
; /* Pointer into `format'. */
478 const char *direc_start
; /* Start of % directive. */
479 size_t direc_length
; /* Length of % directive. */
480 bool have_field_width
; /* True if FIELD_WIDTH is valid. */
481 int field_width
= 0; /* Arg to first '*'. */
482 bool have_precision
; /* True if PRECISION is valid. */
483 int precision
= 0; /* Arg to second '*'. */
484 char ok
[UCHAR_MAX
+ 1]; /* ok['x'] is true if %x is allowed. */
486 for (f
= format
; *f
; ++f
)
493 have_field_width
= have_precision
= false;
501 /* FIXME: Field width and precision are not supported
502 for %b, even though POSIX requires it. */
505 print_esc_string (*argv
);
512 memset (ok
, 0, sizeof ok
);
513 ok
['a'] = ok
['A'] = ok
['c'] = ok
['d'] = ok
['e'] = ok
['E'] =
514 ok
['f'] = ok
['F'] = ok
['g'] = ok
['G'] = ok
['i'] = ok
['o'] =
515 ok
['s'] = ok
['u'] = ok
['x'] = ok
['X'] = 1;
517 for (;; f
++, direc_length
++)
520 #if (__GLIBC__ == 2 && 2 <= __GLIBC_MINOR__) || 3 <= __GLIBC__
524 ok
['a'] = ok
['A'] = ok
['c'] = ok
['e'] = ok
['E'] =
525 ok
['o'] = ok
['s'] = ok
['x'] = ok
['X'] = 0;
527 case '-': case '+': case ' ':
530 ok
['c'] = ok
['d'] = ok
['i'] = ok
['s'] = ok
['u'] = 0;
533 ok
['c'] = ok
['s'] = 0;
536 goto no_more_flag_characters
;
538 no_more_flag_characters
:;
546 intmax_t width
= vstrtoimax (*argv
);
547 if (INT_MIN
<= width
&& width
<= INT_MAX
)
550 error (EXIT_FAILURE
, 0, _("invalid field width: %s"),
557 have_field_width
= true;
576 intmax_t prec
= vstrtoimax (*argv
);
579 /* A negative precision is taken as if the
580 precision were omitted, so -1 is safe
581 here even if prec < INT_MIN. */
584 else if (INT_MAX
< prec
)
585 error (EXIT_FAILURE
, 0, _("invalid precision: %s"),
594 have_precision
= true;
604 while (*f
== 'l' || *f
== 'L' || *f
== 'h'
605 || *f
== 'j' || *f
== 't' || *f
== 'z')
609 unsigned char conversion
= *f
;
610 if (! ok
[conversion
])
611 error (EXIT_FAILURE
, 0,
612 _("%.*s: invalid conversion specification"),
613 (int) (f
+ 1 - direc_start
), direc_start
);
616 print_direc (direc_start
, direc_length
, *f
,
617 have_field_width
, field_width
,
618 have_precision
, precision
,
619 (argc
<= 0 ? "" : (argc
--, *argv
++)));
623 f
+= print_esc (f
, false);
631 return save_argc
- argc
;
635 main (int argc
, char **argv
)
640 initialize_main (&argc
, &argv
);
641 program_name
= argv
[0];
642 setlocale (LC_ALL
, "");
643 bindtextdomain (PACKAGE
, LOCALEDIR
);
644 textdomain (PACKAGE
);
646 atexit (close_stdout
);
648 exit_status
= EXIT_SUCCESS
;
650 posixly_correct
= (getenv ("POSIXLY_CORRECT") != NULL
);
652 parse_long_options (argc
, argv
, PROGRAM_NAME
, GNU_PACKAGE
, VERSION
,
653 usage
, AUTHORS
, (char const *) NULL
);
655 /* The above handles --help and --version.
656 Since there is no other invocation of getopt, handle `--' here. */
657 if (1 < argc
&& STREQ (argv
[1], "--"))
665 error (0, 0, _("missing operand"));
666 usage (EXIT_FAILURE
);
675 args_used
= print_formatted (format
, argc
, argv
);
679 while (args_used
> 0 && argc
> 0);
683 _("warning: ignoring excess arguments, starting with %s"),