diff options
Diffstat (limited to '')
| -rw-r--r-- | src/lua/lauxlib.c (renamed from src/lua-5.3/lauxlib.c) | 352 |
1 files changed, 183 insertions, 169 deletions
diff --git a/src/lua-5.3/lauxlib.c b/src/lua/lauxlib.c index 8bdada5..e3d9be3 100644 --- a/src/lua-5.3/lauxlib.c +++ b/src/lua/lauxlib.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lauxlib.c,v 1.289.1.1 2017/04/19 17:20:42 roberto Exp $ | 2 | ** $Id: lauxlib.c $ |
| 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 | */ |
| @@ -27,6 +27,12 @@ | |||
| 27 | #include "lauxlib.h" | 27 | #include "lauxlib.h" |
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | #if !defined(MAX_SIZET) | ||
| 31 | /* maximum value for size_t */ | ||
| 32 | #define MAX_SIZET ((size_t)(~(size_t)0)) | ||
| 33 | #endif | ||
| 34 | |||
| 35 | |||
| 30 | /* | 36 | /* |
| 31 | ** {====================================================== | 37 | ** {====================================================== |
| 32 | ** Traceback | 38 | ** Traceback |
| @@ -40,8 +46,8 @@ | |||
| 40 | 46 | ||
| 41 | 47 | ||
| 42 | /* | 48 | /* |
| 43 | ** search for 'objidx' in table at index -1. | 49 | ** Search for 'objidx' in table at index -1. ('objidx' must be an |
| 44 | ** return 1 + string at top if find a good name. | 50 | ** absolute index.) Return 1 + string at top if it found a good name. |
| 45 | */ | 51 | */ |
| 46 | static int findfield (lua_State *L, int objidx, int level) { | 52 | static int findfield (lua_State *L, int objidx, int level) { |
| 47 | if (level == 0 || !lua_istable(L, -1)) | 53 | if (level == 0 || !lua_istable(L, -1)) |
| @@ -54,10 +60,10 @@ static int findfield (lua_State *L, int objidx, int level) { | |||
| 54 | return 1; | 60 | return 1; |
| 55 | } | 61 | } |
| 56 | else if (findfield(L, objidx, level - 1)) { /* try recursively */ | 62 | else if (findfield(L, objidx, level - 1)) { /* try recursively */ |
| 57 | lua_remove(L, -2); /* remove table (but keep name) */ | 63 | /* stack: lib_name, lib_table, field_name (top) */ |
| 58 | lua_pushliteral(L, "."); | 64 | lua_pushliteral(L, "."); /* place '.' between the two names */ |
| 59 | lua_insert(L, -2); /* place '.' between the two names */ | 65 | lua_replace(L, -3); /* (in the slot occupied by table) */ |
| 60 | lua_concat(L, 3); | 66 | lua_concat(L, 3); /* lib_name.field_name */ |
| 61 | return 1; | 67 | return 1; |
| 62 | } | 68 | } |
| 63 | } | 69 | } |
| @@ -76,12 +82,12 @@ static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { | |||
| 76 | lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); | 82 | lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); |
| 77 | if (findfield(L, top + 1, 2)) { | 83 | if (findfield(L, top + 1, 2)) { |
| 78 | const char *name = lua_tostring(L, -1); | 84 | const char *name = lua_tostring(L, -1); |
| 79 | if (strncmp(name, "_G.", 3) == 0) { /* name start with '_G.'? */ | 85 | if (strncmp(name, LUA_GNAME ".", 3) == 0) { /* name start with '_G.'? */ |
| 80 | lua_pushstring(L, name + 3); /* push name without prefix */ | 86 | lua_pushstring(L, name + 3); /* push name without prefix */ |
| 81 | lua_remove(L, -2); /* remove original name */ | 87 | lua_remove(L, -2); /* remove original name */ |
| 82 | } | 88 | } |
| 83 | lua_copy(L, -1, top + 1); /* move name to proper place */ | 89 | lua_copy(L, -1, top + 1); /* copy name to proper place */ |
| 84 | lua_pop(L, 2); /* remove pushed values */ | 90 | lua_settop(L, top + 1); /* remove table "loaded" and name copy */ |
| 85 | return 1; | 91 | return 1; |
| 86 | } | 92 | } |
| 87 | else { | 93 | else { |
| @@ -124,32 +130,37 @@ static int lastlevel (lua_State *L) { | |||
| 124 | 130 | ||
| 125 | LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, | 131 | LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, |
| 126 | const char *msg, int level) { | 132 | const char *msg, int level) { |
| 133 | luaL_Buffer b; | ||
| 127 | lua_Debug ar; | 134 | lua_Debug ar; |
| 128 | int top = lua_gettop(L); | ||
| 129 | int last = lastlevel(L1); | 135 | int last = lastlevel(L1); |
| 130 | int n1 = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1; | 136 | int limit2show = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1; |
| 131 | if (msg) | 137 | luaL_buffinit(L, &b); |
| 132 | lua_pushfstring(L, "%s\n", msg); | 138 | if (msg) { |
| 133 | luaL_checkstack(L, 10, NULL); | 139 | luaL_addstring(&b, msg); |
| 134 | lua_pushliteral(L, "stack traceback:"); | 140 | luaL_addchar(&b, '\n'); |
| 141 | } | ||
| 142 | luaL_addstring(&b, "stack traceback:"); | ||
| 135 | while (lua_getstack(L1, level++, &ar)) { | 143 | while (lua_getstack(L1, level++, &ar)) { |
| 136 | if (n1-- == 0) { /* too many levels? */ | 144 | if (limit2show-- == 0) { /* too many levels? */ |
| 137 | lua_pushliteral(L, "\n\t..."); /* add a '...' */ | 145 | int n = last - level - LEVELS2 + 1; /* number of levels to skip */ |
| 138 | level = last - LEVELS2 + 1; /* and skip to last ones */ | 146 | lua_pushfstring(L, "\n\t...\t(skipping %d levels)", n); |
| 147 | luaL_addvalue(&b); /* add warning about skip */ | ||
| 148 | level += n; /* and skip to last levels */ | ||
| 139 | } | 149 | } |
| 140 | else { | 150 | else { |
| 141 | lua_getinfo(L1, "Slnt", &ar); | 151 | lua_getinfo(L1, "Slnt", &ar); |
| 142 | lua_pushfstring(L, "\n\t%s:", ar.short_src); | 152 | if (ar.currentline <= 0) |
| 143 | if (ar.currentline > 0) | 153 | lua_pushfstring(L, "\n\t%s: in ", ar.short_src); |
| 144 | lua_pushfstring(L, "%d:", ar.currentline); | 154 | else |
| 145 | lua_pushliteral(L, " in "); | 155 | lua_pushfstring(L, "\n\t%s:%d: in ", ar.short_src, ar.currentline); |
| 156 | luaL_addvalue(&b); | ||
| 146 | pushfuncname(L, &ar); | 157 | pushfuncname(L, &ar); |
| 158 | luaL_addvalue(&b); | ||
| 147 | if (ar.istailcall) | 159 | if (ar.istailcall) |
| 148 | lua_pushliteral(L, "\n\t(...tail calls...)"); | 160 | luaL_addstring(&b, "\n\t(...tail calls...)"); |
| 149 | lua_concat(L, lua_gettop(L) - top); | ||
| 150 | } | 161 | } |
| 151 | } | 162 | } |
| 152 | lua_concat(L, lua_gettop(L) - top); | 163 | luaL_pushresult(&b); |
| 153 | } | 164 | } |
| 154 | 165 | ||
| 155 | /* }====================================================== */ | 166 | /* }====================================================== */ |
| @@ -179,7 +190,7 @@ LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) { | |||
| 179 | } | 190 | } |
| 180 | 191 | ||
| 181 | 192 | ||
| 182 | static int typeerror (lua_State *L, int arg, const char *tname) { | 193 | int luaL_typeerror (lua_State *L, int arg, const char *tname) { |
| 183 | const char *msg; | 194 | const char *msg; |
| 184 | const char *typearg; /* name for the type of the actual argument */ | 195 | const char *typearg; /* name for the type of the actual argument */ |
| 185 | if (luaL_getmetafield(L, arg, "__name") == LUA_TSTRING) | 196 | if (luaL_getmetafield(L, arg, "__name") == LUA_TSTRING) |
| @@ -194,7 +205,7 @@ static int typeerror (lua_State *L, int arg, const char *tname) { | |||
| 194 | 205 | ||
| 195 | 206 | ||
| 196 | static void tag_error (lua_State *L, int arg, int tag) { | 207 | static void tag_error (lua_State *L, int arg, int tag) { |
| 197 | typeerror(L, arg, lua_typename(L, tag)); | 208 | luaL_typeerror(L, arg, lua_typename(L, tag)); |
| 198 | } | 209 | } |
| 199 | 210 | ||
| 200 | 211 | ||
| @@ -238,7 +249,7 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { | |||
| 238 | return 1; | 249 | return 1; |
| 239 | } | 250 | } |
| 240 | else { | 251 | else { |
| 241 | lua_pushnil(L); | 252 | luaL_pushfail(L); |
| 242 | if (fname) | 253 | if (fname) |
| 243 | lua_pushfstring(L, "%s: %s", fname, strerror(en)); | 254 | lua_pushfstring(L, "%s: %s", fname, strerror(en)); |
| 244 | else | 255 | else |
| @@ -273,23 +284,24 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { | |||
| 273 | 284 | ||
| 274 | LUALIB_API int luaL_execresult (lua_State *L, int stat) { | 285 | LUALIB_API int luaL_execresult (lua_State *L, int stat) { |
| 275 | const char *what = "exit"; /* type of termination */ | 286 | const char *what = "exit"; /* type of termination */ |
| 276 | if (stat == -1) /* error? */ | 287 | if (stat != 0 && errno != 0) /* error with an 'errno'? */ |
| 277 | return luaL_fileresult(L, 0, NULL); | 288 | return luaL_fileresult(L, 0, NULL); |
| 278 | else { | 289 | else { |
| 279 | l_inspectstat(stat, what); /* interpret result */ | 290 | l_inspectstat(stat, what); /* interpret result */ |
| 280 | if (*what == 'e' && stat == 0) /* successful termination? */ | 291 | if (*what == 'e' && stat == 0) /* successful termination? */ |
| 281 | lua_pushboolean(L, 1); | 292 | lua_pushboolean(L, 1); |
| 282 | else | 293 | else |
| 283 | lua_pushnil(L); | 294 | luaL_pushfail(L); |
| 284 | lua_pushstring(L, what); | 295 | lua_pushstring(L, what); |
| 285 | lua_pushinteger(L, stat); | 296 | lua_pushinteger(L, stat); |
| 286 | return 3; /* return true/nil,what,code */ | 297 | return 3; /* return true/fail,what,code */ |
| 287 | } | 298 | } |
| 288 | } | 299 | } |
| 289 | 300 | ||
| 290 | /* }====================================================== */ | 301 | /* }====================================================== */ |
| 291 | 302 | ||
| 292 | 303 | ||
| 304 | |||
| 293 | /* | 305 | /* |
| 294 | ** {====================================================== | 306 | ** {====================================================== |
| 295 | ** Userdata's metatable manipulation | 307 | ** Userdata's metatable manipulation |
| @@ -332,7 +344,7 @@ LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) { | |||
| 332 | 344 | ||
| 333 | LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { | 345 | LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { |
| 334 | void *p = luaL_testudata(L, ud, tname); | 346 | void *p = luaL_testudata(L, ud, tname); |
| 335 | if (p == NULL) typeerror(L, ud, tname); | 347 | luaL_argexpected(L, p != NULL, ud, tname); |
| 336 | return p; | 348 | return p; |
| 337 | } | 349 | } |
| 338 | 350 | ||
| @@ -463,10 +475,8 @@ static void *resizebox (lua_State *L, int idx, size_t newsize) { | |||
| 463 | lua_Alloc allocf = lua_getallocf(L, &ud); | 475 | lua_Alloc allocf = lua_getallocf(L, &ud); |
| 464 | UBox *box = (UBox *)lua_touserdata(L, idx); | 476 | UBox *box = (UBox *)lua_touserdata(L, idx); |
| 465 | void *temp = allocf(ud, box->box, box->bsize, newsize); | 477 | void *temp = allocf(ud, box->box, box->bsize, newsize); |
| 466 | if (temp == NULL && newsize > 0) { /* allocation error? */ | 478 | if (temp == NULL && newsize > 0) /* allocation error? */ |
| 467 | resizebox(L, idx, 0); /* free buffer */ | 479 | luaL_error(L, "not enough memory"); |
| 468 | luaL_error(L, "not enough memory for buffer allocation"); | ||
| 469 | } | ||
| 470 | box->box = temp; | 480 | box->box = temp; |
| 471 | box->bsize = newsize; | 481 | box->bsize = newsize; |
| 472 | return temp; | 482 | return temp; |
| @@ -479,16 +489,20 @@ static int boxgc (lua_State *L) { | |||
| 479 | } | 489 | } |
| 480 | 490 | ||
| 481 | 491 | ||
| 482 | static void *newbox (lua_State *L, size_t newsize) { | 492 | static const luaL_Reg boxmt[] = { /* box metamethods */ |
| 483 | UBox *box = (UBox *)lua_newuserdata(L, sizeof(UBox)); | 493 | {"__gc", boxgc}, |
| 494 | {"__close", boxgc}, | ||
| 495 | {NULL, NULL} | ||
| 496 | }; | ||
| 497 | |||
| 498 | |||
| 499 | static void newbox (lua_State *L) { | ||
| 500 | UBox *box = (UBox *)lua_newuserdatauv(L, sizeof(UBox), 0); | ||
| 484 | box->box = NULL; | 501 | box->box = NULL; |
| 485 | box->bsize = 0; | 502 | box->bsize = 0; |
| 486 | if (luaL_newmetatable(L, "LUABOX")) { /* creating metatable? */ | 503 | if (luaL_newmetatable(L, "_UBOX*")) /* creating metatable? */ |
| 487 | lua_pushcfunction(L, boxgc); | 504 | luaL_setfuncs(L, boxmt, 0); /* set its metamethods */ |
| 488 | lua_setfield(L, -2, "__gc"); /* metatable.__gc = boxgc */ | ||
| 489 | } | ||
| 490 | lua_setmetatable(L, -2); | 505 | lua_setmetatable(L, -2); |
| 491 | return resizebox(L, -1, newsize); | ||
| 492 | } | 506 | } |
| 493 | 507 | ||
| 494 | 508 | ||
| @@ -496,38 +510,64 @@ static void *newbox (lua_State *L, size_t newsize) { | |||
| 496 | ** check whether buffer is using a userdata on the stack as a temporary | 510 | ** check whether buffer is using a userdata on the stack as a temporary |
| 497 | ** buffer | 511 | ** buffer |
| 498 | */ | 512 | */ |
| 499 | #define buffonstack(B) ((B)->b != (B)->initb) | 513 | #define buffonstack(B) ((B)->b != (B)->init.b) |
| 500 | 514 | ||
| 501 | 515 | ||
| 502 | /* | 516 | /* |
| 503 | ** returns a pointer to a free area with at least 'sz' bytes | 517 | ** Compute new size for buffer 'B', enough to accommodate extra 'sz' |
| 518 | ** bytes. | ||
| 504 | */ | 519 | */ |
| 505 | LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { | 520 | static size_t newbuffsize (luaL_Buffer *B, size_t sz) { |
| 506 | lua_State *L = B->L; | 521 | size_t newsize = B->size * 2; /* double buffer size */ |
| 507 | if (B->size - B->n < sz) { /* not enough space? */ | 522 | if (MAX_SIZET - sz < B->n) /* overflow in (B->n + sz)? */ |
| 523 | return luaL_error(B->L, "buffer too large"); | ||
| 524 | if (newsize < B->n + sz) /* double is not big enough? */ | ||
| 525 | newsize = B->n + sz; | ||
| 526 | return newsize; | ||
| 527 | } | ||
| 528 | |||
| 529 | |||
| 530 | /* | ||
| 531 | ** Returns a pointer to a free area with at least 'sz' bytes in buffer | ||
| 532 | ** 'B'. 'boxidx' is the relative position in the stack where the | ||
| 533 | ** buffer's box is or should be. | ||
| 534 | */ | ||
| 535 | static char *prepbuffsize (luaL_Buffer *B, size_t sz, int boxidx) { | ||
| 536 | if (B->size - B->n >= sz) /* enough space? */ | ||
| 537 | return B->b + B->n; | ||
| 538 | else { | ||
| 539 | lua_State *L = B->L; | ||
| 508 | char *newbuff; | 540 | char *newbuff; |
| 509 | size_t newsize = B->size * 2; /* double buffer size */ | 541 | size_t newsize = newbuffsize(B, sz); |
| 510 | if (newsize - B->n < sz) /* not big enough? */ | ||
| 511 | newsize = B->n + sz; | ||
| 512 | if (newsize < B->n || newsize - B->n < sz) | ||
| 513 | luaL_error(L, "buffer too large"); | ||
| 514 | /* create larger buffer */ | 542 | /* create larger buffer */ |
| 515 | if (buffonstack(B)) | 543 | if (buffonstack(B)) /* buffer already has a box? */ |
| 516 | newbuff = (char *)resizebox(L, -1, newsize); | 544 | newbuff = (char *)resizebox(L, boxidx, newsize); /* resize it */ |
| 517 | else { /* no buffer yet */ | 545 | else { /* no box yet */ |
| 518 | newbuff = (char *)newbox(L, newsize); | 546 | lua_pushnil(L); /* reserve slot for final result */ |
| 547 | newbox(L); /* create a new box */ | ||
| 548 | /* move box (and slot) to its intended position */ | ||
| 549 | lua_rotate(L, boxidx - 1, 2); | ||
| 550 | lua_toclose(L, boxidx); | ||
| 551 | newbuff = (char *)resizebox(L, boxidx, newsize); | ||
| 519 | memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */ | 552 | memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */ |
| 520 | } | 553 | } |
| 521 | B->b = newbuff; | 554 | B->b = newbuff; |
| 522 | B->size = newsize; | 555 | B->size = newsize; |
| 556 | return newbuff + B->n; | ||
| 523 | } | 557 | } |
| 524 | return &B->b[B->n]; | 558 | } |
| 559 | |||
| 560 | /* | ||
| 561 | ** returns a pointer to a free area with at least 'sz' bytes | ||
| 562 | */ | ||
| 563 | LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { | ||
| 564 | return prepbuffsize(B, sz, -1); | ||
| 525 | } | 565 | } |
| 526 | 566 | ||
| 527 | 567 | ||
| 528 | LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { | 568 | LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { |
| 529 | if (l > 0) { /* avoid 'memcpy' when 's' can be NULL */ | 569 | if (l > 0) { /* avoid 'memcpy' when 's' can be NULL */ |
| 530 | char *b = luaL_prepbuffsize(B, l); | 570 | char *b = prepbuffsize(B, l, -1); |
| 531 | memcpy(b, s, l * sizeof(char)); | 571 | memcpy(b, s, l * sizeof(char)); |
| 532 | luaL_addsize(B, l); | 572 | luaL_addsize(B, l); |
| 533 | } | 573 | } |
| @@ -543,8 +583,8 @@ LUALIB_API void luaL_pushresult (luaL_Buffer *B) { | |||
| 543 | lua_State *L = B->L; | 583 | lua_State *L = B->L; |
| 544 | lua_pushlstring(L, B->b, B->n); | 584 | lua_pushlstring(L, B->b, B->n); |
| 545 | if (buffonstack(B)) { | 585 | if (buffonstack(B)) { |
| 546 | resizebox(L, -2, 0); /* delete old buffer */ | 586 | lua_copy(L, -1, -3); /* move string to reserved slot */ |
| 547 | lua_remove(L, -2); /* remove its header from the stack */ | 587 | lua_pop(L, 2); /* pop string and box (closing the box) */ |
| 548 | } | 588 | } |
| 549 | } | 589 | } |
| 550 | 590 | ||
| @@ -555,20 +595,29 @@ LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { | |||
| 555 | } | 595 | } |
| 556 | 596 | ||
| 557 | 597 | ||
| 598 | /* | ||
| 599 | ** 'luaL_addvalue' is the only function in the Buffer system where the | ||
| 600 | ** box (if existent) is not on the top of the stack. So, instead of | ||
| 601 | ** calling 'luaL_addlstring', it replicates the code using -2 as the | ||
| 602 | ** last argument to 'prepbuffsize', signaling that the box is (or will | ||
| 603 | ** be) bellow the string being added to the buffer. (Box creation can | ||
| 604 | ** trigger an emergency GC, so we should not remove the string from the | ||
| 605 | ** stack before we have the space guaranteed.) | ||
| 606 | */ | ||
| 558 | LUALIB_API void luaL_addvalue (luaL_Buffer *B) { | 607 | LUALIB_API void luaL_addvalue (luaL_Buffer *B) { |
| 559 | lua_State *L = B->L; | 608 | lua_State *L = B->L; |
| 560 | size_t l; | 609 | size_t len; |
| 561 | const char *s = lua_tolstring(L, -1, &l); | 610 | const char *s = lua_tolstring(L, -1, &len); |
| 562 | if (buffonstack(B)) | 611 | char *b = prepbuffsize(B, len, -2); |
| 563 | lua_insert(L, -2); /* put value below buffer */ | 612 | memcpy(b, s, len * sizeof(char)); |
| 564 | luaL_addlstring(B, s, l); | 613 | luaL_addsize(B, len); |
| 565 | lua_remove(L, (buffonstack(B)) ? -2 : -1); /* remove value */ | 614 | lua_pop(L, 1); /* pop string */ |
| 566 | } | 615 | } |
| 567 | 616 | ||
| 568 | 617 | ||
| 569 | LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { | 618 | LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { |
| 570 | B->L = L; | 619 | B->L = L; |
| 571 | B->b = B->initb; | 620 | B->b = B->init.b; |
| 572 | B->n = 0; | 621 | B->n = 0; |
| 573 | B->size = LUAL_BUFFERSIZE; | 622 | B->size = LUAL_BUFFERSIZE; |
| 574 | } | 623 | } |
| @@ -576,7 +625,7 @@ LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { | |||
| 576 | 625 | ||
| 577 | LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { | 626 | LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { |
| 578 | luaL_buffinit(L, B); | 627 | luaL_buffinit(L, B); |
| 579 | return luaL_prepbuffsize(B, sz); | 628 | return prepbuffsize(B, sz, -1); |
| 580 | } | 629 | } |
| 581 | 630 | ||
| 582 | /* }====================================================== */ | 631 | /* }====================================================== */ |
| @@ -846,87 +895,6 @@ LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { | |||
| 846 | 895 | ||
| 847 | 896 | ||
| 848 | /* | 897 | /* |
| 849 | ** {====================================================== | ||
| 850 | ** Compatibility with 5.1 module functions | ||
| 851 | ** ======================================================= | ||
| 852 | */ | ||
| 853 | #if defined(LUA_COMPAT_MODULE) | ||
| 854 | |||
| 855 | static const char *luaL_findtable (lua_State *L, int idx, | ||
| 856 | const char *fname, int szhint) { | ||
| 857 | const char *e; | ||
| 858 | if (idx) lua_pushvalue(L, idx); | ||
| 859 | do { | ||
| 860 | e = strchr(fname, '.'); | ||
| 861 | if (e == NULL) e = fname + strlen(fname); | ||
| 862 | lua_pushlstring(L, fname, e - fname); | ||
| 863 | if (lua_rawget(L, -2) == LUA_TNIL) { /* no such field? */ | ||
| 864 | lua_pop(L, 1); /* remove this nil */ | ||
| 865 | lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ | ||
| 866 | lua_pushlstring(L, fname, e - fname); | ||
| 867 | lua_pushvalue(L, -2); | ||
| 868 | lua_settable(L, -4); /* set new table into field */ | ||
| 869 | } | ||
| 870 | else if (!lua_istable(L, -1)) { /* field has a non-table value? */ | ||
| 871 | lua_pop(L, 2); /* remove table and value */ | ||
| 872 | return fname; /* return problematic part of the name */ | ||
| 873 | } | ||
| 874 | lua_remove(L, -2); /* remove previous table */ | ||
| 875 | fname = e + 1; | ||
| 876 | } while (*e == '.'); | ||
| 877 | return NULL; | ||
| 878 | } | ||
| 879 | |||
| 880 | |||
| 881 | /* | ||
| 882 | ** Count number of elements in a luaL_Reg list. | ||
| 883 | */ | ||
| 884 | static int libsize (const luaL_Reg *l) { | ||
| 885 | int size = 0; | ||
| 886 | for (; l && l->name; l++) size++; | ||
| 887 | return size; | ||
| 888 | } | ||
| 889 | |||
| 890 | |||
| 891 | /* | ||
| 892 | ** Find or create a module table with a given name. The function | ||
| 893 | ** first looks at the LOADED table and, if that fails, try a | ||
| 894 | ** global variable with that name. In any case, leaves on the stack | ||
| 895 | ** the module table. | ||
| 896 | */ | ||
| 897 | LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname, | ||
| 898 | int sizehint) { | ||
| 899 | luaL_findtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE, 1); | ||
| 900 | if (lua_getfield(L, -1, modname) != LUA_TTABLE) { /* no LOADED[modname]? */ | ||
| 901 | lua_pop(L, 1); /* remove previous result */ | ||
| 902 | /* try global variable (and create one if it does not exist) */ | ||
| 903 | lua_pushglobaltable(L); | ||
| 904 | if (luaL_findtable(L, 0, modname, sizehint) != NULL) | ||
| 905 | luaL_error(L, "name conflict for module '%s'", modname); | ||
| 906 | lua_pushvalue(L, -1); | ||
| 907 | lua_setfield(L, -3, modname); /* LOADED[modname] = new table */ | ||
| 908 | } | ||
| 909 | lua_remove(L, -2); /* remove LOADED table */ | ||
| 910 | } | ||
| 911 | |||
| 912 | |||
| 913 | LUALIB_API void luaL_openlib (lua_State *L, const char *libname, | ||
| 914 | const luaL_Reg *l, int nup) { | ||
| 915 | luaL_checkversion(L); | ||
| 916 | if (libname) { | ||
| 917 | luaL_pushmodule(L, libname, libsize(l)); /* get/create library table */ | ||
| 918 | lua_insert(L, -(nup + 1)); /* move library table to below upvalues */ | ||
| 919 | } | ||
| 920 | if (l) | ||
| 921 | luaL_setfuncs(L, l, nup); | ||
| 922 | else | ||
| 923 | lua_pop(L, nup); /* remove upvalues */ | ||
| 924 | } | ||
| 925 | |||
| 926 | #endif | ||
| 927 | /* }====================================================== */ | ||
| 928 | |||
| 929 | /* | ||
| 930 | ** set functions from list 'l' into table at top - 'nup'; each | 898 | ** set functions from list 'l' into table at top - 'nup'; each |
| 931 | ** function gets the 'nup' elements at the top as upvalues. | 899 | ** function gets the 'nup' elements at the top as upvalues. |
| 932 | ** Returns with only the table at the stack. | 900 | ** Returns with only the table at the stack. |
| @@ -934,10 +902,14 @@ LUALIB_API void luaL_openlib (lua_State *L, const char *libname, | |||
| 934 | LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { | 902 | LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { |
| 935 | luaL_checkstack(L, nup, "too many upvalues"); | 903 | luaL_checkstack(L, nup, "too many upvalues"); |
| 936 | for (; l->name != NULL; l++) { /* fill the table with given functions */ | 904 | for (; l->name != NULL; l++) { /* fill the table with given functions */ |
| 937 | int i; | 905 | if (l->func == NULL) /* place holder? */ |
| 938 | for (i = 0; i < nup; i++) /* copy upvalues to the top */ | 906 | lua_pushboolean(L, 0); |
| 939 | lua_pushvalue(L, -nup); | 907 | else { |
| 940 | lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ | 908 | int i; |
| 909 | for (i = 0; i < nup; i++) /* copy upvalues to the top */ | ||
| 910 | lua_pushvalue(L, -nup); | ||
| 911 | lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ | ||
| 912 | } | ||
| 941 | lua_setfield(L, -(nup + 2), l->name); | 913 | lua_setfield(L, -(nup + 2), l->name); |
| 942 | } | 914 | } |
| 943 | lua_pop(L, nup); /* remove upvalues */ | 915 | lua_pop(L, nup); /* remove upvalues */ |
| @@ -988,18 +960,24 @@ LUALIB_API void luaL_requiref (lua_State *L, const char *modname, | |||
| 988 | } | 960 | } |
| 989 | 961 | ||
| 990 | 962 | ||
| 991 | LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, | 963 | LUALIB_API void luaL_addgsub (luaL_Buffer *b, const char *s, |
| 992 | const char *r) { | 964 | const char *p, const char *r) { |
| 993 | const char *wild; | 965 | const char *wild; |
| 994 | size_t l = strlen(p); | 966 | size_t l = strlen(p); |
| 995 | luaL_Buffer b; | ||
| 996 | luaL_buffinit(L, &b); | ||
| 997 | while ((wild = strstr(s, p)) != NULL) { | 967 | while ((wild = strstr(s, p)) != NULL) { |
| 998 | luaL_addlstring(&b, s, wild - s); /* push prefix */ | 968 | luaL_addlstring(b, s, wild - s); /* push prefix */ |
| 999 | luaL_addstring(&b, r); /* push replacement in place of pattern */ | 969 | luaL_addstring(b, r); /* push replacement in place of pattern */ |
| 1000 | s = wild + l; /* continue after 'p' */ | 970 | s = wild + l; /* continue after 'p' */ |
| 1001 | } | 971 | } |
| 1002 | luaL_addstring(&b, s); /* push last suffix */ | 972 | luaL_addstring(b, s); /* push last suffix */ |
| 973 | } | ||
| 974 | |||
| 975 | |||
| 976 | LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, | ||
| 977 | const char *p, const char *r) { | ||
| 978 | luaL_Buffer b; | ||
| 979 | luaL_buffinit(L, &b); | ||
| 980 | luaL_addgsub(&b, s, p, r); | ||
| 1003 | luaL_pushresult(&b); | 981 | luaL_pushresult(&b); |
| 1004 | return lua_tostring(L, -1); | 982 | return lua_tostring(L, -1); |
| 1005 | } | 983 | } |
| @@ -1017,27 +995,63 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { | |||
| 1017 | 995 | ||
| 1018 | 996 | ||
| 1019 | static int panic (lua_State *L) { | 997 | static int panic (lua_State *L) { |
| 998 | const char *msg = lua_tostring(L, -1); | ||
| 999 | if (msg == NULL) msg = "error object is not a string"; | ||
| 1020 | lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", | 1000 | lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", |
| 1021 | lua_tostring(L, -1)); | 1001 | msg); |
| 1022 | return 0; /* return to Lua to abort */ | 1002 | return 0; /* return to Lua to abort */ |
| 1023 | } | 1003 | } |
| 1024 | 1004 | ||
| 1025 | 1005 | ||
| 1006 | /* | ||
| 1007 | ** Emit a warning. '*warnstate' means: | ||
| 1008 | ** 0 - warning system is off; | ||
| 1009 | ** 1 - ready to start a new message; | ||
| 1010 | ** 2 - previous message is to be continued. | ||
| 1011 | */ | ||
| 1012 | static void warnf (void *ud, const char *message, int tocont) { | ||
| 1013 | int *warnstate = (int *)ud; | ||
| 1014 | if (*warnstate != 2 && !tocont && *message == '@') { /* control message? */ | ||
| 1015 | if (strcmp(message, "@off") == 0) | ||
| 1016 | *warnstate = 0; | ||
| 1017 | else if (strcmp(message, "@on") == 0) | ||
| 1018 | *warnstate = 1; | ||
| 1019 | return; | ||
| 1020 | } | ||
| 1021 | else if (*warnstate == 0) /* warnings off? */ | ||
| 1022 | return; | ||
| 1023 | if (*warnstate == 1) /* previous message was the last? */ | ||
| 1024 | lua_writestringerror("%s", "Lua warning: "); /* start a new warning */ | ||
| 1025 | lua_writestringerror("%s", message); /* write message */ | ||
| 1026 | if (tocont) /* not the last part? */ | ||
| 1027 | *warnstate = 2; /* to be continued */ | ||
| 1028 | else { /* last part */ | ||
| 1029 | lua_writestringerror("%s", "\n"); /* finish message with end-of-line */ | ||
| 1030 | *warnstate = 1; /* ready to start a new message */ | ||
| 1031 | } | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | |||
| 1026 | LUALIB_API lua_State *luaL_newstate (void) { | 1035 | LUALIB_API lua_State *luaL_newstate (void) { |
| 1027 | lua_State *L = lua_newstate(l_alloc, NULL); | 1036 | lua_State *L = lua_newstate(l_alloc, NULL); |
| 1028 | if (L) lua_atpanic(L, &panic); | 1037 | if (L) { |
| 1038 | int *warnstate; /* space for warning state */ | ||
| 1039 | lua_atpanic(L, &panic); | ||
| 1040 | warnstate = (int *)lua_newuserdatauv(L, sizeof(int), 0); | ||
| 1041 | luaL_ref(L, LUA_REGISTRYINDEX); /* make sure it won't be collected */ | ||
| 1042 | *warnstate = 0; /* default is warnings off */ | ||
| 1043 | lua_setwarnf(L, warnf, warnstate); | ||
| 1044 | } | ||
| 1029 | return L; | 1045 | return L; |
| 1030 | } | 1046 | } |
| 1031 | 1047 | ||
| 1032 | 1048 | ||
| 1033 | LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) { | 1049 | LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) { |
| 1034 | const lua_Number *v = lua_version(L); | 1050 | lua_Number v = lua_version(L); |
| 1035 | if (sz != LUAL_NUMSIZES) /* check numeric types */ | 1051 | if (sz != LUAL_NUMSIZES) /* check numeric types */ |
| 1036 | luaL_error(L, "core and library have incompatible numeric types"); | 1052 | luaL_error(L, "core and library have incompatible numeric types"); |
| 1037 | if (v != lua_version(NULL)) | 1053 | else if (v != ver) |
| 1038 | luaL_error(L, "multiple Lua VMs detected"); | ||
| 1039 | else if (*v != ver) | ||
| 1040 | luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", | 1054 | luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", |
| 1041 | (LUAI_UACNUMBER)ver, (LUAI_UACNUMBER)*v); | 1055 | (LUAI_UACNUMBER)ver, (LUAI_UACNUMBER)v); |
| 1042 | } | 1056 | } |
| 1043 | 1057 | ||
