diff --git a/library/changes b/library/changes index fedd9e1..b23ef46 100644 --- a/library/changes +++ b/library/changes @@ -1,3 +1,25 @@ +- strtoimax(), strtoumax(), strtod(), strtof(), strtol(), strtoll(), + strtoul() and strtoull() now count how many digits were converted. + If that number is zero, then the conversion is considered to have + failed: 0 is returned, errno is set to ERANGE and the 'ptr' parameter + reference is initialized with a pointer to the string to be converted. + This has two consequences: + + 1) A floating point number that has no digits in the significand + is no longer converted to zero. For example ".e10" can no longer + result in a successful conversion. + + 2) You can detect if a conversion is successful by comparing pointers + after the conversion function has returned: + + char * str; + char * ptr; + long n; + + n = strtol(str,&ptr,10); + if(n == 0 && str == ptr) + printf("conversion has failed"); + - Following detection of a stack overflow, the startup code eventually called _exit(). It should have called exit() instead. diff --git a/library/inttypes_strtoimax.c b/library/inttypes_strtoimax.c index 90a43e7..cb01151 100644 --- a/library/inttypes_strtoimax.c +++ b/library/inttypes_strtoimax.c @@ -1,5 +1,5 @@ /* - * $Id: inttypes_strtoimax.c,v 1.1 2005-05-12 13:21:43 obarthel Exp $ + * $Id: inttypes_strtoimax.c,v 1.2 2005-09-28 09:28:39 obarthel Exp $ * * :ts=4 * @@ -46,6 +46,8 @@ intmax_t strtoimax(const char *str, char **ptr, int base) { + const char * stop = str; + size_t num_digits_converted = 0; BOOL is_negative; intmax_t result = 0; intmax_t new_sum; @@ -172,20 +174,31 @@ strtoimax(const char *str, char **ptr, int base) str++; c = (*str); + + num_digits_converted++; } } + /* Did we convert anything? */ + if(num_digits_converted == 0) + { + __set_errno(ERANGE); + goto out; + } + if(is_negative) result = (-sum); else result = sum; + stop = str; + out: /* If desired, remember where we stopped reading the number from the buffer. */ if(ptr != NULL) - (*ptr) = (char *)str; + (*ptr) = (char *)stop; RETURN(result); return(result); diff --git a/library/inttypes_strtoumax.c b/library/inttypes_strtoumax.c index 77e9dd0..acaa3d1 100644 --- a/library/inttypes_strtoumax.c +++ b/library/inttypes_strtoumax.c @@ -1,5 +1,5 @@ /* - * $Id: inttypes_strtoumax.c,v 1.1 2005-05-12 13:21:43 obarthel Exp $ + * $Id: inttypes_strtoumax.c,v 1.2 2005-09-28 09:28:39 obarthel Exp $ * * :ts=4 * @@ -46,6 +46,8 @@ uintmax_t strtoumax(const char *str, char **ptr, int base) { + const char * stop = str; + size_t num_digits_converted = 0; BOOL is_negative; uintmax_t result = 0; uintmax_t new_sum; @@ -169,9 +171,22 @@ strtoumax(const char *str, char **ptr, int base) str++; c = (*str); + + /* Remember where the conversion stopped and + that we converted something. */ + stop = str; + + num_digits_converted++; } } + /* Did we convert anything? */ + if(num_digits_converted == 0) + { + __set_errno(ERANGE); + goto out; + } + if(is_negative) result = (-sum); else @@ -182,7 +197,7 @@ strtoumax(const char *str, char **ptr, int base) /* If desired, remember where we stopped reading the number from the buffer. */ if(ptr != NULL) - (*ptr) = (char *)str; + (*ptr) = (char *)stop; RETURN(result); return(result); diff --git a/library/stdlib_strtod.c b/library/stdlib_strtod.c index 750e584..be71d0a 100644 --- a/library/stdlib_strtod.c +++ b/library/stdlib_strtod.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_strtod.c,v 1.8 2005-05-29 08:19:36 obarthel Exp $ + * $Id: stdlib_strtod.c,v 1.9 2005-09-28 09:28:39 obarthel Exp $ * * :ts=4 * @@ -66,6 +66,7 @@ double strtod(const char *str, char ** ptr) { + const char * stop = str; double sum = 0.0; double result; int is_negative; @@ -128,6 +129,8 @@ strtod(const char *str, char ** ptr) str += strlen(str); sum = __inf(); + + stop = str; } else if (strncasecmp(str,"nan",3) == SAME && (str[3] == '(' || str[3] == '\0')) { @@ -146,9 +149,12 @@ strtod(const char *str, char ** ptr) } sum = nan(NULL); + + stop = str; } else { + size_t num_digits_converted = 0; int decimal_point_matches; double new_sum; int error = 0; @@ -191,6 +197,8 @@ strtod(const char *str, char ** ptr) else sum = new_sum; } + + num_digits_converted++; } /* Did we find the decimal point? We accept both the @@ -258,6 +266,8 @@ strtod(const char *str, char ** ptr) divisor = divisor / radix; } + + num_digits_converted++; } } @@ -352,11 +362,22 @@ strtod(const char *str, char ** ptr) } } - if(error != 0) + if(num_digits_converted == 0) { - __set_errno(error); + __set_errno(ERANGE); - sum = __get_huge_val(); + sum = 0; + } + else + { + if(error != 0) + { + __set_errno(error); + + sum = __get_huge_val(); + } + + stop = str; } } @@ -365,12 +386,12 @@ strtod(const char *str, char ** ptr) result = sum; + out: + /* If desired, remember where we stopped reading the number from the buffer. */ if(ptr != NULL) - (*ptr) = (char *)str; - - out: + (*ptr) = (char *)stop; RETURN(result); return(result); diff --git a/library/stdlib_strtof.c b/library/stdlib_strtof.c index 1f487da..ad3aa38 100644 --- a/library/stdlib_strtof.c +++ b/library/stdlib_strtof.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_strtof.c,v 1.8 2005-05-30 18:28:45 obarthel Exp $ + * $Id: stdlib_strtof.c,v 1.9 2005-09-28 09:28:39 obarthel Exp $ * * :ts=4 * @@ -66,6 +66,7 @@ float strtof(const char *str, char ** ptr) { + const char * stop = str; float sum = 0.0; float result; int is_negative; @@ -128,6 +129,8 @@ strtof(const char *str, char ** ptr) str += strlen(str); sum = __inff(); + + stop = str; } else if (strncasecmp(str,"nan",3) == SAME && (str[3] == '(' || str[3] == '\0')) { @@ -146,9 +149,12 @@ strtof(const char *str, char ** ptr) } sum = nanf(NULL); + + stop = str; } else { + size_t num_digits_converted = 0; int decimal_point_matches; float new_sum; int error = 0; @@ -183,6 +189,8 @@ strtof(const char *str, char ** ptr) str++; + num_digits_converted++; + if(error == 0) { new_sum = (radix * sum) + c; @@ -248,6 +256,8 @@ strtof(const char *str, char ** ptr) str++; + num_digits_converted++; + if(error == 0 && divisor != 0.0) { new_sum = sum + c * divisor; @@ -352,11 +362,22 @@ strtof(const char *str, char ** ptr) } } - if(error != 0) + if(num_digits_converted == 0) { - __set_errno(error); + __set_errno(ERANGE); - sum = __get_huge_valf(); + sum = 0; + } + else + { + stop = str; + + if(error != 0) + { + __set_errno(error); + + sum = __get_huge_valf(); + } } } @@ -365,12 +386,12 @@ strtof(const char *str, char ** ptr) result = sum; + out: + /* If desired, remember where we stopped reading the number from the buffer. */ if(ptr != NULL) - (*ptr) = (char *)str; - - out: + (*ptr) = (char *)stop; RETURN(result); return(result); diff --git a/library/stdlib_strtol.c b/library/stdlib_strtol.c index e978d51..fc24b14 100644 --- a/library/stdlib_strtol.c +++ b/library/stdlib_strtol.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_strtol.c,v 1.3 2005-02-03 16:56:17 obarthel Exp $ + * $Id: stdlib_strtol.c,v 1.4 2005-09-28 09:28:39 obarthel Exp $ * * :ts=4 * @@ -46,6 +46,8 @@ long strtol(const char *str, char **ptr, int base) { + const char * stop = str; + size_t num_digits_converted = 0; BOOL is_negative; long result = 0; long new_sum; @@ -103,8 +105,7 @@ strtol(const char *str, char **ptr, int base) is_negative = FALSE; /* But there may be a sign we will choose to - * ignore. - */ + ignore. */ if(c == '+') str++; } @@ -112,8 +113,7 @@ strtol(const char *str, char **ptr, int base) c = (*str); /* There may be a leading '0x' to indicate that what - * follows is a hexadecimal number. - */ + follows is a hexadecimal number. */ if(base == 0 || base == 16) { if((c == '0') && (str[1] == 'x' || str[1] == 'X')) @@ -127,9 +127,8 @@ strtol(const char *str, char **ptr, int base) } /* If we still don't know what base to use and the - * next letter to follow is a zero then this is - * probably a number in octal notation. - */ + next letter to follow is a zero then this is + probably a number in octal notation. */ if(base == 0) { if(c == '0') @@ -175,21 +174,31 @@ strtol(const char *str, char **ptr, int base) str++; c = (*str); + + num_digits_converted++; } } + /* Did we convert anything? */ + if(num_digits_converted == 0) + { + __set_errno(ERANGE); + goto out; + } + if(is_negative) result = (-sum); else result = sum; + stop = str; + out: /* If desired, remember where we stopped reading the - * number from the buffer. - */ + number from the buffer. */ if(ptr != NULL) - (*ptr) = (char *)str; + (*ptr) = (char *)stop; RETURN(result); return(result); diff --git a/library/stdlib_strtoll.c b/library/stdlib_strtoll.c index 59570a1..a6859eb 100644 --- a/library/stdlib_strtoll.c +++ b/library/stdlib_strtoll.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_strtoll.c,v 1.3 2005-02-03 16:56:17 obarthel Exp $ + * $Id: stdlib_strtoll.c,v 1.4 2005-09-28 09:28:39 obarthel Exp $ * * :ts=4 * @@ -50,6 +50,8 @@ long long strtoll(const char *str, char **ptr, int base) { + const char * stop = str; + size_t num_digits_converted = 0; BOOL is_negative; long long result = 0; long long new_sum; @@ -107,8 +109,7 @@ strtoll(const char *str, char **ptr, int base) is_negative = FALSE; /* But there may be a sign we will choose to - * ignore. - */ + ignore. */ if(c == '+') str++; } @@ -116,8 +117,7 @@ strtoll(const char *str, char **ptr, int base) c = (*str); /* There may be a leading '0x' to indicate that what - * follows is a hexadecimal number. - */ + follows is a hexadecimal number. */ if(base == 0 || base == 16) { if((c == '0') && (str[1] == 'x' || str[1] == 'X')) @@ -131,9 +131,8 @@ strtoll(const char *str, char **ptr, int base) } /* If we still don't know what base to use and the - * next letter to follow is a zero then this is - * probably a number in octal notation. - */ + next letter to follow is a zero then this is + probably a number in octal notation. */ if(base == 0) { if(c == '0') @@ -179,21 +178,31 @@ strtoll(const char *str, char **ptr, int base) str++; c = (*str); + + num_digits_converted++; } } + /* Did we convert anything? */ + if(num_digits_converted == 0) + { + __set_errno(ERANGE); + goto out; + } + if(is_negative) result = (-sum); else result = sum; + stop = str; + out: /* If desired, remember where we stopped reading the - * number from the buffer. - */ + number from the buffer. */ if(ptr != NULL) - (*ptr) = (char *)str; + (*ptr) = (char *)stop; RETURN(result); return(result); diff --git a/library/stdlib_strtoul.c b/library/stdlib_strtoul.c index 4f8f596..0a337c7 100644 --- a/library/stdlib_strtoul.c +++ b/library/stdlib_strtoul.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_strtoul.c,v 1.3 2005-02-03 16:56:17 obarthel Exp $ + * $Id: stdlib_strtoul.c,v 1.4 2005-09-28 09:28:39 obarthel Exp $ * * :ts=4 * @@ -46,6 +46,8 @@ unsigned long strtoul(const char *str, char **ptr, int base) { + const char * stop = str; + size_t num_digits_converted = 0; BOOL is_negative; unsigned long result = 0; unsigned long new_sum; @@ -103,8 +105,7 @@ strtoul(const char *str, char **ptr, int base) is_negative = FALSE; /* But there may be a sign we will choose to - * ignore. - */ + ignore. */ if(c == '+') str++; } @@ -112,8 +113,7 @@ strtoul(const char *str, char **ptr, int base) c = (*str); /* There may be a leading '0x' to indicate that what - * follows is a hexadecimal number. - */ + follows is a hexadecimal number. */ if(base == 0 || base == 16) { if((c == '0') && (str[1] == 'x' || str[1] == 'X')) @@ -127,9 +127,8 @@ strtoul(const char *str, char **ptr, int base) } /* If we still don't know what base to use and the - * next letter to follow is a zero then this is - * probably a number in octal notation. - */ + next letter to follow is a zero then this is + probably a number in octal notation. */ if(base == 0) { if(c == '0') @@ -172,21 +171,31 @@ strtoul(const char *str, char **ptr, int base) str++; c = (*str); + + num_digits_converted++; } } + /* Did we convert anything? */ + if(num_digits_converted == 0) + { + __set_errno(ERANGE); + goto out; + } + if(is_negative) result = (-sum); else result = sum; + stop = str; + out: /* If desired, remember where we stopped reading the - * number from the buffer. - */ + number from the buffer. */ if(ptr != NULL) - (*ptr) = (char *)str; + (*ptr) = (char *)stop; RETURN(result); return(result); diff --git a/library/stdlib_strtoull.c b/library/stdlib_strtoull.c index c44d2a8..090dc94 100644 --- a/library/stdlib_strtoull.c +++ b/library/stdlib_strtoull.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_strtoull.c,v 1.3 2005-02-03 16:56:17 obarthel Exp $ + * $Id: stdlib_strtoull.c,v 1.4 2005-09-28 09:28:39 obarthel Exp $ * * :ts=4 * @@ -50,6 +50,8 @@ unsigned long long strtoull(const char *str, char **ptr, int base) { + const char * stop = str; + size_t num_digits_converted = 0; BOOL is_negative; unsigned long long result = 0; unsigned long long new_sum; @@ -107,8 +109,7 @@ strtoull(const char *str, char **ptr, int base) is_negative = FALSE; /* But there may be a sign we will choose to - * ignore. - */ + ignore. */ if(c == '+') str++; } @@ -116,8 +117,7 @@ strtoull(const char *str, char **ptr, int base) c = (*str); /* There may be a leading '0x' to indicate that what - * follows is a hexadecimal number. - */ + follows is a hexadecimal number. */ if(base == 0 || base == 16) { if((c == '0') && (str[1] == 'x' || str[1] == 'X')) @@ -131,9 +131,8 @@ strtoull(const char *str, char **ptr, int base) } /* If we still don't know what base to use and the - * next letter to follow is a zero then this is - * probably a number in octal notation. - */ + next letter to follow is a zero then this is + probably a number in octal notation. */ if(base == 0) { if(c == '0') @@ -176,21 +175,31 @@ strtoull(const char *str, char **ptr, int base) str++; c = (*str); + + num_digits_converted++; } } + /* Did we convert anything? */ + if(num_digits_converted == 0) + { + __set_errno(ERANGE); + goto out; + } + if(is_negative) result = (-sum); else result = sum; + stop = str; + out: /* If desired, remember where we stopped reading the - * number from the buffer. - */ + number from the buffer. */ if(ptr != NULL) - (*ptr) = (char *)str; + (*ptr) = (char *)stop; RETURN(result); return(result);