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

Reply via email to