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