diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2015-02-04 10:52:57 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2015-02-04 10:52:57 -0200 |
| commit | 8efcd411fee4e7103cff7b027fca38290cdaa6f7 (patch) | |
| tree | 3d65016ec6316bed51653e128d540168019a54d7 | |
| parent | 90d016980f47fb4f760be2356e715f92af9a7af8 (diff) | |
| download | lua-8efcd411fee4e7103cff7b027fca38290cdaa6f7.tar.gz lua-8efcd411fee4e7103cff7b027fca38290cdaa6f7.tar.bz2 lua-8efcd411fee4e7103cff7b027fca38290cdaa6f7.zip | |
own implementation for 'string.format("%a")' for C89 platforms
Diffstat (limited to '')
| -rw-r--r-- | lstrlib.c | 87 | ||||
| -rw-r--r-- | luaconf.h | 16 |
2 files changed, 92 insertions, 11 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstrlib.c,v 1.221 2014/12/11 14:03:07 roberto Exp roberto $ | 2 | ** $Id: lstrlib.c,v 1.223 2015/02/04 12:52:57 roberto Exp $ |
| 3 | ** Standard library for string operations and pattern-matching | 3 | ** Standard library for string operations and pattern-matching |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -797,6 +797,86 @@ static int str_gsub (lua_State *L) { | |||
| 797 | ** ======================================================= | 797 | ** ======================================================= |
| 798 | */ | 798 | */ |
| 799 | 799 | ||
| 800 | #if !defined(lua_number2strx) /* { */ | ||
| 801 | |||
| 802 | /* | ||
| 803 | ** Hexadecimal floating-point formatter | ||
| 804 | */ | ||
| 805 | |||
| 806 | #include <math.h> | ||
| 807 | |||
| 808 | #define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char)) | ||
| 809 | |||
| 810 | |||
| 811 | /* | ||
| 812 | ** Number of bits that goes into the first digit. It can be any value | ||
| 813 | ** between 1 and 4; the following definition tries to align the number | ||
| 814 | ** to nibble boundaries. The default is 1 bit, that aligns double | ||
| 815 | ** (1+52-bit mantissa) and quad precision (1+112-bit mantissa). For | ||
| 816 | ** float (24-bit mantissa) and 80-bit long double (64-bit mantissa), 4 | ||
| 817 | ** does the alignment. | ||
| 818 | */ | ||
| 819 | #define L_NBFD ((sizeof(lua_Number) == 4 || sizeof(lua_Number) == 12) ? 4 : 1) | ||
| 820 | |||
| 821 | |||
| 822 | /* | ||
| 823 | ** Add integer part of 'x' to buffer and return new 'x' | ||
| 824 | */ | ||
| 825 | static lua_Number adddigit (char *buff, int n, lua_Number x) { | ||
| 826 | double dd = l_mathop(floor)(x); /* get integer part from 'x' */ | ||
| 827 | int d = (int)dd; | ||
| 828 | buff[n] = (d < 10 ? d + '0' : d - 10 + 'a'); /* add to buffer */ | ||
| 829 | return x - dd; /* return what is left */ | ||
| 830 | } | ||
| 831 | |||
| 832 | |||
| 833 | static int num2straux (char *buff, lua_Number x) { | ||
| 834 | if (x != x || x == HUGE_VAL || x == -HUGE_VAL) /* inf or NaN? */ | ||
| 835 | return sprintf(buff, LUA_NUMBER_FMT, x); /* equal to '%g' */ | ||
| 836 | else if (x == 0) { /* can be -0... */ | ||
| 837 | sprintf(buff, LUA_NUMBER_FMT, x); | ||
| 838 | strcpy(buff + (buff[0] == '-' ? 1 : 0), "0x0p+0"); | ||
| 839 | return strlen(buff); | ||
| 840 | } | ||
| 841 | else { | ||
| 842 | int e; | ||
| 843 | lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */ | ||
| 844 | int n = 0; /* character count */ | ||
| 845 | if (m < 0) { /* is number negative? */ | ||
| 846 | buff[n++] = '-'; /* add signal */ | ||
| 847 | m = -m; /* make it positive */ | ||
| 848 | } | ||
| 849 | buff[n++] = '0'; buff[n++] = 'x'; /* add "0x" */ | ||
| 850 | m = adddigit(buff, n++, m * (1 << L_NBFD)); /* add first digit */ | ||
| 851 | e -= L_NBFD; /* this digit goes before the radix point */ | ||
| 852 | if (m > 0) { /* more digits? */ | ||
| 853 | buff[n++] = '.'; /* add radix point */ | ||
| 854 | do { /* add as many digits as needed */ | ||
| 855 | m = adddigit(buff, n++, m * 16); | ||
| 856 | } while (m > 0); | ||
| 857 | } | ||
| 858 | n += sprintf(buff + n, "p%+d", e); /* add exponent */ | ||
| 859 | return n; | ||
| 860 | } | ||
| 861 | } | ||
| 862 | |||
| 863 | |||
| 864 | static int lua_number2strx (lua_State *L, char *buff, const char *fmt, | ||
| 865 | lua_Number x) { | ||
| 866 | int n = num2straux(buff, x); | ||
| 867 | if (fmt[SIZELENMOD] == 'A') { | ||
| 868 | int i; | ||
| 869 | for (i = 0; i < n; i++) | ||
| 870 | buff[i] = toupper(uchar(buff[i])); | ||
| 871 | } | ||
| 872 | else if (fmt[SIZELENMOD] != 'a') | ||
| 873 | luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented"); | ||
| 874 | return n; | ||
| 875 | } | ||
| 876 | |||
| 877 | #endif /* } */ | ||
| 878 | |||
| 879 | |||
| 800 | /* | 880 | /* |
| 801 | ** Maximum size of each formatted item. This maximum size is produced | 881 | ** Maximum size of each formatted item. This maximum size is produced |
| 802 | ** by format('%.99f', minfloat), and is equal to 99 + 2 ('-' and '.') + | 882 | ** by format('%.99f', minfloat), and is equal to 99 + 2 ('-' and '.') + |
| @@ -908,9 +988,10 @@ static int str_format (lua_State *L) { | |||
| 908 | nb = sprintf(buff, form, n); | 988 | nb = sprintf(buff, form, n); |
| 909 | break; | 989 | break; |
| 910 | } | 990 | } |
| 911 | #if defined(LUA_USE_AFORMAT) | ||
| 912 | case 'a': case 'A': | 991 | case 'a': case 'A': |
| 913 | #endif | 992 | addlenmod(form, LUA_NUMBER_FRMLEN); |
| 993 | nb = lua_number2strx(L, buff, form, luaL_checknumber(L, arg)); | ||
| 994 | break; | ||
| 914 | case 'e': case 'E': case 'f': | 995 | case 'e': case 'E': case 'f': |
| 915 | case 'g': case 'G': { | 996 | case 'g': case 'G': { |
| 916 | addlenmod(form, LUA_NUMBER_FRMLEN); | 997 | addlenmod(form, LUA_NUMBER_FRMLEN); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: luaconf.h,v 1.241 2015/01/16 17:15:52 roberto Exp roberto $ | 2 | ** $Id: luaconf.h,v 1.242 2015/01/16 17:26:56 roberto Exp roberto $ |
| 3 | ** Configuration file for Lua | 3 | ** Configuration file for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -598,7 +598,7 @@ | |||
| 598 | 598 | ||
| 599 | /* | 599 | /* |
| 600 | @@ lua_strx2number converts an hexadecimal numeric string to a number. | 600 | @@ lua_strx2number converts an hexadecimal numeric string to a number. |
| 601 | ** In C99, 'strtod' does both conversions. Otherwise, you can | 601 | ** In C99, 'strtod' does that conversion. Otherwise, you can |
| 602 | ** leave 'lua_strx2number' undefined and Lua will provide its own | 602 | ** leave 'lua_strx2number' undefined and Lua will provide its own |
| 603 | ** implementation. | 603 | ** implementation. |
| 604 | */ | 604 | */ |
| @@ -608,12 +608,13 @@ | |||
| 608 | 608 | ||
| 609 | 609 | ||
| 610 | /* | 610 | /* |
| 611 | @@ LUA_USE_AFORMAT allows '%a'/'%A' specifiers in 'string.format' | 611 | @@ lua_number2strx converts a float to an hexadecimal numeric string. |
| 612 | ** Enable it if the C function 'printf' supports these specifiers. | 612 | ** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that. |
| 613 | ** (C99 demands it and Windows also supports it.) | 613 | ** Otherwise, you can leave 'lua_number2strx' undefined and Lua will |
| 614 | ** provide its own implementation. | ||
| 614 | */ | 615 | */ |
| 615 | #if !defined(LUA_USE_C89) || defined(LUA_USE_WINDOWS) | 616 | #if !defined(LUA_USE_C89) |
| 616 | #define LUA_USE_AFORMAT | 617 | #define lua_number2strx(L,b,f,n) sprintf(b,f,n) |
| 617 | #endif | 618 | #endif |
| 618 | 619 | ||
| 619 | 620 | ||
| @@ -699,7 +700,6 @@ | |||
| 699 | #define LUAL_BUFFERSIZE 8192 | 700 | #define LUAL_BUFFERSIZE 8192 |
| 700 | #else | 701 | #else |
| 701 | #define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer))) | 702 | #define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer))) |
| 702 | |||
| 703 | #endif | 703 | #endif |
| 704 | 704 | ||
| 705 | /* }================================================================== */ | 705 | /* }================================================================== */ |
