diff options
| -rw-r--r-- | lapi.c | 174 |
1 files changed, 81 insertions, 93 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lapi.c,v 1.236 2003/04/28 19:58:06 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 1.237 2003/05/05 18:39:57 roberto Exp roberto $ |
| 3 | ** Lua API | 3 | ** Lua API |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -40,15 +40,22 @@ const char lua_ident[] = | |||
| 40 | 40 | ||
| 41 | #define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) | 41 | #define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) |
| 42 | 42 | ||
| 43 | #define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} | 43 | #define api_checkvalidindex(L, i) api_check(L, (i) != &luaO_nilobject) |
| 44 | 44 | ||
| 45 | #define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} | ||
| 45 | 46 | ||
| 46 | 47 | ||
| 47 | 48 | ||
| 48 | static TObject *negindex (lua_State *L, int idx) { | 49 | static TObject *luaA_index (lua_State *L, int idx) { |
| 49 | if (idx > LUA_REGISTRYINDEX) { | 50 | if (idx > 0) { |
| 51 | TObject *o = L->base + (idx - 1); | ||
| 52 | api_check(L, idx <= L->stack_last - L->base); | ||
| 53 | if (o >= L->top) return cast(TObject *, &luaO_nilobject); | ||
| 54 | else return o; | ||
| 55 | } | ||
| 56 | else if (idx > LUA_REGISTRYINDEX) { | ||
| 50 | api_check(L, idx != 0 && -idx <= L->top - L->base); | 57 | api_check(L, idx != 0 && -idx <= L->top - L->base); |
| 51 | return L->top+idx; | 58 | return L->top + idx; |
| 52 | } | 59 | } |
| 53 | else switch (idx) { /* pseudo-indices */ | 60 | else switch (idx) { /* pseudo-indices */ |
| 54 | case LUA_REGISTRYINDEX: return registry(L); | 61 | case LUA_REGISTRYINDEX: return registry(L); |
| @@ -59,37 +66,12 @@ static TObject *negindex (lua_State *L, int idx) { | |||
| 59 | lua_assert(iscfunction(func)); | 66 | lua_assert(iscfunction(func)); |
| 60 | return (idx <= clvalue(func)->c.nupvalues) | 67 | return (idx <= clvalue(func)->c.nupvalues) |
| 61 | ? &clvalue(func)->c.upvalue[idx-1] | 68 | ? &clvalue(func)->c.upvalue[idx-1] |
| 62 | : NULL; | 69 | : cast(TObject *, &luaO_nilobject); |
| 63 | } | 70 | } |
| 64 | } | 71 | } |
| 65 | } | 72 | } |
| 66 | 73 | ||
| 67 | 74 | ||
| 68 | static TObject *luaA_index (lua_State *L, int idx) { | ||
| 69 | if (idx > 0) { | ||
| 70 | api_check(L, idx <= L->top - L->base); | ||
| 71 | return L->base + idx - 1; | ||
| 72 | } | ||
| 73 | else { | ||
| 74 | TObject *o = negindex(L, idx); | ||
| 75 | api_check(L, o != NULL); | ||
| 76 | return o; | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | |||
| 81 | static TObject *luaA_indexAcceptable (lua_State *L, int idx) { | ||
| 82 | if (idx > 0) { | ||
| 83 | TObject *o = L->base+(idx-1); | ||
| 84 | api_check(L, idx <= L->stack_last - L->base); | ||
| 85 | if (o >= L->top) return NULL; | ||
| 86 | else return o; | ||
| 87 | } | ||
| 88 | else | ||
| 89 | return negindex(L, idx); | ||
| 90 | } | ||
| 91 | |||
| 92 | |||
| 93 | void luaA_pushobject (lua_State *L, const TObject *o) { | 75 | void luaA_pushobject (lua_State *L, const TObject *o) { |
| 94 | setobj2s(L->top, o); | 76 | setobj2s(L->top, o); |
| 95 | incr_top(L); | 77 | incr_top(L); |
| @@ -179,6 +161,7 @@ LUA_API void lua_remove (lua_State *L, int idx) { | |||
| 179 | StkId p; | 161 | StkId p; |
| 180 | lua_lock(L); | 162 | lua_lock(L); |
| 181 | p = luaA_index(L, idx); | 163 | p = luaA_index(L, idx); |
| 164 | api_checkvalidindex(L, p); | ||
| 182 | while (++p < L->top) setobjs2s(p-1, p); | 165 | while (++p < L->top) setobjs2s(p-1, p); |
| 183 | L->top--; | 166 | L->top--; |
| 184 | lua_unlock(L); | 167 | lua_unlock(L); |
| @@ -190,6 +173,7 @@ LUA_API void lua_insert (lua_State *L, int idx) { | |||
| 190 | StkId q; | 173 | StkId q; |
| 191 | lua_lock(L); | 174 | lua_lock(L); |
| 192 | p = luaA_index(L, idx); | 175 | p = luaA_index(L, idx); |
| 176 | api_checkvalidindex(L, p); | ||
| 193 | for (q = L->top; q>p; q--) setobjs2s(q, q-1); | 177 | for (q = L->top; q>p; q--) setobjs2s(q, q-1); |
| 194 | setobjs2s(p, L->top); | 178 | setobjs2s(p, L->top); |
| 195 | lua_unlock(L); | 179 | lua_unlock(L); |
| @@ -197,9 +181,12 @@ LUA_API void lua_insert (lua_State *L, int idx) { | |||
| 197 | 181 | ||
| 198 | 182 | ||
| 199 | LUA_API void lua_replace (lua_State *L, int idx) { | 183 | LUA_API void lua_replace (lua_State *L, int idx) { |
| 184 | StkId o; | ||
| 200 | lua_lock(L); | 185 | lua_lock(L); |
| 201 | api_checknelems(L, 1); | 186 | api_checknelems(L, 1); |
| 202 | setobj(luaA_index(L, idx), L->top - 1); /* write barrier */ | 187 | o = luaA_index(L, idx); |
| 188 | api_checkvalidindex(L, o); | ||
| 189 | setobj(o, L->top - 1); /* write barrier */ | ||
| 203 | L->top--; | 190 | L->top--; |
| 204 | lua_unlock(L); | 191 | lua_unlock(L); |
| 205 | } | 192 | } |
| @@ -220,8 +207,8 @@ LUA_API void lua_pushvalue (lua_State *L, int idx) { | |||
| 220 | 207 | ||
| 221 | 208 | ||
| 222 | LUA_API int lua_type (lua_State *L, int idx) { | 209 | LUA_API int lua_type (lua_State *L, int idx) { |
| 223 | StkId o = luaA_indexAcceptable(L, idx); | 210 | StkId o = luaA_index(L, idx); |
| 224 | return (o == NULL) ? LUA_TNONE : ttype(o); | 211 | return (o == &luaO_nilobject) ? LUA_TNONE : ttype(o); |
| 225 | } | 212 | } |
| 226 | 213 | ||
| 227 | 214 | ||
| @@ -232,15 +219,15 @@ LUA_API const char *lua_typename (lua_State *L, int t) { | |||
| 232 | 219 | ||
| 233 | 220 | ||
| 234 | LUA_API int lua_iscfunction (lua_State *L, int idx) { | 221 | LUA_API int lua_iscfunction (lua_State *L, int idx) { |
| 235 | StkId o = luaA_indexAcceptable(L, idx); | 222 | StkId o = luaA_index(L, idx); |
| 236 | return (o == NULL) ? 0 : iscfunction(o); | 223 | return iscfunction(o); |
| 237 | } | 224 | } |
| 238 | 225 | ||
| 239 | 226 | ||
| 240 | LUA_API int lua_isnumber (lua_State *L, int idx) { | 227 | LUA_API int lua_isnumber (lua_State *L, int idx) { |
| 241 | TObject n; | 228 | TObject n; |
| 242 | const TObject *o = luaA_indexAcceptable(L, idx); | 229 | const TObject *o = luaA_index(L, idx); |
| 243 | return (o != NULL && tonumber(o, &n)); | 230 | return tonumber(o, &n); |
| 244 | } | 231 | } |
| 245 | 232 | ||
| 246 | 233 | ||
| @@ -251,16 +238,16 @@ LUA_API int lua_isstring (lua_State *L, int idx) { | |||
| 251 | 238 | ||
| 252 | 239 | ||
| 253 | LUA_API int lua_isuserdata (lua_State *L, int idx) { | 240 | LUA_API int lua_isuserdata (lua_State *L, int idx) { |
| 254 | const TObject *o = luaA_indexAcceptable(L, idx); | 241 | const TObject *o = luaA_index(L, idx); |
| 255 | return (o != NULL && (ttisuserdata(o) || ttislightuserdata(o))); | 242 | return (ttisuserdata(o) || ttislightuserdata(o)); |
| 256 | } | 243 | } |
| 257 | 244 | ||
| 258 | 245 | ||
| 259 | LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { | 246 | LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { |
| 260 | StkId o1 = luaA_indexAcceptable(L, index1); | 247 | StkId o1 = luaA_index(L, index1); |
| 261 | StkId o2 = luaA_indexAcceptable(L, index2); | 248 | StkId o2 = luaA_index(L, index2); |
| 262 | return (o1 == NULL || o2 == NULL) ? 0 /* index out of range */ | 249 | return (o1 == &luaO_nilobject || o2 == &luaO_nilobject) ? 0 |
| 263 | : luaO_rawequalObj(o1, o2); | 250 | : luaO_rawequalObj(o1, o2); |
| 264 | } | 251 | } |
| 265 | 252 | ||
| 266 | 253 | ||
| @@ -268,10 +255,10 @@ LUA_API int lua_equal (lua_State *L, int index1, int index2) { | |||
| 268 | StkId o1, o2; | 255 | StkId o1, o2; |
| 269 | int i; | 256 | int i; |
| 270 | lua_lock(L); /* may call tag method */ | 257 | lua_lock(L); /* may call tag method */ |
| 271 | o1 = luaA_indexAcceptable(L, index1); | 258 | o1 = luaA_index(L, index1); |
| 272 | o2 = luaA_indexAcceptable(L, index2); | 259 | o2 = luaA_index(L, index2); |
| 273 | i = (o1 == NULL || o2 == NULL) ? 0 /* index out of range */ | 260 | i = (o1 == &luaO_nilobject || o2 == &luaO_nilobject) ? 0 |
| 274 | : equalobj(L, o1, o2); | 261 | : equalobj(L, o1, o2); |
| 275 | lua_unlock(L); | 262 | lua_unlock(L); |
| 276 | return i; | 263 | return i; |
| 277 | } | 264 | } |
| @@ -281,10 +268,10 @@ LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { | |||
| 281 | StkId o1, o2; | 268 | StkId o1, o2; |
| 282 | int i; | 269 | int i; |
| 283 | lua_lock(L); /* may call tag method */ | 270 | lua_lock(L); /* may call tag method */ |
| 284 | o1 = luaA_indexAcceptable(L, index1); | 271 | o1 = luaA_index(L, index1); |
| 285 | o2 = luaA_indexAcceptable(L, index2); | 272 | o2 = luaA_index(L, index2); |
| 286 | i = (o1 == NULL || o2 == NULL) ? 0 /* index out-of-range */ | 273 | i = (o1 == &luaO_nilobject || o2 == &luaO_nilobject) ? 0 |
| 287 | : luaV_lessthan(L, o1, o2); | 274 | : luaV_lessthan(L, o1, o2); |
| 288 | lua_unlock(L); | 275 | lua_unlock(L); |
| 289 | return i; | 276 | return i; |
| 290 | } | 277 | } |
| @@ -293,8 +280,8 @@ LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { | |||
| 293 | 280 | ||
| 294 | LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { | 281 | LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { |
| 295 | TObject n; | 282 | TObject n; |
| 296 | const TObject *o = luaA_indexAcceptable(L, idx); | 283 | const TObject *o = luaA_index(L, idx); |
| 297 | if (o != NULL && tonumber(o, &n)) | 284 | if (tonumber(o, &n)) |
| 298 | return nvalue(o); | 285 | return nvalue(o); |
| 299 | else | 286 | else |
| 300 | return 0; | 287 | return 0; |
| @@ -302,16 +289,14 @@ LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { | |||
| 302 | 289 | ||
| 303 | 290 | ||
| 304 | LUA_API int lua_toboolean (lua_State *L, int idx) { | 291 | LUA_API int lua_toboolean (lua_State *L, int idx) { |
| 305 | const TObject *o = luaA_indexAcceptable(L, idx); | 292 | const TObject *o = luaA_index(L, idx); |
| 306 | return (o != NULL) && !l_isfalse(o); | 293 | return !l_isfalse(o); |
| 307 | } | 294 | } |
| 308 | 295 | ||
| 309 | 296 | ||
| 310 | LUA_API const char *lua_tostring (lua_State *L, int idx) { | 297 | LUA_API const char *lua_tostring (lua_State *L, int idx) { |
| 311 | StkId o = luaA_indexAcceptable(L, idx); | 298 | StkId o = luaA_index(L, idx); |
| 312 | if (o == NULL) | 299 | if (ttisstring(o)) |
| 313 | return NULL; | ||
| 314 | else if (ttisstring(o)) | ||
| 315 | return svalue(o); | 300 | return svalue(o); |
| 316 | else { | 301 | else { |
| 317 | const char *s; | 302 | const char *s; |
| @@ -325,10 +310,8 @@ LUA_API const char *lua_tostring (lua_State *L, int idx) { | |||
| 325 | 310 | ||
| 326 | 311 | ||
| 327 | LUA_API size_t lua_strlen (lua_State *L, int idx) { | 312 | LUA_API size_t lua_strlen (lua_State *L, int idx) { |
| 328 | StkId o = luaA_indexAcceptable(L, idx); | 313 | StkId o = luaA_index(L, idx); |
| 329 | if (o == NULL) | 314 | if (ttisstring(o)) |
| 330 | return 0; | ||
| 331 | else if (ttisstring(o)) | ||
| 332 | return tsvalue(o)->tsv.len; | 315 | return tsvalue(o)->tsv.len; |
| 333 | else { | 316 | else { |
| 334 | size_t l; | 317 | size_t l; |
| @@ -341,14 +324,13 @@ LUA_API size_t lua_strlen (lua_State *L, int idx) { | |||
| 341 | 324 | ||
| 342 | 325 | ||
| 343 | LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { | 326 | LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { |
| 344 | StkId o = luaA_indexAcceptable(L, idx); | 327 | StkId o = luaA_index(L, idx); |
| 345 | return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->c.f; | 328 | return (!iscfunction(o)) ? NULL : clvalue(o)->c.f; |
| 346 | } | 329 | } |
| 347 | 330 | ||
| 348 | 331 | ||
| 349 | LUA_API void *lua_touserdata (lua_State *L, int idx) { | 332 | LUA_API void *lua_touserdata (lua_State *L, int idx) { |
| 350 | StkId o = luaA_indexAcceptable(L, idx); | 333 | StkId o = luaA_index(L, idx); |
| 351 | if (o == NULL) return NULL; | ||
| 352 | switch (ttype(o)) { | 334 | switch (ttype(o)) { |
| 353 | case LUA_TUSERDATA: return (uvalue(o) + 1); | 335 | case LUA_TUSERDATA: return (uvalue(o) + 1); |
| 354 | case LUA_TLIGHTUSERDATA: return pvalue(o); | 336 | case LUA_TLIGHTUSERDATA: return pvalue(o); |
| @@ -358,24 +340,21 @@ LUA_API void *lua_touserdata (lua_State *L, int idx) { | |||
| 358 | 340 | ||
| 359 | 341 | ||
| 360 | LUA_API lua_State *lua_tothread (lua_State *L, int idx) { | 342 | LUA_API lua_State *lua_tothread (lua_State *L, int idx) { |
| 361 | StkId o = luaA_indexAcceptable(L, idx); | 343 | StkId o = luaA_index(L, idx); |
| 362 | return (o == NULL || !ttisthread(o)) ? NULL : thvalue(o); | 344 | return (!ttisthread(o)) ? NULL : thvalue(o); |
| 363 | } | 345 | } |
| 364 | 346 | ||
| 365 | 347 | ||
| 366 | LUA_API const void *lua_topointer (lua_State *L, int idx) { | 348 | LUA_API const void *lua_topointer (lua_State *L, int idx) { |
| 367 | StkId o = luaA_indexAcceptable(L, idx); | 349 | StkId o = luaA_index(L, idx); |
| 368 | if (o == NULL) return NULL; | 350 | switch (ttype(o)) { |
| 369 | else { | 351 | case LUA_TTABLE: return hvalue(o); |
| 370 | switch (ttype(o)) { | 352 | case LUA_TFUNCTION: return clvalue(o); |
| 371 | case LUA_TTABLE: return hvalue(o); | 353 | case LUA_TTHREAD: return thvalue(o); |
| 372 | case LUA_TFUNCTION: return clvalue(o); | 354 | case LUA_TUSERDATA: |
| 373 | case LUA_TTHREAD: return thvalue(o); | 355 | case LUA_TLIGHTUSERDATA: |
| 374 | case LUA_TUSERDATA: | 356 | return lua_touserdata(L, idx); |
| 375 | case LUA_TLIGHTUSERDATA: | 357 | default: return NULL; |
| 376 | return lua_touserdata(L, idx); | ||
| 377 | default: return NULL; | ||
| 378 | } | ||
| 379 | } | 358 | } |
| 380 | } | 359 | } |
| 381 | 360 | ||
| @@ -485,6 +464,7 @@ LUA_API void lua_gettable (lua_State *L, int idx) { | |||
| 485 | StkId t; | 464 | StkId t; |
| 486 | lua_lock(L); | 465 | lua_lock(L); |
| 487 | t = luaA_index(L, idx); | 466 | t = luaA_index(L, idx); |
| 467 | api_checkvalidindex(L, t); | ||
| 488 | luaV_gettable(L, t, L->top - 1, L->top - 1); | 468 | luaV_gettable(L, t, L->top - 1, L->top - 1); |
| 489 | lua_unlock(L); | 469 | lua_unlock(L); |
| 490 | } | 470 | } |
| @@ -525,16 +505,14 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { | |||
| 525 | Table *mt = NULL; | 505 | Table *mt = NULL; |
| 526 | int res; | 506 | int res; |
| 527 | lua_lock(L); | 507 | lua_lock(L); |
| 528 | obj = luaA_indexAcceptable(L, objindex); | 508 | obj = luaA_index(L, objindex); |
| 529 | if (obj != NULL) { | 509 | switch (ttype(obj)) { |
| 530 | switch (ttype(obj)) { | 510 | case LUA_TTABLE: |
| 531 | case LUA_TTABLE: | 511 | mt = hvalue(obj)->metatable; |
| 532 | mt = hvalue(obj)->metatable; | 512 | break; |
| 533 | break; | 513 | case LUA_TUSERDATA: |
| 534 | case LUA_TUSERDATA: | 514 | mt = uvalue(obj)->uv.metatable; |
| 535 | mt = uvalue(obj)->uv.metatable; | 515 | break; |
| 536 | break; | ||
| 537 | } | ||
| 538 | } | 516 | } |
| 539 | if (mt == NULL || mt == hvalue(defaultmeta(L))) | 517 | if (mt == NULL || mt == hvalue(defaultmeta(L))) |
| 540 | res = 0; | 518 | res = 0; |
| @@ -552,6 +530,7 @@ LUA_API void lua_getfenv (lua_State *L, int idx) { | |||
| 552 | StkId o; | 530 | StkId o; |
| 553 | lua_lock(L); | 531 | lua_lock(L); |
| 554 | o = luaA_index(L, idx); | 532 | o = luaA_index(L, idx); |
| 533 | api_checkvalidindex(L, o); | ||
| 555 | setobj2s(L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L)); | 534 | setobj2s(L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L)); |
| 556 | api_incr_top(L); | 535 | api_incr_top(L); |
| 557 | lua_unlock(L); | 536 | lua_unlock(L); |
| @@ -568,6 +547,7 @@ LUA_API void lua_settable (lua_State *L, int idx) { | |||
| 568 | lua_lock(L); | 547 | lua_lock(L); |
| 569 | api_checknelems(L, 2); | 548 | api_checknelems(L, 2); |
| 570 | t = luaA_index(L, idx); | 549 | t = luaA_index(L, idx); |
| 550 | api_checkvalidindex(L, t); | ||
| 571 | luaV_settable(L, t, L->top - 2, L->top - 1); | 551 | luaV_settable(L, t, L->top - 2, L->top - 1); |
| 572 | L->top -= 2; /* pop index and value */ | 552 | L->top -= 2; /* pop index and value */ |
| 573 | lua_unlock(L); | 553 | lua_unlock(L); |
| @@ -604,6 +584,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { | |||
| 604 | lua_lock(L); | 584 | lua_lock(L); |
| 605 | api_checknelems(L, 1); | 585 | api_checknelems(L, 1); |
| 606 | obj = luaA_index(L, objindex); | 586 | obj = luaA_index(L, objindex); |
| 587 | api_checkvalidindex(L, obj); | ||
| 607 | mt = (!ttisnil(L->top - 1)) ? L->top - 1 : defaultmeta(L); | 588 | mt = (!ttisnil(L->top - 1)) ? L->top - 1 : defaultmeta(L); |
| 608 | api_check(L, ttistable(mt)); | 589 | api_check(L, ttistable(mt)); |
| 609 | switch (ttype(obj)) { | 590 | switch (ttype(obj)) { |
| @@ -632,6 +613,7 @@ LUA_API int lua_setfenv (lua_State *L, int idx) { | |||
| 632 | lua_lock(L); | 613 | lua_lock(L); |
| 633 | api_checknelems(L, 1); | 614 | api_checknelems(L, 1); |
| 634 | o = luaA_index(L, idx); | 615 | o = luaA_index(L, idx); |
| 616 | api_checkvalidindex(L, o); | ||
| 635 | L->top--; | 617 | L->top--; |
| 636 | api_check(L, ttistable(L->top)); | 618 | api_check(L, ttistable(L->top)); |
| 637 | if (isLfunction(o)) { | 619 | if (isLfunction(o)) { |
| @@ -679,7 +661,13 @@ LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { | |||
| 679 | int status; | 661 | int status; |
| 680 | ptrdiff_t func; | 662 | ptrdiff_t func; |
| 681 | lua_lock(L); | 663 | lua_lock(L); |
| 682 | func = (errfunc == 0) ? 0 : savestack(L, luaA_index(L, errfunc)); | 664 | if (errfunc == 0) |
| 665 | func = 0; | ||
| 666 | else { | ||
| 667 | StkId o = luaA_index(L, errfunc); | ||
| 668 | api_checkvalidindex(L, o); | ||
| 669 | func = savestack(L, o); | ||
| 670 | } | ||
| 683 | c.func = L->top - (nargs+1); /* function to be called */ | 671 | c.func = L->top - (nargs+1); /* function to be called */ |
| 684 | c.nresults = nresults; | 672 | c.nresults = nresults; |
| 685 | status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); | 673 | status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); |
