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