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