Fossil SCM

Add support for hex (0x), octal (0o) and binary (0b) integers, just as Tcl. Adapted from patch provided by Sergei Gavrikov.

jan.nijtmans 2014-04-03 15:14 trunk
Commit 1f6734c30b00fe070e6b14a04f80c4298c582f35
2 files changed +63 -9 +3
+63 -9
--- src/th.c
+++ src/th.c
@@ -1877,15 +1877,30 @@
18771877
Th_Interp *interp,
18781878
const char *zInput,
18791879
int nInput,
18801880
int *pnLiteral
18811881
){
1882
- int i;
1882
+ int i = 0;
18831883
int seenDot = 0;
1884
- for(i=0; i<nInput; i++){
1884
+ int (*isdigit)(char) = th_isdigit;
1885
+ if( nInput>2 ){
1886
+ if( zInput[0]=='0' && (zInput[1]=='x' || zInput[1]=='X') ){
1887
+ i=2;
1888
+ isdigit = th_ishexdig;
1889
+ }
1890
+ if( zInput[0]=='0' && (zInput[1]=='o' || zInput[1]=='O') ){
1891
+ i=2;
1892
+ isdigit = th_isoctdig;
1893
+ }
1894
+ if( zInput[0]=='0' && (zInput[1]=='b' || zInput[1]=='B') ){
1895
+ i=2;
1896
+ isdigit = th_isbindig;
1897
+ }
1898
+ }
1899
+ for(; i<nInput; i++){
18851900
char c = zInput[i];
1886
- if( (seenDot || c!='.') && !th_isdigit(c) ) break;
1901
+ if( (seenDot || c!='.') && !isdigit(c) ) break;
18871902
if( c=='.' ) seenDot = 1;
18881903
}
18891904
*pnLiteral = i;
18901905
return TH_OK;
18911906
}
@@ -2411,11 +2426,12 @@
24112426
** '\f' 0x0C
24122427
** '\r' 0x0D
24132428
**
24142429
** Whitespace characters have the 0x01 flag set. Decimal digits have the
24152430
** 0x2 flag set. Single byte printable characters have the 0x4 flag set.
2416
-** Alphabet characters have the 0x8 bit set.
2431
+** Alphabet characters have the 0x8 bit set. Hexadecimal digits have the
2432
+** 0x20 flag set.
24172433
**
24182434
** The special list characters have the 0x10 flag set
24192435
**
24202436
** { } [ ] \ ; ' "
24212437
**
@@ -2424,14 +2440,14 @@
24242440
*/
24252441
static unsigned char aCharProp[256] = {
24262442
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, /* 0x0. */
24272443
0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x1. */
24282444
5, 4, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x2. */
2429
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 20, 4, 4, 4, 4, /* 0x3. */
2430
- 4, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, /* 0x4. */
2445
+ 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 4, 20, 4, 4, 4, 4, /* 0x3. */
2446
+ 4, 44, 44, 44, 44, 44, 44, 12, 12, 12, 12, 12, 12, 12, 12, 12, /* 0x4. */
24312447
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 20, 20, 20, 4, 4, /* 0x5. */
2432
- 4, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, /* 0x6. */
2448
+ 4, 44, 44, 44, 44, 44, 44, 12, 12, 12, 12, 12, 12, 12, 12, 12, /* 0x6. */
24332449
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 20, 4, 20, 4, 4, /* 0x7. */
24342450
24352451
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x8. */
24362452
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9. */
24372453
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA. */
@@ -2454,10 +2470,19 @@
24542470
int th_isspecial(char c){
24552471
return (aCharProp[(unsigned char)c] & 0x11);
24562472
}
24572473
int th_isalnum(char c){
24582474
return (aCharProp[(unsigned char)c] & 0x0A);
2475
+}
2476
+int th_ishexdig(char c){
2477
+ return (aCharProp[(unsigned char)c] & 0x20);
2478
+}
2479
+int th_isoctdig(char c){
2480
+ return ((c|7) == '7');
2481
+}
2482
+int th_isbindig(char c){
2483
+ return ((c|1) == '1');
24592484
}
24602485
24612486
#ifndef LONGDOUBLE_TYPE
24622487
# define LONGDOUBLE_TYPE long double
24632488
#endif
@@ -2571,24 +2596,53 @@
25712596
** interpreter result too.
25722597
*/
25732598
int Th_ToInt(Th_Interp *interp, const char *z, int n, int *piOut){
25742599
int i = 0;
25752600
int iOut = 0;
2601
+ int base = 10;
2602
+ int (*isdigit)(char) = th_isdigit;
25762603
25772604
if( n<0 ){
25782605
n = th_strlen(z);
25792606
}
25802607
25812608
if( n>0 && (z[0]=='-' || z[0]=='+') ){
25822609
i = 1;
2610
+ }
2611
+ if( n>2 ){
2612
+ if( z[i]=='0' ){
2613
+ if( z[i+1]=='x' || z[i+1]=='X' ){
2614
+ i += 2;
2615
+ base = 16;
2616
+ isdigit = th_ishexdig;
2617
+ }
2618
+ if( z[i+1]=='o' || z[i+1]=='O' ){
2619
+ i += 2;
2620
+ base = 8;
2621
+ isdigit = th_isoctdig;
2622
+ }
2623
+ if( z[i+1]=='b' || z[i+1]=='B' ){
2624
+ i += 2;
2625
+ base = 2;
2626
+ isdigit = th_isbindig;
2627
+ }
2628
+ }
25832629
}
25842630
for(; i<n; i++){
2585
- if( !th_isdigit(z[i]) ){
2631
+ int shift;
2632
+ if( !isdigit(z[i]) ){
25862633
Th_ErrorMessage(interp, "expected integer, got: \"", z, n);
25872634
return TH_ERROR;
25882635
}
2589
- iOut = iOut * 10 + (z[i] - 48);
2636
+ if( z[i]>='a' ){
2637
+ shift = 'a' - 10;
2638
+ }else if( z[i]>='A' ){
2639
+ shift = 'A' - 10;
2640
+ }else{
2641
+ shift = '0';
2642
+ }
2643
+ iOut = iOut * base + (z[i] - shift);
25902644
}
25912645
25922646
if( n>0 && z[0]=='-' ){
25932647
iOut *= -1;
25942648
}
25952649
--- src/th.c
+++ src/th.c
@@ -1877,15 +1877,30 @@
1877 Th_Interp *interp,
1878 const char *zInput,
1879 int nInput,
1880 int *pnLiteral
1881 ){
1882 int i;
1883 int seenDot = 0;
1884 for(i=0; i<nInput; i++){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1885 char c = zInput[i];
1886 if( (seenDot || c!='.') && !th_isdigit(c) ) break;
1887 if( c=='.' ) seenDot = 1;
1888 }
1889 *pnLiteral = i;
1890 return TH_OK;
1891 }
@@ -2411,11 +2426,12 @@
2411 ** '\f' 0x0C
2412 ** '\r' 0x0D
2413 **
2414 ** Whitespace characters have the 0x01 flag set. Decimal digits have the
2415 ** 0x2 flag set. Single byte printable characters have the 0x4 flag set.
2416 ** Alphabet characters have the 0x8 bit set.
 
2417 **
2418 ** The special list characters have the 0x10 flag set
2419 **
2420 ** { } [ ] \ ; ' "
2421 **
@@ -2424,14 +2440,14 @@
2424 */
2425 static unsigned char aCharProp[256] = {
2426 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, /* 0x0. */
2427 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x1. */
2428 5, 4, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x2. */
2429 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 20, 4, 4, 4, 4, /* 0x3. */
2430 4, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, /* 0x4. */
2431 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 20, 20, 20, 4, 4, /* 0x5. */
2432 4, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, /* 0x6. */
2433 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 20, 4, 20, 4, 4, /* 0x7. */
2434
2435 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x8. */
2436 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9. */
2437 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA. */
@@ -2454,10 +2470,19 @@
2454 int th_isspecial(char c){
2455 return (aCharProp[(unsigned char)c] & 0x11);
2456 }
2457 int th_isalnum(char c){
2458 return (aCharProp[(unsigned char)c] & 0x0A);
 
 
 
 
 
 
 
 
 
2459 }
2460
2461 #ifndef LONGDOUBLE_TYPE
2462 # define LONGDOUBLE_TYPE long double
2463 #endif
@@ -2571,24 +2596,53 @@
2571 ** interpreter result too.
2572 */
2573 int Th_ToInt(Th_Interp *interp, const char *z, int n, int *piOut){
2574 int i = 0;
2575 int iOut = 0;
 
 
2576
2577 if( n<0 ){
2578 n = th_strlen(z);
2579 }
2580
2581 if( n>0 && (z[0]=='-' || z[0]=='+') ){
2582 i = 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2583 }
2584 for(; i<n; i++){
2585 if( !th_isdigit(z[i]) ){
 
2586 Th_ErrorMessage(interp, "expected integer, got: \"", z, n);
2587 return TH_ERROR;
2588 }
2589 iOut = iOut * 10 + (z[i] - 48);
 
 
 
 
 
 
 
2590 }
2591
2592 if( n>0 && z[0]=='-' ){
2593 iOut *= -1;
2594 }
2595
--- src/th.c
+++ src/th.c
@@ -1877,15 +1877,30 @@
1877 Th_Interp *interp,
1878 const char *zInput,
1879 int nInput,
1880 int *pnLiteral
1881 ){
1882 int i = 0;
1883 int seenDot = 0;
1884 int (*isdigit)(char) = th_isdigit;
1885 if( nInput>2 ){
1886 if( zInput[0]=='0' && (zInput[1]=='x' || zInput[1]=='X') ){
1887 i=2;
1888 isdigit = th_ishexdig;
1889 }
1890 if( zInput[0]=='0' && (zInput[1]=='o' || zInput[1]=='O') ){
1891 i=2;
1892 isdigit = th_isoctdig;
1893 }
1894 if( zInput[0]=='0' && (zInput[1]=='b' || zInput[1]=='B') ){
1895 i=2;
1896 isdigit = th_isbindig;
1897 }
1898 }
1899 for(; i<nInput; i++){
1900 char c = zInput[i];
1901 if( (seenDot || c!='.') && !isdigit(c) ) break;
1902 if( c=='.' ) seenDot = 1;
1903 }
1904 *pnLiteral = i;
1905 return TH_OK;
1906 }
@@ -2411,11 +2426,12 @@
2426 ** '\f' 0x0C
2427 ** '\r' 0x0D
2428 **
2429 ** Whitespace characters have the 0x01 flag set. Decimal digits have the
2430 ** 0x2 flag set. Single byte printable characters have the 0x4 flag set.
2431 ** Alphabet characters have the 0x8 bit set. Hexadecimal digits have the
2432 ** 0x20 flag set.
2433 **
2434 ** The special list characters have the 0x10 flag set
2435 **
2436 ** { } [ ] \ ; ' "
2437 **
@@ -2424,14 +2440,14 @@
2440 */
2441 static unsigned char aCharProp[256] = {
2442 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, /* 0x0. */
2443 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x1. */
2444 5, 4, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x2. */
2445 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 4, 20, 4, 4, 4, 4, /* 0x3. */
2446 4, 44, 44, 44, 44, 44, 44, 12, 12, 12, 12, 12, 12, 12, 12, 12, /* 0x4. */
2447 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 20, 20, 20, 4, 4, /* 0x5. */
2448 4, 44, 44, 44, 44, 44, 44, 12, 12, 12, 12, 12, 12, 12, 12, 12, /* 0x6. */
2449 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 20, 4, 20, 4, 4, /* 0x7. */
2450
2451 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x8. */
2452 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9. */
2453 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA. */
@@ -2454,10 +2470,19 @@
2470 int th_isspecial(char c){
2471 return (aCharProp[(unsigned char)c] & 0x11);
2472 }
2473 int th_isalnum(char c){
2474 return (aCharProp[(unsigned char)c] & 0x0A);
2475 }
2476 int th_ishexdig(char c){
2477 return (aCharProp[(unsigned char)c] & 0x20);
2478 }
2479 int th_isoctdig(char c){
2480 return ((c|7) == '7');
2481 }
2482 int th_isbindig(char c){
2483 return ((c|1) == '1');
2484 }
2485
2486 #ifndef LONGDOUBLE_TYPE
2487 # define LONGDOUBLE_TYPE long double
2488 #endif
@@ -2571,24 +2596,53 @@
2596 ** interpreter result too.
2597 */
2598 int Th_ToInt(Th_Interp *interp, const char *z, int n, int *piOut){
2599 int i = 0;
2600 int iOut = 0;
2601 int base = 10;
2602 int (*isdigit)(char) = th_isdigit;
2603
2604 if( n<0 ){
2605 n = th_strlen(z);
2606 }
2607
2608 if( n>0 && (z[0]=='-' || z[0]=='+') ){
2609 i = 1;
2610 }
2611 if( n>2 ){
2612 if( z[i]=='0' ){
2613 if( z[i+1]=='x' || z[i+1]=='X' ){
2614 i += 2;
2615 base = 16;
2616 isdigit = th_ishexdig;
2617 }
2618 if( z[i+1]=='o' || z[i+1]=='O' ){
2619 i += 2;
2620 base = 8;
2621 isdigit = th_isoctdig;
2622 }
2623 if( z[i+1]=='b' || z[i+1]=='B' ){
2624 i += 2;
2625 base = 2;
2626 isdigit = th_isbindig;
2627 }
2628 }
2629 }
2630 for(; i<n; i++){
2631 int shift;
2632 if( !isdigit(z[i]) ){
2633 Th_ErrorMessage(interp, "expected integer, got: \"", z, n);
2634 return TH_ERROR;
2635 }
2636 if( z[i]>='a' ){
2637 shift = 'a' - 10;
2638 }else if( z[i]>='A' ){
2639 shift = 'A' - 10;
2640 }else{
2641 shift = '0';
2642 }
2643 iOut = iOut * base + (z[i] - shift);
2644 }
2645
2646 if( n>0 && z[0]=='-' ){
2647 iOut *= -1;
2648 }
2649
+3
--- src/th.h
+++ src/th.h
@@ -146,10 +146,13 @@
146146
int th_strlen(const char *);
147147
int th_isdigit(char);
148148
int th_isspace(char);
149149
int th_isalnum(char);
150150
int th_isspecial(char);
151
+int th_ishexdig(char);
152
+int th_isoctdig(char);
153
+int th_isbindig(char);
151154
char *th_strdup(Th_Interp *interp, const char *z, int n);
152155
153156
/*
154157
** Interfaces to register the language extensions.
155158
*/
156159
--- src/th.h
+++ src/th.h
@@ -146,10 +146,13 @@
146 int th_strlen(const char *);
147 int th_isdigit(char);
148 int th_isspace(char);
149 int th_isalnum(char);
150 int th_isspecial(char);
 
 
 
151 char *th_strdup(Th_Interp *interp, const char *z, int n);
152
153 /*
154 ** Interfaces to register the language extensions.
155 */
156
--- src/th.h
+++ src/th.h
@@ -146,10 +146,13 @@
146 int th_strlen(const char *);
147 int th_isdigit(char);
148 int th_isspace(char);
149 int th_isalnum(char);
150 int th_isspecial(char);
151 int th_ishexdig(char);
152 int th_isoctdig(char);
153 int th_isbindig(char);
154 char *th_strdup(Th_Interp *interp, const char *z, int n);
155
156 /*
157 ** Interfaces to register the language extensions.
158 */
159

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button