1 This file is printf.def, from which is created printf.c.
2 It implements the builtin "printf" in Bash.
4 Copyright (C) 1997 Free Software Foundation, Inc.
6 This file is part of GNU Bash, the Bourne Again SHell.
8 Bash is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING. If not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
25 $FUNCTION printf_builtin
26 $SHORT_DOC printf format [arguments]
27 printf formats and prints ARGUMENTS under control of the FORMAT. FORMAT
28 is a character string which contains three types of objects: plain
29 characters, which are simply copied to standard output, character escape
30 sequences which are converted and copied to the standard output, and
31 format specifications, each of which causes printing of the next successive
32 argument. In addition to the standard printf(1) formats, %b means to
33 expand backslash escape sequences in the corresponding argument, and %q
34 means to quote the argument in a way that can be reused as shell input.
39 #include "../bashtypes.h"
42 #if defined (HAVE_LIMITS_H)
45 /* Assume 32-bit ints and longs. */
46 # define LONG_MAX 2147483647L
47 # define LONG_MIN (-2147483647L-1)
48 # define INT_MAX 2147483647
49 # define INT_MIN (-2147483647-1)
55 #include "../bashansi.h"
58 #include "bashgetopt.h"
66 if (fieldwidth && precision) \
67 (void)printf(f, fieldwidth, precision, func); \
68 else if (fieldwidth && precision == 0) \
69 (void)printf(f, fieldwidth, func); \
71 (void)printf(f, precision, func); \
73 (void)printf(f, func); \
76 #define PRETURN(value) \
77 do { /* free (format); */ fflush (stdout); return (value); } while (0)
80 #define SKIP2 "*0123456789"
82 static void printstr __P((char *, char *, int, int, int));
83 static int tescape __P((char *, int, char *, int *));
84 static char *bexpand __P((char *, int, int *, int *));
85 static char *mklong __P((char *, int));
86 static int getchr __P((void));
87 static char *getstr __P((void));
88 static int getint __P((void));
89 static int getlong __P((long *));
90 static int getulong __P((unsigned long *));
91 static int getdouble __P((double *));
92 static int asciicode __P((void));
94 static WORD_LIST *garglist;
97 extern char *sh_backslash_quote ();
100 printf_builtin (list)
103 int ch, end, fieldwidth, precision, foundmod, fmtlen;
104 char convch, nextch, *format, *fmt, *start;
106 retval = EXECUTION_SUCCESS;
107 reset_internal_getopt ();
108 while ((ch = internal_getopt (list, "")) != -1)
126 if (list->word->word == 0 || list->word->word[0] == '\0')
127 return (EXECUTION_SUCCESS);
129 format = list->word->word;
131 garglist = list->next;
133 /* If the format string is empty after preprocessing, return immediately. */
134 if (format == 0 || *format == 0)
135 return (EXECUTION_SUCCESS);
137 /* Basic algorithm is to scan the format string for conversion
138 specifications -- once one is found, find out if the field
139 width or precision is a '*'; if it is, gather up value. Note,
140 format strings are reused as necessary to use up the provided
141 arguments, arguments of zero/null string are provided to use
142 up the format string. */
146 /* find next format specification */
147 for (fmt = format; *fmt; fmt++)
149 precision = fieldwidth = foundmod = 0;
154 /* A NULL third argument to tescape means to not do special
155 processing for \c. */
156 fmt += tescape (fmt, 1, &nextch, (int *)NULL);
158 fmt--; /* for loop will increment it for us again */
168 /* ASSERT(*fmt == '%') */
171 if (*fmt == '%') /* %% prints a % */
177 /* found format specification, skip to field width */
178 for (; *fmt && strchr(SKIP1, *fmt); ++fmt)
180 fieldwidth = (*fmt == '*') ? getint () : 0;
182 /* skip to possible '.', get following precision */
183 for (; *fmt && strchr(SKIP2, *fmt); ++fmt)
188 precision = (*fmt == '*') ? getint () : 0;
191 /* skip to conversion char */
192 for (; *fmt && strchr(SKIP2, *fmt); ++fmt)
195 /* skip possible format modifiers */
196 if (*fmt == 'l' || *fmt == 'L' || *fmt == 'h')
204 builtin_error ("`%s': missing format character", start);
205 PRETURN (EXECUTION_FAILURE);
231 case 'b': /* expand escapes in argument */
238 xp = bexpand (p, strlen (p), &ch, &rlen);
242 /* Have to use printstr because of possible NUL bytes
243 in XP -- printf does not handle that well. */
244 printstr (start, xp, rlen, fieldwidth, precision);
253 case 'q': /* print with shell quoting */
258 xp = sh_backslash_quote (p);
261 /* Use printstr to get fieldwidth and precision right. */
262 printstr (start, xp, strlen (xp), fieldwidth, precision);
274 if (foundmod == 0 && ((f = mklong (start, convch)) == NULL))
275 PRETURN (EXECUTION_FAILURE);
279 PRETURN (EXECUTION_FAILURE);
292 if (foundmod == 0 && ((f = mklong (start, convch)) == NULL))
293 PRETURN (EXECUTION_FAILURE);
297 PRETURN (EXECUTION_FAILURE);
311 PRETURN (EXECUTION_FAILURE);
316 /* We don't output unrecognized format characters; we print an
317 error message and return a failure exit status. */
319 builtin_error ("`%c': invalid format character", convch);
320 PRETURN (EXECUTION_FAILURE);
326 while (garglist && garglist != list->next);
331 /* We duplicate a lot of what printf(3) does here. */
333 printstr (fmt, string, len, fieldwidth, precision)
334 char *fmt; /* format */
335 char *string; /* expanded string argument */
336 int len; /* length of expanded string */
337 int fieldwidth; /* argument for width of `*' */
338 int precision; /* argument for precision of `*' */
343 int padlen, nc, ljust, i;
344 int fw, pr; /* fieldwidth and precision */
346 if (string == 0 || *string == '\0')
358 while (*fmt == '#' || *fmt == '-' || *fmt == '+' || *fmt == ' ' || *fmt == '0')
365 /* get fieldwidth, if present */
371 else if (isdigit (*fmt))
374 while (isdigit (*fmt))
375 fw = (fw * 10) + (*fmt++ - '0');
378 /* get precision, if present */
387 else if (isdigit (*fmt))
390 while (isdigit (*fmt))
391 pr = (pr * 10) + (*fmt++ - '0');
396 /* If we remove this, get rid of `s'. */
397 if (*fmt != 'b' && *fmt != 'q')
399 internal_error ("format parsing problem: %s", s);
404 /* chars from string to print */
405 nc = (pr > 0 && pr <= len) ? pr : len;
413 /* leading pad characters */
414 for (; padlen > 0; padlen--)
417 /* output NC characters from STRING */
418 for (i = 0; i < nc; i++)
421 /* output any necessary trailing padding */
422 for (; padlen < 0; padlen++)
426 /* Convert STRING by expanding the escape sequences specified by the
427 POSIX standard for printf's `%b' format string. If SAWC is non-null,
428 recognize `\c' and use that as a string terminator. If we see \c, set
429 *SAWC to 1 before returning. LEN is the length of STRING. */
435 #define isoctal(c) ((c) >= '0' && (c) <= '7')
437 #define OCTVALUE(c) ((c) - '0')
440 # define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
443 #define HEXVALUE(c) \
444 ((c) >= 'a' && (c) <= 'f' ? (c)-'a'+10 : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0')
446 /* Translate a single backslash-escape sequence starting at ESTART (the
447 character after the backslash) and return the number of characters
448 consumed by the sequence. CP is the place to return the translated
449 value. *SAWC is set to 1 if the escape sequence was \c, since that means
450 to short-circuit the rest of the processing. If SAWC is null, we don't
451 do the \c short-circuiting, and \c is treated as an unrecognized escape
454 tescape (estart, trans_squote, cp, sawc)
467 #if defined (__STDC__)
468 case 'a': *cp = '\a'; break;
470 case 'a': *cp = '\007'; break;
473 case 'b': *cp = '\b'; break;
476 case 'E': *cp = '\033'; break; /* ESC -- non-ANSI */
478 case 'f': *cp = '\f'; break;
480 case 'n': *cp = '\n'; break;
482 case 'r': *cp = '\r'; break;
484 case 't': *cp = '\t'; break;
486 case 'v': *cp = '\v'; break;
488 /* %b octal constants are `\0' followed by one, two, or three
491 for (temp = 3, evalue = 0; isoctal (*p) && temp--; p++)
492 evalue = (evalue * 8) + OCTVALUE (*p);
496 /* but, as an extension, the other echo-like octal escape
497 sequences are supported as well. */
498 case '1': case '2': case '3': case '4':
499 case '5': case '6': case '7':
500 for (temp = 2, evalue = c - '0'; isoctal (*p) && temp--; p++)
501 evalue = (evalue * 8) + OCTVALUE (*p);
505 /* And, as another extension, we allow \xNNN, where each N is a
508 for (temp = 3, evalue = 0; isxdigit (*p) && temp--; p++)
509 evalue = (evalue * 16) + HEXVALUE (*p);
512 builtin_error ("missing hex digit for \\x");
519 case '\\': /* \\ -> \ */
523 case '\'': /* TRANS_SQUOTE != 0 means \' -> ' */
539 /* other backslash escapes are passed through unaltered */
548 bexpand (string, len, sawc, lenp)
550 int len, *sawc, *lenp;
553 char *ret, *r, *s, c;
555 if (string == 0 || *string == '\0')
561 return ((char *)NULL);
564 ret = xmalloc (len + 1);
565 for (r = ret, s = string; s && *s; )
568 if (c != '\\' || *s == '\0')
574 s += tescape (s, 0, &c, &temp);
596 static char copy[64];
599 len = strlen (str) + 2;
600 FASTCOPY (str, copy, len - 3);
603 copy[len - 1] = '\0';
615 ret = (int)garglist->word->word[0];
616 garglist = garglist->next;
628 ret = garglist->word->word;
629 garglist = garglist->next;
643 builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
646 else if (ret < INT_MIN)
648 builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
668 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
670 *lp = (long)asciicode ();
675 /* If we use 0 as the third argument, we can handle octal and hex, which
676 legal_number does not. (This was
677 if (legal_number (garglist->word->word, &ret) == 0)
679 ret = strtol (garglist->word->word, &ep, 0);
682 builtin_error ("%s: invalid number", garglist->word->word);
685 else if (errno == ERANGE)
686 builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
689 garglist = garglist->next;
702 *ulp = (unsigned long)0;
706 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
708 *ulp = (unsigned long)asciicode ();
713 ret = strtoul (garglist->word->word, &ep, 0);
717 builtin_error ("%s: invalid number", garglist->word->word);
720 else if (errno == ERANGE)
721 builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
724 garglist = garglist->next;
741 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
743 *dp = (double)asciicode ();
748 ret = strtod (garglist->word->word, &ep);
751 builtin_error ("%s: invalid number", garglist->word->word);
754 else if (errno == ERANGE)
755 builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
758 garglist = garglist->next;
762 /* NO check is needed for garglist here. */
768 ch = garglist->word->word[1];
769 garglist = garglist->next;