1This file is printf.def, from which is created printf.c.
2It implements the builtin "printf" in Bash.
3
4Copyright (C) 1997-2020 Free Software Foundation, Inc.
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
8Bash is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
12
13Bash is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along 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]
26Formats and prints ARGUMENTS under control of the FORMAT.
27
28Options:
29  -v var	assign the output to shell variable VAR rather than
30		display it on the standard output
31
32FORMAT is a character string which contains three types of objects: plain
33characters, which are simply copied to standard output; character escape
34sequences, which are converted and copied to the standard output; and
35format specifications, each of which causes printing of the next successive
36argument.
37
38In addition to the standard format specifications described in printf(1),
39printf 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
46The format is re-used as necessary to consume all of the arguments.  If
47there are fewer arguments than the format requires,  extra format
48specifications behave as if a zero value or null string, as appropriate,
49had been supplied.
50
51Exit Status:
52Returns success unless an invalid option is given or a write or assignment
53error occurs.
54$END
55
56#include <config.h>
57
58#include "../bashtypes.h"
59
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
68
69#if defined (PREFER_STDARG)
70#  include <stdarg.h>
71#else
72#  include <varargs.h>
73#endif
74
75#include <stdio.h>
76#include <chartypes.h>
77
78#ifdef HAVE_INTTYPES_H
79#  include <inttypes.h>
80#endif
81
82#include "posixtime.h"
83#include "../bashansi.h"
84#include "../bashintl.h"
85
86#define NEED_STRFTIME_DECL
87
88#include "../shell.h"
89#include "shmbutil.h"
90#include "stdc.h"
91#include "bashgetopt.h"
92#include "common.h"
93
94#if defined (PRI_MACROS_BROKEN)
95#  undef PRIdMAX
96#endif
97
98#if !defined (PRIdMAX)
99#  if HAVE_LONG_LONG
100#    define PRIdMAX	"lld"
101#  else
102#    define PRIdMAX	"ld"
103#  endif
104#endif
105
106#if !defined (errno)
107extern int errno;
108#endif
109
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)
121
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)) \
137      { \
138	sh_wrerror (); \
139	clearerr (stdout); \
140	return (EXECUTION_FAILURE); \
141      } \
142  } while (0)
143
144/* We free the buffer used by mklong() if it's `too big'. */
145#define PRETURN(value) \
146  do \
147    { \
148      QUIT; \
149      if (vflag) \
150	{ \
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); \
156	} \
157      if (conv_bufsize > 4096 ) \
158	{ \
159	  free (conv_buf); \
160	  conv_bufsize = 0; \
161	  conv_buf = 0; \
162	} \
163      if (vbsize > 4096) \
164	{ \
165	  free (vbuf); \
166	  vbsize = 0; \
167	  vbuf = 0; \
168	} \
169      else if (vbuf) \
170	vbuf[0] = 0; \
171      if (ferror (stdout) == 0) \
172	fflush (stdout); \
173      QUIT; \
174      if (ferror (stdout)) \
175	{ \
176	  sh_wrerror (); \
177	  clearerr (stdout); \
178	  return (EXECUTION_FAILURE); \
179	} \
180      return (value); \
181    } \
182  while (0)
183
184#define SKIP1 "#'-+ 0"
185#define LENMODS "hjlLtz"
186
187extern time_t shell_start_time;
188
189#if !HAVE_ASPRINTF
190extern int asprintf PARAMS((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
191#endif
192
193#if !HAVE_VSNPRINTF
194extern int vsnprintf PARAMS((char *, size_t, const char *, va_list)) __attribute__((__format__ (printf, 3, 0)));
195#endif
196
197static void printf_erange PARAMS((char *));
198static int printstr PARAMS((char *, char *, int, int, int));
199static int tescape PARAMS((char *, char *, int *, int *));
200static char *bexpand PARAMS((char *, int, int *, int *));
201static char *vbadd PARAMS((char *, int));
202static int vbprintf PARAMS((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
203static char *mklong PARAMS((char *, char *, size_t));
204static int getchr PARAMS((void));
205static char *getstr PARAMS((void));
206static int  getint PARAMS((void));
207static intmax_t getintmax PARAMS((void));
208static uintmax_t getuintmax PARAMS((void));
209
210#if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD && !defined(STRTOLD_BROKEN)
211typedef long double floatmax_t;
212#  define FLOATMAX_CONV	"L"
213#  define strtofltmax	strtold
214#else
215typedef double floatmax_t;
216#  define FLOATMAX_CONV	""
217#  define strtofltmax	strtod
218#endif
219static floatmax_t getfloatmax PARAMS((void));
220
221static intmax_t asciicode PARAMS((void));
222
223static WORD_LIST *garglist, *orig_arglist;
224static int retval;
225static int conversion_error;
226
227/* printf -v var support */
228static int vflag = 0;
229static char *vbuf, *vname;
230static size_t vbsize;
231static int vblen;
232
233static intmax_t tw;
234
235static char *conv_buf;
236static size_t conv_bufsize;
237
238int
239printf_builtin (list)
240     WORD_LIST *list;
241{
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
252
253  conversion_error = 0;
254  retval = EXECUTION_SUCCESS;
255
256  vflag = 0;
257
258  reset_internal_getopt ();
259  while ((ch = internal_getopt (list, "v:")) != -1)
260    {
261      switch (ch)
262	{
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
271	    {
272	      vflag = 1;
273	      if (vbsize == 0)
274		vbuf = xmalloc (vbsize = 16);
275	      vblen = 0;
276	      if (vbuf)
277		vbuf[0] = 0;
278	    }
279	  else
280	    {
281	      sh_invalidid (vname);
282	      return (EX_USAGE);
283	    }
284	  break;
285	CASE_HELPOPT;
286	default:
287	  builtin_usage ();
288	  return (EX_USAGE);
289	}
290    }
291  list = loptend;	/* skip over possible `--' */
292
293  if (list == 0)
294    {
295      builtin_usage ();
296      return (EX_USAGE);
297    }
298
299  /* Allow printf -v var "" to act like var="" */
300  if (vflag && list->word->word && list->word->word[0] == '\0')
301    {
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);
306    }
307
308  if (list->word->word == 0 || list->word->word[0] == '\0')
309    return (EXECUTION_SUCCESS);
310
311  format = list->word->word;
312  tw = 0;
313
314  garglist = orig_arglist = list->next;
315
316  /* If the format string is empty after preprocessing, return immediately. */
317  if (format == 0 || *format == 0)
318    return (EXECUTION_SUCCESS);
319
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. */
326  do
327    {
328      tw = 0;
329      /* find next format specification */
330      for (fmt = format; *fmt; fmt++)
331	{
332	  precision = fieldwidth = 0;
333	  have_fieldwidth = have_precision = 0;
334
335	  if (*fmt == '\\')
336	    {
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;
353	    }
354
355	  if (*fmt != '%')
356	    {
357	      PC (*fmt);
358	      continue;
359	    }
360
361	  /* ASSERT(*fmt == '%') */
362	  start = fmt++;
363
364	  if (*fmt == '%')		/* %% prints a % */
365	    {
366	      PC ('%');
367	      continue;
368	    }
369
370	  /* found format specification, skip to field width */
371	  for (; *fmt && strchr(SKIP1, *fmt); ++fmt)
372	    ;
373
374	  /* Skip optional field width. */
375	  if (*fmt == '*')
376	    {
377	      fmt++;
378	      have_fieldwidth = 1;
379	      fieldwidth = getint ();
380	    }
381	  else
382	    while (DIGIT (*fmt))
383	      fmt++;
384
385	  /* Skip optional '.' and precision */
386	  if (*fmt == '.')
387	    {
388	      ++fmt;
389	      if (*fmt == '*')
390		{
391		  fmt++;
392		  have_precision = 1;
393		  precision = getint ();
394		}
395	      else
396		{
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++;
409		}
410	    }
411
412	  /* skip possible format modifiers */
413	  modstart = fmt;
414	  while (*fmt && strchr (LENMODS, *fmt))
415	    fmt++;
416
417	  if (*fmt == 0)
418	    {
419	      builtin_error (_("`%s': missing format character"), start);
420	      PRETURN (EXECUTION_FAILURE);
421	    }
422
423	  convch = *fmt;
424	  thisch = modstart[0];
425	  nextch = modstart[1];
426	  modstart[0] = convch;
427	  modstart[1] = '\0';
428
429	  QUIT;
430	  switch(convch)
431	    {
432	    case 'c':
433	      {
434		char p;
435
436		p = getchr ();
437		PF(start, p);
438		break;
439	      }
440
441	    case 's':
442	      {
443		char *p;
444
445		p = getstr ();
446		PF(start, p);
447		break;
448	      }
449
450	    case '(':
451	      {
452		char *timefmt, timebuf[128], *t;
453		int n;
454		intmax_t arg;
455		time_t secs;
456		struct tm *tm;
457
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; )
462		  {
463		    if (*fmt == '(')
464		      n++;
465		    else if (*fmt == ')')
466		      n--;
467		    if (n == 0)
468		      break;
469		    *t++ = *fmt++;
470		  }
471		*t = '\0';
472		if (*++fmt != 'T')
473		  {
474		    builtin_warning (_("`%c': invalid time format specification"), *fmt);
475		    fmt = start;
476		    free (timefmt);
477		    PC (*fmt);
478		    continue;
479		  }
480		if (timefmt[0] == '\0')
481		  {
482		    timefmt[0] = '%';
483		    timefmt[1] = 'X';	/* locale-specific current time - should we use `+'? */
484		    timefmt[2] = '\0';
485		  }
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)
500		  {
501		    secs = 0;
502		    tm = localtime (&secs);
503		  }
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)
515		  {
516		    if (ferror (stdout) == 0)
517		      {
518			sh_wrerror ();
519			clearerr (stdout);
520		      }
521		    PRETURN (EXECUTION_FAILURE);
522		  }
523		break;
524	      }
525
526	    case 'n':
527	      {
528		char *var;
529
530		var = getstr ();
531		if (var && *var)
532		  {
533		    if (legal_identifier (var))
534		      bind_var_to_int (var, tw);
535		    else
536		      {
537			sh_invalidid (var);
538			PRETURN (EXECUTION_FAILURE);
539		      }
540		  }
541		break;
542	      }
543
544	    case 'b':		/* expand escapes in argument */
545	      {
546		char *p, *xp;
547		int rlen, r;
548
549		p = getstr ();
550		ch = rlen = r = 0;
551		xp = bexpand (p, strlen (p), &ch, &rlen);
552
553		if (xp)
554		  {
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)
559		      {
560			if (ferror (stdout) == 0)
561			  {
562		            sh_wrerror ();
563			    clearerr (stdout);
564			  }
565		        retval = EXECUTION_FAILURE;
566		      }
567		    free (xp);
568		  }
569
570		if (ch || r < 0)
571		  PRETURN (retval);
572		break;
573	      }
574
575	    case 'q':		/* print with shell quoting */
576	      {
577		char *p, *xp;
578		int r;
579
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)
589		  {
590		    /* Use printstr to get fieldwidth and precision right. */
591		    r = printstr (start, xp, strlen (xp), fieldwidth, precision);
592		    if (r < 0)
593		      {
594			sh_wrerror ();
595			clearerr (stdout);
596		      }
597		    free (xp);
598		  }
599
600		if (r < 0)
601		  PRETURN (EXECUTION_FAILURE);
602		break;
603	      }
604
605	    case 'd':
606	    case 'i':
607	      {
608		char *f;
609		long p;
610		intmax_t pp;
611
612		p = pp = getintmax ();
613		if (p != pp)
614		  {
615		    f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
616		    PF (f, pp);
617		  }
618		else
619		  {
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);
626		  }
627		break;
628	      }
629
630	    case 'o':
631	    case 'u':
632	    case 'x':
633	    case 'X':
634	      {
635		char *f;
636		unsigned long p;
637		uintmax_t pp;
638
639		p = pp = getuintmax ();
640		if (p != pp)
641		  {
642		    f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
643		    PF (f, pp);
644		  }
645		else
646		  {
647		    f = mklong (start, "l", 1);
648		    PF (f, p);
649		  }
650		break;
651	      }
652
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
663	      {
664		char *f;
665		floatmax_t p;
666
667		p = getfloatmax ();
668		f = mklong (start, FLOATMAX_CONV, sizeof(FLOATMAX_CONV) - 1);
669		PF (f, p);
670		break;
671	      }
672
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);
678	    }
679
680	  modstart[0] = thisch;
681	  modstart[1] = nextch;
682	}
683
684      if (ferror (stdout))
685	{
686	  /* PRETURN will print error message. */
687	  PRETURN (EXECUTION_FAILURE);
688	}
689    }
690  while (garglist && garglist != list->next);
691
692  if (conversion_error)
693    retval = EXECUTION_FAILURE;
694
695  PRETURN (retval);
696}
697
698static void
699printf_erange (s)
700     char *s;
701{
702  builtin_error (_("warning: %s: %s"), s, strerror(ERANGE));
703}
704
705/* We duplicate a lot of what printf(3) does here. */
706static int
707printstr (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 `*' */
713{
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;
720
721  if (string == 0)
722    string = "";
723
724#if 0
725  s = fmt;
726#endif
727  if (*fmt == '%')
728    fmt++;
729
730  ljust = fw = 0;
731  pr = -1;
732  mfw = 0;
733  mpr = -1;
734
735  /* skip flags */
736  while (strchr (SKIP1, *fmt))
737    {
738      if (*fmt == '-')
739	ljust = 1;
740      fmt++;
741    }
742
743  /* get fieldwidth, if present.  rely on caller to clamp fieldwidth at INT_MAX */
744  if (*fmt == '*')
745    {
746      fmt++;
747      fw = fieldwidth;
748      if (fw < 0)
749	{
750	  fw = -fw;
751	  ljust = 1;
752	}
753    }
754  else if (DIGIT (*fmt))
755    {
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;
761    }
762
763  /* get precision, if present */
764  if (*fmt == '.')
765    {
766      fmt++;
767      if (*fmt == '*')
768	{
769	  fmt++;
770	  pr = precision;
771	}
772      else if (DIGIT (*fmt))
773	{
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;
779	}
780      else
781	pr = 0;		/* "a null digit string is treated as zero" */
782    }
783
784#if 0
785  /* If we remove this, get rid of `s'. */
786  if (*fmt != 'b' && *fmt != 'q')
787    {
788      internal_error (_("format parsing problem: %s"), s);
789      fw = pr = 0;
790    }
791#endif
792
793  /* chars from string to print */
794  nc = (pr >= 0 && pr <= len) ? pr : len;
795
796  padlen = fw - nc;
797  if (padlen < 0)
798    padlen = 0;
799  if (ljust)
800    padlen = -padlen;
801
802  /* leading pad characters */
803  for (; padlen > 0; padlen--)
804    PC (' ');
805
806  /* output NC characters from STRING */
807  for (i = 0; i < nc; i++)
808    PC (string[i]);
809
810  /* output any necessary trailing padding */
811  for (; padlen < 0; padlen++)
812    PC (' ');
813
814  return (ferror (stdout) ? -1 : 0);
815}
816
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. */
822
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.  */
830static int
831tescape (estart, cp, lenp, sawc)
832     char *estart;
833     char *cp;
834     int *lenp, *sawc;
835{
836  register char *p;
837  int temp, c, evalue;
838  unsigned long uvalue;
839
840  p = estart;
841  if (lenp)
842    *lenp = 1;
843
844  switch (c = *p++)
845    {
846#if defined (__STDC__)
847      case 'a': *cp = '\a'; break;
848#else
849      case 'a': *cp = '\007'; break;
850#endif
851
852      case 'b': *cp = '\b'; break;
853
854      case 'e':
855      case 'E': *cp = '\033'; break;	/* ESC -- non-ANSI */
856
857      case 'f': *cp = '\f'; break;
858
859      case 'n': *cp = '\n'; break;
860
861      case 'r': *cp = '\r'; break;
862
863      case 't': *cp = '\t'; break;
864
865      case 'v': *cp = '\v'; break;
866
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;
877
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)
884	  {
885	    builtin_error (_("missing hex digit for \\x"));
886	    *cp = '\\';
887	    return 0;
888	  }
889	*cp = evalue & 0xFF;
890	break;
891
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)
899	  {
900	    builtin_error (_("missing unicode digit for \\%c"), c);
901	    *cp = '\\';
902	    return 0;
903	  }
904	if (uvalue <= 0x7f)		/* <= 0x7f translates directly */
905	  *cp = uvalue;
906	else
907	  {
908	    temp = u32cconv (uvalue, cp);
909	    cp[temp] = '\0';
910	    if (lenp)
911	      *lenp = temp;
912	  }
913	break;
914#endif
915
916      case '\\':	/* \\ -> \ */
917	*cp = c;
918	break;
919
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
927	  {
928	    *cp = '\\';
929	    return 0;
930	  }
931	break;
932
933      case 'c':
934	if (sawc)
935	  {
936	    *sawc = 1;
937	    break;
938	  }
939      /* other backslash escapes are passed through unaltered */
940      default:
941	*cp = '\\';
942	return 0;
943      }
944  return (p - estart);
945}
946
947static char *
948bexpand (string, len, sawc, lenp)
949     char *string;
950     int len, *sawc, *lenp;
951{
952  int temp;
953  char *ret, *r, *s, c;
954#if defined (HANDLE_MULTIBYTE)
955  char mbch[25];
956  int mbind, mblen;
957#endif
958
959  if (string == 0 || len == 0)
960    {
961      if (sawc)
962	*sawc = 0;
963      if (lenp)
964	*lenp = 0;
965      ret = (char *)xmalloc (1);
966      ret[0] = '\0';
967      return (ret);
968    }
969
970  ret = (char *)xmalloc (len + 1);
971  for (r = ret, s = string; s && *s; )
972    {
973      c = *s++;
974      if (c != '\\' || *s == '\0')
975	{
976	  *r++ = c;
977	  continue;
978	}
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)
987	{
988	  if (sawc)
989	    *sawc = 1;
990	  break;
991	}
992
993#if defined (HANDLE_MULTIBYTE)
994      for (mbind = 0; mbind < mblen; mbind++)
995	*r++ = mbch[mbind];
996#else
997      *r++ = c;
998#endif
999    }
1000
1001  *r = '\0';
1002  if (lenp)
1003    *lenp = r - ret;
1004  return ret;
1005}
1006
1007static char *
1008vbadd (buf, blen)
1009     char *buf;
1010     int blen;
1011{
1012  size_t nlen;
1013
1014  nlen = vblen + blen + 1;
1015  if (nlen >= vbsize)
1016    {
1017      vbsize = ((nlen + 63) >> 6) << 6;
1018      vbuf = (char *)xrealloc (vbuf, vbsize);
1019    }
1020
1021  if (blen == 1)
1022    vbuf[vblen++] = buf[0];
1023  else if (blen > 1)
1024    {
1025      FASTCOPY (buf, vbuf  + vblen, blen);
1026      vblen += blen;
1027    }
1028  vbuf[vblen] = '\0';
1029
1030#ifdef DEBUG
1031  if  (strlen (vbuf) != vblen)
1032    internal_error  ("printf:vbadd: vblen (%d) != strlen (vbuf) (%d)", vblen, (int)strlen (vbuf));
1033#endif
1034
1035  return vbuf;
1036}
1037
1038static int
1039#if defined (PREFER_STDARG)
1040vbprintf (const char *format, ...)
1041#else
1042vbprintf (format, va_alist)
1043  const char *format;
1044  va_dcl
1045#endif
1046{
1047  va_list args;
1048  size_t nlen;
1049  int blen;
1050
1051  SH_VA_START (args, format);
1052  blen = vsnprintf (vbuf + vblen, vbsize - vblen, format, args);
1053  va_end (args);
1054
1055  nlen = vblen + blen + 1;
1056  if (nlen >= vbsize)
1057    {
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);
1063    }
1064
1065  vblen += blen;
1066  vbuf[vblen] = '\0';
1067
1068#ifdef DEBUG
1069  if  (strlen (vbuf) != vblen)
1070    internal_error  ("printf:vbprintf: vblen (%d) != strlen (vbuf) (%d)", vblen, (int)strlen (vbuf));
1071#endif
1072
1073  return (blen);
1074}
1075
1076static char *
1077mklong (str, modifiers, mlen)
1078     char *str;
1079     char *modifiers;
1080     size_t mlen;
1081{
1082  size_t len, slen;
1083
1084  slen = strlen (str);
1085  len = slen + mlen + 1;
1086
1087  if (len > conv_bufsize)
1088    {
1089      conv_bufsize = (((len + 1023) >> 10) << 10);
1090      conv_buf = (char *)xrealloc (conv_buf, conv_bufsize);
1091    }
1092
1093  FASTCOPY (str, conv_buf, slen - 1);
1094  FASTCOPY (modifiers, conv_buf + slen - 1, mlen);
1095
1096  conv_buf[len - 2] = str[slen - 1];
1097  conv_buf[len - 1] = '\0';
1098  return (conv_buf);
1099}
1100
1101static int
1102getchr ()
1103{
1104  int ret;
1105
1106  if (garglist == 0)
1107    return ('\0');
1108
1109  ret = (int)garglist->word->word[0];
1110  garglist = garglist->next;
1111  return ret;
1112}
1113
1114static char *
1115getstr ()
1116{
1117  char *ret;
1118
1119  if (garglist == 0)
1120    return ("");
1121
1122  ret = garglist->word->word;
1123  garglist = garglist->next;
1124  return ret;
1125}
1126
1127static int
1128getint ()
1129{
1130  intmax_t ret;
1131
1132  ret = getintmax ();
1133
1134  if (garglist == 0)
1135    return ret;
1136
1137  if (ret > INT_MAX)
1138    {
1139      printf_erange (garglist->word->word);
1140      ret = INT_MAX;
1141    }
1142  else if (ret < INT_MIN)
1143    {
1144      printf_erange (garglist->word->word);
1145      ret = INT_MIN;
1146    }
1147
1148  return ((int)ret);
1149}
1150
1151static intmax_t
1152getintmax ()
1153{
1154  intmax_t ret;
1155  char *ep;
1156
1157  if (garglist == 0)
1158    return (0);
1159
1160  if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
1161    return asciicode ();
1162
1163  errno = 0;
1164  ret = strtoimax (garglist->word->word, &ep, 0);
1165
1166  if (*ep)
1167    {
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;
1178    }
1179  else if (errno == ERANGE)
1180    printf_erange (garglist->word->word);
1181
1182  garglist = garglist->next;
1183  return (ret);
1184}
1185
1186static uintmax_t
1187getuintmax ()
1188{
1189  uintmax_t ret;
1190  char *ep;
1191
1192  if (garglist == 0)
1193    return (0);
1194
1195  if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
1196    return asciicode ();
1197
1198  errno = 0;
1199  ret = strtoumax (garglist->word->word, &ep, 0);
1200
1201  if (*ep)
1202    {
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;
1209    }
1210  else if (errno == ERANGE)
1211    printf_erange (garglist->word->word);
1212
1213  garglist = garglist->next;
1214  return (ret);
1215}
1216
1217static floatmax_t
1218getfloatmax ()
1219{
1220  floatmax_t ret;
1221  char *ep;
1222
1223  if (garglist == 0)
1224    return (0);
1225
1226  if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
1227    return asciicode ();
1228
1229  errno = 0;
1230  ret = strtofltmax (garglist->word->word, &ep);
1231
1232  if (*ep)
1233    {
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;
1240    }
1241  else if (errno == ERANGE)
1242    printf_erange (garglist->word->word);
1243
1244  garglist = garglist->next;
1245  return (ret);
1246}
1247
1248/* NO check is needed for garglist here. */
1249static intmax_t
1250asciicode ()
1251{
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;
1259
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];
1269
1270  garglist = garglist->next;
1271  return (ch);
1272}
1273