On Thu, 3 Apr 2014, Jan Nijtmans wrote:
> 2014-04-03 14:05 GMT+02:00 Sergei Gavrikov <sergei.gavri...@gmail.com>:
> > Could anyone take a look on the workaround, please? Well, Th_ToInt()
> > become itself a bit more slow, but I think it is still more fast than
> > strtoll(). At the least, I can say that the patch does not break the
> > existing Fossil TH1 tests.
>
> I'm not fond of allowing a "0"-prefix for octal numbers, better
> restrict it to "0o", which is more consistent with "0x" for hex.
> Yes, Tcl 8.x allows it now, but in future Tcl versions it will
> most likely being abandoned. See: <http://www.tcl.tk/cgi-bin/tct/tip/114>
Good point. Thak you. With new patch TH1 works as Tcl 8.5
% expr {0o10+10+0x10}
34
% expr {0O10+10+0X10}
34
% expr {0o77+99+0xff}
417
> Other than that, it looks good to me.
Thanks you for review!
Sergei
Index: src/th.c
==================================================================
--- src/th.c
+++ src/th.c
@@ -1867,10 +1867,13 @@
{"|", OP_BITWISE_OR, 10, ARG_INTEGER},
{0,0,0,0}
};
+int th_ishexdig(char c); /* 0x* and 0X* */
+int th_isoctdig(char c); /* 0o* and 0O* */
+
/*
** The first part of the string (zInput,nInput) contains a number.
** Set *pnVarname to the number of bytes in the numeric string.
*/
static int thNextNumber(
@@ -1877,15 +1880,26 @@
Th_Interp *interp,
const char *zInput,
int nInput,
int *pnLiteral
){
- int i;
+ int i = 0;
int seenDot = 0;
- for(i=0; i<nInput; i++){
+ int (*isdigit)(char) = th_isdigit;
+ if( nInput>2 ){
+ if( zInput[0]=='0' && (zInput[1]=='x' || zInput[1]=='X') ){
+ i=2;
+ isdigit = th_ishexdig;
+ }
+ if( zInput[0]=='0' && (zInput[1]=='o' || zInput[1]=='O') ){
+ i=2;
+ isdigit = th_isoctdig;
+ }
+ }
+ for(; i<nInput; i++){
char c = zInput[i];
- if( (seenDot || c!='.') && !th_isdigit(c) ) break;
+ if( (seenDot || c!='.') && !isdigit(c) ) break;
if( c=='.' ) seenDot = 1;
}
*pnLiteral = i;
return TH_OK;
}
@@ -2411,11 +2425,12 @@
** '\f' 0x0C
** '\r' 0x0D
**
** Whitespace characters have the 0x01 flag set. Decimal digits have the
** 0x2 flag set. Single byte printable characters have the 0x4 flag set.
-** Alphabet characters have the 0x8 bit set.
+** Alphabet characters have the 0x8 bit set. Hexadecimal digits have the
+** 0x20 flag set. Octal digits have the 0x40 flag set.
**
** The special list characters have the 0x10 flag set
**
** { } [ ] \ ; ' "
**
@@ -2424,14 +2439,14 @@
*/
static unsigned char aCharProp[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, /* 0x0. */
0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x1. */
5, 4, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x2. */
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 20, 4, 4, 4, 4, /* 0x3. */
- 4, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, /* 0x4. */
+102,102,102,102,102,102,102,102, 102,102, 4, 20, 4, 4, 4, 4, /* 0x3. */
+ 4, 44, 44, 44, 44, 44, 44, 12, 12, 12, 12, 12, 12, 12, 12, 12, /* 0x4. */
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 20, 20, 20, 4, 4, /* 0x5. */
- 4, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, /* 0x6. */
+ 4, 44, 44, 44, 44, 44, 44, 12, 12, 12, 12, 12, 12, 12, 12, 12, /* 0x6. */
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 20, 4, 20, 4, 4, /* 0x7. */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x8. */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9. */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA. */
@@ -2455,10 +2470,16 @@
return (aCharProp[(unsigned char)c] & 0x11);
}
int th_isalnum(char c){
return (aCharProp[(unsigned char)c] & 0x0A);
}
+int th_ishexdig(char c){
+ return (aCharProp[(unsigned char)c] & 0x20);
+}
+int th_isoctdig(char c){
+ return (aCharProp[(unsigned char)c] & 0x40);
+}
#ifndef LONGDOUBLE_TYPE
# define LONGDOUBLE_TYPE long double
#endif
@@ -2571,24 +2592,46 @@
** interpreter result too.
*/
int Th_ToInt(Th_Interp *interp, const char *z, int n, int *piOut){
int i = 0;
int iOut = 0;
+ int base = 10;
+ int (*isdigit)(char) = th_isdigit;
if( n<0 ){
n = th_strlen(z);
}
if( n>0 && (z[0]=='-' || z[0]=='+') ){
i = 1;
+ }
+ if( n>2 ){
+ if( z[i]=='0' && (z[i+1]=='x' || z[i+1]=='X') ){
+ i += 2;
+ base = 16;
+ isdigit = th_ishexdig;
+ }
+ if( z[i]=='0' && (z[i+1]=='o' || z[i+1]=='O') ){
+ i += 2;
+ base = 8;
+ isdigit = th_isoctdig;
+ }
}
for(; i<n; i++){
- if( !th_isdigit(z[i]) ){
+ int shift;
+ if( !isdigit(z[i]) ){
Th_ErrorMessage(interp, "expected integer, got: \"", z, n);
return TH_ERROR;
}
- iOut = iOut * 10 + (z[i] - 48);
+ if( z[i]>='a' ){
+ shift = 87;
+ }else if( z[i]>='A' ){
+ shift = 55;
+ }else{
+ shift = 48;
+ }
+ iOut = iOut * base + (z[i] - shift);
}
if( n>0 && z[0]=='-' ){
iOut *= -1;
}
_______________________________________________
fossil-users mailing list
fossil-users@lists.fossil-scm.org
http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users