diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-06-25 16:19:33 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-06-25 16:19:33 -0300 |
| commit | 25dc9b7fafe608c428a0950986ea8a1cb4dd7fa9 (patch) | |
| tree | 6ef74ba74e88237b0ed2619b5c9a797b8758e7c7 | |
| parent | 78c507b7b83a85c106b619ce2050725a80627a25 (diff) | |
| download | lua-25dc9b7fafe608c428a0950986ea8a1cb4dd7fa9.tar.gz lua-25dc9b7fafe608c428a0950986ea8a1cb4dd7fa9.tar.bz2 lua-25dc9b7fafe608c428a0950986ea8a1cb4dd7fa9.zip | |
new functions `dofile' and `pairs'; correct way to check proxies
| -rw-r--r-- | lbaselib.c | 72 |
1 files changed, 50 insertions, 22 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lbaselib.c,v 1.83 2002/06/20 20:41:46 roberto Exp roberto $ | 2 | ** $Id: lbaselib.c,v 1.84 2002/06/24 17:23:16 roberto Exp roberto $ |
| 3 | ** Basic library | 3 | ** Basic library |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -34,7 +34,7 @@ static int luaB_print (lua_State *L) { | |||
| 34 | const char *s; | 34 | const char *s; |
| 35 | lua_pushvalue(L, -1); /* function to be called */ | 35 | lua_pushvalue(L, -1); /* function to be called */ |
| 36 | lua_pushvalue(L, i); /* value to print */ | 36 | lua_pushvalue(L, i); /* value to print */ |
| 37 | lua_upcall(L, 1, 1); | 37 | lua_call(L, 1, 1); |
| 38 | s = lua_tostring(L, -1); /* get result */ | 38 | s = lua_tostring(L, -1); /* get result */ |
| 39 | if (s == NULL) | 39 | if (s == NULL) |
| 40 | return luaL_error(L, "`tostring' must return a string to `print'"); | 40 | return luaL_error(L, "`tostring' must return a string to `print'"); |
| @@ -83,8 +83,10 @@ static int luaB_error (lua_State *L) { | |||
| 83 | 83 | ||
| 84 | static int luaB_getmetatable (lua_State *L) { | 84 | static int luaB_getmetatable (lua_State *L) { |
| 85 | luaL_check_any(L, 1); | 85 | luaL_check_any(L, 1); |
| 86 | if (!lua_getmetatable(L, 1)) | 86 | if (!lua_getmetatable(L, 1)) { |
| 87 | return 0; /* no metatable */ | 87 | lua_pushnil(L); |
| 88 | return 1; /* no metatable */ | ||
| 89 | } | ||
| 88 | else { | 90 | else { |
| 89 | lua_pushliteral(L, "__metatable"); | 91 | lua_pushliteral(L, "__metatable"); |
| 90 | lua_rawget(L, -2); | 92 | lua_rawget(L, -2); |
| @@ -182,11 +184,20 @@ static int luaB_next (lua_State *L) { | |||
| 182 | } | 184 | } |
| 183 | 185 | ||
| 184 | 186 | ||
| 185 | static int luaB_nexti (lua_State *L) { | 187 | static int luaB_pairs (lua_State *L) { |
| 188 | luaL_check_type(L, 1, LUA_TTABLE); | ||
| 189 | lua_getglobal(L, "next"); /* return generator, */ | ||
| 190 | lua_pushvalue(L, 1); /* state, */ | ||
| 191 | lua_pushnil(L); /* and initial value */ | ||
| 192 | return 3; | ||
| 193 | } | ||
| 194 | |||
| 195 | |||
| 196 | static int luaB_ipairs (lua_State *L) { | ||
| 186 | lua_Number i = lua_tonumber(L, 2); | 197 | lua_Number i = lua_tonumber(L, 2); |
| 187 | luaL_check_type(L, 1, LUA_TTABLE); | 198 | luaL_check_type(L, 1, LUA_TTABLE); |
| 188 | if (i == 0 && lua_isnull(L, 2)) { /* `for' start? */ | 199 | if (i == 0 && lua_isnull(L, 2)) { /* `for' start? */ |
| 189 | lua_getglobal(L, "nexti"); /* return generator, */ | 200 | lua_getglobal(L, "ipairs"); /* return generator, */ |
| 190 | lua_pushvalue(L, 1); /* state, */ | 201 | lua_pushvalue(L, 1); /* state, */ |
| 191 | lua_pushnumber(L, 0); /* and initial value */ | 202 | lua_pushnumber(L, 0); /* and initial value */ |
| 192 | return 3; | 203 | return 3; |
| @@ -225,6 +236,15 @@ static int luaB_loadfile (lua_State *L) { | |||
| 225 | } | 236 | } |
| 226 | 237 | ||
| 227 | 238 | ||
| 239 | static int luaB_dofile (lua_State *L) { | ||
| 240 | const char *fname = luaL_opt_string(L, 1, NULL); | ||
| 241 | int status = luaL_loadfile(L, fname); | ||
| 242 | if (status != 0) lua_error(L); | ||
| 243 | lua_call(L, 0, LUA_MULTRET); | ||
| 244 | return lua_gettop(L) - 1; | ||
| 245 | } | ||
| 246 | |||
| 247 | |||
| 228 | static int luaB_assert (lua_State *L) { | 248 | static int luaB_assert (lua_State *L) { |
| 229 | luaL_check_any(L, 1); | 249 | luaL_check_any(L, 1); |
| 230 | if (!lua_toboolean(L, 1)) | 250 | if (!lua_toboolean(L, 1)) |
| @@ -294,21 +314,27 @@ static int luaB_tostring (lua_State *L) { | |||
| 294 | 314 | ||
| 295 | 315 | ||
| 296 | static int luaB_newproxy (lua_State *L) { | 316 | static int luaB_newproxy (lua_State *L) { |
| 297 | void *u; | 317 | static const char dummy = '\0'; |
| 298 | lua_pushnil(L); /* default argument (if there is nothing at stack[1]) */ | 318 | lua_settop(L, 1); |
| 299 | u = lua_newuserdata(L, sizeof(lua_CFunction)); /* create proxy */ | 319 | luaL_weakregistry(L); /* get weak registry */ |
| 300 | *(lua_CFunction *)u = luaB_newproxy; /* mark it as a proxy */ | 320 | lua_newuserdata(L, 0); /* create proxy */ |
| 301 | if (lua_toboolean(L, 1) == 0) | 321 | if (lua_toboolean(L, 1) == 0) |
| 302 | return 1; /* no metatable */ | 322 | return 1; /* no metatable */ |
| 303 | else if ((u = lua_touserdata(L, 1)) != NULL) { | 323 | else if (lua_isboolean(L, 1)) { |
| 304 | luaL_arg_check(L, *(lua_CFunction *)u == luaB_newproxy, 1, "invalid proxy"); | 324 | lua_newtable(L); /* create a new metatable `m' ... */ |
| 305 | lua_getmetatable(L, 1); /* reuse metatable */ | 325 | lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ |
| 326 | lua_pushudataval(L, (void *)&dummy); | ||
| 327 | lua_rawset(L, 2); /* weakregistry[m] = &dummy */ | ||
| 306 | } | 328 | } |
| 307 | else { | 329 | else { |
| 308 | luaL_check_type(L, 1, LUA_TBOOLEAN); | 330 | if (lua_getmetatable(L, 1)) /* check whether registry[m] == &dummy */ |
| 309 | lua_newtable(L); /* create a new metatable */ | 331 | lua_rawget(L, 2); |
| 332 | luaL_arg_check(L, (char *)lua_touserdata(L, -1) == &dummy, 1, | ||
| 333 | "boolean/proxy expected"); | ||
| 334 | lua_getmetatable(L, 1); /* metatable is valid */ | ||
| 310 | } | 335 | } |
| 311 | lua_setmetatable(L, -2); | 336 | lua_setmetatable(L, 3); |
| 337 | lua_pushvalue(L, 3); | ||
| 312 | return 1; | 338 | return 1; |
| 313 | } | 339 | } |
| 314 | 340 | ||
| @@ -380,7 +406,7 @@ static int luaB_require (lua_State *L) { | |||
| 380 | if (!lua_istable(L, 2)) return luaL_error(L, REQTAB " is not a table"); | 406 | if (!lua_istable(L, 2)) return luaL_error(L, REQTAB " is not a table"); |
| 381 | path = getpath(L); | 407 | path = getpath(L); |
| 382 | lua_pushvalue(L, 1); /* check package's name in book-keeping table */ | 408 | lua_pushvalue(L, 1); /* check package's name in book-keeping table */ |
| 383 | lua_gettable(L, 2); | 409 | lua_rawget(L, 2); |
| 384 | if (!lua_isnil(L, -1)) /* is it there? */ | 410 | if (!lua_isnil(L, -1)) /* is it there? */ |
| 385 | return 0; /* package is already loaded */ | 411 | return 0; /* package is already loaded */ |
| 386 | else { /* must load it */ | 412 | else { /* must load it */ |
| @@ -393,10 +419,10 @@ static int luaB_require (lua_State *L) { | |||
| 393 | } | 419 | } |
| 394 | switch (status) { | 420 | switch (status) { |
| 395 | case 0: { | 421 | case 0: { |
| 396 | lua_upcall(L, 0, 0); /* run loaded module */ | 422 | lua_call(L, 0, 0); /* run loaded module */ |
| 397 | lua_pushvalue(L, 1); | 423 | lua_pushvalue(L, 1); |
| 398 | lua_pushboolean(L, 1); | 424 | lua_pushboolean(L, 1); |
| 399 | lua_settable(L, 2); /* mark it as loaded */ | 425 | lua_rawset(L, 2); /* mark it as loaded */ |
| 400 | return 0; | 426 | return 0; |
| 401 | } | 427 | } |
| 402 | case LUA_ERRFILE: { /* file not found */ | 428 | case LUA_ERRFILE: { /* file not found */ |
| @@ -419,7 +445,8 @@ static const luaL_reg base_funcs[] = { | |||
| 419 | {"getglobals", luaB_getglobals}, | 445 | {"getglobals", luaB_getglobals}, |
| 420 | {"setglobals", luaB_setglobals}, | 446 | {"setglobals", luaB_setglobals}, |
| 421 | {"next", luaB_next}, | 447 | {"next", luaB_next}, |
| 422 | {"nexti", luaB_nexti}, | 448 | {"ipairs", luaB_ipairs}, |
| 449 | {"pairs", luaB_pairs}, | ||
| 423 | {"print", luaB_print}, | 450 | {"print", luaB_print}, |
| 424 | {"tonumber", luaB_tonumber}, | 451 | {"tonumber", luaB_tonumber}, |
| 425 | {"tostring", luaB_tostring}, | 452 | {"tostring", luaB_tostring}, |
| @@ -434,6 +461,7 @@ static const luaL_reg base_funcs[] = { | |||
| 434 | {"collectgarbage", luaB_collectgarbage}, | 461 | {"collectgarbage", luaB_collectgarbage}, |
| 435 | {"gcinfo", luaB_gcinfo}, | 462 | {"gcinfo", luaB_gcinfo}, |
| 436 | {"loadfile", luaB_loadfile}, | 463 | {"loadfile", luaB_loadfile}, |
| 464 | {"dofile", luaB_dofile}, | ||
| 437 | {"loadstring", luaB_loadstring}, | 465 | {"loadstring", luaB_loadstring}, |
| 438 | {"require", luaB_require}, | 466 | {"require", luaB_require}, |
| 439 | {NULL, NULL} | 467 | {NULL, NULL} |
| @@ -531,8 +559,8 @@ static void base_open (lua_State *L) { | |||
| 531 | luaL_openlib(L, base_funcs, 0); /* open lib into global table */ | 559 | luaL_openlib(L, base_funcs, 0); /* open lib into global table */ |
| 532 | lua_pushliteral(L, "_VERSION"); | 560 | lua_pushliteral(L, "_VERSION"); |
| 533 | lua_pushliteral(L, LUA_VERSION); | 561 | lua_pushliteral(L, LUA_VERSION); |
| 534 | lua_settable(L, -3); /* set global _VERSION */ | 562 | lua_rawset(L, -3); /* set global _VERSION */ |
| 535 | lua_settable(L, -1); /* set global _G */ | 563 | lua_rawset(L, -1); /* set global _G */ |
| 536 | } | 564 | } |
| 537 | 565 | ||
| 538 | 566 | ||
