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