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