hio/hio/lib/utl-str.m4

910 lines
21 KiB
Plaintext

dnl ---------------------------------------------------------------------------
changequote(`[[', `]]')dnl
dnl ---------------------------------------------------------------------------
define([[fn_comp_chars]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)pushdef([[_chau_type_]], $3)pushdef([[_to_lower_]], $4)dnl
int _fn_name_ (const _char_type_* str1, hio_oow_t len1, const _char_type_* str2, hio_oow_t len2, int ignorecase)
{
_chau_type_ c1, c2;
const _char_type_* end1 = str1 + len1;
const _char_type_* end2 = str2 + len2;
if (ignorecase)
{
while (str1 < end1)
{
c1 = _to_lower_()(*str1);
if (str2 < end2)
{
c2 = _to_lower_()(*str2);
if (c1 > c2) return 1;
if (c1 < c2) return -1;
}
else return 1;
str1++; str2++;
}
}
else
{
while (str1 < end1)
{
c1 = *str1;
if (str2 < end2)
{
c2 = *str2;
if (c1 > c2) return 1;
if (c1 < c2) return -1;
}
else return 1;
str1++; str2++;
}
}
return (str2 < end2)? -1: 0;
}
popdef([[_fn_name_]])popdef([[_char_type_]])popdef([[_chau_type_]])popdef([[_to_lower_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_comp_cstr]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)pushdef([[_chau_type_]], $3)pushdef([[_to_lower_]], $4)dnl
int _fn_name_ (const _char_type_* str1, const _char_type_* str2, int ignorecase)
{
if (ignorecase)
{
while (_to_lower_()(*str1) == _to_lower_()(*str2))
{
if (*str1 == '\0') return 0;
str1++; str2++;
}
return ((_chau_type_)_to_lower_()(*str1) > (_chau_type_)_to_lower_()(*str2))? 1: -1;
}
else
{
while (*str1 == *str2)
{
if (*str1 == '\0') return 0;
str1++; str2++;
}
return ((_chau_type_)*str1 > (_chau_type_)*str2)? 1: -1;
}
}
popdef([[_fn_name_]])popdef([[_char_type_]])popdef([[_chau_type_]])popdef([[_to_lower_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_comp_cstr_limited]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)pushdef([[_chau_type_]], $3)pushdef([[_to_lower_]], $4)dnl
int _fn_name_ (const _char_type_* str1, const _char_type_* str2, hio_oow_t maxlen, int ignorecase)
{
if (maxlen == 0) return 0;
if (ignorecase)
{
while (_to_lower_()(*str1) == _to_lower_()(*str2))
{
if (*str1 == '\0' || maxlen == 1) return 0;
str1++; str2++; maxlen--;
}
return ((_chau_type_)_to_lower_()(*str1) > (_chau_type_)_to_lower_()(*str2))? 1: -1;
}
else
{
while (*str1 == *str2)
{
if (*str1 == '\0' || maxlen == 1) return 0;
str1++; str2++; maxlen--;
}
return ((_chau_type_)*str1 > (_chau_type_)*str2)? 1: -1;
}
}
popdef([[_fn_name_]])popdef([[_char_type_]])popdef([[_chau_type_]])popdef([[_to_lower_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_comp_chars_cstr]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)pushdef([[_chau_type_]], $3)pushdef([[_to_lower_]], $4)dnl
int _fn_name_ (const _char_type_* str1, hio_oow_t len, const _char_type_* str2, int ignorecase)
{
/* for "abc\0" of length 4 vs "abc", the fourth character
* of the first string is equal to the terminating null of
* the second string. the first string is still considered
* bigger */
if (ignorecase)
{
const _char_type_* end = str1 + len;
_char_type_ c1;
_char_type_ c2;
while (str1 < end && *str2 != '\0')
{
c1 = _to_lower_()(*str1);
c2 = _to_lower_()(*str2);
if (c1 != c2) return ((_chau_type_)c1 > (_chau_type_)c2)? 1: -1;
str1++; str2++;
}
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
}
else
{
const _char_type_* end = str1 + len;
while (str1 < end && *str2 != '\0')
{
if (*str1 != *str2) return ((_chau_type_)*str1 > (_chau_type_)*str2)? 1: -1;
str1++; str2++;
}
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
}
}
popdef([[_fn_name_]])popdef([[_char_type_]])popdef([[_chau_type_]])popdef([[_to_lower_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_concat_chars_to_cstr]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)pushdef([[_count_str_]], $3)dnl
hio_oow_t _fn_name_ (_char_type_* buf, hio_oow_t bsz, const _char_type_* str, hio_oow_t len)
{
_char_type_* p, * p2;
const _char_type_* end;
hio_oow_t blen;
blen = _count_str_()(buf);
if (blen >= bsz) return blen; /* something wrong */
p = buf + blen;
p2 = buf + bsz - 1;
end = str + len;
while (p < p2)
{
if (str >= end) break;
*p++ = *str++;
}
if (bsz > 0) *p = '\0';
return p - buf;
}
popdef([[_fn_name_]])popdef([[_char_type_]])popdef([[_count_str_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_concat_cstr]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)pushdef([[_count_str_]], $3)dnl
hio_oow_t _fn_name_ (_char_type_* buf, hio_oow_t bsz, const _char_type_* str)
{
_char_type_* p, * p2;
hio_oow_t blen;
blen = _count_str_()(buf);
if (blen >= bsz) return blen; /* something wrong */
p = buf + blen;
p2 = buf + bsz - 1;
while (p < p2)
{
if (*str == '\0') break;
*p++ = *str++;
}
if (bsz > 0) *p = '\0';
return p - buf;
}
popdef([[_fn_name_]])popdef([[_char_type_]])popdef([[_count_str_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_copy_chars]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)dnl
void _fn_name_ (_char_type_* dst, const _char_type_* src, hio_oow_t len)
{
/* take note of no forced null termination */
hio_oow_t i;
for (i = 0; i < len; i++) dst[i] = src[i];
}
popdef([[_fn_name_]])popdef([[_char_type_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_copy_chars_to_cstr]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)dnl
hio_oow_t _fn_name_ (_char_type_* dst, hio_oow_t dlen, const _char_type_* src, hio_oow_t slen)
{
hio_oow_t i;
if (dlen <= 0) return 0;
if (dlen <= slen) slen = dlen - 1;
for (i = 0; i < slen; i++) dst[i] = src[i];
dst[i] = '\0';
return i;
}
popdef([[_fn_name_]])popdef([[_char_type_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_copy_chars_to_cstr_unlimited]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)dnl
hio_oow_t _fn_name_ (_char_type_* dst, const _char_type_* src, hio_oow_t len)
{
hio_oow_t i;
for (i = 0; i < len; i++) dst[i] = src[i];
dst[i] = '\0';
return i;
}
popdef([[_fn_name_]])popdef([[_char_type_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_copy_cstr_to_chars]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)dnl
hio_oow_t _fn_name_ (_char_type_* dst, hio_oow_t len, const _char_type_* src)
{
/* no null termination */
_char_type_* p, * p2;
p = dst; p2 = dst + len - 1;
while (p < p2)
{
if (*src == '\0') break;
*p++ = *src++;
}
return p - dst;
}
popdef([[_fn_name_]])popdef([[_char_type_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_copy_cstr]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)dnl
hio_oow_t _fn_name_ (_char_type_* dst, hio_oow_t len, const _char_type_* src)
{
_char_type_* p, * p2;
p = dst; p2 = dst + len - 1;
while (p < p2)
{
if (*src == '\0') break;
*p++ = *src++;
}
if (len > 0) *p = '\0';
return p - dst;
}
popdef([[_fn_name_]])popdef([[_char_type_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_copy_cstr_unlimited]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)dnl
hio_oow_t _fn_name_ (_char_type_* dst, const _char_type_* src)
{
_char_type_* org = dst;
while ((*dst++ = *src++) != '\0');
return dst - org - 1;
}
popdef([[_fn_name_]])popdef([[_char_type_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_count_cstr]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)dnl
hio_oow_t _fn_name_ (const _char_type_* str)
{
const _char_type_* ptr = str;
while (*ptr != '\0') ptr++;
return ptr - str;
}
popdef([[_fn_name_]])popdef([[_char_type_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_equal_chars]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)dnl
int _fn_name_ (const _char_type_* str1, const _char_type_* str2, hio_oow_t len)
{
hio_oow_t i;
/* NOTE: you should call this function after having ensured that
* str1 and str2 are in the same length */
for (i = 0; i < len; i++)
{
if (str1[i] != str2[i]) return 0;
}
return 1;
}
popdef([[_fn_name_]])popdef([[_char_type_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_fill_chars]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)dnl
void _fn_name_ (_char_type_* dst, _char_type_ ch, hio_oow_t len)
{
hio_oow_t i;
for (i = 0; i < len; i++) dst[i] = ch;
}
popdef([[_fn_name_]])popdef([[_char_type_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_find_char]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)dnl
_char_type_* _fn_name_ (const _char_type_* ptr, hio_oow_t len, _char_type_ c)
{
const _char_type_* end;
end = ptr + len;
while (ptr < end)
{
if (*ptr == c) return (_char_type_*)ptr;
ptr++;
}
return HIO_NULL;
}
popdef([[_fn_name_]])popdef([[_char_type_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_rfind_char]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)dnl
_char_type_* _fn_name_ (const _char_type_* ptr, hio_oow_t len, _char_type_ c)
{
const _char_type_* cur;
cur = ptr + len;
while (cur > ptr)
{
--cur;
if (*cur == c) return (_char_type_*)cur;
}
return HIO_NULL;
}
popdef([[_fn_name_]])popdef([[_char_type_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_find_char_in_cstr]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)dnl
_char_type_* _fn_name_ (const _char_type_* ptr, _char_type_ c)
{
while (*ptr != '\0')
{
if (*ptr == c) return (_char_type_*)ptr;
ptr++;
}
return HIO_NULL;
}
popdef([[_fn_name_]])popdef([[_char_type_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_rotate_chars]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)dnl
hio_oow_t _fn_name_ (_char_type_* str, hio_oow_t len, int dir, hio_oow_t n)
{
hio_oow_t first, last, count, index, nk;
_char_type_ c;
if (dir == 0 || len == 0) return len;
if ((n %= len) == 0) return len;
if (dir > 0) n = len - n;
first = 0; nk = len - n; count = 0;
while (count < n)
{
last = first + nk;
index = first;
c = str[first];
do
{
count++;
while (index < nk)
{
str[index] = str[index + n];
index += n;
}
if (index == last) break;
str[index] = str[index - nk];
index -= nk;
}
while (1);
str[last] = c; first++;
}
return len;
}
popdef([[_fn_name_]])popdef([[_char_type_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_trim_chars]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)pushdef([[_is_space_]], $3)pushdef([[_prefix_]], $4)dnl
_char_type_* _fn_name_ (const _char_type_* str, hio_oow_t* len, int flags)
{
const _char_type_* p = str, * end = str + *len;
if (p < end)
{
const _char_type_* s = HIO_NULL, * e = HIO_NULL;
do
{
if (!_is_space_()(*p))
{
if (s == HIO_NULL) s = p;
e = p;
}
p++;
}
while (p < end);
if (e)
{
if (flags & _prefix_()_RIGHT)
{
*len -= end - e - 1;
}
if (flags & _prefix_()_LEFT)
{
*len -= s - str;
str = s;
}
}
else
{
/* the entire string need to be deleted */
if ((flags & _prefix_()_RIGHT) ||
(flags & _prefix_()_LEFT)) *len = 0;
}
}
return (_char_type_*)str;
}
popdef([[_fn_name_]])popdef([[_char_type_]])popdef([[_is_space_]])popdef([[_prefix_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_split_cstr]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)pushdef([[_is_space_]], $3)pushdef([[_copy_str_unlimited_]], $4)dnl
int _fn_name_ (_char_type_* s, const _char_type_* delim, _char_type_ lquote, _char_type_ rquote, _char_type_ escape)
{
_char_type_* p = s, *d;
_char_type_* sp = HIO_NULL, * ep = HIO_NULL;
int delim_mode;
int cnt = 0;
if (delim == HIO_NULL) delim_mode = 0;
else
{
delim_mode = 1;
for (d = (_char_type_*)delim; *d != '\0'; d++)
if (!_is_space_()(*d)) delim_mode = 2;
}
if (delim_mode == 0)
{
/* skip preceding space characters */
while (_is_space_()(*p)) p++;
/* when 0 is given as "delim", it has an effect of cutting
preceding and trailing space characters off "s". */
if (lquote != '\0' && *p == lquote)
{
_copy_str_unlimited_ (p, p + 1);
for (;;)
{
if (*p == '\0') return -1;
if (escape != '\0' && *p == escape)
{
_copy_str_unlimited_ (p, p + 1);
}
else
{
if (*p == rquote)
{
p++;
break;
}
}
if (sp == 0) sp = p;
ep = p;
p++;
}
while (_is_space_()(*p)) p++;
if (*p != '\0') return -1;
if (sp == 0 && ep == 0) s[0] = '\0';
else
{
ep[1] = '\0';
if (s != (_char_type_*)sp) _copy_str_unlimited_ (s, sp);
cnt++;
}
}
else
{
while (*p)
{
if (!_is_space_()(*p))
{
if (sp == 0) sp = p;
ep = p;
}
p++;
}
if (sp == 0 && ep == 0) s[0] = '\0';
else
{
ep[1] = '\0';
if (s != (_char_type_*)sp) _copy_str_unlimited_ (s, sp);
cnt++;
}
}
}
else if (delim_mode == 1)
{
_char_type_* o;
while (*p)
{
o = p;
while (_is_space_()(*p)) p++;
if (o != p) { _copy_str_unlimited_ (o, p); p = o; }
if (lquote != '\0' && *p == lquote)
{
_copy_str_unlimited_ (p, p + 1);
for (;;)
{
if (*p == '\0') return -1;
if (escape != '\0' && *p == escape)
{
_copy_str_unlimited_ (p, p + 1);
}
else
{
if (*p == rquote)
{
*p++ = '\0';
cnt++;
break;
}
}
p++;
}
}
else
{
o = p;
for (;;)
{
if (*p == '\0')
{
if (o != p) cnt++;
break;
}
if (_is_space_()(*p))
{
*p++ = '\0';
cnt++;
break;
}
p++;
}
}
}
}
else /* if (delim_mode == 2) */
{
_char_type_* o;
int ok;
while (*p != '\0')
{
o = p;
while (_is_space_()(*p)) p++;
if (o != p) { _copy_str_unlimited_ (o, p); p = o; }
if (lquote != '\0' && *p == lquote)
{
_copy_str_unlimited_ (p, p + 1);
for (;;)
{
if (*p == '\0') return -1;
if (escape != '\0' && *p == escape)
{
_copy_str_unlimited_ (p, p + 1);
}
else
{
if (*p == rquote)
{
*p++ = '\0';
cnt++;
break;
}
}
p++;
}
ok = 0;
while (_is_space_()(*p)) p++;
if (*p == '\0') ok = 1;
for (d = (_char_type_*)delim; *d != '\0'; d++)
{
if (*p == *d)
{
ok = 1;
_copy_str_unlimited_ (p, p + 1);
break;
}
}
if (ok == 0) return -1;
}
else
{
o = p; sp = ep = 0;
for (;;)
{
if (*p == '\0')
{
if (ep)
{
ep[1] = '\0';
p = &ep[1];
}
cnt++;
break;
}
for (d = (_char_type_*)delim; *d != '\0'; d++)
{
if (*p == *d)
{
if (sp == HIO_NULL)
{
_copy_str_unlimited_ (o, p); p = o;
*p++ = '\0';
}
else
{
_copy_str_unlimited_ (&ep[1], p);
_copy_str_unlimited_ (o, sp);
o[ep - sp + 1] = '\0';
p = &o[ep - sp + 2];
}
cnt++;
/* last empty field after delim */
if (*p == '\0') cnt++;
goto exit_point;
}
}
if (!_is_space_()(*p))
{
if (sp == HIO_NULL) sp = p;
ep = p;
}
p++;
}
exit_point:
;
}
}
}
return cnt;
}
popdef([[_fn_name_]])popdef([[_char_type_]])popdef([[_is_space_]])popdef([[_copy_str_unlimited_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_chars_to_int]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)pushdef([[_int_type_]], $3)pushdef([[_is_space_]], $4)pushdef([[_prefix_]], $5)dnl
_int_type_ _fn_name_ (const _char_type_* str, hio_oow_t len, int option, const _char_type_** endptr, int* is_sober)
{
_int_type_ n = 0;
const _char_type_* p, * pp;
const _char_type_* end;
hio_oow_t rem;
int digit, negative = 0;
int base = _prefix_()_GET_OPTION_BASE(option);
p = str;
end = str + len;
if (_prefix_()_GET_OPTION_LTRIM(option))
{
/* strip off leading spaces */
while (p < end && _is_space_()(*p)) p++;
}
/* check for a sign */
while (p < end)
{
if (*p == '-')
{
negative = ~negative;
p++;
}
else if (*p == '+') p++;
else break;
}
/* check for a binary/octal/hexadecimal notation */
rem = end - p;
if (base == 0)
{
if (rem >= 1 && *p == '0')
{
p++;
if (rem == 1) base = 8;
else if (*p == 'x' || *p == 'X')
{
p++; base = 16;
}
else if (*p == 'b' || *p == 'B')
{
p++; base = 2;
}
else base = 8;
}
else base = 10;
}
else if (rem >= 2 && base == 16)
{
if (*p == '0' &&
(*(p + 1) == 'x' || *(p + 1) == 'X')) p += 2;
}
else if (rem >= 2 && base == 2)
{
if (*p == '0' &&
(*(p + 1) == 'b' || *(p + 1) == 'B')) p += 2;
}
/* process the digits */
pp = p;
while (p < end)
{
digit = HIO_ZDIGIT_TO_NUM(*p, base);
if (digit >= base) break;
n = n * base + digit;
p++;
}
if (_prefix_()_GET_OPTION_E(option))
{
if (*p == 'E' || *p == 'e')
{
_int_type_ e = 0, i;
int e_neg = 0;
p++;
if (*p == '+')
{
p++;
}
else if (*p == '-')
{
p++; e_neg = 1;
}
while (p < end)
{
digit = HIO_ZDIGIT_TO_NUM(*p, base);
if (digit >= base) break;
e = e * base + digit;
p++;
}
if (e_neg)
for (i = 0; i < e; i++) n /= 10;
else
for (i = 0; i < e; i++) n *= 10;
}
}
/* base 8: at least a zero digit has been seen.
* other case: p > pp to be able to have at least 1 meaningful digit. */
if (is_sober) *is_sober = (base == 8 || p > pp);
if (_prefix_()_GET_OPTION_RTRIM(option))
{
/* consume trailing spaces */
while (p < end && _is_space_()(*p)) p++;
}
if (endptr) *endptr = p;
return (negative)? -n: n;
}
popdef([[_fn_name_]])popdef([[_char_type_]])popdef([[_int_type_]])popdef([[_is_space_]])popdef([[_prefix_]])dnl
]])dnl
dnl ---------------------------------------------------------------------------
define([[fn_chars_to_uint]], [[pushdef([[_fn_name_]], $1)pushdef([[_char_type_]], $2)pushdef([[_int_type_]], $3)pushdef([[_is_space_]], $4)pushdef([[_prefix_]], $5)dnl
_int_type_ _fn_name_ (const _char_type_* str, hio_oow_t len, int option, const _char_type_** endptr, int* is_sober)
{
_int_type_ n = 0;
const _char_type_* p, * pp;
const _char_type_* end;
hio_oow_t rem;
int digit;
int base = _prefix_()_GET_OPTION_BASE(option);
p = str;
end = str + len;
if (_prefix_()_GET_OPTION_LTRIM(option))
{
/* strip off leading spaces */
while (p < end && _is_space_()(*p)) p++;
}
/* check for a sign */
while (p < end)
{
if (*p == '+') p++;
else break;
}
/* check for a binary/octal/hexadecimal notation */
rem = end - p;
if (base == 0)
{
if (rem >= 1 && *p == '0')
{
p++;
if (rem == 1) base = 8;
else if (*p == 'x' || *p == 'X')
{
p++; base = 16;
}
else if (*p == 'b' || *p == 'B')
{
p++; base = 2;
}
else base = 8;
}
else base = 10;
}
else if (rem >= 2 && base == 16)
{
if (*p == '0' &&
(*(p + 1) == 'x' || *(p + 1) == 'X')) p += 2;
}
else if (rem >= 2 && base == 2)
{
if (*p == '0' &&
(*(p + 1) == 'b' || *(p + 1) == 'B')) p += 2;
}
/* process the digits */
pp = p;
while (p < end)
{
digit = HIO_ZDIGIT_TO_NUM(*p, base);
if (digit >= base) break;
n = n * base + digit;
p++;
}
if (_prefix_()_GET_OPTION_E(option))
{
if (*p == 'E' || *p == 'e')
{
_int_type_ e = 0, i;
int e_neg = 0;
p++;
if (*p == '+')
{
p++;
}
else if (*p == '-')
{
p++; e_neg = 1;
}
while (p < end)
{
digit = HIO_ZDIGIT_TO_NUM(*p, base);
if (digit >= base) break;
e = e * base + digit;
p++;
}
if (e_neg)
for (i = 0; i < e; i++) n /= 10;
else
for (i = 0; i < e; i++) n *= 10;
}
}
/* base 8: at least a zero digit has been seen.
* other case: p > pp to be able to have at least 1 meaningful digit. */
if (is_sober) *is_sober = (base == 8 || p > pp);
if (_prefix_()_GET_OPTION_RTRIM(option))
{
/* consume trailing spaces */
while (p < end && _is_space_()(*p)) p++;
}
if (endptr) *endptr = p;
return n;
}
popdef([[_fn_name_]])popdef([[_char_type_]])popdef([[_int_type_]])popdef([[_is_space_]])popdef([[_prefix_]])dnl
]])