improve converting strings to ints/longs

The existing code is inconsistent, and in a couple of cases wrong, about
dealing with strings that are not valid ints. For example, there are
locations that call wcstol() and check errno without first setting errno
to zero. Normalize the code to a consistent pattern.  This is mostly to
deal with inconsistencies between BSD, GNU, and other UNIXes.

This does make some syntax more liberal. For example `echo $PATH[1 .. 3]`
is now valid due to uniformly allowing leading and trailing whitespace
around numbers. Whereas prior to this change you would get a "Invalid
index value" error. Contrast this with `echo $PATH[ 1.. 3 ]` which was
valid and still is.
This commit is contained in:
Kurtis Rader
2016-11-22 20:24:03 -08:00
parent 5ec9fcd8d4
commit a928517e95
18 changed files with 266 additions and 215 deletions

View File

@@ -878,10 +878,8 @@ static int string_split(parser_t &parser, io_streams_t &streams, int argc, wchar
break;
}
case 'm': {
errno = 0;
wchar_t *endptr = 0;
max = wcstol(w.woptarg, &endptr, 10);
if (*endptr != L'\0' || errno != 0) {
max = fish_wcstol(w.woptarg);
if (errno) {
string_error(streams, BUILTIN_ERR_NOT_NUMBER, argv[0], w.woptarg);
return BUILTIN_STRING_ERROR;
}
@@ -969,7 +967,7 @@ static int string_sub(parser_t &parser, io_streams_t &streams, int argc, wchar_t
long length = -1;
bool quiet = false;
wgetopter_t w;
wchar_t *endptr = NULL;
for (;;) {
int c = w.wgetopt_long(argc, argv, short_options, long_options, 0);
@@ -981,16 +979,14 @@ static int string_sub(parser_t &parser, io_streams_t &streams, int argc, wchar_t
break;
}
case 'l': {
errno = 0;
length = wcstol(w.woptarg, &endptr, 10);
if (*endptr != L'\0' || (errno != 0 && errno != ERANGE)) {
string_error(streams, BUILTIN_ERR_NOT_NUMBER, argv[0], w.woptarg);
return BUILTIN_STRING_ERROR;
}
length = fish_wcstol(w.woptarg);
if (length < 0 || errno == ERANGE) {
string_error(streams, _(L"%ls: Invalid length value '%ls'\n"), argv[0],
w.woptarg);
return BUILTIN_STRING_ERROR;
} else if (errno) {
string_error(streams, BUILTIN_ERR_NOT_NUMBER, argv[0], w.woptarg);
return BUILTIN_STRING_ERROR;
}
break;
}
@@ -999,16 +995,14 @@ static int string_sub(parser_t &parser, io_streams_t &streams, int argc, wchar_t
break;
}
case 's': {
errno = 0;
start = wcstol(w.woptarg, &endptr, 10);
if (*endptr != L'\0' || (errno != 0 && errno != ERANGE)) {
string_error(streams, BUILTIN_ERR_NOT_NUMBER, argv[0], w.woptarg);
return BUILTIN_STRING_ERROR;
}
start = fish_wcstol(w.woptarg);
if (start == 0 || start == LONG_MIN || errno == ERANGE) {
string_error(streams, _(L"%ls: Invalid start value '%ls'\n"), argv[0],
w.woptarg);
return BUILTIN_STRING_ERROR;
} else if (errno) {
string_error(streams, BUILTIN_ERR_NOT_NUMBER, argv[0], w.woptarg);
return BUILTIN_STRING_ERROR;
}
break;
}