Added gitignore entries needed to ignore derived objects generated from full build...
[bash.git] / builtins / printf.def
blob7892cb5a0940acb0ecb11a1348abe3fd8de349df
1 This file is printf.def, from which is created printf.c.
2 It implements the builtin "printf" in Bash.
4 Copyright (C) 1997-2010 Free Software Foundation, Inc.
6 This file is part of GNU Bash, the Bourne Again SHell.
8 Bash is free software: you can redistribute it and/or modify
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 Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
21 $PRODUCES printf.c
23 $BUILTIN printf
24 $FUNCTION printf_builtin
25 $SHORT_DOC printf [-v var] format [arguments]
26 Formats and prints ARGUMENTS under control of the FORMAT.
28 Options:
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
36 argument.
38 In addition to the standard format specifications described in printf(1)
39 and printf(3), printf interprets:
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 Exit Status:
47 Returns success unless an invalid option is given or a write or assignment
48 error occurs.
49 $END
51 #include <config.h>
53 #include "../bashtypes.h"
55 #include <errno.h>
56 #if defined (HAVE_LIMITS_H)
57 # include <limits.h>
58 #else
59 /* Assume 32-bit ints. */
60 # define INT_MAX 2147483647
61 # define INT_MIN (-2147483647-1)
62 #endif
64 #if defined (PREFER_STDARG)
65 # include <stdarg.h>
66 #else
67 # include <varargs.h>
68 #endif
70 #include <stdio.h>
71 #include <chartypes.h>
73 #ifdef HAVE_INTTYPES_H
74 # include <inttypes.h>
75 #endif
77 #include "posixtime.h"
78 #include "../bashansi.h"
79 #include "../bashintl.h"
81 #define NEED_STRFTIME_DECL
83 #include "../shell.h"
84 #include "shmbutil.h"
85 #include "stdc.h"
86 #include "bashgetopt.h"
87 #include "common.h"
89 #if defined (PRI_MACROS_BROKEN)
90 # undef PRIdMAX
91 #endif
93 #if !defined (PRIdMAX)
94 # if HAVE_LONG_LONG
95 # define PRIdMAX "lld"
96 # else
97 # define PRIdMAX "ld"
98 # endif
99 #endif
101 #if !defined (errno)
102 extern int errno;
103 #endif
105 #define PC(c) \
106 do { \
107 char b[2]; \
108 tw++; \
109 b[0] = c; b[1] = '\0'; \
110 if (vflag) \
111 vbadd (b, 1); \
112 else \
113 putchar (c); \
114 } while (0)
116 #define PF(f, func) \
117 do { \
118 int nw; \
119 clearerr (stdout); \
120 if (have_fieldwidth && have_precision) \
121 nw = vflag ? vbprintf (f, fieldwidth, precision, func) : printf (f, fieldwidth, precision, func); \
122 else if (have_fieldwidth) \
123 nw = vflag ? vbprintf (f, fieldwidth, func) : printf (f, fieldwidth, func); \
124 else if (have_precision) \
125 nw = vflag ? vbprintf (f, precision, func) : printf (f, precision, func); \
126 else \
127 nw = vflag ? vbprintf (f, func) : printf (f, func); \
128 tw += nw; \
129 if (ferror (stdout)) \
131 sh_wrerror (); \
132 clearerr (stdout); \
133 return (EXECUTION_FAILURE); \
135 } while (0)
137 /* We free the buffer used by mklong() if it's `too big'. */
138 #define PRETURN(value) \
139 do \
141 if (vflag) \
143 bind_printf_variable (vname, vbuf, 0); \
144 stupidly_hack_special_variables (vname); \
146 if (conv_bufsize > 4096 ) \
148 free (conv_buf); \
149 conv_bufsize = 0; \
150 conv_buf = 0; \
152 if (vbsize > 4096) \
154 free (vbuf); \
155 vbsize = 0; \
156 vbuf = 0; \
158 else if (vbuf) \
159 vbuf[0] = 0; \
160 terminate_immediately--; \
161 fflush (stdout); \
162 if (ferror (stdout)) \
164 sh_wrerror (); \
165 clearerr (stdout); \
166 return (EXECUTION_FAILURE); \
168 return (value); \
170 while (0)
172 #define SKIP1 "#'-+ 0"
173 #define LENMODS "hjlLtz"
175 extern time_t shell_start_time;
177 #if !HAVE_ASPRINTF
178 extern int asprintf __P((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
179 #endif
181 #if !HAVE_VSNPRINTF
182 extern int vsnprintf __P((char *, size_t, const char *, va_list)) __attribute__((__format__ (printf, 3, 0)));
183 #endif
185 static void printf_erange __P((char *));
186 static int printstr __P((char *, char *, int, int, int));
187 static int tescape __P((char *, char *, int *, int *));
188 static char *bexpand __P((char *, int, int *, int *));
189 static char *vbadd __P((char *, int));
190 static int vbprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
191 static char *mklong __P((char *, char *, size_t));
192 static int getchr __P((void));
193 static char *getstr __P((void));
194 static int getint __P((void));
195 static intmax_t getintmax __P((void));
196 static uintmax_t getuintmax __P((void));
197 static SHELL_VAR *bind_printf_variable __P((char *, char *, int));
199 #if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD && !defined(STRTOLD_BROKEN)
200 typedef long double floatmax_t;
201 # define FLOATMAX_CONV "L"
202 # define strtofltmax strtold
203 #else
204 typedef double floatmax_t;
205 # define FLOATMAX_CONV ""
206 # define strtofltmax strtod
207 #endif
208 static floatmax_t getfloatmax __P((void));
210 static intmax_t asciicode __P((void));
212 static WORD_LIST *garglist;
213 static int retval;
214 static int conversion_error;
216 /* printf -v var support */
217 static int vflag = 0;
218 static char *vbuf, *vname;
219 static size_t vbsize;
220 static int vblen;
222 static intmax_t tw;
224 static char *conv_buf;
225 static size_t conv_bufsize;
228 printf_builtin (list)
229 WORD_LIST *list;
231 int ch, fieldwidth, precision;
232 int have_fieldwidth, have_precision;
233 char convch, thisch, nextch, *format, *modstart, *fmt, *start;
234 #if defined (HANDLE_MULTIBYTE)
235 char mbch[25]; /* 25 > MB_LEN_MAX, plus can handle 4-byte UTF-8 and large Unicode characters*/
236 int mbind, mblen;
237 #endif
239 conversion_error = 0;
240 retval = EXECUTION_SUCCESS;
242 vflag = 0;
244 reset_internal_getopt ();
245 while ((ch = internal_getopt (list, "v:")) != -1)
247 switch (ch)
249 case 'v':
250 vname = list_optarg;
251 #if defined (ARRAY_VARS)
252 if (legal_identifier (vname) || valid_array_reference (vname))
253 #else
254 if (legal_identifier (vname))
255 #endif
257 vflag = 1;
258 vblen = 0;
259 if (vbuf)
260 vbuf[0] = 0;
262 else
264 sh_invalidid (vname);
265 return (EX_USAGE);
267 break;
268 default:
269 builtin_usage ();
270 return (EX_USAGE);
273 list = loptend; /* skip over possible `--' */
275 if (list == 0)
277 builtin_usage ();
278 return (EX_USAGE);
281 if (list->word->word == 0 || list->word->word[0] == '\0')
282 return (EXECUTION_SUCCESS);
284 format = list->word->word;
285 tw = 0;
287 garglist = list->next;
289 /* If the format string is empty after preprocessing, return immediately. */
290 if (format == 0 || *format == 0)
291 return (EXECUTION_SUCCESS);
293 terminate_immediately++;
295 /* Basic algorithm is to scan the format string for conversion
296 specifications -- once one is found, find out if the field
297 width or precision is a '*'; if it is, gather up value. Note,
298 format strings are reused as necessary to use up the provided
299 arguments, arguments of zero/null string are provided to use
300 up the format string. */
303 tw = 0;
304 /* find next format specification */
305 for (fmt = format; *fmt; fmt++)
307 precision = fieldwidth = 0;
308 have_fieldwidth = have_precision = 0;
310 if (*fmt == '\\')
312 fmt++;
313 /* A NULL third argument to tescape means to bypass the
314 special processing for arguments to %b. */
315 #if defined (HANDLE_MULTIBYTE)
316 /* Accommodate possible use of \u or \U, which can result in
317 multibyte characters */
318 memset (mbch, '\0', sizeof (mbch));
319 fmt += tescape (fmt, mbch, &mblen, (int *)NULL);
320 for (mbind = 0; mbind < mblen; mbind++)
321 PC (mbch[mbind]);
322 #else
323 fmt += tescape (fmt, &nextch, (int *)NULL, (int *)NULL);
324 PC (nextch);
325 #endif
326 fmt--; /* for loop will increment it for us again */
327 continue;
330 if (*fmt != '%')
332 PC (*fmt);
333 continue;
336 /* ASSERT(*fmt == '%') */
337 start = fmt++;
339 if (*fmt == '%') /* %% prints a % */
341 PC ('%');
342 continue;
345 /* found format specification, skip to field width */
346 for (; *fmt && strchr(SKIP1, *fmt); ++fmt)
349 /* Skip optional field width. */
350 if (*fmt == '*')
352 fmt++;
353 have_fieldwidth = 1;
354 fieldwidth = getint ();
356 else
357 while (DIGIT (*fmt))
358 fmt++;
360 /* Skip optional '.' and precision */
361 if (*fmt == '.')
363 ++fmt;
364 if (*fmt == '*')
366 fmt++;
367 have_precision = 1;
368 precision = getint ();
370 else
372 /* Negative precisions are allowed but treated as if the
373 precision were missing; I would like to allow a leading
374 `+' in the precision number as an extension, but lots
375 of asprintf/fprintf implementations get this wrong. */
376 #if 0
377 if (*fmt == '-' || *fmt == '+')
378 #else
379 if (*fmt == '-')
380 #endif
381 fmt++;
382 while (DIGIT (*fmt))
383 fmt++;
387 /* skip possible format modifiers */
388 modstart = fmt;
389 while (*fmt && strchr (LENMODS, *fmt))
390 fmt++;
392 if (*fmt == 0)
394 builtin_error (_("`%s': missing format character"), start);
395 PRETURN (EXECUTION_FAILURE);
398 convch = *fmt;
399 thisch = modstart[0];
400 nextch = modstart[1];
401 modstart[0] = convch;
402 modstart[1] = '\0';
404 switch(convch)
406 case 'c':
408 char p;
410 p = getchr ();
411 PF(start, p);
412 break;
415 case 's':
417 char *p;
419 p = getstr ();
420 PF(start, p);
421 break;
424 case '(':
426 char *timefmt, timebuf[128], *t;
427 int n;
428 intmax_t arg;
429 time_t secs;
430 struct tm *tm;
432 modstart[1] = nextch; /* restore char after left paren */
433 timefmt = xmalloc (strlen (fmt) + 3);
434 fmt++; /* skip over left paren */
435 for (t = timefmt, n = 1; *fmt; )
437 if (*fmt == '(')
438 n++;
439 else if (*fmt == ')')
440 n--;
441 if (n == 0)
442 break;
443 *t++ = *fmt++;
445 *t = '\0';
446 if (*++fmt != 'T')
448 builtin_warning (_("`%c': invalid time format specification"), *fmt);
449 fmt = start;
450 free (timefmt);
451 PC (*fmt);
452 continue;
454 if (timefmt[0] == '\0')
456 timefmt[0] = '%';
457 timefmt[1] = 'X'; /* locale-specific current time - should we use `+'? */
458 timefmt[2] = '\0';
460 /* argument is seconds since the epoch with special -1 and -2 */
461 arg = getintmax ();
462 if (arg == -1)
463 secs = NOW; /* roughly date +%s */
464 else if (arg == -2)
465 secs = shell_start_time; /* roughly $SECONDS */
466 else
467 secs = arg;
468 tm = localtime (&secs);
469 n = strftime (timebuf, sizeof (timebuf), timefmt, tm);
470 free (timefmt);
471 if (n == 0)
472 timebuf[0] = '\0';
473 else
474 timebuf[sizeof(timebuf) - 1] = '\0';
475 /* convert to %s format that preserves fieldwidth and precision */
476 modstart[0] = 's';
477 modstart[1] = '\0';
478 n = printstr (start, timebuf, strlen (timebuf), fieldwidth, precision); /* XXX - %s for now */
479 if (n < 0)
481 sh_wrerror ();
482 clearerr (stdout);
483 PRETURN (EXECUTION_FAILURE);
485 break;
488 case 'n':
490 char *var;
492 var = getstr ();
493 if (var && *var)
495 if (legal_identifier (var))
496 bind_var_to_int (var, tw);
497 else
499 sh_invalidid (var);
500 PRETURN (EXECUTION_FAILURE);
503 break;
506 case 'b': /* expand escapes in argument */
508 char *p, *xp;
509 int rlen, r;
511 p = getstr ();
512 ch = rlen = r = 0;
513 xp = bexpand (p, strlen (p), &ch, &rlen);
515 if (xp)
517 /* Have to use printstr because of possible NUL bytes
518 in XP -- printf does not handle that well. */
519 r = printstr (start, xp, rlen, fieldwidth, precision);
520 if (r < 0)
522 sh_wrerror ();
523 clearerr (stdout);
524 retval = EXECUTION_FAILURE;
526 free (xp);
529 if (ch || r < 0)
530 PRETURN (retval);
531 break;
534 case 'q': /* print with shell quoting */
536 char *p, *xp;
537 int r;
539 r = 0;
540 p = getstr ();
541 if (p && *p == 0) /* XXX - getstr never returns null */
542 xp = savestring ("''");
543 else if (ansic_shouldquote (p))
544 xp = ansic_quote (p, 0, (int *)0);
545 else
546 xp = sh_backslash_quote (p);
547 if (xp)
549 /* Use printstr to get fieldwidth and precision right. */
550 r = printstr (start, xp, strlen (xp), fieldwidth, precision);
551 if (r < 0)
553 sh_wrerror ();
554 clearerr (stdout);
556 free (xp);
559 if (r < 0)
560 PRETURN (EXECUTION_FAILURE);
561 break;
564 case 'd':
565 case 'i':
567 char *f;
568 long p;
569 intmax_t pp;
571 p = pp = getintmax ();
572 if (p != pp)
574 f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
575 PF (f, pp);
577 else
579 /* Optimize the common case where the integer fits
580 in "long". This also works around some long
581 long and/or intmax_t library bugs in the common
582 case, e.g. glibc 2.2 x86. */
583 f = mklong (start, "l", 1);
584 PF (f, p);
586 break;
589 case 'o':
590 case 'u':
591 case 'x':
592 case 'X':
594 char *f;
595 unsigned long p;
596 uintmax_t pp;
598 p = pp = getuintmax ();
599 if (p != pp)
601 f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
602 PF (f, pp);
604 else
606 f = mklong (start, "l", 1);
607 PF (f, p);
609 break;
612 case 'e':
613 case 'E':
614 case 'f':
615 case 'F':
616 case 'g':
617 case 'G':
618 #if defined (HAVE_PRINTF_A_FORMAT)
619 case 'a':
620 case 'A':
621 #endif
623 char *f;
624 floatmax_t p;
626 p = getfloatmax ();
627 f = mklong (start, FLOATMAX_CONV, sizeof(FLOATMAX_CONV) - 1);
628 PF (f, p);
629 break;
632 /* We don't output unrecognized format characters; we print an
633 error message and return a failure exit status. */
634 default:
635 builtin_error (_("`%c': invalid format character"), convch);
636 PRETURN (EXECUTION_FAILURE);
639 modstart[0] = thisch;
640 modstart[1] = nextch;
643 if (ferror (stdout))
645 sh_wrerror ();
646 clearerr (stdout);
647 PRETURN (EXECUTION_FAILURE);
650 while (garglist && garglist != list->next);
652 if (conversion_error)
653 retval = EXECUTION_FAILURE;
655 PRETURN (retval);
658 static void
659 printf_erange (s)
660 char *s;
662 builtin_error (_("warning: %s: %s"), s, strerror(ERANGE));
665 /* We duplicate a lot of what printf(3) does here. */
666 static int
667 printstr (fmt, string, len, fieldwidth, precision)
668 char *fmt; /* format */
669 char *string; /* expanded string argument */
670 int len; /* length of expanded string */
671 int fieldwidth; /* argument for width of `*' */
672 int precision; /* argument for precision of `*' */
674 #if 0
675 char *s;
676 #endif
677 int padlen, nc, ljust, i;
678 int fw, pr; /* fieldwidth and precision */
680 #if 0
681 if (string == 0 || *string == '\0')
682 #else
683 if (string == 0 || len == 0)
684 #endif
685 return 0;
687 #if 0
688 s = fmt;
689 #endif
690 if (*fmt == '%')
691 fmt++;
693 ljust = fw = 0;
694 pr = -1;
696 /* skip flags */
697 while (strchr (SKIP1, *fmt))
699 if (*fmt == '-')
700 ljust = 1;
701 fmt++;
704 /* get fieldwidth, if present */
705 if (*fmt == '*')
707 fmt++;
708 fw = fieldwidth;
709 if (fw < 0)
711 fw = -fw;
712 ljust = 1;
715 else if (DIGIT (*fmt))
717 fw = *fmt++ - '0';
718 while (DIGIT (*fmt))
719 fw = (fw * 10) + (*fmt++ - '0');
722 /* get precision, if present */
723 if (*fmt == '.')
725 fmt++;
726 if (*fmt == '*')
728 fmt++;
729 pr = precision;
731 else if (DIGIT (*fmt))
733 pr = *fmt++ - '0';
734 while (DIGIT (*fmt))
735 pr = (pr * 10) + (*fmt++ - '0');
739 #if 0
740 /* If we remove this, get rid of `s'. */
741 if (*fmt != 'b' && *fmt != 'q')
743 internal_error ("format parsing problem: %s", s);
744 fw = pr = 0;
746 #endif
748 /* chars from string to print */
749 nc = (pr >= 0 && pr <= len) ? pr : len;
751 padlen = fw - nc;
752 if (padlen < 0)
753 padlen = 0;
754 if (ljust)
755 padlen = -padlen;
757 /* leading pad characters */
758 for (; padlen > 0; padlen--)
759 PC (' ');
761 /* output NC characters from STRING */
762 for (i = 0; i < nc; i++)
763 PC (string[i]);
765 /* output any necessary trailing padding */
766 for (; padlen < 0; padlen++)
767 PC (' ');
769 return (ferror (stdout) ? -1 : 0);
772 /* Convert STRING by expanding the escape sequences specified by the
773 POSIX standard for printf's `%b' format string. If SAWC is non-null,
774 perform the processing appropriate for %b arguments. In particular,
775 recognize `\c' and use that as a string terminator. If we see \c, set
776 *SAWC to 1 before returning. LEN is the length of STRING. */
778 /* Translate a single backslash-escape sequence starting at ESTART (the
779 character after the backslash) and return the number of characters
780 consumed by the sequence. CP is the place to return the translated
781 value. *SAWC is set to 1 if the escape sequence was \c, since that means
782 to short-circuit the rest of the processing. If SAWC is null, we don't
783 do the \c short-circuiting, and \c is treated as an unrecognized escape
784 sequence; we also bypass the other processing specific to %b arguments. */
785 static int
786 tescape (estart, cp, lenp, sawc)
787 char *estart;
788 char *cp;
789 int *lenp, *sawc;
791 register char *p;
792 int temp, c, evalue;
793 unsigned long uvalue;
795 p = estart;
796 if (lenp)
797 *lenp = 1;
799 switch (c = *p++)
801 #if defined (__STDC__)
802 case 'a': *cp = '\a'; break;
803 #else
804 case 'a': *cp = '\007'; break;
805 #endif
807 case 'b': *cp = '\b'; break;
809 case 'e':
810 case 'E': *cp = '\033'; break; /* ESC -- non-ANSI */
812 case 'f': *cp = '\f'; break;
814 case 'n': *cp = '\n'; break;
816 case 'r': *cp = '\r'; break;
818 case 't': *cp = '\t'; break;
820 case 'v': *cp = '\v'; break;
822 /* The octal escape sequences are `\0' followed by up to three octal
823 digits (if SAWC), or `\' followed by up to three octal digits (if
824 !SAWC). As an extension, we allow the latter form even if SAWC. */
825 case '0': case '1': case '2': case '3':
826 case '4': case '5': case '6': case '7':
827 evalue = OCTVALUE (c);
828 for (temp = 2 + (!evalue && !!sawc); ISOCTAL (*p) && temp--; p++)
829 evalue = (evalue * 8) + OCTVALUE (*p);
830 *cp = evalue & 0xFF;
831 break;
833 /* And, as another extension, we allow \xNN, where each N is a
834 hex digit. */
835 case 'x':
836 for (temp = 2, evalue = 0; ISXDIGIT ((unsigned char)*p) && temp--; p++)
837 evalue = (evalue * 16) + HEXVALUE (*p);
838 if (p == estart + 1)
840 builtin_error (_("missing hex digit for \\x"));
841 *cp = '\\';
842 return 0;
844 *cp = evalue & 0xFF;
845 break;
847 #if defined (HANDLE_MULTIBYTE)
848 case 'u':
849 case 'U':
850 temp = (c == 'u') ? 4 : 8; /* \uNNNN \UNNNNNNNN */
851 for (uvalue = 0; ISXDIGIT ((unsigned char)*p) && temp--; p++)
852 uvalue = (uvalue * 16) + HEXVALUE (*p);
853 if (p == estart + 1)
855 builtin_error (_("missing unicode digit for \\%c"), c);
856 *cp = '\\';
857 return 0;
859 if (uvalue <= UCHAR_MAX)
860 *cp = uvalue;
861 else
863 temp = u32cconv (uvalue, cp);
864 cp[temp] = '\0';
865 if (lenp)
866 *lenp = temp;
868 break;
869 #endif
871 case '\\': /* \\ -> \ */
872 *cp = c;
873 break;
875 /* SAWC == 0 means that \', \", and \? are recognized as escape
876 sequences, though the only processing performed is backslash
877 removal. */
878 case '\'': case '"': case '?':
879 if (!sawc)
880 *cp = c;
881 else
883 *cp = '\\';
884 return 0;
886 break;
888 case 'c':
889 if (sawc)
891 *sawc = 1;
892 break;
894 /* other backslash escapes are passed through unaltered */
895 default:
896 *cp = '\\';
897 return 0;
899 return (p - estart);
902 static char *
903 bexpand (string, len, sawc, lenp)
904 char *string;
905 int len, *sawc, *lenp;
907 int temp;
908 char *ret, *r, *s, c;
909 #if defined (HANDLE_MULTIBYTE)
910 char mbch[25];
911 int mbind, mblen;
912 #endif
914 if (string == 0 || len == 0)
916 if (sawc)
917 *sawc = 0;
918 if (lenp)
919 *lenp = 0;
920 return ((char *)NULL);
923 ret = (char *)xmalloc (len + 1);
924 for (r = ret, s = string; s && *s; )
926 c = *s++;
927 if (c != '\\' || *s == '\0')
929 *r++ = c;
930 continue;
932 temp = 0;
933 #if defined (HANDLE_MULTIBYTE)
934 memset (mbch, '\0', sizeof (mbch));
935 s += tescape (s, mbch, &mblen, &temp);
936 #else
937 s += tescape (s, &c, (int *)NULL, &temp);
938 #endif
939 if (temp)
941 if (sawc)
942 *sawc = 1;
943 break;
946 #if defined (HANDLE_MULTIBYTE)
947 for (mbind = 0; mbind < mblen; mbind++)
948 *r++ = mbch[mbind];
949 #else
950 *r++ = c;
951 #endif
954 *r = '\0';
955 if (lenp)
956 *lenp = r - ret;
957 return ret;
960 static char *
961 vbadd (buf, blen)
962 char *buf;
963 int blen;
965 size_t nlen;
967 nlen = vblen + blen + 1;
968 if (nlen >= vbsize)
970 vbsize = ((nlen + 63) >> 6) << 6;
971 vbuf = (char *)xrealloc (vbuf, vbsize);
974 if (blen == 1)
975 vbuf[vblen++] = buf[0];
976 else if (blen > 1)
978 FASTCOPY (buf, vbuf + vblen, blen);
979 vblen += blen;
981 vbuf[vblen] = '\0';
983 #ifdef DEBUG
984 if (strlen (vbuf) != vblen)
985 internal_error ("printf:vbadd: vblen (%d) != strlen (vbuf) (%d)", vblen, (int)strlen (vbuf));
986 #endif
988 return vbuf;
991 static int
992 #if defined (PREFER_STDARG)
993 vbprintf (const char *format, ...)
994 #else
995 vbprintf (format, va_alist)
996 const char *format;
997 va_dcl
998 #endif
1000 va_list args;
1001 size_t nlen;
1002 int blen;
1004 SH_VA_START (args, format);
1005 blen = vsnprintf (vbuf + vblen, vbsize - vblen, format, args);
1006 va_end (args);
1008 nlen = vblen + blen + 1;
1009 if (nlen >= vbsize)
1011 vbsize = ((nlen + 63) >> 6) << 6;
1012 vbuf = (char *)xrealloc (vbuf, vbsize);
1013 SH_VA_START (args, format);
1014 blen = vsnprintf (vbuf + vblen, vbsize - vblen, format, args);
1015 va_end (args);
1018 vblen += blen;
1019 vbuf[vblen] = '\0';
1021 #ifdef DEBUG
1022 if (strlen (vbuf) != vblen)
1023 internal_error ("printf:vbadd: vblen (%d) != strlen (vbuf) (%d)", vblen, (int)strlen (vbuf));
1024 #endif
1026 return (blen);
1029 static char *
1030 mklong (str, modifiers, mlen)
1031 char *str;
1032 char *modifiers;
1033 size_t mlen;
1035 size_t len, slen;
1037 slen = strlen (str);
1038 len = slen + mlen + 1;
1040 if (len > conv_bufsize)
1042 conv_bufsize = (((len + 1023) >> 10) << 10);
1043 conv_buf = (char *)xrealloc (conv_buf, conv_bufsize);
1046 FASTCOPY (str, conv_buf, slen - 1);
1047 FASTCOPY (modifiers, conv_buf + slen - 1, mlen);
1049 conv_buf[len - 2] = str[slen - 1];
1050 conv_buf[len - 1] = '\0';
1051 return (conv_buf);
1054 static int
1055 getchr ()
1057 int ret;
1059 if (garglist == 0)
1060 return ('\0');
1062 ret = (int)garglist->word->word[0];
1063 garglist = garglist->next;
1064 return ret;
1067 static char *
1068 getstr ()
1070 char *ret;
1072 if (garglist == 0)
1073 return ("");
1075 ret = garglist->word->word;
1076 garglist = garglist->next;
1077 return ret;
1080 static int
1081 getint ()
1083 intmax_t ret;
1085 ret = getintmax ();
1087 if (ret > INT_MAX)
1089 printf_erange (garglist->word->word);
1090 ret = INT_MAX;
1092 else if (ret < INT_MIN)
1094 printf_erange (garglist->word->word);
1095 ret = INT_MIN;
1098 return ((int)ret);
1101 static intmax_t
1102 getintmax ()
1104 intmax_t ret;
1105 char *ep;
1107 if (garglist == 0)
1108 return (0);
1110 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
1111 return asciicode ();
1113 errno = 0;
1114 ret = strtoimax (garglist->word->word, &ep, 0);
1116 if (*ep)
1118 sh_invalidnum (garglist->word->word);
1119 /* POSIX.2 says ``...a diagnostic message shall be written to standard
1120 error, and the utility shall not exit with a zero exit status, but
1121 shall continue processing any remaining operands and shall write the
1122 value accumulated at the time the error was detected to standard
1123 output.'' Yecch. */
1124 #if 0
1125 ret = 0; /* return partially-converted value from strtoimax */
1126 #endif
1127 conversion_error = 1;
1129 else if (errno == ERANGE)
1130 printf_erange (garglist->word->word);
1132 garglist = garglist->next;
1133 return (ret);
1136 static uintmax_t
1137 getuintmax ()
1139 uintmax_t ret;
1140 char *ep;
1142 if (garglist == 0)
1143 return (0);
1145 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
1146 return asciicode ();
1148 errno = 0;
1149 ret = strtoumax (garglist->word->word, &ep, 0);
1151 if (*ep)
1153 sh_invalidnum (garglist->word->word);
1154 /* Same POSIX.2 conversion error requirements as getintmax(). */
1155 ret = 0;
1156 conversion_error = 1;
1158 else if (errno == ERANGE)
1159 printf_erange (garglist->word->word);
1161 garglist = garglist->next;
1162 return (ret);
1165 static floatmax_t
1166 getfloatmax ()
1168 floatmax_t ret;
1169 char *ep;
1171 if (garglist == 0)
1172 return (0);
1174 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
1175 return asciicode ();
1177 errno = 0;
1178 ret = strtofltmax (garglist->word->word, &ep);
1180 if (*ep)
1182 sh_invalidnum (garglist->word->word);
1183 /* Same thing about POSIX.2 conversion error requirements. */
1184 ret = 0;
1185 conversion_error = 1;
1187 else if (errno == ERANGE)
1188 printf_erange (garglist->word->word);
1190 garglist = garglist->next;
1191 return (ret);
1194 /* NO check is needed for garglist here. */
1195 static intmax_t
1196 asciicode ()
1198 register intmax_t ch;
1199 #if defined (HANDLE_MULTIBYTE)
1200 wchar_t wc;
1201 size_t mblength, slen;
1202 #endif
1203 DECLARE_MBSTATE;
1205 #if defined (HANDLE_MULTIBYTE)
1206 slen = strlen (garglist->word->word+1);
1207 mblength = MBLEN (garglist->word->word+1, slen);
1208 if (mblength > 1)
1210 mblength = mbtowc (&wc, garglist->word->word+1, slen);
1211 ch = wc; /* XXX */
1213 else
1214 #endif
1215 ch = (unsigned char)garglist->word->word[1];
1217 garglist = garglist->next;
1218 return (ch);
1221 static SHELL_VAR *
1222 bind_printf_variable (name, value, flags)
1223 char *name;
1224 char *value;
1225 int flags;
1227 #if defined (ARRAY_VARS)
1228 if (valid_array_reference (name) == 0)
1229 return (bind_variable (name, value, flags));
1230 else
1231 return (assign_array_element (name, value, flags));
1232 #else /* !ARRAY_VARS */
1233 return bind_variable (name, value, flags);
1234 #endif /* !ARRAY_VARS */