tests: remove crufty test=test_name code from old tests
[coreutils/ericb.git] / src / printf.c
bloba5317864ae071379f21666cd2d715aa30bc6790f
1 /* printf - format and print data
2 Copyright (C) 1990-2012 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.
21 Backslash escapes:
23 \" = double quote
24 \\ = backslash
25 \a = alert (bell)
26 \b = backspace
27 \c = produce no further output
28 \e = escape
29 \f = form feed
30 \n = new line
31 \r = carriage return
32 \t = horizontal tab
33 \v = vertical tab
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)
39 Additional directive:
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> */
49 #include <config.h>
50 #include <stdio.h>
51 #include <sys/types.h>
53 #include "system.h"
54 #include "c-strtod.h"
55 #include "error.h"
56 #include "quote.h"
57 #include "unicodeio.h"
58 #include "xprintf.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");
81 void
82 usage (int status)
84 if (status != EXIT_SUCCESS)
85 emit_try_help ();
86 else
88 printf (_("\
89 Usage: %s FORMAT [ARGUMENT]...\n\
90 or: %s OPTION\n\
91 "),
92 program_name, program_name);
93 fputs (_("\
94 Print ARGUMENT(s) according to FORMAT, or execute according to OPTION:\n\
95 \n\
96 "), stdout);
97 fputs (HELP_OPTION_DESCRIPTION, stdout);
98 fputs (VERSION_OPTION_DESCRIPTION, stdout);
99 fputs (_("\
101 FORMAT controls the output as in C printf. Interpreted sequences are:\n\
103 \\\" double quote\n\
104 "), stdout);
105 fputs (_("\
106 \\\\ backslash\n\
107 \\a alert (BEL)\n\
108 \\b backspace\n\
109 \\c produce no further output\n\
110 \\e escape\n\
111 \\f form feed\n\
112 \\n new line\n\
113 \\r carriage return\n\
114 \\t horizontal tab\n\
115 \\v vertical tab\n\
116 "), stdout);
117 fputs (_("\
118 \\NNN byte with octal value NNN (1 to 3 digits)\n\
119 \\xHH byte with hexadecimal value HH (1 to 2 digits)\n\
120 \\uHHHH Unicode (ISO/IEC 10646) character with hex value HHHH (4 digits)\n\
121 \\UHHHHHHHH Unicode character with hex value HHHHHHHH (8 digits)\n\
122 "), stdout);
123 fputs (_("\
124 %% a single %\n\
125 %b ARGUMENT as a string with '\\' escapes interpreted,\n\
126 except that octal escapes are of the form \\0 or \\0NNN\n\
128 and all C format specifications ending with one of diouxXfeEgGcs, with\n\
129 ARGUMENTs converted to proper type first. Variable widths are handled.\n\
130 "), stdout);
131 printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
132 emit_ancillary_info ();
134 exit (status);
137 static void
138 verify_numeric (const char *s, const char *end)
140 if (errno)
142 error (0, errno, "%s", s);
143 exit_status = EXIT_FAILURE;
145 else if (*end)
147 if (s == end)
148 error (0, 0, _("%s: expected a numeric value"), s);
149 else
150 error (0, 0, _("%s: value not completely converted"), s);
151 exit_status = EXIT_FAILURE;
155 #define STRTOX(TYPE, FUNC_NAME, LIB_FUNC_EXPR) \
156 static TYPE \
157 FUNC_NAME (char const *s) \
159 char *end; \
160 TYPE val; \
162 if ((*s == '\"' || *s == '\'') && *(s + 1)) \
164 unsigned char ch = *++s; \
165 val = ch; \
166 /* If POSIXLY_CORRECT is not set, then give a warning that there \
167 are characters following the character constant and that GNU \
168 printf is ignoring those characters. If POSIXLY_CORRECT *is* \
169 set, then don't give the warning. */ \
170 if (*++s != 0 && !posixly_correct) \
171 error (0, 0, _(cfcc_msg), s); \
173 else \
175 errno = 0; \
176 val = (LIB_FUNC_EXPR); \
177 verify_numeric (s, end); \
179 return val; \
182 STRTOX (intmax_t, vstrtoimax, strtoimax (s, &end, 0))
183 STRTOX (uintmax_t, vstrtoumax, strtoumax (s, &end, 0))
184 STRTOX (long double, vstrtold, c_strtold (s, &end))
186 /* Output a single-character \ escape. */
188 static void
189 print_esc_char (char c)
191 switch (c)
193 case 'a': /* Alert. */
194 putchar ('\a');
195 break;
196 case 'b': /* Backspace. */
197 putchar ('\b');
198 break;
199 case 'c': /* Cancel the rest of the output. */
200 exit (EXIT_SUCCESS);
201 break;
202 case 'e': /* Escape. */
203 putchar ('\x1B');
204 break;
205 case 'f': /* Form feed. */
206 putchar ('\f');
207 break;
208 case 'n': /* New line. */
209 putchar ('\n');
210 break;
211 case 'r': /* Carriage return. */
212 putchar ('\r');
213 break;
214 case 't': /* Horizontal tab. */
215 putchar ('\t');
216 break;
217 case 'v': /* Vertical tab. */
218 putchar ('\v');
219 break;
220 default:
221 putchar (c);
222 break;
226 /* Print a \ escape sequence starting at ESCSTART.
227 Return the number of characters in the escape sequence
228 besides the backslash.
229 If OCTAL_0 is nonzero, octal escapes are of the form \0ooo, where o
230 is an octal digit; otherwise they are of the form \ooo. */
232 static int
233 print_esc (const char *escstart, bool octal_0)
235 const char *p = escstart + 1;
236 int esc_value = 0; /* Value of \nnn escape. */
237 int esc_length; /* Length of \nnn escape. */
239 if (*p == 'x')
241 /* A hexadecimal \xhh escape sequence must have 1 or 2 hex. digits. */
242 for (esc_length = 0, ++p;
243 esc_length < 2 && isxdigit (to_uchar (*p));
244 ++esc_length, ++p)
245 esc_value = esc_value * 16 + hextobin (*p);
246 if (esc_length == 0)
247 error (EXIT_FAILURE, 0, _("missing hexadecimal number in escape"));
248 putchar (esc_value);
250 else if (isodigit (*p))
252 /* Parse \0ooo (if octal_0 && *p == '0') or \ooo (otherwise).
253 Allow \ooo if octal_0 && *p != '0'; this is an undocumented
254 extension to POSIX that is compatible with Bash 2.05b. */
255 for (esc_length = 0, p += octal_0 && *p == '0';
256 esc_length < 3 && isodigit (*p);
257 ++esc_length, ++p)
258 esc_value = esc_value * 8 + octtobin (*p);
259 putchar (esc_value);
261 else if (*p && strchr ("\"\\abcefnrtv", *p))
262 print_esc_char (*p++);
263 else if (*p == 'u' || *p == 'U')
265 char esc_char = *p;
266 unsigned int uni_value;
268 uni_value = 0;
269 for (esc_length = (esc_char == 'u' ? 4 : 8), ++p;
270 esc_length > 0;
271 --esc_length, ++p)
273 if (! isxdigit (to_uchar (*p)))
274 error (EXIT_FAILURE, 0, _("missing hexadecimal number in escape"));
275 uni_value = uni_value * 16 + hextobin (*p);
278 /* A universal character name shall not specify a character short
279 identifier in the range 00000000 through 00000020, 0000007F through
280 0000009F, or 0000D800 through 0000DFFF inclusive. A universal
281 character name shall not designate a character in the required
282 character set. */
283 if ((uni_value <= 0x9f
284 && uni_value != 0x24 && uni_value != 0x40 && uni_value != 0x60)
285 || (uni_value >= 0xd800 && uni_value <= 0xdfff))
286 error (EXIT_FAILURE, 0, _("invalid universal character name \\%c%0*x"),
287 esc_char, (esc_char == 'u' ? 4 : 8), uni_value);
289 print_unicode_char (stdout, uni_value, 0);
291 else
293 putchar ('\\');
294 if (*p)
296 putchar (*p);
297 p++;
300 return p - escstart - 1;
303 /* Print string STR, evaluating \ escapes. */
305 static void
306 print_esc_string (const char *str)
308 for (; *str; str++)
309 if (*str == '\\')
310 str += print_esc (str, true);
311 else
312 putchar (*str);
315 /* Evaluate a printf conversion specification. START is the start of
316 the directive, LENGTH is its length, and CONVERSION specifies the
317 type of conversion. LENGTH does not include any length modifier or
318 the conversion specifier itself. FIELD_WIDTH and PRECISION are the
319 field width and precision for '*' values, if HAVE_FIELD_WIDTH and
320 HAVE_PRECISION are true, respectively. ARGUMENT is the argument to
321 be formatted. */
323 static void
324 print_direc (const char *start, size_t length, char conversion,
325 bool have_field_width, int field_width,
326 bool have_precision, int precision,
327 char const *argument)
329 char *p; /* Null-terminated copy of % directive. */
331 /* Create a null-terminated copy of the % directive, with an
332 intmax_t-wide length modifier substituted for any existing
333 integer length modifier. */
335 char *q;
336 char const *length_modifier;
337 size_t length_modifier_len;
339 switch (conversion)
341 case 'd': case 'i': case 'o': case 'u': case 'x': case 'X':
342 length_modifier = PRIdMAX;
343 length_modifier_len = sizeof PRIdMAX - 2;
344 break;
346 case 'a': case 'e': case 'f': case 'g':
347 case 'A': case 'E': case 'F': case 'G':
348 length_modifier = "L";
349 length_modifier_len = 1;
350 break;
352 default:
353 length_modifier = start; /* Any valid pointer will do. */
354 length_modifier_len = 0;
355 break;
358 p = xmalloc (length + length_modifier_len + 2);
359 q = mempcpy (p, start, length);
360 q = mempcpy (q, length_modifier, length_modifier_len);
361 *q++ = conversion;
362 *q = '\0';
365 switch (conversion)
367 case 'd':
368 case 'i':
370 intmax_t arg = vstrtoimax (argument);
371 if (!have_field_width)
373 if (!have_precision)
374 xprintf (p, arg);
375 else
376 xprintf (p, precision, arg);
378 else
380 if (!have_precision)
381 xprintf (p, field_width, arg);
382 else
383 xprintf (p, field_width, precision, arg);
386 break;
388 case 'o':
389 case 'u':
390 case 'x':
391 case 'X':
393 uintmax_t arg = vstrtoumax (argument);
394 if (!have_field_width)
396 if (!have_precision)
397 xprintf (p, arg);
398 else
399 xprintf (p, precision, arg);
401 else
403 if (!have_precision)
404 xprintf (p, field_width, arg);
405 else
406 xprintf (p, field_width, precision, arg);
409 break;
411 case 'a':
412 case 'A':
413 case 'e':
414 case 'E':
415 case 'f':
416 case 'F':
417 case 'g':
418 case 'G':
420 long double arg = vstrtold (argument);
421 if (!have_field_width)
423 if (!have_precision)
424 xprintf (p, arg);
425 else
426 xprintf (p, precision, arg);
428 else
430 if (!have_precision)
431 xprintf (p, field_width, arg);
432 else
433 xprintf (p, field_width, precision, arg);
436 break;
438 case 'c':
439 if (!have_field_width)
440 xprintf (p, *argument);
441 else
442 xprintf (p, field_width, *argument);
443 break;
445 case 's':
446 if (!have_field_width)
448 if (!have_precision)
449 xprintf (p, argument);
450 else
451 xprintf (p, precision, argument);
453 else
455 if (!have_precision)
456 xprintf (p, field_width, argument);
457 else
458 xprintf (p, field_width, precision, argument);
460 break;
463 free (p);
466 /* Print the text in FORMAT, using ARGV (with ARGC elements) for
467 arguments to any '%' directives.
468 Return the number of elements of ARGV used. */
470 static int
471 print_formatted (const char *format, int argc, char **argv)
473 int save_argc = argc; /* Preserve original value. */
474 const char *f; /* Pointer into 'format'. */
475 const char *direc_start; /* Start of % directive. */
476 size_t direc_length; /* Length of % directive. */
477 bool have_field_width; /* True if FIELD_WIDTH is valid. */
478 int field_width = 0; /* Arg to first '*'. */
479 bool have_precision; /* True if PRECISION is valid. */
480 int precision = 0; /* Arg to second '*'. */
481 char ok[UCHAR_MAX + 1]; /* ok['x'] is true if %x is allowed. */
483 for (f = format; *f; ++f)
485 switch (*f)
487 case '%':
488 direc_start = f++;
489 direc_length = 1;
490 have_field_width = have_precision = false;
491 if (*f == '%')
493 putchar ('%');
494 break;
496 if (*f == 'b')
498 /* FIXME: Field width and precision are not supported
499 for %b, even though POSIX requires it. */
500 if (argc > 0)
502 print_esc_string (*argv);
503 ++argv;
504 --argc;
506 break;
509 memset (ok, 0, sizeof ok);
510 ok['a'] = ok['A'] = ok['c'] = ok['d'] = ok['e'] = ok['E'] =
511 ok['f'] = ok['F'] = ok['g'] = ok['G'] = ok['i'] = ok['o'] =
512 ok['s'] = ok['u'] = ok['x'] = ok['X'] = 1;
514 for (;; f++, direc_length++)
515 switch (*f)
517 #if (__GLIBC__ == 2 && 2 <= __GLIBC_MINOR__) || 3 <= __GLIBC__
518 case 'I':
519 #endif
520 case '\'':
521 ok['a'] = ok['A'] = ok['c'] = ok['e'] = ok['E'] =
522 ok['o'] = ok['s'] = ok['x'] = ok['X'] = 0;
523 break;
524 case '-': case '+': case ' ':
525 break;
526 case '#':
527 ok['c'] = ok['d'] = ok['i'] = ok['s'] = ok['u'] = 0;
528 break;
529 case '0':
530 ok['c'] = ok['s'] = 0;
531 break;
532 default:
533 goto no_more_flag_characters;
535 no_more_flag_characters:
537 if (*f == '*')
539 ++f;
540 ++direc_length;
541 if (argc > 0)
543 intmax_t width = vstrtoimax (*argv);
544 if (INT_MIN <= width && width <= INT_MAX)
545 field_width = width;
546 else
547 error (EXIT_FAILURE, 0, _("invalid field width: %s"),
548 *argv);
549 ++argv;
550 --argc;
552 else
553 field_width = 0;
554 have_field_width = true;
556 else
557 while (ISDIGIT (*f))
559 ++f;
560 ++direc_length;
562 if (*f == '.')
564 ++f;
565 ++direc_length;
566 ok['c'] = 0;
567 if (*f == '*')
569 ++f;
570 ++direc_length;
571 if (argc > 0)
573 intmax_t prec = vstrtoimax (*argv);
574 if (prec < 0)
576 /* A negative precision is taken as if the
577 precision were omitted, so -1 is safe
578 here even if prec < INT_MIN. */
579 precision = -1;
581 else if (INT_MAX < prec)
582 error (EXIT_FAILURE, 0, _("invalid precision: %s"),
583 *argv);
584 else
585 precision = prec;
586 ++argv;
587 --argc;
589 else
590 precision = 0;
591 have_precision = true;
593 else
594 while (ISDIGIT (*f))
596 ++f;
597 ++direc_length;
601 while (*f == 'l' || *f == 'L' || *f == 'h'
602 || *f == 'j' || *f == 't' || *f == 'z')
603 ++f;
606 unsigned char conversion = *f;
607 if (! ok[conversion])
608 error (EXIT_FAILURE, 0,
609 _("%.*s: invalid conversion specification"),
610 (int) (f + 1 - direc_start), direc_start);
613 print_direc (direc_start, direc_length, *f,
614 have_field_width, field_width,
615 have_precision, precision,
616 (argc <= 0 ? "" : (argc--, *argv++)));
617 break;
619 case '\\':
620 f += print_esc (f, false);
621 break;
623 default:
624 putchar (*f);
628 return save_argc - argc;
632 main (int argc, char **argv)
634 char *format;
635 int args_used;
637 initialize_main (&argc, &argv);
638 set_program_name (argv[0]);
639 setlocale (LC_ALL, "");
640 bindtextdomain (PACKAGE, LOCALEDIR);
641 textdomain (PACKAGE);
643 atexit (close_stdout);
645 exit_status = EXIT_SUCCESS;
647 posixly_correct = (getenv ("POSIXLY_CORRECT") != NULL);
649 /* We directly parse options, rather than use parse_long_options, in
650 order to avoid accepting abbreviations. */
651 if (argc == 2)
653 if (STREQ (argv[1], "--help"))
654 usage (EXIT_SUCCESS);
656 if (STREQ (argv[1], "--version"))
658 version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, Version, AUTHORS,
659 (char *) NULL);
660 exit (EXIT_SUCCESS);
664 /* The above handles --help and --version.
665 Since there is no other invocation of getopt, handle '--' here. */
666 if (1 < argc && STREQ (argv[1], "--"))
668 --argc;
669 ++argv;
672 if (argc <= 1)
674 error (0, 0, _("missing operand"));
675 usage (EXIT_FAILURE);
678 format = argv[1];
679 argc -= 2;
680 argv += 2;
684 args_used = print_formatted (format, argc, argv);
685 argc -= args_used;
686 argv += args_used;
688 while (args_used > 0 && argc > 0);
690 if (argc > 0)
691 error (0, 0,
692 _("warning: ignoring excess arguments, starting with %s"),
693 quote (argv[0]));
695 exit (exit_status);