aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2009-05-27 14:11:27 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2009-05-27 14:11:27 -0300
commit57f8414de1968b6f9f212140f2da14cba3b6dacb (patch)
treef7ee1e6e09a272046f2897bd12d77fb1d1548136
parent139d562861a939ef0a8456c84874b783a7861a24 (diff)
downloadlua-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.c5
-rw-r--r--lobject.c5
-rw-r--r--lvm.c43
-rw-r--r--lvm.h4
4 files changed, 28 insertions, 29 deletions
diff --git a/lapi.c b/lapi.c
index 69307a3c..ec26006b 100644
--- a/lapi.c
+++ b/lapi.c
@@ -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));
diff --git a/lobject.c b/lobject.c
index bcd62086..f02b2ce0 100644
--- a/lobject.c
+++ b/lobject.c
@@ -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
diff --git a/lvm.c b/lvm.c
index a6207984..9842bcb9 100644
--- a/lvm.c
+++ b/lvm.c
@@ -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
267void luaV_concat (lua_State *L, int total, int last) { 267void 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 }
diff --git a/lvm.h b/lvm.h
index 2d68f406..0b45ca0d 100644
--- a/lvm.h
+++ b/lvm.h
@@ -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);
35LUAI_FUNC void luaV_finishOp (lua_State *L); 35LUAI_FUNC void luaV_finishOp (lua_State *L);
36LUAI_FUNC void luaV_execute (lua_State *L); 36LUAI_FUNC void luaV_execute (lua_State *L);
37LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); 37LUAI_FUNC void luaV_concat (lua_State *L, int total);
38 38
39#endif 39#endif