source: vendor/bash/3.1/builtins/printf.def

Last change on this file was 3228, checked in by bird, 18 years ago

bash 3.1

File size: 20.1 KB
Line 
1This file is printf.def, from which is created printf.c.
2It implements the builtin "printf" in Bash.
3
4Copyright (C) 1997-2005 Free Software Foundation, Inc.
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
8Bash is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 2, or (at your option) any later
11version.
12
13Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License along
19with Bash; see the file COPYING. If not, write to the Free Software
20Foundation, 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]
27printf formats and prints ARGUMENTS under control of the FORMAT. FORMAT
28is a character string which contains three types of objects: plain
29characters, which are simply copied to standard output, character escape
30sequences which are converted and copied to the standard output, and
31format specifications, each of which causes printing of the next successive
32argument. In addition to the standard printf(1) formats, %b means to
33expand backslash escape sequences in the corresponding argument, and %q
34means to quote the argument in a way that can be reused as shell input.
35If the -v option is supplied, the output is placed into the value of the
36shell 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)
76extern 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
142static void printf_erange __P((char *));
143static int printstr __P((char *, char *, int, int, int));
144static int tescape __P((char *, char *, int *));
145static char *bexpand __P((char *, int, int *, int *));
146static char *vbadd __P((char *, int));
147static char *mklong __P((char *, char *, size_t));
148static int getchr __P((void));
149static char *getstr __P((void));
150static int getint __P((void));
151static intmax_t getintmax __P((void));
152static uintmax_t getuintmax __P((void));
153
154#if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD && !defined(STRTOLD_BROKEN)
155typedef long double floatmax_t;
156# define FLOATMAX_CONV "L"
157# define strtofltmax strtold
158#else
159typedef double floatmax_t;
160# define FLOATMAX_CONV ""
161# define strtofltmax strtod
162#endif
163static floatmax_t getfloatmax __P((void));
164
165static int asciicode __P((void));
166
167static WORD_LIST *garglist;
168static int retval;
169static int conversion_error;
170
171/* printf -v var support */
172static int vflag = 0;
173static char *vbuf, *vname;
174static size_t vbsize;
175static int vblen;
176
177static intmax_t tw;
178
179static char *conv_buf;
180static size_t conv_bufsize;
181
182int
183printf_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
525static void
526printf_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. */
533static int
534printstr (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. */
652static int
653tescape (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
746static char *
747bexpand (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
794static char *
795vbadd (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
825static char *
826mklong (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
850static int
851getchr ()
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
863static char *
864getstr ()
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
876static int
877getint ()
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
897static intmax_t
898getintmax ()
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
930static uintmax_t
931getuintmax ()
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
959static floatmax_t
960getfloatmax ()
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. */
989static int
990asciicode ()
991{
992 register int ch;
993
994 ch = garglist->word->word[1];
995 garglist = garglist->next;
996 return (ch);
997}
Note: See TracBrowser for help on using the repository browser.