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