init version.
[bush.git] / builtins / printf.def
blob6719eec074de57bbf3522b60a7d2ba702e5e45e8
1 This file is printf.def, from which is created printf.c.
2 It implements the builtin "printf" in Bush.
4 Copyright (C) 1997-2020 Free Software Foundation, Inc.
6 This file is part of GNU Bush, the Bourne Again SHell.
8 Bush 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 Bush 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 Bush. 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 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 The format is re-used as necessary to consume all of the arguments. If
47 there are fewer arguments than the format requires, extra format
48 specifications behave as if a zero value or null string, as appropriate,
49 had been supplied.
51 Exit Status:
52 Returns success unless an invalid option is given or a write or assignment
53 error occurs.
54 $END
56 #include <config.h>
58 #include "../src/bushtypes.h"
60 #include <errno.h>
61 #if defined (HAVE_LIMITS_H)
62 # include <limits.h>
63 #else
64 /* Assume 32-bit ints. */
65 # define INT_MAX 2147483647
66 # define INT_MIN (-2147483647-1)
67 #endif
69 #if defined (PREFER_STDARG)
70 # include <stdarg.h>
71 #else
72 # include <varargs.h>
73 #endif
75 #include <stdio.h>
76 #include <chartypes.h>
78 #ifdef HAVE_INTTYPES_H
79 # include <inttypes.h>
80 #endif
82 #include "posixtime.h"
83 #include "../src/bushansi.h"
84 #include "../src/bushintl.h"
86 #define NEED_STRFTIME_DECL
88 #include "../src/shell.h"
89 #include "shmbutil.h"
90 #include "stdc.h"
91 #include "bushgetopt.h"
92 #include "common.h"
94 #if defined (PRI_MACROS_BROKEN)
95 # undef PRIdMAX
96 #endif
98 #if !defined (PRIdMAX)
99 # if HAVE_LONG_LONG
100 # define PRIdMAX "lld"
101 # else
102 # define PRIdMAX "ld"
103 # endif
104 #endif
106 #if !defined (errno)
107 extern int errno;
108 #endif
110 #define PC(c) \
111 do { \
112 char b[2]; \
113 tw++; \
114 b[0] = c; b[1] = '\0'; \
115 if (vflag) \
116 vbadd (b, 1); \
117 else \
118 putchar (c); \
119 QUIT; \
120 } while (0)
122 #define PF(f, func) \
123 do { \
124 int nw; \
125 clearerr (stdout); \
126 if (have_fieldwidth && have_precision) \
127 nw = vflag ? vbprintf (f, fieldwidth, precision, func) : printf (f, fieldwidth, precision, func); \
128 else if (have_fieldwidth) \
129 nw = vflag ? vbprintf (f, fieldwidth, func) : printf (f, fieldwidth, func); \
130 else if (have_precision) \
131 nw = vflag ? vbprintf (f, precision, func) : printf (f, precision, func); \
132 else \
133 nw = vflag ? vbprintf (f, func) : printf (f, func); \
134 tw += nw; \
135 QUIT; \
136 if (ferror (stdout)) \
138 sh_wrerror (); \
139 clearerr (stdout); \
140 return (EXECUTION_FAILURE); \
142 } while (0)
144 /* We free the buffer used by mklong() if it's `too big'. */
145 #define PRETURN(value) \
146 do \
148 QUIT; \
149 if (vflag) \
151 SHELL_VAR *v; \
152 v = builtin_bind_variable (vname, vbuf, 0); \
153 stupidly_hack_special_variables (vname); \
154 if (v == 0 || readonly_p (v) || noassign_p (v)) \
155 return (EXECUTION_FAILURE); \
157 if (conv_bufsize > 4096 ) \
159 free (conv_buf); \
160 conv_bufsize = 0; \
161 conv_buf = 0; \
163 if (vbsize > 4096) \
165 free (vbuf); \
166 vbsize = 0; \
167 vbuf = 0; \
169 else if (vbuf) \
170 vbuf[0] = 0; \
171 if (ferror (stdout) == 0) \
172 fflush (stdout); \
173 QUIT; \
174 if (ferror (stdout)) \
176 sh_wrerror (); \
177 clearerr (stdout); \
178 return (EXECUTION_FAILURE); \
180 return (value); \
182 while (0)
184 #define SKIP1 "#'-+ 0"
185 #define LENMODS "hjlLtz"
187 extern time_t shell_start_time;
189 #if !HAVE_ASPRINTF
190 extern int asprintf PARAMS((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
191 #endif
193 #if !HAVE_VSNPRINTF
194 extern int vsnprintf PARAMS((char *, size_t, const char *, va_list)) __attribute__((__format__ (printf, 3, 0)));
195 #endif
197 static void printf_erange PARAMS((char *));
198 static int printstr PARAMS((char *, char *, int, int, int));
199 static int tescape PARAMS((char *, char *, int *, int *));
200 static char *bexpand PARAMS((char *, int, int *, int *));
201 static char *vbadd PARAMS((char *, int));
202 static int vbprintf PARAMS((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
203 static char *mklong PARAMS((char *, char *, size_t));
204 static int getchr PARAMS((void));
205 static char *getstr PARAMS((void));
206 static int getint PARAMS((void));
207 static intmax_t getintmax PARAMS((void));
208 static uintmax_t getuintmax PARAMS((void));
210 #if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD && !defined(STRTOLD_BROKEN)
211 typedef long double floatmax_t;
212 # define FLOATMAX_CONV "L"
213 # define strtofltmax strtold
214 #else
215 typedef double floatmax_t;
216 # define FLOATMAX_CONV ""
217 # define strtofltmax strtod
218 #endif
219 static floatmax_t getfloatmax PARAMS((void));
221 static intmax_t asciicode PARAMS((void));
223 static WORD_LIST *garglist, *orig_arglist;
224 static int retval;
225 static int conversion_error;
227 /* printf -v var support */
228 static int vflag = 0;
229 static char *vbuf, *vname;
230 static size_t vbsize;
231 static int vblen;
233 static intmax_t tw;
235 static char *conv_buf;
236 static size_t conv_bufsize;
239 printf_builtin (list)
240 WORD_LIST *list;
242 int ch, fieldwidth, precision;
243 int have_fieldwidth, have_precision;
244 char convch, thisch, nextch, *format, *modstart, *fmt, *start;
245 #if defined (HANDLE_MULTIBYTE)
246 char mbch[25]; /* 25 > MB_LEN_MAX, plus can handle 4-byte UTF-8 and large Unicode characters*/
247 int mbind, mblen;
248 #endif
249 #if defined (ARRAY_VARS)
250 int arrayflags;
251 #endif
253 conversion_error = 0;
254 retval = EXECUTION_SUCCESS;
256 vflag = 0;
258 reset_internal_getopt ();
259 while ((ch = internal_getopt (list, "v:")) != -1)
261 switch (ch)
263 case 'v':
264 vname = list_optarg;
265 #if defined (ARRAY_VARS)
266 arrayflags = assoc_expand_once ? (VA_NOEXPAND|VA_ONEWORD) : 0;
267 if (legal_identifier (vname) || valid_array_reference (vname, arrayflags))
268 #else
269 if (legal_identifier (vname))
270 #endif
272 vflag = 1;
273 if (vbsize == 0)
274 vbuf = xmalloc (vbsize = 16);
275 vblen = 0;
276 if (vbuf)
277 vbuf[0] = 0;
279 else
281 sh_invalidid (vname);
282 return (EX_USAGE);
284 break;
285 CASE_HELPOPT;
286 default:
287 builtin_usage ();
288 return (EX_USAGE);
291 list = loptend; /* skip over possible `--' */
293 if (list == 0)
295 builtin_usage ();
296 return (EX_USAGE);
299 /* Allow printf -v var "" to act like var="" */
300 if (vflag && list->word->word && list->word->word[0] == '\0')
302 SHELL_VAR *v;
303 v = builtin_bind_variable (vname, "", 0);
304 stupidly_hack_special_variables (vname);
305 return ((v == 0 || readonly_p (v) || noassign_p (v)) ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
308 if (list->word->word == 0 || list->word->word[0] == '\0')
309 return (EXECUTION_SUCCESS);
311 format = list->word->word;
312 tw = 0;
314 garglist = orig_arglist = list->next;
316 /* If the format string is empty after preprocessing, return immediately. */
317 if (format == 0 || *format == 0)
318 return (EXECUTION_SUCCESS);
320 /* Basic algorithm is to scan the format string for conversion
321 specifications -- once one is found, find out if the field
322 width or precision is a '*'; if it is, gather up value. Note,
323 format strings are reused as necessary to use up the provided
324 arguments, arguments of zero/null string are provided to use
325 up the format string. */
328 tw = 0;
329 /* find next format specification */
330 for (fmt = format; *fmt; fmt++)
332 precision = fieldwidth = 0;
333 have_fieldwidth = have_precision = 0;
335 if (*fmt == '\\')
337 fmt++;
338 /* A NULL third argument to tescape means to bypass the
339 special processing for arguments to %b. */
340 #if defined (HANDLE_MULTIBYTE)
341 /* Accommodate possible use of \u or \U, which can result in
342 multibyte characters */
343 memset (mbch, '\0', sizeof (mbch));
344 fmt += tescape (fmt, mbch, &mblen, (int *)NULL);
345 for (mbind = 0; mbind < mblen; mbind++)
346 PC (mbch[mbind]);
347 #else
348 fmt += tescape (fmt, &nextch, (int *)NULL, (int *)NULL);
349 PC (nextch);
350 #endif
351 fmt--; /* for loop will increment it for us again */
352 continue;
355 if (*fmt != '%')
357 PC (*fmt);
358 continue;
361 /* ASSERT(*fmt == '%') */
362 start = fmt++;
364 if (*fmt == '%') /* %% prints a % */
366 PC ('%');
367 continue;
370 /* found format specification, skip to field width */
371 for (; *fmt && strchr(SKIP1, *fmt); ++fmt)
374 /* Skip optional field width. */
375 if (*fmt == '*')
377 fmt++;
378 have_fieldwidth = 1;
379 fieldwidth = getint ();
381 else
382 while (DIGIT (*fmt))
383 fmt++;
385 /* Skip optional '.' and precision */
386 if (*fmt == '.')
388 ++fmt;
389 if (*fmt == '*')
391 fmt++;
392 have_precision = 1;
393 precision = getint ();
395 else
397 /* Negative precisions are allowed but treated as if the
398 precision were missing; I would like to allow a leading
399 `+' in the precision number as an extension, but lots
400 of asprintf/fprintf implementations get this wrong. */
401 #if 0
402 if (*fmt == '-' || *fmt == '+')
403 #else
404 if (*fmt == '-')
405 #endif
406 fmt++;
407 while (DIGIT (*fmt))
408 fmt++;
412 /* skip possible format modifiers */
413 modstart = fmt;
414 while (*fmt && strchr (LENMODS, *fmt))
415 fmt++;
417 if (*fmt == 0)
419 builtin_error (_("`%s': missing format character"), start);
420 PRETURN (EXECUTION_FAILURE);
423 convch = *fmt;
424 thisch = modstart[0];
425 nextch = modstart[1];
426 modstart[0] = convch;
427 modstart[1] = '\0';
429 QUIT;
430 switch(convch)
432 case 'c':
434 char p;
436 p = getchr ();
437 PF(start, p);
438 break;
441 case 's':
443 char *p;
445 p = getstr ();
446 PF(start, p);
447 break;
450 case '(':
452 char *timefmt, timebuf[128], *t;
453 int n;
454 intmax_t arg;
455 time_t secs;
456 struct tm *tm;
458 modstart[1] = nextch; /* restore char after left paren */
459 timefmt = xmalloc (strlen (fmt) + 3);
460 fmt++; /* skip over left paren */
461 for (t = timefmt, n = 1; *fmt; )
463 if (*fmt == '(')
464 n++;
465 else if (*fmt == ')')
466 n--;
467 if (n == 0)
468 break;
469 *t++ = *fmt++;
471 *t = '\0';
472 if (*++fmt != 'T')
474 builtin_warning (_("`%c': invalid time format specification"), *fmt);
475 fmt = start;
476 free (timefmt);
477 PC (*fmt);
478 continue;
480 if (timefmt[0] == '\0')
482 timefmt[0] = '%';
483 timefmt[1] = 'X'; /* locale-specific current time - should we use `+'? */
484 timefmt[2] = '\0';
486 /* argument is seconds since the epoch with special -1 and -2 */
487 /* default argument is equivalent to -1; special case */
488 arg = garglist ? getintmax () : -1;
489 if (arg == -1)
490 secs = NOW; /* roughly date +%s */
491 else if (arg == -2)
492 secs = shell_start_time; /* roughly $SECONDS */
493 else
494 secs = arg;
495 #if defined (HAVE_TZSET)
496 sv_tz ("TZ"); /* XXX -- just make sure */
497 #endif
498 tm = localtime (&secs);
499 if (tm == 0)
501 secs = 0;
502 tm = localtime (&secs);
504 n = tm ? strftime (timebuf, sizeof (timebuf), timefmt, tm) : 0;
505 free (timefmt);
506 if (n == 0)
507 timebuf[0] = '\0';
508 else
509 timebuf[sizeof(timebuf) - 1] = '\0';
510 /* convert to %s format that preserves fieldwidth and precision */
511 modstart[0] = 's';
512 modstart[1] = '\0';
513 n = printstr (start, timebuf, strlen (timebuf), fieldwidth, precision); /* XXX - %s for now */
514 if (n < 0)
516 if (ferror (stdout) == 0)
518 sh_wrerror ();
519 clearerr (stdout);
521 PRETURN (EXECUTION_FAILURE);
523 break;
526 case 'n':
528 char *var;
530 var = getstr ();
531 if (var && *var)
533 if (legal_identifier (var))
534 bind_var_to_int (var, tw);
535 else
537 sh_invalidid (var);
538 PRETURN (EXECUTION_FAILURE);
541 break;
544 case 'b': /* expand escapes in argument */
546 char *p, *xp;
547 int rlen, r;
549 p = getstr ();
550 ch = rlen = r = 0;
551 xp = bexpand (p, strlen (p), &ch, &rlen);
553 if (xp)
555 /* Have to use printstr because of possible NUL bytes
556 in XP -- printf does not handle that well. */
557 r = printstr (start, xp, rlen, fieldwidth, precision);
558 if (r < 0)
560 if (ferror (stdout) == 0)
562 sh_wrerror ();
563 clearerr (stdout);
565 retval = EXECUTION_FAILURE;
567 free (xp);
570 if (ch || r < 0)
571 PRETURN (retval);
572 break;
575 case 'q': /* print with shell quoting */
577 char *p, *xp;
578 int r;
580 r = 0;
581 p = getstr ();
582 if (p && *p == 0) /* XXX - getstr never returns null */
583 xp = savestring ("''");
584 else if (ansic_shouldquote (p))
585 xp = ansic_quote (p, 0, (int *)0);
586 else
587 xp = sh_backslash_quote (p, 0, 3);
588 if (xp)
590 /* Use printstr to get fieldwidth and precision right. */
591 r = printstr (start, xp, strlen (xp), fieldwidth, precision);
592 if (r < 0)
594 sh_wrerror ();
595 clearerr (stdout);
597 free (xp);
600 if (r < 0)
601 PRETURN (EXECUTION_FAILURE);
602 break;
605 case 'd':
606 case 'i':
608 char *f;
609 long p;
610 intmax_t pp;
612 p = pp = getintmax ();
613 if (p != pp)
615 f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
616 PF (f, pp);
618 else
620 /* Optimize the common case where the integer fits
621 in "long". This also works around some long
622 long and/or intmax_t library bugs in the common
623 case, e.g. glibc 2.2 x86. */
624 f = mklong (start, "l", 1);
625 PF (f, p);
627 break;
630 case 'o':
631 case 'u':
632 case 'x':
633 case 'X':
635 char *f;
636 unsigned long p;
637 uintmax_t pp;
639 p = pp = getuintmax ();
640 if (p != pp)
642 f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
643 PF (f, pp);
645 else
647 f = mklong (start, "l", 1);
648 PF (f, p);
650 break;
653 case 'e':
654 case 'E':
655 case 'f':
656 case 'F':
657 case 'g':
658 case 'G':
659 #if defined (HAVE_PRINTF_A_FORMAT)
660 case 'a':
661 case 'A':
662 #endif
664 char *f;
665 floatmax_t p;
667 p = getfloatmax ();
668 f = mklong (start, FLOATMAX_CONV, sizeof(FLOATMAX_CONV) - 1);
669 PF (f, p);
670 break;
673 /* We don't output unrecognized format characters; we print an
674 error message and return a failure exit status. */
675 default:
676 builtin_error (_("`%c': invalid format character"), convch);
677 PRETURN (EXECUTION_FAILURE);
680 modstart[0] = thisch;
681 modstart[1] = nextch;
684 if (ferror (stdout))
686 /* PRETURN will print error message. */
687 PRETURN (EXECUTION_FAILURE);
690 while (garglist && garglist != list->next);
692 if (conversion_error)
693 retval = EXECUTION_FAILURE;
695 PRETURN (retval);
698 static void
699 printf_erange (s)
700 char *s;
702 builtin_error (_("warning: %s: %s"), s, strerror(ERANGE));
705 /* We duplicate a lot of what printf(3) does here. */
706 static int
707 printstr (fmt, string, len, fieldwidth, precision)
708 char *fmt; /* format */
709 char *string; /* expanded string argument */
710 int len; /* length of expanded string */
711 int fieldwidth; /* argument for width of `*' */
712 int precision; /* argument for precision of `*' */
714 #if 0
715 char *s;
716 #endif
717 int padlen, nc, ljust, i;
718 int fw, pr; /* fieldwidth and precision */
719 intmax_t mfw, mpr;
721 if (string == 0)
722 string = "";
724 #if 0
725 s = fmt;
726 #endif
727 if (*fmt == '%')
728 fmt++;
730 ljust = fw = 0;
731 pr = -1;
732 mfw = 0;
733 mpr = -1;
735 /* skip flags */
736 while (strchr (SKIP1, *fmt))
738 if (*fmt == '-')
739 ljust = 1;
740 fmt++;
743 /* get fieldwidth, if present. rely on caller to clamp fieldwidth at INT_MAX */
744 if (*fmt == '*')
746 fmt++;
747 fw = fieldwidth;
748 if (fw < 0)
750 fw = -fw;
751 ljust = 1;
754 else if (DIGIT (*fmt))
756 mfw = *fmt++ - '0';
757 while (DIGIT (*fmt))
758 mfw = (mfw * 10) + (*fmt++ - '0');
759 /* Error if fieldwidth > INT_MAX here? */
760 fw = (mfw < 0 || mfw > INT_MAX) ? INT_MAX : mfw;
763 /* get precision, if present */
764 if (*fmt == '.')
766 fmt++;
767 if (*fmt == '*')
769 fmt++;
770 pr = precision;
772 else if (DIGIT (*fmt))
774 mpr = *fmt++ - '0';
775 while (DIGIT (*fmt))
776 mpr = (mpr * 10) + (*fmt++ - '0');
777 /* Error if precision > INT_MAX here? */
778 pr = (mpr < 0 || mpr > INT_MAX) ? INT_MAX : mpr;
780 else
781 pr = 0; /* "a null digit string is treated as zero" */
784 #if 0
785 /* If we remove this, get rid of `s'. */
786 if (*fmt != 'b' && *fmt != 'q')
788 internal_error (_("format parsing problem: %s"), s);
789 fw = pr = 0;
791 #endif
793 /* chars from string to print */
794 nc = (pr >= 0 && pr <= len) ? pr : len;
796 padlen = fw - nc;
797 if (padlen < 0)
798 padlen = 0;
799 if (ljust)
800 padlen = -padlen;
802 /* leading pad characters */
803 for (; padlen > 0; padlen--)
804 PC (' ');
806 /* output NC characters from STRING */
807 for (i = 0; i < nc; i++)
808 PC (string[i]);
810 /* output any necessary trailing padding */
811 for (; padlen < 0; padlen++)
812 PC (' ');
814 return (ferror (stdout) ? -1 : 0);
817 /* Convert STRING by expanding the escape sequences specified by the
818 POSIX standard for printf's `%b' format string. If SAWC is non-null,
819 perform the processing appropriate for %b arguments. In particular,
820 recognize `\c' and use that as a string terminator. If we see \c, set
821 *SAWC to 1 before returning. LEN is the length of STRING. */
823 /* Translate a single backslash-escape sequence starting at ESTART (the
824 character after the backslash) and return the number of characters
825 consumed by the sequence. CP is the place to return the translated
826 value. *SAWC is set to 1 if the escape sequence was \c, since that means
827 to short-circuit the rest of the processing. If SAWC is null, we don't
828 do the \c short-circuiting, and \c is treated as an unrecognized escape
829 sequence; we also bypass the other processing specific to %b arguments. */
830 static int
831 tescape (estart, cp, lenp, sawc)
832 char *estart;
833 char *cp;
834 int *lenp, *sawc;
836 register char *p;
837 int temp, c, evalue;
838 unsigned long uvalue;
840 p = estart;
841 if (lenp)
842 *lenp = 1;
844 switch (c = *p++)
846 #if defined (__STDC__)
847 case 'a': *cp = '\a'; break;
848 #else
849 case 'a': *cp = '\007'; break;
850 #endif
852 case 'b': *cp = '\b'; break;
854 case 'e':
855 case 'E': *cp = '\033'; break; /* ESC -- non-ANSI */
857 case 'f': *cp = '\f'; break;
859 case 'n': *cp = '\n'; break;
861 case 'r': *cp = '\r'; break;
863 case 't': *cp = '\t'; break;
865 case 'v': *cp = '\v'; break;
867 /* The octal escape sequences are `\0' followed by up to three octal
868 digits (if SAWC), or `\' followed by up to three octal digits (if
869 !SAWC). As an extension, we allow the latter form even if SAWC. */
870 case '0': case '1': case '2': case '3':
871 case '4': case '5': case '6': case '7':
872 evalue = OCTVALUE (c);
873 for (temp = 2 + (!evalue && !!sawc); ISOCTAL (*p) && temp--; p++)
874 evalue = (evalue * 8) + OCTVALUE (*p);
875 *cp = evalue & 0xFF;
876 break;
878 /* And, as another extension, we allow \xNN, where each N is a
879 hex digit. */
880 case 'x':
881 for (temp = 2, evalue = 0; ISXDIGIT ((unsigned char)*p) && temp--; p++)
882 evalue = (evalue * 16) + HEXVALUE (*p);
883 if (p == estart + 1)
885 builtin_error (_("missing hex digit for \\x"));
886 *cp = '\\';
887 return 0;
889 *cp = evalue & 0xFF;
890 break;
892 #if defined (HANDLE_MULTIBYTE)
893 case 'u':
894 case 'U':
895 temp = (c == 'u') ? 4 : 8; /* \uNNNN \UNNNNNNNN */
896 for (uvalue = 0; ISXDIGIT ((unsigned char)*p) && temp--; p++)
897 uvalue = (uvalue * 16) + HEXVALUE (*p);
898 if (p == estart + 1)
900 builtin_error (_("missing unicode digit for \\%c"), c);
901 *cp = '\\';
902 return 0;
904 if (uvalue <= 0x7f) /* <= 0x7f translates directly */
905 *cp = uvalue;
906 else
908 temp = u32cconv (uvalue, cp);
909 cp[temp] = '\0';
910 if (lenp)
911 *lenp = temp;
913 break;
914 #endif
916 case '\\': /* \\ -> \ */
917 *cp = c;
918 break;
920 /* SAWC == 0 means that \', \", and \? are recognized as escape
921 sequences, though the only processing performed is backslash
922 removal. */
923 case '\'': case '"': case '?':
924 if (!sawc)
925 *cp = c;
926 else
928 *cp = '\\';
929 return 0;
931 break;
933 case 'c':
934 if (sawc)
936 *sawc = 1;
937 break;
939 /* other backslash escapes are passed through unaltered */
940 default:
941 *cp = '\\';
942 return 0;
944 return (p - estart);
947 static char *
948 bexpand (string, len, sawc, lenp)
949 char *string;
950 int len, *sawc, *lenp;
952 int temp;
953 char *ret, *r, *s, c;
954 #if defined (HANDLE_MULTIBYTE)
955 char mbch[25];
956 int mbind, mblen;
957 #endif
959 if (string == 0 || len == 0)
961 if (sawc)
962 *sawc = 0;
963 if (lenp)
964 *lenp = 0;
965 ret = (char *)xmalloc (1);
966 ret[0] = '\0';
967 return (ret);
970 ret = (char *)xmalloc (len + 1);
971 for (r = ret, s = string; s && *s; )
973 c = *s++;
974 if (c != '\\' || *s == '\0')
976 *r++ = c;
977 continue;
979 temp = 0;
980 #if defined (HANDLE_MULTIBYTE)
981 memset (mbch, '\0', sizeof (mbch));
982 s += tescape (s, mbch, &mblen, &temp);
983 #else
984 s += tescape (s, &c, (int *)NULL, &temp);
985 #endif
986 if (temp)
988 if (sawc)
989 *sawc = 1;
990 break;
993 #if defined (HANDLE_MULTIBYTE)
994 for (mbind = 0; mbind < mblen; mbind++)
995 *r++ = mbch[mbind];
996 #else
997 *r++ = c;
998 #endif
1001 *r = '\0';
1002 if (lenp)
1003 *lenp = r - ret;
1004 return ret;
1007 static char *
1008 vbadd (buf, blen)
1009 char *buf;
1010 int blen;
1012 size_t nlen;
1014 nlen = vblen + blen + 1;
1015 if (nlen >= vbsize)
1017 vbsize = ((nlen + 63) >> 6) << 6;
1018 vbuf = (char *)xrealloc (vbuf, vbsize);
1021 if (blen == 1)
1022 vbuf[vblen++] = buf[0];
1023 else if (blen > 1)
1025 FASTCOPY (buf, vbuf + vblen, blen);
1026 vblen += blen;
1028 vbuf[vblen] = '\0';
1030 #ifdef DEBUG
1031 if (strlen (vbuf) != vblen)
1032 internal_error ("printf:vbadd: vblen (%d) != strlen (vbuf) (%d)", vblen, (int)strlen (vbuf));
1033 #endif
1035 return vbuf;
1038 static int
1039 #if defined (PREFER_STDARG)
1040 vbprintf (const char *format, ...)
1041 #else
1042 vbprintf (format, va_alist)
1043 const char *format;
1044 va_dcl
1045 #endif
1047 va_list args;
1048 size_t nlen;
1049 int blen;
1051 SH_VA_START (args, format);
1052 blen = vsnprintf (vbuf + vblen, vbsize - vblen, format, args);
1053 va_end (args);
1055 nlen = vblen + blen + 1;
1056 if (nlen >= vbsize)
1058 vbsize = ((nlen + 63) >> 6) << 6;
1059 vbuf = (char *)xrealloc (vbuf, vbsize);
1060 SH_VA_START (args, format);
1061 blen = vsnprintf (vbuf + vblen, vbsize - vblen, format, args);
1062 va_end (args);
1065 vblen += blen;
1066 vbuf[vblen] = '\0';
1068 #ifdef DEBUG
1069 if (strlen (vbuf) != vblen)
1070 internal_error ("printf:vbprintf: vblen (%d) != strlen (vbuf) (%d)", vblen, (int)strlen (vbuf));
1071 #endif
1073 return (blen);
1076 static char *
1077 mklong (str, modifiers, mlen)
1078 char *str;
1079 char *modifiers;
1080 size_t mlen;
1082 size_t len, slen;
1084 slen = strlen (str);
1085 len = slen + mlen + 1;
1087 if (len > conv_bufsize)
1089 conv_bufsize = (((len + 1023) >> 10) << 10);
1090 conv_buf = (char *)xrealloc (conv_buf, conv_bufsize);
1093 FASTCOPY (str, conv_buf, slen - 1);
1094 FASTCOPY (modifiers, conv_buf + slen - 1, mlen);
1096 conv_buf[len - 2] = str[slen - 1];
1097 conv_buf[len - 1] = '\0';
1098 return (conv_buf);
1101 static int
1102 getchr ()
1104 int ret;
1106 if (garglist == 0)
1107 return ('\0');
1109 ret = (int)garglist->word->word[0];
1110 garglist = garglist->next;
1111 return ret;
1114 static char *
1115 getstr ()
1117 char *ret;
1119 if (garglist == 0)
1120 return ("");
1122 ret = garglist->word->word;
1123 garglist = garglist->next;
1124 return ret;
1127 static int
1128 getint ()
1130 intmax_t ret;
1132 ret = getintmax ();
1134 if (garglist == 0)
1135 return ret;
1137 if (ret > INT_MAX)
1139 printf_erange (garglist->word->word);
1140 ret = INT_MAX;
1142 else if (ret < INT_MIN)
1144 printf_erange (garglist->word->word);
1145 ret = INT_MIN;
1148 return ((int)ret);
1151 static intmax_t
1152 getintmax ()
1154 intmax_t ret;
1155 char *ep;
1157 if (garglist == 0)
1158 return (0);
1160 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
1161 return asciicode ();
1163 errno = 0;
1164 ret = strtoimax (garglist->word->word, &ep, 0);
1166 if (*ep)
1168 sh_invalidnum (garglist->word->word);
1169 /* POSIX.2 says ``...a diagnostic message shall be written to standard
1170 error, and the utility shall not exit with a zero exit status, but
1171 shall continue processing any remaining operands and shall write the
1172 value accumulated at the time the error was detected to standard
1173 output.'' Yecch. */
1174 #if 0
1175 ret = 0; /* return partially-converted value from strtoimax */
1176 #endif
1177 conversion_error = 1;
1179 else if (errno == ERANGE)
1180 printf_erange (garglist->word->word);
1182 garglist = garglist->next;
1183 return (ret);
1186 static uintmax_t
1187 getuintmax ()
1189 uintmax_t ret;
1190 char *ep;
1192 if (garglist == 0)
1193 return (0);
1195 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
1196 return asciicode ();
1198 errno = 0;
1199 ret = strtoumax (garglist->word->word, &ep, 0);
1201 if (*ep)
1203 sh_invalidnum (garglist->word->word);
1204 #if 0
1205 /* Same POSIX.2 conversion error requirements as getintmax(). */
1206 ret = 0;
1207 #endif
1208 conversion_error = 1;
1210 else if (errno == ERANGE)
1211 printf_erange (garglist->word->word);
1213 garglist = garglist->next;
1214 return (ret);
1217 static floatmax_t
1218 getfloatmax ()
1220 floatmax_t ret;
1221 char *ep;
1223 if (garglist == 0)
1224 return (0);
1226 if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
1227 return asciicode ();
1229 errno = 0;
1230 ret = strtofltmax (garglist->word->word, &ep);
1232 if (*ep)
1234 sh_invalidnum (garglist->word->word);
1235 #if 0
1236 /* Same thing about POSIX.2 conversion error requirements. */
1237 ret = 0;
1238 #endif
1239 conversion_error = 1;
1241 else if (errno == ERANGE)
1242 printf_erange (garglist->word->word);
1244 garglist = garglist->next;
1245 return (ret);
1248 /* NO check is needed for garglist here. */
1249 static intmax_t
1250 asciicode ()
1252 register intmax_t ch;
1253 #if defined (HANDLE_MULTIBYTE)
1254 wchar_t wc;
1255 size_t slen;
1256 int mblength;
1257 #endif
1258 DECLARE_MBSTATE;
1260 #if defined (HANDLE_MULTIBYTE)
1261 slen = strlen (garglist->word->word+1);
1262 wc = 0;
1263 mblength = mbtowc (&wc, garglist->word->word+1, slen);
1264 if (mblength > 0)
1265 ch = wc; /* XXX */
1266 else
1267 #endif
1268 ch = (unsigned char)garglist->word->word[1];
1270 garglist = garglist->next;
1271 return (ch);