From 81cbac9e4dddcc57b2d2e81048a1f712d5f96e4a Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Mon, 15 Apr 2019 04:30:49 +0000 Subject: [PATCH] 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 --- qse/include/qse/awk/awk.h | 90 +++++-- qse/lib/awk/awk-prv.h | 28 ++ qse/lib/awk/misc-imp.h | 503 +++++++++++++++++++++++++++++++++++ qse/lib/awk/misc.c | 545 ++++---------------------------------- qse/lib/awk/parse.c | 24 +- qse/lib/awk/val-imp.h | 49 ++++ qse/lib/awk/val.c | 177 ++++++------- qse/lib/xli/read-ini.c | 4 +- qse/lib/xli/read-json.c | 6 +- qse/lib/xli/read.c | 8 +- 10 files changed, 798 insertions(+), 636 deletions(-) create mode 100644 qse/lib/awk/misc-imp.h create mode 100644 qse/lib/awk/val-imp.h diff --git a/qse/include/qse/awk/awk.h b/qse/include/qse/awk/awk.h index 7c4d4a90..ad361eaa 100644 --- a/qse/include/qse/awk/awk.h +++ b/qse/include/qse/awk/awk.h @@ -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_awk_t* awk, - const qse_char_t* str, - qse_size_t len, - int base, - const qse_char_t** endptr +QSE_EXPORT qse_awk_int_t qse_awk_mbsxtoint ( + qse_awk_t* awk, + const qse_mchar_t* str, + qse_size_t len, + int base, + 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. */ -QSE_EXPORT 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 +QSE_EXPORT qse_awk_flt_t qse_awk_mbsxtoflt ( + qse_awk_t* awk, + const qse_mchar_t* str, + qse_size_t len, + 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_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_STRTONUN_GET_OPTION_BASE(option) ((option) >> 8) -QSE_EXPORT int qse_awk_rtx_strtonum ( - qse_awk_rtx_t* rtx, /**< runtime context */ - int strict, /**< determines to perform strict check */ - const qse_char_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 */ +QSE_EXPORT int qse_awk_rtx_mbstonum ( + qse_awk_rtx_t* rtx, /**< runtime context */ + int strict, /**< determines to perform strict check */ + const qse_mchar_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 */ ); +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 * to a positive integer. It returns -1 for a inhashable value. diff --git a/qse/lib/awk/awk-prv.h b/qse/lib/awk/awk-prv.h index 6237f2fe..afbb04a2 100644 --- a/qse/lib/awk/awk-prv.h +++ b/qse/lib/awk/awk-prv.h @@ -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_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_STRXDUP(awk,str,len) (qse_strxdup(str,len,(awk)->mmgr)) diff --git a/qse/lib/awk/misc-imp.h b/qse/lib/awk/misc-imp.h new file mode 100644 index 00000000..42b86565 --- /dev/null +++ b/qse/lib/awk/misc-imp.h @@ -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; +} diff --git a/qse/lib/awk/misc.c b/qse/lib/awk/misc.c index 8ea0503e..3002100e 100644 --- a/qse/lib/awk/misc.c +++ b/qse/lib/awk/misc.c @@ -82,510 +82,57 @@ qse_char_t* qse_awk_cstrdup (qse_awk_t* awk, const qse_cstr_t* s) return ptr; } -qse_awk_int_t qse_awk_strxtoint ( - qse_awk_t* awk, const qse_char_t* str, qse_size_t len, - int base, const qse_char_t** endptr) -{ - qse_awk_int_t n = 0; - const qse_char_t* p; - const qse_char_t* end; - qse_size_t rem; - int digit, negative = 0; +/* ========================================================================= */ +#undef awk_strxtoint +#undef awk_strtoflt +#undef awk_strxtoflt +#undef char_t +#undef cint_t +#undef AWK_ISSPACE +#undef AWK_ISDIGIT +#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; - - if (awk->opt.trait & QSE_AWK_STRIPSTRSPC) - { - /* strip off leading spaces */ - while (p < end && QSE_AWK_ISSPACE(awk,*p)) p++; - } +/* ------------------------------------------------------------------------- */ +#undef awk_strxtoint +#undef awk_strtoflt +#undef awk_strxtoflt +#undef char_t +#undef cint_t +#undef AWK_ISSPACE +#undef AWK_ISDIGIT +#undef _T +/* ------------------------------------------------------------------------- */ - /* check for a sign */ - while (p < end) - { - if (*p == QSE_T('-')) - { - negative = ~negative; - p++; - } - else if (*p == QSE_T('+')) p++; - else break; - } +#define awk_strxtoint qse_awk_wcsxtoint +#define awk_strtoflt qse_awk_wcstoflt +#define awk_strxtoflt qse_awk_wcsxtoflt +#define char_t qse_wchar_t +#define cint_t qse_wcint_t +#define AWK_ISSPACE QSE_AWK_ISWSPACE +#define AWK_ISDIGIT QSE_AWK_ISWDIGIT +#define _T QSE_WT +#include "misc-imp.h" - /* check for a binary/octal/hexadecimal notation */ - rem = end - p; - if (base == 0) - { - if (rem >= 1 && *p == QSE_T('0')) - { - p++; +#undef awk_strxtoint +#undef awk_strtoflt +#undef awk_strxtoflt +#undef char_t +#undef cint_t +#undef AWK_ISSPACE +#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_awk_t* awk, qse_awk_int_t value, diff --git a/qse/lib/awk/parse.c b/qse/lib/awk/parse.c index 0b96d634..41e7e5b4 100644 --- a/qse/lib/awk/parse.c +++ b/qse/lib/awk/parse.c @@ -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); 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); GET_CHAR_TO (awk, c); - while (QSE_AWK_ISDIGIT (awk, c)) + while (QSE_AWK_ISDIGIT(awk, c)) { ADD_TOKEN_CHAR (awk, tok, 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); } - while (QSE_AWK_ISDIGIT (awk, c)) + while (QSE_AWK_ISDIGIT(awk, c)) { ADD_TOKEN_CHAR (awk, tok, c); GET_CHAR_TO (awk, c); @@ -5879,7 +5879,7 @@ static int skip_spaces (qse_awk_t* awk) } 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; @@ -6105,7 +6105,7 @@ retry: SET_TOKEN_TYPE (awk, tok, TOK_NEWLINE); 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; } @@ -6119,7 +6119,7 @@ retry: unget_char (awk, &awk->sio.last); awk->sio.last = lc; - if (QSE_AWK_ISDIGIT (awk, c)) + if (QSE_AWK_ISDIGIT(awk, c)) { /* for a token such as .123 */ if (get_number (awk, tok) <= -1) return -1; @@ -6137,7 +6137,7 @@ retry: ADD_TOKEN_CHAR (awk, tok, 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, * not followed by a valid word */ @@ -6152,8 +6152,8 @@ retry: GET_CHAR_TO (awk, c); } while (c == QSE_T('_') || - QSE_AWK_ISALPHA (awk, c) || - QSE_AWK_ISDIGIT (awk, c)); + QSE_AWK_ISALPHA(awk, c) || + QSE_AWK_ISDIGIT(awk, c)); type = classify_ident (awk, QSE_STR_XSTR(tok->name)); if (type == TOK_IDENT) @@ -6163,7 +6163,7 @@ retry: } 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; @@ -6174,8 +6174,8 @@ retry: GET_CHAR_TO (awk, c); } while (c == QSE_T('_') || - QSE_AWK_ISALPHA (awk, c) || - QSE_AWK_ISDIGIT (awk, c)); + QSE_AWK_ISALPHA(awk, c) || + QSE_AWK_ISDIGIT(awk, c)); type = classify_ident (awk, QSE_STR_XSTR(tok->name)); SET_TOKEN_TYPE (awk, tok, type); diff --git a/qse/lib/awk/val-imp.h b/qse/lib/awk/val-imp.h new file mode 100644 index 00000000..a7dfe2ec --- /dev/null +++ b/qse/lib/awk/val-imp.h @@ -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 */ +} diff --git a/qse/lib/awk/val.c b/qse/lib/awk/val.c index ae6bfa3d..55dcb495 100644 --- a/qse/lib/awk/val.c +++ b/qse/lib/awk/val.c @@ -1420,8 +1420,7 @@ int qse_awk_rtx_valtostr ( return -1; } -qse_char_t* qse_awk_rtx_valtostrdup ( - qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_size_t* len) +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_valtostr_out_t out; @@ -1432,14 +1431,13 @@ qse_char_t* qse_awk_rtx_valtostrdup ( return out.u.cpldup.ptr; } -qse_mchar_t* qse_awk_rtx_valtombsdup ( - qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_size_t* len) +qse_mchar_t* qse_awk_rtx_valtombsdup (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_size_t* len) { #if defined(QSE_CHAR_IS_MCHAR) qse_awk_rtx_valtostr_out_t out; 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; return out.u.cpldup.ptr; @@ -1448,16 +1446,15 @@ qse_mchar_t* qse_awk_rtx_valtombsdup ( qse_mchar_t* mbs; 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); return mbs; #endif } -qse_wchar_t* qse_awk_rtx_valtowcsdup ( - qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_size_t* len) +qse_wchar_t* qse_awk_rtx_valtowcsdup (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_size_t* len) { #if defined(QSE_CHAR_IS_MCHAR) qse_awk_rtx_valtostr_out_t out; @@ -1480,8 +1477,7 @@ qse_wchar_t* qse_awk_rtx_valtowcsdup ( #endif } -qse_char_t* qse_awk_rtx_getvalstr ( - qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_size_t* len) +qse_char_t* qse_awk_rtx_getvalstr (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) { @@ -1494,8 +1490,7 @@ qse_char_t* qse_awk_rtx_getvalstr ( } } -void qse_awk_rtx_freevalstr ( - qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_char_t* str) +void qse_awk_rtx_freevalstr (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 || str != ((qse_awk_val_str_t*)v)->val.ptr) @@ -1504,8 +1499,7 @@ void qse_awk_rtx_freevalstr ( } } -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) +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) { switch (ref->id) { @@ -1516,7 +1510,7 @@ static int val_ref_to_num ( idx = (qse_size_t)ref->adr; if (idx == 0) { - return qse_awk_rtx_strtonum ( + return qse_awk_rtx_strtonum( rtx, QSE_AWK_RTX_STRTONUM_MAKE_OPTION(0, 0), QSE_STR_PTR(&rtx->inrec.line), @@ -1526,7 +1520,7 @@ static int val_ref_to_num ( } else if (idx <= rtx->inrec.nflds) { - return qse_awk_rtx_strtonum ( + return qse_awk_rtx_strtonum( rtx, QSE_AWK_RTX_STRTONUM_MAKE_OPTION(0, 0), rtx->inrec.flds[idx-1].ptr, @@ -1536,7 +1530,7 @@ static int val_ref_to_num ( } 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 ); } @@ -1558,14 +1552,13 @@ static int val_ref_to_num ( QSE_ASSERT (QSE_AWK_RTX_GETVALTYPE (rtx, *xref) != QSE_AWK_VAL_REF); /* 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 ( - qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_int_t* l, qse_awk_flt_t* r) +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_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: { return qse_awk_rtx_mbstonum ( @@ -1612,7 +1603,6 @@ int qse_awk_rtx_valtonum ( l, r ); } -#endif case QSE_AWK_VAL_MAP: { @@ -1625,7 +1615,7 @@ int qse_awk_rtx_valtonum ( 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 */ } -int qse_awk_rtx_valtoint ( - qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_int_t* l) +int qse_awk_rtx_valtoint (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_int_t* l) { int n; 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) { *l = (qse_awk_int_t)r; @@ -1656,70 +1645,58 @@ int qse_awk_rtx_valtoint ( return n; } -int qse_awk_rtx_valtoflt ( - qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_flt_t* r) +int qse_awk_rtx_valtoflt (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_flt_t* r) { int n; 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; else if (n == 1) n = 0; return n; } -int qse_awk_rtx_strtonum ( - qse_awk_rtx_t* rtx, int option, - const qse_char_t* ptr, qse_size_t len, - qse_awk_int_t* l, qse_awk_flt_t* r) -{ - const qse_char_t* endptr; - const qse_char_t* end; +/* ========================================================================== */ +#undef awk_rtx_strtonum +#undef awk_strxtoint +#undef awk_strxtoflt +#undef char_t +#undef AWK_ISDIGIT +#undef _T - int strict = QSE_AWK_RTX_STRTONUM_GET_OPTION_STRICT(option); - int base = QSE_AWK_RTX_STRTONUN_GET_OPTION_BASE(option); +#define awk_rtx_strtonum qse_awk_rtx_mbstonum +#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); - if (endptr < end) - { - if (*endptr == QSE_T('.') || *endptr == QSE_T('E') || *endptr == QSE_T('e')) - { - handle_float: - *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; - } - } - } +/* ------------------------------------------------------------------------- */ +#undef awk_rtx_strtonum +#undef awk_strxtoint +#undef awk_strxtoflt +#undef char_t +#undef AWK_ISDIGIT +#undef _T +/* ------------------------------------------------------------------------- */ - if (strict && endptr < end) return -1; - return 0; /* int */ -} +#define awk_rtx_strtonum qse_awk_rtx_wcstonum +#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) { @@ -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: { - 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_int_t)hash((qse_uint8_t*)&tmp, QSE_SIZEOF(tmp)); break; } case QSE_AWK_VAL_FLT: - hv = (qse_awk_int_t)hash( - (qse_uint8_t*)&((qse_awk_val_flt_t*)v)->val, - QSE_SIZEOF(((qse_awk_val_flt_t*)v)->val)); + { + qse_awk_val_flt_t* dv = (qse_awk_val_flt_t*)v; + hv = (qse_awk_int_t)hash((qse_uint8_t*)&dv->val, QSE_SIZEOF(dv->val)); break; + } 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*)v)->val.len * QSE_SIZEOF(qse_char_t)); + { + qse_awk_val_str_t* dv = (qse_awk_val_str_t*)v; + hv = (qse_awk_int_t)hash((qse_uint8_t*)dv->val.ptr, dv->val.len * QSE_SIZEOF(*dv->val.ptr)); 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: @@ -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: { int x; - /* handle this separately from the default case * for no duplication. jumping to the default case * and callingqse_awk_rtx_valtostrdup() would also work, anyway. */ qse_awk_rtx_refupval (rtx, val); - x = qse_awk_rtx_setrec ( - rtx, (qse_size_t)ref->adr, - &((qse_awk_val_str_t*)val)->val - ); + x = qse_awk_rtx_setrec (rtx, (qse_size_t)ref->adr, &((qse_awk_val_str_t*)val)->val); qse_awk_rtx_refdownval (rtx, val); return x; } +#if 0 +/* TODO: */ + case QSE_AWK_VAL_BYTEARR: +#endif + default: { qse_cstr_t str; 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); - 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_FREE (rtx->awk, str.ptr); 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: - 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_GBLIDX: diff --git a/qse/lib/xli/read-ini.c b/qse/lib/xli/read-ini.c index 581502c1..c16918cb 100644 --- a/qse/lib/xli/read-ini.c +++ b/qse/lib/xli/read-ini.c @@ -223,7 +223,7 @@ static int get_token_into (qse_xli_t* xli, qse_xli_tok_t* tok) 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))) { 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('-') || c == QSE_T(':') || c == QSE_T('*') || - c == QSE_T('/') || QSE_ISALPHA (c)) + c == QSE_T('/') || QSE_ISALPHA(c)) { all_digits = 0; } diff --git a/qse/lib/xli/read-json.c b/qse/lib/xli/read-json.c index 37794311..81ac3cbd 100644 --- a/qse/lib/xli/read-json.c +++ b/qse/lib/xli/read-json.c @@ -376,7 +376,7 @@ retry: ADD_TOKEN_CHAR (xli, tok, c); GET_CHAR_TO (xli, c); - if (!QSE_ISALPHA (c)) + if (!QSE_ISALPHA(c)) { /* this directive is empty, not followed by a valid word */ qse_xli_seterror (xli, QSE_XLI_EXKWEM, QSE_NULL, &tok->loc); @@ -390,7 +390,7 @@ retry: ADD_TOKEN_CHAR (xli, tok, c); GET_CHAR_TO (xli, c); } - while (QSE_ISALPHA (c)); + while (QSE_ISALPHA(c)); type = classify_ident(xli, QSE_STR_XSTR(tok->name)); if (type == QSE_XLI_TOK_IDENT) @@ -401,7 +401,7 @@ retry: } 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; diff --git a/qse/lib/xli/read.c b/qse/lib/xli/read.c index 07e05638..7b422ad9 100644 --- a/qse/lib/xli/read.c +++ b/qse/lib/xli/read.c @@ -505,7 +505,7 @@ retry: ADD_TOKEN_CHAR (xli, tok, c); GET_CHAR_TO (xli, c); - if (!QSE_ISALPHA (c)) + if (!QSE_ISALPHA(c)) { /* this directive is empty, not followed by a valid word */ qse_xli_seterror (xli, QSE_XLI_EXKWEM, QSE_NULL, &tok->loc); @@ -519,7 +519,7 @@ retry: ADD_TOKEN_CHAR (xli, tok, c); GET_CHAR_TO (xli, c); } - while (QSE_ISALPHA (c)); + while (QSE_ISALPHA(c)); type = classify_ident (xli, QSE_STR_XSTR(tok->name)); if (type == QSE_XLI_TOK_IDENT) @@ -530,7 +530,7 @@ retry: } 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->opt.trait & QSE_XLI_LEADDIGIT) && QSE_ISDIGIT(c))) @@ -548,7 +548,7 @@ retry: if (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; }