diff options
Diffstat (limited to 'lvm.c')
| -rw-r--r-- | lvm.c | 68 |
1 files changed, 28 insertions, 40 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 1.227 2002/04/24 20:07:46 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.228 2002/05/02 13:06:20 roberto Exp roberto $ |
| 3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -189,20 +189,21 @@ static void call_arith (lua_State *L, StkId p1, const TObject *p2, | |||
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | 191 | ||
| 192 | static int luaV_strlessthan (const TString *ls, const TString *rs) { | 192 | static int luaV_strcmp (const TString *ls, const TString *rs) { |
| 193 | const char *l = getstr(ls); | 193 | const char *l = getstr(ls); |
| 194 | size_t ll = ls->tsv.len; | 194 | size_t ll = ls->tsv.len; |
| 195 | const char *r = getstr(rs); | 195 | const char *r = getstr(rs); |
| 196 | size_t lr = rs->tsv.len; | 196 | size_t lr = rs->tsv.len; |
| 197 | for (;;) { | 197 | for (;;) { |
| 198 | int temp = strcoll(l, r); | 198 | int temp = strcoll(l, r); |
| 199 | if (temp != 0) return (temp < 0); | 199 | if (temp < 0) return CMP_LT; |
| 200 | else if (temp > 0) return CMP_GT; | ||
| 200 | else { /* strings are equal up to a `\0' */ | 201 | else { /* strings are equal up to a `\0' */ |
| 201 | size_t len = strlen(l); /* index of first `\0' in both strings */ | 202 | size_t len = strlen(l); /* index of first `\0' in both strings */ |
| 202 | if (len == lr) /* r is finished? */ | 203 | if (len == lr) /* r is finished? */ |
| 203 | return 0; /* l is equal or greater than r */ | 204 | return (len == ll) ? CMP_EQ : CMP_GT; /* l is eq. or gt. than r */ |
| 204 | else if (len == ll) /* l is finished? */ | 205 | else if (len == ll) /* l is finished? */ |
| 205 | return 1; /* l is smaller than r (because r is not finished) */ | 206 | return CMP_LT; /* l is smaller than r (because r is not finished) */ |
| 206 | /* both strings longer than `len'; go on comparing (after the `\0') */ | 207 | /* both strings longer than `len'; go on comparing (after the `\0') */ |
| 207 | len++; | 208 | len++; |
| 208 | l += len; ll -= len; r += len; lr -= len; | 209 | l += len; ll -= len; r += len; lr -= len; |
| @@ -211,15 +212,24 @@ static int luaV_strlessthan (const TString *ls, const TString *rs) { | |||
| 211 | } | 212 | } |
| 212 | 213 | ||
| 213 | 214 | ||
| 214 | int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) { | 215 | int luaV_cmp (lua_State *L, const TObject *l, const TObject *r, int cond) { |
| 215 | if (ttype(l) == LUA_TNUMBER && ttype(r) == LUA_TNUMBER) | 216 | if (ttype(l) == LUA_TNUMBER && ttype(r) == LUA_TNUMBER) { |
| 216 | return (nvalue(l) < nvalue(r)); | 217 | lua_Number n1 = nvalue(l); |
| 218 | lua_Number n2 = nvalue(r); | ||
| 219 | if (n1 < n2) return (cond & CMP_LT); | ||
| 220 | else if (n1 > n2) return (cond & CMP_GT); | ||
| 221 | else if (n1 == n2) return (cond & CMP_EQ); | ||
| 222 | else return (cond & CMP_N); | ||
| 223 | } | ||
| 217 | else if (ttype(l) == LUA_TSTRING && ttype(r) == LUA_TSTRING) | 224 | else if (ttype(l) == LUA_TSTRING && ttype(r) == LUA_TSTRING) |
| 218 | return luaV_strlessthan(tsvalue(l), tsvalue(r)); | 225 | return luaV_strcmp(tsvalue(l), tsvalue(r)) & cond; |
| 219 | else { /* try TM */ | 226 | else { /* try TM */ |
| 227 | if (cond & CMP_EQ ? cond & CMP_LT : cond & CMP_GT) { /* `<=' or `>' ? */ | ||
| 228 | const TObject *temp = l; l = r; r = temp; /* exchange terms */ | ||
| 229 | } | ||
| 220 | if (!call_binTM(L, l, r, L->top, TM_LT)) | 230 | if (!call_binTM(L, l, r, L->top, TM_LT)) |
| 221 | luaG_ordererror(L, l, r); | 231 | luaG_ordererror(L, l, r); |
| 222 | return !l_isfalse(L->top); | 232 | return (cond & CMP_EQ) ? l_isfalse(L->top) : !l_isfalse(L->top); |
| 223 | } | 233 | } |
| 224 | } | 234 | } |
| 225 | 235 | ||
| @@ -437,40 +447,18 @@ StkId luaV_execute (lua_State *L) { | |||
| 437 | dojump(pc, GETARG_sBx(i)); | 447 | dojump(pc, GETARG_sBx(i)); |
| 438 | break; | 448 | break; |
| 439 | } | 449 | } |
| 440 | case OP_TESTEQ: { /* skip next instruction if test fails */ | 450 | case OP_EQ: { /* skip next instruction if test fails */ |
| 441 | if (!luaO_equalObj(ra, RKC(i))) pc++; | 451 | if (luaO_equalObj(ra, RKC(i)) != GETARG_B(i)) pc++; |
| 442 | break; | ||
| 443 | } | ||
| 444 | case OP_TESTNE: { | ||
| 445 | if (luaO_equalObj(ra, RKC(i))) pc++; | ||
| 446 | break; | ||
| 447 | } | ||
| 448 | case OP_TESTLT: { | ||
| 449 | if (!luaV_lessthan(L, ra, RKC(i))) pc++; | ||
| 450 | break; | ||
| 451 | } | ||
| 452 | case OP_TESTLE: { /* b <= c === !(c<b) */ | ||
| 453 | if (luaV_lessthan(L, RKC(i), ra)) pc++; | ||
| 454 | break; | ||
| 455 | } | ||
| 456 | case OP_TESTGT: { /* b > c === (c<b) */ | ||
| 457 | if (!luaV_lessthan(L, RKC(i), ra)) pc++; | ||
| 458 | break; | 452 | break; |
| 459 | } | 453 | } |
| 460 | case OP_TESTGE: { /* b >= c === !(b<c) */ | 454 | case OP_CMP: { |
| 461 | if (luaV_lessthan(L, ra, RKC(i))) pc++; | 455 | if (!(luaV_cmp(L, ra, RKC(i), GETARG_B(i)))) pc++; |
| 462 | break; | 456 | break; |
| 463 | } | 457 | } |
| 464 | case OP_TESTT: { | 458 | case OP_TEST: { |
| 465 | StkId rb = RB(i); | 459 | StkId rc = RKC(i); |
| 466 | if (l_isfalse(rb)) pc++; | 460 | if (l_isfalse(rc) == GETARG_B(i)) pc++; |
| 467 | else setobj(ra, rb); | 461 | else setobj(ra, rc); |
| 468 | break; | ||
| 469 | } | ||
| 470 | case OP_TESTF: { | ||
| 471 | StkId rb = RB(i); | ||
| 472 | if (!l_isfalse(rb)) pc++; | ||
| 473 | else setobj(ra, rb); | ||
| 474 | break; | 462 | break; |
| 475 | } | 463 | } |
| 476 | case OP_CALL: { | 464 | case OP_CALL: { |
