added qse_awk_wcsxtoint()/qse_awk_mbsxtoint() and made qse_awk_strtointo() a macro
added qse_awk_wcsxtoflt()/qse_awk_mbsxtoflt() and made qse_awk_strxtoflt() a macro enhanced qse_awk_rtx_valtonum() to handle a byte array
This commit is contained in:
parent
5e0754e607
commit
81cbac9e4d
@ -1896,29 +1896,63 @@ QSE_EXPORT qse_char_t* qse_awk_cstrdup (
|
|||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The qse_awk_strxtoint() function converts a string to an integer.
|
* The qse_awk_mbsxtoint() function converts a multi-byte string to an integer.
|
||||||
*/
|
*/
|
||||||
QSE_EXPORT qse_awk_int_t qse_awk_strxtoint (
|
QSE_EXPORT qse_awk_int_t qse_awk_mbsxtoint (
|
||||||
qse_awk_t* awk,
|
qse_awk_t* awk,
|
||||||
const qse_char_t* str,
|
const qse_mchar_t* str,
|
||||||
qse_size_t len,
|
qse_size_t len,
|
||||||
int base,
|
int base,
|
||||||
const qse_char_t** endptr
|
const qse_mchar_t** endptr
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The qse_awk_strxtoflt() function converts a string to a floating-point
|
* The qse_awk_wcsxtoint() function converts a wide character string to an integer.
|
||||||
|
*/
|
||||||
|
QSE_EXPORT qse_awk_int_t qse_awk_wcsxtoint (
|
||||||
|
qse_awk_t* awk,
|
||||||
|
const qse_wchar_t* str,
|
||||||
|
qse_size_t len,
|
||||||
|
int base,
|
||||||
|
const qse_wchar_t** endptr
|
||||||
|
);
|
||||||
|
|
||||||
|
#if defined(QSE_CHAR_IS_MCHAR)
|
||||||
|
# define qse_awk_strxtoint(awk,str,len,base,endptr) qse_awk_mbsxtoint(awk,str,len,base,endptr)
|
||||||
|
#else
|
||||||
|
# define qse_awk_strxtoint(awk,str,len,base,endptr) qse_awk_wcsxtoint(awk,str,len,base,endptr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_awk_mbsxtoflt() function converts a multi-byte string to a floating-point
|
||||||
* number.
|
* number.
|
||||||
*/
|
*/
|
||||||
QSE_EXPORT qse_awk_flt_t qse_awk_strxtoflt (
|
QSE_EXPORT qse_awk_flt_t qse_awk_mbsxtoflt (
|
||||||
qse_awk_t* awk,
|
qse_awk_t* awk,
|
||||||
const qse_char_t* str,
|
const qse_mchar_t* str,
|
||||||
qse_size_t len,
|
qse_size_t len,
|
||||||
const qse_char_t** endptr
|
const qse_mchar_t** endptr
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The qse_awk_longtostr() functon converts an integer to a string.
|
* The qse_awk_wcsxtoflt() function converts a wide character string to a floating-point
|
||||||
|
* number.
|
||||||
|
*/
|
||||||
|
QSE_EXPORT qse_awk_flt_t qse_awk_wcsxtoflt (
|
||||||
|
qse_awk_t* awk,
|
||||||
|
const qse_wchar_t* str,
|
||||||
|
qse_size_t len,
|
||||||
|
const qse_wchar_t** endptr
|
||||||
|
);
|
||||||
|
|
||||||
|
#if defined(QSE_CHAR_IS_MCHAR)
|
||||||
|
# define qse_awk_strxtoflt(awk,str,len,endptr) qse_awk_mbsxtoflt(awk,str,len,endptr)
|
||||||
|
#else
|
||||||
|
# define qse_awk_strxtoflt(awk,str,len,endptr) qse_awk_wcsxtoflt(awk,str,len,endptr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_awk_inttostr() functon converts an integer to a string.
|
||||||
*/
|
*/
|
||||||
QSE_EXPORT qse_size_t qse_awk_inttostr (
|
QSE_EXPORT qse_size_t qse_awk_inttostr (
|
||||||
qse_awk_t* awk,
|
qse_awk_t* awk,
|
||||||
@ -2811,15 +2845,29 @@ QSE_EXPORT int qse_awk_rtx_valtoflt (
|
|||||||
#define QSE_AWK_RTX_STRTONUM_GET_OPTION_STRICT(option) ((option) & 1)
|
#define QSE_AWK_RTX_STRTONUM_GET_OPTION_STRICT(option) ((option) & 1)
|
||||||
#define QSE_AWK_RTX_STRTONUN_GET_OPTION_BASE(option) ((option) >> 8)
|
#define QSE_AWK_RTX_STRTONUN_GET_OPTION_BASE(option) ((option) >> 8)
|
||||||
|
|
||||||
QSE_EXPORT int qse_awk_rtx_strtonum (
|
QSE_EXPORT int qse_awk_rtx_mbstonum (
|
||||||
qse_awk_rtx_t* rtx, /**< runtime context */
|
qse_awk_rtx_t* rtx, /**< runtime context */
|
||||||
int strict, /**< determines to perform strict check */
|
int strict, /**< determines to perform strict check */
|
||||||
const qse_char_t* ptr, /**< points to a string to convert */
|
const qse_mchar_t* ptr, /**< points to a string to convert */
|
||||||
qse_size_t len, /**< number of characters in a string */
|
qse_size_t len, /**< number of characters in a string */
|
||||||
qse_awk_int_t* l, /**< stores a converted integer */
|
qse_awk_int_t* l, /**< stores a converted integer */
|
||||||
qse_awk_flt_t* r /**< stores a converted floating-poing number */
|
qse_awk_flt_t* r /**< stores a converted floating-poing number */
|
||||||
);
|
);
|
||||||
|
|
||||||
|
QSE_EXPORT int qse_awk_rtx_wcstonum (
|
||||||
|
qse_awk_rtx_t* rtx, /**< runtime context */
|
||||||
|
int strict, /**< determines to perform strict check */
|
||||||
|
const qse_wchar_t* ptr, /**< points to a string to convert */
|
||||||
|
qse_size_t len, /**< number of characters in a string */
|
||||||
|
qse_awk_int_t* l, /**< stores a converted integer */
|
||||||
|
qse_awk_flt_t* r /**< stores a converted floating-poing number */
|
||||||
|
);
|
||||||
|
|
||||||
|
#if defined(QSE_CHAR_IS_MCHAR)
|
||||||
|
# define qse_awk_rtx_strtonum(rtx,strict,ptr,len,l,r) qse_awk_rtx_mbstonum(rtx,strict,ptr,len,l,r)
|
||||||
|
#else
|
||||||
|
# define qse_awk_rtx_strtonum(rtx,strict,ptr,len,l,r) qse_awk_rtx_wcstonum(rtx,strict,ptr,len,l,r)
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* The qse_awk_rtx_hashval() function hashes a simple value
|
* The qse_awk_rtx_hashval() function hashes a simple value
|
||||||
* to a positive integer. It returns -1 for a inhashable value.
|
* to a positive integer. It returns -1 for a inhashable value.
|
||||||
|
@ -76,6 +76,34 @@ typedef struct qse_awk_tree_t qse_awk_tree_t;
|
|||||||
#define QSE_AWK_TOUPPER(awk,c) QSE_TOUPPER(c)
|
#define QSE_AWK_TOUPPER(awk,c) QSE_TOUPPER(c)
|
||||||
#define QSE_AWK_TOLOWER(awk,c) QSE_TOLOWER(c)
|
#define QSE_AWK_TOLOWER(awk,c) QSE_TOLOWER(c)
|
||||||
|
|
||||||
|
#define QSE_AWK_ISMUPPER(awk,c) QSE_ISMUPPER(c)
|
||||||
|
#define QSE_AWK_ISMLOWER(awk,c) QSE_ISMLOWER(c)
|
||||||
|
#define QSE_AWK_ISMALPHA(awk,c) QSE_ISMALPHA(c)
|
||||||
|
#define QSE_AWK_ISMDIGIT(awk,c) QSE_ISMDIGIT(c)
|
||||||
|
#define QSE_AWK_ISMXDIGIT(awk,c) QSE_ISMXDIGIT(c)
|
||||||
|
#define QSE_AWK_ISMALNUM(awk,c) QSE_ISMALNUM(c)
|
||||||
|
#define QSE_AWK_ISMSPACE(awk,c) QSE_ISMSPACE(c)
|
||||||
|
#define QSE_AWK_ISMPRINT(awk,c) QSE_ISMPRINT(c)
|
||||||
|
#define QSE_AWK_ISMGRAPH(awk,c) QSE_ISMGRAPH(c)
|
||||||
|
#define QSE_AWK_ISMCNTRL(awk,c) QSE_ISMCNTRL(c)
|
||||||
|
#define QSE_AWK_ISMPUNCT(awk,c) QSE_ISMPUNCT(c)
|
||||||
|
#define QSE_AWK_TOMUPPER(awk,c) QSE_TOMUPPER(c)
|
||||||
|
#define QSE_AWK_TOMLOWER(awk,c) QSE_TOMLOWER(c)
|
||||||
|
|
||||||
|
#define QSE_AWK_ISWUPPER(awk,c) QSE_ISWUPPER(c)
|
||||||
|
#define QSE_AWK_ISWLOWER(awk,c) QSE_ISWLOWER(c)
|
||||||
|
#define QSE_AWK_ISWALPHA(awk,c) QSE_ISWALPHA(c)
|
||||||
|
#define QSE_AWK_ISWDIGIT(awk,c) QSE_ISWDIGIT(c)
|
||||||
|
#define QSE_AWK_ISWXDIGIT(awk,c) QSE_ISWXDIGIT(c)
|
||||||
|
#define QSE_AWK_ISWALNUM(awk,c) QSE_ISWALNUM(c)
|
||||||
|
#define QSE_AWK_ISWSPACE(awk,c) QSE_ISWSPACE(c)
|
||||||
|
#define QSE_AWK_ISWPRINT(awk,c) QSE_ISWPRINT(c)
|
||||||
|
#define QSE_AWK_ISWGRAPH(awk,c) QSE_ISWGRAPH(c)
|
||||||
|
#define QSE_AWK_ISWCNTRL(awk,c) QSE_ISWCNTRL(c)
|
||||||
|
#define QSE_AWK_ISWPUNCT(awk,c) QSE_ISWPUNCT(c)
|
||||||
|
#define QSE_AWK_TOWUPPER(awk,c) QSE_TOWUPPER(c)
|
||||||
|
#define QSE_AWK_TOWLOWER(awk,c) QSE_TOWLOWER(c)
|
||||||
|
|
||||||
#define QSE_AWK_STRDUP(awk,str) (qse_strdup(str,(awk)->mmgr))
|
#define QSE_AWK_STRDUP(awk,str) (qse_strdup(str,(awk)->mmgr))
|
||||||
#define QSE_AWK_STRXDUP(awk,str,len) (qse_strxdup(str,len,(awk)->mmgr))
|
#define QSE_AWK_STRXDUP(awk,str,len) (qse_strxdup(str,len,(awk)->mmgr))
|
||||||
|
|
||||||
|
503
qse/lib/awk/misc-imp.h
Normal file
503
qse/lib/awk/misc-imp.h
Normal file
@ -0,0 +1,503 @@
|
|||||||
|
|
||||||
|
|
||||||
|
qse_awk_int_t awk_strxtoint (qse_awk_t* awk, const char_t* str, qse_size_t len, int base, const char_t** endptr)
|
||||||
|
{
|
||||||
|
qse_awk_int_t n = 0;
|
||||||
|
const char_t* p;
|
||||||
|
const char_t* end;
|
||||||
|
qse_size_t rem;
|
||||||
|
int digit, negative = 0;
|
||||||
|
|
||||||
|
QSE_ASSERT (base < 37);
|
||||||
|
|
||||||
|
p = str;
|
||||||
|
end = str + len;
|
||||||
|
|
||||||
|
if (awk->opt.trait & QSE_AWK_STRIPSTRSPC)
|
||||||
|
{
|
||||||
|
/* strip off leading spaces */
|
||||||
|
while (p < end && AWK_ISSPACE(awk,*p)) p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for a sign */
|
||||||
|
while (p < end)
|
||||||
|
{
|
||||||
|
if (*p == _T('-'))
|
||||||
|
{
|
||||||
|
negative = ~negative;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
else if (*p == _T('+')) p++;
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for a binary/octal/hexadecimal notation */
|
||||||
|
rem = end - p;
|
||||||
|
if (base == 0)
|
||||||
|
{
|
||||||
|
if (rem >= 1 && *p == _T('0'))
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
|
||||||
|
if (rem == 1) base = 8;
|
||||||
|
else if (*p == _T('x') || *p == _T('X'))
|
||||||
|
{
|
||||||
|
p++; base = 16;
|
||||||
|
}
|
||||||
|
else if (*p == _T('b') || *p == _T('B'))
|
||||||
|
{
|
||||||
|
p++; base = 2;
|
||||||
|
}
|
||||||
|
else base = 8;
|
||||||
|
}
|
||||||
|
else base = 10;
|
||||||
|
}
|
||||||
|
else if (rem >= 2 && base == 16)
|
||||||
|
{
|
||||||
|
if (*p == _T('0') &&
|
||||||
|
(*(p+1) == _T('x') || *(p+1) == _T('X'))) p += 2;
|
||||||
|
}
|
||||||
|
else if (rem >= 2 && base == 2)
|
||||||
|
{
|
||||||
|
if (*p == _T('0') &&
|
||||||
|
(*(p+1) == _T('b') || *(p+1) == _T('B'))) p += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* process the digits */
|
||||||
|
while (p < end)
|
||||||
|
{
|
||||||
|
if (*p >= _T('0') && *p <= _T('9'))
|
||||||
|
digit = *p - _T('0');
|
||||||
|
else if (*p >= _T('A') && *p <= _T('Z'))
|
||||||
|
digit = *p - _T('A') + 10;
|
||||||
|
else if (*p >= _T('a') && *p <= _T('z'))
|
||||||
|
digit = *p - _T('a') + 10;
|
||||||
|
else break;
|
||||||
|
|
||||||
|
if (digit >= base) break;
|
||||||
|
n = n * base + digit;
|
||||||
|
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endptr) *endptr = p;
|
||||||
|
return (negative)? -n: n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* qse_awk_strtoflt is almost a replica of strtod.
|
||||||
|
*
|
||||||
|
* strtod.c --
|
||||||
|
*
|
||||||
|
* Source code for the "strtod" library procedure.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1988-1993 The Regents of the University of California.
|
||||||
|
* Copyright (c) 1994 Sun Microsystems, Inc.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this
|
||||||
|
* software and its documentation for any purpose and without
|
||||||
|
* fee is hereby granted, provided that the above copyright
|
||||||
|
* notice appear in all copies. The University of California
|
||||||
|
* makes no representations about the suitability of this
|
||||||
|
* software for any purpose. It is provided "as is" without
|
||||||
|
* express or implied warranty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* double(64bits) extended(80-bits) quadruple(128-bits)
|
||||||
|
* exponent 11 bits 15 bits 15 bits
|
||||||
|
* fraction 52 bits 63 bits 112 bits
|
||||||
|
* sign 1 bit 1 bit 1 bit
|
||||||
|
* integer 1 bit
|
||||||
|
*/
|
||||||
|
#define MAX_EXPONENT 511
|
||||||
|
|
||||||
|
qse_awk_flt_t awk_strtoflt (qse_awk_t* awk, const char_t* str)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Table giving binary powers of 10. Entry is 10^2^i.
|
||||||
|
* Used to convert decimal exponents into floating-point numbers.
|
||||||
|
*/
|
||||||
|
static qse_awk_flt_t powers_of_10[] =
|
||||||
|
{
|
||||||
|
10., 100., 1.0e4, 1.0e8, 1.0e16,
|
||||||
|
1.0e32, 1.0e64, 1.0e128, 1.0e256
|
||||||
|
};
|
||||||
|
|
||||||
|
qse_awk_flt_t fraction, dbl_exp, * d;
|
||||||
|
const char_t* p;
|
||||||
|
cint_t c;
|
||||||
|
int exp = 0; /* Exponent read from "EX" field */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exponent that derives from the fractional part. Under normal
|
||||||
|
* circumstatnces, it is the negative of the number of digits in F.
|
||||||
|
* However, if I is very long, the last digits of I get dropped
|
||||||
|
* (otherwise a long I with a large negative exponent could cause an
|
||||||
|
* unnecessary overflow on I alone). In this case, frac_exp is
|
||||||
|
* incremented one for each dropped digit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int frac_exp;
|
||||||
|
int mant_size; /* Number of digits in mantissa. */
|
||||||
|
int dec_pt; /* Number of mantissa digits BEFORE decimal point */
|
||||||
|
const char_t *pexp; /* Temporarily holds location of exponent in string */
|
||||||
|
int negative = 0, exp_negative = 0;
|
||||||
|
|
||||||
|
p = str;
|
||||||
|
|
||||||
|
if (awk->opt.trait & QSE_AWK_STRIPSTRSPC)
|
||||||
|
{
|
||||||
|
/* strip off leading spaces */
|
||||||
|
while (AWK_ISSPACE(awk,*p)) p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for a sign */
|
||||||
|
while (*p != _T('\0'))
|
||||||
|
{
|
||||||
|
if (*p == _T('-'))
|
||||||
|
{
|
||||||
|
negative = ~negative;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
else if (*p == _T('+')) p++;
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Count the number of digits in the mantissa (including the decimal
|
||||||
|
* point), and also locate the decimal point. */
|
||||||
|
dec_pt = -1;
|
||||||
|
for (mant_size = 0; ; mant_size++)
|
||||||
|
{
|
||||||
|
c = *p;
|
||||||
|
if (!AWK_ISDIGIT(awk, c))
|
||||||
|
{
|
||||||
|
if ((c != _T('.')) || (dec_pt >= 0)) break;
|
||||||
|
dec_pt = mant_size;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now suck up the digits in the mantissa. Use two integers to
|
||||||
|
* collect 9 digits each (this is faster than using floating-point).
|
||||||
|
* If the mantissa has more than 18 digits, ignore the extras, since
|
||||||
|
* they can't affect the value anyway.
|
||||||
|
*/
|
||||||
|
pexp = p;
|
||||||
|
p -= mant_size;
|
||||||
|
if (dec_pt < 0)
|
||||||
|
{
|
||||||
|
dec_pt = mant_size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mant_size--; /* One of the digits was the point */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mant_size > 18)
|
||||||
|
{
|
||||||
|
frac_exp = dec_pt - 18;
|
||||||
|
mant_size = 18;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
frac_exp = dec_pt - mant_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mant_size == 0)
|
||||||
|
{
|
||||||
|
fraction = 0.0;
|
||||||
|
/*p = str;*/
|
||||||
|
p = pexp;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int frac1, frac2;
|
||||||
|
frac1 = 0;
|
||||||
|
for ( ; mant_size > 9; mant_size--)
|
||||||
|
{
|
||||||
|
c = *p;
|
||||||
|
p++;
|
||||||
|
if (c == _T('.'))
|
||||||
|
{
|
||||||
|
c = *p;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
frac1 = 10 * frac1 + (c - _T('0'));
|
||||||
|
}
|
||||||
|
frac2 = 0;
|
||||||
|
for (; mant_size > 0; mant_size--) {
|
||||||
|
c = *p;
|
||||||
|
p++;
|
||||||
|
if (c == _T('.'))
|
||||||
|
{
|
||||||
|
c = *p;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
frac2 = 10*frac2 + (c - _T('0'));
|
||||||
|
}
|
||||||
|
fraction = (1.0e9 * frac1) + frac2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skim off the exponent */
|
||||||
|
p = pexp;
|
||||||
|
if ((*p == _T('E')) || (*p == _T('e')))
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
if (*p == _T('-'))
|
||||||
|
{
|
||||||
|
exp_negative = 1;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*p == _T('+')) p++;
|
||||||
|
exp_negative = 0;
|
||||||
|
}
|
||||||
|
if (!AWK_ISDIGIT(awk, *p))
|
||||||
|
{
|
||||||
|
/* p = pexp; */
|
||||||
|
/* goto done; */
|
||||||
|
goto no_exp;
|
||||||
|
}
|
||||||
|
while (AWK_ISDIGIT(awk, *p))
|
||||||
|
{
|
||||||
|
exp = exp * 10 + (*p - _T('0'));
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
no_exp:
|
||||||
|
if (exp_negative) exp = frac_exp - exp;
|
||||||
|
else exp = frac_exp + exp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate a floating-point number that represents the exponent.
|
||||||
|
* Do this by processing the exponent one bit at a time to combine
|
||||||
|
* many powers of 2 of 10. Then combine the exponent with the
|
||||||
|
* fraction.
|
||||||
|
*/
|
||||||
|
if (exp < 0)
|
||||||
|
{
|
||||||
|
exp_negative = 1;
|
||||||
|
exp = -exp;
|
||||||
|
}
|
||||||
|
else exp_negative = 0;
|
||||||
|
|
||||||
|
if (exp > MAX_EXPONENT) exp = MAX_EXPONENT;
|
||||||
|
|
||||||
|
dbl_exp = 1.0;
|
||||||
|
|
||||||
|
for (d = powers_of_10; exp != 0; exp >>= 1, d++)
|
||||||
|
{
|
||||||
|
if (exp & 01) dbl_exp *= *d;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp_negative) fraction /= dbl_exp;
|
||||||
|
else fraction *= dbl_exp;
|
||||||
|
|
||||||
|
done:
|
||||||
|
return (negative)? -fraction: fraction;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_awk_flt_t awk_strxtoflt (qse_awk_t* awk, const char_t* str, qse_size_t len, const char_t** endptr)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Table giving binary powers of 10. Entry is 10^2^i.
|
||||||
|
* Used to convert decimal exponents into floating-point numbers.
|
||||||
|
*/
|
||||||
|
static qse_awk_flt_t powers_of_10[] =
|
||||||
|
{
|
||||||
|
10., 100., 1.0e4, 1.0e8, 1.0e16,
|
||||||
|
1.0e32, 1.0e64, 1.0e128, 1.0e256
|
||||||
|
};
|
||||||
|
|
||||||
|
qse_awk_flt_t fraction, dbl_exp, * d;
|
||||||
|
const char_t* p, * end;
|
||||||
|
cint_t c;
|
||||||
|
int exp = 0; /* Exponent read from "EX" field */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exponent that derives from the fractional part. Under normal
|
||||||
|
* circumstatnces, it is the negative of the number of digits in F.
|
||||||
|
* However, if I is very long, the last digits of I get dropped
|
||||||
|
* (otherwise a long I with a large negative exponent could cause an
|
||||||
|
* unnecessary overflow on I alone). In this case, frac_exp is
|
||||||
|
* incremented one for each dropped digit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int frac_exp;
|
||||||
|
int mant_size; /* Number of digits in mantissa. */
|
||||||
|
int dec_pt; /* Number of mantissa digits BEFORE decimal point */
|
||||||
|
const char_t *pexp; /* Temporarily holds location of exponent in string */
|
||||||
|
int negative = 0, exp_negative = 0;
|
||||||
|
|
||||||
|
p = str;
|
||||||
|
end = str + len;
|
||||||
|
|
||||||
|
/* Strip off leading blanks and check for a sign */
|
||||||
|
/*while (AWK_ISSPACE(awk,*p)) p++;*/
|
||||||
|
|
||||||
|
/*while (*p != _T('\0')) */
|
||||||
|
while (p < end)
|
||||||
|
{
|
||||||
|
if (*p == _T('-'))
|
||||||
|
{
|
||||||
|
negative = ~negative;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
else if (*p == _T('+')) p++;
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Count the number of digits in the mantissa (including the decimal
|
||||||
|
* point), and also locate the decimal point. */
|
||||||
|
dec_pt = -1;
|
||||||
|
/*for (mant_size = 0; ; mant_size++) */
|
||||||
|
for (mant_size = 0; p < end; mant_size++)
|
||||||
|
{
|
||||||
|
c = *p;
|
||||||
|
if (!AWK_ISDIGIT(awk, c))
|
||||||
|
{
|
||||||
|
if (c != _T('.') || dec_pt >= 0) break;
|
||||||
|
dec_pt = mant_size;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now suck up the digits in the mantissa. Use two integers to
|
||||||
|
* collect 9 digits each (this is faster than using floating-point).
|
||||||
|
* If the mantissa has more than 18 digits, ignore the extras, since
|
||||||
|
* they can't affect the value anyway.
|
||||||
|
*/
|
||||||
|
pexp = p;
|
||||||
|
p -= mant_size;
|
||||||
|
if (dec_pt < 0)
|
||||||
|
{
|
||||||
|
dec_pt = mant_size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mant_size--; /* One of the digits was the point */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mant_size > 18) /* TODO: is 18 correct for qse_awk_flt_t??? */
|
||||||
|
{
|
||||||
|
frac_exp = dec_pt - 18;
|
||||||
|
mant_size = 18;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
frac_exp = dec_pt - mant_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mant_size == 0)
|
||||||
|
{
|
||||||
|
fraction = 0.0;
|
||||||
|
/*p = str;*/
|
||||||
|
p = pexp;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int frac1, frac2;
|
||||||
|
|
||||||
|
frac1 = 0;
|
||||||
|
for ( ; mant_size > 9; mant_size--)
|
||||||
|
{
|
||||||
|
c = *p;
|
||||||
|
p++;
|
||||||
|
if (c == _T('.'))
|
||||||
|
{
|
||||||
|
c = *p;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
frac1 = 10 * frac1 + (c - _T('0'));
|
||||||
|
}
|
||||||
|
|
||||||
|
frac2 = 0;
|
||||||
|
for (; mant_size > 0; mant_size--) {
|
||||||
|
c = *p++;
|
||||||
|
if (c == _T('.'))
|
||||||
|
{
|
||||||
|
c = *p;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
frac2 = 10 * frac2 + (c - _T('0'));
|
||||||
|
}
|
||||||
|
fraction = (1.0e9 * frac1) + frac2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skim off the exponent */
|
||||||
|
p = pexp;
|
||||||
|
if (p < end && (*p == _T('E') || *p == _T('e')))
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
|
||||||
|
if (p < end)
|
||||||
|
{
|
||||||
|
if (*p == _T('-'))
|
||||||
|
{
|
||||||
|
exp_negative = 1;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*p == _T('+')) p++;
|
||||||
|
exp_negative = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else exp_negative = 0;
|
||||||
|
|
||||||
|
if (!(p < end && AWK_ISDIGIT(awk, *p)))
|
||||||
|
{
|
||||||
|
/*p = pexp;*/
|
||||||
|
/*goto done;*/
|
||||||
|
goto no_exp;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (p < end && AWK_ISDIGIT(awk, *p))
|
||||||
|
{
|
||||||
|
exp = exp * 10 + (*p - _T('0'));
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
no_exp:
|
||||||
|
if (exp_negative) exp = frac_exp - exp;
|
||||||
|
else exp = frac_exp + exp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate a floating-point number that represents the exponent.
|
||||||
|
* Do this by processing the exponent one bit at a time to combine
|
||||||
|
* many powers of 2 of 10. Then combine the exponent with the
|
||||||
|
* fraction.
|
||||||
|
*/
|
||||||
|
if (exp < 0)
|
||||||
|
{
|
||||||
|
exp_negative = 1;
|
||||||
|
exp = -exp;
|
||||||
|
}
|
||||||
|
else exp_negative = 0;
|
||||||
|
|
||||||
|
if (exp > MAX_EXPONENT) exp = MAX_EXPONENT;
|
||||||
|
|
||||||
|
dbl_exp = 1.0;
|
||||||
|
|
||||||
|
for (d = powers_of_10; exp != 0; exp >>= 1, d++)
|
||||||
|
{
|
||||||
|
if (exp & 01) dbl_exp *= *d;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp_negative) fraction /= dbl_exp;
|
||||||
|
else fraction *= dbl_exp;
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (endptr != QSE_NULL) *endptr = p;
|
||||||
|
return (negative)? -fraction: fraction;
|
||||||
|
}
|
@ -82,510 +82,57 @@ qse_char_t* qse_awk_cstrdup (qse_awk_t* awk, const qse_cstr_t* s)
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_awk_int_t qse_awk_strxtoint (
|
/* ========================================================================= */
|
||||||
qse_awk_t* awk, const qse_char_t* str, qse_size_t len,
|
#undef awk_strxtoint
|
||||||
int base, const qse_char_t** endptr)
|
#undef awk_strtoflt
|
||||||
{
|
#undef awk_strxtoflt
|
||||||
qse_awk_int_t n = 0;
|
#undef char_t
|
||||||
const qse_char_t* p;
|
#undef cint_t
|
||||||
const qse_char_t* end;
|
#undef AWK_ISSPACE
|
||||||
qse_size_t rem;
|
#undef AWK_ISDIGIT
|
||||||
int digit, negative = 0;
|
#undef _T
|
||||||
|
|
||||||
QSE_ASSERT (base < 37);
|
#define awk_strxtoint qse_awk_mbsxtoint
|
||||||
|
#define awk_strtoflt qse_awk_mbstoflt
|
||||||
|
#define awk_strxtoflt qse_awk_mbsxtoflt
|
||||||
|
#define char_t qse_mchar_t
|
||||||
|
#define cint_t qse_mcint_t
|
||||||
|
#define AWK_ISSPACE QSE_AWK_ISMSPACE
|
||||||
|
#define AWK_ISDIGIT QSE_AWK_ISMDIGIT
|
||||||
|
#define _T QSE_MT
|
||||||
|
#include "misc-imp.h"
|
||||||
|
|
||||||
p = str;
|
/* ------------------------------------------------------------------------- */
|
||||||
end = str + len;
|
#undef awk_strxtoint
|
||||||
|
#undef awk_strtoflt
|
||||||
if (awk->opt.trait & QSE_AWK_STRIPSTRSPC)
|
#undef awk_strxtoflt
|
||||||
{
|
#undef char_t
|
||||||
/* strip off leading spaces */
|
#undef cint_t
|
||||||
while (p < end && QSE_AWK_ISSPACE(awk,*p)) p++;
|
#undef AWK_ISSPACE
|
||||||
}
|
#undef AWK_ISDIGIT
|
||||||
|
#undef _T
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* check for a sign */
|
#define awk_strxtoint qse_awk_wcsxtoint
|
||||||
while (p < end)
|
#define awk_strtoflt qse_awk_wcstoflt
|
||||||
{
|
#define awk_strxtoflt qse_awk_wcsxtoflt
|
||||||
if (*p == QSE_T('-'))
|
#define char_t qse_wchar_t
|
||||||
{
|
#define cint_t qse_wcint_t
|
||||||
negative = ~negative;
|
#define AWK_ISSPACE QSE_AWK_ISWSPACE
|
||||||
p++;
|
#define AWK_ISDIGIT QSE_AWK_ISWDIGIT
|
||||||
}
|
#define _T QSE_WT
|
||||||
else if (*p == QSE_T('+')) p++;
|
#include "misc-imp.h"
|
||||||
else break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check for a binary/octal/hexadecimal notation */
|
#undef awk_strxtoint
|
||||||
rem = end - p;
|
#undef awk_strtoflt
|
||||||
if (base == 0)
|
#undef awk_strxtoflt
|
||||||
{
|
#undef char_t
|
||||||
if (rem >= 1 && *p == QSE_T('0'))
|
#undef cint_t
|
||||||
{
|
#undef AWK_ISSPACE
|
||||||
p++;
|
#undef AWK_ISDIGIT
|
||||||
|
#undef _T
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
if (rem == 1) base = 8;
|
|
||||||
else if (*p == QSE_T('x') || *p == QSE_T('X'))
|
|
||||||
{
|
|
||||||
p++; base = 16;
|
|
||||||
}
|
|
||||||
else if (*p == QSE_T('b') || *p == QSE_T('B'))
|
|
||||||
{
|
|
||||||
p++; base = 2;
|
|
||||||
}
|
|
||||||
else base = 8;
|
|
||||||
}
|
|
||||||
else base = 10;
|
|
||||||
}
|
|
||||||
else if (rem >= 2 && base == 16)
|
|
||||||
{
|
|
||||||
if (*p == QSE_T('0') &&
|
|
||||||
(*(p+1) == QSE_T('x') || *(p+1) == QSE_T('X'))) p += 2;
|
|
||||||
}
|
|
||||||
else if (rem >= 2 && base == 2)
|
|
||||||
{
|
|
||||||
if (*p == QSE_T('0') &&
|
|
||||||
(*(p+1) == QSE_T('b') || *(p+1) == QSE_T('B'))) p += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* process the digits */
|
|
||||||
while (p < end)
|
|
||||||
{
|
|
||||||
if (*p >= QSE_T('0') && *p <= QSE_T('9'))
|
|
||||||
digit = *p - QSE_T('0');
|
|
||||||
else if (*p >= QSE_T('A') && *p <= QSE_T('Z'))
|
|
||||||
digit = *p - QSE_T('A') + 10;
|
|
||||||
else if (*p >= QSE_T('a') && *p <= QSE_T('z'))
|
|
||||||
digit = *p - QSE_T('a') + 10;
|
|
||||||
else break;
|
|
||||||
|
|
||||||
if (digit >= base) break;
|
|
||||||
n = n * base + digit;
|
|
||||||
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (endptr) *endptr = p;
|
|
||||||
return (negative)? -n: n;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* qse_awk_strtoflt is almost a replica of strtod.
|
|
||||||
*
|
|
||||||
* strtod.c --
|
|
||||||
*
|
|
||||||
* Source code for the "strtod" library procedure.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1988-1993 The Regents of the University of California.
|
|
||||||
* Copyright (c) 1994 Sun Microsystems, Inc.
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this
|
|
||||||
* software and its documentation for any purpose and without
|
|
||||||
* fee is hereby granted, provided that the above copyright
|
|
||||||
* notice appear in all copies. The University of California
|
|
||||||
* makes no representations about the suitability of this
|
|
||||||
* software for any purpose. It is provided "as is" without
|
|
||||||
* express or implied warranty.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* double(64bits) extended(80-bits) quadruple(128-bits)
|
|
||||||
* exponent 11 bits 15 bits 15 bits
|
|
||||||
* fraction 52 bits 63 bits 112 bits
|
|
||||||
* sign 1 bit 1 bit 1 bit
|
|
||||||
* integer 1 bit
|
|
||||||
*/
|
|
||||||
#define MAX_EXPONENT 511
|
|
||||||
|
|
||||||
qse_awk_flt_t qse_awk_strtoflt (qse_awk_t* awk, const qse_char_t* str)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Table giving binary powers of 10. Entry is 10^2^i.
|
|
||||||
* Used to convert decimal exponents into floating-point numbers.
|
|
||||||
*/
|
|
||||||
static qse_awk_flt_t powers_of_10[] =
|
|
||||||
{
|
|
||||||
10., 100., 1.0e4, 1.0e8, 1.0e16,
|
|
||||||
1.0e32, 1.0e64, 1.0e128, 1.0e256
|
|
||||||
};
|
|
||||||
|
|
||||||
qse_awk_flt_t fraction, dbl_exp, * d;
|
|
||||||
const qse_char_t* p;
|
|
||||||
qse_cint_t c;
|
|
||||||
int exp = 0; /* Exponent read from "EX" field */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Exponent that derives from the fractional part. Under normal
|
|
||||||
* circumstatnces, it is the negative of the number of digits in F.
|
|
||||||
* However, if I is very long, the last digits of I get dropped
|
|
||||||
* (otherwise a long I with a large negative exponent could cause an
|
|
||||||
* unnecessary overflow on I alone). In this case, frac_exp is
|
|
||||||
* incremented one for each dropped digit.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int frac_exp;
|
|
||||||
int mant_size; /* Number of digits in mantissa. */
|
|
||||||
int dec_pt; /* Number of mantissa digits BEFORE decimal point */
|
|
||||||
const qse_char_t *pexp; /* Temporarily holds location of exponent in string */
|
|
||||||
int negative = 0, exp_negative = 0;
|
|
||||||
|
|
||||||
p = str;
|
|
||||||
|
|
||||||
if (awk->opt.trait & QSE_AWK_STRIPSTRSPC)
|
|
||||||
{
|
|
||||||
/* strip off leading spaces */
|
|
||||||
while (QSE_AWK_ISSPACE(awk,*p)) p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check for a sign */
|
|
||||||
while (*p != QSE_T('\0'))
|
|
||||||
{
|
|
||||||
if (*p == QSE_T('-'))
|
|
||||||
{
|
|
||||||
negative = ~negative;
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
else if (*p == QSE_T('+')) p++;
|
|
||||||
else break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Count the number of digits in the mantissa (including the decimal
|
|
||||||
* point), and also locate the decimal point. */
|
|
||||||
dec_pt = -1;
|
|
||||||
for (mant_size = 0; ; mant_size++)
|
|
||||||
{
|
|
||||||
c = *p;
|
|
||||||
if (!QSE_AWK_ISDIGIT (awk, c))
|
|
||||||
{
|
|
||||||
if ((c != QSE_T('.')) || (dec_pt >= 0)) break;
|
|
||||||
dec_pt = mant_size;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now suck up the digits in the mantissa. Use two integers to
|
|
||||||
* collect 9 digits each (this is faster than using floating-point).
|
|
||||||
* If the mantissa has more than 18 digits, ignore the extras, since
|
|
||||||
* they can't affect the value anyway.
|
|
||||||
*/
|
|
||||||
pexp = p;
|
|
||||||
p -= mant_size;
|
|
||||||
if (dec_pt < 0)
|
|
||||||
{
|
|
||||||
dec_pt = mant_size;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mant_size--; /* One of the digits was the point */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mant_size > 18)
|
|
||||||
{
|
|
||||||
frac_exp = dec_pt - 18;
|
|
||||||
mant_size = 18;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
frac_exp = dec_pt - mant_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mant_size == 0)
|
|
||||||
{
|
|
||||||
fraction = 0.0;
|
|
||||||
/*p = str;*/
|
|
||||||
p = pexp;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int frac1, frac2;
|
|
||||||
frac1 = 0;
|
|
||||||
for ( ; mant_size > 9; mant_size--)
|
|
||||||
{
|
|
||||||
c = *p;
|
|
||||||
p++;
|
|
||||||
if (c == QSE_T('.'))
|
|
||||||
{
|
|
||||||
c = *p;
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
frac1 = 10 * frac1 + (c - QSE_T('0'));
|
|
||||||
}
|
|
||||||
frac2 = 0;
|
|
||||||
for (; mant_size > 0; mant_size--) {
|
|
||||||
c = *p;
|
|
||||||
p++;
|
|
||||||
if (c == QSE_T('.'))
|
|
||||||
{
|
|
||||||
c = *p;
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
frac2 = 10*frac2 + (c - QSE_T('0'));
|
|
||||||
}
|
|
||||||
fraction = (1.0e9 * frac1) + frac2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skim off the exponent */
|
|
||||||
p = pexp;
|
|
||||||
if ((*p == QSE_T('E')) || (*p == QSE_T('e')))
|
|
||||||
{
|
|
||||||
p++;
|
|
||||||
if (*p == QSE_T('-'))
|
|
||||||
{
|
|
||||||
exp_negative = 1;
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (*p == QSE_T('+')) p++;
|
|
||||||
exp_negative = 0;
|
|
||||||
}
|
|
||||||
if (!QSE_AWK_ISDIGIT (awk, *p))
|
|
||||||
{
|
|
||||||
/* p = pexp; */
|
|
||||||
/* goto done; */
|
|
||||||
goto no_exp;
|
|
||||||
}
|
|
||||||
while (QSE_AWK_ISDIGIT (awk, *p))
|
|
||||||
{
|
|
||||||
exp = exp * 10 + (*p - QSE_T('0'));
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
no_exp:
|
|
||||||
if (exp_negative) exp = frac_exp - exp;
|
|
||||||
else exp = frac_exp + exp;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Generate a floating-point number that represents the exponent.
|
|
||||||
* Do this by processing the exponent one bit at a time to combine
|
|
||||||
* many powers of 2 of 10. Then combine the exponent with the
|
|
||||||
* fraction.
|
|
||||||
*/
|
|
||||||
if (exp < 0)
|
|
||||||
{
|
|
||||||
exp_negative = 1;
|
|
||||||
exp = -exp;
|
|
||||||
}
|
|
||||||
else exp_negative = 0;
|
|
||||||
|
|
||||||
if (exp > MAX_EXPONENT) exp = MAX_EXPONENT;
|
|
||||||
|
|
||||||
dbl_exp = 1.0;
|
|
||||||
|
|
||||||
for (d = powers_of_10; exp != 0; exp >>= 1, d++)
|
|
||||||
{
|
|
||||||
if (exp & 01) dbl_exp *= *d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exp_negative) fraction /= dbl_exp;
|
|
||||||
else fraction *= dbl_exp;
|
|
||||||
|
|
||||||
done:
|
|
||||||
return (negative)? -fraction: fraction;
|
|
||||||
}
|
|
||||||
|
|
||||||
qse_awk_flt_t qse_awk_strxtoflt (
|
|
||||||
qse_awk_t* awk, const qse_char_t* str, qse_size_t len,
|
|
||||||
const qse_char_t** endptr)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Table giving binary powers of 10. Entry is 10^2^i.
|
|
||||||
* Used to convert decimal exponents into floating-point numbers.
|
|
||||||
*/
|
|
||||||
static qse_awk_flt_t powers_of_10[] =
|
|
||||||
{
|
|
||||||
10., 100., 1.0e4, 1.0e8, 1.0e16,
|
|
||||||
1.0e32, 1.0e64, 1.0e128, 1.0e256
|
|
||||||
};
|
|
||||||
|
|
||||||
qse_awk_flt_t fraction, dbl_exp, * d;
|
|
||||||
const qse_char_t* p, * end;
|
|
||||||
qse_cint_t c;
|
|
||||||
int exp = 0; /* Exponent read from "EX" field */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Exponent that derives from the fractional part. Under normal
|
|
||||||
* circumstatnces, it is the negative of the number of digits in F.
|
|
||||||
* However, if I is very long, the last digits of I get dropped
|
|
||||||
* (otherwise a long I with a large negative exponent could cause an
|
|
||||||
* unnecessary overflow on I alone). In this case, frac_exp is
|
|
||||||
* incremented one for each dropped digit.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int frac_exp;
|
|
||||||
int mant_size; /* Number of digits in mantissa. */
|
|
||||||
int dec_pt; /* Number of mantissa digits BEFORE decimal point */
|
|
||||||
const qse_char_t *pexp; /* Temporarily holds location of exponent in string */
|
|
||||||
int negative = 0, exp_negative = 0;
|
|
||||||
|
|
||||||
p = str;
|
|
||||||
end = str + len;
|
|
||||||
|
|
||||||
/* Strip off leading blanks and check for a sign */
|
|
||||||
/*while (QSE_AWK_ISSPACE(awk,*p)) p++;*/
|
|
||||||
|
|
||||||
/*while (*p != QSE_T('\0')) */
|
|
||||||
while (p < end)
|
|
||||||
{
|
|
||||||
if (*p == QSE_T('-'))
|
|
||||||
{
|
|
||||||
negative = ~negative;
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
else if (*p == QSE_T('+')) p++;
|
|
||||||
else break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Count the number of digits in the mantissa (including the decimal
|
|
||||||
* point), and also locate the decimal point. */
|
|
||||||
dec_pt = -1;
|
|
||||||
/*for (mant_size = 0; ; mant_size++) */
|
|
||||||
for (mant_size = 0; p < end; mant_size++)
|
|
||||||
{
|
|
||||||
c = *p;
|
|
||||||
if (!QSE_AWK_ISDIGIT (awk, c))
|
|
||||||
{
|
|
||||||
if (c != QSE_T('.') || dec_pt >= 0) break;
|
|
||||||
dec_pt = mant_size;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now suck up the digits in the mantissa. Use two integers to
|
|
||||||
* collect 9 digits each (this is faster than using floating-point).
|
|
||||||
* If the mantissa has more than 18 digits, ignore the extras, since
|
|
||||||
* they can't affect the value anyway.
|
|
||||||
*/
|
|
||||||
pexp = p;
|
|
||||||
p -= mant_size;
|
|
||||||
if (dec_pt < 0)
|
|
||||||
{
|
|
||||||
dec_pt = mant_size;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mant_size--; /* One of the digits was the point */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mant_size > 18) /* TODO: is 18 correct for qse_awk_flt_t??? */
|
|
||||||
{
|
|
||||||
frac_exp = dec_pt - 18;
|
|
||||||
mant_size = 18;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
frac_exp = dec_pt - mant_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mant_size == 0)
|
|
||||||
{
|
|
||||||
fraction = 0.0;
|
|
||||||
/*p = str;*/
|
|
||||||
p = pexp;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int frac1, frac2;
|
|
||||||
|
|
||||||
frac1 = 0;
|
|
||||||
for ( ; mant_size > 9; mant_size--)
|
|
||||||
{
|
|
||||||
c = *p;
|
|
||||||
p++;
|
|
||||||
if (c == QSE_T('.'))
|
|
||||||
{
|
|
||||||
c = *p;
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
frac1 = 10 * frac1 + (c - QSE_T('0'));
|
|
||||||
}
|
|
||||||
|
|
||||||
frac2 = 0;
|
|
||||||
for (; mant_size > 0; mant_size--) {
|
|
||||||
c = *p++;
|
|
||||||
if (c == QSE_T('.'))
|
|
||||||
{
|
|
||||||
c = *p;
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
frac2 = 10 * frac2 + (c - QSE_T('0'));
|
|
||||||
}
|
|
||||||
fraction = (1.0e9 * frac1) + frac2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skim off the exponent */
|
|
||||||
p = pexp;
|
|
||||||
if (p < end && (*p == QSE_T('E') || *p == QSE_T('e')))
|
|
||||||
{
|
|
||||||
p++;
|
|
||||||
|
|
||||||
if (p < end)
|
|
||||||
{
|
|
||||||
if (*p == QSE_T('-'))
|
|
||||||
{
|
|
||||||
exp_negative = 1;
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (*p == QSE_T('+')) p++;
|
|
||||||
exp_negative = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else exp_negative = 0;
|
|
||||||
|
|
||||||
if (!(p < end && QSE_AWK_ISDIGIT (awk, *p)))
|
|
||||||
{
|
|
||||||
/*p = pexp;*/
|
|
||||||
/*goto done;*/
|
|
||||||
goto no_exp;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (p < end && QSE_AWK_ISDIGIT (awk, *p))
|
|
||||||
{
|
|
||||||
exp = exp * 10 + (*p - QSE_T('0'));
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
no_exp:
|
|
||||||
if (exp_negative) exp = frac_exp - exp;
|
|
||||||
else exp = frac_exp + exp;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Generate a floating-point number that represents the exponent.
|
|
||||||
* Do this by processing the exponent one bit at a time to combine
|
|
||||||
* many powers of 2 of 10. Then combine the exponent with the
|
|
||||||
* fraction.
|
|
||||||
*/
|
|
||||||
if (exp < 0)
|
|
||||||
{
|
|
||||||
exp_negative = 1;
|
|
||||||
exp = -exp;
|
|
||||||
}
|
|
||||||
else exp_negative = 0;
|
|
||||||
|
|
||||||
if (exp > MAX_EXPONENT) exp = MAX_EXPONENT;
|
|
||||||
|
|
||||||
dbl_exp = 1.0;
|
|
||||||
|
|
||||||
for (d = powers_of_10; exp != 0; exp >>= 1, d++)
|
|
||||||
{
|
|
||||||
if (exp & 01) dbl_exp *= *d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exp_negative) fraction /= dbl_exp;
|
|
||||||
else fraction *= dbl_exp;
|
|
||||||
|
|
||||||
done:
|
|
||||||
if (endptr != QSE_NULL) *endptr = p;
|
|
||||||
return (negative)? -fraction: fraction;
|
|
||||||
}
|
|
||||||
|
|
||||||
qse_size_t qse_awk_inttostr (
|
qse_size_t qse_awk_inttostr (
|
||||||
qse_awk_t* awk, qse_awk_int_t value,
|
qse_awk_t* awk, qse_awk_int_t value,
|
||||||
|
@ -5571,7 +5571,7 @@ static int get_number (qse_awk_t* awk, qse_awk_tok_t* tok)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (QSE_AWK_ISDIGIT (awk, c))
|
while (QSE_AWK_ISDIGIT(awk, c))
|
||||||
{
|
{
|
||||||
ADD_TOKEN_CHAR (awk, tok, c);
|
ADD_TOKEN_CHAR (awk, tok, c);
|
||||||
GET_CHAR_TO (awk, c);
|
GET_CHAR_TO (awk, c);
|
||||||
@ -5585,7 +5585,7 @@ static int get_number (qse_awk_t* awk, qse_awk_tok_t* tok)
|
|||||||
ADD_TOKEN_CHAR (awk, tok, c);
|
ADD_TOKEN_CHAR (awk, tok, c);
|
||||||
GET_CHAR_TO (awk, c);
|
GET_CHAR_TO (awk, c);
|
||||||
|
|
||||||
while (QSE_AWK_ISDIGIT (awk, c))
|
while (QSE_AWK_ISDIGIT(awk, c))
|
||||||
{
|
{
|
||||||
ADD_TOKEN_CHAR (awk, tok, c);
|
ADD_TOKEN_CHAR (awk, tok, c);
|
||||||
GET_CHAR_TO (awk, c);
|
GET_CHAR_TO (awk, c);
|
||||||
@ -5605,7 +5605,7 @@ static int get_number (qse_awk_t* awk, qse_awk_tok_t* tok)
|
|||||||
GET_CHAR_TO (awk, c);
|
GET_CHAR_TO (awk, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (QSE_AWK_ISDIGIT (awk, c))
|
while (QSE_AWK_ISDIGIT(awk, c))
|
||||||
{
|
{
|
||||||
ADD_TOKEN_CHAR (awk, tok, c);
|
ADD_TOKEN_CHAR (awk, tok, c);
|
||||||
GET_CHAR_TO (awk, c);
|
GET_CHAR_TO (awk, c);
|
||||||
@ -5879,7 +5879,7 @@ static int skip_spaces (qse_awk_t* awk)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (QSE_AWK_ISSPACE (awk, c)) GET_CHAR_TO (awk, c);
|
while (QSE_AWK_ISSPACE(awk, c)) GET_CHAR_TO (awk, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -6105,7 +6105,7 @@ retry:
|
|||||||
SET_TOKEN_TYPE (awk, tok, TOK_NEWLINE);
|
SET_TOKEN_TYPE (awk, tok, TOK_NEWLINE);
|
||||||
GET_CHAR (awk);
|
GET_CHAR (awk);
|
||||||
}
|
}
|
||||||
else if (QSE_AWK_ISDIGIT (awk, c)/*|| c == QSE_T('.')*/)
|
else if (QSE_AWK_ISDIGIT(awk, c)/*|| c == QSE_T('.')*/)
|
||||||
{
|
{
|
||||||
if (get_number (awk, tok) <= -1) return -1;
|
if (get_number (awk, tok) <= -1) return -1;
|
||||||
}
|
}
|
||||||
@ -6119,7 +6119,7 @@ retry:
|
|||||||
unget_char (awk, &awk->sio.last);
|
unget_char (awk, &awk->sio.last);
|
||||||
awk->sio.last = lc;
|
awk->sio.last = lc;
|
||||||
|
|
||||||
if (QSE_AWK_ISDIGIT (awk, c))
|
if (QSE_AWK_ISDIGIT(awk, c))
|
||||||
{
|
{
|
||||||
/* for a token such as .123 */
|
/* for a token such as .123 */
|
||||||
if (get_number (awk, tok) <= -1) return -1;
|
if (get_number (awk, tok) <= -1) return -1;
|
||||||
@ -6137,7 +6137,7 @@ retry:
|
|||||||
ADD_TOKEN_CHAR (awk, tok, c);
|
ADD_TOKEN_CHAR (awk, tok, c);
|
||||||
GET_CHAR_TO (awk, c);
|
GET_CHAR_TO (awk, c);
|
||||||
|
|
||||||
if (c != QSE_T('_') && !QSE_AWK_ISALPHA (awk, c))
|
if (c != QSE_T('_') && !QSE_AWK_ISALPHA(awk, c))
|
||||||
{
|
{
|
||||||
/* this extended keyword is empty,
|
/* this extended keyword is empty,
|
||||||
* not followed by a valid word */
|
* not followed by a valid word */
|
||||||
@ -6152,8 +6152,8 @@ retry:
|
|||||||
GET_CHAR_TO (awk, c);
|
GET_CHAR_TO (awk, c);
|
||||||
}
|
}
|
||||||
while (c == QSE_T('_') ||
|
while (c == QSE_T('_') ||
|
||||||
QSE_AWK_ISALPHA (awk, c) ||
|
QSE_AWK_ISALPHA(awk, c) ||
|
||||||
QSE_AWK_ISDIGIT (awk, c));
|
QSE_AWK_ISDIGIT(awk, c));
|
||||||
|
|
||||||
type = classify_ident (awk, QSE_STR_XSTR(tok->name));
|
type = classify_ident (awk, QSE_STR_XSTR(tok->name));
|
||||||
if (type == TOK_IDENT)
|
if (type == TOK_IDENT)
|
||||||
@ -6163,7 +6163,7 @@ retry:
|
|||||||
}
|
}
|
||||||
SET_TOKEN_TYPE (awk, tok, type);
|
SET_TOKEN_TYPE (awk, tok, type);
|
||||||
}
|
}
|
||||||
else if (c == QSE_T('_') || QSE_AWK_ISALPHA (awk, c))
|
else if (c == QSE_T('_') || QSE_AWK_ISALPHA(awk, c))
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
@ -6174,8 +6174,8 @@ retry:
|
|||||||
GET_CHAR_TO (awk, c);
|
GET_CHAR_TO (awk, c);
|
||||||
}
|
}
|
||||||
while (c == QSE_T('_') ||
|
while (c == QSE_T('_') ||
|
||||||
QSE_AWK_ISALPHA (awk, c) ||
|
QSE_AWK_ISALPHA(awk, c) ||
|
||||||
QSE_AWK_ISDIGIT (awk, c));
|
QSE_AWK_ISDIGIT(awk, c));
|
||||||
|
|
||||||
type = classify_ident (awk, QSE_STR_XSTR(tok->name));
|
type = classify_ident (awk, QSE_STR_XSTR(tok->name));
|
||||||
SET_TOKEN_TYPE (awk, tok, type);
|
SET_TOKEN_TYPE (awk, tok, type);
|
||||||
|
49
qse/lib/awk/val-imp.h
Normal file
49
qse/lib/awk/val-imp.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
|
||||||
|
int awk_rtx_strtonum (qse_awk_rtx_t* rtx, int option, const char_t* ptr, qse_size_t len, qse_awk_int_t* l, qse_awk_flt_t* r)
|
||||||
|
{
|
||||||
|
const char_t* endptr;
|
||||||
|
const char_t* end;
|
||||||
|
|
||||||
|
int strict = QSE_AWK_RTX_STRTONUM_GET_OPTION_STRICT(option);
|
||||||
|
int base = QSE_AWK_RTX_STRTONUN_GET_OPTION_BASE(option);
|
||||||
|
|
||||||
|
end = ptr + len;
|
||||||
|
*l = awk_strxtoint(rtx->awk, ptr, len, base, &endptr);
|
||||||
|
if (endptr < end)
|
||||||
|
{
|
||||||
|
if (*endptr == _T('.') || *endptr == _T('E') || *endptr == _T('e'))
|
||||||
|
{
|
||||||
|
handle_float:
|
||||||
|
*r = awk_strxtoflt(rtx->awk, ptr, len, &endptr);
|
||||||
|
if (strict && endptr < end) return -1;
|
||||||
|
return 1; /* flt */
|
||||||
|
}
|
||||||
|
else if (AWK_ISDIGIT(awk, *endptr))
|
||||||
|
{
|
||||||
|
const char_t* p = endptr;
|
||||||
|
do { p++; } while (p < end && AWK_ISDIGIT(awk, *p));
|
||||||
|
if (p < end && (*p == _T('.') || *p == _T('E') || *p == _T('e')))
|
||||||
|
{
|
||||||
|
/* it's probably an floating-point number.
|
||||||
|
*
|
||||||
|
* BEGIN { b=99; printf "%f\n", (0 b 1.112); }
|
||||||
|
*
|
||||||
|
* for the above code, this function gets '0991.112'.
|
||||||
|
* and endptr points to '9' after qse_awk_strxtoint() as
|
||||||
|
* the numeric string beginning with 0 is treated
|
||||||
|
* as an octal number.
|
||||||
|
*
|
||||||
|
* getting side-tracked,
|
||||||
|
* BEGIN { b=99; printf "%f\n", (0 b 1.000); }
|
||||||
|
* the above code cause this function to get 0991, not 0991.000
|
||||||
|
* because of the default CONVFMT '%.6g' which doesn't produce '.000'.
|
||||||
|
* so such a number is not treated as a floating-point number.
|
||||||
|
*/
|
||||||
|
goto handle_float;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strict && endptr < end) return -1;
|
||||||
|
return 0; /* int */
|
||||||
|
}
|
@ -1420,8 +1420,7 @@ int qse_awk_rtx_valtostr (
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_char_t* qse_awk_rtx_valtostrdup (
|
qse_char_t* qse_awk_rtx_valtostrdup (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_size_t* len)
|
||||||
qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_size_t* len)
|
|
||||||
{
|
{
|
||||||
qse_awk_rtx_valtostr_out_t out;
|
qse_awk_rtx_valtostr_out_t out;
|
||||||
|
|
||||||
@ -1432,14 +1431,13 @@ qse_char_t* qse_awk_rtx_valtostrdup (
|
|||||||
return out.u.cpldup.ptr;
|
return out.u.cpldup.ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_mchar_t* qse_awk_rtx_valtombsdup (
|
qse_mchar_t* qse_awk_rtx_valtombsdup (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_size_t* len)
|
||||||
qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_size_t* len)
|
|
||||||
{
|
{
|
||||||
#if defined(QSE_CHAR_IS_MCHAR)
|
#if defined(QSE_CHAR_IS_MCHAR)
|
||||||
qse_awk_rtx_valtostr_out_t out;
|
qse_awk_rtx_valtostr_out_t out;
|
||||||
|
|
||||||
out.type = QSE_AWK_RTX_VALTOSTR_CPLDUP;
|
out.type = QSE_AWK_RTX_VALTOSTR_CPLDUP;
|
||||||
if (qse_awk_rtx_valtostr (rtx, v, &out) <= -1) return QSE_NULL;
|
if (qse_awk_rtx_valtostr(rtx, v, &out) <= -1) return QSE_NULL;
|
||||||
|
|
||||||
if (len) *len = out.u.cpldup.len;
|
if (len) *len = out.u.cpldup.len;
|
||||||
return out.u.cpldup.ptr;
|
return out.u.cpldup.ptr;
|
||||||
@ -1448,16 +1446,15 @@ qse_mchar_t* qse_awk_rtx_valtombsdup (
|
|||||||
qse_mchar_t* mbs;
|
qse_mchar_t* mbs;
|
||||||
|
|
||||||
out.type = QSE_AWK_RTX_VALTOSTR_CPLDUP;
|
out.type = QSE_AWK_RTX_VALTOSTR_CPLDUP;
|
||||||
if (qse_awk_rtx_valtostr (rtx, v, &out) <= -1) return QSE_NULL;
|
if (qse_awk_rtx_valtostr(rtx, v, &out) <= -1) return QSE_NULL;
|
||||||
|
|
||||||
mbs = qse_wcsntombsdup (out.u.cpldup.ptr, out.u.cpldup.len, len, rtx->awk->mmgr);
|
mbs = qse_wcsntombsdup(out.u.cpldup.ptr, out.u.cpldup.len, len, rtx->awk->mmgr);
|
||||||
QSE_AWK_FREE (rtx->awk, out.u.cpldup.ptr);
|
QSE_AWK_FREE (rtx->awk, out.u.cpldup.ptr);
|
||||||
return mbs;
|
return mbs;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_wchar_t* qse_awk_rtx_valtowcsdup (
|
qse_wchar_t* qse_awk_rtx_valtowcsdup (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_size_t* len)
|
||||||
qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_size_t* len)
|
|
||||||
{
|
{
|
||||||
#if defined(QSE_CHAR_IS_MCHAR)
|
#if defined(QSE_CHAR_IS_MCHAR)
|
||||||
qse_awk_rtx_valtostr_out_t out;
|
qse_awk_rtx_valtostr_out_t out;
|
||||||
@ -1480,8 +1477,7 @@ qse_wchar_t* qse_awk_rtx_valtowcsdup (
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_char_t* qse_awk_rtx_getvalstr (
|
qse_char_t* qse_awk_rtx_getvalstr (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_size_t* len)
|
||||||
qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_size_t* len)
|
|
||||||
{
|
{
|
||||||
if (QSE_AWK_RTX_GETVALTYPE(rtx, v) == QSE_AWK_VAL_STR)
|
if (QSE_AWK_RTX_GETVALTYPE(rtx, v) == QSE_AWK_VAL_STR)
|
||||||
{
|
{
|
||||||
@ -1494,8 +1490,7 @@ qse_char_t* qse_awk_rtx_getvalstr (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void qse_awk_rtx_freevalstr (
|
void qse_awk_rtx_freevalstr (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_char_t* str)
|
||||||
qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_char_t* str)
|
|
||||||
{
|
{
|
||||||
if (QSE_AWK_RTX_GETVALTYPE(rtx, v) != QSE_AWK_VAL_STR ||
|
if (QSE_AWK_RTX_GETVALTYPE(rtx, v) != QSE_AWK_VAL_STR ||
|
||||||
str != ((qse_awk_val_str_t*)v)->val.ptr)
|
str != ((qse_awk_val_str_t*)v)->val.ptr)
|
||||||
@ -1504,8 +1499,7 @@ void qse_awk_rtx_freevalstr (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int val_ref_to_num (
|
static int val_ref_to_num (qse_awk_rtx_t* rtx, const qse_awk_val_ref_t* ref, qse_awk_int_t* l, qse_awk_flt_t* r)
|
||||||
qse_awk_rtx_t* rtx, const qse_awk_val_ref_t* ref, qse_awk_int_t* l, qse_awk_flt_t* r)
|
|
||||||
{
|
{
|
||||||
switch (ref->id)
|
switch (ref->id)
|
||||||
{
|
{
|
||||||
@ -1516,7 +1510,7 @@ static int val_ref_to_num (
|
|||||||
idx = (qse_size_t)ref->adr;
|
idx = (qse_size_t)ref->adr;
|
||||||
if (idx == 0)
|
if (idx == 0)
|
||||||
{
|
{
|
||||||
return qse_awk_rtx_strtonum (
|
return qse_awk_rtx_strtonum(
|
||||||
rtx,
|
rtx,
|
||||||
QSE_AWK_RTX_STRTONUM_MAKE_OPTION(0, 0),
|
QSE_AWK_RTX_STRTONUM_MAKE_OPTION(0, 0),
|
||||||
QSE_STR_PTR(&rtx->inrec.line),
|
QSE_STR_PTR(&rtx->inrec.line),
|
||||||
@ -1526,7 +1520,7 @@ static int val_ref_to_num (
|
|||||||
}
|
}
|
||||||
else if (idx <= rtx->inrec.nflds)
|
else if (idx <= rtx->inrec.nflds)
|
||||||
{
|
{
|
||||||
return qse_awk_rtx_strtonum (
|
return qse_awk_rtx_strtonum(
|
||||||
rtx,
|
rtx,
|
||||||
QSE_AWK_RTX_STRTONUM_MAKE_OPTION(0, 0),
|
QSE_AWK_RTX_STRTONUM_MAKE_OPTION(0, 0),
|
||||||
rtx->inrec.flds[idx-1].ptr,
|
rtx->inrec.flds[idx-1].ptr,
|
||||||
@ -1536,7 +1530,7 @@ static int val_ref_to_num (
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return qse_awk_rtx_strtonum (
|
return qse_awk_rtx_strtonum(
|
||||||
rtx, QSE_AWK_RTX_STRTONUM_MAKE_OPTION(0, 0), QSE_T(""), 0, l, r
|
rtx, QSE_AWK_RTX_STRTONUM_MAKE_OPTION(0, 0), QSE_T(""), 0, l, r
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1558,14 +1552,13 @@ static int val_ref_to_num (
|
|||||||
QSE_ASSERT (QSE_AWK_RTX_GETVALTYPE (rtx, *xref) != QSE_AWK_VAL_REF);
|
QSE_ASSERT (QSE_AWK_RTX_GETVALTYPE (rtx, *xref) != QSE_AWK_VAL_REF);
|
||||||
|
|
||||||
/* make a recursive call back to the caller */
|
/* make a recursive call back to the caller */
|
||||||
return qse_awk_rtx_valtonum (rtx, *xref, l, r);
|
return qse_awk_rtx_valtonum(rtx, *xref, l, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int qse_awk_rtx_valtonum (
|
int qse_awk_rtx_valtonum (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_int_t* l, qse_awk_flt_t* r)
|
||||||
qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_int_t* l, qse_awk_flt_t* r)
|
|
||||||
{
|
{
|
||||||
qse_awk_val_type_t vtype = QSE_AWK_RTX_GETVALTYPE (rtx, v);
|
qse_awk_val_type_t vtype = QSE_AWK_RTX_GETVALTYPE (rtx, v);
|
||||||
|
|
||||||
@ -1600,8 +1593,6 @@ int qse_awk_rtx_valtonum (
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* TODO: */
|
|
||||||
case QSE_AWK_VAL_BYTEARR:
|
case QSE_AWK_VAL_BYTEARR:
|
||||||
{
|
{
|
||||||
return qse_awk_rtx_mbstonum (
|
return qse_awk_rtx_mbstonum (
|
||||||
@ -1612,7 +1603,6 @@ int qse_awk_rtx_valtonum (
|
|||||||
l, r
|
l, r
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
case QSE_AWK_VAL_MAP:
|
case QSE_AWK_VAL_MAP:
|
||||||
{
|
{
|
||||||
@ -1625,7 +1615,7 @@ int qse_awk_rtx_valtonum (
|
|||||||
|
|
||||||
case QSE_AWK_VAL_REF:
|
case QSE_AWK_VAL_REF:
|
||||||
{
|
{
|
||||||
return val_ref_to_num (rtx, (qse_awk_val_ref_t*)v, l, r);
|
return val_ref_to_num(rtx, (qse_awk_val_ref_t*)v, l, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1640,13 +1630,12 @@ int qse_awk_rtx_valtonum (
|
|||||||
return -1; /* error */
|
return -1; /* error */
|
||||||
}
|
}
|
||||||
|
|
||||||
int qse_awk_rtx_valtoint (
|
int qse_awk_rtx_valtoint (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_int_t* l)
|
||||||
qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_int_t* l)
|
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
qse_awk_flt_t r;
|
qse_awk_flt_t r;
|
||||||
|
|
||||||
n = qse_awk_rtx_valtonum (rtx, v, l, &r);
|
n = qse_awk_rtx_valtonum(rtx, v, l, &r);
|
||||||
if (n == 1)
|
if (n == 1)
|
||||||
{
|
{
|
||||||
*l = (qse_awk_int_t)r;
|
*l = (qse_awk_int_t)r;
|
||||||
@ -1656,70 +1645,58 @@ int qse_awk_rtx_valtoint (
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qse_awk_rtx_valtoflt (
|
int qse_awk_rtx_valtoflt (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_flt_t* r)
|
||||||
qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_flt_t* r)
|
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
qse_awk_int_t l;
|
qse_awk_int_t l;
|
||||||
|
|
||||||
n = qse_awk_rtx_valtonum (rtx, v, &l, r);
|
n = qse_awk_rtx_valtonum(rtx, v, &l, r);
|
||||||
if (n == 0) *r = (qse_awk_flt_t)l;
|
if (n == 0) *r = (qse_awk_flt_t)l;
|
||||||
else if (n == 1) n = 0;
|
else if (n == 1) n = 0;
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qse_awk_rtx_strtonum (
|
/* ========================================================================== */
|
||||||
qse_awk_rtx_t* rtx, int option,
|
#undef awk_rtx_strtonum
|
||||||
const qse_char_t* ptr, qse_size_t len,
|
#undef awk_strxtoint
|
||||||
qse_awk_int_t* l, qse_awk_flt_t* r)
|
#undef awk_strxtoflt
|
||||||
{
|
#undef char_t
|
||||||
const qse_char_t* endptr;
|
#undef AWK_ISDIGIT
|
||||||
const qse_char_t* end;
|
#undef _T
|
||||||
|
|
||||||
int strict = QSE_AWK_RTX_STRTONUM_GET_OPTION_STRICT(option);
|
#define awk_rtx_strtonum qse_awk_rtx_mbstonum
|
||||||
int base = QSE_AWK_RTX_STRTONUN_GET_OPTION_BASE(option);
|
#define awk_strxtoint qse_awk_mbsxtoint
|
||||||
|
#define awk_strxtoflt qse_awk_mbsxtoflt
|
||||||
|
#define char_t qse_mchar_t
|
||||||
|
#define AWK_ISDIGIT QSE_AWK_ISMDIGIT
|
||||||
|
#define _T QSE_MT
|
||||||
|
#include "val-imp.h"
|
||||||
|
|
||||||
end = ptr + len;
|
/* ------------------------------------------------------------------------- */
|
||||||
*l = qse_awk_strxtoint(rtx->awk, ptr, len, base, &endptr);
|
#undef awk_rtx_strtonum
|
||||||
if (endptr < end)
|
#undef awk_strxtoint
|
||||||
{
|
#undef awk_strxtoflt
|
||||||
if (*endptr == QSE_T('.') || *endptr == QSE_T('E') || *endptr == QSE_T('e'))
|
#undef char_t
|
||||||
{
|
#undef AWK_ISDIGIT
|
||||||
handle_float:
|
#undef _T
|
||||||
*r = qse_awk_strxtoflt (rtx->awk, ptr, len, &endptr);
|
/* ------------------------------------------------------------------------- */
|
||||||
if (strict && endptr < end) return -1;
|
|
||||||
return 1; /* flt */
|
|
||||||
}
|
|
||||||
else if (QSE_AWK_ISDIGIT(awk, *endptr))
|
|
||||||
{
|
|
||||||
const qse_char_t* p = endptr;
|
|
||||||
do { p++; } while (p < end && QSE_AWK_ISDIGIT(awk, *p));
|
|
||||||
if (p < end && (*p == QSE_T('.') || *p == QSE_T('E') || *p == QSE_T('e')))
|
|
||||||
{
|
|
||||||
/* it's probably an floating-point number.
|
|
||||||
*
|
|
||||||
* BEGIN { b=99; printf "%f\n", (0 b 1.112); }
|
|
||||||
*
|
|
||||||
* for the above code, this function gets '0991.112'.
|
|
||||||
* and endptr points to '9' after qse_awk_strxtoint() as
|
|
||||||
* the numeric string beginning with 0 is treated
|
|
||||||
* as an octal number.
|
|
||||||
*
|
|
||||||
* getting side-tracked,
|
|
||||||
* BEGIN { b=99; printf "%f\n", (0 b 1.000); }
|
|
||||||
* the above code cause this function to get 0991, not 0991.000
|
|
||||||
* because of the default CONVFMT '%.6g' which doesn't produce '.000'.
|
|
||||||
* so such a number is not treated as a floating-point number.
|
|
||||||
*/
|
|
||||||
goto handle_float;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strict && endptr < end) return -1;
|
#define awk_rtx_strtonum qse_awk_rtx_wcstonum
|
||||||
return 0; /* int */
|
#define awk_strxtoint qse_awk_wcsxtoint
|
||||||
}
|
#define awk_strxtoflt qse_awk_wcsxtoflt
|
||||||
|
#define char_t qse_wchar_t
|
||||||
|
#define AWK_ISDIGIT QSE_AWK_ISWDIGIT
|
||||||
|
#define _T QSE_WT
|
||||||
|
#include "val-imp.h"
|
||||||
|
|
||||||
|
#undef awk_rtx_strtonum
|
||||||
|
#undef awk_strxtoint
|
||||||
|
#undef awk_strxtoflt
|
||||||
|
#undef char_t
|
||||||
|
#undef AWK_ISDIGIT
|
||||||
|
#undef _T
|
||||||
|
/* ========================================================================== */
|
||||||
|
|
||||||
static QSE_INLINE qse_awk_uint_t hash (qse_uint8_t* ptr, qse_size_t len)
|
static QSE_INLINE qse_awk_uint_t hash (qse_uint8_t* ptr, qse_size_t len)
|
||||||
{
|
{
|
||||||
@ -1741,23 +1718,32 @@ qse_awk_int_t qse_awk_rtx_hashval (qse_awk_rtx_t* rtx, qse_awk_val_t* v)
|
|||||||
|
|
||||||
case QSE_AWK_VAL_INT:
|
case QSE_AWK_VAL_INT:
|
||||||
{
|
{
|
||||||
qse_awk_int_t tmp = QSE_AWK_RTX_GETINTFROMVAL (rtx, v);
|
qse_awk_int_t tmp = QSE_AWK_RTX_GETINTFROMVAL(rtx, v);
|
||||||
/*hv = ((qse_awk_val_int_t*)v)->val;*/
|
/*hv = ((qse_awk_val_int_t*)v)->val;*/
|
||||||
hv = (qse_awk_int_t)hash((qse_uint8_t*)&tmp, QSE_SIZEOF(tmp));
|
hv = (qse_awk_int_t)hash((qse_uint8_t*)&tmp, QSE_SIZEOF(tmp));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case QSE_AWK_VAL_FLT:
|
case QSE_AWK_VAL_FLT:
|
||||||
hv = (qse_awk_int_t)hash(
|
{
|
||||||
(qse_uint8_t*)&((qse_awk_val_flt_t*)v)->val,
|
qse_awk_val_flt_t* dv = (qse_awk_val_flt_t*)v;
|
||||||
QSE_SIZEOF(((qse_awk_val_flt_t*)v)->val));
|
hv = (qse_awk_int_t)hash((qse_uint8_t*)&dv->val, QSE_SIZEOF(dv->val));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case QSE_AWK_VAL_STR:
|
case QSE_AWK_VAL_STR:
|
||||||
hv = (qse_awk_int_t)hash(
|
{
|
||||||
(qse_uint8_t*)((qse_awk_val_str_t*)v)->val.ptr,
|
qse_awk_val_str_t* dv = (qse_awk_val_str_t*)v;
|
||||||
((qse_awk_val_str_t*)v)->val.len * QSE_SIZEOF(qse_char_t));
|
hv = (qse_awk_int_t)hash((qse_uint8_t*)dv->val.ptr, dv->val.len * QSE_SIZEOF(*dv->val.ptr));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case QSE_AWK_VAL_BYTEARR:
|
||||||
|
{
|
||||||
|
qse_awk_val_bytearr_t* dv = (qse_awk_val_bytearr_t*)v;
|
||||||
|
hv = (qse_awk_int_t)hash((qse_uint8_t*)dv->val.ptr, dv->val.len * QSE_SIZEOF(*dv->val.ptr));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
@ -1806,27 +1792,28 @@ int qse_awk_rtx_setrefval (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref, qse_awk_v
|
|||||||
case QSE_AWK_VAL_STR:
|
case QSE_AWK_VAL_STR:
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
/* handle this separately from the default case
|
/* handle this separately from the default case
|
||||||
* for no duplication. jumping to the default case
|
* for no duplication. jumping to the default case
|
||||||
* and callingqse_awk_rtx_valtostrdup() would also work, anyway. */
|
* and callingqse_awk_rtx_valtostrdup() would also work, anyway. */
|
||||||
qse_awk_rtx_refupval (rtx, val);
|
qse_awk_rtx_refupval (rtx, val);
|
||||||
x = qse_awk_rtx_setrec (
|
x = qse_awk_rtx_setrec (rtx, (qse_size_t)ref->adr, &((qse_awk_val_str_t*)val)->val);
|
||||||
rtx, (qse_size_t)ref->adr,
|
|
||||||
&((qse_awk_val_str_t*)val)->val
|
|
||||||
);
|
|
||||||
qse_awk_rtx_refdownval (rtx, val);
|
qse_awk_rtx_refdownval (rtx, val);
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* TODO: */
|
||||||
|
case QSE_AWK_VAL_BYTEARR:
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
qse_cstr_t str;
|
qse_cstr_t str;
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
str.ptr = qse_awk_rtx_valtostrdup (rtx, val, &str.len);
|
str.ptr = qse_awk_rtx_valtostrdup(rtx, val, &str.len);
|
||||||
qse_awk_rtx_refupval (rtx, val);
|
qse_awk_rtx_refupval (rtx, val);
|
||||||
x = qse_awk_rtx_setrec (rtx, (qse_size_t)ref->adr, &str);
|
x = qse_awk_rtx_setrec(rtx, (qse_size_t)ref->adr, &str);
|
||||||
qse_awk_rtx_refdownval (rtx, val);
|
qse_awk_rtx_refdownval (rtx, val);
|
||||||
QSE_AWK_FREE (rtx->awk, str.ptr);
|
QSE_AWK_FREE (rtx->awk, str.ptr);
|
||||||
return x;
|
return x;
|
||||||
@ -1835,7 +1822,7 @@ int qse_awk_rtx_setrefval (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref, qse_awk_v
|
|||||||
}
|
}
|
||||||
|
|
||||||
case QSE_AWK_VAL_REF_GBL:
|
case QSE_AWK_VAL_REF_GBL:
|
||||||
return qse_awk_rtx_setgbl (rtx, (int)ref->adr, val);
|
return qse_awk_rtx_setgbl(rtx, (int)ref->adr, val);
|
||||||
|
|
||||||
case QSE_AWK_VAL_REF_NAMEDIDX:
|
case QSE_AWK_VAL_REF_NAMEDIDX:
|
||||||
case QSE_AWK_VAL_REF_GBLIDX:
|
case QSE_AWK_VAL_REF_GBLIDX:
|
||||||
|
@ -223,7 +223,7 @@ static int get_token_into (qse_xli_t* xli, qse_xli_tok_t* tok)
|
|||||||
ADD_TOKEN_CHAR (xli, tok, c);
|
ADD_TOKEN_CHAR (xli, tok, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (c == QSE_T('_') || QSE_ISALPHA (c) ||
|
else if (c == QSE_T('_') || QSE_ISALPHA(c) ||
|
||||||
((xli->opt.trait & QSE_XLI_LEADDIGIT) && QSE_ISDIGIT(c)))
|
((xli->opt.trait & QSE_XLI_LEADDIGIT) && QSE_ISDIGIT(c)))
|
||||||
{
|
{
|
||||||
int lead_digit = QSE_ISDIGIT(c);
|
int lead_digit = QSE_ISDIGIT(c);
|
||||||
@ -238,7 +238,7 @@ static int get_token_into (qse_xli_t* xli, qse_xli_tok_t* tok)
|
|||||||
|
|
||||||
if (c == QSE_T('_') || c == QSE_T('-') ||
|
if (c == QSE_T('_') || c == QSE_T('-') ||
|
||||||
c == QSE_T(':') || c == QSE_T('*') ||
|
c == QSE_T(':') || c == QSE_T('*') ||
|
||||||
c == QSE_T('/') || QSE_ISALPHA (c))
|
c == QSE_T('/') || QSE_ISALPHA(c))
|
||||||
{
|
{
|
||||||
all_digits = 0;
|
all_digits = 0;
|
||||||
}
|
}
|
||||||
|
@ -376,7 +376,7 @@ retry:
|
|||||||
ADD_TOKEN_CHAR (xli, tok, c);
|
ADD_TOKEN_CHAR (xli, tok, c);
|
||||||
GET_CHAR_TO (xli, c);
|
GET_CHAR_TO (xli, c);
|
||||||
|
|
||||||
if (!QSE_ISALPHA (c))
|
if (!QSE_ISALPHA(c))
|
||||||
{
|
{
|
||||||
/* this directive is empty, not followed by a valid word */
|
/* this directive is empty, not followed by a valid word */
|
||||||
qse_xli_seterror (xli, QSE_XLI_EXKWEM, QSE_NULL, &tok->loc);
|
qse_xli_seterror (xli, QSE_XLI_EXKWEM, QSE_NULL, &tok->loc);
|
||||||
@ -390,7 +390,7 @@ retry:
|
|||||||
ADD_TOKEN_CHAR (xli, tok, c);
|
ADD_TOKEN_CHAR (xli, tok, c);
|
||||||
GET_CHAR_TO (xli, c);
|
GET_CHAR_TO (xli, c);
|
||||||
}
|
}
|
||||||
while (QSE_ISALPHA (c));
|
while (QSE_ISALPHA(c));
|
||||||
|
|
||||||
type = classify_ident(xli, QSE_STR_XSTR(tok->name));
|
type = classify_ident(xli, QSE_STR_XSTR(tok->name));
|
||||||
if (type == QSE_XLI_TOK_IDENT)
|
if (type == QSE_XLI_TOK_IDENT)
|
||||||
@ -401,7 +401,7 @@ retry:
|
|||||||
}
|
}
|
||||||
SET_TOKEN_TYPE (xli, tok, type);
|
SET_TOKEN_TYPE (xli, tok, type);
|
||||||
}
|
}
|
||||||
else if (c == QSE_T('_') || QSE_ISALPHA (c))
|
else if (c == QSE_T('_') || QSE_ISALPHA(c))
|
||||||
{
|
{
|
||||||
qse_xli_tok_type_t type;
|
qse_xli_tok_type_t type;
|
||||||
|
|
||||||
|
@ -505,7 +505,7 @@ retry:
|
|||||||
ADD_TOKEN_CHAR (xli, tok, c);
|
ADD_TOKEN_CHAR (xli, tok, c);
|
||||||
GET_CHAR_TO (xli, c);
|
GET_CHAR_TO (xli, c);
|
||||||
|
|
||||||
if (!QSE_ISALPHA (c))
|
if (!QSE_ISALPHA(c))
|
||||||
{
|
{
|
||||||
/* this directive is empty, not followed by a valid word */
|
/* this directive is empty, not followed by a valid word */
|
||||||
qse_xli_seterror (xli, QSE_XLI_EXKWEM, QSE_NULL, &tok->loc);
|
qse_xli_seterror (xli, QSE_XLI_EXKWEM, QSE_NULL, &tok->loc);
|
||||||
@ -519,7 +519,7 @@ retry:
|
|||||||
ADD_TOKEN_CHAR (xli, tok, c);
|
ADD_TOKEN_CHAR (xli, tok, c);
|
||||||
GET_CHAR_TO (xli, c);
|
GET_CHAR_TO (xli, c);
|
||||||
}
|
}
|
||||||
while (QSE_ISALPHA (c));
|
while (QSE_ISALPHA(c));
|
||||||
|
|
||||||
type = classify_ident (xli, QSE_STR_XSTR(tok->name));
|
type = classify_ident (xli, QSE_STR_XSTR(tok->name));
|
||||||
if (type == QSE_XLI_TOK_IDENT)
|
if (type == QSE_XLI_TOK_IDENT)
|
||||||
@ -530,7 +530,7 @@ retry:
|
|||||||
}
|
}
|
||||||
SET_TOKEN_TYPE (xli, tok, type);
|
SET_TOKEN_TYPE (xli, tok, type);
|
||||||
}
|
}
|
||||||
else if (c == QSE_T('_') || QSE_ISALPHA (c) ||
|
else if (c == QSE_T('_') || QSE_ISALPHA(c) ||
|
||||||
(!(xli->tok_status & TOK_STATUS_ENABLE_NSTR) &&
|
(!(xli->tok_status & TOK_STATUS_ENABLE_NSTR) &&
|
||||||
(xli->opt.trait & QSE_XLI_LEADDIGIT) &&
|
(xli->opt.trait & QSE_XLI_LEADDIGIT) &&
|
||||||
QSE_ISDIGIT(c)))
|
QSE_ISDIGIT(c)))
|
||||||
@ -548,7 +548,7 @@ retry:
|
|||||||
|
|
||||||
if (c == QSE_T('_') || c == QSE_T('-') ||
|
if (c == QSE_T('_') || c == QSE_T('-') ||
|
||||||
c == QSE_T(':') || c == QSE_T('*') ||
|
c == QSE_T(':') || c == QSE_T('*') ||
|
||||||
c == QSE_T('/') || QSE_ISALPHA (c))
|
c == QSE_T('/') || QSE_ISALPHA(c))
|
||||||
{
|
{
|
||||||
all_digits = 0;
|
all_digits = 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user