blob: 0e7fe78644f48cd589c9a31775d2c53a51dfd50c [file] [log] [blame]
Jari Aaltocce855b1998-04-17 19:52:44 +00001This file is printf.def, from which is created printf.c.
2It implements the builtin "printf" in Bash.
3
Chet Ramey495aee42011-11-22 19:11:26 -05004Copyright (C) 1997-2010 Free Software Foundation, Inc.
Jari Aaltocce855b1998-04-17 19:52:44 +00005
6This file is part of GNU Bash, the Bourne Again SHell.
7
Jari Aalto31859422009-01-12 13:36:28 +00008Bash is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
Jari Aaltocce855b1998-04-17 19:52:44 +000012
Jari Aalto31859422009-01-12 13:36:28 +000013Bash is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
Jari Aaltocce855b1998-04-17 19:52:44 +000017
Jari Aalto31859422009-01-12 13:36:28 +000018You should have received a copy of the GNU General Public License
19along with Bash. If not, see <http://www.gnu.org/licenses/>.
Jari Aaltocce855b1998-04-17 19:52:44 +000020
21$PRODUCES printf.c
22
23$BUILTIN printf
24$FUNCTION printf_builtin
Jari Aalto95732b42005-12-07 14:08:12 +000025$SHORT_DOC printf [-v var] format [arguments]
Jari Aalto31859422009-01-12 13:36:28 +000026Formats and prints ARGUMENTS under control of the FORMAT.
27
28Options:
29 -v var assign the output to shell variable VAR rather than
30 display it on the standard output
31
32FORMAT is a character string which contains three types of objects: plain
33characters, which are simply copied to standard output; character escape
34sequences, which are converted and copied to the standard output; and
Jari Aaltocce855b1998-04-17 19:52:44 +000035format specifications, each of which causes printing of the next successive
Jari Aalto31859422009-01-12 13:36:28 +000036argument.
37
Chet Rameyac50fba2014-02-26 09:36:43 -050038In addition to the standard format specifications described in printf(1),
39printf interprets:
Jari Aalto31859422009-01-12 13:36:28 +000040
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
Chet Ramey495aee42011-11-22 19:11:26 -050043 %(fmt)T output the date-time string resulting from using FMT as a format
44 string for strftime(3)
Jari Aalto31859422009-01-12 13:36:28 +000045
Chet Rameyac50fba2014-02-26 09:36:43 -050046The format is re-used as necessary to consume all of the arguments. If
47there are fewer arguments than the format requires, extra format
48specifications behave as if a zero value or null string, as appropriate,
49had been supplied.
50
Jari Aalto31859422009-01-12 13:36:28 +000051Exit Status:
52Returns success unless an invalid option is given or a write or assignment
53error occurs.
Jari Aaltocce855b1998-04-17 19:52:44 +000054$END
55
56#include <config.h>
57
58#include "../bashtypes.h"
59
60#include <errno.h>
61#if defined (HAVE_LIMITS_H)
62# include <limits.h>
63#else
Jari Aaltof73dda02001-11-13 17:56:06 +000064 /* Assume 32-bit ints. */
Jari Aaltocce855b1998-04-17 19:52:44 +000065# define INT_MAX 2147483647
66# define INT_MIN (-2147483647-1)
67#endif
68
Jari Aaltof1be6662008-11-18 13:15:12 +000069#if defined (PREFER_STDARG)
70# include <stdarg.h>
71#else
72# include <varargs.h>
73#endif
74
Jari Aaltocce855b1998-04-17 19:52:44 +000075#include <stdio.h>
Jari Aaltof73dda02001-11-13 17:56:06 +000076#include <chartypes.h>
77
78#ifdef HAVE_INTTYPES_H
79# include <inttypes.h>
80#endif
Jari Aaltocce855b1998-04-17 19:52:44 +000081
Chet Ramey495aee42011-11-22 19:11:26 -050082#include "posixtime.h"
Jari Aaltocce855b1998-04-17 19:52:44 +000083#include "../bashansi.h"
Jari Aaltob80f6442004-07-27 13:29:18 +000084#include "../bashintl.h"
Jari Aaltof73dda02001-11-13 17:56:06 +000085
Chet Ramey495aee42011-11-22 19:11:26 -050086#define NEED_STRFTIME_DECL
87
Jari Aaltocce855b1998-04-17 19:52:44 +000088#include "../shell.h"
Jari Aalto31859422009-01-12 13:36:28 +000089#include "shmbutil.h"
Jari Aaltobb706242000-03-17 21:46:59 +000090#include "stdc.h"
Jari Aaltocce855b1998-04-17 19:52:44 +000091#include "bashgetopt.h"
Jari Aaltof73dda02001-11-13 17:56:06 +000092#include "common.h"
93
Jari Aaltof1be6662008-11-18 13:15:12 +000094#if defined (PRI_MACROS_BROKEN)
95# undef PRIdMAX
96#endif
97
Jari Aalto7117c2d2002-07-17 14:10:11 +000098#if !defined (PRIdMAX)
99# if HAVE_LONG_LONG
100# define PRIdMAX "lld"
101# else
102# define PRIdMAX "ld"
103# endif
Jari Aaltof73dda02001-11-13 17:56:06 +0000104#endif
Jari Aaltocce855b1998-04-17 19:52:44 +0000105
106#if !defined (errno)
Ricardo Cerqueiraa02fbff2013-07-25 22:35:34 +0100107#include <errno.h>
Jari Aaltocce855b1998-04-17 19:52:44 +0000108#endif
109
Jari Aalto95732b42005-12-07 14:08:12 +0000110#define PC(c) \
111 do { \
112 char b[2]; \
113 tw++; \
114 b[0] = c; b[1] = '\0'; \
115 if (vflag) \
116 vbadd (b, 1); \
117 else \
118 putchar (c); \
119 } while (0)
120
Jari Aaltocce855b1998-04-17 19:52:44 +0000121#define PF(f, func) \
122 do { \
Jari Aalto95732b42005-12-07 14:08:12 +0000123 int nw; \
Jari Aalto06285672006-10-10 14:15:34 +0000124 clearerr (stdout); \
Jari Aaltof73dda02001-11-13 17:56:06 +0000125 if (have_fieldwidth && have_precision) \
Jari Aalto31859422009-01-12 13:36:28 +0000126 nw = vflag ? vbprintf (f, fieldwidth, precision, func) : printf (f, fieldwidth, precision, func); \
Jari Aaltof73dda02001-11-13 17:56:06 +0000127 else if (have_fieldwidth) \
Jari Aalto31859422009-01-12 13:36:28 +0000128 nw = vflag ? vbprintf (f, fieldwidth, func) : printf (f, fieldwidth, func); \
Jari Aaltof73dda02001-11-13 17:56:06 +0000129 else if (have_precision) \
Chet Ramey30d188c2011-11-21 20:57:16 -0500130 nw = vflag ? vbprintf (f, precision, func) : printf (f, precision, func); \
Jari Aaltocce855b1998-04-17 19:52:44 +0000131 else \
Jari Aalto31859422009-01-12 13:36:28 +0000132 nw = vflag ? vbprintf (f, func) : printf (f, func); \
Jari Aalto95732b42005-12-07 14:08:12 +0000133 tw += nw; \
Jari Aalto31859422009-01-12 13:36:28 +0000134 if (ferror (stdout)) \
Jari Aalto95732b42005-12-07 14:08:12 +0000135 { \
Jari Aalto31859422009-01-12 13:36:28 +0000136 sh_wrerror (); \
137 clearerr (stdout); \
138 return (EXECUTION_FAILURE); \
Jari Aalto95732b42005-12-07 14:08:12 +0000139 } \
Jari Aaltocce855b1998-04-17 19:52:44 +0000140 } while (0)
141
Jari Aaltof73dda02001-11-13 17:56:06 +0000142/* We free the buffer used by mklong() if it's `too big'. */
Jari Aaltocce855b1998-04-17 19:52:44 +0000143#define PRETURN(value) \
Jari Aaltof73dda02001-11-13 17:56:06 +0000144 do \
145 { \
Jari Aalto95732b42005-12-07 14:08:12 +0000146 if (vflag) \
147 { \
Chet Ramey00018032011-11-21 20:51:19 -0500148 bind_printf_variable (vname, vbuf, 0); \
Jari Aalto95732b42005-12-07 14:08:12 +0000149 stupidly_hack_special_variables (vname); \
150 } \
Jari Aaltof73dda02001-11-13 17:56:06 +0000151 if (conv_bufsize > 4096 ) \
152 { \
Jari Aalto95732b42005-12-07 14:08:12 +0000153 free (conv_buf); \
Jari Aaltof73dda02001-11-13 17:56:06 +0000154 conv_bufsize = 0; \
155 conv_buf = 0; \
156 } \
Jari Aalto95732b42005-12-07 14:08:12 +0000157 if (vbsize > 4096) \
158 { \
159 free (vbuf); \
160 vbsize = 0; \
161 vbuf = 0; \
162 } \
Jari Aalto31859422009-01-12 13:36:28 +0000163 else if (vbuf) \
164 vbuf[0] = 0; \
165 terminate_immediately--; \
Chet Rameyac50fba2014-02-26 09:36:43 -0500166 if (ferror (stdout) == 0) \
167 fflush (stdout); \
Jari Aalto06285672006-10-10 14:15:34 +0000168 if (ferror (stdout)) \
169 { \
Chet Ramey00018032011-11-21 20:51:19 -0500170 sh_wrerror (); \
Jari Aalto06285672006-10-10 14:15:34 +0000171 clearerr (stdout); \
172 return (EXECUTION_FAILURE); \
173 } \
Jari Aaltof73dda02001-11-13 17:56:06 +0000174 return (value); \
175 } \
176 while (0)
Jari Aaltocce855b1998-04-17 19:52:44 +0000177
Jari Aaltof73dda02001-11-13 17:56:06 +0000178#define SKIP1 "#'-+ 0"
179#define LENMODS "hjlLtz"
Jari Aaltocce855b1998-04-17 19:52:44 +0000180
Chet Ramey495aee42011-11-22 19:11:26 -0500181extern time_t shell_start_time;
182
Chet Ramey00018032011-11-21 20:51:19 -0500183#if !HAVE_ASPRINTF
Jari Aaltof1be6662008-11-18 13:15:12 +0000184extern int asprintf __P((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
185#endif
186
Chet Ramey00018032011-11-21 20:51:19 -0500187#if !HAVE_VSNPRINTF
Chet Ramey30d188c2011-11-21 20:57:16 -0500188extern int vsnprintf __P((char *, size_t, const char *, va_list)) __attribute__((__format__ (printf, 3, 0)));
Jari Aalto31859422009-01-12 13:36:28 +0000189#endif
190
Jari Aalto7117c2d2002-07-17 14:10:11 +0000191static void printf_erange __P((char *));
Jari Aalto95732b42005-12-07 14:08:12 +0000192static int printstr __P((char *, char *, int, int, int));
Chet Ramey495aee42011-11-22 19:11:26 -0500193static int tescape __P((char *, char *, int *, int *));
Jari Aaltocce855b1998-04-17 19:52:44 +0000194static char *bexpand __P((char *, int, int *, int *));
Jari Aalto95732b42005-12-07 14:08:12 +0000195static char *vbadd __P((char *, int));
Jari Aalto31859422009-01-12 13:36:28 +0000196static int vbprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
Jari Aalto7117c2d2002-07-17 14:10:11 +0000197static char *mklong __P((char *, char *, size_t));
Jari Aaltocce855b1998-04-17 19:52:44 +0000198static int getchr __P((void));
199static char *getstr __P((void));
200static int getint __P((void));
Jari Aaltof73dda02001-11-13 17:56:06 +0000201static intmax_t getintmax __P((void));
202static uintmax_t getuintmax __P((void));
Chet Ramey00018032011-11-21 20:51:19 -0500203static SHELL_VAR *bind_printf_variable __P((char *, char *, int));
Jari Aalto7117c2d2002-07-17 14:10:11 +0000204
Jari Aaltob80f6442004-07-27 13:29:18 +0000205#if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD && !defined(STRTOLD_BROKEN)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000206typedef long double floatmax_t;
207# define FLOATMAX_CONV "L"
208# define strtofltmax strtold
209#else
210typedef double floatmax_t;
211# define FLOATMAX_CONV ""
212# define strtofltmax strtod
Jari Aaltof73dda02001-11-13 17:56:06 +0000213#endif
Jari Aalto7117c2d2002-07-17 14:10:11 +0000214static floatmax_t getfloatmax __P((void));
215
Jari Aalto31859422009-01-12 13:36:28 +0000216static intmax_t asciicode __P((void));
Jari Aaltocce855b1998-04-17 19:52:44 +0000217
218static WORD_LIST *garglist;
219static int retval;
Jari Aaltof73dda02001-11-13 17:56:06 +0000220static int conversion_error;
Jari Aaltocce855b1998-04-17 19:52:44 +0000221
Jari Aalto95732b42005-12-07 14:08:12 +0000222/* printf -v var support */
223static int vflag = 0;
224static char *vbuf, *vname;
225static size_t vbsize;
226static int vblen;
227
228static intmax_t tw;
229
Jari Aaltof73dda02001-11-13 17:56:06 +0000230static char *conv_buf;
231static size_t conv_bufsize;
Jari Aaltocce855b1998-04-17 19:52:44 +0000232
233int
234printf_builtin (list)
235 WORD_LIST *list;
236{
Jari Aaltof73dda02001-11-13 17:56:06 +0000237 int ch, fieldwidth, precision;
238 int have_fieldwidth, have_precision;
Jari Aaltof73dda02001-11-13 17:56:06 +0000239 char convch, thisch, nextch, *format, *modstart, *fmt, *start;
Chet Ramey495aee42011-11-22 19:11:26 -0500240#if defined (HANDLE_MULTIBYTE)
241 char mbch[25]; /* 25 > MB_LEN_MAX, plus can handle 4-byte UTF-8 and large Unicode characters*/
242 int mbind, mblen;
243#endif
Jari Aaltocce855b1998-04-17 19:52:44 +0000244
Jari Aaltof73dda02001-11-13 17:56:06 +0000245 conversion_error = 0;
Jari Aaltocce855b1998-04-17 19:52:44 +0000246 retval = EXECUTION_SUCCESS;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000247
Jari Aalto95732b42005-12-07 14:08:12 +0000248 vflag = 0;
249
250 reset_internal_getopt ();
251 while ((ch = internal_getopt (list, "v:")) != -1)
252 {
253 switch (ch)
254 {
255 case 'v':
Chet Ramey00018032011-11-21 20:51:19 -0500256 vname = list_optarg;
257#if defined (ARRAY_VARS)
258 if (legal_identifier (vname) || valid_array_reference (vname))
259#else
260 if (legal_identifier (vname))
261#endif
Jari Aalto95732b42005-12-07 14:08:12 +0000262 {
263 vflag = 1;
Chet Ramey6c191482012-03-13 15:12:26 -0400264 if (vbsize == 0)
265 vbuf = xmalloc (vbsize = 16);
Jari Aalto95732b42005-12-07 14:08:12 +0000266 vblen = 0;
Jari Aalto31859422009-01-12 13:36:28 +0000267 if (vbuf)
268 vbuf[0] = 0;
Jari Aalto95732b42005-12-07 14:08:12 +0000269 }
270 else
271 {
272 sh_invalidid (vname);
273 return (EX_USAGE);
274 }
275 break;
276 default:
277 builtin_usage ();
278 return (EX_USAGE);
279 }
280 }
Jari Aalto7117c2d2002-07-17 14:10:11 +0000281 list = loptend; /* skip over possible `--' */
Jari Aaltocce855b1998-04-17 19:52:44 +0000282
283 if (list == 0)
284 {
285 builtin_usage ();
286 return (EX_USAGE);
287 }
288
289 if (list->word->word == 0 || list->word->word[0] == '\0')
290 return (EXECUTION_SUCCESS);
291
Jari Aaltobb706242000-03-17 21:46:59 +0000292 format = list->word->word;
Jari Aalto95732b42005-12-07 14:08:12 +0000293 tw = 0;
Jari Aaltocce855b1998-04-17 19:52:44 +0000294
295 garglist = list->next;
296
Jari Aaltobc4cd231998-07-23 14:37:54 +0000297 /* If the format string is empty after preprocessing, return immediately. */
Jari Aaltobb706242000-03-17 21:46:59 +0000298 if (format == 0 || *format == 0)
Jari Aaltobc4cd231998-07-23 14:37:54 +0000299 return (EXECUTION_SUCCESS);
Jari Aalto31859422009-01-12 13:36:28 +0000300
301 terminate_immediately++;
Jari Aaltobc4cd231998-07-23 14:37:54 +0000302
Jari Aaltocce855b1998-04-17 19:52:44 +0000303 /* Basic algorithm is to scan the format string for conversion
304 specifications -- once one is found, find out if the field
305 width or precision is a '*'; if it is, gather up value. Note,
306 format strings are reused as necessary to use up the provided
307 arguments, arguments of zero/null string are provided to use
308 up the format string. */
Jari Aaltocce855b1998-04-17 19:52:44 +0000309 do
310 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000311 tw = 0;
Jari Aaltocce855b1998-04-17 19:52:44 +0000312 /* find next format specification */
Jari Aaltobb706242000-03-17 21:46:59 +0000313 for (fmt = format; *fmt; fmt++)
Jari Aaltocce855b1998-04-17 19:52:44 +0000314 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000315 precision = fieldwidth = 0;
316 have_fieldwidth = have_precision = 0;
317
Jari Aaltobb706242000-03-17 21:46:59 +0000318 if (*fmt == '\\')
319 {
320 fmt++;
Jari Aaltob80f6442004-07-27 13:29:18 +0000321 /* A NULL third argument to tescape means to bypass the
322 special processing for arguments to %b. */
Chet Ramey495aee42011-11-22 19:11:26 -0500323#if defined (HANDLE_MULTIBYTE)
324 /* Accommodate possible use of \u or \U, which can result in
325 multibyte characters */
326 memset (mbch, '\0', sizeof (mbch));
327 fmt += tescape (fmt, mbch, &mblen, (int *)NULL);
328 for (mbind = 0; mbind < mblen; mbind++)
329 PC (mbch[mbind]);
330#else
331 fmt += tescape (fmt, &nextch, (int *)NULL, (int *)NULL);
Jari Aalto95732b42005-12-07 14:08:12 +0000332 PC (nextch);
Chet Ramey495aee42011-11-22 19:11:26 -0500333#endif
Jari Aaltobb706242000-03-17 21:46:59 +0000334 fmt--; /* for loop will increment it for us again */
335 continue;
336 }
337
Jari Aaltocce855b1998-04-17 19:52:44 +0000338 if (*fmt != '%')
339 {
Jari Aalto95732b42005-12-07 14:08:12 +0000340 PC (*fmt);
Jari Aaltocce855b1998-04-17 19:52:44 +0000341 continue;
342 }
343
344 /* ASSERT(*fmt == '%') */
345 start = fmt++;
346
347 if (*fmt == '%') /* %% prints a % */
348 {
Jari Aalto95732b42005-12-07 14:08:12 +0000349 PC ('%');
Jari Aaltocce855b1998-04-17 19:52:44 +0000350 continue;
351 }
352
353 /* found format specification, skip to field width */
354 for (; *fmt && strchr(SKIP1, *fmt); ++fmt)
355 ;
Jari Aaltocce855b1998-04-17 19:52:44 +0000356
Jari Aaltof73dda02001-11-13 17:56:06 +0000357 /* Skip optional field width. */
358 if (*fmt == '*')
359 {
360 fmt++;
361 have_fieldwidth = 1;
362 fieldwidth = getint ();
363 }
364 else
365 while (DIGIT (*fmt))
366 fmt++;
367
368 /* Skip optional '.' and precision */
Jari Aaltocce855b1998-04-17 19:52:44 +0000369 if (*fmt == '.')
370 {
371 ++fmt;
Jari Aaltof73dda02001-11-13 17:56:06 +0000372 if (*fmt == '*')
373 {
374 fmt++;
375 have_precision = 1;
376 precision = getint ();
377 }
378 else
Jari Aalto95732b42005-12-07 14:08:12 +0000379 {
380 /* Negative precisions are allowed but treated as if the
381 precision were missing; I would like to allow a leading
382 `+' in the precision number as an extension, but lots
383 of asprintf/fprintf implementations get this wrong. */
384#if 0
385 if (*fmt == '-' || *fmt == '+')
386#else
387 if (*fmt == '-')
388#endif
389 fmt++;
390 while (DIGIT (*fmt))
391 fmt++;
392 }
Jari Aaltocce855b1998-04-17 19:52:44 +0000393 }
394
Jari Aaltocce855b1998-04-17 19:52:44 +0000395 /* skip possible format modifiers */
Jari Aaltof73dda02001-11-13 17:56:06 +0000396 modstart = fmt;
397 while (*fmt && strchr (LENMODS, *fmt))
398 fmt++;
Jari Aaltocce855b1998-04-17 19:52:44 +0000399
Jari Aaltob72432f1999-02-19 17:11:39 +0000400 if (*fmt == 0)
401 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000402 builtin_error (_("`%s': missing format character"), start);
Jari Aaltob72432f1999-02-19 17:11:39 +0000403 PRETURN (EXECUTION_FAILURE);
404 }
405
Jari Aaltocce855b1998-04-17 19:52:44 +0000406 convch = *fmt;
Jari Aaltof73dda02001-11-13 17:56:06 +0000407 thisch = modstart[0];
408 nextch = modstart[1];
409 modstart[0] = convch;
410 modstart[1] = '\0';
411
Jari Aaltocce855b1998-04-17 19:52:44 +0000412 switch(convch)
413 {
414 case 'c':
415 {
416 char p;
417
418 p = getchr ();
419 PF(start, p);
420 break;
421 }
422
423 case 's':
424 {
425 char *p;
426
427 p = getstr ();
428 PF(start, p);
429 break;
430 }
431
Chet Ramey495aee42011-11-22 19:11:26 -0500432 case '(':
433 {
434 char *timefmt, timebuf[128], *t;
435 int n;
436 intmax_t arg;
437 time_t secs;
438 struct tm *tm;
439
440 modstart[1] = nextch; /* restore char after left paren */
441 timefmt = xmalloc (strlen (fmt) + 3);
442 fmt++; /* skip over left paren */
443 for (t = timefmt, n = 1; *fmt; )
444 {
445 if (*fmt == '(')
446 n++;
447 else if (*fmt == ')')
448 n--;
449 if (n == 0)
450 break;
451 *t++ = *fmt++;
452 }
453 *t = '\0';
454 if (*++fmt != 'T')
455 {
456 builtin_warning (_("`%c': invalid time format specification"), *fmt);
457 fmt = start;
458 free (timefmt);
459 PC (*fmt);
460 continue;
461 }
462 if (timefmt[0] == '\0')
463 {
464 timefmt[0] = '%';
465 timefmt[1] = 'X'; /* locale-specific current time - should we use `+'? */
466 timefmt[2] = '\0';
467 }
468 /* argument is seconds since the epoch with special -1 and -2 */
Chet Rameyac50fba2014-02-26 09:36:43 -0500469 /* default argument is equivalent to -1; special case */
470 arg = garglist ? getintmax () : -1;
Chet Ramey495aee42011-11-22 19:11:26 -0500471 if (arg == -1)
472 secs = NOW; /* roughly date +%s */
473 else if (arg == -2)
474 secs = shell_start_time; /* roughly $SECONDS */
475 else
476 secs = arg;
Chet Ramey2bbe8052011-11-22 20:00:19 -0500477#if defined (HAVE_TZSET)
478 sv_tz ("TZ"); /* XXX -- just make sure */
479#endif
Chet Ramey495aee42011-11-22 19:11:26 -0500480 tm = localtime (&secs);
Chet Rameyac50fba2014-02-26 09:36:43 -0500481 if (tm == 0)
482 {
483 secs = 0;
484 tm = localtime (&secs);
485 }
486 n = tm ? strftime (timebuf, sizeof (timebuf), timefmt, tm) : 0;
Chet Ramey495aee42011-11-22 19:11:26 -0500487 free (timefmt);
488 if (n == 0)
489 timebuf[0] = '\0';
490 else
491 timebuf[sizeof(timebuf) - 1] = '\0';
492 /* convert to %s format that preserves fieldwidth and precision */
493 modstart[0] = 's';
494 modstart[1] = '\0';
495 n = printstr (start, timebuf, strlen (timebuf), fieldwidth, precision); /* XXX - %s for now */
496 if (n < 0)
497 {
Chet Rameyac50fba2014-02-26 09:36:43 -0500498 if (ferror (stdout) == 0)
499 {
500 sh_wrerror ();
501 clearerr (stdout);
502 }
Chet Ramey495aee42011-11-22 19:11:26 -0500503 PRETURN (EXECUTION_FAILURE);
504 }
505 break;
506 }
507
Jari Aaltof73dda02001-11-13 17:56:06 +0000508 case 'n':
509 {
510 char *var;
511
512 var = getstr ();
513 if (var && *var)
514 {
515 if (legal_identifier (var))
516 bind_var_to_int (var, tw);
517 else
518 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000519 sh_invalidid (var);
Jari Aaltof73dda02001-11-13 17:56:06 +0000520 PRETURN (EXECUTION_FAILURE);
521 }
522 }
523 break;
524 }
525
Jari Aaltocce855b1998-04-17 19:52:44 +0000526 case 'b': /* expand escapes in argument */
527 {
528 char *p, *xp;
Jari Aalto95732b42005-12-07 14:08:12 +0000529 int rlen, r;
Jari Aaltocce855b1998-04-17 19:52:44 +0000530
531 p = getstr ();
Jari Aalto95732b42005-12-07 14:08:12 +0000532 ch = rlen = r = 0;
Jari Aaltocce855b1998-04-17 19:52:44 +0000533 xp = bexpand (p, strlen (p), &ch, &rlen);
534
535 if (xp)
536 {
537 /* Have to use printstr because of possible NUL bytes
538 in XP -- printf does not handle that well. */
Jari Aalto95732b42005-12-07 14:08:12 +0000539 r = printstr (start, xp, rlen, fieldwidth, precision);
540 if (r < 0)
541 {
Chet Rameyac50fba2014-02-26 09:36:43 -0500542 if (ferror (stdout) == 0)
543 {
544 sh_wrerror ();
545 clearerr (stdout);
546 }
Jari Aalto95732b42005-12-07 14:08:12 +0000547 retval = EXECUTION_FAILURE;
548 }
Jari Aaltocce855b1998-04-17 19:52:44 +0000549 free (xp);
550 }
551
Jari Aalto95732b42005-12-07 14:08:12 +0000552 if (ch || r < 0)
Jari Aaltocce855b1998-04-17 19:52:44 +0000553 PRETURN (retval);
554 break;
555 }
556
557 case 'q': /* print with shell quoting */
558 {
559 char *p, *xp;
Jari Aalto95732b42005-12-07 14:08:12 +0000560 int r;
Jari Aaltocce855b1998-04-17 19:52:44 +0000561
Jari Aalto95732b42005-12-07 14:08:12 +0000562 r = 0;
Jari Aaltocce855b1998-04-17 19:52:44 +0000563 p = getstr ();
Jari Aalto06285672006-10-10 14:15:34 +0000564 if (p && *p == 0) /* XXX - getstr never returns null */
565 xp = savestring ("''");
566 else if (ansic_shouldquote (p))
Jari Aalto7117c2d2002-07-17 14:10:11 +0000567 xp = ansic_quote (p, 0, (int *)0);
568 else
Chet Rameyac50fba2014-02-26 09:36:43 -0500569 xp = sh_backslash_quote (p, 0, 1);
Jari Aaltocce855b1998-04-17 19:52:44 +0000570 if (xp)
571 {
572 /* Use printstr to get fieldwidth and precision right. */
Jari Aalto95732b42005-12-07 14:08:12 +0000573 r = printstr (start, xp, strlen (xp), fieldwidth, precision);
574 if (r < 0)
575 {
576 sh_wrerror ();
577 clearerr (stdout);
578 }
Jari Aaltocce855b1998-04-17 19:52:44 +0000579 free (xp);
580 }
Jari Aalto95732b42005-12-07 14:08:12 +0000581
582 if (r < 0)
583 PRETURN (EXECUTION_FAILURE);
Jari Aaltocce855b1998-04-17 19:52:44 +0000584 break;
585 }
586
587 case 'd':
588 case 'i':
589 {
Jari Aaltocce855b1998-04-17 19:52:44 +0000590 char *f;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000591 long p;
592 intmax_t pp;
Jari Aaltocce855b1998-04-17 19:52:44 +0000593
Jari Aalto7117c2d2002-07-17 14:10:11 +0000594 p = pp = getintmax ();
595 if (p != pp)
Jari Aaltof73dda02001-11-13 17:56:06 +0000596 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000597 f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
598 PF (f, pp);
Jari Aaltof73dda02001-11-13 17:56:06 +0000599 }
600 else
601 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000602 /* Optimize the common case where the integer fits
603 in "long". This also works around some long
604 long and/or intmax_t library bugs in the common
605 case, e.g. glibc 2.2 x86. */
606 f = mklong (start, "l", 1);
607 PF (f, p);
Jari Aaltof73dda02001-11-13 17:56:06 +0000608 }
Jari Aaltocce855b1998-04-17 19:52:44 +0000609 break;
610 }
611
612 case 'o':
613 case 'u':
614 case 'x':
615 case 'X':
616 {
Jari Aaltocce855b1998-04-17 19:52:44 +0000617 char *f;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000618 unsigned long p;
619 uintmax_t pp;
Jari Aaltocce855b1998-04-17 19:52:44 +0000620
Jari Aalto7117c2d2002-07-17 14:10:11 +0000621 p = pp = getuintmax ();
622 if (p != pp)
Jari Aaltof73dda02001-11-13 17:56:06 +0000623 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000624 f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
625 PF (f, pp);
Jari Aaltof73dda02001-11-13 17:56:06 +0000626 }
627 else
628 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000629 f = mklong (start, "l", 1);
Jari Aaltof73dda02001-11-13 17:56:06 +0000630 PF (f, p);
631 }
Jari Aaltocce855b1998-04-17 19:52:44 +0000632 break;
633 }
634
635 case 'e':
636 case 'E':
637 case 'f':
Jari Aaltof73dda02001-11-13 17:56:06 +0000638 case 'F':
Jari Aaltocce855b1998-04-17 19:52:44 +0000639 case 'g':
640 case 'G':
Jari Aaltof73dda02001-11-13 17:56:06 +0000641#if defined (HAVE_PRINTF_A_FORMAT)
642 case 'a':
643 case 'A':
644#endif
Jari Aaltocce855b1998-04-17 19:52:44 +0000645 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000646 char *f;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000647 floatmax_t p;
Jari Aaltocce855b1998-04-17 19:52:44 +0000648
Jari Aalto7117c2d2002-07-17 14:10:11 +0000649 p = getfloatmax ();
650 f = mklong (start, FLOATMAX_CONV, sizeof(FLOATMAX_CONV) - 1);
651 PF (f, p);
Jari Aaltocce855b1998-04-17 19:52:44 +0000652 break;
653 }
654
Jari Aaltobb706242000-03-17 21:46:59 +0000655 /* We don't output unrecognized format characters; we print an
656 error message and return a failure exit status. */
Jari Aaltocce855b1998-04-17 19:52:44 +0000657 default:
Jari Aaltob80f6442004-07-27 13:29:18 +0000658 builtin_error (_("`%c': invalid format character"), convch);
Jari Aaltocce855b1998-04-17 19:52:44 +0000659 PRETURN (EXECUTION_FAILURE);
660 }
661
Jari Aaltof73dda02001-11-13 17:56:06 +0000662 modstart[0] = thisch;
663 modstart[1] = nextch;
Jari Aaltocce855b1998-04-17 19:52:44 +0000664 }
Jari Aalto95732b42005-12-07 14:08:12 +0000665
666 if (ferror (stdout))
667 {
Chet Rameyac50fba2014-02-26 09:36:43 -0500668 /* PRETURN will print error message. */
Jari Aalto95732b42005-12-07 14:08:12 +0000669 PRETURN (EXECUTION_FAILURE);
670 }
Jari Aaltocce855b1998-04-17 19:52:44 +0000671 }
Jari Aaltobc4cd231998-07-23 14:37:54 +0000672 while (garglist && garglist != list->next);
Jari Aaltocce855b1998-04-17 19:52:44 +0000673
Jari Aaltof73dda02001-11-13 17:56:06 +0000674 if (conversion_error)
675 retval = EXECUTION_FAILURE;
676
Jari Aaltocce855b1998-04-17 19:52:44 +0000677 PRETURN (retval);
678}
679
Jari Aalto7117c2d2002-07-17 14:10:11 +0000680static void
681printf_erange (s)
682 char *s;
683{
Jari Aalto31859422009-01-12 13:36:28 +0000684 builtin_error (_("warning: %s: %s"), s, strerror(ERANGE));
Jari Aalto7117c2d2002-07-17 14:10:11 +0000685}
686
Jari Aaltocce855b1998-04-17 19:52:44 +0000687/* We duplicate a lot of what printf(3) does here. */
Jari Aalto95732b42005-12-07 14:08:12 +0000688static int
Jari Aaltocce855b1998-04-17 19:52:44 +0000689printstr (fmt, string, len, fieldwidth, precision)
690 char *fmt; /* format */
691 char *string; /* expanded string argument */
692 int len; /* length of expanded string */
693 int fieldwidth; /* argument for width of `*' */
694 int precision; /* argument for precision of `*' */
695{
696#if 0
697 char *s;
698#endif
699 int padlen, nc, ljust, i;
700 int fw, pr; /* fieldwidth and precision */
Chet Rameyac50fba2014-02-26 09:36:43 -0500701 intmax_t mfw, mpr;
Jari Aaltocce855b1998-04-17 19:52:44 +0000702
Jari Aalto95732b42005-12-07 14:08:12 +0000703 if (string == 0 || len == 0)
Jari Aalto31859422009-01-12 13:36:28 +0000704 return 0;
Jari Aaltocce855b1998-04-17 19:52:44 +0000705
706#if 0
707 s = fmt;
708#endif
709 if (*fmt == '%')
710 fmt++;
711
Jari Aaltof73dda02001-11-13 17:56:06 +0000712 ljust = fw = 0;
713 pr = -1;
Chet Rameyac50fba2014-02-26 09:36:43 -0500714 mfw = 0;
715 mpr = -1;
Jari Aaltocce855b1998-04-17 19:52:44 +0000716
717 /* skip flags */
Jari Aaltof73dda02001-11-13 17:56:06 +0000718 while (strchr (SKIP1, *fmt))
Jari Aaltocce855b1998-04-17 19:52:44 +0000719 {
720 if (*fmt == '-')
721 ljust = 1;
722 fmt++;
723 }
724
Chet Rameyac50fba2014-02-26 09:36:43 -0500725 /* get fieldwidth, if present. rely on caller to clamp fieldwidth at INT_MAX */
Jari Aaltocce855b1998-04-17 19:52:44 +0000726 if (*fmt == '*')
727 {
728 fmt++;
729 fw = fieldwidth;
Jari Aaltof73dda02001-11-13 17:56:06 +0000730 if (fw < 0)
731 {
732 fw = -fw;
733 ljust = 1;
734 }
Jari Aaltocce855b1998-04-17 19:52:44 +0000735 }
Jari Aaltof73dda02001-11-13 17:56:06 +0000736 else if (DIGIT (*fmt))
Jari Aaltocce855b1998-04-17 19:52:44 +0000737 {
Chet Rameyac50fba2014-02-26 09:36:43 -0500738 mfw = *fmt++ - '0';
Jari Aaltof73dda02001-11-13 17:56:06 +0000739 while (DIGIT (*fmt))
Chet Rameyac50fba2014-02-26 09:36:43 -0500740 mfw = (mfw * 10) + (*fmt++ - '0');
741 /* Error if fieldwidth > INT_MAX here? */
742 fw = (mfw < 0 || mfw > INT_MAX) ? INT_MAX : mfw;
Jari Aaltocce855b1998-04-17 19:52:44 +0000743 }
744
745 /* get precision, if present */
746 if (*fmt == '.')
747 {
748 fmt++;
749 if (*fmt == '*')
750 {
751 fmt++;
752 pr = precision;
753 }
Jari Aaltof73dda02001-11-13 17:56:06 +0000754 else if (DIGIT (*fmt))
Jari Aaltocce855b1998-04-17 19:52:44 +0000755 {
Chet Rameyac50fba2014-02-26 09:36:43 -0500756 mpr = *fmt++ - '0';
Jari Aaltof73dda02001-11-13 17:56:06 +0000757 while (DIGIT (*fmt))
Chet Rameyac50fba2014-02-26 09:36:43 -0500758 mpr = (mpr * 10) + (*fmt++ - '0');
759 /* Error if precision > INT_MAX here? */
760 pr = (mpr < 0 || mpr > INT_MAX) ? INT_MAX : mpr;
Jari Aaltocce855b1998-04-17 19:52:44 +0000761 }
762 }
763
764#if 0
765 /* If we remove this, get rid of `s'. */
766 if (*fmt != 'b' && *fmt != 'q')
767 {
Chet Rameyac50fba2014-02-26 09:36:43 -0500768 internal_error (_("format parsing problem: %s"), s);
Jari Aaltocce855b1998-04-17 19:52:44 +0000769 fw = pr = 0;
770 }
771#endif
772
773 /* chars from string to print */
Jari Aaltof73dda02001-11-13 17:56:06 +0000774 nc = (pr >= 0 && pr <= len) ? pr : len;
Jari Aaltocce855b1998-04-17 19:52:44 +0000775
776 padlen = fw - nc;
777 if (padlen < 0)
778 padlen = 0;
779 if (ljust)
780 padlen = -padlen;
781
782 /* leading pad characters */
783 for (; padlen > 0; padlen--)
Jari Aalto95732b42005-12-07 14:08:12 +0000784 PC (' ');
Jari Aaltocce855b1998-04-17 19:52:44 +0000785
786 /* output NC characters from STRING */
787 for (i = 0; i < nc; i++)
Jari Aalto95732b42005-12-07 14:08:12 +0000788 PC (string[i]);
Jari Aaltocce855b1998-04-17 19:52:44 +0000789
790 /* output any necessary trailing padding */
791 for (; padlen < 0; padlen++)
Jari Aalto95732b42005-12-07 14:08:12 +0000792 PC (' ');
793
794 return (ferror (stdout) ? -1 : 0);
Jari Aaltocce855b1998-04-17 19:52:44 +0000795}
796
797/* Convert STRING by expanding the escape sequences specified by the
798 POSIX standard for printf's `%b' format string. If SAWC is non-null,
Jari Aaltob80f6442004-07-27 13:29:18 +0000799 perform the processing appropriate for %b arguments. In particular,
Jari Aaltocce855b1998-04-17 19:52:44 +0000800 recognize `\c' and use that as a string terminator. If we see \c, set
801 *SAWC to 1 before returning. LEN is the length of STRING. */
802
Jari Aaltobb706242000-03-17 21:46:59 +0000803/* Translate a single backslash-escape sequence starting at ESTART (the
804 character after the backslash) and return the number of characters
805 consumed by the sequence. CP is the place to return the translated
806 value. *SAWC is set to 1 if the escape sequence was \c, since that means
807 to short-circuit the rest of the processing. If SAWC is null, we don't
808 do the \c short-circuiting, and \c is treated as an unrecognized escape
Jari Aaltob80f6442004-07-27 13:29:18 +0000809 sequence; we also bypass the other processing specific to %b arguments. */
Jari Aaltobb706242000-03-17 21:46:59 +0000810static int
Chet Ramey495aee42011-11-22 19:11:26 -0500811tescape (estart, cp, lenp, sawc)
Jari Aaltobb706242000-03-17 21:46:59 +0000812 char *estart;
Jari Aaltobb706242000-03-17 21:46:59 +0000813 char *cp;
Chet Ramey495aee42011-11-22 19:11:26 -0500814 int *lenp, *sawc;
Jari Aaltobb706242000-03-17 21:46:59 +0000815{
816 register char *p;
817 int temp, c, evalue;
Chet Ramey495aee42011-11-22 19:11:26 -0500818 unsigned long uvalue;
Jari Aaltobb706242000-03-17 21:46:59 +0000819
820 p = estart;
Chet Ramey495aee42011-11-22 19:11:26 -0500821 if (lenp)
822 *lenp = 1;
Jari Aaltobb706242000-03-17 21:46:59 +0000823
824 switch (c = *p++)
825 {
826#if defined (__STDC__)
827 case 'a': *cp = '\a'; break;
828#else
829 case 'a': *cp = '\007'; break;
830#endif
831
832 case 'b': *cp = '\b'; break;
833
Jari Aalto28ef6c32001-04-06 19:14:31 +0000834 case 'e':
835 case 'E': *cp = '\033'; break; /* ESC -- non-ANSI */
Jari Aaltobb706242000-03-17 21:46:59 +0000836
837 case 'f': *cp = '\f'; break;
838
839 case 'n': *cp = '\n'; break;
840
841 case 'r': *cp = '\r'; break;
842
843 case 't': *cp = '\t'; break;
844
845 case 'v': *cp = '\v'; break;
846
Jari Aaltob80f6442004-07-27 13:29:18 +0000847 /* The octal escape sequences are `\0' followed by up to three octal
848 digits (if SAWC), or `\' followed by up to three octal digits (if
849 !SAWC). As an extension, we allow the latter form even if SAWC. */
850 case '0': case '1': case '2': case '3':
851 case '4': case '5': case '6': case '7':
852 evalue = OCTVALUE (c);
853 for (temp = 2 + (!evalue && !!sawc); ISOCTAL (*p) && temp--; p++)
Jari Aaltobb706242000-03-17 21:46:59 +0000854 evalue = (evalue * 8) + OCTVALUE (*p);
Jari Aaltof73dda02001-11-13 17:56:06 +0000855 *cp = evalue & 0xFF;
Jari Aaltobb706242000-03-17 21:46:59 +0000856 break;
857
Chet Ramey495aee42011-11-22 19:11:26 -0500858 /* And, as another extension, we allow \xNN, where each N is a
Jari Aaltobb706242000-03-17 21:46:59 +0000859 hex digit. */
860 case 'x':
Jari Aaltof73dda02001-11-13 17:56:06 +0000861 for (temp = 2, evalue = 0; ISXDIGIT ((unsigned char)*p) && temp--; p++)
Jari Aaltobb706242000-03-17 21:46:59 +0000862 evalue = (evalue * 16) + HEXVALUE (*p);
Jari Aaltob80f6442004-07-27 13:29:18 +0000863 if (p == estart + 1)
Jari Aaltobb706242000-03-17 21:46:59 +0000864 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000865 builtin_error (_("missing hex digit for \\x"));
Jari Aaltobb706242000-03-17 21:46:59 +0000866 *cp = '\\';
867 return 0;
868 }
Jari Aaltof73dda02001-11-13 17:56:06 +0000869 *cp = evalue & 0xFF;
Jari Aaltobb706242000-03-17 21:46:59 +0000870 break;
871
Chet Ramey495aee42011-11-22 19:11:26 -0500872#if defined (HANDLE_MULTIBYTE)
873 case 'u':
874 case 'U':
875 temp = (c == 'u') ? 4 : 8; /* \uNNNN \UNNNNNNNN */
876 for (uvalue = 0; ISXDIGIT ((unsigned char)*p) && temp--; p++)
877 uvalue = (uvalue * 16) + HEXVALUE (*p);
878 if (p == estart + 1)
879 {
880 builtin_error (_("missing unicode digit for \\%c"), c);
881 *cp = '\\';
882 return 0;
883 }
Chet Rameyac50fba2014-02-26 09:36:43 -0500884 if (uvalue <= 0x7f) /* <= 0x7f translates directly */
Chet Ramey495aee42011-11-22 19:11:26 -0500885 *cp = uvalue;
886 else
887 {
888 temp = u32cconv (uvalue, cp);
889 cp[temp] = '\0';
890 if (lenp)
891 *lenp = temp;
892 }
893 break;
894#endif
895
Jari Aaltobb706242000-03-17 21:46:59 +0000896 case '\\': /* \\ -> \ */
897 *cp = c;
898 break;
899
Jari Aaltob80f6442004-07-27 13:29:18 +0000900 /* SAWC == 0 means that \', \", and \? are recognized as escape
901 sequences, though the only processing performed is backslash
902 removal. */
903 case '\'': case '"': case '?':
904 if (!sawc)
Jari Aaltobb706242000-03-17 21:46:59 +0000905 *cp = c;
906 else
907 {
908 *cp = '\\';
909 return 0;
910 }
911 break;
912
913 case 'c':
914 if (sawc)
915 {
916 *sawc = 1;
917 break;
918 }
919 /* other backslash escapes are passed through unaltered */
920 default:
921 *cp = '\\';
922 return 0;
923 }
924 return (p - estart);
925}
926
Jari Aaltocce855b1998-04-17 19:52:44 +0000927static char *
928bexpand (string, len, sawc, lenp)
929 char *string;
930 int len, *sawc, *lenp;
931{
Jari Aaltobb706242000-03-17 21:46:59 +0000932 int temp;
933 char *ret, *r, *s, c;
Chet Ramey495aee42011-11-22 19:11:26 -0500934#if defined (HANDLE_MULTIBYTE)
935 char mbch[25];
936 int mbind, mblen;
Jari Aalto95732b42005-12-07 14:08:12 +0000937#endif
Chet Ramey495aee42011-11-22 19:11:26 -0500938
939 if (string == 0 || len == 0)
Jari Aaltocce855b1998-04-17 19:52:44 +0000940 {
941 if (sawc)
942 *sawc = 0;
943 if (lenp)
944 *lenp = 0;
945 return ((char *)NULL);
946 }
947
Jari Aaltof73dda02001-11-13 17:56:06 +0000948 ret = (char *)xmalloc (len + 1);
Jari Aaltocce855b1998-04-17 19:52:44 +0000949 for (r = ret, s = string; s && *s; )
950 {
951 c = *s++;
952 if (c != '\\' || *s == '\0')
953 {
954 *r++ = c;
955 continue;
956 }
Jari Aaltobb706242000-03-17 21:46:59 +0000957 temp = 0;
Chet Ramey495aee42011-11-22 19:11:26 -0500958#if defined (HANDLE_MULTIBYTE)
959 memset (mbch, '\0', sizeof (mbch));
960 s += tescape (s, mbch, &mblen, &temp);
961#else
962 s += tescape (s, &c, (int *)NULL, &temp);
963#endif
Jari Aaltobb706242000-03-17 21:46:59 +0000964 if (temp)
Jari Aaltocce855b1998-04-17 19:52:44 +0000965 {
Jari Aaltocce855b1998-04-17 19:52:44 +0000966 if (sawc)
967 *sawc = 1;
Jari Aaltobb706242000-03-17 21:46:59 +0000968 break;
Jari Aaltocce855b1998-04-17 19:52:44 +0000969 }
970
Chet Ramey495aee42011-11-22 19:11:26 -0500971#if defined (HANDLE_MULTIBYTE)
972 for (mbind = 0; mbind < mblen; mbind++)
973 *r++ = mbch[mbind];
974#else
Jari Aaltocce855b1998-04-17 19:52:44 +0000975 *r++ = c;
Chet Ramey495aee42011-11-22 19:11:26 -0500976#endif
Jari Aaltocce855b1998-04-17 19:52:44 +0000977 }
978
979 *r = '\0';
980 if (lenp)
981 *lenp = r - ret;
982 return ret;
983}
984
985static char *
Jari Aalto95732b42005-12-07 14:08:12 +0000986vbadd (buf, blen)
987 char *buf;
988 int blen;
989{
990 size_t nlen;
991
992 nlen = vblen + blen + 1;
993 if (nlen >= vbsize)
994 {
995 vbsize = ((nlen + 63) >> 6) << 6;
996 vbuf = (char *)xrealloc (vbuf, vbsize);
997 }
998
999 if (blen == 1)
1000 vbuf[vblen++] = buf[0];
Jari Aalto31859422009-01-12 13:36:28 +00001001 else if (blen > 1)
Jari Aalto95732b42005-12-07 14:08:12 +00001002 {
1003 FASTCOPY (buf, vbuf + vblen, blen);
1004 vblen += blen;
1005 }
1006 vbuf[vblen] = '\0';
1007
1008#ifdef DEBUG
1009 if (strlen (vbuf) != vblen)
Jari Aalto06285672006-10-10 14:15:34 +00001010 internal_error ("printf:vbadd: vblen (%d) != strlen (vbuf) (%d)", vblen, (int)strlen (vbuf));
Jari Aalto95732b42005-12-07 14:08:12 +00001011#endif
1012
1013 return vbuf;
1014}
1015
Jari Aalto31859422009-01-12 13:36:28 +00001016static int
1017#if defined (PREFER_STDARG)
1018vbprintf (const char *format, ...)
1019#else
1020vbprintf (format, va_alist)
1021 const char *format;
1022 va_dcl
1023#endif
1024{
1025 va_list args;
1026 size_t nlen;
1027 int blen;
1028
1029 SH_VA_START (args, format);
1030 blen = vsnprintf (vbuf + vblen, vbsize - vblen, format, args);
Jari Aalto17345e52009-02-19 22:21:29 +00001031 va_end (args);
Jari Aalto31859422009-01-12 13:36:28 +00001032
1033 nlen = vblen + blen + 1;
1034 if (nlen >= vbsize)
1035 {
1036 vbsize = ((nlen + 63) >> 6) << 6;
1037 vbuf = (char *)xrealloc (vbuf, vbsize);
Jari Aalto17345e52009-02-19 22:21:29 +00001038 SH_VA_START (args, format);
Jari Aalto31859422009-01-12 13:36:28 +00001039 blen = vsnprintf (vbuf + vblen, vbsize - vblen, format, args);
Jari Aalto17345e52009-02-19 22:21:29 +00001040 va_end (args);
Jari Aalto31859422009-01-12 13:36:28 +00001041 }
1042
Jari Aalto31859422009-01-12 13:36:28 +00001043 vblen += blen;
1044 vbuf[vblen] = '\0';
1045
1046#ifdef DEBUG
1047 if (strlen (vbuf) != vblen)
1048 internal_error ("printf:vbadd: vblen (%d) != strlen (vbuf) (%d)", vblen, (int)strlen (vbuf));
1049#endif
1050
1051 return (blen);
1052}
1053
Jari Aalto95732b42005-12-07 14:08:12 +00001054static char *
Jari Aalto7117c2d2002-07-17 14:10:11 +00001055mklong (str, modifiers, mlen)
Jari Aaltocce855b1998-04-17 19:52:44 +00001056 char *str;
Jari Aaltof73dda02001-11-13 17:56:06 +00001057 char *modifiers;
Jari Aalto7117c2d2002-07-17 14:10:11 +00001058 size_t mlen;
Jari Aaltocce855b1998-04-17 19:52:44 +00001059{
Jari Aalto7117c2d2002-07-17 14:10:11 +00001060 size_t len, slen;
Jari Aaltocce855b1998-04-17 19:52:44 +00001061
Jari Aaltof73dda02001-11-13 17:56:06 +00001062 slen = strlen (str);
Jari Aaltof73dda02001-11-13 17:56:06 +00001063 len = slen + mlen + 1;
1064
1065 if (len > conv_bufsize)
1066 {
1067 conv_bufsize = (((len + 1023) >> 10) << 10);
1068 conv_buf = (char *)xrealloc (conv_buf, conv_bufsize);
1069 }
1070
1071 FASTCOPY (str, conv_buf, slen - 1);
1072 FASTCOPY (modifiers, conv_buf + slen - 1, mlen);
1073
1074 conv_buf[len - 2] = str[slen - 1];
1075 conv_buf[len - 1] = '\0';
1076 return (conv_buf);
Jari Aaltocce855b1998-04-17 19:52:44 +00001077}
1078
1079static int
1080getchr ()
1081{
1082 int ret;
1083
1084 if (garglist == 0)
1085 return ('\0');
1086
1087 ret = (int)garglist->word->word[0];
1088 garglist = garglist->next;
1089 return ret;
1090}
1091
1092static char *
1093getstr ()
1094{
1095 char *ret;
1096
1097 if (garglist == 0)
1098 return ("");
1099
1100 ret = garglist->word->word;
1101 garglist = garglist->next;
1102 return ret;
1103}
1104
1105static int
1106getint ()
1107{
Jari Aalto7117c2d2002-07-17 14:10:11 +00001108 intmax_t ret;
Jari Aaltocce855b1998-04-17 19:52:44 +00001109
Jari Aalto7117c2d2002-07-17 14:10:11 +00001110 ret = getintmax ();
Jari Aaltocce855b1998-04-17 19:52:44 +00001111
Chet Rameyac50fba2014-02-26 09:36:43 -05001112 if (garglist == 0)
1113 return ret;
1114
Jari Aaltocce855b1998-04-17 19:52:44 +00001115 if (ret > INT_MAX)
1116 {
Jari Aalto7117c2d2002-07-17 14:10:11 +00001117 printf_erange (garglist->word->word);
Jari Aalto28ef6c32001-04-06 19:14:31 +00001118 ret = INT_MAX;
1119 }
1120 else if (ret < INT_MIN)
1121 {
Jari Aalto7117c2d2002-07-17 14:10:11 +00001122 printf_erange (garglist->word->word);
Jari Aalto28ef6c32001-04-06 19:14:31 +00001123 ret = INT_MIN;
Jari Aaltocce855b1998-04-17 19:52:44 +00001124 }
1125
1126 return ((int)ret);
1127}
1128
Jari Aaltof73dda02001-11-13 17:56:06 +00001129static intmax_t
1130getintmax ()
1131{
1132 intmax_t ret;
1133 char *ep;
1134
1135 if (garglist == 0)
1136 return (0);
1137
1138 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
1139 return asciicode ();
1140
1141 errno = 0;
1142 ret = strtoimax (garglist->word->word, &ep, 0);
1143
1144 if (*ep)
1145 {
Jari Aalto7117c2d2002-07-17 14:10:11 +00001146 sh_invalidnum (garglist->word->word);
Jari Aaltof73dda02001-11-13 17:56:06 +00001147 /* POSIX.2 says ``...a diagnostic message shall be written to standard
1148 error, and the utility shall not exit with a zero exit status, but
1149 shall continue processing any remaining operands and shall write the
1150 value accumulated at the time the error was detected to standard
1151 output.'' Yecch. */
Chet Ramey00018032011-11-21 20:51:19 -05001152#if 0
1153 ret = 0; /* return partially-converted value from strtoimax */
1154#endif
Jari Aaltof73dda02001-11-13 17:56:06 +00001155 conversion_error = 1;
1156 }
1157 else if (errno == ERANGE)
Jari Aalto7117c2d2002-07-17 14:10:11 +00001158 printf_erange (garglist->word->word);
Jari Aaltof73dda02001-11-13 17:56:06 +00001159
1160 garglist = garglist->next;
1161 return (ret);
1162}
1163
1164static uintmax_t
1165getuintmax ()
1166{
1167 uintmax_t ret;
1168 char *ep;
1169
1170 if (garglist == 0)
1171 return (0);
1172
1173 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
1174 return asciicode ();
1175
1176 errno = 0;
1177 ret = strtoumax (garglist->word->word, &ep, 0);
1178
1179 if (*ep)
1180 {
Jari Aalto7117c2d2002-07-17 14:10:11 +00001181 sh_invalidnum (garglist->word->word);
1182 /* Same POSIX.2 conversion error requirements as getintmax(). */
Jari Aaltof73dda02001-11-13 17:56:06 +00001183 ret = 0;
1184 conversion_error = 1;
1185 }
1186 else if (errno == ERANGE)
Jari Aalto7117c2d2002-07-17 14:10:11 +00001187 printf_erange (garglist->word->word);
Jari Aaltof73dda02001-11-13 17:56:06 +00001188
1189 garglist = garglist->next;
1190 return (ret);
1191}
1192
Jari Aalto7117c2d2002-07-17 14:10:11 +00001193static floatmax_t
1194getfloatmax ()
Jari Aaltocce855b1998-04-17 19:52:44 +00001195{
Jari Aalto7117c2d2002-07-17 14:10:11 +00001196 floatmax_t ret;
Jari Aalto28ef6c32001-04-06 19:14:31 +00001197 char *ep;
Jari Aaltocce855b1998-04-17 19:52:44 +00001198
1199 if (garglist == 0)
Jari Aaltof73dda02001-11-13 17:56:06 +00001200 return (0);
Jari Aaltocce855b1998-04-17 19:52:44 +00001201
1202 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
Jari Aaltof73dda02001-11-13 17:56:06 +00001203 return asciicode ();
Jari Aaltocce855b1998-04-17 19:52:44 +00001204
Jari Aalto28ef6c32001-04-06 19:14:31 +00001205 errno = 0;
Jari Aalto7117c2d2002-07-17 14:10:11 +00001206 ret = strtofltmax (garglist->word->word, &ep);
Jari Aaltof73dda02001-11-13 17:56:06 +00001207
Jari Aalto28ef6c32001-04-06 19:14:31 +00001208 if (*ep)
1209 {
Jari Aalto7117c2d2002-07-17 14:10:11 +00001210 sh_invalidnum (garglist->word->word);
Jari Aaltof73dda02001-11-13 17:56:06 +00001211 /* Same thing about POSIX.2 conversion error requirements. */
1212 ret = 0;
1213 conversion_error = 1;
Jari Aalto28ef6c32001-04-06 19:14:31 +00001214 }
1215 else if (errno == ERANGE)
Jari Aalto7117c2d2002-07-17 14:10:11 +00001216 printf_erange (garglist->word->word);
Jari Aalto28ef6c32001-04-06 19:14:31 +00001217
Jari Aaltocce855b1998-04-17 19:52:44 +00001218 garglist = garglist->next;
Jari Aaltof73dda02001-11-13 17:56:06 +00001219 return (ret);
Jari Aaltocce855b1998-04-17 19:52:44 +00001220}
1221
Jari Aaltocce855b1998-04-17 19:52:44 +00001222/* NO check is needed for garglist here. */
Jari Aalto31859422009-01-12 13:36:28 +00001223static intmax_t
Jari Aaltocce855b1998-04-17 19:52:44 +00001224asciicode ()
1225{
Jari Aalto31859422009-01-12 13:36:28 +00001226 register intmax_t ch;
1227#if defined (HANDLE_MULTIBYTE)
1228 wchar_t wc;
1229 size_t mblength, slen;
1230#endif
1231 DECLARE_MBSTATE;
Jari Aaltocce855b1998-04-17 19:52:44 +00001232
Jari Aalto31859422009-01-12 13:36:28 +00001233#if defined (HANDLE_MULTIBYTE)
1234 slen = strlen (garglist->word->word+1);
1235 mblength = MBLEN (garglist->word->word+1, slen);
1236 if (mblength > 1)
1237 {
1238 mblength = mbtowc (&wc, garglist->word->word+1, slen);
1239 ch = wc; /* XXX */
1240 }
1241 else
1242#endif
1243 ch = (unsigned char)garglist->word->word[1];
1244
Jari Aaltocce855b1998-04-17 19:52:44 +00001245 garglist = garglist->next;
1246 return (ch);
1247}
Chet Ramey00018032011-11-21 20:51:19 -05001248
1249static SHELL_VAR *
1250bind_printf_variable (name, value, flags)
1251 char *name;
1252 char *value;
1253 int flags;
1254{
Chet Rameyac50fba2014-02-26 09:36:43 -05001255 SHELL_VAR *v;
1256
Chet Ramey00018032011-11-21 20:51:19 -05001257#if defined (ARRAY_VARS)
1258 if (valid_array_reference (name) == 0)
Chet Rameyac50fba2014-02-26 09:36:43 -05001259 v = bind_variable (name, value, flags);
Chet Ramey00018032011-11-21 20:51:19 -05001260 else
Chet Rameyac50fba2014-02-26 09:36:43 -05001261 v = assign_array_element (name, value, flags);
Chet Ramey00018032011-11-21 20:51:19 -05001262#else /* !ARRAY_VARS */
Chet Rameyac50fba2014-02-26 09:36:43 -05001263 v = bind_variable (name, value, flags);
Chet Ramey00018032011-11-21 20:51:19 -05001264#endif /* !ARRAY_VARS */
Chet Rameyac50fba2014-02-26 09:36:43 -05001265
1266 if (v && readonly_p (v) == 0 && noassign_p (v) == 0)
1267 VUNSETATTR (v, att_invisible);
1268
1269 return v;
Chet Ramey00018032011-11-21 20:51:19 -05001270}