|
@@ -39,17 +39,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
-static TaggedString *strconc (lua_State *L, const TaggedString *l,
|
|
|
- const TaggedString *r) {
|
|
|
- long nl = l->u.s.len;
|
|
|
- long nr = r->u.s.len;
|
|
|
- char *buffer = luaL_openspace(L, nl+nr);
|
|
|
- memcpy(buffer, l->str, nl);
|
|
|
- memcpy(buffer+nl, r->str, nr);
|
|
|
- return luaS_newlstr(L, buffer, nl+nr);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
int luaV_tonumber (TObject *obj) { /* LUA_NUMBER */
|
|
|
if (ttype(obj) != LUA_T_STRING)
|
|
|
return 1;
|
|
@@ -253,22 +242,16 @@ static int luaV_strcomp (const TaggedString *ls, const TaggedString *rs) {
|
|
|
}
|
|
|
|
|
|
|
|
|
-int luaV_lessthan (lua_State *L, TObject *l, TObject *r) {
|
|
|
+int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r, StkId top) {
|
|
|
if (ttype(l) == LUA_T_NUMBER && ttype(r) == LUA_T_NUMBER)
|
|
|
return (nvalue(l) < nvalue(r));
|
|
|
else if (ttype(l) == LUA_T_STRING && ttype(r) == LUA_T_STRING)
|
|
|
return (luaV_strcomp(tsvalue(l), tsvalue(r)) < 0);
|
|
|
- else {
|
|
|
- /* update top and put arguments in correct order to call TM */
|
|
|
- if (l<r) /* are arguments in correct order? */
|
|
|
- L->top = r+1; /* yes; 2nd is on top */
|
|
|
- else { /* no; exchange them */
|
|
|
- TObject temp = *r;
|
|
|
- *r = *l;
|
|
|
- *l = temp;
|
|
|
- L->top = l+1; /* 1st is on top */
|
|
|
- }
|
|
|
- call_binTM(L, L->top, IM_LT, "unexpected type in comparison");
|
|
|
+ else { /* call TM */
|
|
|
+ luaD_checkstack(L, 2);
|
|
|
+ *top++ = *l;
|
|
|
+ *top++ = *r;
|
|
|
+ call_binTM(L, top, IM_LT, "unexpected type in comparison");
|
|
|
L->top--;
|
|
|
return (ttype(L->top) != LUA_T_NIL);
|
|
|
}
|
|
@@ -280,6 +263,34 @@ int luaV_lessthan (lua_State *L, TObject *l, TObject *r) {
|
|
|
else ttype(o) = LUA_T_NIL
|
|
|
|
|
|
|
|
|
+static void strconc (lua_State *L, int total, StkId top) {
|
|
|
+ do {
|
|
|
+ int n = 2; /* number of elements handled in this pass (at least 2) */
|
|
|
+ if (tostring(L, top-2) || tostring(L, top-1))
|
|
|
+ call_binTM(L, top, IM_CONCAT, "unexpected type for concatenation");
|
|
|
+ else { /* at least two string values; get as many as possible */
|
|
|
+ long tl = tsvalue(top-2)->u.s.len + tsvalue(top-1)->u.s.len;
|
|
|
+ char *buffer;
|
|
|
+ int i;
|
|
|
+ while (n < total && !tostring(L, top-n-1)) { /* collect total length */
|
|
|
+ tl += tsvalue(top-n-1)->u.s.len;
|
|
|
+ n++;
|
|
|
+ }
|
|
|
+ buffer = luaL_openspace(L, tl);
|
|
|
+ tl = 0;
|
|
|
+ for (i=n; i>0; i--) { /* concat all strings */
|
|
|
+ long l = tsvalue(top-i)->u.s.len;
|
|
|
+ memcpy(buffer+tl, tsvalue(top-i)->str, l);
|
|
|
+ tl += l;
|
|
|
+ }
|
|
|
+ tsvalue(top-n) = luaS_newlstr(L, buffer, tl);
|
|
|
+ }
|
|
|
+ total -= n-1; /* got `n' strings to create 1 new */
|
|
|
+ top -= n-1;
|
|
|
+ } while (total > 1); /* repeat until only 1 result left */
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
void luaV_pack (lua_State *L, StkId firstelem, int nvararg, TObject *tab) {
|
|
|
int i;
|
|
|
Hash *htab;
|
|
@@ -479,22 +490,22 @@ StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf,
|
|
|
|
|
|
case LTOP:
|
|
|
top--;
|
|
|
- setbool(top-1, luaV_lessthan(L, top-1, top));
|
|
|
+ setbool(top-1, luaV_lessthan(L, top-1, top, top+1));
|
|
|
break;
|
|
|
|
|
|
case LEOP: /* a <= b === !(b<a) */
|
|
|
top--;
|
|
|
- setbool(top-1, !luaV_lessthan(L, top, top-1));
|
|
|
+ setbool(top-1, !luaV_lessthan(L, top, top-1, top+1));
|
|
|
break;
|
|
|
|
|
|
case GTOP: /* a > b === (b<a) */
|
|
|
top--;
|
|
|
- setbool(top-1, luaV_lessthan(L, top, top-1));
|
|
|
+ setbool(top-1, luaV_lessthan(L, top, top-1, top+1));
|
|
|
break;
|
|
|
|
|
|
case GEOP: /* a >= b === !(a<b) */
|
|
|
top--;
|
|
|
- setbool(top-1, !luaV_lessthan(L, top-1, top));
|
|
|
+ setbool(top-1, !luaV_lessthan(L, top-1, top, top+1));
|
|
|
break;
|
|
|
|
|
|
case ADDOP:
|
|
@@ -544,15 +555,14 @@ StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf,
|
|
|
top--;
|
|
|
break;
|
|
|
|
|
|
- case CONCOP:
|
|
|
- if (tostring(L, top-2) || tostring(L, top-1))
|
|
|
- call_binTM(L, top, IM_CONCAT, "unexpected type for concatenation");
|
|
|
- else
|
|
|
- tsvalue(top-2) = strconc(L, tsvalue(top-2), tsvalue(top-1));
|
|
|
- top--;
|
|
|
+ case CONCOP: {
|
|
|
+ int n = GETARG_U(i);
|
|
|
+ strconc(L, n, top);
|
|
|
+ top -= n-1;
|
|
|
L->top = top;
|
|
|
luaC_checkGC(L);
|
|
|
break;
|
|
|
+ }
|
|
|
|
|
|
case MINUSOP:
|
|
|
if (tonumber(top-1)) {
|