Fossil SCM
Add support for hex (0x), octal (0o) and binary (0b) integers, just as Tcl. Adapted from patch provided by Sergei Gavrikov.
Commit
1f6734c30b00fe070e6b14a04f80c4298c582f35
Parent
544d22139da66d9…
2 files changed
+63
-9
+3
M
src/th.c
+63
-9
| --- src/th.c | ||
| +++ src/th.c | ||
| @@ -1877,15 +1877,30 @@ | ||
| 1877 | 1877 | Th_Interp *interp, |
| 1878 | 1878 | const char *zInput, |
| 1879 | 1879 | int nInput, |
| 1880 | 1880 | int *pnLiteral |
| 1881 | 1881 | ){ |
| 1882 | - int i; | |
| 1882 | + int i = 0; | |
| 1883 | 1883 | 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++){ | |
| 1885 | 1900 | char c = zInput[i]; |
| 1886 | - if( (seenDot || c!='.') && !th_isdigit(c) ) break; | |
| 1901 | + if( (seenDot || c!='.') && !isdigit(c) ) break; | |
| 1887 | 1902 | if( c=='.' ) seenDot = 1; |
| 1888 | 1903 | } |
| 1889 | 1904 | *pnLiteral = i; |
| 1890 | 1905 | return TH_OK; |
| 1891 | 1906 | } |
| @@ -2411,11 +2426,12 @@ | ||
| 2411 | 2426 | ** '\f' 0x0C |
| 2412 | 2427 | ** '\r' 0x0D |
| 2413 | 2428 | ** |
| 2414 | 2429 | ** Whitespace characters have the 0x01 flag set. Decimal digits have the |
| 2415 | 2430 | ** 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. | |
| 2417 | 2433 | ** |
| 2418 | 2434 | ** The special list characters have the 0x10 flag set |
| 2419 | 2435 | ** |
| 2420 | 2436 | ** { } [ ] \ ; ' " |
| 2421 | 2437 | ** |
| @@ -2424,14 +2440,14 @@ | ||
| 2424 | 2440 | */ |
| 2425 | 2441 | static unsigned char aCharProp[256] = { |
| 2426 | 2442 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, /* 0x0. */ |
| 2427 | 2443 | 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x1. */ |
| 2428 | 2444 | 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. */ | |
| 2431 | 2447 | 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. */ | |
| 2433 | 2449 | 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 20, 4, 20, 4, 4, /* 0x7. */ |
| 2434 | 2450 | |
| 2435 | 2451 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x8. */ |
| 2436 | 2452 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9. */ |
| 2437 | 2453 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA. */ |
| @@ -2454,10 +2470,19 @@ | ||
| 2454 | 2470 | int th_isspecial(char c){ |
| 2455 | 2471 | return (aCharProp[(unsigned char)c] & 0x11); |
| 2456 | 2472 | } |
| 2457 | 2473 | int th_isalnum(char c){ |
| 2458 | 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'); | |
| 2459 | 2484 | } |
| 2460 | 2485 | |
| 2461 | 2486 | #ifndef LONGDOUBLE_TYPE |
| 2462 | 2487 | # define LONGDOUBLE_TYPE long double |
| 2463 | 2488 | #endif |
| @@ -2571,24 +2596,53 @@ | ||
| 2571 | 2596 | ** interpreter result too. |
| 2572 | 2597 | */ |
| 2573 | 2598 | int Th_ToInt(Th_Interp *interp, const char *z, int n, int *piOut){ |
| 2574 | 2599 | int i = 0; |
| 2575 | 2600 | int iOut = 0; |
| 2601 | + int base = 10; | |
| 2602 | + int (*isdigit)(char) = th_isdigit; | |
| 2576 | 2603 | |
| 2577 | 2604 | if( n<0 ){ |
| 2578 | 2605 | n = th_strlen(z); |
| 2579 | 2606 | } |
| 2580 | 2607 | |
| 2581 | 2608 | if( n>0 && (z[0]=='-' || z[0]=='+') ){ |
| 2582 | 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 | + } | |
| 2583 | 2629 | } |
| 2584 | 2630 | for(; i<n; i++){ |
| 2585 | - if( !th_isdigit(z[i]) ){ | |
| 2631 | + int shift; | |
| 2632 | + if( !isdigit(z[i]) ){ | |
| 2586 | 2633 | Th_ErrorMessage(interp, "expected integer, got: \"", z, n); |
| 2587 | 2634 | return TH_ERROR; |
| 2588 | 2635 | } |
| 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); | |
| 2590 | 2644 | } |
| 2591 | 2645 | |
| 2592 | 2646 | if( n>0 && z[0]=='-' ){ |
| 2593 | 2647 | iOut *= -1; |
| 2594 | 2648 | } |
| 2595 | 2649 |
| --- 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 |
M
src/th.h
+3
| --- src/th.h | ||
| +++ src/th.h | ||
| @@ -146,10 +146,13 @@ | ||
| 146 | 146 | int th_strlen(const char *); |
| 147 | 147 | int th_isdigit(char); |
| 148 | 148 | int th_isspace(char); |
| 149 | 149 | int th_isalnum(char); |
| 150 | 150 | int th_isspecial(char); |
| 151 | +int th_ishexdig(char); | |
| 152 | +int th_isoctdig(char); | |
| 153 | +int th_isbindig(char); | |
| 151 | 154 | char *th_strdup(Th_Interp *interp, const char *z, int n); |
| 152 | 155 | |
| 153 | 156 | /* |
| 154 | 157 | ** Interfaces to register the language extensions. |
| 155 | 158 | */ |
| 156 | 159 |
| --- 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 |