diff options
author | griffin <briang42@easystreet.net> | 2020-05-30 23:47:10 (GMT) |
---|---|---|
committer | griffin <briang42@easystreet.net> | 2020-05-30 23:47:10 (GMT) |
commit | ea25a2d32d5f1c090e0f6a0a02950ed621be8efe (patch) | |
tree | cdbc53c057ede13726ef2b8476eeffcacc96b801 /generic | |
parent | b44555477cda94fd227969fd4a281daa0a1dbb52 (diff) | |
parent | 6d2fb7b84d5d50f685186f9866337e167a249118 (diff) | |
download | tcl-ea25a2d32d5f1c090e0f6a0a02950ed621be8efe.zip tcl-ea25a2d32d5f1c090e0f6a0a02950ed621be8efe.tar.gz tcl-ea25a2d32d5f1c090e0f6a0a02950ed621be8efe.tar.bz2 |
tip-551 implementation.
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclInt.h | 2 | ||||
-rw-r--r-- | generic/tclScan.c | 4 | ||||
-rw-r--r-- | generic/tclStrToD.c | 93 |
3 files changed, 91 insertions, 8 deletions
diff --git a/generic/tclInt.h b/generic/tclInt.h index f7b3cc4..f343469 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -2714,6 +2714,8 @@ typedef struct ProcessGlobalValue { /* Reject leading/trailing whitespace. */ #define TCL_PARSE_BINARY_ONLY 64 /* Parse binary even without prefix. */ +#define TCL_PARSE_NO_UNDERSCORE 128 + /* Reject underscore digit separator */ /* *---------------------------------------------------------------------- diff --git a/generic/tclScan.c b/generic/tclScan.c index dc98f54..4d86382 100644 --- a/generic/tclScan.c +++ b/generic/tclScan.c @@ -896,7 +896,7 @@ Tcl_ScanObjCmd( width = ~0; } if (TCL_OK != TclParseNumber(NULL, objPtr, NULL, string, width, - &end, TCL_PARSE_INTEGER_ONLY | parseFlag)) { + &end, TCL_PARSE_INTEGER_ONLY | TCL_PARSE_NO_UNDERSCORE | parseFlag)) { Tcl_DecrRefCount(objPtr); if (width < 0) { if (*end == '\0') { @@ -998,7 +998,7 @@ Tcl_ScanObjCmd( width = ~0; } if (TCL_OK != TclParseNumber(NULL, objPtr, NULL, string, width, - &end, TCL_PARSE_DECIMAL_ONLY | TCL_PARSE_NO_WHITESPACE)) { + &end, TCL_PARSE_DECIMAL_ONLY | TCL_PARSE_NO_WHITESPACE | TCL_PARSE_NO_UNDERSCORE)) { Tcl_DecrRefCount(objPtr); if (width < 0) { if (*end == '\0') { diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c index 7ef2c60..85b660d 100644 --- a/generic/tclStrToD.c +++ b/generic/tclStrToD.c @@ -535,7 +535,9 @@ TclParseNumber( int shift = 0; /* Amount to shift when accumulating binary */ int explicitOctal = 0; mp_err err = MP_OKAY; - + int under = 0; /* Flag trailing '_' as error if true once + * number is accepted. */ + #define ALL_BITS ((Tcl_WideUInt)-1) #define MOST_BITS (ALL_BITS >> 1) @@ -643,7 +645,7 @@ TclParseNumber( acceptPoint = p; acceptLen = len; if (c == 'x' || c == 'X') { - if (flags & (TCL_PARSE_OCTAL_ONLY|TCL_PARSE_BINARY_ONLY)) { + if (flags & (TCL_PARSE_OCTAL_ONLY|TCL_PARSE_BINARY_ONLY) || under) { goto endgame; } state = ZERO_X; @@ -656,7 +658,7 @@ TclParseNumber( goto zeroo; } if (c == 'b' || c == 'B') { - if (flags & TCL_PARSE_OCTAL_ONLY) { + if ((flags & TCL_PARSE_OCTAL_ONLY) || under) { goto endgame; } state = ZERO_B; @@ -666,11 +668,17 @@ TclParseNumber( goto zerob; } if (c == 'o' || c == 'O') { + if (under) { + goto endgame; + } explicitOctal = 1; state = ZERO_O; break; } if (c == 'd' || c == 'D') { + if (under) { + goto endgame; + } state = ZERO_D; break; } @@ -694,9 +702,11 @@ TclParseNumber( zeroo: if (c == '0') { numTrailZeros++; + under = 0; state = OCTAL; break; } else if (c >= '1' && c <= '7') { + under = 0; if (objPtr != NULL) { shift = 3 * (numTrailZeros + 1); significandOverflow = AccumulateDecimalDigit( @@ -746,6 +756,10 @@ TclParseNumber( numTrailZeros = 0; state = OCTAL; break; + } else if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) { + /* Ignore numeric "white space" */ + under = 1; + break; } /* FALLTHROUGH */ @@ -774,6 +788,7 @@ TclParseNumber( if (c == '0') { numTrailZeros++; + under = 0; state = BAD_OCTAL; break; } else if (isdigit(UCHAR(c))) { @@ -789,12 +804,15 @@ TclParseNumber( numSigDigs = 1; } numTrailZeros = 0; + under = 0; state = BAD_OCTAL; break; } else if (c == '.') { + under = 0; state = FRACTION; break; } else if (c == 'E' || c == 'e') { + under = 0; state = EXPONENT_START; break; } @@ -817,14 +835,22 @@ TclParseNumber( zerox: if (c == '0') { numTrailZeros++; + under = 0; state = HEXADECIMAL; break; } else if (isdigit(UCHAR(c))) { + under = 0; d = (c-'0'); } else if (c >= 'A' && c <= 'F') { + under = 0; d = (c-'A'+10); } else if (c >= 'a' && c <= 'f') { + under = 0; d = (c-'a'+10); + } else if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) { + /* Ignore numeric "white space" */ + under = 1; + break; } else { goto endgame; } @@ -870,8 +896,13 @@ TclParseNumber( zerob: if (c == '0') { numTrailZeros++; + under = 0; state = BINARY; break; + } else if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) { + /* Ignore numeric "white space" */ + under = 1; + break; } else if (c != '1') { goto endgame; } @@ -910,10 +941,17 @@ TclParseNumber( case ZERO_D: if (c == '0') { + under = 0; numTrailZeros++; } else if ( ! isdigit(UCHAR(c))) { + if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) { + /* Ignore numeric "white space" */ + under = 1; + break; + } goto endgame; } + under = 0; state = DECIMAL; flags |= TCL_PARSE_INTEGER_ONLY; /* FALLTHROUGH */ @@ -932,6 +970,7 @@ TclParseNumber( acceptLen = len; if (c == '0') { numTrailZeros++; + under = 0; state = DECIMAL; break; } else if (isdigit(UCHAR(c))) { @@ -943,14 +982,21 @@ TclParseNumber( } numSigDigs += numTrailZeros+1; numTrailZeros = 0; + under = 0; state = DECIMAL; break; + } else if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) { + /* Ignore numeric "white space" */ + under = 1; + break; } else if (flags & TCL_PARSE_INTEGER_ONLY) { goto endgame; } else if (c == '.') { + under = 0; state = FRACTION; break; } else if (c == 'E' || c == 'e') { + under = 0; state = EXPONENT_START; break; } @@ -976,6 +1022,7 @@ TclParseNumber( if (c == '0') { numDigitsAfterDp++; numTrailZeros++; + under = 0; state = FRACTION; break; } else if (isdigit(UCHAR(c))) { @@ -992,8 +1039,13 @@ TclParseNumber( numSigDigs = 1; } numTrailZeros = 0; + under = 0; state = FRACTION; break; + } else if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) { + /* Ignore numeric "white space" */ + under = 1; + break; } goto endgame; @@ -1005,10 +1057,12 @@ TclParseNumber( */ if (c == '+') { + under = 0; state = EXPONENT_SIGNUM; break; } else if (c == '-') { exponentSignum = 1; + under = 0; state = EXPONENT_SIGNUM; break; } @@ -1022,8 +1076,13 @@ TclParseNumber( if (isdigit(UCHAR(c))) { exponent = c - '0'; + under = 0; state = EXPONENT; break; + } else if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) { + /* Ignore numeric "white space" */ + under = 1; + break; } goto endgame; @@ -1042,8 +1101,13 @@ TclParseNumber( } else { exponent = LONG_MAX; } + under = 0; state = EXPONENT; break; + } else if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) { + /* Ignore numeric "white space" */ + under = 1; + break; } goto endgame; @@ -1054,12 +1118,14 @@ TclParseNumber( case sI: if (c == 'n' || c == 'N') { + under = 0; state = sIN; break; } goto endgame; case sIN: if (c == 'f' || c == 'F') { + under = 0; state = sINF; break; } @@ -1068,6 +1134,7 @@ TclParseNumber( acceptState = state; acceptPoint = p; acceptLen = len; + under = 0; if (c == 'i' || c == 'I') { state = sINFI; break; @@ -1075,24 +1142,28 @@ TclParseNumber( goto endgame; case sINFI: if (c == 'n' || c == 'N') { + under = 0; state = sINFIN; break; } goto endgame; case sINFIN: if (c == 'i' || c == 'I') { + under = 0; state = sINFINI; break; } goto endgame; case sINFINI: if (c == 't' || c == 'T') { + under = 0; state = sINFINIT; break; } goto endgame; case sINFINIT: if (c == 'y' || c == 'Y') { + under = 0; state = sINFINITY; break; } @@ -1104,12 +1175,14 @@ TclParseNumber( #ifdef IEEE_FLOATING_POINT case sN: if (c == 'a' || c == 'A') { + under = 0; state = sNA; break; } goto endgame; case sNA: if (c == 'n' || c == 'N') { + under = 0; state = sNAN; break; } @@ -1119,6 +1192,7 @@ TclParseNumber( acceptPoint = p; acceptLen = len; if (c == '(') { + under = 0; state = sNANPAREN; break; } @@ -1129,12 +1203,14 @@ TclParseNumber( */ case sNANHEX: if (c == ')') { + under = 0; state = sNANFINISH; break; } /* FALLTHROUGH */ case sNANPAREN: if (TclIsSpaceProcM(c)) { + under = 0; break; } if (numSigDigs < 13) { @@ -1149,6 +1225,7 @@ TclParseNumber( } numSigDigs++; significandWide = (significandWide << 4) + d; + under = 0; state = sNANHEX; break; } @@ -1161,6 +1238,7 @@ TclParseNumber( acceptPoint = p; acceptLen = len; goto endgame; + } p++; len--; @@ -1178,11 +1256,14 @@ TclParseNumber( } } else { /* - * Back up to the last accepting state in the lexer. + * Back up to the last accepting state in the lexer. + * If the last char seen is the numeric whitespace character '_', + * backup to that. */ - p = acceptPoint; - len = acceptLen; + p = under ? acceptPoint-1 : acceptPoint; + len = under ? acceptLen-1 : acceptLen; + if (!(flags & TCL_PARSE_NO_WHITESPACE)) { /* * Accept trailing whitespace. |