From: Hugo van der Sanden Date: Sun, 10 Jun 2001 11:23:30 +0000 (+0100) Subject: Re: pragma/locale.t #107 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=f20cc2f4b57d0af6ae56e81a5194c331ceb01e3b;p=p5sagit%2Fp5-mst-13.2.git Re: pragma/locale.t #107 Message-Id: <200106101023.LAA32085@crypt.compulink.co.uk> Encapsulate the scan of the decimal radix separator. p4raw-id: //depot/perl@10495 --- diff --git a/embed.h b/embed.h index 36f2728..80500da 100644 --- a/embed.h +++ b/embed.h @@ -1115,6 +1115,7 @@ #define gv_share S_gv_share # endif #define grok_number S_grok_number +#define grok_numeric_radix S_grok_numeric_radix #endif #if defined(PERL_IN_TOKE_C) || defined(PERL_DECL_PROT) #define check_uni S_check_uni @@ -2609,6 +2610,7 @@ #define gv_share(a) S_gv_share(aTHX_ a) # endif #define grok_number(a,b,c) S_grok_number(aTHX_ a,b,c) +#define grok_numeric_radix(a,b) S_grok_numeric_radix(aTHX_ a,b) #endif #if defined(PERL_IN_TOKE_C) || defined(PERL_DECL_PROT) #define check_uni() S_check_uni(aTHX) @@ -5083,6 +5085,8 @@ # endif #define S_grok_number CPerlObj::S_grok_number #define grok_number S_grok_number +#define S_grok_numeric_radix CPerlObj::S_grok_numeric_radix +#define grok_numeric_radix S_grok_numeric_radix #endif #if defined(PERL_IN_TOKE_C) || defined(PERL_DECL_PROT) #define S_check_uni CPerlObj::S_check_uni diff --git a/embed.pl b/embed.pl index 67e142a..5557eab 100755 --- a/embed.pl +++ b/embed.pl @@ -2522,6 +2522,7 @@ s |I32 |expect_number |char** pattern s |SV* |gv_share |SV *sv # endif s |int |grok_number |const char *pv|STRLEN len|UV *valuep +s |bool |grok_numeric_radix|const char **sp|const char *send #endif #if defined(PERL_IN_TOKE_C) || defined(PERL_DECL_PROT) diff --git a/proto.h b/proto.h index 5005708..f4706ed 100644 --- a/proto.h +++ b/proto.h @@ -1246,6 +1246,7 @@ STATIC I32 S_expect_number(pTHX_ char** pattern); STATIC SV* S_gv_share(pTHX_ SV *sv); # endif STATIC int S_grok_number(pTHX_ const char *pv, STRLEN len, UV *valuep); +STATIC int S_grok_numeric_radix(pTHX_ const char **sp, const char *send); #endif #if defined(PERL_IN_TOKE_C) || defined(PERL_DECL_PROT) diff --git a/sv.c b/sv.c index 2a843e6..4b86aab 100644 --- a/sv.c +++ b/sv.c @@ -1494,6 +1494,30 @@ S_not_a_number(pTHX_ SV *sv) #define IS_NUMBER_NEG 0x08 /* leading minus sign */ #define IS_NUMBER_INFINITY 0x10 /* this is big */ +static bool +S_grok_numeric_radix(pTHX_ const char **sp, const char *send) +{ +#ifdef USE_LOCALE_NUMERIC + if (PL_numeric_radix_sv && IN_LOCALE) { + STRLEN len; + char* radix = SvPV(PL_numeric_radix_sv, len); + if (*sp + len <= send && memEQ(*sp, radix, len)) { + *sp += len; + return TRUE; + } + } + /* always try "." if numeric radix didn't match because + * we may have data from different locales mixed */ +#endif + if (*sp < send && **sp == '.') { + ++*sp; + return TRUE; + } + return FALSE; +} + +#define GROK_NUMERIC_RADIX(sp, send) grok_numeric_radix(sp, send) + static int S_grok_number(pTHX_ const char *pv, STRLEN len, UV *valuep) { @@ -1503,9 +1527,6 @@ S_grok_number(pTHX_ const char *pv, STRLEN len, UV *valuep) const char max_mod_10 = UV_MAX % 10 + '0'; int numtype = 0; int sawinf = 0; - char* radix = "."; - STRLEN radixlen = 1; - bool radixfound; while (isSPACE(*s)) s++; @@ -1516,11 +1537,6 @@ S_grok_number(pTHX_ const char *pv, STRLEN len, UV *valuep) else if (*s == '+') s++; -#ifdef USE_LOCALE_NUMERIC - if (PL_numeric_radix_sv && IN_LOCALE) - radix = SvPV(PL_numeric_radix_sv, radixlen); -#endif - /* next must be digit or the radix separator or beginning of infinity */ if (isDIGIT(*s)) { /* UVs are at least 32 bits, so the first 9 decimal digits cannot @@ -1589,64 +1605,42 @@ S_grok_number(pTHX_ const char *pv, STRLEN len, UV *valuep) *valuep = value; skip_value: - if (s + radixlen <= send && memEQ(s, radix, radixlen)) - radixfound = TRUE; -#ifdef USE_LOCALE_NUMERIC - /* if we did change the radix and the radix is not the "." - * retry with the "." (in case of mixed data) */ - else if (IN_LOCALE && !(*radix == '.' && radixlen == 1) && *s == '.') { - radixlen = 1; - radixfound = TRUE; - } -#endif - if (radixfound) { - s += radixlen; + if (GROK_NUMERIC_RADIX(&s, send)) { numtype |= IS_NUMBER_NOT_INT; while (isDIGIT(*s)) /* optional digits after the radix */ s++; } } - else { - if (s + radixlen <= send && memEQ(s, radix, radixlen)) - radixfound = TRUE; -#ifdef USE_LOCALE_NUMERIC - else if (IN_LOCALE && !(*radix == '.' && radixlen == 1) && *s == '.') { - radixlen = 1; - radixfound = TRUE; + else if (GROK_NUMERIC_RADIX(&s, send)) { + numtype |= IS_NUMBER_NOT_INT; + /* no digits before the radix means we need digits after it */ + if (isDIGIT(*s)) { + do { + s++; + } while (isDIGIT(*s)); + numtype |= IS_NUMBER_IN_UV; + if (valuep) { + /* integer approximation is valid - it's 0. */ + *valuep = 0; + } } -#endif - if (radixfound) { - s += radixlen; - numtype |= IS_NUMBER_NOT_INT; - /* no digits before the radix means we need digits after it */ - if (isDIGIT(*s)) { - do { - s++; - } while (isDIGIT(*s)); - numtype |= IS_NUMBER_IN_UV; - if (valuep) { - /* integer approximation is valid - it's 0. */ - *valuep = 0; - } - } - else + else return 0; - } - else if (*s == 'I' || *s == 'i') { + } + else if (*s == 'I' || *s == 'i') { + s++; if (*s != 'N' && *s != 'n') return 0; + s++; if (*s != 'F' && *s != 'f') return 0; + s++; if (*s == 'I' || *s == 'i') { s++; if (*s != 'N' && *s != 'n') return 0; - s++; if (*s != 'F' && *s != 'f') return 0; - s++; if (*s == 'I' || *s == 'i') { - s++; if (*s != 'N' && *s != 'n') return 0; - s++; if (*s != 'I' && *s != 'i') return 0; - s++; if (*s != 'T' && *s != 't') return 0; - s++; if (*s != 'Y' && *s != 'y') return 0; - s++; - } - sawinf = 1; + s++; if (*s != 'I' && *s != 'i') return 0; + s++; if (*s != 'T' && *s != 't') return 0; + s++; if (*s != 'Y' && *s != 'y') return 0; + s++; } - else /* Add test for NaN here. */ - return 0; + sawinf = 1; } + else /* Add test for NaN here. */ + return 0; if (sawinf) { numtype &= IS_NUMBER_NEG; /* Keep track of sign */