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