]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/printf.def
Bash-4.3 patch 39
[thirdparty/bash.git] / builtins / printf.def
CommitLineData
cce855bc
JA
1This file is printf.def, from which is created printf.c.
2It implements the builtin "printf" in Bash.
3
495aee44 4Copyright (C) 1997-2010 Free Software Foundation, Inc.
cce855bc
JA
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
3185942a
JA
8Bash 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.
cce855bc 12
3185942a
JA
13Bash 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.
cce855bc 17
3185942a
JA
18You should have received a copy of the GNU General Public License
19along with Bash. If not, see <http://www.gnu.org/licenses/>.
cce855bc
JA
20
21$PRODUCES printf.c
22
23$BUILTIN printf
24$FUNCTION printf_builtin
95732b49 25$SHORT_DOC printf [-v var] format [arguments]
3185942a
JA
26Formats 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
cce855bc 35format specifications, each of which causes printing of the next successive
3185942a
JA
36argument.
37
ac50fbac
CR
38In addition to the standard format specifications described in printf(1),
39printf interprets:
3185942a
JA
40
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
495aee44
CR
43 %(fmt)T output the date-time string resulting from using FMT as a format
44 string for strftime(3)
3185942a 45
ac50fbac
CR
46The 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
3185942a
JA
51Exit Status:
52Returns success unless an invalid option is given or a write or assignment
53error occurs.
cce855bc
JA
54$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
f73dda09 64 /* Assume 32-bit ints. */
cce855bc
JA
65# define INT_MAX 2147483647
66# define INT_MIN (-2147483647-1)
67#endif
68
f1be666c
JA
69#if defined (PREFER_STDARG)
70# include <stdarg.h>
71#else
72# include <varargs.h>
73#endif
74
cce855bc 75#include <stdio.h>
f73dda09
JA
76#include <chartypes.h>
77
78#ifdef HAVE_INTTYPES_H
79# include <inttypes.h>
80#endif
cce855bc 81
495aee44 82#include "posixtime.h"
cce855bc 83#include "../bashansi.h"
b80f6443 84#include "../bashintl.h"
f73dda09 85
495aee44
CR
86#define NEED_STRFTIME_DECL
87
cce855bc 88#include "../shell.h"
3185942a 89#include "shmbutil.h"
bb70624e 90#include "stdc.h"
cce855bc 91#include "bashgetopt.h"
f73dda09
JA
92#include "common.h"
93
f1be666c
JA
94#if defined (PRI_MACROS_BROKEN)
95# undef PRIdMAX
96#endif
97
7117c2d2
JA
98#if !defined (PRIdMAX)
99# if HAVE_LONG_LONG
100# define PRIdMAX "lld"
101# else
102# define PRIdMAX "ld"
103# endif
f73dda09 104#endif
cce855bc
JA
105
106#if !defined (errno)
107extern int errno;
108#endif
109
95732b49
JA
110#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
cce855bc
JA
121#define PF(f, func) \
122 do { \
95732b49 123 int nw; \
0628567a 124 clearerr (stdout); \
f73dda09 125 if (have_fieldwidth && have_precision) \
3185942a 126 nw = vflag ? vbprintf (f, fieldwidth, precision, func) : printf (f, fieldwidth, precision, func); \
f73dda09 127 else if (have_fieldwidth) \
3185942a 128 nw = vflag ? vbprintf (f, fieldwidth, func) : printf (f, fieldwidth, func); \
f73dda09 129 else if (have_precision) \
30d188c2 130 nw = vflag ? vbprintf (f, precision, func) : printf (f, precision, func); \
cce855bc 131 else \
3185942a 132 nw = vflag ? vbprintf (f, func) : printf (f, func); \
95732b49 133 tw += nw; \
3185942a 134 if (ferror (stdout)) \
95732b49 135 { \
3185942a
JA
136 sh_wrerror (); \
137 clearerr (stdout); \
138 return (EXECUTION_FAILURE); \
95732b49 139 } \
cce855bc
JA
140 } while (0)
141
f73dda09 142/* We free the buffer used by mklong() if it's `too big'. */
cce855bc 143#define PRETURN(value) \
f73dda09
JA
144 do \
145 { \
95732b49
JA
146 if (vflag) \
147 { \
0001803f 148 bind_printf_variable (vname, vbuf, 0); \
95732b49
JA
149 stupidly_hack_special_variables (vname); \
150 } \
f73dda09
JA
151 if (conv_bufsize > 4096 ) \
152 { \
95732b49 153 free (conv_buf); \
f73dda09
JA
154 conv_bufsize = 0; \
155 conv_buf = 0; \
156 } \
95732b49
JA
157 if (vbsize > 4096) \
158 { \
159 free (vbuf); \
160 vbsize = 0; \
161 vbuf = 0; \
162 } \
3185942a
JA
163 else if (vbuf) \
164 vbuf[0] = 0; \
165 terminate_immediately--; \
ac50fbac
CR
166 if (ferror (stdout) == 0) \
167 fflush (stdout); \
0628567a
JA
168 if (ferror (stdout)) \
169 { \
0001803f 170 sh_wrerror (); \
0628567a
JA
171 clearerr (stdout); \
172 return (EXECUTION_FAILURE); \
173 } \
f73dda09
JA
174 return (value); \
175 } \
176 while (0)
177
178#define SKIP1 "#'-+ 0"
179#define LENMODS "hjlLtz"
cce855bc 180
495aee44
CR
181extern time_t shell_start_time;
182
0001803f 183#if !HAVE_ASPRINTF
f1be666c
JA
184extern int asprintf __P((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
185#endif
186
0001803f 187#if !HAVE_VSNPRINTF
30d188c2 188extern int vsnprintf __P((char *, size_t, const char *, va_list)) __attribute__((__format__ (printf, 3, 0)));
3185942a
JA
189#endif
190
7117c2d2 191static void printf_erange __P((char *));
95732b49 192static int printstr __P((char *, char *, int, int, int));
495aee44 193static int tescape __P((char *, char *, int *, int *));
cce855bc 194static char *bexpand __P((char *, int, int *, int *));
95732b49 195static char *vbadd __P((char *, int));
3185942a 196static int vbprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
7117c2d2 197static char *mklong __P((char *, char *, size_t));
cce855bc
JA
198static int getchr __P((void));
199static char *getstr __P((void));
200static int getint __P((void));
f73dda09
JA
201static intmax_t getintmax __P((void));
202static uintmax_t getuintmax __P((void));
0001803f 203static SHELL_VAR *bind_printf_variable __P((char *, char *, int));
7117c2d2 204
b80f6443 205#if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD && !defined(STRTOLD_BROKEN)
7117c2d2
JA
206typedef 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
f73dda09 213#endif
7117c2d2
JA
214static floatmax_t getfloatmax __P((void));
215
3185942a 216static intmax_t asciicode __P((void));
cce855bc
JA
217
218static WORD_LIST *garglist;
219static int retval;
f73dda09 220static int conversion_error;
cce855bc 221
95732b49
JA
222/* 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
f73dda09
JA
230static char *conv_buf;
231static size_t conv_bufsize;
cce855bc
JA
232
233int
234printf_builtin (list)
235 WORD_LIST *list;
236{
f73dda09
JA
237 int ch, fieldwidth, precision;
238 int have_fieldwidth, have_precision;
f73dda09 239 char convch, thisch, nextch, *format, *modstart, *fmt, *start;
495aee44
CR
240#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
cce855bc 244
f73dda09 245 conversion_error = 0;
cce855bc 246 retval = EXECUTION_SUCCESS;
7117c2d2 247
95732b49
JA
248 vflag = 0;
249
250 reset_internal_getopt ();
251 while ((ch = internal_getopt (list, "v:")) != -1)
252 {
253 switch (ch)
254 {
255 case 'v':
0001803f
CR
256 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
95732b49
JA
262 {
263 vflag = 1;
6c19148d
CR
264 if (vbsize == 0)
265 vbuf = xmalloc (vbsize = 16);
95732b49 266 vblen = 0;
3185942a
JA
267 if (vbuf)
268 vbuf[0] = 0;
95732b49
JA
269 }
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 }
7117c2d2 281 list = loptend; /* skip over possible `--' */
cce855bc
JA
282
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
bb70624e 292 format = list->word->word;
95732b49 293 tw = 0;
cce855bc
JA
294
295 garglist = list->next;
296
bc4cd23c 297 /* If the format string is empty after preprocessing, return immediately. */
bb70624e 298 if (format == 0 || *format == 0)
bc4cd23c 299 return (EXECUTION_SUCCESS);
3185942a
JA
300
301 terminate_immediately++;
bc4cd23c 302
cce855bc
JA
303 /* 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. */
cce855bc
JA
309 do
310 {
f73dda09 311 tw = 0;
cce855bc 312 /* find next format specification */
bb70624e 313 for (fmt = format; *fmt; fmt++)
cce855bc 314 {
f73dda09
JA
315 precision = fieldwidth = 0;
316 have_fieldwidth = have_precision = 0;
317
bb70624e
JA
318 if (*fmt == '\\')
319 {
320 fmt++;
b80f6443
JA
321 /* A NULL third argument to tescape means to bypass the
322 special processing for arguments to %b. */
495aee44
CR
323#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);
95732b49 332 PC (nextch);
495aee44 333#endif
bb70624e
JA
334 fmt--; /* for loop will increment it for us again */
335 continue;
336 }
337
cce855bc
JA
338 if (*fmt != '%')
339 {
95732b49 340 PC (*fmt);
cce855bc
JA
341 continue;
342 }
343
344 /* ASSERT(*fmt == '%') */
345 start = fmt++;
346
347 if (*fmt == '%') /* %% prints a % */
348 {
95732b49 349 PC ('%');
cce855bc
JA
350 continue;
351 }
352
353 /* found format specification, skip to field width */
354 for (; *fmt && strchr(SKIP1, *fmt); ++fmt)
355 ;
cce855bc 356
f73dda09
JA
357 /* 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 */
cce855bc
JA
369 if (*fmt == '.')
370 {
371 ++fmt;
f73dda09
JA
372 if (*fmt == '*')
373 {
374 fmt++;
375 have_precision = 1;
376 precision = getint ();
377 }
378 else
95732b49
JA
379 {
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 }
cce855bc
JA
393 }
394
cce855bc 395 /* skip possible format modifiers */
f73dda09
JA
396 modstart = fmt;
397 while (*fmt && strchr (LENMODS, *fmt))
398 fmt++;
cce855bc 399
b72432fd
JA
400 if (*fmt == 0)
401 {
b80f6443 402 builtin_error (_("`%s': missing format character"), start);
b72432fd
JA
403 PRETURN (EXECUTION_FAILURE);
404 }
405
cce855bc 406 convch = *fmt;
f73dda09
JA
407 thisch = modstart[0];
408 nextch = modstart[1];
409 modstart[0] = convch;
410 modstart[1] = '\0';
411
cce855bc
JA
412 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
495aee44
CR
432 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 */
ac50fbac
CR
469 /* default argument is equivalent to -1; special case */
470 arg = garglist ? getintmax () : -1;
495aee44
CR
471 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;
2bbe8058
CR
477#if defined (HAVE_TZSET)
478 sv_tz ("TZ"); /* XXX -- just make sure */
479#endif
495aee44 480 tm = localtime (&secs);
ac50fbac
CR
481 if (tm == 0)
482 {
483 secs = 0;
484 tm = localtime (&secs);
485 }
486 n = tm ? strftime (timebuf, sizeof (timebuf), timefmt, tm) : 0;
495aee44
CR
487 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 {
ac50fbac
CR
498 if (ferror (stdout) == 0)
499 {
500 sh_wrerror ();
501 clearerr (stdout);
502 }
495aee44
CR
503 PRETURN (EXECUTION_FAILURE);
504 }
505 break;
506 }
507
f73dda09
JA
508 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 {
7117c2d2 519 sh_invalidid (var);
f73dda09
JA
520 PRETURN (EXECUTION_FAILURE);
521 }
522 }
523 break;
524 }
525
cce855bc
JA
526 case 'b': /* expand escapes in argument */
527 {
528 char *p, *xp;
95732b49 529 int rlen, r;
cce855bc
JA
530
531 p = getstr ();
95732b49 532 ch = rlen = r = 0;
cce855bc
JA
533 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. */
95732b49
JA
539 r = printstr (start, xp, rlen, fieldwidth, precision);
540 if (r < 0)
541 {
ac50fbac
CR
542 if (ferror (stdout) == 0)
543 {
544 sh_wrerror ();
545 clearerr (stdout);
546 }
95732b49
JA
547 retval = EXECUTION_FAILURE;
548 }
cce855bc
JA
549 free (xp);
550 }
551
95732b49 552 if (ch || r < 0)
cce855bc
JA
553 PRETURN (retval);
554 break;
555 }
556
557 case 'q': /* print with shell quoting */
558 {
559 char *p, *xp;
95732b49 560 int r;
cce855bc 561
95732b49 562 r = 0;
cce855bc 563 p = getstr ();
0628567a
JA
564 if (p && *p == 0) /* XXX - getstr never returns null */
565 xp = savestring ("''");
566 else if (ansic_shouldquote (p))
7117c2d2
JA
567 xp = ansic_quote (p, 0, (int *)0);
568 else
ac50fbac 569 xp = sh_backslash_quote (p, 0, 1);
cce855bc
JA
570 if (xp)
571 {
572 /* Use printstr to get fieldwidth and precision right. */
95732b49
JA
573 r = printstr (start, xp, strlen (xp), fieldwidth, precision);
574 if (r < 0)
575 {
576 sh_wrerror ();
577 clearerr (stdout);
578 }
cce855bc
JA
579 free (xp);
580 }
95732b49
JA
581
582 if (r < 0)
583 PRETURN (EXECUTION_FAILURE);
cce855bc
JA
584 break;
585 }
586
587 case 'd':
588 case 'i':
589 {
cce855bc 590 char *f;
7117c2d2
JA
591 long p;
592 intmax_t pp;
f73dda09 593
7117c2d2
JA
594 p = pp = getintmax ();
595 if (p != pp)
f73dda09 596 {
7117c2d2
JA
597 f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
598 PF (f, pp);
f73dda09 599 }
cce855bc 600 else
f73dda09 601 {
7117c2d2
JA
602 /* 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);
f73dda09 608 }
cce855bc
JA
609 break;
610 }
611
612 case 'o':
613 case 'u':
614 case 'x':
615 case 'X':
616 {
cce855bc 617 char *f;
7117c2d2
JA
618 unsigned long p;
619 uintmax_t pp;
f73dda09 620
7117c2d2
JA
621 p = pp = getuintmax ();
622 if (p != pp)
f73dda09 623 {
7117c2d2
JA
624 f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
625 PF (f, pp);
f73dda09 626 }
cce855bc 627 else
f73dda09 628 {
7117c2d2 629 f = mklong (start, "l", 1);
f73dda09
JA
630 PF (f, p);
631 }
cce855bc
JA
632 break;
633 }
634
635 case 'e':
636 case 'E':
637 case 'f':
f73dda09 638 case 'F':
cce855bc
JA
639 case 'g':
640 case 'G':
f73dda09
JA
641#if defined (HAVE_PRINTF_A_FORMAT)
642 case 'a':
643 case 'A':
644#endif
cce855bc 645 {
f73dda09 646 char *f;
7117c2d2 647 floatmax_t p;
f73dda09 648
7117c2d2
JA
649 p = getfloatmax ();
650 f = mklong (start, FLOATMAX_CONV, sizeof(FLOATMAX_CONV) - 1);
651 PF (f, p);
cce855bc
JA
652 break;
653 }
654
bb70624e
JA
655 /* We don't output unrecognized format characters; we print an
656 error message and return a failure exit status. */
cce855bc 657 default:
b80f6443 658 builtin_error (_("`%c': invalid format character"), convch);
cce855bc
JA
659 PRETURN (EXECUTION_FAILURE);
660 }
661
f73dda09
JA
662 modstart[0] = thisch;
663 modstart[1] = nextch;
cce855bc 664 }
95732b49
JA
665
666 if (ferror (stdout))
667 {
ac50fbac 668 /* PRETURN will print error message. */
95732b49
JA
669 PRETURN (EXECUTION_FAILURE);
670 }
cce855bc 671 }
bc4cd23c 672 while (garglist && garglist != list->next);
cce855bc 673
f73dda09
JA
674 if (conversion_error)
675 retval = EXECUTION_FAILURE;
676
cce855bc
JA
677 PRETURN (retval);
678}
679
7117c2d2
JA
680static void
681printf_erange (s)
682 char *s;
683{
3185942a 684 builtin_error (_("warning: %s: %s"), s, strerror(ERANGE));
7117c2d2
JA
685}
686
cce855bc 687/* We duplicate a lot of what printf(3) does here. */
95732b49 688static int
cce855bc
JA
689printstr (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 */
ac50fbac 701 intmax_t mfw, mpr;
cce855bc 702
95732b49 703 if (string == 0 || len == 0)
3185942a 704 return 0;
cce855bc
JA
705
706#if 0
707 s = fmt;
708#endif
709 if (*fmt == '%')
710 fmt++;
711
f73dda09
JA
712 ljust = fw = 0;
713 pr = -1;
ac50fbac
CR
714 mfw = 0;
715 mpr = -1;
cce855bc
JA
716
717 /* skip flags */
f73dda09 718 while (strchr (SKIP1, *fmt))
cce855bc
JA
719 {
720 if (*fmt == '-')
721 ljust = 1;
722 fmt++;
723 }
724
ac50fbac 725 /* get fieldwidth, if present. rely on caller to clamp fieldwidth at INT_MAX */
cce855bc
JA
726 if (*fmt == '*')
727 {
728 fmt++;
729 fw = fieldwidth;
f73dda09
JA
730 if (fw < 0)
731 {
732 fw = -fw;
733 ljust = 1;
734 }
cce855bc 735 }
f73dda09 736 else if (DIGIT (*fmt))
cce855bc 737 {
ac50fbac 738 mfw = *fmt++ - '0';
f73dda09 739 while (DIGIT (*fmt))
ac50fbac
CR
740 mfw = (mfw * 10) + (*fmt++ - '0');
741 /* Error if fieldwidth > INT_MAX here? */
742 fw = (mfw < 0 || mfw > INT_MAX) ? INT_MAX : mfw;
cce855bc
JA
743 }
744
745 /* get precision, if present */
746 if (*fmt == '.')
747 {
748 fmt++;
749 if (*fmt == '*')
750 {
751 fmt++;
752 pr = precision;
753 }
f73dda09 754 else if (DIGIT (*fmt))
cce855bc 755 {
ac50fbac 756 mpr = *fmt++ - '0';
f73dda09 757 while (DIGIT (*fmt))
ac50fbac
CR
758 mpr = (mpr * 10) + (*fmt++ - '0');
759 /* Error if precision > INT_MAX here? */
760 pr = (mpr < 0 || mpr > INT_MAX) ? INT_MAX : mpr;
cce855bc
JA
761 }
762 }
763
764#if 0
765 /* If we remove this, get rid of `s'. */
766 if (*fmt != 'b' && *fmt != 'q')
767 {
ac50fbac 768 internal_error (_("format parsing problem: %s"), s);
cce855bc
JA
769 fw = pr = 0;
770 }
771#endif
772
773 /* chars from string to print */
f73dda09 774 nc = (pr >= 0 && pr <= len) ? pr : len;
cce855bc
JA
775
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--)
95732b49 784 PC (' ');
cce855bc
JA
785
786 /* output NC characters from STRING */
787 for (i = 0; i < nc; i++)
95732b49 788 PC (string[i]);
cce855bc
JA
789
790 /* output any necessary trailing padding */
791 for (; padlen < 0; padlen++)
95732b49
JA
792 PC (' ');
793
794 return (ferror (stdout) ? -1 : 0);
cce855bc
JA
795}
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,
b80f6443 799 perform the processing appropriate for %b arguments. In particular,
cce855bc
JA
800 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
bb70624e
JA
803/* 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
b80f6443 809 sequence; we also bypass the other processing specific to %b arguments. */
bb70624e 810static int
495aee44 811tescape (estart, cp, lenp, sawc)
bb70624e 812 char *estart;
bb70624e 813 char *cp;
495aee44 814 int *lenp, *sawc;
bb70624e
JA
815{
816 register char *p;
817 int temp, c, evalue;
495aee44 818 unsigned long uvalue;
bb70624e
JA
819
820 p = estart;
495aee44
CR
821 if (lenp)
822 *lenp = 1;
bb70624e
JA
823
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
28ef6c31
JA
834 case 'e':
835 case 'E': *cp = '\033'; break; /* ESC -- non-ANSI */
bb70624e
JA
836
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
b80f6443
JA
847 /* 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++)
bb70624e 854 evalue = (evalue * 8) + OCTVALUE (*p);
f73dda09 855 *cp = evalue & 0xFF;
bb70624e
JA
856 break;
857
495aee44 858 /* And, as another extension, we allow \xNN, where each N is a
bb70624e
JA
859 hex digit. */
860 case 'x':
f73dda09 861 for (temp = 2, evalue = 0; ISXDIGIT ((unsigned char)*p) && temp--; p++)
bb70624e 862 evalue = (evalue * 16) + HEXVALUE (*p);
b80f6443 863 if (p == estart + 1)
bb70624e 864 {
b80f6443 865 builtin_error (_("missing hex digit for \\x"));
bb70624e
JA
866 *cp = '\\';
867 return 0;
868 }
f73dda09 869 *cp = evalue & 0xFF;
bb70624e
JA
870 break;
871
495aee44
CR
872#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 }
ac50fbac 884 if (uvalue <= 0x7f) /* <= 0x7f translates directly */
495aee44
CR
885 *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
bb70624e
JA
896 case '\\': /* \\ -> \ */
897 *cp = c;
898 break;
899
b80f6443
JA
900 /* 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)
bb70624e
JA
905 *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
cce855bc
JA
927static char *
928bexpand (string, len, sawc, lenp)
929 char *string;
930 int len, *sawc, *lenp;
931{
bb70624e
JA
932 int temp;
933 char *ret, *r, *s, c;
495aee44
CR
934#if defined (HANDLE_MULTIBYTE)
935 char mbch[25];
936 int mbind, mblen;
937#endif
cce855bc 938
95732b49 939 if (string == 0 || len == 0)
cce855bc
JA
940 {
941 if (sawc)
942 *sawc = 0;
943 if (lenp)
944 *lenp = 0;
945 return ((char *)NULL);
946 }
947
f73dda09 948 ret = (char *)xmalloc (len + 1);
cce855bc
JA
949 for (r = ret, s = string; s && *s; )
950 {
951 c = *s++;
952 if (c != '\\' || *s == '\0')
953 {
954 *r++ = c;
955 continue;
956 }
bb70624e 957 temp = 0;
495aee44
CR
958#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
bb70624e 964 if (temp)
cce855bc 965 {
cce855bc
JA
966 if (sawc)
967 *sawc = 1;
bb70624e 968 break;
cce855bc
JA
969 }
970
495aee44
CR
971#if defined (HANDLE_MULTIBYTE)
972 for (mbind = 0; mbind < mblen; mbind++)
973 *r++ = mbch[mbind];
974#else
cce855bc 975 *r++ = c;
495aee44 976#endif
cce855bc
JA
977 }
978
979 *r = '\0';
980 if (lenp)
981 *lenp = r - ret;
982 return ret;
983}
984
95732b49
JA
985static char *
986vbadd (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];
3185942a 1001 else if (blen > 1)
95732b49
JA
1002 {
1003 FASTCOPY (buf, vbuf + vblen, blen);
1004 vblen += blen;
1005 }
1006 vbuf[vblen] = '\0';
1007
1008#ifdef DEBUG
1009 if (strlen (vbuf) != vblen)
0628567a 1010 internal_error ("printf:vbadd: vblen (%d) != strlen (vbuf) (%d)", vblen, (int)strlen (vbuf));
95732b49
JA
1011#endif
1012
1013 return vbuf;
1014}
1015
3185942a
JA
1016static 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);
17345e5a 1031 va_end (args);
3185942a
JA
1032
1033 nlen = vblen + blen + 1;
1034 if (nlen >= vbsize)
1035 {
1036 vbsize = ((nlen + 63) >> 6) << 6;
1037 vbuf = (char *)xrealloc (vbuf, vbsize);
17345e5a 1038 SH_VA_START (args, format);
3185942a 1039 blen = vsnprintf (vbuf + vblen, vbsize - vblen, format, args);
17345e5a 1040 va_end (args);
3185942a
JA
1041 }
1042
3185942a
JA
1043 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
cce855bc 1054static char *
7117c2d2 1055mklong (str, modifiers, mlen)
cce855bc 1056 char *str;
f73dda09 1057 char *modifiers;
7117c2d2 1058 size_t mlen;
cce855bc 1059{
7117c2d2 1060 size_t len, slen;
f73dda09
JA
1061
1062 slen = strlen (str);
f73dda09
JA
1063 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);
cce855bc
JA
1077}
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{
7117c2d2 1108 intmax_t ret;
cce855bc 1109
7117c2d2 1110 ret = getintmax ();
cce855bc 1111
ac50fbac
CR
1112 if (garglist == 0)
1113 return ret;
1114
cce855bc
JA
1115 if (ret > INT_MAX)
1116 {
7117c2d2 1117 printf_erange (garglist->word->word);
28ef6c31
JA
1118 ret = INT_MAX;
1119 }
1120 else if (ret < INT_MIN)
1121 {
7117c2d2 1122 printf_erange (garglist->word->word);
28ef6c31 1123 ret = INT_MIN;
cce855bc
JA
1124 }
1125
1126 return ((int)ret);
1127}
1128
f73dda09
JA
1129static intmax_t
1130getintmax ()
cce855bc 1131{
f73dda09 1132 intmax_t ret;
28ef6c31 1133 char *ep;
cce855bc
JA
1134
1135 if (garglist == 0)
f73dda09
JA
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)
28ef6c31 1145 {
7117c2d2 1146 sh_invalidnum (garglist->word->word);
f73dda09
JA
1147 /* 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. */
0001803f
CR
1152#if 0
1153 ret = 0; /* return partially-converted value from strtoimax */
1154#endif
f73dda09 1155 conversion_error = 1;
28ef6c31 1156 }
f73dda09 1157 else if (errno == ERANGE)
7117c2d2 1158 printf_erange (garglist->word->word);
f73dda09
JA
1159
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);
cce855bc
JA
1172
1173 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
f73dda09
JA
1174 return asciicode ();
1175
1176 errno = 0;
1177 ret = strtoumax (garglist->word->word, &ep, 0);
1178
1179 if (*ep)
28ef6c31 1180 {
7117c2d2
JA
1181 sh_invalidnum (garglist->word->word);
1182 /* Same POSIX.2 conversion error requirements as getintmax(). */
f73dda09
JA
1183 ret = 0;
1184 conversion_error = 1;
28ef6c31 1185 }
f73dda09 1186 else if (errno == ERANGE)
7117c2d2 1187 printf_erange (garglist->word->word);
f73dda09
JA
1188
1189 garglist = garglist->next;
1190 return (ret);
1191}
1192
7117c2d2
JA
1193static floatmax_t
1194getfloatmax ()
f73dda09 1195{
7117c2d2 1196 floatmax_t ret;
f73dda09
JA
1197 char *ep;
1198
1199 if (garglist == 0)
1200 return (0);
1201
1202 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
1203 return asciicode ();
cce855bc 1204
28ef6c31 1205 errno = 0;
7117c2d2 1206 ret = strtofltmax (garglist->word->word, &ep);
f73dda09 1207
28ef6c31
JA
1208 if (*ep)
1209 {
7117c2d2 1210 sh_invalidnum (garglist->word->word);
f73dda09
JA
1211 /* Same thing about POSIX.2 conversion error requirements. */
1212 ret = 0;
1213 conversion_error = 1;
28ef6c31
JA
1214 }
1215 else if (errno == ERANGE)
7117c2d2 1216 printf_erange (garglist->word->word);
28ef6c31 1217
cce855bc 1218 garglist = garglist->next;
f73dda09 1219 return (ret);
cce855bc
JA
1220}
1221
1222/* NO check is needed for garglist here. */
3185942a 1223static intmax_t
cce855bc
JA
1224asciicode ()
1225{
3185942a
JA
1226 register intmax_t ch;
1227#if defined (HANDLE_MULTIBYTE)
1228 wchar_t wc;
1229 size_t mblength, slen;
1230#endif
1231 DECLARE_MBSTATE;
1232
1233#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];
cce855bc 1244
cce855bc
JA
1245 garglist = garglist->next;
1246 return (ch);
1247}
0001803f
CR
1248
1249static SHELL_VAR *
1250bind_printf_variable (name, value, flags)
1251 char *name;
1252 char *value;
1253 int flags;
1254{
ac50fbac
CR
1255 SHELL_VAR *v;
1256
0001803f
CR
1257#if defined (ARRAY_VARS)
1258 if (valid_array_reference (name) == 0)
ac50fbac 1259 v = bind_variable (name, value, flags);
0001803f 1260 else
ac50fbac 1261 v = assign_array_element (name, value, flags);
0001803f 1262#else /* !ARRAY_VARS */
ac50fbac 1263 v = bind_variable (name, value, flags);
0001803f 1264#endif /* !ARRAY_VARS */
ac50fbac
CR
1265
1266 if (v && readonly_p (v) == 0 && noassign_p (v) == 0)
1267 VUNSETATTR (v, att_invisible);
1268
1269 return v;
0001803f 1270}