diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-05-27 14:11:27 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-05-27 14:11:27 -0300 |
commit | 57f8414de1968b6f9f212140f2da14cba3b6dacb (patch) | |
tree | f7ee1e6e09a272046f2897bd12d77fb1d1548136 | |
parent | 139d562861a939ef0a8456c84874b783a7861a24 (diff) | |
download | lua-57f8414de1968b6f9f212140f2da14cba3b6dacb.tar.gz lua-57f8414de1968b6f9f212140f2da14cba3b6dacb.tar.bz2 lua-57f8414de1968b6f9f212140f2da14cba3b6dacb.zip |
small bug in 'luaV_concat' (L->top was left incorrect in some cases)
-rw-r--r-- | lapi.c | 5 | ||||
-rw-r--r-- | lobject.c | 5 | ||||
-rw-r--r-- | lvm.c | 43 | ||||
-rw-r--r-- | lvm.h | 4 |
4 files changed, 28 insertions, 29 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.c,v 2.75 2009/04/17 14:28:06 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.76 2009/04/17 22:00:01 roberto Exp $ |
3 | ** Lua API | 3 | ** Lua API |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -1017,8 +1017,7 @@ LUA_API void lua_concat (lua_State *L, int n) { | |||
1017 | api_checknelems(L, n); | 1017 | api_checknelems(L, n); |
1018 | if (n >= 2) { | 1018 | if (n >= 2) { |
1019 | luaC_checkGC(L); | 1019 | luaC_checkGC(L); |
1020 | luaV_concat(L, n, cast_int(L->top - L->base) - 1); | 1020 | luaV_concat(L, n); |
1021 | L->top -= (n-1); | ||
1022 | } | 1021 | } |
1023 | else if (n == 0) { /* push empty string */ | 1022 | else if (n == 0) { /* push empty string */ |
1024 | setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); | 1023 | setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lobject.c,v 2.28 2008/01/30 18:05:23 roberto Exp roberto $ | 2 | ** $Id: lobject.c,v 2.29 2009/02/19 17:18:25 roberto Exp $ |
3 | ** Some generic functions over Lua objects | 3 | ** Some generic functions over Lua objects |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -162,8 +162,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { | |||
162 | fmt = e+2; | 162 | fmt = e+2; |
163 | } | 163 | } |
164 | pushstr(L, fmt); | 164 | pushstr(L, fmt); |
165 | luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); | 165 | luaV_concat(L, n+1); |
166 | L->top -= n; | ||
167 | return svalue(L->top - 1); | 166 | return svalue(L->top - 1); |
168 | } | 167 | } |
169 | 168 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.87 2009/04/30 17:42:21 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.88 2009/05/22 15:19:54 roberto Exp $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -264,24 +264,22 @@ int luaV_equalval_ (lua_State *L, const TValue *t1, const TValue *t2) { | |||
264 | } | 264 | } |
265 | 265 | ||
266 | 266 | ||
267 | void luaV_concat (lua_State *L, int total, int last) { | 267 | void luaV_concat (lua_State *L, int total) { |
268 | lua_assert(total >= 2); | ||
268 | do { | 269 | do { |
269 | StkId top = L->base + last + 1; | 270 | StkId top = L->top; |
270 | int n = 2; /* number of elements handled in this pass (at least 2) */ | 271 | int n = 2; /* number of elements handled in this pass (at least 2) */ |
271 | if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { | 272 | if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { |
272 | L->top = top; /* set top to current position (in case of yield) */ | ||
273 | if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) | 273 | if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) |
274 | luaG_concaterror(L, top-2, top-1); | 274 | luaG_concaterror(L, top-2, top-1); |
275 | L->top = L->ci->top; /* restore top */ | ||
276 | } | ||
277 | else if (tsvalue(top-1)->len == 0) { /* second operand is empty? */ | ||
278 | (void)tostring(L, top - 2); /* result is first operand */ ; | ||
279 | } | 275 | } |
276 | else if (tsvalue(top-1)->len == 0) /* second operand is empty? */ | ||
277 | (void)tostring(L, top - 2); /* result is first operand */ | ||
280 | else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) { | 278 | else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) { |
281 | setsvalue2s(L, top-2, rawtsvalue(top-1)); /* result is second op. */ | 279 | setsvalue2s(L, top-2, rawtsvalue(top-1)); /* result is second op. */ |
282 | } | 280 | } |
283 | else { | 281 | else { |
284 | /* at least two (non-empty) string values; get as many as possible */ | 282 | /* at least two non-empty string values; get as many as possible */ |
285 | size_t tl = tsvalue(top-1)->len; | 283 | size_t tl = tsvalue(top-1)->len; |
286 | char *buffer; | 284 | char *buffer; |
287 | int i; | 285 | int i; |
@@ -300,8 +298,8 @@ void luaV_concat (lua_State *L, int total, int last) { | |||
300 | } | 298 | } |
301 | setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); | 299 | setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); |
302 | } | 300 | } |
303 | total -= n-1; /* got `n' strings to create 1 new */ | 301 | total -= n-1; /* got 'n' strings to create 1 new */ |
304 | last -= n-1; | 302 | L->top -= n-1; /* poped 'n' strings and pushed one */ |
305 | } while (total > 1); /* repeat until only 1 result left */ | 303 | } while (total > 1); /* repeat until only 1 result left */ |
306 | } | 304 | } |
307 | 305 | ||
@@ -381,16 +379,17 @@ void luaV_finishOp (lua_State *L) { | |||
381 | break; | 379 | break; |
382 | } | 380 | } |
383 | case OP_CONCAT: { | 381 | case OP_CONCAT: { |
384 | StkId top = L->top - 1; /* top when __concat was called */ | 382 | StkId top = L->top - 1; /* top when 'call_binTM' was called */ |
385 | int last = cast_int(top - ci->base) - 2; /* last element and ... */ | 383 | int b = GETARG_B(inst); /* first element to concatenate */ |
386 | int b = GETARG_B(inst); /* ... first element to concatenate */ | 384 | int total = top - 1 - (ci->base + b); /* elements yet to concatenate */ |
387 | int total = last - b + 1; /* number of elements to concatenate */ | ||
388 | setobj2s(L, top - 2, top); /* put TM result in proper position */ | 385 | setobj2s(L, top - 2, top); /* put TM result in proper position */ |
389 | L->top = ci->top; /* correct top */ | 386 | if (total > 1) { /* are there elements to concat? */ |
390 | if (total > 1) /* are there elements to concat? */ | 387 | L->top = top - 1; /* top is one after last element (at top-2) */ |
391 | luaV_concat(L, total, last); /* concat them (may yield again) */ | 388 | luaV_concat(L, total); /* concat them (may yield again) */ |
389 | } | ||
392 | /* move final result to final position */ | 390 | /* move final result to final position */ |
393 | setobj2s(L, ci->base + GETARG_A(inst), ci->base + b); | 391 | setobj2s(L, ci->base + GETARG_A(inst), L->top - 1); |
392 | L->top = ci->top; /* restore top */ | ||
394 | break; | 393 | break; |
395 | } | 394 | } |
396 | case OP_TFORCALL: { | 395 | case OP_TFORCALL: { |
@@ -586,7 +585,9 @@ void luaV_execute (lua_State *L) { | |||
586 | case OP_CONCAT: { | 585 | case OP_CONCAT: { |
587 | int b = GETARG_B(i); | 586 | int b = GETARG_B(i); |
588 | int c = GETARG_C(i); | 587 | int c = GETARG_C(i); |
589 | Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); | 588 | L->top = base + c + 1; /* mark the end of concat operands */ |
589 | Protect(luaV_concat(L, c-b+1); luaC_checkGC(L)); | ||
590 | L->top = ci->top; /* restore top */ | ||
590 | setobjs2s(L, RA(i), base+b); | 591 | setobjs2s(L, RA(i), base+b); |
591 | continue; | 592 | continue; |
592 | } | 593 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.h,v 2.7 2008/08/26 13:27:42 roberto Exp roberto $ | 2 | ** $Id: lvm.h,v 2.8 2009/03/10 17:14:37 roberto Exp $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -34,6 +34,6 @@ LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, | |||
34 | StkId val); | 34 | StkId val); |
35 | LUAI_FUNC void luaV_finishOp (lua_State *L); | 35 | LUAI_FUNC void luaV_finishOp (lua_State *L); |
36 | LUAI_FUNC void luaV_execute (lua_State *L); | 36 | LUAI_FUNC void luaV_execute (lua_State *L); |
37 | LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); | 37 | LUAI_FUNC void luaV_concat (lua_State *L, int total); |
38 | 38 | ||
39 | #endif | 39 | #endif |