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