aboutsummaryrefslogtreecommitdiff
path: root/lvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'lvm.c')
-rw-r--r--lvm.c148
1 files changed, 93 insertions, 55 deletions
diff --git a/lvm.c b/lvm.c
index 3854c90a..12e2b090 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.205 2014/05/01 18:18:06 roberto Exp roberto $ 2** $Id: lvm.c,v 2.206 2014/05/09 14:20:52 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*/
@@ -56,7 +56,8 @@ static int tofloat (const TValue *obj, lua_Number *n) {
56 56
57 57
58/* 58/*
59** Try to convert a value to a float 59** Try to convert a value to a float. Check 'isinteger' first, because
60** in general the float case is already handled by the macro 'tonumber'.
60*/ 61*/
61int luaV_tonumber_ (const TValue *obj, lua_Number *n) { 62int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
62 TValue v; 63 TValue v;
@@ -69,7 +70,7 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
69 *n = fltvalue(obj); 70 *n = fltvalue(obj);
70 return 1; 71 return 1;
71 } 72 }
72 else if (ttisstring(obj) && 73 else if (ttisstring(obj) && /* string convertible to number? */
73 luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) { 74 luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) {
74 obj = &v; 75 obj = &v;
75 goto again; /* convert result from 'luaO_str2num' to a float */ 76 goto again; /* convert result from 'luaO_str2num' to a float */
@@ -178,8 +179,12 @@ static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
178} 179}
179 180
180 181
182/*
183** Main function for table access (invoking metamethods if needed).
184** Compute 'val = t[key]'
185*/
181void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { 186void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
182 int loop; 187 int loop; /* counter to avoid infinite loops */
183 for (loop = 0; loop < MAXTAGLOOP; loop++) { 188 for (loop = 0; loop < MAXTAGLOOP; loop++) {
184 const TValue *tm; 189 const TValue *tm;
185 if (ttistable(t)) { /* `t' is a table? */ 190 if (ttistable(t)) { /* `t' is a table? */
@@ -187,32 +192,36 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
187 const TValue *res = luaH_get(h, key); /* do a primitive get */ 192 const TValue *res = luaH_get(h, key); /* do a primitive get */
188 if (!ttisnil(res) || /* result is not nil? */ 193 if (!ttisnil(res) || /* result is not nil? */
189 (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ 194 (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
190 setobj2s(L, val, res); 195 setobj2s(L, val, res); /* result is the raw get */
191 return; 196 return;
192 } 197 }
193 /* else will try the tag method */ 198 /* else will try metamethod */
194 } 199 }
195 else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) 200 else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
196 luaG_typeerror(L, t, "index"); 201 luaG_typeerror(L, t, "index"); /* no metamethod */
197 if (ttisfunction(tm)) { 202 if (ttisfunction(tm)) { /* metamethod is a function */
198 luaT_callTM(L, tm, t, key, val, 1); 203 luaT_callTM(L, tm, t, key, val, 1);
199 return; 204 return;
200 } 205 }
201 t = tm; /* else repeat with 'tm' */ 206 t = tm; /* else repeat access over 'tm' */
202 } 207 }
203 luaG_runerror(L, "gettable chain too long; possible loop"); 208 luaG_runerror(L, "gettable chain too long; possible loop");
204} 209}
205 210
206 211
212/*
213** Main function for table assignment (invoking metamethods if needed).
214** Compute 't[key] = val'
215*/
207void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { 216void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
208 int loop; 217 int loop; /* counter to avoid infinite loops */
209 for (loop = 0; loop < MAXTAGLOOP; loop++) { 218 for (loop = 0; loop < MAXTAGLOOP; loop++) {
210 const TValue *tm; 219 const TValue *tm;
211 if (ttistable(t)) { /* `t' is a table? */ 220 if (ttistable(t)) { /* `t' is a table? */
212 Table *h = hvalue(t); 221 Table *h = hvalue(t);
213 TValue *oldval = cast(TValue *, luaH_get(h, key)); 222 TValue *oldval = cast(TValue *, luaH_get(h, key));
214 /* if previous value is not nil, there must be a previous entry 223 /* if previous value is not nil, there must be a previous entry
215 in the table; moreover, a metamethod has no relevance */ 224 in the table; a metamethod has no relevance */
216 if (!ttisnil(oldval) || 225 if (!ttisnil(oldval) ||
217 /* previous value is nil; must check the metamethod */ 226 /* previous value is nil; must check the metamethod */
218 ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL && 227 ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL &&
@@ -232,32 +241,40 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
232 else /* not a table; check metamethod */ 241 else /* not a table; check metamethod */
233 if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) 242 if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
234 luaG_typeerror(L, t, "index"); 243 luaG_typeerror(L, t, "index");
235 /* there is a metamethod */ 244 /* try the metamethod */
236 if (ttisfunction(tm)) { 245 if (ttisfunction(tm)) {
237 luaT_callTM(L, tm, t, key, val, 0); 246 luaT_callTM(L, tm, t, key, val, 0);
238 return; 247 return;
239 } 248 }
240 t = tm; /* else repeat with 'tm' */ 249 t = tm; /* else repeat assginment over 'tm' */
241 } 250 }
242 luaG_runerror(L, "settable chain too long; possible loop"); 251 luaG_runerror(L, "settable chain too long; possible loop");
243} 252}
244 253
245 254
255/*
256** Compare two strings 'ls' x 'rs', returning an integer smaller-equal-
257** -larger than zero if 'ls' is smaller-equal-larger than 'rs'.
258** The code is a little tricky because it allows '\0' in the strings
259** and it uses 'strcoll' (to respect locales) for each segments
260** of the strings.
261*/
246static int l_strcmp (const TString *ls, const TString *rs) { 262static int l_strcmp (const TString *ls, const TString *rs) {
247 const char *l = getstr(ls); 263 const char *l = getstr(ls);
248 size_t ll = ls->tsv.len; 264 size_t ll = ls->tsv.len;
249 const char *r = getstr(rs); 265 const char *r = getstr(rs);
250 size_t lr = rs->tsv.len; 266 size_t lr = rs->tsv.len;
251 for (;;) { 267 for (;;) { /* for each segment */
252 int temp = strcoll(l, r); 268 int temp = strcoll(l, r);
253 if (temp != 0) return temp; 269 if (temp != 0) /* not equal? */
254 else { /* strings are equal up to a `\0' */ 270 return temp; /* done */
271 else { /* strings are equal up to a '\0' */
255 size_t len = strlen(l); /* index of first `\0' in both strings */ 272 size_t len = strlen(l); /* index of first `\0' in both strings */
256 if (len == lr) /* r is finished? */ 273 if (len == lr) /* 'rs' is finished? */
257 return (len == ll) ? 0 : 1; 274 return (len == ll) ? 0 : 1; /* check 'ls' */
258 else if (len == ll) /* l is finished? */ 275 else if (len == ll) /* 'ls' is finished? */
259 return -1; /* l is smaller than r (because r is not finished) */ 276 return -1; /* 'ls' is smaller than 'rs' ('rs' is not finished) */
260 /* both strings longer than `len'; go on comparing (after the `\0') */ 277 /* both strings longer than `len'; go on comparing after the '\0' */
261 len++; 278 len++;
262 l += len; ll -= len; r += len; lr -= len; 279 l += len; ll -= len; r += len; lr -= len;
263 } 280 }
@@ -265,29 +282,35 @@ static int l_strcmp (const TString *ls, const TString *rs) {
265} 282}
266 283
267 284
285/*
286** Main operation less than; return 'l < r'.
287*/
268int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { 288int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
269 int res; 289 int res;
270 lua_Number nl, nr; 290 lua_Number nl, nr;
271 if (ttisinteger(l) && ttisinteger(r)) 291 if (ttisinteger(l) && ttisinteger(r)) /* both operands are integers? */
272 return (ivalue(l) < ivalue(r)); 292 return (ivalue(l) < ivalue(r));
273 else if (tofloat(l, &nl) && tofloat(r, &nr)) 293 else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */
274 return luai_numlt(nl, nr); 294 return luai_numlt(nl, nr);
275 else if (ttisstring(l) && ttisstring(r)) 295 else if (ttisstring(l) && ttisstring(r)) /* both are strings? */
276 return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; 296 return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
277 else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) 297 else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) /* no metamethod? */
278 luaG_ordererror(L, l, r); 298 luaG_ordererror(L, l, r); /* error */
279 return res; 299 return res;
280} 300}
281 301
282 302
303/*
304** Main operation less than or equal to; return 'l <= r'.
305*/
283int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { 306int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
284 int res; 307 int res;
285 lua_Number nl, nr; 308 lua_Number nl, nr;
286 if (ttisinteger(l) && ttisinteger(r)) 309 if (ttisinteger(l) && ttisinteger(r)) /* both operands are integers? */
287 return (ivalue(l) <= ivalue(r)); 310 return (ivalue(l) <= ivalue(r));
288 else if (tofloat(l, &nl) && tofloat(r, &nr)) 311 else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */
289 return luai_numle(nl, nr); 312 return luai_numle(nl, nr);
290 else if (ttisstring(l) && ttisstring(r)) 313 else if (ttisstring(l) && ttisstring(r)) /* both are strings? */
291 return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; 314 return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
292 else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */ 315 else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */
293 return res; 316 return res;
@@ -298,15 +321,16 @@ int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
298 321
299 322
300/* 323/*
301** equality of Lua values. L == NULL means raw equality (no metamethods) 324** Main operation for equality of Lua values; return 't1 == t2'.
325** L == NULL means raw equality (no metamethods)
302*/ 326*/
303int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { 327int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
304 const TValue *tm; 328 const TValue *tm;
305 if (ttype(t1) != ttype(t2)) { 329 if (ttype(t1) != ttype(t2)) { /* not the same variant? */
306 if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER) 330 if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER)
307 return 0; /* only numbers can be equal with different variants */ 331 return 0; /* only numbers can be equal with different variants */
308 else { /* two numbers with different variants */ 332 else { /* two numbers with different variants */
309 lua_Number n1, n2; 333 lua_Number n1, n2; /* compare them as floats */
310 lua_assert(ttisnumber(t1) && ttisnumber(t2)); 334 lua_assert(ttisnumber(t1) && ttisnumber(t2));
311 cast_void(tofloat(t1, &n1)); cast_void(tofloat(t2, &n2)); 335 cast_void(tofloat(t1, &n1)); cast_void(tofloat(t2, &n2));
312 return luai_numeq(n1, n2); 336 return luai_numeq(n1, n2);
@@ -343,8 +367,13 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
343} 367}
344 368
345 369
370/* macro used by 'luaV_concat' to ensure that element at 'o' is a string */
346#define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o))) 371#define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o)))
347 372
373/*
374** Main operation for concatenation: concat 'total' values in the stack,
375** from 'L->top - total' up to 'L->top - 1'.
376*/
348void luaV_concat (lua_State *L, int total) { 377void luaV_concat (lua_State *L, int total) {
349 lua_assert(total >= 2); 378 lua_assert(total >= 2);
350 do { 379 do {
@@ -372,12 +401,12 @@ void luaV_concat (lua_State *L, int total) {
372 buffer = luaZ_openspace(L, &G(L)->buff, tl); 401 buffer = luaZ_openspace(L, &G(L)->buff, tl);
373 tl = 0; 402 tl = 0;
374 n = i; 403 n = i;
375 do { /* concat all strings */ 404 do { /* copy all strings to buffer */
376 size_t l = tsvalue(top-i)->len; 405 size_t l = tsvalue(top-i)->len;
377 memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); 406 memcpy(buffer+tl, svalue(top-i), l * sizeof(char));
378 tl += l; 407 tl += l;
379 } while (--i > 0); 408 } while (--i > 0);
380 setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); 409 setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); /* create result */
381 } 410 }
382 total -= n-1; /* got 'n' strings to create 1 new */ 411 total -= n-1; /* got 'n' strings to create 1 new */
383 L->top -= n-1; /* popped 'n' strings and pushed one */ 412 L->top -= n-1; /* popped 'n' strings and pushed one */
@@ -385,6 +414,9 @@ void luaV_concat (lua_State *L, int total) {
385} 414}
386 415
387 416
417/*
418** Main operation 'ra' = #rb'.
419*/
388void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { 420void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
389 const TValue *tm; 421 const TValue *tm;
390 switch (ttnov(rb)) { 422 switch (ttnov(rb)) {
@@ -410,15 +442,18 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
410} 442}
411 443
412 444
413lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y) { 445/*
414 if (l_castS2U(y) + 1u <= 1u) { /* special cases: -1 or 0 */ 446** Integer division; return 'm // n'.
415 if (y == 0) 447*/
448lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) {
449 if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */
450 if (n == 0)
416 luaG_runerror(L, "attempt to divide by zero"); 451 luaG_runerror(L, "attempt to divide by zero");
417 return intop(-, 0, x); /* y==-1; avoid overflow with 0x80000...//-1 */ 452 return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */
418 } 453 }
419 else { 454 else {
420 lua_Integer d = x / y; /* perform division */ 455 lua_Integer d = m / n; /* perform division */
421 if ((x ^ y) >= 0 || x % y == 0) /* same signal or no rest? */ 456 if ((m ^ n) >= 0 || m % n == 0) /* same signal or no rest? */
422 return d; 457 return d;
423 else 458 else
424 return d - 1; /* correct 'div' for negative case */ 459 return d - 1; /* correct 'div' for negative case */
@@ -426,33 +461,36 @@ lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y) {
426} 461}
427 462
428 463
429lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y) { 464/*
430 if (l_castS2U(y) + 1u <= 1u) { /* special cases: -1 or 0 */ 465** Integer modulus; return 'm % n'.
431 if (y == 0) 466*/
467lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) {
468 if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */
469 if (n == 0)
432 luaG_runerror(L, "attempt to perform 'n%%0'"); 470 luaG_runerror(L, "attempt to perform 'n%%0'");
433 return 0; /* y==-1; avoid overflow with 0x80000...%-1 */ 471 return 0; /* m % -1 == 0; avoid overflow with 0x80000...%-1 */
434 } 472 }
435 else { 473 else {
436 lua_Integer r = x % y; 474 lua_Integer r = m % n;
437 if (r == 0 || (x ^ y) >= 0) 475 if (r == 0 || (m ^ n) >= 0)
438 return r; 476 return r;
439 else 477 else
440 return r + y; /* correct 'mod' for negative case */ 478 return r + n; /* correct 'mod' for negative case */
441 } 479 }
442} 480}
443 481
444 482
445lua_Integer luaV_pow (lua_Integer x, lua_Integer y) { 483lua_Integer luaV_pow (lua_Integer m, lua_Integer n) {
446 lua_assert(y >= 0); 484 lua_assert(n >= 0);
447 if (y == 0) 485 if (n == 0)
448 return 1; /* x^0 == 1 */ 486 return 1; /* m^0 == 1 */
449 else { 487 else {
450 lua_Integer r = 1; 488 lua_Integer r = 1;
451 for (; y > 1; y >>= 1) { 489 for (; n > 1; n >>= 1) {
452 if (y & 1) r = intop(*, r, x); 490 if (n & 1) r = intop(*, r, m);
453 x = intop(*, x, x); 491 m = intop(*, m, m);
454 } 492 }
455 r = intop(*, r, x); 493 r = intop(*, r, m);
456 return r; 494 return r;
457 } 495 }
458} 496}