diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2007-06-21 11:09:59 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2007-06-21 11:09:59 -0300 |
| commit | d26bfb5ae4fd11b784298317b39a390ea2a5beb5 (patch) | |
| tree | 6f2e8c72db93e7c969f5204a86e40b3e3a96a2f4 | |
| parent | 8d3dd04137348b604ec9ebee87df84c8ef5fdced (diff) | |
| download | lua-d26bfb5ae4fd11b784298317b39a390ea2a5beb5.tar.gz lua-d26bfb5ae4fd11b784298317b39a390ea2a5beb5.tar.bz2 lua-d26bfb5ae4fd11b784298317b39a390ea2a5beb5.zip | |
"spacial" reorganization to keep related functions in groups
| -rw-r--r-- | lauxlib.c | 307 |
1 files changed, 163 insertions, 144 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lauxlib.c,v 1.167 2007/05/15 18:46:12 roberto Exp roberto $ | 2 | ** $Id: lauxlib.c,v 1.168 2007/06/21 13:48:04 roberto Exp roberto $ |
| 3 | ** Auxiliary functions for building Lua libraries | 3 | ** Auxiliary functions for building Lua libraries |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -25,13 +25,6 @@ | |||
| 25 | #include "lauxlib.h" | 25 | #include "lauxlib.h" |
| 26 | 26 | ||
| 27 | 27 | ||
| 28 | /* number of prereserved references (for internal use) */ | ||
| 29 | #define RESERVED_REFS 1 /* only FREELIST_REF is reserved */ | ||
| 30 | |||
| 31 | #define FREELIST_REF 1 /* free list of references */ | ||
| 32 | |||
| 33 | |||
| 34 | |||
| 35 | /* convert a stack index to positive */ | 28 | /* convert a stack index to positive */ |
| 36 | #define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ | 29 | #define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ |
| 37 | lua_gettop(L) + (i) + 1) | 30 | lua_gettop(L) + (i) + 1) |
| @@ -43,7 +36,6 @@ | |||
| 43 | ** ======================================================= | 36 | ** ======================================================= |
| 44 | */ | 37 | */ |
| 45 | 38 | ||
| 46 | |||
| 47 | LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { | 39 | LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { |
| 48 | lua_Debug ar; | 40 | lua_Debug ar; |
| 49 | if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ | 41 | if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ |
| @@ -100,18 +92,11 @@ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { | |||
| 100 | /* }====================================================== */ | 92 | /* }====================================================== */ |
| 101 | 93 | ||
| 102 | 94 | ||
| 103 | LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, | 95 | /* |
| 104 | const char *const lst[]) { | 96 | ** {====================================================== |
| 105 | const char *name = (def) ? luaL_optstring(L, narg, def) : | 97 | ** Userdata's metatable manipulation |
| 106 | luaL_checkstring(L, narg); | 98 | ** ======================================================= |
| 107 | int i; | 99 | */ |
| 108 | for (i=0; lst[i]; i++) | ||
| 109 | if (strcmp(lst[i], name) == 0) | ||
| 110 | return i; | ||
| 111 | return luaL_argerror(L, narg, | ||
| 112 | lua_pushfstring(L, "invalid option " LUA_QS, name)); | ||
| 113 | } | ||
| 114 | |||
| 115 | 100 | ||
| 116 | LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { | 101 | LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { |
| 117 | lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ | 102 | lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ |
| @@ -146,6 +131,27 @@ LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { | |||
| 146 | return p; | 131 | return p; |
| 147 | } | 132 | } |
| 148 | 133 | ||
| 134 | /* }====================================================== */ | ||
| 135 | |||
| 136 | |||
| 137 | /* | ||
| 138 | ** {====================================================== | ||
| 139 | ** Argument check functions | ||
| 140 | ** ======================================================= | ||
| 141 | */ | ||
| 142 | |||
| 143 | LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, | ||
| 144 | const char *const lst[]) { | ||
| 145 | const char *name = (def) ? luaL_optstring(L, narg, def) : | ||
| 146 | luaL_checkstring(L, narg); | ||
| 147 | int i; | ||
| 148 | for (i=0; lst[i]; i++) | ||
| 149 | if (strcmp(lst[i], name) == 0) | ||
| 150 | return i; | ||
| 151 | return luaL_argerror(L, narg, | ||
| 152 | lua_pushfstring(L, "invalid option " LUA_QS, name)); | ||
| 153 | } | ||
| 154 | |||
| 149 | 155 | ||
| 150 | LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { | 156 | LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { |
| 151 | if (!lua_checkstack(L, space)) | 157 | if (!lua_checkstack(L, space)) |
| @@ -209,128 +215,7 @@ LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, | |||
| 209 | return luaL_opt(L, luaL_checkinteger, narg, def); | 215 | return luaL_opt(L, luaL_checkinteger, narg, def); |
| 210 | } | 216 | } |
| 211 | 217 | ||
| 212 | 218 | /* }====================================================== */ | |
| 213 | LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { | ||
| 214 | if (!lua_getmetatable(L, obj)) /* no metatable? */ | ||
| 215 | return 0; | ||
| 216 | lua_pushstring(L, event); | ||
| 217 | lua_rawget(L, -2); | ||
| 218 | if (lua_isnil(L, -1)) { | ||
| 219 | lua_pop(L, 2); /* remove metatable and metafield */ | ||
| 220 | return 0; | ||
| 221 | } | ||
| 222 | else { | ||
| 223 | lua_remove(L, -2); /* remove only metatable */ | ||
| 224 | return 1; | ||
| 225 | } | ||
| 226 | } | ||
| 227 | |||
| 228 | |||
| 229 | LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { | ||
| 230 | obj = abs_index(L, obj); | ||
| 231 | if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ | ||
| 232 | return 0; | ||
| 233 | lua_pushvalue(L, obj); | ||
| 234 | lua_call(L, 1, 1); | ||
| 235 | return 1; | ||
| 236 | } | ||
| 237 | |||
| 238 | |||
| 239 | LUALIB_API const char *luaL_tostring (lua_State *L, int idx) { | ||
| 240 | if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */ | ||
| 241 | switch (lua_type(L, idx)) { | ||
| 242 | case LUA_TNUMBER: | ||
| 243 | return lua_pushstring(L, lua_tostring(L, idx)); | ||
| 244 | case LUA_TSTRING: | ||
| 245 | lua_pushvalue(L, idx); | ||
| 246 | break; | ||
| 247 | case LUA_TBOOLEAN: | ||
| 248 | return lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); | ||
| 249 | case LUA_TNIL: | ||
| 250 | return lua_pushliteral(L, "nil"); | ||
| 251 | default: | ||
| 252 | return lua_pushfstring(L, "%s: %p", luaL_typename(L, idx), | ||
| 253 | lua_topointer(L, idx)); | ||
| 254 | } | ||
| 255 | } | ||
| 256 | return lua_tostring(L, -1); | ||
| 257 | } | ||
| 258 | |||
| 259 | |||
| 260 | static int libsize (const luaL_Reg *l) { | ||
| 261 | int size = 0; | ||
| 262 | for (; l->name; l++) size++; | ||
| 263 | return size; | ||
| 264 | } | ||
| 265 | |||
| 266 | |||
| 267 | LUALIB_API void luaL_register (lua_State *L, const char *libname, | ||
| 268 | const luaL_Reg *l) { | ||
| 269 | if (libname) { | ||
| 270 | int size = libsize(l); | ||
| 271 | /* check whether lib already exists */ | ||
| 272 | luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", size); | ||
| 273 | lua_getfield(L, -1, libname); /* get _LOADED[libname] */ | ||
| 274 | if (!lua_istable(L, -1)) { /* not found? */ | ||
| 275 | lua_pop(L, 1); /* remove previous result */ | ||
| 276 | /* try global variable (and create one if it does not exist) */ | ||
| 277 | if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) | ||
| 278 | luaL_error(L, "name conflict for module " LUA_QS, libname); | ||
| 279 | lua_pushvalue(L, -1); | ||
| 280 | lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ | ||
| 281 | } | ||
| 282 | lua_remove(L, -2); /* remove _LOADED table */ | ||
| 283 | } | ||
| 284 | for (; l->name; l++) { | ||
| 285 | lua_pushcfunction(L, l->func); | ||
| 286 | lua_setfield(L, -2, l->name); | ||
| 287 | } | ||
| 288 | } | ||
| 289 | |||
| 290 | |||
| 291 | LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, | ||
| 292 | const char *r) { | ||
| 293 | const char *wild; | ||
| 294 | size_t l = strlen(p); | ||
| 295 | luaL_Buffer b; | ||
| 296 | luaL_buffinit(L, &b); | ||
| 297 | while ((wild = strstr(s, p)) != NULL) { | ||
| 298 | luaL_addlstring(&b, s, wild - s); /* push prefix */ | ||
| 299 | luaL_addstring(&b, r); /* push replacement in place of pattern */ | ||
| 300 | s = wild + l; /* continue after `p' */ | ||
| 301 | } | ||
| 302 | luaL_addstring(&b, s); /* push last suffix */ | ||
| 303 | luaL_pushresult(&b); | ||
| 304 | return lua_tostring(L, -1); | ||
| 305 | } | ||
| 306 | |||
| 307 | |||
| 308 | LUALIB_API const char *luaL_findtable (lua_State *L, int idx, | ||
| 309 | const char *fname, int szhint) { | ||
| 310 | const char *e; | ||
| 311 | lua_pushvalue(L, idx); | ||
| 312 | do { | ||
| 313 | e = strchr(fname, '.'); | ||
| 314 | if (e == NULL) e = fname + strlen(fname); | ||
| 315 | lua_pushlstring(L, fname, e - fname); | ||
| 316 | lua_rawget(L, -2); | ||
| 317 | if (lua_isnil(L, -1)) { /* no such field? */ | ||
| 318 | lua_pop(L, 1); /* remove this nil */ | ||
| 319 | lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ | ||
| 320 | lua_pushlstring(L, fname, e - fname); | ||
| 321 | lua_pushvalue(L, -2); | ||
| 322 | lua_settable(L, -4); /* set new table into field */ | ||
| 323 | } | ||
| 324 | else if (!lua_istable(L, -1)) { /* field has a non-table value? */ | ||
| 325 | lua_pop(L, 2); /* remove table and value */ | ||
| 326 | return fname; /* return problematic part of the name */ | ||
| 327 | } | ||
| 328 | lua_remove(L, -2); /* remove previous table */ | ||
| 329 | fname = e + 1; | ||
| 330 | } while (*e == '.'); | ||
| 331 | return NULL; | ||
| 332 | } | ||
| 333 | |||
| 334 | 219 | ||
| 335 | 220 | ||
| 336 | /* | 221 | /* |
| @@ -429,6 +314,18 @@ LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { | |||
| 429 | /* }====================================================== */ | 314 | /* }====================================================== */ |
| 430 | 315 | ||
| 431 | 316 | ||
| 317 | /* | ||
| 318 | ** {====================================================== | ||
| 319 | ** Reference system | ||
| 320 | ** ======================================================= | ||
| 321 | */ | ||
| 322 | |||
| 323 | /* number of prereserved references (for internal use) */ | ||
| 324 | #define RESERVED_REFS 1 /* only FREELIST_REF is reserved */ | ||
| 325 | |||
| 326 | #define FREELIST_REF 1 /* free list of references */ | ||
| 327 | |||
| 328 | |||
| 432 | LUALIB_API int luaL_ref (lua_State *L, int t) { | 329 | LUALIB_API int luaL_ref (lua_State *L, int t) { |
| 433 | int ref; | 330 | int ref; |
| 434 | t = abs_index(L, t); | 331 | t = abs_index(L, t); |
| @@ -464,6 +361,7 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { | |||
| 464 | } | 361 | } |
| 465 | } | 362 | } |
| 466 | 363 | ||
| 364 | /* }====================================================== */ | ||
| 467 | 365 | ||
| 468 | 366 | ||
| 469 | /* | 367 | /* |
| @@ -572,9 +470,130 @@ LUALIB_API int luaL_loadstring (lua_State *L, const char *s) { | |||
| 572 | return luaL_loadbuffer(L, s, strlen(s), s); | 470 | return luaL_loadbuffer(L, s, strlen(s), s); |
| 573 | } | 471 | } |
| 574 | 472 | ||
| 473 | /* }====================================================== */ | ||
| 575 | 474 | ||
| 576 | 475 | ||
| 577 | /* }====================================================== */ | 476 | |
| 477 | LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { | ||
| 478 | if (!lua_getmetatable(L, obj)) /* no metatable? */ | ||
| 479 | return 0; | ||
| 480 | lua_pushstring(L, event); | ||
| 481 | lua_rawget(L, -2); | ||
| 482 | if (lua_isnil(L, -1)) { | ||
| 483 | lua_pop(L, 2); /* remove metatable and metafield */ | ||
| 484 | return 0; | ||
| 485 | } | ||
| 486 | else { | ||
| 487 | lua_remove(L, -2); /* remove only metatable */ | ||
| 488 | return 1; | ||
| 489 | } | ||
| 490 | } | ||
| 491 | |||
| 492 | |||
| 493 | LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { | ||
| 494 | obj = abs_index(L, obj); | ||
| 495 | if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ | ||
| 496 | return 0; | ||
| 497 | lua_pushvalue(L, obj); | ||
| 498 | lua_call(L, 1, 1); | ||
| 499 | return 1; | ||
| 500 | } | ||
| 501 | |||
| 502 | |||
| 503 | LUALIB_API const char *luaL_tostring (lua_State *L, int idx) { | ||
| 504 | if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */ | ||
| 505 | switch (lua_type(L, idx)) { | ||
| 506 | case LUA_TNUMBER: | ||
| 507 | return lua_pushstring(L, lua_tostring(L, idx)); | ||
| 508 | case LUA_TSTRING: | ||
| 509 | lua_pushvalue(L, idx); | ||
| 510 | break; | ||
| 511 | case LUA_TBOOLEAN: | ||
| 512 | return lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); | ||
| 513 | case LUA_TNIL: | ||
| 514 | return lua_pushliteral(L, "nil"); | ||
| 515 | default: | ||
| 516 | return lua_pushfstring(L, "%s: %p", luaL_typename(L, idx), | ||
| 517 | lua_topointer(L, idx)); | ||
| 518 | } | ||
| 519 | } | ||
| 520 | return lua_tostring(L, -1); | ||
| 521 | } | ||
| 522 | |||
| 523 | |||
| 524 | static int libsize (const luaL_Reg *l) { | ||
| 525 | int size = 0; | ||
| 526 | for (; l->name; l++) size++; | ||
| 527 | return size; | ||
| 528 | } | ||
| 529 | |||
| 530 | |||
| 531 | LUALIB_API void luaL_register (lua_State *L, const char *libname, | ||
| 532 | const luaL_Reg *l) { | ||
| 533 | if (libname) { | ||
| 534 | int size = libsize(l); | ||
| 535 | /* check whether lib already exists */ | ||
| 536 | luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", size); | ||
| 537 | lua_getfield(L, -1, libname); /* get _LOADED[libname] */ | ||
| 538 | if (!lua_istable(L, -1)) { /* not found? */ | ||
| 539 | lua_pop(L, 1); /* remove previous result */ | ||
| 540 | /* try global variable (and create one if it does not exist) */ | ||
| 541 | if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) | ||
| 542 | luaL_error(L, "name conflict for module " LUA_QS, libname); | ||
| 543 | lua_pushvalue(L, -1); | ||
| 544 | lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ | ||
| 545 | } | ||
| 546 | lua_remove(L, -2); /* remove _LOADED table */ | ||
| 547 | } | ||
| 548 | for (; l->name; l++) { | ||
| 549 | lua_pushcfunction(L, l->func); | ||
| 550 | lua_setfield(L, -2, l->name); | ||
| 551 | } | ||
| 552 | } | ||
| 553 | |||
| 554 | |||
| 555 | LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, | ||
| 556 | const char *r) { | ||
| 557 | const char *wild; | ||
| 558 | size_t l = strlen(p); | ||
| 559 | luaL_Buffer b; | ||
| 560 | luaL_buffinit(L, &b); | ||
| 561 | while ((wild = strstr(s, p)) != NULL) { | ||
| 562 | luaL_addlstring(&b, s, wild - s); /* push prefix */ | ||
| 563 | luaL_addstring(&b, r); /* push replacement in place of pattern */ | ||
| 564 | s = wild + l; /* continue after `p' */ | ||
| 565 | } | ||
| 566 | luaL_addstring(&b, s); /* push last suffix */ | ||
| 567 | luaL_pushresult(&b); | ||
| 568 | return lua_tostring(L, -1); | ||
| 569 | } | ||
| 570 | |||
| 571 | |||
| 572 | LUALIB_API const char *luaL_findtable (lua_State *L, int idx, | ||
| 573 | const char *fname, int szhint) { | ||
| 574 | const char *e; | ||
| 575 | lua_pushvalue(L, idx); | ||
| 576 | do { | ||
| 577 | e = strchr(fname, '.'); | ||
| 578 | if (e == NULL) e = fname + strlen(fname); | ||
| 579 | lua_pushlstring(L, fname, e - fname); | ||
| 580 | lua_rawget(L, -2); | ||
| 581 | if (lua_isnil(L, -1)) { /* no such field? */ | ||
| 582 | lua_pop(L, 1); /* remove this nil */ | ||
| 583 | lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ | ||
| 584 | lua_pushlstring(L, fname, e - fname); | ||
| 585 | lua_pushvalue(L, -2); | ||
| 586 | lua_settable(L, -4); /* set new table into field */ | ||
| 587 | } | ||
| 588 | else if (!lua_istable(L, -1)) { /* field has a non-table value? */ | ||
| 589 | lua_pop(L, 2); /* remove table and value */ | ||
| 590 | return fname; /* return problematic part of the name */ | ||
| 591 | } | ||
| 592 | lua_remove(L, -2); /* remove previous table */ | ||
| 593 | fname = e + 1; | ||
| 594 | } while (*e == '.'); | ||
| 595 | return NULL; | ||
| 596 | } | ||
| 578 | 597 | ||
| 579 | 598 | ||
| 580 | static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { | 599 | static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { |
