Imported from ../bash-2.05b.tar.gz.
This commit is contained in:
parent
f73dda092b
commit
7117c2d221
362 changed files with 34387 additions and 15063 deletions
|
|
@ -1,7 +1,7 @@
|
|||
This file is printf.def, from which is created printf.c.
|
||||
It implements the builtin "printf" in Bash.
|
||||
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997-2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -56,18 +56,17 @@ $END
|
|||
|
||||
#include "../bashansi.h"
|
||||
|
||||
#define NEED_STRTOIMAX_DECL
|
||||
|
||||
#include "../shell.h"
|
||||
#include "stdc.h"
|
||||
#include "bashgetopt.h"
|
||||
#include "common.h"
|
||||
|
||||
/* This should use the ISO C constant format strings; I'll do that later. */
|
||||
#if SIZEOF_LONG < SIZEOF_LONG_LONG
|
||||
# define INTMAX_CONV "ll"
|
||||
#else
|
||||
# define INTMAX_CONV "l"
|
||||
#if !defined (PRIdMAX)
|
||||
# if HAVE_LONG_LONG
|
||||
# define PRIdMAX "lld"
|
||||
# else
|
||||
# define PRIdMAX "ld"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined (errno)
|
||||
|
|
@ -104,25 +103,28 @@ extern int errno;
|
|||
#define SKIP1 "#'-+ 0"
|
||||
#define LENMODS "hjlLtz"
|
||||
|
||||
static void printf_erange __P((char *));
|
||||
static void printstr __P((char *, char *, int, int, int));
|
||||
static int tescape __P((char *, int, char *, int *));
|
||||
static char *bexpand __P((char *, int, int *, int *));
|
||||
static char *mklong __P((char *, char *));
|
||||
static char *mklong __P((char *, char *, size_t));
|
||||
static int getchr __P((void));
|
||||
static char *getstr __P((void));
|
||||
static int getint __P((void));
|
||||
static long getlong __P((void));
|
||||
static unsigned long getulong __P((void));
|
||||
#if defined (HAVE_LONG_LONG)
|
||||
static long long getllong __P((void));
|
||||
static unsigned long long getullong __P((void));
|
||||
#endif
|
||||
static intmax_t getintmax __P((void));
|
||||
static uintmax_t getuintmax __P((void));
|
||||
static double getdouble __P((void));
|
||||
|
||||
#if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD
|
||||
static long double getldouble __P((void));
|
||||
typedef long double floatmax_t;
|
||||
# define FLOATMAX_CONV "L"
|
||||
# define strtofltmax strtold
|
||||
#else
|
||||
typedef double floatmax_t;
|
||||
# define FLOATMAX_CONV ""
|
||||
# define strtofltmax strtod
|
||||
#endif
|
||||
static floatmax_t getfloatmax __P((void));
|
||||
|
||||
static int asciicode __P((void));
|
||||
|
||||
static WORD_LIST *garglist;
|
||||
|
|
@ -138,18 +140,15 @@ printf_builtin (list)
|
|||
{
|
||||
int ch, fieldwidth, precision;
|
||||
int have_fieldwidth, have_precision;
|
||||
long tw;
|
||||
intmax_t tw;
|
||||
char convch, thisch, nextch, *format, *modstart, *fmt, *start;
|
||||
|
||||
conversion_error = 0;
|
||||
retval = EXECUTION_SUCCESS;
|
||||
reset_internal_getopt ();
|
||||
if (internal_getopt (list, "") != -1)
|
||||
{
|
||||
builtin_usage();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
list = loptend;
|
||||
|
||||
if (no_options (list))
|
||||
return (EX_USAGE);
|
||||
list = loptend; /* skip over possible `--' */
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
|
|
@ -288,7 +287,7 @@ printf_builtin (list)
|
|||
bind_var_to_int (var, tw);
|
||||
else
|
||||
{
|
||||
builtin_error ("%s: invalid variable name", var);
|
||||
sh_invalidid (var);
|
||||
PRETURN (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
|
|
@ -322,7 +321,10 @@ printf_builtin (list)
|
|||
char *p, *xp;
|
||||
|
||||
p = getstr ();
|
||||
xp = sh_backslash_quote (p);
|
||||
if (ansic_shouldquote (p))
|
||||
xp = ansic_quote (p, 0, (int *)0);
|
||||
else
|
||||
xp = sh_backslash_quote (p);
|
||||
if (xp)
|
||||
{
|
||||
/* Use printstr to get fieldwidth and precision right. */
|
||||
|
|
@ -336,32 +338,23 @@ printf_builtin (list)
|
|||
case 'i':
|
||||
{
|
||||
char *f;
|
||||
#if defined (HAVE_LONG_LONG)
|
||||
if (thisch == 'l' && nextch == 'l')
|
||||
{
|
||||
long long p;
|
||||
long p;
|
||||
intmax_t pp;
|
||||
|
||||
p = getllong ();
|
||||
f = mklong (start, "ll");
|
||||
PF(f, p);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (thisch == 'j')
|
||||
p = pp = getintmax ();
|
||||
if (p != pp)
|
||||
{
|
||||
intmax_t p;
|
||||
|
||||
p = getintmax ();
|
||||
f = mklong (start, INTMAX_CONV);
|
||||
PF(f, p);
|
||||
f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
|
||||
PF (f, pp);
|
||||
}
|
||||
else
|
||||
{
|
||||
long p;
|
||||
|
||||
p = getlong ();
|
||||
f = mklong (start, "l");
|
||||
PF(f, p);
|
||||
/* Optimize the common case where the integer fits
|
||||
in "long". This also works around some long
|
||||
long and/or intmax_t library bugs in the common
|
||||
case, e.g. glibc 2.2 x86. */
|
||||
f = mklong (start, "l", 1);
|
||||
PF (f, p);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -372,31 +365,18 @@ printf_builtin (list)
|
|||
case 'X':
|
||||
{
|
||||
char *f;
|
||||
#if defined (HAVE_LONG_LONG)
|
||||
if (thisch == 'l' && nextch == 'l')
|
||||
{
|
||||
unsigned long long p;
|
||||
unsigned long p;
|
||||
uintmax_t pp;
|
||||
|
||||
p = getullong ();
|
||||
f = mklong (start, "ll");
|
||||
PF(f, p);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (thisch == 'j')
|
||||
p = pp = getuintmax ();
|
||||
if (p != pp)
|
||||
{
|
||||
uintmax_t p;
|
||||
|
||||
p = getuintmax ();
|
||||
f = mklong (start, INTMAX_CONV);
|
||||
PF(f, p);
|
||||
f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
|
||||
PF (f, pp);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long p;
|
||||
|
||||
p = getulong ();
|
||||
f = mklong (start, "l");
|
||||
f = mklong (start, "l", 1);
|
||||
PF (f, p);
|
||||
}
|
||||
break;
|
||||
|
|
@ -414,24 +394,11 @@ printf_builtin (list)
|
|||
#endif
|
||||
{
|
||||
char *f;
|
||||
#if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD
|
||||
if (thisch == 'L')
|
||||
{
|
||||
long double p;
|
||||
floatmax_t p;
|
||||
|
||||
p = getldouble ();
|
||||
f = mklong (start, "L");
|
||||
PF (f, p);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
double p;
|
||||
|
||||
p = getdouble ();
|
||||
f = mklong (start, "");
|
||||
PF (f, p);
|
||||
}
|
||||
p = getfloatmax ();
|
||||
f = mklong (start, FLOATMAX_CONV, sizeof(FLOATMAX_CONV) - 1);
|
||||
PF (f, p);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -454,6 +421,13 @@ printf_builtin (list)
|
|||
PRETURN (retval);
|
||||
}
|
||||
|
||||
static void
|
||||
printf_erange (s)
|
||||
char *s;
|
||||
{
|
||||
builtin_error ("warning: %s: %s", s, strerror(ERANGE));
|
||||
}
|
||||
|
||||
/* We duplicate a lot of what printf(3) does here. */
|
||||
static void
|
||||
printstr (fmt, string, len, fieldwidth, precision)
|
||||
|
|
@ -605,16 +579,11 @@ tescape (estart, trans_squote, cp, sawc)
|
|||
/* %b octal constants are `\0' followed by one, two, or three
|
||||
octal digits... */
|
||||
case '0':
|
||||
for (temp = 3, evalue = 0; ISOCTAL (*p) && temp--; p++)
|
||||
evalue = (evalue * 8) + OCTVALUE (*p);
|
||||
*cp = evalue & 0xFF;
|
||||
break;
|
||||
|
||||
/* but, as an extension, the other echo-like octal escape
|
||||
sequences are supported as well. */
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7':
|
||||
for (temp = 2, evalue = c - '0'; ISOCTAL (*p) && temp--; p++)
|
||||
for (temp = 2+(c=='0'), evalue = c - '0'; ISOCTAL (*p) && temp--; p++)
|
||||
evalue = (evalue * 8) + OCTVALUE (*p);
|
||||
*cp = evalue & 0xFF;
|
||||
break;
|
||||
|
|
@ -706,14 +675,14 @@ bexpand (string, len, sawc, lenp)
|
|||
}
|
||||
|
||||
static char *
|
||||
mklong (str, modifiers)
|
||||
mklong (str, modifiers, mlen)
|
||||
char *str;
|
||||
char *modifiers;
|
||||
size_t mlen;
|
||||
{
|
||||
size_t len, slen, mlen;
|
||||
size_t len, slen;
|
||||
|
||||
slen = strlen (str);
|
||||
mlen = strlen (modifiers);
|
||||
len = slen + mlen + 1;
|
||||
|
||||
if (len > conv_bufsize)
|
||||
|
|
@ -759,152 +728,24 @@ getstr ()
|
|||
static int
|
||||
getint ()
|
||||
{
|
||||
long ret;
|
||||
intmax_t ret;
|
||||
|
||||
ret = getlong ();
|
||||
ret = getintmax ();
|
||||
|
||||
if (ret > INT_MAX)
|
||||
{
|
||||
builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
|
||||
printf_erange (garglist->word->word);
|
||||
ret = INT_MAX;
|
||||
}
|
||||
else if (ret < INT_MIN)
|
||||
{
|
||||
builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
|
||||
printf_erange (garglist->word->word);
|
||||
ret = INT_MIN;
|
||||
}
|
||||
|
||||
return ((int)ret);
|
||||
}
|
||||
|
||||
static long
|
||||
getlong ()
|
||||
{
|
||||
long ret;
|
||||
char *ep;
|
||||
|
||||
if (garglist == 0)
|
||||
return (0);
|
||||
|
||||
if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
|
||||
return asciicode ();
|
||||
|
||||
errno = 0;
|
||||
ret = strtol (garglist->word->word, &ep, 0);
|
||||
|
||||
if (*ep)
|
||||
{
|
||||
builtin_error ("%s: invalid number", garglist->word->word);
|
||||
/* POSIX.2 says ``...a diagnostic message shall be written to standard
|
||||
error, and the utility shall not exit with a zero exit status, but
|
||||
shall continue processing any remaining operands and shall write the
|
||||
value accumulated at the time the error was detected to standard
|
||||
output.'' Yecch. */
|
||||
ret = 0;
|
||||
conversion_error = 1;
|
||||
}
|
||||
else if (errno == ERANGE)
|
||||
builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
|
||||
|
||||
garglist = garglist->next;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
getulong ()
|
||||
{
|
||||
unsigned long ret;
|
||||
char *ep;
|
||||
|
||||
if (garglist == 0)
|
||||
return (0);
|
||||
|
||||
if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
|
||||
return asciicode ();
|
||||
|
||||
errno = 0;
|
||||
ret = strtoul (garglist->word->word, &ep, 0);
|
||||
|
||||
if (*ep)
|
||||
{
|
||||
builtin_error ("%s: invalid number", garglist->word->word);
|
||||
/* Same thing about POSIX.2 conversion error requirements as getlong(). */
|
||||
ret = 0;
|
||||
conversion_error = 1;
|
||||
}
|
||||
else if (errno == ERANGE)
|
||||
builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
|
||||
|
||||
garglist = garglist->next;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#if defined (HAVE_LONG_LONG)
|
||||
|
||||
static long long
|
||||
getllong ()
|
||||
{
|
||||
long long ret;
|
||||
char *ep;
|
||||
|
||||
if (garglist == 0)
|
||||
return (0);
|
||||
|
||||
if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
|
||||
return asciicode ();
|
||||
|
||||
errno = 0;
|
||||
ret = strtoll (garglist->word->word, &ep, 0);
|
||||
|
||||
if (*ep)
|
||||
{
|
||||
builtin_error ("%s: invalid number", garglist->word->word);
|
||||
/* POSIX.2 says ``...a diagnostic message shall be written to standard
|
||||
error, and the utility shall not exit with a zero exit status, but
|
||||
shall continue processing any remaining operands and shall write the
|
||||
value accumulated at the time the error was detected to standard
|
||||
output.'' Yecch. */
|
||||
ret = 0;
|
||||
conversion_error = 1;
|
||||
}
|
||||
else if (errno == ERANGE)
|
||||
builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
|
||||
|
||||
garglist = garglist->next;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static unsigned long long
|
||||
getullong ()
|
||||
{
|
||||
unsigned long long ret;
|
||||
char *ep;
|
||||
|
||||
if (garglist == 0)
|
||||
return (0);
|
||||
|
||||
if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
|
||||
return asciicode ();
|
||||
|
||||
errno = 0;
|
||||
ret = strtoull (garglist->word->word, &ep, 0);
|
||||
|
||||
if (*ep)
|
||||
{
|
||||
builtin_error ("%s: invalid number", garglist->word->word);
|
||||
/* Same thing about POSIX.2 conversion error requirements as getlong(). */
|
||||
ret = 0;
|
||||
conversion_error = 1;
|
||||
}
|
||||
else if (errno == ERANGE)
|
||||
builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
|
||||
|
||||
garglist = garglist->next;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#endif /* HAVE_LONG_LONG */
|
||||
|
||||
static intmax_t
|
||||
getintmax ()
|
||||
{
|
||||
|
|
@ -922,7 +763,7 @@ getintmax ()
|
|||
|
||||
if (*ep)
|
||||
{
|
||||
builtin_error ("%s: invalid number", garglist->word->word);
|
||||
sh_invalidnum (garglist->word->word);
|
||||
/* POSIX.2 says ``...a diagnostic message shall be written to standard
|
||||
error, and the utility shall not exit with a zero exit status, but
|
||||
shall continue processing any remaining operands and shall write the
|
||||
|
|
@ -932,7 +773,7 @@ getintmax ()
|
|||
conversion_error = 1;
|
||||
}
|
||||
else if (errno == ERANGE)
|
||||
builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
|
||||
printf_erange (garglist->word->word);
|
||||
|
||||
garglist = garglist->next;
|
||||
return (ret);
|
||||
|
|
@ -955,22 +796,22 @@ getuintmax ()
|
|||
|
||||
if (*ep)
|
||||
{
|
||||
builtin_error ("%s: invalid number", garglist->word->word);
|
||||
/* Same thing about POSIX.2 conversion error requirements as getlong(). */
|
||||
sh_invalidnum (garglist->word->word);
|
||||
/* Same POSIX.2 conversion error requirements as getintmax(). */
|
||||
ret = 0;
|
||||
conversion_error = 1;
|
||||
}
|
||||
else if (errno == ERANGE)
|
||||
builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
|
||||
printf_erange (garglist->word->word);
|
||||
|
||||
garglist = garglist->next;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static double
|
||||
getdouble ()
|
||||
static floatmax_t
|
||||
getfloatmax ()
|
||||
{
|
||||
double ret;
|
||||
floatmax_t ret;
|
||||
char *ep;
|
||||
|
||||
if (garglist == 0)
|
||||
|
|
@ -980,53 +821,22 @@ getdouble ()
|
|||
return asciicode ();
|
||||
|
||||
errno = 0;
|
||||
ret = strtod (garglist->word->word, &ep);
|
||||
ret = strtofltmax (garglist->word->word, &ep);
|
||||
|
||||
if (*ep)
|
||||
{
|
||||
builtin_error ("%s: invalid number", garglist->word->word);
|
||||
sh_invalidnum (garglist->word->word);
|
||||
/* Same thing about POSIX.2 conversion error requirements. */
|
||||
ret = 0;
|
||||
conversion_error = 1;
|
||||
}
|
||||
else if (errno == ERANGE)
|
||||
builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
|
||||
printf_erange (garglist->word->word);
|
||||
|
||||
garglist = garglist->next;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD
|
||||
static long double
|
||||
getldouble ()
|
||||
{
|
||||
long double ret;
|
||||
char *ep;
|
||||
|
||||
if (garglist == 0)
|
||||
return (0);
|
||||
|
||||
if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
|
||||
return (asciicode ());
|
||||
|
||||
errno = 0;
|
||||
ret = strtold (garglist->word->word, &ep);
|
||||
|
||||
if (*ep)
|
||||
{
|
||||
builtin_error ("%s: invalid number", garglist->word->word);
|
||||
/* Same thing about POSIX.2 conversion error requirements. */
|
||||
ret = 0;
|
||||
conversion_error = 1;
|
||||
}
|
||||
else if (errno == ERANGE)
|
||||
builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
|
||||
|
||||
garglist = garglist->next;
|
||||
return (ret);
|
||||
}
|
||||
#endif /* HAVE_LONG_DOUBLE && HAVE_DECL_STRTOLD */
|
||||
|
||||
/* NO check is needed for garglist here. */
|
||||
static int
|
||||
asciicode ()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue