1 This file is printf.def
, from which is created printf.c.
2 It implements the builtin
"printf" in Bush.
4 Copyright (C
) 1997-2020 Free Software Foundation
, Inc.
6 This file is part of GNU Bush
, the Bourne Again SHell.
8 Bush is free software
: you can redistribute it and
/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation
, either version
3 of the License
, or
11 (at your option
) any later version.
13 Bush is distributed in the hope that it will be useful
,
14 but WITHOUT ANY WARRANTY
; without even the implied warranty of
15 MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Bush. If not
, see
<http
://www.gnu.org
/licenses
/>.
24 $FUNCTION printf_builtin
25 $SHORT_DOC printf
[-v var
] format
[arguments
]
26 Formats and prints ARGUMENTS under control of the FORMAT.
29 -v var assign the output to shell variable
VAR rather than
30 display it on the standard output
32 FORMAT is a character string which contains three types of objects
: plain
33 characters
, which are simply copied to standard output
; character escape
34 sequences
, which are converted and copied to the standard output
; and
35 format specifications
, each of which causes printing of the next successive
38 In addition to the standard format specifications described in
printf(1),
41 %b expand backslash escape sequences in the corresponding argument
42 %q quote the argument in a way that can be reused as shell input
43 %(fmt
)T output the date
-time string resulting from using FMT as a format
44 string for
strftime(3)
46 The format is re
-used as necessary to consume all of the arguments. If
47 there are fewer arguments than the format requires
, extra format
48 specifications behave as if a zero value or null string
, as appropriate
,
52 Returns success unless an invalid option is given or a write or assignment
58 #include
"../src/bushtypes.h"
61 #if
defined (HAVE_LIMITS_H
)
64 /* Assume
32-bit ints.
*/
65 # define INT_MAX
2147483647
66 # define
INT_MIN (-2147483647-1)
69 #if
defined (PREFER_STDARG
)
76 #include
<chartypes.h
>
78 #ifdef HAVE_INTTYPES_H
79 # include
<inttypes.h
>
82 #include
"posixtime.h"
83 #include
"../src/bushansi.h"
84 #include
"../src/bushintl.h"
86 #define NEED_STRFTIME_DECL
88 #include
"../src/shell.h"
91 #include
"bushgetopt.h"
94 #if
defined (PRI_MACROS_BROKEN
)
98 #if
!defined (PRIdMAX
)
100 # define PRIdMAX
"lld"
102 # define PRIdMAX
"ld"
114 b
[0] = c
; b
[1] = '\0'; \
122 #define
PF(f
, func
) \
126 if (have_fieldwidth
&& have_precision
) \
127 nw
= vflag ?
vbprintf (f
, fieldwidth
, precision
, func
) : printf (f
, fieldwidth
, precision
, func
); \
128 else
if (have_fieldwidth
) \
129 nw
= vflag ?
vbprintf (f
, fieldwidth
, func
) : printf (f
, fieldwidth
, func
); \
130 else
if (have_precision
) \
131 nw
= vflag ?
vbprintf (f
, precision
, func
) : printf (f
, precision
, func
); \
133 nw
= vflag ?
vbprintf (f
, func
) : printf (f
, func
); \
136 if (ferror (stdout
)) \
140 return (EXECUTION_FAILURE
); \
144 /* We free the buffer used by
mklong() if it
's `too big'.
*/
145 #define
PRETURN(value
) \
152 v
= builtin_bind_variable (vname
, vbuf
, 0); \
153 stupidly_hack_special_variables (vname
); \
154 if (v
== 0 ||
readonly_p (v
) ||
noassign_p (v
)) \
155 return (EXECUTION_FAILURE
); \
157 if (conv_bufsize
> 4096 ) \
171 if (ferror (stdout
) == 0) \
174 if (ferror (stdout
)) \
178 return (EXECUTION_FAILURE
); \
184 #define SKIP1
"#'-+ 0"
185 #define LENMODS
"hjlLtz"
187 extern time_t shell_start_time
;
190 extern int asprintf
PARAMS((char
**, const char
*, ...
)) __attribute__((__format__ (printf
, 2, 3)));
194 extern int vsnprintf
PARAMS((char
*, size_t
, const char
*, va_list
)) __attribute__((__format__ (printf
, 3, 0)));
197 static void printf_erange
PARAMS((char *)
);
198 static int printstr
PARAMS((char
*, char
*, int
, int
, int
));
199 static int tescape
PARAMS((char
*, char
*, int
*, int *)
);
200 static char
*bexpand
PARAMS((char
*, int
, int
*, int *)
);
201 static char
*vbadd
PARAMS((char
*, int
));
202 static int vbprintf
PARAMS((const char
*, ...
)) __attribute__((__format__ (printf
, 1, 2)));
203 static char
*mklong
PARAMS((char
*, char
*, size_t
));
204 static int getchr
PARAMS((void
));
205 static char
*getstr
PARAMS((void
));
206 static int getint
PARAMS((void
));
207 static intmax_t getintmax
PARAMS((void
));
208 static uintmax_t getuintmax
PARAMS((void
));
210 #if
defined (HAVE_LONG_DOUBLE
) && HAVE_DECL_STRTOLD
&& !defined(STRTOLD_BROKEN
)
211 typedef long double floatmax_t
;
212 # define FLOATMAX_CONV
"L"
213 # define strtofltmax strtold
215 typedef double floatmax_t
;
216 # define FLOATMAX_CONV
""
217 # define strtofltmax strtod
219 static floatmax_t getfloatmax
PARAMS((void
));
221 static intmax_t asciicode
PARAMS((void
));
223 static WORD_LIST
*garglist
, *orig_arglist
;
225 static int conversion_error
;
227 /* printf
-v var support
*/
228 static int vflag
= 0;
229 static char
*vbuf
, *vname
;
230 static size_t vbsize
;
235 static char
*conv_buf
;
236 static size_t conv_bufsize
;
239 printf_builtin (list
)
242 int ch
, fieldwidth
, precision
;
243 int have_fieldwidth
, have_precision
;
244 char convch
, thisch
, nextch
, *format
, *modstart
, *fmt
, *start
;
245 #if
defined (HANDLE_MULTIBYTE
)
246 char mbch
[25]; /* 25 > MB_LEN_MAX
, plus can handle
4-byte UTF
-8 and large Unicode characters
*/
249 #if
defined (ARRAY_VARS
)
253 conversion_error
= 0;
254 retval
= EXECUTION_SUCCESS
;
258 reset_internal_getopt ();
259 while ((ch
= internal_getopt (list
, "v:")) != -1)
265 #if
defined (ARRAY_VARS
)
266 arrayflags
= assoc_expand_once ?
(VA_NOEXPAND|VA_ONEWORD
) : 0;
267 if (legal_identifier (vname
) ||
valid_array_reference (vname
, arrayflags
))
269 if (legal_identifier (vname
))
274 vbuf
= xmalloc (vbsize
= 16);
281 sh_invalidid (vname
);
291 list
= loptend
; /* skip over possible `
--' */
299 /* Allow printf -v var "" to act like var="" */
300 if (vflag && list->word->word && list->word->word[0] == '\
0')
303 v = builtin_bind_variable (vname, "", 0);
304 stupidly_hack_special_variables (vname);
305 return ((v == 0 || readonly_p (v) || noassign_p (v)) ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
308 if (list->word->word == 0 || list->word->word[0] == '\
0')
309 return (EXECUTION_SUCCESS);
311 format = list->word->word;
314 garglist = orig_arglist = list->next;
316 /* If the format string is empty after preprocessing, return immediately. */
317 if (format == 0 || *format == 0)
318 return (EXECUTION_SUCCESS);
320 /* Basic algorithm is to scan the format string for conversion
321 specifications -- once one is found, find out if the field
322 width or precision is a '*'; if it is, gather up value. Note,
323 format strings are reused as necessary to use up the provided
324 arguments, arguments of zero/null string are provided to use
325 up the format string. */
329 /* find next format specification */
330 for (fmt = format; *fmt; fmt++)
332 precision = fieldwidth = 0;
333 have_fieldwidth = have_precision = 0;
338 /* A NULL third argument to tescape means to bypass the
339 special processing for arguments to %b. */
340 #if defined (HANDLE_MULTIBYTE)
341 /* Accommodate possible use of \u or \U, which can result in
342 multibyte characters */
343 memset (mbch, '\
0', sizeof (mbch));
344 fmt += tescape (fmt, mbch, &mblen, (int *)NULL);
345 for (mbind = 0; mbind < mblen; mbind++)
348 fmt += tescape (fmt, &nextch, (int *)NULL, (int *)NULL);
351 fmt--; /* for loop will increment it for us again */
361 /* ASSERT(*fmt == '%') */
364 if (*fmt == '%') /* %% prints a % */
370 /* found format specification, skip to field width */
371 for (; *fmt && strchr(SKIP1, *fmt); ++fmt)
374 /* Skip optional field width. */
379 fieldwidth = getint ();
385 /* Skip optional '.
' and precision */
393 precision = getint ();
397 /* Negative precisions are allowed but treated as if the
398 precision were missing; I would like to allow a leading
399 `+' in the precision number as an extension
, but lots
400 of asprintf
/fprintf implementations get this wrong.
*/
402 if (*fmt == '-' || *fmt == '+')
412 /* skip possible format modifiers */
414 while (*fmt && strchr (LENMODS, *fmt))
419 builtin_error (_("`%s': missing format character"), start);
420 PRETURN (EXECUTION_FAILURE);
424 thisch = modstart[0];
425 nextch = modstart[1];
426 modstart[0] = convch;
452 char *timefmt, timebuf[128], *t;
458 modstart[1] = nextch; /* restore char after left paren */
459 timefmt = xmalloc (strlen (fmt) + 3);
460 fmt++; /* skip over left paren */
461 for (t = timefmt, n = 1; *fmt; )
465 else if (*fmt == ')')
474 builtin_warning (_("`%c': invalid time format specification"), *fmt);
480 if (timefmt[0] == '\0')
483 timefmt[1] = 'X'; /* locale-specific current time - should we use `+'? */
486 /* argument is seconds since the epoch with special -1 and -2 */
487 /* default argument is equivalent to -1; special case */
488 arg = garglist ? getintmax () : -1;
490 secs = NOW; /* roughly date +%s */
492 secs = shell_start_time; /* roughly $SECONDS */
495 #if defined (HAVE_TZSET)
496 sv_tz ("TZ"); /* XXX -- just make sure */
498 tm = localtime (&secs);
502 tm = localtime (&secs);
504 n = tm ? strftime (timebuf, sizeof (timebuf), timefmt, tm) : 0;
509 timebuf[sizeof(timebuf) - 1] = '\0';
510 /* convert to %s format that preserves fieldwidth and precision */
513 n = printstr (start, timebuf, strlen (timebuf), fieldwidth, precision); /* XXX - %s for now */
516 if (ferror (stdout) == 0)
521 PRETURN (EXECUTION_FAILURE);
533 if (legal_identifier (var))
534 bind_var_to_int (var, tw);
538 PRETURN (EXECUTION_FAILURE);
544 case 'b': /* expand escapes in argument */
551 xp = bexpand (p, strlen (p), &ch, &rlen);
555 /* Have to use printstr because of possible NUL bytes
556 in XP -- printf does not handle that well. */
557 r = printstr (start, xp, rlen, fieldwidth, precision);
560 if (ferror (stdout) == 0)
565 retval = EXECUTION_FAILURE;
575 case 'q': /* print with shell quoting */
582 if (p && *p == 0) /* XXX - getstr never returns null */
583 xp = savestring ("''");
584 else if (ansic_shouldquote (p))
585 xp = ansic_quote (p, 0, (int *)0);
587 xp
= sh_backslash_quote (p
, 0, 3);
590 /* Use printstr to get fieldwidth and precision right.
*/
591 r
= printstr (start
, xp
, strlen (xp
), fieldwidth
, precision
);
601 PRETURN (EXECUTION_FAILURE
);
612 p
= pp
= getintmax ();
615 f
= mklong (start
, PRIdMAX
, sizeof (PRIdMAX
) - 2);
620 /* Optimize the common case where the integer fits
621 in
"long". This also works around some long
622 long and
/or intmax_t library bugs in the common
623 case
, e.g. glibc
2.2 x86.
*/
624 f
= mklong (start
, "l", 1);
639 p
= pp
= getuintmax ();
642 f
= mklong (start
, PRIdMAX
, sizeof (PRIdMAX
) - 2);
647 f
= mklong (start
, "l", 1);
659 #if
defined (HAVE_PRINTF_A_FORMAT
)
668 f
= mklong (start
, FLOATMAX_CONV
, sizeof(FLOATMAX_CONV
) - 1);
673 /* We don
't output unrecognized format characters; we print an
674 error message and return a failure exit status. */
676 builtin_error (_("`%c': invalid format character
"), convch);
677 PRETURN (EXECUTION_FAILURE);
680 modstart[0] = thisch;
681 modstart[1] = nextch;
686 /* PRETURN will print error message. */
687 PRETURN (EXECUTION_FAILURE);
690 while (garglist && garglist != list->next);
692 if (conversion_error)
693 retval = EXECUTION_FAILURE;
702 builtin_error (_("warning
: %s
: %s
"), s, strerror(ERANGE));
705 /* We duplicate a lot of what printf(3) does here. */
707 printstr (fmt, string, len, fieldwidth, precision)
708 char *fmt; /* format */
709 char *string; /* expanded string argument */
710 int len; /* length of expanded string */
711 int fieldwidth; /* argument for width of `*' */
712 int precision; /* argument for precision of `*' */
717 int padlen, nc, ljust, i;
718 int fw, pr; /* fieldwidth and precision */
736 while (strchr (SKIP1, *fmt))
743 /* get fieldwidth, if present. rely on caller to clamp fieldwidth at INT_MAX */
754 else if (DIGIT (*fmt))
758 mfw = (mfw * 10) + (*fmt++ - '0');
759 /* Error if fieldwidth > INT_MAX here? */
760 fw = (mfw < 0 || mfw > INT_MAX) ? INT_MAX : mfw;
763 /* get precision, if present */
772 else if (DIGIT (*fmt))
776 mpr = (mpr * 10) + (*fmt++ - '0');
777 /* Error if precision > INT_MAX here? */
778 pr = (mpr < 0 || mpr > INT_MAX) ? INT_MAX : mpr;
781 pr = 0; /* "a null digit string is treated as zero
" */
785 /* If we remove this, get rid of `s'. */
786 if (*fmt != 'b' && *fmt != 'q')
788 internal_error (_("format parsing problem
: %s
"), s);
793 /* chars from string to print */
794 nc = (pr >= 0 && pr <= len) ? pr : len;
802 /* leading pad characters */
803 for (; padlen > 0; padlen--)
806 /* output NC characters from STRING */
807 for (i = 0; i < nc; i++)
810 /* output any necessary trailing padding */
811 for (; padlen < 0; padlen++)
814 return (ferror (stdout) ? -1 : 0);
817 /* Convert STRING by expanding the escape sequences specified by the
818 POSIX standard for printf's `%b' format string. If SAWC is non-null,
819 perform the processing appropriate for %b arguments. In particular,
820 recognize `\c' and use that as a string terminator. If we see \c, set
821 *SAWC to 1 before returning. LEN is the length of STRING. */
823 /* Translate a single backslash-escape sequence starting at ESTART (the
824 character after the backslash) and return the number of characters
825 consumed by the sequence. CP is the place to return the translated
826 value. *SAWC is set to 1 if the escape sequence was \c, since that means
827 to short-circuit the rest of the processing. If SAWC is null, we don't
828 do the \c short-circuiting, and \c is treated as an unrecognized escape
829 sequence; we also bypass the other processing specific to %b arguments. */
831 tescape (estart, cp, lenp, sawc)
838 unsigned long uvalue;
846 #if defined (__STDC__)
847 case 'a': *cp = '\a'; break;
849 case 'a': *cp = '\007'; break;
852 case 'b': *cp = '\b'; break;
855 case 'E': *cp = '\033'; break; /* ESC -- non-ANSI */
857 case 'f': *cp = '\f'; break;
859 case 'n': *cp = '\n'; break;
861 case 'r': *cp = '\r'; break;
863 case 't': *cp = '\t'; break;
865 case 'v': *cp = '\v'; break;
867 /* The octal escape sequences are `\0' followed by up to three octal
868 digits (if SAWC), or `\' followed by up to three octal digits (if
869 !SAWC). As an extension, we allow the latter form even if SAWC. */
870 case '0': case '1': case '2': case '3':
871 case '4': case '5': case '6': case '7':
872 evalue = OCTVALUE (c);
873 for (temp = 2 + (!evalue && !!sawc); ISOCTAL (*p) && temp--; p++)
874 evalue = (evalue * 8) + OCTVALUE (*p);
878 /* And, as another extension, we allow \xNN, where each N is a
881 for (temp = 2, evalue = 0; ISXDIGIT ((unsigned char)*p) && temp--; p++)
882 evalue = (evalue * 16) + HEXVALUE (*p);
885 builtin_error (_("missing hex digit for
\\x
"));
892 #if defined (HANDLE_MULTIBYTE)
895 temp = (c == 'u') ? 4 : 8; /* \uNNNN \UNNNNNNNN */
896 for (uvalue = 0; ISXDIGIT ((unsigned char)*p) && temp--; p++)
897 uvalue = (uvalue * 16) + HEXVALUE (*p);
900 builtin_error (_("missing unicode digit for
\\%c
"), c);
904 if (uvalue <= 0x7f) /* <= 0x7f translates directly */
908 temp = u32cconv (uvalue, cp);
916 case '\\': /* \\ -> \ */
920 /* SAWC == 0 means that \', \", and \? are recognized as escape
921 sequences, though the only processing performed is backslash
923 case '\'': case '"': case '?
':
939 /* other backslash escapes are passed through unaltered */
948 bexpand (string, len, sawc, lenp)
950 int len, *sawc, *lenp;
953 char *ret, *r, *s, c;
954 #if defined (HANDLE_MULTIBYTE)
959 if (string == 0 || len == 0)
965 ret = (char *)xmalloc (1);
970 ret = (char *)xmalloc (len + 1);
971 for (r = ret, s = string; s && *s; )
974 if (c != '\\' || *s == '\
0')
980 #if defined (HANDLE_MULTIBYTE)
981 memset (mbch, '\
0', sizeof (mbch));
982 s += tescape (s, mbch, &mblen, &temp);
984 s += tescape (s, &c, (int *)NULL, &temp);
993 #if defined (HANDLE_MULTIBYTE)
994 for (mbind = 0; mbind < mblen; mbind++)
1014 nlen = vblen + blen + 1;
1017 vbsize = ((nlen + 63) >> 6) << 6;
1018 vbuf = (char *)xrealloc (vbuf, vbsize);
1022 vbuf[vblen++] = buf[0];
1025 FASTCOPY (buf, vbuf + vblen, blen);
1031 if (strlen (vbuf) != vblen)
1032 internal_error ("printf:vbadd: vblen (%d) != strlen (vbuf) (%d)", vblen, (int)strlen (vbuf));
1039 #if defined (PREFER_STDARG)
1040 vbprintf (const char *format, ...)
1042 vbprintf (format, va_alist)
1051 SH_VA_START (args, format);
1052 blen = vsnprintf (vbuf + vblen, vbsize - vblen, format, args);
1055 nlen = vblen + blen + 1;
1058 vbsize = ((nlen + 63) >> 6) << 6;
1059 vbuf = (char *)xrealloc (vbuf, vbsize);
1060 SH_VA_START (args, format);
1061 blen = vsnprintf (vbuf + vblen, vbsize - vblen, format, args);
1069 if (strlen (vbuf) != vblen)
1070 internal_error ("printf:vbprintf: vblen (%d) != strlen (vbuf) (%d)", vblen, (int)strlen (vbuf));
1077 mklong (str, modifiers, mlen)
1084 slen = strlen (str);
1085 len = slen + mlen + 1;
1087 if (len > conv_bufsize)
1089 conv_bufsize = (((len + 1023) >> 10) << 10);
1090 conv_buf = (char *)xrealloc (conv_buf, conv_bufsize);
1093 FASTCOPY (str, conv_buf, slen - 1);
1094 FASTCOPY (modifiers, conv_buf + slen - 1, mlen);
1096 conv_buf[len - 2] = str[slen - 1];
1097 conv_buf[len - 1] = '\
0';
1109 ret = (int)garglist->word->word[0];
1110 garglist = garglist->next;
1122 ret = garglist->word->word;
1123 garglist = garglist->next;
1139 printf_erange (garglist->word->word);
1142 else if (ret < INT_MIN)
1144 printf_erange (garglist->word->word);
1160 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
1161 return asciicode ();
1164 ret = strtoimax (garglist->word->word, &ep, 0);
1168 sh_invalidnum (garglist->word->word);
1169 /* POSIX.2 says ``...a diagnostic message shall be written to standard
1170 error, and the utility shall not exit with a zero exit status, but
1171 shall continue processing any remaining operands and shall write the
1172 value accumulated at the time the error was detected to standard
1175 ret = 0; /* return partially-converted value from strtoimax */
1177 conversion_error = 1;
1179 else if (errno == ERANGE)
1180 printf_erange (garglist->word->word);
1182 garglist = garglist->next;
1195 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
1196 return asciicode ();
1199 ret = strtoumax (garglist->word->word, &ep, 0);
1203 sh_invalidnum (garglist->word->word);
1205 /* Same POSIX.2 conversion error requirements as getintmax(). */
1208 conversion_error = 1;
1210 else if (errno == ERANGE)
1211 printf_erange (garglist->word->word);
1213 garglist = garglist->next;
1226 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
1227 return asciicode ();
1230 ret = strtofltmax (garglist->word->word, &ep);
1234 sh_invalidnum (garglist->word->word);
1236 /* Same thing about POSIX.2 conversion error requirements. */
1239 conversion_error = 1;
1241 else if (errno == ERANGE)
1242 printf_erange (garglist->word->word);
1244 garglist = garglist->next;
1248 /* NO check is needed for garglist here. */
1252 register intmax_t ch;
1253 #if defined (HANDLE_MULTIBYTE)
1260 #if defined (HANDLE_MULTIBYTE)
1261 slen = strlen (garglist->word->word+1);
1263 mblength = mbtowc (&wc, garglist->word->word+1, slen);
1268 ch = (unsigned char)garglist->word->word[1];
1270 garglist = garglist->next;