diff options
-rw-r--r-- | lprefix.h | 9 | ||||
-rw-r--r-- | lstrlib.c | 157 | ||||
-rw-r--r-- | ltablib.c | 41 | ||||
-rw-r--r-- | lutf8lib.c | 4 |
4 files changed, 126 insertions, 85 deletions
@@ -98,6 +98,15 @@ static const char *compat53_utf8_escape (lua_State* L, long x) { | |||
98 | # define LUA_INTEGER_FRMLEN "" | 98 | # define LUA_INTEGER_FRMLEN "" |
99 | # define LUA_NUMBER_FRMLEN "" | 99 | # define LUA_NUMBER_FRMLEN "" |
100 | # endif | 100 | # endif |
101 | # ifndef LUA_MININTEGER | ||
102 | # define LUA_MININTEGER 0 | ||
103 | # endif | ||
104 | # ifndef LUA_INTEGER_FMT | ||
105 | # define LUA_INTEGER_FMT "%d" | ||
106 | # endif | ||
107 | # ifndef LUAI_UACINT | ||
108 | # define LUAI_UACINT lua_Integer | ||
109 | # endif | ||
101 | /* different Lua 5.3 versions have conflicting variants of this macro | 110 | /* different Lua 5.3 versions have conflicting variants of this macro |
102 | * in luaconf.h, there's a fallback implementation in lstrlib.c, and | 111 | * in luaconf.h, there's a fallback implementation in lstrlib.c, and |
103 | * the macro isn't used for string (un)packing anyway! | 112 | * the macro isn't used for string (un)packing anyway! |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstrlib.c,v 1.239 2015/11/25 16:28:17 roberto Exp $ | 2 | ** $Id: lstrlib.c,v 1.254 2016/12/22 13:08:50 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 | */ |
@@ -13,6 +13,7 @@ | |||
13 | #include <ctype.h> | 13 | #include <ctype.h> |
14 | #include <float.h> | 14 | #include <float.h> |
15 | #include <limits.h> | 15 | #include <limits.h> |
16 | #include <locale.h> | ||
16 | #include <stddef.h> | 17 | #include <stddef.h> |
17 | #include <stdio.h> | 18 | #include <stdio.h> |
18 | #include <stdlib.h> | 19 | #include <stdlib.h> |
@@ -26,7 +27,8 @@ | |||
26 | 27 | ||
27 | /* | 28 | /* |
28 | ** maximum number of captures that a pattern can do during | 29 | ** maximum number of captures that a pattern can do during |
29 | ** pattern-matching. This limit is arbitrary. | 30 | ** pattern-matching. This limit is arbitrary, but must fit in |
31 | ** an unsigned char. | ||
30 | */ | 32 | */ |
31 | #if !defined(LUA_MAXCAPTURES) | 33 | #if !defined(LUA_MAXCAPTURES) |
32 | #define LUA_MAXCAPTURES 32 | 34 | #define LUA_MAXCAPTURES 32 |
@@ -214,9 +216,8 @@ typedef struct MatchState { | |||
214 | const char *src_end; /* end ('\0') of source string */ | 216 | const char *src_end; /* end ('\0') of source string */ |
215 | const char *p_end; /* end ('\0') of pattern */ | 217 | const char *p_end; /* end ('\0') of pattern */ |
216 | lua_State *L; | 218 | lua_State *L; |
217 | size_t nrep; /* limit to avoid non-linear complexity */ | ||
218 | int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ | 219 | int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ |
219 | int level; /* total number of captures (finished or unfinished) */ | 220 | unsigned char level; /* total number of captures (finished or unfinished) */ |
220 | struct { | 221 | struct { |
221 | const char *init; | 222 | const char *init; |
222 | ptrdiff_t len; | 223 | ptrdiff_t len; |
@@ -234,17 +235,6 @@ static const char *match (MatchState *ms, const char *s, const char *p); | |||
234 | #endif | 235 | #endif |
235 | 236 | ||
236 | 237 | ||
237 | /* | ||
238 | ** parameters to control the maximum number of operators handled in | ||
239 | ** a match (to avoid non-linear complexity). The maximum will be: | ||
240 | ** (subject length) * A_REPS + B_REPS | ||
241 | */ | ||
242 | #if !defined(A_REPS) | ||
243 | #define A_REPS 4 | ||
244 | #define B_REPS 100000 | ||
245 | #endif | ||
246 | |||
247 | |||
248 | #define L_ESC '%' | 238 | #define L_ESC '%' |
249 | #define SPECIALS "^$*+?.([%-" | 239 | #define SPECIALS "^$*+?.([%-" |
250 | 240 | ||
@@ -502,8 +492,6 @@ static const char *match (MatchState *ms, const char *s, const char *p) { | |||
502 | s = NULL; /* fail */ | 492 | s = NULL; /* fail */ |
503 | } | 493 | } |
504 | else { /* matched once */ | 494 | else { /* matched once */ |
505 | if (ms->nrep-- == 0) | ||
506 | luaL_error(ms->L, "pattern too complex"); | ||
507 | switch (*ep) { /* handle optional suffix */ | 495 | switch (*ep) { /* handle optional suffix */ |
508 | case '?': { /* optional */ | 496 | case '?': { /* optional */ |
509 | const char *res; | 497 | const char *res; |
@@ -607,10 +595,6 @@ static void prepstate (MatchState *ms, lua_State *L, | |||
607 | ms->src_init = s; | 595 | ms->src_init = s; |
608 | ms->src_end = s + ls; | 596 | ms->src_end = s + ls; |
609 | ms->p_end = p + lp; | 597 | ms->p_end = p + lp; |
610 | if (ls < (MAX_SIZET - B_REPS) / A_REPS) | ||
611 | ms->nrep = A_REPS * ls + B_REPS; | ||
612 | else /* overflow (very long subject) */ | ||
613 | ms->nrep = MAX_SIZET; /* no limit */ | ||
614 | } | 598 | } |
615 | 599 | ||
616 | 600 | ||
@@ -681,6 +665,7 @@ static int str_match (lua_State *L) { | |||
681 | typedef struct GMatchState { | 665 | typedef struct GMatchState { |
682 | const char *src; /* current position */ | 666 | const char *src; /* current position */ |
683 | const char *p; /* pattern */ | 667 | const char *p; /* pattern */ |
668 | const char *lastmatch; /* end of last match */ | ||
684 | MatchState ms; /* match state */ | 669 | MatchState ms; /* match state */ |
685 | } GMatchState; | 670 | } GMatchState; |
686 | 671 | ||
@@ -688,14 +673,12 @@ typedef struct GMatchState { | |||
688 | static int gmatch_aux (lua_State *L) { | 673 | static int gmatch_aux (lua_State *L) { |
689 | GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3)); | 674 | GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3)); |
690 | const char *src; | 675 | const char *src; |
676 | gm->ms.L = L; | ||
691 | for (src = gm->src; src <= gm->ms.src_end; src++) { | 677 | for (src = gm->src; src <= gm->ms.src_end; src++) { |
692 | const char *e; | 678 | const char *e; |
693 | reprepstate(&gm->ms); | 679 | reprepstate(&gm->ms); |
694 | if ((e = match(&gm->ms, src, gm->p)) != NULL) { | 680 | if ((e = match(&gm->ms, src, gm->p)) != NULL && e != gm->lastmatch) { |
695 | if (e == src) /* empty match? */ | 681 | gm->src = gm->lastmatch = e; |
696 | gm->src =src + 1; /* go at least one position */ | ||
697 | else | ||
698 | gm->src = e; | ||
699 | return push_captures(&gm->ms, src, e); | 682 | return push_captures(&gm->ms, src, e); |
700 | } | 683 | } |
701 | } | 684 | } |
@@ -711,7 +694,7 @@ static int gmatch (lua_State *L) { | |||
711 | lua_settop(L, 2); /* keep them on closure to avoid being collected */ | 694 | lua_settop(L, 2); /* keep them on closure to avoid being collected */ |
712 | gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState)); | 695 | gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState)); |
713 | prepstate(&gm->ms, L, s, ls, p, lp); | 696 | prepstate(&gm->ms, L, s, ls, p, lp); |
714 | gm->src = s; gm->p = p; | 697 | gm->src = s; gm->p = p; gm->lastmatch = NULL; |
715 | lua_pushcclosure(L, gmatch_aux, 3); | 698 | lua_pushcclosure(L, gmatch_aux, 3); |
716 | return 1; | 699 | return 1; |
717 | } | 700 | } |
@@ -778,12 +761,13 @@ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, | |||
778 | 761 | ||
779 | static int str_gsub (lua_State *L) { | 762 | static int str_gsub (lua_State *L) { |
780 | size_t srcl, lp; | 763 | size_t srcl, lp; |
781 | const char *src = luaL_checklstring(L, 1, &srcl); | 764 | const char *src = luaL_checklstring(L, 1, &srcl); /* subject */ |
782 | const char *p = luaL_checklstring(L, 2, &lp); | 765 | const char *p = luaL_checklstring(L, 2, &lp); /* pattern */ |
783 | int tr = lua_type(L, 3); | 766 | const char *lastmatch = NULL; /* end of last match */ |
784 | lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); | 767 | int tr = lua_type(L, 3); /* replacement type */ |
768 | lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */ | ||
785 | int anchor = (*p == '^'); | 769 | int anchor = (*p == '^'); |
786 | lua_Integer n = 0; | 770 | lua_Integer n = 0; /* replacement count */ |
787 | MatchState ms; | 771 | MatchState ms; |
788 | luaL_Buffer b; | 772 | luaL_Buffer b; |
789 | luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || | 773 | luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || |
@@ -796,16 +780,15 @@ static int str_gsub (lua_State *L) { | |||
796 | prepstate(&ms, L, src, srcl, p, lp); | 780 | prepstate(&ms, L, src, srcl, p, lp); |
797 | while (n < max_s) { | 781 | while (n < max_s) { |
798 | const char *e; | 782 | const char *e; |
799 | reprepstate(&ms); | 783 | reprepstate(&ms); /* (re)prepare state for new match */ |
800 | if ((e = match(&ms, src, p)) != NULL) { | 784 | if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */ |
801 | n++; | 785 | n++; |
802 | add_value(&ms, &b, src, e, tr); | 786 | add_value(&ms, &b, src, e, tr); /* add replacement to buffer */ |
787 | src = lastmatch = e; | ||
803 | } | 788 | } |
804 | if (e && e>src) /* non empty match? */ | 789 | else if (src < ms.src_end) /* otherwise, skip one character */ |
805 | src = e; /* skip it */ | ||
806 | else if (src < ms.src_end) | ||
807 | luaL_addchar(&b, *src++); | 790 | luaL_addchar(&b, *src++); |
808 | else break; | 791 | else break; /* end of subject */ |
809 | if (anchor) break; | 792 | if (anchor) break; |
810 | } | 793 | } |
811 | luaL_addlstring(&b, src, ms.src_end-src); | 794 | luaL_addlstring(&b, src, ms.src_end-src); |
@@ -830,7 +813,6 @@ static int str_gsub (lua_State *L) { | |||
830 | ** Hexadecimal floating-point formatter | 813 | ** Hexadecimal floating-point formatter |
831 | */ | 814 | */ |
832 | 815 | ||
833 | #include <locale.h> | ||
834 | #include <math.h> | 816 | #include <math.h> |
835 | 817 | ||
836 | #define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char)) | 818 | #define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char)) |
@@ -857,11 +839,12 @@ static lua_Number adddigit (char *buff, int n, lua_Number x) { | |||
857 | 839 | ||
858 | 840 | ||
859 | static int num2straux (char *buff, int sz, lua_Number x) { | 841 | static int num2straux (char *buff, int sz, lua_Number x) { |
860 | if (x != x || x == HUGE_VAL || x == -HUGE_VAL) /* inf or NaN? */ | 842 | /* if 'inf' or 'NaN', format it like '%g' */ |
861 | return l_sprintf(buff, sz, LUA_NUMBER_FMT, x); /* equal to '%g' */ | 843 | if (x != x || x == (lua_Number)HUGE_VAL || x == -(lua_Number)HUGE_VAL) |
844 | return l_sprintf(buff, sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)x); | ||
862 | else if (x == 0) { /* can be -0... */ | 845 | else if (x == 0) { /* can be -0... */ |
863 | /* create "0" or "-0" followed by exponent */ | 846 | /* create "0" or "-0" followed by exponent */ |
864 | return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", x); | 847 | return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", (LUAI_UACNUMBER)x); |
865 | } | 848 | } |
866 | else { | 849 | else { |
867 | int e; | 850 | int e; |
@@ -922,16 +905,14 @@ static int lua_number2strx (lua_State *L, char *buff, int sz, | |||
922 | #define MAX_FORMAT 32 | 905 | #define MAX_FORMAT 32 |
923 | 906 | ||
924 | 907 | ||
925 | static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { | 908 | static void addquoted (luaL_Buffer *b, const char *s, size_t len) { |
926 | size_t l; | ||
927 | const char *s = luaL_checklstring(L, arg, &l); | ||
928 | luaL_addchar(b, '"'); | 909 | luaL_addchar(b, '"'); |
929 | while (l--) { | 910 | while (len--) { |
930 | if (*s == '"' || *s == '\\' || *s == '\n') { | 911 | if (*s == '"' || *s == '\\' || *s == '\n') { |
931 | luaL_addchar(b, '\\'); | 912 | luaL_addchar(b, '\\'); |
932 | luaL_addchar(b, *s); | 913 | luaL_addchar(b, *s); |
933 | } | 914 | } |
934 | else if (*s == '\0' || iscntrl(uchar(*s))) { | 915 | else if (iscntrl(uchar(*s))) { |
935 | char buff[10]; | 916 | char buff[10]; |
936 | if (!isdigit(uchar(*(s+1)))) | 917 | if (!isdigit(uchar(*(s+1)))) |
937 | l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s)); | 918 | l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s)); |
@@ -946,6 +927,57 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { | |||
946 | luaL_addchar(b, '"'); | 927 | luaL_addchar(b, '"'); |
947 | } | 928 | } |
948 | 929 | ||
930 | |||
931 | /* | ||
932 | ** Ensures the 'buff' string uses a dot as the radix character. | ||
933 | */ | ||
934 | static void checkdp (char *buff, int nb) { | ||
935 | if (memchr(buff, '.', nb) == NULL) { /* no dot? */ | ||
936 | char point = lua_getlocaledecpoint(); /* try locale point */ | ||
937 | char *ppoint = (char *)memchr(buff, point, nb); | ||
938 | if (ppoint) *ppoint = '.'; /* change it to a dot */ | ||
939 | } | ||
940 | } | ||
941 | |||
942 | |||
943 | static void addliteral (lua_State *L, luaL_Buffer *b, int arg) { | ||
944 | switch (lua_type(L, arg)) { | ||
945 | case LUA_TSTRING: { | ||
946 | size_t len; | ||
947 | const char *s = lua_tolstring(L, arg, &len); | ||
948 | addquoted(b, s, len); | ||
949 | break; | ||
950 | } | ||
951 | case LUA_TNUMBER: { | ||
952 | char *buff = luaL_prepbuffsize(b, MAX_ITEM); | ||
953 | int nb; | ||
954 | if (!lua_isinteger(L, arg)) { /* float? */ | ||
955 | lua_Number n = lua_tonumber(L, arg); /* write as hexa ('%a') */ | ||
956 | nb = lua_number2strx(L, buff, MAX_ITEM, "%" LUA_NUMBER_FRMLEN "a", n); | ||
957 | checkdp(buff, nb); /* ensure it uses a dot */ | ||
958 | } | ||
959 | else { /* integers */ | ||
960 | lua_Integer n = lua_tointeger(L, arg); | ||
961 | const char *format = (n == LUA_MININTEGER) /* corner case? */ | ||
962 | ? "0x%" LUA_INTEGER_FRMLEN "x" /* use hexa */ | ||
963 | : LUA_INTEGER_FMT; /* else use default format */ | ||
964 | nb = l_sprintf(buff, MAX_ITEM, format, (LUAI_UACINT)n); | ||
965 | } | ||
966 | luaL_addsize(b, nb); | ||
967 | break; | ||
968 | } | ||
969 | case LUA_TNIL: case LUA_TBOOLEAN: { | ||
970 | luaL_tolstring(L, arg, NULL); | ||
971 | luaL_addvalue(b); | ||
972 | break; | ||
973 | } | ||
974 | default: { | ||
975 | luaL_argerror(L, arg, "value has no literal form"); | ||
976 | } | ||
977 | } | ||
978 | } | ||
979 | |||
980 | |||
949 | static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { | 981 | static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { |
950 | const char *p = strfrmt; | 982 | const char *p = strfrmt; |
951 | while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ | 983 | while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ |
@@ -1010,7 +1042,7 @@ static int str_format (lua_State *L) { | |||
1010 | case 'o': case 'u': case 'x': case 'X': { | 1042 | case 'o': case 'u': case 'x': case 'X': { |
1011 | lua_Integer n = luaL_checkinteger(L, arg); | 1043 | lua_Integer n = luaL_checkinteger(L, arg); |
1012 | addlenmod(form, LUA_INTEGER_FRMLEN); | 1044 | addlenmod(form, LUA_INTEGER_FRMLEN); |
1013 | nb = l_sprintf(buff, MAX_ITEM, form, n); | 1045 | nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACINT)n); |
1014 | break; | 1046 | break; |
1015 | } | 1047 | } |
1016 | case 'a': case 'A': | 1048 | case 'a': case 'A': |
@@ -1020,12 +1052,13 @@ static int str_format (lua_State *L) { | |||
1020 | break; | 1052 | break; |
1021 | case 'e': case 'E': case 'f': | 1053 | case 'e': case 'E': case 'f': |
1022 | case 'g': case 'G': { | 1054 | case 'g': case 'G': { |
1055 | lua_Number n = luaL_checknumber(L, arg); | ||
1023 | addlenmod(form, LUA_NUMBER_FRMLEN); | 1056 | addlenmod(form, LUA_NUMBER_FRMLEN); |
1024 | nb = l_sprintf(buff, MAX_ITEM, form, luaL_checknumber(L, arg)); | 1057 | nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACNUMBER)n); |
1025 | break; | 1058 | break; |
1026 | } | 1059 | } |
1027 | case 'q': { | 1060 | case 'q': { |
1028 | addquoted(L, &b, arg); | 1061 | addliteral(L, &b, arg); |
1029 | break; | 1062 | break; |
1030 | } | 1063 | } |
1031 | case 's': { | 1064 | case 's': { |
@@ -1070,8 +1103,8 @@ static int str_format (lua_State *L) { | |||
1070 | 1103 | ||
1071 | 1104 | ||
1072 | /* value used for padding */ | 1105 | /* value used for padding */ |
1073 | #if !defined(LUA_PACKPADBYTE) | 1106 | #if !defined(LUAL_PACKPADBYTE) |
1074 | #define LUA_PACKPADBYTE 0x00 | 1107 | #define LUAL_PACKPADBYTE 0x00 |
1075 | #endif | 1108 | #endif |
1076 | 1109 | ||
1077 | /* maximum size for the binary representation of an integer */ | 1110 | /* maximum size for the binary representation of an integer */ |
@@ -1228,7 +1261,7 @@ static KOption getoption (Header *h, const char **fmt, int *size) { | |||
1228 | ** 'psize' is filled with option's size, 'notoalign' with its | 1261 | ** 'psize' is filled with option's size, 'notoalign' with its |
1229 | ** alignment requirements. | 1262 | ** alignment requirements. |
1230 | ** Local variable 'size' gets the size to be aligned. (Kpadal option | 1263 | ** Local variable 'size' gets the size to be aligned. (Kpadal option |
1231 | ** always gets its full alignment, other options are limited by | 1264 | ** always gets its full alignment, other options are limited by |
1232 | ** the maximum alignment ('maxalign'). Kchar option needs no alignment | 1265 | ** the maximum alignment ('maxalign'). Kchar option needs no alignment |
1233 | ** despite its size. | 1266 | ** despite its size. |
1234 | */ | 1267 | */ |
@@ -1308,7 +1341,7 @@ static int str_pack (lua_State *L) { | |||
1308 | KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); | 1341 | KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); |
1309 | totalsize += ntoalign + size; | 1342 | totalsize += ntoalign + size; |
1310 | while (ntoalign-- > 0) | 1343 | while (ntoalign-- > 0) |
1311 | luaL_addchar(&b, LUA_PACKPADBYTE); /* fill alignment */ | 1344 | luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */ |
1312 | arg++; | 1345 | arg++; |
1313 | switch (opt) { | 1346 | switch (opt) { |
1314 | case Kint: { /* signed integers */ | 1347 | case Kint: { /* signed integers */ |
@@ -1343,13 +1376,11 @@ static int str_pack (lua_State *L) { | |||
1343 | case Kchar: { /* fixed-size string */ | 1376 | case Kchar: { /* fixed-size string */ |
1344 | size_t len; | 1377 | size_t len; |
1345 | const char *s = luaL_checklstring(L, arg, &len); | 1378 | const char *s = luaL_checklstring(L, arg, &len); |
1346 | if ((size_t)size <= len) /* string larger than (or equal to) needed? */ | 1379 | luaL_argcheck(L, len <= (size_t)size, arg, |
1347 | luaL_addlstring(&b, s, size); /* truncate string to asked size */ | 1380 | "string longer than given size"); |
1348 | else { /* string smaller than needed */ | 1381 | luaL_addlstring(&b, s, len); /* add string */ |
1349 | luaL_addlstring(&b, s, len); /* add it all */ | 1382 | while (len++ < (size_t)size) /* pad extra space */ |
1350 | while (len++ < (size_t)size) /* pad extra space */ | 1383 | luaL_addchar(&b, LUAL_PACKPADBYTE); |
1351 | luaL_addchar(&b, LUA_PACKPADBYTE); | ||
1352 | } | ||
1353 | break; | 1384 | break; |
1354 | } | 1385 | } |
1355 | case Kstring: { /* strings with length count */ | 1386 | case Kstring: { /* strings with length count */ |
@@ -1372,7 +1403,7 @@ static int str_pack (lua_State *L) { | |||
1372 | totalsize += len + 1; | 1403 | totalsize += len + 1; |
1373 | break; | 1404 | break; |
1374 | } | 1405 | } |
1375 | case Kpadding: luaL_addchar(&b, LUA_PACKPADBYTE); /* FALLTHROUGH */ | 1406 | case Kpadding: luaL_addchar(&b, LUAL_PACKPADBYTE); /* FALLTHROUGH */ |
1376 | case Kpaddalign: case Knop: | 1407 | case Kpaddalign: case Knop: |
1377 | arg--; /* undo increment */ | 1408 | arg--; /* undo increment */ |
1378 | break; | 1409 | break; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltablib.c,v 1.90 2015/11/25 12:48:57 roberto Exp $ | 2 | ** $Id: ltablib.c,v 1.93 2016/02/25 19:41:54 roberto Exp $ |
3 | ** Library for Table Manipulation | 3 | ** Library for Table Manipulation |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -53,7 +53,7 @@ static void checktab (lua_State *L, int arg, int what) { | |||
53 | lua_pop(L, n); /* pop metatable and tested metamethods */ | 53 | lua_pop(L, n); /* pop metatable and tested metamethods */ |
54 | } | 54 | } |
55 | else | 55 | else |
56 | luaL_argerror(L, arg, "table expected"); /* force an error */ | 56 | luaL_checktype(L, arg, LUA_TTABLE); /* force an error */ |
57 | } | 57 | } |
58 | } | 58 | } |
59 | 59 | ||
@@ -139,7 +139,7 @@ static int tmove (lua_State *L) { | |||
139 | n = e - f + 1; /* number of elements to move */ | 139 | n = e - f + 1; /* number of elements to move */ |
140 | luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4, | 140 | luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4, |
141 | "destination wrap around"); | 141 | "destination wrap around"); |
142 | if (t > e || t <= f || tt != 1) { | 142 | if (t > e || t <= f || (tt != 1 && !lua_compare(L, 1, tt, LUA_OPEQ))) { |
143 | for (i = 0; i < n; i++) { | 143 | for (i = 0; i < n; i++) { |
144 | lua_geti(L, 1, f + i); | 144 | lua_geti(L, 1, f + i); |
145 | lua_seti(L, tt, t + i); | 145 | lua_seti(L, tt, t + i); |
@@ -152,7 +152,7 @@ static int tmove (lua_State *L) { | |||
152 | } | 152 | } |
153 | } | 153 | } |
154 | } | 154 | } |
155 | lua_pushvalue(L, tt); /* return "to table" */ | 155 | lua_pushvalue(L, tt); /* return destination table */ |
156 | return 1; | 156 | return 1; |
157 | } | 157 | } |
158 | 158 | ||
@@ -172,7 +172,7 @@ static int tconcat (lua_State *L) { | |||
172 | size_t lsep; | 172 | size_t lsep; |
173 | const char *sep = luaL_optlstring(L, 2, "", &lsep); | 173 | const char *sep = luaL_optlstring(L, 2, "", &lsep); |
174 | lua_Integer i = luaL_optinteger(L, 3, 1); | 174 | lua_Integer i = luaL_optinteger(L, 3, 1); |
175 | last = luaL_opt(L, luaL_checkinteger, 4, last); | 175 | last = luaL_optinteger(L, 4, last); |
176 | luaL_buffinit(L, &b); | 176 | luaL_buffinit(L, &b); |
177 | for (; i < last; i++) { | 177 | for (; i < last; i++) { |
178 | addfield(L, &b, i); | 178 | addfield(L, &b, i); |
@@ -232,6 +232,10 @@ static int unpack (lua_State *L) { | |||
232 | */ | 232 | */ |
233 | 233 | ||
234 | 234 | ||
235 | /* type for array indices */ | ||
236 | typedef unsigned int IdxT; | ||
237 | |||
238 | |||
235 | /* | 239 | /* |
236 | ** Produce a "random" 'unsigned int' to randomize pivot choice. This | 240 | ** Produce a "random" 'unsigned int' to randomize pivot choice. This |
237 | ** macro is used only when 'sort' detects a big imbalance in the result | 241 | ** macro is used only when 'sort' detects a big imbalance in the result |
@@ -270,7 +274,7 @@ static unsigned int l_randomizePivot (void) { | |||
270 | #define RANLIMIT 100u | 274 | #define RANLIMIT 100u |
271 | 275 | ||
272 | 276 | ||
273 | static void set2 (lua_State *L, unsigned int i, unsigned int j) { | 277 | static void set2 (lua_State *L, IdxT i, IdxT j) { |
274 | lua_seti(L, 1, i); | 278 | lua_seti(L, 1, i); |
275 | lua_seti(L, 1, j); | 279 | lua_seti(L, 1, j); |
276 | } | 280 | } |
@@ -303,10 +307,9 @@ static int sort_comp (lua_State *L, int a, int b) { | |||
303 | ** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up] | 307 | ** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up] |
304 | ** returns 'i'. | 308 | ** returns 'i'. |
305 | */ | 309 | */ |
306 | static unsigned int partition (lua_State *L, unsigned int lo, | 310 | static IdxT partition (lua_State *L, IdxT lo, IdxT up) { |
307 | unsigned int up) { | 311 | IdxT i = lo; /* will be incremented before first use */ |
308 | unsigned int i = lo; /* will be incremented before first use */ | 312 | IdxT j = up - 1; /* will be decremented before first use */ |
309 | unsigned int j = up - 1; /* will be decremented before first use */ | ||
310 | /* loop invariant: a[lo .. i] <= P <= a[j .. up] */ | 313 | /* loop invariant: a[lo .. i] <= P <= a[j .. up] */ |
311 | for (;;) { | 314 | for (;;) { |
312 | /* next loop: repeat ++i while a[i] < P */ | 315 | /* next loop: repeat ++i while a[i] < P */ |
@@ -340,10 +343,9 @@ static unsigned int partition (lua_State *L, unsigned int lo, | |||
340 | ** Choose an element in the middle (2nd-3th quarters) of [lo,up] | 343 | ** Choose an element in the middle (2nd-3th quarters) of [lo,up] |
341 | ** "randomized" by 'rnd' | 344 | ** "randomized" by 'rnd' |
342 | */ | 345 | */ |
343 | static unsigned int choosePivot (unsigned int lo, unsigned int up, | 346 | static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) { |
344 | unsigned int rnd) { | 347 | IdxT r4 = (up - lo) / 4; /* range/4 */ |
345 | unsigned int r4 = (unsigned int)(up - lo) / 4u; /* range/4 */ | 348 | IdxT p = rnd % (r4 * 2) + (lo + r4); |
346 | unsigned int p = rnd % (r4 * 2) + (lo + r4); | ||
347 | lua_assert(lo + r4 <= p && p <= up - r4); | 349 | lua_assert(lo + r4 <= p && p <= up - r4); |
348 | return p; | 350 | return p; |
349 | } | 351 | } |
@@ -352,11 +354,11 @@ static unsigned int choosePivot (unsigned int lo, unsigned int up, | |||
352 | /* | 354 | /* |
353 | ** QuickSort algorithm (recursive function) | 355 | ** QuickSort algorithm (recursive function) |
354 | */ | 356 | */ |
355 | static void auxsort (lua_State *L, unsigned int lo, unsigned int up, | 357 | static void auxsort (lua_State *L, IdxT lo, IdxT up, |
356 | unsigned int rnd) { | 358 | unsigned int rnd) { |
357 | while (lo < up) { /* loop for tail recursion */ | 359 | while (lo < up) { /* loop for tail recursion */ |
358 | unsigned int p; /* Pivot index */ | 360 | IdxT p; /* Pivot index */ |
359 | unsigned int n; /* to be used later */ | 361 | IdxT n; /* to be used later */ |
360 | /* sort elements 'lo', 'p', and 'up' */ | 362 | /* sort elements 'lo', 'p', and 'up' */ |
361 | lua_geti(L, 1, lo); | 363 | lua_geti(L, 1, lo); |
362 | lua_geti(L, 1, up); | 364 | lua_geti(L, 1, up); |
@@ -400,7 +402,7 @@ static void auxsort (lua_State *L, unsigned int lo, unsigned int up, | |||
400 | n = up - p; /* size of smaller interval */ | 402 | n = up - p; /* size of smaller interval */ |
401 | up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */ | 403 | up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */ |
402 | } | 404 | } |
403 | if ((up - lo) / 128u > n) /* partition too imbalanced? */ | 405 | if ((up - lo) / 128 > n) /* partition too imbalanced? */ |
404 | rnd = l_randomizePivot(); /* try a new randomization */ | 406 | rnd = l_randomizePivot(); /* try a new randomization */ |
405 | } /* tail call auxsort(L, lo, up, rnd) */ | 407 | } /* tail call auxsort(L, lo, up, rnd) */ |
406 | } | 408 | } |
@@ -410,11 +412,10 @@ static int sort (lua_State *L) { | |||
410 | lua_Integer n = aux_getn(L, 1, TAB_RW); | 412 | lua_Integer n = aux_getn(L, 1, TAB_RW); |
411 | if (n > 1) { /* non-trivial interval? */ | 413 | if (n > 1) { /* non-trivial interval? */ |
412 | luaL_argcheck(L, n < INT_MAX, 1, "array too big"); | 414 | luaL_argcheck(L, n < INT_MAX, 1, "array too big"); |
413 | luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */ | ||
414 | if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ | 415 | if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ |
415 | luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */ | 416 | luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */ |
416 | lua_settop(L, 2); /* make sure there are two arguments */ | 417 | lua_settop(L, 2); /* make sure there are two arguments */ |
417 | auxsort(L, 1, (unsigned int)n, 0u); | 418 | auxsort(L, 1, (IdxT)n, 0); |
418 | } | 419 | } |
419 | return 0; | 420 | return 0; |
420 | } | 421 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lutf8lib.c,v 1.15 2015/03/28 19:16:55 roberto Exp $ | 2 | ** $Id: lutf8lib.c,v 1.16 2016/12/22 13:08:50 roberto Exp $ |
3 | ** Standard library for UTF-8 manipulation | 3 | ** Standard library for UTF-8 manipulation |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -194,7 +194,7 @@ static int byteoffset (lua_State *L) { | |||
194 | lua_pushinteger(L, posi + 1); | 194 | lua_pushinteger(L, posi + 1); |
195 | else /* no such character */ | 195 | else /* no such character */ |
196 | lua_pushnil(L); | 196 | lua_pushnil(L); |
197 | return 1; | 197 | return 1; |
198 | } | 198 | } |
199 | 199 | ||
200 | 200 | ||