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 /lvm.c | |
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)
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 43 |
1 files changed, 22 insertions, 21 deletions
@@ -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 | } |