Imported from ../bash-2.05a.tar.gz.
This commit is contained in:
parent
28ef6c316f
commit
f73dda092b
303 changed files with 37069 additions and 28812 deletions
|
|
@ -42,20 +42,33 @@ $END
|
|||
#if defined (HAVE_LIMITS_H)
|
||||
# include <limits.h>
|
||||
#else
|
||||
/* Assume 32-bit ints and longs. */
|
||||
# define LONG_MAX 2147483647L
|
||||
# define LONG_MIN (-2147483647L-1)
|
||||
/* Assume 32-bit ints. */
|
||||
# define INT_MAX 2147483647
|
||||
# define INT_MIN (-2147483647-1)
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <chartypes.h>
|
||||
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#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"
|
||||
#endif
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
|
|
@ -63,57 +76,78 @@ extern int errno;
|
|||
|
||||
#define PF(f, func) \
|
||||
do { \
|
||||
if (fieldwidth && precision) \
|
||||
(void)printf(f, fieldwidth, precision, func); \
|
||||
else if (fieldwidth && precision == 0) \
|
||||
(void)printf(f, fieldwidth, func); \
|
||||
else if (precision) \
|
||||
(void)printf(f, precision, func); \
|
||||
if (have_fieldwidth && have_precision) \
|
||||
tw += printf(f, fieldwidth, precision, func); \
|
||||
else if (have_fieldwidth) \
|
||||
tw += printf(f, fieldwidth, func); \
|
||||
else if (have_precision) \
|
||||
tw += printf(f, precision, func); \
|
||||
else \
|
||||
(void)printf(f, func); \
|
||||
tw += printf(f, func); \
|
||||
} while (0)
|
||||
|
||||
/* We free the buffer used by mklong() if it's `too big'. */
|
||||
#define PRETURN(value) \
|
||||
do { /* free (format); */ fflush (stdout); return (value); } while (0)
|
||||
do \
|
||||
{ \
|
||||
if (conv_bufsize > 4096 ) \
|
||||
{ \
|
||||
free(conv_buf); \
|
||||
conv_bufsize = 0; \
|
||||
conv_buf = 0; \
|
||||
} \
|
||||
fflush (stdout); \
|
||||
return (value); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define SKIP1 "#-+ 0"
|
||||
#define SKIP2 "*0123456789"
|
||||
#define SKIP1 "#'-+ 0"
|
||||
#define LENMODS "hjlLtz"
|
||||
|
||||
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 *, int));
|
||||
static char *mklong __P((char *, char *));
|
||||
static int getchr __P((void));
|
||||
static char *getstr __P((void));
|
||||
static int getint __P((void));
|
||||
static int getlong __P((long *));
|
||||
static int getulong __P((unsigned long *));
|
||||
static int getdouble __P((double *));
|
||||
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));
|
||||
#endif
|
||||
static int asciicode __P((void));
|
||||
|
||||
static WORD_LIST *garglist;
|
||||
static int retval;
|
||||
static int conversion_error;
|
||||
|
||||
extern char *sh_backslash_quote ();
|
||||
static char *conv_buf;
|
||||
static size_t conv_bufsize;
|
||||
|
||||
int
|
||||
printf_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int ch, end, fieldwidth, precision, foundmod, fmtlen;
|
||||
char convch, nextch, *format, *fmt, *start;
|
||||
int ch, fieldwidth, precision;
|
||||
int have_fieldwidth, have_precision;
|
||||
long tw;
|
||||
char convch, thisch, nextch, *format, *modstart, *fmt, *start;
|
||||
|
||||
conversion_error = 0;
|
||||
retval = EXECUTION_SUCCESS;
|
||||
reset_internal_getopt ();
|
||||
while ((ch = internal_getopt (list, "")) != -1)
|
||||
if (internal_getopt (list, "") != -1)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case '?':
|
||||
default:
|
||||
builtin_usage();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
builtin_usage();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
list = loptend;
|
||||
|
||||
|
|
@ -140,18 +174,20 @@ printf_builtin (list)
|
|||
format strings are reused as necessary to use up the provided
|
||||
arguments, arguments of zero/null string are provided to use
|
||||
up the format string. */
|
||||
|
||||
do
|
||||
{
|
||||
tw = 0;
|
||||
/* find next format specification */
|
||||
for (fmt = format; *fmt; fmt++)
|
||||
{
|
||||
precision = fieldwidth = foundmod = 0;
|
||||
precision = fieldwidth = 0;
|
||||
have_fieldwidth = have_precision = 0;
|
||||
|
||||
|
||||
if (*fmt == '\\')
|
||||
{
|
||||
fmt++;
|
||||
/* A NULL third argument to tescape means to not do special
|
||||
/* A NULL fourth argument to tescape means to not do special
|
||||
processing for \c. */
|
||||
fmt += tescape (fmt, 1, &nextch, (int *)NULL);
|
||||
putchar (nextch);
|
||||
|
|
@ -177,27 +213,37 @@ printf_builtin (list)
|
|||
/* found format specification, skip to field width */
|
||||
for (; *fmt && strchr(SKIP1, *fmt); ++fmt)
|
||||
;
|
||||
fieldwidth = (*fmt == '*') ? getint () : 0;
|
||||
|
||||
/* skip to possible '.', get following precision */
|
||||
for (; *fmt && strchr(SKIP2, *fmt); ++fmt)
|
||||
;
|
||||
/* Skip optional field width. */
|
||||
if (*fmt == '*')
|
||||
{
|
||||
fmt++;
|
||||
have_fieldwidth = 1;
|
||||
fieldwidth = getint ();
|
||||
}
|
||||
else
|
||||
while (DIGIT (*fmt))
|
||||
fmt++;
|
||||
|
||||
/* Skip optional '.' and precision */
|
||||
if (*fmt == '.')
|
||||
{
|
||||
++fmt;
|
||||
precision = (*fmt == '*') ? getint () : 0;
|
||||
if (*fmt == '*')
|
||||
{
|
||||
fmt++;
|
||||
have_precision = 1;
|
||||
precision = getint ();
|
||||
}
|
||||
else
|
||||
while (DIGIT (*fmt))
|
||||
fmt++;
|
||||
}
|
||||
|
||||
/* skip to conversion char */
|
||||
for (; *fmt && strchr(SKIP2, *fmt); ++fmt)
|
||||
;
|
||||
|
||||
/* skip possible format modifiers */
|
||||
if (*fmt == 'l' || *fmt == 'L' || *fmt == 'h')
|
||||
{
|
||||
fmt++;
|
||||
foundmod = 1;
|
||||
}
|
||||
modstart = fmt;
|
||||
while (*fmt && strchr (LENMODS, *fmt))
|
||||
fmt++;
|
||||
|
||||
if (*fmt == 0)
|
||||
{
|
||||
|
|
@ -206,8 +252,11 @@ printf_builtin (list)
|
|||
}
|
||||
|
||||
convch = *fmt;
|
||||
nextch = fmt[1];
|
||||
fmt[1] = '\0';
|
||||
thisch = modstart[0];
|
||||
nextch = modstart[1];
|
||||
modstart[0] = convch;
|
||||
modstart[1] = '\0';
|
||||
|
||||
switch(convch)
|
||||
{
|
||||
case 'c':
|
||||
|
|
@ -228,6 +277,24 @@ printf_builtin (list)
|
|||
break;
|
||||
}
|
||||
|
||||
case 'n':
|
||||
{
|
||||
char *var;
|
||||
|
||||
var = getstr ();
|
||||
if (var && *var)
|
||||
{
|
||||
if (legal_identifier (var))
|
||||
bind_var_to_int (var, tw);
|
||||
else
|
||||
{
|
||||
builtin_error ("%s: invalid variable name", var);
|
||||
PRETURN (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'b': /* expand escapes in argument */
|
||||
{
|
||||
char *p, *xp;
|
||||
|
|
@ -268,16 +335,34 @@ printf_builtin (list)
|
|||
case 'd':
|
||||
case 'i':
|
||||
{
|
||||
long p;
|
||||
char *f;
|
||||
#if defined (HAVE_LONG_LONG)
|
||||
if (thisch == 'l' && nextch == 'l')
|
||||
{
|
||||
long long p;
|
||||
|
||||
if (foundmod == 0 && ((f = mklong (start, convch)) == NULL))
|
||||
PRETURN (EXECUTION_FAILURE);
|
||||
p = getllong ();
|
||||
f = mklong (start, "ll");
|
||||
PF(f, p);
|
||||
}
|
||||
else
|
||||
f = start;
|
||||
if (getlong (&p))
|
||||
PRETURN (EXECUTION_FAILURE);
|
||||
PF(f, p);
|
||||
#endif
|
||||
if (thisch == 'j')
|
||||
{
|
||||
intmax_t p;
|
||||
|
||||
p = getintmax ();
|
||||
f = mklong (start, INTMAX_CONV);
|
||||
PF(f, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
long p;
|
||||
|
||||
p = getlong ();
|
||||
f = mklong (start, "l");
|
||||
PF(f, p);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -286,30 +371,67 @@ printf_builtin (list)
|
|||
case 'x':
|
||||
case 'X':
|
||||
{
|
||||
unsigned long p;
|
||||
char *f;
|
||||
#if defined (HAVE_LONG_LONG)
|
||||
if (thisch == 'l' && nextch == 'l')
|
||||
{
|
||||
unsigned long long p;
|
||||
|
||||
if (foundmod == 0 && ((f = mklong (start, convch)) == NULL))
|
||||
PRETURN (EXECUTION_FAILURE);
|
||||
p = getullong ();
|
||||
f = mklong (start, "ll");
|
||||
PF(f, p);
|
||||
}
|
||||
else
|
||||
f = start;
|
||||
if (getulong (&p))
|
||||
PRETURN (EXECUTION_FAILURE);
|
||||
PF (f, p);
|
||||
#endif
|
||||
if (thisch == 'j')
|
||||
{
|
||||
uintmax_t p;
|
||||
|
||||
p = getuintmax ();
|
||||
f = mklong (start, INTMAX_CONV);
|
||||
PF(f, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long p;
|
||||
|
||||
p = getulong ();
|
||||
f = mklong (start, "l");
|
||||
PF (f, p);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 'g':
|
||||
case 'G':
|
||||
#if defined (HAVE_PRINTF_A_FORMAT)
|
||||
case 'a':
|
||||
case 'A':
|
||||
#endif
|
||||
{
|
||||
double p;
|
||||
char *f;
|
||||
#if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD
|
||||
if (thisch == 'L')
|
||||
{
|
||||
long double p;
|
||||
|
||||
if (getdouble (&p))
|
||||
PRETURN (EXECUTION_FAILURE);
|
||||
PF(start, p);
|
||||
p = getldouble ();
|
||||
f = mklong (start, "L");
|
||||
PF (f, p);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
double p;
|
||||
|
||||
p = getdouble ();
|
||||
f = mklong (start, "");
|
||||
PF (f, p);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -320,11 +442,15 @@ printf_builtin (list)
|
|||
PRETURN (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
fmt[1] = nextch;
|
||||
modstart[0] = thisch;
|
||||
modstart[1] = nextch;
|
||||
}
|
||||
}
|
||||
while (garglist && garglist != list->next);
|
||||
|
||||
if (conversion_error)
|
||||
retval = EXECUTION_FAILURE;
|
||||
|
||||
PRETURN (retval);
|
||||
}
|
||||
|
||||
|
|
@ -352,10 +478,11 @@ printstr (fmt, string, len, fieldwidth, precision)
|
|||
if (*fmt == '%')
|
||||
fmt++;
|
||||
|
||||
ljust = fw = pr = 0;
|
||||
ljust = fw = 0;
|
||||
pr = -1;
|
||||
|
||||
/* skip flags */
|
||||
while (*fmt == '#' || *fmt == '-' || *fmt == '+' || *fmt == ' ' || *fmt == '0')
|
||||
while (strchr (SKIP1, *fmt))
|
||||
{
|
||||
if (*fmt == '-')
|
||||
ljust = 1;
|
||||
|
|
@ -367,11 +494,16 @@ printstr (fmt, string, len, fieldwidth, precision)
|
|||
{
|
||||
fmt++;
|
||||
fw = fieldwidth;
|
||||
if (fw < 0)
|
||||
{
|
||||
fw = -fw;
|
||||
ljust = 1;
|
||||
}
|
||||
}
|
||||
else if (isdigit (*fmt))
|
||||
else if (DIGIT (*fmt))
|
||||
{
|
||||
fw = *fmt++ - '0';
|
||||
while (isdigit (*fmt))
|
||||
while (DIGIT (*fmt))
|
||||
fw = (fw * 10) + (*fmt++ - '0');
|
||||
}
|
||||
|
||||
|
|
@ -384,10 +516,10 @@ printstr (fmt, string, len, fieldwidth, precision)
|
|||
fmt++;
|
||||
pr = precision;
|
||||
}
|
||||
else if (isdigit (*fmt))
|
||||
else if (DIGIT (*fmt))
|
||||
{
|
||||
pr = *fmt++ - '0';
|
||||
while (isdigit (*fmt))
|
||||
while (DIGIT (*fmt))
|
||||
pr = (pr * 10) + (*fmt++ - '0');
|
||||
}
|
||||
}
|
||||
|
|
@ -402,7 +534,7 @@ printstr (fmt, string, len, fieldwidth, precision)
|
|||
#endif
|
||||
|
||||
/* chars from string to print */
|
||||
nc = (pr > 0 && pr <= len) ? pr : len;
|
||||
nc = (pr >= 0 && pr <= len) ? pr : len;
|
||||
|
||||
padlen = fw - nc;
|
||||
if (padlen < 0)
|
||||
|
|
@ -428,21 +560,6 @@ printstr (fmt, string, len, fieldwidth, precision)
|
|||
recognize `\c' and use that as a string terminator. If we see \c, set
|
||||
*SAWC to 1 before returning. LEN is the length of STRING. */
|
||||
|
||||
#ifdef isoctal
|
||||
#undef isoctal
|
||||
#endif
|
||||
|
||||
#define isoctal(c) ((c) >= '0' && (c) <= '7')
|
||||
|
||||
#define OCTVALUE(c) ((c) - '0')
|
||||
|
||||
#ifndef isxdigit
|
||||
# define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
|
||||
#endif
|
||||
|
||||
#define HEXVALUE(c) \
|
||||
((c) >= 'a' && (c) <= 'f' ? (c)-'a'+10 : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0')
|
||||
|
||||
/* Translate a single backslash-escape sequence starting at ESTART (the
|
||||
character after the backslash) and return the number of characters
|
||||
consumed by the sequence. CP is the place to return the translated
|
||||
|
|
@ -488,32 +605,32 @@ 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++)
|
||||
for (temp = 3, evalue = 0; ISOCTAL (*p) && temp--; p++)
|
||||
evalue = (evalue * 8) + OCTVALUE (*p);
|
||||
*cp = evalue;
|
||||
*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, evalue = c - '0'; ISOCTAL (*p) && temp--; p++)
|
||||
evalue = (evalue * 8) + OCTVALUE (*p);
|
||||
*cp = evalue;
|
||||
*cp = evalue & 0xFF;
|
||||
break;
|
||||
|
||||
/* And, as another extension, we allow \xNNN, where each N is a
|
||||
hex digit. */
|
||||
case 'x':
|
||||
for (temp = 3, evalue = 0; isxdigit (*p) && temp--; p++)
|
||||
for (temp = 2, evalue = 0; ISXDIGIT ((unsigned char)*p) && temp--; p++)
|
||||
evalue = (evalue * 16) + HEXVALUE (*p);
|
||||
if (temp == 3)
|
||||
if (temp == 2)
|
||||
{
|
||||
builtin_error ("missing hex digit for \\x");
|
||||
*cp = '\\';
|
||||
return 0;
|
||||
}
|
||||
*cp = evalue;
|
||||
*cp = evalue & 0xFF;
|
||||
break;
|
||||
|
||||
case '\\': /* \\ -> \ */
|
||||
|
|
@ -561,7 +678,7 @@ bexpand (string, len, sawc, lenp)
|
|||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
ret = xmalloc (len + 1);
|
||||
ret = (char *)xmalloc (len + 1);
|
||||
for (r = ret, s = string; s && *s; )
|
||||
{
|
||||
c = *s++;
|
||||
|
|
@ -589,19 +706,28 @@ bexpand (string, len, sawc, lenp)
|
|||
}
|
||||
|
||||
static char *
|
||||
mklong (str, ch)
|
||||
mklong (str, modifiers)
|
||||
char *str;
|
||||
int ch;
|
||||
char *modifiers;
|
||||
{
|
||||
static char copy[64];
|
||||
int len;
|
||||
size_t len, slen, mlen;
|
||||
|
||||
len = strlen (str) + 2;
|
||||
FASTCOPY (str, copy, len - 3);
|
||||
copy[len - 3] = 'l';
|
||||
copy[len - 2] = ch;
|
||||
copy[len - 1] = '\0';
|
||||
return (copy);
|
||||
slen = strlen (str);
|
||||
mlen = strlen (modifiers);
|
||||
len = slen + mlen + 1;
|
||||
|
||||
if (len > conv_bufsize)
|
||||
{
|
||||
conv_bufsize = (((len + 1023) >> 10) << 10);
|
||||
conv_buf = (char *)xrealloc (conv_buf, conv_bufsize);
|
||||
}
|
||||
|
||||
FASTCOPY (str, conv_buf, slen - 1);
|
||||
FASTCOPY (modifiers, conv_buf + slen - 1, mlen);
|
||||
|
||||
conv_buf[len - 2] = str[slen - 1];
|
||||
conv_buf[len - 1] = '\0';
|
||||
return (conv_buf);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -635,8 +761,7 @@ getint ()
|
|||
{
|
||||
long ret;
|
||||
|
||||
if (getlong (&ret))
|
||||
return (0);
|
||||
ret = getlong ();
|
||||
|
||||
if (ret > INT_MAX)
|
||||
{
|
||||
|
|
@ -652,62 +777,50 @@ getint ()
|
|||
return ((int)ret);
|
||||
}
|
||||
|
||||
static int
|
||||
getlong (lp)
|
||||
long *lp;
|
||||
static long
|
||||
getlong ()
|
||||
{
|
||||
long ret;
|
||||
char *ep;
|
||||
|
||||
if (garglist == 0)
|
||||
{
|
||||
*lp = 0L;
|
||||
return (0);
|
||||
}
|
||||
return (0);
|
||||
|
||||
if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
|
||||
{
|
||||
*lp = (long)asciicode ();
|
||||
return (0);
|
||||
}
|
||||
return asciicode ();
|
||||
|
||||
errno = 0;
|
||||
/* If we use 0 as the third argument, we can handle octal and hex, which
|
||||
legal_number does not. (This was
|
||||
if (legal_number (garglist->word->word, &ret) == 0)
|
||||
) */
|
||||
ret = strtol (garglist->word->word, &ep, 0);
|
||||
if (*ep != '\0')
|
||||
|
||||
if (*ep)
|
||||
{
|
||||
builtin_error ("%s: invalid number", garglist->word->word);
|
||||
return (1);
|
||||
/* 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));
|
||||
|
||||
*lp = ret;
|
||||
garglist = garglist->next;
|
||||
return (0);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
getulong (ulp)
|
||||
unsigned long *ulp;
|
||||
static unsigned long
|
||||
getulong ()
|
||||
{
|
||||
unsigned long ret;
|
||||
char *ep;
|
||||
|
||||
if (garglist == 0)
|
||||
{
|
||||
*ulp = (unsigned long)0;
|
||||
return (0);
|
||||
}
|
||||
return (0);
|
||||
|
||||
if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
|
||||
{
|
||||
*ulp = (unsigned long)asciicode ();
|
||||
return (0);
|
||||
}
|
||||
return asciicode ();
|
||||
|
||||
errno = 0;
|
||||
ret = strtoul (garglist->word->word, &ep, 0);
|
||||
|
|
@ -715,50 +828,205 @@ getulong (ulp)
|
|||
if (*ep)
|
||||
{
|
||||
builtin_error ("%s: invalid number", garglist->word->word);
|
||||
return (1);
|
||||
/* 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));
|
||||
|
||||
*ulp = ret;
|
||||
garglist = garglist->next;
|
||||
return (0);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
getdouble (dp)
|
||||
double *dp;
|
||||
#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 ()
|
||||
{
|
||||
intmax_t ret;
|
||||
char *ep;
|
||||
|
||||
if (garglist == 0)
|
||||
return (0);
|
||||
|
||||
if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
|
||||
return asciicode ();
|
||||
|
||||
errno = 0;
|
||||
ret = strtoimax (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 uintmax_t
|
||||
getuintmax ()
|
||||
{
|
||||
uintmax_t ret;
|
||||
char *ep;
|
||||
|
||||
if (garglist == 0)
|
||||
return (0);
|
||||
|
||||
if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
|
||||
return asciicode ();
|
||||
|
||||
errno = 0;
|
||||
ret = strtoumax (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);
|
||||
}
|
||||
|
||||
static double
|
||||
getdouble ()
|
||||
{
|
||||
double ret;
|
||||
char *ep;
|
||||
|
||||
if (garglist == 0)
|
||||
{
|
||||
*dp = (double)0;
|
||||
return (0);
|
||||
}
|
||||
return (0);
|
||||
|
||||
if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
|
||||
{
|
||||
*dp = (double)asciicode ();
|
||||
return (0);
|
||||
}
|
||||
return asciicode ();
|
||||
|
||||
errno = 0;
|
||||
ret = strtod (garglist->word->word, &ep);
|
||||
|
||||
if (*ep)
|
||||
{
|
||||
builtin_error ("%s: invalid number", garglist->word->word);
|
||||
return (1);
|
||||
/* 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));
|
||||
|
||||
*dp = ret;
|
||||
garglist = garglist->next;
|
||||
return (0);
|
||||
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