mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
cleanup: remove buggy str2int, replace with a template
remove one str->int implementation (we still have 10+ more), replace with a convenience template that calls my_strntoll_8bit()
This commit is contained in:
@@ -5389,7 +5389,7 @@ static int com_status(String *, char *)
|
||||
ulong sec;
|
||||
/* print label */
|
||||
tee_fprintf(stdout, "%.*s\t\t\t", (int) (pos-status_str), status_str);
|
||||
if ((status_str= str2int(pos,10,0,LONG_MAX,(long*) &sec)))
|
||||
if ((status_str= str2int(pos,INT16_MAX, 10, &sec)))
|
||||
{
|
||||
nice_time((double) sec,buff, sizeof(buff),0);
|
||||
tee_puts(buff, stdout); /* print nice time */
|
||||
|
||||
@@ -791,7 +791,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
|
||||
pos= (char*) strchr(status,' ');
|
||||
*pos++=0;
|
||||
printf("%s\t\t\t",status); /* print label */
|
||||
if ((status=str2int(pos,10,0,LONG_MAX,(long*) &sec)))
|
||||
if ((status=str2int(pos,1000,10,&sec)))
|
||||
{
|
||||
nice_time(sec,buff);
|
||||
puts(buff); /* print nice time */
|
||||
|
||||
@@ -3228,7 +3228,7 @@ set_result_format_version(ulong new_version)
|
||||
static void
|
||||
do_result_format_version(struct st_command *command)
|
||||
{
|
||||
long version;
|
||||
uint version;
|
||||
static DYNAMIC_STRING ds_version;
|
||||
const struct command_arg result_format_args[] = {
|
||||
{"version", ARG_STRING, TRUE, &ds_version, "Version to use"}
|
||||
@@ -3242,7 +3242,7 @@ do_result_format_version(struct st_command *command)
|
||||
',');
|
||||
|
||||
/* Convert version number to int */
|
||||
if (!str2int(ds_version.str, 10, (long) 0, (long) INT_MAX, &version))
|
||||
if (!str2int(ds_version.str, ds_version.length, 10, &version))
|
||||
die("Invalid version number: '%s'", ds_version.str);
|
||||
|
||||
set_result_format_version(version);
|
||||
@@ -3279,7 +3279,7 @@ do_result_format_version(struct st_command *command)
|
||||
|
||||
void var_set_query_get_value(struct st_command *command, VAR *var)
|
||||
{
|
||||
long row_no;
|
||||
uint row_no;
|
||||
int col_no= -1;
|
||||
MYSQL_RES* UNINIT_VAR(res);
|
||||
MYSQL* mysql= cur_con->mysql;
|
||||
@@ -3311,9 +3311,9 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
|
||||
DBUG_PRINT("info", ("col: %s", ds_col.str));
|
||||
|
||||
/* Convert row number to int */
|
||||
if (!str2int(ds_row.str, 10, (long) 0, (long) INT_MAX, &row_no))
|
||||
if (!str2int(ds_row.str, ds_row.length, 10, &row_no))
|
||||
die("Invalid row number: '%s'", ds_row.str);
|
||||
DBUG_PRINT("info", ("row: %s, row_no: %ld", ds_row.str, row_no));
|
||||
DBUG_PRINT("info", ("row: %s, row_no: %u", ds_row.str, row_no));
|
||||
dynstr_free(&ds_row);
|
||||
|
||||
/* Remove any surrounding "'s from the query - if there is any */
|
||||
@@ -3373,7 +3373,7 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
|
||||
{
|
||||
/* Get the value */
|
||||
MYSQL_ROW row;
|
||||
long rows= 0;
|
||||
uint rows= 0;
|
||||
const char* value= "No such row";
|
||||
|
||||
while ((row= mysql_fetch_row(res)))
|
||||
@@ -3381,7 +3381,7 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
|
||||
if (++rows == row_no)
|
||||
{
|
||||
|
||||
DBUG_PRINT("info", ("At row %ld, column %d is '%s'",
|
||||
DBUG_PRINT("info", ("At row %u, column %d is '%s'",
|
||||
row_no, col_no, row[col_no]));
|
||||
/* Found the row to get */
|
||||
if (row[col_no])
|
||||
@@ -4359,7 +4359,7 @@ void do_move_file(struct st_command *command)
|
||||
|
||||
void do_chmod_file(struct st_command *command)
|
||||
{
|
||||
long mode= 0;
|
||||
uint mode= 0;
|
||||
int err_code;
|
||||
static DYNAMIC_STRING ds_mode;
|
||||
static DYNAMIC_STRING ds_file;
|
||||
@@ -4379,10 +4379,10 @@ void do_chmod_file(struct st_command *command)
|
||||
|
||||
/* Parse what mode to set */
|
||||
if (ds_mode.length != 4 ||
|
||||
str2int(ds_mode.str, 8, 0, INT_MAX, &mode) == NullS)
|
||||
str2int(ds_mode.str, ds_mode.length, 8, &mode) == NullS)
|
||||
die("You must write a 4 digit octal number for mode");
|
||||
|
||||
DBUG_PRINT("info", ("chmod %o %s", (uint)mode, ds_file.str));
|
||||
DBUG_PRINT("info", ("chmod %o %s", mode, ds_file.str));
|
||||
err_code= chmod(ds_file.str, mode);
|
||||
if (err_code < 0)
|
||||
err_code= 1;
|
||||
@@ -8430,7 +8430,7 @@ void do_get_errcodes(struct st_command *command)
|
||||
}
|
||||
else
|
||||
{
|
||||
long val;
|
||||
uint val;
|
||||
char *start= p;
|
||||
/* Check that the string passed to str2int only contain digits */
|
||||
while (*p && p != end)
|
||||
@@ -8443,10 +8443,10 @@ void do_get_errcodes(struct st_command *command)
|
||||
}
|
||||
|
||||
/* Convert the string to int */
|
||||
if (!str2int(start, 10, (long) INT_MIN, (long) INT_MAX, &val))
|
||||
if (!str2int(start, p - start, 10, &val))
|
||||
die("Invalid argument to error: '%s'", command->first_argument);
|
||||
|
||||
to->code.errnum= (uint) val;
|
||||
to->code.errnum= val;
|
||||
to->type= ERR_ERRNO;
|
||||
DBUG_PRINT("info", ("ERR_ERRNO: %d", to->code.errnum));
|
||||
}
|
||||
|
||||
@@ -2076,9 +2076,30 @@ public:
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C++" {
|
||||
template<typename T> inline char *str2int(const char *s, size_t l, int base, T *val)
|
||||
{
|
||||
char *end= const_cast<char*>(s) + l;
|
||||
int err;
|
||||
longlong v= my_strntoll_8bit(&my_charset_latin1, s, l, base, &end, &err);
|
||||
if (!err && static_cast<longlong>(*val= static_cast<T>(v)) != v)
|
||||
err= EDOM;
|
||||
return (errno= err) ? NULL : end;
|
||||
}
|
||||
|
||||
template<> inline char *str2int<ulonglong>(const char *s, size_t l, int base, ulonglong *val)
|
||||
{
|
||||
char *end= const_cast<char*>(s) + l;
|
||||
int err;
|
||||
*val= my_strntoull_8bit(&my_charset_latin1, s, l, base, &end, &err);
|
||||
return (errno= err) ? NULL : end;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _m_ctype_h */
|
||||
|
||||
@@ -163,8 +163,6 @@ extern char *ullstr(longlong value,char *buff);
|
||||
|
||||
extern char *int2str(long val, char *dst, int radix, int upcase);
|
||||
extern char *int10_to_str(long val,char *dst,int radix);
|
||||
extern char *str2int(const char *src,int radix,long lower,long upper,
|
||||
long *val);
|
||||
longlong my_strtoll10(const char *nptr, char **endptr, int *error);
|
||||
#if SIZEOF_LONG == SIZEOF_LONG_LONG
|
||||
#define ll2str(A,B,C,D) int2str((A),(B),(C),(D))
|
||||
|
||||
@@ -62,12 +62,14 @@ ulonglong my_thread_stack_size= (sizeof(void*) <= 4)? 65536: ((256-16)*1024);
|
||||
|
||||
static mode_t atoi_octal(const char *str)
|
||||
{
|
||||
long int tmp;
|
||||
long long tmp;
|
||||
int err;
|
||||
while (*str && my_isspace(&my_charset_latin1, *str))
|
||||
str++;
|
||||
str2int(str,
|
||||
(*str == '0' ? 8 : 10), /* Octalt or decimalt */
|
||||
0, INT_MAX, &tmp);
|
||||
tmp= my_strntoul_8bit(&my_charset_latin1, str, strlen(str),
|
||||
(*str == '0' ? 8 : 10), /* Octal or decimal */
|
||||
NULL, &err);
|
||||
|
||||
return (mode_t) tmp;
|
||||
}
|
||||
|
||||
|
||||
@@ -295,7 +295,7 @@ private:
|
||||
bool
|
||||
load_from_file(const Mem_fn *values, size_t size, size_t default_line_count)
|
||||
{
|
||||
long val;
|
||||
int val;
|
||||
/**
|
||||
The first row is temporarily stored in the first value. If it is a line
|
||||
count and not a log name (new format), the second row will overwrite it.
|
||||
@@ -303,7 +303,7 @@ private:
|
||||
auto &line1= dynamic_cast<String_value<> &>(values[0](this));
|
||||
if (line1.load_from(&file))
|
||||
return true;
|
||||
char *end= str2int(line1.buf, 10, 0, INT32_MAX, &val);
|
||||
char *end= str2int(line1.buf, sizeof(line1.buf), 10, &val);
|
||||
/**
|
||||
If this first line was not a number - the line count,
|
||||
then it was the first value for real,
|
||||
|
||||
@@ -249,7 +249,7 @@ struct Master_info_file: Info_file
|
||||
|
||||
bool load_from(IO_CACHE *file) override
|
||||
{
|
||||
long count;
|
||||
int count;
|
||||
size_t i;
|
||||
/// +1 for the terminating delimiter
|
||||
char buf[Int_IO_CACHE::BUF_SIZE<uint32_t> + 1];
|
||||
@@ -262,13 +262,13 @@ struct Master_info_file: Info_file
|
||||
if (c == /* End of Line */ '\n' || c == /* End of Count */ ' ')
|
||||
break;
|
||||
}
|
||||
char *end= str2int(buf, 10, 1, INT32_MAX, &count);
|
||||
char *end= str2int(buf, i, 10, &count);
|
||||
// Reserve enough elements ahead of time.
|
||||
if (!end || allocate_dynamic(&array, count))
|
||||
if (!end || count<0 || allocate_dynamic(&array, count))
|
||||
return true;
|
||||
while (count--)
|
||||
{
|
||||
long value;
|
||||
int value;
|
||||
/*
|
||||
Check that the previous number ended with a ` `,
|
||||
not `\n` or anything else.
|
||||
@@ -288,8 +288,8 @@ struct Master_info_file: Info_file
|
||||
if (c == /* End of Count */ ' ' || c == /* End of Line */ '\n')
|
||||
break;
|
||||
}
|
||||
end= str2int(buf, 10, 1, INT32_MAX, &value);
|
||||
if (!end)
|
||||
end= str2int(buf, i, 10, &value);
|
||||
if (!end || value <= 0)
|
||||
return true;
|
||||
ulong id= value;
|
||||
bool oom= insert_dynamic(&array, (uchar *)&id);
|
||||
|
||||
12
sql/slave.cc
12
sql/slave.cc
@@ -902,8 +902,8 @@ bool init_slave_skip_errors(const char* arg)
|
||||
}
|
||||
for (p= arg ; *p; )
|
||||
{
|
||||
long err_code;
|
||||
if (!(p= str2int(p, 10, 0, LONG_MAX, &err_code)))
|
||||
uint err_code;
|
||||
if (!(p= str2int(p, INT16_MAX, 10, &err_code)))
|
||||
break;
|
||||
if (err_code < MAX_SLAVE_ERROR)
|
||||
{
|
||||
@@ -915,7 +915,7 @@ bool init_slave_skip_errors(const char* arg)
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmap_set_bit(&slave_error_mask,(uint)err_code);
|
||||
bitmap_set_bit(&slave_error_mask,err_code);
|
||||
}
|
||||
}
|
||||
while (!my_isdigit(system_charset_info,*p) && *p)
|
||||
@@ -975,7 +975,7 @@ static constexpr uint DEFAULT_SLAVE_RETRY_ERRORS= 10;
|
||||
bool init_slave_transaction_retry_errors(const char* arg)
|
||||
{
|
||||
const char *p;
|
||||
long err_code;
|
||||
int err_code;
|
||||
uint i;
|
||||
DBUG_ENTER("init_slave_transaction_retry_errors");
|
||||
|
||||
@@ -988,7 +988,7 @@ bool init_slave_transaction_retry_errors(const char* arg)
|
||||
/* empty */;
|
||||
for (p= arg; *p; )
|
||||
{
|
||||
if (!(p= str2int(p, 10, 0, LONG_MAX, &err_code)))
|
||||
if (!(p= str2int(p, INT16_MAX, 10, &err_code)))
|
||||
break;
|
||||
slave_transaction_retry_error_length++;
|
||||
while (!my_isdigit(system_charset_info,*p) && *p)
|
||||
@@ -1020,7 +1020,7 @@ bool init_slave_transaction_retry_errors(const char* arg)
|
||||
/* Add user codes after this */
|
||||
for (p= arg, i= DEFAULT_SLAVE_RETRY_ERRORS; *p; )
|
||||
{
|
||||
if (!(p= str2int(p, 10, 0, LONG_MAX, &err_code)))
|
||||
if (!(p= str2int(p, INT16_MAX, 10, &err_code)))
|
||||
break;
|
||||
if (err_code > 0)
|
||||
slave_transaction_retry_errors[i++]= (uint) err_code;
|
||||
|
||||
@@ -5386,19 +5386,20 @@ static ACL_USER_BASE *find_acl_user_base(const LEX_CSTRING &user,
|
||||
|
||||
static const char *calc_ip(const char *ip, long *val, char end)
|
||||
{
|
||||
long ip_val,tmp;
|
||||
if (!(ip=str2int(ip,10,0,255,&ip_val)) || *ip != '.')
|
||||
long ip_val;
|
||||
uchar tmp;
|
||||
if (!(ip=str2int(ip,INT16_MAX,10,&tmp)) || *ip != '.')
|
||||
return 0;
|
||||
ip_val<<=24;
|
||||
if (!(ip=str2int(ip+1,10,0,255,&tmp)) || *ip != '.')
|
||||
ip_val=tmp;
|
||||
if (!(ip=str2int(ip+1,INT16_MAX,10,&tmp)) || *ip != '.')
|
||||
return 0;
|
||||
ip_val+=tmp<<16;
|
||||
if (!(ip=str2int(ip+1,10,0,255,&tmp)) || *ip != '.')
|
||||
ip_val=ip_val*256 + tmp;
|
||||
if (!(ip=str2int(ip+1,INT16_MAX,10,&tmp)) || *ip != '.')
|
||||
return 0;
|
||||
ip_val+=tmp<<8;
|
||||
if (!(ip=str2int(ip+1,10,0,255,&tmp)) || *ip != end)
|
||||
ip_val=ip_val*256 + tmp;
|
||||
if (!(ip=str2int(ip+1,INT16_MAX,10,&tmp)) || *ip != end)
|
||||
return 0;
|
||||
*val=ip_val+tmp;
|
||||
*val= ip_val*256 + tmp;
|
||||
return ip;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ SET(STRINGS_SOURCES bchange.c bmove_upp.c ctype-big5.c ctype-bin.c ctype-cp932.c
|
||||
ctype-ucs2.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype.c decimal.c dtoa.c int2str.c
|
||||
ctype-unidata.c
|
||||
is_prefix.c llstr.c longlong2str.c my_strtoll10.c my_vsnprintf.c
|
||||
str2int.c strcend.c strend.c strfill.c strmake.c strnmov.c
|
||||
strcend.c strend.c strfill.c strmake.c strnmov.c
|
||||
strxmov.c strxnmov.c xml.c
|
||||
strmov_overlapp.c
|
||||
my_strchr.c strcont.c strappend.c json_lib.c json_normalize.c
|
||||
|
||||
@@ -1,213 +0,0 @@
|
||||
/* Copyright (c) 2000 TXT DataKonsult Ab & Monty Program Ab
|
||||
Copyright (c) 2009-2011, Monty Program Ab
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
str2int(src, radix, lower, upper, &val)
|
||||
converts the string pointed to by src to an integer and stores it in
|
||||
val. It skips leading spaces and tabs (but not newlines, formfeeds,
|
||||
backspaces), then it accepts an optional sign and a sequence of digits
|
||||
in the specified radix. The result should satisfy lower <= *val <= upper.
|
||||
The result is a pointer to the first character after the number;
|
||||
trailing spaces will NOT be skipped.
|
||||
|
||||
If an error is detected, the result will be NullS, the value put
|
||||
in val will be 0, and errno will be set to
|
||||
EDOM if there are no digits
|
||||
ERANGE if the result would overflow or otherwise fail to lie
|
||||
within the specified bounds.
|
||||
Check that the bounds are right for your machine.
|
||||
This looks amazingly complicated for what you probably thought was an
|
||||
easy task. Coping with integer overflow and the asymmetric range of
|
||||
twos complement machines is anything but easy.
|
||||
|
||||
So that users of atoi and atol can check whether an error occurred,
|
||||
I have taken a wholly unprecedented step: errno is CLEARED if this
|
||||
call has no problems.
|
||||
*/
|
||||
|
||||
#include "strings_def.h"
|
||||
#include <m_ctype.h>
|
||||
#include "my_sys.h" /* defines errno */
|
||||
#include <errno.h>
|
||||
|
||||
#define char_val(X, Y) (X >= '0' && X <= '9' ? X-'0' :\
|
||||
X >= 'A' && X <= 'Z' ? X-'A'+10 :\
|
||||
X >= 'a' && X <= 'z' ? (Y <= 36 ? X-'a'+10 : X-'a'+36) :\
|
||||
'\177')
|
||||
|
||||
char *str2int(register const char *src, register int radix, long int lower,
|
||||
long int upper, long int *val)
|
||||
{
|
||||
int sign; /* is number negative (+1) or positive (-1) */
|
||||
int n; /* number of digits yet to be converted */
|
||||
long limit; /* "largest" possible valid input */
|
||||
long scale; /* the amount to multiply next digit by */
|
||||
long sofar; /* the running value */
|
||||
register int d; /* (negative of) next digit */
|
||||
char *start;
|
||||
int digits[32]; /* Room for numbers */
|
||||
|
||||
/* Make sure *val is sensible in case of error */
|
||||
|
||||
*val = 0;
|
||||
|
||||
/* Check that the radix is in the range 2..62 */
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
if (radix < 2 || radix > 62) {
|
||||
errno=EDOM;
|
||||
return NullS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The basic problem is: how do we handle the conversion of
|
||||
a number without resorting to machine-specific code to
|
||||
check for overflow? Obviously, we have to ensure that
|
||||
no calculation can overflow. We are guaranteed that the
|
||||
"lower" and "upper" arguments are valid machine integers.
|
||||
On sign-and-magnitude, twos-complement, and ones-complement
|
||||
machines all, if +|n| is representable, so is -|n|, but on
|
||||
twos complement machines the converse is not true. So the
|
||||
"maximum" representable number has a negative representative.
|
||||
Limit is set to MY_MIN(-|lower|,-|upper|); this is the "largest"
|
||||
number we are concerned with. */
|
||||
|
||||
/* Calculate Limit using Scale as a scratch variable */
|
||||
|
||||
if ((limit = lower) > 0) limit = -limit;
|
||||
if ((scale = upper) > 0) scale = -scale;
|
||||
if (scale < limit) limit = scale;
|
||||
|
||||
/* Skip leading spaces and check for a sign.
|
||||
Note: because on a 2s complement machine MinLong is a valid
|
||||
integer but |MinLong| is not, we have to keep the current
|
||||
converted value (and the scale!) as *negative* numbers,
|
||||
so the sign is the opposite of what you might expect.
|
||||
*/
|
||||
while (my_isspace(&my_charset_latin1,*src)) src++;
|
||||
sign = -1;
|
||||
if (*src == '+') src++; else
|
||||
if (*src == '-') src++, sign = 1;
|
||||
|
||||
/* Skip leading zeros so that we never compute a power of radix
|
||||
in scale that we won't have a need for. Otherwise sticking
|
||||
enough 0s in front of a number could cause the multiplication
|
||||
to overflow when it neededn't.
|
||||
*/
|
||||
start=(char*) src;
|
||||
while (*src == '0') src++;
|
||||
|
||||
/* Move over the remaining digits. We have to convert from left
|
||||
to left in order to avoid overflow. Answer is after last digit.
|
||||
*/
|
||||
|
||||
for (n = 0; (digits[n]=char_val(*src, radix)) < radix && n < 20; n++,src++) ;
|
||||
|
||||
/* Check that there is at least one digit */
|
||||
|
||||
if (start == src) {
|
||||
errno=EDOM;
|
||||
return NullS;
|
||||
}
|
||||
|
||||
/* The invariant we want to maintain is that src is just
|
||||
to the right of n digits, we've converted k digits to
|
||||
sofar, scale = -radix**k, and scale < sofar < 0. Now
|
||||
if the final number is to be within the original
|
||||
Limit, we must have (to the left)*scale+sofar >= Limit,
|
||||
or (to the left)*scale >= Limit-sofar, i.e. the digits
|
||||
to the left of src must form an integer <= (Limit-sofar)/(scale).
|
||||
In particular, this is true of the next digit. In our
|
||||
incremental calculation of Limit,
|
||||
|
||||
IT IS VITAL that (-|N|)/(-|D|) = |N|/|D|
|
||||
*/
|
||||
|
||||
for (sofar = 0, scale = -1; --n >= 1;)
|
||||
{
|
||||
if ((long) -(d=digits[n]) < limit) {
|
||||
errno=ERANGE;
|
||||
return NullS;
|
||||
}
|
||||
limit = (limit+d)/radix, sofar += d*scale; scale *= radix;
|
||||
}
|
||||
if (n == 0)
|
||||
{
|
||||
if ((long) -(d=digits[n]) < limit) /* get last digit */
|
||||
{
|
||||
errno=ERANGE;
|
||||
return NullS;
|
||||
}
|
||||
sofar+=d*scale;
|
||||
}
|
||||
|
||||
/* Now it might still happen that sofar = -32768 or its equivalent,
|
||||
so we can't just multiply by the sign and check that the result
|
||||
is in the range lower..upper. All of this caution is a right
|
||||
pain in the neck. If only there were a standard routine which
|
||||
says generate thus and such a signal on integer overflow...
|
||||
But not enough machines can do it *SIGH*.
|
||||
*/
|
||||
if (sign < 0)
|
||||
{
|
||||
if (sofar < -LONG_MAX || (sofar= -sofar) > upper)
|
||||
{
|
||||
errno=ERANGE;
|
||||
return NullS;
|
||||
}
|
||||
}
|
||||
else if (sofar < lower)
|
||||
{
|
||||
errno=ERANGE;
|
||||
return NullS;
|
||||
}
|
||||
*val = sofar;
|
||||
errno=0; /* indicate that all went well */
|
||||
return (char*) src;
|
||||
}
|
||||
|
||||
/* These are so slow compared with ordinary, optimized atoi */
|
||||
|
||||
#ifdef WANT_OUR_ATOI
|
||||
|
||||
int atoi(const char *src)
|
||||
{
|
||||
long val;
|
||||
str2int(src, 10, (long) INT_MIN, (long) INT_MAX, &val);
|
||||
return (int) val;
|
||||
}
|
||||
|
||||
|
||||
long atol(const char *src)
|
||||
{
|
||||
long val;
|
||||
str2int(src, 10, LONG_MIN, LONG_MAX, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
#endif /* WANT_OUR_ATOI */
|
||||
Reference in New Issue
Block a user