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 1, 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 char *bexpand __P((char *, int, int *, int *));
84 static char *mklong __P((char *, int));
85 static int getchr __P((void));
86 static char *getstr __P((void));
87 static int getint __P((void));
88 static int getlong __P((long *));
89 static int getulong __P((unsigned long *));
90 static double getdouble __P((void));
91 static int asciicode __P((void));
93 static WORD_LIST *garglist;
96 extern char *backslash_quote ();
102 int ch, end, fieldwidth, precision, foundmod;
103 char convch, nextch, *format, *fmt, *start;
105 retval = EXECUTION_SUCCESS;
106 reset_internal_getopt ();
107 while ((ch = internal_getopt (list, "")) != -1)
125 if (list->word->word == 0 || list->word->word[0] == '\0')
126 return (EXECUTION_SUCCESS);
128 format = ansicstr (list->word->word, strlen (list->word->word), (int *)NULL, (int *)NULL);
130 garglist = list->next;
132 /* If the format string is empty after preprocessing, return immediately. */
133 if (format == 0 || *format == 0)
134 return (EXECUTION_SUCCESS);
136 /* Basic algorithm is to scan the format string for conversion
137 specifications -- once one is found, find out if the field
138 width or precision is a '*'; if it is, gather up value. Note,
139 format strings are reused as necessary to use up the provided
140 arguments, arguments of zero/null string are provided to use
141 up the format string. */
145 /* find next format specification */
146 for (fmt = format; *fmt; fmt++)
148 precision = fieldwidth = foundmod = 0;
156 /* ASSERT(*fmt == '%') */
159 if (*fmt == '%') /* %% prints a % */
165 /* found format specification, skip to field width */
166 for (; *fmt && strchr(SKIP1, *fmt); ++fmt)
168 fieldwidth = (*fmt == '*') ? getint () : 0;
170 /* skip to possible '.', get following precision */
171 for (; *fmt && strchr(SKIP2, *fmt); ++fmt)
176 precision = (*fmt == '*') ? getint () : 0;
179 /* skip to conversion char */
180 for (; *fmt && strchr(SKIP2, *fmt); ++fmt)
184 builtin_error ("`%s': missing format character", start);
185 PRETURN (EXECUTION_FAILURE);
188 /* skip possible format modifiers */
189 if (*fmt == 'l' || *fmt == 'L' || *fmt == 'h')
218 case 'b': /* expand escapes in argument */
225 xp = bexpand (p, strlen (p), &ch, &rlen);
229 /* Have to use printstr because of possible NUL bytes
230 in XP -- printf does not handle that well. */
231 printstr (start, xp, rlen, fieldwidth, precision);
240 case 'q': /* print with shell quoting */
245 xp = backslash_quote (p);
248 /* Use printstr to get fieldwidth and precision right. */
249 printstr (start, xp, strlen (xp), fieldwidth, precision);
261 if (foundmod == 0 && ((f = mklong (start, convch)) == NULL))
262 PRETURN (EXECUTION_FAILURE);
266 PRETURN (EXECUTION_FAILURE);
279 if (foundmod == 0 && ((f = mklong (start, convch)) == NULL))
280 PRETURN (EXECUTION_FAILURE);
284 PRETURN (EXECUTION_FAILURE);
302 /* We output unrecognized format characters, but we print a
303 warning message and return a failure exit status. */
305 builtin_error ("`%c': illegal format character", convch);
306 PRETURN (EXECUTION_FAILURE);
312 while (garglist && garglist != list->next);
317 /* We duplicate a lot of what printf(3) does here. */
319 printstr (fmt, string, len, fieldwidth, precision)
320 char *fmt; /* format */
321 char *string; /* expanded string argument */
322 int len; /* length of expanded string */
323 int fieldwidth; /* argument for width of `*' */
324 int precision; /* argument for precision of `*' */
329 int padlen, nc, ljust, i;
330 int fw, pr; /* fieldwidth and precision */
332 if (string == 0 || *string == '\0')
344 while (*fmt == '#' || *fmt == '-' || *fmt == '+' || *fmt == ' ' || *fmt == '0')
351 /* get fieldwidth, if present */
357 else if (isdigit (*fmt))
360 while (isdigit (*fmt))
361 fw = (fw * 10) + (*fmt++ - '0');
364 /* get precision, if present */
373 else if (isdigit (*fmt))
376 while (isdigit (*fmt))
377 pr = (pr * 10) + (*fmt++ - '0');
382 /* If we remove this, get rid of `s'. */
383 if (*fmt != 'b' && *fmt != 'q')
385 internal_error ("format parsing problem: %s", s);
390 /* chars from string to print */
391 nc = (pr > 0 && pr <= len) ? pr : len;
399 /* leading pad characters */
400 for (; padlen > 0; padlen--)
403 /* output NC characters from STRING */
404 for (i = 0; i < nc; i++)
407 /* output any necessary trailing padding */
408 for (; padlen < 0; padlen++)
412 /* Convert STRING by expanding the escape sequences specified by the
413 POSIX standard for printf's `%b' format string. If SAWC is non-null,
414 recognize `\c' and use that as a string terminator. If we see \c, set
415 *SAWC to 1 before returning. LEN is the length of STRING. */
421 #define isoctal(c) ((c) >= '0' && (c) <= '7')
423 #define OCTVALUE(c) ((c) - '0')
426 # define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
429 #define HEXVALUE(c) \
430 ((c) >= 'a' && (c) <= 'f' ? (c)-'a'+10 : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0')
433 bexpand (string, len, sawc, lenp)
435 int len, *sawc, *lenp;
440 if (string == 0 || *string == '\0')
446 return ((char *)NULL);
449 ret = xmalloc (len + 1);
450 for (r = ret, s = string; s && *s; )
453 if (c != '\\' || *s == '\0')
461 #if defined (__STDC__)
462 case 'a': c = '\a'; break;
464 case 'a': c = '\007'; break;
467 case 'b': c = '\b'; break;
469 case 'e': c = '\033'; break; /* ESC -- non-ANSI */
471 case 'f': c = '\f'; break;
473 case 'n': c = '\n'; break;
475 case 'r': c = '\r'; break;
477 case 't': c = '\t'; break;
479 case 'v': c = '\v'; break;
481 /* %b octal constants are `\0' followed by one, two, or three
484 for (temp = 3, c = 0; isoctal (*s) && temp--; s++)
485 c = (c * 8) + OCTVALUE (*s);
488 /* but, as an extension, the other echo-like octal escape
489 sequences are supported as well. */
490 case '1': case '2': case '3': case '4':
491 case '5': case '6': case '7':
492 for (temp = 2, c -= '0'; isoctal (*s) && temp--; s++)
493 c = (c * 8) + OCTVALUE (*s);
496 /* And, as another extension, we allow \xNNN, where each N is a
499 for (temp = 3, c = 0; isxdigit (*s) && temp--; s++)
500 c = (c * 16) + HEXVALUE (*s);
503 builtin_error ("missing hex digit for \\x");
524 /* other backslash escapes are passed through unaltered */
525 default: *r++ = '\\'; break;
542 static char copy[64];
545 len = strlen (str) + 2;
546 FASTCOPY (str, copy, len - 3);
549 copy[len - 1] = '\0';
561 ret = (int)garglist->word->word[0];
562 garglist = garglist->next;
574 ret = garglist->word->word;
575 garglist = garglist->next;
589 builtin_error ("%s: %s", garglist->word->word, strerror(ERANGE));
608 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
610 *lp = (long)asciicode ();
615 /* legal_number does not currently detect overflow, but it should.
617 if (legal_number (garglist->word->word, &ret) == 0)
619 builtin_error ("%s: illegal number", garglist->word->word);
622 else if (errno == ERANGE)
624 builtin_error ("%s: %s", garglist->word->word, strerror(ERANGE));
629 garglist = garglist->next;
642 *ulp = (unsigned long)0;
646 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
648 *ulp = (unsigned long)asciicode ();
653 ret = strtoul (garglist->word->word, &ep, 0);
657 builtin_error ("%s: illegal number", garglist->word->word);
660 else if (errno == ERANGE)
662 builtin_error ("%s: %s", garglist->word->word, strerror(ERANGE));
667 garglist = garglist->next;
679 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
680 return ((double)asciicode ());
682 /* This should use strtod if it is available. */
683 ret = atof (garglist->word->word);
684 garglist = garglist->next;
688 /* NO check is needed for garglist here. */
694 ch = garglist->word->word[1];
695 garglist = garglist->next;