]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/printf.def
Bash-4.1 distribution source
[thirdparty/bash.git] / builtins / printf.def
1 This file is printf.def, from which is created printf.c.
2 It implements the builtin "printf" in Bash.
3
4 Copyright (C) 1997-2009 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
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.
12
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.
17
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/>.
20
21 $PRODUCES printf.c
22
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.
27
28 Options:
29 -v var assign the output to shell variable VAR rather than
30 display it on the standard output
31
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.
37
38 In addition to the standard format specifications described in printf(1)
39 and printf(3), printf interprets:
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
43
44 Exit Status:
45 Returns success unless an invalid option is given or a write or assignment
46 error occurs.
47 $END
48
49 #include <config.h>
50
51 #include "../bashtypes.h"
52
53 #include <errno.h>
54 #if defined (HAVE_LIMITS_H)
55 # include <limits.h>
56 #else
57 /* Assume 32-bit ints. */
58 # define INT_MAX 2147483647
59 # define INT_MIN (-2147483647-1)
60 #endif
61
62 #if defined (PREFER_STDARG)
63 # include <stdarg.h>
64 #else
65 # include <varargs.h>
66 #endif
67
68 #include <stdio.h>
69 #include <chartypes.h>
70
71 #ifdef HAVE_INTTYPES_H
72 # include <inttypes.h>
73 #endif
74
75 #include "../bashansi.h"
76 #include "../bashintl.h"
77
78 #include "../shell.h"
79 #include "shmbutil.h"
80 #include "stdc.h"
81 #include "bashgetopt.h"
82 #include "common.h"
83
84 #if defined (PRI_MACROS_BROKEN)
85 # undef PRIdMAX
86 #endif
87
88 #if !defined (PRIdMAX)
89 # if HAVE_LONG_LONG
90 # define PRIdMAX "lld"
91 # else
92 # define PRIdMAX "ld"
93 # endif
94 #endif
95
96 #if !defined (errno)
97 extern int errno;
98 #endif
99
100 #define PC(c) \
101 do { \
102 char b[2]; \
103 tw++; \
104 b[0] = c; b[1] = '\0'; \
105 if (vflag) \
106 vbadd (b, 1); \
107 else \
108 putchar (c); \
109 } while (0)
110
111 #define PF(f, func) \
112 do { \
113 int nw; \
114 clearerr (stdout); \
115 if (have_fieldwidth && have_precision) \
116 nw = vflag ? vbprintf (f, fieldwidth, precision, func) : printf (f, fieldwidth, precision, func); \
117 else if (have_fieldwidth) \
118 nw = vflag ? vbprintf (f, fieldwidth, func) : printf (f, fieldwidth, func); \
119 else if (have_precision) \
120 nw = vflag ? vbprintf (f, precision, func) : printf (f, fieldwidth, func); \
121 else \
122 nw = vflag ? vbprintf (f, func) : printf (f, func); \
123 tw += nw; \
124 if (ferror (stdout)) \
125 { \
126 sh_wrerror (); \
127 clearerr (stdout); \
128 return (EXECUTION_FAILURE); \
129 } \
130 } while (0)
131
132 /* We free the buffer used by mklong() if it's `too big'. */
133 #define PRETURN(value) \
134 do \
135 { \
136 if (vflag) \
137 { \
138 bind_printf_variable (vname, vbuf, 0); \
139 stupidly_hack_special_variables (vname); \
140 } \
141 if (conv_bufsize > 4096 ) \
142 { \
143 free (conv_buf); \
144 conv_bufsize = 0; \
145 conv_buf = 0; \
146 } \
147 if (vbsize > 4096) \
148 { \
149 free (vbuf); \
150 vbsize = 0; \
151 vbuf = 0; \
152 } \
153 else if (vbuf) \
154 vbuf[0] = 0; \
155 terminate_immediately--; \
156 fflush (stdout); \
157 if (ferror (stdout)) \
158 { \
159 sh_wrerror (); \
160 clearerr (stdout); \
161 return (EXECUTION_FAILURE); \
162 } \
163 return (value); \
164 } \
165 while (0)
166
167 #define SKIP1 "#'-+ 0"
168 #define LENMODS "hjlLtz"
169
170 #if !HAVE_ASPRINTF
171 extern int asprintf __P((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
172 #endif
173
174 #if !HAVE_VSNPRINTF
175 extern int vsnprintf __P((char *, size_t, const char *, ...)) __attribute__((__format__ (printf, 3, 4)));
176 #endif
177
178 static void printf_erange __P((char *));
179 static int printstr __P((char *, char *, int, int, int));
180 static int tescape __P((char *, char *, int *));
181 static char *bexpand __P((char *, int, int *, int *));
182 static char *vbadd __P((char *, int));
183 static int vbprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
184 static char *mklong __P((char *, char *, size_t));
185 static int getchr __P((void));
186 static char *getstr __P((void));
187 static int getint __P((void));
188 static intmax_t getintmax __P((void));
189 static uintmax_t getuintmax __P((void));
190 static SHELL_VAR *bind_printf_variable __P((char *, char *, int));
191
192 #if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD && !defined(STRTOLD_BROKEN)
193 typedef long double floatmax_t;
194 # define FLOATMAX_CONV "L"
195 # define strtofltmax strtold
196 #else
197 typedef double floatmax_t;
198 # define FLOATMAX_CONV ""
199 # define strtofltmax strtod
200 #endif
201 static floatmax_t getfloatmax __P((void));
202
203 static intmax_t asciicode __P((void));
204
205 static WORD_LIST *garglist;
206 static int retval;
207 static int conversion_error;
208
209 /* printf -v var support */
210 static int vflag = 0;
211 static char *vbuf, *vname;
212 static size_t vbsize;
213 static int vblen;
214
215 static intmax_t tw;
216
217 static char *conv_buf;
218 static size_t conv_bufsize;
219
220 int
221 printf_builtin (list)
222 WORD_LIST *list;
223 {
224 int ch, fieldwidth, precision;
225 int have_fieldwidth, have_precision;
226 char convch, thisch, nextch, *format, *modstart, *fmt, *start;
227
228 conversion_error = 0;
229 retval = EXECUTION_SUCCESS;
230
231 vflag = 0;
232
233 reset_internal_getopt ();
234 while ((ch = internal_getopt (list, "v:")) != -1)
235 {
236 switch (ch)
237 {
238 case 'v':
239 vname = list_optarg;
240 #if defined (ARRAY_VARS)
241 if (legal_identifier (vname) || valid_array_reference (vname))
242 #else
243 if (legal_identifier (vname))
244 #endif
245 {
246 vflag = 1;
247 vblen = 0;
248 if (vbuf)
249 vbuf[0] = 0;
250 }
251 else
252 {
253 sh_invalidid (vname);
254 return (EX_USAGE);
255 }
256 break;
257 default:
258 builtin_usage ();
259 return (EX_USAGE);
260 }
261 }
262 list = loptend; /* skip over possible `--' */
263
264 if (list == 0)
265 {
266 builtin_usage ();
267 return (EX_USAGE);
268 }
269
270 if (list->word->word == 0 || list->word->word[0] == '\0')
271 return (EXECUTION_SUCCESS);
272
273 format = list->word->word;
274 tw = 0;
275
276 garglist = list->next;
277
278 /* If the format string is empty after preprocessing, return immediately. */
279 if (format == 0 || *format == 0)
280 return (EXECUTION_SUCCESS);
281
282 terminate_immediately++;
283
284 /* Basic algorithm is to scan the format string for conversion
285 specifications -- once one is found, find out if the field
286 width or precision is a '*'; if it is, gather up value. Note,
287 format strings are reused as necessary to use up the provided
288 arguments, arguments of zero/null string are provided to use
289 up the format string. */
290 do
291 {
292 tw = 0;
293 /* find next format specification */
294 for (fmt = format; *fmt; fmt++)
295 {
296 precision = fieldwidth = 0;
297 have_fieldwidth = have_precision = 0;
298
299 if (*fmt == '\\')
300 {
301 fmt++;
302 /* A NULL third argument to tescape means to bypass the
303 special processing for arguments to %b. */
304 fmt += tescape (fmt, &nextch, (int *)NULL);
305 PC (nextch);
306 fmt--; /* for loop will increment it for us again */
307 continue;
308 }
309
310 if (*fmt != '%')
311 {
312 PC (*fmt);
313 continue;
314 }
315
316 /* ASSERT(*fmt == '%') */
317 start = fmt++;
318
319 if (*fmt == '%') /* %% prints a % */
320 {
321 PC ('%');
322 continue;
323 }
324
325 /* found format specification, skip to field width */
326 for (; *fmt && strchr(SKIP1, *fmt); ++fmt)
327 ;
328
329 /* Skip optional field width. */
330 if (*fmt == '*')
331 {
332 fmt++;
333 have_fieldwidth = 1;
334 fieldwidth = getint ();
335 }
336 else
337 while (DIGIT (*fmt))
338 fmt++;
339
340 /* Skip optional '.' and precision */
341 if (*fmt == '.')
342 {
343 ++fmt;
344 if (*fmt == '*')
345 {
346 fmt++;
347 have_precision = 1;
348 precision = getint ();
349 }
350 else
351 {
352 /* Negative precisions are allowed but treated as if the
353 precision were missing; I would like to allow a leading
354 `+' in the precision number as an extension, but lots
355 of asprintf/fprintf implementations get this wrong. */
356 #if 0
357 if (*fmt == '-' || *fmt == '+')
358 #else
359 if (*fmt == '-')
360 #endif
361 fmt++;
362 while (DIGIT (*fmt))
363 fmt++;
364 }
365 }
366
367 /* skip possible format modifiers */
368 modstart = fmt;
369 while (*fmt && strchr (LENMODS, *fmt))
370 fmt++;
371
372 if (*fmt == 0)
373 {
374 builtin_error (_("`%s': missing format character"), start);
375 PRETURN (EXECUTION_FAILURE);
376 }
377
378 convch = *fmt;
379 thisch = modstart[0];
380 nextch = modstart[1];
381 modstart[0] = convch;
382 modstart[1] = '\0';
383
384 switch(convch)
385 {
386 case 'c':
387 {
388 char p;
389
390 p = getchr ();
391 PF(start, p);
392 break;
393 }
394
395 case 's':
396 {
397 char *p;
398
399 p = getstr ();
400 PF(start, p);
401 break;
402 }
403
404 case 'n':
405 {
406 char *var;
407
408 var = getstr ();
409 if (var && *var)
410 {
411 if (legal_identifier (var))
412 bind_var_to_int (var, tw);
413 else
414 {
415 sh_invalidid (var);
416 PRETURN (EXECUTION_FAILURE);
417 }
418 }
419 break;
420 }
421
422 case 'b': /* expand escapes in argument */
423 {
424 char *p, *xp;
425 int rlen, r;
426
427 p = getstr ();
428 ch = rlen = r = 0;
429 xp = bexpand (p, strlen (p), &ch, &rlen);
430
431 if (xp)
432 {
433 /* Have to use printstr because of possible NUL bytes
434 in XP -- printf does not handle that well. */
435 r = printstr (start, xp, rlen, fieldwidth, precision);
436 if (r < 0)
437 {
438 sh_wrerror ();
439 clearerr (stdout);
440 retval = EXECUTION_FAILURE;
441 }
442 free (xp);
443 }
444
445 if (ch || r < 0)
446 PRETURN (retval);
447 break;
448 }
449
450 case 'q': /* print with shell quoting */
451 {
452 char *p, *xp;
453 int r;
454
455 r = 0;
456 p = getstr ();
457 if (p && *p == 0) /* XXX - getstr never returns null */
458 xp = savestring ("''");
459 else if (ansic_shouldquote (p))
460 xp = ansic_quote (p, 0, (int *)0);
461 else
462 xp = sh_backslash_quote (p);
463 if (xp)
464 {
465 /* Use printstr to get fieldwidth and precision right. */
466 r = printstr (start, xp, strlen (xp), fieldwidth, precision);
467 if (r < 0)
468 {
469 sh_wrerror ();
470 clearerr (stdout);
471 }
472 free (xp);
473 }
474
475 if (r < 0)
476 PRETURN (EXECUTION_FAILURE);
477 break;
478 }
479
480 case 'd':
481 case 'i':
482 {
483 char *f;
484 long p;
485 intmax_t pp;
486
487 p = pp = getintmax ();
488 if (p != pp)
489 {
490 f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
491 PF (f, pp);
492 }
493 else
494 {
495 /* Optimize the common case where the integer fits
496 in "long". This also works around some long
497 long and/or intmax_t library bugs in the common
498 case, e.g. glibc 2.2 x86. */
499 f = mklong (start, "l", 1);
500 PF (f, p);
501 }
502 break;
503 }
504
505 case 'o':
506 case 'u':
507 case 'x':
508 case 'X':
509 {
510 char *f;
511 unsigned long p;
512 uintmax_t pp;
513
514 p = pp = getuintmax ();
515 if (p != pp)
516 {
517 f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
518 PF (f, pp);
519 }
520 else
521 {
522 f = mklong (start, "l", 1);
523 PF (f, p);
524 }
525 break;
526 }
527
528 case 'e':
529 case 'E':
530 case 'f':
531 case 'F':
532 case 'g':
533 case 'G':
534 #if defined (HAVE_PRINTF_A_FORMAT)
535 case 'a':
536 case 'A':
537 #endif
538 {
539 char *f;
540 floatmax_t p;
541
542 p = getfloatmax ();
543 f = mklong (start, FLOATMAX_CONV, sizeof(FLOATMAX_CONV) - 1);
544 PF (f, p);
545 break;
546 }
547
548 /* We don't output unrecognized format characters; we print an
549 error message and return a failure exit status. */
550 default:
551 builtin_error (_("`%c': invalid format character"), convch);
552 PRETURN (EXECUTION_FAILURE);
553 }
554
555 modstart[0] = thisch;
556 modstart[1] = nextch;
557 }
558
559 if (ferror (stdout))
560 {
561 sh_wrerror ();
562 clearerr (stdout);
563 PRETURN (EXECUTION_FAILURE);
564 }
565 }
566 while (garglist && garglist != list->next);
567
568 if (conversion_error)
569 retval = EXECUTION_FAILURE;
570
571 PRETURN (retval);
572 }
573
574 static void
575 printf_erange (s)
576 char *s;
577 {
578 builtin_error (_("warning: %s: %s"), s, strerror(ERANGE));
579 }
580
581 /* We duplicate a lot of what printf(3) does here. */
582 static int
583 printstr (fmt, string, len, fieldwidth, precision)
584 char *fmt; /* format */
585 char *string; /* expanded string argument */
586 int len; /* length of expanded string */
587 int fieldwidth; /* argument for width of `*' */
588 int precision; /* argument for precision of `*' */
589 {
590 #if 0
591 char *s;
592 #endif
593 int padlen, nc, ljust, i;
594 int fw, pr; /* fieldwidth and precision */
595
596 #if 0
597 if (string == 0 || *string == '\0')
598 #else
599 if (string == 0 || len == 0)
600 #endif
601 return 0;
602
603 #if 0
604 s = fmt;
605 #endif
606 if (*fmt == '%')
607 fmt++;
608
609 ljust = fw = 0;
610 pr = -1;
611
612 /* skip flags */
613 while (strchr (SKIP1, *fmt))
614 {
615 if (*fmt == '-')
616 ljust = 1;
617 fmt++;
618 }
619
620 /* get fieldwidth, if present */
621 if (*fmt == '*')
622 {
623 fmt++;
624 fw = fieldwidth;
625 if (fw < 0)
626 {
627 fw = -fw;
628 ljust = 1;
629 }
630 }
631 else if (DIGIT (*fmt))
632 {
633 fw = *fmt++ - '0';
634 while (DIGIT (*fmt))
635 fw = (fw * 10) + (*fmt++ - '0');
636 }
637
638 /* get precision, if present */
639 if (*fmt == '.')
640 {
641 fmt++;
642 if (*fmt == '*')
643 {
644 fmt++;
645 pr = precision;
646 }
647 else if (DIGIT (*fmt))
648 {
649 pr = *fmt++ - '0';
650 while (DIGIT (*fmt))
651 pr = (pr * 10) + (*fmt++ - '0');
652 }
653 }
654
655 #if 0
656 /* If we remove this, get rid of `s'. */
657 if (*fmt != 'b' && *fmt != 'q')
658 {
659 internal_error ("format parsing problem: %s", s);
660 fw = pr = 0;
661 }
662 #endif
663
664 /* chars from string to print */
665 nc = (pr >= 0 && pr <= len) ? pr : len;
666
667 padlen = fw - nc;
668 if (padlen < 0)
669 padlen = 0;
670 if (ljust)
671 padlen = -padlen;
672
673 /* leading pad characters */
674 for (; padlen > 0; padlen--)
675 PC (' ');
676
677 /* output NC characters from STRING */
678 for (i = 0; i < nc; i++)
679 PC (string[i]);
680
681 /* output any necessary trailing padding */
682 for (; padlen < 0; padlen++)
683 PC (' ');
684
685 return (ferror (stdout) ? -1 : 0);
686 }
687
688 /* Convert STRING by expanding the escape sequences specified by the
689 POSIX standard for printf's `%b' format string. If SAWC is non-null,
690 perform the processing appropriate for %b arguments. In particular,
691 recognize `\c' and use that as a string terminator. If we see \c, set
692 *SAWC to 1 before returning. LEN is the length of STRING. */
693
694 /* Translate a single backslash-escape sequence starting at ESTART (the
695 character after the backslash) and return the number of characters
696 consumed by the sequence. CP is the place to return the translated
697 value. *SAWC is set to 1 if the escape sequence was \c, since that means
698 to short-circuit the rest of the processing. If SAWC is null, we don't
699 do the \c short-circuiting, and \c is treated as an unrecognized escape
700 sequence; we also bypass the other processing specific to %b arguments. */
701 static int
702 tescape (estart, cp, sawc)
703 char *estart;
704 char *cp;
705 int *sawc;
706 {
707 register char *p;
708 int temp, c, evalue;
709
710 p = estart;
711
712 switch (c = *p++)
713 {
714 #if defined (__STDC__)
715 case 'a': *cp = '\a'; break;
716 #else
717 case 'a': *cp = '\007'; break;
718 #endif
719
720 case 'b': *cp = '\b'; break;
721
722 case 'e':
723 case 'E': *cp = '\033'; break; /* ESC -- non-ANSI */
724
725 case 'f': *cp = '\f'; break;
726
727 case 'n': *cp = '\n'; break;
728
729 case 'r': *cp = '\r'; break;
730
731 case 't': *cp = '\t'; break;
732
733 case 'v': *cp = '\v'; break;
734
735 /* The octal escape sequences are `\0' followed by up to three octal
736 digits (if SAWC), or `\' followed by up to three octal digits (if
737 !SAWC). As an extension, we allow the latter form even if SAWC. */
738 case '0': case '1': case '2': case '3':
739 case '4': case '5': case '6': case '7':
740 evalue = OCTVALUE (c);
741 for (temp = 2 + (!evalue && !!sawc); ISOCTAL (*p) && temp--; p++)
742 evalue = (evalue * 8) + OCTVALUE (*p);
743 *cp = evalue & 0xFF;
744 break;
745
746 /* And, as another extension, we allow \xNNN, where each N is a
747 hex digit. */
748 case 'x':
749 #if 0
750 for (evalue = 0; ISXDIGIT ((unsigned char)*p); p++)
751 #else
752 for (temp = 2, evalue = 0; ISXDIGIT ((unsigned char)*p) && temp--; p++)
753 #endif
754 evalue = (evalue * 16) + HEXVALUE (*p);
755 if (p == estart + 1)
756 {
757 builtin_error (_("missing hex digit for \\x"));
758 *cp = '\\';
759 return 0;
760 }
761 *cp = evalue & 0xFF;
762 break;
763
764 case '\\': /* \\ -> \ */
765 *cp = c;
766 break;
767
768 /* SAWC == 0 means that \', \", and \? are recognized as escape
769 sequences, though the only processing performed is backslash
770 removal. */
771 case '\'': case '"': case '?':
772 if (!sawc)
773 *cp = c;
774 else
775 {
776 *cp = '\\';
777 return 0;
778 }
779 break;
780
781 case 'c':
782 if (sawc)
783 {
784 *sawc = 1;
785 break;
786 }
787 /* other backslash escapes are passed through unaltered */
788 default:
789 *cp = '\\';
790 return 0;
791 }
792 return (p - estart);
793 }
794
795 static char *
796 bexpand (string, len, sawc, lenp)
797 char *string;
798 int len, *sawc, *lenp;
799 {
800 int temp;
801 char *ret, *r, *s, c;
802
803 #if 0
804 if (string == 0 || *string == '\0')
805 #else
806 if (string == 0 || len == 0)
807 #endif
808 {
809 if (sawc)
810 *sawc = 0;
811 if (lenp)
812 *lenp = 0;
813 return ((char *)NULL);
814 }
815
816 ret = (char *)xmalloc (len + 1);
817 for (r = ret, s = string; s && *s; )
818 {
819 c = *s++;
820 if (c != '\\' || *s == '\0')
821 {
822 *r++ = c;
823 continue;
824 }
825 temp = 0;
826 s += tescape (s, &c, &temp);
827 if (temp)
828 {
829 if (sawc)
830 *sawc = 1;
831 break;
832 }
833
834 *r++ = c;
835 }
836
837 *r = '\0';
838 if (lenp)
839 *lenp = r - ret;
840 return ret;
841 }
842
843 static char *
844 vbadd (buf, blen)
845 char *buf;
846 int blen;
847 {
848 size_t nlen;
849
850 nlen = vblen + blen + 1;
851 if (nlen >= vbsize)
852 {
853 vbsize = ((nlen + 63) >> 6) << 6;
854 vbuf = (char *)xrealloc (vbuf, vbsize);
855 }
856
857 if (blen == 1)
858 vbuf[vblen++] = buf[0];
859 else if (blen > 1)
860 {
861 FASTCOPY (buf, vbuf + vblen, blen);
862 vblen += blen;
863 }
864 vbuf[vblen] = '\0';
865
866 #ifdef DEBUG
867 if (strlen (vbuf) != vblen)
868 internal_error ("printf:vbadd: vblen (%d) != strlen (vbuf) (%d)", vblen, (int)strlen (vbuf));
869 #endif
870
871 return vbuf;
872 }
873
874 static int
875 #if defined (PREFER_STDARG)
876 vbprintf (const char *format, ...)
877 #else
878 vbprintf (format, va_alist)
879 const char *format;
880 va_dcl
881 #endif
882 {
883 va_list args;
884 size_t nlen;
885 int blen;
886
887 SH_VA_START (args, format);
888 blen = vsnprintf (vbuf + vblen, vbsize - vblen, format, args);
889 va_end (args);
890
891 nlen = vblen + blen + 1;
892 if (nlen >= vbsize)
893 {
894 vbsize = ((nlen + 63) >> 6) << 6;
895 vbuf = (char *)xrealloc (vbuf, vbsize);
896 SH_VA_START (args, format);
897 blen = vsnprintf (vbuf + vblen, vbsize - vblen, format, args);
898 va_end (args);
899 }
900
901 vblen += blen;
902 vbuf[vblen] = '\0';
903
904 #ifdef DEBUG
905 if (strlen (vbuf) != vblen)
906 internal_error ("printf:vbadd: vblen (%d) != strlen (vbuf) (%d)", vblen, (int)strlen (vbuf));
907 #endif
908
909 return (blen);
910 }
911
912 static char *
913 mklong (str, modifiers, mlen)
914 char *str;
915 char *modifiers;
916 size_t mlen;
917 {
918 size_t len, slen;
919
920 slen = strlen (str);
921 len = slen + mlen + 1;
922
923 if (len > conv_bufsize)
924 {
925 conv_bufsize = (((len + 1023) >> 10) << 10);
926 conv_buf = (char *)xrealloc (conv_buf, conv_bufsize);
927 }
928
929 FASTCOPY (str, conv_buf, slen - 1);
930 FASTCOPY (modifiers, conv_buf + slen - 1, mlen);
931
932 conv_buf[len - 2] = str[slen - 1];
933 conv_buf[len - 1] = '\0';
934 return (conv_buf);
935 }
936
937 static int
938 getchr ()
939 {
940 int ret;
941
942 if (garglist == 0)
943 return ('\0');
944
945 ret = (int)garglist->word->word[0];
946 garglist = garglist->next;
947 return ret;
948 }
949
950 static char *
951 getstr ()
952 {
953 char *ret;
954
955 if (garglist == 0)
956 return ("");
957
958 ret = garglist->word->word;
959 garglist = garglist->next;
960 return ret;
961 }
962
963 static int
964 getint ()
965 {
966 intmax_t ret;
967
968 ret = getintmax ();
969
970 if (ret > INT_MAX)
971 {
972 printf_erange (garglist->word->word);
973 ret = INT_MAX;
974 }
975 else if (ret < INT_MIN)
976 {
977 printf_erange (garglist->word->word);
978 ret = INT_MIN;
979 }
980
981 return ((int)ret);
982 }
983
984 static intmax_t
985 getintmax ()
986 {
987 intmax_t ret;
988 char *ep;
989
990 if (garglist == 0)
991 return (0);
992
993 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
994 return asciicode ();
995
996 errno = 0;
997 ret = strtoimax (garglist->word->word, &ep, 0);
998
999 if (*ep)
1000 {
1001 sh_invalidnum (garglist->word->word);
1002 /* POSIX.2 says ``...a diagnostic message shall be written to standard
1003 error, and the utility shall not exit with a zero exit status, but
1004 shall continue processing any remaining operands and shall write the
1005 value accumulated at the time the error was detected to standard
1006 output.'' Yecch. */
1007 #if 0
1008 ret = 0; /* return partially-converted value from strtoimax */
1009 #endif
1010 conversion_error = 1;
1011 }
1012 else if (errno == ERANGE)
1013 printf_erange (garglist->word->word);
1014
1015 garglist = garglist->next;
1016 return (ret);
1017 }
1018
1019 static uintmax_t
1020 getuintmax ()
1021 {
1022 uintmax_t ret;
1023 char *ep;
1024
1025 if (garglist == 0)
1026 return (0);
1027
1028 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
1029 return asciicode ();
1030
1031 errno = 0;
1032 ret = strtoumax (garglist->word->word, &ep, 0);
1033
1034 if (*ep)
1035 {
1036 sh_invalidnum (garglist->word->word);
1037 /* Same POSIX.2 conversion error requirements as getintmax(). */
1038 ret = 0;
1039 conversion_error = 1;
1040 }
1041 else if (errno == ERANGE)
1042 printf_erange (garglist->word->word);
1043
1044 garglist = garglist->next;
1045 return (ret);
1046 }
1047
1048 static floatmax_t
1049 getfloatmax ()
1050 {
1051 floatmax_t ret;
1052 char *ep;
1053
1054 if (garglist == 0)
1055 return (0);
1056
1057 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
1058 return asciicode ();
1059
1060 errno = 0;
1061 ret = strtofltmax (garglist->word->word, &ep);
1062
1063 if (*ep)
1064 {
1065 sh_invalidnum (garglist->word->word);
1066 /* Same thing about POSIX.2 conversion error requirements. */
1067 ret = 0;
1068 conversion_error = 1;
1069 }
1070 else if (errno == ERANGE)
1071 printf_erange (garglist->word->word);
1072
1073 garglist = garglist->next;
1074 return (ret);
1075 }
1076
1077 /* NO check is needed for garglist here. */
1078 static intmax_t
1079 asciicode ()
1080 {
1081 register intmax_t ch;
1082 #if defined (HANDLE_MULTIBYTE)
1083 wchar_t wc;
1084 size_t mblength, slen;
1085 #endif
1086 DECLARE_MBSTATE;
1087
1088 #if defined (HANDLE_MULTIBYTE)
1089 slen = strlen (garglist->word->word+1);
1090 mblength = MBLEN (garglist->word->word+1, slen);
1091 if (mblength > 1)
1092 {
1093 mblength = mbtowc (&wc, garglist->word->word+1, slen);
1094 ch = wc; /* XXX */
1095 }
1096 else
1097 #endif
1098 ch = (unsigned char)garglist->word->word[1];
1099
1100 garglist = garglist->next;
1101 return (ch);
1102 }
1103
1104 static SHELL_VAR *
1105 bind_printf_variable (name, value, flags)
1106 char *name;
1107 char *value;
1108 int flags;
1109 {
1110 #if defined (ARRAY_VARS)
1111 if (valid_array_reference (name) == 0)
1112 return (bind_variable (name, value, flags));
1113 else
1114 return (assign_array_element (name, value, flags));
1115 #else /* !ARRAY_VARS */
1116 return bind_variable (name, value, flags);
1117 #endif /* !ARRAY_VARS */
1118 }