aboutsummaryrefslogtreecommitdiff
path: root/src/lua/lstrlib.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lua/lstrlib.c (renamed from src/lua-5.3/lstrlib.c)483
1 files changed, 352 insertions, 131 deletions
diff --git a/src/lua-5.3/lstrlib.c b/src/lua/lstrlib.c
index b4bed7e..2ba8bde 100644
--- a/src/lua-5.3/lstrlib.c
+++ b/src/lua/lstrlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstrlib.c,v 1.254.1.1 2017/04/19 17:29:57 roberto Exp $ 2** $Id: lstrlib.c $
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*/
@@ -14,6 +14,7 @@
14#include <float.h> 14#include <float.h>
15#include <limits.h> 15#include <limits.h>
16#include <locale.h> 16#include <locale.h>
17#include <math.h>
17#include <stddef.h> 18#include <stddef.h>
18#include <stdio.h> 19#include <stdio.h>
19#include <stdlib.h> 20#include <stdlib.h>
@@ -59,23 +60,50 @@ static int str_len (lua_State *L) {
59} 60}
60 61
61 62
62/* translate a relative string position: negative means back from end */ 63/*
63static lua_Integer posrelat (lua_Integer pos, size_t len) { 64** translate a relative initial string position
64 if (pos >= 0) return pos; 65** (negative means back from end): clip result to [1, inf).
65 else if (0u - (size_t)pos > len) return 0; 66** The length of any string in Lua must fit in a lua_Integer,
66 else return (lua_Integer)len + pos + 1; 67** so there are no overflows in the casts.
68** The inverted comparison avoids a possible overflow
69** computing '-pos'.
70*/
71static size_t posrelatI (lua_Integer pos, size_t len) {
72 if (pos > 0)
73 return (size_t)pos;
74 else if (pos == 0)
75 return 1;
76 else if (pos < -(lua_Integer)len) /* inverted comparison */
77 return 1; /* clip to 1 */
78 else return len + (size_t)pos + 1;
79}
80
81
82/*
83** Gets an optional ending string position from argument 'arg',
84** with default value 'def'.
85** Negative means back from end: clip result to [0, len]
86*/
87static size_t getendpos (lua_State *L, int arg, lua_Integer def,
88 size_t len) {
89 lua_Integer pos = luaL_optinteger(L, arg, def);
90 if (pos > (lua_Integer)len)
91 return len;
92 else if (pos >= 0)
93 return (size_t)pos;
94 else if (pos < -(lua_Integer)len)
95 return 0;
96 else return len + (size_t)pos + 1;
67} 97}
68 98
69 99
70static int str_sub (lua_State *L) { 100static int str_sub (lua_State *L) {
71 size_t l; 101 size_t l;
72 const char *s = luaL_checklstring(L, 1, &l); 102 const char *s = luaL_checklstring(L, 1, &l);
73 lua_Integer start = posrelat(luaL_checkinteger(L, 2), l); 103 size_t start = posrelatI(luaL_checkinteger(L, 2), l);
74 lua_Integer end = posrelat(luaL_optinteger(L, 3, -1), l); 104 size_t end = getendpos(L, 3, -1, l);
75 if (start < 1) start = 1;
76 if (end > (lua_Integer)l) end = l;
77 if (start <= end) 105 if (start <= end)
78 lua_pushlstring(L, s + start - 1, (size_t)(end - start) + 1); 106 lua_pushlstring(L, s + start - 1, (end - start) + 1);
79 else lua_pushliteral(L, ""); 107 else lua_pushliteral(L, "");
80 return 1; 108 return 1;
81} 109}
@@ -148,13 +176,12 @@ static int str_rep (lua_State *L) {
148static int str_byte (lua_State *L) { 176static int str_byte (lua_State *L) {
149 size_t l; 177 size_t l;
150 const char *s = luaL_checklstring(L, 1, &l); 178 const char *s = luaL_checklstring(L, 1, &l);
151 lua_Integer posi = posrelat(luaL_optinteger(L, 2, 1), l); 179 lua_Integer pi = luaL_optinteger(L, 2, 1);
152 lua_Integer pose = posrelat(luaL_optinteger(L, 3, posi), l); 180 size_t posi = posrelatI(pi, l);
181 size_t pose = getendpos(L, 3, pi, l);
153 int n, i; 182 int n, i;
154 if (posi < 1) posi = 1;
155 if (pose > (lua_Integer)l) pose = l;
156 if (posi > pose) return 0; /* empty interval; return no values */ 183 if (posi > pose) return 0; /* empty interval; return no values */
157 if (pose - posi >= INT_MAX) /* arithmetic overflow? */ 184 if (pose - posi >= (size_t)INT_MAX) /* arithmetic overflow? */
158 return luaL_error(L, "string slice too long"); 185 return luaL_error(L, "string slice too long");
159 n = (int)(pose - posi) + 1; 186 n = (int)(pose - posi) + 1;
160 luaL_checkstack(L, n, "string slice too long"); 187 luaL_checkstack(L, n, "string slice too long");
@@ -170,8 +197,8 @@ static int str_char (lua_State *L) {
170 luaL_Buffer b; 197 luaL_Buffer b;
171 char *p = luaL_buffinitsize(L, &b, n); 198 char *p = luaL_buffinitsize(L, &b, n);
172 for (i=1; i<=n; i++) { 199 for (i=1; i<=n; i++) {
173 lua_Integer c = luaL_checkinteger(L, i); 200 lua_Unsigned c = (lua_Unsigned)luaL_checkinteger(L, i);
174 luaL_argcheck(L, uchar(c) == c, i, "value out of range"); 201 luaL_argcheck(L, c <= (lua_Unsigned)UCHAR_MAX, i, "value out of range");
175 p[i - 1] = uchar(c); 202 p[i - 1] = uchar(c);
176 } 203 }
177 luaL_pushresultsize(&b, n); 204 luaL_pushresultsize(&b, n);
@@ -179,22 +206,38 @@ static int str_char (lua_State *L) {
179} 206}
180 207
181 208
182static int writer (lua_State *L, const void *b, size_t size, void *B) { 209/*
183 (void)L; 210** Buffer to store the result of 'string.dump'. It must be initialized
184 luaL_addlstring((luaL_Buffer *) B, (const char *)b, size); 211** after the call to 'lua_dump', to ensure that the function is on the
212** top of the stack when 'lua_dump' is called. ('luaL_buffinit' might
213** push stuff.)
214*/
215struct str_Writer {
216 int init; /* true iff buffer has been initialized */
217 luaL_Buffer B;
218};
219
220
221static int writer (lua_State *L, const void *b, size_t size, void *ud) {
222 struct str_Writer *state = (struct str_Writer *)ud;
223 if (!state->init) {
224 state->init = 1;
225 luaL_buffinit(L, &state->B);
226 }
227 luaL_addlstring(&state->B, (const char *)b, size);
185 return 0; 228 return 0;
186} 229}
187 230
188 231
189static int str_dump (lua_State *L) { 232static int str_dump (lua_State *L) {
190 luaL_Buffer b; 233 struct str_Writer state;
191 int strip = lua_toboolean(L, 2); 234 int strip = lua_toboolean(L, 2);
192 luaL_checktype(L, 1, LUA_TFUNCTION); 235 luaL_checktype(L, 1, LUA_TFUNCTION);
193 lua_settop(L, 1); 236 lua_settop(L, 1); /* ensure function is on the top of the stack */
194 luaL_buffinit(L,&b); 237 state.init = 0;
195 if (lua_dump(L, writer, &b, strip) != 0) 238 if (lua_dump(L, writer, &state, strip) != 0)
196 return luaL_error(L, "unable to dump given function"); 239 return luaL_error(L, "unable to dump given function");
197 luaL_pushresult(&b); 240 luaL_pushresult(&state.B);
198 return 1; 241 return 1;
199} 242}
200 243
@@ -202,6 +245,105 @@ static int str_dump (lua_State *L) {
202 245
203/* 246/*
204** {====================================================== 247** {======================================================
248** METAMETHODS
249** =======================================================
250*/
251
252#if defined(LUA_NOCVTS2N) /* { */
253
254/* no coercion from strings to numbers */
255
256static const luaL_Reg stringmetamethods[] = {
257 {"__index", NULL}, /* placeholder */
258 {NULL, NULL}
259};
260
261#else /* }{ */
262
263static int tonum (lua_State *L, int arg) {
264 if (lua_type(L, arg) == LUA_TNUMBER) { /* already a number? */
265 lua_pushvalue(L, arg);
266 return 1;
267 }
268 else { /* check whether it is a numerical string */
269 size_t len;
270 const char *s = lua_tolstring(L, arg, &len);
271 return (s != NULL && lua_stringtonumber(L, s) == len + 1);
272 }
273}
274
275
276static void trymt (lua_State *L, const char *mtname) {
277 lua_settop(L, 2); /* back to the original arguments */
278 if (lua_type(L, 2) == LUA_TSTRING || !luaL_getmetafield(L, 2, mtname))
279 luaL_error(L, "attempt to %s a '%s' with a '%s'", mtname + 2,
280 luaL_typename(L, -2), luaL_typename(L, -1));
281 lua_insert(L, -3); /* put metamethod before arguments */
282 lua_call(L, 2, 1); /* call metamethod */
283}
284
285
286static int arith (lua_State *L, int op, const char *mtname) {
287 if (tonum(L, 1) && tonum(L, 2))
288 lua_arith(L, op); /* result will be on the top */
289 else
290 trymt(L, mtname);
291 return 1;
292}
293
294
295static int arith_add (lua_State *L) {
296 return arith(L, LUA_OPADD, "__add");
297}
298
299static int arith_sub (lua_State *L) {
300 return arith(L, LUA_OPSUB, "__sub");
301}
302
303static int arith_mul (lua_State *L) {
304 return arith(L, LUA_OPMUL, "__mul");
305}
306
307static int arith_mod (lua_State *L) {
308 return arith(L, LUA_OPMOD, "__mod");
309}
310
311static int arith_pow (lua_State *L) {
312 return arith(L, LUA_OPPOW, "__pow");
313}
314
315static int arith_div (lua_State *L) {
316 return arith(L, LUA_OPDIV, "__div");
317}
318
319static int arith_idiv (lua_State *L) {
320 return arith(L, LUA_OPIDIV, "__idiv");
321}
322
323static int arith_unm (lua_State *L) {
324 return arith(L, LUA_OPUNM, "__unm");
325}
326
327
328static const luaL_Reg stringmetamethods[] = {
329 {"__add", arith_add},
330 {"__sub", arith_sub},
331 {"__mul", arith_mul},
332 {"__mod", arith_mod},
333 {"__pow", arith_pow},
334 {"__div", arith_div},
335 {"__idiv", arith_idiv},
336 {"__unm", arith_unm},
337 {"__index", NULL}, /* placeholder */
338 {NULL, NULL}
339};
340
341#endif /* } */
342
343/* }====================================================== */
344
345/*
346** {======================================================
205** PATTERN MATCHING 347** PATTERN MATCHING
206** ======================================================= 348** =======================================================
207*/ 349*/
@@ -547,25 +689,46 @@ static const char *lmemfind (const char *s1, size_t l1,
547} 689}
548 690
549 691
550static void push_onecapture (MatchState *ms, int i, const char *s, 692/*
551 const char *e) { 693** get information about the i-th capture. If there are no captures
694** and 'i==0', return information about the whole match, which
695** is the range 's'..'e'. If the capture is a string, return
696** its length and put its address in '*cap'. If it is an integer
697** (a position), push it on the stack and return CAP_POSITION.
698*/
699static size_t get_onecapture (MatchState *ms, int i, const char *s,
700 const char *e, const char **cap) {
552 if (i >= ms->level) { 701 if (i >= ms->level) {
553 if (i == 0) /* ms->level == 0, too */ 702 if (i != 0)
554 lua_pushlstring(ms->L, s, e - s); /* add whole match */
555 else
556 luaL_error(ms->L, "invalid capture index %%%d", i + 1); 703 luaL_error(ms->L, "invalid capture index %%%d", i + 1);
704 *cap = s;
705 return e - s;
557 } 706 }
558 else { 707 else {
559 ptrdiff_t l = ms->capture[i].len; 708 ptrdiff_t capl = ms->capture[i].len;
560 if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); 709 *cap = ms->capture[i].init;
561 if (l == CAP_POSITION) 710 if (capl == CAP_UNFINISHED)
711 luaL_error(ms->L, "unfinished capture");
712 else if (capl == CAP_POSITION)
562 lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1); 713 lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1);
563 else 714 return capl;
564 lua_pushlstring(ms->L, ms->capture[i].init, l);
565 } 715 }
566} 716}
567 717
568 718
719/*
720** Push the i-th capture on the stack.
721*/
722static void push_onecapture (MatchState *ms, int i, const char *s,
723 const char *e) {
724 const char *cap;
725 ptrdiff_t l = get_onecapture(ms, i, s, e, &cap);
726 if (l != CAP_POSITION)
727 lua_pushlstring(ms->L, cap, l);
728 /* else position was already pushed */
729}
730
731
569static int push_captures (MatchState *ms, const char *s, const char *e) { 732static int push_captures (MatchState *ms, const char *s, const char *e) {
570 int i; 733 int i;
571 int nlevels = (ms->level == 0 && s) ? 1 : ms->level; 734 int nlevels = (ms->level == 0 && s) ? 1 : ms->level;
@@ -608,16 +771,15 @@ static int str_find_aux (lua_State *L, int find) {
608 size_t ls, lp; 771 size_t ls, lp;
609 const char *s = luaL_checklstring(L, 1, &ls); 772 const char *s = luaL_checklstring(L, 1, &ls);
610 const char *p = luaL_checklstring(L, 2, &lp); 773 const char *p = luaL_checklstring(L, 2, &lp);
611 lua_Integer init = posrelat(luaL_optinteger(L, 3, 1), ls); 774 size_t init = posrelatI(luaL_optinteger(L, 3, 1), ls) - 1;
612 if (init < 1) init = 1; 775 if (init > ls) { /* start after string's end? */
613 else if (init > (lua_Integer)ls + 1) { /* start after string's end? */ 776 luaL_pushfail(L); /* cannot find anything */
614 lua_pushnil(L); /* cannot find anything */
615 return 1; 777 return 1;
616 } 778 }
617 /* explicit request or no special characters? */ 779 /* explicit request or no special characters? */
618 if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) { 780 if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) {
619 /* do a plain search */ 781 /* do a plain search */
620 const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp); 782 const char *s2 = lmemfind(s + init, ls - init, p, lp);
621 if (s2) { 783 if (s2) {
622 lua_pushinteger(L, (s2 - s) + 1); 784 lua_pushinteger(L, (s2 - s) + 1);
623 lua_pushinteger(L, (s2 - s) + lp); 785 lua_pushinteger(L, (s2 - s) + lp);
@@ -626,7 +788,7 @@ static int str_find_aux (lua_State *L, int find) {
626 } 788 }
627 else { 789 else {
628 MatchState ms; 790 MatchState ms;
629 const char *s1 = s + init - 1; 791 const char *s1 = s + init;
630 int anchor = (*p == '^'); 792 int anchor = (*p == '^');
631 if (anchor) { 793 if (anchor) {
632 p++; lp--; /* skip anchor character */ 794 p++; lp--; /* skip anchor character */
@@ -646,7 +808,7 @@ static int str_find_aux (lua_State *L, int find) {
646 } 808 }
647 } while (s1++ < ms.src_end && !anchor); 809 } while (s1++ < ms.src_end && !anchor);
648 } 810 }
649 lua_pushnil(L); /* not found */ 811 luaL_pushfail(L); /* not found */
650 return 1; 812 return 1;
651} 813}
652 814
@@ -690,11 +852,14 @@ static int gmatch (lua_State *L) {
690 size_t ls, lp; 852 size_t ls, lp;
691 const char *s = luaL_checklstring(L, 1, &ls); 853 const char *s = luaL_checklstring(L, 1, &ls);
692 const char *p = luaL_checklstring(L, 2, &lp); 854 const char *p = luaL_checklstring(L, 2, &lp);
855 size_t init = posrelatI(luaL_optinteger(L, 3, 1), ls) - 1;
693 GMatchState *gm; 856 GMatchState *gm;
694 lua_settop(L, 2); /* keep them on closure to avoid being collected */ 857 lua_settop(L, 2); /* keep strings on closure to avoid being collected */
695 gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState)); 858 gm = (GMatchState *)lua_newuserdatauv(L, sizeof(GMatchState), 0);
859 if (init > ls) /* start after string's end? */
860 init = ls + 1; /* avoid overflows in 's + init' */
696 prepstate(&gm->ms, L, s, ls, p, lp); 861 prepstate(&gm->ms, L, s, ls, p, lp);
697 gm->src = s; gm->p = p; gm->lastmatch = NULL; 862 gm->src = s + init; gm->p = p; gm->lastmatch = NULL;
698 lua_pushcclosure(L, gmatch_aux, 3); 863 lua_pushcclosure(L, gmatch_aux, 3);
699 return 1; 864 return 1;
700} 865}
@@ -702,60 +867,72 @@ static int gmatch (lua_State *L) {
702 867
703static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, 868static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
704 const char *e) { 869 const char *e) {
705 size_t l, i; 870 size_t l;
706 lua_State *L = ms->L; 871 lua_State *L = ms->L;
707 const char *news = lua_tolstring(L, 3, &l); 872 const char *news = lua_tolstring(L, 3, &l);
708 for (i = 0; i < l; i++) { 873 const char *p;
709 if (news[i] != L_ESC) 874 while ((p = (char *)memchr(news, L_ESC, l)) != NULL) {
710 luaL_addchar(b, news[i]); 875 luaL_addlstring(b, news, p - news);
711 else { 876 p++; /* skip ESC */
712 i++; /* skip ESC */ 877 if (*p == L_ESC) /* '%%' */
713 if (!isdigit(uchar(news[i]))) { 878 luaL_addchar(b, *p);
714 if (news[i] != L_ESC) 879 else if (*p == '0') /* '%0' */
715 luaL_error(L, "invalid use of '%c' in replacement string", L_ESC); 880 luaL_addlstring(b, s, e - s);
716 luaL_addchar(b, news[i]); 881 else if (isdigit(uchar(*p))) { /* '%n' */
717 } 882 const char *cap;
718 else if (news[i] == '0') 883 ptrdiff_t resl = get_onecapture(ms, *p - '1', s, e, &cap);
719 luaL_addlstring(b, s, e - s); 884 if (resl == CAP_POSITION)
720 else { 885 luaL_addvalue(b); /* add position to accumulated result */
721 push_onecapture(ms, news[i] - '1', s, e); 886 else
722 luaL_tolstring(L, -1, NULL); /* if number, convert it to string */ 887 luaL_addlstring(b, cap, resl);
723 lua_remove(L, -2); /* remove original value */
724 luaL_addvalue(b); /* add capture to accumulated result */
725 }
726 } 888 }
889 else
890 luaL_error(L, "invalid use of '%c' in replacement string", L_ESC);
891 l -= p + 1 - news;
892 news = p + 1;
727 } 893 }
894 luaL_addlstring(b, news, l);
728} 895}
729 896
730 897
731static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, 898/*
732 const char *e, int tr) { 899** Add the replacement value to the string buffer 'b'.
900** Return true if the original string was changed. (Function calls and
901** table indexing resulting in nil or false do not change the subject.)
902*/
903static int add_value (MatchState *ms, luaL_Buffer *b, const char *s,
904 const char *e, int tr) {
733 lua_State *L = ms->L; 905 lua_State *L = ms->L;
734 switch (tr) { 906 switch (tr) {
735 case LUA_TFUNCTION: { 907 case LUA_TFUNCTION: { /* call the function */
736 int n; 908 int n;
737 lua_pushvalue(L, 3); 909 lua_pushvalue(L, 3); /* push the function */
738 n = push_captures(ms, s, e); 910 n = push_captures(ms, s, e); /* all captures as arguments */
739 lua_call(L, n, 1); 911 lua_call(L, n, 1); /* call it */
740 break; 912 break;
741 } 913 }
742 case LUA_TTABLE: { 914 case LUA_TTABLE: { /* index the table */
743 push_onecapture(ms, 0, s, e); 915 push_onecapture(ms, 0, s, e); /* first capture is the index */
744 lua_gettable(L, 3); 916 lua_gettable(L, 3);
745 break; 917 break;
746 } 918 }
747 default: { /* LUA_TNUMBER or LUA_TSTRING */ 919 default: { /* LUA_TNUMBER or LUA_TSTRING */
748 add_s(ms, b, s, e); 920 add_s(ms, b, s, e); /* add value to the buffer */
749 return; 921 return 1; /* something changed */
750 } 922 }
751 } 923 }
752 if (!lua_toboolean(L, -1)) { /* nil or false? */ 924 if (!lua_toboolean(L, -1)) { /* nil or false? */
753 lua_pop(L, 1); 925 lua_pop(L, 1); /* remove value */
754 lua_pushlstring(L, s, e - s); /* keep original text */ 926 luaL_addlstring(b, s, e - s); /* keep original text */
927 return 0; /* no changes */
755 } 928 }
756 else if (!lua_isstring(L, -1)) 929 else if (!lua_isstring(L, -1))
757 luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); 930 return luaL_error(L, "invalid replacement value (a %s)",
758 luaL_addvalue(b); /* add result to accumulator */ 931 luaL_typename(L, -1));
932 else {
933 luaL_addvalue(b); /* add result to accumulator */
934 return 1; /* something changed */
935 }
759} 936}
760 937
761 938
@@ -768,11 +945,12 @@ static int str_gsub (lua_State *L) {
768 lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */ 945 lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */
769 int anchor = (*p == '^'); 946 int anchor = (*p == '^');
770 lua_Integer n = 0; /* replacement count */ 947 lua_Integer n = 0; /* replacement count */
948 int changed = 0; /* change flag */
771 MatchState ms; 949 MatchState ms;
772 luaL_Buffer b; 950 luaL_Buffer b;
773 luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || 951 luaL_argexpected(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
774 tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, 952 tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,
775 "string/function/table expected"); 953 "string/function/table");
776 luaL_buffinit(L, &b); 954 luaL_buffinit(L, &b);
777 if (anchor) { 955 if (anchor) {
778 p++; lp--; /* skip anchor character */ 956 p++; lp--; /* skip anchor character */
@@ -783,7 +961,7 @@ static int str_gsub (lua_State *L) {
783 reprepstate(&ms); /* (re)prepare state for new match */ 961 reprepstate(&ms); /* (re)prepare state for new match */
784 if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */ 962 if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */
785 n++; 963 n++;
786 add_value(&ms, &b, src, e, tr); /* add replacement to buffer */ 964 changed = add_value(&ms, &b, src, e, tr) | changed;
787 src = lastmatch = e; 965 src = lastmatch = e;
788 } 966 }
789 else if (src < ms.src_end) /* otherwise, skip one character */ 967 else if (src < ms.src_end) /* otherwise, skip one character */
@@ -791,8 +969,12 @@ static int str_gsub (lua_State *L) {
791 else break; /* end of subject */ 969 else break; /* end of subject */
792 if (anchor) break; 970 if (anchor) break;
793 } 971 }
794 luaL_addlstring(&b, src, ms.src_end-src); 972 if (!changed) /* no changes? */
795 luaL_pushresult(&b); 973 lua_pushvalue(L, 1); /* return original string */
974 else { /* something changed */
975 luaL_addlstring(&b, src, ms.src_end-src);
976 luaL_pushresult(&b); /* create and return new string */
977 }
796 lua_pushinteger(L, n); /* number of substitutions */ 978 lua_pushinteger(L, n); /* number of substitutions */
797 return 2; 979 return 2;
798} 980}
@@ -813,8 +995,6 @@ static int str_gsub (lua_State *L) {
813** Hexadecimal floating-point formatter 995** Hexadecimal floating-point formatter
814*/ 996*/
815 997
816#include <math.h>
817
818#define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char)) 998#define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char))
819 999
820 1000
@@ -824,7 +1004,7 @@ static int str_gsub (lua_State *L) {
824** to nibble boundaries by making what is left after that first digit a 1004** to nibble boundaries by making what is left after that first digit a
825** multiple of 4. 1005** multiple of 4.
826*/ 1006*/
827#define L_NBFD ((l_mathlim(MANT_DIG) - 1)%4 + 1) 1007#define L_NBFD ((l_floatatt(MANT_DIG) - 1)%4 + 1)
828 1008
829 1009
830/* 1010/*
@@ -851,7 +1031,7 @@ static int num2straux (char *buff, int sz, lua_Number x) {
851 lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */ 1031 lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */
852 int n = 0; /* character count */ 1032 int n = 0; /* character count */
853 if (m < 0) { /* is number negative? */ 1033 if (m < 0) { /* is number negative? */
854 buff[n++] = '-'; /* add signal */ 1034 buff[n++] = '-'; /* add sign */
855 m = -m; /* make it positive */ 1035 m = -m; /* make it positive */
856 } 1036 }
857 buff[n++] = '0'; buff[n++] = 'x'; /* add "0x" */ 1037 buff[n++] = '0'; buff[n++] = 'x'; /* add "0x" */
@@ -887,17 +1067,30 @@ static int lua_number2strx (lua_State *L, char *buff, int sz,
887 1067
888 1068
889/* 1069/*
890** Maximum size of each formatted item. This maximum size is produced 1070** Maximum size for items formatted with '%f'. This size is produced
891** by format('%.99f', -maxfloat), and is equal to 99 + 3 ('-', '.', 1071** by format('%.99f', -maxfloat), and is equal to 99 + 3 ('-', '.',
892** and '\0') + number of decimal digits to represent maxfloat (which 1072** and '\0') + number of decimal digits to represent maxfloat (which
893** is maximum exponent + 1). (99+3+1 then rounded to 120 for "extra 1073** is maximum exponent + 1). (99+3+1, adding some extra, 110)
894** expenses", such as locale-dependent stuff)
895*/ 1074*/
896#define MAX_ITEM (120 + l_mathlim(MAX_10_EXP)) 1075#define MAX_ITEMF (110 + l_floatatt(MAX_10_EXP))
1076
1077
1078/*
1079** All formats except '%f' do not need that large limit. The other
1080** float formats use exponents, so that they fit in the 99 limit for
1081** significant digits; 's' for large strings and 'q' add items directly
1082** to the buffer; all integer formats also fit in the 99 limit. The
1083** worst case are floats: they may need 99 significant digits, plus
1084** '0x', '-', '.', 'e+XXXX', and '\0'. Adding some extra, 120.
1085*/
1086#define MAX_ITEM 120
897 1087
898 1088
899/* valid flags in a format specification */ 1089/* valid flags in a format specification */
900#define FLAGS "-+ #0" 1090#if !defined(L_FMTFLAGS)
1091#define L_FMTFLAGS "-+ #0"
1092#endif
1093
901 1094
902/* 1095/*
903** maximum size of each format specification (such as "%-099.99d") 1096** maximum size of each format specification (such as "%-099.99d")
@@ -929,14 +1122,32 @@ static void addquoted (luaL_Buffer *b, const char *s, size_t len) {
929 1122
930 1123
931/* 1124/*
932** Ensures the 'buff' string uses a dot as the radix character. 1125** Serialize a floating-point number in such a way that it can be
1126** scanned back by Lua. Use hexadecimal format for "common" numbers
1127** (to preserve precision); inf, -inf, and NaN are handled separately.
1128** (NaN cannot be expressed as a numeral, so we write '(0/0)' for it.)
933*/ 1129*/
934static void checkdp (char *buff, int nb) { 1130static int quotefloat (lua_State *L, char *buff, lua_Number n) {
935 if (memchr(buff, '.', nb) == NULL) { /* no dot? */ 1131 const char *s; /* for the fixed representations */
936 char point = lua_getlocaledecpoint(); /* try locale point */ 1132 if (n == (lua_Number)HUGE_VAL) /* inf? */
937 char *ppoint = (char *)memchr(buff, point, nb); 1133 s = "1e9999";
938 if (ppoint) *ppoint = '.'; /* change it to a dot */ 1134 else if (n == -(lua_Number)HUGE_VAL) /* -inf? */
1135 s = "-1e9999";
1136 else if (n != n) /* NaN? */
1137 s = "(0/0)";
1138 else { /* format number as hexadecimal */
1139 int nb = lua_number2strx(L, buff, MAX_ITEM,
1140 "%" LUA_NUMBER_FRMLEN "a", n);
1141 /* ensures that 'buff' string uses a dot as the radix character */
1142 if (memchr(buff, '.', nb) == NULL) { /* no dot? */
1143 char point = lua_getlocaledecpoint(); /* try locale point */
1144 char *ppoint = (char *)memchr(buff, point, nb);
1145 if (ppoint) *ppoint = '.'; /* change it to a dot */
1146 }
1147 return nb;
939 } 1148 }
1149 /* for the fixed representations */
1150 return l_sprintf(buff, MAX_ITEM, "%s", s);
940} 1151}
941 1152
942 1153
@@ -951,15 +1162,12 @@ static void addliteral (lua_State *L, luaL_Buffer *b, int arg) {
951 case LUA_TNUMBER: { 1162 case LUA_TNUMBER: {
952 char *buff = luaL_prepbuffsize(b, MAX_ITEM); 1163 char *buff = luaL_prepbuffsize(b, MAX_ITEM);
953 int nb; 1164 int nb;
954 if (!lua_isinteger(L, arg)) { /* float? */ 1165 if (!lua_isinteger(L, arg)) /* float? */
955 lua_Number n = lua_tonumber(L, arg); /* write as hexa ('%a') */ 1166 nb = quotefloat(L, buff, lua_tonumber(L, arg));
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 */ 1167 else { /* integers */
960 lua_Integer n = lua_tointeger(L, arg); 1168 lua_Integer n = lua_tointeger(L, arg);
961 const char *format = (n == LUA_MININTEGER) /* corner case? */ 1169 const char *format = (n == LUA_MININTEGER) /* corner case? */
962 ? "0x%" LUA_INTEGER_FRMLEN "x" /* use hexa */ 1170 ? "0x%" LUA_INTEGER_FRMLEN "x" /* use hex */
963 : LUA_INTEGER_FMT; /* else use default format */ 1171 : LUA_INTEGER_FMT; /* else use default format */
964 nb = l_sprintf(buff, MAX_ITEM, format, (LUAI_UACINT)n); 1172 nb = l_sprintf(buff, MAX_ITEM, format, (LUAI_UACINT)n);
965 } 1173 }
@@ -980,8 +1188,8 @@ static void addliteral (lua_State *L, luaL_Buffer *b, int arg) {
980 1188
981static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { 1189static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
982 const char *p = strfrmt; 1190 const char *p = strfrmt;
983 while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ 1191 while (*p != '\0' && strchr(L_FMTFLAGS, *p) != NULL) p++; /* skip flags */
984 if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char)) 1192 if ((size_t)(p - strfrmt) >= sizeof(L_FMTFLAGS)/sizeof(char))
985 luaL_error(L, "invalid format (repeated flags)"); 1193 luaL_error(L, "invalid format (repeated flags)");
986 if (isdigit(uchar(*p))) p++; /* skip width */ 1194 if (isdigit(uchar(*p))) p++; /* skip width */
987 if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ 1195 if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
@@ -1028,36 +1236,51 @@ static int str_format (lua_State *L) {
1028 luaL_addchar(&b, *strfrmt++); /* %% */ 1236 luaL_addchar(&b, *strfrmt++); /* %% */
1029 else { /* format item */ 1237 else { /* format item */
1030 char form[MAX_FORMAT]; /* to store the format ('%...') */ 1238 char form[MAX_FORMAT]; /* to store the format ('%...') */
1031 char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ 1239 int maxitem = MAX_ITEM;
1240 char *buff = luaL_prepbuffsize(&b, maxitem); /* to put formatted item */
1032 int nb = 0; /* number of bytes in added item */ 1241 int nb = 0; /* number of bytes in added item */
1033 if (++arg > top) 1242 if (++arg > top)
1034 luaL_argerror(L, arg, "no value"); 1243 return luaL_argerror(L, arg, "no value");
1035 strfrmt = scanformat(L, strfrmt, form); 1244 strfrmt = scanformat(L, strfrmt, form);
1036 switch (*strfrmt++) { 1245 switch (*strfrmt++) {
1037 case 'c': { 1246 case 'c': {
1038 nb = l_sprintf(buff, MAX_ITEM, form, (int)luaL_checkinteger(L, arg)); 1247 nb = l_sprintf(buff, maxitem, form, (int)luaL_checkinteger(L, arg));
1039 break; 1248 break;
1040 } 1249 }
1041 case 'd': case 'i': 1250 case 'd': case 'i':
1042 case 'o': case 'u': case 'x': case 'X': { 1251 case 'o': case 'u': case 'x': case 'X': {
1043 lua_Integer n = luaL_checkinteger(L, arg); 1252 lua_Integer n = luaL_checkinteger(L, arg);
1044 addlenmod(form, LUA_INTEGER_FRMLEN); 1253 addlenmod(form, LUA_INTEGER_FRMLEN);
1045 nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACINT)n); 1254 nb = l_sprintf(buff, maxitem, form, (LUAI_UACINT)n);
1046 break; 1255 break;
1047 } 1256 }
1048 case 'a': case 'A': 1257 case 'a': case 'A':
1049 addlenmod(form, LUA_NUMBER_FRMLEN); 1258 addlenmod(form, LUA_NUMBER_FRMLEN);
1050 nb = lua_number2strx(L, buff, MAX_ITEM, form, 1259 nb = lua_number2strx(L, buff, maxitem, form,
1051 luaL_checknumber(L, arg)); 1260 luaL_checknumber(L, arg));
1052 break; 1261 break;
1053 case 'e': case 'E': case 'f': 1262 case 'f':
1054 case 'g': case 'G': { 1263 maxitem = MAX_ITEMF; /* extra space for '%f' */
1264 buff = luaL_prepbuffsize(&b, maxitem);
1265 /* FALLTHROUGH */
1266 case 'e': case 'E': case 'g': case 'G': {
1055 lua_Number n = luaL_checknumber(L, arg); 1267 lua_Number n = luaL_checknumber(L, arg);
1056 addlenmod(form, LUA_NUMBER_FRMLEN); 1268 addlenmod(form, LUA_NUMBER_FRMLEN);
1057 nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACNUMBER)n); 1269 nb = l_sprintf(buff, maxitem, form, (LUAI_UACNUMBER)n);
1270 break;
1271 }
1272 case 'p': {
1273 const void *p = lua_topointer(L, arg);
1274 if (p == NULL) { /* avoid calling 'printf' with argument NULL */
1275 p = "(null)"; /* result */
1276 form[strlen(form) - 1] = 's'; /* format it as a string */
1277 }
1278 nb = l_sprintf(buff, maxitem, form, p);
1058 break; 1279 break;
1059 } 1280 }
1060 case 'q': { 1281 case 'q': {
1282 if (form[2] != '\0') /* modifiers? */
1283 return luaL_error(L, "specifier '%%q' cannot have modifiers");
1061 addliteral(L, &b, arg); 1284 addliteral(L, &b, arg);
1062 break; 1285 break;
1063 } 1286 }
@@ -1073,18 +1296,17 @@ static int str_format (lua_State *L) {
1073 luaL_addvalue(&b); /* keep entire string */ 1296 luaL_addvalue(&b); /* keep entire string */
1074 } 1297 }
1075 else { /* format the string into 'buff' */ 1298 else { /* format the string into 'buff' */
1076 nb = l_sprintf(buff, MAX_ITEM, form, s); 1299 nb = l_sprintf(buff, maxitem, form, s);
1077 lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ 1300 lua_pop(L, 1); /* remove result from 'luaL_tolstring' */
1078 } 1301 }
1079 } 1302 }
1080 break; 1303 break;
1081 } 1304 }
1082 default: { /* also treat cases 'pnLlh' */ 1305 default: { /* also treat cases 'pnLlh' */
1083 return luaL_error(L, "invalid option '%%%c' to 'format'", 1306 return luaL_error(L, "invalid conversion '%s' to 'format'", form);
1084 *(strfrmt - 1));
1085 } 1307 }
1086 } 1308 }
1087 lua_assert(nb < MAX_ITEM); 1309 lua_assert(nb < maxitem);
1088 luaL_addsize(&b, nb); 1310 luaL_addsize(&b, nb);
1089 } 1311 }
1090 } 1312 }
@@ -1422,17 +1644,12 @@ static int str_packsize (lua_State *L) {
1422 while (*fmt != '\0') { 1644 while (*fmt != '\0') {
1423 int size, ntoalign; 1645 int size, ntoalign;
1424 KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); 1646 KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
1647 luaL_argcheck(L, opt != Kstring && opt != Kzstr, 1,
1648 "variable-length format");
1425 size += ntoalign; /* total space used by option */ 1649 size += ntoalign; /* total space used by option */
1426 luaL_argcheck(L, totalsize <= MAXSIZE - size, 1, 1650 luaL_argcheck(L, totalsize <= MAXSIZE - size, 1,
1427 "format result too large"); 1651 "format result too large");
1428 totalsize += size; 1652 totalsize += size;
1429 switch (opt) {
1430 case Kstring: /* strings with length count */
1431 case Kzstr: /* zero-terminated string */
1432 luaL_argerror(L, 1, "variable-length format");
1433 /* call never return, but to avoid warnings: *//* FALLTHROUGH */
1434 default: break;
1435 }
1436 } 1653 }
1437 lua_pushinteger(L, (lua_Integer)totalsize); 1654 lua_pushinteger(L, (lua_Integer)totalsize);
1438 return 1; 1655 return 1;
@@ -1478,15 +1695,15 @@ static int str_unpack (lua_State *L) {
1478 const char *fmt = luaL_checkstring(L, 1); 1695 const char *fmt = luaL_checkstring(L, 1);
1479 size_t ld; 1696 size_t ld;
1480 const char *data = luaL_checklstring(L, 2, &ld); 1697 const char *data = luaL_checklstring(L, 2, &ld);
1481 size_t pos = (size_t)posrelat(luaL_optinteger(L, 3, 1), ld) - 1; 1698 size_t pos = posrelatI(luaL_optinteger(L, 3, 1), ld) - 1;
1482 int n = 0; /* number of results */ 1699 int n = 0; /* number of results */
1483 luaL_argcheck(L, pos <= ld, 3, "initial position out of string"); 1700 luaL_argcheck(L, pos <= ld, 3, "initial position out of string");
1484 initheader(L, &h); 1701 initheader(L, &h);
1485 while (*fmt != '\0') { 1702 while (*fmt != '\0') {
1486 int size, ntoalign; 1703 int size, ntoalign;
1487 KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign); 1704 KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign);
1488 if ((size_t)ntoalign + size > ~pos || pos + ntoalign + size > ld) 1705 luaL_argcheck(L, (size_t)ntoalign + size <= ld - pos, 2,
1489 luaL_argerror(L, 2, "data string too short"); 1706 "data string too short");
1490 pos += ntoalign; /* skip alignment */ 1707 pos += ntoalign; /* skip alignment */
1491 /* stack space for item + next position */ 1708 /* stack space for item + next position */
1492 luaL_checkstack(L, 2, "too many results"); 1709 luaL_checkstack(L, 2, "too many results");
@@ -1515,13 +1732,15 @@ static int str_unpack (lua_State *L) {
1515 } 1732 }
1516 case Kstring: { 1733 case Kstring: {
1517 size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0); 1734 size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0);
1518 luaL_argcheck(L, pos + len + size <= ld, 2, "data string too short"); 1735 luaL_argcheck(L, len <= ld - pos - size, 2, "data string too short");
1519 lua_pushlstring(L, data + pos + size, len); 1736 lua_pushlstring(L, data + pos + size, len);
1520 pos += len; /* skip string */ 1737 pos += len; /* skip string */
1521 break; 1738 break;
1522 } 1739 }
1523 case Kzstr: { 1740 case Kzstr: {
1524 size_t len = (int)strlen(data + pos); 1741 size_t len = (int)strlen(data + pos);
1742 luaL_argcheck(L, pos + len < ld, 2,
1743 "unfinished string for format 'z'");
1525 lua_pushlstring(L, data + pos, len); 1744 lua_pushlstring(L, data + pos, len);
1526 pos += len + 1; /* skip string plus final '\0' */ 1745 pos += len + 1; /* skip string plus final '\0' */
1527 break; 1746 break;
@@ -1562,7 +1781,9 @@ static const luaL_Reg strlib[] = {
1562 1781
1563 1782
1564static void createmetatable (lua_State *L) { 1783static void createmetatable (lua_State *L) {
1565 lua_createtable(L, 0, 1); /* table to be metatable for strings */ 1784 /* table to be metatable for strings */
1785 luaL_newlibtable(L, stringmetamethods);
1786 luaL_setfuncs(L, stringmetamethods, 0);
1566 lua_pushliteral(L, ""); /* dummy string */ 1787 lua_pushliteral(L, ""); /* dummy string */
1567 lua_pushvalue(L, -2); /* copy table */ 1788 lua_pushvalue(L, -2); /* copy table */
1568 lua_setmetatable(L, -2); /* set table as metatable for strings */ 1789 lua_setmetatable(L, -2); /* set table as metatable for strings */