1 /* printf - format and print data
2 Copyright (C) 1990-2008 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
33 \ooo = octal number (ooo is 1 to 3 digits)
34 \xhh = hexadecimal number (hhh is 1 to 2 digits)
35 \uhhhh = 16-bit Unicode character (hhhh is 4 digits)
36 \Uhhhhhhhh = 32-bit Unicode character (hhhhhhhh is 8 digits)
40 %b = print an argument string, interpreting backslash escapes,
41 except that octal escapes are of the form \0 or \0ooo.
43 The `format' argument is re-used as many times as necessary
44 to convert all of the given arguments.
46 David MacKenzie <djm@gnu.ai.mit.edu> */
50 #include <sys/types.h>
55 #include "long-options.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\
105 \\NNN character with octal value NNN (1 to 3 digits)\n\
111 \\c produce no further output\n\
116 \\r carriage return\n\
117 \\t horizontal tab\n\
121 \\xHH byte with hexadecimal value HH (1 to 2 digits)\n\
122 \\uHHHH Unicode (ISO/IEC 10646) character with hex value HHHH (4 digits)\n\
123 \\UHHHHHHHH Unicode character with hex value HHHHHHHH (8 digits)\n\
127 %b ARGUMENT as a string with `\\' escapes interpreted,\n\
128 except that octal escapes are of the form \\0 or \\0NNN\n\
130 and all C format specifications ending with one of diouxXfeEgGcs, with\n\
131 ARGUMENTs converted to proper type first. Variable widths are handled.\n\
133 printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
134 emit_bug_reporting_address ();
140 verify_numeric (const char *s, const char *end)
144 error (0, errno, "%s", s);
145 exit_status = EXIT_FAILURE;
150 error (0, 0, _("%s: expected a numeric value"), s);
152 error (0, 0, _("%s: value not completely converted"), s);
153 exit_status = EXIT_FAILURE;
157 #define STRTOX(TYPE, FUNC_NAME, LIB_FUNC_EXPR) \
159 FUNC_NAME (char const *s) \
164 if (*s == '\"' || *s == '\'') \
166 unsigned char ch = *++s; \
168 /* If POSIXLY_CORRECT is not set, then give a warning that there \
169 are characters following the character constant and that GNU \
170 printf is ignoring those characters. If POSIXLY_CORRECT *is* \
171 set, then don't give the warning. */ \
172 if (*++s != 0 && !posixly_correct) \
173 error (0, 0, _(cfcc_msg), s); \
178 val = (LIB_FUNC_EXPR); \
179 verify_numeric (s, end); \
184 STRTOX (intmax_t, vstrtoimax, strtoimax (s, &end, 0))
185 STRTOX (uintmax_t, vstrtoumax, strtoumax (s, &end, 0))
186 STRTOX (long double, vstrtold, c_strtold (s, &end))
188 /* Output a single-character \ escape. */
191 print_esc_char (char c)
195 case 'a': /* Alert. */
198 case 'b': /* Backspace. */
201 case 'c': /* Cancel the rest of the output. */
204 case 'f': /* Form feed. */
207 case 'n': /* New line. */
210 case 'r': /* Carriage return. */
213 case 't': /* Horizontal tab. */
216 case 'v': /* Vertical tab. */
225 /* Print a \ escape sequence starting at ESCSTART.
226 Return the number of characters in the escape sequence
227 besides the backslash.
228 If OCTAL_0 is nonzero, octal escapes are of the form \0ooo, where o
229 is an octal digit; otherwise they are of the form \ooo. */
232 print_esc (const char *escstart, bool octal_0)
234 const char *p = escstart + 1;
235 int esc_value = 0; /* Value of \nnn escape. */
236 int esc_length; /* Length of \nnn escape. */
240 /* A hexadecimal \xhh escape sequence must have 1 or 2 hex. digits. */
241 for (esc_length = 0, ++p;
242 esc_length < 2 && isxdigit (to_uchar (*p));
244 esc_value = esc_value * 16 + hextobin (*p);
246 error (EXIT_FAILURE, 0, _("missing hexadecimal number in escape"));
249 else if (isodigit (*p))
251 /* Parse \0ooo (if octal_0 && *p == '0') or \ooo (otherwise).
252 Allow \ooo if octal_0 && *p != '0'; this is an undocumented
253 extension to POSIX that is compatible with Bash 2.05b. */
254 for (esc_length = 0, p += octal_0 && *p == '0';
255 esc_length < 3 && isodigit (*p);
257 esc_value = esc_value * 8 + octtobin (*p);
260 else if (*p && strchr ("\"\\abcfnrtv", *p))
261 print_esc_char (*p++);
262 else if (*p == 'u' || *p == 'U')
265 unsigned int uni_value;
268 for (esc_length = (esc_char == 'u' ? 4 : 8), ++p;
272 if (! isxdigit (to_uchar (*p)))
273 error (EXIT_FAILURE, 0, _("missing hexadecimal number in escape"));
274 uni_value = uni_value * 16 + hextobin (*p);
277 /* A universal character name shall not specify a character short
278 identifier in the range 00000000 through 00000020, 0000007F through
279 0000009F, or 0000D800 through 0000DFFF inclusive. A universal
280 character name shall not designate a character in the required
282 if ((uni_value <= 0x9f
283 && uni_value != 0x24 && uni_value != 0x40 && uni_value != 0x60)
284 || (uni_value >= 0xd800 && uni_value <= 0xdfff))
285 error (EXIT_FAILURE, 0, _("invalid universal character name \\%c%0*x"),
286 esc_char, (esc_char == 'u' ? 4 : 8), uni_value);
288 print_unicode_char (stdout, uni_value, 0);
299 return p - escstart - 1;
302 /* Print string STR, evaluating \ escapes. */
305 print_esc_string (const char *str)
309 str += print_esc (str, true);
314 /* Evaluate a printf conversion specification. START is the start of
315 the directive, LENGTH is its length, and CONVERSION specifies the
316 type of conversion. LENGTH does not include any length modifier or
317 the conversion specifier itself. FIELD_WIDTH and PRECISION are the
318 field width and precision for '*' values, if HAVE_FIELD_WIDTH and
319 HAVE_PRECISION are true, respectively. ARGUMENT is the argument to
323 print_direc (const char *start, size_t length, char conversion,
324 bool have_field_width, int field_width,
325 bool have_precision, int precision,
326 char const *argument)
328 char *p; /* Null-terminated copy of % directive. */
330 /* Create a null-terminated copy of the % directive, with an
331 intmax_t-wide length modifier substituted for any existing
332 integer length modifier. */
335 char const *length_modifier;
336 size_t length_modifier_len;
340 case 'd': case 'i': case 'o': case 'u': case 'x': case 'X':
341 length_modifier = PRIdMAX;
342 length_modifier_len = sizeof PRIdMAX - 2;
345 case 'a': case 'e': case 'f': case 'g':
346 case 'A': case 'E': case 'F': case 'G':
347 length_modifier = "L";
348 length_modifier_len = 1;
352 length_modifier = start; /* Any valid pointer will do. */
353 length_modifier_len = 0;
357 p = xmalloc (length + length_modifier_len + 2);
358 q = mempcpy (p, start, length);
359 q = mempcpy (q, length_modifier, length_modifier_len);
369 intmax_t arg = vstrtoimax (argument);
370 if (!have_field_width)
375 xprintf (p, precision, arg);
380 xprintf (p, field_width, arg);
382 xprintf (p, field_width, precision, arg);
392 uintmax_t arg = vstrtoumax (argument);
393 if (!have_field_width)
398 xprintf (p, precision, arg);
403 xprintf (p, field_width, arg);
405 xprintf (p, field_width, precision, arg);
419 long double arg = vstrtold (argument);
420 if (!have_field_width)
425 xprintf (p, precision, arg);
430 xprintf (p, field_width, arg);
432 xprintf (p, field_width, precision, arg);
438 if (!have_field_width)
439 xprintf (p, *argument);
441 xprintf (p, field_width, *argument);
445 if (!have_field_width)
448 xprintf (p, argument);
450 xprintf (p, precision, argument);
455 xprintf (p, field_width, argument);
457 xprintf (p, field_width, precision, argument);
465 /* Print the text in FORMAT, using ARGV (with ARGC elements) for
466 arguments to any `%' directives.
467 Return the number of elements of ARGV used. */
470 print_formatted (const char *format, int argc, char **argv)
472 int save_argc = argc; /* Preserve original value. */
473 const char *f; /* Pointer into `format'. */
474 const char *direc_start; /* Start of % directive. */
475 size_t direc_length; /* Length of % directive. */
476 bool have_field_width; /* True if FIELD_WIDTH is valid. */
477 int field_width = 0; /* Arg to first '*'. */
478 bool have_precision; /* True if PRECISION is valid. */
479 int precision = 0; /* Arg to second '*'. */
480 char ok[UCHAR_MAX + 1]; /* ok['x'] is true if %x is allowed. */
482 for (f = format; *f; ++f)
489 have_field_width = have_precision = false;
497 /* FIXME: Field width and precision are not supported
498 for %b, even though POSIX requires it. */
501 print_esc_string (*argv);
508 memset (ok, 0, sizeof ok);
509 ok['a'] = ok['A'] = ok['c'] = ok['d'] = ok['e'] = ok['E'] =
510 ok['f'] = ok['F'] = ok['g'] = ok['G'] = ok['i'] = ok['o'] =
511 ok['s'] = ok['u'] = ok['x'] = ok['X'] = 1;
513 for (;; f++, direc_length++)
516 #if (__GLIBC__ == 2 && 2 <= __GLIBC_MINOR__) || 3 <= __GLIBC__
520 ok['a'] = ok['A'] = ok['c'] = ok['e'] = ok['E'] =
521 ok['o'] = ok['s'] = ok['x'] = ok['X'] = 0;
523 case '-': case '+': case ' ':
526 ok['c'] = ok['d'] = ok['i'] = ok['s'] = ok['u'] = 0;
529 ok['c'] = ok['s'] = 0;
532 goto no_more_flag_characters;
534 no_more_flag_characters:;
542 intmax_t width = vstrtoimax (*argv);
543 if (INT_MIN <= width && width <= INT_MAX)
546 error (EXIT_FAILURE, 0, _("invalid field width: %s"),
553 have_field_width = true;
572 intmax_t prec = vstrtoimax (*argv);
575 /* A negative precision is taken as if the
576 precision were omitted, so -1 is safe
577 here even if prec < INT_MIN. */
580 else if (INT_MAX < prec)
581 error (EXIT_FAILURE, 0, _("invalid precision: %s"),
590 have_precision = true;
600 while (*f == 'l' || *f == 'L' || *f == 'h'
601 || *f == 'j' || *f == 't' || *f == 'z')
605 unsigned char conversion = *f;
606 if (! ok[conversion])
607 error (EXIT_FAILURE, 0,
608 _("%.*s: invalid conversion specification"),
609 (int) (f + 1 - direc_start), direc_start);
612 print_direc (direc_start, direc_length, *f,
613 have_field_width, field_width,
614 have_precision, precision,
615 (argc <= 0 ? "" : (argc--, *argv++)));
619 f += print_esc (f, false);
627 return save_argc - argc;
631 main (int argc, char **argv)
636 initialize_main (&argc, &argv);
637 set_program_name (argv[0]);
638 setlocale (LC_ALL, "");
639 bindtextdomain (PACKAGE, LOCALEDIR);
640 textdomain (PACKAGE);
642 atexit (close_stdout);
644 exit_status = EXIT_SUCCESS;
646 posixly_correct = (getenv ("POSIXLY_CORRECT") != NULL);
648 parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
649 usage, AUTHORS, (char const *) NULL);
651 /* The above handles --help and --version.
652 Since there is no other invocation of getopt, handle `--' here. */
653 if (1 < argc && STREQ (argv[1], "--"))
661 error (0, 0, _("missing operand"));
662 usage (EXIT_FAILURE);
671 args_used = print_formatted (format, argc, argv);
675 while (args_used > 0 && argc > 0);
679 _("warning: ignoring excess arguments, starting with %s"),