TODO: add an item for a chmod optimization
[platform/upstream/coreutils.git] / src / printf.c
1 /* printf - format and print data
2    Copyright (C) 1990-2008 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>.  */
16
17 /* Usage: printf format [argument...]
18
19    A front end to the printf function that lets it be used from the shell.
20
21    Backslash escapes:
22
23    \" = double quote
24    \\ = backslash
25    \a = alert (bell)
26    \b = backspace
27    \c = produce no further output
28    \f = form feed
29    \n = new line
30    \r = carriage return
31    \t = horizontal tab
32    \v = vertical tab
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)
37
38    Additional directive:
39
40    %b = print an argument string, interpreting backslash escapes,
41      except that octal escapes are of the form \0 or \0ooo.
42
43    The `format' argument is re-used as many times as necessary
44    to convert all of the given arguments.
45
46    David MacKenzie <djm@gnu.ai.mit.edu> */
47
48 #include <config.h>
49 #include <stdio.h>
50 #include <sys/types.h>
51
52 #include "system.h"
53 #include "c-strtod.h"
54 #include "error.h"
55 #include "long-options.h"
56 #include "quote.h"
57 #include "unicodeio.h"
58 #include "xprintf.h"
59
60 /* The official name of this program (e.g., no `g' prefix).  */
61 #define PROGRAM_NAME "printf"
62
63 #define AUTHORS proper_name ("David MacKenzie")
64
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')
69
70 /* The value to return to the calling program.  */
71 static int exit_status;
72
73 /* True if the POSIXLY_CORRECT environment variable is set.  */
74 static bool posixly_correct;
75
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");
80
81 void
82 usage (int status)
83 {
84   if (status != EXIT_SUCCESS)
85     fprintf (stderr, _("Try `%s --help' for more information.\n"),
86              program_name);
87   else
88     {
89       printf (_("\
90 Usage: %s FORMAT [ARGUMENT]...\n\
91   or:  %s OPTION\n\
92 "),
93               program_name, program_name);
94       fputs (_("\
95 Print ARGUMENT(s) according to FORMAT, or execute according to OPTION:\n\
96 \n\
97 "), stdout);
98       fputs (HELP_OPTION_DESCRIPTION, stdout);
99       fputs (VERSION_OPTION_DESCRIPTION, stdout);
100       fputs (_("\
101 \n\
102 FORMAT controls the output as in C printf.  Interpreted sequences are:\n\
103 \n\
104   \\\"      double quote\n\
105   \\NNN    character with octal value NNN (1 to 3 digits)\n\
106   \\\\      backslash\n\
107 "), stdout);
108       fputs (_("\
109   \\a      alert (BEL)\n\
110   \\b      backspace\n\
111   \\c      produce no further output\n\
112   \\f      form feed\n\
113 "), stdout);
114       fputs (_("\
115   \\n      new line\n\
116   \\r      carriage return\n\
117   \\t      horizontal tab\n\
118   \\v      vertical tab\n\
119 "), stdout);
120       fputs (_("\
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\
124 "), stdout);
125       fputs (_("\
126   %%      a single %\n\
127   %b      ARGUMENT as a string with `\\' escapes interpreted,\n\
128           except that octal escapes are of the form \\0 or \\0NNN\n\
129 \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\
132 "), stdout);
133       printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
134       emit_bug_reporting_address ();
135     }
136   exit (status);
137 }
138
139 static void
140 verify_numeric (const char *s, const char *end)
141 {
142   if (errno)
143     {
144       error (0, errno, "%s", s);
145       exit_status = EXIT_FAILURE;
146     }
147   else if (*end)
148     {
149       if (s == end)
150         error (0, 0, _("%s: expected a numeric value"), s);
151       else
152         error (0, 0, _("%s: value not completely converted"), s);
153       exit_status = EXIT_FAILURE;
154     }
155 }
156
157 #define STRTOX(TYPE, FUNC_NAME, LIB_FUNC_EXPR)                           \
158 static TYPE                                                              \
159 FUNC_NAME (char const *s)                                                \
160 {                                                                        \
161   char *end;                                                             \
162   TYPE val;                                                              \
163                                                                          \
164   if (*s == '\"' || *s == '\'')                                          \
165     {                                                                    \
166       unsigned char ch = *++s;                                           \
167       val = ch;                                                          \
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);                                    \
174     }                                                                    \
175   else                                                                   \
176     {                                                                    \
177       errno = 0;                                                         \
178       val = (LIB_FUNC_EXPR);                                             \
179       verify_numeric (s, end);                                           \
180     }                                                                    \
181   return val;                                                            \
182 }                                                                        \
183
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))
187
188 /* Output a single-character \ escape.  */
189
190 static void
191 print_esc_char (char c)
192 {
193   switch (c)
194     {
195     case 'a':                   /* Alert. */
196       putchar ('\a');
197       break;
198     case 'b':                   /* Backspace. */
199       putchar ('\b');
200       break;
201     case 'c':                   /* Cancel the rest of the output. */
202       exit (EXIT_SUCCESS);
203       break;
204     case 'f':                   /* Form feed. */
205       putchar ('\f');
206       break;
207     case 'n':                   /* New line. */
208       putchar ('\n');
209       break;
210     case 'r':                   /* Carriage return. */
211       putchar ('\r');
212       break;
213     case 't':                   /* Horizontal tab. */
214       putchar ('\t');
215       break;
216     case 'v':                   /* Vertical tab. */
217       putchar ('\v');
218       break;
219     default:
220       putchar (c);
221       break;
222     }
223 }
224
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.  */
230
231 static int
232 print_esc (const char *escstart, bool octal_0)
233 {
234   const char *p = escstart + 1;
235   int esc_value = 0;            /* Value of \nnn escape. */
236   int esc_length;               /* Length of \nnn escape. */
237
238   if (*p == 'x')
239     {
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));
243            ++esc_length, ++p)
244         esc_value = esc_value * 16 + hextobin (*p);
245       if (esc_length == 0)
246         error (EXIT_FAILURE, 0, _("missing hexadecimal number in escape"));
247       putchar (esc_value);
248     }
249   else if (isodigit (*p))
250     {
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);
256            ++esc_length, ++p)
257         esc_value = esc_value * 8 + octtobin (*p);
258       putchar (esc_value);
259     }
260   else if (*p && strchr ("\"\\abcfnrtv", *p))
261     print_esc_char (*p++);
262   else if (*p == 'u' || *p == 'U')
263     {
264       char esc_char = *p;
265       unsigned int uni_value;
266
267       uni_value = 0;
268       for (esc_length = (esc_char == 'u' ? 4 : 8), ++p;
269            esc_length > 0;
270            --esc_length, ++p)
271         {
272           if (! isxdigit (to_uchar (*p)))
273             error (EXIT_FAILURE, 0, _("missing hexadecimal number in escape"));
274           uni_value = uni_value * 16 + hextobin (*p);
275         }
276
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
281          character set.  */
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);
287
288       print_unicode_char (stdout, uni_value, 0);
289     }
290   else
291     {
292       putchar ('\\');
293       if (*p)
294         {
295           putchar (*p);
296           p++;
297         }
298     }
299   return p - escstart - 1;
300 }
301
302 /* Print string STR, evaluating \ escapes. */
303
304 static void
305 print_esc_string (const char *str)
306 {
307   for (; *str; str++)
308     if (*str == '\\')
309       str += print_esc (str, true);
310     else
311       putchar (*str);
312 }
313
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
320    be formatted.  */
321
322 static void
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)
327 {
328   char *p;              /* Null-terminated copy of % directive. */
329
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.  */
333   {
334     char *q;
335     char const *length_modifier;
336     size_t length_modifier_len;
337
338     switch (conversion)
339       {
340       case 'd': case 'i': case 'o': case 'u': case 'x': case 'X':
341         length_modifier = PRIdMAX;
342         length_modifier_len = sizeof PRIdMAX - 2;
343         break;
344
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;
349         break;
350
351       default:
352         length_modifier = start;  /* Any valid pointer will do.  */
353         length_modifier_len = 0;
354         break;
355       }
356
357     p = xmalloc (length + length_modifier_len + 2);
358     q = mempcpy (p, start, length);
359     q = mempcpy (q, length_modifier, length_modifier_len);
360     *q++ = conversion;
361     *q = '\0';
362   }
363
364   switch (conversion)
365     {
366     case 'd':
367     case 'i':
368       {
369         intmax_t arg = vstrtoimax (argument);
370         if (!have_field_width)
371           {
372             if (!have_precision)
373               xprintf (p, arg);
374             else
375               xprintf (p, precision, arg);
376           }
377         else
378           {
379             if (!have_precision)
380               xprintf (p, field_width, arg);
381             else
382               xprintf (p, field_width, precision, arg);
383           }
384       }
385       break;
386
387     case 'o':
388     case 'u':
389     case 'x':
390     case 'X':
391       {
392         uintmax_t arg = vstrtoumax (argument);
393         if (!have_field_width)
394           {
395             if (!have_precision)
396               xprintf (p, arg);
397             else
398               xprintf (p, precision, arg);
399           }
400         else
401           {
402             if (!have_precision)
403               xprintf (p, field_width, arg);
404             else
405               xprintf (p, field_width, precision, arg);
406           }
407       }
408       break;
409
410     case 'a':
411     case 'A':
412     case 'e':
413     case 'E':
414     case 'f':
415     case 'F':
416     case 'g':
417     case 'G':
418       {
419         long double arg = vstrtold (argument);
420         if (!have_field_width)
421           {
422             if (!have_precision)
423               xprintf (p, arg);
424             else
425               xprintf (p, precision, arg);
426           }
427         else
428           {
429             if (!have_precision)
430               xprintf (p, field_width, arg);
431             else
432               xprintf (p, field_width, precision, arg);
433           }
434       }
435       break;
436
437     case 'c':
438       if (!have_field_width)
439         xprintf (p, *argument);
440       else
441         xprintf (p, field_width, *argument);
442       break;
443
444     case 's':
445       if (!have_field_width)
446         {
447           if (!have_precision)
448             xprintf (p, argument);
449           else
450             xprintf (p, precision, argument);
451         }
452       else
453         {
454           if (!have_precision)
455             xprintf (p, field_width, argument);
456           else
457             xprintf (p, field_width, precision, argument);
458         }
459       break;
460     }
461
462   free (p);
463 }
464
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.  */
468
469 static int
470 print_formatted (const char *format, int argc, char **argv)
471 {
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.  */
481
482   for (f = format; *f; ++f)
483     {
484       switch (*f)
485         {
486         case '%':
487           direc_start = f++;
488           direc_length = 1;
489           have_field_width = have_precision = false;
490           if (*f == '%')
491             {
492               putchar ('%');
493               break;
494             }
495           if (*f == 'b')
496             {
497               /* FIXME: Field width and precision are not supported
498                  for %b, even though POSIX requires it.  */
499               if (argc > 0)
500                 {
501                   print_esc_string (*argv);
502                   ++argv;
503                   --argc;
504                 }
505               break;
506             }
507
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;
512
513           for (;; f++, direc_length++)
514             switch (*f)
515               {
516 #if (__GLIBC__ == 2 && 2 <= __GLIBC_MINOR__) || 3 <= __GLIBC__
517               case 'I':
518 #endif
519               case '\'':
520                 ok['a'] = ok['A'] = ok['c'] = ok['e'] = ok['E'] =
521                   ok['o'] = ok['s'] = ok['x'] = ok['X'] = 0;
522                 break;
523               case '-': case '+': case ' ':
524                 break;
525               case '#':
526                 ok['c'] = ok['d'] = ok['i'] = ok['s'] = ok['u'] = 0;
527                 break;
528               case '0':
529                 ok['c'] = ok['s'] = 0;
530                 break;
531               default:
532                 goto no_more_flag_characters;
533               }
534         no_more_flag_characters:;
535
536           if (*f == '*')
537             {
538               ++f;
539               ++direc_length;
540               if (argc > 0)
541                 {
542                   intmax_t width = vstrtoimax (*argv);
543                   if (INT_MIN <= width && width <= INT_MAX)
544                     field_width = width;
545                   else
546                     error (EXIT_FAILURE, 0, _("invalid field width: %s"),
547                            *argv);
548                   ++argv;
549                   --argc;
550                 }
551               else
552                 field_width = 0;
553               have_field_width = true;
554             }
555           else
556             while (ISDIGIT (*f))
557               {
558                 ++f;
559                 ++direc_length;
560               }
561           if (*f == '.')
562             {
563               ++f;
564               ++direc_length;
565               ok['c'] = 0;
566               if (*f == '*')
567                 {
568                   ++f;
569                   ++direc_length;
570                   if (argc > 0)
571                     {
572                       intmax_t prec = vstrtoimax (*argv);
573                       if (prec < 0)
574                         {
575                           /* A negative precision is taken as if the
576                              precision were omitted, so -1 is safe
577                              here even if prec < INT_MIN.  */
578                           precision = -1;
579                         }
580                       else if (INT_MAX < prec)
581                         error (EXIT_FAILURE, 0, _("invalid precision: %s"),
582                                *argv);
583                       else
584                         precision = prec;
585                       ++argv;
586                       --argc;
587                     }
588                   else
589                     precision = 0;
590                   have_precision = true;
591                 }
592               else
593                 while (ISDIGIT (*f))
594                   {
595                     ++f;
596                     ++direc_length;
597                   }
598             }
599
600           while (*f == 'l' || *f == 'L' || *f == 'h'
601                  || *f == 'j' || *f == 't' || *f == 'z')
602             ++f;
603
604           {
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);
610           }
611
612           print_direc (direc_start, direc_length, *f,
613                        have_field_width, field_width,
614                        have_precision, precision,
615                        (argc <= 0 ? "" : (argc--, *argv++)));
616           break;
617
618         case '\\':
619           f += print_esc (f, false);
620           break;
621
622         default:
623           putchar (*f);
624         }
625     }
626
627   return save_argc - argc;
628 }
629
630 int
631 main (int argc, char **argv)
632 {
633   char *format;
634   int args_used;
635
636   initialize_main (&argc, &argv);
637   set_program_name (argv[0]);
638   setlocale (LC_ALL, "");
639   bindtextdomain (PACKAGE, LOCALEDIR);
640   textdomain (PACKAGE);
641
642   atexit (close_stdout);
643
644   exit_status = EXIT_SUCCESS;
645
646   posixly_correct = (getenv ("POSIXLY_CORRECT") != NULL);
647
648   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
649                       usage, AUTHORS, (char const *) NULL);
650
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], "--"))
654     {
655       --argc;
656       ++argv;
657     }
658
659   if (argc <= 1)
660     {
661       error (0, 0, _("missing operand"));
662       usage (EXIT_FAILURE);
663     }
664
665   format = argv[1];
666   argc -= 2;
667   argv += 2;
668
669   do
670     {
671       args_used = print_formatted (format, argc, argv);
672       argc -= args_used;
673       argv += args_used;
674     }
675   while (args_used > 0 && argc > 0);
676
677   if (argc > 0)
678     error (0, 0,
679            _("warning: ignoring excess arguments, starting with %s"),
680            quote (argv[0]));
681
682   exit (exit_status);
683 }