diff --git a/Lua/auxiliar.c b/Lua/auxiliar.c index 5251549..38b18b8 100644 --- a/Lua/auxiliar.c +++ b/Lua/auxiliar.c @@ -13,146 +13,163 @@ /*-------------------------------------------------------------------------*\ * Initializes the module \*-------------------------------------------------------------------------*/ -int auxiliar_open(lua_State *L) { - (void) L; - return 0; +int auxiliar_open(lua_State* L) +{ + (void)L; + return 0; } /*-------------------------------------------------------------------------*\ * Creates a new class with given methods * Methods whose names start with __ are passed directly to the metatable. \*-------------------------------------------------------------------------*/ -void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func) { - luaL_newmetatable(L, classname); /* mt */ - /* create __index table to place methods */ - lua_pushstring(L, "__index"); /* mt,"__index" */ - lua_newtable(L); /* mt,"__index",it */ - /* put class name into class metatable */ - lua_pushstring(L, "class"); /* mt,"__index",it,"class" */ - lua_pushstring(L, classname); /* mt,"__index",it,"class",classname */ - lua_rawset(L, -3); /* mt,"__index",it */ - /* pass all methods that start with _ to the metatable, and all others - * to the index table */ - for (; func->name; func++) { /* mt,"__index",it */ - lua_pushstring(L, func->name); - lua_pushcfunction(L, func->func); - lua_rawset(L, func->name[0] == '_' ? -5: -3); - } - lua_rawset(L, -3); /* mt */ - lua_pop(L, 1); +void auxiliar_newclass(lua_State* L, const char* classname, luaL_Reg* func) +{ + luaL_newmetatable(L, classname); /* mt */ + /* create __index table to place methods */ + lua_pushstring(L, "__index"); /* mt,"__index" */ + lua_newtable(L); /* mt,"__index",it */ + /* put class name into class metatable */ + lua_pushstring(L, "class"); /* mt,"__index",it,"class" */ + lua_pushstring(L, classname); /* mt,"__index",it,"class",classname */ + lua_rawset(L, -3); /* mt,"__index",it */ + /* pass all methods that start with _ to the metatable, and all others + * to the index table */ + for (; func->name; func++) + { + /* mt,"__index",it */ + lua_pushstring(L, func->name); + lua_pushcfunction(L, func->func); + lua_rawset(L, func->name[0] == '_' ? -5 : -3); + } + lua_rawset(L, -3); /* mt */ + lua_pop(L, 1); } /*-------------------------------------------------------------------------*\ * Prints the value of a class in a nice way \*-------------------------------------------------------------------------*/ -int auxiliar_tostring(lua_State *L) { - char buf[32]; - if (!lua_getmetatable(L, 1)) goto error; - lua_pushstring(L, "__index"); - lua_gettable(L, -2); - if (!lua_istable(L, -1)) goto error; - lua_pushstring(L, "class"); - lua_gettable(L, -2); - if (!lua_isstring(L, -1)) goto error; - sprintf(buf, "%p", lua_touserdata(L, 1)); - lua_pushfstring(L, "%s: %s", lua_tostring(L, -1), buf); - return 1; +int auxiliar_tostring(lua_State* L) +{ + char buf[32]; + if (!lua_getmetatable(L, 1)) goto error; + lua_pushstring(L, "__index"); + lua_gettable(L, -2); + if (!lua_istable(L, -1)) goto error; + lua_pushstring(L, "class"); + lua_gettable(L, -2); + if (!lua_isstring(L, -1)) goto error; + sprintf(buf, "%p", lua_touserdata(L, 1)); + lua_pushfstring(L, "%s: %s", lua_tostring(L, -1), buf); + return 1; error: - lua_pushstring(L, "invalid object passed to 'auxiliar.c:__tostring'"); - lua_error(L); - return 1; + lua_pushstring(L, "invalid object passed to 'auxiliar.c:__tostring'"); + lua_error(L); + return 1; } /*-------------------------------------------------------------------------*\ * Insert class into group \*-------------------------------------------------------------------------*/ -void auxiliar_add2group(lua_State *L, const char *classname, const char *groupname) { - luaL_getmetatable(L, classname); - lua_pushstring(L, groupname); - lua_pushboolean(L, 1); - lua_rawset(L, -3); - lua_pop(L, 1); +void auxiliar_add2group(lua_State* L, const char* classname, const char* groupname) +{ + luaL_getmetatable(L, classname); + lua_pushstring(L, groupname); + lua_pushboolean(L, 1); + lua_rawset(L, -3); + lua_pop(L, 1); } /*-------------------------------------------------------------------------*\ * Make sure argument is a boolean \*-------------------------------------------------------------------------*/ -int auxiliar_checkboolean(lua_State *L, int objidx) { - if (!lua_isboolean(L, objidx)) - auxiliar_typeerror(L, objidx, lua_typename(L, LUA_TBOOLEAN)); - return lua_toboolean(L, objidx); +int auxiliar_checkboolean(lua_State* L, int objidx) +{ + if (!lua_isboolean(L, objidx)) + auxiliar_typeerror(L, objidx, lua_typename(L, LUA_TBOOLEAN)); + return lua_toboolean(L, objidx); } /*-------------------------------------------------------------------------*\ * Return userdata pointer if object belongs to a given class, abort with * error otherwise \*-------------------------------------------------------------------------*/ -void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx) { - void *data = auxiliar_getclassudata(L, classname, objidx); - if (!data) { - char msg[45]; - sprintf(msg, "%.35s expected", classname); - luaL_argerror(L, objidx, msg); - } - return data; +void* auxiliar_checkclass(lua_State* L, const char* classname, int objidx) +{ + void* data = auxiliar_getclassudata(L, classname, objidx); + if (!data) + { + char msg[45]; + sprintf(msg, "%.35s expected", classname); + luaL_argerror(L, objidx, msg); + } + return data; } /*-------------------------------------------------------------------------*\ * Return userdata pointer if object belongs to a given group, abort with * error otherwise \*-------------------------------------------------------------------------*/ -void *auxiliar_checkgroup(lua_State *L, const char *groupname, int objidx) { - void *data = auxiliar_getgroupudata(L, groupname, objidx); - if (!data) { - char msg[45]; - sprintf(msg, "%.35s expected", groupname); - luaL_argerror(L, objidx, msg); - } - return data; +void* auxiliar_checkgroup(lua_State* L, const char* groupname, int objidx) +{ + void* data = auxiliar_getgroupudata(L, groupname, objidx); + if (!data) + { + char msg[45]; + sprintf(msg, "%.35s expected", groupname); + luaL_argerror(L, objidx, msg); + } + return data; } /*-------------------------------------------------------------------------*\ * Set object class \*-------------------------------------------------------------------------*/ -void auxiliar_setclass(lua_State *L, const char *classname, int objidx) { - luaL_getmetatable(L, classname); - if (objidx < 0) objidx--; - lua_setmetatable(L, objidx); +void auxiliar_setclass(lua_State* L, const char* classname, int objidx) +{ + luaL_getmetatable(L, classname); + if (objidx < 0) objidx--; + lua_setmetatable(L, objidx); } /*-------------------------------------------------------------------------*\ * Get a userdata pointer if object belongs to a given group. Return NULL * otherwise \*-------------------------------------------------------------------------*/ -void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx) { - if (!lua_getmetatable(L, objidx)) - return NULL; - lua_pushstring(L, groupname); - lua_rawget(L, -2); - if (lua_isnil(L, -1)) { - lua_pop(L, 2); - return NULL; - } else { - lua_pop(L, 2); - return lua_touserdata(L, objidx); - } +void* auxiliar_getgroupudata(lua_State* L, const char* groupname, int objidx) +{ + if (!lua_getmetatable(L, objidx)) + return NULL; + lua_pushstring(L, groupname); + lua_rawget(L, -2); + if (lua_isnil(L, -1)) + { + lua_pop(L, 2); + return NULL; + } + else + { + lua_pop(L, 2); + return lua_touserdata(L, objidx); + } } /*-------------------------------------------------------------------------*\ * Get a userdata pointer if object belongs to a given class. Return NULL * otherwise \*-------------------------------------------------------------------------*/ -void *auxiliar_getclassudata(lua_State *L, const char *classname, int objidx) { - return luaL_testudata(L, objidx, classname); +void* auxiliar_getclassudata(lua_State* L, const char* classname, int objidx) +{ + return luaL_testudata(L, objidx, classname); } /*-------------------------------------------------------------------------*\ * Throws error when argument does not have correct type. * Used to be part of lauxlib in Lua 5.1, was dropped from 5.2. \*-------------------------------------------------------------------------*/ -int auxiliar_typeerror (lua_State *L, int narg, const char *tname) { - const char *msg = lua_pushfstring(L, "%s expected, got %s", tname, - luaL_typename(L, narg)); - return luaL_argerror(L, narg, msg); +int auxiliar_typeerror(lua_State* L, int narg, const char* tname) +{ + const char* msg = lua_pushfstring(L, "%s expected, got %s", tname, + luaL_typename(L, narg)); + return luaL_argerror(L, narg, msg); } - diff --git a/Lua/auxiliar.h b/Lua/auxiliar.h index 65511d4..5a1b522 100644 --- a/Lua/auxiliar.h +++ b/Lua/auxiliar.h @@ -33,16 +33,16 @@ #include "lauxlib.h" #include "compat.h" -int auxiliar_open(lua_State *L); -void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func); -void auxiliar_add2group(lua_State *L, const char *classname, const char *group); -void auxiliar_setclass(lua_State *L, const char *classname, int objidx); -void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx); -void *auxiliar_checkgroup(lua_State *L, const char *groupname, int objidx); -void *auxiliar_getclassudata(lua_State *L, const char *groupname, int objidx); -void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx); -int auxiliar_checkboolean(lua_State *L, int objidx); -int auxiliar_tostring(lua_State *L); -int auxiliar_typeerror(lua_State *L, int narg, const char *tname); +int auxiliar_open(lua_State* L); +void auxiliar_newclass(lua_State* L, const char* classname, luaL_Reg* func); +void auxiliar_add2group(lua_State* L, const char* classname, const char* group); +void auxiliar_setclass(lua_State* L, const char* classname, int objidx); +void* auxiliar_checkclass(lua_State* L, const char* classname, int objidx); +void* auxiliar_checkgroup(lua_State* L, const char* groupname, int objidx); +void* auxiliar_getclassudata(lua_State* L, const char* groupname, int objidx); +void* auxiliar_getgroupudata(lua_State* L, const char* groupname, int objidx); +int auxiliar_checkboolean(lua_State* L, int objidx); +int auxiliar_tostring(lua_State* L); +int auxiliar_typeerror(lua_State* L, int narg, const char* tname); #endif /* AUXILIAR_H */ diff --git a/Lua/buffer.c b/Lua/buffer.c index fff1634..4498e93 100644 --- a/Lua/buffer.c +++ b/Lua/buffer.c @@ -11,12 +11,12 @@ /*=========================================================================*\ * Internal function prototypes \*=========================================================================*/ -static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b); -static int recvline(p_buffer buf, luaL_Buffer *b); -static int recvall(p_buffer buf, luaL_Buffer *b); -static int buffer_get(p_buffer buf, const char **data, size_t *count); +static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer* b); +static int recvline(p_buffer buf, luaL_Buffer* b); +static int recvall(p_buffer buf, luaL_Buffer* b); +static int buffer_get(p_buffer buf, const char** data, size_t* count); static void buffer_skip(p_buffer buf, size_t count); -static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent); +static int sendraw(p_buffer buf, const char* data, size_t count, size_t* sent); /* min and max macros */ #ifndef MIN @@ -32,130 +32,147 @@ static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent); /*-------------------------------------------------------------------------*\ * Initializes module \*-------------------------------------------------------------------------*/ -int buffer_open(lua_State *L) { - (void) L; - return 0; +int buffer_open(lua_State* L) +{ + (void)L; + return 0; } /*-------------------------------------------------------------------------*\ * Initializes C structure \*-------------------------------------------------------------------------*/ -void buffer_init(p_buffer buf, p_io io, p_timeout tm) { - buf->first = buf->last = 0; - buf->io = io; - buf->tm = tm; - buf->received = buf->sent = 0; - buf->birthday = timeout_gettime(); +void buffer_init(p_buffer buf, p_io io, p_timeout tm) +{ + buf->first = buf->last = 0; + buf->io = io; + buf->tm = tm; + buf->received = buf->sent = 0; + buf->birthday = timeout_gettime(); } /*-------------------------------------------------------------------------*\ * object:getstats() interface \*-------------------------------------------------------------------------*/ -int buffer_meth_getstats(lua_State *L, p_buffer buf) { - lua_pushnumber(L, (lua_Number) buf->received); - lua_pushnumber(L, (lua_Number) buf->sent); - lua_pushnumber(L, timeout_gettime() - buf->birthday); - return 3; +int buffer_meth_getstats(lua_State* L, p_buffer buf) +{ + lua_pushnumber(L, (lua_Number)buf->received); + lua_pushnumber(L, (lua_Number)buf->sent); + lua_pushnumber(L, timeout_gettime() - buf->birthday); + return 3; } /*-------------------------------------------------------------------------*\ * object:setstats() interface \*-------------------------------------------------------------------------*/ -int buffer_meth_setstats(lua_State *L, p_buffer buf) { - buf->received = (long) luaL_optnumber(L, 2, (lua_Number) buf->received); - buf->sent = (long) luaL_optnumber(L, 3, (lua_Number) buf->sent); - if (lua_isnumber(L, 4)) buf->birthday = timeout_gettime() - lua_tonumber(L, 4); - lua_pushnumber(L, 1); - return 1; +int buffer_meth_setstats(lua_State* L, p_buffer buf) +{ + buf->received = (long)luaL_optnumber(L, 2, (lua_Number)buf->received); + buf->sent = (long)luaL_optnumber(L, 3, (lua_Number)buf->sent); + if (lua_isnumber(L, 4)) buf->birthday = timeout_gettime() - lua_tonumber(L, 4); + lua_pushnumber(L, 1); + return 1; } /*-------------------------------------------------------------------------*\ * object:send() interface \*-------------------------------------------------------------------------*/ -int buffer_meth_send(lua_State *L, p_buffer buf) { - int top = lua_gettop(L); - int err = IO_DONE; - size_t size = 0, sent = 0; - const char *data = luaL_checklstring(L, 2, &size); - long start = (long) luaL_optnumber(L, 3, 1); - long end = (long) luaL_optnumber(L, 4, -1); - timeout_markstart(buf->tm); - if (start < 0) start = (long) (size+start+1); - if (end < 0) end = (long) (size+end+1); - if (start < 1) start = (long) 1; - if (end > (long) size) end = (long) size; - if (start <= end) err = sendraw(buf, data+start-1, end-start+1, &sent); - /* check if there was an error */ - if (err != IO_DONE) { - lua_pushnil(L); - lua_pushstring(L, buf->io->error(buf->io->ctx, err)); - lua_pushnumber(L, (lua_Number) (sent+start-1)); - } else { - lua_pushnumber(L, (lua_Number) (sent+start-1)); - lua_pushnil(L); - lua_pushnil(L); - } +int buffer_meth_send(lua_State* L, p_buffer buf) +{ + int top = lua_gettop(L); + int err = IO_DONE; + size_t size = 0, sent = 0; + const char* data = luaL_checklstring(L, 2, &size); + long start = (long)luaL_optnumber(L, 3, 1); + long end = (long)luaL_optnumber(L, 4, -1); + timeout_markstart(buf->tm); + if (start < 0) start = (long)(size + start + 1); + if (end < 0) end = (long)(size + end + 1); + if (start < 1) start = (long)1; + if (end > (long)size) end = (long)size; + if (start <= end) err = sendraw(buf, data + start - 1, end - start + 1, &sent); + /* check if there was an error */ + if (err != IO_DONE) + { + lua_pushnil(L); + lua_pushstring(L, buf->io->error(buf->io->ctx, err)); + lua_pushnumber(L, (lua_Number)(sent + start - 1)); + } + else + { + lua_pushnumber(L, (lua_Number)(sent + start - 1)); + lua_pushnil(L); + lua_pushnil(L); + } #ifdef LUASOCKET_DEBUG /* push time elapsed during operation as the last return value */ lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm)); #endif - return lua_gettop(L) - top; + return lua_gettop(L) - top; } /*-------------------------------------------------------------------------*\ * object:receive() interface \*-------------------------------------------------------------------------*/ -int buffer_meth_receive(lua_State *L, p_buffer buf) { - int err = IO_DONE, top = lua_gettop(L); - luaL_Buffer b; - size_t size; - const char *part = luaL_optlstring(L, 3, "", &size); - timeout_markstart(buf->tm); - /* initialize buffer with optional extra prefix - * (useful for concatenating previous partial results) */ - luaL_buffinit(L, &b); - luaL_addlstring(&b, part, size); - /* receive new patterns */ - if (!lua_isnumber(L, 2)) { - const char *p= luaL_optstring(L, 2, "*l"); - if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b); - else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b); - else luaL_argcheck(L, 0, 2, "invalid receive pattern"); - /* get a fixed number of bytes (minus what was already partially - * received) */ - } else { - double n = lua_tonumber(L, 2); - size_t wanted = (size_t) n; - luaL_argcheck(L, n >= 0, 2, "invalid receive pattern"); - if (size == 0 || wanted > size) - err = recvraw(buf, wanted-size, &b); - } - /* check if there was an error */ - if (err != IO_DONE) { - /* we can't push anyting in the stack before pushing the - * contents of the buffer. this is the reason for the complication */ - luaL_pushresult(&b); - lua_pushstring(L, buf->io->error(buf->io->ctx, err)); - lua_pushvalue(L, -2); - lua_pushnil(L); - lua_replace(L, -4); - } else { - luaL_pushresult(&b); - lua_pushnil(L); - lua_pushnil(L); - } +int buffer_meth_receive(lua_State* L, p_buffer buf) +{ + int err = IO_DONE, top = lua_gettop(L); + luaL_Buffer b; + size_t size; + const char* part = luaL_optlstring(L, 3, "", &size); + timeout_markstart(buf->tm); + /* initialize buffer with optional extra prefix + * (useful for concatenating previous partial results) */ + luaL_buffinit(L, &b); + luaL_addlstring(&b, part, size); + /* receive new patterns */ + if (!lua_isnumber(L, 2)) + { + const char* p = luaL_optstring(L, 2, "*l"); + if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b); + else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b); + else + luaL_argcheck(L, 0, 2, "invalid receive pattern"); + /* get a fixed number of bytes (minus what was already partially + * received) */ + } + else + { + double n = lua_tonumber(L, 2); + size_t wanted = (size_t)n; + luaL_argcheck(L, n >= 0, 2, "invalid receive pattern"); + if (size == 0 || wanted > size) + err = recvraw(buf, wanted - size, &b); + } + /* check if there was an error */ + if (err != IO_DONE) + { + /* we can't push anyting in the stack before pushing the + * contents of the buffer. this is the reason for the complication */ + luaL_pushresult(&b); + lua_pushstring(L, buf->io->error(buf->io->ctx, err)); + lua_pushvalue(L, -2); + lua_pushnil(L); + lua_replace(L, -4); + } + else + { + luaL_pushresult(&b); + lua_pushnil(L); + lua_pushnil(L); + } #ifdef LUASOCKET_DEBUG /* push time elapsed during operation as the last return value */ lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm)); #endif - return lua_gettop(L) - top; + return lua_gettop(L) - top; } /*-------------------------------------------------------------------------*\ * Determines if there is any data in the read buffer \*-------------------------------------------------------------------------*/ -int buffer_isempty(p_buffer buf) { - return buf->first >= buf->last; +int buffer_isempty(p_buffer buf) +{ + return buf->first >= buf->last; } /*=========================================================================*\ @@ -165,109 +182,131 @@ int buffer_isempty(p_buffer buf) { * Sends a block of data (unbuffered) \*-------------------------------------------------------------------------*/ #define STEPSIZE 8192 -static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent) { - p_io io = buf->io; - p_timeout tm = buf->tm; - size_t total = 0; - int err = IO_DONE; - while (total < count && err == IO_DONE) { - size_t done = 0; - size_t step = (count-total <= STEPSIZE)? count-total: STEPSIZE; - err = io->send(io->ctx, data+total, step, &done, tm); - total += done; - } - *sent = total; - buf->sent += total; - return err; + +static int sendraw(p_buffer buf, const char* data, size_t count, size_t* sent) +{ + p_io io = buf->io; + p_timeout tm = buf->tm; + size_t total = 0; + int err = IO_DONE; + while (total < count && err == IO_DONE) + { + size_t done = 0; + size_t step = (count - total <= STEPSIZE) ? count - total : STEPSIZE; + err = io->send(io->ctx, data + total, step, &done, tm); + total += done; + } + *sent = total; + buf->sent += total; + return err; } /*-------------------------------------------------------------------------*\ * Reads a fixed number of bytes (buffered) \*-------------------------------------------------------------------------*/ -static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b) { - int err = IO_DONE; - size_t total = 0; - while (err == IO_DONE) { - size_t count; const char *data; - err = buffer_get(buf, &data, &count); - count = MIN(count, wanted - total); - luaL_addlstring(b, data, count); - buffer_skip(buf, count); - total += count; - if (total >= wanted) break; - } - return err; +static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer* b) +{ + int err = IO_DONE; + size_t total = 0; + while (err == IO_DONE) + { + size_t count; + const char* data; + err = buffer_get(buf, &data, &count); + count = MIN(count, wanted - total); + luaL_addlstring(b, data, count); + buffer_skip(buf, count); + total += count; + if (total >= wanted) break; + } + return err; } /*-------------------------------------------------------------------------*\ * Reads everything until the connection is closed (buffered) \*-------------------------------------------------------------------------*/ -static int recvall(p_buffer buf, luaL_Buffer *b) { - int err = IO_DONE; - size_t total = 0; - while (err == IO_DONE) { - const char *data; size_t count; - err = buffer_get(buf, &data, &count); - total += count; - luaL_addlstring(b, data, count); - buffer_skip(buf, count); - } - if (err == IO_CLOSED) { - if (total > 0) return IO_DONE; - else return IO_CLOSED; - } else return err; +static int recvall(p_buffer buf, luaL_Buffer* b) +{ + int err = IO_DONE; + size_t total = 0; + while (err == IO_DONE) + { + const char* data; + size_t count; + err = buffer_get(buf, &data, &count); + total += count; + luaL_addlstring(b, data, count); + buffer_skip(buf, count); + } + if (err == IO_CLOSED) + { + if (total > 0) return IO_DONE; + else return IO_CLOSED; + } + else return err; } /*-------------------------------------------------------------------------*\ * Reads a line terminated by a CR LF pair or just by a LF. The CR and LF * are not returned by the function and are discarded from the buffer \*-------------------------------------------------------------------------*/ -static int recvline(p_buffer buf, luaL_Buffer *b) { - int err = IO_DONE; - while (err == IO_DONE) { - size_t count, pos; const char *data; - err = buffer_get(buf, &data, &count); - pos = 0; - while (pos < count && data[pos] != '\n') { - /* we ignore all \r's */ - if (data[pos] != '\r') luaL_addchar(b, data[pos]); - pos++; - } - if (pos < count) { /* found '\n' */ - buffer_skip(buf, pos+1); /* skip '\n' too */ - break; /* we are done */ - } else /* reached the end of the buffer */ - buffer_skip(buf, pos); - } - return err; +static int recvline(p_buffer buf, luaL_Buffer* b) +{ + int err = IO_DONE; + while (err == IO_DONE) + { + size_t count, pos; + const char* data; + err = buffer_get(buf, &data, &count); + pos = 0; + while (pos < count && data[pos] != '\n') + { + /* we ignore all \r's */ + if (data[pos] != '\r') + luaL_addchar(b, data[pos]); + pos++; + } + if (pos < count) + { + /* found '\n' */ + buffer_skip(buf, pos + 1); /* skip '\n' too */ + break; /* we are done */ + } + else /* reached the end of the buffer */ + buffer_skip(buf, pos); + } + return err; } /*-------------------------------------------------------------------------*\ * Skips a given number of bytes from read buffer. No data is read from the * transport layer \*-------------------------------------------------------------------------*/ -static void buffer_skip(p_buffer buf, size_t count) { - buf->received += count; - buf->first += count; - if (buffer_isempty(buf)) - buf->first = buf->last = 0; +static void buffer_skip(p_buffer buf, size_t count) +{ + buf->received += count; + buf->first += count; + if (buffer_isempty(buf)) + buf->first = buf->last = 0; } /*-------------------------------------------------------------------------*\ * Return any data available in buffer, or get more data from transport layer * if buffer is empty \*-------------------------------------------------------------------------*/ -static int buffer_get(p_buffer buf, const char **data, size_t *count) { - int err = IO_DONE; - p_io io = buf->io; - p_timeout tm = buf->tm; - if (buffer_isempty(buf)) { - size_t got; - err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm); - buf->first = 0; - buf->last = got; - } - *count = buf->last - buf->first; - *data = buf->data + buf->first; - return err; +static int buffer_get(p_buffer buf, const char** data, size_t* count) +{ + int err = IO_DONE; + p_io io = buf->io; + p_timeout tm = buf->tm; + if (buffer_isempty(buf)) + { + size_t got; + err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm); + buf->first = 0; + buf->last = got; + } + *count = buf->last - buf->first; + *data = buf->data + buf->first; + return err; } diff --git a/Lua/buffer.h b/Lua/buffer.h index 1281bb3..4e3d525 100644 --- a/Lua/buffer.h +++ b/Lua/buffer.h @@ -24,22 +24,24 @@ #define BUF_SIZE 8192 /* buffer control structure */ -typedef struct t_buffer_ { - double birthday; /* throttle support info: creation time, */ - size_t sent, received; /* bytes sent, and bytes received */ - p_io io; /* IO driver used for this buffer */ - p_timeout tm; /* timeout management for this buffer */ - size_t first, last; /* index of first and last bytes of stored data */ - char data[BUF_SIZE]; /* storage space for buffer data */ +typedef struct t_buffer_ +{ + double birthday; /* throttle support info: creation time, */ + size_t sent, received; /* bytes sent, and bytes received */ + p_io io; /* IO driver used for this buffer */ + p_timeout tm; /* timeout management for this buffer */ + size_t first, last; /* index of first and last bytes of stored data */ + char data[BUF_SIZE]; /* storage space for buffer data */ } t_buffer; -typedef t_buffer *p_buffer; -int buffer_open(lua_State *L); +typedef t_buffer* p_buffer; + +int buffer_open(lua_State* L); void buffer_init(p_buffer buf, p_io io, p_timeout tm); -int buffer_meth_send(lua_State *L, p_buffer buf); -int buffer_meth_receive(lua_State *L, p_buffer buf); -int buffer_meth_getstats(lua_State *L, p_buffer buf); -int buffer_meth_setstats(lua_State *L, p_buffer buf); +int buffer_meth_send(lua_State* L, p_buffer buf); +int buffer_meth_receive(lua_State* L, p_buffer buf); +int buffer_meth_getstats(lua_State* L, p_buffer buf); +int buffer_meth_setstats(lua_State* L, p_buffer buf); int buffer_isempty(p_buffer buf); #endif /* BUF_H */ diff --git a/Lua/except.c b/Lua/except.c index 60b5005..80769ac 100644 --- a/Lua/except.c +++ b/Lua/except.c @@ -22,77 +22,90 @@ typedef int lua_KContext; /*=========================================================================*\ * Internal function prototypes. \*=========================================================================*/ -static int global_protect(lua_State *L); -static int global_newtry(lua_State *L); -static int protected_(lua_State *L); -static int finalize(lua_State *L); -static int do_nothing(lua_State *L); +static int global_protect(lua_State* L); +static int global_newtry(lua_State* L); +static int protected_(lua_State* L); +static int finalize(lua_State* L); +static int do_nothing(lua_State* L); /* except functions */ static luaL_Reg func[] = { - {"newtry", global_newtry}, - {"protect", global_protect}, - {NULL, NULL} + {"newtry", global_newtry}, + {"protect", global_protect}, + {NULL, NULL} }; /*-------------------------------------------------------------------------*\ * Try factory \*-------------------------------------------------------------------------*/ -static void wrap(lua_State *L) { - lua_createtable(L, 1, 0); - lua_pushvalue(L, -2); - lua_rawseti(L, -2, 1); - lua_pushvalue(L, lua_upvalueindex(1)); - lua_setmetatable(L, -2); +static void wrap(lua_State* L) +{ + lua_createtable(L, 1, 0); + lua_pushvalue(L, -2); + lua_rawseti(L, -2, 1); + lua_pushvalue(L, lua_upvalueindex(1)); + lua_setmetatable(L, -2); } -static int finalize(lua_State *L) { - if (!lua_toboolean(L, 1)) { - lua_pushvalue(L, lua_upvalueindex(2)); - lua_call(L, 0, 0); - lua_settop(L, 2); - wrap(L); - lua_error(L); - return 0; - } else return lua_gettop(L); +static int finalize(lua_State* L) +{ + if (!lua_toboolean(L, 1)) + { + lua_pushvalue(L, lua_upvalueindex(2)); + lua_call(L, 0, 0); + lua_settop(L, 2); + wrap(L); + lua_error(L); + return 0; + } + else return lua_gettop(L); } -static int do_nothing(lua_State *L) { - (void) L; - return 0; +static int do_nothing(lua_State* L) +{ + (void)L; + return 0; } -static int global_newtry(lua_State *L) { - lua_settop(L, 1); - if (lua_isnil(L, 1)) lua_pushcfunction(L, do_nothing); - lua_pushvalue(L, lua_upvalueindex(1)); - lua_insert(L, -2); - lua_pushcclosure(L, finalize, 2); - return 1; +static int global_newtry(lua_State* L) +{ + lua_settop(L, 1); + if (lua_isnil(L, 1)) + lua_pushcfunction(L, do_nothing); + lua_pushvalue(L, lua_upvalueindex(1)); + lua_insert(L, -2); + lua_pushcclosure(L, finalize, 2); + return 1; } /*-------------------------------------------------------------------------*\ * Protect factory \*-------------------------------------------------------------------------*/ -static int unwrap(lua_State *L) { - if (lua_istable(L, -1) && lua_getmetatable(L, -1)) { - int r = lua_rawequal(L, -1, lua_upvalueindex(1)); - lua_pop(L, 1); - if (r) { - lua_pushnil(L); - lua_rawgeti(L, -2, 1); - return 1; - } - } - return 0; +static int unwrap(lua_State* L) +{ + if (lua_istable(L, -1) && lua_getmetatable(L, -1)) + { + int r = lua_rawequal(L, -1, lua_upvalueindex(1)); + lua_pop(L, 1); + if (r) + { + lua_pushnil(L); + lua_rawgeti(L, -2, 1); + return 1; + } + } + return 0; } -static int protected_finish(lua_State *L, int status, lua_KContext ctx) { - (void)ctx; - if (status != 0 && status != LUA_YIELD) { - if (unwrap(L)) return 2; - else return lua_error(L); - } else return lua_gettop(L); +static int protected_finish(lua_State* L, int status, lua_KContext ctx) +{ + (void)ctx; + if (status != 0 && status != LUA_YIELD) + { + if (unwrap(L)) return 2; + else return lua_error(L); + } + else return lua_gettop(L); } #if LUA_VERSION_NUM == 502 @@ -105,29 +118,32 @@ static int protected_cont(lua_State *L) { #define protected_cont protected_finish #endif -static int protected_(lua_State *L) { - int status; - lua_pushvalue(L, lua_upvalueindex(2)); - lua_insert(L, 1); - status = lua_pcallk(L, lua_gettop(L) - 1, LUA_MULTRET, 0, 0, protected_cont); - return protected_finish(L, status, 0); +static int protected_(lua_State* L) +{ + int status; + lua_pushvalue(L, lua_upvalueindex(2)); + lua_insert(L, 1); + status = lua_pcallk(L, lua_gettop(L) - 1, LUA_MULTRET, 0, 0, protected_cont); + return protected_finish(L, status, 0); } -static int global_protect(lua_State *L) { - lua_settop(L, 1); - lua_pushvalue(L, lua_upvalueindex(1)); - lua_insert(L, 1); - lua_pushcclosure(L, protected_, 2); - return 1; +static int global_protect(lua_State* L) +{ + lua_settop(L, 1); + lua_pushvalue(L, lua_upvalueindex(1)); + lua_insert(L, 1); + lua_pushcclosure(L, protected_, 2); + return 1; } /*-------------------------------------------------------------------------*\ * Init module \*-------------------------------------------------------------------------*/ -int except_open(lua_State *L) { - lua_newtable(L); /* metatable for wrapped exceptions */ - lua_pushboolean(L, 0); - lua_setfield(L, -2, "__metatable"); - luaL_setfuncs(L, func, 1); - return 0; +int except_open(lua_State* L) +{ + lua_newtable(L); /* metatable for wrapped exceptions */ + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + luaL_setfuncs(L, func, 1); + return 0; } diff --git a/Lua/except.h b/Lua/except.h index 2497c05..29bceca 100644 --- a/Lua/except.h +++ b/Lua/except.h @@ -33,6 +33,6 @@ #include "lua.h" -int except_open(lua_State *L); +int except_open(lua_State* L); #endif diff --git a/Lua/inet.c b/Lua/inet.c index 84d0ebd..65a427c 100644 --- a/Lua/inet.c +++ b/Lua/inet.c @@ -15,21 +15,21 @@ /*=========================================================================*\ * Internal function prototypes. \*=========================================================================*/ -static int inet_global_toip(lua_State *L); -static int inet_global_getaddrinfo(lua_State *L); -static int inet_global_tohostname(lua_State *L); -static int inet_global_getnameinfo(lua_State *L); -static void inet_pushresolved(lua_State *L, struct hostent *hp); -static int inet_global_gethostname(lua_State *L); +static int inet_global_toip(lua_State* L); +static int inet_global_getaddrinfo(lua_State* L); +static int inet_global_tohostname(lua_State* L); +static int inet_global_getnameinfo(lua_State* L); +static void inet_pushresolved(lua_State* L, struct hostent* hp); +static int inet_global_gethostname(lua_State* L); /* DNS functions */ static luaL_Reg func[] = { - { "toip", inet_global_toip}, - { "getaddrinfo", inet_global_getaddrinfo}, - { "tohostname", inet_global_tohostname}, - { "getnameinfo", inet_global_getnameinfo}, - { "gethostname", inet_global_gethostname}, - { NULL, NULL} + {"toip", inet_global_toip}, + {"getaddrinfo", inet_global_getaddrinfo}, + {"tohostname", inet_global_tohostname}, + {"getnameinfo", inet_global_getnameinfo}, + {"gethostname", inet_global_gethostname}, + {NULL, NULL} }; /*=========================================================================*\ @@ -38,13 +38,13 @@ static luaL_Reg func[] = { /*-------------------------------------------------------------------------*\ * Initializes module \*-------------------------------------------------------------------------*/ -int inet_open(lua_State *L) +int inet_open(lua_State* L) { - lua_pushstring(L, "dns"); - lua_newtable(L); - luaL_setfuncs(L, func, 0); - lua_settable(L, -3); - return 0; + lua_pushstring(L, "dns"); + lua_newtable(L); + luaL_setfuncs(L, func, 0); + lua_settable(L, -3); + return 0; } /*=========================================================================*\ @@ -54,186 +54,204 @@ int inet_open(lua_State *L) * Returns all information provided by the resolver given a host name * or ip address \*-------------------------------------------------------------------------*/ -static int inet_gethost(const char *address, struct hostent **hp) { - struct in_addr addr; - if (inet_aton(address, &addr)) - return socket_gethostbyaddr((char *) &addr, sizeof(addr), hp); - else - return socket_gethostbyname(address, hp); -} - -/*-------------------------------------------------------------------------*\ -* Returns all information provided by the resolver given a host name -* or ip address -\*-------------------------------------------------------------------------*/ -static int inet_global_tohostname(lua_State *L) { - const char *address = luaL_checkstring(L, 1); - struct hostent *hp = NULL; - int err = inet_gethost(address, &hp); - if (err != IO_DONE) { - lua_pushnil(L); - lua_pushstring(L, socket_hoststrerror(err)); - return 2; - } - lua_pushstring(L, hp->h_name); - inet_pushresolved(L, hp); - return 2; -} - -static int inet_global_getnameinfo(lua_State *L) { - char hbuf[NI_MAXHOST]; - char sbuf[NI_MAXSERV]; - int i, ret; - struct addrinfo hints; - struct addrinfo *resolved, *iter; - const char *host = luaL_optstring(L, 1, NULL); - const char *serv = luaL_optstring(L, 2, NULL); - - if (!(host || serv)) - luaL_error(L, "host and serv cannot be both nil"); - - memset(&hints, 0, sizeof(hints)); - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = AF_UNSPEC; - - ret = getaddrinfo(host, serv, &hints, &resolved); - if (ret != 0) { - lua_pushnil(L); - lua_pushstring(L, socket_gaistrerror(ret)); - return 2; - } - - lua_newtable(L); - for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) { - getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen, - hbuf, host? (socklen_t) sizeof(hbuf): 0, - sbuf, serv? (socklen_t) sizeof(sbuf): 0, 0); - if (host) { - lua_pushnumber(L, i); - lua_pushstring(L, hbuf); - lua_settable(L, -3); - } - } - freeaddrinfo(resolved); - - if (serv) { - lua_pushstring(L, sbuf); - return 2; - } else { - return 1; - } -} - -/*-------------------------------------------------------------------------*\ -* Returns all information provided by the resolver given a host name -* or ip address -\*-------------------------------------------------------------------------*/ -static int inet_global_toip(lua_State *L) +static int inet_gethost(const char* address, struct hostent** hp) { - const char *address = luaL_checkstring(L, 1); - struct hostent *hp = NULL; - int err = inet_gethost(address, &hp); - if (err != IO_DONE) { - lua_pushnil(L); - lua_pushstring(L, socket_hoststrerror(err)); - return 2; - } - lua_pushstring(L, inet_ntoa(*((struct in_addr *) hp->h_addr))); - inet_pushresolved(L, hp); - return 2; + struct in_addr addr; + if (inet_aton(address, &addr)) + return socket_gethostbyaddr((char*)&addr, sizeof(addr), hp); + else + return socket_gethostbyname(address, hp); +} + +/*-------------------------------------------------------------------------*\ +* Returns all information provided by the resolver given a host name +* or ip address +\*-------------------------------------------------------------------------*/ +static int inet_global_tohostname(lua_State* L) +{ + const char* address = luaL_checkstring(L, 1); + struct hostent* hp = NULL; + int err = inet_gethost(address, &hp); + if (err != IO_DONE) + { + lua_pushnil(L); + lua_pushstring(L, socket_hoststrerror(err)); + return 2; + } + lua_pushstring(L, hp->h_name); + inet_pushresolved(L, hp); + return 2; +} + +static int inet_global_getnameinfo(lua_State* L) +{ + char hbuf[NI_MAXHOST]; + char sbuf[NI_MAXSERV]; + int i, ret; + struct addrinfo hints; + struct addrinfo *resolved, *iter; + const char* host = luaL_optstring(L, 1, NULL); + const char* serv = luaL_optstring(L, 2, NULL); + + if (!(host || serv)) + luaL_error(L, "host and serv cannot be both nil"); + + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_UNSPEC; + + ret = getaddrinfo(host, serv, &hints, &resolved); + if (ret != 0) + { + lua_pushnil(L); + lua_pushstring(L, socket_gaistrerror(ret)); + return 2; + } + + lua_newtable(L); + for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) + { + getnameinfo(iter->ai_addr, (socklen_t)iter->ai_addrlen, + hbuf, host ? (socklen_t)sizeof(hbuf) : 0, + sbuf, serv ? (socklen_t)sizeof(sbuf) : 0, 0); + if (host) + { + lua_pushnumber(L, i); + lua_pushstring(L, hbuf); + lua_settable(L, -3); + } + } + freeaddrinfo(resolved); + + if (serv) + { + lua_pushstring(L, sbuf); + return 2; + } + else + { + return 1; + } +} + +/*-------------------------------------------------------------------------*\ +* Returns all information provided by the resolver given a host name +* or ip address +\*-------------------------------------------------------------------------*/ +static int inet_global_toip(lua_State* L) +{ + const char* address = luaL_checkstring(L, 1); + struct hostent* hp = NULL; + int err = inet_gethost(address, &hp); + if (err != IO_DONE) + { + lua_pushnil(L); + lua_pushstring(L, socket_hoststrerror(err)); + return 2; + } + lua_pushstring(L, inet_ntoa(*((struct in_addr*)hp->h_addr))); + inet_pushresolved(L, hp); + return 2; } int inet_optfamily(lua_State* L, int narg, const char* def) { - static const char* optname[] = { "unspec", "inet", "inet6", NULL }; - static int optvalue[] = { AF_UNSPEC, AF_INET, AF_INET6, 0 }; + static const char* optname[] = {"unspec", "inet", "inet6", NULL}; + static int optvalue[] = {AF_UNSPEC, AF_INET, AF_INET6, 0}; - return optvalue[luaL_checkoption(L, narg, def, optname)]; + return optvalue[luaL_checkoption(L, narg, def, optname)]; } int inet_optsocktype(lua_State* L, int narg, const char* def) { - static const char* optname[] = { "stream", "dgram", NULL }; - static int optvalue[] = { SOCK_STREAM, SOCK_DGRAM, 0 }; + static const char* optname[] = {"stream", "dgram", NULL}; + static int optvalue[] = {SOCK_STREAM, SOCK_DGRAM, 0}; - return optvalue[luaL_checkoption(L, narg, def, optname)]; + return optvalue[luaL_checkoption(L, narg, def, optname)]; } -static int inet_global_getaddrinfo(lua_State *L) +static int inet_global_getaddrinfo(lua_State* L) { - const char *hostname = luaL_checkstring(L, 1); - struct addrinfo *iterator = NULL, *resolved = NULL; - struct addrinfo hints; - int i = 1, ret = 0; - memset(&hints, 0, sizeof(hints)); - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = AF_UNSPEC; - ret = getaddrinfo(hostname, NULL, &hints, &resolved); - if (ret != 0) { - lua_pushnil(L); - lua_pushstring(L, socket_gaistrerror(ret)); - return 2; - } - lua_newtable(L); - for (iterator = resolved; iterator; iterator = iterator->ai_next) { - char hbuf[NI_MAXHOST]; - ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen, - hbuf, (socklen_t) sizeof(hbuf), NULL, 0, NI_NUMERICHOST); - if (ret){ - freeaddrinfo(resolved); - lua_pushnil(L); - lua_pushstring(L, socket_gaistrerror(ret)); - return 2; - } - lua_pushnumber(L, i); - lua_newtable(L); - switch (iterator->ai_family) { - case AF_INET: - lua_pushliteral(L, "family"); - lua_pushliteral(L, "inet"); - lua_settable(L, -3); - break; - case AF_INET6: - lua_pushliteral(L, "family"); - lua_pushliteral(L, "inet6"); - lua_settable(L, -3); - break; - case AF_UNSPEC: - lua_pushliteral(L, "family"); - lua_pushliteral(L, "unspec"); - lua_settable(L, -3); - break; - default: - lua_pushliteral(L, "family"); - lua_pushliteral(L, "unknown"); - lua_settable(L, -3); - break; - } - lua_pushliteral(L, "addr"); - lua_pushstring(L, hbuf); - lua_settable(L, -3); - lua_settable(L, -3); - i++; - } - freeaddrinfo(resolved); - return 1; + const char* hostname = luaL_checkstring(L, 1); + struct addrinfo *iterator = NULL, *resolved = NULL; + struct addrinfo hints; + int i = 1, ret = 0; + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_UNSPEC; + ret = getaddrinfo(hostname, NULL, &hints, &resolved); + if (ret != 0) + { + lua_pushnil(L); + lua_pushstring(L, socket_gaistrerror(ret)); + return 2; + } + lua_newtable(L); + for (iterator = resolved; iterator; iterator = iterator->ai_next) + { + char hbuf[NI_MAXHOST]; + ret = getnameinfo(iterator->ai_addr, (socklen_t)iterator->ai_addrlen, + hbuf, (socklen_t)sizeof(hbuf), NULL, 0, NI_NUMERICHOST); + if (ret) + { + freeaddrinfo(resolved); + lua_pushnil(L); + lua_pushstring(L, socket_gaistrerror(ret)); + return 2; + } + lua_pushnumber(L, i); + lua_newtable(L); + switch (iterator->ai_family) + { + case AF_INET: + lua_pushliteral(L, "family"); + lua_pushliteral(L, "inet"); + lua_settable(L, -3); + break; + case AF_INET6: + lua_pushliteral(L, "family"); + lua_pushliteral(L, "inet6"); + lua_settable(L, -3); + break; + case AF_UNSPEC: + lua_pushliteral(L, "family"); + lua_pushliteral(L, "unspec"); + lua_settable(L, -3); + break; + default: + lua_pushliteral(L, "family"); + lua_pushliteral(L, "unknown"); + lua_settable(L, -3); + break; + } + lua_pushliteral(L, "addr"); + lua_pushstring(L, hbuf); + lua_settable(L, -3); + lua_settable(L, -3); + i++; + } + freeaddrinfo(resolved); + return 1; } /*-------------------------------------------------------------------------*\ * Gets the host name \*-------------------------------------------------------------------------*/ -static int inet_global_gethostname(lua_State *L) +static int inet_global_gethostname(lua_State* L) { - char name[257]; - name[256] = '\0'; - if (gethostname(name, 256) < 0) { - lua_pushnil(L); - lua_pushstring(L, socket_strerror(errno)); - return 2; - } else { - lua_pushstring(L, name); - return 1; - } + char name[257]; + name[256] = '\0'; + if (gethostname(name, 256) < 0) + { + lua_pushnil(L); + lua_pushstring(L, socket_strerror(errno)); + return 2; + } + else + { + lua_pushstring(L, name); + return 1; + } } /*=========================================================================*\ @@ -242,68 +260,82 @@ static int inet_global_gethostname(lua_State *L) /*-------------------------------------------------------------------------*\ * Retrieves socket peer name \*-------------------------------------------------------------------------*/ -int inet_meth_getpeername(lua_State *L, p_socket ps, int family) +int inet_meth_getpeername(lua_State* L, p_socket ps, int family) { - int err; - struct sockaddr_storage peer; - socklen_t peer_len = sizeof(peer); - char name[INET6_ADDRSTRLEN]; - char port[6]; /* 65535 = 5 bytes + 0 to terminate it */ - if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) { - lua_pushnil(L); - lua_pushstring(L, socket_strerror(errno)); - return 2; - } - err = getnameinfo((struct sockaddr *) &peer, peer_len, - name, INET6_ADDRSTRLEN, - port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); - if (err) { - lua_pushnil(L); - lua_pushstring(L, gai_strerrorA(err)); - return 2; - } - lua_pushstring(L, name); - lua_pushinteger(L, (int) strtol(port, (char **) NULL, 10)); - switch (family) { - case AF_INET: lua_pushliteral(L, "inet"); break; - case AF_INET6: lua_pushliteral(L, "inet6"); break; - case AF_UNSPEC: lua_pushliteral(L, "unspec"); break; - default: lua_pushliteral(L, "unknown"); break; - } - return 3; + int err; + struct sockaddr_storage peer; + socklen_t peer_len = sizeof(peer); + char name[INET6_ADDRSTRLEN]; + char port[6]; /* 65535 = 5 bytes + 0 to terminate it */ + if (getpeername(*ps, (SA*)&peer, &peer_len) < 0) + { + lua_pushnil(L); + lua_pushstring(L, socket_strerror(errno)); + return 2; + } + err = getnameinfo((struct sockaddr*)&peer, peer_len, + name, INET6_ADDRSTRLEN, + port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); + if (err) + { + lua_pushnil(L); + lua_pushstring(L, gai_strerrorA(err)); + return 2; + } + lua_pushstring(L, name); + lua_pushinteger(L, (int)strtol(port, (char**)NULL, 10)); + switch (family) + { + case AF_INET: lua_pushliteral(L, "inet"); + break; + case AF_INET6: lua_pushliteral(L, "inet6"); + break; + case AF_UNSPEC: lua_pushliteral(L, "unspec"); + break; + default: lua_pushliteral(L, "unknown"); + break; + } + return 3; } /*-------------------------------------------------------------------------*\ * Retrieves socket local name \*-------------------------------------------------------------------------*/ -int inet_meth_getsockname(lua_State *L, p_socket ps, int family) +int inet_meth_getsockname(lua_State* L, p_socket ps, int family) { - int err; - struct sockaddr_storage peer; - socklen_t peer_len = sizeof(peer); - char name[INET6_ADDRSTRLEN]; - char port[6]; /* 65535 = 5 bytes + 0 to terminate it */ - if (getsockname(*ps, (SA *) &peer, &peer_len) < 0) { - lua_pushnil(L); - lua_pushstring(L, socket_strerror(errno)); - return 2; - } - err=getnameinfo((struct sockaddr *)&peer, peer_len, - name, INET6_ADDRSTRLEN, port, 6, NI_NUMERICHOST | NI_NUMERICSERV); - if (err) { - lua_pushnil(L); - lua_pushstring(L, gai_strerrorA(err)); - return 2; - } - lua_pushstring(L, name); - lua_pushstring(L, port); - switch (family) { - case AF_INET: lua_pushliteral(L, "inet"); break; - case AF_INET6: lua_pushliteral(L, "inet6"); break; - case AF_UNSPEC: lua_pushliteral(L, "unspec"); break; - default: lua_pushliteral(L, "unknown"); break; - } - return 3; + int err; + struct sockaddr_storage peer; + socklen_t peer_len = sizeof(peer); + char name[INET6_ADDRSTRLEN]; + char port[6]; /* 65535 = 5 bytes + 0 to terminate it */ + if (getsockname(*ps, (SA*)&peer, &peer_len) < 0) + { + lua_pushnil(L); + lua_pushstring(L, socket_strerror(errno)); + return 2; + } + err = getnameinfo((struct sockaddr*)&peer, peer_len, + name, INET6_ADDRSTRLEN, port, 6, NI_NUMERICHOST | NI_NUMERICSERV); + if (err) + { + lua_pushnil(L); + lua_pushstring(L, gai_strerrorA(err)); + return 2; + } + lua_pushstring(L, name); + lua_pushstring(L, port); + switch (family) + { + case AF_INET: lua_pushliteral(L, "inet"); + break; + case AF_INET6: lua_pushliteral(L, "inet6"); + break; + case AF_UNSPEC: lua_pushliteral(L, "unspec"); + break; + default: lua_pushliteral(L, "unknown"); + break; + } + return 3; } /*=========================================================================*\ @@ -312,209 +344,239 @@ int inet_meth_getsockname(lua_State *L, p_socket ps, int family) /*-------------------------------------------------------------------------*\ * Passes all resolver information to Lua as a table \*-------------------------------------------------------------------------*/ -static void inet_pushresolved(lua_State *L, struct hostent *hp) +static void inet_pushresolved(lua_State* L, struct hostent* hp) { - char **alias; - struct in_addr **addr; - int i, resolved; - lua_newtable(L); resolved = lua_gettop(L); - lua_pushstring(L, "name"); - lua_pushstring(L, hp->h_name); - lua_settable(L, resolved); - lua_pushstring(L, "ip"); - lua_pushstring(L, "alias"); - i = 1; - alias = hp->h_aliases; - lua_newtable(L); - if (alias) { - while (*alias) { - lua_pushnumber(L, i); - lua_pushstring(L, *alias); - lua_settable(L, -3); - i++; alias++; - } - } - lua_settable(L, resolved); - i = 1; - lua_newtable(L); - addr = (struct in_addr **) hp->h_addr_list; - if (addr) { - while (*addr) { - lua_pushnumber(L, i); - lua_pushstring(L, inet_ntoa(**addr)); - lua_settable(L, -3); - i++; addr++; - } - } - lua_settable(L, resolved); + char** alias; + struct in_addr** addr; + int i, resolved; + lua_newtable(L); + resolved = lua_gettop(L); + lua_pushstring(L, "name"); + lua_pushstring(L, hp->h_name); + lua_settable(L, resolved); + lua_pushstring(L, "ip"); + lua_pushstring(L, "alias"); + i = 1; + alias = hp->h_aliases; + lua_newtable(L); + if (alias) + { + while (*alias) + { + lua_pushnumber(L, i); + lua_pushstring(L, *alias); + lua_settable(L, -3); + i++; + alias++; + } + } + lua_settable(L, resolved); + i = 1; + lua_newtable(L); + addr = (struct in_addr**)hp->h_addr_list; + if (addr) + { + while (*addr) + { + lua_pushnumber(L, i); + lua_pushstring(L, inet_ntoa(**addr)); + lua_settable(L, -3); + i++; + addr++; + } + } + lua_settable(L, resolved); } /*-------------------------------------------------------------------------*\ * Tries to create a new inet socket \*-------------------------------------------------------------------------*/ -const char *inet_trycreate(p_socket ps, int family, int type, int protocol) { - const char *err = socket_strerror(socket_create(ps, family, type, protocol)); - if (err == NULL && family == AF_INET6) { - int yes = 1; - setsockopt(*ps, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&yes, sizeof(yes)); - } - return err; +const char* inet_trycreate(p_socket ps, int family, int type, int protocol) +{ + const char* err = socket_strerror(socket_create(ps, family, type, protocol)); + if (err == NULL && family == AF_INET6) + { + int yes = 1; + setsockopt(*ps, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&yes, sizeof(yes)); + } + return err; } /*-------------------------------------------------------------------------*\ * "Disconnects" a DGRAM socket \*-------------------------------------------------------------------------*/ -const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm) +const char* inet_trydisconnect(p_socket ps, int family, p_timeout tm) { - switch (family) { - case AF_INET: { - struct sockaddr_in sin; - memset((char *) &sin, 0, sizeof(sin)); - sin.sin_family = AF_UNSPEC; - sin.sin_addr.s_addr = INADDR_ANY; - return socket_strerror(socket_connect(ps, (SA *) &sin, - sizeof(sin), tm)); - } - case AF_INET6: { - struct sockaddr_in6 sin6; - struct in6_addr addrany = IN6ADDR_ANY_INIT; - memset((char *) &sin6, 0, sizeof(sin6)); - sin6.sin6_family = AF_UNSPEC; - sin6.sin6_addr = addrany; - return socket_strerror(socket_connect(ps, (SA *) &sin6, - sizeof(sin6), tm)); - } - } - return NULL; + switch (family) + { + case AF_INET: + { + struct sockaddr_in sin; + memset((char*)&sin, 0, sizeof(sin)); + sin.sin_family = AF_UNSPEC; + sin.sin_addr.s_addr = INADDR_ANY; + return socket_strerror(socket_connect(ps, (SA*)&sin, + sizeof(sin), tm)); + } + case AF_INET6: + { + struct sockaddr_in6 sin6; + struct in6_addr addrany = IN6ADDR_ANY_INIT; + memset((char*)&sin6, 0, sizeof(sin6)); + sin6.sin6_family = AF_UNSPEC; + sin6.sin6_addr = addrany; + return socket_strerror(socket_connect(ps, (SA*)&sin6, + sizeof(sin6), tm)); + } + } + return NULL; } /*-------------------------------------------------------------------------*\ * Tries to connect to remote address (address, port) \*-------------------------------------------------------------------------*/ -const char *inet_tryconnect(p_socket ps, int *family, const char *address, - const char *serv, p_timeout tm, struct addrinfo *connecthints) +const char* inet_tryconnect(p_socket ps, int* family, const char* address, + const char* serv, p_timeout tm, struct addrinfo* connecthints) { - struct addrinfo *iterator = NULL, *resolved = NULL; - const char *err = NULL; - int current_family = *family; - /* try resolving */ - err = socket_gaistrerror(getaddrinfo(address, serv, - connecthints, &resolved)); - if (err != NULL) { - if (resolved) freeaddrinfo(resolved); - return err; - } - for (iterator = resolved; iterator; iterator = iterator->ai_next) { - timeout_markstart(tm); - /* create new socket if necessary. if there was no - * bind, we need to create one for every new family - * that shows up while iterating. if there was a - * bind, all families will be the same and we will - * not enter this branch. */ - if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) { - socket_destroy(ps); - err = inet_trycreate(ps, iterator->ai_family, - iterator->ai_socktype, iterator->ai_protocol); - if (err) continue; - current_family = iterator->ai_family; - /* set non-blocking before connect */ - socket_setnonblocking(ps); - } - /* try connecting to remote address */ - err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr, - (socklen_t) iterator->ai_addrlen, tm)); - /* if success or timeout is zero, break out of loop */ - if (err == NULL || timeout_iszero(tm)) { - *family = current_family; - break; - } - } - freeaddrinfo(resolved); - /* here, if err is set, we failed */ - return err; + struct addrinfo *iterator = NULL, *resolved = NULL; + const char* err = NULL; + int current_family = *family; + /* try resolving */ + err = socket_gaistrerror(getaddrinfo(address, serv, + connecthints, &resolved)); + if (err != NULL) + { + if (resolved) freeaddrinfo(resolved); + return err; + } + for (iterator = resolved; iterator; iterator = iterator->ai_next) + { + timeout_markstart(tm); + /* create new socket if necessary. if there was no + * bind, we need to create one for every new family + * that shows up while iterating. if there was a + * bind, all families will be the same and we will + * not enter this branch. */ + if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) + { + socket_destroy(ps); + err = inet_trycreate(ps, iterator->ai_family, + iterator->ai_socktype, iterator->ai_protocol); + if (err) continue; + current_family = iterator->ai_family; + /* set non-blocking before connect */ + socket_setnonblocking(ps); + } + /* try connecting to remote address */ + err = socket_strerror(socket_connect(ps, (SA*)iterator->ai_addr, + (socklen_t)iterator->ai_addrlen, tm)); + /* if success or timeout is zero, break out of loop */ + if (err == NULL || timeout_iszero(tm)) + { + *family = current_family; + break; + } + } + freeaddrinfo(resolved); + /* here, if err is set, we failed */ + return err; } /*-------------------------------------------------------------------------*\ * Tries to accept a socket \*-------------------------------------------------------------------------*/ -const char *inet_tryaccept(p_socket server, int family, p_socket client, - p_timeout tm) { +const char* inet_tryaccept(p_socket server, int family, p_socket client, + p_timeout tm) +{ socklen_t len; t_sockaddr_storage addr; - switch (family) { - case AF_INET6: len = sizeof(struct sockaddr_in6); break; - case AF_INET: len = sizeof(struct sockaddr_in); break; - default: len = sizeof(addr); break; - } - return socket_strerror(socket_accept(server, client, (SA *) &addr, - &len, tm)); + switch (family) + { + case AF_INET6: len = sizeof(struct sockaddr_in6); + break; + case AF_INET: len = sizeof(struct sockaddr_in); + break; + default: len = sizeof(addr); + break; + } + return socket_strerror(socket_accept(server, client, (SA*)&addr, + &len, tm)); } /*-------------------------------------------------------------------------*\ * Tries to bind socket to (address, port) \*-------------------------------------------------------------------------*/ -const char *inet_trybind(p_socket ps, int *family, const char *address, - const char *serv, struct addrinfo *bindhints) { - struct addrinfo *iterator = NULL, *resolved = NULL; - const char *err = NULL; - int current_family = *family; - /* translate luasocket special values to C */ - if (strcmp(address, "*") == 0) address = NULL; - if (!serv) serv = "0"; - /* try resolving */ - err = socket_gaistrerror(getaddrinfo(address, serv, bindhints, &resolved)); - if (err) { - if (resolved) freeaddrinfo(resolved); - return err; - } - /* iterate over resolved addresses until one is good */ - for (iterator = resolved; iterator; iterator = iterator->ai_next) { - if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) { - socket_destroy(ps); - err = inet_trycreate(ps, iterator->ai_family, - iterator->ai_socktype, iterator->ai_protocol); - if (err) continue; - current_family = iterator->ai_family; - } - /* try binding to local address */ - err = socket_strerror(socket_bind(ps, (SA *) iterator->ai_addr, - (socklen_t) iterator->ai_addrlen)); - /* keep trying unless bind succeeded */ - if (err == NULL) { - *family = current_family; - /* set to non-blocking after bind */ - socket_setnonblocking(ps); - break; - } - } - /* cleanup and return error */ - freeaddrinfo(resolved); - /* here, if err is set, we failed */ - return err; +const char* inet_trybind(p_socket ps, int* family, const char* address, + const char* serv, struct addrinfo* bindhints) +{ + struct addrinfo *iterator = NULL, *resolved = NULL; + const char* err = NULL; + int current_family = *family; + /* translate luasocket special values to C */ + if (strcmp(address, "*") == 0) address = NULL; + if (!serv) serv = "0"; + /* try resolving */ + err = socket_gaistrerror(getaddrinfo(address, serv, bindhints, &resolved)); + if (err) + { + if (resolved) freeaddrinfo(resolved); + return err; + } + /* iterate over resolved addresses until one is good */ + for (iterator = resolved; iterator; iterator = iterator->ai_next) + { + if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) + { + socket_destroy(ps); + err = inet_trycreate(ps, iterator->ai_family, + iterator->ai_socktype, iterator->ai_protocol); + if (err) continue; + current_family = iterator->ai_family; + } + /* try binding to local address */ + err = socket_strerror(socket_bind(ps, (SA*)iterator->ai_addr, + (socklen_t)iterator->ai_addrlen)); + /* keep trying unless bind succeeded */ + if (err == NULL) + { + *family = current_family; + /* set to non-blocking after bind */ + socket_setnonblocking(ps); + break; + } + } + /* cleanup and return error */ + freeaddrinfo(resolved); + /* here, if err is set, we failed */ + return err; } /*-------------------------------------------------------------------------*\ * Some systems do not provide these so that we provide our own. \*-------------------------------------------------------------------------*/ #ifdef LUASOCKET_INET_ATON -int inet_aton(const char *cp, struct in_addr *inp) +int inet_aton(const char* cp, struct in_addr* inp) { - unsigned int a = 0, b = 0, c = 0, d = 0; - int n = 0, r; - unsigned long int addr = 0; - r = sscanf(cp, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n); - if (r == 0 || n == 0) return 0; - cp += n; - if (*cp) return 0; - if (a > 255 || b > 255 || c > 255 || d > 255) return 0; - if (inp) { - addr += a; addr <<= 8; - addr += b; addr <<= 8; - addr += c; addr <<= 8; - addr += d; - inp->s_addr = htonl(addr); - } - return 1; + unsigned int a = 0, b = 0, c = 0, d = 0; + int n = 0, r; + unsigned long int addr = 0; + r = sscanf(cp, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n); + if (r == 0 || n == 0) return 0; + cp += n; + if (*cp) return 0; + if (a > 255 || b > 255 || c > 255 || d > 255) return 0; + if (inp) + { + addr += a; + addr <<= 8; + addr += b; + addr <<= 8; + addr += c; + addr <<= 8; + addr += d; + inp->s_addr = htonl(addr); + } + return 1; } #endif diff --git a/Lua/inet.h b/Lua/inet.h index feb3541..2385060 100644 --- a/Lua/inet.h +++ b/Lua/inet.h @@ -22,24 +22,24 @@ #define LUASOCKET_INET_ATON #endif -int inet_open(lua_State *L); +int inet_open(lua_State* L); -const char *inet_trycreate(p_socket ps, int family, int type, int protocol); -const char *inet_tryconnect(p_socket ps, int *family, const char *address, - const char *serv, p_timeout tm, struct addrinfo *connecthints); -const char *inet_trybind(p_socket ps, int *family, const char *address, - const char *serv, struct addrinfo *bindhints); -const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm); -const char *inet_tryaccept(p_socket server, int family, p_socket client, p_timeout tm); +const char* inet_trycreate(p_socket ps, int family, int type, int protocol); +const char* inet_tryconnect(p_socket ps, int* family, const char* address, + const char* serv, p_timeout tm, struct addrinfo* connecthints); +const char* inet_trybind(p_socket ps, int* family, const char* address, + const char* serv, struct addrinfo* bindhints); +const char* inet_trydisconnect(p_socket ps, int family, p_timeout tm); +const char* inet_tryaccept(p_socket server, int family, p_socket client, p_timeout tm); -int inet_meth_getpeername(lua_State *L, p_socket ps, int family); -int inet_meth_getsockname(lua_State *L, p_socket ps, int family); +int inet_meth_getpeername(lua_State* L, p_socket ps, int family); +int inet_meth_getsockname(lua_State* L, p_socket ps, int family); int inet_optfamily(lua_State* L, int narg, const char* def); int inet_optsocktype(lua_State* L, int narg, const char* def); #ifdef LUASOCKET_INET_ATON -int inet_aton(const char *cp, struct in_addr *inp); +int inet_aton(const char* cp, struct in_addr* inp); #endif #ifdef LUASOCKET_INET_PTON diff --git a/Lua/io.c b/Lua/io.c index a4230ce..1b04689 100644 --- a/Lua/io.c +++ b/Lua/io.c @@ -10,21 +10,24 @@ /*-------------------------------------------------------------------------*\ * Initializes C structure \*-------------------------------------------------------------------------*/ -void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx) { - io->send = send; - io->recv = recv; - io->error = error; - io->ctx = ctx; +void io_init(p_io io, p_send send, p_recv recv, p_error error, void* ctx) +{ + io->send = send; + io->recv = recv; + io->error = error; + io->ctx = ctx; } /*-------------------------------------------------------------------------*\ * I/O error strings \*-------------------------------------------------------------------------*/ -const char *io_strerror(int err) { - switch (err) { - case IO_DONE: return NULL; - case IO_CLOSED: return "closed"; - case IO_TIMEOUT: return "timeout"; - default: return "unknown error"; - } +const char* io_strerror(int err) +{ + switch (err) + { + case IO_DONE: return NULL; + case IO_CLOSED: return "closed"; + case IO_TIMEOUT: return "timeout"; + default: return "unknown error"; + } } diff --git a/Lua/io.h b/Lua/io.h index 8cca08a..22ddcb3 100644 --- a/Lua/io.h +++ b/Lua/io.h @@ -18,48 +18,53 @@ #include "timeout.h" /* IO error codes */ -enum { - IO_DONE = 0, /* operation completed successfully */ - IO_TIMEOUT = -1, /* operation timed out */ - IO_CLOSED = -2, /* the connection has been closed */ +enum +{ + IO_DONE = 0, + /* operation completed successfully */ + IO_TIMEOUT = -1, + /* operation timed out */ + IO_CLOSED = -2, + /* the connection has been closed */ IO_UNKNOWN = -3 }; /* interface to error message function */ -typedef const char *(*p_error) ( - void *ctx, /* context needed by send */ - int err /* error code */ +typedef const char*(*p_error)( + void* ctx, /* context needed by send */ + int err /* error code */ ); /* interface to send function */ -typedef int (*p_send) ( - void *ctx, /* context needed by send */ - const char *data, /* pointer to buffer with data to send */ - size_t count, /* number of bytes to send from buffer */ - size_t *sent, /* number of bytes sent uppon return */ - p_timeout tm /* timeout control */ +typedef int (*p_send)( + void* ctx, /* context needed by send */ + const char* data, /* pointer to buffer with data to send */ + size_t count, /* number of bytes to send from buffer */ + size_t* sent, /* number of bytes sent uppon return */ + p_timeout tm /* timeout control */ ); /* interface to recv function */ -typedef int (*p_recv) ( - void *ctx, /* context needed by recv */ - char *data, /* pointer to buffer where data will be writen */ - size_t count, /* number of bytes to receive into buffer */ - size_t *got, /* number of bytes received uppon return */ - p_timeout tm /* timeout control */ +typedef int (*p_recv)( + void* ctx, /* context needed by recv */ + char* data, /* pointer to buffer where data will be writen */ + size_t count, /* number of bytes to receive into buffer */ + size_t* got, /* number of bytes received uppon return */ + p_timeout tm /* timeout control */ ); /* IO driver definition */ -typedef struct t_io_ { - void *ctx; /* context needed by send/recv */ - p_send send; /* send function pointer */ - p_recv recv; /* receive function pointer */ - p_error error; /* strerror function */ +typedef struct t_io_ +{ + void* ctx; /* context needed by send/recv */ + p_send send; /* send function pointer */ + p_recv recv; /* receive function pointer */ + p_error error; /* strerror function */ } t_io; -typedef t_io *p_io; -void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx); -const char *io_strerror(int err); +typedef t_io* p_io; + +void io_init(p_io io, p_send send, p_recv recv, p_error error, void* ctx); +const char* io_strerror(int err); #endif /* IO_H */ - diff --git a/Lua/lapi.c b/Lua/lapi.c index c9455a5..f1614b9 100644 --- a/Lua/lapi.c +++ b/Lua/lapi.c @@ -30,10 +30,9 @@ #include "lvm.h" - const char lua_ident[] = - "$LuaVersion: " LUA_COPYRIGHT " $" - "$LuaAuthors: " LUA_AUTHORS " $"; + "$LuaVersion: " LUA_COPYRIGHT " $" + "$LuaAuthors: " LUA_AUTHORS " $"; /* value at a non-valid index */ @@ -57,30 +56,37 @@ const char lua_ident[] = api_check(l, isstackindex(i, o), "index not in the stack") -static TValue *index2addr (lua_State *L, int idx) { - CallInfo *ci = L->ci; - if (idx > 0) { - TValue *o = ci->func + idx; - api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index"); - if (o >= L->top) return NONVALIDVALUE; - else return o; - } - else if (!ispseudo(idx)) { /* negative index */ - api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); - return L->top + idx; - } - else if (idx == LUA_REGISTRYINDEX) - return &G(L)->l_registry; - else { /* upvalues */ - idx = LUA_REGISTRYINDEX - idx; - api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); - if (ttislcf(ci->func)) /* light C function? */ - return NONVALIDVALUE; /* it has no upvalues */ - else { - CClosure *func = clCvalue(ci->func); - return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE; - } - } +static TValue* index2addr(lua_State* L, int idx) +{ + CallInfo* ci = L->ci; + if (idx > 0) + { + TValue* o = ci->func + idx; + api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index"); + if (o >= L->top) return NONVALIDVALUE; + else return o; + } + else if (!ispseudo(idx)) + { + /* negative index */ + api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); + return L->top + idx; + } + else if (idx == LUA_REGISTRYINDEX) + return &G(L)->l_registry; + else + { + /* upvalues */ + idx = LUA_REGISTRYINDEX - idx; + api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); + if (ttislcf(ci->func)) /* light C function? */ + return NONVALIDVALUE; /* it has no upvalues */ + else + { + CClosure* func = clCvalue(ci->func); + return (idx <= func->nupvalues) ? &func->upvalue[idx - 1] : NONVALIDVALUE; + } + } } @@ -88,67 +94,74 @@ static TValue *index2addr (lua_State *L, int idx) { ** to be called by 'lua_checkstack' in protected mode, to grow stack ** capturing memory errors */ -static void growstack (lua_State *L, void *ud) { - int size = *(int *)ud; - luaD_growstack(L, size); +static void growstack(lua_State* L, void* ud) +{ + int size = *(int*)ud; + luaD_growstack(L, size); } -LUA_API int lua_checkstack (lua_State *L, int n) { - int res; - CallInfo *ci = L->ci; - lua_lock(L); - api_check(L, n >= 0, "negative 'n'"); - if (L->stack_last - L->top > n) /* stack large enough? */ - res = 1; /* yes; check is OK */ - else { /* no; need to grow stack */ - int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; - if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */ - res = 0; /* no */ - else /* try to grow stack */ - res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK); - } - if (res && ci->top < L->top + n) - ci->top = L->top + n; /* adjust frame top */ - lua_unlock(L); - return res; +LUA_API int lua_checkstack(lua_State* L, int n) +{ + int res; + CallInfo* ci = L->ci; + lua_lock(L); + api_check(L, n >= 0, "negative 'n'"); + if (L->stack_last - L->top > n) /* stack large enough? */ + res = 1; /* yes; check is OK */ + else + { + /* no; need to grow stack */ + int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; + if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */ + res = 0; /* no */ + else /* try to grow stack */ + res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK); + } + if (res && ci->top < L->top + n) + ci->top = L->top + n; /* adjust frame top */ + lua_unlock(L); + return res; } -LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { - int i; - if (from == to) return; - lua_lock(to); - api_checknelems(from, n); - api_check(from, G(from) == G(to), "moving among independent states"); - api_check(from, to->ci->top - to->top >= n, "stack overflow"); - from->top -= n; - for (i = 0; i < n; i++) { - setobj2s(to, to->top, from->top + i); - to->top++; /* stack already checked by previous 'api_check' */ - } - lua_unlock(to); +LUA_API void lua_xmove(lua_State* from, lua_State* to, int n) +{ + int i; + if (from == to) return; + lua_lock(to); + api_checknelems(from, n); + api_check(from, G(from) == G(to), "moving among independent states"); + api_check(from, to->ci->top - to->top >= n, "stack overflow"); + from->top -= n; + for (i = 0; i < n; i++) + { + setobj2s(to, to->top, from->top + i); + to->top++; /* stack already checked by previous 'api_check' */ + } + lua_unlock(to); } -LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { - lua_CFunction old; - lua_lock(L); - old = G(L)->panic; - G(L)->panic = panicf; - lua_unlock(L); - return old; +LUA_API lua_CFunction lua_atpanic(lua_State* L, lua_CFunction panicf) +{ + lua_CFunction old; + lua_lock(L); + old = G(L)->panic; + G(L)->panic = panicf; + lua_unlock(L); + return old; } -LUA_API const lua_Number *lua_version (lua_State *L) { - static const lua_Number version = LUA_VERSION_NUM; - if (L == NULL) return &version; - else return G(L)->version; +LUA_API const lua_Number* lua_version(lua_State* L) +{ + static const lua_Number version = LUA_VERSION_NUM; + if (L == NULL) return &version; + else return G(L)->version; } - /* ** basic stack manipulation */ @@ -157,32 +170,37 @@ LUA_API const lua_Number *lua_version (lua_State *L) { /* ** convert an acceptable stack index into an absolute index */ -LUA_API int lua_absindex (lua_State *L, int idx) { - return (idx > 0 || ispseudo(idx)) - ? idx - : cast_int(L->top - L->ci->func) + idx; +LUA_API int lua_absindex(lua_State* L, int idx) +{ + return (idx > 0 || ispseudo(idx)) + ? idx + : cast_int(L->top - L->ci->func) + idx; } -LUA_API int lua_gettop (lua_State *L) { - return cast_int(L->top - (L->ci->func + 1)); +LUA_API int lua_gettop(lua_State* L) +{ + return cast_int(L->top - (L->ci->func + 1)); } -LUA_API void lua_settop (lua_State *L, int idx) { - StkId func = L->ci->func; - lua_lock(L); - if (idx >= 0) { - api_check(L, idx <= L->stack_last - (func + 1), "new top too large"); - while (L->top < (func + 1) + idx) - setnilvalue(L->top++); - L->top = (func + 1) + idx; - } - else { - api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); - L->top += idx+1; /* 'subtract' index (index is negative) */ - } - lua_unlock(L); +LUA_API void lua_settop(lua_State* L, int idx) +{ + StkId func = L->ci->func; + lua_lock(L); + if (idx >= 0) + { + api_check(L, idx <= L->stack_last - (func + 1), "new top too large"); + while (L->top < (func + 1) + idx) + setnilvalue(L->top++); + L->top = (func + 1) + idx; + } + else + { + api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); + L->top += idx + 1; /* 'subtract' index (index is negative) */ + } + lua_unlock(L); } @@ -190,13 +208,15 @@ LUA_API void lua_settop (lua_State *L, int idx) { ** Reverse the stack segment from 'from' to 'to' ** (auxiliary to 'lua_rotate') */ -static void reverse (lua_State *L, StkId from, StkId to) { - for (; from < to; from++, to--) { - TValue temp; - setobj(L, &temp, from); - setobjs2s(L, from, to); - setobj2s(L, to, &temp); - } +static void reverse(lua_State* L, StkId from, StkId to) +{ + for (; from < to; from++, to--) + { + TValue temp; + setobj(L, &temp, from); + setobjs2s(L, from, to); + setobj2s(L, to, &temp); + } } @@ -204,270 +224,307 @@ static void reverse (lua_State *L, StkId from, StkId to) { ** Let x = AB, where A is a prefix of length 'n'. Then, ** rotate x n == BA. But BA == (A^r . B^r)^r. */ -LUA_API void lua_rotate (lua_State *L, int idx, int n) { - StkId p, t, m; - lua_lock(L); - t = L->top - 1; /* end of stack segment being rotated */ - p = index2addr(L, idx); /* start of segment */ - api_checkstackindex(L, idx, p); - api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); - m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ - reverse(L, p, m); /* reverse the prefix with length 'n' */ - reverse(L, m + 1, t); /* reverse the suffix */ - reverse(L, p, t); /* reverse the entire segment */ - lua_unlock(L); +LUA_API void lua_rotate(lua_State* L, int idx, int n) +{ + StkId p, t, m; + lua_lock(L); + t = L->top - 1; /* end of stack segment being rotated */ + p = index2addr(L, idx); /* start of segment */ + api_checkstackindex(L, idx, p); + api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); + m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ + reverse(L, p, m); /* reverse the prefix with length 'n' */ + reverse(L, m + 1, t); /* reverse the suffix */ + reverse(L, p, t); /* reverse the entire segment */ + lua_unlock(L); } -LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { - TValue *fr, *to; - lua_lock(L); - fr = index2addr(L, fromidx); - to = index2addr(L, toidx); - api_checkvalidindex(L, to); - setobj(L, to, fr); - if (isupvalue(toidx)) /* function upvalue? */ - luaC_barrier(L, clCvalue(L->ci->func), fr); - /* LUA_REGISTRYINDEX does not need gc barrier - (collector revisits it before finishing collection) */ - lua_unlock(L); +LUA_API void lua_copy(lua_State* L, int fromidx, int toidx) +{ + TValue *fr, *to; + lua_lock(L); + fr = index2addr(L, fromidx); + to = index2addr(L, toidx); + api_checkvalidindex(L, to); + setobj(L, to, fr); + if (isupvalue(toidx)) /* function upvalue? */ + luaC_barrier(L, clCvalue(L->ci->func), fr); + /* LUA_REGISTRYINDEX does not need gc barrier + (collector revisits it before finishing collection) */ + lua_unlock(L); } -LUA_API void lua_pushvalue (lua_State *L, int idx) { - lua_lock(L); - setobj2s(L, L->top, index2addr(L, idx)); - api_incr_top(L); - lua_unlock(L); +LUA_API void lua_pushvalue(lua_State* L, int idx) +{ + lua_lock(L); + setobj2s(L, L->top, index2addr(L, idx)); + api_incr_top(L); + lua_unlock(L); } - /* ** access functions (stack -> C) */ -LUA_API int lua_type (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - return (isvalid(o) ? ttnov(o) : LUA_TNONE); +LUA_API int lua_type(lua_State* L, int idx) +{ + StkId o = index2addr(L, idx); + return (isvalid(o) ? ttnov(o) : LUA_TNONE); } -LUA_API const char *lua_typename (lua_State *L, int t) { - UNUSED(L); - api_check(L, LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag"); - return ttypename(t); +LUA_API const char* lua_typename(lua_State* L, int t) +{ + UNUSED(L); + api_check(L, LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag"); + return ttypename(t); } -LUA_API int lua_iscfunction (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - return (ttislcf(o) || (ttisCclosure(o))); +LUA_API int lua_iscfunction(lua_State* L, int idx) +{ + StkId o = index2addr(L, idx); + return (ttislcf(o) || (ttisCclosure(o))); } -LUA_API int lua_isinteger (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - return ttisinteger(o); +LUA_API int lua_isinteger(lua_State* L, int idx) +{ + StkId o = index2addr(L, idx); + return ttisinteger(o); } -LUA_API int lua_isnumber (lua_State *L, int idx) { - lua_Number n; - const TValue *o = index2addr(L, idx); - return tonumber(o, &n); +LUA_API int lua_isnumber(lua_State* L, int idx) +{ + lua_Number n; + const TValue* o = index2addr(L, idx); + return tonumber(o, &n); } -LUA_API int lua_isstring (lua_State *L, int idx) { - const TValue *o = index2addr(L, idx); - return (ttisstring(o) || cvt2str(o)); +LUA_API int lua_isstring(lua_State* L, int idx) +{ + const TValue* o = index2addr(L, idx); + return (ttisstring(o) || cvt2str(o)); } -LUA_API int lua_isuserdata (lua_State *L, int idx) { - const TValue *o = index2addr(L, idx); - return (ttisfulluserdata(o) || ttislightuserdata(o)); +LUA_API int lua_isuserdata(lua_State* L, int idx) +{ + const TValue* o = index2addr(L, idx); + return (ttisfulluserdata(o) || ttislightuserdata(o)); } -LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { - StkId o1 = index2addr(L, index1); - StkId o2 = index2addr(L, index2); - return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0; +LUA_API int lua_rawequal(lua_State* L, int index1, int index2) +{ + StkId o1 = index2addr(L, index1); + StkId o2 = index2addr(L, index2); + return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0; } -LUA_API void lua_arith (lua_State *L, int op) { - lua_lock(L); - if (op != LUA_OPUNM && op != LUA_OPBNOT) - api_checknelems(L, 2); /* all other operations expect two operands */ - else { /* for unary operations, add fake 2nd operand */ - api_checknelems(L, 1); - setobjs2s(L, L->top, L->top - 1); - api_incr_top(L); - } - /* first operand at top - 2, second at top - 1; result go to top - 2 */ - luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2); - L->top--; /* remove second operand */ - lua_unlock(L); +LUA_API void lua_arith(lua_State* L, int op) +{ + lua_lock(L); + if (op != LUA_OPUNM && op != LUA_OPBNOT) + api_checknelems(L, 2); /* all other operations expect two operands */ + else + { + /* for unary operations, add fake 2nd operand */ + api_checknelems(L, 1); + setobjs2s(L, L->top, L->top - 1); + api_incr_top(L); + } + /* first operand at top - 2, second at top - 1; result go to top - 2 */ + luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2); + L->top--; /* remove second operand */ + lua_unlock(L); } -LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { - StkId o1, o2; - int i = 0; - lua_lock(L); /* may call tag method */ - o1 = index2addr(L, index1); - o2 = index2addr(L, index2); - if (isvalid(o1) && isvalid(o2)) { - switch (op) { - case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break; - case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; - case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; - default: api_check(L, 0, "invalid option"); - } - } - lua_unlock(L); - return i; +LUA_API int lua_compare(lua_State* L, int index1, int index2, int op) +{ + StkId o1, o2; + int i = 0; + lua_lock(L); /* may call tag method */ + o1 = index2addr(L, index1); + o2 = index2addr(L, index2); + if (isvalid(o1) && isvalid(o2)) + { + switch (op) + { + case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); + break; + case LUA_OPLT: i = luaV_lessthan(L, o1, o2); + break; + case LUA_OPLE: i = luaV_lessequal(L, o1, o2); + break; + default: api_check(L, 0, "invalid option"); + } + } + lua_unlock(L); + return i; } -LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) { - size_t sz = luaO_str2num(s, L->top); - if (sz != 0) - api_incr_top(L); - return sz; +LUA_API size_t lua_stringtonumber(lua_State* L, const char* s) +{ + size_t sz = luaO_str2num(s, L->top); + if (sz != 0) + api_incr_top(L); + return sz; } -LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) { - lua_Number n; - const TValue *o = index2addr(L, idx); - int isnum = tonumber(o, &n); - if (!isnum) - n = 0; /* call to 'tonumber' may change 'n' even if it fails */ - if (pisnum) *pisnum = isnum; - return n; +LUA_API lua_Number lua_tonumberx(lua_State* L, int idx, int* pisnum) +{ + lua_Number n; + const TValue* o = index2addr(L, idx); + int isnum = tonumber(o, &n); + if (!isnum) + n = 0; /* call to 'tonumber' may change 'n' even if it fails */ + if (pisnum) *pisnum = isnum; + return n; } -LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) { - lua_Integer res; - const TValue *o = index2addr(L, idx); - int isnum = tointeger(o, &res); - if (!isnum) - res = 0; /* call to 'tointeger' may change 'n' even if it fails */ - if (pisnum) *pisnum = isnum; - return res; +LUA_API lua_Integer lua_tointegerx(lua_State* L, int idx, int* pisnum) +{ + lua_Integer res; + const TValue* o = index2addr(L, idx); + int isnum = tointeger(o, &res); + if (!isnum) + res = 0; /* call to 'tointeger' may change 'n' even if it fails */ + if (pisnum) *pisnum = isnum; + return res; } -LUA_API int lua_toboolean (lua_State *L, int idx) { - const TValue *o = index2addr(L, idx); - return !l_isfalse(o); +LUA_API int lua_toboolean(lua_State* L, int idx) +{ + const TValue* o = index2addr(L, idx); + return !l_isfalse(o); } -LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { - StkId o = index2addr(L, idx); - if (!ttisstring(o)) { - if (!cvt2str(o)) { /* not convertible? */ - if (len != NULL) *len = 0; - return NULL; - } - lua_lock(L); /* 'luaO_tostring' may create a new string */ - luaO_tostring(L, o); - luaC_checkGC(L); - o = index2addr(L, idx); /* previous call may reallocate the stack */ - lua_unlock(L); - } - if (len != NULL) - *len = vslen(o); - return svalue(o); +LUA_API const char* lua_tolstring(lua_State* L, int idx, size_t* len) +{ + StkId o = index2addr(L, idx); + if (!ttisstring(o)) + { + if (!cvt2str(o)) + { + /* not convertible? */ + if (len != NULL) *len = 0; + return NULL; + } + lua_lock(L); /* 'luaO_tostring' may create a new string */ + luaO_tostring(L, o); + luaC_checkGC(L); + o = index2addr(L, idx); /* previous call may reallocate the stack */ + lua_unlock(L); + } + if (len != NULL) + *len = vslen(o); + return svalue(o); } -LUA_API size_t lua_rawlen (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - switch (ttype(o)) { - case LUA_TSHRSTR: return tsvalue(o)->shrlen; - case LUA_TLNGSTR: return tsvalue(o)->u.lnglen; - case LUA_TUSERDATA: return uvalue(o)->len; - case LUA_TTABLE: return luaH_getn(hvalue(o)); - default: return 0; - } +LUA_API size_t lua_rawlen(lua_State* L, int idx) +{ + StkId o = index2addr(L, idx); + switch (ttype(o)) + { + case LUA_TSHRSTR: return tsvalue(o)->shrlen; + case LUA_TLNGSTR: return tsvalue(o)->u.lnglen; + case LUA_TUSERDATA: return uvalue(o)->len; + case LUA_TTABLE: return luaH_getn(hvalue(o)); + default: return 0; + } } -LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - if (ttislcf(o)) return fvalue(o); - else if (ttisCclosure(o)) - return clCvalue(o)->f; - else return NULL; /* not a C function */ +LUA_API lua_CFunction lua_tocfunction(lua_State* L, int idx) +{ + StkId o = index2addr(L, idx); + if (ttislcf(o)) return fvalue(o); + else if (ttisCclosure(o)) + return clCvalue(o)->f; + else return NULL; /* not a C function */ } -LUA_API void *lua_touserdata (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - switch (ttnov(o)) { - case LUA_TUSERDATA: return getudatamem(uvalue(o)); - case LUA_TLIGHTUSERDATA: return pvalue(o); - default: return NULL; - } +LUA_API void* lua_touserdata(lua_State* L, int idx) +{ + StkId o = index2addr(L, idx); + switch (ttnov(o)) + { + case LUA_TUSERDATA: return getudatamem(uvalue(o)); + case LUA_TLIGHTUSERDATA: return pvalue(o); + default: return NULL; + } } -LUA_API lua_State *lua_tothread (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - return (!ttisthread(o)) ? NULL : thvalue(o); +LUA_API lua_State* lua_tothread(lua_State* L, int idx) +{ + StkId o = index2addr(L, idx); + return (!ttisthread(o)) ? NULL : thvalue(o); } -LUA_API const void *lua_topointer (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - switch (ttype(o)) { - case LUA_TTABLE: return hvalue(o); - case LUA_TLCL: return clLvalue(o); - case LUA_TCCL: return clCvalue(o); - case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o))); - case LUA_TTHREAD: return thvalue(o); - case LUA_TUSERDATA: return getudatamem(uvalue(o)); - case LUA_TLIGHTUSERDATA: return pvalue(o); - default: return NULL; - } +LUA_API const void* lua_topointer(lua_State* L, int idx) +{ + StkId o = index2addr(L, idx); + switch (ttype(o)) + { + case LUA_TTABLE: return hvalue(o); + case LUA_TLCL: return clLvalue(o); + case LUA_TCCL: return clCvalue(o); + case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o))); + case LUA_TTHREAD: return thvalue(o); + case LUA_TUSERDATA: return getudatamem(uvalue(o)); + case LUA_TLIGHTUSERDATA: return pvalue(o); + default: return NULL; + } } - /* ** push functions (C -> stack) */ -LUA_API void lua_pushnil (lua_State *L) { - lua_lock(L); - setnilvalue(L->top); - api_incr_top(L); - lua_unlock(L); +LUA_API void lua_pushnil(lua_State* L) +{ + lua_lock(L); + setnilvalue(L->top); + api_incr_top(L); + lua_unlock(L); } -LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { - lua_lock(L); - setfltvalue(L->top, n); - api_incr_top(L); - lua_unlock(L); +LUA_API void lua_pushnumber(lua_State* L, lua_Number n) +{ + lua_lock(L); + setfltvalue(L->top, n); + api_incr_top(L); + lua_unlock(L); } -LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { - lua_lock(L); - setivalue(L->top, n); - api_incr_top(L); - lua_unlock(L); +LUA_API void lua_pushinteger(lua_State* L, lua_Integer n) +{ + lua_lock(L); + setivalue(L->top, n); + api_incr_top(L); + lua_unlock(L); } @@ -476,259 +533,287 @@ LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { ** 'len' == 0 (as 's' can be NULL in that case), due to later use of ** 'memcmp' and 'memcpy'. */ -LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { - TString *ts; - lua_lock(L); - ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); - setsvalue2s(L, L->top, ts); - api_incr_top(L); - luaC_checkGC(L); - lua_unlock(L); - return getstr(ts); +LUA_API const char* lua_pushlstring(lua_State* L, const char* s, size_t len) +{ + TString* ts; + lua_lock(L); + ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); + setsvalue2s(L, L->top, ts); + api_incr_top(L); + luaC_checkGC(L); + lua_unlock(L); + return getstr(ts); } -LUA_API const char *lua_pushstring (lua_State *L, const char *s) { - lua_lock(L); - if (s == NULL) - setnilvalue(L->top); - else { - TString *ts; - ts = luaS_new(L, s); - setsvalue2s(L, L->top, ts); - s = getstr(ts); /* internal copy's address */ - } - api_incr_top(L); - luaC_checkGC(L); - lua_unlock(L); - return s; +LUA_API const char* lua_pushstring(lua_State* L, const char* s) +{ + lua_lock(L); + if (s == NULL) + setnilvalue(L->top); + else + { + TString* ts; + ts = luaS_new(L, s); + setsvalue2s(L, L->top, ts); + s = getstr(ts); /* internal copy's address */ + } + api_incr_top(L); + luaC_checkGC(L); + lua_unlock(L); + return s; } -LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, - va_list argp) { - const char *ret; - lua_lock(L); - ret = luaO_pushvfstring(L, fmt, argp); - luaC_checkGC(L); - lua_unlock(L); - return ret; +LUA_API const char* lua_pushvfstring(lua_State* L, const char* fmt, + va_list argp) +{ + const char* ret; + lua_lock(L); + ret = luaO_pushvfstring(L, fmt, argp); + luaC_checkGC(L); + lua_unlock(L); + return ret; } -LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { - const char *ret; - va_list argp; - lua_lock(L); - va_start(argp, fmt); - ret = luaO_pushvfstring(L, fmt, argp); - va_end(argp); - luaC_checkGC(L); - lua_unlock(L); - return ret; +LUA_API const char* lua_pushfstring(lua_State* L, const char* fmt, ...) +{ + const char* ret; + va_list argp; + lua_lock(L); + va_start(argp, fmt); + ret = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + luaC_checkGC(L); + lua_unlock(L); + return ret; } -LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { - lua_lock(L); - if (n == 0) { - setfvalue(L->top, fn); - } - else { - CClosure *cl; - api_checknelems(L, n); - api_check(L, n <= MAXUPVAL, "upvalue index too large"); - cl = luaF_newCclosure(L, n); - cl->f = fn; - L->top -= n; - while (n--) { - setobj2n(L, &cl->upvalue[n], L->top + n); - /* does not need barrier because closure is white */ - } - setclCvalue(L, L->top, cl); - } - api_incr_top(L); - luaC_checkGC(L); - lua_unlock(L); +LUA_API void lua_pushcclosure(lua_State* L, lua_CFunction fn, int n) +{ + lua_lock(L); + if (n == 0) + { + setfvalue(L->top, fn); + } + else + { + CClosure* cl; + api_checknelems(L, n); + api_check(L, n <= MAXUPVAL, "upvalue index too large"); + cl = luaF_newCclosure(L, n); + cl->f = fn; + L->top -= n; + while (n--) + { + setobj2n(L, &cl->upvalue[n], L->top + n); + /* does not need barrier because closure is white */ + } + setclCvalue(L, L->top, cl); + } + api_incr_top(L); + luaC_checkGC(L); + lua_unlock(L); } -LUA_API void lua_pushboolean (lua_State *L, int b) { - lua_lock(L); - setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ - api_incr_top(L); - lua_unlock(L); +LUA_API void lua_pushboolean(lua_State* L, int b) +{ + lua_lock(L); + setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ + api_incr_top(L); + lua_unlock(L); } -LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { - lua_lock(L); - setpvalue(L->top, p); - api_incr_top(L); - lua_unlock(L); +LUA_API void lua_pushlightuserdata(lua_State* L, void* p) +{ + lua_lock(L); + setpvalue(L->top, p); + api_incr_top(L); + lua_unlock(L); } -LUA_API int lua_pushthread (lua_State *L) { - lua_lock(L); - setthvalue(L, L->top, L); - api_incr_top(L); - lua_unlock(L); - return (G(L)->mainthread == L); +LUA_API int lua_pushthread(lua_State* L) +{ + lua_lock(L); + setthvalue(L, L->top, L); + api_incr_top(L); + lua_unlock(L); + return (G(L)->mainthread == L); } - /* ** get functions (Lua -> stack) */ -static int auxgetstr (lua_State *L, const TValue *t, const char *k) { - const TValue *slot; - TString *str = luaS_new(L, k); - if (luaV_fastget(L, t, str, slot, luaH_getstr)) { - setobj2s(L, L->top, slot); - api_incr_top(L); - } - else { - setsvalue2s(L, L->top, str); - api_incr_top(L); - luaV_finishget(L, t, L->top - 1, L->top - 1, slot); - } - lua_unlock(L); - return ttnov(L->top - 1); +static int auxgetstr(lua_State* L, const TValue* t, const char* k) +{ + const TValue* slot; + TString* str = luaS_new(L, k); + if (luaV_fastget(L, t, str, slot, luaH_getstr)) + { + setobj2s(L, L->top, slot); + api_incr_top(L); + } + else + { + setsvalue2s(L, L->top, str); + api_incr_top(L); + luaV_finishget(L, t, L->top - 1, L->top - 1, slot); + } + lua_unlock(L); + return ttnov(L->top - 1); } -LUA_API int lua_getglobal (lua_State *L, const char *name) { - Table *reg = hvalue(&G(L)->l_registry); - lua_lock(L); - return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); +LUA_API int lua_getglobal(lua_State* L, const char* name) +{ + Table* reg = hvalue(&G(L)->l_registry); + lua_lock(L); + return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); } -LUA_API int lua_gettable (lua_State *L, int idx) { - StkId t; - lua_lock(L); - t = index2addr(L, idx); - luaV_gettable(L, t, L->top - 1, L->top - 1); - lua_unlock(L); - return ttnov(L->top - 1); +LUA_API int lua_gettable(lua_State* L, int idx) +{ + StkId t; + lua_lock(L); + t = index2addr(L, idx); + luaV_gettable(L, t, L->top - 1, L->top - 1); + lua_unlock(L); + return ttnov(L->top - 1); } -LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { - lua_lock(L); - return auxgetstr(L, index2addr(L, idx), k); +LUA_API int lua_getfield(lua_State* L, int idx, const char* k) +{ + lua_lock(L); + return auxgetstr(L, index2addr(L, idx), k); } -LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { - StkId t; - const TValue *slot; - lua_lock(L); - t = index2addr(L, idx); - if (luaV_fastget(L, t, n, slot, luaH_getint)) { - setobj2s(L, L->top, slot); - api_incr_top(L); - } - else { - setivalue(L->top, n); - api_incr_top(L); - luaV_finishget(L, t, L->top - 1, L->top - 1, slot); - } - lua_unlock(L); - return ttnov(L->top - 1); +LUA_API int lua_geti(lua_State* L, int idx, lua_Integer n) +{ + StkId t; + const TValue* slot; + lua_lock(L); + t = index2addr(L, idx); + if (luaV_fastget(L, t, n, slot, luaH_getint)) + { + setobj2s(L, L->top, slot); + api_incr_top(L); + } + else + { + setivalue(L->top, n); + api_incr_top(L); + luaV_finishget(L, t, L->top - 1, L->top - 1, slot); + } + lua_unlock(L); + return ttnov(L->top - 1); } -LUA_API int lua_rawget (lua_State *L, int idx) { - StkId t; - lua_lock(L); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); - lua_unlock(L); - return ttnov(L->top - 1); +LUA_API int lua_rawget(lua_State* L, int idx) +{ + StkId t; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); + lua_unlock(L); + return ttnov(L->top - 1); } -LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { - StkId t; - lua_lock(L); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - setobj2s(L, L->top, luaH_getint(hvalue(t), n)); - api_incr_top(L); - lua_unlock(L); - return ttnov(L->top - 1); +LUA_API int lua_rawgeti(lua_State* L, int idx, lua_Integer n) +{ + StkId t; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setobj2s(L, L->top, luaH_getint(hvalue(t), n)); + api_incr_top(L); + lua_unlock(L); + return ttnov(L->top - 1); } -LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { - StkId t; - TValue k; - lua_lock(L); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - setpvalue(&k, cast(void *, p)); - setobj2s(L, L->top, luaH_get(hvalue(t), &k)); - api_incr_top(L); - lua_unlock(L); - return ttnov(L->top - 1); +LUA_API int lua_rawgetp(lua_State* L, int idx, const void* p) +{ + StkId t; + TValue k; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setpvalue(&k, cast(void *, p)); + setobj2s(L, L->top, luaH_get(hvalue(t), &k)); + api_incr_top(L); + lua_unlock(L); + return ttnov(L->top - 1); } -LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { - Table *t; - lua_lock(L); - t = luaH_new(L); - sethvalue(L, L->top, t); - api_incr_top(L); - if (narray > 0 || nrec > 0) - luaH_resize(L, t, narray, nrec); - luaC_checkGC(L); - lua_unlock(L); +LUA_API void lua_createtable(lua_State* L, int narray, int nrec) +{ + Table* t; + lua_lock(L); + t = luaH_new(L); + sethvalue(L, L->top, t); + api_incr_top(L); + if (narray > 0 || nrec > 0) + luaH_resize(L, t, narray, nrec); + luaC_checkGC(L); + lua_unlock(L); } -LUA_API int lua_getmetatable (lua_State *L, int objindex) { - const TValue *obj; - Table *mt; - int res = 0; - lua_lock(L); - obj = index2addr(L, objindex); - switch (ttnov(obj)) { - case LUA_TTABLE: - mt = hvalue(obj)->metatable; - break; - case LUA_TUSERDATA: - mt = uvalue(obj)->metatable; - break; - default: - mt = G(L)->mt[ttnov(obj)]; - break; - } - if (mt != NULL) { - sethvalue(L, L->top, mt); - api_incr_top(L); - res = 1; - } - lua_unlock(L); - return res; +LUA_API int lua_getmetatable(lua_State* L, int objindex) +{ + const TValue* obj; + Table* mt; + int res = 0; + lua_lock(L); + obj = index2addr(L, objindex); + switch (ttnov(obj)) + { + case LUA_TTABLE: + mt = hvalue(obj)->metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(obj)->metatable; + break; + default: + mt = G(L)->mt[ttnov(obj)]; + break; + } + if (mt != NULL) + { + sethvalue(L, L->top, mt); + api_incr_top(L); + res = 1; + } + lua_unlock(L); + return res; } -LUA_API int lua_getuservalue (lua_State *L, int idx) { - StkId o; - lua_lock(L); - o = index2addr(L, idx); - api_check(L, ttisfulluserdata(o), "full userdata expected"); - getuservalue(L, uvalue(o), L->top); - api_incr_top(L); - lua_unlock(L); - return ttnov(L->top - 1); +LUA_API int lua_getuservalue(lua_State* L, int idx) +{ + StkId o; + lua_lock(L); + o = index2addr(L, idx); + api_check(L, ttisfulluserdata(o), "full userdata expected"); + getuservalue(L, uvalue(o), L->top); + api_incr_top(L); + lua_unlock(L); + return ttnov(L->top - 1); } @@ -739,159 +824,178 @@ LUA_API int lua_getuservalue (lua_State *L, int idx) { /* ** t[k] = value at the top of the stack (where 'k' is a string) */ -static void auxsetstr (lua_State *L, const TValue *t, const char *k) { - const TValue *slot; - TString *str = luaS_new(L, k); - api_checknelems(L, 1); - if (luaV_fastset(L, t, str, slot, luaH_getstr, L->top - 1)) - L->top--; /* pop value */ - else { - setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */ - api_incr_top(L); - luaV_finishset(L, t, L->top - 1, L->top - 2, slot); - L->top -= 2; /* pop value and key */ - } - lua_unlock(L); /* lock done by caller */ +static void auxsetstr(lua_State* L, const TValue* t, const char* k) +{ + const TValue* slot; + TString* str = luaS_new(L, k); + api_checknelems(L, 1); + if (luaV_fastset(L, t, str, slot, luaH_getstr, L->top - 1)) + L->top--; /* pop value */ + else + { + setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */ + api_incr_top(L); + luaV_finishset(L, t, L->top - 1, L->top - 2, slot); + L->top -= 2; /* pop value and key */ + } + lua_unlock(L); /* lock done by caller */ } -LUA_API void lua_setglobal (lua_State *L, const char *name) { - Table *reg = hvalue(&G(L)->l_registry); - lua_lock(L); /* unlock done in 'auxsetstr' */ - auxsetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); +LUA_API void lua_setglobal(lua_State* L, const char* name) +{ + Table* reg = hvalue(&G(L)->l_registry); + lua_lock(L); /* unlock done in 'auxsetstr' */ + auxsetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); } -LUA_API void lua_settable (lua_State *L, int idx) { - StkId t; - lua_lock(L); - api_checknelems(L, 2); - t = index2addr(L, idx); - luaV_settable(L, t, L->top - 2, L->top - 1); - L->top -= 2; /* pop index and value */ - lua_unlock(L); +LUA_API void lua_settable(lua_State* L, int idx) +{ + StkId t; + lua_lock(L); + api_checknelems(L, 2); + t = index2addr(L, idx); + luaV_settable(L, t, L->top - 2, L->top - 1); + L->top -= 2; /* pop index and value */ + lua_unlock(L); } -LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { - lua_lock(L); /* unlock done in 'auxsetstr' */ - auxsetstr(L, index2addr(L, idx), k); +LUA_API void lua_setfield(lua_State* L, int idx, const char* k) +{ + lua_lock(L); /* unlock done in 'auxsetstr' */ + auxsetstr(L, index2addr(L, idx), k); } -LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { - StkId t; - const TValue *slot; - lua_lock(L); - api_checknelems(L, 1); - t = index2addr(L, idx); - if (luaV_fastset(L, t, n, slot, luaH_getint, L->top - 1)) - L->top--; /* pop value */ - else { - setivalue(L->top, n); - api_incr_top(L); - luaV_finishset(L, t, L->top - 1, L->top - 2, slot); - L->top -= 2; /* pop value and key */ - } - lua_unlock(L); +LUA_API void lua_seti(lua_State* L, int idx, lua_Integer n) +{ + StkId t; + const TValue* slot; + lua_lock(L); + api_checknelems(L, 1); + t = index2addr(L, idx); + if (luaV_fastset(L, t, n, slot, luaH_getint, L->top - 1)) + L->top--; /* pop value */ + else + { + setivalue(L->top, n); + api_incr_top(L); + luaV_finishset(L, t, L->top - 1, L->top - 2, slot); + L->top -= 2; /* pop value and key */ + } + lua_unlock(L); } -LUA_API void lua_rawset (lua_State *L, int idx) { - StkId o; - TValue *slot; - lua_lock(L); - api_checknelems(L, 2); - o = index2addr(L, idx); - api_check(L, ttistable(o), "table expected"); - slot = luaH_set(L, hvalue(o), L->top - 2); - setobj2t(L, slot, L->top - 1); - invalidateTMcache(hvalue(o)); - luaC_barrierback(L, hvalue(o), L->top-1); - L->top -= 2; - lua_unlock(L); +LUA_API void lua_rawset(lua_State* L, int idx) +{ + StkId o; + TValue* slot; + lua_lock(L); + api_checknelems(L, 2); + o = index2addr(L, idx); + api_check(L, ttistable(o), "table expected"); + slot = luaH_set(L, hvalue(o), L->top - 2); + setobj2t(L, slot, L->top - 1); + invalidateTMcache(hvalue(o)); + luaC_barrierback(L, hvalue(o), L->top-1); + L->top -= 2; + lua_unlock(L); } -LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { - StkId o; - lua_lock(L); - api_checknelems(L, 1); - o = index2addr(L, idx); - api_check(L, ttistable(o), "table expected"); - luaH_setint(L, hvalue(o), n, L->top - 1); - luaC_barrierback(L, hvalue(o), L->top-1); - L->top--; - lua_unlock(L); +LUA_API void lua_rawseti(lua_State* L, int idx, lua_Integer n) +{ + StkId o; + lua_lock(L); + api_checknelems(L, 1); + o = index2addr(L, idx); + api_check(L, ttistable(o), "table expected"); + luaH_setint(L, hvalue(o), n, L->top - 1); + luaC_barrierback(L, hvalue(o), L->top-1); + L->top--; + lua_unlock(L); } -LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { - StkId o; - TValue k, *slot; - lua_lock(L); - api_checknelems(L, 1); - o = index2addr(L, idx); - api_check(L, ttistable(o), "table expected"); - setpvalue(&k, cast(void *, p)); - slot = luaH_set(L, hvalue(o), &k); - setobj2t(L, slot, L->top - 1); - luaC_barrierback(L, hvalue(o), L->top - 1); - L->top--; - lua_unlock(L); +LUA_API void lua_rawsetp(lua_State* L, int idx, const void* p) +{ + StkId o; + TValue k, *slot; + lua_lock(L); + api_checknelems(L, 1); + o = index2addr(L, idx); + api_check(L, ttistable(o), "table expected"); + setpvalue(&k, cast(void *, p)); + slot = luaH_set(L, hvalue(o), &k); + setobj2t(L, slot, L->top - 1); + luaC_barrierback(L, hvalue(o), L->top - 1); + L->top--; + lua_unlock(L); } -LUA_API int lua_setmetatable (lua_State *L, int objindex) { - TValue *obj; - Table *mt; - lua_lock(L); - api_checknelems(L, 1); - obj = index2addr(L, objindex); - if (ttisnil(L->top - 1)) - mt = NULL; - else { - api_check(L, ttistable(L->top - 1), "table expected"); - mt = hvalue(L->top - 1); - } - switch (ttnov(obj)) { - case LUA_TTABLE: { - hvalue(obj)->metatable = mt; - if (mt) { - luaC_objbarrier(L, gcvalue(obj), mt); - luaC_checkfinalizer(L, gcvalue(obj), mt); - } - break; - } - case LUA_TUSERDATA: { - uvalue(obj)->metatable = mt; - if (mt) { - luaC_objbarrier(L, uvalue(obj), mt); - luaC_checkfinalizer(L, gcvalue(obj), mt); - } - break; - } - default: { - G(L)->mt[ttnov(obj)] = mt; - break; - } - } - L->top--; - lua_unlock(L); - return 1; +LUA_API int lua_setmetatable(lua_State* L, int objindex) +{ + TValue* obj; + Table* mt; + lua_lock(L); + api_checknelems(L, 1); + obj = index2addr(L, objindex); + if (ttisnil(L->top - 1)) + mt = NULL; + else + { + api_check(L, ttistable(L->top - 1), "table expected"); + mt = hvalue(L->top - 1); + } + switch (ttnov(obj)) + { + case LUA_TTABLE: + { + hvalue(obj)->metatable = mt; + if (mt) + { + luaC_objbarrier(L, gcvalue(obj), mt); + luaC_checkfinalizer(L, gcvalue(obj), mt); + } + break; + } + case LUA_TUSERDATA: + { + uvalue(obj)->metatable = mt; + if (mt) + { + luaC_objbarrier(L, uvalue(obj), mt); + luaC_checkfinalizer(L, gcvalue(obj), mt); + } + break; + } + default: + { + G(L)->mt[ttnov(obj)] = mt; + break; + } + } + L->top--; + lua_unlock(L); + return 1; } -LUA_API void lua_setuservalue (lua_State *L, int idx) { - StkId o; - lua_lock(L); - api_checknelems(L, 1); - o = index2addr(L, idx); - api_check(L, ttisfulluserdata(o), "full userdata expected"); - setuservalue(L, uvalue(o), L->top - 1); - luaC_barrier(L, gcvalue(o), L->top - 1); - L->top--; - lua_unlock(L); +LUA_API void lua_setuservalue(lua_State* L, int idx) +{ + StkId o; + lua_lock(L); + api_checknelems(L, 1); + o = index2addr(L, idx); + api_check(L, ttisfulluserdata(o), "full userdata expected"); + setuservalue(L, uvalue(o), L->top - 1); + luaC_barrier(L, gcvalue(o), L->top - 1); + L->top--; + lua_unlock(L); } @@ -905,130 +1009,147 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) { "results from function overflow current stack size") -LUA_API void lua_callk (lua_State *L, int nargs, int nresults, - lua_KContext ctx, lua_KFunction k) { - StkId func; - lua_lock(L); - api_check(L, k == NULL || !isLua(L->ci), - "cannot use continuations inside hooks"); - api_checknelems(L, nargs+1); - api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); - checkresults(L, nargs, nresults); - func = L->top - (nargs+1); - if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ - L->ci->u.c.k = k; /* save continuation */ - L->ci->u.c.ctx = ctx; /* save context */ - luaD_call(L, func, nresults); /* do the call */ - } - else /* no continuation or no yieldable */ - luaD_callnoyield(L, func, nresults); /* just do the call */ - adjustresults(L, nresults); - lua_unlock(L); +LUA_API void lua_callk(lua_State* L, int nargs, int nresults, + lua_KContext ctx, lua_KFunction k) +{ + StkId func; + lua_lock(L); + api_check(L, k == NULL || !isLua(L->ci), + "cannot use continuations inside hooks"); + api_checknelems(L, nargs+1); + api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); + checkresults(L, nargs, nresults); + func = L->top - (nargs + 1); + if (k != NULL && L->nny == 0) + { + /* need to prepare continuation? */ + L->ci->u.c.k = k; /* save continuation */ + L->ci->u.c.ctx = ctx; /* save context */ + luaD_call(L, func, nresults); /* do the call */ + } + else /* no continuation or no yieldable */ + luaD_callnoyield(L, func, nresults); /* just do the call */ + adjustresults(L, nresults); + lua_unlock(L); } - /* ** Execute a protected call. */ -struct CallS { /* data to 'f_call' */ - StkId func; - int nresults; +struct CallS +{ + /* data to 'f_call' */ + StkId func; + int nresults; }; -static void f_call (lua_State *L, void *ud) { - struct CallS *c = cast(struct CallS *, ud); - luaD_callnoyield(L, c->func, c->nresults); +static void f_call(lua_State* L, void* ud) +{ + struct CallS* c = cast(struct CallS *, ud); + luaD_callnoyield(L, c->func, c->nresults); } - -LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, - lua_KContext ctx, lua_KFunction k) { - struct CallS c; - int status; - ptrdiff_t func; - lua_lock(L); - api_check(L, k == NULL || !isLua(L->ci), - "cannot use continuations inside hooks"); - api_checknelems(L, nargs+1); - api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); - checkresults(L, nargs, nresults); - if (errfunc == 0) - func = 0; - else { - StkId o = index2addr(L, errfunc); - api_checkstackindex(L, errfunc, o); - func = savestack(L, o); - } - c.func = L->top - (nargs+1); /* function to be called */ - if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ - c.nresults = nresults; /* do a 'conventional' protected call */ - status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); - } - else { /* prepare continuation (call is already protected by 'resume') */ - CallInfo *ci = L->ci; - ci->u.c.k = k; /* save continuation */ - ci->u.c.ctx = ctx; /* save context */ - /* save information for error recovery */ - ci->extra = savestack(L, c.func); - ci->u.c.old_errfunc = L->errfunc; - L->errfunc = func; - setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ - ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ - luaD_call(L, c.func, nresults); /* do the call */ - ci->callstatus &= ~CIST_YPCALL; - L->errfunc = ci->u.c.old_errfunc; - status = LUA_OK; /* if it is here, there were no errors */ - } - adjustresults(L, nresults); - lua_unlock(L); - return status; +LUA_API int lua_pcallk(lua_State* L, int nargs, int nresults, int errfunc, + lua_KContext ctx, lua_KFunction k) +{ + struct CallS c; + int status; + ptrdiff_t func; + lua_lock(L); + api_check(L, k == NULL || !isLua(L->ci), + "cannot use continuations inside hooks"); + api_checknelems(L, nargs+1); + api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); + checkresults(L, nargs, nresults); + if (errfunc == 0) + func = 0; + else + { + StkId o = index2addr(L, errfunc); + api_checkstackindex(L, errfunc, o); + func = savestack(L, o); + } + c.func = L->top - (nargs + 1); /* function to be called */ + if (k == NULL || L->nny > 0) + { + /* no continuation or no yieldable? */ + c.nresults = nresults; /* do a 'conventional' protected call */ + status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); + } + else + { + /* prepare continuation (call is already protected by 'resume') */ + CallInfo* ci = L->ci; + ci->u.c.k = k; /* save continuation */ + ci->u.c.ctx = ctx; /* save context */ + /* save information for error recovery */ + ci->extra = savestack(L, c.func); + ci->u.c.old_errfunc = L->errfunc; + L->errfunc = func; + setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ + ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ + luaD_call(L, c.func, nresults); /* do the call */ + ci->callstatus &= ~CIST_YPCALL; + L->errfunc = ci->u.c.old_errfunc; + status = LUA_OK; /* if it is here, there were no errors */ + } + adjustresults(L, nresults); + lua_unlock(L); + return status; } -LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, - const char *chunkname, const char *mode) { - ZIO z; - int status; - lua_lock(L); - if (!chunkname) chunkname = "?"; - luaZ_init(L, &z, reader, data); - status = luaD_protectedparser(L, &z, chunkname, mode); - if (status == LUA_OK) { /* no errors? */ - LClosure *f = clLvalue(L->top - 1); /* get newly created function */ - if (f->nupvalues >= 1) { /* does it have an upvalue? */ - /* get global table from registry */ - Table *reg = hvalue(&G(L)->l_registry); - const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); - /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ - setobj(L, f->upvals[0]->v, gt); - luaC_upvalbarrier(L, f->upvals[0]); - } - } - lua_unlock(L); - return status; +LUA_API int lua_load(lua_State* L, lua_Reader reader, void* data, + const char* chunkname, const char* mode) +{ + ZIO z; + int status; + lua_lock(L); + if (!chunkname) chunkname = "?"; + luaZ_init(L, &z, reader, data); + status = luaD_protectedparser(L, &z, chunkname, mode); + if (status == LUA_OK) + { + /* no errors? */ + LClosure* f = clLvalue(L->top - 1); /* get newly created function */ + if (f->nupvalues >= 1) + { + /* does it have an upvalue? */ + /* get global table from registry */ + Table* reg = hvalue(&G(L)->l_registry); + const TValue* gt = luaH_getint(reg, LUA_RIDX_GLOBALS); + /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ + setobj(L, f->upvals[0]->v, gt); + luaC_upvalbarrier(L, f->upvals[0]); + } + } + lua_unlock(L); + return status; } -LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { - int status; - TValue *o; - lua_lock(L); - api_checknelems(L, 1); - o = L->top - 1; - if (isLfunction(o)) - status = luaU_dump(L, getproto(o), writer, data, strip); - else - status = 1; - lua_unlock(L); - return status; +LUA_API int lua_dump(lua_State* L, lua_Writer writer, void* data, int strip) +{ + int status; + TValue* o; + lua_lock(L); + api_checknelems(L, 1); + o = L->top - 1; + if (isLfunction(o)) + status = luaU_dump(L, getproto(o), writer, data, strip); + else + status = 1; + lua_unlock(L); + return status; } -LUA_API int lua_status (lua_State *L) { - return L->status; +LUA_API int lua_status(lua_State* L) +{ + return L->status; } @@ -1036,263 +1157,303 @@ LUA_API int lua_status (lua_State *L) { ** Garbage-collection function */ -LUA_API int lua_gc (lua_State *L, int what, int data) { - int res = 0; - global_State *g; - lua_lock(L); - g = G(L); - switch (what) { - case LUA_GCSTOP: { - g->gcrunning = 0; - break; - } - case LUA_GCRESTART: { - luaE_setdebt(g, 0); - g->gcrunning = 1; - break; - } - case LUA_GCCOLLECT: { - luaC_fullgc(L, 0); - break; - } - case LUA_GCCOUNT: { - /* GC values are expressed in Kbytes: #bytes/2^10 */ - res = cast_int(gettotalbytes(g) >> 10); - break; - } - case LUA_GCCOUNTB: { - res = cast_int(gettotalbytes(g) & 0x3ff); - break; - } - case LUA_GCSTEP: { - l_mem debt = 1; /* =1 to signal that it did an actual step */ - lu_byte oldrunning = g->gcrunning; - g->gcrunning = 1; /* allow GC to run */ - if (data == 0) { - luaE_setdebt(g, -GCSTEPSIZE); /* to do a "small" step */ - luaC_step(L); - } - else { /* add 'data' to total debt */ - debt = cast(l_mem, data) * 1024 + g->GCdebt; - luaE_setdebt(g, debt); - luaC_checkGC(L); - } - g->gcrunning = oldrunning; /* restore previous state */ - if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */ - res = 1; /* signal it */ - break; - } - case LUA_GCSETPAUSE: { - res = g->gcpause; - g->gcpause = data; - break; - } - case LUA_GCSETSTEPMUL: { - res = g->gcstepmul; - if (data < 40) data = 40; /* avoid ridiculous low values (and 0) */ - g->gcstepmul = data; - break; - } - case LUA_GCISRUNNING: { - res = g->gcrunning; - break; - } - default: res = -1; /* invalid option */ - } - lua_unlock(L); - return res; +LUA_API int lua_gc(lua_State* L, int what, int data) +{ + int res = 0; + global_State* g; + lua_lock(L); + g = G(L); + switch (what) + { + case LUA_GCSTOP: + { + g->gcrunning = 0; + break; + } + case LUA_GCRESTART: + { + luaE_setdebt(g, 0); + g->gcrunning = 1; + break; + } + case LUA_GCCOLLECT: + { + luaC_fullgc(L, 0); + break; + } + case LUA_GCCOUNT: + { + /* GC values are expressed in Kbytes: #bytes/2^10 */ + res = cast_int(gettotalbytes(g) >> 10); + break; + } + case LUA_GCCOUNTB: + { + res = cast_int(gettotalbytes(g) & 0x3ff); + break; + } + case LUA_GCSTEP: + { + l_mem debt = 1; /* =1 to signal that it did an actual step */ + lu_byte oldrunning = g->gcrunning; + g->gcrunning = 1; /* allow GC to run */ + if (data == 0) + { + luaE_setdebt(g, -GCSTEPSIZE); /* to do a "small" step */ + luaC_step(L); + } + else + { + /* add 'data' to total debt */ + debt = cast(l_mem, data) * 1024 + g->GCdebt; + luaE_setdebt(g, debt); + luaC_checkGC(L); + } + g->gcrunning = oldrunning; /* restore previous state */ + if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */ + res = 1; /* signal it */ + break; + } + case LUA_GCSETPAUSE: + { + res = g->gcpause; + g->gcpause = data; + break; + } + case LUA_GCSETSTEPMUL: + { + res = g->gcstepmul; + if (data < 40) data = 40; /* avoid ridiculous low values (and 0) */ + g->gcstepmul = data; + break; + } + case LUA_GCISRUNNING: + { + res = g->gcrunning; + break; + } + default: res = -1; /* invalid option */ + } + lua_unlock(L); + return res; } - /* ** miscellaneous functions */ -LUA_API int lua_error (lua_State *L) { - lua_lock(L); - api_checknelems(L, 1); - luaG_errormsg(L); - /* code unreachable; will unlock when control actually leaves the kernel */ - return 0; /* to avoid warnings */ +LUA_API int lua_error(lua_State* L) +{ + lua_lock(L); + api_checknelems(L, 1); + luaG_errormsg(L); + /* code unreachable; will unlock when control actually leaves the kernel */ + return 0; /* to avoid warnings */ } -LUA_API int lua_next (lua_State *L, int idx) { - StkId t; - int more; - lua_lock(L); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - more = luaH_next(L, hvalue(t), L->top - 1); - if (more) { - api_incr_top(L); - } - else /* no more elements */ - L->top -= 1; /* remove key */ - lua_unlock(L); - return more; +LUA_API int lua_next(lua_State* L, int idx) +{ + StkId t; + int more; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + more = luaH_next(L, hvalue(t), L->top - 1); + if (more) + { + api_incr_top(L); + } + else /* no more elements */ + L->top -= 1; /* remove key */ + lua_unlock(L); + return more; } -LUA_API void lua_concat (lua_State *L, int n) { - lua_lock(L); - api_checknelems(L, n); - if (n >= 2) { - luaV_concat(L, n); - } - else if (n == 0) { /* push empty string */ - setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); - api_incr_top(L); - } - /* else n == 1; nothing to do */ - luaC_checkGC(L); - lua_unlock(L); +LUA_API void lua_concat(lua_State* L, int n) +{ + lua_lock(L); + api_checknelems(L, n); + if (n >= 2) + { + luaV_concat(L, n); + } + else if (n == 0) + { + /* push empty string */ + setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); + api_incr_top(L); + } + /* else n == 1; nothing to do */ + luaC_checkGC(L); + lua_unlock(L); } -LUA_API void lua_len (lua_State *L, int idx) { - StkId t; - lua_lock(L); - t = index2addr(L, idx); - luaV_objlen(L, L->top, t); - api_incr_top(L); - lua_unlock(L); +LUA_API void lua_len(lua_State* L, int idx) +{ + StkId t; + lua_lock(L); + t = index2addr(L, idx); + luaV_objlen(L, L->top, t); + api_incr_top(L); + lua_unlock(L); } -LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { - lua_Alloc f; - lua_lock(L); - if (ud) *ud = G(L)->ud; - f = G(L)->frealloc; - lua_unlock(L); - return f; +LUA_API lua_Alloc lua_getallocf(lua_State* L, void** ud) +{ + lua_Alloc f; + lua_lock(L); + if (ud) *ud = G(L)->ud; + f = G(L)->frealloc; + lua_unlock(L); + return f; } -LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { - lua_lock(L); - G(L)->ud = ud; - G(L)->frealloc = f; - lua_unlock(L); +LUA_API void lua_setallocf(lua_State* L, lua_Alloc f, void* ud) +{ + lua_lock(L); + G(L)->ud = ud; + G(L)->frealloc = f; + lua_unlock(L); } -LUA_API void *lua_newuserdata (lua_State *L, size_t size) { - Udata *u; - lua_lock(L); - u = luaS_newudata(L, size); - setuvalue(L, L->top, u); - api_incr_top(L); - luaC_checkGC(L); - lua_unlock(L); - return getudatamem(u); +LUA_API void* lua_newuserdata(lua_State* L, size_t size) +{ + Udata* u; + lua_lock(L); + u = luaS_newudata(L, size); + setuvalue(L, L->top, u); + api_incr_top(L); + luaC_checkGC(L); + lua_unlock(L); + return getudatamem(u); } - -static const char *aux_upvalue (StkId fi, int n, TValue **val, - CClosure **owner, UpVal **uv) { - switch (ttype(fi)) { - case LUA_TCCL: { /* C closure */ - CClosure *f = clCvalue(fi); - if (!(1 <= n && n <= f->nupvalues)) return NULL; - *val = &f->upvalue[n-1]; - if (owner) *owner = f; - return ""; - } - case LUA_TLCL: { /* Lua closure */ - LClosure *f = clLvalue(fi); - TString *name; - Proto *p = f->p; - if (!(1 <= n && n <= p->sizeupvalues)) return NULL; - *val = f->upvals[n-1]->v; - if (uv) *uv = f->upvals[n - 1]; - name = p->upvalues[n-1].name; - return (name == NULL) ? "(*no name)" : getstr(name); - } - default: return NULL; /* not a closure */ - } +static const char* aux_upvalue(StkId fi, int n, TValue** val, + CClosure** owner, UpVal** uv) +{ + switch (ttype(fi)) + { + case LUA_TCCL: + { + /* C closure */ + CClosure* f = clCvalue(fi); + if (!(1 <= n && n <= f->nupvalues)) return NULL; + *val = &f->upvalue[n - 1]; + if (owner) *owner = f; + return ""; + } + case LUA_TLCL: + { + /* Lua closure */ + LClosure* f = clLvalue(fi); + TString* name; + Proto* p = f->p; + if (!(1 <= n && n <= p->sizeupvalues)) return NULL; + *val = f->upvals[n - 1]->v; + if (uv) *uv = f->upvals[n - 1]; + name = p->upvalues[n - 1].name; + return (name == NULL) ? "(*no name)" : getstr(name); + } + default: return NULL; /* not a closure */ + } } -LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { - const char *name; - TValue *val = NULL; /* to avoid warnings */ - lua_lock(L); - name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL, NULL); - if (name) { - setobj2s(L, L->top, val); - api_incr_top(L); - } - lua_unlock(L); - return name; +LUA_API const char* lua_getupvalue(lua_State* L, int funcindex, int n) +{ + const char* name; + TValue* val = NULL; /* to avoid warnings */ + lua_lock(L); + name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL, NULL); + if (name) + { + setobj2s(L, L->top, val); + api_incr_top(L); + } + lua_unlock(L); + return name; } -LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { - const char *name; - TValue *val = NULL; /* to avoid warnings */ - CClosure *owner = NULL; - UpVal *uv = NULL; - StkId fi; - lua_lock(L); - fi = index2addr(L, funcindex); - api_checknelems(L, 1); - name = aux_upvalue(fi, n, &val, &owner, &uv); - if (name) { - L->top--; - setobj(L, val, L->top); - if (owner) { luaC_barrier(L, owner, L->top); } - else if (uv) { luaC_upvalbarrier(L, uv); } - } - lua_unlock(L); - return name; +LUA_API const char* lua_setupvalue(lua_State* L, int funcindex, int n) +{ + const char* name; + TValue* val = NULL; /* to avoid warnings */ + CClosure* owner = NULL; + UpVal* uv = NULL; + StkId fi; + lua_lock(L); + fi = index2addr(L, funcindex); + api_checknelems(L, 1); + name = aux_upvalue(fi, n, &val, &owner, &uv); + if (name) + { + L->top--; + setobj(L, val, L->top); + if (owner) { luaC_barrier(L, owner, L->top); } + else if (uv) { luaC_upvalbarrier(L, uv); } + } + lua_unlock(L); + return name; } -static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { - LClosure *f; - StkId fi = index2addr(L, fidx); - api_check(L, ttisLclosure(fi), "Lua function expected"); - f = clLvalue(fi); - api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); - if (pf) *pf = f; - return &f->upvals[n - 1]; /* get its upvalue pointer */ +static UpVal** getupvalref(lua_State* L, int fidx, int n, LClosure** pf) +{ + LClosure* f; + StkId fi = index2addr(L, fidx); + api_check(L, ttisLclosure(fi), "Lua function expected"); + f = clLvalue(fi); + api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); + if (pf) *pf = f; + return &f->upvals[n - 1]; /* get its upvalue pointer */ } -LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { - StkId fi = index2addr(L, fidx); - switch (ttype(fi)) { - case LUA_TLCL: { /* lua closure */ - return *getupvalref(L, fidx, n, NULL); - } - case LUA_TCCL: { /* C closure */ - CClosure *f = clCvalue(fi); - api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); - return &f->upvalue[n - 1]; - } - default: { - api_check(L, 0, "closure expected"); - return NULL; - } - } +LUA_API void* lua_upvalueid(lua_State* L, int fidx, int n) +{ + StkId fi = index2addr(L, fidx); + switch (ttype(fi)) + { + case LUA_TLCL: + { + /* lua closure */ + return *getupvalref(L, fidx, n, NULL); + } + case LUA_TCCL: + { + /* C closure */ + CClosure* f = clCvalue(fi); + api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); + return &f->upvalue[n - 1]; + } + default: + { + api_check(L, 0, "closure expected"); + return NULL; + } + } } -LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, - int fidx2, int n2) { - LClosure *f1; - UpVal **up1 = getupvalref(L, fidx1, n1, &f1); - UpVal **up2 = getupvalref(L, fidx2, n2, NULL); - luaC_upvdeccount(L, *up1); - *up1 = *up2; - (*up1)->refcount++; - if (upisopen(*up1)) (*up1)->u.open.touched = 1; - luaC_upvalbarrier(L, *up1); +LUA_API void lua_upvaluejoin(lua_State* L, int fidx1, int n1, + int fidx2, int n2) +{ + LClosure* f1; + UpVal** up1 = getupvalref(L, fidx1, n1, &f1); + UpVal** up2 = getupvalref(L, fidx2, n2, NULL); + luaC_upvdeccount(L, *up1); + *up1 = *up2; + (*up1)->refcount++; + if (upisopen(*up1)) (*up1)->u.open.touched = 1; + luaC_upvalbarrier(L, *up1); } - - diff --git a/Lua/lauxlib.c b/Lua/lauxlib.c index f7a3836..69e83a0 100644 --- a/Lua/lauxlib.c +++ b/Lua/lauxlib.c @@ -38,118 +38,145 @@ #define LEVELS2 11 /* size of the second part of the stack */ - /* ** search for 'objidx' in table at index -1. ** return 1 + string at top if find a good name. */ -static int findfield (lua_State *L, int objidx, int level) { - if (level == 0 || !lua_istable(L, -1)) - return 0; /* not found */ - lua_pushnil(L); /* start 'next' loop */ - while (lua_next(L, -2)) { /* for each pair in table */ - if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ - if (lua_rawequal(L, objidx, -1)) { /* found object? */ - lua_pop(L, 1); /* remove value (but keep name) */ - return 1; - } - else if (findfield(L, objidx, level - 1)) { /* try recursively */ - lua_remove(L, -2); /* remove table (but keep name) */ - lua_pushliteral(L, "."); - lua_insert(L, -2); /* place '.' between the two names */ - lua_concat(L, 3); - return 1; - } - } - lua_pop(L, 1); /* remove value */ - } - return 0; /* not found */ +static int findfield(lua_State* L, int objidx, int level) +{ + if (level == 0 || !lua_istable(L, -1)) + return 0; /* not found */ + lua_pushnil(L); /* start 'next' loop */ + while (lua_next(L, -2)) + { + /* for each pair in table */ + if (lua_type(L, -2) == LUA_TSTRING) + { + /* ignore non-string keys */ + if (lua_rawequal(L, objidx, -1)) + { + /* found object? */ + lua_pop(L, 1); /* remove value (but keep name) */ + return 1; + } + else if (findfield(L, objidx, level - 1)) + { + /* try recursively */ + lua_remove(L, -2); /* remove table (but keep name) */ + lua_pushliteral(L, "."); + lua_insert(L, -2); /* place '.' between the two names */ + lua_concat(L, 3); + return 1; + } + } + lua_pop(L, 1); /* remove value */ + } + return 0; /* not found */ } /* ** Search for a name for a function in all loaded modules */ -static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { - int top = lua_gettop(L); - lua_getinfo(L, "f", ar); /* push function */ - lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); - if (findfield(L, top + 1, 2)) { - const char *name = lua_tostring(L, -1); - if (strncmp(name, "_G.", 3) == 0) { /* name start with '_G.'? */ - lua_pushstring(L, name + 3); /* push name without prefix */ - lua_remove(L, -2); /* remove original name */ - } - lua_copy(L, -1, top + 1); /* move name to proper place */ - lua_pop(L, 2); /* remove pushed values */ - return 1; - } - else { - lua_settop(L, top); /* remove function and global table */ - return 0; - } +static int pushglobalfuncname(lua_State* L, lua_Debug* ar) +{ + int top = lua_gettop(L); + lua_getinfo(L, "f", ar); /* push function */ + lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + if (findfield(L, top + 1, 2)) + { + const char* name = lua_tostring(L, -1); + if (strncmp(name, "_G.", 3) == 0) + { + /* name start with '_G.'? */ + lua_pushstring(L, name + 3); /* push name without prefix */ + lua_remove(L, -2); /* remove original name */ + } + lua_copy(L, -1, top + 1); /* move name to proper place */ + lua_pop(L, 2); /* remove pushed values */ + return 1; + } + else + { + lua_settop(L, top); /* remove function and global table */ + return 0; + } } -static void pushfuncname (lua_State *L, lua_Debug *ar) { - if (pushglobalfuncname(L, ar)) { /* try first a global name */ - lua_pushfstring(L, "function '%s'", lua_tostring(L, -1)); - lua_remove(L, -2); /* remove name */ - } - else if (*ar->namewhat != '\0') /* is there a name from code? */ - lua_pushfstring(L, "%s '%s'", ar->namewhat, ar->name); /* use it */ - else if (*ar->what == 'm') /* main? */ - lua_pushliteral(L, "main chunk"); - else if (*ar->what != 'C') /* for Lua functions, use */ - lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); - else /* nothing left... */ - lua_pushliteral(L, "?"); +static void pushfuncname(lua_State* L, lua_Debug* ar) +{ + if (pushglobalfuncname(L, ar)) + { + /* try first a global name */ + lua_pushfstring(L, "function '%s'", lua_tostring(L, -1)); + lua_remove(L, -2); /* remove name */ + } + else if (*ar->namewhat != '\0') /* is there a name from code? */ + lua_pushfstring(L, "%s '%s'", ar->namewhat, ar->name); /* use it */ + else if (*ar->what == 'm') /* main? */ + lua_pushliteral(L, "main chunk"); + else if (*ar->what != 'C') /* for Lua functions, use */ + lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); + else /* nothing left... */ + lua_pushliteral(L, "?"); } -static int lastlevel (lua_State *L) { - lua_Debug ar; - int li = 1, le = 1; - /* find an upper bound */ - while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } - /* do a binary search */ - while (li < le) { - int m = (li + le)/2; - if (lua_getstack(L, m, &ar)) li = m + 1; - else le = m; - } - return le - 1; +static int lastlevel(lua_State* L) +{ + lua_Debug ar; + int li = 1, le = 1; + /* find an upper bound */ + while (lua_getstack(L, le, &ar)) + { + li = le; + le *= 2; + } + /* do a binary search */ + while (li < le) + { + int m = (li + le) / 2; + if (lua_getstack(L, m, &ar)) li = m + 1; + else le = m; + } + return le - 1; } -LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, - const char *msg, int level) { - lua_Debug ar; - int top = lua_gettop(L); - int last = lastlevel(L1); - int n1 = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1; - if (msg) - lua_pushfstring(L, "%s\n", msg); - luaL_checkstack(L, 10, NULL); - lua_pushliteral(L, "stack traceback:"); - while (lua_getstack(L1, level++, &ar)) { - if (n1-- == 0) { /* too many levels? */ - lua_pushliteral(L, "\n\t..."); /* add a '...' */ - level = last - LEVELS2 + 1; /* and skip to last ones */ - } - else { - lua_getinfo(L1, "Slnt", &ar); - lua_pushfstring(L, "\n\t%s:", ar.short_src); - if (ar.currentline > 0) - lua_pushfstring(L, "%d:", ar.currentline); - lua_pushliteral(L, " in "); - pushfuncname(L, &ar); - if (ar.istailcall) - lua_pushliteral(L, "\n\t(...tail calls...)"); - lua_concat(L, lua_gettop(L) - top); - } - } - lua_concat(L, lua_gettop(L) - top); +LUALIB_API void luaL_traceback(lua_State* L, lua_State* L1, + const char* msg, int level) +{ + lua_Debug ar; + int top = lua_gettop(L); + int last = lastlevel(L1); + int n1 = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1; + if (msg) + lua_pushfstring(L, "%s\n", msg); + luaL_checkstack(L, 10, NULL); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) + { + if (n1-- == 0) + { + /* too many levels? */ + lua_pushliteral(L, "\n\t..."); /* add a '...' */ + level = last - LEVELS2 + 1; /* and skip to last ones */ + } + else + { + lua_getinfo(L1, "Slnt", &ar); + lua_pushfstring(L, "\n\t%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + lua_pushliteral(L, " in "); + pushfuncname(L, &ar); + if (ar.istailcall) + lua_pushliteral(L, "\n\t(...tail calls...)"); + lua_concat(L, lua_gettop(L) - top); + } + } + lua_concat(L, lua_gettop(L) - top); } /* }====================================================== */ @@ -161,40 +188,44 @@ LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, ** ======================================================= */ -LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) { - lua_Debug ar; - if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ - return luaL_error(L, "bad argument #%d (%s)", arg, extramsg); - lua_getinfo(L, "n", &ar); - if (strcmp(ar.namewhat, "method") == 0) { - arg--; /* do not count 'self' */ - if (arg == 0) /* error is in the self argument itself? */ - return luaL_error(L, "calling '%s' on bad self (%s)", - ar.name, extramsg); - } - if (ar.name == NULL) - ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; - return luaL_error(L, "bad argument #%d to '%s' (%s)", - arg, ar.name, extramsg); +LUALIB_API int luaL_argerror(lua_State* L, int arg, const char* extramsg) +{ + lua_Debug ar; + if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ + return luaL_error(L, "bad argument #%d (%s)", arg, extramsg); + lua_getinfo(L, "n", &ar); + if (strcmp(ar.namewhat, "method") == 0) + { + arg--; /* do not count 'self' */ + if (arg == 0) /* error is in the self argument itself? */ + return luaL_error(L, "calling '%s' on bad self (%s)", + ar.name, extramsg); + } + if (ar.name == NULL) + ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; + return luaL_error(L, "bad argument #%d to '%s' (%s)", + arg, ar.name, extramsg); } -static int typeerror (lua_State *L, int arg, const char *tname) { - const char *msg; - const char *typearg; /* name for the type of the actual argument */ - if (luaL_getmetafield(L, arg, "__name") == LUA_TSTRING) - typearg = lua_tostring(L, -1); /* use the given type name */ - else if (lua_type(L, arg) == LUA_TLIGHTUSERDATA) - typearg = "light userdata"; /* special name for messages */ - else - typearg = luaL_typename(L, arg); /* standard name */ - msg = lua_pushfstring(L, "%s expected, got %s", tname, typearg); - return luaL_argerror(L, arg, msg); +static int typeerror(lua_State* L, int arg, const char* tname) +{ + const char* msg; + const char* typearg; /* name for the type of the actual argument */ + if (luaL_getmetafield(L, arg, "__name") == LUA_TSTRING) + typearg = lua_tostring(L, -1); /* use the given type name */ + else if (lua_type(L, arg) == LUA_TLIGHTUSERDATA) + typearg = "light userdata"; /* special name for messages */ + else + typearg = luaL_typename(L, arg); /* standard name */ + msg = lua_pushfstring(L, "%s expected, got %s", tname, typearg); + return luaL_argerror(L, arg, msg); } -static void tag_error (lua_State *L, int arg, int tag) { - typeerror(L, arg, lua_typename(L, tag)); +static void tag_error(lua_State* L, int arg, int tag) +{ + typeerror(L, arg, lua_typename(L, tag)); } @@ -202,16 +233,21 @@ static void tag_error (lua_State *L, int arg, int tag) { ** The use of 'lua_pushfstring' ensures this function does not ** need reserved stack space when called. */ -LUALIB_API void luaL_where (lua_State *L, int level) { - lua_Debug ar; - if (lua_getstack(L, level, &ar)) { /* check function at level */ - lua_getinfo(L, "Sl", &ar); /* get info about it */ - if (ar.currentline > 0) { /* is there info? */ - lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); - return; - } - } - lua_pushfstring(L, ""); /* else, no information available... */ +LUALIB_API void luaL_where(lua_State* L, int level) +{ + lua_Debug ar; + if (lua_getstack(L, level, &ar)) + { + /* check function at level */ + lua_getinfo(L, "Sl", &ar); /* get info about it */ + if (ar.currentline > 0) + { + /* is there info? */ + lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); + return; + } + } + lua_pushfstring(L, ""); /* else, no information available... */ } @@ -220,32 +256,36 @@ LUALIB_API void luaL_where (lua_State *L, int level) { ** not need reserved stack space when called. (At worst, it generates ** an error with "stack overflow" instead of the given message.) */ -LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { - va_list argp; - va_start(argp, fmt); - luaL_where(L, 1); - lua_pushvfstring(L, fmt, argp); - va_end(argp); - lua_concat(L, 2); - return lua_error(L); +LUALIB_API int luaL_error(lua_State* L, const char* fmt, ...) +{ + va_list argp; + va_start(argp, fmt); + luaL_where(L, 1); + lua_pushvfstring(L, fmt, argp); + va_end(argp); + lua_concat(L, 2); + return lua_error(L); } -LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { - int en = errno; /* calls to Lua API may change this value */ - if (stat) { - lua_pushboolean(L, 1); - return 1; - } - else { - lua_pushnil(L); - if (fname) - lua_pushfstring(L, "%s: %s", fname, strerror(en)); - else - lua_pushstring(L, strerror(en)); - lua_pushinteger(L, en); - return 3; - } +LUALIB_API int luaL_fileresult(lua_State* L, int stat, const char* fname) +{ + int en = errno; /* calls to Lua API may change this value */ + if (stat) + { + lua_pushboolean(L, 1); + return 1; + } + else + { + lua_pushnil(L); + if (fname) + lua_pushfstring(L, "%s: %s", fname, strerror(en)); + else + lua_pushstring(L, strerror(en)); + lua_pushinteger(L, en); + return 3; + } } @@ -271,20 +311,22 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { #endif /* } */ -LUALIB_API int luaL_execresult (lua_State *L, int stat) { - const char *what = "exit"; /* type of termination */ - if (stat == -1) /* error? */ - return luaL_fileresult(L, 0, NULL); - else { - l_inspectstat(stat, what); /* interpret result */ - if (*what == 'e' && stat == 0) /* successful termination? */ - lua_pushboolean(L, 1); - else - lua_pushnil(L); - lua_pushstring(L, what); - lua_pushinteger(L, stat); - return 3; /* return true/nil,what,code */ - } +LUALIB_API int luaL_execresult(lua_State* L, int stat) +{ + const char* what = "exit"; /* type of termination */ + if (stat == -1) /* error? */ + return luaL_fileresult(L, 0, NULL); + else + { + l_inspectstat(stat, what); /* interpret result */ + if (*what == 'e' && stat == 0) /* successful termination? */ + lua_pushboolean(L, 1); + else + lua_pushnil(L); + lua_pushstring(L, what); + lua_pushinteger(L, stat); + return 3; /* return true/nil,what,code */ + } } /* }====================================================== */ @@ -296,44 +338,52 @@ LUALIB_API int luaL_execresult (lua_State *L, int stat) { ** ======================================================= */ -LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { - if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */ - return 0; /* leave previous value on top, but return 0 */ - lua_pop(L, 1); - lua_createtable(L, 0, 2); /* create metatable */ - lua_pushstring(L, tname); - lua_setfield(L, -2, "__name"); /* metatable.__name = tname */ - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ - return 1; +LUALIB_API int luaL_newmetatable(lua_State* L, const char* tname) +{ + if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */ + return 0; /* leave previous value on top, but return 0 */ + lua_pop(L, 1); + lua_createtable(L, 0, 2); /* create metatable */ + lua_pushstring(L, tname); + lua_setfield(L, -2, "__name"); /* metatable.__name = tname */ + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ + return 1; } -LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) { - luaL_getmetatable(L, tname); - lua_setmetatable(L, -2); +LUALIB_API void luaL_setmetatable(lua_State* L, const char* tname) +{ + luaL_getmetatable(L, tname); + lua_setmetatable(L, -2); } -LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) { - void *p = lua_touserdata(L, ud); - if (p != NULL) { /* value is a userdata? */ - if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ - luaL_getmetatable(L, tname); /* get correct metatable */ - if (!lua_rawequal(L, -1, -2)) /* not the same? */ - p = NULL; /* value is a userdata with wrong metatable */ - lua_pop(L, 2); /* remove both metatables */ - return p; - } - } - return NULL; /* value is not a userdata with a metatable */ +LUALIB_API void* luaL_testudata(lua_State* L, int ud, const char* tname) +{ + void* p = lua_touserdata(L, ud); + if (p != NULL) + { + /* value is a userdata? */ + if (lua_getmetatable(L, ud)) + { + /* does it have a metatable? */ + luaL_getmetatable(L, tname); /* get correct metatable */ + if (!lua_rawequal(L, -1, -2)) /* not the same? */ + p = NULL; /* value is a userdata with wrong metatable */ + lua_pop(L, 2); /* remove both metatables */ + return p; + } + } + return NULL; /* value is not a userdata with a metatable */ } -LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { - void *p = luaL_testudata(L, ud, tname); - if (p == NULL) typeerror(L, ud, tname); - return p; +LUALIB_API void* luaL_checkudata(lua_State* L, int ud, const char* tname) +{ + void* p = luaL_testudata(L, ud, tname); + if (p == NULL) typeerror(L, ud, tname); + return p; } /* }====================================================== */ @@ -345,16 +395,16 @@ LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { ** ======================================================= */ -LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def, - const char *const lst[]) { - const char *name = (def) ? luaL_optstring(L, arg, def) : - luaL_checkstring(L, arg); - int i; - for (i=0; lst[i]; i++) - if (strcmp(lst[i], name) == 0) - return i; - return luaL_argerror(L, arg, - lua_pushfstring(L, "invalid option '%s'", name)); +LUALIB_API int luaL_checkoption(lua_State* L, int arg, const char* def, + const char* const lst[]) +{ + const char* name = (def) ? luaL_optstring(L, arg, def) : luaL_checkstring(L, arg); + int i; + for (i = 0; lst[i]; i++) + if (strcmp(lst[i], name) == 0) + return i; + return luaL_argerror(L, arg, + lua_pushfstring(L, "invalid option '%s'", name)); } @@ -365,81 +415,94 @@ LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def, ** this extra space, Lua will generate the same 'stack overflow' error, ** but without 'msg'.) */ -LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) { - if (!lua_checkstack(L, space)) { - if (msg) - luaL_error(L, "stack overflow (%s)", msg); - else - luaL_error(L, "stack overflow"); - } +LUALIB_API void luaL_checkstack(lua_State* L, int space, const char* msg) +{ + if (!lua_checkstack(L, space)) + { + if (msg) + luaL_error(L, "stack overflow (%s)", msg); + else + luaL_error(L, "stack overflow"); + } } -LUALIB_API void luaL_checktype (lua_State *L, int arg, int t) { - if (lua_type(L, arg) != t) - tag_error(L, arg, t); +LUALIB_API void luaL_checktype(lua_State* L, int arg, int t) +{ + if (lua_type(L, arg) != t) + tag_error(L, arg, t); } -LUALIB_API void luaL_checkany (lua_State *L, int arg) { - if (lua_type(L, arg) == LUA_TNONE) - luaL_argerror(L, arg, "value expected"); +LUALIB_API void luaL_checkany(lua_State* L, int arg) +{ + if (lua_type(L, arg) == LUA_TNONE) + luaL_argerror(L, arg, "value expected"); } -LUALIB_API const char *luaL_checklstring (lua_State *L, int arg, size_t *len) { - const char *s = lua_tolstring(L, arg, len); - if (!s) tag_error(L, arg, LUA_TSTRING); - return s; +LUALIB_API const char* luaL_checklstring(lua_State* L, int arg, size_t* len) +{ + const char* s = lua_tolstring(L, arg, len); + if (!s) tag_error(L, arg, LUA_TSTRING); + return s; } -LUALIB_API const char *luaL_optlstring (lua_State *L, int arg, - const char *def, size_t *len) { - if (lua_isnoneornil(L, arg)) { - if (len) - *len = (def ? strlen(def) : 0); - return def; - } - else return luaL_checklstring(L, arg, len); +LUALIB_API const char* luaL_optlstring(lua_State* L, int arg, + const char* def, size_t* len) +{ + if (lua_isnoneornil(L, arg)) + { + if (len) + *len = (def ? strlen(def) : 0); + return def; + } + else return luaL_checklstring(L, arg, len); } -LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) { - int isnum; - lua_Number d = lua_tonumberx(L, arg, &isnum); - if (!isnum) - tag_error(L, arg, LUA_TNUMBER); - return d; +LUALIB_API lua_Number luaL_checknumber(lua_State* L, int arg) +{ + int isnum; + lua_Number d = lua_tonumberx(L, arg, &isnum); + if (!isnum) + tag_error(L, arg, LUA_TNUMBER); + return d; } -LUALIB_API lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number def) { - return luaL_opt(L, luaL_checknumber, arg, def); +LUALIB_API lua_Number luaL_optnumber(lua_State* L, int arg, lua_Number def) +{ + return luaL_opt(L, luaL_checknumber, arg, def); } -static void interror (lua_State *L, int arg) { - if (lua_isnumber(L, arg)) - luaL_argerror(L, arg, "number has no integer representation"); - else - tag_error(L, arg, LUA_TNUMBER); +static void interror(lua_State* L, int arg) +{ + if (lua_isnumber(L, arg)) + luaL_argerror(L, arg, "number has no integer representation"); + else + tag_error(L, arg, LUA_TNUMBER); } -LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) { - int isnum; - lua_Integer d = lua_tointegerx(L, arg, &isnum); - if (!isnum) { - interror(L, arg); - } - return d; +LUALIB_API lua_Integer luaL_checkinteger(lua_State* L, int arg) +{ + int isnum; + lua_Integer d = lua_tointegerx(L, arg, &isnum); + if (!isnum) + { + interror(L, arg); + } + return d; } -LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg, - lua_Integer def) { - return luaL_opt(L, luaL_checkinteger, arg, def); +LUALIB_API lua_Integer luaL_optinteger(lua_State* L, int arg, + lua_Integer def) +{ + return luaL_opt(L, luaL_checkinteger, arg, def); } /* }====================================================== */ @@ -452,43 +515,51 @@ LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg, */ /* userdata to box arbitrary data */ -typedef struct UBox { - void *box; - size_t bsize; +typedef struct UBox +{ + void* box; + size_t bsize; } UBox; -static void *resizebox (lua_State *L, int idx, size_t newsize) { - void *ud; - lua_Alloc allocf = lua_getallocf(L, &ud); - UBox *box = (UBox *)lua_touserdata(L, idx); - void *temp = allocf(ud, box->box, box->bsize, newsize); - if (temp == NULL && newsize > 0) { /* allocation error? */ - resizebox(L, idx, 0); /* free buffer */ - luaL_error(L, "not enough memory for buffer allocation"); - } - box->box = temp; - box->bsize = newsize; - return temp; +static void* resizebox(lua_State* L, int idx, size_t newsize) +{ + void* ud; + lua_Alloc allocf = lua_getallocf(L, &ud); + UBox* box = (UBox*)lua_touserdata(L, idx); + void* temp = allocf(ud, box->box, box->bsize, newsize); + if (temp == NULL && newsize > 0) + { + /* allocation error? */ + resizebox(L, idx, 0); /* free buffer */ + luaL_error(L, "not enough memory for buffer allocation"); + } + box->box = temp; + box->bsize = newsize; + return temp; } -static int boxgc (lua_State *L) { - resizebox(L, 1, 0); - return 0; +static int boxgc(lua_State* L) +{ + resizebox(L, 1, 0); + return 0; } -static void *newbox (lua_State *L, size_t newsize) { - UBox *box = (UBox *)lua_newuserdata(L, sizeof(UBox)); - box->box = NULL; - box->bsize = 0; - if (luaL_newmetatable(L, "LUABOX")) { /* creating metatable? */ - lua_pushcfunction(L, boxgc); - lua_setfield(L, -2, "__gc"); /* metatable.__gc = boxgc */ - } - lua_setmetatable(L, -2); - return resizebox(L, -1, newsize); +static void* newbox(lua_State* L, size_t newsize) +{ + UBox* box = (UBox*)lua_newuserdata(L, sizeof(UBox)); + box->box = NULL; + box->bsize = 0; + if (luaL_newmetatable(L, "LUABOX")) + { + /* creating metatable? */ + lua_pushcfunction(L, boxgc); + lua_setfield(L, -2, "__gc"); /* metatable.__gc = boxgc */ + } + lua_setmetatable(L, -2); + return resizebox(L, -1, newsize); } @@ -502,81 +573,96 @@ static void *newbox (lua_State *L, size_t newsize) { /* ** returns a pointer to a free area with at least 'sz' bytes */ -LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { - lua_State *L = B->L; - if (B->size - B->n < sz) { /* not enough space? */ - char *newbuff; - size_t newsize = B->size * 2; /* double buffer size */ - if (newsize - B->n < sz) /* not big enough? */ - newsize = B->n + sz; - if (newsize < B->n || newsize - B->n < sz) - luaL_error(L, "buffer too large"); - /* create larger buffer */ - if (buffonstack(B)) - newbuff = (char *)resizebox(L, -1, newsize); - else { /* no buffer yet */ - newbuff = (char *)newbox(L, newsize); - memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */ - } - B->b = newbuff; - B->size = newsize; - } - return &B->b[B->n]; +LUALIB_API char* luaL_prepbuffsize(luaL_Buffer* B, size_t sz) +{ + lua_State* L = B->L; + if (B->size - B->n < sz) + { + /* not enough space? */ + char* newbuff; + size_t newsize = B->size * 2; /* double buffer size */ + if (newsize - B->n < sz) /* not big enough? */ + newsize = B->n + sz; + if (newsize < B->n || newsize - B->n < sz) + luaL_error(L, "buffer too large"); + /* create larger buffer */ + if (buffonstack(B)) + newbuff = (char*)resizebox(L, -1, newsize); + else + { + /* no buffer yet */ + newbuff = (char*)newbox(L, newsize); + memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */ + } + B->b = newbuff; + B->size = newsize; + } + return &B->b[B->n]; } -LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { - if (l > 0) { /* avoid 'memcpy' when 's' can be NULL */ - char *b = luaL_prepbuffsize(B, l); - memcpy(b, s, l * sizeof(char)); - luaL_addsize(B, l); - } +LUALIB_API void luaL_addlstring(luaL_Buffer* B, const char* s, size_t l) +{ + if (l > 0) + { + /* avoid 'memcpy' when 's' can be NULL */ + char* b = luaL_prepbuffsize(B, l); + memcpy(b, s, l * sizeof(char)); + luaL_addsize(B, l); + } } -LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { - luaL_addlstring(B, s, strlen(s)); +LUALIB_API void luaL_addstring(luaL_Buffer* B, const char* s) +{ + luaL_addlstring(B, s, strlen(s)); } -LUALIB_API void luaL_pushresult (luaL_Buffer *B) { - lua_State *L = B->L; - lua_pushlstring(L, B->b, B->n); - if (buffonstack(B)) { - resizebox(L, -2, 0); /* delete old buffer */ - lua_remove(L, -2); /* remove its header from the stack */ - } +LUALIB_API void luaL_pushresult(luaL_Buffer* B) +{ + lua_State* L = B->L; + lua_pushlstring(L, B->b, B->n); + if (buffonstack(B)) + { + resizebox(L, -2, 0); /* delete old buffer */ + lua_remove(L, -2); /* remove its header from the stack */ + } } -LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { - luaL_addsize(B, sz); - luaL_pushresult(B); +LUALIB_API void luaL_pushresultsize(luaL_Buffer* B, size_t sz) +{ + luaL_addsize(B, sz); + luaL_pushresult(B); } -LUALIB_API void luaL_addvalue (luaL_Buffer *B) { - lua_State *L = B->L; - size_t l; - const char *s = lua_tolstring(L, -1, &l); - if (buffonstack(B)) - lua_insert(L, -2); /* put value below buffer */ - luaL_addlstring(B, s, l); - lua_remove(L, (buffonstack(B)) ? -2 : -1); /* remove value */ +LUALIB_API void luaL_addvalue(luaL_Buffer* B) +{ + lua_State* L = B->L; + size_t l; + const char* s = lua_tolstring(L, -1, &l); + if (buffonstack(B)) + lua_insert(L, -2); /* put value below buffer */ + luaL_addlstring(B, s, l); + lua_remove(L, (buffonstack(B)) ? -2 : -1); /* remove value */ } -LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { - B->L = L; - B->b = B->initb; - B->n = 0; - B->size = LUAL_BUFFERSIZE; +LUALIB_API void luaL_buffinit(lua_State* L, luaL_Buffer* B) +{ + B->L = L; + B->b = B->initb; + B->n = 0; + B->size = LUAL_BUFFERSIZE; } -LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { - luaL_buffinit(L, B); - return luaL_prepbuffsize(B, sz); +LUALIB_API char* luaL_buffinitsize(lua_State* L, luaL_Buffer* B, size_t sz) +{ + luaL_buffinit(L, B); + return luaL_prepbuffsize(B, sz); } /* }====================================================== */ @@ -592,35 +678,41 @@ LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { #define freelist 0 -LUALIB_API int luaL_ref (lua_State *L, int t) { - int ref; - if (lua_isnil(L, -1)) { - lua_pop(L, 1); /* remove from stack */ - return LUA_REFNIL; /* 'nil' has a unique fixed reference */ - } - t = lua_absindex(L, t); - lua_rawgeti(L, t, freelist); /* get first free element */ - ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ - lua_pop(L, 1); /* remove it from stack */ - if (ref != 0) { /* any free element? */ - lua_rawgeti(L, t, ref); /* remove it from list */ - lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ - } - else /* no free elements */ - ref = (int)lua_rawlen(L, t) + 1; /* get a new reference */ - lua_rawseti(L, t, ref); - return ref; +LUALIB_API int luaL_ref(lua_State* L, int t) +{ + int ref; + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); /* remove from stack */ + return LUA_REFNIL; /* 'nil' has a unique fixed reference */ + } + t = lua_absindex(L, t); + lua_rawgeti(L, t, freelist); /* get first free element */ + ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ + lua_pop(L, 1); /* remove it from stack */ + if (ref != 0) + { + /* any free element? */ + lua_rawgeti(L, t, ref); /* remove it from list */ + lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ + } + else /* no free elements */ + ref = (int)lua_rawlen(L, t) + 1; /* get a new reference */ + lua_rawseti(L, t, ref); + return ref; } -LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { - if (ref >= 0) { - t = lua_absindex(L, t); - lua_rawgeti(L, t, freelist); - lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ - lua_pushinteger(L, ref); - lua_rawseti(L, t, freelist); /* t[freelist] = ref */ - } +LUALIB_API void luaL_unref(lua_State* L, int t, int ref) +{ + if (ref >= 0) + { + t = lua_absindex(L, t); + lua_rawgeti(L, t, freelist); + lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ + lua_pushinteger(L, ref); + lua_rawseti(L, t, freelist); /* t[freelist] = ref */ + } } /* }====================================================== */ @@ -632,51 +724,61 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { ** ======================================================= */ -typedef struct LoadF { - int n; /* number of pre-read characters */ - FILE *f; /* file being read */ - char buff[BUFSIZ]; /* area for reading file */ +typedef struct LoadF +{ + int n; /* number of pre-read characters */ + FILE* f; /* file being read */ + char buff[BUFSIZ]; /* area for reading file */ } LoadF; -static const char *getF (lua_State *L, void *ud, size_t *size) { - LoadF *lf = (LoadF *)ud; - (void)L; /* not used */ - if (lf->n > 0) { /* are there pre-read characters to be read? */ - *size = lf->n; /* return them (chars already in buffer) */ - lf->n = 0; /* no more pre-read characters */ - } - else { /* read a block from file */ - /* 'fread' can return > 0 *and* set the EOF flag. If next call to - 'getF' called 'fread', it might still wait for user input. - The next check avoids this problem. */ - if (feof(lf->f)) return NULL; - *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ - } - return lf->buff; +static const char* getF(lua_State* L, void* ud, size_t* size) +{ + LoadF* lf = (LoadF*)ud; + (void)L; /* not used */ + if (lf->n > 0) + { + /* are there pre-read characters to be read? */ + *size = lf->n; /* return them (chars already in buffer) */ + lf->n = 0; /* no more pre-read characters */ + } + else + { + /* read a block from file */ + /* 'fread' can return > 0 *and* set the EOF flag. If next call to + 'getF' called 'fread', it might still wait for user input. + The next check avoids this problem. */ + if (feof(lf->f)) return NULL; + *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ + } + return lf->buff; } -static int errfile (lua_State *L, const char *what, int fnameindex) { - const char *serr = strerror(errno); - const char *filename = lua_tostring(L, fnameindex) + 1; - lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); - lua_remove(L, fnameindex); - return LUA_ERRFILE; +static int errfile(lua_State* L, const char* what, int fnameindex) +{ + const char* serr = strerror(errno); + const char* filename = lua_tostring(L, fnameindex) + 1; + lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); + lua_remove(L, fnameindex); + return LUA_ERRFILE; } -static int skipBOM (LoadF *lf) { - const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ - int c; - lf->n = 0; - do { - c = getc(lf->f); - if (c == EOF || c != *(const unsigned char *)p++) return c; - lf->buff[lf->n++] = c; /* to be read by the parser */ - } while (*p != '\0'); - lf->n = 0; /* prefix matched; discard it */ - return getc(lf->f); /* return next character */ +static int skipBOM(LoadF* lf) +{ + const char* p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ + int c; + lf->n = 0; + do + { + c = getc(lf->f); + if (c == EOF || c != *(const unsigned char*)p++) return c; + lf->buff[lf->n++] = c; /* to be read by the parser */ + } + while (*p != '\0'); + lf->n = 0; /* prefix matched; discard it */ + return getc(lf->f); /* return next character */ } @@ -687,161 +789,186 @@ static int skipBOM (LoadF *lf) { ** first "valid" character of the file (after the optional BOM and ** a first-line comment). */ -static int skipcomment (LoadF *lf, int *cp) { - int c = *cp = skipBOM(lf); - if (c == '#') { /* first line is a comment (Unix exec. file)? */ - do { /* skip first line */ - c = getc(lf->f); - } while (c != EOF && c != '\n'); - *cp = getc(lf->f); /* skip end-of-line, if present */ - return 1; /* there was a comment */ - } - else return 0; /* no comment */ +static int skipcomment(LoadF* lf, int* cp) +{ + int c = *cp = skipBOM(lf); + if (c == '#') + { + /* first line is a comment (Unix exec. file)? */ + do + { + /* skip first line */ + c = getc(lf->f); + } + while (c != EOF && c != '\n'); + *cp = getc(lf->f); /* skip end-of-line, if present */ + return 1; /* there was a comment */ + } + else return 0; /* no comment */ } -LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, - const char *mode) { - LoadF lf; - int status, readstatus; - int c; - int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ - if (filename == NULL) { - lua_pushliteral(L, "=stdin"); - lf.f = stdin; - } - else { - lua_pushfstring(L, "@%s", filename); - lf.f = fopen(filename, "r"); - if (lf.f == NULL) return errfile(L, "open", fnameindex); - } - if (skipcomment(&lf, &c)) /* read initial portion */ - lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ - if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ - lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ - if (lf.f == NULL) return errfile(L, "reopen", fnameindex); - skipcomment(&lf, &c); /* re-read initial portion */ - } - if (c != EOF) - lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ - status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); - readstatus = ferror(lf.f); - if (filename) fclose(lf.f); /* close file (even in case of errors) */ - if (readstatus) { - lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ - return errfile(L, "read", fnameindex); - } - lua_remove(L, fnameindex); - return status; +LUALIB_API int luaL_loadfilex(lua_State* L, const char* filename, + const char* mode) +{ + LoadF lf; + int status, readstatus; + int c; + int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ + if (filename == NULL) + { + lua_pushliteral(L, "=stdin"); + lf.f = stdin; + } + else + { + lua_pushfstring(L, "@%s", filename); + lf.f = fopen(filename, "r"); + if (lf.f == NULL) return errfile(L, "open", fnameindex); + } + if (skipcomment(&lf, &c)) /* read initial portion */ + lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ + if (c == LUA_SIGNATURE[0] && filename) + { + /* binary file? */ + lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ + if (lf.f == NULL) return errfile(L, "reopen", fnameindex); + skipcomment(&lf, &c); /* re-read initial portion */ + } + if (c != EOF) + lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ + status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); + readstatus = ferror(lf.f); + if (filename) fclose(lf.f); /* close file (even in case of errors) */ + if (readstatus) + { + lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ + return errfile(L, "read", fnameindex); + } + lua_remove(L, fnameindex); + return status; } -typedef struct LoadS { - const char *s; - size_t size; +typedef struct LoadS +{ + const char* s; + size_t size; } LoadS; -static const char *getS (lua_State *L, void *ud, size_t *size) { - LoadS *ls = (LoadS *)ud; - (void)L; /* not used */ - if (ls->size == 0) return NULL; - *size = ls->size; - ls->size = 0; - return ls->s; +static const char* getS(lua_State* L, void* ud, size_t* size) +{ + LoadS* ls = (LoadS*)ud; + (void)L; /* not used */ + if (ls->size == 0) return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; } -LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size, - const char *name, const char *mode) { - LoadS ls; - ls.s = buff; - ls.size = size; - return lua_load(L, getS, &ls, name, mode); +LUALIB_API int luaL_loadbufferx(lua_State* L, const char* buff, size_t size, + const char* name, const char* mode) +{ + LoadS ls; + ls.s = buff; + ls.size = size; + return lua_load(L, getS, &ls, name, mode); } -LUALIB_API int luaL_loadstring (lua_State *L, const char *s) { - return luaL_loadbuffer(L, s, strlen(s), s); +LUALIB_API int luaL_loadstring(lua_State* L, const char* s) +{ + return luaL_loadbuffer(L, s, strlen(s), s); } /* }====================================================== */ - -LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { - if (!lua_getmetatable(L, obj)) /* no metatable? */ - return LUA_TNIL; - else { - int tt; - lua_pushstring(L, event); - tt = lua_rawget(L, -2); - if (tt == LUA_TNIL) /* is metafield nil? */ - lua_pop(L, 2); /* remove metatable and metafield */ - else - lua_remove(L, -2); /* remove only metatable */ - return tt; /* return metafield type */ - } +LUALIB_API int luaL_getmetafield(lua_State* L, int obj, const char* event) +{ + if (!lua_getmetatable(L, obj)) /* no metatable? */ + return LUA_TNIL; + else + { + int tt; + lua_pushstring(L, event); + tt = lua_rawget(L, -2); + if (tt == LUA_TNIL) /* is metafield nil? */ + lua_pop(L, 2); /* remove metatable and metafield */ + else + lua_remove(L, -2); /* remove only metatable */ + return tt; /* return metafield type */ + } } -LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { - obj = lua_absindex(L, obj); - if (luaL_getmetafield(L, obj, event) == LUA_TNIL) /* no metafield? */ - return 0; - lua_pushvalue(L, obj); - lua_call(L, 1, 1); - return 1; +LUALIB_API int luaL_callmeta(lua_State* L, int obj, const char* event) +{ + obj = lua_absindex(L, obj); + if (luaL_getmetafield(L, obj, event) == LUA_TNIL) /* no metafield? */ + return 0; + lua_pushvalue(L, obj); + lua_call(L, 1, 1); + return 1; } -LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) { - lua_Integer l; - int isnum; - lua_len(L, idx); - l = lua_tointegerx(L, -1, &isnum); - if (!isnum) - luaL_error(L, "object length is not an integer"); - lua_pop(L, 1); /* remove object */ - return l; +LUALIB_API lua_Integer luaL_len(lua_State* L, int idx) +{ + lua_Integer l; + int isnum; + lua_len(L, idx); + l = lua_tointegerx(L, -1, &isnum); + if (!isnum) + luaL_error(L, "object length is not an integer"); + lua_pop(L, 1); /* remove object */ + return l; } -LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { - if (luaL_callmeta(L, idx, "__tostring")) { /* metafield? */ - if (!lua_isstring(L, -1)) - luaL_error(L, "'__tostring' must return a string"); - } - else { - switch (lua_type(L, idx)) { - case LUA_TNUMBER: { - if (lua_isinteger(L, idx)) - lua_pushfstring(L, "%I", (LUAI_UACINT)lua_tointeger(L, idx)); - else - lua_pushfstring(L, "%f", (LUAI_UACNUMBER)lua_tonumber(L, idx)); - break; - } - case LUA_TSTRING: - lua_pushvalue(L, idx); - break; - case LUA_TBOOLEAN: - lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); - break; - case LUA_TNIL: - lua_pushliteral(L, "nil"); - break; - default: { - int tt = luaL_getmetafield(L, idx, "__name"); /* try name */ - const char *kind = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : - luaL_typename(L, idx); - lua_pushfstring(L, "%s: %p", kind, lua_topointer(L, idx)); - if (tt != LUA_TNIL) - lua_remove(L, -2); /* remove '__name' */ - break; - } - } - } - return lua_tolstring(L, -1, len); +LUALIB_API const char* luaL_tolstring(lua_State* L, int idx, size_t* len) +{ + if (luaL_callmeta(L, idx, "__tostring")) + { + /* metafield? */ + if (!lua_isstring(L, -1)) + luaL_error(L, "'__tostring' must return a string"); + } + else + { + switch (lua_type(L, idx)) + { + case LUA_TNUMBER: + { + if (lua_isinteger(L, idx)) + lua_pushfstring(L, "%I", (LUAI_UACINT)lua_tointeger(L, idx)); + else + lua_pushfstring(L, "%f", (LUAI_UACNUMBER)lua_tonumber(L, idx)); + break; + } + case LUA_TSTRING: + lua_pushvalue(L, idx); + break; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); + break; + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + default: + { + int tt = luaL_getmetafield(L, idx, "__name"); /* try name */ + const char* kind = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : luaL_typename(L, idx); + lua_pushfstring(L, "%s: %p", kind, lua_topointer(L, idx)); + if (tt != LUA_TNIL) + lua_remove(L, -2); /* remove '__name' */ + break; + } + } + } + return lua_tolstring(L, -1, len); } @@ -931,16 +1058,19 @@ LUALIB_API void luaL_openlib (lua_State *L, const char *libname, ** function gets the 'nup' elements at the top as upvalues. ** Returns with only the table at the stack. */ -LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkstack(L, nup, "too many upvalues"); - for (; l->name != NULL; l++) { /* fill the table with given functions */ - int i; - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -nup); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - lua_setfield(L, -(nup + 2), l->name); - } - lua_pop(L, nup); /* remove upvalues */ +LUALIB_API void luaL_setfuncs(lua_State* L, const luaL_Reg* l, int nup) +{ + luaL_checkstack(L, nup, "too many upvalues"); + for (; l->name != NULL; l++) + { + /* fill the table with given functions */ + int i; + for (i = 0; i < nup; i++) /* copy upvalues to the top */ + lua_pushvalue(L, -nup); + lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ + lua_setfield(L, -(nup + 2), l->name); + } + lua_pop(L, nup); /* remove upvalues */ } @@ -948,17 +1078,19 @@ LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { ** ensure that stack[idx][fname] has a table and push that table ** into the stack */ -LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) { - if (lua_getfield(L, idx, fname) == LUA_TTABLE) - return 1; /* table already there */ - else { - lua_pop(L, 1); /* remove previous result */ - idx = lua_absindex(L, idx); - lua_newtable(L); - lua_pushvalue(L, -1); /* copy to be left at top */ - lua_setfield(L, idx, fname); /* assign new table to field */ - return 0; /* false, because did not find table there */ - } +LUALIB_API int luaL_getsubtable(lua_State* L, int idx, const char* fname) +{ + if (lua_getfield(L, idx, fname) == LUA_TTABLE) + return 1; /* table already there */ + else + { + lua_pop(L, 1); /* remove previous result */ + idx = lua_absindex(L, idx); + lua_newtable(L); + lua_pushvalue(L, -1); /* copy to be left at top */ + lua_setfield(L, idx, fname); /* assign new table to field */ + return 0; /* false, because did not find table there */ + } } @@ -968,76 +1100,87 @@ LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) { ** if 'glb' is true, also registers the result in the global table. ** Leaves resulting module on the top. */ -LUALIB_API void luaL_requiref (lua_State *L, const char *modname, - lua_CFunction openf, int glb) { - luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); - lua_getfield(L, -1, modname); /* LOADED[modname] */ - if (!lua_toboolean(L, -1)) { /* package not already loaded? */ - lua_pop(L, 1); /* remove field */ - lua_pushcfunction(L, openf); - lua_pushstring(L, modname); /* argument to open function */ - lua_call(L, 1, 1); /* call 'openf' to open module */ - lua_pushvalue(L, -1); /* make copy of module (call result) */ - lua_setfield(L, -3, modname); /* LOADED[modname] = module */ - } - lua_remove(L, -2); /* remove LOADED table */ - if (glb) { - lua_pushvalue(L, -1); /* copy of module */ - lua_setglobal(L, modname); /* _G[modname] = module */ - } +LUALIB_API void luaL_requiref(lua_State* L, const char* modname, + lua_CFunction openf, int glb) +{ + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + lua_getfield(L, -1, modname); /* LOADED[modname] */ + if (!lua_toboolean(L, -1)) + { + /* package not already loaded? */ + lua_pop(L, 1); /* remove field */ + lua_pushcfunction(L, openf); + lua_pushstring(L, modname); /* argument to open function */ + lua_call(L, 1, 1); /* call 'openf' to open module */ + lua_pushvalue(L, -1); /* make copy of module (call result) */ + lua_setfield(L, -3, modname); /* LOADED[modname] = module */ + } + lua_remove(L, -2); /* remove LOADED table */ + if (glb) + { + lua_pushvalue(L, -1); /* copy of module */ + lua_setglobal(L, modname); /* _G[modname] = module */ + } } -LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, - const char *r) { - const char *wild; - size_t l = strlen(p); - luaL_Buffer b; - luaL_buffinit(L, &b); - while ((wild = strstr(s, p)) != NULL) { - luaL_addlstring(&b, s, wild - s); /* push prefix */ - luaL_addstring(&b, r); /* push replacement in place of pattern */ - s = wild + l; /* continue after 'p' */ - } - luaL_addstring(&b, s); /* push last suffix */ - luaL_pushresult(&b); - return lua_tostring(L, -1); +LUALIB_API const char* luaL_gsub(lua_State* L, const char* s, const char* p, + const char* r) +{ + const char* wild; + size_t l = strlen(p); + luaL_Buffer b; + luaL_buffinit(L, &b); + while ((wild = strstr(s, p)) != NULL) + { + luaL_addlstring(&b, s, wild - s); /* push prefix */ + luaL_addstring(&b, r); /* push replacement in place of pattern */ + s = wild + l; /* continue after 'p' */ + } + luaL_addstring(&b, s); /* push last suffix */ + luaL_pushresult(&b); + return lua_tostring(L, -1); } -static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { - (void)ud; (void)osize; /* not used */ - if (nsize == 0) { - free(ptr); - return NULL; - } - else - return realloc(ptr, nsize); +static void* l_alloc(void* ud, void* ptr, size_t osize, size_t nsize) +{ + (void)ud; + (void)osize; /* not used */ + if (nsize == 0) + { + free(ptr); + return NULL; + } + else + return realloc(ptr, nsize); } -static int panic (lua_State *L) { - lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", - lua_tostring(L, -1)); - return 0; /* return to Lua to abort */ +static int panic(lua_State* L) +{ + lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", + lua_tostring(L, -1)); + return 0; /* return to Lua to abort */ } -LUALIB_API lua_State *luaL_newstate (void) { - lua_State *L = lua_newstate(l_alloc, NULL); - if (L) lua_atpanic(L, &panic); - return L; +LUALIB_API lua_State* luaL_newstate(void) +{ + lua_State* L = lua_newstate(l_alloc, NULL); + if (L) lua_atpanic(L, &panic); + return L; } -LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) { - const lua_Number *v = lua_version(L); - if (sz != LUAL_NUMSIZES) /* check numeric types */ - luaL_error(L, "core and library have incompatible numeric types"); - if (v != lua_version(NULL)) - luaL_error(L, "multiple Lua VMs detected"); - else if (*v != ver) - luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", - (LUAI_UACNUMBER)ver, (LUAI_UACNUMBER)*v); +LUALIB_API void luaL_checkversion_(lua_State* L, lua_Number ver, size_t sz) +{ + const lua_Number* v = lua_version(L); + if (sz != LUAL_NUMSIZES) /* check numeric types */ + luaL_error(L, "core and library have incompatible numeric types"); + if (v != lua_version(NULL)) + luaL_error(L, "multiple Lua VMs detected"); + else if (*v != ver) + luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", + (LUAI_UACNUMBER)ver, (LUAI_UACNUMBER)*v); } - diff --git a/Lua/lauxlib.h b/Lua/lauxlib.h index 9a2e66a..4eba667 100644 --- a/Lua/lauxlib.h +++ b/Lua/lauxlib.h @@ -15,7 +15,6 @@ #include "lua.h" - /* extra error code for 'luaL_loadfilex' */ #define LUA_ERRFILE (LUA_ERRERR+1) @@ -28,83 +27,84 @@ #define LUA_PRELOAD_TABLE "_PRELOAD" -typedef struct luaL_Reg { - const char *name; - lua_CFunction func; +typedef struct luaL_Reg +{ + const char* name; + lua_CFunction func; } luaL_Reg; #define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number)) -LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz); +LUALIB_API void (luaL_checkversion_)(lua_State* L, lua_Number ver, size_t sz); #define luaL_checkversion(L) \ luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES) -LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); -LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); -LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); -LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg); -LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg, - size_t *l); -LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg, - const char *def, size_t *l); -LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg); -LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def); +LUALIB_API int (luaL_getmetafield)(lua_State* L, int obj, const char* e); +LUALIB_API int (luaL_callmeta)(lua_State* L, int obj, const char* e); +LUALIB_API const char*(luaL_tolstring)(lua_State* L, int idx, size_t* len); +LUALIB_API int (luaL_argerror)(lua_State* L, int arg, const char* extramsg); +LUALIB_API const char*(luaL_checklstring)(lua_State* L, int arg, + size_t* l); +LUALIB_API const char*(luaL_optlstring)(lua_State* L, int arg, + const char* def, size_t* l); +LUALIB_API lua_Number (luaL_checknumber)(lua_State* L, int arg); +LUALIB_API lua_Number (luaL_optnumber)(lua_State* L, int arg, lua_Number def); -LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg); -LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg, - lua_Integer def); +LUALIB_API lua_Integer (luaL_checkinteger)(lua_State* L, int arg); +LUALIB_API lua_Integer (luaL_optinteger)(lua_State* L, int arg, + lua_Integer def); -LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); -LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t); -LUALIB_API void (luaL_checkany) (lua_State *L, int arg); +LUALIB_API void (luaL_checkstack)(lua_State* L, int sz, const char* msg); +LUALIB_API void (luaL_checktype)(lua_State* L, int arg, int t); +LUALIB_API void (luaL_checkany)(lua_State* L, int arg); -LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); -LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); -LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); -LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); +LUALIB_API int (luaL_newmetatable)(lua_State* L, const char* tname); +LUALIB_API void (luaL_setmetatable)(lua_State* L, const char* tname); +LUALIB_API void*(luaL_testudata)(lua_State* L, int ud, const char* tname); +LUALIB_API void*(luaL_checkudata)(lua_State* L, int ud, const char* tname); -LUALIB_API void (luaL_where) (lua_State *L, int lvl); -LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); +LUALIB_API void (luaL_where)(lua_State* L, int lvl); +LUALIB_API int (luaL_error)(lua_State* L, const char* fmt, ...); -LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def, - const char *const lst[]); +LUALIB_API int (luaL_checkoption)(lua_State* L, int arg, const char* def, + const char* const lst[]); -LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); -LUALIB_API int (luaL_execresult) (lua_State *L, int stat); +LUALIB_API int (luaL_fileresult)(lua_State* L, int stat, const char* fname); +LUALIB_API int (luaL_execresult)(lua_State* L, int stat); /* predefined references */ #define LUA_NOREF (-2) #define LUA_REFNIL (-1) -LUALIB_API int (luaL_ref) (lua_State *L, int t); -LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); +LUALIB_API int (luaL_ref)(lua_State* L, int t); +LUALIB_API void (luaL_unref)(lua_State* L, int t, int ref); -LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, - const char *mode); +LUALIB_API int (luaL_loadfilex)(lua_State* L, const char* filename, + const char* mode); #define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) -LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, - const char *name, const char *mode); -LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); +LUALIB_API int (luaL_loadbufferx)(lua_State* L, const char* buff, size_t sz, + const char* name, const char* mode); +LUALIB_API int (luaL_loadstring)(lua_State* L, const char* s); -LUALIB_API lua_State *(luaL_newstate) (void); +LUALIB_API lua_State*(luaL_newstate)(void); -LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx); +LUALIB_API lua_Integer (luaL_len)(lua_State* L, int idx); -LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, - const char *r); +LUALIB_API const char*(luaL_gsub)(lua_State* L, const char* s, const char* p, + const char* r); -LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); +LUALIB_API void (luaL_setfuncs)(lua_State* L, const luaL_Reg* l, int nup); -LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); +LUALIB_API int (luaL_getsubtable)(lua_State* L, int idx, const char* fname); -LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, - const char *msg, int level); +LUALIB_API void (luaL_traceback)(lua_State* L, lua_State* L1, + const char* msg, int level); -LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, - lua_CFunction openf, int glb); +LUALIB_API void (luaL_requiref)(lua_State* L, const char* modname, + lua_CFunction openf, int glb); /* ** =============================================================== @@ -145,12 +145,13 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, ** ======================================================= */ -typedef struct luaL_Buffer { - char *b; /* buffer address */ - size_t size; /* buffer size */ - size_t n; /* number of characters in buffer */ - lua_State *L; - char initb[LUAL_BUFFERSIZE]; /* initial buffer */ +typedef struct luaL_Buffer +{ + char* b; /* buffer address */ + size_t size; /* buffer size */ + size_t n; /* number of characters in buffer */ + lua_State* L; + char initb[LUAL_BUFFERSIZE]; /* initial buffer */ } luaL_Buffer; @@ -160,21 +161,20 @@ typedef struct luaL_Buffer { #define luaL_addsize(B,s) ((B)->n += (s)) -LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); -LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); -LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); -LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); -LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); -LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); -LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); -LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); +LUALIB_API void (luaL_buffinit)(lua_State* L, luaL_Buffer* B); +LUALIB_API char*(luaL_prepbuffsize)(luaL_Buffer* B, size_t sz); +LUALIB_API void (luaL_addlstring)(luaL_Buffer* B, const char* s, size_t l); +LUALIB_API void (luaL_addstring)(luaL_Buffer* B, const char* s); +LUALIB_API void (luaL_addvalue)(luaL_Buffer* B); +LUALIB_API void (luaL_pushresult)(luaL_Buffer* B); +LUALIB_API void (luaL_pushresultsize)(luaL_Buffer* B, size_t sz); +LUALIB_API char*(luaL_buffinitsize)(lua_State* L, luaL_Buffer* B, size_t sz); #define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) /* }====================================================== */ - /* ** {====================================================== ** File handles for IO library @@ -190,15 +190,15 @@ LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); #define LUA_FILEHANDLE "FILE*" -typedef struct luaL_Stream { - FILE *f; /* stream (NULL for incompletely created streams) */ - lua_CFunction closef; /* to close stream (NULL for closed streams) */ +typedef struct luaL_Stream +{ + FILE* f; /* stream (NULL for incompletely created streams) */ + lua_CFunction closef; /* to close stream (NULL for closed streams) */ } luaL_Stream; /* }====================================================== */ - /* compatibility with old module system */ #if defined(LUA_COMPAT_MODULE) @@ -258,7 +258,4 @@ LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, /* }============================================================ */ - #endif - - diff --git a/Lua/lbaselib.c b/Lua/lbaselib.c index 08523e6..f932bca 100644 --- a/Lua/lbaselib.c +++ b/Lua/lbaselib.c @@ -21,232 +21,279 @@ #include "lualib.h" -static int luaB_print (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - int i; - lua_getglobal(L, "tostring"); - for (i=1; i<=n; i++) { - const char *s; - size_t l; - lua_pushvalue(L, -1); /* function to be called */ - lua_pushvalue(L, i); /* value to print */ - lua_call(L, 1, 1); - s = lua_tolstring(L, -1, &l); /* get result */ - if (s == NULL) - return luaL_error(L, "'tostring' must return a string to 'print'"); - if (i>1) lua_writestring("\t", 1); - lua_writestring(s, l); - lua_pop(L, 1); /* pop result */ - } - lua_writeline(); - return 0; +static int luaB_print(lua_State* L) +{ + int n = lua_gettop(L); /* number of arguments */ + int i; + lua_getglobal(L, "tostring"); + for (i = 1; i <= n; i++) + { + const char* s; + size_t l; + lua_pushvalue(L, -1); /* function to be called */ + lua_pushvalue(L, i); /* value to print */ + lua_call(L, 1, 1); + s = lua_tolstring(L, -1, &l); /* get result */ + if (s == NULL) + return luaL_error(L, "'tostring' must return a string to 'print'"); + if (i > 1) + lua_writestring("\t", 1); + lua_writestring(s, l); + lua_pop(L, 1); /* pop result */ + } + lua_writeline(); + return 0; } #define SPACECHARS " \f\n\r\t\v" -static const char *b_str2int (const char *s, int base, lua_Integer *pn) { - lua_Unsigned n = 0; - int neg = 0; - s += strspn(s, SPACECHARS); /* skip initial spaces */ - if (*s == '-') { s++; neg = 1; } /* handle signal */ - else if (*s == '+') s++; - if (!isalnum((unsigned char)*s)) /* no digit? */ - return NULL; - do { - int digit = (isdigit((unsigned char)*s)) ? *s - '0' - : (toupper((unsigned char)*s) - 'A') + 10; - if (digit >= base) return NULL; /* invalid numeral */ - n = n * base + digit; - s++; - } while (isalnum((unsigned char)*s)); - s += strspn(s, SPACECHARS); /* skip trailing spaces */ - *pn = (lua_Integer)((neg) ? (0u - n) : n); - return s; +static const char* b_str2int(const char* s, int base, lua_Integer* pn) +{ + lua_Unsigned n = 0; + int neg = 0; + s += strspn(s, SPACECHARS); /* skip initial spaces */ + if (*s == '-') + { + s++; + neg = 1; + } /* handle signal */ + else if (*s == '+') s++; + if (!isalnum((unsigned char)*s)) /* no digit? */ + return NULL; + do + { + int digit = (isdigit((unsigned char)*s)) + ? *s - '0' + : (toupper((unsigned char)*s) - 'A') + 10; + if (digit >= base) return NULL; /* invalid numeral */ + n = n * base + digit; + s++; + } + while (isalnum((unsigned char)*s)); + s += strspn(s, SPACECHARS); /* skip trailing spaces */ + *pn = (lua_Integer)((neg) ? (0u - n) : n); + return s; } -static int luaB_tonumber (lua_State *L) { - if (lua_isnoneornil(L, 2)) { /* standard conversion? */ - luaL_checkany(L, 1); - if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */ - lua_settop(L, 1); /* yes; return it */ - return 1; - } - else { - size_t l; - const char *s = lua_tolstring(L, 1, &l); - if (s != NULL && lua_stringtonumber(L, s) == l + 1) - return 1; /* successful conversion to number */ - /* else not a number */ - } - } - else { - size_t l; - const char *s; - lua_Integer n = 0; /* to avoid warnings */ - lua_Integer base = luaL_checkinteger(L, 2); - luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */ - s = lua_tolstring(L, 1, &l); - luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); - if (b_str2int(s, (int)base, &n) == s + l) { - lua_pushinteger(L, n); - return 1; - } /* else not a number */ - } /* else not a number */ - lua_pushnil(L); /* not a number */ - return 1; +static int luaB_tonumber(lua_State* L) +{ + if (lua_isnoneornil(L, 2)) + { + /* standard conversion? */ + luaL_checkany(L, 1); + if (lua_type(L, 1) == LUA_TNUMBER) + { + /* already a number? */ + lua_settop(L, 1); /* yes; return it */ + return 1; + } + else + { + size_t l; + const char* s = lua_tolstring(L, 1, &l); + if (s != NULL && lua_stringtonumber(L, s) == l + 1) + return 1; /* successful conversion to number */ + /* else not a number */ + } + } + else + { + size_t l; + const char* s; + lua_Integer n = 0; /* to avoid warnings */ + lua_Integer base = luaL_checkinteger(L, 2); + luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */ + s = lua_tolstring(L, 1, &l); + luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); + if (b_str2int(s, (int)base, &n) == s + l) + { + lua_pushinteger(L, n); + return 1; + } /* else not a number */ + } /* else not a number */ + lua_pushnil(L); /* not a number */ + return 1; } -static int luaB_error (lua_State *L) { - int level = (int)luaL_optinteger(L, 2, 1); - lua_settop(L, 1); - if (lua_type(L, 1) == LUA_TSTRING && level > 0) { - luaL_where(L, level); /* add extra information */ - lua_pushvalue(L, 1); - lua_concat(L, 2); - } - return lua_error(L); +static int luaB_error(lua_State* L) +{ + int level = (int)luaL_optinteger(L, 2, 1); + lua_settop(L, 1); + if (lua_type(L, 1) == LUA_TSTRING && level > 0) + { + luaL_where(L, level); /* add extra information */ + lua_pushvalue(L, 1); + lua_concat(L, 2); + } + return lua_error(L); } -static int luaB_getmetatable (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_getmetatable(L, 1)) { - lua_pushnil(L); - return 1; /* no metatable */ - } - luaL_getmetafield(L, 1, "__metatable"); - return 1; /* returns either __metatable field (if present) or metatable */ +static int luaB_getmetatable(lua_State* L) +{ + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) + { + lua_pushnil(L); + return 1; /* no metatable */ + } + luaL_getmetafield(L, 1, "__metatable"); + return 1; /* returns either __metatable field (if present) or metatable */ } -static int luaB_setmetatable (lua_State *L) { - int t = lua_type(L, 2); - luaL_checktype(L, 1, LUA_TTABLE); - luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, - "nil or table expected"); - if (luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL) - return luaL_error(L, "cannot change a protected metatable"); - lua_settop(L, 2); - lua_setmetatable(L, 1); - return 1; +static int luaB_setmetatable(lua_State* L) +{ + int t = lua_type(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + if (luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL) + return luaL_error(L, "cannot change a protected metatable"); + lua_settop(L, 2); + lua_setmetatable(L, 1); + return 1; } -static int luaB_rawequal (lua_State *L) { - luaL_checkany(L, 1); - luaL_checkany(L, 2); - lua_pushboolean(L, lua_rawequal(L, 1, 2)); - return 1; +static int luaB_rawequal(lua_State* L) +{ + luaL_checkany(L, 1); + luaL_checkany(L, 2); + lua_pushboolean(L, lua_rawequal(L, 1, 2)); + return 1; } -static int luaB_rawlen (lua_State *L) { - int t = lua_type(L, 1); - luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1, - "table or string expected"); - lua_pushinteger(L, lua_rawlen(L, 1)); - return 1; +static int luaB_rawlen(lua_State* L) +{ + int t = lua_type(L, 1); + luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1, + "table or string expected"); + lua_pushinteger(L, lua_rawlen(L, 1)); + return 1; } -static int luaB_rawget (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - lua_settop(L, 2); - lua_rawget(L, 1); - return 1; +static int luaB_rawget(lua_State* L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_rawget(L, 1); + return 1; } -static int luaB_rawset (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - luaL_checkany(L, 3); - lua_settop(L, 3); - lua_rawset(L, 1); - return 1; +static int luaB_rawset(lua_State* L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + luaL_checkany(L, 3); + lua_settop(L, 3); + lua_rawset(L, 1); + return 1; } -static int luaB_collectgarbage (lua_State *L) { - static const char *const opts[] = {"stop", "restart", "collect", - "count", "step", "setpause", "setstepmul", - "isrunning", NULL}; - static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, - LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, - LUA_GCISRUNNING}; - int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; - int ex = (int)luaL_optinteger(L, 2, 0); - int res = lua_gc(L, o, ex); - switch (o) { - case LUA_GCCOUNT: { - int b = lua_gc(L, LUA_GCCOUNTB, 0); - lua_pushnumber(L, (lua_Number)res + ((lua_Number)b/1024)); - return 1; - } - case LUA_GCSTEP: case LUA_GCISRUNNING: { - lua_pushboolean(L, res); - return 1; - } - default: { - lua_pushinteger(L, res); - return 1; - } - } +static int luaB_collectgarbage(lua_State* L) +{ + static const char* const opts[] = { + "stop", "restart", "collect", + "count", "step", "setpause", "setstepmul", + "isrunning", NULL + }; + static const int optsnum[] = { + LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, + LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, + LUA_GCISRUNNING + }; + int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; + int ex = (int)luaL_optinteger(L, 2, 0); + int res = lua_gc(L, o, ex); + switch (o) + { + case LUA_GCCOUNT: + { + int b = lua_gc(L, LUA_GCCOUNTB, 0); + lua_pushnumber(L, (lua_Number)res + ((lua_Number)b / 1024)); + return 1; + } + case LUA_GCSTEP: + case LUA_GCISRUNNING: + { + lua_pushboolean(L, res); + return 1; + } + default: + { + lua_pushinteger(L, res); + return 1; + } + } } -static int luaB_type (lua_State *L) { - int t = lua_type(L, 1); - luaL_argcheck(L, t != LUA_TNONE, 1, "value expected"); - lua_pushstring(L, lua_typename(L, t)); - return 1; +static int luaB_type(lua_State* L) +{ + int t = lua_type(L, 1); + luaL_argcheck(L, t != LUA_TNONE, 1, "value expected"); + lua_pushstring(L, lua_typename(L, t)); + return 1; } -static int pairsmeta (lua_State *L, const char *method, int iszero, - lua_CFunction iter) { - luaL_checkany(L, 1); - if (luaL_getmetafield(L, 1, method) == LUA_TNIL) { /* no metamethod? */ - lua_pushcfunction(L, iter); /* will return generator, */ - lua_pushvalue(L, 1); /* state, */ - if (iszero) lua_pushinteger(L, 0); /* and initial value */ - else lua_pushnil(L); - } - else { - lua_pushvalue(L, 1); /* argument 'self' to metamethod */ - lua_call(L, 1, 3); /* get 3 values from metamethod */ - } - return 3; +static int pairsmeta(lua_State* L, const char* method, int iszero, + lua_CFunction iter) +{ + luaL_checkany(L, 1); + if (luaL_getmetafield(L, 1, method) == LUA_TNIL) + { + /* no metamethod? */ + lua_pushcfunction(L, iter); /* will return generator, */ + lua_pushvalue(L, 1); /* state, */ + if (iszero) lua_pushinteger(L, 0); /* and initial value */ + else lua_pushnil(L); + } + else + { + lua_pushvalue(L, 1); /* argument 'self' to metamethod */ + lua_call(L, 1, 3); /* get 3 values from metamethod */ + } + return 3; } -static int luaB_next (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 2); /* create a 2nd argument if there isn't one */ - if (lua_next(L, 1)) - return 2; - else { - lua_pushnil(L); - return 1; - } +static int luaB_next(lua_State* L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 2); /* create a 2nd argument if there isn't one */ + if (lua_next(L, 1)) + return 2; + else + { + lua_pushnil(L); + return 1; + } } -static int luaB_pairs (lua_State *L) { - return pairsmeta(L, "__pairs", 0, luaB_next); +static int luaB_pairs(lua_State* L) +{ + return pairsmeta(L, "__pairs", 0, luaB_next); } /* ** Traversal function for 'ipairs' */ -static int ipairsaux (lua_State *L) { - lua_Integer i = luaL_checkinteger(L, 2) + 1; - lua_pushinteger(L, i); - return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2; +static int ipairsaux(lua_State* L) +{ + lua_Integer i = luaL_checkinteger(L, 2) + 1; + lua_pushinteger(L, i); + return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2; } @@ -254,42 +301,50 @@ static int ipairsaux (lua_State *L) { ** 'ipairs' function. Returns 'ipairsaux', given "table", 0. ** (The given "table" may not be a table.) */ -static int luaB_ipairs (lua_State *L) { +static int luaB_ipairs(lua_State* L) +{ #if defined(LUA_COMPAT_IPAIRS) return pairsmeta(L, "__ipairs", 1, ipairsaux); #else - luaL_checkany(L, 1); - lua_pushcfunction(L, ipairsaux); /* iteration function */ - lua_pushvalue(L, 1); /* state */ - lua_pushinteger(L, 0); /* initial value */ - return 3; + luaL_checkany(L, 1); + lua_pushcfunction(L, ipairsaux); /* iteration function */ + lua_pushvalue(L, 1); /* state */ + lua_pushinteger(L, 0); /* initial value */ + return 3; #endif } -static int load_aux (lua_State *L, int status, int envidx) { - if (status == LUA_OK) { - if (envidx != 0) { /* 'env' parameter? */ - lua_pushvalue(L, envidx); /* environment for loaded function */ - if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ - lua_pop(L, 1); /* remove 'env' if not used by previous call */ - } - return 1; - } - else { /* error (message is on top of the stack) */ - lua_pushnil(L); - lua_insert(L, -2); /* put before error message */ - return 2; /* return nil plus error message */ - } +static int load_aux(lua_State* L, int status, int envidx) +{ + if (status == LUA_OK) + { + if (envidx != 0) + { + /* 'env' parameter? */ + lua_pushvalue(L, envidx); /* environment for loaded function */ + if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ + lua_pop(L, 1); /* remove 'env' if not used by previous call */ + } + return 1; + } + else + { + /* error (message is on top of the stack) */ + lua_pushnil(L); + lua_insert(L, -2); /* put before error message */ + return 2; /* return nil plus error message */ + } } -static int luaB_loadfile (lua_State *L) { - const char *fname = luaL_optstring(L, 1, NULL); - const char *mode = luaL_optstring(L, 2, NULL); - int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ - int status = luaL_loadfilex(L, fname, mode); - return load_aux(L, status, env); +static int luaB_loadfile(lua_State* L) +{ + const char* fname = luaL_optstring(L, 1, NULL); + const char* mode = luaL_optstring(L, 2, NULL); + int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ + int status = luaL_loadfilex(L, fname, mode); + return load_aux(L, status, env); } @@ -314,87 +369,103 @@ static int luaB_loadfile (lua_State *L) { ** stack top. Instead, it keeps its resulting string in a ** reserved slot inside the stack. */ -static const char *generic_reader (lua_State *L, void *ud, size_t *size) { - (void)(ud); /* not used */ - luaL_checkstack(L, 2, "too many nested functions"); - lua_pushvalue(L, 1); /* get function */ - lua_call(L, 0, 1); /* call it */ - if (lua_isnil(L, -1)) { - lua_pop(L, 1); /* pop result */ - *size = 0; - return NULL; - } - else if (!lua_isstring(L, -1)) - luaL_error(L, "reader function must return a string"); - lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ - return lua_tolstring(L, RESERVEDSLOT, size); +static const char* generic_reader(lua_State* L, void* ud, size_t* size) +{ + (void)(ud); /* not used */ + luaL_checkstack(L, 2, "too many nested functions"); + lua_pushvalue(L, 1); /* get function */ + lua_call(L, 0, 1); /* call it */ + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); /* pop result */ + *size = 0; + return NULL; + } + else if (!lua_isstring(L, -1)) + luaL_error(L, "reader function must return a string"); + lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ + return lua_tolstring(L, RESERVEDSLOT, size); } -static int luaB_load (lua_State *L) { - int status; - size_t l; - const char *s = lua_tolstring(L, 1, &l); - const char *mode = luaL_optstring(L, 3, "bt"); - int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ - if (s != NULL) { /* loading a string? */ - const char *chunkname = luaL_optstring(L, 2, s); - status = luaL_loadbufferx(L, s, l, chunkname, mode); - } - else { /* loading from a reader function */ - const char *chunkname = luaL_optstring(L, 2, "=(load)"); - luaL_checktype(L, 1, LUA_TFUNCTION); - lua_settop(L, RESERVEDSLOT); /* create reserved slot */ - status = lua_load(L, generic_reader, NULL, chunkname, mode); - } - return load_aux(L, status, env); +static int luaB_load(lua_State* L) +{ + int status; + size_t l; + const char* s = lua_tolstring(L, 1, &l); + const char* mode = luaL_optstring(L, 3, "bt"); + int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ + if (s != NULL) + { + /* loading a string? */ + const char* chunkname = luaL_optstring(L, 2, s); + status = luaL_loadbufferx(L, s, l, chunkname, mode); + } + else + { + /* loading from a reader function */ + const char* chunkname = luaL_optstring(L, 2, "=(load)"); + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L, RESERVEDSLOT); /* create reserved slot */ + status = lua_load(L, generic_reader, NULL, chunkname, mode); + } + return load_aux(L, status, env); } /* }====================================================== */ -static int dofilecont (lua_State *L, int d1, lua_KContext d2) { - (void)d1; (void)d2; /* only to match 'lua_Kfunction' prototype */ - return lua_gettop(L) - 1; +static int dofilecont(lua_State* L, int d1, lua_KContext d2) +{ + (void)d1; + (void)d2; /* only to match 'lua_Kfunction' prototype */ + return lua_gettop(L) - 1; } -static int luaB_dofile (lua_State *L) { - const char *fname = luaL_optstring(L, 1, NULL); - lua_settop(L, 1); - if (luaL_loadfile(L, fname) != LUA_OK) - return lua_error(L); - lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); - return dofilecont(L, 0, 0); +static int luaB_dofile(lua_State* L) +{ + const char* fname = luaL_optstring(L, 1, NULL); + lua_settop(L, 1); + if (luaL_loadfile(L, fname) != LUA_OK) + return lua_error(L); + lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); + return dofilecont(L, 0, 0); } -static int luaB_assert (lua_State *L) { - if (lua_toboolean(L, 1)) /* condition is true? */ - return lua_gettop(L); /* return all arguments */ - else { /* error */ - luaL_checkany(L, 1); /* there must be a condition */ - lua_remove(L, 1); /* remove it */ - lua_pushliteral(L, "assertion failed!"); /* default message */ - lua_settop(L, 1); /* leave only message (default if no other one) */ - return luaB_error(L); /* call 'error' */ - } +static int luaB_assert(lua_State* L) +{ + if (lua_toboolean(L, 1)) /* condition is true? */ + return lua_gettop(L); /* return all arguments */ + else + { + /* error */ + luaL_checkany(L, 1); /* there must be a condition */ + lua_remove(L, 1); /* remove it */ + lua_pushliteral(L, "assertion failed!"); /* default message */ + lua_settop(L, 1); /* leave only message (default if no other one) */ + return luaB_error(L); /* call 'error' */ + } } -static int luaB_select (lua_State *L) { - int n = lua_gettop(L); - if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { - lua_pushinteger(L, n-1); - return 1; - } - else { - lua_Integer i = luaL_checkinteger(L, 1); - if (i < 0) i = n + i; - else if (i > n) i = n; - luaL_argcheck(L, 1 <= i, 1, "index out of range"); - return n - (int)i; - } +static int luaB_select(lua_State* L) +{ + int n = lua_gettop(L); + if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') + { + lua_pushinteger(L, n - 1); + return 1; + } + else + { + lua_Integer i = luaL_checkinteger(L, 1); + if (i < 0) i = n + i; + else if (i > n) i = n; + luaL_argcheck(L, 1 <= i, 1, "index out of range"); + return n - (int)i; + } } @@ -405,24 +476,28 @@ static int luaB_select (lua_State *L) { ** 'extra' values (where 'extra' is exactly the number of items to be ** ignored). */ -static int finishpcall (lua_State *L, int status, lua_KContext extra) { - if (status != LUA_OK && status != LUA_YIELD) { /* error? */ - lua_pushboolean(L, 0); /* first result (false) */ - lua_pushvalue(L, -2); /* error message */ - return 2; /* return false, msg */ - } - else - return lua_gettop(L) - (int)extra; /* return all results */ +static int finishpcall(lua_State* L, int status, lua_KContext extra) +{ + if (status != LUA_OK && status != LUA_YIELD) + { + /* error? */ + lua_pushboolean(L, 0); /* first result (false) */ + lua_pushvalue(L, -2); /* error message */ + return 2; /* return false, msg */ + } + else + return lua_gettop(L) - (int)extra; /* return all results */ } -static int luaB_pcall (lua_State *L) { - int status; - luaL_checkany(L, 1); - lua_pushboolean(L, 1); /* first result if no errors */ - lua_insert(L, 1); /* put it in place */ - status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall); - return finishpcall(L, status, 0); +static int luaB_pcall(lua_State* L) +{ + int status; + luaL_checkany(L, 1); + lua_pushboolean(L, 1); /* first result if no errors */ + lua_insert(L, 1); /* put it in place */ + status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall); + return finishpcall(L, status, 0); } @@ -431,68 +506,70 @@ static int luaB_pcall (lua_State *L) { ** stack will have ; so, the function passes ** 2 to 'finishpcall' to skip the 2 first values when returning results. */ -static int luaB_xpcall (lua_State *L) { - int status; - int n = lua_gettop(L); - luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */ - lua_pushboolean(L, 1); /* first result */ - lua_pushvalue(L, 1); /* function */ - lua_rotate(L, 3, 2); /* move them below function's arguments */ - status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall); - return finishpcall(L, status, 2); +static int luaB_xpcall(lua_State* L) +{ + int status; + int n = lua_gettop(L); + luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */ + lua_pushboolean(L, 1); /* first result */ + lua_pushvalue(L, 1); /* function */ + lua_rotate(L, 3, 2); /* move them below function's arguments */ + status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall); + return finishpcall(L, status, 2); } -static int luaB_tostring (lua_State *L) { - luaL_checkany(L, 1); - luaL_tolstring(L, 1, NULL); - return 1; +static int luaB_tostring(lua_State* L) +{ + luaL_checkany(L, 1); + luaL_tolstring(L, 1, NULL); + return 1; } static const luaL_Reg base_funcs[] = { - {"assert", luaB_assert}, - {"collectgarbage", luaB_collectgarbage}, - {"dofile", luaB_dofile}, - {"error", luaB_error}, - {"getmetatable", luaB_getmetatable}, - {"ipairs", luaB_ipairs}, - {"loadfile", luaB_loadfile}, - {"load", luaB_load}, + {"assert", luaB_assert}, + {"collectgarbage", luaB_collectgarbage}, + {"dofile", luaB_dofile}, + {"error", luaB_error}, + {"getmetatable", luaB_getmetatable}, + {"ipairs", luaB_ipairs}, + {"loadfile", luaB_loadfile}, + {"load", luaB_load}, #if defined(LUA_COMPAT_LOADSTRING) {"loadstring", luaB_load}, #endif - {"next", luaB_next}, - {"pairs", luaB_pairs}, - {"pcall", luaB_pcall}, - {"print", luaB_print}, - {"rawequal", luaB_rawequal}, - {"rawlen", luaB_rawlen}, - {"rawget", luaB_rawget}, - {"rawset", luaB_rawset}, - {"select", luaB_select}, - {"setmetatable", luaB_setmetatable}, - {"tonumber", luaB_tonumber}, - {"tostring", luaB_tostring}, - {"type", luaB_type}, - {"xpcall", luaB_xpcall}, - /* placeholders */ - {"_G", NULL}, - {"_VERSION", NULL}, - {NULL, NULL} + {"next", luaB_next}, + {"pairs", luaB_pairs}, + {"pcall", luaB_pcall}, + {"print", luaB_print}, + {"rawequal", luaB_rawequal}, + {"rawlen", luaB_rawlen}, + {"rawget", luaB_rawget}, + {"rawset", luaB_rawset}, + {"select", luaB_select}, + {"setmetatable", luaB_setmetatable}, + {"tonumber", luaB_tonumber}, + {"tostring", luaB_tostring}, + {"type", luaB_type}, + {"xpcall", luaB_xpcall}, + /* placeholders */ + {"_G", NULL}, + {"_VERSION", NULL}, + {NULL, NULL} }; -LUAMOD_API int luaopen_base (lua_State *L) { - /* open lib into global table */ - lua_pushglobaltable(L); - luaL_setfuncs(L, base_funcs, 0); - /* set global _G */ - lua_pushvalue(L, -1); - lua_setfield(L, -2, "_G"); - /* set global _VERSION */ - lua_pushliteral(L, LUA_VERSION); - lua_setfield(L, -2, "_VERSION"); - return 1; +LUAMOD_API int luaopen_base(lua_State* L) +{ + /* open lib into global table */ + lua_pushglobaltable(L); + luaL_setfuncs(L, base_funcs, 0); + /* set global _G */ + lua_pushvalue(L, -1); + lua_setfield(L, -2, "_G"); + /* set global _VERSION */ + lua_pushliteral(L, LUA_VERSION); + lua_setfield(L, -2, "_VERSION"); + return 1; } - diff --git a/Lua/lbitlib.c b/Lua/lbitlib.c index 1cb1d5b..77a628a 100644 --- a/Lua/lbitlib.c +++ b/Lua/lbitlib.c @@ -226,8 +226,9 @@ LUAMOD_API int luaopen_bit32 (lua_State *L) { #else /* }{ */ -LUAMOD_API int luaopen_bit32 (lua_State *L) { - return luaL_error(L, "library 'bit32' has been deprecated"); +LUAMOD_API int luaopen_bit32(lua_State* L) +{ + return luaL_error(L, "library 'bit32' has been deprecated"); } #endif /* } */ diff --git a/Lua/lcode.c b/Lua/lcode.c index 0bb4142..8e18c9a 100644 --- a/Lua/lcode.c +++ b/Lua/lcode.c @@ -40,18 +40,20 @@ ** If expression is a numeric constant, fills 'v' with its value ** and returns 1. Otherwise, returns 0. */ -static int tonumeral(const expdesc *e, TValue *v) { - if (hasjumps(e)) - return 0; /* not a numeral */ - switch (e->k) { - case VKINT: - if (v) setivalue(v, e->u.ival); - return 1; - case VKFLT: - if (v) setfltvalue(v, e->u.nval); - return 1; - default: return 0; - } +static int tonumeral(const expdesc* e, TValue* v) +{ + if (hasjumps(e)) + return 0; /* not a numeral */ + switch (e->k) + { + case VKINT: + if (v) setivalue(v, e->u.ival); + return 1; + case VKFLT: + if (v) setfltvalue(v, e->u.nval); + return 1; + default: return 0; + } } @@ -61,25 +63,32 @@ static int tonumeral(const expdesc *e, TValue *v) { ** range of previous instruction instead of emitting a new one. (For ** instance, 'local a; local b' will generate a single opcode.) */ -void luaK_nil (FuncState *fs, int from, int n) { - Instruction *previous; - int l = from + n - 1; /* last register to set nil */ - if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ - previous = &fs->f->code[fs->pc-1]; - if (GET_OPCODE(*previous) == OP_LOADNIL) { /* previous is LOADNIL? */ - int pfrom = GETARG_A(*previous); /* get previous range */ - int pl = pfrom + GETARG_B(*previous); - if ((pfrom <= from && from <= pl + 1) || - (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ - if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ - if (pl > l) l = pl; /* l = max(l, pl) */ - SETARG_A(*previous, from); - SETARG_B(*previous, l - from); - return; - } - } /* else go through */ - } - luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ +void luaK_nil(FuncState* fs, int from, int n) +{ + Instruction* previous; + int l = from + n - 1; /* last register to set nil */ + if (fs->pc > fs->lasttarget) + { + /* no jumps to current position? */ + previous = &fs->f->code[fs->pc - 1]; + if (GET_OPCODE(*previous) == OP_LOADNIL) + { + /* previous is LOADNIL? */ + int pfrom = GETARG_A(*previous); /* get previous range */ + int pl = pfrom + GETARG_B(*previous); + if ((pfrom <= from && from <= pl + 1) || + (from <= pfrom && pfrom <= l + 1)) + { + /* can connect both? */ + if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ + if (pl > l) l = pl; /* l = max(l, pl) */ + SETARG_A(*previous, from); + SETARG_B(*previous, l - from); + return; + } + } /* else go through */ + } + luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ } @@ -87,12 +96,13 @@ void luaK_nil (FuncState *fs, int from, int n) { ** Gets the destination address of a jump instruction. Used to traverse ** a list of jumps. */ -static int getjump (FuncState *fs, int pc) { - int offset = GETARG_sBx(fs->f->code[pc]); - if (offset == NO_JUMP) /* point to itself represents end of list */ - return NO_JUMP; /* end of list */ - else - return (pc+1)+offset; /* turn offset into absolute position */ +static int getjump(FuncState* fs, int pc) +{ + int offset = GETARG_sBx(fs->f->code[pc]); + if (offset == NO_JUMP) /* point to itself represents end of list */ + return NO_JUMP; /* end of list */ + else + return (pc + 1) + offset; /* turn offset into absolute position */ } @@ -100,30 +110,33 @@ static int getjump (FuncState *fs, int pc) { ** Fix jump instruction at position 'pc' to jump to 'dest'. ** (Jump addresses are relative in Lua) */ -static void fixjump (FuncState *fs, int pc, int dest) { - Instruction *jmp = &fs->f->code[pc]; - int offset = dest - (pc + 1); - lua_assert(dest != NO_JUMP); - if (abs(offset) > MAXARG_sBx) - luaX_syntaxerror(fs->ls, "control structure too long"); - SETARG_sBx(*jmp, offset); +static void fixjump(FuncState* fs, int pc, int dest) +{ + Instruction* jmp = &fs->f->code[pc]; + int offset = dest - (pc + 1); + lua_assert(dest != NO_JUMP); + if (abs(offset) > MAXARG_sBx) + luaX_syntaxerror(fs->ls, "control structure too long"); + SETARG_sBx(*jmp, offset); } /* ** Concatenate jump-list 'l2' into jump-list 'l1' */ -void luaK_concat (FuncState *fs, int *l1, int l2) { - if (l2 == NO_JUMP) return; /* nothing to concatenate? */ - else if (*l1 == NO_JUMP) /* no original list? */ - *l1 = l2; /* 'l1' points to 'l2' */ - else { - int list = *l1; - int next; - while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ - list = next; - fixjump(fs, list, l2); /* last element links to 'l2' */ - } +void luaK_concat(FuncState* fs, int* l1, int l2) +{ + if (l2 == NO_JUMP) return; /* nothing to concatenate? */ + else if (*l1 == NO_JUMP) /* no original list? */ + *l1 = l2; /* 'l1' points to 'l2' */ + else + { + int list = *l1; + int next; + while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ + list = next; + fixjump(fs, list, l2); /* last element links to 'l2' */ + } } @@ -133,21 +146,23 @@ void luaK_concat (FuncState *fs, int *l1, int l2) { ** this position (kept in 'jpc'), link them all together so that ** 'patchlistaux' will fix all them directly to the final destination. */ -int luaK_jump (FuncState *fs) { - int jpc = fs->jpc; /* save list of jumps to here */ - int j; - fs->jpc = NO_JUMP; /* no more jumps to here */ - j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); - luaK_concat(fs, &j, jpc); /* keep them on hold */ - return j; +int luaK_jump(FuncState* fs) +{ + int jpc = fs->jpc; /* save list of jumps to here */ + int j; + fs->jpc = NO_JUMP; /* no more jumps to here */ + j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); + luaK_concat(fs, &j, jpc); /* keep them on hold */ + return j; } /* ** Code a 'return' instruction */ -void luaK_ret (FuncState *fs, int first, int nret) { - luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); +void luaK_ret(FuncState* fs, int first, int nret) +{ + luaK_codeABC(fs, OP_RETURN, first, nret + 1, 0); } @@ -155,9 +170,10 @@ void luaK_ret (FuncState *fs, int first, int nret) { ** Code a "conditional jump", that is, a test or comparison opcode ** followed by a jump. Return jump position. */ -static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { - luaK_codeABC(fs, op, A, B, C); - return luaK_jump(fs); +static int condjump(FuncState* fs, OpCode op, int A, int B, int C) +{ + luaK_codeABC(fs, op, A, B, C); + return luaK_jump(fs); } @@ -165,9 +181,10 @@ static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { ** returns current 'pc' and marks it as a jump target (to avoid wrong ** optimizations with consecutive instructions not in the same basic block). */ -int luaK_getlabel (FuncState *fs) { - fs->lasttarget = fs->pc; - return fs->pc; +int luaK_getlabel(FuncState* fs) +{ + fs->lasttarget = fs->pc; + return fs->pc; } @@ -176,12 +193,13 @@ int luaK_getlabel (FuncState *fs) { ** jump (that is, its condition), or the jump itself if it is ** unconditional. */ -static Instruction *getjumpcontrol (FuncState *fs, int pc) { - Instruction *pi = &fs->f->code[pc]; - if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) - return pi-1; - else - return pi; +static Instruction* getjumpcontrol(FuncState* fs, int pc) +{ + Instruction* pi = &fs->f->code[pc]; + if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) + return pi - 1; + else + return pi; } @@ -192,27 +210,30 @@ static Instruction *getjumpcontrol (FuncState *fs, int pc) { ** register. Otherwise, change instruction to a simple 'TEST' (produces ** no register value) */ -static int patchtestreg (FuncState *fs, int node, int reg) { - Instruction *i = getjumpcontrol(fs, node); - if (GET_OPCODE(*i) != OP_TESTSET) - return 0; /* cannot patch other instructions */ - if (reg != NO_REG && reg != GETARG_B(*i)) - SETARG_A(*i, reg); - else { - /* no register to put value or register already has the value; - change instruction to simple test */ - *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); - } - return 1; +static int patchtestreg(FuncState* fs, int node, int reg) +{ + Instruction* i = getjumpcontrol(fs, node); + if (GET_OPCODE(*i) != OP_TESTSET) + return 0; /* cannot patch other instructions */ + if (reg != NO_REG && reg != GETARG_B(*i)) + SETARG_A(*i, reg); + else + { + /* no register to put value or register already has the value; + change instruction to simple test */ + *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); + } + return 1; } /* ** Traverse a list of tests ensuring no one produces a value */ -static void removevalues (FuncState *fs, int list) { - for (; list != NO_JUMP; list = getjump(fs, list)) - patchtestreg(fs, list, NO_REG); +static void removevalues(FuncState* fs, int list) +{ + for (; list != NO_JUMP; list = getjump(fs, list)) + patchtestreg(fs, list, NO_REG); } @@ -221,16 +242,18 @@ static void removevalues (FuncState *fs, int list) { ** registers: tests producing values jump to 'vtarget' (and put their ** values in 'reg'), other tests jump to 'dtarget'. */ -static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, - int dtarget) { - while (list != NO_JUMP) { - int next = getjump(fs, list); - if (patchtestreg(fs, list, reg)) - fixjump(fs, list, vtarget); - else - fixjump(fs, list, dtarget); /* jump to default target */ - list = next; - } +static void patchlistaux(FuncState* fs, int list, int vtarget, int reg, + int dtarget) +{ + while (list != NO_JUMP) + { + int next = getjump(fs, list); + if (patchtestreg(fs, list, reg)) + fixjump(fs, list, vtarget); + else + fixjump(fs, list, dtarget); /* jump to default target */ + list = next; + } } @@ -239,9 +262,10 @@ static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, ** to current position with no values) and reset list of pending ** jumps */ -static void dischargejpc (FuncState *fs) { - patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); - fs->jpc = NO_JUMP; +static void dischargejpc(FuncState* fs) +{ + patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); + fs->jpc = NO_JUMP; } @@ -249,9 +273,10 @@ static void dischargejpc (FuncState *fs) { ** Add elements in 'list' to list of pending jumps to "here" ** (current position) */ -void luaK_patchtohere (FuncState *fs, int list) { - luaK_getlabel(fs); /* mark "here" as a jump target */ - luaK_concat(fs, &fs->jpc, list); +void luaK_patchtohere(FuncState* fs, int list) +{ + luaK_getlabel(fs); /* mark "here" as a jump target */ + luaK_concat(fs, &fs->jpc, list); } @@ -260,13 +285,15 @@ void luaK_patchtohere (FuncState *fs, int list) { ** (The assert means that we cannot fix a jump to a forward address ** because we only know addresses once code is generated.) */ -void luaK_patchlist (FuncState *fs, int list, int target) { - if (target == fs->pc) /* 'target' is current position? */ - luaK_patchtohere(fs, list); /* add list to pending jumps */ - else { - lua_assert(target < fs->pc); - patchlistaux(fs, list, target, NO_REG, target); - } +void luaK_patchlist(FuncState* fs, int list, int target) +{ + if (target == fs->pc) /* 'target' is current position? */ + luaK_patchtohere(fs, list); /* add list to pending jumps */ + else + { + lua_assert(target < fs->pc); + patchlistaux(fs, list, target, NO_REG, target); + } } @@ -275,14 +302,16 @@ void luaK_patchlist (FuncState *fs, int list, int target) { ** (The assertion checks that jumps either were closing nothing ** or were closing higher levels, from inner blocks.) */ -void luaK_patchclose (FuncState *fs, int list, int level) { - level++; /* argument is +1 to reserve 0 as non-op */ - for (; list != NO_JUMP; list = getjump(fs, list)) { - lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && - (GETARG_A(fs->f->code[list]) == 0 || - GETARG_A(fs->f->code[list]) >= level)); - SETARG_A(fs->f->code[list], level); - } +void luaK_patchclose(FuncState* fs, int list, int level) +{ + level++; /* argument is +1 to reserve 0 as non-op */ + for (; list != NO_JUMP; list = getjump(fs, list)) + { + lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && + (GETARG_A(fs->f->code[list]) == 0 || + GETARG_A(fs->f->code[list]) >= level)); + SETARG_A(fs->f->code[list], level); + } } @@ -290,18 +319,19 @@ void luaK_patchclose (FuncState *fs, int list, int level) { ** Emit instruction 'i', checking for array sizes and saving also its ** line information. Return 'i' position. */ -static int luaK_code (FuncState *fs, Instruction i) { - Proto *f = fs->f; - dischargejpc(fs); /* 'pc' will change */ - /* put new instruction in code array */ - luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, - MAX_INT, "opcodes"); - f->code[fs->pc] = i; - /* save corresponding line information */ - luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int, - MAX_INT, "opcodes"); - f->lineinfo[fs->pc] = fs->ls->lastline; - return fs->pc++; +static int luaK_code(FuncState* fs, Instruction i) +{ + Proto* f = fs->f; + dischargejpc(fs); /* 'pc' will change */ + /* put new instruction in code array */ + luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, + MAX_INT, "opcodes"); + f->code[fs->pc] = i; + /* save corresponding line information */ + luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int, + MAX_INT, "opcodes"); + f->lineinfo[fs->pc] = fs->ls->lastline; + return fs->pc++; } @@ -309,32 +339,35 @@ static int luaK_code (FuncState *fs, Instruction i) { ** Format and emit an 'iABC' instruction. (Assertions check consistency ** of parameters versus opcode.) */ -int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { - lua_assert(getOpMode(o) == iABC); - lua_assert(getBMode(o) != OpArgN || b == 0); - lua_assert(getCMode(o) != OpArgN || c == 0); - lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C); - return luaK_code(fs, CREATE_ABC(o, a, b, c)); +int luaK_codeABC(FuncState* fs, OpCode o, int a, int b, int c) +{ + lua_assert(getOpMode(o) == iABC); + lua_assert(getBMode(o) != OpArgN || b == 0); + lua_assert(getCMode(o) != OpArgN || c == 0); + lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C); + return luaK_code(fs, CREATE_ABC(o, a, b, c)); } /* ** Format and emit an 'iABx' instruction. */ -int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { - lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); - lua_assert(getCMode(o) == OpArgN); - lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); - return luaK_code(fs, CREATE_ABx(o, a, bc)); +int luaK_codeABx(FuncState* fs, OpCode o, int a, unsigned int bc) +{ + lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); + lua_assert(getCMode(o) == OpArgN); + lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); + return luaK_code(fs, CREATE_ABx(o, a, bc)); } /* ** Emit an "extra argument" instruction (format 'iAx') */ -static int codeextraarg (FuncState *fs, int a) { - lua_assert(a <= MAXARG_Ax); - return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); +static int codeextraarg(FuncState* fs, int a) +{ + lua_assert(a <= MAXARG_Ax); + return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); } @@ -343,14 +376,16 @@ static int codeextraarg (FuncState *fs, int a) { ** (if constant index 'k' fits in 18 bits) or an 'OP_LOADKX' ** instruction with "extra argument". */ -int luaK_codek (FuncState *fs, int reg, int k) { - if (k <= MAXARG_Bx) - return luaK_codeABx(fs, OP_LOADK, reg, k); - else { - int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); - codeextraarg(fs, k); - return p; - } +int luaK_codek(FuncState* fs, int reg, int k) +{ + if (k <= MAXARG_Bx) + return luaK_codeABx(fs, OP_LOADK, reg, k); + else + { + int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); + codeextraarg(fs, k); + return p; + } } @@ -358,23 +393,26 @@ int luaK_codek (FuncState *fs, int reg, int k) { ** Check register-stack level, keeping track of its maximum size ** in field 'maxstacksize' */ -void luaK_checkstack (FuncState *fs, int n) { - int newstack = fs->freereg + n; - if (newstack > fs->f->maxstacksize) { - if (newstack >= MAXREGS) - luaX_syntaxerror(fs->ls, - "function or expression needs too many registers"); - fs->f->maxstacksize = cast_byte(newstack); - } +void luaK_checkstack(FuncState* fs, int n) +{ + int newstack = fs->freereg + n; + if (newstack > fs->f->maxstacksize) + { + if (newstack >= MAXREGS) + luaX_syntaxerror(fs->ls, + "function or expression needs too many registers"); + fs->f->maxstacksize = cast_byte(newstack); + } } /* ** Reserve 'n' registers in register stack */ -void luaK_reserveregs (FuncState *fs, int n) { - luaK_checkstack(fs, n); - fs->freereg += n; +void luaK_reserveregs(FuncState* fs, int n) +{ + luaK_checkstack(fs, n); + fs->freereg += n; } @@ -383,20 +421,23 @@ void luaK_reserveregs (FuncState *fs, int n) { ** a local variable. ) */ -static void freereg (FuncState *fs, int reg) { - if (!ISK(reg) && reg >= fs->nactvar) { - fs->freereg--; - lua_assert(reg == fs->freereg); - } +static void freereg(FuncState* fs, int reg) +{ + if (!ISK(reg) && reg >= fs->nactvar) + { + fs->freereg--; + lua_assert(reg == fs->freereg); + } } /* ** Free register used by expression 'e' (if any) */ -static void freeexp (FuncState *fs, expdesc *e) { - if (e->k == VNONRELOC) - freereg(fs, e->u.info); +static void freeexp(FuncState* fs, expdesc* e) +{ + if (e->k == VNONRELOC) + freereg(fs, e->u.info); } @@ -404,17 +445,20 @@ static void freeexp (FuncState *fs, expdesc *e) { ** Free registers used by expressions 'e1' and 'e2' (if any) in proper ** order. */ -static void freeexps (FuncState *fs, expdesc *e1, expdesc *e2) { - int r1 = (e1->k == VNONRELOC) ? e1->u.info : -1; - int r2 = (e2->k == VNONRELOC) ? e2->u.info : -1; - if (r1 > r2) { - freereg(fs, r1); - freereg(fs, r2); - } - else { - freereg(fs, r2); - freereg(fs, r1); - } +static void freeexps(FuncState* fs, expdesc* e1, expdesc* e2) +{ + int r1 = (e1->k == VNONRELOC) ? e1->u.info : -1; + int r2 = (e2->k == VNONRELOC) ? e2->u.info : -1; + if (r1 > r2) + { + freereg(fs, r1); + freereg(fs, r2); + } + else + { + freereg(fs, r2); + freereg(fs, r1); + } } @@ -425,40 +469,45 @@ static void freeexps (FuncState *fs, expdesc *e1, expdesc *e2) { ** as keys (nil cannot be a key, integer keys can collapse with float ** keys), the caller must provide a useful 'key' for indexing the cache. */ -static int addk (FuncState *fs, TValue *key, TValue *v) { - lua_State *L = fs->ls->L; - Proto *f = fs->f; - TValue *idx = luaH_set(L, fs->ls->h, key); /* index scanner table */ - int k, oldsize; - if (ttisinteger(idx)) { /* is there an index there? */ - k = cast_int(ivalue(idx)); - /* correct value? (warning: must distinguish floats from integers!) */ - if (k < fs->nk && ttype(&f->k[k]) == ttype(v) && - luaV_rawequalobj(&f->k[k], v)) - return k; /* reuse index */ - } - /* constant not found; create a new entry */ - oldsize = f->sizek; - k = fs->nk; - /* numerical value does not need GC barrier; - table has no metatable, so it does not need to invalidate cache */ - setivalue(idx, k); - luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); - while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); - setobj(L, &f->k[k], v); - fs->nk++; - luaC_barrier(L, f, v); - return k; +static int addk(FuncState* fs, TValue* key, TValue* v) +{ + lua_State* L = fs->ls->L; + Proto* f = fs->f; + TValue* idx = luaH_set(L, fs->ls->h, key); /* index scanner table */ + int k, oldsize; + if (ttisinteger(idx)) + { + /* is there an index there? */ + k = cast_int(ivalue(idx)); + /* correct value? (warning: must distinguish floats from integers!) */ + if (k < fs->nk && ttype(&f->k[k]) == ttype(v) && + luaV_rawequalobj(&f->k[k], v)) + return k; /* reuse index */ + } + /* constant not found; create a new entry */ + oldsize = f->sizek; + k = fs->nk; + /* numerical value does not need GC barrier; + table has no metatable, so it does not need to invalidate cache */ + setivalue(idx, k); + luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); + while (oldsize < f->sizek) + setnilvalue(&f->k[oldsize++]); + setobj(L, &f->k[k], v); + fs->nk++; + luaC_barrier(L, f, v); + return k; } /* ** Add a string to list of constants and return its index. */ -int luaK_stringK (FuncState *fs, TString *s) { - TValue o; - setsvalue(fs->ls->L, &o, s); - return addk(fs, &o, &o); /* use string itself as key */ +int luaK_stringK(FuncState* fs, TString* s) +{ + TValue o; + setsvalue(fs->ls->L, &o, s); + return addk(fs, &o, &o); /* use string itself as key */ } @@ -468,42 +517,46 @@ int luaK_stringK (FuncState *fs, TString *s) { ** same value; conversion to 'void*' is used only for hashing, so there ** are no "precision" problems. */ -int luaK_intK (FuncState *fs, lua_Integer n) { - TValue k, o; - setpvalue(&k, cast(void*, cast(size_t, n))); - setivalue(&o, n); - return addk(fs, &k, &o); +int luaK_intK(FuncState* fs, lua_Integer n) +{ + TValue k, o; + setpvalue(&k, cast(void*, cast(size_t, n))); + setivalue(&o, n); + return addk(fs, &k, &o); } /* ** Add a float to list of constants and return its index. */ -static int luaK_numberK (FuncState *fs, lua_Number r) { - TValue o; - setfltvalue(&o, r); - return addk(fs, &o, &o); /* use number itself as key */ +static int luaK_numberK(FuncState* fs, lua_Number r) +{ + TValue o; + setfltvalue(&o, r); + return addk(fs, &o, &o); /* use number itself as key */ } /* ** Add a boolean to list of constants and return its index. */ -static int boolK (FuncState *fs, int b) { - TValue o; - setbvalue(&o, b); - return addk(fs, &o, &o); /* use boolean itself as key */ +static int boolK(FuncState* fs, int b) +{ + TValue o; + setbvalue(&o, b); + return addk(fs, &o, &o); /* use boolean itself as key */ } /* ** Add nil to list of constants and return its index. */ -static int nilK (FuncState *fs) { - TValue k, v; - setnilvalue(&v); - /* cannot use nil as key; instead use table itself to represent nil */ - sethvalue(fs->ls->L, &k, fs->ls->h); - return addk(fs, &k, &v); +static int nilK(FuncState* fs) +{ + TValue k, v; + setnilvalue(&v); + /* cannot use nil as key; instead use table itself to represent nil */ + sethvalue(fs->ls->L, &k, fs->ls->h); + return addk(fs, &k, &v); } @@ -512,17 +565,22 @@ static int nilK (FuncState *fs) { ** Either 'e' is a multi-ret expression (function call or vararg) ** or 'nresults' is LUA_MULTRET (as any expression can satisfy that). */ -void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { - if (e->k == VCALL) { /* expression is an open function call? */ - SETARG_C(getinstruction(fs, e), nresults + 1); - } - else if (e->k == VVARARG) { - Instruction *pc = &getinstruction(fs, e); - SETARG_B(*pc, nresults + 1); - SETARG_A(*pc, fs->freereg); - luaK_reserveregs(fs, 1); - } - else lua_assert(nresults == LUA_MULTRET); +void luaK_setreturns(FuncState* fs, expdesc* e, int nresults) +{ + if (e->k == VCALL) + { + /* expression is an open function call? */ + SETARG_C(getinstruction(fs, e), nresults + 1); + } + else if (e->k == VVARARG) + { + Instruction* pc = &getinstruction(fs, e); + SETARG_B(*pc, nresults + 1); + SETARG_A(*pc, fs->freereg); + luaK_reserveregs(fs, 1); + } + else + lua_assert(nresults == LUA_MULTRET); } @@ -536,55 +594,71 @@ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { ** (Calls are created returning one result, so that does not need ** to be fixed.) */ -void luaK_setoneret (FuncState *fs, expdesc *e) { - if (e->k == VCALL) { /* expression is an open function call? */ - /* already returns 1 value */ - lua_assert(GETARG_C(getinstruction(fs, e)) == 2); - e->k = VNONRELOC; /* result has fixed position */ - e->u.info = GETARG_A(getinstruction(fs, e)); - } - else if (e->k == VVARARG) { - SETARG_B(getinstruction(fs, e), 2); - e->k = VRELOCABLE; /* can relocate its simple result */ - } +void luaK_setoneret(FuncState* fs, expdesc* e) +{ + if (e->k == VCALL) + { + /* expression is an open function call? */ + /* already returns 1 value */ + lua_assert(GETARG_C(getinstruction(fs, e)) == 2); + e->k = VNONRELOC; /* result has fixed position */ + e->u.info = GETARG_A(getinstruction(fs, e)); + } + else if (e->k == VVARARG) + { + SETARG_B(getinstruction(fs, e), 2); + e->k = VRELOCABLE; /* can relocate its simple result */ + } } /* ** Ensure that expression 'e' is not a variable. */ -void luaK_dischargevars (FuncState *fs, expdesc *e) { - switch (e->k) { - case VLOCAL: { /* already in a register */ - e->k = VNONRELOC; /* becomes a non-relocatable value */ - break; - } - case VUPVAL: { /* move value to some (pending) register */ - e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); - e->k = VRELOCABLE; - break; - } - case VINDEXED: { - OpCode op; - freereg(fs, e->u.ind.idx); - if (e->u.ind.vt == VLOCAL) { /* is 't' in a register? */ - freereg(fs, e->u.ind.t); - op = OP_GETTABLE; - } - else { - lua_assert(e->u.ind.vt == VUPVAL); - op = OP_GETTABUP; /* 't' is in an upvalue */ - } - e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); - e->k = VRELOCABLE; - break; - } - case VVARARG: case VCALL: { - luaK_setoneret(fs, e); - break; - } - default: break; /* there is one value available (somewhere) */ - } +void luaK_dischargevars(FuncState* fs, expdesc* e) +{ + switch (e->k) + { + case VLOCAL: + { + /* already in a register */ + e->k = VNONRELOC; /* becomes a non-relocatable value */ + break; + } + case VUPVAL: + { + /* move value to some (pending) register */ + e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); + e->k = VRELOCABLE; + break; + } + case VINDEXED: + { + OpCode op; + freereg(fs, e->u.ind.idx); + if (e->u.ind.vt == VLOCAL) + { + /* is 't' in a register? */ + freereg(fs, e->u.ind.t); + op = OP_GETTABLE; + } + else + { + lua_assert(e->u.ind.vt == VUPVAL); + op = OP_GETTABUP; /* 't' is in an upvalue */ + } + e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); + e->k = VRELOCABLE; + break; + } + case VVARARG: + case VCALL: + { + luaK_setoneret(fs, e); + break; + } + default: break; /* there is one value available (somewhere) */ + } } @@ -592,63 +666,78 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { ** Ensures expression value is in register 'reg' (and therefore ** 'e' will become a non-relocatable expression). */ -static void discharge2reg (FuncState *fs, expdesc *e, int reg) { - luaK_dischargevars(fs, e); - switch (e->k) { - case VNIL: { - luaK_nil(fs, reg, 1); - break; - } - case VFALSE: case VTRUE: { - luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); - break; - } - case VK: { - luaK_codek(fs, reg, e->u.info); - break; - } - case VKFLT: { - luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval)); - break; - } - case VKINT: { - luaK_codek(fs, reg, luaK_intK(fs, e->u.ival)); - break; - } - case VRELOCABLE: { - Instruction *pc = &getinstruction(fs, e); - SETARG_A(*pc, reg); /* instruction will put result in 'reg' */ - break; - } - case VNONRELOC: { - if (reg != e->u.info) - luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); - break; - } - default: { - lua_assert(e->k == VJMP); - return; /* nothing to do... */ - } - } - e->u.info = reg; - e->k = VNONRELOC; +static void discharge2reg(FuncState* fs, expdesc* e, int reg) +{ + luaK_dischargevars(fs, e); + switch (e->k) + { + case VNIL: + { + luaK_nil(fs, reg, 1); + break; + } + case VFALSE: + case VTRUE: + { + luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); + break; + } + case VK: + { + luaK_codek(fs, reg, e->u.info); + break; + } + case VKFLT: + { + luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval)); + break; + } + case VKINT: + { + luaK_codek(fs, reg, luaK_intK(fs, e->u.ival)); + break; + } + case VRELOCABLE: + { + Instruction* pc = &getinstruction(fs, e); + SETARG_A(*pc, reg); /* instruction will put result in 'reg' */ + break; + } + case VNONRELOC: + { + if (reg != e->u.info) + luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); + break; + } + default: + { + lua_assert(e->k == VJMP); + return; /* nothing to do... */ + } + } + e->u.info = reg; + e->k = VNONRELOC; } /* ** Ensures expression value is in any register. */ -static void discharge2anyreg (FuncState *fs, expdesc *e) { - if (e->k != VNONRELOC) { /* no fixed register yet? */ - luaK_reserveregs(fs, 1); /* get a register */ - discharge2reg(fs, e, fs->freereg-1); /* put value there */ - } +static void discharge2anyreg(FuncState* fs, expdesc* e) +{ + if (e->k != VNONRELOC) + { + /* no fixed register yet? */ + luaK_reserveregs(fs, 1); /* get a register */ + discharge2reg(fs, e, fs->freereg - 1); /* put value there */ + } } -static int code_loadbool (FuncState *fs, int A, int b, int jump) { - luaK_getlabel(fs); /* those instructions may be jump targets */ - return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); +static int code_loadbool(FuncState* fs, int A, int b, int jump) +{ + luaK_getlabel(fs); /* those instructions may be jump targets */ + return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); } @@ -656,12 +745,14 @@ static int code_loadbool (FuncState *fs, int A, int b, int jump) { ** check whether list has any jump that do not produce a value ** or produce an inverted value */ -static int need_value (FuncState *fs, int list) { - for (; list != NO_JUMP; list = getjump(fs, list)) { - Instruction i = *getjumpcontrol(fs, list); - if (GET_OPCODE(i) != OP_TESTSET) return 1; - } - return 0; /* not found */ +static int need_value(FuncState* fs, int list) +{ + for (; list != NO_JUMP; list = getjump(fs, list)) + { + Instruction i = *getjumpcontrol(fs, list); + if (GET_OPCODE(i) != OP_TESTSET) return 1; + } + return 0; /* not found */ } @@ -672,27 +763,30 @@ static int need_value (FuncState *fs, int list) { ** its final position or to "load" instructions (for those tests ** that do not produce values). */ -static void exp2reg (FuncState *fs, expdesc *e, int reg) { - discharge2reg(fs, e, reg); - if (e->k == VJMP) /* expression itself is a test? */ - luaK_concat(fs, &e->t, e->u.info); /* put this jump in 't' list */ - if (hasjumps(e)) { - int final; /* position after whole expression */ - int p_f = NO_JUMP; /* position of an eventual LOAD false */ - int p_t = NO_JUMP; /* position of an eventual LOAD true */ - if (need_value(fs, e->t) || need_value(fs, e->f)) { - int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); - p_f = code_loadbool(fs, reg, 0, 1); - p_t = code_loadbool(fs, reg, 1, 0); - luaK_patchtohere(fs, fj); - } - final = luaK_getlabel(fs); - patchlistaux(fs, e->f, final, reg, p_f); - patchlistaux(fs, e->t, final, reg, p_t); - } - e->f = e->t = NO_JUMP; - e->u.info = reg; - e->k = VNONRELOC; +static void exp2reg(FuncState* fs, expdesc* e, int reg) +{ + discharge2reg(fs, e, reg); + if (e->k == VJMP) /* expression itself is a test? */ + luaK_concat(fs, &e->t, e->u.info); /* put this jump in 't' list */ + if (hasjumps(e)) + { + int final; /* position after whole expression */ + int p_f = NO_JUMP; /* position of an eventual LOAD false */ + int p_t = NO_JUMP; /* position of an eventual LOAD true */ + if (need_value(fs, e->t) || need_value(fs, e->f)) + { + int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); + p_f = code_loadbool(fs, reg, 0, 1); + p_t = code_loadbool(fs, reg, 1, 0); + luaK_patchtohere(fs, fj); + } + final = luaK_getlabel(fs); + patchlistaux(fs, e->f, final, reg, p_f); + patchlistaux(fs, e->t, final, reg, p_t); + } + e->f = e->t = NO_JUMP; + e->u.info = reg; + e->k = VNONRELOC; } @@ -700,11 +794,12 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) { ** Ensures final expression result (including results from its jump ** lists) is in next available register. */ -void luaK_exp2nextreg (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - freeexp(fs, e); - luaK_reserveregs(fs, 1); - exp2reg(fs, e, fs->freereg - 1); +void luaK_exp2nextreg(FuncState* fs, expdesc* e) +{ + luaK_dischargevars(fs, e); + freeexp(fs, e); + luaK_reserveregs(fs, 1); + exp2reg(fs, e, fs->freereg - 1); } @@ -712,18 +807,23 @@ void luaK_exp2nextreg (FuncState *fs, expdesc *e) { ** Ensures final expression result (including results from its jump ** lists) is in some (any) register and return that register. */ -int luaK_exp2anyreg (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - if (e->k == VNONRELOC) { /* expression already has a register? */ - if (!hasjumps(e)) /* no jumps? */ - return e->u.info; /* result is already in a register */ - if (e->u.info >= fs->nactvar) { /* reg. is not a local? */ - exp2reg(fs, e, e->u.info); /* put final result in it */ - return e->u.info; - } - } - luaK_exp2nextreg(fs, e); /* otherwise, use next available register */ - return e->u.info; +int luaK_exp2anyreg(FuncState* fs, expdesc* e) +{ + luaK_dischargevars(fs, e); + if (e->k == VNONRELOC) + { + /* expression already has a register? */ + if (!hasjumps(e)) /* no jumps? */ + return e->u.info; /* result is already in a register */ + if (e->u.info >= fs->nactvar) + { + /* reg. is not a local? */ + exp2reg(fs, e, e->u.info); /* put final result in it */ + return e->u.info; + } + } + luaK_exp2nextreg(fs, e); /* otherwise, use next available register */ + return e->u.info; } @@ -731,9 +831,10 @@ int luaK_exp2anyreg (FuncState *fs, expdesc *e) { ** Ensures final expression result is either in a register or in an ** upvalue. */ -void luaK_exp2anyregup (FuncState *fs, expdesc *e) { - if (e->k != VUPVAL || hasjumps(e)) - luaK_exp2anyreg(fs, e); +void luaK_exp2anyregup(FuncState* fs, expdesc* e) +{ + if (e->k != VUPVAL || hasjumps(e)) + luaK_exp2anyreg(fs, e); } @@ -741,11 +842,12 @@ void luaK_exp2anyregup (FuncState *fs, expdesc *e) { ** Ensures final expression result is either in a register or it is ** a constant. */ -void luaK_exp2val (FuncState *fs, expdesc *e) { - if (hasjumps(e)) - luaK_exp2anyreg(fs, e); - else - luaK_dischargevars(fs, e); +void luaK_exp2val(FuncState* fs, expdesc* e) +{ + if (hasjumps(e)) + luaK_exp2anyreg(fs, e); + else + luaK_dischargevars(fs, e); } @@ -755,78 +857,93 @@ void luaK_exp2val (FuncState *fs, expdesc *e) { ** in the range of R/K indices). ** Returns R/K index. */ -int luaK_exp2RK (FuncState *fs, expdesc *e) { - luaK_exp2val(fs, e); - switch (e->k) { /* move constants to 'k' */ - case VTRUE: e->u.info = boolK(fs, 1); goto vk; - case VFALSE: e->u.info = boolK(fs, 0); goto vk; - case VNIL: e->u.info = nilK(fs); goto vk; - case VKINT: e->u.info = luaK_intK(fs, e->u.ival); goto vk; - case VKFLT: e->u.info = luaK_numberK(fs, e->u.nval); goto vk; - case VK: - vk: - e->k = VK; - if (e->u.info <= MAXINDEXRK) /* constant fits in 'argC'? */ - return RKASK(e->u.info); - else break; - default: break; - } - /* not a constant in the right range: put it in a register */ - return luaK_exp2anyreg(fs, e); +int luaK_exp2RK(FuncState* fs, expdesc* e) +{ + luaK_exp2val(fs, e); + switch (e->k) + { + /* move constants to 'k' */ + case VTRUE: e->u.info = boolK(fs, 1); + goto vk; + case VFALSE: e->u.info = boolK(fs, 0); + goto vk; + case VNIL: e->u.info = nilK(fs); + goto vk; + case VKINT: e->u.info = luaK_intK(fs, e->u.ival); + goto vk; + case VKFLT: e->u.info = luaK_numberK(fs, e->u.nval); + goto vk; + case VK: + vk: + e->k = VK; + if (e->u.info <= MAXINDEXRK) /* constant fits in 'argC'? */ + return RKASK(e->u.info); + else break; + default: break; + } + /* not a constant in the right range: put it in a register */ + return luaK_exp2anyreg(fs, e); } /* ** Generate code to store result of expression 'ex' into variable 'var'. */ -void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { - switch (var->k) { - case VLOCAL: { - freeexp(fs, ex); - exp2reg(fs, ex, var->u.info); /* compute 'ex' into proper place */ - return; - } - case VUPVAL: { - int e = luaK_exp2anyreg(fs, ex); - luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); - break; - } - case VINDEXED: { - OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP; - int e = luaK_exp2RK(fs, ex); - luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); - break; - } - default: lua_assert(0); /* invalid var kind to store */ - } - freeexp(fs, ex); +void luaK_storevar(FuncState* fs, expdesc* var, expdesc* ex) +{ + switch (var->k) + { + case VLOCAL: + { + freeexp(fs, ex); + exp2reg(fs, ex, var->u.info); /* compute 'ex' into proper place */ + return; + } + case VUPVAL: + { + int e = luaK_exp2anyreg(fs, ex); + luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); + break; + } + case VINDEXED: + { + OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP; + int e = luaK_exp2RK(fs, ex); + luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); + break; + } + default: lua_assert(0); /* invalid var kind to store */ + } + freeexp(fs, ex); } /* ** Emit SELF instruction (convert expression 'e' into 'e:key(e,'). */ -void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { - int ereg; - luaK_exp2anyreg(fs, e); - ereg = e->u.info; /* register where 'e' was placed */ - freeexp(fs, e); - e->u.info = fs->freereg; /* base register for op_self */ - e->k = VNONRELOC; /* self expression has a fixed register */ - luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ - luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key)); - freeexp(fs, key); +void luaK_self(FuncState* fs, expdesc* e, expdesc* key) +{ + int ereg; + luaK_exp2anyreg(fs, e); + ereg = e->u.info; /* register where 'e' was placed */ + freeexp(fs, e); + e->u.info = fs->freereg; /* base register for op_self */ + e->k = VNONRELOC; /* self expression has a fixed register */ + luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ + luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key)); + freeexp(fs, key); } /* ** Negate condition 'e' (where 'e' is a comparison). */ -static void negatecondition (FuncState *fs, expdesc *e) { - Instruction *pc = getjumpcontrol(fs, e->u.info); - lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && - GET_OPCODE(*pc) != OP_TEST); - SETARG_A(*pc, !(GETARG_A(*pc))); +static void negatecondition(FuncState* fs, expdesc* e) +{ + Instruction* pc = getjumpcontrol(fs, e->u.info); + lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && + GET_OPCODE(*pc) != OP_TEST); + SETARG_A(*pc, !(GETARG_A(*pc))); } @@ -836,106 +953,138 @@ static void negatecondition (FuncState *fs, expdesc *e) { ** Optimize when 'e' is 'not' something, inverting the condition ** and removing the 'not'. */ -static int jumponcond (FuncState *fs, expdesc *e, int cond) { - if (e->k == VRELOCABLE) { - Instruction ie = getinstruction(fs, e); - if (GET_OPCODE(ie) == OP_NOT) { - fs->pc--; /* remove previous OP_NOT */ - return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); - } - /* else go through */ - } - discharge2anyreg(fs, e); - freeexp(fs, e); - return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond); +static int jumponcond(FuncState* fs, expdesc* e, int cond) +{ + if (e->k == VRELOCABLE) + { + Instruction ie = getinstruction(fs, e); + if (GET_OPCODE(ie) == OP_NOT) + { + fs->pc--; /* remove previous OP_NOT */ + return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); + } + /* else go through */ + } + discharge2anyreg(fs, e); + freeexp(fs, e); + return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond); } /* ** Emit code to go through if 'e' is true, jump otherwise. */ -void luaK_goiftrue (FuncState *fs, expdesc *e) { - int pc; /* pc of new jump */ - luaK_dischargevars(fs, e); - switch (e->k) { - case VJMP: { /* condition? */ - negatecondition(fs, e); /* jump when it is false */ - pc = e->u.info; /* save jump position */ - break; - } - case VK: case VKFLT: case VKINT: case VTRUE: { - pc = NO_JUMP; /* always true; do nothing */ - break; - } - default: { - pc = jumponcond(fs, e, 0); /* jump when false */ - break; - } - } - luaK_concat(fs, &e->f, pc); /* insert new jump in false list */ - luaK_patchtohere(fs, e->t); /* true list jumps to here (to go through) */ - e->t = NO_JUMP; +void luaK_goiftrue(FuncState* fs, expdesc* e) +{ + int pc; /* pc of new jump */ + luaK_dischargevars(fs, e); + switch (e->k) + { + case VJMP: + { + /* condition? */ + negatecondition(fs, e); /* jump when it is false */ + pc = e->u.info; /* save jump position */ + break; + } + case VK: + case VKFLT: + case VKINT: + case VTRUE: + { + pc = NO_JUMP; /* always true; do nothing */ + break; + } + default: + { + pc = jumponcond(fs, e, 0); /* jump when false */ + break; + } + } + luaK_concat(fs, &e->f, pc); /* insert new jump in false list */ + luaK_patchtohere(fs, e->t); /* true list jumps to here (to go through) */ + e->t = NO_JUMP; } /* ** Emit code to go through if 'e' is false, jump otherwise. */ -void luaK_goiffalse (FuncState *fs, expdesc *e) { - int pc; /* pc of new jump */ - luaK_dischargevars(fs, e); - switch (e->k) { - case VJMP: { - pc = e->u.info; /* already jump if true */ - break; - } - case VNIL: case VFALSE: { - pc = NO_JUMP; /* always false; do nothing */ - break; - } - default: { - pc = jumponcond(fs, e, 1); /* jump if true */ - break; - } - } - luaK_concat(fs, &e->t, pc); /* insert new jump in 't' list */ - luaK_patchtohere(fs, e->f); /* false list jumps to here (to go through) */ - e->f = NO_JUMP; +void luaK_goiffalse(FuncState* fs, expdesc* e) +{ + int pc; /* pc of new jump */ + luaK_dischargevars(fs, e); + switch (e->k) + { + case VJMP: + { + pc = e->u.info; /* already jump if true */ + break; + } + case VNIL: + case VFALSE: + { + pc = NO_JUMP; /* always false; do nothing */ + break; + } + default: + { + pc = jumponcond(fs, e, 1); /* jump if true */ + break; + } + } + luaK_concat(fs, &e->t, pc); /* insert new jump in 't' list */ + luaK_patchtohere(fs, e->f); /* false list jumps to here (to go through) */ + e->f = NO_JUMP; } /* ** Code 'not e', doing constant folding. */ -static void codenot (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - switch (e->k) { - case VNIL: case VFALSE: { - e->k = VTRUE; /* true == not nil == not false */ - break; - } - case VK: case VKFLT: case VKINT: case VTRUE: { - e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */ - break; - } - case VJMP: { - negatecondition(fs, e); - break; - } - case VRELOCABLE: - case VNONRELOC: { - discharge2anyreg(fs, e); - freeexp(fs, e); - e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); - e->k = VRELOCABLE; - break; - } - default: lua_assert(0); /* cannot happen */ - } - /* interchange true and false lists */ - { int temp = e->f; e->f = e->t; e->t = temp; } - removevalues(fs, e->f); /* values are useless when negated */ - removevalues(fs, e->t); +static void codenot(FuncState* fs, expdesc* e) +{ + luaK_dischargevars(fs, e); + switch (e->k) + { + case VNIL: + case VFALSE: + { + e->k = VTRUE; /* true == not nil == not false */ + break; + } + case VK: + case VKFLT: + case VKINT: + case VTRUE: + { + e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */ + break; + } + case VJMP: + { + negatecondition(fs, e); + break; + } + case VRELOCABLE: + case VNONRELOC: + { + discharge2anyreg(fs, e); + freeexp(fs, e); + e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); + e->k = VRELOCABLE; + break; + } + default: lua_assert(0); /* cannot happen */ + } + /* interchange true and false lists */ + { + int temp = e->f; + e->f = e->t; + e->t = temp; + } + removevalues(fs, e->f); /* values are useless when negated */ + removevalues(fs, e->t); } @@ -943,12 +1092,13 @@ static void codenot (FuncState *fs, expdesc *e) { ** Create expression 't[k]'. 't' must have its final result already in a ** register or upvalue. */ -void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { - lua_assert(!hasjumps(t) && (vkisinreg(t->k) || t->k == VUPVAL)); - t->u.ind.t = t->u.info; /* register or upvalue index */ - t->u.ind.idx = luaK_exp2RK(fs, k); /* R/K index for key */ - t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL : VLOCAL; - t->k = VINDEXED; +void luaK_indexed(FuncState* fs, expdesc* t, expdesc* k) +{ + lua_assert(!hasjumps(t) && (vkisinreg(t->k) || t->k == VUPVAL)); + t->u.ind.t = t->u.info; /* register or upvalue index */ + t->u.ind.idx = luaK_exp2RK(fs, k); /* R/K index for key */ + t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL : VLOCAL; + t->k = VINDEXED; } @@ -957,17 +1107,27 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { ** Bitwise operations need operands convertible to integers; division ** operations cannot have 0 as divisor. */ -static int validop (int op, TValue *v1, TValue *v2) { - switch (op) { - case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: - case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: { /* conversion errors */ - lua_Integer i; - return (tointeger(v1, &i) && tointeger(v2, &i)); - } - case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */ - return (nvalue(v2) != 0); - default: return 1; /* everything else is valid */ - } +static int validop(int op, TValue* v1, TValue* v2) +{ + switch (op) + { + case LUA_OPBAND: + case LUA_OPBOR: + case LUA_OPBXOR: + case LUA_OPSHL: + case LUA_OPSHR: + case LUA_OPBNOT: + { + /* conversion errors */ + lua_Integer i; + return (tointeger(v1, &i) && tointeger(v2, &i)); + } + case LUA_OPDIV: + case LUA_OPIDIV: + case LUA_OPMOD: /* division by 0 */ + return (nvalue(v2) != 0); + default: return 1; /* everything else is valid */ + } } @@ -975,24 +1135,28 @@ static int validop (int op, TValue *v1, TValue *v2) { ** Try to "constant-fold" an operation; return 1 iff successful. ** (In this case, 'e1' has the final result.) */ -static int constfolding (FuncState *fs, int op, expdesc *e1, - const expdesc *e2) { - TValue v1, v2, res; - if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2)) - return 0; /* non-numeric operands or not safe to fold */ - luaO_arith(fs->ls->L, op, &v1, &v2, &res); /* does operation */ - if (ttisinteger(&res)) { - e1->k = VKINT; - e1->u.ival = ivalue(&res); - } - else { /* folds neither NaN nor 0.0 (to avoid problems with -0.0) */ - lua_Number n = fltvalue(&res); - if (luai_numisnan(n) || n == 0) - return 0; - e1->k = VKFLT; - e1->u.nval = n; - } - return 1; +static int constfolding(FuncState* fs, int op, expdesc* e1, + const expdesc* e2) +{ + TValue v1, v2, res; + if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2)) + return 0; /* non-numeric operands or not safe to fold */ + luaO_arith(fs->ls->L, op, &v1, &v2, &res); /* does operation */ + if (ttisinteger(&res)) + { + e1->k = VKINT; + e1->u.ival = ivalue(&res); + } + else + { + /* folds neither NaN nor 0.0 (to avoid problems with -0.0) */ + lua_Number n = fltvalue(&res); + if (luai_numisnan(n) || n == 0) + return 0; + e1->k = VKFLT; + e1->u.nval = n; + } + return 1; } @@ -1001,12 +1165,13 @@ static int constfolding (FuncState *fs, int op, expdesc *e1, ** (everything but 'not'). ** Expression to produce final result will be encoded in 'e'. */ -static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { - int r = luaK_exp2anyreg(fs, e); /* opcodes operate only on registers */ - freeexp(fs, e); - e->u.info = luaK_codeABC(fs, op, 0, r, 0); /* generate opcode */ - e->k = VRELOCABLE; /* all those operations are relocatable */ - luaK_fixline(fs, line); +static void codeunexpval(FuncState* fs, OpCode op, expdesc* e, int line) +{ + int r = luaK_exp2anyreg(fs, e); /* opcodes operate only on registers */ + freeexp(fs, e); + e->u.info = luaK_codeABC(fs, op, 0, r, 0); /* generate opcode */ + e->k = VRELOCABLE; /* all those operations are relocatable */ + luaK_fixline(fs, line); } @@ -1019,14 +1184,15 @@ static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { ** in "stack order" (that is, first on 'e2', which may have more ** recent registers to be released). */ -static void codebinexpval (FuncState *fs, OpCode op, - expdesc *e1, expdesc *e2, int line) { - int rk2 = luaK_exp2RK(fs, e2); /* both operands are "RK" */ - int rk1 = luaK_exp2RK(fs, e1); - freeexps(fs, e1, e2); - e1->u.info = luaK_codeABC(fs, op, 0, rk1, rk2); /* generate opcode */ - e1->k = VRELOCABLE; /* all those operations are relocatable */ - luaK_fixline(fs, line); +static void codebinexpval(FuncState* fs, OpCode op, + expdesc* e1, expdesc* e2, int line) +{ + int rk2 = luaK_exp2RK(fs, e2); /* both operands are "RK" */ + int rk1 = luaK_exp2RK(fs, e1); + freeexps(fs, e1, e2); + e1->u.info = luaK_codeABC(fs, op, 0, rk1, rk2); /* generate opcode */ + e1->k = VRELOCABLE; /* all those operations are relocatable */ + luaK_fixline(fs, line); } @@ -1034,48 +1200,61 @@ static void codebinexpval (FuncState *fs, OpCode op, ** Emit code for comparisons. ** 'e1' was already put in R/K form by 'luaK_infix'. */ -static void codecomp (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { - int rk1 = (e1->k == VK) ? RKASK(e1->u.info) - : check_exp(e1->k == VNONRELOC, e1->u.info); - int rk2 = luaK_exp2RK(fs, e2); - freeexps(fs, e1, e2); - switch (opr) { - case OPR_NE: { /* '(a ~= b)' ==> 'not (a == b)' */ - e1->u.info = condjump(fs, OP_EQ, 0, rk1, rk2); - break; - } - case OPR_GT: case OPR_GE: { - /* '(a > b)' ==> '(b < a)'; '(a >= b)' ==> '(b <= a)' */ - OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ); - e1->u.info = condjump(fs, op, 1, rk2, rk1); /* invert operands */ - break; - } - default: { /* '==', '<', '<=' use their own opcodes */ - OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ); - e1->u.info = condjump(fs, op, 1, rk1, rk2); - break; - } - } - e1->k = VJMP; +static void codecomp(FuncState* fs, BinOpr opr, expdesc* e1, expdesc* e2) +{ + int rk1 = (e1->k == VK) + ? RKASK(e1->u.info) + : check_exp(e1->k == VNONRELOC, e1->u.info); + int rk2 = luaK_exp2RK(fs, e2); + freeexps(fs, e1, e2); + switch (opr) + { + case OPR_NE: + { + /* '(a ~= b)' ==> 'not (a == b)' */ + e1->u.info = condjump(fs, OP_EQ, 0, rk1, rk2); + break; + } + case OPR_GT: + case OPR_GE: + { + /* '(a > b)' ==> '(b < a)'; '(a >= b)' ==> '(b <= a)' */ + OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ); + e1->u.info = condjump(fs, op, 1, rk2, rk1); /* invert operands */ + break; + } + default: + { + /* '==', '<', '<=' use their own opcodes */ + OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ); + e1->u.info = condjump(fs, op, 1, rk1, rk2); + break; + } + } + e1->k = VJMP; } /* ** Aplly prefix operation 'op' to expression 'e'. */ -void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { - static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP}; - switch (op) { - case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */ - if (constfolding(fs, op + LUA_OPUNM, e, &ef)) - break; - /* FALLTHROUGH */ - case OPR_LEN: - codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line); - break; - case OPR_NOT: codenot(fs, e); break; - default: lua_assert(0); - } +void luaK_prefix(FuncState* fs, UnOpr op, expdesc* e, int line) +{ + static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP}; + switch (op) + { + case OPR_MINUS: + case OPR_BNOT: /* use 'ef' as fake 2nd operand */ + if (constfolding(fs, op + LUA_OPUNM, e, &ef)) + break; + /* FALLTHROUGH */ + case OPR_LEN: + codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line); + break; + case OPR_NOT: codenot(fs, e); + break; + default: lua_assert(0); + } } @@ -1083,35 +1262,49 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { ** Process 1st operand 'v' of binary operation 'op' before reading ** 2nd operand. */ -void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { - switch (op) { - case OPR_AND: { - luaK_goiftrue(fs, v); /* go ahead only if 'v' is true */ - break; - } - case OPR_OR: { - luaK_goiffalse(fs, v); /* go ahead only if 'v' is false */ - break; - } - case OPR_CONCAT: { - luaK_exp2nextreg(fs, v); /* operand must be on the 'stack' */ - break; - } - case OPR_ADD: case OPR_SUB: - case OPR_MUL: case OPR_DIV: case OPR_IDIV: - case OPR_MOD: case OPR_POW: - case OPR_BAND: case OPR_BOR: case OPR_BXOR: - case OPR_SHL: case OPR_SHR: { - if (!tonumeral(v, NULL)) - luaK_exp2RK(fs, v); - /* else keep numeral, which may be folded with 2nd operand */ - break; - } - default: { - luaK_exp2RK(fs, v); - break; - } - } +void luaK_infix(FuncState* fs, BinOpr op, expdesc* v) +{ + switch (op) + { + case OPR_AND: + { + luaK_goiftrue(fs, v); /* go ahead only if 'v' is true */ + break; + } + case OPR_OR: + { + luaK_goiffalse(fs, v); /* go ahead only if 'v' is false */ + break; + } + case OPR_CONCAT: + { + luaK_exp2nextreg(fs, v); /* operand must be on the 'stack' */ + break; + } + case OPR_ADD: + case OPR_SUB: + case OPR_MUL: + case OPR_DIV: + case OPR_IDIV: + case OPR_MOD: + case OPR_POW: + case OPR_BAND: + case OPR_BOR: + case OPR_BXOR: + case OPR_SHL: + case OPR_SHR: + { + if (!tonumeral(v, NULL)) + luaK_exp2RK(fs, v); + /* else keep numeral, which may be folded with 2nd operand */ + break; + } + default: + { + luaK_exp2RK(fs, v); + break; + } + } } @@ -1121,61 +1314,84 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { ** concatenation is right associative), merge second CONCAT into first ** one. */ -void luaK_posfix (FuncState *fs, BinOpr op, - expdesc *e1, expdesc *e2, int line) { - switch (op) { - case OPR_AND: { - lua_assert(e1->t == NO_JUMP); /* list closed by 'luK_infix' */ - luaK_dischargevars(fs, e2); - luaK_concat(fs, &e2->f, e1->f); - *e1 = *e2; - break; - } - case OPR_OR: { - lua_assert(e1->f == NO_JUMP); /* list closed by 'luK_infix' */ - luaK_dischargevars(fs, e2); - luaK_concat(fs, &e2->t, e1->t); - *e1 = *e2; - break; - } - case OPR_CONCAT: { - luaK_exp2val(fs, e2); - if (e2->k == VRELOCABLE && - GET_OPCODE(getinstruction(fs, e2)) == OP_CONCAT) { - lua_assert(e1->u.info == GETARG_B(getinstruction(fs, e2))-1); - freeexp(fs, e1); - SETARG_B(getinstruction(fs, e2), e1->u.info); - e1->k = VRELOCABLE; e1->u.info = e2->u.info; - } - else { - luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ - codebinexpval(fs, OP_CONCAT, e1, e2, line); - } - break; - } - case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: - case OPR_IDIV: case OPR_MOD: case OPR_POW: - case OPR_BAND: case OPR_BOR: case OPR_BXOR: - case OPR_SHL: case OPR_SHR: { - if (!constfolding(fs, op + LUA_OPADD, e1, e2)) - codebinexpval(fs, cast(OpCode, op + OP_ADD), e1, e2, line); - break; - } - case OPR_EQ: case OPR_LT: case OPR_LE: - case OPR_NE: case OPR_GT: case OPR_GE: { - codecomp(fs, op, e1, e2); - break; - } - default: lua_assert(0); - } +void luaK_posfix(FuncState* fs, BinOpr op, + expdesc* e1, expdesc* e2, int line) +{ + switch (op) + { + case OPR_AND: + { + lua_assert(e1->t == NO_JUMP); /* list closed by 'luK_infix' */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e2->f, e1->f); + *e1 = *e2; + break; + } + case OPR_OR: + { + lua_assert(e1->f == NO_JUMP); /* list closed by 'luK_infix' */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e2->t, e1->t); + *e1 = *e2; + break; + } + case OPR_CONCAT: + { + luaK_exp2val(fs, e2); + if (e2->k == VRELOCABLE && + GET_OPCODE(getinstruction(fs, e2)) == OP_CONCAT) + { + lua_assert(e1->u.info == GETARG_B(getinstruction(fs, e2))-1); + freeexp(fs, e1); + SETARG_B(getinstruction(fs, e2), e1->u.info); + e1->k = VRELOCABLE; + e1->u.info = e2->u.info; + } + else + { + luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ + codebinexpval(fs, OP_CONCAT, e1, e2, line); + } + break; + } + case OPR_ADD: + case OPR_SUB: + case OPR_MUL: + case OPR_DIV: + case OPR_IDIV: + case OPR_MOD: + case OPR_POW: + case OPR_BAND: + case OPR_BOR: + case OPR_BXOR: + case OPR_SHL: + case OPR_SHR: + { + if (!constfolding(fs, op + LUA_OPADD, e1, e2)) + codebinexpval(fs, cast(OpCode, op + OP_ADD), e1, e2, line); + break; + } + case OPR_EQ: + case OPR_LT: + case OPR_LE: + case OPR_NE: + case OPR_GT: + case OPR_GE: + { + codecomp(fs, op, e1, e2); + break; + } + default: lua_assert(0); + } } /* ** Change line information associated with current position. */ -void luaK_fixline (FuncState *fs, int line) { - fs->f->lineinfo[fs->pc - 1] = line; +void luaK_fixline(FuncState* fs, int line) +{ + fs->f->lineinfo[fs->pc - 1] = line; } @@ -1186,18 +1402,19 @@ void luaK_fixline (FuncState *fs, int line) { ** 'tostore' is number of values (in registers 'base + 1',...) to add to ** table (or LUA_MULTRET to add up to stack top). */ -void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { - int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; - int b = (tostore == LUA_MULTRET) ? 0 : tostore; - lua_assert(tostore != 0 && tostore <= LFIELDS_PER_FLUSH); - if (c <= MAXARG_C) - luaK_codeABC(fs, OP_SETLIST, base, b, c); - else if (c <= MAXARG_Ax) { - luaK_codeABC(fs, OP_SETLIST, base, b, 0); - codeextraarg(fs, c); - } - else - luaX_syntaxerror(fs->ls, "constructor too long"); - fs->freereg = base + 1; /* free registers with list values */ +void luaK_setlist(FuncState* fs, int base, int nelems, int tostore) +{ + int c = (nelems - 1) / LFIELDS_PER_FLUSH + 1; + int b = (tostore == LUA_MULTRET) ? 0 : tostore; + lua_assert(tostore != 0 && tostore <= LFIELDS_PER_FLUSH); + if (c <= MAXARG_C) + luaK_codeABC(fs, OP_SETLIST, base, b, c); + else if (c <= MAXARG_Ax) + { + luaK_codeABC(fs, OP_SETLIST, base, b, 0); + codeextraarg(fs, c); + } + else + luaX_syntaxerror(fs->ls, "constructor too long"); + fs->freereg = base + 1; /* free registers with list values */ } - diff --git a/Lua/lcode.h b/Lua/lcode.h index cd306d5..69fb5b7 100644 --- a/Lua/lcode.h +++ b/Lua/lcode.h @@ -23,17 +23,30 @@ /* ** grep "ORDER OPR" if you change these enums (ORDER OP) */ -typedef enum BinOpr { - OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW, - OPR_DIV, - OPR_IDIV, - OPR_BAND, OPR_BOR, OPR_BXOR, - OPR_SHL, OPR_SHR, - OPR_CONCAT, - OPR_EQ, OPR_LT, OPR_LE, - OPR_NE, OPR_GT, OPR_GE, - OPR_AND, OPR_OR, - OPR_NOBINOPR +typedef enum BinOpr +{ + OPR_ADD, + OPR_SUB, + OPR_MUL, + OPR_MOD, + OPR_POW, + OPR_DIV, + OPR_IDIV, + OPR_BAND, + OPR_BOR, + OPR_BXOR, + OPR_SHL, + OPR_SHR, + OPR_CONCAT, + OPR_EQ, + OPR_LT, + OPR_LE, + OPR_NE, + OPR_GT, + OPR_GE, + OPR_AND, + OPR_OR, + OPR_NOBINOPR } BinOpr; @@ -49,40 +62,40 @@ typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; #define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) -LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); -LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); -LUAI_FUNC int luaK_codek (FuncState *fs, int reg, int k); -LUAI_FUNC void luaK_fixline (FuncState *fs, int line); -LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); -LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); -LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); -LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); -LUAI_FUNC int luaK_intK (FuncState *fs, lua_Integer n); -LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); -LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); -LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); -LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); -LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_jump (FuncState *fs); -LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); -LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); -LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); -LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level); -LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); -LUAI_FUNC int luaK_getlabel (FuncState *fs); -LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); -LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); -LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, - expdesc *v2, int line); -LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); +LUAI_FUNC int luaK_codeABx(FuncState* fs, OpCode o, int A, unsigned int Bx); +LUAI_FUNC int luaK_codeABC(FuncState* fs, OpCode o, int A, int B, int C); +LUAI_FUNC int luaK_codek(FuncState* fs, int reg, int k); +LUAI_FUNC void luaK_fixline(FuncState* fs, int line); +LUAI_FUNC void luaK_nil(FuncState* fs, int from, int n); +LUAI_FUNC void luaK_reserveregs(FuncState* fs, int n); +LUAI_FUNC void luaK_checkstack(FuncState* fs, int n); +LUAI_FUNC int luaK_stringK(FuncState* fs, TString* s); +LUAI_FUNC int luaK_intK(FuncState* fs, lua_Integer n); +LUAI_FUNC void luaK_dischargevars(FuncState* fs, expdesc* e); +LUAI_FUNC int luaK_exp2anyreg(FuncState* fs, expdesc* e); +LUAI_FUNC void luaK_exp2anyregup(FuncState* fs, expdesc* e); +LUAI_FUNC void luaK_exp2nextreg(FuncState* fs, expdesc* e); +LUAI_FUNC void luaK_exp2val(FuncState* fs, expdesc* e); +LUAI_FUNC int luaK_exp2RK(FuncState* fs, expdesc* e); +LUAI_FUNC void luaK_self(FuncState* fs, expdesc* e, expdesc* key); +LUAI_FUNC void luaK_indexed(FuncState* fs, expdesc* t, expdesc* k); +LUAI_FUNC void luaK_goiftrue(FuncState* fs, expdesc* e); +LUAI_FUNC void luaK_goiffalse(FuncState* fs, expdesc* e); +LUAI_FUNC void luaK_storevar(FuncState* fs, expdesc* var, expdesc* e); +LUAI_FUNC void luaK_setreturns(FuncState* fs, expdesc* e, int nresults); +LUAI_FUNC void luaK_setoneret(FuncState* fs, expdesc* e); +LUAI_FUNC int luaK_jump(FuncState* fs); +LUAI_FUNC void luaK_ret(FuncState* fs, int first, int nret); +LUAI_FUNC void luaK_patchlist(FuncState* fs, int list, int target); +LUAI_FUNC void luaK_patchtohere(FuncState* fs, int list); +LUAI_FUNC void luaK_patchclose(FuncState* fs, int list, int level); +LUAI_FUNC void luaK_concat(FuncState* fs, int* l1, int l2); +LUAI_FUNC int luaK_getlabel(FuncState* fs); +LUAI_FUNC void luaK_prefix(FuncState* fs, UnOpr op, expdesc* v, int line); +LUAI_FUNC void luaK_infix(FuncState* fs, BinOpr op, expdesc* v); +LUAI_FUNC void luaK_posfix(FuncState* fs, BinOpr op, expdesc* v1, + expdesc* v2, int line); +LUAI_FUNC void luaK_setlist(FuncState* fs, int base, int nelems, int tostore); #endif diff --git a/Lua/lcorolib.c b/Lua/lcorolib.c index 2303429..df822dc 100644 --- a/Lua/lcorolib.c +++ b/Lua/lcorolib.c @@ -18,151 +18,174 @@ #include "lualib.h" -static lua_State *getco (lua_State *L) { - lua_State *co = lua_tothread(L, 1); - luaL_argcheck(L, co, 1, "thread expected"); - return co; +static lua_State* getco(lua_State* L) +{ + lua_State* co = lua_tothread(L, 1); + luaL_argcheck(L, co, 1, "thread expected"); + return co; } -static int auxresume (lua_State *L, lua_State *co, int narg) { - int status; - if (!lua_checkstack(co, narg)) { - lua_pushliteral(L, "too many arguments to resume"); - return -1; /* error flag */ - } - if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) { - lua_pushliteral(L, "cannot resume dead coroutine"); - return -1; /* error flag */ - } - lua_xmove(L, co, narg); - status = lua_resume(co, L, narg); - if (status == LUA_OK || status == LUA_YIELD) { - int nres = lua_gettop(co); - if (!lua_checkstack(L, nres + 1)) { - lua_pop(co, nres); /* remove results anyway */ - lua_pushliteral(L, "too many results to resume"); - return -1; /* error flag */ - } - lua_xmove(co, L, nres); /* move yielded values */ - return nres; - } - else { - lua_xmove(co, L, 1); /* move error message */ - return -1; /* error flag */ - } +static int auxresume(lua_State* L, lua_State* co, int narg) +{ + int status; + if (!lua_checkstack(co, narg)) + { + lua_pushliteral(L, "too many arguments to resume"); + return -1; /* error flag */ + } + if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) + { + lua_pushliteral(L, "cannot resume dead coroutine"); + return -1; /* error flag */ + } + lua_xmove(L, co, narg); + status = lua_resume(co, L, narg); + if (status == LUA_OK || status == LUA_YIELD) + { + int nres = lua_gettop(co); + if (!lua_checkstack(L, nres + 1)) + { + lua_pop(co, nres); /* remove results anyway */ + lua_pushliteral(L, "too many results to resume"); + return -1; /* error flag */ + } + lua_xmove(co, L, nres); /* move yielded values */ + return nres; + } + else + { + lua_xmove(co, L, 1); /* move error message */ + return -1; /* error flag */ + } } -static int luaB_coresume (lua_State *L) { - lua_State *co = getco(L); - int r; - r = auxresume(L, co, lua_gettop(L) - 1); - if (r < 0) { - lua_pushboolean(L, 0); - lua_insert(L, -2); - return 2; /* return false + error message */ - } - else { - lua_pushboolean(L, 1); - lua_insert(L, -(r + 1)); - return r + 1; /* return true + 'resume' returns */ - } +static int luaB_coresume(lua_State* L) +{ + lua_State* co = getco(L); + int r; + r = auxresume(L, co, lua_gettop(L) - 1); + if (r < 0) + { + lua_pushboolean(L, 0); + lua_insert(L, -2); + return 2; /* return false + error message */ + } + else + { + lua_pushboolean(L, 1); + lua_insert(L, -(r + 1)); + return r + 1; /* return true + 'resume' returns */ + } } -static int luaB_auxwrap (lua_State *L) { - lua_State *co = lua_tothread(L, lua_upvalueindex(1)); - int r = auxresume(L, co, lua_gettop(L)); - if (r < 0) { - if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */ - luaL_where(L, 1); /* add extra info */ - lua_insert(L, -2); - lua_concat(L, 2); - } - return lua_error(L); /* propagate error */ - } - return r; +static int luaB_auxwrap(lua_State* L) +{ + lua_State* co = lua_tothread(L, lua_upvalueindex(1)); + int r = auxresume(L, co, lua_gettop(L)); + if (r < 0) + { + if (lua_type(L, -1) == LUA_TSTRING) + { + /* error object is a string? */ + luaL_where(L, 1); /* add extra info */ + lua_insert(L, -2); + lua_concat(L, 2); + } + return lua_error(L); /* propagate error */ + } + return r; } -static int luaB_cocreate (lua_State *L) { - lua_State *NL; - luaL_checktype(L, 1, LUA_TFUNCTION); - NL = lua_newthread(L); - lua_pushvalue(L, 1); /* move function to top */ - lua_xmove(L, NL, 1); /* move function from L to NL */ - return 1; +static int luaB_cocreate(lua_State* L) +{ + lua_State* NL; + luaL_checktype(L, 1, LUA_TFUNCTION); + NL = lua_newthread(L); + lua_pushvalue(L, 1); /* move function to top */ + lua_xmove(L, NL, 1); /* move function from L to NL */ + return 1; } -static int luaB_cowrap (lua_State *L) { - luaB_cocreate(L); - lua_pushcclosure(L, luaB_auxwrap, 1); - return 1; +static int luaB_cowrap(lua_State* L) +{ + luaB_cocreate(L); + lua_pushcclosure(L, luaB_auxwrap, 1); + return 1; } -static int luaB_yield (lua_State *L) { - return lua_yield(L, lua_gettop(L)); +static int luaB_yield(lua_State* L) +{ + return lua_yield(L, lua_gettop(L)); } -static int luaB_costatus (lua_State *L) { - lua_State *co = getco(L); - if (L == co) lua_pushliteral(L, "running"); - else { - switch (lua_status(co)) { - case LUA_YIELD: - lua_pushliteral(L, "suspended"); - break; - case LUA_OK: { - lua_Debug ar; - if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ - lua_pushliteral(L, "normal"); /* it is running */ - else if (lua_gettop(co) == 0) - lua_pushliteral(L, "dead"); - else - lua_pushliteral(L, "suspended"); /* initial state */ - break; - } - default: /* some error occurred */ - lua_pushliteral(L, "dead"); - break; - } - } - return 1; +static int luaB_costatus(lua_State* L) +{ + lua_State* co = getco(L); + if (L == co) + lua_pushliteral(L, "running"); + else + { + switch (lua_status(co)) + { + case LUA_YIELD: + lua_pushliteral(L, "suspended"); + break; + case LUA_OK: + { + lua_Debug ar; + if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ + lua_pushliteral(L, "normal"); /* it is running */ + else if (lua_gettop(co) == 0) + lua_pushliteral(L, "dead"); + else + lua_pushliteral(L, "suspended"); /* initial state */ + break; + } + default: /* some error occurred */ + lua_pushliteral(L, "dead"); + break; + } + } + return 1; } -static int luaB_yieldable (lua_State *L) { - lua_pushboolean(L, lua_isyieldable(L)); - return 1; +static int luaB_yieldable(lua_State* L) +{ + lua_pushboolean(L, lua_isyieldable(L)); + return 1; } -static int luaB_corunning (lua_State *L) { - int ismain = lua_pushthread(L); - lua_pushboolean(L, ismain); - return 2; +static int luaB_corunning(lua_State* L) +{ + int ismain = lua_pushthread(L); + lua_pushboolean(L, ismain); + return 2; } static const luaL_Reg co_funcs[] = { - {"create", luaB_cocreate}, - {"resume", luaB_coresume}, - {"running", luaB_corunning}, - {"status", luaB_costatus}, - {"wrap", luaB_cowrap}, - {"yield", luaB_yield}, - {"isyieldable", luaB_yieldable}, - {NULL, NULL} + {"create", luaB_cocreate}, + {"resume", luaB_coresume}, + {"running", luaB_corunning}, + {"status", luaB_costatus}, + {"wrap", luaB_cowrap}, + {"yield", luaB_yield}, + {"isyieldable", luaB_yieldable}, + {NULL, NULL} }; - -LUAMOD_API int luaopen_coroutine (lua_State *L) { - luaL_newlib(L, co_funcs); - return 1; +LUAMOD_API int luaopen_coroutine(lua_State* L) +{ + luaL_newlib(L, co_funcs); + return 1; } - diff --git a/Lua/lctype.c b/Lua/lctype.c index ae9367e..863615c 100644 --- a/Lua/lctype.c +++ b/Lua/lctype.c @@ -17,39 +17,39 @@ #include LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = { - 0x00, /* EOZ */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ - 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ - 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ - 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, - 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ - 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, /* EOZ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ + 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ + 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, + 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ + 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; #endif /* } */ diff --git a/Lua/lctype.h b/Lua/lctype.h index 99c7d12..8c2d56a 100644 --- a/Lua/lctype.h +++ b/Lua/lctype.h @@ -92,4 +92,3 @@ LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2]; #endif /* } */ #endif - diff --git a/Lua/ldblib.c b/Lua/ldblib.c index 786f6cd..e47c726 100644 --- a/Lua/ldblib.c +++ b/Lua/ldblib.c @@ -32,52 +32,59 @@ static const int HOOKKEY = 0; ** guarantees about its stack space; any push in L1 must be ** checked. */ -static void checkstack (lua_State *L, lua_State *L1, int n) { - if (L != L1 && !lua_checkstack(L1, n)) - luaL_error(L, "stack overflow"); +static void checkstack(lua_State* L, lua_State* L1, int n) +{ + if (L != L1 && !lua_checkstack(L1, n)) + luaL_error(L, "stack overflow"); } -static int db_getregistry (lua_State *L) { - lua_pushvalue(L, LUA_REGISTRYINDEX); - return 1; +static int db_getregistry(lua_State* L) +{ + lua_pushvalue(L, LUA_REGISTRYINDEX); + return 1; } -static int db_getmetatable (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_getmetatable(L, 1)) { - lua_pushnil(L); /* no metatable */ - } - return 1; +static int db_getmetatable(lua_State* L) +{ + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) + { + lua_pushnil(L); /* no metatable */ + } + return 1; } -static int db_setmetatable (lua_State *L) { - int t = lua_type(L, 2); - luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, - "nil or table expected"); - lua_settop(L, 2); - lua_setmetatable(L, 1); - return 1; /* return 1st argument */ +static int db_setmetatable(lua_State* L) +{ + int t = lua_type(L, 2); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + lua_settop(L, 2); + lua_setmetatable(L, 1); + return 1; /* return 1st argument */ } -static int db_getuservalue (lua_State *L) { - if (lua_type(L, 1) != LUA_TUSERDATA) - lua_pushnil(L); - else - lua_getuservalue(L, 1); - return 1; +static int db_getuservalue(lua_State* L) +{ + if (lua_type(L, 1) != LUA_TUSERDATA) + lua_pushnil(L); + else + lua_getuservalue(L, 1); + return 1; } -static int db_setuservalue (lua_State *L) { - luaL_checktype(L, 1, LUA_TUSERDATA); - luaL_checkany(L, 2); - lua_settop(L, 2); - lua_setuservalue(L, 1); - return 1; +static int db_setuservalue(lua_State* L) +{ + luaL_checktype(L, 1, LUA_TUSERDATA); + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_setuservalue(L, 1); + return 1; } @@ -87,15 +94,18 @@ static int db_setuservalue (lua_State *L) { ** 1 if this argument is present (so that functions can skip it to ** access their other arguments) */ -static lua_State *getthread (lua_State *L, int *arg) { - if (lua_isthread(L, 1)) { - *arg = 1; - return lua_tothread(L, 1); - } - else { - *arg = 0; - return L; /* function will operate over current thread */ - } +static lua_State* getthread(lua_State* L, int* arg) +{ + if (lua_isthread(L, 1)) + { + *arg = 1; + return lua_tothread(L, 1); + } + else + { + *arg = 0; + return L; /* function will operate over current thread */ + } } @@ -104,19 +114,22 @@ static lua_State *getthread (lua_State *L, int *arg) { ** from 'lua_getinfo' into result table. Key is always a string; ** value can be a string, an int, or a boolean. */ -static void settabss (lua_State *L, const char *k, const char *v) { - lua_pushstring(L, v); - lua_setfield(L, -2, k); +static void settabss(lua_State* L, const char* k, const char* v) +{ + lua_pushstring(L, v); + lua_setfield(L, -2, k); } -static void settabsi (lua_State *L, const char *k, int v) { - lua_pushinteger(L, v); - lua_setfield(L, -2, k); +static void settabsi(lua_State* L, const char* k, int v) +{ + lua_pushinteger(L, v); + lua_setfield(L, -2, k); } -static void settabsb (lua_State *L, const char *k, int v) { - lua_pushboolean(L, v); - lua_setfield(L, -2, k); +static void settabsb(lua_State* L, const char* k, int v) +{ + lua_pushboolean(L, v); + lua_setfield(L, -2, k); } @@ -127,12 +140,13 @@ static void settabsb (lua_State *L, const char *k, int v) { ** 'lua_getinfo' on top of the result table so that it can call ** 'lua_setfield'. */ -static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { - if (L == L1) - lua_rotate(L, -2, 1); /* exchange object and table */ - else - lua_xmove(L1, L, 1); /* move object to the "main" stack */ - lua_setfield(L, -2, fname); /* put object into table */ +static void treatstackoption(lua_State* L, lua_State* L1, const char* fname) +{ + if (L == L1) + lua_rotate(L, -2, 1); /* exchange object and table */ + else + lua_xmove(L1, L, 1); /* move object to the "main" stack */ + lua_setfield(L, -2, fname); /* put object into table */ } @@ -142,129 +156,149 @@ static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { ** two optional outputs (function and line table) from function ** 'lua_getinfo'. */ -static int db_getinfo (lua_State *L) { - lua_Debug ar; - int arg; - lua_State *L1 = getthread(L, &arg); - const char *options = luaL_optstring(L, arg+2, "flnStu"); - checkstack(L, L1, 3); - if (lua_isfunction(L, arg + 1)) { /* info about a function? */ - options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */ - lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */ - lua_xmove(L, L1, 1); - } - else { /* stack level */ - if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) { - lua_pushnil(L); /* level out of range */ - return 1; - } - } - if (!lua_getinfo(L1, options, &ar)) - return luaL_argerror(L, arg+2, "invalid option"); - lua_newtable(L); /* table to collect results */ - if (strchr(options, 'S')) { - settabss(L, "source", ar.source); - settabss(L, "short_src", ar.short_src); - settabsi(L, "linedefined", ar.linedefined); - settabsi(L, "lastlinedefined", ar.lastlinedefined); - settabss(L, "what", ar.what); - } - if (strchr(options, 'l')) - settabsi(L, "currentline", ar.currentline); - if (strchr(options, 'u')) { - settabsi(L, "nups", ar.nups); - settabsi(L, "nparams", ar.nparams); - settabsb(L, "isvararg", ar.isvararg); - } - if (strchr(options, 'n')) { - settabss(L, "name", ar.name); - settabss(L, "namewhat", ar.namewhat); - } - if (strchr(options, 't')) - settabsb(L, "istailcall", ar.istailcall); - if (strchr(options, 'L')) - treatstackoption(L, L1, "activelines"); - if (strchr(options, 'f')) - treatstackoption(L, L1, "func"); - return 1; /* return table */ +static int db_getinfo(lua_State* L) +{ + lua_Debug ar; + int arg; + lua_State* L1 = getthread(L, &arg); + const char* options = luaL_optstring(L, arg+2, "flnStu"); + checkstack(L, L1, 3); + if (lua_isfunction(L, arg + 1)) + { + /* info about a function? */ + options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */ + lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */ + lua_xmove(L, L1, 1); + } + else + { + /* stack level */ + if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) + { + lua_pushnil(L); /* level out of range */ + return 1; + } + } + if (!lua_getinfo(L1, options, &ar)) + return luaL_argerror(L, arg + 2, "invalid option"); + lua_newtable(L); /* table to collect results */ + if (strchr(options, 'S')) + { + settabss(L, "source", ar.source); + settabss(L, "short_src", ar.short_src); + settabsi(L, "linedefined", ar.linedefined); + settabsi(L, "lastlinedefined", ar.lastlinedefined); + settabss(L, "what", ar.what); + } + if (strchr(options, 'l')) + settabsi(L, "currentline", ar.currentline); + if (strchr(options, 'u')) + { + settabsi(L, "nups", ar.nups); + settabsi(L, "nparams", ar.nparams); + settabsb(L, "isvararg", ar.isvararg); + } + if (strchr(options, 'n')) + { + settabss(L, "name", ar.name); + settabss(L, "namewhat", ar.namewhat); + } + if (strchr(options, 't')) + settabsb(L, "istailcall", ar.istailcall); + if (strchr(options, 'L')) + treatstackoption(L, L1, "activelines"); + if (strchr(options, 'f')) + treatstackoption(L, L1, "func"); + return 1; /* return table */ } -static int db_getlocal (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - lua_Debug ar; - const char *name; - int nvar = (int)luaL_checkinteger(L, arg + 2); /* local-variable index */ - if (lua_isfunction(L, arg + 1)) { /* function argument? */ - lua_pushvalue(L, arg + 1); /* push function */ - lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */ - return 1; /* return only name (there is no value) */ - } - else { /* stack-level argument */ - int level = (int)luaL_checkinteger(L, arg + 1); - if (!lua_getstack(L1, level, &ar)) /* out of range? */ - return luaL_argerror(L, arg+1, "level out of range"); - checkstack(L, L1, 1); - name = lua_getlocal(L1, &ar, nvar); - if (name) { - lua_xmove(L1, L, 1); /* move local value */ - lua_pushstring(L, name); /* push name */ - lua_rotate(L, -2, 1); /* re-order */ - return 2; - } - else { - lua_pushnil(L); /* no name (nor value) */ - return 1; - } - } +static int db_getlocal(lua_State* L) +{ + int arg; + lua_State* L1 = getthread(L, &arg); + lua_Debug ar; + const char* name; + int nvar = (int)luaL_checkinteger(L, arg + 2); /* local-variable index */ + if (lua_isfunction(L, arg + 1)) + { + /* function argument? */ + lua_pushvalue(L, arg + 1); /* push function */ + lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */ + return 1; /* return only name (there is no value) */ + } + else + { + /* stack-level argument */ + int level = (int)luaL_checkinteger(L, arg + 1); + if (!lua_getstack(L1, level, &ar)) /* out of range? */ + return luaL_argerror(L, arg + 1, "level out of range"); + checkstack(L, L1, 1); + name = lua_getlocal(L1, &ar, nvar); + if (name) + { + lua_xmove(L1, L, 1); /* move local value */ + lua_pushstring(L, name); /* push name */ + lua_rotate(L, -2, 1); /* re-order */ + return 2; + } + else + { + lua_pushnil(L); /* no name (nor value) */ + return 1; + } + } } -static int db_setlocal (lua_State *L) { - int arg; - const char *name; - lua_State *L1 = getthread(L, &arg); - lua_Debug ar; - int level = (int)luaL_checkinteger(L, arg + 1); - int nvar = (int)luaL_checkinteger(L, arg + 2); - if (!lua_getstack(L1, level, &ar)) /* out of range? */ - return luaL_argerror(L, arg+1, "level out of range"); - luaL_checkany(L, arg+3); - lua_settop(L, arg+3); - checkstack(L, L1, 1); - lua_xmove(L, L1, 1); - name = lua_setlocal(L1, &ar, nvar); - if (name == NULL) - lua_pop(L1, 1); /* pop value (if not popped by 'lua_setlocal') */ - lua_pushstring(L, name); - return 1; +static int db_setlocal(lua_State* L) +{ + int arg; + const char* name; + lua_State* L1 = getthread(L, &arg); + lua_Debug ar; + int level = (int)luaL_checkinteger(L, arg + 1); + int nvar = (int)luaL_checkinteger(L, arg + 2); + if (!lua_getstack(L1, level, &ar)) /* out of range? */ + return luaL_argerror(L, arg + 1, "level out of range"); + luaL_checkany(L, arg + 3); + lua_settop(L, arg + 3); + checkstack(L, L1, 1); + lua_xmove(L, L1, 1); + name = lua_setlocal(L1, &ar, nvar); + if (name == NULL) + lua_pop(L1, 1); /* pop value (if not popped by 'lua_setlocal') */ + lua_pushstring(L, name); + return 1; } /* ** get (if 'get' is true) or set an upvalue from a closure */ -static int auxupvalue (lua_State *L, int get) { - const char *name; - int n = (int)luaL_checkinteger(L, 2); /* upvalue index */ - luaL_checktype(L, 1, LUA_TFUNCTION); /* closure */ - name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); - if (name == NULL) return 0; - lua_pushstring(L, name); - lua_insert(L, -(get+1)); /* no-op if get is false */ - return get + 1; +static int auxupvalue(lua_State* L, int get) +{ + const char* name; + int n = (int)luaL_checkinteger(L, 2); /* upvalue index */ + luaL_checktype(L, 1, LUA_TFUNCTION); /* closure */ + name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); + if (name == NULL) return 0; + lua_pushstring(L, name); + lua_insert(L, -(get+1)); /* no-op if get is false */ + return get + 1; } -static int db_getupvalue (lua_State *L) { - return auxupvalue(L, 1); +static int db_getupvalue(lua_State* L) +{ + return auxupvalue(L, 1); } -static int db_setupvalue (lua_State *L) { - luaL_checkany(L, 3); - return auxupvalue(L, 0); +static int db_setupvalue(lua_State* L) +{ + luaL_checkany(L, 3); + return auxupvalue(L, 0); } @@ -272,29 +306,32 @@ static int db_setupvalue (lua_State *L) { ** Check whether a given upvalue from a given closure exists and ** returns its index */ -static int checkupval (lua_State *L, int argf, int argnup) { - int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */ - luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */ - luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup, - "invalid upvalue index"); - return nup; +static int checkupval(lua_State* L, int argf, int argnup) +{ + int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */ + luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */ + luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup, + "invalid upvalue index"); + return nup; } -static int db_upvalueid (lua_State *L) { - int n = checkupval(L, 1, 2); - lua_pushlightuserdata(L, lua_upvalueid(L, 1, n)); - return 1; +static int db_upvalueid(lua_State* L) +{ + int n = checkupval(L, 1, 2); + lua_pushlightuserdata(L, lua_upvalueid(L, 1, n)); + return 1; } -static int db_upvaluejoin (lua_State *L) { - int n1 = checkupval(L, 1, 2); - int n2 = checkupval(L, 3, 4); - luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); - luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); - lua_upvaluejoin(L, 1, n1, 3, n2); - return 0; +static int db_upvaluejoin(lua_State* L) +{ + int n1 = checkupval(L, 1, 2); + int n2 = checkupval(L, 3, 4); + luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); + luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); + lua_upvaluejoin(L, 1, n1, 3, n2); + return 0; } @@ -302,155 +339,177 @@ static int db_upvaluejoin (lua_State *L) { ** Call hook function registered at hook table for the current ** thread (if there is one) */ -static void hookf (lua_State *L, lua_Debug *ar) { - static const char *const hooknames[] = - {"call", "return", "line", "count", "tail call"}; - lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY); - lua_pushthread(L); - if (lua_rawget(L, -2) == LUA_TFUNCTION) { /* is there a hook function? */ - lua_pushstring(L, hooknames[(int)ar->event]); /* push event name */ - if (ar->currentline >= 0) - lua_pushinteger(L, ar->currentline); /* push current line */ - else lua_pushnil(L); - lua_assert(lua_getinfo(L, "lS", ar)); - lua_call(L, 2, 0); /* call hook function */ - } +static void hookf(lua_State* L, lua_Debug* ar) +{ + static const char* const hooknames[] = + {"call", "return", "line", "count", "tail call"}; + lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY); + lua_pushthread(L); + if (lua_rawget(L, -2) == LUA_TFUNCTION) + { + /* is there a hook function? */ + lua_pushstring(L, hooknames[(int)ar->event]); /* push event name */ + if (ar->currentline >= 0) + lua_pushinteger(L, ar->currentline); /* push current line */ + else lua_pushnil(L); + lua_assert(lua_getinfo(L, "lS", ar)); + lua_call(L, 2, 0); /* call hook function */ + } } /* ** Convert a string mask (for 'sethook') into a bit mask */ -static int makemask (const char *smask, int count) { - int mask = 0; - if (strchr(smask, 'c')) mask |= LUA_MASKCALL; - if (strchr(smask, 'r')) mask |= LUA_MASKRET; - if (strchr(smask, 'l')) mask |= LUA_MASKLINE; - if (count > 0) mask |= LUA_MASKCOUNT; - return mask; +static int makemask(const char* smask, int count) +{ + int mask = 0; + if (strchr(smask, 'c')) mask |= LUA_MASKCALL; + if (strchr(smask, 'r')) mask |= LUA_MASKRET; + if (strchr(smask, 'l')) mask |= LUA_MASKLINE; + if (count > 0) mask |= LUA_MASKCOUNT; + return mask; } /* ** Convert a bit mask (for 'gethook') into a string mask */ -static char *unmakemask (int mask, char *smask) { - int i = 0; - if (mask & LUA_MASKCALL) smask[i++] = 'c'; - if (mask & LUA_MASKRET) smask[i++] = 'r'; - if (mask & LUA_MASKLINE) smask[i++] = 'l'; - smask[i] = '\0'; - return smask; +static char* unmakemask(int mask, char* smask) +{ + int i = 0; + if (mask & LUA_MASKCALL) smask[i++] = 'c'; + if (mask & LUA_MASKRET) smask[i++] = 'r'; + if (mask & LUA_MASKLINE) smask[i++] = 'l'; + smask[i] = '\0'; + return smask; } -static int db_sethook (lua_State *L) { - int arg, mask, count; - lua_Hook func; - lua_State *L1 = getthread(L, &arg); - if (lua_isnoneornil(L, arg+1)) { /* no hook? */ - lua_settop(L, arg+1); - func = NULL; mask = 0; count = 0; /* turn off hooks */ - } - else { - const char *smask = luaL_checkstring(L, arg+2); - luaL_checktype(L, arg+1, LUA_TFUNCTION); - count = (int)luaL_optinteger(L, arg + 3, 0); - func = hookf; mask = makemask(smask, count); - } - if (lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY) == LUA_TNIL) { - lua_createtable(L, 0, 2); /* create a hook table */ - lua_pushvalue(L, -1); - lua_rawsetp(L, LUA_REGISTRYINDEX, &HOOKKEY); /* set it in position */ - lua_pushstring(L, "k"); - lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */ - lua_pushvalue(L, -1); - lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */ - } - checkstack(L, L1, 1); - lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */ - lua_pushvalue(L, arg + 1); /* value (hook function) */ - lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */ - lua_sethook(L1, func, mask, count); - return 0; +static int db_sethook(lua_State* L) +{ + int arg, mask, count; + lua_Hook func; + lua_State* L1 = getthread(L, &arg); + if (lua_isnoneornil(L, arg+1)) + { + /* no hook? */ + lua_settop(L, arg + 1); + func = NULL; + mask = 0; + count = 0; /* turn off hooks */ + } + else + { + const char* smask = luaL_checkstring(L, arg+2); + luaL_checktype(L, arg + 1, LUA_TFUNCTION); + count = (int)luaL_optinteger(L, arg + 3, 0); + func = hookf; + mask = makemask(smask, count); + } + if (lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY) == LUA_TNIL) + { + lua_createtable(L, 0, 2); /* create a hook table */ + lua_pushvalue(L, -1); + lua_rawsetp(L, LUA_REGISTRYINDEX, &HOOKKEY); /* set it in position */ + lua_pushstring(L, "k"); + lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */ + lua_pushvalue(L, -1); + lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */ + } + checkstack(L, L1, 1); + lua_pushthread(L1); + lua_xmove(L1, L, 1); /* key (thread) */ + lua_pushvalue(L, arg + 1); /* value (hook function) */ + lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */ + lua_sethook(L1, func, mask, count); + return 0; } -static int db_gethook (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - char buff[5]; - int mask = lua_gethookmask(L1); - lua_Hook hook = lua_gethook(L1); - if (hook == NULL) /* no hook? */ - lua_pushnil(L); - else if (hook != hookf) /* external hook? */ - lua_pushliteral(L, "external hook"); - else { /* hook table must exist */ - lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY); - checkstack(L, L1, 1); - lua_pushthread(L1); lua_xmove(L1, L, 1); - lua_rawget(L, -2); /* 1st result = hooktable[L1] */ - lua_remove(L, -2); /* remove hook table */ - } - lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */ - lua_pushinteger(L, lua_gethookcount(L1)); /* 3rd result = count */ - return 3; +static int db_gethook(lua_State* L) +{ + int arg; + lua_State* L1 = getthread(L, &arg); + char buff[5]; + int mask = lua_gethookmask(L1); + lua_Hook hook = lua_gethook(L1); + if (hook == NULL) /* no hook? */ + lua_pushnil(L); + else if (hook != hookf) /* external hook? */ + lua_pushliteral(L, "external hook"); + else + { + /* hook table must exist */ + lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY); + checkstack(L, L1, 1); + lua_pushthread(L1); + lua_xmove(L1, L, 1); + lua_rawget(L, -2); /* 1st result = hooktable[L1] */ + lua_remove(L, -2); /* remove hook table */ + } + lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */ + lua_pushinteger(L, lua_gethookcount(L1)); /* 3rd result = count */ + return 3; } -static int db_debug (lua_State *L) { - for (;;) { - char buffer[250]; - lua_writestringerror("%s", "lua_debug> "); - if (fgets(buffer, sizeof(buffer), stdin) == 0 || - strcmp(buffer, "cont\n") == 0) - return 0; - if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || - lua_pcall(L, 0, 0, 0)) - lua_writestringerror("%s\n", lua_tostring(L, -1)); - lua_settop(L, 0); /* remove eventual returns */ - } +static int db_debug(lua_State* L) +{ + for (;;) + { + char buffer[250]; + lua_writestringerror("%s", "lua_debug> "); + if (fgets(buffer, sizeof(buffer), stdin) == 0 || + strcmp(buffer, "cont\n") == 0) + return 0; + if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || + lua_pcall(L, 0, 0, 0)) + lua_writestringerror("%s\n", lua_tostring(L, -1)); + lua_settop(L, 0); /* remove eventual returns */ + } } -static int db_traceback (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - const char *msg = lua_tostring(L, arg + 1); - if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */ - lua_pushvalue(L, arg + 1); /* return it untouched */ - else { - int level = (int)luaL_optinteger(L, arg + 2, (L == L1) ? 1 : 0); - luaL_traceback(L, L1, msg, level); - } - return 1; +static int db_traceback(lua_State* L) +{ + int arg; + lua_State* L1 = getthread(L, &arg); + const char* msg = lua_tostring(L, arg + 1); + if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */ + lua_pushvalue(L, arg + 1); /* return it untouched */ + else + { + int level = (int)luaL_optinteger(L, arg + 2, (L == L1) ? 1 : 0); + luaL_traceback(L, L1, msg, level); + } + return 1; } static const luaL_Reg dblib[] = { - {"debug", db_debug}, - {"getuservalue", db_getuservalue}, - {"gethook", db_gethook}, - {"getinfo", db_getinfo}, - {"getlocal", db_getlocal}, - {"getregistry", db_getregistry}, - {"getmetatable", db_getmetatable}, - {"getupvalue", db_getupvalue}, - {"upvaluejoin", db_upvaluejoin}, - {"upvalueid", db_upvalueid}, - {"setuservalue", db_setuservalue}, - {"sethook", db_sethook}, - {"setlocal", db_setlocal}, - {"setmetatable", db_setmetatable}, - {"setupvalue", db_setupvalue}, - {"traceback", db_traceback}, - {NULL, NULL} + {"debug", db_debug}, + {"getuservalue", db_getuservalue}, + {"gethook", db_gethook}, + {"getinfo", db_getinfo}, + {"getlocal", db_getlocal}, + {"getregistry", db_getregistry}, + {"getmetatable", db_getmetatable}, + {"getupvalue", db_getupvalue}, + {"upvaluejoin", db_upvaluejoin}, + {"upvalueid", db_upvalueid}, + {"setuservalue", db_setuservalue}, + {"sethook", db_sethook}, + {"setlocal", db_setlocal}, + {"setmetatable", db_setmetatable}, + {"setupvalue", db_setupvalue}, + {"traceback", db_traceback}, + {NULL, NULL} }; -LUAMOD_API int luaopen_debug (lua_State *L) { - luaL_newlib(L, dblib); - return 1; +LUAMOD_API int luaopen_debug(lua_State* L) +{ + luaL_newlib(L, dblib); + return 1; } - diff --git a/Lua/ldebug.c b/Lua/ldebug.c index 239affb..90a17a7 100644 --- a/Lua/ldebug.c +++ b/Lua/ldebug.c @@ -30,7 +30,6 @@ #include "lvm.h" - #define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL) @@ -38,18 +37,20 @@ #define ci_func(ci) (clLvalue((ci)->func)) -static const char *funcnamefromcode (lua_State *L, CallInfo *ci, - const char **name); +static const char* funcnamefromcode(lua_State* L, CallInfo* ci, + const char** name); -static int currentpc (CallInfo *ci) { - lua_assert(isLua(ci)); - return pcRel(ci->u.l.savedpc, ci_func(ci)->p); +static int currentpc(CallInfo* ci) +{ + lua_assert(isLua(ci)); + return pcRel(ci->u.l.savedpc, ci_func(ci)->p); } -static int currentline (CallInfo *ci) { - return getfuncline(ci_func(ci)->p, currentpc(ci)); +static int currentline(CallInfo* ci) +{ + return getfuncline(ci_func(ci)->p, currentpc(ci)); } @@ -59,13 +60,15 @@ static int currentline (CallInfo *ci) { ** purposes. (It exchanges 'func' and 'extra'; so, when called again, ** after debugging, it also "re-restores" ** 'func' to its altered value. */ -static void swapextra (lua_State *L) { - if (L->status == LUA_YIELD) { - CallInfo *ci = L->ci; /* get function that yielded */ - StkId temp = ci->func; /* exchange its 'func' and 'extra' values */ - ci->func = restorestack(L, ci->extra); - ci->extra = savestack(L, temp); - } +static void swapextra(lua_State* L) +{ + if (L->status == LUA_YIELD) + { + CallInfo* ci = L->ci; /* get function that yielded */ + StkId temp = ci->func; /* exchange its 'func' and 'extra' values */ + ci->func = restorestack(L, ci->extra); + ci->extra = savestack(L, temp); + } } @@ -78,264 +81,313 @@ static void swapextra (lua_State *L) { ** ensures that for all platforms where it runs). Moreover, 'hook' is ** always checked before being called (see 'luaD_hook'). */ -LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { - if (func == NULL || mask == 0) { /* turn off hooks? */ - mask = 0; - func = NULL; - } - if (isLua(L->ci)) - L->oldpc = L->ci->u.l.savedpc; - L->hook = func; - L->basehookcount = count; - resethookcount(L); - L->hookmask = cast_byte(mask); +LUA_API void lua_sethook(lua_State* L, lua_Hook func, int mask, int count) +{ + if (func == NULL || mask == 0) + { + /* turn off hooks? */ + mask = 0; + func = NULL; + } + if (isLua(L->ci)) + L->oldpc = L->ci->u.l.savedpc; + L->hook = func; + L->basehookcount = count; + resethookcount(L); + L->hookmask = cast_byte(mask); } -LUA_API lua_Hook lua_gethook (lua_State *L) { - return L->hook; +LUA_API lua_Hook lua_gethook(lua_State* L) +{ + return L->hook; } -LUA_API int lua_gethookmask (lua_State *L) { - return L->hookmask; +LUA_API int lua_gethookmask(lua_State* L) +{ + return L->hookmask; } -LUA_API int lua_gethookcount (lua_State *L) { - return L->basehookcount; +LUA_API int lua_gethookcount(lua_State* L) +{ + return L->basehookcount; } -LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { - int status; - CallInfo *ci; - if (level < 0) return 0; /* invalid (negative) level */ - lua_lock(L); - for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous) - level--; - if (level == 0 && ci != &L->base_ci) { /* level found? */ - status = 1; - ar->i_ci = ci; - } - else status = 0; /* no such level */ - lua_unlock(L); - return status; +LUA_API int lua_getstack(lua_State* L, int level, lua_Debug* ar) +{ + int status; + CallInfo* ci; + if (level < 0) return 0; /* invalid (negative) level */ + lua_lock(L); + for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous) + level--; + if (level == 0 && ci != &L->base_ci) + { + /* level found? */ + status = 1; + ar->i_ci = ci; + } + else status = 0; /* no such level */ + lua_unlock(L); + return status; } -static const char *upvalname (Proto *p, int uv) { - TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); - if (s == NULL) return "?"; - else return getstr(s); +static const char* upvalname(Proto* p, int uv) +{ + TString* s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); + if (s == NULL) return "?"; + else return getstr(s); } -static const char *findvararg (CallInfo *ci, int n, StkId *pos) { - int nparams = clLvalue(ci->func)->p->numparams; - if (n >= cast_int(ci->u.l.base - ci->func) - nparams) - return NULL; /* no such vararg */ - else { - *pos = ci->func + nparams + n; - return "(*vararg)"; /* generic name for any vararg */ - } +static const char* findvararg(CallInfo* ci, int n, StkId* pos) +{ + int nparams = clLvalue(ci->func)->p->numparams; + if (n >= cast_int(ci->u.l.base - ci->func) - nparams) + return NULL; /* no such vararg */ + else + { + *pos = ci->func + nparams + n; + return "(*vararg)"; /* generic name for any vararg */ + } } -static const char *findlocal (lua_State *L, CallInfo *ci, int n, - StkId *pos) { - const char *name = NULL; - StkId base; - if (isLua(ci)) { - if (n < 0) /* access to vararg values? */ - return findvararg(ci, -n, pos); - else { - base = ci->u.l.base; - name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); - } - } - else - base = ci->func + 1; - if (name == NULL) { /* no 'standard' name? */ - StkId limit = (ci == L->ci) ? L->top : ci->next->func; - if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */ - name = "(*temporary)"; /* generic name for any valid slot */ - else - return NULL; /* no name */ - } - *pos = base + (n - 1); - return name; +static const char* findlocal(lua_State* L, CallInfo* ci, int n, + StkId* pos) +{ + const char* name = NULL; + StkId base; + if (isLua(ci)) + { + if (n < 0) /* access to vararg values? */ + return findvararg(ci, -n, pos); + else + { + base = ci->u.l.base; + name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); + } + } + else + base = ci->func + 1; + if (name == NULL) + { + /* no 'standard' name? */ + StkId limit = (ci == L->ci) ? L->top : ci->next->func; + if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */ + name = "(*temporary)"; /* generic name for any valid slot */ + else + return NULL; /* no name */ + } + *pos = base + (n - 1); + return name; } -LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { - const char *name; - lua_lock(L); - swapextra(L); - if (ar == NULL) { /* information about non-active function? */ - if (!isLfunction(L->top - 1)) /* not a Lua function? */ - name = NULL; - else /* consider live variables at function start (parameters) */ - name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0); - } - else { /* active function; get information through 'ar' */ - StkId pos = NULL; /* to avoid warnings */ - name = findlocal(L, ar->i_ci, n, &pos); - if (name) { - setobj2s(L, L->top, pos); - api_incr_top(L); - } - } - swapextra(L); - lua_unlock(L); - return name; +LUA_API const char* lua_getlocal(lua_State* L, const lua_Debug* ar, int n) +{ + const char* name; + lua_lock(L); + swapextra(L); + if (ar == NULL) + { + /* information about non-active function? */ + if (!isLfunction(L->top - 1)) /* not a Lua function? */ + name = NULL; + else /* consider live variables at function start (parameters) */ + name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0); + } + else + { + /* active function; get information through 'ar' */ + StkId pos = NULL; /* to avoid warnings */ + name = findlocal(L, ar->i_ci, n, &pos); + if (name) + { + setobj2s(L, L->top, pos); + api_incr_top(L); + } + } + swapextra(L); + lua_unlock(L); + return name; } -LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { - StkId pos = NULL; /* to avoid warnings */ - const char *name; - lua_lock(L); - swapextra(L); - name = findlocal(L, ar->i_ci, n, &pos); - if (name) { - setobjs2s(L, pos, L->top - 1); - L->top--; /* pop value */ - } - swapextra(L); - lua_unlock(L); - return name; +LUA_API const char* lua_setlocal(lua_State* L, const lua_Debug* ar, int n) +{ + StkId pos = NULL; /* to avoid warnings */ + const char* name; + lua_lock(L); + swapextra(L); + name = findlocal(L, ar->i_ci, n, &pos); + if (name) + { + setobjs2s(L, pos, L->top - 1); + L->top--; /* pop value */ + } + swapextra(L); + lua_unlock(L); + return name; } -static void funcinfo (lua_Debug *ar, Closure *cl) { - if (noLuaClosure(cl)) { - ar->source = "=[C]"; - ar->linedefined = -1; - ar->lastlinedefined = -1; - ar->what = "C"; - } - else { - Proto *p = cl->l.p; - ar->source = p->source ? getstr(p->source) : "=?"; - ar->linedefined = p->linedefined; - ar->lastlinedefined = p->lastlinedefined; - ar->what = (ar->linedefined == 0) ? "main" : "Lua"; - } - luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); +static void funcinfo(lua_Debug* ar, Closure* cl) +{ + if (noLuaClosure(cl)) + { + ar->source = "=[C]"; + ar->linedefined = -1; + ar->lastlinedefined = -1; + ar->what = "C"; + } + else + { + Proto* p = cl->l.p; + ar->source = p->source ? getstr(p->source) : "=?"; + ar->linedefined = p->linedefined; + ar->lastlinedefined = p->lastlinedefined; + ar->what = (ar->linedefined == 0) ? "main" : "Lua"; + } + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); } -static void collectvalidlines (lua_State *L, Closure *f) { - if (noLuaClosure(f)) { - setnilvalue(L->top); - api_incr_top(L); - } - else { - int i; - TValue v; - int *lineinfo = f->l.p->lineinfo; - Table *t = luaH_new(L); /* new table to store active lines */ - sethvalue(L, L->top, t); /* push it on stack */ - api_incr_top(L); - setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ - for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */ - luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */ - } +static void collectvalidlines(lua_State* L, Closure* f) +{ + if (noLuaClosure(f)) + { + setnilvalue(L->top); + api_incr_top(L); + } + else + { + int i; + TValue v; + int* lineinfo = f->l.p->lineinfo; + Table* t = luaH_new(L); /* new table to store active lines */ + sethvalue(L, L->top, t); /* push it on stack */ + api_incr_top(L); + setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ + for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */ + luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */ + } } -static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { - if (ci == NULL) /* no 'ci'? */ - return NULL; /* no info */ - else if (ci->callstatus & CIST_FIN) { /* is this a finalizer? */ - *name = "__gc"; - return "metamethod"; /* report it as such */ - } - /* calling function is a known Lua function? */ - else if (!(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) - return funcnamefromcode(L, ci->previous, name); - else return NULL; /* no way to find a name */ +static const char* getfuncname(lua_State* L, CallInfo* ci, const char** name) +{ + if (ci == NULL) /* no 'ci'? */ + return NULL; /* no info */ + else if (ci->callstatus & CIST_FIN) + { + /* is this a finalizer? */ + *name = "__gc"; + return "metamethod"; /* report it as such */ + } + /* calling function is a known Lua function? */ + else if (!(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) + return funcnamefromcode(L, ci->previous, name); + else return NULL; /* no way to find a name */ } -static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, - Closure *f, CallInfo *ci) { - int status = 1; - for (; *what; what++) { - switch (*what) { - case 'S': { - funcinfo(ar, f); - break; - } - case 'l': { - ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1; - break; - } - case 'u': { - ar->nups = (f == NULL) ? 0 : f->c.nupvalues; - if (noLuaClosure(f)) { - ar->isvararg = 1; - ar->nparams = 0; - } - else { - ar->isvararg = f->l.p->is_vararg; - ar->nparams = f->l.p->numparams; - } - break; - } - case 't': { - ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; - break; - } - case 'n': { - ar->namewhat = getfuncname(L, ci, &ar->name); - if (ar->namewhat == NULL) { - ar->namewhat = ""; /* not found */ - ar->name = NULL; - } - break; - } - case 'L': - case 'f': /* handled by lua_getinfo */ - break; - default: status = 0; /* invalid option */ - } - } - return status; +static int auxgetinfo(lua_State* L, const char* what, lua_Debug* ar, + Closure* f, CallInfo* ci) +{ + int status = 1; + for (; *what; what++) + { + switch (*what) + { + case 'S': + { + funcinfo(ar, f); + break; + } + case 'l': + { + ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1; + break; + } + case 'u': + { + ar->nups = (f == NULL) ? 0 : f->c.nupvalues; + if (noLuaClosure(f)) + { + ar->isvararg = 1; + ar->nparams = 0; + } + else + { + ar->isvararg = f->l.p->is_vararg; + ar->nparams = f->l.p->numparams; + } + break; + } + case 't': + { + ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; + break; + } + case 'n': + { + ar->namewhat = getfuncname(L, ci, &ar->name); + if (ar->namewhat == NULL) + { + ar->namewhat = ""; /* not found */ + ar->name = NULL; + } + break; + } + case 'L': + case 'f': /* handled by lua_getinfo */ + break; + default: status = 0; /* invalid option */ + } + } + return status; } -LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { - int status; - Closure *cl; - CallInfo *ci; - StkId func; - lua_lock(L); - swapextra(L); - if (*what == '>') { - ci = NULL; - func = L->top - 1; - api_check(L, ttisfunction(func), "function expected"); - what++; /* skip the '>' */ - L->top--; /* pop function */ - } - else { - ci = ar->i_ci; - func = ci->func; - lua_assert(ttisfunction(ci->func)); - } - cl = ttisclosure(func) ? clvalue(func) : NULL; - status = auxgetinfo(L, what, ar, cl, ci); - if (strchr(what, 'f')) { - setobjs2s(L, L->top, func); - api_incr_top(L); - } - swapextra(L); /* correct before option 'L', which can raise a mem. error */ - if (strchr(what, 'L')) - collectvalidlines(L, cl); - lua_unlock(L); - return status; +LUA_API int lua_getinfo(lua_State* L, const char* what, lua_Debug* ar) +{ + int status; + Closure* cl; + CallInfo* ci; + StkId func; + lua_lock(L); + swapextra(L); + if (*what == '>') + { + ci = NULL; + func = L->top - 1; + api_check(L, ttisfunction(func), "function expected"); + what++; /* skip the '>' */ + L->top--; /* pop function */ + } + else + { + ci = ar->i_ci; + func = ci->func; + lua_assert(ttisfunction(ci->func)); + } + cl = ttisclosure(func) ? clvalue(func) : NULL; + status = auxgetinfo(L, what, ar, cl, ci); + if (strchr(what, 'f')) + { + setobjs2s(L, L->top, func); + api_incr_top(L); + } + swapextra(L); /* correct before option 'L', which can raise a mem. error */ + if (strchr(what, 'L')) + collectvalidlines(L, cl); + lua_unlock(L); + return status; } @@ -345,140 +397,169 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { ** ======================================================= */ -static const char *getobjname (Proto *p, int lastpc, int reg, - const char **name); +static const char* getobjname(Proto* p, int lastpc, int reg, + const char** name); /* ** find a "name" for the RK value 'c' */ -static void kname (Proto *p, int pc, int c, const char **name) { - if (ISK(c)) { /* is 'c' a constant? */ - TValue *kvalue = &p->k[INDEXK(c)]; - if (ttisstring(kvalue)) { /* literal constant? */ - *name = svalue(kvalue); /* it is its own name */ - return; - } - /* else no reasonable name found */ - } - else { /* 'c' is a register */ - const char *what = getobjname(p, pc, c, name); /* search for 'c' */ - if (what && *what == 'c') { /* found a constant name? */ - return; /* 'name' already filled */ - } - /* else no reasonable name found */ - } - *name = "?"; /* no reasonable name found */ +static void kname(Proto* p, int pc, int c, const char** name) +{ + if (ISK(c)) + { + /* is 'c' a constant? */ + TValue* kvalue = &p->k[INDEXK(c)]; + if (ttisstring(kvalue)) + { + /* literal constant? */ + *name = svalue(kvalue); /* it is its own name */ + return; + } + /* else no reasonable name found */ + } + else + { + /* 'c' is a register */ + const char* what = getobjname(p, pc, c, name); /* search for 'c' */ + if (what && *what == 'c') + { + /* found a constant name? */ + return; /* 'name' already filled */ + } + /* else no reasonable name found */ + } + *name = "?"; /* no reasonable name found */ } -static int filterpc (int pc, int jmptarget) { - if (pc < jmptarget) /* is code conditional (inside a jump)? */ - return -1; /* cannot know who sets that register */ - else return pc; /* current position sets that register */ +static int filterpc(int pc, int jmptarget) +{ + if (pc < jmptarget) /* is code conditional (inside a jump)? */ + return -1; /* cannot know who sets that register */ + else return pc; /* current position sets that register */ } /* ** try to find last instruction before 'lastpc' that modified register 'reg' */ -static int findsetreg (Proto *p, int lastpc, int reg) { - int pc; - int setreg = -1; /* keep last instruction that changed 'reg' */ - int jmptarget = 0; /* any code before this address is conditional */ - for (pc = 0; pc < lastpc; pc++) { - Instruction i = p->code[pc]; - OpCode op = GET_OPCODE(i); - int a = GETARG_A(i); - switch (op) { - case OP_LOADNIL: { - int b = GETARG_B(i); - if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ - setreg = filterpc(pc, jmptarget); - break; - } - case OP_TFORCALL: { - if (reg >= a + 2) /* affect all regs above its base */ - setreg = filterpc(pc, jmptarget); - break; - } - case OP_CALL: - case OP_TAILCALL: { - if (reg >= a) /* affect all registers above base */ - setreg = filterpc(pc, jmptarget); - break; - } - case OP_JMP: { - int b = GETARG_sBx(i); - int dest = pc + 1 + b; - /* jump is forward and do not skip 'lastpc'? */ - if (pc < dest && dest <= lastpc) { - if (dest > jmptarget) - jmptarget = dest; /* update 'jmptarget' */ - } - break; - } - default: - if (testAMode(op) && reg == a) /* any instruction that set A */ - setreg = filterpc(pc, jmptarget); - break; - } - } - return setreg; +static int findsetreg(Proto* p, int lastpc, int reg) +{ + int pc; + int setreg = -1; /* keep last instruction that changed 'reg' */ + int jmptarget = 0; /* any code before this address is conditional */ + for (pc = 0; pc < lastpc; pc++) + { + Instruction i = p->code[pc]; + OpCode op = GET_OPCODE(i); + int a = GETARG_A(i); + switch (op) + { + case OP_LOADNIL: + { + int b = GETARG_B(i); + if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ + setreg = filterpc(pc, jmptarget); + break; + } + case OP_TFORCALL: + { + if (reg >= a + 2) /* affect all regs above its base */ + setreg = filterpc(pc, jmptarget); + break; + } + case OP_CALL: + case OP_TAILCALL: + { + if (reg >= a) /* affect all registers above base */ + setreg = filterpc(pc, jmptarget); + break; + } + case OP_JMP: + { + int b = GETARG_sBx(i); + int dest = pc + 1 + b; + /* jump is forward and do not skip 'lastpc'? */ + if (pc < dest && dest <= lastpc) + { + if (dest > jmptarget) + jmptarget = dest; /* update 'jmptarget' */ + } + break; + } + default: + if (testAMode(op) && reg == a) /* any instruction that set A */ + setreg = filterpc(pc, jmptarget); + break; + } + } + return setreg; } -static const char *getobjname (Proto *p, int lastpc, int reg, - const char **name) { - int pc; - *name = luaF_getlocalname(p, reg + 1, lastpc); - if (*name) /* is a local? */ - return "local"; - /* else try symbolic execution */ - pc = findsetreg(p, lastpc, reg); - if (pc != -1) { /* could find instruction? */ - Instruction i = p->code[pc]; - OpCode op = GET_OPCODE(i); - switch (op) { - case OP_MOVE: { - int b = GETARG_B(i); /* move from 'b' to 'a' */ - if (b < GETARG_A(i)) - return getobjname(p, pc, b, name); /* get name for 'b' */ - break; - } - case OP_GETTABUP: - case OP_GETTABLE: { - int k = GETARG_C(i); /* key index */ - int t = GETARG_B(i); /* table index */ - const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ - ? luaF_getlocalname(p, t + 1, pc) - : upvalname(p, t); - kname(p, pc, k, name); - return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; - } - case OP_GETUPVAL: { - *name = upvalname(p, GETARG_B(i)); - return "upvalue"; - } - case OP_LOADK: - case OP_LOADKX: { - int b = (op == OP_LOADK) ? GETARG_Bx(i) - : GETARG_Ax(p->code[pc + 1]); - if (ttisstring(&p->k[b])) { - *name = svalue(&p->k[b]); - return "constant"; - } - break; - } - case OP_SELF: { - int k = GETARG_C(i); /* key index */ - kname(p, pc, k, name); - return "method"; - } - default: break; /* go through to return NULL */ - } - } - return NULL; /* could not find reasonable name */ +static const char* getobjname(Proto* p, int lastpc, int reg, + const char** name) +{ + int pc; + *name = luaF_getlocalname(p, reg + 1, lastpc); + if (*name) /* is a local? */ + return "local"; + /* else try symbolic execution */ + pc = findsetreg(p, lastpc, reg); + if (pc != -1) + { + /* could find instruction? */ + Instruction i = p->code[pc]; + OpCode op = GET_OPCODE(i); + switch (op) + { + case OP_MOVE: + { + int b = GETARG_B(i); /* move from 'b' to 'a' */ + if (b < GETARG_A(i)) + return getobjname(p, pc, b, name); /* get name for 'b' */ + break; + } + case OP_GETTABUP: + case OP_GETTABLE: + { + int k = GETARG_C(i); /* key index */ + int t = GETARG_B(i); /* table index */ + const char* vn = (op == OP_GETTABLE) /* name of indexed variable */ + ? luaF_getlocalname(p, t + 1, pc) + : upvalname(p, t); + kname(p, pc, k, name); + return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; + } + case OP_GETUPVAL: + { + *name = upvalname(p, GETARG_B(i)); + return "upvalue"; + } + case OP_LOADK: + case OP_LOADKX: + { + int b = (op == OP_LOADK) + ? GETARG_Bx(i) + : GETARG_Ax(p->code[pc + 1]); + if (ttisstring(&p->k[b])) + { + *name = svalue(&p->k[b]); + return "constant"; + } + break; + } + case OP_SELF: + { + int k = GETARG_C(i); /* key index */ + kname(p, pc, k, name); + return "method"; + } + default: break; /* go through to return NULL */ + } + } + return NULL; /* could not find reasonable name */ } @@ -488,64 +569,90 @@ static const char *getobjname (Proto *p, int lastpc, int reg, ** Returns what the name is (e.g., "for iterator", "method", ** "metamethod") and sets '*name' to point to the name. */ -static const char *funcnamefromcode (lua_State *L, CallInfo *ci, - const char **name) { - TMS tm = (TMS)0; /* (initial value avoids warnings) */ - Proto *p = ci_func(ci)->p; /* calling function */ - int pc = currentpc(ci); /* calling instruction index */ - Instruction i = p->code[pc]; /* calling instruction */ - if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */ - *name = "?"; - return "hook"; - } - switch (GET_OPCODE(i)) { - case OP_CALL: - case OP_TAILCALL: - return getobjname(p, pc, GETARG_A(i), name); /* get function name */ - case OP_TFORCALL: { /* for iterator */ - *name = "for iterator"; - return "for iterator"; - } - /* other instructions can do calls through metamethods */ - case OP_SELF: case OP_GETTABUP: case OP_GETTABLE: - tm = TM_INDEX; - break; - case OP_SETTABUP: case OP_SETTABLE: - tm = TM_NEWINDEX; - break; - case OP_ADD: case OP_SUB: case OP_MUL: case OP_MOD: - case OP_POW: case OP_DIV: case OP_IDIV: case OP_BAND: - case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: { - int offset = cast_int(GET_OPCODE(i)) - cast_int(OP_ADD); /* ORDER OP */ - tm = cast(TMS, offset + cast_int(TM_ADD)); /* ORDER TM */ - break; - } - case OP_UNM: tm = TM_UNM; break; - case OP_BNOT: tm = TM_BNOT; break; - case OP_LEN: tm = TM_LEN; break; - case OP_CONCAT: tm = TM_CONCAT; break; - case OP_EQ: tm = TM_EQ; break; - case OP_LT: tm = TM_LT; break; - case OP_LE: tm = TM_LE; break; - default: - return NULL; /* cannot find a reasonable name */ - } - *name = getstr(G(L)->tmname[tm]); - return "metamethod"; +static const char* funcnamefromcode(lua_State* L, CallInfo* ci, + const char** name) +{ + TMS tm = (TMS)0; /* (initial value avoids warnings) */ + Proto* p = ci_func(ci)->p; /* calling function */ + int pc = currentpc(ci); /* calling instruction index */ + Instruction i = p->code[pc]; /* calling instruction */ + if (ci->callstatus & CIST_HOOKED) + { + /* was it called inside a hook? */ + *name = "?"; + return "hook"; + } + switch (GET_OPCODE(i)) + { + case OP_CALL: + case OP_TAILCALL: + return getobjname(p, pc, GETARG_A(i), name); /* get function name */ + case OP_TFORCALL: + { + /* for iterator */ + *name = "for iterator"; + return "for iterator"; + } + /* other instructions can do calls through metamethods */ + case OP_SELF: + case OP_GETTABUP: + case OP_GETTABLE: + tm = TM_INDEX; + break; + case OP_SETTABUP: + case OP_SETTABLE: + tm = TM_NEWINDEX; + break; + case OP_ADD: + case OP_SUB: + case OP_MUL: + case OP_MOD: + case OP_POW: + case OP_DIV: + case OP_IDIV: + case OP_BAND: + case OP_BOR: + case OP_BXOR: + case OP_SHL: + case OP_SHR: + { + int offset = cast_int(GET_OPCODE(i)) - cast_int(OP_ADD); /* ORDER OP */ + tm = cast(TMS, offset + cast_int(TM_ADD)); /* ORDER TM */ + break; + } + case OP_UNM: tm = TM_UNM; + break; + case OP_BNOT: tm = TM_BNOT; + break; + case OP_LEN: tm = TM_LEN; + break; + case OP_CONCAT: tm = TM_CONCAT; + break; + case OP_EQ: tm = TM_EQ; + break; + case OP_LT: tm = TM_LT; + break; + case OP_LE: tm = TM_LE; + break; + default: + return NULL; /* cannot find a reasonable name */ + } + *name = getstr(G(L)->tmname[tm]); + return "metamethod"; } /* }====================================================== */ - /* ** The subtraction of two potentially unrelated pointers is ** not ISO C, but it should not crash a program; the subsequent ** checks are ISO C and ensure a correct result. */ -static int isinstack (CallInfo *ci, const TValue *o) { - ptrdiff_t i = o - ci->u.l.base; - return (0 <= i && i < (ci->top - ci->u.l.base) && ci->u.l.base + i == o); +static int isinstack(CallInfo* ci, const TValue* o) +{ + ptrdiff_t i = o - ci->u.l.base; + return (0 <= i && i < (ci->top - ci->u.l.base) && ci->u.l.base + i == o); } @@ -554,145 +661,168 @@ static int isinstack (CallInfo *ci, const TValue *o) { ** with instructions OP_GETTABUP/OP_SETTABUP, which operate directly on ** upvalues.) */ -static const char *getupvalname (CallInfo *ci, const TValue *o, - const char **name) { - LClosure *c = ci_func(ci); - int i; - for (i = 0; i < c->nupvalues; i++) { - if (c->upvals[i]->v == o) { - *name = upvalname(c->p, i); - return "upvalue"; - } - } - return NULL; +static const char* getupvalname(CallInfo* ci, const TValue* o, + const char** name) +{ + LClosure* c = ci_func(ci); + int i; + for (i = 0; i < c->nupvalues; i++) + { + if (c->upvals[i]->v == o) + { + *name = upvalname(c->p, i); + return "upvalue"; + } + } + return NULL; } -static const char *varinfo (lua_State *L, const TValue *o) { - const char *name = NULL; /* to avoid warnings */ - CallInfo *ci = L->ci; - const char *kind = NULL; - if (isLua(ci)) { - kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ - if (!kind && isinstack(ci, o)) /* no? try a register */ - kind = getobjname(ci_func(ci)->p, currentpc(ci), - cast_int(o - ci->u.l.base), &name); - } - return (kind) ? luaO_pushfstring(L, " (%s '%s')", kind, name) : ""; +static const char* varinfo(lua_State* L, const TValue* o) +{ + const char* name = NULL; /* to avoid warnings */ + CallInfo* ci = L->ci; + const char* kind = NULL; + if (isLua(ci)) + { + kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ + if (!kind && isinstack(ci, o)) /* no? try a register */ + kind = getobjname(ci_func(ci)->p, currentpc(ci), + cast_int(o - ci->u.l.base), &name); + } + return (kind) ? luaO_pushfstring(L, " (%s '%s')", kind, name) : ""; } -l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { - const char *t = luaT_objtypename(L, o); - luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o)); +l_noret luaG_typeerror(lua_State* L, const TValue* o, const char* op) +{ + const char* t = luaT_objtypename(L, o); + luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o)); } -l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) { - if (ttisstring(p1) || cvt2str(p1)) p1 = p2; - luaG_typeerror(L, p1, "concatenate"); +l_noret luaG_concaterror(lua_State* L, const TValue* p1, const TValue* p2) +{ + if (ttisstring(p1) || cvt2str(p1)) p1 = p2; + luaG_typeerror(L, p1, "concatenate"); } -l_noret luaG_opinterror (lua_State *L, const TValue *p1, - const TValue *p2, const char *msg) { - lua_Number temp; - if (!tonumber(p1, &temp)) /* first operand is wrong? */ - p2 = p1; /* now second is wrong */ - luaG_typeerror(L, p2, msg); +l_noret luaG_opinterror(lua_State* L, const TValue* p1, + const TValue* p2, const char* msg) +{ + lua_Number temp; + if (!tonumber(p1, &temp)) /* first operand is wrong? */ + p2 = p1; /* now second is wrong */ + luaG_typeerror(L, p2, msg); } /* ** Error when both values are convertible to numbers, but not to integers */ -l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) { - lua_Integer temp; - if (!tointeger(p1, &temp)) - p2 = p1; - luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2)); +l_noret luaG_tointerror(lua_State* L, const TValue* p1, const TValue* p2) +{ + lua_Integer temp; + if (!tointeger(p1, &temp)) + p2 = p1; + luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2)); } -l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { - const char *t1 = luaT_objtypename(L, p1); - const char *t2 = luaT_objtypename(L, p2); - if (strcmp(t1, t2) == 0) - luaG_runerror(L, "attempt to compare two %s values", t1); - else - luaG_runerror(L, "attempt to compare %s with %s", t1, t2); +l_noret luaG_ordererror(lua_State* L, const TValue* p1, const TValue* p2) +{ + const char* t1 = luaT_objtypename(L, p1); + const char* t2 = luaT_objtypename(L, p2); + if (strcmp(t1, t2) == 0) + luaG_runerror(L, "attempt to compare two %s values", t1); + else + luaG_runerror(L, "attempt to compare %s with %s", t1, t2); } /* add src:line information to 'msg' */ -const char *luaG_addinfo (lua_State *L, const char *msg, TString *src, - int line) { - char buff[LUA_IDSIZE]; - if (src) - luaO_chunkid(buff, getstr(src), LUA_IDSIZE); - else { /* no source available; use "?" instead */ - buff[0] = '?'; buff[1] = '\0'; - } - return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); +const char* luaG_addinfo(lua_State* L, const char* msg, TString* src, + int line) +{ + char buff[LUA_IDSIZE]; + if (src) + luaO_chunkid(buff, getstr(src), LUA_IDSIZE); + else + { + /* no source available; use "?" instead */ + buff[0] = '?'; + buff[1] = '\0'; + } + return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); } -l_noret luaG_errormsg (lua_State *L) { - if (L->errfunc != 0) { /* is there an error handling function? */ - StkId errfunc = restorestack(L, L->errfunc); - setobjs2s(L, L->top, L->top - 1); /* move argument */ - setobjs2s(L, L->top - 1, errfunc); /* push function */ - L->top++; /* assume EXTRA_STACK */ - luaD_callnoyield(L, L->top - 2, 1); /* call it */ - } - luaD_throw(L, LUA_ERRRUN); +l_noret luaG_errormsg(lua_State* L) +{ + if (L->errfunc != 0) + { + /* is there an error handling function? */ + StkId errfunc = restorestack(L, L->errfunc); + setobjs2s(L, L->top, L->top - 1); /* move argument */ + setobjs2s(L, L->top - 1, errfunc); /* push function */ + L->top++; /* assume EXTRA_STACK */ + luaD_callnoyield(L, L->top - 2, 1); /* call it */ + } + luaD_throw(L, LUA_ERRRUN); } -l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { - CallInfo *ci = L->ci; - const char *msg; - va_list argp; - va_start(argp, fmt); - msg = luaO_pushvfstring(L, fmt, argp); /* format message */ - va_end(argp); - if (isLua(ci)) /* if Lua function, add source:line information */ - luaG_addinfo(L, msg, ci_func(ci)->p->source, currentline(ci)); - luaG_errormsg(L); +l_noret luaG_runerror(lua_State* L, const char* fmt, ...) +{ + CallInfo* ci = L->ci; + const char* msg; + va_list argp; + va_start(argp, fmt); + msg = luaO_pushvfstring(L, fmt, argp); /* format message */ + va_end(argp); + if (isLua(ci)) /* if Lua function, add source:line information */ + luaG_addinfo(L, msg, ci_func(ci)->p->source, currentline(ci)); + luaG_errormsg(L); } -void luaG_traceexec (lua_State *L) { - CallInfo *ci = L->ci; - lu_byte mask = L->hookmask; - int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT)); - if (counthook) - resethookcount(L); /* reset count */ - else if (!(mask & LUA_MASKLINE)) - return; /* no line hook and count != 0; nothing to be done */ - if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ - ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ - return; /* do not call hook again (VM yielded, so it did not move) */ - } - if (counthook) - luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */ - if (mask & LUA_MASKLINE) { - Proto *p = ci_func(ci)->p; - int npc = pcRel(ci->u.l.savedpc, p); - int newline = getfuncline(p, npc); - if (npc == 0 || /* call linehook when enter a new function, */ - ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ - newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */ - luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */ - } - L->oldpc = ci->u.l.savedpc; - if (L->status == LUA_YIELD) { /* did hook yield? */ - if (counthook) - L->hookcount = 1; /* undo decrement to zero */ - ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ - ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ - ci->func = L->top - 1; /* protect stack below results */ - luaD_throw(L, LUA_YIELD); - } +void luaG_traceexec(lua_State* L) +{ + CallInfo* ci = L->ci; + lu_byte mask = L->hookmask; + int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT)); + if (counthook) + resethookcount(L); /* reset count */ + else if (!(mask & LUA_MASKLINE)) + return; /* no line hook and count != 0; nothing to be done */ + if (ci->callstatus & CIST_HOOKYIELD) + { + /* called hook last time? */ + ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ + return; /* do not call hook again (VM yielded, so it did not move) */ + } + if (counthook) + luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */ + if (mask & LUA_MASKLINE) + { + Proto* p = ci_func(ci)->p; + int npc = pcRel(ci->u.l.savedpc, p); + int newline = getfuncline(p, npc); + if (npc == 0 || /* call linehook when enter a new function, */ + ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ + newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */ + luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */ + } + L->oldpc = ci->u.l.savedpc; + if (L->status == LUA_YIELD) + { + /* did hook yield? */ + if (counthook) + L->hookcount = 1; /* undo decrement to zero */ + ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ + ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ + ci->func = L->top - 1; /* protect stack below results */ + luaD_throw(L, LUA_YIELD); + } } - diff --git a/Lua/ldebug.h b/Lua/ldebug.h index 0e31546..36ee35e 100644 --- a/Lua/ldebug.h +++ b/Lua/ldebug.h @@ -18,22 +18,22 @@ #define resethookcount(L) (L->hookcount = L->basehookcount) -LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, - const char *opname); -LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1, - const TValue *p2, - const char *msg); -LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); -LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg, - TString *src, int line); -LUAI_FUNC l_noret luaG_errormsg (lua_State *L); -LUAI_FUNC void luaG_traceexec (lua_State *L); +LUAI_FUNC l_noret luaG_typeerror(lua_State* L, const TValue* o, + const char* opname); +LUAI_FUNC l_noret luaG_concaterror(lua_State* L, const TValue* p1, + const TValue* p2); +LUAI_FUNC l_noret luaG_opinterror(lua_State* L, const TValue* p1, + const TValue* p2, + const char* msg); +LUAI_FUNC l_noret luaG_tointerror(lua_State* L, const TValue* p1, + const TValue* p2); +LUAI_FUNC l_noret luaG_ordererror(lua_State* L, const TValue* p1, + const TValue* p2); +LUAI_FUNC l_noret luaG_runerror(lua_State* L, const char* fmt, ...); +LUAI_FUNC const char* luaG_addinfo(lua_State* L, const char* msg, + TString* src, int line); +LUAI_FUNC l_noret luaG_errormsg(lua_State* L); +LUAI_FUNC void luaG_traceexec(lua_State* L); #endif diff --git a/Lua/ldo.c b/Lua/ldo.c index 90b695f..316e4ce 100644 --- a/Lua/ldo.c +++ b/Lua/ldo.c @@ -34,7 +34,6 @@ #include "lzio.h" - #define errorstatus(s) ((s) > LUA_YIELD) @@ -79,72 +78,90 @@ #endif /* } */ - /* chain list of long jump buffers */ -struct lua_longjmp { - struct lua_longjmp *previous; - luai_jmpbuf b; - volatile int status; /* error code */ +struct lua_longjmp +{ + struct lua_longjmp* previous; + luai_jmpbuf b; + volatile int status; /* error code */ }; -static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { - switch (errcode) { - case LUA_ERRMEM: { /* memory error? */ - setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ - break; - } - case LUA_ERRERR: { - setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); - break; - } - default: { - setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ - break; - } - } - L->top = oldtop + 1; +static void seterrorobj(lua_State* L, int errcode, StkId oldtop) +{ + switch (errcode) + { + case LUA_ERRMEM: + { + /* memory error? */ + setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ + break; + } + case LUA_ERRERR: + { + setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); + break; + } + default: + { + setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ + break; + } + } + L->top = oldtop + 1; } -l_noret luaD_throw (lua_State *L, int errcode) { - if (L->errorJmp) { /* thread has an error handler? */ - L->errorJmp->status = errcode; /* set status */ - LUAI_THROW(L, L->errorJmp); /* jump to it */ - } - else { /* thread has no error handler */ - global_State *g = G(L); - L->status = cast_byte(errcode); /* mark it as dead */ - if (g->mainthread->errorJmp) { /* main thread has a handler? */ - setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */ - luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ - } - else { /* no handler at all; abort */ - if (g->panic) { /* panic function? */ - seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */ - if (L->ci->top < L->top) - L->ci->top = L->top; /* pushing msg. can break this invariant */ - lua_unlock(L); - g->panic(L); /* call panic function (last chance to jump out) */ - } - abort(); - } - } +l_noret luaD_throw(lua_State* L, int errcode) +{ + if (L->errorJmp) + { + /* thread has an error handler? */ + L->errorJmp->status = errcode; /* set status */ + LUAI_THROW(L, L->errorJmp); /* jump to it */ + } + else + { + /* thread has no error handler */ + global_State* g = G(L); + L->status = cast_byte(errcode); /* mark it as dead */ + if (g->mainthread->errorJmp) + { + /* main thread has a handler? */ + setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */ + luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ + } + else + { + /* no handler at all; abort */ + if (g->panic) + { + /* panic function? */ + seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */ + if (L->ci->top < L->top) + L->ci->top = L->top; /* pushing msg. can break this invariant */ + lua_unlock(L); + g->panic(L); /* call panic function (last chance to jump out) */ + } + abort(); + } + } } -int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { - unsigned short oldnCcalls = L->nCcalls; - struct lua_longjmp lj; - lj.status = LUA_OK; - lj.previous = L->errorJmp; /* chain new error handler */ - L->errorJmp = &lj; - LUAI_TRY(L, &lj, - (*f)(L, ud); - ); - L->errorJmp = lj.previous; /* restore old error handler */ - L->nCcalls = oldnCcalls; - return lj.status; +int luaD_rawrunprotected(lua_State* L, Pfunc f, void* ud) +{ + unsigned short oldnCcalls = L->nCcalls; + struct lua_longjmp lj; + lj.status = LUA_OK; + lj.previous = L->errorJmp; /* chain new error handler */ + L->errorJmp = &lj; + LUAI_TRY(L, &lj, + (*f)(L, ud); + ); + L->errorJmp = lj.previous; /* restore old error handler */ + L->nCcalls = oldnCcalls; + return lj.status; } /* }====================================================== */ @@ -155,18 +172,20 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { ** Stack reallocation ** =================================================================== */ -static void correctstack (lua_State *L, TValue *oldstack) { - CallInfo *ci; - UpVal *up; - L->top = (L->top - oldstack) + L->stack; - for (up = L->openupval; up != NULL; up = up->u.open.next) - up->v = (up->v - oldstack) + L->stack; - for (ci = L->ci; ci != NULL; ci = ci->previous) { - ci->top = (ci->top - oldstack) + L->stack; - ci->func = (ci->func - oldstack) + L->stack; - if (isLua(ci)) - ci->u.l.base = (ci->u.l.base - oldstack) + L->stack; - } +static void correctstack(lua_State* L, TValue* oldstack) +{ + CallInfo* ci; + UpVal* up; + L->top = (L->top - oldstack) + L->stack; + for (up = L->openupval; up != NULL; up = up->u.open.next) + up->v = (up->v - oldstack) + L->stack; + for (ci = L->ci; ci != NULL; ci = ci->previous) + { + ci->top = (ci->top - oldstack) + L->stack; + ci->func = (ci->func - oldstack) + L->stack; + if (isLua(ci)) + ci->u.l.base = (ci->u.l.base - oldstack) + L->stack; + } } @@ -174,72 +193,81 @@ static void correctstack (lua_State *L, TValue *oldstack) { #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) -void luaD_reallocstack (lua_State *L, int newsize) { - TValue *oldstack = L->stack; - int lim = L->stacksize; - lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); - lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); - luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue); - for (; lim < newsize; lim++) - setnilvalue(L->stack + lim); /* erase new segment */ - L->stacksize = newsize; - L->stack_last = L->stack + newsize - EXTRA_STACK; - correctstack(L, oldstack); +void luaD_reallocstack(lua_State* L, int newsize) +{ + TValue* oldstack = L->stack; + int lim = L->stacksize; + lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); + lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); + luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue); + for (; lim < newsize; lim++) + setnilvalue(L->stack + lim); /* erase new segment */ + L->stacksize = newsize; + L->stack_last = L->stack + newsize - EXTRA_STACK; + correctstack(L, oldstack); } -void luaD_growstack (lua_State *L, int n) { - int size = L->stacksize; - if (size > LUAI_MAXSTACK) /* error after extra size? */ - luaD_throw(L, LUA_ERRERR); - else { - int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; - int newsize = 2 * size; - if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; - if (newsize < needed) newsize = needed; - if (newsize > LUAI_MAXSTACK) { /* stack overflow? */ - luaD_reallocstack(L, ERRORSTACKSIZE); - luaG_runerror(L, "stack overflow"); - } - else - luaD_reallocstack(L, newsize); - } +void luaD_growstack(lua_State* L, int n) +{ + int size = L->stacksize; + if (size > LUAI_MAXSTACK) /* error after extra size? */ + luaD_throw(L, LUA_ERRERR); + else + { + int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; + int newsize = 2 * size; + if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; + if (newsize < needed) newsize = needed; + if (newsize > LUAI_MAXSTACK) + { + /* stack overflow? */ + luaD_reallocstack(L, ERRORSTACKSIZE); + luaG_runerror(L, "stack overflow"); + } + else + luaD_reallocstack(L, newsize); + } } -static int stackinuse (lua_State *L) { - CallInfo *ci; - StkId lim = L->top; - for (ci = L->ci; ci != NULL; ci = ci->previous) { - if (lim < ci->top) lim = ci->top; - } - lua_assert(lim <= L->stack_last); - return cast_int(lim - L->stack) + 1; /* part of stack in use */ +static int stackinuse(lua_State* L) +{ + CallInfo* ci; + StkId lim = L->top; + for (ci = L->ci; ci != NULL; ci = ci->previous) + { + if (lim < ci->top) lim = ci->top; + } + lua_assert(lim <= L->stack_last); + return cast_int(lim - L->stack) + 1; /* part of stack in use */ } -void luaD_shrinkstack (lua_State *L) { - int inuse = stackinuse(L); - int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; - if (goodsize > LUAI_MAXSTACK) - goodsize = LUAI_MAXSTACK; /* respect stack limit */ - if (L->stacksize > LUAI_MAXSTACK) /* had been handling stack overflow? */ - luaE_freeCI(L); /* free all CIs (list grew because of an error) */ - else - luaE_shrinkCI(L); /* shrink list */ - /* if thread is currently not handling a stack overflow and its - good size is smaller than current size, shrink its stack */ - if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && - goodsize < L->stacksize) - luaD_reallocstack(L, goodsize); - else /* don't change stack */ - condmovestack(L,{},{}); /* (change only for debugging) */ +void luaD_shrinkstack(lua_State* L) +{ + int inuse = stackinuse(L); + int goodsize = inuse + (inuse / 8) + 2 * EXTRA_STACK; + if (goodsize > LUAI_MAXSTACK) + goodsize = LUAI_MAXSTACK; /* respect stack limit */ + if (L->stacksize > LUAI_MAXSTACK) /* had been handling stack overflow? */ + luaE_freeCI(L); /* free all CIs (list grew because of an error) */ + else + luaE_shrinkCI(L); /* shrink list */ + /* if thread is currently not handling a stack overflow and its + good size is smaller than current size, shrink its stack */ + if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && + goodsize < L->stacksize) + luaD_reallocstack(L, goodsize); + else /* don't change stack */ + condmovestack(L, {}, {}); /* (change only for debugging) */ } -void luaD_inctop (lua_State *L) { - luaD_checkstack(L, 1); - L->top++; +void luaD_inctop(lua_State* L) +{ + luaD_checkstack(L, 1); + L->top++; } /* }================================================================== */ @@ -250,60 +278,67 @@ void luaD_inctop (lua_State *L) { ** called. (Both 'L->hook' and 'L->hookmask', which triggers this ** function, can be changed asynchronously by signals.) */ -void luaD_hook (lua_State *L, int event, int line) { - lua_Hook hook = L->hook; - if (hook && L->allowhook) { /* make sure there is a hook */ - CallInfo *ci = L->ci; - ptrdiff_t top = savestack(L, L->top); - ptrdiff_t ci_top = savestack(L, ci->top); - lua_Debug ar; - ar.event = event; - ar.currentline = line; - ar.i_ci = ci; - luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - ci->top = L->top + LUA_MINSTACK; - lua_assert(ci->top <= L->stack_last); - L->allowhook = 0; /* cannot call hooks inside a hook */ - ci->callstatus |= CIST_HOOKED; - lua_unlock(L); - (*hook)(L, &ar); - lua_lock(L); - lua_assert(!L->allowhook); - L->allowhook = 1; - ci->top = restorestack(L, ci_top); - L->top = restorestack(L, top); - ci->callstatus &= ~CIST_HOOKED; - } +void luaD_hook(lua_State* L, int event, int line) +{ + lua_Hook hook = L->hook; + if (hook && L->allowhook) + { + /* make sure there is a hook */ + CallInfo* ci = L->ci; + ptrdiff_t top = savestack(L, L->top); + ptrdiff_t ci_top = savestack(L, ci->top); + lua_Debug ar; + ar.event = event; + ar.currentline = line; + ar.i_ci = ci; + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); + L->allowhook = 0; /* cannot call hooks inside a hook */ + ci->callstatus |= CIST_HOOKED; + lua_unlock(L); + (*hook)(L, &ar); + lua_lock(L); + lua_assert(!L->allowhook); + L->allowhook = 1; + ci->top = restorestack(L, ci_top); + L->top = restorestack(L, top); + ci->callstatus &= ~CIST_HOOKED; + } } -static void callhook (lua_State *L, CallInfo *ci) { - int hook = LUA_HOOKCALL; - ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ - if (isLua(ci->previous) && - GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { - ci->callstatus |= CIST_TAIL; - hook = LUA_HOOKTAILCALL; - } - luaD_hook(L, hook, -1); - ci->u.l.savedpc--; /* correct 'pc' */ +static void callhook(lua_State* L, CallInfo* ci) +{ + int hook = LUA_HOOKCALL; + ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ + if (isLua(ci->previous) && + GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) + { + ci->callstatus |= CIST_TAIL; + hook = LUA_HOOKTAILCALL; + } + luaD_hook(L, hook, -1); + ci->u.l.savedpc--; /* correct 'pc' */ } -static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { - int i; - int nfixargs = p->numparams; - StkId base, fixed; - /* move fixed parameters to final position */ - fixed = L->top - actual; /* first fixed argument */ - base = L->top; /* final position of first argument */ - for (i = 0; i < nfixargs && i < actual; i++) { - setobjs2s(L, L->top++, fixed + i); - setnilvalue(fixed + i); /* erase original copy (for GC) */ - } - for (; i < nfixargs; i++) - setnilvalue(L->top++); /* complete missing arguments */ - return base; +static StkId adjust_varargs(lua_State* L, Proto* p, int actual) +{ + int i; + int nfixargs = p->numparams; + StkId base, fixed; + /* move fixed parameters to final position */ + fixed = L->top - actual; /* first fixed argument */ + base = L->top; /* final position of first argument */ + for (i = 0; i < nfixargs && i < actual; i++) + { + setobjs2s(L, L->top++, fixed + i); + setnilvalue(fixed + i); /* erase original copy (for GC) */ + } + for (; i < nfixargs; i++) + setnilvalue(L->top++); /* complete missing arguments */ + return base; } @@ -312,16 +347,17 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { ** it in stack below original 'func' so that 'luaD_precall' can call ** it. Raise an error if __call metafield is not a function. */ -static void tryfuncTM (lua_State *L, StkId func) { - const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); - StkId p; - if (!ttisfunction(tm)) - luaG_typeerror(L, func, "call"); - /* Open a hole inside the stack at 'func' */ - for (p = L->top; p > func; p--) - setobjs2s(L, p, p-1); - L->top++; /* slot ensured by caller */ - setobj2s(L, func, tm); /* tag method is the new function to be called */ +static void tryfuncTM(lua_State* L, StkId func) +{ + const TValue* tm = luaT_gettmbyobj(L, func, TM_CALL); + StkId p; + if (!ttisfunction(tm)) + luaG_typeerror(L, func, "call"); + /* Open a hole inside the stack at 'func' */ + for (p = L->top; p > func; p--) + setobjs2s(L, p, p-1); + L->top++; /* slot ensured by caller */ + setobj2s(L, func, tm); /* tag method is the new function to be called */ } @@ -331,40 +367,51 @@ static void tryfuncTM (lua_State *L, StkId func) { ** expressions, multiple results for tail calls/single parameters) ** separated. */ -static int moveresults (lua_State *L, const TValue *firstResult, StkId res, - int nres, int wanted) { - switch (wanted) { /* handle typical cases separately */ - case 0: break; /* nothing to move */ - case 1: { /* one result needed */ - if (nres == 0) /* no results? */ - firstResult = luaO_nilobject; /* adjust with nil */ - setobjs2s(L, res, firstResult); /* move it to proper place */ - break; - } - case LUA_MULTRET: { - int i; - for (i = 0; i < nres; i++) /* move all results to correct place */ - setobjs2s(L, res + i, firstResult + i); - L->top = res + nres; - return 0; /* wanted == LUA_MULTRET */ - } - default: { - int i; - if (wanted <= nres) { /* enough results? */ - for (i = 0; i < wanted; i++) /* move wanted results to correct place */ - setobjs2s(L, res + i, firstResult + i); - } - else { /* not enough results; use all of them plus nils */ - for (i = 0; i < nres; i++) /* move all results to correct place */ - setobjs2s(L, res + i, firstResult + i); - for (; i < wanted; i++) /* complete wanted number of results */ - setnilvalue(res + i); - } - break; - } - } - L->top = res + wanted; /* top points after the last result */ - return 1; +static int moveresults(lua_State* L, const TValue* firstResult, StkId res, + int nres, int wanted) +{ + switch (wanted) + { + /* handle typical cases separately */ + case 0: break; /* nothing to move */ + case 1: + { + /* one result needed */ + if (nres == 0) /* no results? */ + firstResult = luaO_nilobject; /* adjust with nil */ + setobjs2s(L, res, firstResult); /* move it to proper place */ + break; + } + case LUA_MULTRET: + { + int i; + for (i = 0; i < nres; i++) /* move all results to correct place */ + setobjs2s(L, res + i, firstResult + i); + L->top = res + nres; + return 0; /* wanted == LUA_MULTRET */ + } + default: + { + int i; + if (wanted <= nres) + { + /* enough results? */ + for (i = 0; i < wanted; i++) /* move wanted results to correct place */ + setobjs2s(L, res + i, firstResult + i); + } + else + { + /* not enough results; use all of them plus nils */ + for (i = 0; i < nres; i++) /* move all results to correct place */ + setobjs2s(L, res + i, firstResult + i); + for (; i < wanted; i++) /* complete wanted number of results */ + setnilvalue(res + i); + } + break; + } + } + L->top = res + wanted; /* top points after the last result */ + return 1; } @@ -373,25 +420,27 @@ static int moveresults (lua_State *L, const TValue *firstResult, StkId res, ** moves current number of results to proper place; returns 0 iff call ** wanted multiple (variable number of) results. */ -int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { - StkId res; - int wanted = ci->nresults; - if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { - if (L->hookmask & LUA_MASKRET) { - ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ - luaD_hook(L, LUA_HOOKRET, -1); - firstResult = restorestack(L, fr); - } - L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ - } - res = ci->func; /* res == final position of 1st result */ - L->ci = ci->previous; /* back to caller */ - /* move results to proper place */ - return moveresults(L, firstResult, res, nres, wanted); +int luaD_poscall(lua_State* L, CallInfo* ci, StkId firstResult, int nres) +{ + StkId res; + int wanted = ci->nresults; + if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) + { + if (L->hookmask & LUA_MASKRET) + { + ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ + luaD_hook(L, LUA_HOOKRET, -1); + firstResult = restorestack(L, fr); + } + L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ + } + res = ci->func; /* res == final position of 1st result */ + L->ci = ci->previous; /* back to caller */ + /* move results to proper place */ + return moveresults(L, firstResult, res, nres, wanted); } - #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) @@ -410,64 +459,73 @@ int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { ** the execution ('luaV_execute') to the caller, to allow stackless ** calls.) Returns true iff function has been executed (C function). */ -int luaD_precall (lua_State *L, StkId func, int nresults) { - lua_CFunction f; - CallInfo *ci; - switch (ttype(func)) { - case LUA_TCCL: /* C closure */ - f = clCvalue(func)->f; - goto Cfunc; - case LUA_TLCF: /* light C function */ - f = fvalue(func); - Cfunc: { - int n; /* number of returns */ - checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ - ci = next_ci(L); /* now 'enter' new function */ - ci->nresults = nresults; - ci->func = func; - ci->top = L->top + LUA_MINSTACK; - lua_assert(ci->top <= L->stack_last); - ci->callstatus = 0; - if (L->hookmask & LUA_MASKCALL) - luaD_hook(L, LUA_HOOKCALL, -1); - lua_unlock(L); - n = (*f)(L); /* do the actual call */ - lua_lock(L); - api_checknelems(L, n); - luaD_poscall(L, ci, L->top - n, n); - return 1; - } - case LUA_TLCL: { /* Lua function: prepare its call */ - StkId base; - Proto *p = clLvalue(func)->p; - int n = cast_int(L->top - func) - 1; /* number of real arguments */ - int fsize = p->maxstacksize; /* frame size */ - checkstackp(L, fsize, func); - if (p->is_vararg) - base = adjust_varargs(L, p, n); - else { /* non vararg function */ - for (; n < p->numparams; n++) - setnilvalue(L->top++); /* complete missing arguments */ - base = func + 1; - } - ci = next_ci(L); /* now 'enter' new function */ - ci->nresults = nresults; - ci->func = func; - ci->u.l.base = base; - L->top = ci->top = base + fsize; - lua_assert(ci->top <= L->stack_last); - ci->u.l.savedpc = p->code; /* starting point */ - ci->callstatus = CIST_LUA; - if (L->hookmask & LUA_MASKCALL) - callhook(L, ci); - return 0; - } - default: { /* not a function */ - checkstackp(L, 1, func); /* ensure space for metamethod */ - tryfuncTM(L, func); /* try to get '__call' metamethod */ - return luaD_precall(L, func, nresults); /* now it must be a function */ - } - } +int luaD_precall(lua_State* L, StkId func, int nresults) +{ + lua_CFunction f; + CallInfo* ci; + switch (ttype(func)) + { + case LUA_TCCL: /* C closure */ + f = clCvalue(func)->f; + goto Cfunc; + case LUA_TLCF: /* light C function */ + f = fvalue(func); + Cfunc: + { + int n; /* number of returns */ + checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ + ci = next_ci(L); /* now 'enter' new function */ + ci->nresults = nresults; + ci->func = func; + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); + ci->callstatus = 0; + if (L->hookmask & LUA_MASKCALL) + luaD_hook(L, LUA_HOOKCALL, -1); + lua_unlock(L); + n = (*f)(L); /* do the actual call */ + lua_lock(L); + api_checknelems(L, n); + luaD_poscall(L, ci, L->top - n, n); + return 1; + } + case LUA_TLCL: + { + /* Lua function: prepare its call */ + StkId base; + Proto* p = clLvalue(func)->p; + int n = cast_int(L->top - func) - 1; /* number of real arguments */ + int fsize = p->maxstacksize; /* frame size */ + checkstackp(L, fsize, func); + if (p->is_vararg) + base = adjust_varargs(L, p, n); + else + { + /* non vararg function */ + for (; n < p->numparams; n++) + setnilvalue(L->top++); /* complete missing arguments */ + base = func + 1; + } + ci = next_ci(L); /* now 'enter' new function */ + ci->nresults = nresults; + ci->func = func; + ci->u.l.base = base; + L->top = ci->top = base + fsize; + lua_assert(ci->top <= L->stack_last); + ci->u.l.savedpc = p->code; /* starting point */ + ci->callstatus = CIST_LUA; + if (L->hookmask & LUA_MASKCALL) + callhook(L, ci); + return 0; + } + default: + { + /* not a function */ + checkstackp(L, 1, func); /* ensure space for metamethod */ + tryfuncTM(L, func); /* try to get '__call' metamethod */ + return luaD_precall(L, func, nresults); /* now it must be a function */ + } + } } @@ -478,11 +536,12 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { ** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to ** allow overflow handling to work) */ -static void stackerror (lua_State *L) { - if (L->nCcalls == LUAI_MAXCCALLS) - luaG_runerror(L, "C stack overflow"); - else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) - luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ +static void stackerror(lua_State* L) +{ + if (L->nCcalls == LUAI_MAXCCALLS) + luaG_runerror(L, "C stack overflow"); + else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS >> 3))) + luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ } @@ -492,22 +551,24 @@ static void stackerror (lua_State *L) { ** When returns, all the results are on the stack, starting at the original ** function position. */ -void luaD_call (lua_State *L, StkId func, int nResults) { - if (++L->nCcalls >= LUAI_MAXCCALLS) - stackerror(L); - if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ - luaV_execute(L); /* call it */ - L->nCcalls--; +void luaD_call(lua_State* L, StkId func, int nResults) +{ + if (++L->nCcalls >= LUAI_MAXCCALLS) + stackerror(L); + if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ + luaV_execute(L); /* call it */ + L->nCcalls--; } /* ** Similar to 'luaD_call', but does not allow yields during the call */ -void luaD_callnoyield (lua_State *L, StkId func, int nResults) { - L->nny++; - luaD_call(L, func, nResults); - L->nny--; +void luaD_callnoyield(lua_State* L, StkId func, int nResults) +{ + L->nny++; + luaD_call(L, func, nResults); + L->nny--; } @@ -515,25 +576,28 @@ void luaD_callnoyield (lua_State *L, StkId func, int nResults) { ** Completes the execution of an interrupted C function, calling its ** continuation function. */ -static void finishCcall (lua_State *L, int status) { - CallInfo *ci = L->ci; - int n; - /* must have a continuation and must be able to call it */ - lua_assert(ci->u.c.k != NULL && L->nny == 0); - /* error status can only happen in a protected call */ - lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD); - if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ - ci->callstatus &= ~CIST_YPCALL; /* continuation is also inside it */ - L->errfunc = ci->u.c.old_errfunc; /* with the same error function */ - } - /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already - handled */ - adjustresults(L, ci->nresults); - lua_unlock(L); - n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ - lua_lock(L); - api_checknelems(L, n); - luaD_poscall(L, ci, L->top - n, n); /* finish 'luaD_precall' */ +static void finishCcall(lua_State* L, int status) +{ + CallInfo* ci = L->ci; + int n; + /* must have a continuation and must be able to call it */ + lua_assert(ci->u.c.k != NULL && L->nny == 0); + /* error status can only happen in a protected call */ + lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD); + if (ci->callstatus & CIST_YPCALL) + { + /* was inside a pcall? */ + ci->callstatus &= ~CIST_YPCALL; /* continuation is also inside it */ + L->errfunc = ci->u.c.old_errfunc; /* with the same error function */ + } + /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already + handled */ + adjustresults(L, ci->nresults); + lua_unlock(L); + n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ + lua_lock(L); + api_checknelems(L, n); + luaD_poscall(L, ci, L->top - n, n); /* finish 'luaD_precall' */ } @@ -545,17 +609,22 @@ static void finishCcall (lua_State *L, int status) { ** be passed to the first continuation function (otherwise the default ** status is LUA_YIELD). */ -static void unroll (lua_State *L, void *ud) { - if (ud != NULL) /* error status? */ - finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */ - while (L->ci != &L->base_ci) { /* something in the stack */ - if (!isLua(L->ci)) /* C function? */ - finishCcall(L, LUA_YIELD); /* complete its execution */ - else { /* Lua function */ - luaV_finishOp(L); /* finish interrupted instruction */ - luaV_execute(L); /* execute down to higher C 'boundary' */ - } - } +static void unroll(lua_State* L, void* ud) +{ + if (ud != NULL) /* error status? */ + finishCcall(L, *(int*)ud); /* finish 'lua_pcallk' callee */ + while (L->ci != &L->base_ci) + { + /* something in the stack */ + if (!isLua(L->ci)) /* C function? */ + finishCcall(L, LUA_YIELD); /* complete its execution */ + else + { + /* Lua function */ + luaV_finishOp(L); /* finish interrupted instruction */ + luaV_execute(L); /* execute down to higher C 'boundary' */ + } + } } @@ -563,13 +632,16 @@ static void unroll (lua_State *L, void *ud) { ** Try to find a suspended protected call (a "recover point") for the ** given thread. */ -static CallInfo *findpcall (lua_State *L) { - CallInfo *ci; - for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ - if (ci->callstatus & CIST_YPCALL) - return ci; - } - return NULL; /* no pending pcall */ +static CallInfo* findpcall(lua_State* L) +{ + CallInfo* ci; + for (ci = L->ci; ci != NULL; ci = ci->previous) + { + /* search for a pcall */ + if (ci->callstatus & CIST_YPCALL) + return ci; + } + return NULL; /* no pending pcall */ } @@ -578,20 +650,21 @@ static CallInfo *findpcall (lua_State *L) { ** there is one) and completes the execution of the interrupted ** 'luaD_pcall'. If there is no recover point, returns zero. */ -static int recover (lua_State *L, int status) { - StkId oldtop; - CallInfo *ci = findpcall(L); - if (ci == NULL) return 0; /* no recovery point */ - /* "finish" luaD_pcall */ - oldtop = restorestack(L, ci->extra); - luaF_close(L, oldtop); - seterrorobj(L, status, oldtop); - L->ci = ci; - L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ - L->nny = 0; /* should be zero to be yieldable */ - luaD_shrinkstack(L); - L->errfunc = ci->u.c.old_errfunc; - return 1; /* continue running the coroutine */ +static int recover(lua_State* L, int status) +{ + StkId oldtop; + CallInfo* ci = findpcall(L); + if (ci == NULL) return 0; /* no recovery point */ + /* "finish" luaD_pcall */ + oldtop = restorestack(L, ci->extra); + luaF_close(L, oldtop); + seterrorobj(L, status, oldtop); + L->ci = ci; + L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ + L->nny = 0; /* should be zero to be yieldable */ + luaD_shrinkstack(L); + L->errfunc = ci->u.c.old_errfunc; + return 1; /* continue running the coroutine */ } @@ -600,12 +673,13 @@ static int recover (lua_State *L, int status) { ** of the coroutine itself. (Such errors should not be handled by any ** coroutine error handler and should not kill the coroutine.) */ -static int resume_error (lua_State *L, const char *msg, int narg) { - L->top -= narg; /* remove args from the stack */ - setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ - api_incr_top(L); - lua_unlock(L); - return LUA_ERRRUN; +static int resume_error(lua_State* L, const char* msg, int narg) +{ + L->top -= narg; /* remove args from the stack */ + setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ + api_incr_top(L); + lua_unlock(L); + return LUA_ERRRUN; } @@ -616,187 +690,224 @@ static int resume_error (lua_State *L, const char *msg, int narg) { ** function), plus erroneous cases: non-suspended coroutine or dead ** coroutine. */ -static void resume (lua_State *L, void *ud) { - int n = *(cast(int*, ud)); /* number of arguments */ - StkId firstArg = L->top - n; /* first argument */ - CallInfo *ci = L->ci; - if (L->status == LUA_OK) { /* starting a coroutine? */ - if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ - luaV_execute(L); /* call it */ - } - else { /* resuming from previous yield */ - lua_assert(L->status == LUA_YIELD); - L->status = LUA_OK; /* mark that it is running (again) */ - ci->func = restorestack(L, ci->extra); - if (isLua(ci)) /* yielded inside a hook? */ - luaV_execute(L); /* just continue running Lua code */ - else { /* 'common' yield */ - if (ci->u.c.k != NULL) { /* does it have a continuation function? */ - lua_unlock(L); - n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ - lua_lock(L); - api_checknelems(L, n); - firstArg = L->top - n; /* yield results come from continuation */ - } - luaD_poscall(L, ci, firstArg, n); /* finish 'luaD_precall' */ - } - unroll(L, NULL); /* run continuation */ - } +static void resume(lua_State* L, void* ud) +{ + int n = *(cast(int*, ud)); /* number of arguments */ + StkId firstArg = L->top - n; /* first argument */ + CallInfo* ci = L->ci; + if (L->status == LUA_OK) + { + /* starting a coroutine? */ + if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ + luaV_execute(L); /* call it */ + } + else + { + /* resuming from previous yield */ + lua_assert(L->status == LUA_YIELD); + L->status = LUA_OK; /* mark that it is running (again) */ + ci->func = restorestack(L, ci->extra); + if (isLua(ci)) /* yielded inside a hook? */ + luaV_execute(L); /* just continue running Lua code */ + else + { + /* 'common' yield */ + if (ci->u.c.k != NULL) + { + /* does it have a continuation function? */ + lua_unlock(L); + n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ + lua_lock(L); + api_checknelems(L, n); + firstArg = L->top - n; /* yield results come from continuation */ + } + luaD_poscall(L, ci, firstArg, n); /* finish 'luaD_precall' */ + } + unroll(L, NULL); /* run continuation */ + } } -LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { - int status; - unsigned short oldnny = L->nny; /* save "number of non-yieldable" calls */ - lua_lock(L); - if (L->status == LUA_OK) { /* may be starting a coroutine */ - if (L->ci != &L->base_ci) /* not in base level? */ - return resume_error(L, "cannot resume non-suspended coroutine", nargs); - } - else if (L->status != LUA_YIELD) - return resume_error(L, "cannot resume dead coroutine", nargs); - L->nCcalls = (from) ? from->nCcalls + 1 : 1; - if (L->nCcalls >= LUAI_MAXCCALLS) - return resume_error(L, "C stack overflow", nargs); - luai_userstateresume(L, nargs); - L->nny = 0; /* allow yields */ - api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); - status = luaD_rawrunprotected(L, resume, &nargs); - if (status == -1) /* error calling 'lua_resume'? */ - status = LUA_ERRRUN; - else { /* continue running after recoverable errors */ - while (errorstatus(status) && recover(L, status)) { - /* unroll continuation */ - status = luaD_rawrunprotected(L, unroll, &status); - } - if (errorstatus(status)) { /* unrecoverable error? */ - L->status = cast_byte(status); /* mark thread as 'dead' */ - seterrorobj(L, status, L->top); /* push error message */ - L->ci->top = L->top; - } - else lua_assert(status == L->status); /* normal end or yield */ - } - L->nny = oldnny; /* restore 'nny' */ - L->nCcalls--; - lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); - lua_unlock(L); - return status; +LUA_API int lua_resume(lua_State* L, lua_State* from, int nargs) +{ + int status; + unsigned short oldnny = L->nny; /* save "number of non-yieldable" calls */ + lua_lock(L); + if (L->status == LUA_OK) + { + /* may be starting a coroutine */ + if (L->ci != &L->base_ci) /* not in base level? */ + return resume_error(L, "cannot resume non-suspended coroutine", nargs); + } + else if (L->status != LUA_YIELD) + return resume_error(L, "cannot resume dead coroutine", nargs); + L->nCcalls = (from) ? from->nCcalls + 1 : 1; + if (L->nCcalls >= LUAI_MAXCCALLS) + return resume_error(L, "C stack overflow", nargs); + luai_userstateresume(L, nargs); + L->nny = 0; /* allow yields */ + api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); + status = luaD_rawrunprotected(L, resume, &nargs); + if (status == -1) /* error calling 'lua_resume'? */ + status = LUA_ERRRUN; + else + { + /* continue running after recoverable errors */ + while (errorstatus(status) && recover(L, status)) + { + /* unroll continuation */ + status = luaD_rawrunprotected(L, unroll, &status); + } + if (errorstatus(status)) + { + /* unrecoverable error? */ + L->status = cast_byte(status); /* mark thread as 'dead' */ + seterrorobj(L, status, L->top); /* push error message */ + L->ci->top = L->top; + } + else + lua_assert(status == L->status); /* normal end or yield */ + } + L->nny = oldnny; /* restore 'nny' */ + L->nCcalls--; + lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); + lua_unlock(L); + return status; } -LUA_API int lua_isyieldable (lua_State *L) { - return (L->nny == 0); +LUA_API int lua_isyieldable(lua_State* L) +{ + return (L->nny == 0); } -LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, - lua_KFunction k) { - CallInfo *ci = L->ci; - luai_userstateyield(L, nresults); - lua_lock(L); - api_checknelems(L, nresults); - if (L->nny > 0) { - if (L != G(L)->mainthread) - luaG_runerror(L, "attempt to yield across a C-call boundary"); - else - luaG_runerror(L, "attempt to yield from outside a coroutine"); - } - L->status = LUA_YIELD; - ci->extra = savestack(L, ci->func); /* save current 'func' */ - if (isLua(ci)) { /* inside a hook? */ - api_check(L, k == NULL, "hooks cannot continue after yielding"); - } - else { - if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ - ci->u.c.ctx = ctx; /* save context */ - ci->func = L->top - nresults - 1; /* protect stack below results */ - luaD_throw(L, LUA_YIELD); - } - lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ - lua_unlock(L); - return 0; /* return to 'luaD_hook' */ +LUA_API int lua_yieldk(lua_State* L, int nresults, lua_KContext ctx, + lua_KFunction k) +{ + CallInfo* ci = L->ci; + luai_userstateyield(L, nresults); + lua_lock(L); + api_checknelems(L, nresults); + if (L->nny > 0) + { + if (L != G(L)->mainthread) + luaG_runerror(L, "attempt to yield across a C-call boundary"); + else + luaG_runerror(L, "attempt to yield from outside a coroutine"); + } + L->status = LUA_YIELD; + ci->extra = savestack(L, ci->func); /* save current 'func' */ + if (isLua(ci)) + { + /* inside a hook? */ + api_check(L, k == NULL, "hooks cannot continue after yielding"); + } + else + { + if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ + ci->u.c.ctx = ctx; /* save context */ + ci->func = L->top - nresults - 1; /* protect stack below results */ + luaD_throw(L, LUA_YIELD); + } + lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ + lua_unlock(L); + return 0; /* return to 'luaD_hook' */ } -int luaD_pcall (lua_State *L, Pfunc func, void *u, - ptrdiff_t old_top, ptrdiff_t ef) { - int status; - CallInfo *old_ci = L->ci; - lu_byte old_allowhooks = L->allowhook; - unsigned short old_nny = L->nny; - ptrdiff_t old_errfunc = L->errfunc; - L->errfunc = ef; - status = luaD_rawrunprotected(L, func, u); - if (status != LUA_OK) { /* an error occurred? */ - StkId oldtop = restorestack(L, old_top); - luaF_close(L, oldtop); /* close possible pending closures */ - seterrorobj(L, status, oldtop); - L->ci = old_ci; - L->allowhook = old_allowhooks; - L->nny = old_nny; - luaD_shrinkstack(L); - } - L->errfunc = old_errfunc; - return status; +int luaD_pcall(lua_State* L, Pfunc func, void* u, + ptrdiff_t old_top, ptrdiff_t ef) +{ + int status; + CallInfo* old_ci = L->ci; + lu_byte old_allowhooks = L->allowhook; + unsigned short old_nny = L->nny; + ptrdiff_t old_errfunc = L->errfunc; + L->errfunc = ef; + status = luaD_rawrunprotected(L, func, u); + if (status != LUA_OK) + { + /* an error occurred? */ + StkId oldtop = restorestack(L, old_top); + luaF_close(L, oldtop); /* close possible pending closures */ + seterrorobj(L, status, oldtop); + L->ci = old_ci; + L->allowhook = old_allowhooks; + L->nny = old_nny; + luaD_shrinkstack(L); + } + L->errfunc = old_errfunc; + return status; } - /* ** Execute a protected parser. */ -struct SParser { /* data to 'f_parser' */ - ZIO *z; - Mbuffer buff; /* dynamic structure used by the scanner */ - Dyndata dyd; /* dynamic structures used by the parser */ - const char *mode; - const char *name; +struct SParser +{ + /* data to 'f_parser' */ + ZIO* z; + Mbuffer buff; /* dynamic structure used by the scanner */ + Dyndata dyd; /* dynamic structures used by the parser */ + const char* mode; + const char* name; }; -static void checkmode (lua_State *L, const char *mode, const char *x) { - if (mode && strchr(mode, x[0]) == NULL) { - luaO_pushfstring(L, - "attempt to load a %s chunk (mode is '%s')", x, mode); - luaD_throw(L, LUA_ERRSYNTAX); - } +static void checkmode(lua_State* L, const char* mode, const char* x) +{ + if (mode && strchr(mode, x[0]) == NULL) + { + luaO_pushfstring(L, + "attempt to load a %s chunk (mode is '%s')", x, mode); + luaD_throw(L, LUA_ERRSYNTAX); + } } -static void f_parser (lua_State *L, void *ud) { - LClosure *cl; - struct SParser *p = cast(struct SParser *, ud); - int c = zgetc(p->z); /* read first character */ - if (c == LUA_SIGNATURE[0]) { - checkmode(L, p->mode, "binary"); - cl = luaU_undump(L, p->z, p->name); - } - else { - checkmode(L, p->mode, "text"); - cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); - } - lua_assert(cl->nupvalues == cl->p->sizeupvalues); - luaF_initupvals(L, cl); +static void f_parser(lua_State* L, void* ud) +{ + LClosure* cl; + struct SParser* p = cast(struct SParser *, ud); + int c = zgetc(p->z); /* read first character */ + if (c == LUA_SIGNATURE[0]) + { + checkmode(L, p->mode, "binary"); + cl = luaU_undump(L, p->z, p->name); + } + else + { + checkmode(L, p->mode, "text"); + cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); + } + lua_assert(cl->nupvalues == cl->p->sizeupvalues); + luaF_initupvals(L, cl); } -int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, - const char *mode) { - struct SParser p; - int status; - L->nny++; /* cannot yield during parsing */ - p.z = z; p.name = name; p.mode = mode; - p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; - p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; - p.dyd.label.arr = NULL; p.dyd.label.size = 0; - luaZ_initbuffer(L, &p.buff); - status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); - luaZ_freebuffer(L, &p.buff); - luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); - luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); - luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); - L->nny--; - return status; +int luaD_protectedparser(lua_State* L, ZIO* z, const char* name, + const char* mode) +{ + struct SParser p; + int status; + L->nny++; /* cannot yield during parsing */ + p.z = z; + p.name = name; + p.mode = mode; + p.dyd.actvar.arr = NULL; + p.dyd.actvar.size = 0; + p.dyd.gt.arr = NULL; + p.dyd.gt.size = 0; + p.dyd.label.arr = NULL; + p.dyd.label.size = 0; + luaZ_initbuffer(L, &p.buff); + status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); + luaZ_freebuffer(L, &p.buff); + luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); + luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); + luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); + L->nny--; + return status; } - - diff --git a/Lua/ldo.h b/Lua/ldo.h index 4f5d51c..8685894 100644 --- a/Lua/ldo.h +++ b/Lua/ldo.h @@ -28,31 +28,29 @@ #define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0) - #define savestack(L,p) ((char *)(p) - (char *)L->stack) #define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) /* type of protected functions, to be ran by 'runprotected' */ -typedef void (*Pfunc) (lua_State *L, void *ud); +typedef void (*Pfunc)(lua_State* L, void* ud); -LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, - const char *mode); -LUAI_FUNC void luaD_hook (lua_State *L, int event, int line); -LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); -LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); -LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); -LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, - ptrdiff_t oldtop, ptrdiff_t ef); -LUAI_FUNC int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, - int nres); -LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); -LUAI_FUNC void luaD_growstack (lua_State *L, int n); -LUAI_FUNC void luaD_shrinkstack (lua_State *L); -LUAI_FUNC void luaD_inctop (lua_State *L); +LUAI_FUNC int luaD_protectedparser(lua_State* L, ZIO* z, const char* name, + const char* mode); +LUAI_FUNC void luaD_hook(lua_State* L, int event, int line); +LUAI_FUNC int luaD_precall(lua_State* L, StkId func, int nresults); +LUAI_FUNC void luaD_call(lua_State* L, StkId func, int nResults); +LUAI_FUNC void luaD_callnoyield(lua_State* L, StkId func, int nResults); +LUAI_FUNC int luaD_pcall(lua_State* L, Pfunc func, void* u, + ptrdiff_t oldtop, ptrdiff_t ef); +LUAI_FUNC int luaD_poscall(lua_State* L, CallInfo* ci, StkId firstResult, + int nres); +LUAI_FUNC void luaD_reallocstack(lua_State* L, int newsize); +LUAI_FUNC void luaD_growstack(lua_State* L, int n); +LUAI_FUNC void luaD_shrinkstack(lua_State* L); +LUAI_FUNC void luaD_inctop(lua_State* L); -LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); -LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); +LUAI_FUNC l_noret luaD_throw(lua_State* L, int errcode); +LUAI_FUNC int luaD_rawrunprotected(lua_State* L, Pfunc f, void* ud); #endif - diff --git a/Lua/ldump.c b/Lua/ldump.c index 016e300..ae6b4fb 100644 --- a/Lua/ldump.c +++ b/Lua/ldump.c @@ -19,12 +19,13 @@ #include "lundump.h" -typedef struct { - lua_State *L; - lua_Writer writer; - void *data; - int strip; - int status; +typedef struct +{ + lua_State* L; + lua_Writer writer; + void* data; + int strip; + int status; } DumpState; @@ -37,179 +38,199 @@ typedef struct { #define DumpLiteral(s,D) DumpBlock(s, sizeof(s) - sizeof(char), D) -static void DumpBlock (const void *b, size_t size, DumpState *D) { - if (D->status == 0 && size > 0) { - lua_unlock(D->L); - D->status = (*D->writer)(D->L, b, size, D->data); - lua_lock(D->L); - } +static void DumpBlock(const void* b, size_t size, DumpState* D) +{ + if (D->status == 0 && size > 0) + { + lua_unlock(D->L); + D->status = (*D->writer)(D->L, b, size, D->data); + lua_lock(D->L); + } } #define DumpVar(x,D) DumpVector(&x,1,D) -static void DumpByte (int y, DumpState *D) { - lu_byte x = (lu_byte)y; - DumpVar(x, D); +static void DumpByte(int y, DumpState* D) +{ + lu_byte x = (lu_byte)y; + DumpVar(x, D); } -static void DumpInt (int x, DumpState *D) { - DumpVar(x, D); +static void DumpInt(int x, DumpState* D) +{ + DumpVar(x, D); } -static void DumpNumber (lua_Number x, DumpState *D) { - DumpVar(x, D); +static void DumpNumber(lua_Number x, DumpState* D) +{ + DumpVar(x, D); } -static void DumpInteger (lua_Integer x, DumpState *D) { - DumpVar(x, D); +static void DumpInteger(lua_Integer x, DumpState* D) +{ + DumpVar(x, D); } -static void DumpString (const TString *s, DumpState *D) { - if (s == NULL) - DumpByte(0, D); - else { - size_t size = tsslen(s) + 1; /* include trailing '\0' */ - const char *str = getstr(s); - if (size < 0xFF) - DumpByte(cast_int(size), D); - else { - DumpByte(0xFF, D); - DumpVar(size, D); - } - DumpVector(str, size - 1, D); /* no need to save '\0' */ - } +static void DumpString(const TString* s, DumpState* D) +{ + if (s == NULL) + DumpByte(0, D); + else + { + size_t size = tsslen(s) + 1; /* include trailing '\0' */ + const char* str = getstr(s); + if (size < 0xFF) + DumpByte(cast_int(size), D); + else + { + DumpByte(0xFF, D); + DumpVar(size, D); + } + DumpVector(str, size - 1, D); /* no need to save '\0' */ + } } -static void DumpCode (const Proto *f, DumpState *D) { - DumpInt(f->sizecode, D); - DumpVector(f->code, f->sizecode, D); +static void DumpCode(const Proto* f, DumpState* D) +{ + DumpInt(f->sizecode, D); + DumpVector(f->code, f->sizecode, D); } -static void DumpFunction(const Proto *f, TString *psource, DumpState *D); +static void DumpFunction(const Proto* f, TString* psource, DumpState* D); -static void DumpConstants (const Proto *f, DumpState *D) { - int i; - int n = f->sizek; - DumpInt(n, D); - for (i = 0; i < n; i++) { - const TValue *o = &f->k[i]; - DumpByte(ttype(o), D); - switch (ttype(o)) { - case LUA_TNIL: - break; - case LUA_TBOOLEAN: - DumpByte(bvalue(o), D); - break; - case LUA_TNUMFLT: - DumpNumber(fltvalue(o), D); - break; - case LUA_TNUMINT: - DumpInteger(ivalue(o), D); - break; - case LUA_TSHRSTR: - case LUA_TLNGSTR: - DumpString(tsvalue(o), D); - break; - default: - lua_assert(0); - } - } +static void DumpConstants(const Proto* f, DumpState* D) +{ + int i; + int n = f->sizek; + DumpInt(n, D); + for (i = 0; i < n; i++) + { + const TValue* o = &f->k[i]; + DumpByte(ttype(o), D); + switch (ttype(o)) + { + case LUA_TNIL: + break; + case LUA_TBOOLEAN: + DumpByte(bvalue(o), D); + break; + case LUA_TNUMFLT: + DumpNumber(fltvalue(o), D); + break; + case LUA_TNUMINT: + DumpInteger(ivalue(o), D); + break; + case LUA_TSHRSTR: + case LUA_TLNGSTR: + DumpString(tsvalue(o), D); + break; + default: + lua_assert(0); + } + } } -static void DumpProtos (const Proto *f, DumpState *D) { - int i; - int n = f->sizep; - DumpInt(n, D); - for (i = 0; i < n; i++) - DumpFunction(f->p[i], f->source, D); +static void DumpProtos(const Proto* f, DumpState* D) +{ + int i; + int n = f->sizep; + DumpInt(n, D); + for (i = 0; i < n; i++) + DumpFunction(f->p[i], f->source, D); } -static void DumpUpvalues (const Proto *f, DumpState *D) { - int i, n = f->sizeupvalues; - DumpInt(n, D); - for (i = 0; i < n; i++) { - DumpByte(f->upvalues[i].instack, D); - DumpByte(f->upvalues[i].idx, D); - } +static void DumpUpvalues(const Proto* f, DumpState* D) +{ + int i, n = f->sizeupvalues; + DumpInt(n, D); + for (i = 0; i < n; i++) + { + DumpByte(f->upvalues[i].instack, D); + DumpByte(f->upvalues[i].idx, D); + } } -static void DumpDebug (const Proto *f, DumpState *D) { - int i, n; - n = (D->strip) ? 0 : f->sizelineinfo; - DumpInt(n, D); - DumpVector(f->lineinfo, n, D); - n = (D->strip) ? 0 : f->sizelocvars; - DumpInt(n, D); - for (i = 0; i < n; i++) { - DumpString(f->locvars[i].varname, D); - DumpInt(f->locvars[i].startpc, D); - DumpInt(f->locvars[i].endpc, D); - } - n = (D->strip) ? 0 : f->sizeupvalues; - DumpInt(n, D); - for (i = 0; i < n; i++) - DumpString(f->upvalues[i].name, D); +static void DumpDebug(const Proto* f, DumpState* D) +{ + int i, n; + n = (D->strip) ? 0 : f->sizelineinfo; + DumpInt(n, D); + DumpVector(f->lineinfo, n, D); + n = (D->strip) ? 0 : f->sizelocvars; + DumpInt(n, D); + for (i = 0; i < n; i++) + { + DumpString(f->locvars[i].varname, D); + DumpInt(f->locvars[i].startpc, D); + DumpInt(f->locvars[i].endpc, D); + } + n = (D->strip) ? 0 : f->sizeupvalues; + DumpInt(n, D); + for (i = 0; i < n; i++) + DumpString(f->upvalues[i].name, D); } -static void DumpFunction (const Proto *f, TString *psource, DumpState *D) { - if (D->strip || f->source == psource) - DumpString(NULL, D); /* no debug info or same source as its parent */ - else - DumpString(f->source, D); - DumpInt(f->linedefined, D); - DumpInt(f->lastlinedefined, D); - DumpByte(f->numparams, D); - DumpByte(f->is_vararg, D); - DumpByte(f->maxstacksize, D); - DumpCode(f, D); - DumpConstants(f, D); - DumpUpvalues(f, D); - DumpProtos(f, D); - DumpDebug(f, D); +static void DumpFunction(const Proto* f, TString* psource, DumpState* D) +{ + if (D->strip || f->source == psource) + DumpString(NULL, D); /* no debug info or same source as its parent */ + else + DumpString(f->source, D); + DumpInt(f->linedefined, D); + DumpInt(f->lastlinedefined, D); + DumpByte(f->numparams, D); + DumpByte(f->is_vararg, D); + DumpByte(f->maxstacksize, D); + DumpCode(f, D); + DumpConstants(f, D); + DumpUpvalues(f, D); + DumpProtos(f, D); + DumpDebug(f, D); } -static void DumpHeader (DumpState *D) { - DumpLiteral(LUA_SIGNATURE, D); - DumpByte(LUAC_VERSION, D); - DumpByte(LUAC_FORMAT, D); - DumpLiteral(LUAC_DATA, D); - DumpByte(sizeof(int), D); - DumpByte(sizeof(size_t), D); - DumpByte(sizeof(Instruction), D); - DumpByte(sizeof(lua_Integer), D); - DumpByte(sizeof(lua_Number), D); - DumpInteger(LUAC_INT, D); - DumpNumber(LUAC_NUM, D); +static void DumpHeader(DumpState* D) +{ + DumpLiteral(LUA_SIGNATURE, D); + DumpByte(LUAC_VERSION, D); + DumpByte(LUAC_FORMAT, D); + DumpLiteral(LUAC_DATA, D); + DumpByte(sizeof(int), D); + DumpByte(sizeof(size_t), D); + DumpByte(sizeof(Instruction), D); + DumpByte(sizeof(lua_Integer), D); + DumpByte(sizeof(lua_Number), D); + DumpInteger(LUAC_INT, D); + DumpNumber(LUAC_NUM, D); } /* ** dump Lua function as precompiled chunk */ -int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, - int strip) { - DumpState D; - D.L = L; - D.writer = w; - D.data = data; - D.strip = strip; - D.status = 0; - DumpHeader(&D); - DumpByte(f->sizeupvalues, &D); - DumpFunction(f, NULL, &D); - return D.status; +int luaU_dump(lua_State* L, const Proto* f, lua_Writer w, void* data, + int strip) +{ + DumpState D; + D.L = L; + D.writer = w; + D.data = data; + D.strip = strip; + D.status = 0; + DumpHeader(&D); + DumpByte(f->sizeupvalues, &D); + DumpFunction(f, NULL, &D); + return D.status; } - diff --git a/Lua/lfunc.c b/Lua/lfunc.c index 67967da..38f1f54 100644 --- a/Lua/lfunc.c +++ b/Lua/lfunc.c @@ -21,115 +21,127 @@ #include "lstate.h" - -CClosure *luaF_newCclosure (lua_State *L, int n) { - GCObject *o = luaC_newobj(L, LUA_TCCL, sizeCclosure(n)); - CClosure *c = gco2ccl(o); - c->nupvalues = cast_byte(n); - return c; +CClosure* luaF_newCclosure(lua_State* L, int n) +{ + GCObject* o = luaC_newobj(L, LUA_TCCL, sizeCclosure(n)); + CClosure* c = gco2ccl(o); + c->nupvalues = cast_byte(n); + return c; } -LClosure *luaF_newLclosure (lua_State *L, int n) { - GCObject *o = luaC_newobj(L, LUA_TLCL, sizeLclosure(n)); - LClosure *c = gco2lcl(o); - c->p = NULL; - c->nupvalues = cast_byte(n); - while (n--) c->upvals[n] = NULL; - return c; +LClosure* luaF_newLclosure(lua_State* L, int n) +{ + GCObject* o = luaC_newobj(L, LUA_TLCL, sizeLclosure(n)); + LClosure* c = gco2lcl(o); + c->p = NULL; + c->nupvalues = cast_byte(n); + while (n--) c->upvals[n] = NULL; + return c; } /* ** fill a closure with new closed upvalues */ -void luaF_initupvals (lua_State *L, LClosure *cl) { - int i; - for (i = 0; i < cl->nupvalues; i++) { - UpVal *uv = luaM_new(L, UpVal); - uv->refcount = 1; - uv->v = &uv->u.value; /* make it closed */ - setnilvalue(uv->v); - cl->upvals[i] = uv; - } +void luaF_initupvals(lua_State* L, LClosure* cl) +{ + int i; + for (i = 0; i < cl->nupvalues; i++) + { + UpVal* uv = luaM_new(L, UpVal); + uv->refcount = 1; + uv->v = &uv->u.value; /* make it closed */ + setnilvalue(uv->v); + cl->upvals[i] = uv; + } } -UpVal *luaF_findupval (lua_State *L, StkId level) { - UpVal **pp = &L->openupval; - UpVal *p; - UpVal *uv; - lua_assert(isintwups(L) || L->openupval == NULL); - while (*pp != NULL && (p = *pp)->v >= level) { - lua_assert(upisopen(p)); - if (p->v == level) /* found a corresponding upvalue? */ - return p; /* return it */ - pp = &p->u.open.next; - } - /* not found: create a new upvalue */ - uv = luaM_new(L, UpVal); - uv->refcount = 0; - uv->u.open.next = *pp; /* link it to list of open upvalues */ - uv->u.open.touched = 1; - *pp = uv; - uv->v = level; /* current value lives in the stack */ - if (!isintwups(L)) { /* thread not in list of threads with upvalues? */ - L->twups = G(L)->twups; /* link it to the list */ - G(L)->twups = L; - } - return uv; +UpVal* luaF_findupval(lua_State* L, StkId level) +{ + UpVal** pp = &L->openupval; + UpVal* p; + UpVal* uv; + lua_assert(isintwups(L) || L->openupval == NULL); + while (*pp != NULL && (p = *pp)->v >= level) + { + lua_assert(upisopen(p)); + if (p->v == level) /* found a corresponding upvalue? */ + return p; /* return it */ + pp = &p->u.open.next; + } + /* not found: create a new upvalue */ + uv = luaM_new(L, UpVal); + uv->refcount = 0; + uv->u.open.next = *pp; /* link it to list of open upvalues */ + uv->u.open.touched = 1; + *pp = uv; + uv->v = level; /* current value lives in the stack */ + if (!isintwups(L)) + { + /* thread not in list of threads with upvalues? */ + L->twups = G(L)->twups; /* link it to the list */ + G(L)->twups = L; + } + return uv; } -void luaF_close (lua_State *L, StkId level) { - UpVal *uv; - while (L->openupval != NULL && (uv = L->openupval)->v >= level) { - lua_assert(upisopen(uv)); - L->openupval = uv->u.open.next; /* remove from 'open' list */ - if (uv->refcount == 0) /* no references? */ - luaM_free(L, uv); /* free upvalue */ - else { - setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ - uv->v = &uv->u.value; /* now current value lives here */ - luaC_upvalbarrier(L, uv); - } - } +void luaF_close(lua_State* L, StkId level) +{ + UpVal* uv; + while (L->openupval != NULL && (uv = L->openupval)->v >= level) + { + lua_assert(upisopen(uv)); + L->openupval = uv->u.open.next; /* remove from 'open' list */ + if (uv->refcount == 0) /* no references? */ + luaM_free(L, uv); /* free upvalue */ + else + { + setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ + uv->v = &uv->u.value; /* now current value lives here */ + luaC_upvalbarrier(L, uv); + } + } } -Proto *luaF_newproto (lua_State *L) { - GCObject *o = luaC_newobj(L, LUA_TPROTO, sizeof(Proto)); - Proto *f = gco2p(o); - f->k = NULL; - f->sizek = 0; - f->p = NULL; - f->sizep = 0; - f->code = NULL; - f->cache = NULL; - f->sizecode = 0; - f->lineinfo = NULL; - f->sizelineinfo = 0; - f->upvalues = NULL; - f->sizeupvalues = 0; - f->numparams = 0; - f->is_vararg = 0; - f->maxstacksize = 0; - f->locvars = NULL; - f->sizelocvars = 0; - f->linedefined = 0; - f->lastlinedefined = 0; - f->source = NULL; - return f; +Proto* luaF_newproto(lua_State* L) +{ + GCObject* o = luaC_newobj(L, LUA_TPROTO, sizeof(Proto)); + Proto* f = gco2p(o); + f->k = NULL; + f->sizek = 0; + f->p = NULL; + f->sizep = 0; + f->code = NULL; + f->cache = NULL; + f->sizecode = 0; + f->lineinfo = NULL; + f->sizelineinfo = 0; + f->upvalues = NULL; + f->sizeupvalues = 0; + f->numparams = 0; + f->is_vararg = 0; + f->maxstacksize = 0; + f->locvars = NULL; + f->sizelocvars = 0; + f->linedefined = 0; + f->lastlinedefined = 0; + f->source = NULL; + return f; } -void luaF_freeproto (lua_State *L, Proto *f) { - luaM_freearray(L, f->code, f->sizecode); - luaM_freearray(L, f->p, f->sizep); - luaM_freearray(L, f->k, f->sizek); - luaM_freearray(L, f->lineinfo, f->sizelineinfo); - luaM_freearray(L, f->locvars, f->sizelocvars); - luaM_freearray(L, f->upvalues, f->sizeupvalues); - luaM_free(L, f); +void luaF_freeproto(lua_State* L, Proto* f) +{ + luaM_freearray(L, f->code, f->sizecode); + luaM_freearray(L, f->p, f->sizep); + luaM_freearray(L, f->k, f->sizek); + luaM_freearray(L, f->lineinfo, f->sizelineinfo); + luaM_freearray(L, f->locvars, f->sizelocvars); + luaM_freearray(L, f->upvalues, f->sizeupvalues); + luaM_free(L, f); } @@ -137,15 +149,18 @@ void luaF_freeproto (lua_State *L, Proto *f) { ** Look for n-th local variable at line 'line' in function 'func'. ** Returns NULL if not found. */ -const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { - int i; - for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { - if (pc < f->locvars[i].endpc) { /* is variable active? */ - local_number--; - if (local_number == 0) - return getstr(f->locvars[i].varname); - } - } - return NULL; /* not found */ +const char* luaF_getlocalname(const Proto* f, int local_number, int pc) +{ + int i; + for (i = 0; i < f->sizelocvars && f->locvars[i].startpc <= pc; i++) + { + if (pc < f->locvars[i].endpc) + { + /* is variable active? */ + local_number--; + if (local_number == 0) + return getstr(f->locvars[i].varname); + } + } + return NULL; /* not found */ } - diff --git a/Lua/lfunc.h b/Lua/lfunc.h index 2eeb0d5..4720113 100644 --- a/Lua/lfunc.h +++ b/Lua/lfunc.h @@ -32,30 +32,35 @@ /* ** Upvalues for Lua closures */ -struct UpVal { - TValue *v; /* points to stack or to its own value */ - lu_mem refcount; /* reference counter */ - union { - struct { /* (when open) */ - UpVal *next; /* linked list */ - int touched; /* mark to avoid cycles with dead threads */ - } open; - TValue value; /* the value (when closed) */ - } u; +struct UpVal +{ + TValue* v; /* points to stack or to its own value */ + lu_mem refcount; /* reference counter */ + union + { + struct + { + /* (when open) */ + UpVal* next; /* linked list */ + int touched; /* mark to avoid cycles with dead threads */ + } open; + + TValue value; /* the value (when closed) */ + } u; }; #define upisopen(up) ((up)->v != &(up)->u.value) -LUAI_FUNC Proto *luaF_newproto (lua_State *L); -LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems); -LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems); -LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); -LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); -LUAI_FUNC void luaF_close (lua_State *L, StkId level); -LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); -LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, - int pc); +LUAI_FUNC Proto* luaF_newproto(lua_State* L); +LUAI_FUNC CClosure* luaF_newCclosure(lua_State* L, int nelems); +LUAI_FUNC LClosure* luaF_newLclosure(lua_State* L, int nelems); +LUAI_FUNC void luaF_initupvals(lua_State* L, LClosure* cl); +LUAI_FUNC UpVal* luaF_findupval(lua_State* L, StkId level); +LUAI_FUNC void luaF_close(lua_State* L, StkId level); +LUAI_FUNC void luaF_freeproto(lua_State* L, Proto* f); +LUAI_FUNC const char* luaF_getlocalname(const Proto* func, int local_number, + int pc); #endif diff --git a/Lua/lgc.c b/Lua/lgc.c index ba2c19e..d0aa5e6 100644 --- a/Lua/lgc.c +++ b/Lua/lgc.c @@ -91,7 +91,7 @@ */ #define markobjectN(g,t) { if (t) markobject(g,t); } -static void reallymarkobject (global_State *g, GCObject *o); +static void reallymarkobject(global_State* g, GCObject* o); /* @@ -122,10 +122,11 @@ static void reallymarkobject (global_State *g, GCObject *o); ** associated nil value is enough to signal that the entry is logically ** empty. */ -static void removeentry (Node *n) { - lua_assert(ttisnil(gval(n))); - if (valiswhite(gkey(n))) - setdeadvalue(wgkey(n)); /* unused and unmarked key; remove it */ +static void removeentry(Node* n) +{ + lua_assert(ttisnil(gval(n))); + if (valiswhite(gkey(n))) + setdeadvalue(wgkey(n)); /* unused and unmarked key; remove it */ } @@ -136,13 +137,15 @@ static void removeentry (Node *n) { ** other objects: if really collected, cannot keep them; for objects ** being finalized, keep them in keys, but not in values */ -static int iscleared (global_State *g, const TValue *o) { - if (!iscollectable(o)) return 0; - else if (ttisstring(o)) { - markobject(g, tsvalue(o)); /* strings are 'values', so are never weak */ - return 0; - } - else return iswhite(gcvalue(o)); +static int iscleared(global_State* g, const TValue* o) +{ + if (!iscollectable(o)) return 0; + else if (ttisstring(o)) + { + markobject(g, tsvalue(o)); /* strings are 'values', so are never weak */ + return 0; + } + else return iswhite(gcvalue(o)); } @@ -152,15 +155,18 @@ static int iscleared (global_State *g, const TValue *o) { ** object to white [sweep it] to avoid other barrier calls for this ** same object.) */ -void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { - global_State *g = G(L); - lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); - if (keepinvariant(g)) /* must keep invariant? */ - reallymarkobject(g, v); /* restore invariant */ - else { /* sweep phase */ - lua_assert(issweepphase(g)); - makewhite(g, o); /* mark main obj. as white to avoid other barriers */ - } +void luaC_barrier_(lua_State* L, GCObject* o, GCObject* v) +{ + global_State* g = G(L); + lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); + if (keepinvariant(g)) /* must keep invariant? */ + reallymarkobject(g, v); /* restore invariant */ + else + { + /* sweep phase */ + lua_assert(issweepphase(g)); + makewhite(g, o); /* mark main obj. as white to avoid other barriers */ + } } @@ -168,11 +174,12 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { ** barrier that moves collector backward, that is, mark the black object ** pointing to a white object as gray again. */ -void luaC_barrierback_ (lua_State *L, Table *t) { - global_State *g = G(L); - lua_assert(isblack(t) && !isdead(g, t)); - black2gray(t); /* make table gray (again) */ - linkgclist(t, g->grayagain); +void luaC_barrierback_(lua_State* L, Table* t) +{ + global_State* g = G(L); + lua_assert(isblack(t) && !isdead(g, t)); + black2gray(t); /* make table gray (again) */ + linkgclist(t, g->grayagain); } @@ -182,22 +189,24 @@ void luaC_barrierback_ (lua_State *L, Table *t) { ** closures pointing to it. So, we assume that the object being assigned ** must be marked. */ -void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) { - global_State *g = G(L); - GCObject *o = gcvalue(uv->v); - lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */ - if (keepinvariant(g)) - markobject(g, o); +void luaC_upvalbarrier_(lua_State* L, UpVal* uv) +{ + global_State* g = G(L); + GCObject* o = gcvalue(uv->v); + lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */ + if (keepinvariant(g)) + markobject(g, o); } -void luaC_fix (lua_State *L, GCObject *o) { - global_State *g = G(L); - lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */ - white2gray(o); /* they will be gray forever */ - g->allgc = o->next; /* remove object from 'allgc' list */ - o->next = g->fixedgc; /* link it to 'fixedgc' list */ - g->fixedgc = o; +void luaC_fix(lua_State* L, GCObject* o) +{ + global_State* g = G(L); + lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */ + white2gray(o); /* they will be gray forever */ + g->allgc = o->next; /* remove object from 'allgc' list */ + o->next = g->fixedgc; /* link it to 'fixedgc' list */ + g->fixedgc = o; } @@ -205,20 +214,20 @@ void luaC_fix (lua_State *L, GCObject *o) { ** create a new collectable object (with given type and size) and link ** it to 'allgc' list. */ -GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { - global_State *g = G(L); - GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); - o->marked = luaC_white(g); - o->tt = tt; - o->next = g->allgc; - g->allgc = o; - return o; +GCObject* luaC_newobj(lua_State* L, int tt, size_t sz) +{ + global_State* g = G(L); + GCObject* o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); + o->marked = luaC_white(g); + o->tt = tt; + o->next = g->allgc; + g->allgc = o; + return o; } /* }====================================================== */ - /* ** {====================================================== ** Mark functions @@ -232,74 +241,89 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { ** to appropriate list to be visited (and turned black) later. (Open ** upvalues are already linked in 'headuv' list.) */ -static void reallymarkobject (global_State *g, GCObject *o) { - reentry: - white2gray(o); - switch (o->tt) { - case LUA_TSHRSTR: { - gray2black(o); - g->GCmemtrav += sizelstring(gco2ts(o)->shrlen); - break; - } - case LUA_TLNGSTR: { - gray2black(o); - g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen); - break; - } - case LUA_TUSERDATA: { - TValue uvalue; - markobjectN(g, gco2u(o)->metatable); /* mark its metatable */ - gray2black(o); - g->GCmemtrav += sizeudata(gco2u(o)); - getuservalue(g->mainthread, gco2u(o), &uvalue); - if (valiswhite(&uvalue)) { /* markvalue(g, &uvalue); */ - o = gcvalue(&uvalue); - goto reentry; - } - break; - } - case LUA_TLCL: { - linkgclist(gco2lcl(o), g->gray); - break; - } - case LUA_TCCL: { - linkgclist(gco2ccl(o), g->gray); - break; - } - case LUA_TTABLE: { - linkgclist(gco2t(o), g->gray); - break; - } - case LUA_TTHREAD: { - linkgclist(gco2th(o), g->gray); - break; - } - case LUA_TPROTO: { - linkgclist(gco2p(o), g->gray); - break; - } - default: lua_assert(0); break; - } +static void reallymarkobject(global_State* g, GCObject* o) +{ +reentry: + white2gray(o); + switch (o->tt) + { + case LUA_TSHRSTR: + { + gray2black(o); + g->GCmemtrav += sizelstring(gco2ts(o)->shrlen); + break; + } + case LUA_TLNGSTR: + { + gray2black(o); + g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen); + break; + } + case LUA_TUSERDATA: + { + TValue uvalue; + markobjectN(g, gco2u(o)->metatable); /* mark its metatable */ + gray2black(o); + g->GCmemtrav += sizeudata(gco2u(o)); + getuservalue(g->mainthread, gco2u(o), &uvalue); + if (valiswhite(&uvalue)) + { + /* markvalue(g, &uvalue); */ + o = gcvalue(&uvalue); + goto reentry; + } + break; + } + case LUA_TLCL: + { + linkgclist(gco2lcl(o), g->gray); + break; + } + case LUA_TCCL: + { + linkgclist(gco2ccl(o), g->gray); + break; + } + case LUA_TTABLE: + { + linkgclist(gco2t(o), g->gray); + break; + } + case LUA_TTHREAD: + { + linkgclist(gco2th(o), g->gray); + break; + } + case LUA_TPROTO: + { + linkgclist(gco2p(o), g->gray); + break; + } + default: lua_assert(0); + break; + } } /* ** mark metamethods for basic types */ -static void markmt (global_State *g) { - int i; - for (i=0; i < LUA_NUMTAGS; i++) - markobjectN(g, g->mt[i]); +static void markmt(global_State* g) +{ + int i; + for (i = 0; i < LUA_NUMTAGS; i++) + markobjectN(g, g->mt[i]); } /* ** mark all objects in list of being-finalized */ -static void markbeingfnz (global_State *g) { - GCObject *o; - for (o = g->tobefnz; o != NULL; o = o->next) - markobject(g, o); +static void markbeingfnz(global_State* g) +{ + GCObject* o; + for (o = g->tobefnz; o != NULL; o = o->next) + markobject(g, o); } @@ -309,38 +333,45 @@ static void markbeingfnz (global_State *g) { ** thread.) Remove from the list threads that no longer have upvalues and ** not-marked threads. */ -static void remarkupvals (global_State *g) { - lua_State *thread; - lua_State **p = &g->twups; - while ((thread = *p) != NULL) { - lua_assert(!isblack(thread)); /* threads are never black */ - if (isgray(thread) && thread->openupval != NULL) - p = &thread->twups; /* keep marked thread with upvalues in the list */ - else { /* thread is not marked or without upvalues */ - UpVal *uv; - *p = thread->twups; /* remove thread from the list */ - thread->twups = thread; /* mark that it is out of list */ - for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) { - if (uv->u.open.touched) { - markvalue(g, uv->v); /* remark upvalue's value */ - uv->u.open.touched = 0; - } - } - } - } +static void remarkupvals(global_State* g) +{ + lua_State* thread; + lua_State** p = &g->twups; + while ((thread = *p) != NULL) + { + lua_assert(!isblack(thread)); /* threads are never black */ + if (isgray(thread) && thread->openupval != NULL) + p = &thread->twups; /* keep marked thread with upvalues in the list */ + else + { + /* thread is not marked or without upvalues */ + UpVal* uv; + *p = thread->twups; /* remove thread from the list */ + thread->twups = thread; /* mark that it is out of list */ + for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) + { + if (uv->u.open.touched) + { + markvalue(g, uv->v); /* remark upvalue's value */ + uv->u.open.touched = 0; + } + } + } + } } /* ** mark root set and reset all gray lists, to start a new collection */ -static void restartcollection (global_State *g) { - g->gray = g->grayagain = NULL; - g->weak = g->allweak = g->ephemeron = NULL; - markobject(g, g->mainthread); - markvalue(g, &g->l_registry); - markmt(g); - markbeingfnz(g); /* mark any finalizing object left from previous cycle */ +static void restartcollection(global_State* g) +{ + g->gray = g->grayagain = NULL; + g->weak = g->allweak = g->ephemeron = NULL; + markobject(g, g->mainthread); + markvalue(g, &g->l_registry); + markmt(g); + markbeingfnz(g); /* mark any finalizing object left from previous cycle */ } /* }====================================================== */ @@ -358,26 +389,30 @@ static void restartcollection (global_State *g) { ** atomic phase. In the atomic phase, if table has any white value, ** put it in 'weak' list, to be cleared. */ -static void traverseweakvalue (global_State *g, Table *h) { - Node *n, *limit = gnodelast(h); - /* if there is array part, assume it may have white values (it is not - worth traversing it now just to check) */ - int hasclears = (h->sizearray > 0); - for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ - checkdeadkey(n); - if (ttisnil(gval(n))) /* entry is empty? */ - removeentry(n); /* remove it */ - else { - lua_assert(!ttisnil(gkey(n))); - markvalue(g, gkey(n)); /* mark key */ - if (!hasclears && iscleared(g, gval(n))) /* is there a white value? */ - hasclears = 1; /* table will have to be cleared */ - } - } - if (g->gcstate == GCSpropagate) - linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ - else if (hasclears) - linkgclist(h, g->weak); /* has to be cleared later */ +static void traverseweakvalue(global_State* g, Table* h) +{ + Node *n, *limit = gnodelast(h); + /* if there is array part, assume it may have white values (it is not + worth traversing it now just to check) */ + int hasclears = (h->sizearray > 0); + for (n = gnode(h, 0); n < limit; n++) + { + /* traverse hash part */ + checkdeadkey(n); + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else + { + lua_assert(!ttisnil(gkey(n))); + markvalue(g, gkey(n)); /* mark key */ + if (!hasclears && iscleared(g, gval(n))) /* is there a white value? */ + hasclears = 1; /* table will have to be cleared */ + } + } + if (g->gcstate == GCSpropagate) + linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ + else if (hasclears) + linkgclist(h, g->weak); /* has to be cleared later */ } @@ -391,83 +426,98 @@ static void traverseweakvalue (global_State *g, Table *h) { ** black). Otherwise, if it has any white key, table has to be cleared ** (in the atomic phase). */ -static int traverseephemeron (global_State *g, Table *h) { - int marked = 0; /* true if an object is marked in this traversal */ - int hasclears = 0; /* true if table has white keys */ - int hasww = 0; /* true if table has entry "white-key -> white-value" */ - Node *n, *limit = gnodelast(h); - unsigned int i; - /* traverse array part */ - for (i = 0; i < h->sizearray; i++) { - if (valiswhite(&h->array[i])) { - marked = 1; - reallymarkobject(g, gcvalue(&h->array[i])); - } - } - /* traverse hash part */ - for (n = gnode(h, 0); n < limit; n++) { - checkdeadkey(n); - if (ttisnil(gval(n))) /* entry is empty? */ - removeentry(n); /* remove it */ - else if (iscleared(g, gkey(n))) { /* key is not marked (yet)? */ - hasclears = 1; /* table must be cleared */ - if (valiswhite(gval(n))) /* value not marked yet? */ - hasww = 1; /* white-white entry */ - } - else if (valiswhite(gval(n))) { /* value not marked yet? */ - marked = 1; - reallymarkobject(g, gcvalue(gval(n))); /* mark it now */ - } - } - /* link table into proper list */ - if (g->gcstate == GCSpropagate) - linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ - else if (hasww) /* table has white->white entries? */ - linkgclist(h, g->ephemeron); /* have to propagate again */ - else if (hasclears) /* table has white keys? */ - linkgclist(h, g->allweak); /* may have to clean white keys */ - return marked; +static int traverseephemeron(global_State* g, Table* h) +{ + int marked = 0; /* true if an object is marked in this traversal */ + int hasclears = 0; /* true if table has white keys */ + int hasww = 0; /* true if table has entry "white-key -> white-value" */ + Node *n, *limit = gnodelast(h); + unsigned int i; + /* traverse array part */ + for (i = 0; i < h->sizearray; i++) + { + if (valiswhite(&h->array[i])) + { + marked = 1; + reallymarkobject(g, gcvalue(&h->array[i])); + } + } + /* traverse hash part */ + for (n = gnode(h, 0); n < limit; n++) + { + checkdeadkey(n); + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else if (iscleared(g, gkey(n))) + { + /* key is not marked (yet)? */ + hasclears = 1; /* table must be cleared */ + if (valiswhite(gval(n))) /* value not marked yet? */ + hasww = 1; /* white-white entry */ + } + else if (valiswhite(gval(n))) + { + /* value not marked yet? */ + marked = 1; + reallymarkobject(g, gcvalue(gval(n))); /* mark it now */ + } + } + /* link table into proper list */ + if (g->gcstate == GCSpropagate) + linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ + else if (hasww) /* table has white->white entries? */ + linkgclist(h, g->ephemeron); /* have to propagate again */ + else if (hasclears) /* table has white keys? */ + linkgclist(h, g->allweak); /* may have to clean white keys */ + return marked; } -static void traversestrongtable (global_State *g, Table *h) { - Node *n, *limit = gnodelast(h); - unsigned int i; - for (i = 0; i < h->sizearray; i++) /* traverse array part */ - markvalue(g, &h->array[i]); - for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ - checkdeadkey(n); - if (ttisnil(gval(n))) /* entry is empty? */ - removeentry(n); /* remove it */ - else { - lua_assert(!ttisnil(gkey(n))); - markvalue(g, gkey(n)); /* mark key */ - markvalue(g, gval(n)); /* mark value */ - } - } +static void traversestrongtable(global_State* g, Table* h) +{ + Node *n, *limit = gnodelast(h); + unsigned int i; + for (i = 0; i < h->sizearray; i++) /* traverse array part */ + markvalue(g, &h->array[i]); + for (n = gnode(h, 0); n < limit; n++) + { + /* traverse hash part */ + checkdeadkey(n); + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else + { + lua_assert(!ttisnil(gkey(n))); + markvalue(g, gkey(n)); /* mark key */ + markvalue(g, gval(n)); /* mark value */ + } + } } -static lu_mem traversetable (global_State *g, Table *h) { - const char *weakkey, *weakvalue; - const TValue *mode = gfasttm(g, h->metatable, TM_MODE); - markobjectN(g, h->metatable); - if (mode && ttisstring(mode) && /* is there a weak mode? */ - ((weakkey = strchr(svalue(mode), 'k')), - (weakvalue = strchr(svalue(mode), 'v')), - (weakkey || weakvalue))) { /* is really weak? */ - black2gray(h); /* keep table gray */ - if (!weakkey) /* strong keys? */ - traverseweakvalue(g, h); - else if (!weakvalue) /* strong values? */ - traverseephemeron(g, h); - else /* all weak */ - linkgclist(h, g->allweak); /* nothing to traverse now */ - } - else /* not weak */ - traversestrongtable(g, h); - return sizeof(Table) + sizeof(TValue) * h->sizearray + - sizeof(Node) * cast(size_t, allocsizenode(h)); +static lu_mem traversetable(global_State* g, Table* h) +{ + const char *weakkey, *weakvalue; + const TValue* mode = gfasttm(g, h->metatable, TM_MODE); + markobjectN(g, h->metatable); + if (mode && ttisstring(mode) && /* is there a weak mode? */ + ((weakkey = strchr(svalue(mode), 'k')), + (weakvalue = strchr(svalue(mode), 'v')), + (weakkey || weakvalue))) + { + /* is really weak? */ + black2gray(h); /* keep table gray */ + if (!weakkey) /* strong keys? */ + traverseweakvalue(g, h); + else if (!weakvalue) /* strong values? */ + traverseephemeron(g, h); + else /* all weak */ + linkgclist(h, g->allweak); /* nothing to traverse now */ + } + else /* not weak */ + traversestrongtable(g, h); + return sizeof(Table) + sizeof(TValue) * h->sizearray + + sizeof(Node) * cast(size_t, allocsizenode(h)); } @@ -476,33 +526,35 @@ static lu_mem traversetable (global_State *g, Table *h) { ** arrays can be larger than needed; the extra slots are filled with ** NULL, so the use of 'markobjectN') */ -static int traverseproto (global_State *g, Proto *f) { - int i; - if (f->cache && iswhite(f->cache)) - f->cache = NULL; /* allow cache to be collected */ - markobjectN(g, f->source); - for (i = 0; i < f->sizek; i++) /* mark literals */ - markvalue(g, &f->k[i]); - for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ - markobjectN(g, f->upvalues[i].name); - for (i = 0; i < f->sizep; i++) /* mark nested protos */ - markobjectN(g, f->p[i]); - for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ - markobjectN(g, f->locvars[i].varname); - return sizeof(Proto) + sizeof(Instruction) * f->sizecode + - sizeof(Proto *) * f->sizep + - sizeof(TValue) * f->sizek + - sizeof(int) * f->sizelineinfo + - sizeof(LocVar) * f->sizelocvars + - sizeof(Upvaldesc) * f->sizeupvalues; +static int traverseproto(global_State* g, Proto* f) +{ + int i; + if (f->cache && iswhite(f->cache)) + f->cache = NULL; /* allow cache to be collected */ + markobjectN(g, f->source); + for (i = 0; i < f->sizek; i++) /* mark literals */ + markvalue(g, &f->k[i]); + for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ + markobjectN(g, f->upvalues[i].name); + for (i = 0; i < f->sizep; i++) /* mark nested protos */ + markobjectN(g, f->p[i]); + for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ + markobjectN(g, f->locvars[i].varname); + return sizeof(Proto) + sizeof(Instruction) * f->sizecode + + sizeof(Proto*) * f->sizep + + sizeof(TValue) * f->sizek + + sizeof(int) * f->sizelineinfo + + sizeof(LocVar) * f->sizelocvars + + sizeof(Upvaldesc) * f->sizeupvalues; } -static lu_mem traverseCclosure (global_State *g, CClosure *cl) { - int i; - for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ - markvalue(g, &cl->upvalue[i]); - return sizeCclosure(cl->nupvalues); +static lu_mem traverseCclosure(global_State* g, CClosure* cl) +{ + int i; + for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ + markvalue(g, &cl->upvalue[i]); + return sizeCclosure(cl->nupvalues); } /* @@ -511,44 +563,52 @@ static lu_mem traverseCclosure (global_State *g, CClosure *cl) { ** (because then the value cannot be changed by the thread and the ** thread may not be traversed again) */ -static lu_mem traverseLclosure (global_State *g, LClosure *cl) { - int i; - markobjectN(g, cl->p); /* mark its prototype */ - for (i = 0; i < cl->nupvalues; i++) { /* mark its upvalues */ - UpVal *uv = cl->upvals[i]; - if (uv != NULL) { - if (upisopen(uv) && g->gcstate != GCSinsideatomic) - uv->u.open.touched = 1; /* can be marked in 'remarkupvals' */ - else - markvalue(g, uv->v); - } - } - return sizeLclosure(cl->nupvalues); +static lu_mem traverseLclosure(global_State* g, LClosure* cl) +{ + int i; + markobjectN(g, cl->p); /* mark its prototype */ + for (i = 0; i < cl->nupvalues; i++) + { + /* mark its upvalues */ + UpVal* uv = cl->upvals[i]; + if (uv != NULL) + { + if (upisopen(uv) && g->gcstate != GCSinsideatomic) + uv->u.open.touched = 1; /* can be marked in 'remarkupvals' */ + else + markvalue(g, uv->v); + } + } + return sizeLclosure(cl->nupvalues); } -static lu_mem traversethread (global_State *g, lua_State *th) { - StkId o = th->stack; - if (o == NULL) - return 1; /* stack not completely built yet */ - lua_assert(g->gcstate == GCSinsideatomic || - th->openupval == NULL || isintwups(th)); - for (; o < th->top; o++) /* mark live elements in the stack */ - markvalue(g, o); - if (g->gcstate == GCSinsideatomic) { /* final traversal? */ - StkId lim = th->stack + th->stacksize; /* real end of stack */ - for (; o < lim; o++) /* clear not-marked stack slice */ - setnilvalue(o); - /* 'remarkupvals' may have removed thread from 'twups' list */ - if (!isintwups(th) && th->openupval != NULL) { - th->twups = g->twups; /* link it back to the list */ - g->twups = th; - } - } - else if (g->gckind != KGC_EMERGENCY) - luaD_shrinkstack(th); /* do not change stack in emergency cycle */ - return (sizeof(lua_State) + sizeof(TValue) * th->stacksize + - sizeof(CallInfo) * th->nci); +static lu_mem traversethread(global_State* g, lua_State* th) +{ + StkId o = th->stack; + if (o == NULL) + return 1; /* stack not completely built yet */ + lua_assert(g->gcstate == GCSinsideatomic || + th->openupval == NULL || isintwups(th)); + for (; o < th->top; o++) /* mark live elements in the stack */ + markvalue(g, o); + if (g->gcstate == GCSinsideatomic) + { + /* final traversal? */ + StkId lim = th->stack + th->stacksize; /* real end of stack */ + for (; o < lim; o++) /* clear not-marked stack slice */ + setnilvalue(o); + /* 'remarkupvals' may have removed thread from 'twups' list */ + if (!isintwups(th) && th->openupval != NULL) + { + th->twups = g->twups; /* link it back to the list */ + g->twups = th; + } + } + else if (g->gckind != KGC_EMERGENCY) + luaD_shrinkstack(th); /* do not change stack in emergency cycle */ + return (sizeof(lua_State) + sizeof(TValue) * th->stacksize + + sizeof(CallInfo) * th->nci); } @@ -556,70 +616,85 @@ static lu_mem traversethread (global_State *g, lua_State *th) { ** traverse one gray object, turning it to black (except for threads, ** which are always gray). */ -static void propagatemark (global_State *g) { - lu_mem size; - GCObject *o = g->gray; - lua_assert(isgray(o)); - gray2black(o); - switch (o->tt) { - case LUA_TTABLE: { - Table *h = gco2t(o); - g->gray = h->gclist; /* remove from 'gray' list */ - size = traversetable(g, h); - break; - } - case LUA_TLCL: { - LClosure *cl = gco2lcl(o); - g->gray = cl->gclist; /* remove from 'gray' list */ - size = traverseLclosure(g, cl); - break; - } - case LUA_TCCL: { - CClosure *cl = gco2ccl(o); - g->gray = cl->gclist; /* remove from 'gray' list */ - size = traverseCclosure(g, cl); - break; - } - case LUA_TTHREAD: { - lua_State *th = gco2th(o); - g->gray = th->gclist; /* remove from 'gray' list */ - linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ - black2gray(o); - size = traversethread(g, th); - break; - } - case LUA_TPROTO: { - Proto *p = gco2p(o); - g->gray = p->gclist; /* remove from 'gray' list */ - size = traverseproto(g, p); - break; - } - default: lua_assert(0); return; - } - g->GCmemtrav += size; +static void propagatemark(global_State* g) +{ + lu_mem size; + GCObject* o = g->gray; + lua_assert(isgray(o)); + gray2black(o); + switch (o->tt) + { + case LUA_TTABLE: + { + Table* h = gco2t(o); + g->gray = h->gclist; /* remove from 'gray' list */ + size = traversetable(g, h); + break; + } + case LUA_TLCL: + { + LClosure* cl = gco2lcl(o); + g->gray = cl->gclist; /* remove from 'gray' list */ + size = traverseLclosure(g, cl); + break; + } + case LUA_TCCL: + { + CClosure* cl = gco2ccl(o); + g->gray = cl->gclist; /* remove from 'gray' list */ + size = traverseCclosure(g, cl); + break; + } + case LUA_TTHREAD: + { + lua_State* th = gco2th(o); + g->gray = th->gclist; /* remove from 'gray' list */ + linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ + black2gray(o); + size = traversethread(g, th); + break; + } + case LUA_TPROTO: + { + Proto* p = gco2p(o); + g->gray = p->gclist; /* remove from 'gray' list */ + size = traverseproto(g, p); + break; + } + default: lua_assert(0); + return; + } + g->GCmemtrav += size; } -static void propagateall (global_State *g) { - while (g->gray) propagatemark(g); +static void propagateall(global_State* g) +{ + while (g->gray) propagatemark(g); } -static void convergeephemerons (global_State *g) { - int changed; - do { - GCObject *w; - GCObject *next = g->ephemeron; /* get ephemeron list */ - g->ephemeron = NULL; /* tables may return to this list when traversed */ - changed = 0; - while ((w = next) != NULL) { - next = gco2t(w)->gclist; - if (traverseephemeron(g, gco2t(w))) { /* traverse marked some value? */ - propagateall(g); /* propagate changes */ - changed = 1; /* will have to revisit all ephemeron tables */ - } - } - } while (changed); +static void convergeephemerons(global_State* g) +{ + int changed; + do + { + GCObject* w; + GCObject* next = g->ephemeron; /* get ephemeron list */ + g->ephemeron = NULL; /* tables may return to this list when traversed */ + changed = 0; + while ((w = next) != NULL) + { + next = gco2t(w)->gclist; + if (traverseephemeron(g, gco2t(w))) + { + /* traverse marked some value? */ + propagateall(g); /* propagate changes */ + changed = 1; /* will have to revisit all ephemeron tables */ + } + } + } + while (changed); } /* }====================================================== */ @@ -636,17 +711,21 @@ static void convergeephemerons (global_State *g) { ** clear entries with unmarked keys from all weaktables in list 'l' up ** to element 'f' */ -static void clearkeys (global_State *g, GCObject *l, GCObject *f) { - for (; l != f; l = gco2t(l)->gclist) { - Table *h = gco2t(l); - Node *n, *limit = gnodelast(h); - for (n = gnode(h, 0); n < limit; n++) { - if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) { - setnilvalue(gval(n)); /* remove value ... */ - removeentry(n); /* and remove entry from table */ - } - } - } +static void clearkeys(global_State* g, GCObject* l, GCObject* f) +{ + for (; l != f; l = gco2t(l)->gclist) + { + Table* h = gco2t(l); + Node *n, *limit = gnodelast(h); + for (n = gnode(h, 0); n < limit; n++) + { + if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) + { + setnilvalue(gval(n)); /* remove value ... */ + removeentry(n); /* and remove entry from table */ + } + } + } } @@ -654,74 +733,91 @@ static void clearkeys (global_State *g, GCObject *l, GCObject *f) { ** clear entries with unmarked values from all weaktables in list 'l' up ** to element 'f' */ -static void clearvalues (global_State *g, GCObject *l, GCObject *f) { - for (; l != f; l = gco2t(l)->gclist) { - Table *h = gco2t(l); - Node *n, *limit = gnodelast(h); - unsigned int i; - for (i = 0; i < h->sizearray; i++) { - TValue *o = &h->array[i]; - if (iscleared(g, o)) /* value was collected? */ - setnilvalue(o); /* remove value */ - } - for (n = gnode(h, 0); n < limit; n++) { - if (!ttisnil(gval(n)) && iscleared(g, gval(n))) { - setnilvalue(gval(n)); /* remove value ... */ - removeentry(n); /* and remove entry from table */ - } - } - } +static void clearvalues(global_State* g, GCObject* l, GCObject* f) +{ + for (; l != f; l = gco2t(l)->gclist) + { + Table* h = gco2t(l); + Node *n, *limit = gnodelast(h); + unsigned int i; + for (i = 0; i < h->sizearray; i++) + { + TValue* o = &h->array[i]; + if (iscleared(g, o)) /* value was collected? */ + setnilvalue(o); /* remove value */ + } + for (n = gnode(h, 0); n < limit; n++) + { + if (!ttisnil(gval(n)) && iscleared(g, gval(n))) + { + setnilvalue(gval(n)); /* remove value ... */ + removeentry(n); /* and remove entry from table */ + } + } + } } -void luaC_upvdeccount (lua_State *L, UpVal *uv) { - lua_assert(uv->refcount > 0); - uv->refcount--; - if (uv->refcount == 0 && !upisopen(uv)) - luaM_free(L, uv); +void luaC_upvdeccount(lua_State* L, UpVal* uv) +{ + lua_assert(uv->refcount > 0); + uv->refcount--; + if (uv->refcount == 0 && !upisopen(uv)) + luaM_free(L, uv); } -static void freeLclosure (lua_State *L, LClosure *cl) { - int i; - for (i = 0; i < cl->nupvalues; i++) { - UpVal *uv = cl->upvals[i]; - if (uv) - luaC_upvdeccount(L, uv); - } - luaM_freemem(L, cl, sizeLclosure(cl->nupvalues)); +static void freeLclosure(lua_State* L, LClosure* cl) +{ + int i; + for (i = 0; i < cl->nupvalues; i++) + { + UpVal* uv = cl->upvals[i]; + if (uv) + luaC_upvdeccount(L, uv); + } + luaM_freemem(L, cl, sizeLclosure(cl->nupvalues)); } -static void freeobj (lua_State *L, GCObject *o) { - switch (o->tt) { - case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; - case LUA_TLCL: { - freeLclosure(L, gco2lcl(o)); - break; - } - case LUA_TCCL: { - luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); - break; - } - case LUA_TTABLE: luaH_free(L, gco2t(o)); break; - case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; - case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; - case LUA_TSHRSTR: - luaS_remove(L, gco2ts(o)); /* remove it from hash table */ - luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); - break; - case LUA_TLNGSTR: { - luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen)); - break; - } - default: lua_assert(0); - } +static void freeobj(lua_State* L, GCObject* o) +{ + switch (o->tt) + { + case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); + break; + case LUA_TLCL: + { + freeLclosure(L, gco2lcl(o)); + break; + } + case LUA_TCCL: + { + luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); + break; + } + case LUA_TTABLE: luaH_free(L, gco2t(o)); + break; + case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); + break; + case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); + break; + case LUA_TSHRSTR: + luaS_remove(L, gco2ts(o)); /* remove it from hash table */ + luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); + break; + case LUA_TLNGSTR: + { + luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen)); + break; + } + default: lua_assert(0); + } } #define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) -static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count); +static GCObject** sweeplist(lua_State* L, GCObject** p, lu_mem count); /* @@ -731,35 +827,44 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count); ** collection cycle. Return where to continue the traversal or NULL if ** list is finished. */ -static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { - global_State *g = G(L); - int ow = otherwhite(g); - int white = luaC_white(g); /* current white */ - while (*p != NULL && count-- > 0) { - GCObject *curr = *p; - int marked = curr->marked; - if (isdeadm(ow, marked)) { /* is 'curr' dead? */ - *p = curr->next; /* remove 'curr' from list */ - freeobj(L, curr); /* erase 'curr' */ - } - else { /* change mark to 'white' */ - curr->marked = cast_byte((marked & maskcolors) | white); - p = &curr->next; /* go to next element */ - } - } - return (*p == NULL) ? NULL : p; +static GCObject** sweeplist(lua_State* L, GCObject** p, lu_mem count) +{ + global_State* g = G(L); + int ow = otherwhite(g); + int white = luaC_white(g); /* current white */ + while (*p != NULL && count-- > 0) + { + GCObject* curr = *p; + int marked = curr->marked; + if (isdeadm(ow, marked)) + { + /* is 'curr' dead? */ + *p = curr->next; /* remove 'curr' from list */ + freeobj(L, curr); /* erase 'curr' */ + } + else + { + /* change mark to 'white' */ + curr->marked = cast_byte((marked & maskcolors) | white); + p = &curr->next; /* go to next element */ + } + } + return (*p == NULL) ? NULL : p; } /* ** sweep a list until a live object (or end of list) */ -static GCObject **sweeptolive (lua_State *L, GCObject **p) { - GCObject **old = p; - do { - p = sweeplist(L, p, 1); - } while (p == old); - return p; +static GCObject** sweeptolive(lua_State* L, GCObject** p) +{ + GCObject** old = p; + do + { + p = sweeplist(L, p, 1); + } + while (p == old); + return p; } /* }====================================================== */ @@ -774,101 +879,116 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p) { /* ** If possible, shrink string table */ -static void checkSizes (lua_State *L, global_State *g) { - if (g->gckind != KGC_EMERGENCY) { - l_mem olddebt = g->GCdebt; - if (g->strt.nuse < g->strt.size / 4) /* string table too big? */ - luaS_resize(L, g->strt.size / 2); /* shrink it a little */ - g->GCestimate += g->GCdebt - olddebt; /* update estimate */ - } +static void checkSizes(lua_State* L, global_State* g) +{ + if (g->gckind != KGC_EMERGENCY) + { + l_mem olddebt = g->GCdebt; + if (g->strt.nuse < g->strt.size / 4) /* string table too big? */ + luaS_resize(L, g->strt.size / 2); /* shrink it a little */ + g->GCestimate += g->GCdebt - olddebt; /* update estimate */ + } } -static GCObject *udata2finalize (global_State *g) { - GCObject *o = g->tobefnz; /* get first element */ - lua_assert(tofinalize(o)); - g->tobefnz = o->next; /* remove it from 'tobefnz' list */ - o->next = g->allgc; /* return it to 'allgc' list */ - g->allgc = o; - resetbit(o->marked, FINALIZEDBIT); /* object is "normal" again */ - if (issweepphase(g)) - makewhite(g, o); /* "sweep" object */ - return o; +static GCObject* udata2finalize(global_State* g) +{ + GCObject* o = g->tobefnz; /* get first element */ + lua_assert(tofinalize(o)); + g->tobefnz = o->next; /* remove it from 'tobefnz' list */ + o->next = g->allgc; /* return it to 'allgc' list */ + g->allgc = o; + resetbit(o->marked, FINALIZEDBIT); /* object is "normal" again */ + if (issweepphase(g)) + makewhite(g, o); /* "sweep" object */ + return o; } -static void dothecall (lua_State *L, void *ud) { - UNUSED(ud); - luaD_callnoyield(L, L->top - 2, 0); +static void dothecall(lua_State* L, void* ud) +{ + UNUSED(ud); + luaD_callnoyield(L, L->top - 2, 0); } -static void GCTM (lua_State *L, int propagateerrors) { - global_State *g = G(L); - const TValue *tm; - TValue v; - setgcovalue(L, &v, udata2finalize(g)); - tm = luaT_gettmbyobj(L, &v, TM_GC); - if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ - int status; - lu_byte oldah = L->allowhook; - int running = g->gcrunning; - L->allowhook = 0; /* stop debug hooks during GC metamethod */ - g->gcrunning = 0; /* avoid GC steps */ - setobj2s(L, L->top, tm); /* push finalizer... */ - setobj2s(L, L->top + 1, &v); /* ... and its argument */ - L->top += 2; /* and (next line) call the finalizer */ - L->ci->callstatus |= CIST_FIN; /* will run a finalizer */ - status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); - L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */ - L->allowhook = oldah; /* restore hooks */ - g->gcrunning = running; /* restore state */ - if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ - if (status == LUA_ERRRUN) { /* is there an error object? */ - const char *msg = (ttisstring(L->top - 1)) - ? svalue(L->top - 1) - : "no message"; - luaO_pushfstring(L, "error in __gc metamethod (%s)", msg); - status = LUA_ERRGCMM; /* error in __gc metamethod */ - } - luaD_throw(L, status); /* re-throw error */ - } - } +static void GCTM(lua_State* L, int propagateerrors) +{ + global_State* g = G(L); + const TValue* tm; + TValue v; + setgcovalue(L, &v, udata2finalize(g)); + tm = luaT_gettmbyobj(L, &v, TM_GC); + if (tm != NULL && ttisfunction(tm)) + { + /* is there a finalizer? */ + int status; + lu_byte oldah = L->allowhook; + int running = g->gcrunning; + L->allowhook = 0; /* stop debug hooks during GC metamethod */ + g->gcrunning = 0; /* avoid GC steps */ + setobj2s(L, L->top, tm); /* push finalizer... */ + setobj2s(L, L->top + 1, &v); /* ... and its argument */ + L->top += 2; /* and (next line) call the finalizer */ + L->ci->callstatus |= CIST_FIN; /* will run a finalizer */ + status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); + L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */ + L->allowhook = oldah; /* restore hooks */ + g->gcrunning = running; /* restore state */ + if (status != LUA_OK && propagateerrors) + { + /* error while running __gc? */ + if (status == LUA_ERRRUN) + { + /* is there an error object? */ + const char* msg = (ttisstring(L->top - 1)) + ? svalue(L->top - 1) + : "no message"; + luaO_pushfstring(L, "error in __gc metamethod (%s)", msg); + status = LUA_ERRGCMM; /* error in __gc metamethod */ + } + luaD_throw(L, status); /* re-throw error */ + } + } } /* ** call a few (up to 'g->gcfinnum') finalizers */ -static int runafewfinalizers (lua_State *L) { - global_State *g = G(L); - unsigned int i; - lua_assert(!g->tobefnz || g->gcfinnum > 0); - for (i = 0; g->tobefnz && i < g->gcfinnum; i++) - GCTM(L, 1); /* call one finalizer */ - g->gcfinnum = (!g->tobefnz) ? 0 /* nothing more to finalize? */ - : g->gcfinnum * 2; /* else call a few more next time */ - return i; +static int runafewfinalizers(lua_State* L) +{ + global_State* g = G(L); + unsigned int i; + lua_assert(!g->tobefnz || g->gcfinnum > 0); + for (i = 0; g->tobefnz && i < g->gcfinnum; i++) + GCTM(L, 1); /* call one finalizer */ + g->gcfinnum = (!g->tobefnz) + ? 0 /* nothing more to finalize? */ + : g->gcfinnum * 2; /* else call a few more next time */ + return i; } /* ** call all pending finalizers */ -static void callallpendingfinalizers (lua_State *L) { - global_State *g = G(L); - while (g->tobefnz) - GCTM(L, 0); +static void callallpendingfinalizers(lua_State* L) +{ + global_State* g = G(L); + while (g->tobefnz) + GCTM(L, 0); } /* ** find last 'next' field in list 'p' list (to add elements in its end) */ -static GCObject **findlast (GCObject **p) { - while (*p != NULL) - p = &(*p)->next; - return p; +static GCObject** findlast(GCObject** p) +{ + while (*p != NULL) + p = &(*p)->next; + return p; } @@ -876,21 +996,25 @@ static GCObject **findlast (GCObject **p) { ** move all unreachable objects (or 'all' objects) that need ** finalization from list 'finobj' to list 'tobefnz' (to be finalized) */ -static void separatetobefnz (global_State *g, int all) { - GCObject *curr; - GCObject **p = &g->finobj; - GCObject **lastnext = findlast(&g->tobefnz); - while ((curr = *p) != NULL) { /* traverse all finalizable objects */ - lua_assert(tofinalize(curr)); - if (!(iswhite(curr) || all)) /* not being collected? */ - p = &curr->next; /* don't bother with it */ - else { - *p = curr->next; /* remove 'curr' from 'finobj' list */ - curr->next = *lastnext; /* link at the end of 'tobefnz' list */ - *lastnext = curr; - lastnext = &curr->next; - } - } +static void separatetobefnz(global_State* g, int all) +{ + GCObject* curr; + GCObject** p = &g->finobj; + GCObject** lastnext = findlast(&g->tobefnz); + while ((curr = *p) != NULL) + { + /* traverse all finalizable objects */ + lua_assert(tofinalize(curr)); + if (!(iswhite(curr) || all)) /* not being collected? */ + p = &curr->next; /* don't bother with it */ + else + { + *p = curr->next; /* remove 'curr' from 'finobj' list */ + curr->next = *lastnext; /* link at the end of 'tobefnz' list */ + *lastnext = curr; + lastnext = &curr->next; + } + } } @@ -898,31 +1022,34 @@ static void separatetobefnz (global_State *g, int all) { ** if object 'o' has a finalizer, remove it from 'allgc' list (must ** search the list to find it) and link it in 'finobj' list. */ -void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { - global_State *g = G(L); - if (tofinalize(o) || /* obj. is already marked... */ - gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ - return; /* nothing to be done */ - else { /* move 'o' to 'finobj' list */ - GCObject **p; - if (issweepphase(g)) { - makewhite(g, o); /* "sweep" object 'o' */ - if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */ - g->sweepgc = sweeptolive(L, g->sweepgc); /* change 'sweepgc' */ - } - /* search for pointer pointing to 'o' */ - for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ } - *p = o->next; /* remove 'o' from 'allgc' list */ - o->next = g->finobj; /* link it in 'finobj' list */ - g->finobj = o; - l_setbit(o->marked, FINALIZEDBIT); /* mark it as such */ - } +void luaC_checkfinalizer(lua_State* L, GCObject* o, Table* mt) +{ + global_State* g = G(L); + if (tofinalize(o) || /* obj. is already marked... */ + gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ + return; /* nothing to be done */ + else + { + /* move 'o' to 'finobj' list */ + GCObject** p; + if (issweepphase(g)) + { + makewhite(g, o); /* "sweep" object 'o' */ + if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */ + g->sweepgc = sweeptolive(L, g->sweepgc); /* change 'sweepgc' */ + } + /* search for pointer pointing to 'o' */ + for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ } + *p = o->next; /* remove 'o' from 'allgc' list */ + o->next = g->finobj; /* link it in 'finobj' list */ + g->finobj = o; + l_setbit(o->marked, FINALIZEDBIT); /* mark it as such */ + } } /* }====================================================== */ - /* ** {====================================================== ** GC control @@ -936,15 +1063,16 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { ** should be OK: it cannot be zero (because Lua cannot even start with ** less than PAUSEADJ bytes). */ -static void setpause (global_State *g) { - l_mem threshold, debt; - l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ - lua_assert(estimate > 0); - threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ - ? estimate * g->gcpause /* no overflow */ - : MAX_LMEM; /* overflow; truncate to maximum */ - debt = gettotalbytes(g) - threshold; - luaE_setdebt(g, debt); +static void setpause(global_State* g) +{ + l_mem threshold, debt; + l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ + lua_assert(estimate > 0); + threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ + ? estimate * g->gcpause /* no overflow */ + : MAX_LMEM; /* overflow; truncate to maximum */ + debt = gettotalbytes(g) - threshold; + luaE_setdebt(g, debt); } @@ -955,144 +1083,170 @@ static void setpause (global_State *g) { ** not need to skip objects created between "now" and the start of the ** real sweep. */ -static void entersweep (lua_State *L) { - global_State *g = G(L); - g->gcstate = GCSswpallgc; - lua_assert(g->sweepgc == NULL); - g->sweepgc = sweeplist(L, &g->allgc, 1); +static void entersweep(lua_State* L) +{ + global_State* g = G(L); + g->gcstate = GCSswpallgc; + lua_assert(g->sweepgc == NULL); + g->sweepgc = sweeplist(L, &g->allgc, 1); } -void luaC_freeallobjects (lua_State *L) { - global_State *g = G(L); - separatetobefnz(g, 1); /* separate all objects with finalizers */ - lua_assert(g->finobj == NULL); - callallpendingfinalizers(L); - lua_assert(g->tobefnz == NULL); - g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ - g->gckind = KGC_NORMAL; - sweepwholelist(L, &g->finobj); - sweepwholelist(L, &g->allgc); - sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ - lua_assert(g->strt.nuse == 0); +void luaC_freeallobjects(lua_State* L) +{ + global_State* g = G(L); + separatetobefnz(g, 1); /* separate all objects with finalizers */ + lua_assert(g->finobj == NULL); + callallpendingfinalizers(L); + lua_assert(g->tobefnz == NULL); + g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ + g->gckind = KGC_NORMAL; + sweepwholelist(L, &g->finobj); + sweepwholelist(L, &g->allgc); + sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ + lua_assert(g->strt.nuse == 0); } -static l_mem atomic (lua_State *L) { - global_State *g = G(L); - l_mem work; - GCObject *origweak, *origall; - GCObject *grayagain = g->grayagain; /* save original list */ - lua_assert(g->ephemeron == NULL && g->weak == NULL); - lua_assert(!iswhite(g->mainthread)); - g->gcstate = GCSinsideatomic; - g->GCmemtrav = 0; /* start counting work */ - markobject(g, L); /* mark running thread */ - /* registry and global metatables may be changed by API */ - markvalue(g, &g->l_registry); - markmt(g); /* mark global metatables */ - /* remark occasional upvalues of (maybe) dead threads */ - remarkupvals(g); - propagateall(g); /* propagate changes */ - work = g->GCmemtrav; /* stop counting (do not recount 'grayagain') */ - g->gray = grayagain; - propagateall(g); /* traverse 'grayagain' list */ - g->GCmemtrav = 0; /* restart counting */ - convergeephemerons(g); - /* at this point, all strongly accessible objects are marked. */ - /* Clear values from weak tables, before checking finalizers */ - clearvalues(g, g->weak, NULL); - clearvalues(g, g->allweak, NULL); - origweak = g->weak; origall = g->allweak; - work += g->GCmemtrav; /* stop counting (objects being finalized) */ - separatetobefnz(g, 0); /* separate objects to be finalized */ - g->gcfinnum = 1; /* there may be objects to be finalized */ - markbeingfnz(g); /* mark objects that will be finalized */ - propagateall(g); /* remark, to propagate 'resurrection' */ - g->GCmemtrav = 0; /* restart counting */ - convergeephemerons(g); - /* at this point, all resurrected objects are marked. */ - /* remove dead objects from weak tables */ - clearkeys(g, g->ephemeron, NULL); /* clear keys from all ephemeron tables */ - clearkeys(g, g->allweak, NULL); /* clear keys from all 'allweak' tables */ - /* clear values from resurrected weak tables */ - clearvalues(g, g->weak, origweak); - clearvalues(g, g->allweak, origall); - luaS_clearcache(g); - g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ - work += g->GCmemtrav; /* complete counting */ - return work; /* estimate of memory marked by 'atomic' */ +static l_mem atomic(lua_State* L) +{ + global_State* g = G(L); + l_mem work; + GCObject *origweak, *origall; + GCObject* grayagain = g->grayagain; /* save original list */ + lua_assert(g->ephemeron == NULL && g->weak == NULL); + lua_assert(!iswhite(g->mainthread)); + g->gcstate = GCSinsideatomic; + g->GCmemtrav = 0; /* start counting work */ + markobject(g, L); /* mark running thread */ + /* registry and global metatables may be changed by API */ + markvalue(g, &g->l_registry); + markmt(g); /* mark global metatables */ + /* remark occasional upvalues of (maybe) dead threads */ + remarkupvals(g); + propagateall(g); /* propagate changes */ + work = g->GCmemtrav; /* stop counting (do not recount 'grayagain') */ + g->gray = grayagain; + propagateall(g); /* traverse 'grayagain' list */ + g->GCmemtrav = 0; /* restart counting */ + convergeephemerons(g); + /* at this point, all strongly accessible objects are marked. */ + /* Clear values from weak tables, before checking finalizers */ + clearvalues(g, g->weak, NULL); + clearvalues(g, g->allweak, NULL); + origweak = g->weak; + origall = g->allweak; + work += g->GCmemtrav; /* stop counting (objects being finalized) */ + separatetobefnz(g, 0); /* separate objects to be finalized */ + g->gcfinnum = 1; /* there may be objects to be finalized */ + markbeingfnz(g); /* mark objects that will be finalized */ + propagateall(g); /* remark, to propagate 'resurrection' */ + g->GCmemtrav = 0; /* restart counting */ + convergeephemerons(g); + /* at this point, all resurrected objects are marked. */ + /* remove dead objects from weak tables */ + clearkeys(g, g->ephemeron, NULL); /* clear keys from all ephemeron tables */ + clearkeys(g, g->allweak, NULL); /* clear keys from all 'allweak' tables */ + /* clear values from resurrected weak tables */ + clearvalues(g, g->weak, origweak); + clearvalues(g, g->allweak, origall); + luaS_clearcache(g); + g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ + work += g->GCmemtrav; /* complete counting */ + return work; /* estimate of memory marked by 'atomic' */ } -static lu_mem sweepstep (lua_State *L, global_State *g, - int nextstate, GCObject **nextlist) { - if (g->sweepgc) { - l_mem olddebt = g->GCdebt; - g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); - g->GCestimate += g->GCdebt - olddebt; /* update estimate */ - if (g->sweepgc) /* is there still something to sweep? */ - return (GCSWEEPMAX * GCSWEEPCOST); - } - /* else enter next state */ - g->gcstate = nextstate; - g->sweepgc = nextlist; - return 0; +static lu_mem sweepstep(lua_State* L, global_State* g, + int nextstate, GCObject** nextlist) +{ + if (g->sweepgc) + { + l_mem olddebt = g->GCdebt; + g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); + g->GCestimate += g->GCdebt - olddebt; /* update estimate */ + if (g->sweepgc) /* is there still something to sweep? */ + return (GCSWEEPMAX * GCSWEEPCOST); + } + /* else enter next state */ + g->gcstate = nextstate; + g->sweepgc = nextlist; + return 0; } -static lu_mem singlestep (lua_State *L) { - global_State *g = G(L); - switch (g->gcstate) { - case GCSpause: { - g->GCmemtrav = g->strt.size * sizeof(GCObject*); - restartcollection(g); - g->gcstate = GCSpropagate; - return g->GCmemtrav; - } - case GCSpropagate: { - g->GCmemtrav = 0; - lua_assert(g->gray); - propagatemark(g); - if (g->gray == NULL) /* no more gray objects? */ - g->gcstate = GCSatomic; /* finish propagate phase */ - return g->GCmemtrav; /* memory traversed in this step */ - } - case GCSatomic: { - lu_mem work; - propagateall(g); /* make sure gray list is empty */ - work = atomic(L); /* work is what was traversed by 'atomic' */ - entersweep(L); - g->GCestimate = gettotalbytes(g); /* first estimate */; - return work; - } - case GCSswpallgc: { /* sweep "regular" objects */ - return sweepstep(L, g, GCSswpfinobj, &g->finobj); - } - case GCSswpfinobj: { /* sweep objects with finalizers */ - return sweepstep(L, g, GCSswptobefnz, &g->tobefnz); - } - case GCSswptobefnz: { /* sweep objects to be finalized */ - return sweepstep(L, g, GCSswpend, NULL); - } - case GCSswpend: { /* finish sweeps */ - makewhite(g, g->mainthread); /* sweep main thread */ - checkSizes(L, g); - g->gcstate = GCScallfin; - return 0; - } - case GCScallfin: { /* call remaining finalizers */ - if (g->tobefnz && g->gckind != KGC_EMERGENCY) { - int n = runafewfinalizers(L); - return (n * GCFINALIZECOST); - } - else { /* emergency mode or no more finalizers */ - g->gcstate = GCSpause; /* finish collection */ - return 0; - } - } - default: lua_assert(0); return 0; - } +static lu_mem singlestep(lua_State* L) +{ + global_State* g = G(L); + switch (g->gcstate) + { + case GCSpause: + { + g->GCmemtrav = g->strt.size * sizeof(GCObject*); + restartcollection(g); + g->gcstate = GCSpropagate; + return g->GCmemtrav; + } + case GCSpropagate: + { + g->GCmemtrav = 0; + lua_assert(g->gray); + propagatemark(g); + if (g->gray == NULL) /* no more gray objects? */ + g->gcstate = GCSatomic; /* finish propagate phase */ + return g->GCmemtrav; /* memory traversed in this step */ + } + case GCSatomic: + { + lu_mem work; + propagateall(g); /* make sure gray list is empty */ + work = atomic(L); /* work is what was traversed by 'atomic' */ + entersweep(L); + g->GCestimate = gettotalbytes(g); /* first estimate */ + ; + return work; + } + case GCSswpallgc: + { + /* sweep "regular" objects */ + return sweepstep(L, g, GCSswpfinobj, &g->finobj); + } + case GCSswpfinobj: + { + /* sweep objects with finalizers */ + return sweepstep(L, g, GCSswptobefnz, &g->tobefnz); + } + case GCSswptobefnz: + { + /* sweep objects to be finalized */ + return sweepstep(L, g, GCSswpend, NULL); + } + case GCSswpend: + { + /* finish sweeps */ + makewhite(g, g->mainthread); /* sweep main thread */ + checkSizes(L, g); + g->gcstate = GCScallfin; + return 0; + } + case GCScallfin: + { + /* call remaining finalizers */ + if (g->tobefnz && g->gckind != KGC_EMERGENCY) + { + int n = runafewfinalizers(L); + return (n * GCFINALIZECOST); + } + else + { + /* emergency mode or no more finalizers */ + g->gcstate = GCSpause; /* finish collection */ + return 0; + } + } + default: lua_assert(0); + return 0; + } } @@ -1100,10 +1254,11 @@ static lu_mem singlestep (lua_State *L) { ** advances the garbage collector until it reaches a state allowed ** by 'statemask' */ -void luaC_runtilstate (lua_State *L, int statesmask) { - global_State *g = G(L); - while (!testbit(statesmask, g->gcstate)) - singlestep(L); +void luaC_runtilstate(lua_State* L, int statesmask) +{ + global_State* g = G(L); + while (!testbit(statesmask, g->gcstate)) + singlestep(L); } @@ -1111,38 +1266,47 @@ void luaC_runtilstate (lua_State *L, int statesmask) { ** get GC debt and convert it from Kb to 'work units' (avoid zero debt ** and overflows) */ -static l_mem getdebt (global_State *g) { - l_mem debt = g->GCdebt; - int stepmul = g->gcstepmul; - if (debt <= 0) return 0; /* minimal debt */ - else { - debt = (debt / STEPMULADJ) + 1; - debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; - return debt; - } +static l_mem getdebt(global_State* g) +{ + l_mem debt = g->GCdebt; + int stepmul = g->gcstepmul; + if (debt <= 0) return 0; /* minimal debt */ + else + { + debt = (debt / STEPMULADJ) + 1; + debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; + return debt; + } } /* ** performs a basic GC step when collector is running */ -void luaC_step (lua_State *L) { - global_State *g = G(L); - l_mem debt = getdebt(g); /* GC deficit (be paid now) */ - if (!g->gcrunning) { /* not running? */ - luaE_setdebt(g, -GCSTEPSIZE * 10); /* avoid being called too often */ - return; - } - do { /* repeat until pause or enough "credit" (negative debt) */ - lu_mem work = singlestep(L); /* perform one single step */ - debt -= work; - } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); - if (g->gcstate == GCSpause) - setpause(g); /* pause until next cycle */ - else { - debt = (debt / g->gcstepmul) * STEPMULADJ; /* convert 'work units' to Kb */ - luaE_setdebt(g, debt); - runafewfinalizers(L); - } +void luaC_step(lua_State* L) +{ + global_State* g = G(L); + l_mem debt = getdebt(g); /* GC deficit (be paid now) */ + if (!g->gcrunning) + { + /* not running? */ + luaE_setdebt(g, -GCSTEPSIZE * 10); /* avoid being called too often */ + return; + } + do + { + /* repeat until pause or enough "credit" (negative debt) */ + lu_mem work = singlestep(L); /* perform one single step */ + debt -= work; + } + while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); + if (g->gcstate == GCSpause) + setpause(g); /* pause until next cycle */ + else + { + debt = (debt / g->gcstepmul) * STEPMULADJ; /* convert 'work units' to Kb */ + luaE_setdebt(g, debt); + runafewfinalizers(L); + } } @@ -1155,24 +1319,25 @@ void luaC_step (lua_State *L) { ** to sweep all objects to turn them back to white (as white has not ** changed, nothing will be collected). */ -void luaC_fullgc (lua_State *L, int isemergency) { - global_State *g = G(L); - lua_assert(g->gckind == KGC_NORMAL); - if (isemergency) g->gckind = KGC_EMERGENCY; /* set flag */ - if (keepinvariant(g)) { /* black objects? */ - entersweep(L); /* sweep everything to turn them back to white */ - } - /* finish any pending sweep phase to start a new cycle */ - luaC_runtilstate(L, bitmask(GCSpause)); - luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ - luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ - /* estimate must be correct after a full GC cycle */ - lua_assert(g->GCestimate == gettotalbytes(g)); - luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ - g->gckind = KGC_NORMAL; - setpause(g); +void luaC_fullgc(lua_State* L, int isemergency) +{ + global_State* g = G(L); + lua_assert(g->gckind == KGC_NORMAL); + if (isemergency) g->gckind = KGC_EMERGENCY; /* set flag */ + if (keepinvariant(g)) + { + /* black objects? */ + entersweep(L); /* sweep everything to turn them back to white */ + } + /* finish any pending sweep phase to start a new cycle */ + luaC_runtilstate(L, bitmask(GCSpause)); + luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ + luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ + /* estimate must be correct after a full GC cycle */ + lua_assert(g->GCestimate == gettotalbytes(g)); + luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ + g->gckind = KGC_NORMAL; + setpause(g); } /* }====================================================== */ - - diff --git a/Lua/lgc.h b/Lua/lgc.h index aed3e18..3a2a27c 100644 --- a/Lua/lgc.h +++ b/Lua/lgc.h @@ -25,7 +25,6 @@ */ - /* how much to allocate before next GC step */ #if !defined(GCSTEPSIZE) /* ~100 small strings */ @@ -131,17 +130,17 @@ (iscollectable((uv)->v) && !upisopen(uv)) ? \ luaC_upvalbarrier_(L,uv) : cast_void(0)) -LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); -LUAI_FUNC void luaC_freeallobjects (lua_State *L); -LUAI_FUNC void luaC_step (lua_State *L); -LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); -LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); -LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); -LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); -LUAI_FUNC void luaC_barrierback_ (lua_State *L, Table *o); -LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv); -LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); -LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv); +LUAI_FUNC void luaC_fix(lua_State* L, GCObject* o); +LUAI_FUNC void luaC_freeallobjects(lua_State* L); +LUAI_FUNC void luaC_step(lua_State* L); +LUAI_FUNC void luaC_runtilstate(lua_State* L, int statesmask); +LUAI_FUNC void luaC_fullgc(lua_State* L, int isemergency); +LUAI_FUNC GCObject* luaC_newobj(lua_State* L, int tt, size_t sz); +LUAI_FUNC void luaC_barrier_(lua_State* L, GCObject* o, GCObject* v); +LUAI_FUNC void luaC_barrierback_(lua_State* L, Table* o); +LUAI_FUNC void luaC_upvalbarrier_(lua_State* L, UpVal* uv); +LUAI_FUNC void luaC_checkfinalizer(lua_State* L, GCObject* o, Table* mt); +LUAI_FUNC void luaC_upvdeccount(lua_State* L, UpVal* uv); #endif diff --git a/Lua/linit.c b/Lua/linit.c index afcaf98..9abd109 100644 --- a/Lua/linit.c +++ b/Lua/linit.c @@ -40,29 +40,30 @@ ** program */ static const luaL_Reg loadedlibs[] = { - {"_G", luaopen_base}, - {LUA_LOADLIBNAME, luaopen_package}, - {LUA_COLIBNAME, luaopen_coroutine}, - {LUA_TABLIBNAME, luaopen_table}, - {LUA_IOLIBNAME, luaopen_io}, - {LUA_OSLIBNAME, luaopen_os}, - {LUA_STRLIBNAME, luaopen_string}, - {LUA_MATHLIBNAME, luaopen_math}, - {LUA_UTF8LIBNAME, luaopen_utf8}, - {LUA_DBLIBNAME, luaopen_debug}, + {"_G", luaopen_base}, + {LUA_LOADLIBNAME, luaopen_package}, + {LUA_COLIBNAME, luaopen_coroutine}, + {LUA_TABLIBNAME, luaopen_table}, + {LUA_IOLIBNAME, luaopen_io}, + {LUA_OSLIBNAME, luaopen_os}, + {LUA_STRLIBNAME, luaopen_string}, + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_UTF8LIBNAME, luaopen_utf8}, + {LUA_DBLIBNAME, luaopen_debug}, #if defined(LUA_COMPAT_BITLIB) {LUA_BITLIBNAME, luaopen_bit32}, #endif - {NULL, NULL} + {NULL, NULL} }; -LUALIB_API void luaL_openlibs (lua_State *L) { - const luaL_Reg *lib; - /* "require" functions from 'loadedlibs' and set results to global table */ - for (lib = loadedlibs; lib->func; lib++) { - luaL_requiref(L, lib->name, lib->func, 1); - lua_pop(L, 1); /* remove lib */ - } +LUALIB_API void luaL_openlibs(lua_State* L) +{ + const luaL_Reg* lib; + /* "require" functions from 'loadedlibs' and set results to global table */ + for (lib = loadedlibs; lib->func; lib++) + { + luaL_requiref(L, lib->name, lib->func, 1); + lua_pop(L, 1); /* remove lib */ + } } - diff --git a/Lua/liolib.c b/Lua/liolib.c index 1568403..cbc6743 100644 --- a/Lua/liolib.c +++ b/Lua/liolib.c @@ -23,8 +23,6 @@ #include "lualib.h" - - /* ** Change this macro to accept other modes for 'fopen' besides ** the standard ones. @@ -37,10 +35,11 @@ #endif /* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */ -static int l_checkmode (const char *mode) { - return (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && - (*mode != '+' || (++mode, 1)) && /* skip if char is '+' */ - (strspn(mode, L_MODEEXT) == strlen(mode))); /* check extensions */ +static int l_checkmode(const char* mode) +{ + return (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && + (*mode != '+' || (++mode, 1)) && /* skip if char is '+' */ + (strspn(mode, L_MODEEXT) == strlen(mode))); /* check extensions */ } #endif @@ -147,36 +146,39 @@ typedef luaL_Stream LStream; #define isclosed(p) ((p)->closef == NULL) -static int io_type (lua_State *L) { - LStream *p; - luaL_checkany(L, 1); - p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); - if (p == NULL) - lua_pushnil(L); /* not a file */ - else if (isclosed(p)) - lua_pushliteral(L, "closed file"); - else - lua_pushliteral(L, "file"); - return 1; +static int io_type(lua_State* L) +{ + LStream* p; + luaL_checkany(L, 1); + p = (LStream*)luaL_testudata(L, 1, LUA_FILEHANDLE); + if (p == NULL) + lua_pushnil(L); /* not a file */ + else if (isclosed(p)) + lua_pushliteral(L, "closed file"); + else + lua_pushliteral(L, "file"); + return 1; } -static int f_tostring (lua_State *L) { - LStream *p = tolstream(L); - if (isclosed(p)) - lua_pushliteral(L, "file (closed)"); - else - lua_pushfstring(L, "file (%p)", p->f); - return 1; +static int f_tostring(lua_State* L) +{ + LStream* p = tolstream(L); + if (isclosed(p)) + lua_pushliteral(L, "file (closed)"); + else + lua_pushfstring(L, "file (%p)", p->f); + return 1; } -static FILE *tofile (lua_State *L) { - LStream *p = tolstream(L); - if (isclosed(p)) - luaL_error(L, "attempt to use a closed file"); - lua_assert(p->f); - return p->f; +static FILE* tofile(lua_State* L) +{ + LStream* p = tolstream(L); + if (isclosed(p)) + luaL_error(L, "attempt to use a closed file"); + lua_assert(p->f); + return p->f; } @@ -185,11 +187,12 @@ static FILE *tofile (lua_State *L) { ** before opening the actual file; so, if there is a memory error, the ** handle is in a consistent state. */ -static LStream *newprefile (lua_State *L) { - LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream)); - p->closef = NULL; /* mark file handle as 'closed' */ - luaL_setmetatable(L, LUA_FILEHANDLE); - return p; +static LStream* newprefile(lua_State* L) +{ + LStream* p = (LStream*)lua_newuserdata(L, sizeof(LStream)); + p->closef = NULL; /* mark file handle as 'closed' */ + luaL_setmetatable(L, LUA_FILEHANDLE); + return p; } @@ -198,131 +201,147 @@ static LStream *newprefile (lua_State *L) { ** a bug in some versions of the Clang compiler (e.g., clang 3.0 for ** 32 bits). */ -static int aux_close (lua_State *L) { - LStream *p = tolstream(L); - volatile lua_CFunction cf = p->closef; - p->closef = NULL; /* mark stream as closed */ - return (*cf)(L); /* close it */ +static int aux_close(lua_State* L) +{ + LStream* p = tolstream(L); + volatile lua_CFunction cf = p->closef; + p->closef = NULL; /* mark stream as closed */ + return (*cf)(L); /* close it */ } -static int io_close (lua_State *L) { - if (lua_isnone(L, 1)) /* no argument? */ - lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */ - tofile(L); /* make sure argument is an open stream */ - return aux_close(L); +static int io_close(lua_State* L) +{ + if (lua_isnone(L, 1)) /* no argument? */ + lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */ + tofile(L); /* make sure argument is an open stream */ + return aux_close(L); } -static int f_gc (lua_State *L) { - LStream *p = tolstream(L); - if (!isclosed(p) && p->f != NULL) - aux_close(L); /* ignore closed and incompletely open files */ - return 0; +static int f_gc(lua_State* L) +{ + LStream* p = tolstream(L); + if (!isclosed(p) && p->f != NULL) + aux_close(L); /* ignore closed and incompletely open files */ + return 0; } /* ** function to close regular files */ -static int io_fclose (lua_State *L) { - LStream *p = tolstream(L); - int res = fclose(p->f); - return luaL_fileresult(L, (res == 0), NULL); +static int io_fclose(lua_State* L) +{ + LStream* p = tolstream(L); + int res = fclose(p->f); + return luaL_fileresult(L, (res == 0), NULL); } -static LStream *newfile (lua_State *L) { - LStream *p = newprefile(L); - p->f = NULL; - p->closef = &io_fclose; - return p; +static LStream* newfile(lua_State* L) +{ + LStream* p = newprefile(L); + p->f = NULL; + p->closef = &io_fclose; + return p; } -static void opencheck (lua_State *L, const char *fname, const char *mode) { - LStream *p = newfile(L); - p->f = fopen(fname, mode); - if (p->f == NULL) - luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno)); +static void opencheck(lua_State* L, const char* fname, const char* mode) +{ + LStream* p = newfile(L); + p->f = fopen(fname, mode); + if (p->f == NULL) + luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno)); } -static int io_open (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - LStream *p = newfile(L); - const char *md = mode; /* to traverse/check mode */ - luaL_argcheck(L, l_checkmode(md), 2, "invalid mode"); - p->f = fopen(filename, mode); - return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; +static int io_open(lua_State* L) +{ + const char* filename = luaL_checkstring(L, 1); + const char* mode = luaL_optstring(L, 2, "r"); + LStream* p = newfile(L); + const char* md = mode; /* to traverse/check mode */ + luaL_argcheck(L, l_checkmode(md), 2, "invalid mode"); + p->f = fopen(filename, mode); + return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; } /* ** function to close 'popen' files */ -static int io_pclose (lua_State *L) { - LStream *p = tolstream(L); - return luaL_execresult(L, l_pclose(L, p->f)); +static int io_pclose(lua_State* L) +{ + LStream* p = tolstream(L); + return luaL_execresult(L, l_pclose(L, p->f)); } -static int io_popen (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - LStream *p = newprefile(L); - p->f = l_popen(L, filename, mode); - p->closef = &io_pclose; - return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; +static int io_popen(lua_State* L) +{ + const char* filename = luaL_checkstring(L, 1); + const char* mode = luaL_optstring(L, 2, "r"); + LStream* p = newprefile(L); + p->f = l_popen(L, filename, mode); + p->closef = &io_pclose; + return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; } -static int io_tmpfile (lua_State *L) { - LStream *p = newfile(L); - p->f = tmpfile(); - return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1; +static int io_tmpfile(lua_State* L) +{ + LStream* p = newfile(L); + p->f = tmpfile(); + return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1; } -static FILE *getiofile (lua_State *L, const char *findex) { - LStream *p; - lua_getfield(L, LUA_REGISTRYINDEX, findex); - p = (LStream *)lua_touserdata(L, -1); - if (isclosed(p)) - luaL_error(L, "standard %s file is closed", findex + IOPREF_LEN); - return p->f; +static FILE* getiofile(lua_State* L, const char* findex) +{ + LStream* p; + lua_getfield(L, LUA_REGISTRYINDEX, findex); + p = (LStream*)lua_touserdata(L, -1); + if (isclosed(p)) + luaL_error(L, "standard %s file is closed", findex + IOPREF_LEN); + return p->f; } -static int g_iofile (lua_State *L, const char *f, const char *mode) { - if (!lua_isnoneornil(L, 1)) { - const char *filename = lua_tostring(L, 1); - if (filename) - opencheck(L, filename, mode); - else { - tofile(L); /* check that it's a valid file handle */ - lua_pushvalue(L, 1); - } - lua_setfield(L, LUA_REGISTRYINDEX, f); - } - /* return current value */ - lua_getfield(L, LUA_REGISTRYINDEX, f); - return 1; +static int g_iofile(lua_State* L, const char* f, const char* mode) +{ + if (!lua_isnoneornil(L, 1)) + { + const char* filename = lua_tostring(L, 1); + if (filename) + opencheck(L, filename, mode); + else + { + tofile(L); /* check that it's a valid file handle */ + lua_pushvalue(L, 1); + } + lua_setfield(L, LUA_REGISTRYINDEX, f); + } + /* return current value */ + lua_getfield(L, LUA_REGISTRYINDEX, f); + return 1; } -static int io_input (lua_State *L) { - return g_iofile(L, IO_INPUT, "r"); +static int io_input(lua_State* L) +{ + return g_iofile(L, IO_INPUT, "r"); } -static int io_output (lua_State *L) { - return g_iofile(L, IO_OUTPUT, "w"); +static int io_output(lua_State* L) +{ + return g_iofile(L, IO_OUTPUT, "w"); } -static int io_readline (lua_State *L); +static int io_readline(lua_State* L); /* @@ -331,40 +350,47 @@ static int io_readline (lua_State *L); */ #define MAXARGLINE 250 -static void aux_lines (lua_State *L, int toclose) { - int n = lua_gettop(L) - 1; /* number of arguments to read */ - luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments"); - lua_pushinteger(L, n); /* number of arguments to read */ - lua_pushboolean(L, toclose); /* close/not close file when finished */ - lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */ - lua_pushcclosure(L, io_readline, 3 + n); +static void aux_lines(lua_State* L, int toclose) +{ + int n = lua_gettop(L) - 1; /* number of arguments to read */ + luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments"); + lua_pushinteger(L, n); /* number of arguments to read */ + lua_pushboolean(L, toclose); /* close/not close file when finished */ + lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */ + lua_pushcclosure(L, io_readline, 3 + n); } -static int f_lines (lua_State *L) { - tofile(L); /* check that it's a valid file handle */ - aux_lines(L, 0); - return 1; +static int f_lines(lua_State* L) +{ + tofile(L); /* check that it's a valid file handle */ + aux_lines(L, 0); + return 1; } -static int io_lines (lua_State *L) { - int toclose; - if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ - if (lua_isnil(L, 1)) { /* no file name? */ - lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */ - lua_replace(L, 1); /* put it at index 1 */ - tofile(L); /* check that it's a valid file handle */ - toclose = 0; /* do not close it after iteration */ - } - else { /* open a new file */ - const char *filename = luaL_checkstring(L, 1); - opencheck(L, filename, "r"); - lua_replace(L, 1); /* put file at index 1 */ - toclose = 1; /* close it after iteration */ - } - aux_lines(L, toclose); - return 1; +static int io_lines(lua_State* L) +{ + int toclose; + if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ + if (lua_isnil(L, 1)) + { + /* no file name? */ + lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */ + lua_replace(L, 1); /* put it at index 1 */ + tofile(L); /* check that it's a valid file handle */ + toclose = 0; /* do not close it after iteration */ + } + else + { + /* open a new file */ + const char* filename = luaL_checkstring(L, 1); + opencheck(L, filename, "r"); + lua_replace(L, 1); /* put file at index 1 */ + toclose = 1; /* close it after iteration */ + } + aux_lines(L, toclose); + return 1; } @@ -382,48 +408,55 @@ static int io_lines (lua_State *L) { /* auxiliary structure used by 'read_number' */ -typedef struct { - FILE *f; /* file being read */ - int c; /* current character (look ahead) */ - int n; /* number of elements in buffer 'buff' */ - char buff[L_MAXLENNUM + 1]; /* +1 for ending '\0' */ +typedef struct +{ + FILE* f; /* file being read */ + int c; /* current character (look ahead) */ + int n; /* number of elements in buffer 'buff' */ + char buff[L_MAXLENNUM + 1]; /* +1 for ending '\0' */ } RN; /* ** Add current char to buffer (if not out of space) and read next one */ -static int nextc (RN *rn) { - if (rn->n >= L_MAXLENNUM) { /* buffer overflow? */ - rn->buff[0] = '\0'; /* invalidate result */ - return 0; /* fail */ - } - else { - rn->buff[rn->n++] = rn->c; /* save current char */ - rn->c = l_getc(rn->f); /* read next one */ - return 1; - } +static int nextc(RN* rn) +{ + if (rn->n >= L_MAXLENNUM) + { + /* buffer overflow? */ + rn->buff[0] = '\0'; /* invalidate result */ + return 0; /* fail */ + } + else + { + rn->buff[rn->n++] = rn->c; /* save current char */ + rn->c = l_getc(rn->f); /* read next one */ + return 1; + } } /* ** Accept current char if it is in 'set' (of size 2) */ -static int test2 (RN *rn, const char *set) { - if (rn->c == set[0] || rn->c == set[1]) - return nextc(rn); - else return 0; +static int test2(RN* rn, const char* set) +{ + if (rn->c == set[0] || rn->c == set[1]) + return nextc(rn); + else return 0; } /* ** Read a sequence of (hex)digits */ -static int readdigits (RN *rn, int hex) { - int count = 0; - while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn)) - count++; - return count; +static int readdigits(RN* rn, int hex) +{ + int count = 0; + while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn)) + count++; + return count; } @@ -432,260 +465,306 @@ static int readdigits (RN *rn, int hex) { ** Then it calls 'lua_stringtonumber' to check whether the format is ** correct and to convert it to a Lua number */ -static int read_number (lua_State *L, FILE *f) { - RN rn; - int count = 0; - int hex = 0; - char decp[2]; - rn.f = f; rn.n = 0; - decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */ - decp[1] = '.'; /* always accept a dot */ - l_lockfile(rn.f); - do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */ - test2(&rn, "-+"); /* optional signal */ - if (test2(&rn, "00")) { - if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */ - else count = 1; /* count initial '0' as a valid digit */ - } - count += readdigits(&rn, hex); /* integral part */ - if (test2(&rn, decp)) /* decimal point? */ - count += readdigits(&rn, hex); /* fractional part */ - if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) { /* exponent mark? */ - test2(&rn, "-+"); /* exponent signal */ - readdigits(&rn, 0); /* exponent digits */ - } - ungetc(rn.c, rn.f); /* unread look-ahead char */ - l_unlockfile(rn.f); - rn.buff[rn.n] = '\0'; /* finish string */ - if (lua_stringtonumber(L, rn.buff)) /* is this a valid number? */ - return 1; /* ok */ - else { /* invalid format */ - lua_pushnil(L); /* "result" to be removed */ - return 0; /* read fails */ - } +static int read_number(lua_State* L, FILE* f) +{ + RN rn; + int count = 0; + int hex = 0; + char decp[2]; + rn.f = f; + rn.n = 0; + decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */ + decp[1] = '.'; /* always accept a dot */ + l_lockfile(rn.f); + do { rn.c = l_getc(rn.f); } + while (isspace(rn.c)); /* skip spaces */ + test2(&rn, "-+"); /* optional signal */ + if (test2(&rn, "00")) + { + if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */ + else count = 1; /* count initial '0' as a valid digit */ + } + count += readdigits(&rn, hex); /* integral part */ + if (test2(&rn, decp)) /* decimal point? */ + count += readdigits(&rn, hex); /* fractional part */ + if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) + { + /* exponent mark? */ + test2(&rn, "-+"); /* exponent signal */ + readdigits(&rn, 0); /* exponent digits */ + } + ungetc(rn.c, rn.f); /* unread look-ahead char */ + l_unlockfile(rn.f); + rn.buff[rn.n] = '\0'; /* finish string */ + if (lua_stringtonumber(L, rn.buff)) /* is this a valid number? */ + return 1; /* ok */ + else + { + /* invalid format */ + lua_pushnil(L); /* "result" to be removed */ + return 0; /* read fails */ + } } -static int test_eof (lua_State *L, FILE *f) { - int c = getc(f); - ungetc(c, f); /* no-op when c == EOF */ - lua_pushliteral(L, ""); - return (c != EOF); +static int test_eof(lua_State* L, FILE* f) +{ + int c = getc(f); + ungetc(c, f); /* no-op when c == EOF */ + lua_pushliteral(L, ""); + return (c != EOF); } -static int read_line (lua_State *L, FILE *f, int chop) { - luaL_Buffer b; - int c = '\0'; - luaL_buffinit(L, &b); - while (c != EOF && c != '\n') { /* repeat until end of line */ - char *buff = luaL_prepbuffer(&b); /* preallocate buffer */ - int i = 0; - l_lockfile(f); /* no memory errors can happen inside the lock */ - while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n') - buff[i++] = c; - l_unlockfile(f); - luaL_addsize(&b, i); - } - if (!chop && c == '\n') /* want a newline and have one? */ - luaL_addchar(&b, c); /* add ending newline to result */ - luaL_pushresult(&b); /* close buffer */ - /* return ok if read something (either a newline or something else) */ - return (c == '\n' || lua_rawlen(L, -1) > 0); +static int read_line(lua_State* L, FILE* f, int chop) +{ + luaL_Buffer b; + int c = '\0'; + luaL_buffinit(L, &b); + while (c != EOF && c != '\n') + { + /* repeat until end of line */ + char* buff = luaL_prepbuffer(&b); /* preallocate buffer */ + int i = 0; + l_lockfile(f); /* no memory errors can happen inside the lock */ + while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n') + buff[i++] = c; + l_unlockfile(f); + luaL_addsize(&b, i); + } + if (!chop && c == '\n') /* want a newline and have one? */ + luaL_addchar(&b, c); /* add ending newline to result */ + luaL_pushresult(&b); /* close buffer */ + /* return ok if read something (either a newline or something else) */ + return (c == '\n' || lua_rawlen(L, -1) > 0); } -static void read_all (lua_State *L, FILE *f) { - size_t nr; - luaL_Buffer b; - luaL_buffinit(L, &b); - do { /* read file in chunks of LUAL_BUFFERSIZE bytes */ - char *p = luaL_prepbuffer(&b); - nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f); - luaL_addsize(&b, nr); - } while (nr == LUAL_BUFFERSIZE); - luaL_pushresult(&b); /* close buffer */ +static void read_all(lua_State* L, FILE* f) +{ + size_t nr; + luaL_Buffer b; + luaL_buffinit(L, &b); + do + { + /* read file in chunks of LUAL_BUFFERSIZE bytes */ + char* p = luaL_prepbuffer(&b); + nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f); + luaL_addsize(&b, nr); + } + while (nr == LUAL_BUFFERSIZE); + luaL_pushresult(&b); /* close buffer */ } -static int read_chars (lua_State *L, FILE *f, size_t n) { - size_t nr; /* number of chars actually read */ - char *p; - luaL_Buffer b; - luaL_buffinit(L, &b); - p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */ - nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */ - luaL_addsize(&b, nr); - luaL_pushresult(&b); /* close buffer */ - return (nr > 0); /* true iff read something */ +static int read_chars(lua_State* L, FILE* f, size_t n) +{ + size_t nr; /* number of chars actually read */ + char* p; + luaL_Buffer b; + luaL_buffinit(L, &b); + p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */ + nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */ + luaL_addsize(&b, nr); + luaL_pushresult(&b); /* close buffer */ + return (nr > 0); /* true iff read something */ } -static int g_read (lua_State *L, FILE *f, int first) { - int nargs = lua_gettop(L) - 1; - int success; - int n; - clearerr(f); - if (nargs == 0) { /* no arguments? */ - success = read_line(L, f, 1); - n = first+1; /* to return 1 result */ - } - else { /* ensure stack space for all results and for auxlib's buffer */ - luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); - success = 1; - for (n = first; nargs-- && success; n++) { - if (lua_type(L, n) == LUA_TNUMBER) { - size_t l = (size_t)luaL_checkinteger(L, n); - success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); - } - else { - const char *p = luaL_checkstring(L, n); - if (*p == '*') p++; /* skip optional '*' (for compatibility) */ - switch (*p) { - case 'n': /* number */ - success = read_number(L, f); - break; - case 'l': /* line */ - success = read_line(L, f, 1); - break; - case 'L': /* line with end-of-line */ - success = read_line(L, f, 0); - break; - case 'a': /* file */ - read_all(L, f); /* read entire file */ - success = 1; /* always success */ - break; - default: - return luaL_argerror(L, n, "invalid format"); - } - } - } - } - if (ferror(f)) - return luaL_fileresult(L, 0, NULL); - if (!success) { - lua_pop(L, 1); /* remove last result */ - lua_pushnil(L); /* push nil instead */ - } - return n - first; +static int g_read(lua_State* L, FILE* f, int first) +{ + int nargs = lua_gettop(L) - 1; + int success; + int n; + clearerr(f); + if (nargs == 0) + { + /* no arguments? */ + success = read_line(L, f, 1); + n = first + 1; /* to return 1 result */ + } + else + { + /* ensure stack space for all results and for auxlib's buffer */ + luaL_checkstack(L, nargs + LUA_MINSTACK, "too many arguments"); + success = 1; + for (n = first; nargs-- && success; n++) + { + if (lua_type(L, n) == LUA_TNUMBER) + { + size_t l = (size_t)luaL_checkinteger(L, n); + success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); + } + else + { + const char* p = luaL_checkstring(L, n); + if (*p == '*') p++; /* skip optional '*' (for compatibility) */ + switch (*p) + { + case 'n': /* number */ + success = read_number(L, f); + break; + case 'l': /* line */ + success = read_line(L, f, 1); + break; + case 'L': /* line with end-of-line */ + success = read_line(L, f, 0); + break; + case 'a': /* file */ + read_all(L, f); /* read entire file */ + success = 1; /* always success */ + break; + default: + return luaL_argerror(L, n, "invalid format"); + } + } + } + } + if (ferror(f)) + return luaL_fileresult(L, 0, NULL); + if (!success) + { + lua_pop(L, 1); /* remove last result */ + lua_pushnil(L); /* push nil instead */ + } + return n - first; } -static int io_read (lua_State *L) { - return g_read(L, getiofile(L, IO_INPUT), 1); +static int io_read(lua_State* L) +{ + return g_read(L, getiofile(L, IO_INPUT), 1); } -static int f_read (lua_State *L) { - return g_read(L, tofile(L), 2); +static int f_read(lua_State* L) +{ + return g_read(L, tofile(L), 2); } -static int io_readline (lua_State *L) { - LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); - int i; - int n = (int)lua_tointeger(L, lua_upvalueindex(2)); - if (isclosed(p)) /* file is already closed? */ - return luaL_error(L, "file is already closed"); - lua_settop(L , 1); - luaL_checkstack(L, n, "too many arguments"); - for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ - lua_pushvalue(L, lua_upvalueindex(3 + i)); - n = g_read(L, p->f, 2); /* 'n' is number of results */ - lua_assert(n > 0); /* should return at least a nil */ - if (lua_toboolean(L, -n)) /* read at least one value? */ - return n; /* return them */ - else { /* first result is nil: EOF or error */ - if (n > 1) { /* is there error information? */ - /* 2nd result is error message */ - return luaL_error(L, "%s", lua_tostring(L, -n + 1)); - } - if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ - lua_settop(L, 0); - lua_pushvalue(L, lua_upvalueindex(1)); - aux_close(L); /* close it */ - } - return 0; - } +static int io_readline(lua_State* L) +{ + LStream* p = (LStream*)lua_touserdata(L, lua_upvalueindex(1)); + int i; + int n = (int)lua_tointeger(L, lua_upvalueindex(2)); + if (isclosed(p)) /* file is already closed? */ + return luaL_error(L, "file is already closed"); + lua_settop(L, 1); + luaL_checkstack(L, n, "too many arguments"); + for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ + lua_pushvalue(L, lua_upvalueindex(3 + i)); + n = g_read(L, p->f, 2); /* 'n' is number of results */ + lua_assert(n > 0); /* should return at least a nil */ + if (lua_toboolean(L, -n)) /* read at least one value? */ + return n; /* return them */ + else + { + /* first result is nil: EOF or error */ + if (n > 1) + { + /* is there error information? */ + /* 2nd result is error message */ + return luaL_error(L, "%s", lua_tostring(L, -n + 1)); + } + if (lua_toboolean(L, lua_upvalueindex(3))) + { + /* generator created file? */ + lua_settop(L, 0); + lua_pushvalue(L, lua_upvalueindex(1)); + aux_close(L); /* close it */ + } + return 0; + } } /* }====================================================== */ -static int g_write (lua_State *L, FILE *f, int arg) { - int nargs = lua_gettop(L) - arg; - int status = 1; - for (; nargs--; arg++) { - if (lua_type(L, arg) == LUA_TNUMBER) { - /* optimization: could be done exactly as for strings */ - int len = lua_isinteger(L, arg) - ? fprintf(f, LUA_INTEGER_FMT, - (LUAI_UACINT)lua_tointeger(L, arg)) - : fprintf(f, LUA_NUMBER_FMT, - (LUAI_UACNUMBER)lua_tonumber(L, arg)); - status = status && (len > 0); - } - else { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - status = status && (fwrite(s, sizeof(char), l, f) == l); - } - } - if (status) return 1; /* file handle already on stack top */ - else return luaL_fileresult(L, status, NULL); +static int g_write(lua_State* L, FILE* f, int arg) +{ + int nargs = lua_gettop(L) - arg; + int status = 1; + for (; nargs--; arg++) + { + if (lua_type(L, arg) == LUA_TNUMBER) + { + /* optimization: could be done exactly as for strings */ + int len = lua_isinteger(L, arg) + ? fprintf(f, LUA_INTEGER_FMT, + (LUAI_UACINT)lua_tointeger(L, arg)) + : fprintf(f, LUA_NUMBER_FMT, + (LUAI_UACNUMBER)lua_tonumber(L, arg)); + status = status && (len > 0); + } + else + { + size_t l; + const char* s = luaL_checklstring(L, arg, &l); + status = status && (fwrite(s, sizeof(char), l, f) == l); + } + } + if (status) return 1; /* file handle already on stack top */ + else return luaL_fileresult(L, status, NULL); } -static int io_write (lua_State *L) { - return g_write(L, getiofile(L, IO_OUTPUT), 1); +static int io_write(lua_State* L) +{ + return g_write(L, getiofile(L, IO_OUTPUT), 1); } -static int f_write (lua_State *L) { - FILE *f = tofile(L); - lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ - return g_write(L, f, 2); +static int f_write(lua_State* L) +{ + FILE* f = tofile(L); + lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ + return g_write(L, f, 2); } -static int f_seek (lua_State *L) { - static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; - static const char *const modenames[] = {"set", "cur", "end", NULL}; - FILE *f = tofile(L); - int op = luaL_checkoption(L, 2, "cur", modenames); - lua_Integer p3 = luaL_optinteger(L, 3, 0); - l_seeknum offset = (l_seeknum)p3; - luaL_argcheck(L, (lua_Integer)offset == p3, 3, - "not an integer in proper range"); - op = l_fseek(f, offset, mode[op]); - if (op) - return luaL_fileresult(L, 0, NULL); /* error */ - else { - lua_pushinteger(L, (lua_Integer)l_ftell(f)); - return 1; - } +static int f_seek(lua_State* L) +{ + static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; + static const char* const modenames[] = {"set", "cur", "end", NULL}; + FILE* f = tofile(L); + int op = luaL_checkoption(L, 2, "cur", modenames); + lua_Integer p3 = luaL_optinteger(L, 3, 0); + l_seeknum offset = (l_seeknum)p3; + luaL_argcheck(L, (lua_Integer)offset == p3, 3, + "not an integer in proper range"); + op = l_fseek(f, offset, mode[op]); + if (op) + return luaL_fileresult(L, 0, NULL); /* error */ + else + { + lua_pushinteger(L, (lua_Integer)l_ftell(f)); + return 1; + } } -static int f_setvbuf (lua_State *L) { - static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; - static const char *const modenames[] = {"no", "full", "line", NULL}; - FILE *f = tofile(L); - int op = luaL_checkoption(L, 2, NULL, modenames); - lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); - int res = setvbuf(f, NULL, mode[op], (size_t)sz); - return luaL_fileresult(L, res == 0, NULL); +static int f_setvbuf(lua_State* L) +{ + static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; + static const char* const modenames[] = {"no", "full", "line", NULL}; + FILE* f = tofile(L); + int op = luaL_checkoption(L, 2, NULL, modenames); + lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); + int res = setvbuf(f, NULL, mode[op], (size_t)sz); + return luaL_fileresult(L, res == 0, NULL); } - -static int io_flush (lua_State *L) { - return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); +static int io_flush(lua_State* L) +{ + return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); } -static int f_flush (lua_State *L) { - return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL); +static int f_flush(lua_State* L) +{ + return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL); } @@ -693,18 +772,18 @@ static int f_flush (lua_State *L) { ** functions for 'io' library */ static const luaL_Reg iolib[] = { - {"close", io_close}, - {"flush", io_flush}, - {"input", io_input}, - {"lines", io_lines}, - {"open", io_open}, - {"output", io_output}, - {"popen", io_popen}, - {"read", io_read}, - {"tmpfile", io_tmpfile}, - {"type", io_type}, - {"write", io_write}, - {NULL, NULL} + {"close", io_close}, + {"flush", io_flush}, + {"input", io_input}, + {"lines", io_lines}, + {"open", io_open}, + {"output", io_output}, + {"popen", io_popen}, + {"read", io_read}, + {"tmpfile", io_tmpfile}, + {"type", io_type}, + {"write", io_write}, + {NULL, NULL} }; @@ -712,60 +791,64 @@ static const luaL_Reg iolib[] = { ** methods for file handles */ static const luaL_Reg flib[] = { - {"close", io_close}, - {"flush", f_flush}, - {"lines", f_lines}, - {"read", f_read}, - {"seek", f_seek}, - {"setvbuf", f_setvbuf}, - {"write", f_write}, - {"__gc", f_gc}, - {"__tostring", f_tostring}, - {NULL, NULL} + {"close", io_close}, + {"flush", f_flush}, + {"lines", f_lines}, + {"read", f_read}, + {"seek", f_seek}, + {"setvbuf", f_setvbuf}, + {"write", f_write}, + {"__gc", f_gc}, + {"__tostring", f_tostring}, + {NULL, NULL} }; -static void createmeta (lua_State *L) { - luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ - lua_pushvalue(L, -1); /* push metatable */ - lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */ - lua_pop(L, 1); /* pop new metatable */ +static void createmeta(lua_State* L) +{ + luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ + lua_pushvalue(L, -1); /* push metatable */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ + luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */ + lua_pop(L, 1); /* pop new metatable */ } /* ** function to (not) close the standard files stdin, stdout, and stderr */ -static int io_noclose (lua_State *L) { - LStream *p = tolstream(L); - p->closef = &io_noclose; /* keep file opened */ - lua_pushnil(L); - lua_pushliteral(L, "cannot close standard file"); - return 2; +static int io_noclose(lua_State* L) +{ + LStream* p = tolstream(L); + p->closef = &io_noclose; /* keep file opened */ + lua_pushnil(L); + lua_pushliteral(L, "cannot close standard file"); + return 2; } -static void createstdfile (lua_State *L, FILE *f, const char *k, - const char *fname) { - LStream *p = newprefile(L); - p->f = f; - p->closef = &io_noclose; - if (k != NULL) { - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */ - } - lua_setfield(L, -2, fname); /* add file to module */ +static void createstdfile(lua_State* L, FILE* f, const char* k, + const char* fname) +{ + LStream* p = newprefile(L); + p->f = f; + p->closef = &io_noclose; + if (k != NULL) + { + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */ + } + lua_setfield(L, -2, fname); /* add file to module */ } -LUAMOD_API int luaopen_io (lua_State *L) { - luaL_newlib(L, iolib); /* new module */ - createmeta(L); - /* create (and set) default files */ - createstdfile(L, stdin, IO_INPUT, "stdin"); - createstdfile(L, stdout, IO_OUTPUT, "stdout"); - createstdfile(L, stderr, NULL, "stderr"); - return 1; +LUAMOD_API int luaopen_io(lua_State* L) +{ + luaL_newlib(L, iolib); /* new module */ + createmeta(L); + /* create (and set) default files */ + createstdfile(L, stdin, IO_INPUT, "stdin"); + createstdfile(L, stdout, IO_OUTPUT, "stdout"); + createstdfile(L, stderr, NULL, "stderr"); + return 1; } - diff --git a/Lua/llex.c b/Lua/llex.c index 7032827..d0b6dbd 100644 --- a/Lua/llex.c +++ b/Lua/llex.c @@ -28,94 +28,106 @@ #include "lzio.h" - #define next(ls) (ls->current = zgetc(ls->z)) - #define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') /* ORDER RESERVED */ -static const char *const luaX_tokens [] = { - "and", "break", "do", "else", "elseif", - "end", "false", "for", "function", "goto", "if", - "in", "local", "nil", "not", "or", "repeat", - "return", "then", "true", "until", "while", - "//", "..", "...", "==", ">=", "<=", "~=", - "<<", ">>", "::", "", - "", "", "", "" +static const char* const luaX_tokens[] = { + "and", "break", "do", "else", "elseif", + "end", "false", "for", "function", "goto", "if", + "in", "local", "nil", "not", "or", "repeat", + "return", "then", "true", "until", "while", + "//", "..", "...", "==", ">=", "<=", "~=", + "<<", ">>", "::", "", + "", "", "", "" }; #define save_and_next(ls) (save(ls, ls->current), next(ls)) -static l_noret lexerror (LexState *ls, const char *msg, int token); +static l_noret lexerror(LexState* ls, const char* msg, int token); -static void save (LexState *ls, int c) { - Mbuffer *b = ls->buff; - if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { - size_t newsize; - if (luaZ_sizebuffer(b) >= MAX_SIZE/2) - lexerror(ls, "lexical element too long", 0); - newsize = luaZ_sizebuffer(b) * 2; - luaZ_resizebuffer(ls->L, b, newsize); - } - b->buffer[luaZ_bufflen(b)++] = cast(char, c); +static void save(LexState* ls, int c) +{ + Mbuffer* b = ls->buff; + if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) + { + size_t newsize; + if (luaZ_sizebuffer(b) >= MAX_SIZE / 2) + lexerror(ls, "lexical element too long", 0); + newsize = luaZ_sizebuffer(b) * 2; + luaZ_resizebuffer(ls->L, b, newsize); + } + b->buffer[luaZ_bufflen(b)++] = cast(char, c); } -void luaX_init (lua_State *L) { - int i; - TString *e = luaS_newliteral(L, LUA_ENV); /* create env name */ - luaC_fix(L, obj2gco(e)); /* never collect this name */ - for (i=0; iextra = cast_byte(i+1); /* reserved word */ - } +void luaX_init(lua_State* L) +{ + int i; + TString* e = luaS_newliteral(L, LUA_ENV); /* create env name */ + luaC_fix(L, obj2gco(e)); /* never collect this name */ + for (i = 0; i < NUM_RESERVED; i++) + { + TString* ts = luaS_new(L, luaX_tokens[i]); + luaC_fix(L, obj2gco(ts)); /* reserved words are never collected */ + ts->extra = cast_byte(i+1); /* reserved word */ + } } -const char *luaX_token2str (LexState *ls, int token) { - if (token < FIRST_RESERVED) { /* single-byte symbols? */ - lua_assert(token == cast_uchar(token)); - return luaO_pushfstring(ls->L, "'%c'", token); - } - else { - const char *s = luaX_tokens[token - FIRST_RESERVED]; - if (token < TK_EOS) /* fixed format (symbols and reserved words)? */ - return luaO_pushfstring(ls->L, "'%s'", s); - else /* names, strings, and numerals */ - return s; - } +const char* luaX_token2str(LexState* ls, int token) +{ + if (token < FIRST_RESERVED) + { + /* single-byte symbols? */ + lua_assert(token == cast_uchar(token)); + return luaO_pushfstring(ls->L, "'%c'", token); + } + else + { + const char* s = luaX_tokens[token - FIRST_RESERVED]; + if (token < TK_EOS) /* fixed format (symbols and reserved words)? */ + return luaO_pushfstring(ls->L, "'%s'", s); + else /* names, strings, and numerals */ + return s; + } } -static const char *txtToken (LexState *ls, int token) { - switch (token) { - case TK_NAME: case TK_STRING: - case TK_FLT: case TK_INT: - save(ls, '\0'); - return luaO_pushfstring(ls->L, "'%s'", luaZ_buffer(ls->buff)); - default: - return luaX_token2str(ls, token); - } +static const char* txtToken(LexState* ls, int token) +{ + switch (token) + { + case TK_NAME: + case TK_STRING: + case TK_FLT: + case TK_INT: + save(ls, '\0'); + return luaO_pushfstring(ls->L, "'%s'", luaZ_buffer(ls->buff)); + default: + return luaX_token2str(ls, token); + } } -static l_noret lexerror (LexState *ls, const char *msg, int token) { - msg = luaG_addinfo(ls->L, msg, ls->source, ls->linenumber); - if (token) - luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token)); - luaD_throw(ls->L, LUA_ERRSYNTAX); +static l_noret lexerror(LexState* ls, const char* msg, int token) +{ + msg = luaG_addinfo(ls->L, msg, ls->source, ls->linenumber); + if (token) + luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token)); + luaD_throw(ls->L, LUA_ERRSYNTAX); } -l_noret luaX_syntaxerror (LexState *ls, const char *msg) { - lexerror(ls, msg, ls->t.token); +l_noret luaX_syntaxerror(LexState* ls, const char* msg) +{ + lexerror(ls, msg, ls->t.token); } @@ -124,23 +136,28 @@ l_noret luaX_syntaxerror (LexState *ls, const char *msg) { ** it will not be collected until the end of the compilation ** (by that time it should be anchored somewhere) */ -TString *luaX_newstring (LexState *ls, const char *str, size_t l) { - lua_State *L = ls->L; - TValue *o; /* entry for 'str' */ - TString *ts = luaS_newlstr(L, str, l); /* create new string */ - setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ - o = luaH_set(L, ls->h, L->top - 1); - if (ttisnil(o)) { /* not in use yet? */ - /* boolean value does not need GC barrier; - table has no metatable, so it does not need to invalidate cache */ - setbvalue(o, 1); /* t[string] = true */ - luaC_checkGC(L); - } - else { /* string already present */ - ts = tsvalue(keyfromval(o)); /* re-use value previously stored */ - } - L->top--; /* remove string from stack */ - return ts; +TString* luaX_newstring(LexState* ls, const char* str, size_t l) +{ + lua_State* L = ls->L; + TValue* o; /* entry for 'str' */ + TString* ts = luaS_newlstr(L, str, l); /* create new string */ + setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ + o = luaH_set(L, ls->h, L->top - 1); + if (ttisnil(o)) + { + /* not in use yet? */ + /* boolean value does not need GC barrier; + table has no metatable, so it does not need to invalidate cache */ + setbvalue(o, 1); /* t[string] = true */ + luaC_checkGC(L); + } + else + { + /* string already present */ + ts = tsvalue(keyfromval(o)); /* re-use value previously stored */ + } + L->top--; /* remove string from stack */ + return ts; } @@ -148,34 +165,35 @@ TString *luaX_newstring (LexState *ls, const char *str, size_t l) { ** increment line number and skips newline sequence (any of ** \n, \r, \n\r, or \r\n) */ -static void inclinenumber (LexState *ls) { - int old = ls->current; - lua_assert(currIsNewline(ls)); - next(ls); /* skip '\n' or '\r' */ - if (currIsNewline(ls) && ls->current != old) - next(ls); /* skip '\n\r' or '\r\n' */ - if (++ls->linenumber >= MAX_INT) - lexerror(ls, "chunk has too many lines", 0); +static void inclinenumber(LexState* ls) +{ + int old = ls->current; + lua_assert(currIsNewline(ls)); + next(ls); /* skip '\n' or '\r' */ + if (currIsNewline(ls) && ls->current != old) + next(ls); /* skip '\n\r' or '\r\n' */ + if (++ls->linenumber >= MAX_INT) + lexerror(ls, "chunk has too many lines", 0); } -void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, - int firstchar) { - ls->t.token = 0; - ls->L = L; - ls->current = firstchar; - ls->lookahead.token = TK_EOS; /* no look-ahead token */ - ls->z = z; - ls->fs = NULL; - ls->linenumber = 1; - ls->lastline = 1; - ls->source = source; - ls->envn = luaS_newliteral(L, LUA_ENV); /* get env name */ - luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ +void luaX_setinput(lua_State* L, LexState* ls, ZIO* z, TString* source, + int firstchar) +{ + ls->t.token = 0; + ls->L = L; + ls->current = firstchar; + ls->lookahead.token = TK_EOS; /* no look-ahead token */ + ls->z = z; + ls->fs = NULL; + ls->linenumber = 1; + ls->lastline = 1; + ls->source = source; + ls->envn = luaS_newliteral(L, LUA_ENV); /* get env name */ + luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ } - /* ** ======================================================= ** LEXICAL ANALYZER @@ -183,12 +201,14 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, */ -static int check_next1 (LexState *ls, int c) { - if (ls->current == c) { - next(ls); - return 1; - } - else return 0; +static int check_next1(LexState* ls, int c) +{ + if (ls->current == c) + { + next(ls); + return 1; + } + else return 0; } @@ -196,13 +216,15 @@ static int check_next1 (LexState *ls, int c) { ** Check whether current char is in set 'set' (with two chars) and ** saves it */ -static int check_next2 (LexState *ls, const char *set) { - lua_assert(set[2] == '\0'); - if (ls->current == set[0] || ls->current == set[1]) { - save_and_next(ls); - return 1; - } - else return 0; +static int check_next2(LexState* ls, const char* set) +{ + lua_assert(set[2] == '\0'); + if (ls->current == set[0] || ls->current == set[1]) + { + save_and_next(ls); + return 1; + } + else return 0; } @@ -211,35 +233,39 @@ static int check_next2 (LexState *ls, const char *set) { ** this function is quite liberal in what it accepts, as 'luaO_str2num' ** will reject ill-formed numerals. */ -static int read_numeral (LexState *ls, SemInfo *seminfo) { - TValue obj; - const char *expo = "Ee"; - int first = ls->current; - lua_assert(lisdigit(ls->current)); - save_and_next(ls); - if (first == '0' && check_next2(ls, "xX")) /* hexadecimal? */ - expo = "Pp"; - for (;;) { - if (check_next2(ls, expo)) /* exponent part? */ - check_next2(ls, "-+"); /* optional exponent sign */ - if (lisxdigit(ls->current)) - save_and_next(ls); - else if (ls->current == '.') - save_and_next(ls); - else break; - } - save(ls, '\0'); - if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0) /* format error? */ - lexerror(ls, "malformed number", TK_FLT); - if (ttisinteger(&obj)) { - seminfo->i = ivalue(&obj); - return TK_INT; - } - else { - lua_assert(ttisfloat(&obj)); - seminfo->r = fltvalue(&obj); - return TK_FLT; - } +static int read_numeral(LexState* ls, SemInfo* seminfo) +{ + TValue obj; + const char* expo = "Ee"; + int first = ls->current; + lua_assert(lisdigit(ls->current)); + save_and_next(ls); + if (first == '0' && check_next2(ls, "xX")) /* hexadecimal? */ + expo = "Pp"; + for (;;) + { + if (check_next2(ls, expo)) /* exponent part? */ + check_next2(ls, "-+"); /* optional exponent sign */ + if (lisxdigit(ls->current)) + save_and_next(ls); + else if (ls->current == '.') + save_and_next(ls); + else break; + } + save(ls, '\0'); + if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0) /* format error? */ + lexerror(ls, "malformed number", TK_FLT); + if (ttisinteger(&obj)) + { + seminfo->i = ivalue(&obj); + return TK_INT; + } + else + { + lua_assert(ttisfloat(&obj)); + seminfo->r = fltvalue(&obj); + return TK_FLT; + } } @@ -248,318 +274,422 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) { ** its number of '='s; otherwise, return a negative number (-1 iff there ** are no '='s after initial bracket) */ -static int skip_sep (LexState *ls) { - int count = 0; - int s = ls->current; - lua_assert(s == '[' || s == ']'); - save_and_next(ls); - while (ls->current == '=') { - save_and_next(ls); - count++; - } - return (ls->current == s) ? count : (-count) - 1; +static int skip_sep(LexState* ls) +{ + int count = 0; + int s = ls->current; + lua_assert(s == '[' || s == ']'); + save_and_next(ls); + while (ls->current == '=') + { + save_and_next(ls); + count++; + } + return (ls->current == s) ? count : (-count) - 1; } -static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { - int line = ls->linenumber; /* initial line (for error message) */ - save_and_next(ls); /* skip 2nd '[' */ - if (currIsNewline(ls)) /* string starts with a newline? */ - inclinenumber(ls); /* skip it */ - for (;;) { - switch (ls->current) { - case EOZ: { /* error */ - const char *what = (seminfo ? "string" : "comment"); - const char *msg = luaO_pushfstring(ls->L, - "unfinished long %s (starting at line %d)", what, line); - lexerror(ls, msg, TK_EOS); - break; /* to avoid warnings */ - } - case ']': { - if (skip_sep(ls) == sep) { - save_and_next(ls); /* skip 2nd ']' */ - goto endloop; - } - break; - } - case '\n': case '\r': { - save(ls, '\n'); - inclinenumber(ls); - if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ - break; - } - default: { - if (seminfo) save_and_next(ls); - else next(ls); - } - } - } endloop: - if (seminfo) - seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), - luaZ_bufflen(ls->buff) - 2*(2 + sep)); +static void read_long_string(LexState* ls, SemInfo* seminfo, int sep) +{ + int line = ls->linenumber; /* initial line (for error message) */ + save_and_next(ls); /* skip 2nd '[' */ + if (currIsNewline(ls)) /* string starts with a newline? */ + inclinenumber(ls); /* skip it */ + for (;;) + { + switch (ls->current) + { + case EOZ: + { + /* error */ + const char* what = (seminfo ? "string" : "comment"); + const char* msg = luaO_pushfstring(ls->L, + "unfinished long %s (starting at line %d)", what, line); + lexerror(ls, msg, TK_EOS); + break; /* to avoid warnings */ + } + case ']': + { + if (skip_sep(ls) == sep) + { + save_and_next(ls); /* skip 2nd ']' */ + goto endloop; + } + break; + } + case '\n': + case '\r': + { + save(ls, '\n'); + inclinenumber(ls); + if (!seminfo) + luaZ_resetbuffer(ls->buff); /* avoid wasting space */ + break; + } + default: + { + if (seminfo) + save_and_next(ls); + else + next(ls); + } + } + } +endloop: + if (seminfo) + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), + luaZ_bufflen(ls->buff) - 2 * (2 + sep)); } -static void esccheck (LexState *ls, int c, const char *msg) { - if (!c) { - if (ls->current != EOZ) - save_and_next(ls); /* add current to buffer for error message */ - lexerror(ls, msg, TK_STRING); - } +static void esccheck(LexState* ls, int c, const char* msg) +{ + if (!c) + { + if (ls->current != EOZ) + save_and_next(ls); /* add current to buffer for error message */ + lexerror(ls, msg, TK_STRING); + } } -static int gethexa (LexState *ls) { - save_and_next(ls); - esccheck (ls, lisxdigit(ls->current), "hexadecimal digit expected"); - return luaO_hexavalue(ls->current); +static int gethexa(LexState* ls) +{ + save_and_next(ls); + esccheck(ls, lisxdigit(ls->current), "hexadecimal digit expected"); + return luaO_hexavalue(ls->current); } -static int readhexaesc (LexState *ls) { - int r = gethexa(ls); - r = (r << 4) + gethexa(ls); - luaZ_buffremove(ls->buff, 2); /* remove saved chars from buffer */ - return r; +static int readhexaesc(LexState* ls) +{ + int r = gethexa(ls); + r = (r << 4) + gethexa(ls); + luaZ_buffremove(ls->buff, 2); /* remove saved chars from buffer */ + return r; } -static unsigned long readutf8esc (LexState *ls) { - unsigned long r; - int i = 4; /* chars to be removed: '\', 'u', '{', and first digit */ - save_and_next(ls); /* skip 'u' */ - esccheck(ls, ls->current == '{', "missing '{'"); - r = gethexa(ls); /* must have at least one digit */ - while ((save_and_next(ls), lisxdigit(ls->current))) { - i++; - r = (r << 4) + luaO_hexavalue(ls->current); - esccheck(ls, r <= 0x10FFFF, "UTF-8 value too large"); - } - esccheck(ls, ls->current == '}', "missing '}'"); - next(ls); /* skip '}' */ - luaZ_buffremove(ls->buff, i); /* remove saved chars from buffer */ - return r; +static unsigned long readutf8esc(LexState* ls) +{ + unsigned long r; + int i = 4; /* chars to be removed: '\', 'u', '{', and first digit */ + save_and_next(ls); /* skip 'u' */ + esccheck(ls, ls->current == '{', "missing '{'"); + r = gethexa(ls); /* must have at least one digit */ + while ((save_and_next(ls), lisxdigit(ls->current))) + { + i++; + r = (r << 4) + luaO_hexavalue(ls->current); + esccheck(ls, r <= 0x10FFFF, "UTF-8 value too large"); + } + esccheck(ls, ls->current == '}', "missing '}'"); + next(ls); /* skip '}' */ + luaZ_buffremove(ls->buff, i); /* remove saved chars from buffer */ + return r; } -static void utf8esc (LexState *ls) { - char buff[UTF8BUFFSZ]; - int n = luaO_utf8esc(buff, readutf8esc(ls)); - for (; n > 0; n--) /* add 'buff' to string */ - save(ls, buff[UTF8BUFFSZ - n]); +static void utf8esc(LexState* ls) +{ + char buff[UTF8BUFFSZ]; + int n = luaO_utf8esc(buff, readutf8esc(ls)); + for (; n > 0; n--) /* add 'buff' to string */ + save(ls, buff[UTF8BUFFSZ - n]); } -static int readdecesc (LexState *ls) { - int i; - int r = 0; /* result accumulator */ - for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */ - r = 10*r + ls->current - '0'; - save_and_next(ls); - } - esccheck(ls, r <= UCHAR_MAX, "decimal escape too large"); - luaZ_buffremove(ls->buff, i); /* remove read digits from buffer */ - return r; +static int readdecesc(LexState* ls) +{ + int i; + int r = 0; /* result accumulator */ + for (i = 0; i < 3 && lisdigit(ls->current); i++) + { + /* read up to 3 digits */ + r = 10 * r + ls->current - '0'; + save_and_next(ls); + } + esccheck(ls, r <= UCHAR_MAX, "decimal escape too large"); + luaZ_buffremove(ls->buff, i); /* remove read digits from buffer */ + return r; } -static void read_string (LexState *ls, int del, SemInfo *seminfo) { - save_and_next(ls); /* keep delimiter (for error messages) */ - while (ls->current != del) { - switch (ls->current) { - case EOZ: - lexerror(ls, "unfinished string", TK_EOS); - break; /* to avoid warnings */ - case '\n': - case '\r': - lexerror(ls, "unfinished string", TK_STRING); - break; /* to avoid warnings */ - case '\\': { /* escape sequences */ - int c; /* final character to be saved */ - save_and_next(ls); /* keep '\\' for error messages */ - switch (ls->current) { - case 'a': c = '\a'; goto read_save; - case 'b': c = '\b'; goto read_save; - case 'f': c = '\f'; goto read_save; - case 'n': c = '\n'; goto read_save; - case 'r': c = '\r'; goto read_save; - case 't': c = '\t'; goto read_save; - case 'v': c = '\v'; goto read_save; - case 'x': c = readhexaesc(ls); goto read_save; - case 'u': utf8esc(ls); goto no_save; - case '\n': case '\r': - inclinenumber(ls); c = '\n'; goto only_save; - case '\\': case '\"': case '\'': - c = ls->current; goto read_save; - case EOZ: goto no_save; /* will raise an error next loop */ - case 'z': { /* zap following span of spaces */ - luaZ_buffremove(ls->buff, 1); /* remove '\\' */ - next(ls); /* skip the 'z' */ - while (lisspace(ls->current)) { - if (currIsNewline(ls)) inclinenumber(ls); - else next(ls); - } - goto no_save; - } - default: { - esccheck(ls, lisdigit(ls->current), "invalid escape sequence"); - c = readdecesc(ls); /* digital escape '\ddd' */ - goto only_save; - } - } - read_save: - next(ls); - /* go through */ - only_save: - luaZ_buffremove(ls->buff, 1); /* remove '\\' */ - save(ls, c); - /* go through */ - no_save: break; - } - default: - save_and_next(ls); - } - } - save_and_next(ls); /* skip delimiter */ - seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, - luaZ_bufflen(ls->buff) - 2); +static void read_string(LexState* ls, int del, SemInfo* seminfo) +{ + save_and_next(ls); /* keep delimiter (for error messages) */ + while (ls->current != del) + { + switch (ls->current) + { + case EOZ: + lexerror(ls, "unfinished string", TK_EOS); + break; /* to avoid warnings */ + case '\n': + case '\r': + lexerror(ls, "unfinished string", TK_STRING); + break; /* to avoid warnings */ + case '\\': + { + /* escape sequences */ + int c; /* final character to be saved */ + save_and_next(ls); /* keep '\\' for error messages */ + switch (ls->current) + { + case 'a': c = '\a'; + goto read_save; + case 'b': c = '\b'; + goto read_save; + case 'f': c = '\f'; + goto read_save; + case 'n': c = '\n'; + goto read_save; + case 'r': c = '\r'; + goto read_save; + case 't': c = '\t'; + goto read_save; + case 'v': c = '\v'; + goto read_save; + case 'x': c = readhexaesc(ls); + goto read_save; + case 'u': utf8esc(ls); + goto no_save; + case '\n': + case '\r': + inclinenumber(ls); + c = '\n'; + goto only_save; + case '\\': + case '\"': + case '\'': + c = ls->current; + goto read_save; + case EOZ: goto no_save; /* will raise an error next loop */ + case 'z': + { + /* zap following span of spaces */ + luaZ_buffremove(ls->buff, 1); /* remove '\\' */ + next(ls); /* skip the 'z' */ + while (lisspace(ls->current)) + { + if (currIsNewline(ls)) inclinenumber(ls); + else + next(ls); + } + goto no_save; + } + default: + { + esccheck(ls, lisdigit(ls->current), "invalid escape sequence"); + c = readdecesc(ls); /* digital escape '\ddd' */ + goto only_save; + } + } + read_save: + next(ls); + /* go through */ + only_save: + luaZ_buffremove(ls->buff, 1); /* remove '\\' */ + save(ls, c); + /* go through */ + no_save: break; + } + default: + save_and_next(ls); + } + } + save_and_next(ls); /* skip delimiter */ + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, + luaZ_bufflen(ls->buff) - 2); } -static int llex (LexState *ls, SemInfo *seminfo) { - luaZ_resetbuffer(ls->buff); - for (;;) { - switch (ls->current) { - case '\n': case '\r': { /* line breaks */ - inclinenumber(ls); - break; - } - case ' ': case '\f': case '\t': case '\v': { /* spaces */ - next(ls); - break; - } - case '-': { /* '-' or '--' (comment) */ - next(ls); - if (ls->current != '-') return '-'; - /* else is a comment */ - next(ls); - if (ls->current == '[') { /* long comment? */ - int sep = skip_sep(ls); - luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */ - if (sep >= 0) { - read_long_string(ls, NULL, sep); /* skip long comment */ - luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ - break; - } - } - /* else short comment */ - while (!currIsNewline(ls) && ls->current != EOZ) - next(ls); /* skip until end of line (or end of file) */ - break; - } - case '[': { /* long string or simply '[' */ - int sep = skip_sep(ls); - if (sep >= 0) { - read_long_string(ls, seminfo, sep); - return TK_STRING; - } - else if (sep != -1) /* '[=...' missing second bracket */ - lexerror(ls, "invalid long string delimiter", TK_STRING); - return '['; - } - case '=': { - next(ls); - if (check_next1(ls, '=')) return TK_EQ; - else return '='; - } - case '<': { - next(ls); - if (check_next1(ls, '=')) return TK_LE; - else if (check_next1(ls, '<')) return TK_SHL; - else return '<'; - } - case '>': { - next(ls); - if (check_next1(ls, '=')) return TK_GE; - else if (check_next1(ls, '>')) return TK_SHR; - else return '>'; - } - case '/': { - next(ls); - if (check_next1(ls, '/')) return TK_IDIV; - else return '/'; - } - case '~': { - next(ls); - if (check_next1(ls, '=')) return TK_NE; - else return '~'; - } - case ':': { - next(ls); - if (check_next1(ls, ':')) return TK_DBCOLON; - else return ':'; - } - case '"': case '\'': { /* short literal strings */ - read_string(ls, ls->current, seminfo); - return TK_STRING; - } - case '.': { /* '.', '..', '...', or number */ - save_and_next(ls); - if (check_next1(ls, '.')) { - if (check_next1(ls, '.')) - return TK_DOTS; /* '...' */ - else return TK_CONCAT; /* '..' */ - } - else if (!lisdigit(ls->current)) return '.'; - else return read_numeral(ls, seminfo); - } - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': { - return read_numeral(ls, seminfo); - } - case EOZ: { - return TK_EOS; - } - default: { - if (lislalpha(ls->current)) { /* identifier or reserved word? */ - TString *ts; - do { - save_and_next(ls); - } while (lislalnum(ls->current)); - ts = luaX_newstring(ls, luaZ_buffer(ls->buff), - luaZ_bufflen(ls->buff)); - seminfo->ts = ts; - if (isreserved(ts)) /* reserved word? */ - return ts->extra - 1 + FIRST_RESERVED; - else { - return TK_NAME; - } - } - else { /* single-char tokens (+ - / ...) */ - int c = ls->current; - next(ls); - return c; - } - } - } - } +static int llex(LexState* ls, SemInfo* seminfo) +{ + luaZ_resetbuffer(ls->buff); + for (;;) + { + switch (ls->current) + { + case '\n': + case '\r': + { + /* line breaks */ + inclinenumber(ls); + break; + } + case ' ': + case '\f': + case '\t': + case '\v': + { + /* spaces */ + next(ls); + break; + } + case '-': + { + /* '-' or '--' (comment) */ + next(ls); + if (ls->current != '-') return '-'; + /* else is a comment */ + next(ls); + if (ls->current == '[') + { + /* long comment? */ + int sep = skip_sep(ls); + luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */ + if (sep >= 0) + { + read_long_string(ls, NULL, sep); /* skip long comment */ + luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ + break; + } + } + /* else short comment */ + while (!currIsNewline(ls) && ls->current != EOZ) + next(ls); /* skip until end of line (or end of file) */ + break; + } + case '[': + { + /* long string or simply '[' */ + int sep = skip_sep(ls); + if (sep >= 0) + { + read_long_string(ls, seminfo, sep); + return TK_STRING; + } + else if (sep != -1) /* '[=...' missing second bracket */ + lexerror(ls, "invalid long string delimiter", TK_STRING); + return '['; + } + case '=': + { + next(ls); + if (check_next1(ls, '=')) return TK_EQ; + else return '='; + } + case '<': + { + next(ls); + if (check_next1(ls, '=')) return TK_LE; + else if (check_next1(ls, '<')) return TK_SHL; + else return '<'; + } + case '>': + { + next(ls); + if (check_next1(ls, '=')) return TK_GE; + else if (check_next1(ls, '>')) return TK_SHR; + else return '>'; + } + case '/': + { + next(ls); + if (check_next1(ls, '/')) return TK_IDIV; + else return '/'; + } + case '~': + { + next(ls); + if (check_next1(ls, '=')) return TK_NE; + else return '~'; + } + case ':': + { + next(ls); + if (check_next1(ls, ':')) return TK_DBCOLON; + else return ':'; + } + case '"': + case '\'': + { + /* short literal strings */ + read_string(ls, ls->current, seminfo); + return TK_STRING; + } + case '.': + { + /* '.', '..', '...', or number */ + save_and_next(ls); + if (check_next1(ls, '.')) + { + if (check_next1(ls, '.')) + return TK_DOTS; /* '...' */ + else return TK_CONCAT; /* '..' */ + } + else if (!lisdigit(ls->current)) return '.'; + else return read_numeral(ls, seminfo); + } + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + return read_numeral(ls, seminfo); + } + case EOZ: + { + return TK_EOS; + } + default: + { + if (lislalpha(ls->current)) + { + /* identifier or reserved word? */ + TString* ts; + do + { + save_and_next(ls); + } + while (lislalnum(ls->current)); + ts = luaX_newstring(ls, luaZ_buffer(ls->buff), + luaZ_bufflen(ls->buff)); + seminfo->ts = ts; + if (isreserved(ts)) /* reserved word? */ + return ts->extra - 1 + FIRST_RESERVED; + else + { + return TK_NAME; + } + } + else + { + /* single-char tokens (+ - / ...) */ + int c = ls->current; + next(ls); + return c; + } + } + } + } } -void luaX_next (LexState *ls) { - ls->lastline = ls->linenumber; - if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ - ls->t = ls->lookahead; /* use this one */ - ls->lookahead.token = TK_EOS; /* and discharge it */ - } - else - ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ +void luaX_next(LexState* ls) +{ + ls->lastline = ls->linenumber; + if (ls->lookahead.token != TK_EOS) + { + /* is there a look-ahead token? */ + ls->t = ls->lookahead; /* use this one */ + ls->lookahead.token = TK_EOS; /* and discharge it */ + } + else + ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ } -int luaX_lookahead (LexState *ls) { - lua_assert(ls->lookahead.token == TK_EOS); - ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); - return ls->lookahead.token; +int luaX_lookahead(LexState* ls) +{ + lua_assert(ls->lookahead.token == TK_EOS); + ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); + return ls->lookahead.token; } - diff --git a/Lua/llex.h b/Lua/llex.h index 2363d87..23304f2 100644 --- a/Lua/llex.h +++ b/Lua/llex.h @@ -23,63 +23,96 @@ * WARNING: if you change the order of this enumeration, * grep "ORDER RESERVED" */ -enum RESERVED { - /* terminal symbols denoted by reserved words */ - TK_AND = FIRST_RESERVED, TK_BREAK, - TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, - TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, - TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, - /* other terminal symbols */ - TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, - TK_SHL, TK_SHR, - TK_DBCOLON, TK_EOS, - TK_FLT, TK_INT, TK_NAME, TK_STRING +enum RESERVED +{ + /* terminal symbols denoted by reserved words */ + TK_AND = FIRST_RESERVED, + TK_BREAK, + TK_DO, + TK_ELSE, + TK_ELSEIF, + TK_END, + TK_FALSE, + TK_FOR, + TK_FUNCTION, + TK_GOTO, + TK_IF, + TK_IN, + TK_LOCAL, + TK_NIL, + TK_NOT, + TK_OR, + TK_REPEAT, + TK_RETURN, + TK_THEN, + TK_TRUE, + TK_UNTIL, + TK_WHILE, + /* other terminal symbols */ + TK_IDIV, + TK_CONCAT, + TK_DOTS, + TK_EQ, + TK_GE, + TK_LE, + TK_NE, + TK_SHL, + TK_SHR, + TK_DBCOLON, + TK_EOS, + TK_FLT, + TK_INT, + TK_NAME, + TK_STRING }; /* number of reserved words */ #define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) -typedef union { - lua_Number r; - lua_Integer i; - TString *ts; -} SemInfo; /* semantics information */ +typedef union +{ + lua_Number r; + lua_Integer i; + TString* ts; +} SemInfo; /* semantics information */ -typedef struct Token { - int token; - SemInfo seminfo; +typedef struct Token +{ + int token; + SemInfo seminfo; } Token; /* state of the lexer plus state of the parser when shared by all functions */ -typedef struct LexState { - int current; /* current character (charint) */ - int linenumber; /* input line counter */ - int lastline; /* line of last token 'consumed' */ - Token t; /* current token */ - Token lookahead; /* look ahead token */ - struct FuncState *fs; /* current function (parser) */ - struct lua_State *L; - ZIO *z; /* input stream */ - Mbuffer *buff; /* buffer for tokens */ - Table *h; /* to avoid collection/reuse strings */ - struct Dyndata *dyd; /* dynamic structures used by the parser */ - TString *source; /* current source name */ - TString *envn; /* environment variable name */ +typedef struct LexState +{ + int current; /* current character (charint) */ + int linenumber; /* input line counter */ + int lastline; /* line of last token 'consumed' */ + Token t; /* current token */ + Token lookahead; /* look ahead token */ + struct FuncState* fs; /* current function (parser) */ + struct lua_State* L; + ZIO* z; /* input stream */ + Mbuffer* buff; /* buffer for tokens */ + Table* h; /* to avoid collection/reuse strings */ + struct Dyndata* dyd; /* dynamic structures used by the parser */ + TString* source; /* current source name */ + TString* envn; /* environment variable name */ } LexState; -LUAI_FUNC void luaX_init (lua_State *L); -LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, - TString *source, int firstchar); -LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); -LUAI_FUNC void luaX_next (LexState *ls); -LUAI_FUNC int luaX_lookahead (LexState *ls); -LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); -LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); +LUAI_FUNC void luaX_init(lua_State* L); +LUAI_FUNC void luaX_setinput(lua_State* L, LexState* ls, ZIO* z, + TString* source, int firstchar); +LUAI_FUNC TString* luaX_newstring(LexState* ls, const char* str, size_t l); +LUAI_FUNC void luaX_next(LexState* ls); +LUAI_FUNC int luaX_lookahead(LexState* ls); +LUAI_FUNC l_noret luaX_syntaxerror(LexState* ls, const char* s); +LUAI_FUNC const char* luaX_token2str(LexState* ls, int token); #endif diff --git a/Lua/llimits.h b/Lua/llimits.h index f21377f..a0db4d3 100644 --- a/Lua/llimits.h +++ b/Lua/llimits.h @@ -59,22 +59,21 @@ typedef unsigned char lu_byte; #define point2uint(p) ((unsigned int)((size_t)(p) & UINT_MAX)) - /* type to ensure maximum alignment */ #if defined(LUAI_USER_ALIGNMENT_T) typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; #else -typedef union { - lua_Number n; - double u; - void *s; - lua_Integer i; - long l; +typedef union +{ + lua_Number n; + double u; + void* s; + lua_Integer i; + long l; } L_Umaxalign; #endif - /* types of 'usual argument conversions' for lua_Number and lua_Integer */ typedef LUAI_UACNUMBER l_uacNumber; typedef LUAI_UACINT l_uacInt; @@ -144,7 +143,6 @@ typedef LUAI_UACINT l_uacInt; #endif - /* ** maximum depth for nested C calls and syntactical nested non-terminals ** in a program. (Value must fit in an unsigned short int.) @@ -154,7 +152,6 @@ typedef LUAI_UACINT l_uacInt; #endif - /* ** type for virtual-machine instructions; ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) @@ -166,7 +163,6 @@ typedef unsigned long Instruction; #endif - /* ** Maximum length for short strings, that is, strings that are ** internalized. (Cannot be smaller than reserved words or tags for @@ -254,7 +250,6 @@ typedef unsigned long Instruction; #endif - /* ** The luai_num* macros define the primitive operations over numbers. */ @@ -299,9 +294,6 @@ typedef unsigned long Instruction; #endif - - - /* ** macro to control inclusion of some hard tests on stack reallocation */ diff --git a/Lua/lmathlib.c b/Lua/lmathlib.c index b7f8bae..fcad850 100644 --- a/Lua/lmathlib.c +++ b/Lua/lmathlib.c @@ -36,108 +36,127 @@ #endif /* } */ -static int math_abs (lua_State *L) { - if (lua_isinteger(L, 1)) { - lua_Integer n = lua_tointeger(L, 1); - if (n < 0) n = (lua_Integer)(0u - (lua_Unsigned)n); - lua_pushinteger(L, n); - } - else - lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1))); - return 1; +static int math_abs(lua_State* L) +{ + if (lua_isinteger(L, 1)) + { + lua_Integer n = lua_tointeger(L, 1); + if (n < 0) n = (lua_Integer)(0u - (lua_Unsigned)n); + lua_pushinteger(L, n); + } + else + lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1))); + return 1; } -static int math_sin (lua_State *L) { - lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1))); - return 1; +static int math_sin(lua_State* L) +{ + lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1))); + return 1; } -static int math_cos (lua_State *L) { - lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1))); - return 1; +static int math_cos(lua_State* L) +{ + lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1))); + return 1; } -static int math_tan (lua_State *L) { - lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1))); - return 1; +static int math_tan(lua_State* L) +{ + lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1))); + return 1; } -static int math_asin (lua_State *L) { - lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1))); - return 1; +static int math_asin(lua_State* L) +{ + lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1))); + return 1; } -static int math_acos (lua_State *L) { - lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1))); - return 1; +static int math_acos(lua_State* L) +{ + lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1))); + return 1; } -static int math_atan (lua_State *L) { - lua_Number y = luaL_checknumber(L, 1); - lua_Number x = luaL_optnumber(L, 2, 1); - lua_pushnumber(L, l_mathop(atan2)(y, x)); - return 1; +static int math_atan(lua_State* L) +{ + lua_Number y = luaL_checknumber(L, 1); + lua_Number x = luaL_optnumber(L, 2, 1); + lua_pushnumber(L, l_mathop(atan2)(y, x)); + return 1; } -static int math_toint (lua_State *L) { - int valid; - lua_Integer n = lua_tointegerx(L, 1, &valid); - if (valid) - lua_pushinteger(L, n); - else { - luaL_checkany(L, 1); - lua_pushnil(L); /* value is not convertible to integer */ - } - return 1; +static int math_toint(lua_State* L) +{ + int valid; + lua_Integer n = lua_tointegerx(L, 1, &valid); + if (valid) + lua_pushinteger(L, n); + else + { + luaL_checkany(L, 1); + lua_pushnil(L); /* value is not convertible to integer */ + } + return 1; } -static void pushnumint (lua_State *L, lua_Number d) { - lua_Integer n; - if (lua_numbertointeger(d, &n)) /* does 'd' fit in an integer? */ - lua_pushinteger(L, n); /* result is integer */ - else - lua_pushnumber(L, d); /* result is float */ +static void pushnumint(lua_State* L, lua_Number d) +{ + lua_Integer n; + if (lua_numbertointeger(d, &n)) /* does 'd' fit in an integer? */ + lua_pushinteger(L, n); /* result is integer */ + else + lua_pushnumber(L, d); /* result is float */ } -static int math_floor (lua_State *L) { - if (lua_isinteger(L, 1)) - lua_settop(L, 1); /* integer is its own floor */ - else { - lua_Number d = l_mathop(floor)(luaL_checknumber(L, 1)); - pushnumint(L, d); - } - return 1; +static int math_floor(lua_State* L) +{ + if (lua_isinteger(L, 1)) + lua_settop(L, 1); /* integer is its own floor */ + else + { + lua_Number d = l_mathop(floor)(luaL_checknumber(L, 1)); + pushnumint(L, d); + } + return 1; } -static int math_ceil (lua_State *L) { - if (lua_isinteger(L, 1)) - lua_settop(L, 1); /* integer is its own ceil */ - else { - lua_Number d = l_mathop(ceil)(luaL_checknumber(L, 1)); - pushnumint(L, d); - } - return 1; +static int math_ceil(lua_State* L) +{ + if (lua_isinteger(L, 1)) + lua_settop(L, 1); /* integer is its own ceil */ + else + { + lua_Number d = l_mathop(ceil)(luaL_checknumber(L, 1)); + pushnumint(L, d); + } + return 1; } -static int math_fmod (lua_State *L) { - if (lua_isinteger(L, 1) && lua_isinteger(L, 2)) { - lua_Integer d = lua_tointeger(L, 2); - if ((lua_Unsigned)d + 1u <= 1u) { /* special cases: -1 or 0 */ - luaL_argcheck(L, d != 0, 2, "zero"); - lua_pushinteger(L, 0); /* avoid overflow with 0x80000... / -1 */ - } - else - lua_pushinteger(L, lua_tointeger(L, 1) % d); - } - else - lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1), - luaL_checknumber(L, 2))); - return 1; +static int math_fmod(lua_State* L) +{ + if (lua_isinteger(L, 1) && lua_isinteger(L, 2)) + { + lua_Integer d = lua_tointeger(L, 2); + if ((lua_Unsigned)d + 1u <= 1u) + { + /* special cases: -1 or 0 */ + luaL_argcheck(L, d != 0, 2, "zero"); + lua_pushinteger(L, 0); /* avoid overflow with 0x80000... / -1 */ + } + else + lua_pushinteger(L, lua_tointeger(L, 1) % d); + } + else + lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1), + luaL_checknumber(L, 2))); + return 1; } @@ -146,97 +165,111 @@ static int math_fmod (lua_State *L) { ** (which is not compatible with 'float*') when lua_Number is not ** 'double'. */ -static int math_modf (lua_State *L) { - if (lua_isinteger(L ,1)) { - lua_settop(L, 1); /* number is its own integer part */ - lua_pushnumber(L, 0); /* no fractional part */ - } - else { - lua_Number n = luaL_checknumber(L, 1); - /* integer part (rounds toward zero) */ - lua_Number ip = (n < 0) ? l_mathop(ceil)(n) : l_mathop(floor)(n); - pushnumint(L, ip); - /* fractional part (test needed for inf/-inf) */ - lua_pushnumber(L, (n == ip) ? l_mathop(0.0) : (n - ip)); - } - return 2; +static int math_modf(lua_State* L) +{ + if (lua_isinteger(L, 1)) + { + lua_settop(L, 1); /* number is its own integer part */ + lua_pushnumber(L, 0); /* no fractional part */ + } + else + { + lua_Number n = luaL_checknumber(L, 1); + /* integer part (rounds toward zero) */ + lua_Number ip = (n < 0) ? l_mathop(ceil)(n) : l_mathop(floor)(n); + pushnumint(L, ip); + /* fractional part (test needed for inf/-inf) */ + lua_pushnumber(L, (n == ip) ? l_mathop(0.0) : (n - ip)); + } + return 2; } -static int math_sqrt (lua_State *L) { - lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1))); - return 1; +static int math_sqrt(lua_State* L) +{ + lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1))); + return 1; } -static int math_ult (lua_State *L) { - lua_Integer a = luaL_checkinteger(L, 1); - lua_Integer b = luaL_checkinteger(L, 2); - lua_pushboolean(L, (lua_Unsigned)a < (lua_Unsigned)b); - return 1; +static int math_ult(lua_State* L) +{ + lua_Integer a = luaL_checkinteger(L, 1); + lua_Integer b = luaL_checkinteger(L, 2); + lua_pushboolean(L, (lua_Unsigned)a < (lua_Unsigned)b); + return 1; } -static int math_log (lua_State *L) { - lua_Number x = luaL_checknumber(L, 1); - lua_Number res; - if (lua_isnoneornil(L, 2)) - res = l_mathop(log)(x); - else { - lua_Number base = luaL_checknumber(L, 2); +static int math_log(lua_State* L) +{ + lua_Number x = luaL_checknumber(L, 1); + lua_Number res; + if (lua_isnoneornil(L, 2)) + res = l_mathop(log)(x); + else + { + lua_Number base = luaL_checknumber(L, 2); #if !defined(LUA_USE_C89) if (base == l_mathop(2.0)) res = l_mathop(log2)(x); else #endif - if (base == l_mathop(10.0)) - res = l_mathop(log10)(x); - else - res = l_mathop(log)(x)/l_mathop(log)(base); - } - lua_pushnumber(L, res); - return 1; + if (base == l_mathop(10.0)) + res = l_mathop(log10)(x); + else + res = l_mathop(log)(x) / l_mathop(log)(base); + } + lua_pushnumber(L, res); + return 1; } -static int math_exp (lua_State *L) { - lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1))); - return 1; +static int math_exp(lua_State* L) +{ + lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1))); + return 1; } -static int math_deg (lua_State *L) { - lua_pushnumber(L, luaL_checknumber(L, 1) * (l_mathop(180.0) / PI)); - return 1; +static int math_deg(lua_State* L) +{ + lua_pushnumber(L, luaL_checknumber(L, 1) * (l_mathop(180.0) / PI)); + return 1; } -static int math_rad (lua_State *L) { - lua_pushnumber(L, luaL_checknumber(L, 1) * (PI / l_mathop(180.0))); - return 1; +static int math_rad(lua_State* L) +{ + lua_pushnumber(L, luaL_checknumber(L, 1) * (PI / l_mathop(180.0))); + return 1; } -static int math_min (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - int imin = 1; /* index of current minimum value */ - int i; - luaL_argcheck(L, n >= 1, 1, "value expected"); - for (i = 2; i <= n; i++) { - if (lua_compare(L, i, imin, LUA_OPLT)) - imin = i; - } - lua_pushvalue(L, imin); - return 1; +static int math_min(lua_State* L) +{ + int n = lua_gettop(L); /* number of arguments */ + int imin = 1; /* index of current minimum value */ + int i; + luaL_argcheck(L, n >= 1, 1, "value expected"); + for (i = 2; i <= n; i++) + { + if (lua_compare(L, i, imin, LUA_OPLT)) + imin = i; + } + lua_pushvalue(L, imin); + return 1; } -static int math_max (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - int imax = 1; /* index of current maximum value */ - int i; - luaL_argcheck(L, n >= 1, 1, "value expected"); - for (i = 2; i <= n; i++) { - if (lua_compare(L, imax, i, LUA_OPLT)) - imax = i; - } - lua_pushvalue(L, imax); - return 1; +static int math_max(lua_State* L) +{ + int n = lua_gettop(L); /* number of arguments */ + int imax = 1; /* index of current maximum value */ + int i; + luaL_argcheck(L, n >= 1, 1, "value expected"); + for (i = 2; i <= n; i++) + { + if (lua_compare(L, imax, i, LUA_OPLT)) + imax = i; + } + lua_pushvalue(L, imax); + return 1; } /* @@ -244,55 +277,68 @@ static int math_max (lua_State *L) { ** all bits from 'l_rand' can be represented, and that 'RANDMAX + 1.0' ** will keep full precision (ensuring that 'r' is always less than 1.0.) */ -static int math_random (lua_State *L) { - lua_Integer low, up; - double r = (double)l_rand() * (1.0 / ((double)L_RANDMAX + 1.0)); - switch (lua_gettop(L)) { /* check number of arguments */ - case 0: { /* no arguments */ - lua_pushnumber(L, (lua_Number)r); /* Number between 0 and 1 */ - return 1; - } - case 1: { /* only upper limit */ - low = 1; - up = luaL_checkinteger(L, 1); - break; - } - case 2: { /* lower and upper limits */ - low = luaL_checkinteger(L, 1); - up = luaL_checkinteger(L, 2); - break; - } - default: return luaL_error(L, "wrong number of arguments"); - } - /* random integer in the interval [low, up] */ - luaL_argcheck(L, low <= up, 1, "interval is empty"); - luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1, - "interval too large"); - r *= (double)(up - low) + 1.0; - lua_pushinteger(L, (lua_Integer)r + low); - return 1; +static int math_random(lua_State* L) +{ + lua_Integer low, up; + double r = (double)l_rand() * (1.0 / ((double)L_RANDMAX + 1.0)); + switch (lua_gettop(L)) + { + /* check number of arguments */ + case 0: + { + /* no arguments */ + lua_pushnumber(L, (lua_Number)r); /* Number between 0 and 1 */ + return 1; + } + case 1: + { + /* only upper limit */ + low = 1; + up = luaL_checkinteger(L, 1); + break; + } + case 2: + { + /* lower and upper limits */ + low = luaL_checkinteger(L, 1); + up = luaL_checkinteger(L, 2); + break; + } + default: return luaL_error(L, "wrong number of arguments"); + } + /* random integer in the interval [low, up] */ + luaL_argcheck(L, low <= up, 1, "interval is empty"); + luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1, + "interval too large"); + r *= (double)(up - low) + 1.0; + lua_pushinteger(L, (lua_Integer)r + low); + return 1; } -static int math_randomseed (lua_State *L) { - l_srand((unsigned int)(lua_Integer)luaL_checknumber(L, 1)); - (void)l_rand(); /* discard first value to avoid undesirable correlations */ - return 0; +static int math_randomseed(lua_State* L) +{ + l_srand((unsigned int)(lua_Integer)luaL_checknumber(L, 1)); + (void)l_rand(); /* discard first value to avoid undesirable correlations */ + return 0; } -static int math_type (lua_State *L) { - if (lua_type(L, 1) == LUA_TNUMBER) { - if (lua_isinteger(L, 1)) - lua_pushliteral(L, "integer"); - else - lua_pushliteral(L, "float"); - } - else { - luaL_checkany(L, 1); - lua_pushnil(L); - } - return 1; +static int math_type(lua_State* L) +{ + if (lua_type(L, 1) == LUA_TNUMBER) + { + if (lua_isinteger(L, 1)) + lua_pushliteral(L, "integer"); + else + lua_pushliteral(L, "float"); + } + else + { + luaL_checkany(L, 1); + lua_pushnil(L); + } + return 1; } @@ -348,31 +394,30 @@ static int math_log10 (lua_State *L) { /* }================================================================== */ - static const luaL_Reg mathlib[] = { - {"abs", math_abs}, - {"acos", math_acos}, - {"asin", math_asin}, - {"atan", math_atan}, - {"ceil", math_ceil}, - {"cos", math_cos}, - {"deg", math_deg}, - {"exp", math_exp}, - {"tointeger", math_toint}, - {"floor", math_floor}, - {"fmod", math_fmod}, - {"ult", math_ult}, - {"log", math_log}, - {"max", math_max}, - {"min", math_min}, - {"modf", math_modf}, - {"rad", math_rad}, - {"random", math_random}, - {"randomseed", math_randomseed}, - {"sin", math_sin}, - {"sqrt", math_sqrt}, - {"tan", math_tan}, - {"type", math_type}, + {"abs", math_abs}, + {"acos", math_acos}, + {"asin", math_asin}, + {"atan", math_atan}, + {"ceil", math_ceil}, + {"cos", math_cos}, + {"deg", math_deg}, + {"exp", math_exp}, + {"tointeger", math_toint}, + {"floor", math_floor}, + {"fmod", math_fmod}, + {"ult", math_ult}, + {"log", math_log}, + {"max", math_max}, + {"min", math_min}, + {"modf", math_modf}, + {"rad", math_rad}, + {"random", math_random}, + {"randomseed", math_randomseed}, + {"sin", math_sin}, + {"sqrt", math_sqrt}, + {"tan", math_tan}, + {"type", math_type}, #if defined(LUA_COMPAT_MATHLIB) {"atan2", math_atan}, {"cosh", math_cosh}, @@ -383,28 +428,28 @@ static const luaL_Reg mathlib[] = { {"ldexp", math_ldexp}, {"log10", math_log10}, #endif - /* placeholders */ - {"pi", NULL}, - {"huge", NULL}, - {"maxinteger", NULL}, - {"mininteger", NULL}, - {NULL, NULL} + /* placeholders */ + {"pi", NULL}, + {"huge", NULL}, + {"maxinteger", NULL}, + {"mininteger", NULL}, + {NULL, NULL} }; /* ** Open math library */ -LUAMOD_API int luaopen_math (lua_State *L) { - luaL_newlib(L, mathlib); - lua_pushnumber(L, PI); - lua_setfield(L, -2, "pi"); - lua_pushnumber(L, (lua_Number)HUGE_VAL); - lua_setfield(L, -2, "huge"); - lua_pushinteger(L, LUA_MAXINTEGER); - lua_setfield(L, -2, "maxinteger"); - lua_pushinteger(L, LUA_MININTEGER); - lua_setfield(L, -2, "mininteger"); - return 1; +LUAMOD_API int luaopen_math(lua_State* L) +{ + luaL_newlib(L, mathlib); + lua_pushnumber(L, PI); + lua_setfield(L, -2, "pi"); + lua_pushnumber(L, (lua_Number)HUGE_VAL); + lua_setfield(L, -2, "huge"); + lua_pushinteger(L, LUA_MAXINTEGER); + lua_setfield(L, -2, "maxinteger"); + lua_pushinteger(L, LUA_MININTEGER); + lua_setfield(L, -2, "mininteger"); + return 1; } - diff --git a/Lua/lmem.c b/Lua/lmem.c index 0a0476c..ea62ccd 100644 --- a/Lua/lmem.c +++ b/Lua/lmem.c @@ -22,7 +22,6 @@ #include "lstate.h" - /* ** About the realloc function: ** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); @@ -41,60 +40,66 @@ */ - #define MINSIZEARRAY 4 -void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, - int limit, const char *what) { - void *newblock; - int newsize; - if (*size >= limit/2) { /* cannot double it? */ - if (*size >= limit) /* cannot grow even a little? */ - luaG_runerror(L, "too many %s (limit is %d)", what, limit); - newsize = limit; /* still have at least one free place */ - } - else { - newsize = (*size)*2; - if (newsize < MINSIZEARRAY) - newsize = MINSIZEARRAY; /* minimum size */ - } - newblock = luaM_reallocv(L, block, *size, newsize, size_elems); - *size = newsize; /* update only when everything else is OK */ - return newblock; +void* luaM_growaux_(lua_State* L, void* block, int* size, size_t size_elems, + int limit, const char* what) +{ + void* newblock; + int newsize; + if (*size >= limit / 2) + { + /* cannot double it? */ + if (*size >= limit) /* cannot grow even a little? */ + luaG_runerror(L, "too many %s (limit is %d)", what, limit); + newsize = limit; /* still have at least one free place */ + } + else + { + newsize = (*size) * 2; + if (newsize < MINSIZEARRAY) + newsize = MINSIZEARRAY; /* minimum size */ + } + newblock = luaM_reallocv(L, block, *size, newsize, size_elems); + *size = newsize; /* update only when everything else is OK */ + return newblock; } -l_noret luaM_toobig (lua_State *L) { - luaG_runerror(L, "memory allocation error: block too big"); +l_noret luaM_toobig(lua_State* L) +{ + luaG_runerror(L, "memory allocation error: block too big"); } - /* ** generic allocation routine. */ -void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { - void *newblock; - global_State *g = G(L); - size_t realosize = (block) ? osize : 0; - lua_assert((realosize == 0) == (block == NULL)); +void* luaM_realloc_(lua_State* L, void* block, size_t osize, size_t nsize) +{ + void* newblock; + global_State* g = G(L); + size_t realosize = (block) ? osize : 0; + lua_assert((realosize == 0) == (block == NULL)); #if defined(HARDMEMTESTS) if (nsize > realosize && g->gcrunning) luaC_fullgc(L, 1); /* force a GC whenever possible */ #endif - newblock = (*g->frealloc)(g->ud, block, osize, nsize); - if (newblock == NULL && nsize > 0) { - lua_assert(nsize > realosize); /* cannot fail when shrinking a block */ - if (g->version) { /* is state fully built? */ - luaC_fullgc(L, 1); /* try to free some memory... */ - newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ - } - if (newblock == NULL) - luaD_throw(L, LUA_ERRMEM); - } - lua_assert((nsize == 0) == (newblock == NULL)); - g->GCdebt = (g->GCdebt + nsize) - realosize; - return newblock; + newblock = (*g->frealloc)(g->ud, block, osize, nsize); + if (newblock == NULL && nsize > 0) + { + lua_assert(nsize > realosize); /* cannot fail when shrinking a block */ + if (g->version) + { + /* is state fully built? */ + luaC_fullgc(L, 1); /* try to free some memory... */ + newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ + } + if (newblock == NULL) + luaD_throw(L, LUA_ERRMEM); + } + lua_assert((nsize == 0) == (newblock == NULL)); + g->GCdebt = (g->GCdebt + nsize) - realosize; + return newblock; } - diff --git a/Lua/lmem.h b/Lua/lmem.h index 30f4848..55343f7 100644 --- a/Lua/lmem.h +++ b/Lua/lmem.h @@ -56,14 +56,13 @@ #define luaM_reallocvector(L, v,oldn,n,t) \ ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) -LUAI_FUNC l_noret luaM_toobig (lua_State *L); +LUAI_FUNC l_noret luaM_toobig(lua_State* L); /* not to be called directly */ -LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, - size_t size); -LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, - size_t size_elem, int limit, - const char *what); +LUAI_FUNC void* luaM_realloc_(lua_State* L, void* block, size_t oldsize, + size_t size); +LUAI_FUNC void* luaM_growaux_(lua_State* L, void* block, int* size, + size_t size_elem, int limit, + const char* what); #endif - diff --git a/Lua/loadlib.c b/Lua/loadlib.c index 4791e74..016057b 100644 --- a/Lua/loadlib.c +++ b/Lua/loadlib.c @@ -74,7 +74,7 @@ static const int CLIBS = 0; /* ** unload library 'lib' */ -static void lsys_unloadlib (void *lib); +static void lsys_unloadlib(void* lib); /* ** load C library in file 'path'. If 'seeglb', load with all names in @@ -82,16 +82,14 @@ static void lsys_unloadlib (void *lib); ** Returns the library; in case of error, returns NULL plus an ** error string in the stack. */ -static void *lsys_load (lua_State *L, const char *path, int seeglb); +static void* lsys_load(lua_State* L, const char* path, int seeglb); /* ** Try to find a function named 'sym' in library 'lib'. ** Returns the function; in case of error, returns NULL plus an ** error string in the stack. */ -static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym); - - +static lua_CFunction lsys_sym(lua_State* L, void* lib, const char* sym); #if defined(LUA_USE_DLOPEN) /* { */ @@ -139,7 +137,6 @@ static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { /* }====================================================== */ - #elif defined(LUA_DL_DLL) /* }{ */ /* ** {====================================================================== @@ -165,50 +162,54 @@ static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { ** Replace in the path (on the top of the stack) any occurrence ** of LUA_EXEC_DIR with the executable's path. */ -static void setprogdir (lua_State *L) { - char buff[MAX_PATH + 1]; - char *lb; - DWORD nsize = sizeof(buff)/sizeof(char); - DWORD n = GetModuleFileNameA(NULL, buff, nsize); /* get exec. name */ - if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) - luaL_error(L, "unable to get ModuleFileName"); - else { - *lb = '\0'; /* cut name on the last '\\' to get the path */ - luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff); - lua_remove(L, -2); /* remove original string */ - } +static void setprogdir(lua_State* L) +{ + char buff[MAX_PATH + 1]; + char* lb; + DWORD nsize = sizeof(buff) / sizeof(char); + DWORD n = GetModuleFileNameA(NULL, buff, nsize); /* get exec. name */ + if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) + luaL_error(L, "unable to get ModuleFileName"); + else + { + *lb = '\0'; /* cut name on the last '\\' to get the path */ + luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff); + lua_remove(L, -2); /* remove original string */ + } } - - -static void pusherror (lua_State *L) { - int error = GetLastError(); - char buffer[128]; - if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL)) - lua_pushstring(L, buffer); - else - lua_pushfstring(L, "system error %d\n", error); +static void pusherror(lua_State* L) +{ + int error = GetLastError(); + char buffer[128]; + if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, error, 0, buffer, sizeof(buffer) / sizeof(char), NULL)) + lua_pushstring(L, buffer); + else + lua_pushfstring(L, "system error %d\n", error); } -static void lsys_unloadlib (void *lib) { - FreeLibrary((HMODULE)lib); +static void lsys_unloadlib(void* lib) +{ + FreeLibrary((HMODULE)lib); } -static void *lsys_load (lua_State *L, const char *path, int seeglb) { - HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); - (void)(seeglb); /* not used: symbols are 'global' by default */ - if (lib == NULL) pusherror(L); - return lib; +static void* lsys_load(lua_State* L, const char* path, int seeglb) +{ + HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); + (void)(seeglb); /* not used: symbols are 'global' by default */ + if (lib == NULL) pusherror(L); + return lib; } -static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { - lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym); - if (f == NULL) pusherror(L); - return f; +static lua_CFunction lsys_sym(lua_State* L, void* lib, const char* sym) +{ + lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym); + if (f == NULL) pusherror(L); + return f; } /* }====================================================== */ @@ -275,37 +276,40 @@ static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { /* ** return registry.LUA_NOENV as a boolean */ -static int noenv (lua_State *L) { - int b; - lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); - b = lua_toboolean(L, -1); - lua_pop(L, 1); /* remove value */ - return b; +static int noenv(lua_State* L) +{ + int b; + lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + b = lua_toboolean(L, -1); + lua_pop(L, 1); /* remove value */ + return b; } /* ** Set a path */ -static void setpath (lua_State *L, const char *fieldname, - const char *envname, - const char *dft) { - const char *nver = lua_pushfstring(L, "%s%s", envname, LUA_VERSUFFIX); - const char *path = getenv(nver); /* use versioned name */ - if (path == NULL) /* no environment variable? */ - path = getenv(envname); /* try unversioned name */ - if (path == NULL || noenv(L)) /* no environment variable? */ - lua_pushstring(L, dft); /* use default */ - else { - /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ - path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP, - LUA_PATH_SEP AUXMARK LUA_PATH_SEP); - luaL_gsub(L, path, AUXMARK, dft); - lua_remove(L, -2); /* remove result from 1st 'gsub' */ - } - setprogdir(L); - lua_setfield(L, -3, fieldname); /* package[fieldname] = path value */ - lua_pop(L, 1); /* pop versioned variable name */ +static void setpath(lua_State* L, const char* fieldname, + const char* envname, + const char* dft) +{ + const char* nver = lua_pushfstring(L, "%s%s", envname, LUA_VERSUFFIX); + const char* path = getenv(nver); /* use versioned name */ + if (path == NULL) /* no environment variable? */ + path = getenv(envname); /* try unversioned name */ + if (path == NULL || noenv(L)) /* no environment variable? */ + lua_pushstring(L, dft); /* use default */ + else + { + /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ + path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP, + LUA_PATH_SEP AUXMARK LUA_PATH_SEP); + luaL_gsub(L, path, AUXMARK, dft); + lua_remove(L, -2); /* remove result from 1st 'gsub' */ + } + setprogdir(L); + lua_setfield(L, -3, fieldname); /* package[fieldname] = path value */ + lua_pop(L, 1); /* pop versioned variable name */ } /* }================================================================== */ @@ -314,13 +318,14 @@ static void setpath (lua_State *L, const char *fieldname, /* ** return registry.CLIBS[path] */ -static void *checkclib (lua_State *L, const char *path) { - void *plib; - lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS); - lua_getfield(L, -1, path); - plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ - lua_pop(L, 2); /* pop CLIBS table and 'plib' */ - return plib; +static void* checkclib(lua_State* L, const char* path) +{ + void* plib; + lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS); + lua_getfield(L, -1, path); + plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ + lua_pop(L, 2); /* pop CLIBS table and 'plib' */ + return plib; } @@ -328,13 +333,14 @@ static void *checkclib (lua_State *L, const char *path) { ** registry.CLIBS[path] = plib -- for queries ** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries */ -static void addtoclib (lua_State *L, const char *path, void *plib) { - lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS); - lua_pushlightuserdata(L, plib); - lua_pushvalue(L, -1); - lua_setfield(L, -3, path); /* CLIBS[path] = plib */ - lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ - lua_pop(L, 1); /* pop CLIBS table */ +static void addtoclib(lua_State* L, const char* path, void* plib) +{ + lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS); + lua_pushlightuserdata(L, plib); + lua_pushvalue(L, -1); + lua_setfield(L, -3, path); /* CLIBS[path] = plib */ + lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ + lua_pop(L, 1); /* pop CLIBS table */ } @@ -342,18 +348,20 @@ static void addtoclib (lua_State *L, const char *path, void *plib) { ** __gc tag method for CLIBS table: calls 'lsys_unloadlib' for all lib ** handles in list CLIBS */ -static int gctm (lua_State *L) { - lua_Integer n = luaL_len(L, 1); - for (; n >= 1; n--) { /* for each handle, in reverse order */ - lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ - lsys_unloadlib(lua_touserdata(L, -1)); - lua_pop(L, 1); /* pop handle */ - } - return 0; +static int gctm(lua_State* L) +{ + lua_Integer n = luaL_len(L, 1); + for (; n >= 1; n--) + { + /* for each handle, in reverse order */ + lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ + lsys_unloadlib(lua_touserdata(L, -1)); + lua_pop(L, 1); /* pop handle */ + } + return 0; } - /* error codes for 'lookforfunc' */ #define ERRLIB 1 #define ERRFUNC 2 @@ -369,43 +377,51 @@ static int gctm (lua_State *L) { ** Return 0 and 'true' or a function in the stack; in case of ** errors, return an error code and an error message in the stack. */ -static int lookforfunc (lua_State *L, const char *path, const char *sym) { - void *reg = checkclib(L, path); /* check loaded C libraries */ - if (reg == NULL) { /* must load library? */ - reg = lsys_load(L, path, *sym == '*'); /* global symbols if 'sym'=='*' */ - if (reg == NULL) return ERRLIB; /* unable to load library */ - addtoclib(L, path, reg); - } - if (*sym == '*') { /* loading only library (no function)? */ - lua_pushboolean(L, 1); /* return 'true' */ - return 0; /* no errors */ - } - else { - lua_CFunction f = lsys_sym(L, reg, sym); - if (f == NULL) - return ERRFUNC; /* unable to find function */ - lua_pushcfunction(L, f); /* else create new function */ - return 0; /* no errors */ - } +static int lookforfunc(lua_State* L, const char* path, const char* sym) +{ + void* reg = checkclib(L, path); /* check loaded C libraries */ + if (reg == NULL) + { + /* must load library? */ + reg = lsys_load(L, path, *sym == '*'); /* global symbols if 'sym'=='*' */ + if (reg == NULL) return ERRLIB; /* unable to load library */ + addtoclib(L, path, reg); + } + if (*sym == '*') + { + /* loading only library (no function)? */ + lua_pushboolean(L, 1); /* return 'true' */ + return 0; /* no errors */ + } + else + { + lua_CFunction f = lsys_sym(L, reg, sym); + if (f == NULL) + return ERRFUNC; /* unable to find function */ + lua_pushcfunction(L, f); /* else create new function */ + return 0; /* no errors */ + } } -static int ll_loadlib (lua_State *L) { - const char *path = luaL_checkstring(L, 1); - const char *init = luaL_checkstring(L, 2); - int stat = lookforfunc(L, path, init); - if (stat == 0) /* no errors? */ - return 1; /* return the loaded function */ - else { /* error; error message is on stack top */ - lua_pushnil(L); - lua_insert(L, -2); - lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); - return 3; /* return nil, error message, and where */ - } +static int ll_loadlib(lua_State* L) +{ + const char* path = luaL_checkstring(L, 1); + const char* init = luaL_checkstring(L, 2); + int stat = lookforfunc(L, path, init); + if (stat == 0) /* no errors? */ + return 1; /* return the loaded function */ + else + { + /* error; error message is on stack top */ + lua_pushnil(L); + lua_insert(L, -2); + lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); + return 3; /* return nil, error message, and where */ + } } - /* ** {====================================================== ** 'require' function @@ -413,91 +429,103 @@ static int ll_loadlib (lua_State *L) { */ -static int readable (const char *filename) { - FILE *f = fopen(filename, "r"); /* try to open file */ - if (f == NULL) return 0; /* open failed */ - fclose(f); - return 1; +static int readable(const char* filename) +{ + FILE* f = fopen(filename, "r"); /* try to open file */ + if (f == NULL) return 0; /* open failed */ + fclose(f); + return 1; } -static const char *pushnexttemplate (lua_State *L, const char *path) { - const char *l; - while (*path == *LUA_PATH_SEP) path++; /* skip separators */ - if (*path == '\0') return NULL; /* no more templates */ - l = strchr(path, *LUA_PATH_SEP); /* find next separator */ - if (l == NULL) l = path + strlen(path); - lua_pushlstring(L, path, l - path); /* template */ - return l; +static const char* pushnexttemplate(lua_State* L, const char* path) +{ + const char* l; + while (*path == *LUA_PATH_SEP) path++; /* skip separators */ + if (*path == '\0') return NULL; /* no more templates */ + l = strchr(path, *LUA_PATH_SEP); /* find next separator */ + if (l == NULL) l = path + strlen(path); + lua_pushlstring(L, path, l - path); /* template */ + return l; } -static const char *searchpath (lua_State *L, const char *name, - const char *path, - const char *sep, - const char *dirsep) { - luaL_Buffer msg; /* to build error message */ - luaL_buffinit(L, &msg); - if (*sep != '\0') /* non-empty separator? */ - name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ - while ((path = pushnexttemplate(L, path)) != NULL) { - const char *filename = luaL_gsub(L, lua_tostring(L, -1), - LUA_PATH_MARK, name); - lua_remove(L, -2); /* remove path template */ - if (readable(filename)) /* does file exist and is readable? */ - return filename; /* return that file name */ - lua_pushfstring(L, "\n\tno file '%s'", filename); - lua_remove(L, -2); /* remove file name */ - luaL_addvalue(&msg); /* concatenate error msg. entry */ - } - luaL_pushresult(&msg); /* create error message */ - return NULL; /* not found */ +static const char* searchpath(lua_State* L, const char* name, + const char* path, + const char* sep, + const char* dirsep) +{ + luaL_Buffer msg; /* to build error message */ + luaL_buffinit(L, &msg); + if (*sep != '\0') /* non-empty separator? */ + name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ + while ((path = pushnexttemplate(L, path)) != NULL) + { + const char* filename = luaL_gsub(L, lua_tostring(L, -1), + LUA_PATH_MARK, name); + lua_remove(L, -2); /* remove path template */ + if (readable(filename)) /* does file exist and is readable? */ + return filename; /* return that file name */ + lua_pushfstring(L, "\n\tno file '%s'", filename); + lua_remove(L, -2); /* remove file name */ + luaL_addvalue(&msg); /* concatenate error msg. entry */ + } + luaL_pushresult(&msg); /* create error message */ + return NULL; /* not found */ } -static int ll_searchpath (lua_State *L) { - const char *f = searchpath(L, luaL_checkstring(L, 1), - luaL_checkstring(L, 2), - luaL_optstring(L, 3, "."), - luaL_optstring(L, 4, LUA_DIRSEP)); - if (f != NULL) return 1; - else { /* error message is on top of the stack */ - lua_pushnil(L); - lua_insert(L, -2); - return 2; /* return nil + error message */ - } +static int ll_searchpath(lua_State* L) +{ + const char* f = searchpath(L, luaL_checkstring(L, 1), + luaL_checkstring(L, 2), + luaL_optstring(L, 3, "."), + luaL_optstring(L, 4, LUA_DIRSEP)); + if (f != NULL) return 1; + else + { + /* error message is on top of the stack */ + lua_pushnil(L); + lua_insert(L, -2); + return 2; /* return nil + error message */ + } } -static const char *findfile (lua_State *L, const char *name, - const char *pname, - const char *dirsep) { - const char *path; - lua_getfield(L, lua_upvalueindex(1), pname); - path = lua_tostring(L, -1); - if (path == NULL) - luaL_error(L, "'package.%s' must be a string", pname); - return searchpath(L, name, path, ".", dirsep); +static const char* findfile(lua_State* L, const char* name, + const char* pname, + const char* dirsep) +{ + const char* path; + lua_getfield(L, lua_upvalueindex(1), pname); + path = lua_tostring(L, -1); + if (path == NULL) + luaL_error(L, "'package.%s' must be a string", pname); + return searchpath(L, name, path, ".", dirsep); } -static int checkload (lua_State *L, int stat, const char *filename) { - if (stat) { /* module loaded successfully? */ - lua_pushstring(L, filename); /* will be 2nd argument to module */ - return 2; /* return open function and file name */ - } - else - return luaL_error(L, "error loading module '%s' from file '%s':\n\t%s", - lua_tostring(L, 1), filename, lua_tostring(L, -1)); +static int checkload(lua_State* L, int stat, const char* filename) +{ + if (stat) + { + /* module loaded successfully? */ + lua_pushstring(L, filename); /* will be 2nd argument to module */ + return 2; /* return open function and file name */ + } + else + return luaL_error(L, "error loading module '%s' from file '%s':\n\t%s", + lua_tostring(L, 1), filename, lua_tostring(L, -1)); } -static int searcher_Lua (lua_State *L) { - const char *filename; - const char *name = luaL_checkstring(L, 1); - filename = findfile(L, name, "path", LUA_LSUBSEP); - if (filename == NULL) return 1; /* module not found in this path */ - return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename); +static int searcher_Lua(lua_State* L) +{ + const char* filename; + const char* name = luaL_checkstring(L, 1); + filename = findfile(L, name, "path", LUA_LSUBSEP); + if (filename == NULL) return 1; /* module not found in this path */ + return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename); } @@ -509,118 +537,134 @@ static int searcher_Lua (lua_State *L) { ** fails, it also tries "luaopen_Y".) If there is no ignore mark, ** look for a function named "luaopen_modname". */ -static int loadfunc (lua_State *L, const char *filename, const char *modname) { - const char *openfunc; - const char *mark; - modname = luaL_gsub(L, modname, ".", LUA_OFSEP); - mark = strchr(modname, *LUA_IGMARK); - if (mark) { - int stat; - openfunc = lua_pushlstring(L, modname, mark - modname); - openfunc = lua_pushfstring(L, LUA_POF"%s", openfunc); - stat = lookforfunc(L, filename, openfunc); - if (stat != ERRFUNC) return stat; - modname = mark + 1; /* else go ahead and try old-style name */ - } - openfunc = lua_pushfstring(L, LUA_POF"%s", modname); - return lookforfunc(L, filename, openfunc); +static int loadfunc(lua_State* L, const char* filename, const char* modname) +{ + const char* openfunc; + const char* mark; + modname = luaL_gsub(L, modname, ".", LUA_OFSEP); + mark = strchr(modname, *LUA_IGMARK); + if (mark) + { + int stat; + openfunc = lua_pushlstring(L, modname, mark - modname); + openfunc = lua_pushfstring(L, LUA_POF"%s", openfunc); + stat = lookforfunc(L, filename, openfunc); + if (stat != ERRFUNC) return stat; + modname = mark + 1; /* else go ahead and try old-style name */ + } + openfunc = lua_pushfstring(L, LUA_POF"%s", modname); + return lookforfunc(L, filename, openfunc); } -static int searcher_C (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP); - if (filename == NULL) return 1; /* module not found in this path */ - return checkload(L, (loadfunc(L, filename, name) == 0), filename); +static int searcher_C(lua_State* L) +{ + const char* name = luaL_checkstring(L, 1); + const char* filename = findfile(L, name, "cpath", LUA_CSUBSEP); + if (filename == NULL) return 1; /* module not found in this path */ + return checkload(L, (loadfunc(L, filename, name) == 0), filename); } -static int searcher_Croot (lua_State *L) { - const char *filename; - const char *name = luaL_checkstring(L, 1); - const char *p = strchr(name, '.'); - int stat; - if (p == NULL) return 0; /* is root */ - lua_pushlstring(L, name, p - name); - filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP); - if (filename == NULL) return 1; /* root not found */ - if ((stat = loadfunc(L, filename, name)) != 0) { - if (stat != ERRFUNC) - return checkload(L, 0, filename); /* real error */ - else { /* open function not found */ - lua_pushfstring(L, "\n\tno module '%s' in file '%s'", name, filename); - return 1; - } - } - lua_pushstring(L, filename); /* will be 2nd argument to module */ - return 2; +static int searcher_Croot(lua_State* L) +{ + const char* filename; + const char* name = luaL_checkstring(L, 1); + const char* p = strchr(name, '.'); + int stat; + if (p == NULL) return 0; /* is root */ + lua_pushlstring(L, name, p - name); + filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP); + if (filename == NULL) return 1; /* root not found */ + if ((stat = loadfunc(L, filename, name)) != 0) + { + if (stat != ERRFUNC) + return checkload(L, 0, filename); /* real error */ + else + { + /* open function not found */ + lua_pushfstring(L, "\n\tno module '%s' in file '%s'", name, filename); + return 1; + } + } + lua_pushstring(L, filename); /* will be 2nd argument to module */ + return 2; } -static int searcher_preload (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - lua_getfield(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); - if (lua_getfield(L, -1, name) == LUA_TNIL) /* not found? */ - lua_pushfstring(L, "\n\tno field package.preload['%s']", name); - return 1; +static int searcher_preload(lua_State* L) +{ + const char* name = luaL_checkstring(L, 1); + lua_getfield(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); + if (lua_getfield(L, -1, name) == LUA_TNIL) /* not found? */ + lua_pushfstring(L, "\n\tno field package.preload['%s']", name); + return 1; } -static void findloader (lua_State *L, const char *name) { - int i; - luaL_Buffer msg; /* to build error message */ - luaL_buffinit(L, &msg); - /* push 'package.searchers' to index 3 in the stack */ - if (lua_getfield(L, lua_upvalueindex(1), "searchers") != LUA_TTABLE) - luaL_error(L, "'package.searchers' must be a table"); - /* iterate over available searchers to find a loader */ - for (i = 1; ; i++) { - if (lua_rawgeti(L, 3, i) == LUA_TNIL) { /* no more searchers? */ - lua_pop(L, 1); /* remove nil */ - luaL_pushresult(&msg); /* create error message */ - luaL_error(L, "module '%s' not found:%s", name, lua_tostring(L, -1)); - } - lua_pushstring(L, name); - lua_call(L, 1, 2); /* call it */ - if (lua_isfunction(L, -2)) /* did it find a loader? */ - return; /* module loader found */ - else if (lua_isstring(L, -2)) { /* searcher returned error message? */ - lua_pop(L, 1); /* remove extra return */ - luaL_addvalue(&msg); /* concatenate error message */ - } - else - lua_pop(L, 2); /* remove both returns */ - } +static void findloader(lua_State* L, const char* name) +{ + int i; + luaL_Buffer msg; /* to build error message */ + luaL_buffinit(L, &msg); + /* push 'package.searchers' to index 3 in the stack */ + if (lua_getfield(L, lua_upvalueindex(1), "searchers") != LUA_TTABLE) + luaL_error(L, "'package.searchers' must be a table"); + /* iterate over available searchers to find a loader */ + for (i = 1; ; i++) + { + if (lua_rawgeti(L, 3, i) == LUA_TNIL) + { + /* no more searchers? */ + lua_pop(L, 1); /* remove nil */ + luaL_pushresult(&msg); /* create error message */ + luaL_error(L, "module '%s' not found:%s", name, lua_tostring(L, -1)); + } + lua_pushstring(L, name); + lua_call(L, 1, 2); /* call it */ + if (lua_isfunction(L, -2)) /* did it find a loader? */ + return; /* module loader found */ + else if (lua_isstring(L, -2)) + { + /* searcher returned error message? */ + lua_pop(L, 1); /* remove extra return */ + luaL_addvalue(&msg); /* concatenate error message */ + } + else + lua_pop(L, 2); /* remove both returns */ + } } -static int ll_require (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - lua_settop(L, 1); /* LOADED table will be at index 2 */ - lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); - lua_getfield(L, 2, name); /* LOADED[name] */ - if (lua_toboolean(L, -1)) /* is it there? */ - return 1; /* package is already loaded */ - /* else must load package */ - lua_pop(L, 1); /* remove 'getfield' result */ - findloader(L, name); - lua_pushstring(L, name); /* pass name as argument to module loader */ - lua_insert(L, -2); /* name is 1st argument (before search data) */ - lua_call(L, 2, 1); /* run loader to load module */ - if (!lua_isnil(L, -1)) /* non-nil return? */ - lua_setfield(L, 2, name); /* LOADED[name] = returned value */ - if (lua_getfield(L, 2, name) == LUA_TNIL) { /* module set no value? */ - lua_pushboolean(L, 1); /* use true as result */ - lua_pushvalue(L, -1); /* extra copy to be returned */ - lua_setfield(L, 2, name); /* LOADED[name] = true */ - } - return 1; +static int ll_require(lua_State* L) +{ + const char* name = luaL_checkstring(L, 1); + lua_settop(L, 1); /* LOADED table will be at index 2 */ + lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + lua_getfield(L, 2, name); /* LOADED[name] */ + if (lua_toboolean(L, -1)) /* is it there? */ + return 1; /* package is already loaded */ + /* else must load package */ + lua_pop(L, 1); /* remove 'getfield' result */ + findloader(L, name); + lua_pushstring(L, name); /* pass name as argument to module loader */ + lua_insert(L, -2); /* name is 1st argument (before search data) */ + lua_call(L, 2, 1); /* run loader to load module */ + if (!lua_isnil(L, -1)) /* non-nil return? */ + lua_setfield(L, 2, name); /* LOADED[name] = returned value */ + if (lua_getfield(L, 2, name) == LUA_TNIL) + { + /* module set no value? */ + lua_pushboolean(L, 1); /* use true as result */ + lua_pushvalue(L, -1); /* extra copy to be returned */ + lua_setfield(L, 2, name); /* LOADED[name] = true */ + } + return 1; } /* }====================================================== */ - /* ** {====================================================== ** 'module' function @@ -704,20 +748,19 @@ static int ll_seeall (lua_State *L) { /* }====================================================== */ - static const luaL_Reg pk_funcs[] = { - {"loadlib", ll_loadlib}, - {"searchpath", ll_searchpath}, + {"loadlib", ll_loadlib}, + {"searchpath", ll_searchpath}, #if defined(LUA_COMPAT_MODULE) {"seeall", ll_seeall}, #endif - /* placeholders */ - {"preload", NULL}, - {"cpath", NULL}, - {"path", NULL}, - {"searchers", NULL}, - {"loaded", NULL}, - {NULL, NULL} + /* placeholders */ + {"preload", NULL}, + {"cpath", NULL}, + {"path", NULL}, + {"searchers", NULL}, + {"loaded", NULL}, + {NULL, NULL} }; @@ -725,28 +768,30 @@ static const luaL_Reg ll_funcs[] = { #if defined(LUA_COMPAT_MODULE) {"module", ll_module}, #endif - {"require", ll_require}, - {NULL, NULL} + {"require", ll_require}, + {NULL, NULL} }; -static void createsearcherstable (lua_State *L) { - static const lua_CFunction searchers[] = - {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL}; - int i; - /* create 'searchers' table */ - lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); - /* fill it with predefined searchers */ - for (i=0; searchers[i] != NULL; i++) { - lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */ - lua_pushcclosure(L, searchers[i], 1); - lua_rawseti(L, -2, i+1); - } +static void createsearcherstable(lua_State* L) +{ + static const lua_CFunction searchers[] = + {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL}; + int i; + /* create 'searchers' table */ + lua_createtable(L, sizeof(searchers) / sizeof(searchers[0]) - 1, 0); + /* fill it with predefined searchers */ + for (i = 0; searchers[i] != NULL; i++) + { + lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */ + lua_pushcclosure(L, searchers[i], 1); + lua_rawseti(L, -2, i + 1); + } #if defined(LUA_COMPAT_LOADERS) lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ lua_setfield(L, -3, "loaders"); /* put it in field 'loaders' */ #endif - lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ + lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ } @@ -754,37 +799,38 @@ static void createsearcherstable (lua_State *L) { ** create table CLIBS to keep track of loaded C libraries, ** setting a finalizer to close all libraries when closing state. */ -static void createclibstable (lua_State *L) { - lua_newtable(L); /* create CLIBS table */ - lua_createtable(L, 0, 1); /* create metatable for CLIBS */ - lua_pushcfunction(L, gctm); - lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ - lua_setmetatable(L, -2); - lua_rawsetp(L, LUA_REGISTRYINDEX, &CLIBS); /* set CLIBS table in registry */ +static void createclibstable(lua_State* L) +{ + lua_newtable(L); /* create CLIBS table */ + lua_createtable(L, 0, 1); /* create metatable for CLIBS */ + lua_pushcfunction(L, gctm); + lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ + lua_setmetatable(L, -2); + lua_rawsetp(L, LUA_REGISTRYINDEX, &CLIBS); /* set CLIBS table in registry */ } -LUAMOD_API int luaopen_package (lua_State *L) { - createclibstable(L); - luaL_newlib(L, pk_funcs); /* create 'package' table */ - createsearcherstable(L); - /* set paths */ - setpath(L, "path", LUA_PATH_VAR, LUA_PATH_DEFAULT); - setpath(L, "cpath", LUA_CPATH_VAR, LUA_CPATH_DEFAULT); - /* store config information */ - lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n" - LUA_EXEC_DIR "\n" LUA_IGMARK "\n"); - lua_setfield(L, -2, "config"); - /* set field 'loaded' */ - luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); - lua_setfield(L, -2, "loaded"); - /* set field 'preload' */ - luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); - lua_setfield(L, -2, "preload"); - lua_pushglobaltable(L); - lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */ - luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */ - lua_pop(L, 1); /* pop global table */ - return 1; /* return 'package' table */ +LUAMOD_API int luaopen_package(lua_State* L) +{ + createclibstable(L); + luaL_newlib(L, pk_funcs); /* create 'package' table */ + createsearcherstable(L); + /* set paths */ + setpath(L, "path", LUA_PATH_VAR, LUA_PATH_DEFAULT); + setpath(L, "cpath", LUA_CPATH_VAR, LUA_CPATH_DEFAULT); + /* store config information */ + lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n" + LUA_EXEC_DIR "\n" LUA_IGMARK "\n"); + lua_setfield(L, -2, "config"); + /* set field 'loaded' */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + lua_setfield(L, -2, "loaded"); + /* set field 'preload' */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); + lua_setfield(L, -2, "preload"); + lua_pushglobaltable(L); + lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */ + luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */ + lua_pop(L, 1); /* pop global table */ + return 1; /* return 'package' table */ } - diff --git a/Lua/lobject.c b/Lua/lobject.c index 2da7689..53c3e3f 100644 --- a/Lua/lobject.c +++ b/Lua/lobject.c @@ -29,7 +29,6 @@ #include "lvm.h" - LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; @@ -38,142 +37,185 @@ LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; ** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if ** eeeee != 0 and (xxx) otherwise. */ -int luaO_int2fb (unsigned int x) { - int e = 0; /* exponent */ - if (x < 8) return x; - while (x >= (8 << 4)) { /* coarse steps */ - x = (x + 0xf) >> 4; /* x = ceil(x / 16) */ - e += 4; - } - while (x >= (8 << 1)) { /* fine steps */ - x = (x + 1) >> 1; /* x = ceil(x / 2) */ - e++; - } - return ((e+1) << 3) | (cast_int(x) - 8); +int luaO_int2fb(unsigned int x) +{ + int e = 0; /* exponent */ + if (x < 8) return x; + while (x >= (8 << 4)) + { + /* coarse steps */ + x = (x + 0xf) >> 4; /* x = ceil(x / 16) */ + e += 4; + } + while (x >= (8 << 1)) + { + /* fine steps */ + x = (x + 1) >> 1; /* x = ceil(x / 2) */ + e++; + } + return ((e + 1) << 3) | (cast_int(x) - 8); } /* converts back */ -int luaO_fb2int (int x) { - return (x < 8) ? x : ((x & 7) + 8) << ((x >> 3) - 1); +int luaO_fb2int(int x) +{ + return (x < 8) ? x : ((x & 7) + 8) << ((x >> 3) - 1); } /* ** Computes ceil(log2(x)) */ -int luaO_ceillog2 (unsigned int x) { - static const lu_byte log_2[256] = { /* log_2[i] = ceil(log2(i - 1)) */ - 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 - }; - int l = 0; - x--; - while (x >= 256) { l += 8; x >>= 8; } - return l + log_2[x]; +int luaO_ceillog2(unsigned int x) +{ + static const lu_byte log_2[256] = { + /* log_2[i] = ceil(log2(i - 1)) */ + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 + }; + int l = 0; + x--; + while (x >= 256) + { + l += 8; + x >>= 8; + } + return l + log_2[x]; } -static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, - lua_Integer v2) { - switch (op) { - case LUA_OPADD: return intop(+, v1, v2); - case LUA_OPSUB:return intop(-, v1, v2); - case LUA_OPMUL:return intop(*, v1, v2); - case LUA_OPMOD: return luaV_mod(L, v1, v2); - case LUA_OPIDIV: return luaV_div(L, v1, v2); - case LUA_OPBAND: return intop(&, v1, v2); - case LUA_OPBOR: return intop(|, v1, v2); - case LUA_OPBXOR: return intop(^, v1, v2); - case LUA_OPSHL: return luaV_shiftl(v1, v2); - case LUA_OPSHR: return luaV_shiftl(v1, -v2); - case LUA_OPUNM: return intop(-, 0, v1); - case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1); - default: lua_assert(0); return 0; - } +static lua_Integer intarith(lua_State* L, int op, lua_Integer v1, + lua_Integer v2) +{ + switch (op) + { + case LUA_OPADD: return intop(+, v1, v2); + case LUA_OPSUB: return intop(-, v1, v2); + case LUA_OPMUL: return intop(*, v1, v2); + case LUA_OPMOD: return luaV_mod(L, v1, v2); + case LUA_OPIDIV: return luaV_div(L, v1, v2); + case LUA_OPBAND: return intop(&, v1, v2); + case LUA_OPBOR: return intop(|, v1, v2); + case LUA_OPBXOR: return intop(^, v1, v2); + case LUA_OPSHL: return luaV_shiftl(v1, v2); + case LUA_OPSHR: return luaV_shiftl(v1, -v2); + case LUA_OPUNM: return intop(-, 0, v1); + case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1); + default: lua_assert(0); + return 0; + } } -static lua_Number numarith (lua_State *L, int op, lua_Number v1, - lua_Number v2) { - switch (op) { - case LUA_OPADD: return luai_numadd(L, v1, v2); - case LUA_OPSUB: return luai_numsub(L, v1, v2); - case LUA_OPMUL: return luai_nummul(L, v1, v2); - case LUA_OPDIV: return luai_numdiv(L, v1, v2); - case LUA_OPPOW: return luai_numpow(L, v1, v2); - case LUA_OPIDIV: return luai_numidiv(L, v1, v2); - case LUA_OPUNM: return luai_numunm(L, v1); - case LUA_OPMOD: { - lua_Number m; - luai_nummod(L, v1, v2, m); - return m; - } - default: lua_assert(0); return 0; - } +static lua_Number numarith(lua_State* L, int op, lua_Number v1, + lua_Number v2) +{ + switch (op) + { + case LUA_OPADD: return luai_numadd(L, v1, v2); + case LUA_OPSUB: return luai_numsub(L, v1, v2); + case LUA_OPMUL: return luai_nummul(L, v1, v2); + case LUA_OPDIV: return luai_numdiv(L, v1, v2); + case LUA_OPPOW: return luai_numpow(L, v1, v2); + case LUA_OPIDIV: return luai_numidiv(L, v1, v2); + case LUA_OPUNM: return luai_numunm(L, v1); + case LUA_OPMOD: + { + lua_Number m; + luai_nummod(L, v1, v2, m); + return m; + } + default: lua_assert(0); + return 0; + } } -void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, - TValue *res) { - switch (op) { - case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: - case LUA_OPSHL: case LUA_OPSHR: - case LUA_OPBNOT: { /* operate only on integers */ - lua_Integer i1; lua_Integer i2; - if (tointeger(p1, &i1) && tointeger(p2, &i2)) { - setivalue(res, intarith(L, op, i1, i2)); - return; - } - else break; /* go to the end */ - } - case LUA_OPDIV: case LUA_OPPOW: { /* operate only on floats */ - lua_Number n1; lua_Number n2; - if (tonumber(p1, &n1) && tonumber(p2, &n2)) { - setfltvalue(res, numarith(L, op, n1, n2)); - return; - } - else break; /* go to the end */ - } - default: { /* other operations */ - lua_Number n1; lua_Number n2; - if (ttisinteger(p1) && ttisinteger(p2)) { - setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2))); - return; - } - else if (tonumber(p1, &n1) && tonumber(p2, &n2)) { - setfltvalue(res, numarith(L, op, n1, n2)); - return; - } - else break; /* go to the end */ - } - } - /* could not perform raw operation; try metamethod */ - lua_assert(L != NULL); /* should not fail when folding (compile time) */ - luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD)); +void luaO_arith(lua_State* L, int op, const TValue* p1, const TValue* p2, + TValue* res) +{ + switch (op) + { + case LUA_OPBAND: + case LUA_OPBOR: + case LUA_OPBXOR: + case LUA_OPSHL: + case LUA_OPSHR: + case LUA_OPBNOT: + { + /* operate only on integers */ + lua_Integer i1; + lua_Integer i2; + if (tointeger(p1, &i1) && tointeger(p2, &i2)) + { + setivalue(res, intarith(L, op, i1, i2)); + return; + } + else break; /* go to the end */ + } + case LUA_OPDIV: + case LUA_OPPOW: + { + /* operate only on floats */ + lua_Number n1; + lua_Number n2; + if (tonumber(p1, &n1) && tonumber(p2, &n2)) + { + setfltvalue(res, numarith(L, op, n1, n2)); + return; + } + else break; /* go to the end */ + } + default: + { + /* other operations */ + lua_Number n1; + lua_Number n2; + if (ttisinteger(p1) && ttisinteger(p2)) + { + setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2))); + return; + } + else if (tonumber(p1, &n1) && tonumber(p2, &n2)) + { + setfltvalue(res, numarith(L, op, n1, n2)); + return; + } + else break; /* go to the end */ + } + } + /* could not perform raw operation; try metamethod */ + lua_assert(L != NULL); /* should not fail when folding (compile time) */ + luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD)); } -int luaO_hexavalue (int c) { - if (lisdigit(c)) return c - '0'; - else return (ltolower(c) - 'a') + 10; +int luaO_hexavalue(int c) +{ + if (lisdigit(c)) return c - '0'; + else return (ltolower(c) - 'a') + 10; } -static int isneg (const char **s) { - if (**s == '-') { (*s)++; return 1; } - else if (**s == '+') (*s)++; - return 0; +static int isneg(const char** s) +{ + if (**s == '-') + { + (*s)++; + return 1; + } + else if (**s == '+') (*s)++; + return 0; } - /* ** {================================================================== ** Lua's implementation for 'lua_strx2number' @@ -190,53 +232,60 @@ static int isneg (const char **s) { ** convert an hexadecimal numeric string to a number, following ** C99 specification for 'strtod' */ -static lua_Number lua_strx2number (const char *s, char **endptr) { - int dot = lua_getlocaledecpoint(); - lua_Number r = 0.0; /* result (accumulator) */ - int sigdig = 0; /* number of significant digits */ - int nosigdig = 0; /* number of non-significant digits */ - int e = 0; /* exponent correction */ - int neg; /* 1 if number is negative */ - int hasdot = 0; /* true after seen a dot */ - *endptr = cast(char *, s); /* nothing is valid yet */ - while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ - neg = isneg(&s); /* check signal */ - if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ - return 0.0; /* invalid format (no '0x') */ - for (s += 2; ; s++) { /* skip '0x' and read numeral */ - if (*s == dot) { - if (hasdot) break; /* second dot? stop loop */ - else hasdot = 1; - } - else if (lisxdigit(cast_uchar(*s))) { - if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */ - nosigdig++; - else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */ - r = (r * cast_num(16.0)) + luaO_hexavalue(*s); - else e++; /* too many digits; ignore, but still count for exponent */ - if (hasdot) e--; /* decimal digit? correct exponent */ - } - else break; /* neither a dot nor a digit */ - } - if (nosigdig + sigdig == 0) /* no digits? */ - return 0.0; /* invalid format */ - *endptr = cast(char *, s); /* valid up to here */ - e *= 4; /* each digit multiplies/divides value by 2^4 */ - if (*s == 'p' || *s == 'P') { /* exponent part? */ - int exp1 = 0; /* exponent value */ - int neg1; /* exponent signal */ - s++; /* skip 'p' */ - neg1 = isneg(&s); /* signal */ - if (!lisdigit(cast_uchar(*s))) - return 0.0; /* invalid; must have at least one digit */ - while (lisdigit(cast_uchar(*s))) /* read exponent */ - exp1 = exp1 * 10 + *(s++) - '0'; - if (neg1) exp1 = -exp1; - e += exp1; - *endptr = cast(char *, s); /* valid up to here */ - } - if (neg) r = -r; - return l_mathop(ldexp)(r, e); +static lua_Number lua_strx2number(const char* s, char** endptr) +{ + int dot = lua_getlocaledecpoint(); + lua_Number r = 0.0; /* result (accumulator) */ + int sigdig = 0; /* number of significant digits */ + int nosigdig = 0; /* number of non-significant digits */ + int e = 0; /* exponent correction */ + int neg; /* 1 if number is negative */ + int hasdot = 0; /* true after seen a dot */ + *endptr = cast(char *, s); /* nothing is valid yet */ + while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ + neg = isneg(&s); /* check signal */ + if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ + return 0.0; /* invalid format (no '0x') */ + for (s += 2; ; s++) + { + /* skip '0x' and read numeral */ + if (*s == dot) + { + if (hasdot) break; /* second dot? stop loop */ + else hasdot = 1; + } + else if (lisxdigit(cast_uchar(*s))) + { + if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */ + nosigdig++; + else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */ + r = (r * cast_num(16.0)) + luaO_hexavalue(*s); + else e++; /* too many digits; ignore, but still count for exponent */ + if (hasdot) e--; /* decimal digit? correct exponent */ + } + else break; /* neither a dot nor a digit */ + } + if (nosigdig + sigdig == 0) /* no digits? */ + return 0.0; /* invalid format */ + *endptr = cast(char *, s); /* valid up to here */ + e *= 4; /* each digit multiplies/divides value by 2^4 */ + if (*s == 'p' || *s == 'P') + { + /* exponent part? */ + int exp1 = 0; /* exponent value */ + int neg1; /* exponent signal */ + s++; /* skip 'p' */ + neg1 = isneg(&s); /* signal */ + if (!lisdigit(cast_uchar(*s))) + return 0.0; /* invalid; must have at least one digit */ + while (lisdigit(cast_uchar(*s))) /* read exponent */ + exp1 = exp1 * 10 + *(s++) - '0'; + if (neg1) exp1 = -exp1; + e += exp1; + *endptr = cast(char *, s); /* valid up to here */ + } + if (neg) r = -r; + return l_mathop(ldexp)(r, e); } #endif @@ -248,13 +297,15 @@ static lua_Number lua_strx2number (const char *s, char **endptr) { #define L_MAXLENNUM 200 #endif -static const char *l_str2dloc (const char *s, lua_Number *result, int mode) { - char *endptr; - *result = (mode == 'x') ? lua_strx2number(s, &endptr) /* try to convert */ - : lua_str2number(s, &endptr); - if (endptr == s) return NULL; /* nothing recognized? */ - while (lisspace(cast_uchar(*endptr))) endptr++; /* skip trailing spaces */ - return (*endptr == '\0') ? endptr : NULL; /* OK if no trailing characters */ +static const char* l_str2dloc(const char* s, lua_Number* result, int mode) +{ + char* endptr; + *result = (mode == 'x') + ? lua_strx2number(s, &endptr) /* try to convert */ + : lua_str2number(s, &endptr); + if (endptr == s) return NULL; /* nothing recognized? */ + while (lisspace(cast_uchar(*endptr))) endptr++; /* skip trailing spaces */ + return (*endptr == '\0') ? endptr : NULL; /* OK if no trailing characters */ } @@ -271,93 +322,116 @@ static const char *l_str2dloc (const char *s, lua_Number *result, int mode) { ** to a buffer (because 's' is read-only), changes the dot to the ** current locale radix mark, and tries to convert again. */ -static const char *l_str2d (const char *s, lua_Number *result) { - const char *endptr; - const char *pmode = strpbrk(s, ".xXnN"); - int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0; - if (mode == 'n') /* reject 'inf' and 'nan' */ - return NULL; - endptr = l_str2dloc(s, result, mode); /* try to convert */ - if (endptr == NULL) { /* failed? may be a different locale */ - char buff[L_MAXLENNUM + 1]; - const char *pdot = strchr(s, '.'); - if (strlen(s) > L_MAXLENNUM || pdot == NULL) - return NULL; /* string too long or no dot; fail */ - strcpy(buff, s); /* copy string to buffer */ - buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */ - endptr = l_str2dloc(buff, result, mode); /* try again */ - if (endptr != NULL) - endptr = s + (endptr - buff); /* make relative to 's' */ - } - return endptr; +static const char* l_str2d(const char* s, lua_Number* result) +{ + const char* endptr; + const char* pmode = strpbrk(s, ".xXnN"); + int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0; + if (mode == 'n') /* reject 'inf' and 'nan' */ + return NULL; + endptr = l_str2dloc(s, result, mode); /* try to convert */ + if (endptr == NULL) + { + /* failed? may be a different locale */ + char buff[L_MAXLENNUM + 1]; + const char* pdot = strchr(s, '.'); + if (strlen(s) > L_MAXLENNUM || pdot == NULL) + return NULL; /* string too long or no dot; fail */ + strcpy(buff, s); /* copy string to buffer */ + buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */ + endptr = l_str2dloc(buff, result, mode); /* try again */ + if (endptr != NULL) + endptr = s + (endptr - buff); /* make relative to 's' */ + } + return endptr; } #define MAXBY10 cast(lua_Unsigned, LUA_MAXINTEGER / 10) #define MAXLASTD cast_int(LUA_MAXINTEGER % 10) -static const char *l_str2int (const char *s, lua_Integer *result) { - lua_Unsigned a = 0; - int empty = 1; - int neg; - while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ - neg = isneg(&s); - if (s[0] == '0' && - (s[1] == 'x' || s[1] == 'X')) { /* hex? */ - s += 2; /* skip '0x' */ - for (; lisxdigit(cast_uchar(*s)); s++) { - a = a * 16 + luaO_hexavalue(*s); - empty = 0; - } - } - else { /* decimal */ - for (; lisdigit(cast_uchar(*s)); s++) { - int d = *s - '0'; - if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg)) /* overflow? */ - return NULL; /* do not accept it (as integer) */ - a = a * 10 + d; - empty = 0; - } - } - while (lisspace(cast_uchar(*s))) s++; /* skip trailing spaces */ - if (empty || *s != '\0') return NULL; /* something wrong in the numeral */ - else { - *result = l_castU2S((neg) ? 0u - a : a); - return s; - } +static const char* l_str2int(const char* s, lua_Integer* result) +{ + lua_Unsigned a = 0; + int empty = 1; + int neg; + while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ + neg = isneg(&s); + if (s[0] == '0' && + (s[1] == 'x' || s[1] == 'X')) + { + /* hex? */ + s += 2; /* skip '0x' */ + for (; lisxdigit(cast_uchar(*s)); s++) + { + a = a * 16 + luaO_hexavalue(*s); + empty = 0; + } + } + else + { + /* decimal */ + for (; lisdigit(cast_uchar(*s)); s++) + { + int d = *s - '0'; + if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg)) /* overflow? */ + return NULL; /* do not accept it (as integer) */ + a = a * 10 + d; + empty = 0; + } + } + while (lisspace(cast_uchar(*s))) s++; /* skip trailing spaces */ + if (empty || *s != '\0') return NULL; /* something wrong in the numeral */ + else + { + *result = l_castU2S((neg) ? 0u - a : a); + return s; + } } -size_t luaO_str2num (const char *s, TValue *o) { - lua_Integer i; lua_Number n; - const char *e; - if ((e = l_str2int(s, &i)) != NULL) { /* try as an integer */ - setivalue(o, i); - } - else if ((e = l_str2d(s, &n)) != NULL) { /* else try as a float */ - setfltvalue(o, n); - } - else - return 0; /* conversion failed */ - return (e - s) + 1; /* success; return string size */ +size_t luaO_str2num(const char* s, TValue* o) +{ + lua_Integer i; + lua_Number n; + const char* e; + if ((e = l_str2int(s, &i)) != NULL) + { + /* try as an integer */ + setivalue(o, i); + } + else if ((e = l_str2d(s, &n)) != NULL) + { + /* else try as a float */ + setfltvalue(o, n); + } + else + return 0; /* conversion failed */ + return (e - s) + 1; /* success; return string size */ } -int luaO_utf8esc (char *buff, unsigned long x) { - int n = 1; /* number of bytes put in buffer (backwards) */ - lua_assert(x <= 0x10FFFF); - if (x < 0x80) /* ascii? */ - buff[UTF8BUFFSZ - 1] = cast(char, x); - else { /* need continuation bytes */ - unsigned int mfb = 0x3f; /* maximum that fits in first byte */ - do { /* add continuation bytes */ - buff[UTF8BUFFSZ - (n++)] = cast(char, 0x80 | (x & 0x3f)); - x >>= 6; /* remove added bits */ - mfb >>= 1; /* now there is one less bit available in first byte */ - } while (x > mfb); /* still needs continuation byte? */ - buff[UTF8BUFFSZ - n] = cast(char, (~mfb << 1) | x); /* add first byte */ - } - return n; +int luaO_utf8esc(char* buff, unsigned long x) +{ + int n = 1; /* number of bytes put in buffer (backwards) */ + lua_assert(x <= 0x10FFFF); + if (x < 0x80) /* ascii? */ + buff[UTF8BUFFSZ - 1] = cast(char, x); + else + { + /* need continuation bytes */ + unsigned int mfb = 0x3f; /* maximum that fits in first byte */ + do + { + /* add continuation bytes */ + buff[UTF8BUFFSZ - (n++)] = cast(char, 0x80 | (x & 0x3f)); + x >>= 6; /* remove added bits */ + mfb >>= 1; /* now there is one less bit available in first byte */ + } + while (x > mfb); /* still needs continuation byte? */ + buff[UTF8BUFFSZ - n] = cast(char, (~mfb << 1) | x); /* add first byte */ + } + return n; } @@ -368,28 +442,33 @@ int luaO_utf8esc (char *buff, unsigned long x) { /* ** Convert a number object to a string */ -void luaO_tostring (lua_State *L, StkId obj) { - char buff[MAXNUMBER2STR]; - size_t len; - lua_assert(ttisnumber(obj)); - if (ttisinteger(obj)) - len = lua_integer2str(buff, sizeof(buff), ivalue(obj)); - else { - len = lua_number2str(buff, sizeof(buff), fltvalue(obj)); +void luaO_tostring(lua_State* L, StkId obj) +{ + char buff[MAXNUMBER2STR]; + size_t len; + lua_assert(ttisnumber(obj)); + if (ttisinteger(obj)) + len = lua_integer2str(buff, sizeof(buff), ivalue(obj)); + else + { + len = lua_number2str(buff, sizeof(buff), fltvalue(obj)); #if !defined(LUA_COMPAT_FLOATSTRING) - if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */ - buff[len++] = lua_getlocaledecpoint(); - buff[len++] = '0'; /* adds '.0' to result */ - } + if (buff[strspn(buff, "-0123456789")] == '\0') + { + /* looks like an int? */ + buff[len++] = lua_getlocaledecpoint(); + buff[len++] = '0'; /* adds '.0' to result */ + } #endif - } - setsvalue2s(L, obj, luaS_newlstr(L, buff, len)); + } + setsvalue2s(L, obj, luaS_newlstr(L, buff, len)); } -static void pushstr (lua_State *L, const char *str, size_t l) { - setsvalue2s(L, L->top, luaS_newlstr(L, str, l)); - luaD_inctop(L); +static void pushstr(lua_State* L, const char* str, size_t l) +{ + setsvalue2s(L, L->top, luaS_newlstr(L, str, l)); + luaD_inctop(L); } @@ -397,80 +476,100 @@ static void pushstr (lua_State *L, const char *str, size_t l) { ** this function handles only '%d', '%c', '%f', '%p', and '%s' conventional formats, plus Lua-specific '%I' and '%U' */ -const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { - int n = 0; - for (;;) { - const char *e = strchr(fmt, '%'); - if (e == NULL) break; - pushstr(L, fmt, e - fmt); - switch (*(e+1)) { - case 's': { /* zero-terminated string */ - const char *s = va_arg(argp, char *); - if (s == NULL) s = "(null)"; - pushstr(L, s, strlen(s)); - break; - } - case 'c': { /* an 'int' as a character */ - char buff = cast(char, va_arg(argp, int)); - if (lisprint(cast_uchar(buff))) - pushstr(L, &buff, 1); - else /* non-printable character; print its code */ - luaO_pushfstring(L, "<\\%d>", cast_uchar(buff)); - break; - } - case 'd': { /* an 'int' */ - setivalue(L->top, va_arg(argp, int)); - goto top2str; - } - case 'I': { /* a 'lua_Integer' */ - setivalue(L->top, cast(lua_Integer, va_arg(argp, l_uacInt))); - goto top2str; - } - case 'f': { /* a 'lua_Number' */ - setfltvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); - top2str: /* convert the top element to a string */ - luaD_inctop(L); - luaO_tostring(L, L->top - 1); - break; - } - case 'p': { /* a pointer */ - char buff[4*sizeof(void *) + 8]; /* should be enough space for a '%p' */ - int l = l_sprintf(buff, sizeof(buff), "%p", va_arg(argp, void *)); - pushstr(L, buff, l); - break; - } - case 'U': { /* an 'int' as a UTF-8 sequence */ - char buff[UTF8BUFFSZ]; - int l = luaO_utf8esc(buff, cast(long, va_arg(argp, long))); - pushstr(L, buff + UTF8BUFFSZ - l, l); - break; - } - case '%': { - pushstr(L, "%", 1); - break; - } - default: { - luaG_runerror(L, "invalid option '%%%c' to 'lua_pushfstring'", - *(e + 1)); - } - } - n += 2; - fmt = e+2; - } - luaD_checkstack(L, 1); - pushstr(L, fmt, strlen(fmt)); - if (n > 0) luaV_concat(L, n + 1); - return svalue(L->top - 1); +const char* luaO_pushvfstring(lua_State* L, const char* fmt, va_list argp) +{ + int n = 0; + for (;;) + { + const char* e = strchr(fmt, '%'); + if (e == NULL) break; + pushstr(L, fmt, e - fmt); + switch (*(e + 1)) + { + case 's': + { + /* zero-terminated string */ + const char* s = va_arg(argp, char *); + if (s == NULL) s = "(null)"; + pushstr(L, s, strlen(s)); + break; + } + case 'c': + { + /* an 'int' as a character */ + char buff = cast(char, va_arg(argp, int)); + if (lisprint(cast_uchar(buff))) + pushstr(L, &buff, 1); + else /* non-printable character; print its code */ + luaO_pushfstring(L, "<\\%d>", cast_uchar(buff)); + break; + } + case 'd': + { + /* an 'int' */ + setivalue(L->top, va_arg(argp, int)); + goto top2str; + } + case 'I': + { + /* a 'lua_Integer' */ + setivalue(L->top, cast(lua_Integer, va_arg(argp, l_uacInt))); + goto top2str; + } + case 'f': + { + /* a 'lua_Number' */ + setfltvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); + top2str: /* convert the top element to a string */ + luaD_inctop(L); + luaO_tostring(L, L->top - 1); + break; + } + case 'p': + { + /* a pointer */ + char buff[4 * sizeof(void*) + 8]; /* should be enough space for a '%p' */ + int l = l_sprintf(buff, sizeof(buff), "%p", va_arg(argp, void *)); + pushstr(L, buff, l); + break; + } + case 'U': + { + /* an 'int' as a UTF-8 sequence */ + char buff[UTF8BUFFSZ]; + int l = luaO_utf8esc(buff, cast(long, va_arg(argp, long))); + pushstr(L, buff + UTF8BUFFSZ - l, l); + break; + } + case '%': + { + pushstr(L, "%", 1); + break; + } + default: + { + luaG_runerror(L, "invalid option '%%%c' to 'lua_pushfstring'", + *(e + 1)); + } + } + n += 2; + fmt = e + 2; + } + luaD_checkstack(L, 1); + pushstr(L, fmt, strlen(fmt)); + if (n > 0) luaV_concat(L, n + 1); + return svalue(L->top - 1); } -const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { - const char *msg; - va_list argp; - va_start(argp, fmt); - msg = luaO_pushvfstring(L, fmt, argp); - va_end(argp); - return msg; +const char* luaO_pushfstring(lua_State* L, const char* fmt, ...) +{ + const char* msg; + va_list argp; + va_start(argp, fmt); + msg = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + return msg; } @@ -483,39 +582,52 @@ const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { #define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) ) -void luaO_chunkid (char *out, const char *source, size_t bufflen) { - size_t l = strlen(source); - if (*source == '=') { /* 'literal' source */ - if (l <= bufflen) /* small enough? */ - memcpy(out, source + 1, l * sizeof(char)); - else { /* truncate it */ - addstr(out, source + 1, bufflen - 1); - *out = '\0'; - } - } - else if (*source == '@') { /* file name */ - if (l <= bufflen) /* small enough? */ - memcpy(out, source + 1, l * sizeof(char)); - else { /* add '...' before rest of name */ - addstr(out, RETS, LL(RETS)); - bufflen -= LL(RETS); - memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char)); - } - } - else { /* string; format as [string "source"] */ - const char *nl = strchr(source, '\n'); /* find first new line (if any) */ - addstr(out, PRE, LL(PRE)); /* add prefix */ - bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ - if (l < bufflen && nl == NULL) { /* small one-line source? */ - addstr(out, source, l); /* keep it */ - } - else { - if (nl != NULL) l = nl - source; /* stop at first newline */ - if (l > bufflen) l = bufflen; - addstr(out, source, l); - addstr(out, RETS, LL(RETS)); - } - memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); - } +void luaO_chunkid(char* out, const char* source, size_t bufflen) +{ + size_t l = strlen(source); + if (*source == '=') + { + /* 'literal' source */ + if (l <= bufflen) /* small enough? */ + memcpy(out, source + 1, l * sizeof(char)); + else + { + /* truncate it */ + addstr(out, source + 1, bufflen - 1); + *out = '\0'; + } + } + else if (*source == '@') + { + /* file name */ + if (l <= bufflen) /* small enough? */ + memcpy(out, source + 1, l * sizeof(char)); + else + { + /* add '...' before rest of name */ + addstr(out, RETS, LL(RETS)); + bufflen -= LL(RETS); + memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char)); + } + } + else + { + /* string; format as [string "source"] */ + const char* nl = strchr(source, '\n'); /* find first new line (if any) */ + addstr(out, PRE, LL(PRE)); /* add prefix */ + bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ + if (l < bufflen && nl == NULL) + { + /* small one-line source? */ + addstr(out, source, l); /* keep it */ + } + else + { + if (nl != NULL) l = nl - source; /* stop at first newline */ + if (l > bufflen) l = bufflen; + addstr(out, source, l); + addstr(out, RETS, LL(RETS)); + } + memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); + } } - diff --git a/Lua/lobject.h b/Lua/lobject.h index 3c04228..539c2a1 100644 --- a/Lua/lobject.h +++ b/Lua/lobject.h @@ -82,13 +82,12 @@ typedef struct GCObject GCObject; /* ** Common type has only the common header */ -struct GCObject { - CommonHeader; +struct GCObject +{ + CommonHeader; }; - - /* ** Tagged Values. This is the basic representation of values in Lua, ** an actual value plus a tag with its type. @@ -97,25 +96,26 @@ struct GCObject { /* ** Union of all Lua values */ -typedef union Value { - GCObject *gc; /* collectable objects */ - void *p; /* light userdata */ - int b; /* booleans */ - lua_CFunction f; /* light C functions */ - lua_Integer i; /* integer numbers */ - lua_Number n; /* float numbers */ +typedef union Value +{ + GCObject* gc; /* collectable objects */ + void* p; /* light userdata */ + int b; /* booleans */ + lua_CFunction f; /* light C functions */ + lua_Integer i; /* integer numbers */ + lua_Number n; /* float numbers */ } Value; #define TValuefields Value value_; int tt_ -typedef struct lua_TValue { - TValuefields; +typedef struct lua_TValue +{ + TValuefields; } TValue; - /* macro defining a nil value */ #define NILCONSTANT {NULL}, LUA_TNIL @@ -255,7 +255,6 @@ typedef struct lua_TValue { #define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY) - #define setobj(L,obj1,obj2) \ { TValue *io1=(obj1); *io1 = *(obj2); \ (void)L; checkliveness(L,io1); } @@ -282,8 +281,6 @@ typedef struct lua_TValue { #define setobj2t(L,o1,o2) ((void)L, *(o1)=*(o2), checkliveness(L,(o1))) - - /* ** {====================================================== ** types and prototypes @@ -291,33 +288,35 @@ typedef struct lua_TValue { */ -typedef TValue *StkId; /* index to stack elements */ - - +typedef TValue* StkId; /* index to stack elements */ /* ** Header for string value; string bytes follow the end of this structure ** (aligned according to 'UTString'; see next). */ -typedef struct TString { - CommonHeader; - lu_byte extra; /* reserved words for short strings; "has hash" for longs */ - lu_byte shrlen; /* length for short strings */ - unsigned int hash; - union { - size_t lnglen; /* length for long strings */ - struct TString *hnext; /* linked list for hash table */ - } u; +typedef struct TString +{ + CommonHeader; + lu_byte extra; /* reserved words for short strings; "has hash" for longs */ + lu_byte shrlen; /* length for short strings */ + unsigned int hash; + + union + { + size_t lnglen; /* length for long strings */ + struct TString* hnext; /* linked list for hash table */ + } u; } TString; /* ** Ensures that address after this type is always fully aligned. */ -typedef union UTString { - L_Umaxalign dummy; /* ensures maximum alignment for strings */ - TString tsv; +typedef union UTString +{ + L_Umaxalign dummy; /* ensures maximum alignment for strings */ + TString tsv; } UTString; @@ -343,21 +342,23 @@ typedef union UTString { ** Header for userdata; memory area follows the end of this structure ** (aligned according to 'UUdata'; see next). */ -typedef struct Udata { - CommonHeader; - lu_byte ttuv_; /* user value's tag */ - struct Table *metatable; - size_t len; /* number of bytes */ - union Value user_; /* user value */ +typedef struct Udata +{ + CommonHeader; + lu_byte ttuv_; /* user value's tag */ + struct Table* metatable; + size_t len; /* number of bytes */ + union Value user_; /* user value */ } Udata; /* ** Ensures that address after this type is always fully aligned. */ -typedef union UUdata { - L_Umaxalign dummy; /* ensures maximum alignment for 'local' udata */ - Udata uv; +typedef union UUdata +{ + L_Umaxalign dummy; /* ensures maximum alignment for 'local' udata */ + Udata uv; } UUdata; @@ -383,10 +384,11 @@ typedef union UUdata { /* ** Description of an upvalue for function prototypes */ -typedef struct Upvaldesc { - TString *name; /* upvalue name (for debug information) */ - lu_byte instack; /* whether it is in stack (register) */ - lu_byte idx; /* index of upvalue (in stack or in outer function's list) */ +typedef struct Upvaldesc +{ + TString* name; /* upvalue name (for debug information) */ + lu_byte instack; /* whether it is in stack (register) */ + lu_byte idx; /* index of upvalue (in stack or in outer function's list) */ } Upvaldesc; @@ -394,42 +396,43 @@ typedef struct Upvaldesc { ** Description of a local variable for function prototypes ** (used for debug information) */ -typedef struct LocVar { - TString *varname; - int startpc; /* first point where variable is active */ - int endpc; /* first point where variable is dead */ +typedef struct LocVar +{ + TString* varname; + int startpc; /* first point where variable is active */ + int endpc; /* first point where variable is dead */ } LocVar; /* ** Function Prototypes */ -typedef struct Proto { - CommonHeader; - lu_byte numparams; /* number of fixed parameters */ - lu_byte is_vararg; - lu_byte maxstacksize; /* number of registers needed by this function */ - int sizeupvalues; /* size of 'upvalues' */ - int sizek; /* size of 'k' */ - int sizecode; - int sizelineinfo; - int sizep; /* size of 'p' */ - int sizelocvars; - int linedefined; /* debug information */ - int lastlinedefined; /* debug information */ - TValue *k; /* constants used by the function */ - Instruction *code; /* opcodes */ - struct Proto **p; /* functions defined inside the function */ - int *lineinfo; /* map from opcodes to source lines (debug information) */ - LocVar *locvars; /* information about local variables (debug information) */ - Upvaldesc *upvalues; /* upvalue information */ - struct LClosure *cache; /* last-created closure with this prototype */ - TString *source; /* used for debug information */ - GCObject *gclist; +typedef struct Proto +{ + CommonHeader; + lu_byte numparams; /* number of fixed parameters */ + lu_byte is_vararg; + lu_byte maxstacksize; /* number of registers needed by this function */ + int sizeupvalues; /* size of 'upvalues' */ + int sizek; /* size of 'k' */ + int sizecode; + int sizelineinfo; + int sizep; /* size of 'p' */ + int sizelocvars; + int linedefined; /* debug information */ + int lastlinedefined; /* debug information */ + TValue* k; /* constants used by the function */ + Instruction* code; /* opcodes */ + struct Proto** p; /* functions defined inside the function */ + int* lineinfo; /* map from opcodes to source lines (debug information) */ + LocVar* locvars; /* information about local variables (debug information) */ + Upvaldesc* upvalues; /* upvalue information */ + struct LClosure* cache; /* last-created closure with this prototype */ + TString* source; /* used for debug information */ + GCObject* gclist; } Proto; - /* ** Lua Upvalues */ @@ -443,23 +446,26 @@ typedef struct UpVal UpVal; #define ClosureHeader \ CommonHeader; lu_byte nupvalues; GCObject *gclist -typedef struct CClosure { - ClosureHeader; - lua_CFunction f; - TValue upvalue[1]; /* list of upvalues */ +typedef struct CClosure +{ + ClosureHeader; + lua_CFunction f; + TValue upvalue[1]; /* list of upvalues */ } CClosure; -typedef struct LClosure { - ClosureHeader; - struct Proto *p; - UpVal *upvals[1]; /* list of upvalues */ +typedef struct LClosure +{ + ClosureHeader; + struct Proto* p; + UpVal* upvals[1]; /* list of upvalues */ } LClosure; -typedef union Closure { - CClosure c; - LClosure l; +typedef union Closure +{ + CClosure c; + LClosure l; } Closure; @@ -472,12 +478,15 @@ typedef union Closure { ** Tables */ -typedef union TKey { - struct { - TValuefields; - int next; /* for chaining (offset for next node) */ - } nk; - TValue tvk; +typedef union TKey +{ + struct + { + TValuefields; + int next; /* for chaining (offset for next node) */ + } nk; + + TValue tvk; } TKey; @@ -488,26 +497,27 @@ typedef union TKey { (void)L; checkliveness(L,io_); } -typedef struct Node { - TValue i_val; - TKey i_key; +typedef struct Node +{ + TValue i_val; + TKey i_key; } Node; -typedef struct Table { - CommonHeader; - lu_byte flags; /* 1<

> RK(C) */ -OP_UNM,/* A B R(A) := -R(B) */ -OP_BNOT,/* A B R(A) := ~R(B) */ -OP_NOT,/* A B R(A) := not R(B) */ -OP_LEN,/* A B R(A) := length of R(B) */ + OP_ADD, + /* A B C R(A) := RK(B) + RK(C) */ + OP_SUB, + /* A B C R(A) := RK(B) - RK(C) */ + OP_MUL, + /* A B C R(A) := RK(B) * RK(C) */ + OP_MOD, + /* A B C R(A) := RK(B) % RK(C) */ + OP_POW, + /* A B C R(A) := RK(B) ^ RK(C) */ + OP_DIV, + /* A B C R(A) := RK(B) / RK(C) */ + OP_IDIV, + /* A B C R(A) := RK(B) // RK(C) */ + OP_BAND, + /* A B C R(A) := RK(B) & RK(C) */ + OP_BOR, + /* A B C R(A) := RK(B) | RK(C) */ + OP_BXOR, + /* A B C R(A) := RK(B) ~ RK(C) */ + OP_SHL, + /* A B C R(A) := RK(B) << RK(C) */ + OP_SHR, + /* A B C R(A) := RK(B) >> RK(C) */ + OP_UNM, + /* A B R(A) := -R(B) */ + OP_BNOT, + /* A B R(A) := ~R(B) */ + OP_NOT, + /* A B R(A) := not R(B) */ + OP_LEN, + /* A B R(A) := length of R(B) */ -OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ + OP_CONCAT, + /* A B C R(A) := R(B).. ... ..R(C) */ -OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */ -OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ -OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ -OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ + OP_JMP, + /* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */ + OP_EQ, + /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ + OP_LT, + /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ + OP_LE, + /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ -OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ -OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ + OP_TEST, + /* A C if not (R(A) <=> C) then pc++ */ + OP_TESTSET, + /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ -OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ -OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ -OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ + OP_CALL, + /* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ + OP_TAILCALL, + /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ + OP_RETURN, + /* A B return R(A), ... ,R(A+B-2) (see note) */ -OP_FORLOOP,/* A sBx R(A)+=R(A+2); - if R(A) tm_sec); - setfield(L, "min", stm->tm_min); - setfield(L, "hour", stm->tm_hour); - setfield(L, "day", stm->tm_mday); - setfield(L, "month", stm->tm_mon + 1); - setfield(L, "year", stm->tm_year + 1900); - setfield(L, "wday", stm->tm_wday + 1); - setfield(L, "yday", stm->tm_yday + 1); - setboolfield(L, "isdst", stm->tm_isdst); +static void setallfields(lua_State* L, struct tm* stm) +{ + setfield(L, "sec", stm->tm_sec); + setfield(L, "min", stm->tm_min); + setfield(L, "hour", stm->tm_hour); + setfield(L, "day", stm->tm_mday); + setfield(L, "month", stm->tm_mon + 1); + setfield(L, "year", stm->tm_year + 1900); + setfield(L, "wday", stm->tm_wday + 1); + setfield(L, "yday", stm->tm_yday + 1); + setboolfield(L, "isdst", stm->tm_isdst); } -static int getboolfield (lua_State *L, const char *key) { - int res; - res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1); - lua_pop(L, 1); - return res; +static int getboolfield(lua_State* L, const char* key) +{ + int res; + res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1); + lua_pop(L, 1); + return res; } @@ -236,43 +246,51 @@ static int getboolfield (lua_State *L, const char *key) { #define L_MAXDATEFIELD (INT_MAX / 2) #endif -static int getfield (lua_State *L, const char *key, int d, int delta) { - int isnum; - int t = lua_getfield(L, -1, key); /* get field and its type */ - lua_Integer res = lua_tointegerx(L, -1, &isnum); - if (!isnum) { /* field is not an integer? */ - if (t != LUA_TNIL) /* some other value? */ - return luaL_error(L, "field '%s' is not an integer", key); - else if (d < 0) /* absent field; no default? */ - return luaL_error(L, "field '%s' missing in date table", key); - res = d; - } - else { - if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD)) - return luaL_error(L, "field '%s' is out-of-bound", key); - res -= delta; - } - lua_pop(L, 1); - return (int)res; +static int getfield(lua_State* L, const char* key, int d, int delta) +{ + int isnum; + int t = lua_getfield(L, -1, key); /* get field and its type */ + lua_Integer res = lua_tointegerx(L, -1, &isnum); + if (!isnum) + { + /* field is not an integer? */ + if (t != LUA_TNIL) /* some other value? */ + return luaL_error(L, "field '%s' is not an integer", key); + else if (d < 0) /* absent field; no default? */ + return luaL_error(L, "field '%s' missing in date table", key); + res = d; + } + else + { + if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD)) + return luaL_error(L, "field '%s' is out-of-bound", key); + res -= delta; + } + lua_pop(L, 1); + return (int)res; } -static const char *checkoption (lua_State *L, const char *conv, - ptrdiff_t convlen, char *buff) { - const char *option = LUA_STRFTIMEOPTIONS; - int oplen = 1; /* length of options being checked */ - for (; *option != '\0' && oplen <= convlen; option += oplen) { - if (*option == '|') /* next block? */ - oplen++; /* will check options with next length (+1) */ - else if (memcmp(conv, option, oplen) == 0) { /* match? */ - memcpy(buff, conv, oplen); /* copy valid option to buffer */ - buff[oplen] = '\0'; - return conv + oplen; /* return next item */ - } - } - luaL_argerror(L, 1, - lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); - return conv; /* to avoid warnings */ +static const char* checkoption(lua_State* L, const char* conv, + ptrdiff_t convlen, char* buff) +{ + const char* option = LUA_STRFTIMEOPTIONS; + int oplen = 1; /* length of options being checked */ + for (; *option != '\0' && oplen <= convlen; option += oplen) + { + if (*option == '|') /* next block? */ + oplen++; /* will check options with next length (+1) */ + else if (memcmp(conv, option, oplen) == 0) + { + /* match? */ + memcpy(buff, conv, oplen); /* copy valid option to buffer */ + buff[oplen] = '\0'; + return conv + oplen; /* return next item */ + } + } + luaL_argerror(L, 1, + lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); + return conv; /* to avoid warnings */ } @@ -280,128 +298,143 @@ static const char *checkoption (lua_State *L, const char *conv, #define SIZETIMEFMT 250 -static int os_date (lua_State *L) { - size_t slen; - const char *s = luaL_optlstring(L, 1, "%c", &slen); - time_t t = luaL_opt(L, l_checktime, 2, time(NULL)); - const char *se = s + slen; /* 's' end */ - struct tm tmr, *stm; - if (*s == '!') { /* UTC? */ - stm = l_gmtime(&t, &tmr); - s++; /* skip '!' */ - } - else - stm = l_localtime(&t, &tmr); - if (stm == NULL) /* invalid date? */ - luaL_error(L, "time result cannot be represented in this installation"); - if (strcmp(s, "*t") == 0) { - lua_createtable(L, 0, 9); /* 9 = number of fields */ - setallfields(L, stm); - } - else { - char cc[4]; /* buffer for individual conversion specifiers */ - luaL_Buffer b; - cc[0] = '%'; - luaL_buffinit(L, &b); - while (s < se) { - if (*s != '%') /* not a conversion specifier? */ - luaL_addchar(&b, *s++); - else { - size_t reslen; - char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT); - s++; /* skip '%' */ - s = checkoption(L, s, se - s, cc + 1); /* copy specifier to 'cc' */ - reslen = strftime(buff, SIZETIMEFMT, cc, stm); - luaL_addsize(&b, reslen); - } - } - luaL_pushresult(&b); - } - return 1; +static int os_date(lua_State* L) +{ + size_t slen; + const char* s = luaL_optlstring(L, 1, "%c", &slen); + time_t t = luaL_opt(L, l_checktime, 2, time(NULL)); + const char* se = s + slen; /* 's' end */ + struct tm tmr, *stm; + if (*s == '!') + { + /* UTC? */ + stm = l_gmtime(&t, &tmr); + s++; /* skip '!' */ + } + else + stm = l_localtime(&t, &tmr); + if (stm == NULL) /* invalid date? */ + luaL_error(L, "time result cannot be represented in this installation"); + if (strcmp(s, "*t") == 0) + { + lua_createtable(L, 0, 9); /* 9 = number of fields */ + setallfields(L, stm); + } + else + { + char cc[4]; /* buffer for individual conversion specifiers */ + luaL_Buffer b; + cc[0] = '%'; + luaL_buffinit(L, &b); + while (s < se) + { + if (*s != '%') /* not a conversion specifier? */ + luaL_addchar(&b, *s++); + else + { + size_t reslen; + char* buff = luaL_prepbuffsize(&b, SIZETIMEFMT); + s++; /* skip '%' */ + s = checkoption(L, s, se - s, cc + 1); /* copy specifier to 'cc' */ + reslen = strftime(buff, SIZETIMEFMT, cc, stm); + luaL_addsize(&b, reslen); + } + } + luaL_pushresult(&b); + } + return 1; } -static int os_time (lua_State *L) { - time_t t; - if (lua_isnoneornil(L, 1)) /* called without args? */ - t = time(NULL); /* get current time */ - else { - struct tm ts; - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 1); /* make sure table is at the top */ - ts.tm_sec = getfield(L, "sec", 0, 0); - ts.tm_min = getfield(L, "min", 0, 0); - ts.tm_hour = getfield(L, "hour", 12, 0); - ts.tm_mday = getfield(L, "day", -1, 0); - ts.tm_mon = getfield(L, "month", -1, 1); - ts.tm_year = getfield(L, "year", -1, 1900); - ts.tm_isdst = getboolfield(L, "isdst"); - t = mktime(&ts); - setallfields(L, &ts); /* update fields with normalized values */ - } - if (t != (time_t)(l_timet)t || t == (time_t)(-1)) - luaL_error(L, "time result cannot be represented in this installation"); - l_pushtime(L, t); - return 1; +static int os_time(lua_State* L) +{ + time_t t; + if (lua_isnoneornil(L, 1)) /* called without args? */ + t = time(NULL); /* get current time */ + else + { + struct tm ts; + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 1); /* make sure table is at the top */ + ts.tm_sec = getfield(L, "sec", 0, 0); + ts.tm_min = getfield(L, "min", 0, 0); + ts.tm_hour = getfield(L, "hour", 12, 0); + ts.tm_mday = getfield(L, "day", -1, 0); + ts.tm_mon = getfield(L, "month", -1, 1); + ts.tm_year = getfield(L, "year", -1, 1900); + ts.tm_isdst = getboolfield(L, "isdst"); + t = mktime(&ts); + setallfields(L, &ts); /* update fields with normalized values */ + } + if (t != (time_t)(l_timet)t || t == (time_t)(-1)) + luaL_error(L, "time result cannot be represented in this installation"); + l_pushtime(L, t); + return 1; } -static int os_difftime (lua_State *L) { - time_t t1 = l_checktime(L, 1); - time_t t2 = l_checktime(L, 2); - lua_pushnumber(L, (lua_Number)difftime(t1, t2)); - return 1; +static int os_difftime(lua_State* L) +{ + time_t t1 = l_checktime(L, 1); + time_t t2 = l_checktime(L, 2); + lua_pushnumber(L, (lua_Number)difftime(t1, t2)); + return 1; } /* }====================================================== */ -static int os_setlocale (lua_State *L) { - static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, - LC_NUMERIC, LC_TIME}; - static const char *const catnames[] = {"all", "collate", "ctype", "monetary", - "numeric", "time", NULL}; - const char *l = luaL_optstring(L, 1, NULL); - int op = luaL_checkoption(L, 2, "all", catnames); - lua_pushstring(L, setlocale(cat[op], l)); - return 1; +static int os_setlocale(lua_State* L) +{ + static const int cat[] = { + LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, + LC_NUMERIC, LC_TIME + }; + static const char* const catnames[] = { + "all", "collate", "ctype", "monetary", + "numeric", "time", NULL + }; + const char* l = luaL_optstring(L, 1, NULL); + int op = luaL_checkoption(L, 2, "all", catnames); + lua_pushstring(L, setlocale(cat[op], l)); + return 1; } -static int os_exit (lua_State *L) { - int status; - if (lua_isboolean(L, 1)) - status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE); - else - status = (int)luaL_optinteger(L, 1, EXIT_SUCCESS); - if (lua_toboolean(L, 2)) - lua_close(L); - if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */ - return 0; +static int os_exit(lua_State* L) +{ + int status; + if (lua_isboolean(L, 1)) + status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE); + else + status = (int)luaL_optinteger(L, 1, EXIT_SUCCESS); + if (lua_toboolean(L, 2)) + lua_close(L); + if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */ + return 0; } static const luaL_Reg syslib[] = { - {"clock", os_clock}, - {"date", os_date}, - {"difftime", os_difftime}, - {"execute", os_execute}, - {"exit", os_exit}, - {"getenv", os_getenv}, - {"remove", os_remove}, - {"rename", os_rename}, - {"setlocale", os_setlocale}, - {"time", os_time}, - {"tmpname", os_tmpname}, - {NULL, NULL} + {"clock", os_clock}, + {"date", os_date}, + {"difftime", os_difftime}, + {"execute", os_execute}, + {"exit", os_exit}, + {"getenv", os_getenv}, + {"remove", os_remove}, + {"rename", os_rename}, + {"setlocale", os_setlocale}, + {"time", os_time}, + {"tmpname", os_tmpname}, + {NULL, NULL} }; /* }====================================================== */ - -LUAMOD_API int luaopen_os (lua_State *L) { - luaL_newlib(L, syslib); - return 1; +LUAMOD_API int luaopen_os(lua_State* L) +{ + luaL_newlib(L, syslib); + return 1; } - diff --git a/Lua/lparser.c b/Lua/lparser.c index cd4512d..6a81824 100644 --- a/Lua/lparser.c +++ b/Lua/lparser.c @@ -28,7 +28,6 @@ #include "ltable.h" - /* maximum number of local variables per function (must be smaller than 250, due to the bytecode format) */ #define MAXVARS 200 @@ -45,209 +44,235 @@ /* ** nodes for block list (list of active blocks) */ -typedef struct BlockCnt { - struct BlockCnt *previous; /* chain */ - int firstlabel; /* index of first label in this block */ - int firstgoto; /* index of first pending goto in this block */ - lu_byte nactvar; /* # active locals outside the block */ - lu_byte upval; /* true if some variable in the block is an upvalue */ - lu_byte isloop; /* true if 'block' is a loop */ +typedef struct BlockCnt +{ + struct BlockCnt* previous; /* chain */ + int firstlabel; /* index of first label in this block */ + int firstgoto; /* index of first pending goto in this block */ + lu_byte nactvar; /* # active locals outside the block */ + lu_byte upval; /* true if some variable in the block is an upvalue */ + lu_byte isloop; /* true if 'block' is a loop */ } BlockCnt; - /* ** prototypes for recursive non-terminal functions */ -static void statement (LexState *ls); -static void expr (LexState *ls, expdesc *v); +static void statement(LexState* ls); +static void expr(LexState* ls, expdesc* v); /* semantic error */ -static l_noret semerror (LexState *ls, const char *msg) { - ls->t.token = 0; /* remove "near " from final message */ - luaX_syntaxerror(ls, msg); +static l_noret semerror(LexState* ls, const char* msg) +{ + ls->t.token = 0; /* remove "near " from final message */ + luaX_syntaxerror(ls, msg); } -static l_noret error_expected (LexState *ls, int token) { - luaX_syntaxerror(ls, - luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token))); +static l_noret error_expected(LexState* ls, int token) +{ + luaX_syntaxerror(ls, + luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token))); } -static l_noret errorlimit (FuncState *fs, int limit, const char *what) { - lua_State *L = fs->ls->L; - const char *msg; - int line = fs->f->linedefined; - const char *where = (line == 0) - ? "main function" - : luaO_pushfstring(L, "function at line %d", line); - msg = luaO_pushfstring(L, "too many %s (limit is %d) in %s", - what, limit, where); - luaX_syntaxerror(fs->ls, msg); +static l_noret errorlimit(FuncState* fs, int limit, const char* what) +{ + lua_State* L = fs->ls->L; + const char* msg; + int line = fs->f->linedefined; + const char* where = (line == 0) + ? "main function" + : luaO_pushfstring(L, "function at line %d", line); + msg = luaO_pushfstring(L, "too many %s (limit is %d) in %s", + what, limit, where); + luaX_syntaxerror(fs->ls, msg); } -static void checklimit (FuncState *fs, int v, int l, const char *what) { - if (v > l) errorlimit(fs, l, what); +static void checklimit(FuncState* fs, int v, int l, const char* what) +{ + if (v > l) errorlimit(fs, l, what); } -static int testnext (LexState *ls, int c) { - if (ls->t.token == c) { - luaX_next(ls); - return 1; - } - else return 0; +static int testnext(LexState* ls, int c) +{ + if (ls->t.token == c) + { + luaX_next(ls); + return 1; + } + else return 0; } -static void check (LexState *ls, int c) { - if (ls->t.token != c) - error_expected(ls, c); +static void check(LexState* ls, int c) +{ + if (ls->t.token != c) + error_expected(ls, c); } -static void checknext (LexState *ls, int c) { - check(ls, c); - luaX_next(ls); +static void checknext(LexState* ls, int c) +{ + check(ls, c); + luaX_next(ls); } #define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } - -static void check_match (LexState *ls, int what, int who, int where) { - if (!testnext(ls, what)) { - if (where == ls->linenumber) - error_expected(ls, what); - else { - luaX_syntaxerror(ls, luaO_pushfstring(ls->L, - "%s expected (to close %s at line %d)", - luaX_token2str(ls, what), luaX_token2str(ls, who), where)); - } - } +static void check_match(LexState* ls, int what, int who, int where) +{ + if (!testnext(ls, what)) + { + if (where == ls->linenumber) + error_expected(ls, what); + else + { + luaX_syntaxerror(ls, luaO_pushfstring(ls->L, + "%s expected (to close %s at line %d)", + luaX_token2str(ls, what), luaX_token2str(ls, who), where)); + } + } } -static TString *str_checkname (LexState *ls) { - TString *ts; - check(ls, TK_NAME); - ts = ls->t.seminfo.ts; - luaX_next(ls); - return ts; +static TString* str_checkname(LexState* ls) +{ + TString* ts; + check(ls, TK_NAME); + ts = ls->t.seminfo.ts; + luaX_next(ls); + return ts; } -static void init_exp (expdesc *e, expkind k, int i) { - e->f = e->t = NO_JUMP; - e->k = k; - e->u.info = i; +static void init_exp(expdesc* e, expkind k, int i) +{ + e->f = e->t = NO_JUMP; + e->k = k; + e->u.info = i; } -static void codestring (LexState *ls, expdesc *e, TString *s) { - init_exp(e, VK, luaK_stringK(ls->fs, s)); +static void codestring(LexState* ls, expdesc* e, TString* s) +{ + init_exp(e, VK, luaK_stringK(ls->fs, s)); } -static void checkname (LexState *ls, expdesc *e) { - codestring(ls, e, str_checkname(ls)); +static void checkname(LexState* ls, expdesc* e) +{ + codestring(ls, e, str_checkname(ls)); } -static int registerlocalvar (LexState *ls, TString *varname) { - FuncState *fs = ls->fs; - Proto *f = fs->f; - int oldsize = f->sizelocvars; - luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, - LocVar, SHRT_MAX, "local variables"); - while (oldsize < f->sizelocvars) - f->locvars[oldsize++].varname = NULL; - f->locvars[fs->nlocvars].varname = varname; - luaC_objbarrier(ls->L, f, varname); - return fs->nlocvars++; +static int registerlocalvar(LexState* ls, TString* varname) +{ + FuncState* fs = ls->fs; + Proto* f = fs->f; + int oldsize = f->sizelocvars; + luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, + LocVar, SHRT_MAX, "local variables"); + while (oldsize < f->sizelocvars) + f->locvars[oldsize++].varname = NULL; + f->locvars[fs->nlocvars].varname = varname; + luaC_objbarrier(ls->L, f, varname); + return fs->nlocvars++; } -static void new_localvar (LexState *ls, TString *name) { - FuncState *fs = ls->fs; - Dyndata *dyd = ls->dyd; - int reg = registerlocalvar(ls, name); - checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, - MAXVARS, "local variables"); - luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1, - dyd->actvar.size, Vardesc, MAX_INT, "local variables"); - dyd->actvar.arr[dyd->actvar.n++].idx = cast(short, reg); +static void new_localvar(LexState* ls, TString* name) +{ + FuncState* fs = ls->fs; + Dyndata* dyd = ls->dyd; + int reg = registerlocalvar(ls, name); + checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, + MAXVARS, "local variables"); + luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1, + dyd->actvar.size, Vardesc, MAX_INT, "local variables"); + dyd->actvar.arr[dyd->actvar.n++].idx = cast(short, reg); } -static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) { - new_localvar(ls, luaX_newstring(ls, name, sz)); +static void new_localvarliteral_(LexState* ls, const char* name, size_t sz) +{ + new_localvar(ls, luaX_newstring(ls, name, sz)); } #define new_localvarliteral(ls,v) \ new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1) -static LocVar *getlocvar (FuncState *fs, int i) { - int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx; - lua_assert(idx < fs->nlocvars); - return &fs->f->locvars[idx]; +static LocVar* getlocvar(FuncState* fs, int i) +{ + int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx; + lua_assert(idx < fs->nlocvars); + return &fs->f->locvars[idx]; } -static void adjustlocalvars (LexState *ls, int nvars) { - FuncState *fs = ls->fs; - fs->nactvar = cast_byte(fs->nactvar + nvars); - for (; nvars; nvars--) { - getlocvar(fs, fs->nactvar - nvars)->startpc = fs->pc; - } +static void adjustlocalvars(LexState* ls, int nvars) +{ + FuncState* fs = ls->fs; + fs->nactvar = cast_byte(fs->nactvar + nvars); + for (; nvars; nvars--) + { + getlocvar(fs, fs->nactvar - nvars)->startpc = fs->pc; + } } -static void removevars (FuncState *fs, int tolevel) { - fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); - while (fs->nactvar > tolevel) - getlocvar(fs, --fs->nactvar)->endpc = fs->pc; +static void removevars(FuncState* fs, int tolevel) +{ + fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); + while (fs->nactvar > tolevel) + getlocvar(fs, --fs->nactvar)->endpc = fs->pc; } -static int searchupvalue (FuncState *fs, TString *name) { - int i; - Upvaldesc *up = fs->f->upvalues; - for (i = 0; i < fs->nups; i++) { - if (eqstr(up[i].name, name)) return i; - } - return -1; /* not found */ +static int searchupvalue(FuncState* fs, TString* name) +{ + int i; + Upvaldesc* up = fs->f->upvalues; + for (i = 0; i < fs->nups; i++) + { + if (eqstr(up[i].name, name)) return i; + } + return -1; /* not found */ } -static int newupvalue (FuncState *fs, TString *name, expdesc *v) { - Proto *f = fs->f; - int oldsize = f->sizeupvalues; - checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); - luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, - Upvaldesc, MAXUPVAL, "upvalues"); - while (oldsize < f->sizeupvalues) - f->upvalues[oldsize++].name = NULL; - f->upvalues[fs->nups].instack = (v->k == VLOCAL); - f->upvalues[fs->nups].idx = cast_byte(v->u.info); - f->upvalues[fs->nups].name = name; - luaC_objbarrier(fs->ls->L, f, name); - return fs->nups++; +static int newupvalue(FuncState* fs, TString* name, expdesc* v) +{ + Proto* f = fs->f; + int oldsize = f->sizeupvalues; + checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); + luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, + Upvaldesc, MAXUPVAL, "upvalues"); + while (oldsize < f->sizeupvalues) + f->upvalues[oldsize++].name = NULL; + f->upvalues[fs->nups].instack = (v->k == VLOCAL); + f->upvalues[fs->nups].idx = cast_byte(v->u.info); + f->upvalues[fs->nups].name = name; + luaC_objbarrier(fs->ls->L, f, name); + return fs->nups++; } -static int searchvar (FuncState *fs, TString *n) { - int i; - for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { - if (eqstr(n, getlocvar(fs, i)->varname)) - return i; - } - return -1; /* not found */ +static int searchvar(FuncState* fs, TString* n) +{ + int i; + for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) + { + if (eqstr(n, getlocvar(fs, i)->varname)) + return i; + } + return -1; /* not found */ } @@ -255,11 +280,12 @@ static int searchvar (FuncState *fs, TString *n) { Mark block where variable at given level was defined (to emit close instructions later). */ -static void markupval (FuncState *fs, int level) { - BlockCnt *bl = fs->bl; - while (bl->nactvar > level) - bl = bl->previous; - bl->upval = 1; +static void markupval(FuncState* fs, int level) +{ + BlockCnt* bl = fs->bl; + while (bl->nactvar > level) + bl = bl->previous; + bl->upval = 1; } @@ -267,132 +293,155 @@ static void markupval (FuncState *fs, int level) { Find variable with given name 'n'. If it is an upvalue, add this upvalue into all intermediate functions. */ -static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { - if (fs == NULL) /* no more levels? */ - init_exp(var, VVOID, 0); /* default is global */ - else { - int v = searchvar(fs, n); /* look up locals at current level */ - if (v >= 0) { /* found? */ - init_exp(var, VLOCAL, v); /* variable is local */ - if (!base) - markupval(fs, v); /* local will be used as an upval */ - } - else { /* not found as local at current level; try upvalues */ - int idx = searchupvalue(fs, n); /* try existing upvalues */ - if (idx < 0) { /* not found? */ - singlevaraux(fs->prev, n, var, 0); /* try upper levels */ - if (var->k == VVOID) /* not found? */ - return; /* it is a global */ - /* else was LOCAL or UPVAL */ - idx = newupvalue(fs, n, var); /* will be a new upvalue */ - } - init_exp(var, VUPVAL, idx); /* new or old upvalue */ - } - } +static void singlevaraux(FuncState* fs, TString* n, expdesc* var, int base) +{ + if (fs == NULL) /* no more levels? */ + init_exp(var, VVOID, 0); /* default is global */ + else + { + int v = searchvar(fs, n); /* look up locals at current level */ + if (v >= 0) + { + /* found? */ + init_exp(var, VLOCAL, v); /* variable is local */ + if (!base) + markupval(fs, v); /* local will be used as an upval */ + } + else + { + /* not found as local at current level; try upvalues */ + int idx = searchupvalue(fs, n); /* try existing upvalues */ + if (idx < 0) + { + /* not found? */ + singlevaraux(fs->prev, n, var, 0); /* try upper levels */ + if (var->k == VVOID) /* not found? */ + return; /* it is a global */ + /* else was LOCAL or UPVAL */ + idx = newupvalue(fs, n, var); /* will be a new upvalue */ + } + init_exp(var, VUPVAL, idx); /* new or old upvalue */ + } + } } -static void singlevar (LexState *ls, expdesc *var) { - TString *varname = str_checkname(ls); - FuncState *fs = ls->fs; - singlevaraux(fs, varname, var, 1); - if (var->k == VVOID) { /* global name? */ - expdesc key; - singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ - lua_assert(var->k != VVOID); /* this one must exist */ - codestring(ls, &key, varname); /* key is variable name */ - luaK_indexed(fs, var, &key); /* env[varname] */ - } +static void singlevar(LexState* ls, expdesc* var) +{ + TString* varname = str_checkname(ls); + FuncState* fs = ls->fs; + singlevaraux(fs, varname, var, 1); + if (var->k == VVOID) + { + /* global name? */ + expdesc key; + singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ + lua_assert(var->k != VVOID); /* this one must exist */ + codestring(ls, &key, varname); /* key is variable name */ + luaK_indexed(fs, var, &key); /* env[varname] */ + } } -static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { - FuncState *fs = ls->fs; - int extra = nvars - nexps; - if (hasmultret(e->k)) { - extra++; /* includes call itself */ - if (extra < 0) extra = 0; - luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ - if (extra > 1) luaK_reserveregs(fs, extra-1); - } - else { - if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ - if (extra > 0) { - int reg = fs->freereg; - luaK_reserveregs(fs, extra); - luaK_nil(fs, reg, extra); - } - } - if (nexps > nvars) - ls->fs->freereg -= nexps - nvars; /* remove extra values */ +static void adjust_assign(LexState* ls, int nvars, int nexps, expdesc* e) +{ + FuncState* fs = ls->fs; + int extra = nvars - nexps; + if (hasmultret(e->k)) + { + extra++; /* includes call itself */ + if (extra < 0) extra = 0; + luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ + if (extra > 1) luaK_reserveregs(fs, extra - 1); + } + else + { + if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ + if (extra > 0) + { + int reg = fs->freereg; + luaK_reserveregs(fs, extra); + luaK_nil(fs, reg, extra); + } + } + if (nexps > nvars) + ls->fs->freereg -= nexps - nvars; /* remove extra values */ } -static void enterlevel (LexState *ls) { - lua_State *L = ls->L; - ++L->nCcalls; - checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels"); +static void enterlevel(LexState* ls) +{ + lua_State* L = ls->L; + ++L->nCcalls; + checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels"); } #define leavelevel(ls) ((ls)->L->nCcalls--) -static void closegoto (LexState *ls, int g, Labeldesc *label) { - int i; - FuncState *fs = ls->fs; - Labellist *gl = &ls->dyd->gt; - Labeldesc *gt = &gl->arr[g]; - lua_assert(eqstr(gt->name, label->name)); - if (gt->nactvar < label->nactvar) { - TString *vname = getlocvar(fs, gt->nactvar)->varname; - const char *msg = luaO_pushfstring(ls->L, - " at line %d jumps into the scope of local '%s'", - getstr(gt->name), gt->line, getstr(vname)); - semerror(ls, msg); - } - luaK_patchlist(fs, gt->pc, label->pc); - /* remove goto from pending list */ - for (i = g; i < gl->n - 1; i++) - gl->arr[i] = gl->arr[i + 1]; - gl->n--; +static void closegoto(LexState* ls, int g, Labeldesc* label) +{ + int i; + FuncState* fs = ls->fs; + Labellist* gl = &ls->dyd->gt; + Labeldesc* gt = &gl->arr[g]; + lua_assert(eqstr(gt->name, label->name)); + if (gt->nactvar < label->nactvar) + { + TString* vname = getlocvar(fs, gt->nactvar)->varname; + const char* msg = luaO_pushfstring(ls->L, + " at line %d jumps into the scope of local '%s'", + getstr(gt->name), gt->line, getstr(vname)); + semerror(ls, msg); + } + luaK_patchlist(fs, gt->pc, label->pc); + /* remove goto from pending list */ + for (i = g; i < gl->n - 1; i++) + gl->arr[i] = gl->arr[i + 1]; + gl->n--; } /* ** try to close a goto with existing labels; this solves backward jumps */ -static int findlabel (LexState *ls, int g) { - int i; - BlockCnt *bl = ls->fs->bl; - Dyndata *dyd = ls->dyd; - Labeldesc *gt = &dyd->gt.arr[g]; - /* check labels in current block for a match */ - for (i = bl->firstlabel; i < dyd->label.n; i++) { - Labeldesc *lb = &dyd->label.arr[i]; - if (eqstr(lb->name, gt->name)) { /* correct label? */ - if (gt->nactvar > lb->nactvar && - (bl->upval || dyd->label.n > bl->firstlabel)) - luaK_patchclose(ls->fs, gt->pc, lb->nactvar); - closegoto(ls, g, lb); /* close it */ - return 1; - } - } - return 0; /* label not found; cannot close goto */ +static int findlabel(LexState* ls, int g) +{ + int i; + BlockCnt* bl = ls->fs->bl; + Dyndata* dyd = ls->dyd; + Labeldesc* gt = &dyd->gt.arr[g]; + /* check labels in current block for a match */ + for (i = bl->firstlabel; i < dyd->label.n; i++) + { + Labeldesc* lb = &dyd->label.arr[i]; + if (eqstr(lb->name, gt->name)) + { + /* correct label? */ + if (gt->nactvar > lb->nactvar && + (bl->upval || dyd->label.n > bl->firstlabel)) + luaK_patchclose(ls->fs, gt->pc, lb->nactvar); + closegoto(ls, g, lb); /* close it */ + return 1; + } + } + return 0; /* label not found; cannot close goto */ } -static int newlabelentry (LexState *ls, Labellist *l, TString *name, - int line, int pc) { - int n = l->n; - luaM_growvector(ls->L, l->arr, n, l->size, - Labeldesc, SHRT_MAX, "labels/gotos"); - l->arr[n].name = name; - l->arr[n].line = line; - l->arr[n].nactvar = ls->fs->nactvar; - l->arr[n].pc = pc; - l->n = n + 1; - return n; +static int newlabelentry(LexState* ls, Labellist* l, TString* name, + int line, int pc) +{ + int n = l->n; + luaM_growvector(ls->L, l->arr, n, l->size, + Labeldesc, SHRT_MAX, "labels/gotos"); + l->arr[n].name = name; + l->arr[n].line = line; + l->arr[n].nactvar = ls->fs->nactvar; + l->arr[n].pc = pc; + l->n = n + 1; + return n; } @@ -400,15 +449,17 @@ static int newlabelentry (LexState *ls, Labellist *l, TString *name, ** check whether new label 'lb' matches any pending gotos in current ** block; solves forward jumps */ -static void findgotos (LexState *ls, Labeldesc *lb) { - Labellist *gl = &ls->dyd->gt; - int i = ls->fs->bl->firstgoto; - while (i < gl->n) { - if (eqstr(gl->arr[i].name, lb->name)) - closegoto(ls, i, lb); - else - i++; - } +static void findgotos(LexState* ls, Labeldesc* lb) +{ + Labellist* gl = &ls->dyd->gt; + int i = ls->fs->bl->firstgoto; + while (i < gl->n) + { + if (eqstr(gl->arr[i].name, lb->name)) + closegoto(ls, i, lb); + else + i++; + } } @@ -418,98 +469,108 @@ static void findgotos (LexState *ls, Labeldesc *lb) { ** the goto exits the scope of any variable (which can be the ** upvalue), close those variables being exited. */ -static void movegotosout (FuncState *fs, BlockCnt *bl) { - int i = bl->firstgoto; - Labellist *gl = &fs->ls->dyd->gt; - /* correct pending gotos to current block and try to close it - with visible labels */ - while (i < gl->n) { - Labeldesc *gt = &gl->arr[i]; - if (gt->nactvar > bl->nactvar) { - if (bl->upval) - luaK_patchclose(fs, gt->pc, bl->nactvar); - gt->nactvar = bl->nactvar; - } - if (!findlabel(fs->ls, i)) - i++; /* move to next one */ - } +static void movegotosout(FuncState* fs, BlockCnt* bl) +{ + int i = bl->firstgoto; + Labellist* gl = &fs->ls->dyd->gt; + /* correct pending gotos to current block and try to close it + with visible labels */ + while (i < gl->n) + { + Labeldesc* gt = &gl->arr[i]; + if (gt->nactvar > bl->nactvar) + { + if (bl->upval) + luaK_patchclose(fs, gt->pc, bl->nactvar); + gt->nactvar = bl->nactvar; + } + if (!findlabel(fs->ls, i)) + i++; /* move to next one */ + } } -static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { - bl->isloop = isloop; - bl->nactvar = fs->nactvar; - bl->firstlabel = fs->ls->dyd->label.n; - bl->firstgoto = fs->ls->dyd->gt.n; - bl->upval = 0; - bl->previous = fs->bl; - fs->bl = bl; - lua_assert(fs->freereg == fs->nactvar); +static void enterblock(FuncState* fs, BlockCnt* bl, lu_byte isloop) +{ + bl->isloop = isloop; + bl->nactvar = fs->nactvar; + bl->firstlabel = fs->ls->dyd->label.n; + bl->firstgoto = fs->ls->dyd->gt.n; + bl->upval = 0; + bl->previous = fs->bl; + fs->bl = bl; + lua_assert(fs->freereg == fs->nactvar); } /* ** create a label named 'break' to resolve break statements */ -static void breaklabel (LexState *ls) { - TString *n = luaS_new(ls->L, "break"); - int l = newlabelentry(ls, &ls->dyd->label, n, 0, ls->fs->pc); - findgotos(ls, &ls->dyd->label.arr[l]); +static void breaklabel(LexState* ls) +{ + TString* n = luaS_new(ls->L, "break"); + int l = newlabelentry(ls, &ls->dyd->label, n, 0, ls->fs->pc); + findgotos(ls, &ls->dyd->label.arr[l]); } /* ** generates an error for an undefined 'goto'; choose appropriate ** message when label name is a reserved word (which can only be 'break') */ -static l_noret undefgoto (LexState *ls, Labeldesc *gt) { - const char *msg = isreserved(gt->name) - ? "<%s> at line %d not inside a loop" - : "no visible label '%s' for at line %d"; - msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); - semerror(ls, msg); +static l_noret undefgoto(LexState* ls, Labeldesc* gt) +{ + const char* msg = isreserved(gt->name) + ? "<%s> at line %d not inside a loop" + : "no visible label '%s' for at line %d"; + msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); + semerror(ls, msg); } -static void leaveblock (FuncState *fs) { - BlockCnt *bl = fs->bl; - LexState *ls = fs->ls; - if (bl->previous && bl->upval) { - /* create a 'jump to here' to close upvalues */ - int j = luaK_jump(fs); - luaK_patchclose(fs, j, bl->nactvar); - luaK_patchtohere(fs, j); - } - if (bl->isloop) - breaklabel(ls); /* close pending breaks */ - fs->bl = bl->previous; - removevars(fs, bl->nactvar); - lua_assert(bl->nactvar == fs->nactvar); - fs->freereg = fs->nactvar; /* free registers */ - ls->dyd->label.n = bl->firstlabel; /* remove local labels */ - if (bl->previous) /* inner block? */ - movegotosout(fs, bl); /* update pending gotos to outer block */ - else if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */ - undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ +static void leaveblock(FuncState* fs) +{ + BlockCnt* bl = fs->bl; + LexState* ls = fs->ls; + if (bl->previous && bl->upval) + { + /* create a 'jump to here' to close upvalues */ + int j = luaK_jump(fs); + luaK_patchclose(fs, j, bl->nactvar); + luaK_patchtohere(fs, j); + } + if (bl->isloop) + breaklabel(ls); /* close pending breaks */ + fs->bl = bl->previous; + removevars(fs, bl->nactvar); + lua_assert(bl->nactvar == fs->nactvar); + fs->freereg = fs->nactvar; /* free registers */ + ls->dyd->label.n = bl->firstlabel; /* remove local labels */ + if (bl->previous) /* inner block? */ + movegotosout(fs, bl); /* update pending gotos to outer block */ + else if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */ + undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ } /* ** adds a new prototype into list of prototypes */ -static Proto *addprototype (LexState *ls) { - Proto *clp; - lua_State *L = ls->L; - FuncState *fs = ls->fs; - Proto *f = fs->f; /* prototype of current function */ - if (fs->np >= f->sizep) { - int oldsize = f->sizep; - luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions"); - while (oldsize < f->sizep) - f->p[oldsize++] = NULL; - } - f->p[fs->np++] = clp = luaF_newproto(L); - luaC_objbarrier(L, f, clp); - return clp; +static Proto* addprototype(LexState* ls) +{ + Proto* clp; + lua_State* L = ls->L; + FuncState* fs = ls->fs; + Proto* f = fs->f; /* prototype of current function */ + if (fs->np >= f->sizep) + { + int oldsize = f->sizep; + luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions"); + while (oldsize < f->sizep) + f->p[oldsize++] = NULL; + } + f->p[fs->np++] = clp = luaF_newproto(L); + luaC_objbarrier(L, f, clp); + return clp; } @@ -519,61 +580,63 @@ static Proto *addprototype (LexState *ls) { ** so that, if it invokes the GC, the GC knows which registers ** are in use at that time. */ -static void codeclosure (LexState *ls, expdesc *v) { - FuncState *fs = ls->fs->prev; - init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1)); - luaK_exp2nextreg(fs, v); /* fix it at the last register */ +static void codeclosure(LexState* ls, expdesc* v) +{ + FuncState* fs = ls->fs->prev; + init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1)); + luaK_exp2nextreg(fs, v); /* fix it at the last register */ } -static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { - Proto *f; - fs->prev = ls->fs; /* linked list of funcstates */ - fs->ls = ls; - ls->fs = fs; - fs->pc = 0; - fs->lasttarget = 0; - fs->jpc = NO_JUMP; - fs->freereg = 0; - fs->nk = 0; - fs->np = 0; - fs->nups = 0; - fs->nlocvars = 0; - fs->nactvar = 0; - fs->firstlocal = ls->dyd->actvar.n; - fs->bl = NULL; - f = fs->f; - f->source = ls->source; - f->maxstacksize = 2; /* registers 0/1 are always valid */ - enterblock(fs, bl, 0); +static void open_func(LexState* ls, FuncState* fs, BlockCnt* bl) +{ + Proto* f; + fs->prev = ls->fs; /* linked list of funcstates */ + fs->ls = ls; + ls->fs = fs; + fs->pc = 0; + fs->lasttarget = 0; + fs->jpc = NO_JUMP; + fs->freereg = 0; + fs->nk = 0; + fs->np = 0; + fs->nups = 0; + fs->nlocvars = 0; + fs->nactvar = 0; + fs->firstlocal = ls->dyd->actvar.n; + fs->bl = NULL; + f = fs->f; + f->source = ls->source; + f->maxstacksize = 2; /* registers 0/1 are always valid */ + enterblock(fs, bl, 0); } -static void close_func (LexState *ls) { - lua_State *L = ls->L; - FuncState *fs = ls->fs; - Proto *f = fs->f; - luaK_ret(fs, 0, 0); /* final return */ - leaveblock(fs); - luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); - f->sizecode = fs->pc; - luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); - f->sizelineinfo = fs->pc; - luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); - f->sizek = fs->nk; - luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); - f->sizep = fs->np; - luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); - f->sizelocvars = fs->nlocvars; - luaM_reallocvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); - f->sizeupvalues = fs->nups; - lua_assert(fs->bl == NULL); - ls->fs = fs->prev; - luaC_checkGC(L); +static void close_func(LexState* ls) +{ + lua_State* L = ls->L; + FuncState* fs = ls->fs; + Proto* f = fs->f; + luaK_ret(fs, 0, 0); /* final return */ + leaveblock(fs); + luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); + f->sizecode = fs->pc; + luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); + f->sizelineinfo = fs->pc; + luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); + f->sizek = fs->nk; + luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); + f->sizep = fs->np; + luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); + f->sizelocvars = fs->nlocvars; + luaM_reallocvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); + f->sizeupvalues = fs->nups; + lua_assert(fs->bl == NULL); + ls->fs = fs->prev; + luaC_checkGC(L); } - /*============================================================*/ /* GRAMMAR RULES */ /*============================================================*/ @@ -584,46 +647,55 @@ static void close_func (LexState *ls) { ** 'until' closes syntactical blocks, but do not close scope, ** so it is handled in separate. */ -static int block_follow (LexState *ls, int withuntil) { - switch (ls->t.token) { - case TK_ELSE: case TK_ELSEIF: - case TK_END: case TK_EOS: - return 1; - case TK_UNTIL: return withuntil; - default: return 0; - } +static int block_follow(LexState* ls, int withuntil) +{ + switch (ls->t.token) + { + case TK_ELSE: + case TK_ELSEIF: + case TK_END: + case TK_EOS: + return 1; + case TK_UNTIL: return withuntil; + default: return 0; + } } -static void statlist (LexState *ls) { - /* statlist -> { stat [';'] } */ - while (!block_follow(ls, 1)) { - if (ls->t.token == TK_RETURN) { - statement(ls); - return; /* 'return' must be last statement */ - } - statement(ls); - } +static void statlist(LexState* ls) +{ + /* statlist -> { stat [';'] } */ + while (!block_follow(ls, 1)) + { + if (ls->t.token == TK_RETURN) + { + statement(ls); + return; /* 'return' must be last statement */ + } + statement(ls); + } } -static void fieldsel (LexState *ls, expdesc *v) { - /* fieldsel -> ['.' | ':'] NAME */ - FuncState *fs = ls->fs; - expdesc key; - luaK_exp2anyregup(fs, v); - luaX_next(ls); /* skip the dot or colon */ - checkname(ls, &key); - luaK_indexed(fs, v, &key); +static void fieldsel(LexState* ls, expdesc* v) +{ + /* fieldsel -> ['.' | ':'] NAME */ + FuncState* fs = ls->fs; + expdesc key; + luaK_exp2anyregup(fs, v); + luaX_next(ls); /* skip the dot or colon */ + checkname(ls, &key); + luaK_indexed(fs, v, &key); } -static void yindex (LexState *ls, expdesc *v) { - /* index -> '[' expr ']' */ - luaX_next(ls); /* skip the '[' */ - expr(ls, v); - luaK_exp2val(ls->fs, v); - checknext(ls, ']'); +static void yindex(LexState* ls, expdesc* v) +{ + /* index -> '[' expr ']' */ + luaX_next(ls); /* skip the '[' */ + expr(ls, v); + luaK_exp2val(ls->fs, v); + checknext(ls, ']'); } @@ -634,233 +706,273 @@ static void yindex (LexState *ls, expdesc *v) { */ -struct ConsControl { - expdesc v; /* last list item read */ - expdesc *t; /* table descriptor */ - int nh; /* total number of 'record' elements */ - int na; /* total number of array elements */ - int tostore; /* number of array elements pending to be stored */ +struct ConsControl +{ + expdesc v; /* last list item read */ + expdesc* t; /* table descriptor */ + int nh; /* total number of 'record' elements */ + int na; /* total number of array elements */ + int tostore; /* number of array elements pending to be stored */ }; -static void recfield (LexState *ls, struct ConsControl *cc) { - /* recfield -> (NAME | '['exp1']') = exp1 */ - FuncState *fs = ls->fs; - int reg = ls->fs->freereg; - expdesc key, val; - int rkkey; - if (ls->t.token == TK_NAME) { - checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); - checkname(ls, &key); - } - else /* ls->t.token == '[' */ - yindex(ls, &key); - cc->nh++; - checknext(ls, '='); - rkkey = luaK_exp2RK(fs, &key); - expr(ls, &val); - luaK_codeABC(fs, OP_SETTABLE, cc->t->u.info, rkkey, luaK_exp2RK(fs, &val)); - fs->freereg = reg; /* free registers */ +static void recfield(LexState* ls, struct ConsControl* cc) +{ + /* recfield -> (NAME | '['exp1']') = exp1 */ + FuncState* fs = ls->fs; + int reg = ls->fs->freereg; + expdesc key, val; + int rkkey; + if (ls->t.token == TK_NAME) + { + checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); + checkname(ls, &key); + } + else /* ls->t.token == '[' */ + yindex(ls, &key); + cc->nh++; + checknext(ls, '='); + rkkey = luaK_exp2RK(fs, &key); + expr(ls, &val); + luaK_codeABC(fs, OP_SETTABLE, cc->t->u.info, rkkey, luaK_exp2RK(fs, &val)); + fs->freereg = reg; /* free registers */ } -static void closelistfield (FuncState *fs, struct ConsControl *cc) { - if (cc->v.k == VVOID) return; /* there is no list item */ - luaK_exp2nextreg(fs, &cc->v); - cc->v.k = VVOID; - if (cc->tostore == LFIELDS_PER_FLUSH) { - luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ - cc->tostore = 0; /* no more items pending */ - } +static void closelistfield(FuncState* fs, struct ConsControl* cc) +{ + if (cc->v.k == VVOID) return; /* there is no list item */ + luaK_exp2nextreg(fs, &cc->v); + cc->v.k = VVOID; + if (cc->tostore == LFIELDS_PER_FLUSH) + { + luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ + cc->tostore = 0; /* no more items pending */ + } } -static void lastlistfield (FuncState *fs, struct ConsControl *cc) { - if (cc->tostore == 0) return; - if (hasmultret(cc->v.k)) { - luaK_setmultret(fs, &cc->v); - luaK_setlist(fs, cc->t->u.info, cc->na, LUA_MULTRET); - cc->na--; /* do not count last expression (unknown number of elements) */ - } - else { - if (cc->v.k != VVOID) - luaK_exp2nextreg(fs, &cc->v); - luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); - } +static void lastlistfield(FuncState* fs, struct ConsControl* cc) +{ + if (cc->tostore == 0) return; + if (hasmultret(cc->v.k)) + { + luaK_setmultret(fs, &cc->v); + luaK_setlist(fs, cc->t->u.info, cc->na, LUA_MULTRET); + cc->na--; /* do not count last expression (unknown number of elements) */ + } + else + { + if (cc->v.k != VVOID) + luaK_exp2nextreg(fs, &cc->v); + luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); + } } -static void listfield (LexState *ls, struct ConsControl *cc) { - /* listfield -> exp */ - expr(ls, &cc->v); - checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); - cc->na++; - cc->tostore++; +static void listfield(LexState* ls, struct ConsControl* cc) +{ + /* listfield -> exp */ + expr(ls, &cc->v); + checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); + cc->na++; + cc->tostore++; } -static void field (LexState *ls, struct ConsControl *cc) { - /* field -> listfield | recfield */ - switch(ls->t.token) { - case TK_NAME: { /* may be 'listfield' or 'recfield' */ - if (luaX_lookahead(ls) != '=') /* expression? */ - listfield(ls, cc); - else - recfield(ls, cc); - break; - } - case '[': { - recfield(ls, cc); - break; - } - default: { - listfield(ls, cc); - break; - } - } +static void field(LexState* ls, struct ConsControl* cc) +{ + /* field -> listfield | recfield */ + switch (ls->t.token) + { + case TK_NAME: + { + /* may be 'listfield' or 'recfield' */ + if (luaX_lookahead(ls) != '=') /* expression? */ + listfield(ls, cc); + else + recfield(ls, cc); + break; + } + case '[': + { + recfield(ls, cc); + break; + } + default: + { + listfield(ls, cc); + break; + } + } } -static void constructor (LexState *ls, expdesc *t) { - /* constructor -> '{' [ field { sep field } [sep] ] '}' - sep -> ',' | ';' */ - FuncState *fs = ls->fs; - int line = ls->linenumber; - int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); - struct ConsControl cc; - cc.na = cc.nh = cc.tostore = 0; - cc.t = t; - init_exp(t, VRELOCABLE, pc); - init_exp(&cc.v, VVOID, 0); /* no value (yet) */ - luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */ - checknext(ls, '{'); - do { - lua_assert(cc.v.k == VVOID || cc.tostore > 0); - if (ls->t.token == '}') break; - closelistfield(fs, &cc); - field(ls, &cc); - } while (testnext(ls, ',') || testnext(ls, ';')); - check_match(ls, '}', '{', line); - lastlistfield(fs, &cc); - SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ - SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ +static void constructor(LexState* ls, expdesc* t) +{ + /* constructor -> '{' [ field { sep field } [sep] ] '}' + sep -> ',' | ';' */ + FuncState* fs = ls->fs; + int line = ls->linenumber; + int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); + struct ConsControl cc; + cc.na = cc.nh = cc.tostore = 0; + cc.t = t; + init_exp(t, VRELOCABLE, pc); + init_exp(&cc.v, VVOID, 0); /* no value (yet) */ + luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */ + checknext(ls, '{'); + do + { + lua_assert(cc.v.k == VVOID || cc.tostore > 0); + if (ls->t.token == '}') break; + closelistfield(fs, &cc); + field(ls, &cc); + } + while (testnext(ls, ',') || testnext(ls, ';')); + check_match(ls, '}', '{', line); + lastlistfield(fs, &cc); + SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ + SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ } /* }====================================================================== */ - -static void parlist (LexState *ls) { - /* parlist -> [ param { ',' param } ] */ - FuncState *fs = ls->fs; - Proto *f = fs->f; - int nparams = 0; - f->is_vararg = 0; - if (ls->t.token != ')') { /* is 'parlist' not empty? */ - do { - switch (ls->t.token) { - case TK_NAME: { /* param -> NAME */ - new_localvar(ls, str_checkname(ls)); - nparams++; - break; - } - case TK_DOTS: { /* param -> '...' */ - luaX_next(ls); - f->is_vararg = 1; /* declared vararg */ - break; - } - default: luaX_syntaxerror(ls, " or '...' expected"); - } - } while (!f->is_vararg && testnext(ls, ',')); - } - adjustlocalvars(ls, nparams); - f->numparams = cast_byte(fs->nactvar); - luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ +static void parlist(LexState* ls) +{ + /* parlist -> [ param { ',' param } ] */ + FuncState* fs = ls->fs; + Proto* f = fs->f; + int nparams = 0; + f->is_vararg = 0; + if (ls->t.token != ')') + { + /* is 'parlist' not empty? */ + do + { + switch (ls->t.token) + { + case TK_NAME: + { + /* param -> NAME */ + new_localvar(ls, str_checkname(ls)); + nparams++; + break; + } + case TK_DOTS: + { + /* param -> '...' */ + luaX_next(ls); + f->is_vararg = 1; /* declared vararg */ + break; + } + default: luaX_syntaxerror(ls, " or '...' expected"); + } + } + while (!f->is_vararg && testnext(ls, ',')); + } + adjustlocalvars(ls, nparams); + f->numparams = cast_byte(fs->nactvar); + luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ } -static void body (LexState *ls, expdesc *e, int ismethod, int line) { - /* body -> '(' parlist ')' block END */ - FuncState new_fs; - BlockCnt bl; - new_fs.f = addprototype(ls); - new_fs.f->linedefined = line; - open_func(ls, &new_fs, &bl); - checknext(ls, '('); - if (ismethod) { - new_localvarliteral(ls, "self"); /* create 'self' parameter */ - adjustlocalvars(ls, 1); - } - parlist(ls); - checknext(ls, ')'); - statlist(ls); - new_fs.f->lastlinedefined = ls->linenumber; - check_match(ls, TK_END, TK_FUNCTION, line); - codeclosure(ls, e); - close_func(ls); +static void body(LexState* ls, expdesc* e, int ismethod, int line) +{ + /* body -> '(' parlist ')' block END */ + FuncState new_fs; + BlockCnt bl; + new_fs.f = addprototype(ls); + new_fs.f->linedefined = line; + open_func(ls, &new_fs, &bl); + checknext(ls, '('); + if (ismethod) + { + new_localvarliteral(ls, "self"); /* create 'self' parameter */ + adjustlocalvars(ls, 1); + } + parlist(ls); + checknext(ls, ')'); + statlist(ls); + new_fs.f->lastlinedefined = ls->linenumber; + check_match(ls, TK_END, TK_FUNCTION, line); + codeclosure(ls, e); + close_func(ls); } -static int explist (LexState *ls, expdesc *v) { - /* explist -> expr { ',' expr } */ - int n = 1; /* at least one expression */ - expr(ls, v); - while (testnext(ls, ',')) { - luaK_exp2nextreg(ls->fs, v); - expr(ls, v); - n++; - } - return n; +static int explist(LexState* ls, expdesc* v) +{ + /* explist -> expr { ',' expr } */ + int n = 1; /* at least one expression */ + expr(ls, v); + while (testnext(ls, ',')) + { + luaK_exp2nextreg(ls->fs, v); + expr(ls, v); + n++; + } + return n; } -static void funcargs (LexState *ls, expdesc *f, int line) { - FuncState *fs = ls->fs; - expdesc args; - int base, nparams; - switch (ls->t.token) { - case '(': { /* funcargs -> '(' [ explist ] ')' */ - luaX_next(ls); - if (ls->t.token == ')') /* arg list is empty? */ - args.k = VVOID; - else { - explist(ls, &args); - luaK_setmultret(fs, &args); - } - check_match(ls, ')', '(', line); - break; - } - case '{': { /* funcargs -> constructor */ - constructor(ls, &args); - break; - } - case TK_STRING: { /* funcargs -> STRING */ - codestring(ls, &args, ls->t.seminfo.ts); - luaX_next(ls); /* must use 'seminfo' before 'next' */ - break; - } - default: { - luaX_syntaxerror(ls, "function arguments expected"); - } - } - lua_assert(f->k == VNONRELOC); - base = f->u.info; /* base register for call */ - if (hasmultret(args.k)) - nparams = LUA_MULTRET; /* open call */ - else { - if (args.k != VVOID) - luaK_exp2nextreg(fs, &args); /* close last argument */ - nparams = fs->freereg - (base+1); - } - init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); - luaK_fixline(fs, line); - fs->freereg = base+1; /* call remove function and arguments and leaves +static void funcargs(LexState* ls, expdesc* f, int line) +{ + FuncState* fs = ls->fs; + expdesc args; + int base, nparams; + switch (ls->t.token) + { + case '(': + { + /* funcargs -> '(' [ explist ] ')' */ + luaX_next(ls); + if (ls->t.token == ')') /* arg list is empty? */ + args.k = VVOID; + else + { + explist(ls, &args); + luaK_setmultret(fs, &args); + } + check_match(ls, ')', '(', line); + break; + } + case '{': + { + /* funcargs -> constructor */ + constructor(ls, &args); + break; + } + case TK_STRING: + { + /* funcargs -> STRING */ + codestring(ls, &args, ls->t.seminfo.ts); + luaX_next(ls); /* must use 'seminfo' before 'next' */ + break; + } + default: + { + luaX_syntaxerror(ls, "function arguments expected"); + } + } + lua_assert(f->k == VNONRELOC); + base = f->u.info; /* base register for call */ + if (hasmultret(args.k)) + nparams = LUA_MULTRET; /* open call */ + else + { + if (args.k != VVOID) + luaK_exp2nextreg(fs, &args); /* close last argument */ + nparams = fs->freereg - (base + 1); + } + init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams + 1, 2)); + luaK_fixline(fs, line); + fs->freereg = base + 1; /* call remove function and arguments and leaves (unless changed) one result */ } - - /* ** {====================================================================== ** Expression parsing @@ -868,174 +980,212 @@ static void funcargs (LexState *ls, expdesc *f, int line) { */ -static void primaryexp (LexState *ls, expdesc *v) { - /* primaryexp -> NAME | '(' expr ')' */ - switch (ls->t.token) { - case '(': { - int line = ls->linenumber; - luaX_next(ls); - expr(ls, v); - check_match(ls, ')', '(', line); - luaK_dischargevars(ls->fs, v); - return; - } - case TK_NAME: { - singlevar(ls, v); - return; - } - default: { - luaX_syntaxerror(ls, "unexpected symbol"); - } - } +static void primaryexp(LexState* ls, expdesc* v) +{ + /* primaryexp -> NAME | '(' expr ')' */ + switch (ls->t.token) + { + case '(': + { + int line = ls->linenumber; + luaX_next(ls); + expr(ls, v); + check_match(ls, ')', '(', line); + luaK_dischargevars(ls->fs, v); + return; + } + case TK_NAME: + { + singlevar(ls, v); + return; + } + default: + { + luaX_syntaxerror(ls, "unexpected symbol"); + } + } } -static void suffixedexp (LexState *ls, expdesc *v) { - /* suffixedexp -> - primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */ - FuncState *fs = ls->fs; - int line = ls->linenumber; - primaryexp(ls, v); - for (;;) { - switch (ls->t.token) { - case '.': { /* fieldsel */ - fieldsel(ls, v); - break; - } - case '[': { /* '[' exp1 ']' */ - expdesc key; - luaK_exp2anyregup(fs, v); - yindex(ls, &key); - luaK_indexed(fs, v, &key); - break; - } - case ':': { /* ':' NAME funcargs */ - expdesc key; - luaX_next(ls); - checkname(ls, &key); - luaK_self(fs, v, &key); - funcargs(ls, v, line); - break; - } - case '(': case TK_STRING: case '{': { /* funcargs */ - luaK_exp2nextreg(fs, v); - funcargs(ls, v, line); - break; - } - default: return; - } - } +static void suffixedexp(LexState* ls, expdesc* v) +{ + /* suffixedexp -> + primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */ + FuncState* fs = ls->fs; + int line = ls->linenumber; + primaryexp(ls, v); + for (;;) + { + switch (ls->t.token) + { + case '.': + { + /* fieldsel */ + fieldsel(ls, v); + break; + } + case '[': + { + /* '[' exp1 ']' */ + expdesc key; + luaK_exp2anyregup(fs, v); + yindex(ls, &key); + luaK_indexed(fs, v, &key); + break; + } + case ':': + { + /* ':' NAME funcargs */ + expdesc key; + luaX_next(ls); + checkname(ls, &key); + luaK_self(fs, v, &key); + funcargs(ls, v, line); + break; + } + case '(': + case TK_STRING: + case '{': + { + /* funcargs */ + luaK_exp2nextreg(fs, v); + funcargs(ls, v, line); + break; + } + default: return; + } + } } -static void simpleexp (LexState *ls, expdesc *v) { - /* simpleexp -> FLT | INT | STRING | NIL | TRUE | FALSE | ... | - constructor | FUNCTION body | suffixedexp */ - switch (ls->t.token) { - case TK_FLT: { - init_exp(v, VKFLT, 0); - v->u.nval = ls->t.seminfo.r; - break; - } - case TK_INT: { - init_exp(v, VKINT, 0); - v->u.ival = ls->t.seminfo.i; - break; - } - case TK_STRING: { - codestring(ls, v, ls->t.seminfo.ts); - break; - } - case TK_NIL: { - init_exp(v, VNIL, 0); - break; - } - case TK_TRUE: { - init_exp(v, VTRUE, 0); - break; - } - case TK_FALSE: { - init_exp(v, VFALSE, 0); - break; - } - case TK_DOTS: { /* vararg */ - FuncState *fs = ls->fs; - check_condition(ls, fs->f->is_vararg, - "cannot use '...' outside a vararg function"); - init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); - break; - } - case '{': { /* constructor */ - constructor(ls, v); - return; - } - case TK_FUNCTION: { - luaX_next(ls); - body(ls, v, 0, ls->linenumber); - return; - } - default: { - suffixedexp(ls, v); - return; - } - } - luaX_next(ls); +static void simpleexp(LexState* ls, expdesc* v) +{ + /* simpleexp -> FLT | INT | STRING | NIL | TRUE | FALSE | ... | + constructor | FUNCTION body | suffixedexp */ + switch (ls->t.token) + { + case TK_FLT: + { + init_exp(v, VKFLT, 0); + v->u.nval = ls->t.seminfo.r; + break; + } + case TK_INT: + { + init_exp(v, VKINT, 0); + v->u.ival = ls->t.seminfo.i; + break; + } + case TK_STRING: + { + codestring(ls, v, ls->t.seminfo.ts); + break; + } + case TK_NIL: + { + init_exp(v, VNIL, 0); + break; + } + case TK_TRUE: + { + init_exp(v, VTRUE, 0); + break; + } + case TK_FALSE: + { + init_exp(v, VFALSE, 0); + break; + } + case TK_DOTS: + { + /* vararg */ + FuncState* fs = ls->fs; + check_condition(ls, fs->f->is_vararg, + "cannot use '...' outside a vararg function"); + init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); + break; + } + case '{': + { + /* constructor */ + constructor(ls, v); + return; + } + case TK_FUNCTION: + { + luaX_next(ls); + body(ls, v, 0, ls->linenumber); + return; + } + default: + { + suffixedexp(ls, v); + return; + } + } + luaX_next(ls); } -static UnOpr getunopr (int op) { - switch (op) { - case TK_NOT: return OPR_NOT; - case '-': return OPR_MINUS; - case '~': return OPR_BNOT; - case '#': return OPR_LEN; - default: return OPR_NOUNOPR; - } +static UnOpr getunopr(int op) +{ + switch (op) + { + case TK_NOT: return OPR_NOT; + case '-': return OPR_MINUS; + case '~': return OPR_BNOT; + case '#': return OPR_LEN; + default: return OPR_NOUNOPR; + } } -static BinOpr getbinopr (int op) { - switch (op) { - case '+': return OPR_ADD; - case '-': return OPR_SUB; - case '*': return OPR_MUL; - case '%': return OPR_MOD; - case '^': return OPR_POW; - case '/': return OPR_DIV; - case TK_IDIV: return OPR_IDIV; - case '&': return OPR_BAND; - case '|': return OPR_BOR; - case '~': return OPR_BXOR; - case TK_SHL: return OPR_SHL; - case TK_SHR: return OPR_SHR; - case TK_CONCAT: return OPR_CONCAT; - case TK_NE: return OPR_NE; - case TK_EQ: return OPR_EQ; - case '<': return OPR_LT; - case TK_LE: return OPR_LE; - case '>': return OPR_GT; - case TK_GE: return OPR_GE; - case TK_AND: return OPR_AND; - case TK_OR: return OPR_OR; - default: return OPR_NOBINOPR; - } +static BinOpr getbinopr(int op) +{ + switch (op) + { + case '+': return OPR_ADD; + case '-': return OPR_SUB; + case '*': return OPR_MUL; + case '%': return OPR_MOD; + case '^': return OPR_POW; + case '/': return OPR_DIV; + case TK_IDIV: return OPR_IDIV; + case '&': return OPR_BAND; + case '|': return OPR_BOR; + case '~': return OPR_BXOR; + case TK_SHL: return OPR_SHL; + case TK_SHR: return OPR_SHR; + case TK_CONCAT: return OPR_CONCAT; + case TK_NE: return OPR_NE; + case TK_EQ: return OPR_EQ; + case '<': return OPR_LT; + case TK_LE: return OPR_LE; + case '>': return OPR_GT; + case TK_GE: return OPR_GE; + case TK_AND: return OPR_AND; + case TK_OR: return OPR_OR; + default: return OPR_NOBINOPR; + } } -static const struct { - lu_byte left; /* left priority for each binary operator */ - lu_byte right; /* right priority */ -} priority[] = { /* ORDER OPR */ - {10, 10}, {10, 10}, /* '+' '-' */ - {11, 11}, {11, 11}, /* '*' '%' */ - {14, 13}, /* '^' (right associative) */ - {11, 11}, {11, 11}, /* '/' '//' */ - {6, 6}, {4, 4}, {5, 5}, /* '&' '|' '~' */ - {7, 7}, {7, 7}, /* '<<' '>>' */ - {9, 8}, /* '..' (right associative) */ - {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ - {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ - {2, 2}, {1, 1} /* and, or */ +static const struct +{ + lu_byte left; /* left priority for each binary operator */ + lu_byte right; /* right priority */ +} priority[] = { + /* ORDER OPR */ + {10, 10}, {10, 10}, /* '+' '-' */ + {11, 11}, {11, 11}, /* '*' '%' */ + {14, 13}, /* '^' (right associative) */ + {11, 11}, {11, 11}, /* '/' '//' */ + {6, 6}, {4, 4}, {5, 5}, /* '&' '|' '~' */ + {7, 7}, {7, 7}, /* '<<' '>>' */ + {9, 8}, /* '..' (right associative) */ + {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ + {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ + {2, 2}, {1, 1} /* and, or */ }; #define UNARY_PRIORITY 12 /* priority for unary operators */ @@ -1045,44 +1195,47 @@ static const struct { ** subexpr -> (simpleexp | unop subexpr) { binop subexpr } ** where 'binop' is any binary operator with a priority higher than 'limit' */ -static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { - BinOpr op; - UnOpr uop; - enterlevel(ls); - uop = getunopr(ls->t.token); - if (uop != OPR_NOUNOPR) { - int line = ls->linenumber; - luaX_next(ls); - subexpr(ls, v, UNARY_PRIORITY); - luaK_prefix(ls->fs, uop, v, line); - } - else simpleexp(ls, v); - /* expand while operators have priorities higher than 'limit' */ - op = getbinopr(ls->t.token); - while (op != OPR_NOBINOPR && priority[op].left > limit) { - expdesc v2; - BinOpr nextop; - int line = ls->linenumber; - luaX_next(ls); - luaK_infix(ls->fs, op, v); - /* read sub-expression with higher priority */ - nextop = subexpr(ls, &v2, priority[op].right); - luaK_posfix(ls->fs, op, v, &v2, line); - op = nextop; - } - leavelevel(ls); - return op; /* return first untreated operator */ +static BinOpr subexpr(LexState* ls, expdesc* v, int limit) +{ + BinOpr op; + UnOpr uop; + enterlevel(ls); + uop = getunopr(ls->t.token); + if (uop != OPR_NOUNOPR) + { + int line = ls->linenumber; + luaX_next(ls); + subexpr(ls, v, UNARY_PRIORITY); + luaK_prefix(ls->fs, uop, v, line); + } + else simpleexp(ls, v); + /* expand while operators have priorities higher than 'limit' */ + op = getbinopr(ls->t.token); + while (op != OPR_NOBINOPR && priority[op].left > limit) + { + expdesc v2; + BinOpr nextop; + int line = ls->linenumber; + luaX_next(ls); + luaK_infix(ls->fs, op, v); + /* read sub-expression with higher priority */ + nextop = subexpr(ls, &v2, priority[op].right); + luaK_posfix(ls->fs, op, v, &v2, line); + op = nextop; + } + leavelevel(ls); + return op; /* return first untreated operator */ } -static void expr (LexState *ls, expdesc *v) { - subexpr(ls, v, 0); +static void expr(LexState* ls, expdesc* v) +{ + subexpr(ls, v, 0); } /* }==================================================================== */ - /* ** {====================================================================== ** Rules for Statements @@ -1090,13 +1243,14 @@ static void expr (LexState *ls, expdesc *v) { */ -static void block (LexState *ls) { - /* block -> statlist */ - FuncState *fs = ls->fs; - BlockCnt bl; - enterblock(fs, &bl, 0); - statlist(ls); - leaveblock(fs); +static void block(LexState* ls) +{ + /* block -> statlist */ + FuncState* fs = ls->fs; + BlockCnt bl; + enterblock(fs, &bl, 0); + statlist(ls); + leaveblock(fs); } @@ -1104,9 +1258,10 @@ static void block (LexState *ls) { ** structure to chain all variables in the left-hand side of an ** assignment */ -struct LHS_assign { - struct LHS_assign *prev; - expdesc v; /* variable (global, local, upvalue, or indexed) */ +struct LHS_assign +{ + struct LHS_assign* prev; + expdesc v; /* variable (global, local, upvalue, or indexed) */ }; @@ -1116,490 +1271,583 @@ struct LHS_assign { ** table. If so, save original upvalue/local value in a safe place and ** use this safe copy in the previous assignment. */ -static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { - FuncState *fs = ls->fs; - int extra = fs->freereg; /* eventual position to save local variable */ - int conflict = 0; - for (; lh; lh = lh->prev) { /* check all previous assignments */ - if (lh->v.k == VINDEXED) { /* assigning to a table? */ - /* table is the upvalue/local being assigned now? */ - if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { - conflict = 1; - lh->v.u.ind.vt = VLOCAL; - lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ - } - /* index is the local being assigned? (index cannot be upvalue) */ - if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { - conflict = 1; - lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ - } - } - } - if (conflict) { - /* copy upvalue/local value to a temporary (in position 'extra') */ - OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; - luaK_codeABC(fs, op, extra, v->u.info, 0); - luaK_reserveregs(fs, 1); - } +static void check_conflict(LexState* ls, struct LHS_assign* lh, expdesc* v) +{ + FuncState* fs = ls->fs; + int extra = fs->freereg; /* eventual position to save local variable */ + int conflict = 0; + for (; lh; lh = lh->prev) + { + /* check all previous assignments */ + if (lh->v.k == VINDEXED) + { + /* assigning to a table? */ + /* table is the upvalue/local being assigned now? */ + if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) + { + conflict = 1; + lh->v.u.ind.vt = VLOCAL; + lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ + } + /* index is the local being assigned? (index cannot be upvalue) */ + if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) + { + conflict = 1; + lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ + } + } + } + if (conflict) + { + /* copy upvalue/local value to a temporary (in position 'extra') */ + OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; + luaK_codeABC(fs, op, extra, v->u.info, 0); + luaK_reserveregs(fs, 1); + } } -static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { - expdesc e; - check_condition(ls, vkisvar(lh->v.k), "syntax error"); - if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */ - struct LHS_assign nv; - nv.prev = lh; - suffixedexp(ls, &nv.v); - if (nv.v.k != VINDEXED) - check_conflict(ls, lh, &nv.v); - checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS, - "C levels"); - assignment(ls, &nv, nvars+1); - } - else { /* assignment -> '=' explist */ - int nexps; - checknext(ls, '='); - nexps = explist(ls, &e); - if (nexps != nvars) - adjust_assign(ls, nvars, nexps, &e); - else { - luaK_setoneret(ls->fs, &e); /* close last expression */ - luaK_storevar(ls->fs, &lh->v, &e); - return; /* avoid default */ - } - } - init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ - luaK_storevar(ls->fs, &lh->v, &e); +static void assignment(LexState* ls, struct LHS_assign* lh, int nvars) +{ + expdesc e; + check_condition(ls, vkisvar(lh->v.k), "syntax error"); + if (testnext(ls, ',')) + { + /* assignment -> ',' suffixedexp assignment */ + struct LHS_assign nv; + nv.prev = lh; + suffixedexp(ls, &nv.v); + if (nv.v.k != VINDEXED) + check_conflict(ls, lh, &nv.v); + checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS, + "C levels"); + assignment(ls, &nv, nvars + 1); + } + else + { + /* assignment -> '=' explist */ + int nexps; + checknext(ls, '='); + nexps = explist(ls, &e); + if (nexps != nvars) + adjust_assign(ls, nvars, nexps, &e); + else + { + luaK_setoneret(ls->fs, &e); /* close last expression */ + luaK_storevar(ls->fs, &lh->v, &e); + return; /* avoid default */ + } + } + init_exp(&e, VNONRELOC, ls->fs->freereg - 1); /* default assignment */ + luaK_storevar(ls->fs, &lh->v, &e); } -static int cond (LexState *ls) { - /* cond -> exp */ - expdesc v; - expr(ls, &v); /* read condition */ - if (v.k == VNIL) v.k = VFALSE; /* 'falses' are all equal here */ - luaK_goiftrue(ls->fs, &v); - return v.f; +static int cond(LexState* ls) +{ + /* cond -> exp */ + expdesc v; + expr(ls, &v); /* read condition */ + if (v.k == VNIL) v.k = VFALSE; /* 'falses' are all equal here */ + luaK_goiftrue(ls->fs, &v); + return v.f; } -static void gotostat (LexState *ls, int pc) { - int line = ls->linenumber; - TString *label; - int g; - if (testnext(ls, TK_GOTO)) - label = str_checkname(ls); - else { - luaX_next(ls); /* skip break */ - label = luaS_new(ls->L, "break"); - } - g = newlabelentry(ls, &ls->dyd->gt, label, line, pc); - findlabel(ls, g); /* close it if label already defined */ +static void gotostat(LexState* ls, int pc) +{ + int line = ls->linenumber; + TString* label; + int g; + if (testnext(ls, TK_GOTO)) + label = str_checkname(ls); + else + { + luaX_next(ls); /* skip break */ + label = luaS_new(ls->L, "break"); + } + g = newlabelentry(ls, &ls->dyd->gt, label, line, pc); + findlabel(ls, g); /* close it if label already defined */ } /* check for repeated labels on the same block */ -static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { - int i; - for (i = fs->bl->firstlabel; i < ll->n; i++) { - if (eqstr(label, ll->arr[i].name)) { - const char *msg = luaO_pushfstring(fs->ls->L, - "label '%s' already defined on line %d", - getstr(label), ll->arr[i].line); - semerror(fs->ls, msg); - } - } +static void checkrepeated(FuncState* fs, Labellist* ll, TString* label) +{ + int i; + for (i = fs->bl->firstlabel; i < ll->n; i++) + { + if (eqstr(label, ll->arr[i].name)) + { + const char* msg = luaO_pushfstring(fs->ls->L, + "label '%s' already defined on line %d", + getstr(label), ll->arr[i].line); + semerror(fs->ls, msg); + } + } } /* skip no-op statements */ -static void skipnoopstat (LexState *ls) { - while (ls->t.token == ';' || ls->t.token == TK_DBCOLON) - statement(ls); +static void skipnoopstat(LexState* ls) +{ + while (ls->t.token == ';' || ls->t.token == TK_DBCOLON) + statement(ls); } -static void labelstat (LexState *ls, TString *label, int line) { - /* label -> '::' NAME '::' */ - FuncState *fs = ls->fs; - Labellist *ll = &ls->dyd->label; - int l; /* index of new label being created */ - checkrepeated(fs, ll, label); /* check for repeated labels */ - checknext(ls, TK_DBCOLON); /* skip double colon */ - /* create new entry for this label */ - l = newlabelentry(ls, ll, label, line, luaK_getlabel(fs)); - skipnoopstat(ls); /* skip other no-op statements */ - if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */ - /* assume that locals are already out of scope */ - ll->arr[l].nactvar = fs->bl->nactvar; - } - findgotos(ls, &ll->arr[l]); +static void labelstat(LexState* ls, TString* label, int line) +{ + /* label -> '::' NAME '::' */ + FuncState* fs = ls->fs; + Labellist* ll = &ls->dyd->label; + int l; /* index of new label being created */ + checkrepeated(fs, ll, label); /* check for repeated labels */ + checknext(ls, TK_DBCOLON); /* skip double colon */ + /* create new entry for this label */ + l = newlabelentry(ls, ll, label, line, luaK_getlabel(fs)); + skipnoopstat(ls); /* skip other no-op statements */ + if (block_follow(ls, 0)) + { + /* label is last no-op statement in the block? */ + /* assume that locals are already out of scope */ + ll->arr[l].nactvar = fs->bl->nactvar; + } + findgotos(ls, &ll->arr[l]); } -static void whilestat (LexState *ls, int line) { - /* whilestat -> WHILE cond DO block END */ - FuncState *fs = ls->fs; - int whileinit; - int condexit; - BlockCnt bl; - luaX_next(ls); /* skip WHILE */ - whileinit = luaK_getlabel(fs); - condexit = cond(ls); - enterblock(fs, &bl, 1); - checknext(ls, TK_DO); - block(ls); - luaK_jumpto(fs, whileinit); - check_match(ls, TK_END, TK_WHILE, line); - leaveblock(fs); - luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ +static void whilestat(LexState* ls, int line) +{ + /* whilestat -> WHILE cond DO block END */ + FuncState* fs = ls->fs; + int whileinit; + int condexit; + BlockCnt bl; + luaX_next(ls); /* skip WHILE */ + whileinit = luaK_getlabel(fs); + condexit = cond(ls); + enterblock(fs, &bl, 1); + checknext(ls, TK_DO); + block(ls); + luaK_jumpto(fs, whileinit); + check_match(ls, TK_END, TK_WHILE, line); + leaveblock(fs); + luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ } -static void repeatstat (LexState *ls, int line) { - /* repeatstat -> REPEAT block UNTIL cond */ - int condexit; - FuncState *fs = ls->fs; - int repeat_init = luaK_getlabel(fs); - BlockCnt bl1, bl2; - enterblock(fs, &bl1, 1); /* loop block */ - enterblock(fs, &bl2, 0); /* scope block */ - luaX_next(ls); /* skip REPEAT */ - statlist(ls); - check_match(ls, TK_UNTIL, TK_REPEAT, line); - condexit = cond(ls); /* read condition (inside scope block) */ - if (bl2.upval) /* upvalues? */ - luaK_patchclose(fs, condexit, bl2.nactvar); - leaveblock(fs); /* finish scope */ - luaK_patchlist(fs, condexit, repeat_init); /* close the loop */ - leaveblock(fs); /* finish loop */ +static void repeatstat(LexState* ls, int line) +{ + /* repeatstat -> REPEAT block UNTIL cond */ + int condexit; + FuncState* fs = ls->fs; + int repeat_init = luaK_getlabel(fs); + BlockCnt bl1, bl2; + enterblock(fs, &bl1, 1); /* loop block */ + enterblock(fs, &bl2, 0); /* scope block */ + luaX_next(ls); /* skip REPEAT */ + statlist(ls); + check_match(ls, TK_UNTIL, TK_REPEAT, line); + condexit = cond(ls); /* read condition (inside scope block) */ + if (bl2.upval) /* upvalues? */ + luaK_patchclose(fs, condexit, bl2.nactvar); + leaveblock(fs); /* finish scope */ + luaK_patchlist(fs, condexit, repeat_init); /* close the loop */ + leaveblock(fs); /* finish loop */ } -static int exp1 (LexState *ls) { - expdesc e; - int reg; - expr(ls, &e); - luaK_exp2nextreg(ls->fs, &e); - lua_assert(e.k == VNONRELOC); - reg = e.u.info; - return reg; +static int exp1(LexState* ls) +{ + expdesc e; + int reg; + expr(ls, &e); + luaK_exp2nextreg(ls->fs, &e); + lua_assert(e.k == VNONRELOC); + reg = e.u.info; + return reg; } -static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { - /* forbody -> DO block */ - BlockCnt bl; - FuncState *fs = ls->fs; - int prep, endfor; - adjustlocalvars(ls, 3); /* control variables */ - checknext(ls, TK_DO); - prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); - enterblock(fs, &bl, 0); /* scope for declared variables */ - adjustlocalvars(ls, nvars); - luaK_reserveregs(fs, nvars); - block(ls); - leaveblock(fs); /* end of scope for declared variables */ - luaK_patchtohere(fs, prep); - if (isnum) /* numeric for? */ - endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP); - else { /* generic for */ - luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); - luaK_fixline(fs, line); - endfor = luaK_codeAsBx(fs, OP_TFORLOOP, base + 2, NO_JUMP); - } - luaK_patchlist(fs, endfor, prep + 1); - luaK_fixline(fs, line); +static void forbody(LexState* ls, int base, int line, int nvars, int isnum) +{ + /* forbody -> DO block */ + BlockCnt bl; + FuncState* fs = ls->fs; + int prep, endfor; + adjustlocalvars(ls, 3); /* control variables */ + checknext(ls, TK_DO); + prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); + enterblock(fs, &bl, 0); /* scope for declared variables */ + adjustlocalvars(ls, nvars); + luaK_reserveregs(fs, nvars); + block(ls); + leaveblock(fs); /* end of scope for declared variables */ + luaK_patchtohere(fs, prep); + if (isnum) /* numeric for? */ + endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP); + else + { + /* generic for */ + luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); + luaK_fixline(fs, line); + endfor = luaK_codeAsBx(fs, OP_TFORLOOP, base + 2, NO_JUMP); + } + luaK_patchlist(fs, endfor, prep + 1); + luaK_fixline(fs, line); } -static void fornum (LexState *ls, TString *varname, int line) { - /* fornum -> NAME = exp1,exp1[,exp1] forbody */ - FuncState *fs = ls->fs; - int base = fs->freereg; - new_localvarliteral(ls, "(for index)"); - new_localvarliteral(ls, "(for limit)"); - new_localvarliteral(ls, "(for step)"); - new_localvar(ls, varname); - checknext(ls, '='); - exp1(ls); /* initial value */ - checknext(ls, ','); - exp1(ls); /* limit */ - if (testnext(ls, ',')) - exp1(ls); /* optional step */ - else { /* default step = 1 */ - luaK_codek(fs, fs->freereg, luaK_intK(fs, 1)); - luaK_reserveregs(fs, 1); - } - forbody(ls, base, line, 1, 1); +static void fornum(LexState* ls, TString* varname, int line) +{ + /* fornum -> NAME = exp1,exp1[,exp1] forbody */ + FuncState* fs = ls->fs; + int base = fs->freereg; + new_localvarliteral(ls, "(for index)"); + new_localvarliteral(ls, "(for limit)"); + new_localvarliteral(ls, "(for step)"); + new_localvar(ls, varname); + checknext(ls, '='); + exp1(ls); /* initial value */ + checknext(ls, ','); + exp1(ls); /* limit */ + if (testnext(ls, ',')) + exp1(ls); /* optional step */ + else + { + /* default step = 1 */ + luaK_codek(fs, fs->freereg, luaK_intK(fs, 1)); + luaK_reserveregs(fs, 1); + } + forbody(ls, base, line, 1, 1); } -static void forlist (LexState *ls, TString *indexname) { - /* forlist -> NAME {,NAME} IN explist forbody */ - FuncState *fs = ls->fs; - expdesc e; - int nvars = 4; /* gen, state, control, plus at least one declared var */ - int line; - int base = fs->freereg; - /* create control variables */ - new_localvarliteral(ls, "(for generator)"); - new_localvarliteral(ls, "(for state)"); - new_localvarliteral(ls, "(for control)"); - /* create declared variables */ - new_localvar(ls, indexname); - while (testnext(ls, ',')) { - new_localvar(ls, str_checkname(ls)); - nvars++; - } - checknext(ls, TK_IN); - line = ls->linenumber; - adjust_assign(ls, 3, explist(ls, &e), &e); - luaK_checkstack(fs, 3); /* extra space to call generator */ - forbody(ls, base, line, nvars - 3, 0); +static void forlist(LexState* ls, TString* indexname) +{ + /* forlist -> NAME {,NAME} IN explist forbody */ + FuncState* fs = ls->fs; + expdesc e; + int nvars = 4; /* gen, state, control, plus at least one declared var */ + int line; + int base = fs->freereg; + /* create control variables */ + new_localvarliteral(ls, "(for generator)"); + new_localvarliteral(ls, "(for state)"); + new_localvarliteral(ls, "(for control)"); + /* create declared variables */ + new_localvar(ls, indexname); + while (testnext(ls, ',')) + { + new_localvar(ls, str_checkname(ls)); + nvars++; + } + checknext(ls, TK_IN); + line = ls->linenumber; + adjust_assign(ls, 3, explist(ls, &e), &e); + luaK_checkstack(fs, 3); /* extra space to call generator */ + forbody(ls, base, line, nvars - 3, 0); } -static void forstat (LexState *ls, int line) { - /* forstat -> FOR (fornum | forlist) END */ - FuncState *fs = ls->fs; - TString *varname; - BlockCnt bl; - enterblock(fs, &bl, 1); /* scope for loop and control variables */ - luaX_next(ls); /* skip 'for' */ - varname = str_checkname(ls); /* first variable name */ - switch (ls->t.token) { - case '=': fornum(ls, varname, line); break; - case ',': case TK_IN: forlist(ls, varname); break; - default: luaX_syntaxerror(ls, "'=' or 'in' expected"); - } - check_match(ls, TK_END, TK_FOR, line); - leaveblock(fs); /* loop scope ('break' jumps to this point) */ +static void forstat(LexState* ls, int line) +{ + /* forstat -> FOR (fornum | forlist) END */ + FuncState* fs = ls->fs; + TString* varname; + BlockCnt bl; + enterblock(fs, &bl, 1); /* scope for loop and control variables */ + luaX_next(ls); /* skip 'for' */ + varname = str_checkname(ls); /* first variable name */ + switch (ls->t.token) + { + case '=': fornum(ls, varname, line); + break; + case ',': + case TK_IN: forlist(ls, varname); + break; + default: luaX_syntaxerror(ls, "'=' or 'in' expected"); + } + check_match(ls, TK_END, TK_FOR, line); + leaveblock(fs); /* loop scope ('break' jumps to this point) */ } -static void test_then_block (LexState *ls, int *escapelist) { - /* test_then_block -> [IF | ELSEIF] cond THEN block */ - BlockCnt bl; - FuncState *fs = ls->fs; - expdesc v; - int jf; /* instruction to skip 'then' code (if condition is false) */ - luaX_next(ls); /* skip IF or ELSEIF */ - expr(ls, &v); /* read condition */ - checknext(ls, TK_THEN); - if (ls->t.token == TK_GOTO || ls->t.token == TK_BREAK) { - luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ - enterblock(fs, &bl, 0); /* must enter block before 'goto' */ - gotostat(ls, v.t); /* handle goto/break */ - skipnoopstat(ls); /* skip other no-op statements */ - if (block_follow(ls, 0)) { /* 'goto' is the entire block? */ - leaveblock(fs); - return; /* and that is it */ - } - else /* must skip over 'then' part if condition is false */ - jf = luaK_jump(fs); - } - else { /* regular case (not goto/break) */ - luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ - enterblock(fs, &bl, 0); - jf = v.f; - } - statlist(ls); /* 'then' part */ - leaveblock(fs); - if (ls->t.token == TK_ELSE || - ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */ - luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */ - luaK_patchtohere(fs, jf); +static void test_then_block(LexState* ls, int* escapelist) +{ + /* test_then_block -> [IF | ELSEIF] cond THEN block */ + BlockCnt bl; + FuncState* fs = ls->fs; + expdesc v; + int jf; /* instruction to skip 'then' code (if condition is false) */ + luaX_next(ls); /* skip IF or ELSEIF */ + expr(ls, &v); /* read condition */ + checknext(ls, TK_THEN); + if (ls->t.token == TK_GOTO || ls->t.token == TK_BREAK) + { + luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ + enterblock(fs, &bl, 0); /* must enter block before 'goto' */ + gotostat(ls, v.t); /* handle goto/break */ + skipnoopstat(ls); /* skip other no-op statements */ + if (block_follow(ls, 0)) + { + /* 'goto' is the entire block? */ + leaveblock(fs); + return; /* and that is it */ + } + else /* must skip over 'then' part if condition is false */ + jf = luaK_jump(fs); + } + else + { + /* regular case (not goto/break) */ + luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ + enterblock(fs, &bl, 0); + jf = v.f; + } + statlist(ls); /* 'then' part */ + leaveblock(fs); + if (ls->t.token == TK_ELSE || + ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */ + luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */ + luaK_patchtohere(fs, jf); } -static void ifstat (LexState *ls, int line) { - /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ - FuncState *fs = ls->fs; - int escapelist = NO_JUMP; /* exit list for finished parts */ - test_then_block(ls, &escapelist); /* IF cond THEN block */ - while (ls->t.token == TK_ELSEIF) - test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */ - if (testnext(ls, TK_ELSE)) - block(ls); /* 'else' part */ - check_match(ls, TK_END, TK_IF, line); - luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */ +static void ifstat(LexState* ls, int line) +{ + /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ + FuncState* fs = ls->fs; + int escapelist = NO_JUMP; /* exit list for finished parts */ + test_then_block(ls, &escapelist); /* IF cond THEN block */ + while (ls->t.token == TK_ELSEIF) + test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */ + if (testnext(ls, TK_ELSE)) + block(ls); /* 'else' part */ + check_match(ls, TK_END, TK_IF, line); + luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */ } -static void localfunc (LexState *ls) { - expdesc b; - FuncState *fs = ls->fs; - new_localvar(ls, str_checkname(ls)); /* new local variable */ - adjustlocalvars(ls, 1); /* enter its scope */ - body(ls, &b, 0, ls->linenumber); /* function created in next register */ - /* debug information will only see the variable after this point! */ - getlocvar(fs, b.u.info)->startpc = fs->pc; +static void localfunc(LexState* ls) +{ + expdesc b; + FuncState* fs = ls->fs; + new_localvar(ls, str_checkname(ls)); /* new local variable */ + adjustlocalvars(ls, 1); /* enter its scope */ + body(ls, &b, 0, ls->linenumber); /* function created in next register */ + /* debug information will only see the variable after this point! */ + getlocvar(fs, b.u.info)->startpc = fs->pc; } -static void localstat (LexState *ls) { - /* stat -> LOCAL NAME {',' NAME} ['=' explist] */ - int nvars = 0; - int nexps; - expdesc e; - do { - new_localvar(ls, str_checkname(ls)); - nvars++; - } while (testnext(ls, ',')); - if (testnext(ls, '=')) - nexps = explist(ls, &e); - else { - e.k = VVOID; - nexps = 0; - } - adjust_assign(ls, nvars, nexps, &e); - adjustlocalvars(ls, nvars); +static void localstat(LexState* ls) +{ + /* stat -> LOCAL NAME {',' NAME} ['=' explist] */ + int nvars = 0; + int nexps; + expdesc e; + do + { + new_localvar(ls, str_checkname(ls)); + nvars++; + } + while (testnext(ls, ',')); + if (testnext(ls, '=')) + nexps = explist(ls, &e); + else + { + e.k = VVOID; + nexps = 0; + } + adjust_assign(ls, nvars, nexps, &e); + adjustlocalvars(ls, nvars); } -static int funcname (LexState *ls, expdesc *v) { - /* funcname -> NAME {fieldsel} [':' NAME] */ - int ismethod = 0; - singlevar(ls, v); - while (ls->t.token == '.') - fieldsel(ls, v); - if (ls->t.token == ':') { - ismethod = 1; - fieldsel(ls, v); - } - return ismethod; +static int funcname(LexState* ls, expdesc* v) +{ + /* funcname -> NAME {fieldsel} [':' NAME] */ + int ismethod = 0; + singlevar(ls, v); + while (ls->t.token == '.') + fieldsel(ls, v); + if (ls->t.token == ':') + { + ismethod = 1; + fieldsel(ls, v); + } + return ismethod; } -static void funcstat (LexState *ls, int line) { - /* funcstat -> FUNCTION funcname body */ - int ismethod; - expdesc v, b; - luaX_next(ls); /* skip FUNCTION */ - ismethod = funcname(ls, &v); - body(ls, &b, ismethod, line); - luaK_storevar(ls->fs, &v, &b); - luaK_fixline(ls->fs, line); /* definition "happens" in the first line */ +static void funcstat(LexState* ls, int line) +{ + /* funcstat -> FUNCTION funcname body */ + int ismethod; + expdesc v, b; + luaX_next(ls); /* skip FUNCTION */ + ismethod = funcname(ls, &v); + body(ls, &b, ismethod, line); + luaK_storevar(ls->fs, &v, &b); + luaK_fixline(ls->fs, line); /* definition "happens" in the first line */ } -static void exprstat (LexState *ls) { - /* stat -> func | assignment */ - FuncState *fs = ls->fs; - struct LHS_assign v; - suffixedexp(ls, &v.v); - if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */ - v.prev = NULL; - assignment(ls, &v, 1); - } - else { /* stat -> func */ - check_condition(ls, v.v.k == VCALL, "syntax error"); - SETARG_C(getinstruction(fs, &v.v), 1); /* call statement uses no results */ - } +static void exprstat(LexState* ls) +{ + /* stat -> func | assignment */ + FuncState* fs = ls->fs; + struct LHS_assign v; + suffixedexp(ls, &v.v); + if (ls->t.token == '=' || ls->t.token == ',') + { + /* stat -> assignment ? */ + v.prev = NULL; + assignment(ls, &v, 1); + } + else + { + /* stat -> func */ + check_condition(ls, v.v.k == VCALL, "syntax error"); + SETARG_C(getinstruction(fs, &v.v), 1); /* call statement uses no results */ + } } -static void retstat (LexState *ls) { - /* stat -> RETURN [explist] [';'] */ - FuncState *fs = ls->fs; - expdesc e; - int first, nret; /* registers with returned values */ - if (block_follow(ls, 1) || ls->t.token == ';') - first = nret = 0; /* return no values */ - else { - nret = explist(ls, &e); /* optional return values */ - if (hasmultret(e.k)) { - luaK_setmultret(fs, &e); - if (e.k == VCALL && nret == 1) { /* tail call? */ - SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL); - lua_assert(GETARG_A(getinstruction(fs,&e)) == fs->nactvar); - } - first = fs->nactvar; - nret = LUA_MULTRET; /* return all values */ - } - else { - if (nret == 1) /* only one single value? */ - first = luaK_exp2anyreg(fs, &e); - else { - luaK_exp2nextreg(fs, &e); /* values must go to the stack */ - first = fs->nactvar; /* return all active values */ - lua_assert(nret == fs->freereg - first); - } - } - } - luaK_ret(fs, first, nret); - testnext(ls, ';'); /* skip optional semicolon */ +static void retstat(LexState* ls) +{ + /* stat -> RETURN [explist] [';'] */ + FuncState* fs = ls->fs; + expdesc e; + int first, nret; /* registers with returned values */ + if (block_follow(ls, 1) || ls->t.token == ';') + first = nret = 0; /* return no values */ + else + { + nret = explist(ls, &e); /* optional return values */ + if (hasmultret(e.k)) + { + luaK_setmultret(fs, &e); + if (e.k == VCALL && nret == 1) + { + /* tail call? */ + SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL); + lua_assert(GETARG_A(getinstruction(fs,&e)) == fs->nactvar); + } + first = fs->nactvar; + nret = LUA_MULTRET; /* return all values */ + } + else + { + if (nret == 1) /* only one single value? */ + first = luaK_exp2anyreg(fs, &e); + else + { + luaK_exp2nextreg(fs, &e); /* values must go to the stack */ + first = fs->nactvar; /* return all active values */ + lua_assert(nret == fs->freereg - first); + } + } + } + luaK_ret(fs, first, nret); + testnext(ls, ';'); /* skip optional semicolon */ } -static void statement (LexState *ls) { - int line = ls->linenumber; /* may be needed for error messages */ - enterlevel(ls); - switch (ls->t.token) { - case ';': { /* stat -> ';' (empty statement) */ - luaX_next(ls); /* skip ';' */ - break; - } - case TK_IF: { /* stat -> ifstat */ - ifstat(ls, line); - break; - } - case TK_WHILE: { /* stat -> whilestat */ - whilestat(ls, line); - break; - } - case TK_DO: { /* stat -> DO block END */ - luaX_next(ls); /* skip DO */ - block(ls); - check_match(ls, TK_END, TK_DO, line); - break; - } - case TK_FOR: { /* stat -> forstat */ - forstat(ls, line); - break; - } - case TK_REPEAT: { /* stat -> repeatstat */ - repeatstat(ls, line); - break; - } - case TK_FUNCTION: { /* stat -> funcstat */ - funcstat(ls, line); - break; - } - case TK_LOCAL: { /* stat -> localstat */ - luaX_next(ls); /* skip LOCAL */ - if (testnext(ls, TK_FUNCTION)) /* local function? */ - localfunc(ls); - else - localstat(ls); - break; - } - case TK_DBCOLON: { /* stat -> label */ - luaX_next(ls); /* skip double colon */ - labelstat(ls, str_checkname(ls), line); - break; - } - case TK_RETURN: { /* stat -> retstat */ - luaX_next(ls); /* skip RETURN */ - retstat(ls); - break; - } - case TK_BREAK: /* stat -> breakstat */ - case TK_GOTO: { /* stat -> 'goto' NAME */ - gotostat(ls, luaK_jump(ls->fs)); - break; - } - default: { /* stat -> func | assignment */ - exprstat(ls); - break; - } - } - lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && - ls->fs->freereg >= ls->fs->nactvar); - ls->fs->freereg = ls->fs->nactvar; /* free registers */ - leavelevel(ls); +static void statement(LexState* ls) +{ + int line = ls->linenumber; /* may be needed for error messages */ + enterlevel(ls); + switch (ls->t.token) + { + case ';': + { + /* stat -> ';' (empty statement) */ + luaX_next(ls); /* skip ';' */ + break; + } + case TK_IF: + { + /* stat -> ifstat */ + ifstat(ls, line); + break; + } + case TK_WHILE: + { + /* stat -> whilestat */ + whilestat(ls, line); + break; + } + case TK_DO: + { + /* stat -> DO block END */ + luaX_next(ls); /* skip DO */ + block(ls); + check_match(ls, TK_END, TK_DO, line); + break; + } + case TK_FOR: + { + /* stat -> forstat */ + forstat(ls, line); + break; + } + case TK_REPEAT: + { + /* stat -> repeatstat */ + repeatstat(ls, line); + break; + } + case TK_FUNCTION: + { + /* stat -> funcstat */ + funcstat(ls, line); + break; + } + case TK_LOCAL: + { + /* stat -> localstat */ + luaX_next(ls); /* skip LOCAL */ + if (testnext(ls, TK_FUNCTION)) /* local function? */ + localfunc(ls); + else + localstat(ls); + break; + } + case TK_DBCOLON: + { + /* stat -> label */ + luaX_next(ls); /* skip double colon */ + labelstat(ls, str_checkname(ls), line); + break; + } + case TK_RETURN: + { + /* stat -> retstat */ + luaX_next(ls); /* skip RETURN */ + retstat(ls); + break; + } + case TK_BREAK: /* stat -> breakstat */ + case TK_GOTO: + { + /* stat -> 'goto' NAME */ + gotostat(ls, luaK_jump(ls->fs)); + break; + } + default: + { + /* stat -> func | assignment */ + exprstat(ls); + break; + } + } + lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && + ls->fs->freereg >= ls->fs->nactvar); + ls->fs->freereg = ls->fs->nactvar; /* free registers */ + leavelevel(ls); } /* }====================================================================== */ @@ -1609,42 +1857,43 @@ static void statement (LexState *ls) { ** compiles the main function, which is a regular vararg function with an ** upvalue named LUA_ENV */ -static void mainfunc (LexState *ls, FuncState *fs) { - BlockCnt bl; - expdesc v; - open_func(ls, fs, &bl); - fs->f->is_vararg = 1; /* main function is always declared vararg */ - init_exp(&v, VLOCAL, 0); /* create and... */ - newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ - luaX_next(ls); /* read first token */ - statlist(ls); /* parse main body */ - check(ls, TK_EOS); - close_func(ls); +static void mainfunc(LexState* ls, FuncState* fs) +{ + BlockCnt bl; + expdesc v; + open_func(ls, fs, &bl); + fs->f->is_vararg = 1; /* main function is always declared vararg */ + init_exp(&v, VLOCAL, 0); /* create and... */ + newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ + luaX_next(ls); /* read first token */ + statlist(ls); /* parse main body */ + check(ls, TK_EOS); + close_func(ls); } -LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, - Dyndata *dyd, const char *name, int firstchar) { - LexState lexstate; - FuncState funcstate; - LClosure *cl = luaF_newLclosure(L, 1); /* create main closure */ - setclLvalue(L, L->top, cl); /* anchor it (to avoid being collected) */ - luaD_inctop(L); - lexstate.h = luaH_new(L); /* create table for scanner */ - sethvalue(L, L->top, lexstate.h); /* anchor it */ - luaD_inctop(L); - funcstate.f = cl->p = luaF_newproto(L); - funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ - lua_assert(iswhite(funcstate.f)); /* do not need barrier here */ - lexstate.buff = buff; - lexstate.dyd = dyd; - dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; - luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar); - mainfunc(&lexstate, &funcstate); - lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); - /* all scopes should be correctly finished */ - lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); - L->top--; /* remove scanner's table */ - return cl; /* closure is on the stack, too */ +LClosure* luaY_parser(lua_State* L, ZIO* z, Mbuffer* buff, + Dyndata* dyd, const char* name, int firstchar) +{ + LexState lexstate; + FuncState funcstate; + LClosure* cl = luaF_newLclosure(L, 1); /* create main closure */ + setclLvalue(L, L->top, cl); /* anchor it (to avoid being collected) */ + luaD_inctop(L); + lexstate.h = luaH_new(L); /* create table for scanner */ + sethvalue(L, L->top, lexstate.h); /* anchor it */ + luaD_inctop(L); + funcstate.f = cl->p = luaF_newproto(L); + funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ + lua_assert(iswhite(funcstate.f)); /* do not need barrier here */ + lexstate.buff = buff; + lexstate.dyd = dyd; + dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; + luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar); + mainfunc(&lexstate, &funcstate); + lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); + /* all scopes should be correctly finished */ + lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); + L->top--; /* remove scanner's table */ + return cl; /* closure is on the stack, too */ } - diff --git a/Lua/lparser.h b/Lua/lparser.h index 02e9b03..d2a3b1a 100644 --- a/Lua/lparser.h +++ b/Lua/lparser.h @@ -22,112 +22,141 @@ */ /* kinds of variables/expressions */ -typedef enum { - VVOID, /* when 'expdesc' describes the last expression a list, - this kind means an empty list (so, no expression) */ - VNIL, /* constant nil */ - VTRUE, /* constant true */ - VFALSE, /* constant false */ - VK, /* constant in 'k'; info = index of constant in 'k' */ - VKFLT, /* floating constant; nval = numerical float value */ - VKINT, /* integer constant; nval = numerical integer value */ - VNONRELOC, /* expression has its value in a fixed register; - info = result register */ - VLOCAL, /* local variable; info = local register */ - VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */ - VINDEXED, /* indexed variable; - ind.vt = whether 't' is register or upvalue; - ind.t = table register or upvalue; - ind.idx = key's R/K index */ - VJMP, /* expression is a test/comparison; - info = pc of corresponding jump instruction */ - VRELOCABLE, /* expression can put result in any register; - info = instruction pc */ - VCALL, /* expression is a function call; info = instruction pc */ - VVARARG /* vararg expression; info = instruction pc */ +typedef enum +{ + VVOID, + /* when 'expdesc' describes the last expression a list, + this kind means an empty list (so, no expression) */ + VNIL, + /* constant nil */ + VTRUE, + /* constant true */ + VFALSE, + /* constant false */ + VK, + /* constant in 'k'; info = index of constant in 'k' */ + VKFLT, + /* floating constant; nval = numerical float value */ + VKINT, + /* integer constant; nval = numerical integer value */ + VNONRELOC, + /* expression has its value in a fixed register; + info = result register */ + VLOCAL, + /* local variable; info = local register */ + VUPVAL, + /* upvalue variable; info = index of upvalue in 'upvalues' */ + VINDEXED, + /* indexed variable; + ind.vt = whether 't' is register or upvalue; + ind.t = table register or upvalue; + ind.idx = key's R/K index */ + VJMP, + /* expression is a test/comparison; + info = pc of corresponding jump instruction */ + VRELOCABLE, + /* expression can put result in any register; + info = instruction pc */ + VCALL, + /* expression is a function call; info = instruction pc */ + VVARARG /* vararg expression; info = instruction pc */ } expkind; #define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) #define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) -typedef struct expdesc { - expkind k; - union { - lua_Integer ival; /* for VKINT */ - lua_Number nval; /* for VKFLT */ - int info; /* for generic use */ - struct { /* for indexed variables (VINDEXED) */ - short idx; /* index (R/K) */ - lu_byte t; /* table (register or upvalue) */ - lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ - } ind; - } u; - int t; /* patch list of 'exit when true' */ - int f; /* patch list of 'exit when false' */ +typedef struct expdesc +{ + expkind k; + + union + { + lua_Integer ival; /* for VKINT */ + lua_Number nval; /* for VKFLT */ + int info; /* for generic use */ + struct + { + /* for indexed variables (VINDEXED) */ + short idx; /* index (R/K) */ + lu_byte t; /* table (register or upvalue) */ + lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ + } ind; + } u; + + int t; /* patch list of 'exit when true' */ + int f; /* patch list of 'exit when false' */ } expdesc; /* description of active local variable */ -typedef struct Vardesc { - short idx; /* variable index in stack */ +typedef struct Vardesc +{ + short idx; /* variable index in stack */ } Vardesc; /* description of pending goto statements and label statements */ -typedef struct Labeldesc { - TString *name; /* label identifier */ - int pc; /* position in code */ - int line; /* line where it appeared */ - lu_byte nactvar; /* local level where it appears in current block */ +typedef struct Labeldesc +{ + TString* name; /* label identifier */ + int pc; /* position in code */ + int line; /* line where it appeared */ + lu_byte nactvar; /* local level where it appears in current block */ } Labeldesc; /* list of labels or gotos */ -typedef struct Labellist { - Labeldesc *arr; /* array */ - int n; /* number of entries in use */ - int size; /* array size */ +typedef struct Labellist +{ + Labeldesc* arr; /* array */ + int n; /* number of entries in use */ + int size; /* array size */ } Labellist; /* dynamic structures used by the parser */ -typedef struct Dyndata { - struct { /* list of active local variables */ - Vardesc *arr; - int n; - int size; - } actvar; - Labellist gt; /* list of pending gotos */ - Labellist label; /* list of active labels */ +typedef struct Dyndata +{ + struct + { + /* list of active local variables */ + Vardesc* arr; + int n; + int size; + } actvar; + + Labellist gt; /* list of pending gotos */ + Labellist label; /* list of active labels */ } Dyndata; /* control of blocks */ -struct BlockCnt; /* defined in lparser.c */ +struct BlockCnt; /* defined in lparser.c */ /* state needed to generate code for a given function */ -typedef struct FuncState { - Proto *f; /* current function header */ - struct FuncState *prev; /* enclosing function */ - struct LexState *ls; /* lexical state */ - struct BlockCnt *bl; /* chain of current blocks */ - int pc; /* next position to code (equivalent to 'ncode') */ - int lasttarget; /* 'label' of last 'jump label' */ - int jpc; /* list of pending jumps to 'pc' */ - int nk; /* number of elements in 'k' */ - int np; /* number of elements in 'p' */ - int firstlocal; /* index of first local var (in Dyndata array) */ - short nlocvars; /* number of elements in 'f->locvars' */ - lu_byte nactvar; /* number of active local variables */ - lu_byte nups; /* number of upvalues */ - lu_byte freereg; /* first free register */ +typedef struct FuncState +{ + Proto* f; /* current function header */ + struct FuncState* prev; /* enclosing function */ + struct LexState* ls; /* lexical state */ + struct BlockCnt* bl; /* chain of current blocks */ + int pc; /* next position to code (equivalent to 'ncode') */ + int lasttarget; /* 'label' of last 'jump label' */ + int jpc; /* list of pending jumps to 'pc' */ + int nk; /* number of elements in 'k' */ + int np; /* number of elements in 'p' */ + int firstlocal; /* index of first local var (in Dyndata array) */ + short nlocvars; /* number of elements in 'f->locvars' */ + lu_byte nactvar; /* number of active local variables */ + lu_byte nups; /* number of upvalues */ + lu_byte freereg; /* first free register */ } FuncState; -LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, - Dyndata *dyd, const char *name, int firstchar); +LUAI_FUNC LClosure* luaY_parser(lua_State* L, ZIO* z, Mbuffer* buff, + Dyndata* dyd, const char* name, int firstchar); #endif diff --git a/Lua/lprefix.h b/Lua/lprefix.h index 02daa83..053f05f 100644 --- a/Lua/lprefix.h +++ b/Lua/lprefix.h @@ -42,4 +42,3 @@ #endif /* } */ #endif - diff --git a/Lua/lstate.c b/Lua/lstate.c index 9194ac3..e592976 100644 --- a/Lua/lstate.c +++ b/Lua/lstate.c @@ -47,26 +47,26 @@ #endif - /* ** thread state + extra space */ -typedef struct LX { - lu_byte extra_[LUA_EXTRASPACE]; - lua_State l; +typedef struct LX +{ + lu_byte extra_[LUA_EXTRASPACE]; + lua_State l; } LX; /* ** Main thread combines a thread state and the global state */ -typedef struct LG { - LX l; - global_State g; +typedef struct LG +{ + LX l; + global_State g; } LG; - #define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) @@ -78,16 +78,17 @@ typedef struct LG { { size_t t = cast(size_t, e); \ memcpy(b + p, &t, sizeof(t)); p += sizeof(t); } -static unsigned int makeseed (lua_State *L) { - char buff[4 * sizeof(size_t)]; - unsigned int h = luai_makeseed(); - int p = 0; - addbuff(buff, p, L); /* heap variable */ - addbuff(buff, p, &h); /* local variable */ - addbuff(buff, p, luaO_nilobject); /* global variable */ - addbuff(buff, p, &lua_newstate); /* public function */ - lua_assert(p == sizeof(buff)); - return luaS_hash(buff, p, h); +static unsigned int makeseed(lua_State* L) +{ + char buff[4 * sizeof(size_t)]; + unsigned int h = luai_makeseed(); + int p = 0; + addbuff(buff, p, L); /* heap variable */ + addbuff(buff, p, &h); /* local variable */ + addbuff(buff, p, luaO_nilobject); /* global variable */ + addbuff(buff, p, &lua_newstate); /* public function */ + lua_assert(p == sizeof(buff)); + return luaS_hash(buff, p, h); } @@ -95,104 +96,114 @@ static unsigned int makeseed (lua_State *L) { ** set GCdebt to a new value keeping the value (totalbytes + GCdebt) ** invariant (and avoiding underflows in 'totalbytes') */ -void luaE_setdebt (global_State *g, l_mem debt) { - l_mem tb = gettotalbytes(g); - lua_assert(tb > 0); - if (debt < tb - MAX_LMEM) - debt = tb - MAX_LMEM; /* will make 'totalbytes == MAX_LMEM' */ - g->totalbytes = tb - debt; - g->GCdebt = debt; +void luaE_setdebt(global_State* g, l_mem debt) +{ + l_mem tb = gettotalbytes(g); + lua_assert(tb > 0); + if (debt < tb - MAX_LMEM) + debt = tb - MAX_LMEM; /* will make 'totalbytes == MAX_LMEM' */ + g->totalbytes = tb - debt; + g->GCdebt = debt; } -CallInfo *luaE_extendCI (lua_State *L) { - CallInfo *ci = luaM_new(L, CallInfo); - lua_assert(L->ci->next == NULL); - L->ci->next = ci; - ci->previous = L->ci; - ci->next = NULL; - L->nci++; - return ci; +CallInfo* luaE_extendCI(lua_State* L) +{ + CallInfo* ci = luaM_new(L, CallInfo); + lua_assert(L->ci->next == NULL); + L->ci->next = ci; + ci->previous = L->ci; + ci->next = NULL; + L->nci++; + return ci; } /* ** free all CallInfo structures not in use by a thread */ -void luaE_freeCI (lua_State *L) { - CallInfo *ci = L->ci; - CallInfo *next = ci->next; - ci->next = NULL; - while ((ci = next) != NULL) { - next = ci->next; - luaM_free(L, ci); - L->nci--; - } +void luaE_freeCI(lua_State* L) +{ + CallInfo* ci = L->ci; + CallInfo* next = ci->next; + ci->next = NULL; + while ((ci = next) != NULL) + { + next = ci->next; + luaM_free(L, ci); + L->nci--; + } } /* ** free half of the CallInfo structures not in use by a thread */ -void luaE_shrinkCI (lua_State *L) { - CallInfo *ci = L->ci; - CallInfo *next2; /* next's next */ - /* while there are two nexts */ - while (ci->next != NULL && (next2 = ci->next->next) != NULL) { - luaM_free(L, ci->next); /* free next */ - L->nci--; - ci->next = next2; /* remove 'next' from the list */ - next2->previous = ci; - ci = next2; /* keep next's next */ - } +void luaE_shrinkCI(lua_State* L) +{ + CallInfo* ci = L->ci; + CallInfo* next2; /* next's next */ + /* while there are two nexts */ + while (ci->next != NULL && (next2 = ci->next->next) != NULL) + { + luaM_free(L, ci->next); /* free next */ + L->nci--; + ci->next = next2; /* remove 'next' from the list */ + next2->previous = ci; + ci = next2; /* keep next's next */ + } } -static void stack_init (lua_State *L1, lua_State *L) { - int i; CallInfo *ci; - /* initialize stack array */ - L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, TValue); - L1->stacksize = BASIC_STACK_SIZE; - for (i = 0; i < BASIC_STACK_SIZE; i++) - setnilvalue(L1->stack + i); /* erase new stack */ - L1->top = L1->stack; - L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK; - /* initialize first ci */ - ci = &L1->base_ci; - ci->next = ci->previous = NULL; - ci->callstatus = 0; - ci->func = L1->top; - setnilvalue(L1->top++); /* 'function' entry for this 'ci' */ - ci->top = L1->top + LUA_MINSTACK; - L1->ci = ci; +static void stack_init(lua_State* L1, lua_State* L) +{ + int i; + CallInfo* ci; + /* initialize stack array */ + L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, TValue); + L1->stacksize = BASIC_STACK_SIZE; + for (i = 0; i < BASIC_STACK_SIZE; i++) + setnilvalue(L1->stack + i); /* erase new stack */ + L1->top = L1->stack; + L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK; + /* initialize first ci */ + ci = &L1->base_ci; + ci->next = ci->previous = NULL; + ci->callstatus = 0; + ci->func = L1->top; + setnilvalue(L1->top++); /* 'function' entry for this 'ci' */ + ci->top = L1->top + LUA_MINSTACK; + L1->ci = ci; } -static void freestack (lua_State *L) { - if (L->stack == NULL) - return; /* stack not completely built yet */ - L->ci = &L->base_ci; /* free the entire 'ci' list */ - luaE_freeCI(L); - lua_assert(L->nci == 0); - luaM_freearray(L, L->stack, L->stacksize); /* free stack array */ +static void freestack(lua_State* L) +{ + if (L->stack == NULL) + return; /* stack not completely built yet */ + L->ci = &L->base_ci; /* free the entire 'ci' list */ + luaE_freeCI(L); + lua_assert(L->nci == 0); + luaM_freearray(L, L->stack, L->stacksize); /* free stack array */ } /* ** Create registry table and its predefined values */ -static void init_registry (lua_State *L, global_State *g) { - TValue temp; - /* create registry */ - Table *registry = luaH_new(L); - sethvalue(L, &g->l_registry, registry); - luaH_resize(L, registry, LUA_RIDX_LAST, 0); - /* registry[LUA_RIDX_MAINTHREAD] = L */ - setthvalue(L, &temp, L); /* temp = L */ - luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp); - /* registry[LUA_RIDX_GLOBALS] = table of globals */ - sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */ - luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp); +static void init_registry(lua_State* L, global_State* g) +{ + TValue temp; + /* create registry */ + Table* registry = luaH_new(L); + sethvalue(L, &g->l_registry, registry); + luaH_resize(L, registry, LUA_RIDX_LAST, 0); + /* registry[LUA_RIDX_MAINTHREAD] = L */ + setthvalue(L, &temp, L); /* temp = L */ + luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp); + /* registry[LUA_RIDX_GLOBALS] = table of globals */ + sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */ + luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp); } @@ -200,17 +211,18 @@ static void init_registry (lua_State *L, global_State *g) { ** open parts of the state that may cause memory-allocation errors. ** ('g->version' != NULL flags that the state was completely build) */ -static void f_luaopen (lua_State *L, void *ud) { - global_State *g = G(L); - UNUSED(ud); - stack_init(L, L); /* init stack */ - init_registry(L, g); - luaS_init(L); - luaT_init(L); - luaX_init(L); - g->gcrunning = 1; /* allow gc */ - g->version = lua_version(NULL); - luai_userstateopen(L); +static void f_luaopen(lua_State* L, void* ud) +{ + global_State* g = G(L); + UNUSED(ud); + stack_init(L, L); /* init stack */ + init_registry(L, g); + luaS_init(L); + luaT_init(L); + luaX_init(L); + g->gcrunning = 1; /* allow gc */ + g->version = lua_version(NULL); + luai_userstateopen(L); } @@ -218,130 +230,135 @@ static void f_luaopen (lua_State *L, void *ud) { ** preinitialize a thread with consistent values without allocating ** any memory (to avoid errors) */ -static void preinit_thread (lua_State *L, global_State *g) { - G(L) = g; - L->stack = NULL; - L->ci = NULL; - L->nci = 0; - L->stacksize = 0; - L->twups = L; /* thread has no upvalues */ - L->errorJmp = NULL; - L->nCcalls = 0; - L->hook = NULL; - L->hookmask = 0; - L->basehookcount = 0; - L->allowhook = 1; - resethookcount(L); - L->openupval = NULL; - L->nny = 1; - L->status = LUA_OK; - L->errfunc = 0; +static void preinit_thread(lua_State* L, global_State* g) +{ + G(L) = g; + L->stack = NULL; + L->ci = NULL; + L->nci = 0; + L->stacksize = 0; + L->twups = L; /* thread has no upvalues */ + L->errorJmp = NULL; + L->nCcalls = 0; + L->hook = NULL; + L->hookmask = 0; + L->basehookcount = 0; + L->allowhook = 1; + resethookcount(L); + L->openupval = NULL; + L->nny = 1; + L->status = LUA_OK; + L->errfunc = 0; } -static void close_state (lua_State *L) { - global_State *g = G(L); - luaF_close(L, L->stack); /* close all upvalues for this thread */ - luaC_freeallobjects(L); /* collect all objects */ - if (g->version) /* closing a fully built state? */ - luai_userstateclose(L); - luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); - freestack(L); - lua_assert(gettotalbytes(g) == sizeof(LG)); - (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ +static void close_state(lua_State* L) +{ + global_State* g = G(L); + luaF_close(L, L->stack); /* close all upvalues for this thread */ + luaC_freeallobjects(L); /* collect all objects */ + if (g->version) /* closing a fully built state? */ + luai_userstateclose(L); + luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); + freestack(L); + lua_assert(gettotalbytes(g) == sizeof(LG)); + (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ } -LUA_API lua_State *lua_newthread (lua_State *L) { - global_State *g = G(L); - lua_State *L1; - lua_lock(L); - luaC_checkGC(L); - /* create new thread */ - L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; - L1->marked = luaC_white(g); - L1->tt = LUA_TTHREAD; - /* link it on list 'allgc' */ - L1->next = g->allgc; - g->allgc = obj2gco(L1); - /* anchor it on L stack */ - setthvalue(L, L->top, L1); - api_incr_top(L); - preinit_thread(L1, g); - L1->hookmask = L->hookmask; - L1->basehookcount = L->basehookcount; - L1->hook = L->hook; - resethookcount(L1); - /* initialize L1 extra space */ - memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread), - LUA_EXTRASPACE); - luai_userstatethread(L, L1); - stack_init(L1, L); /* init stack */ - lua_unlock(L); - return L1; +LUA_API lua_State* lua_newthread(lua_State* L) +{ + global_State* g = G(L); + lua_State* L1; + lua_lock(L); + luaC_checkGC(L); + /* create new thread */ + L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; + L1->marked = luaC_white(g); + L1->tt = LUA_TTHREAD; + /* link it on list 'allgc' */ + L1->next = g->allgc; + g->allgc = obj2gco(L1); + /* anchor it on L stack */ + setthvalue(L, L->top, L1); + api_incr_top(L); + preinit_thread(L1, g); + L1->hookmask = L->hookmask; + L1->basehookcount = L->basehookcount; + L1->hook = L->hook; + resethookcount(L1); + /* initialize L1 extra space */ + memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread), + LUA_EXTRASPACE); + luai_userstatethread(L, L1); + stack_init(L1, L); /* init stack */ + lua_unlock(L); + return L1; } -void luaE_freethread (lua_State *L, lua_State *L1) { - LX *l = fromstate(L1); - luaF_close(L1, L1->stack); /* close all upvalues for this thread */ - lua_assert(L1->openupval == NULL); - luai_userstatefree(L, L1); - freestack(L1); - luaM_free(L, l); +void luaE_freethread(lua_State* L, lua_State* L1) +{ + LX* l = fromstate(L1); + luaF_close(L1, L1->stack); /* close all upvalues for this thread */ + lua_assert(L1->openupval == NULL); + luai_userstatefree(L, L1); + freestack(L1); + luaM_free(L, l); } -LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { - int i; - lua_State *L; - global_State *g; - LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG))); - if (l == NULL) return NULL; - L = &l->l.l; - g = &l->g; - L->next = NULL; - L->tt = LUA_TTHREAD; - g->currentwhite = bitmask(WHITE0BIT); - L->marked = luaC_white(g); - preinit_thread(L, g); - g->frealloc = f; - g->ud = ud; - g->mainthread = L; - g->seed = makeseed(L); - g->gcrunning = 0; /* no GC while building state */ - g->GCestimate = 0; - g->strt.size = g->strt.nuse = 0; - g->strt.hash = NULL; - setnilvalue(&g->l_registry); - g->panic = NULL; - g->version = NULL; - g->gcstate = GCSpause; - g->gckind = KGC_NORMAL; - g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL; - g->sweepgc = NULL; - g->gray = g->grayagain = NULL; - g->weak = g->ephemeron = g->allweak = NULL; - g->twups = NULL; - g->totalbytes = sizeof(LG); - g->GCdebt = 0; - g->gcfinnum = 0; - g->gcpause = LUAI_GCPAUSE; - g->gcstepmul = LUAI_GCMUL; - for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; - if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { - /* memory allocation error: free partial state */ - close_state(L); - L = NULL; - } - return L; +LUA_API lua_State* lua_newstate(lua_Alloc f, void* ud) +{ + int i; + lua_State* L; + global_State* g; + LG* l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG))); + if (l == NULL) return NULL; + L = &l->l.l; + g = &l->g; + L->next = NULL; + L->tt = LUA_TTHREAD; + g->currentwhite = bitmask(WHITE0BIT); + L->marked = luaC_white(g); + preinit_thread(L, g); + g->frealloc = f; + g->ud = ud; + g->mainthread = L; + g->seed = makeseed(L); + g->gcrunning = 0; /* no GC while building state */ + g->GCestimate = 0; + g->strt.size = g->strt.nuse = 0; + g->strt.hash = NULL; + setnilvalue(&g->l_registry); + g->panic = NULL; + g->version = NULL; + g->gcstate = GCSpause; + g->gckind = KGC_NORMAL; + g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL; + g->sweepgc = NULL; + g->gray = g->grayagain = NULL; + g->weak = g->ephemeron = g->allweak = NULL; + g->twups = NULL; + g->totalbytes = sizeof(LG); + g->GCdebt = 0; + g->gcfinnum = 0; + g->gcpause = LUAI_GCPAUSE; + g->gcstepmul = LUAI_GCMUL; + for (i = 0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; + if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) + { + /* memory allocation error: free partial state */ + close_state(L); + L = NULL; + } + return L; } -LUA_API void lua_close (lua_State *L) { - L = G(L)->mainthread; /* only the main thread can be closed */ - lua_lock(L); - close_state(L); +LUA_API void lua_close(lua_State* L) +{ + L = G(L)->mainthread; /* only the main thread can be closed */ + lua_lock(L); + close_state(L); } - - diff --git a/Lua/lstate.h b/Lua/lstate.h index a469466..7d86509 100644 --- a/Lua/lstate.h +++ b/Lua/lstate.h @@ -30,7 +30,7 @@ */ -struct lua_longjmp; /* defined in ldo.c */ +struct lua_longjmp; /* defined in ldo.c */ /* @@ -55,10 +55,11 @@ struct lua_longjmp; /* defined in ldo.c */ #define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */ -typedef struct stringtable { - TString **hash; - int nuse; /* number of elements */ - int size; +typedef struct stringtable +{ + TString** hash; + int nuse; /* number of elements */ + int size; } stringtable; @@ -71,24 +72,32 @@ typedef struct stringtable { ** the function index so that, in case of errors, the continuation ** function can be called with the correct top. */ -typedef struct CallInfo { - StkId func; /* function index in the stack */ - StkId top; /* top for this function */ - struct CallInfo *previous, *next; /* dynamic call link */ - union { - struct { /* only for Lua functions */ - StkId base; /* base for this function */ - const Instruction *savedpc; - } l; - struct { /* only for C functions */ - lua_KFunction k; /* continuation in case of yields */ - ptrdiff_t old_errfunc; - lua_KContext ctx; /* context info. in case of yields */ - } c; - } u; - ptrdiff_t extra; - short nresults; /* expected number of results from this function */ - unsigned short callstatus; +typedef struct CallInfo +{ + StkId func; /* function index in the stack */ + StkId top; /* top for this function */ + struct CallInfo *previous, *next; /* dynamic call link */ + union + { + struct + { + /* only for Lua functions */ + StkId base; /* base for this function */ + const Instruction* savedpc; + } l; + + struct + { + /* only for C functions */ + lua_KFunction k; /* continuation in case of yields */ + ptrdiff_t old_errfunc; + lua_KContext ctx; /* context info. in case of yields */ + } c; + } u; + + ptrdiff_t extra; + short nresults; /* expected number of results from this function */ + unsigned short callstatus; } CallInfo; @@ -116,71 +125,73 @@ typedef struct CallInfo { /* ** 'global state', shared by all threads of this state */ -typedef struct global_State { - lua_Alloc frealloc; /* function to reallocate memory */ - void *ud; /* auxiliary data to 'frealloc' */ - l_mem totalbytes; /* number of bytes currently allocated - GCdebt */ - l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ - lu_mem GCmemtrav; /* memory traversed by the GC */ - lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ - stringtable strt; /* hash table for strings */ - TValue l_registry; - unsigned int seed; /* randomized seed for hashes */ - lu_byte currentwhite; - lu_byte gcstate; /* state of garbage collector */ - lu_byte gckind; /* kind of GC running */ - lu_byte gcrunning; /* true if GC is running */ - GCObject *allgc; /* list of all collectable objects */ - GCObject **sweepgc; /* current position of sweep in list */ - GCObject *finobj; /* list of collectable objects with finalizers */ - GCObject *gray; /* list of gray objects */ - GCObject *grayagain; /* list of objects to be traversed atomically */ - GCObject *weak; /* list of tables with weak values */ - GCObject *ephemeron; /* list of ephemeron tables (weak keys) */ - GCObject *allweak; /* list of all-weak tables */ - GCObject *tobefnz; /* list of userdata to be GC */ - GCObject *fixedgc; /* list of objects not to be collected */ - struct lua_State *twups; /* list of threads with open upvalues */ - unsigned int gcfinnum; /* number of finalizers to call in each GC step */ - int gcpause; /* size of pause between successive GCs */ - int gcstepmul; /* GC 'granularity' */ - lua_CFunction panic; /* to be called in unprotected errors */ - struct lua_State *mainthread; - const lua_Number *version; /* pointer to version number */ - TString *memerrmsg; /* memory-error message */ - TString *tmname[TM_N]; /* array with tag-method names */ - struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ - TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */ +typedef struct global_State +{ + lua_Alloc frealloc; /* function to reallocate memory */ + void* ud; /* auxiliary data to 'frealloc' */ + l_mem totalbytes; /* number of bytes currently allocated - GCdebt */ + l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ + lu_mem GCmemtrav; /* memory traversed by the GC */ + lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ + stringtable strt; /* hash table for strings */ + TValue l_registry; + unsigned int seed; /* randomized seed for hashes */ + lu_byte currentwhite; + lu_byte gcstate; /* state of garbage collector */ + lu_byte gckind; /* kind of GC running */ + lu_byte gcrunning; /* true if GC is running */ + GCObject* allgc; /* list of all collectable objects */ + GCObject** sweepgc; /* current position of sweep in list */ + GCObject* finobj; /* list of collectable objects with finalizers */ + GCObject* gray; /* list of gray objects */ + GCObject* grayagain; /* list of objects to be traversed atomically */ + GCObject* weak; /* list of tables with weak values */ + GCObject* ephemeron; /* list of ephemeron tables (weak keys) */ + GCObject* allweak; /* list of all-weak tables */ + GCObject* tobefnz; /* list of userdata to be GC */ + GCObject* fixedgc; /* list of objects not to be collected */ + struct lua_State* twups; /* list of threads with open upvalues */ + unsigned int gcfinnum; /* number of finalizers to call in each GC step */ + int gcpause; /* size of pause between successive GCs */ + int gcstepmul; /* GC 'granularity' */ + lua_CFunction panic; /* to be called in unprotected errors */ + struct lua_State* mainthread; + const lua_Number* version; /* pointer to version number */ + TString* memerrmsg; /* memory-error message */ + TString* tmname[TM_N]; /* array with tag-method names */ + struct Table* mt[LUA_NUMTAGS]; /* metatables for basic types */ + TString* strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */ } global_State; /* ** 'per thread' state */ -struct lua_State { - CommonHeader; - unsigned short nci; /* number of items in 'ci' list */ - lu_byte status; - StkId top; /* first free slot in the stack */ - global_State *l_G; - CallInfo *ci; /* call info for current function */ - const Instruction *oldpc; /* last pc traced */ - StkId stack_last; /* last free slot in the stack */ - StkId stack; /* stack base */ - UpVal *openupval; /* list of open upvalues in this stack */ - GCObject *gclist; - struct lua_State *twups; /* list of threads with open upvalues */ - struct lua_longjmp *errorJmp; /* current error recover point */ - CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ - volatile lua_Hook hook; - ptrdiff_t errfunc; /* current error handling function (stack index) */ - int stacksize; - int basehookcount; - int hookcount; - unsigned short nny; /* number of non-yieldable calls in stack */ - unsigned short nCcalls; /* number of nested C calls */ - l_signalT hookmask; - lu_byte allowhook; +struct lua_State +{ + CommonHeader; + unsigned short nci; /* number of items in 'ci' list */ + lu_byte status; + StkId top; /* first free slot in the stack */ + global_State* l_G; + CallInfo* ci; /* call info for current function */ + const Instruction* oldpc; /* last pc traced */ + StkId stack_last; /* last free slot in the stack */ + StkId stack; /* stack base */ + UpVal* openupval; /* list of open upvalues in this stack */ + GCObject* gclist; + struct lua_State* twups; /* list of threads with open upvalues */ + struct lua_longjmp* errorJmp; /* current error recover point */ + CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ + volatile lua_Hook hook; + ptrdiff_t errfunc; /* current error handling function (stack index) */ + int stacksize; + int basehookcount; + int hookcount; + unsigned short nny; /* number of non-yieldable calls in stack */ + unsigned short nCcalls; /* number of nested C calls */ + l_signalT hookmask; + lu_byte allowhook; }; @@ -190,14 +201,15 @@ struct lua_State { /* ** Union of all collectable objects (only for conversions) */ -union GCUnion { - GCObject gc; /* common header */ - struct TString ts; - struct Udata u; - union Closure cl; - struct Table h; - struct Proto p; - struct lua_State th; /* thread */ +union GCUnion +{ + GCObject gc; /* common header */ + struct TString ts; + struct Udata u; + union Closure cl; + struct Table h; + struct Proto p; + struct lua_State th; /* thread */ }; @@ -224,12 +236,11 @@ union GCUnion { /* actual number of total bytes allocated */ #define gettotalbytes(g) cast(lu_mem, (g)->totalbytes + (g)->GCdebt) -LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); -LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); -LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); -LUAI_FUNC void luaE_freeCI (lua_State *L); -LUAI_FUNC void luaE_shrinkCI (lua_State *L); +LUAI_FUNC void luaE_setdebt(global_State* g, l_mem debt); +LUAI_FUNC void luaE_freethread(lua_State* L, lua_State* L1); +LUAI_FUNC CallInfo* luaE_extendCI(lua_State* L); +LUAI_FUNC void luaE_freeCI(lua_State* L); +LUAI_FUNC void luaE_shrinkCI(lua_State* L); #endif - diff --git a/Lua/lstring.c b/Lua/lstring.c index 9351766..c29c49f 100644 --- a/Lua/lstring.c +++ b/Lua/lstring.c @@ -37,62 +37,76 @@ /* ** equality for long strings */ -int luaS_eqlngstr (TString *a, TString *b) { - size_t len = a->u.lnglen; - lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR); - return (a == b) || /* same instance or... */ - ((len == b->u.lnglen) && /* equal length and ... */ - (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ +int luaS_eqlngstr(TString* a, TString* b) +{ + size_t len = a->u.lnglen; + lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR); + return (a == b) || /* same instance or... */ + ((len == b->u.lnglen) && /* equal length and ... */ + (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ } -unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { - unsigned int h = seed ^ cast(unsigned int, l); - size_t step = (l >> LUAI_HASHLIMIT) + 1; - for (; l >= step; l -= step) - h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1])); - return h; +unsigned int luaS_hash(const char* str, size_t l, unsigned int seed) +{ + unsigned int h = seed ^ cast(unsigned int, l); + size_t step = (l >> LUAI_HASHLIMIT) + 1; + for (; l >= step; l -= step) + h ^= ((h << 5) + (h >> 2) + cast_byte(str[l - 1])); + return h; } -unsigned int luaS_hashlongstr (TString *ts) { - lua_assert(ts->tt == LUA_TLNGSTR); - if (ts->extra == 0) { /* no hash? */ - ts->hash = luaS_hash(getstr(ts), ts->u.lnglen, ts->hash); - ts->extra = 1; /* now it has its hash */ - } - return ts->hash; +unsigned int luaS_hashlongstr(TString* ts) +{ + lua_assert(ts->tt == LUA_TLNGSTR); + if (ts->extra == 0) + { + /* no hash? */ + ts->hash = luaS_hash(getstr(ts), ts->u.lnglen, ts->hash); + ts->extra = 1; /* now it has its hash */ + } + return ts->hash; } /* ** resizes the string table */ -void luaS_resize (lua_State *L, int newsize) { - int i; - stringtable *tb = &G(L)->strt; - if (newsize > tb->size) { /* grow table if needed */ - luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); - for (i = tb->size; i < newsize; i++) - tb->hash[i] = NULL; - } - for (i = 0; i < tb->size; i++) { /* rehash */ - TString *p = tb->hash[i]; - tb->hash[i] = NULL; - while (p) { /* for each node in the list */ - TString *hnext = p->u.hnext; /* save next */ - unsigned int h = lmod(p->hash, newsize); /* new position */ - p->u.hnext = tb->hash[h]; /* chain it */ - tb->hash[h] = p; - p = hnext; - } - } - if (newsize < tb->size) { /* shrink table if needed */ - /* vanishing slice should be empty */ - lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL); - luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); - } - tb->size = newsize; +void luaS_resize(lua_State* L, int newsize) +{ + int i; + stringtable* tb = &G(L)->strt; + if (newsize > tb->size) + { + /* grow table if needed */ + luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); + for (i = tb->size; i < newsize; i++) + tb->hash[i] = NULL; + } + for (i = 0; i < tb->size; i++) + { + /* rehash */ + TString* p = tb->hash[i]; + tb->hash[i] = NULL; + while (p) + { + /* for each node in the list */ + TString* hnext = p->u.hnext; /* save next */ + unsigned int h = lmod(p->hash, newsize); /* new position */ + p->u.hnext = tb->hash[h]; /* chain it */ + tb->hash[h] = p; + p = hnext; + } + } + if (newsize < tb->size) + { + /* shrink table if needed */ + /* vanishing slice should be empty */ + lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL); + luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); + } + tb->size = newsize; } @@ -100,113 +114,124 @@ void luaS_resize (lua_State *L, int newsize) { ** Clear API string cache. (Entries cannot be empty, so fill them with ** a non-collectable string.) */ -void luaS_clearcache (global_State *g) { - int i, j; - for (i = 0; i < STRCACHE_N; i++) - for (j = 0; j < STRCACHE_M; j++) { - if (iswhite(g->strcache[i][j])) /* will entry be collected? */ - g->strcache[i][j] = g->memerrmsg; /* replace it with something fixed */ - } +void luaS_clearcache(global_State* g) +{ + int i, j; + for (i = 0; i < STRCACHE_N; i++) + for (j = 0; j < STRCACHE_M; j++) + { + if (iswhite(g->strcache[i][j])) /* will entry be collected? */ + g->strcache[i][j] = g->memerrmsg; /* replace it with something fixed */ + } } /* ** Initialize the string table and the string cache */ -void luaS_init (lua_State *L) { - global_State *g = G(L); - int i, j; - luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ - /* pre-create memory-error message */ - g->memerrmsg = luaS_newliteral(L, MEMERRMSG); - luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */ - for (i = 0; i < STRCACHE_N; i++) /* fill cache with valid strings */ - for (j = 0; j < STRCACHE_M; j++) - g->strcache[i][j] = g->memerrmsg; +void luaS_init(lua_State* L) +{ + global_State* g = G(L); + int i, j; + luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ + /* pre-create memory-error message */ + g->memerrmsg = luaS_newliteral(L, MEMERRMSG); + luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */ + for (i = 0; i < STRCACHE_N; i++) /* fill cache with valid strings */ + for (j = 0; j < STRCACHE_M; j++) + g->strcache[i][j] = g->memerrmsg; } - /* ** creates a new string object */ -static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) { - TString *ts; - GCObject *o; - size_t totalsize; /* total size of TString object */ - totalsize = sizelstring(l); - o = luaC_newobj(L, tag, totalsize); - ts = gco2ts(o); - ts->hash = h; - ts->extra = 0; - getstr(ts)[l] = '\0'; /* ending 0 */ - return ts; +static TString* createstrobj(lua_State* L, size_t l, int tag, unsigned int h) +{ + TString* ts; + GCObject* o; + size_t totalsize; /* total size of TString object */ + totalsize = sizelstring(l); + o = luaC_newobj(L, tag, totalsize); + ts = gco2ts(o); + ts->hash = h; + ts->extra = 0; + getstr(ts)[l] = '\0'; /* ending 0 */ + return ts; } -TString *luaS_createlngstrobj (lua_State *L, size_t l) { - TString *ts = createstrobj(L, l, LUA_TLNGSTR, G(L)->seed); - ts->u.lnglen = l; - return ts; +TString* luaS_createlngstrobj(lua_State* L, size_t l) +{ + TString* ts = createstrobj(L, l, LUA_TLNGSTR, G(L)->seed); + ts->u.lnglen = l; + return ts; } -void luaS_remove (lua_State *L, TString *ts) { - stringtable *tb = &G(L)->strt; - TString **p = &tb->hash[lmod(ts->hash, tb->size)]; - while (*p != ts) /* find previous element */ - p = &(*p)->u.hnext; - *p = (*p)->u.hnext; /* remove element from its list */ - tb->nuse--; +void luaS_remove(lua_State* L, TString* ts) +{ + stringtable* tb = &G(L)->strt; + TString** p = &tb->hash[lmod(ts->hash, tb->size)]; + while (*p != ts) /* find previous element */ + p = &(*p)->u.hnext; + *p = (*p)->u.hnext; /* remove element from its list */ + tb->nuse--; } /* ** checks whether short string exists and reuses it or creates a new one */ -static TString *internshrstr (lua_State *L, const char *str, size_t l) { - TString *ts; - global_State *g = G(L); - unsigned int h = luaS_hash(str, l, g->seed); - TString **list = &g->strt.hash[lmod(h, g->strt.size)]; - lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */ - for (ts = *list; ts != NULL; ts = ts->u.hnext) { - if (l == ts->shrlen && - (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { - /* found! */ - if (isdead(g, ts)) /* dead (but not collected yet)? */ - changewhite(ts); /* resurrect it */ - return ts; - } - } - if (g->strt.nuse >= g->strt.size && g->strt.size <= MAX_INT/2) { - luaS_resize(L, g->strt.size * 2); - list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */ - } - ts = createstrobj(L, l, LUA_TSHRSTR, h); - memcpy(getstr(ts), str, l * sizeof(char)); - ts->shrlen = cast_byte(l); - ts->u.hnext = *list; - *list = ts; - g->strt.nuse++; - return ts; +static TString* internshrstr(lua_State* L, const char* str, size_t l) +{ + TString* ts; + global_State* g = G(L); + unsigned int h = luaS_hash(str, l, g->seed); + TString** list = &g->strt.hash[lmod(h, g->strt.size)]; + lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */ + for (ts = *list; ts != NULL; ts = ts->u.hnext) + { + if (l == ts->shrlen && + (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) + { + /* found! */ + if (isdead(g, ts)) /* dead (but not collected yet)? */ + changewhite(ts); /* resurrect it */ + return ts; + } + } + if (g->strt.nuse >= g->strt.size && g->strt.size <= MAX_INT / 2) + { + luaS_resize(L, g->strt.size * 2); + list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */ + } + ts = createstrobj(L, l, LUA_TSHRSTR, h); + memcpy(getstr(ts), str, l * sizeof(char)); + ts->shrlen = cast_byte(l); + ts->u.hnext = *list; + *list = ts; + g->strt.nuse++; + return ts; } /* ** new string (with explicit length) */ -TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { - if (l <= LUAI_MAXSHORTLEN) /* short string? */ - return internshrstr(L, str, l); - else { - TString *ts; - if (l >= (MAX_SIZE - sizeof(TString))/sizeof(char)) - luaM_toobig(L); - ts = luaS_createlngstrobj(L, l); - memcpy(getstr(ts), str, l * sizeof(char)); - return ts; - } +TString* luaS_newlstr(lua_State* L, const char* str, size_t l) +{ + if (l <= LUAI_MAXSHORTLEN) /* short string? */ + return internshrstr(L, str, l); + else + { + TString* ts; + if (l >= (MAX_SIZE - sizeof(TString)) / sizeof(char)) + luaM_toobig(L); + ts = luaS_createlngstrobj(L, l); + memcpy(getstr(ts), str, l * sizeof(char)); + return ts; + } } @@ -216,33 +241,35 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { ** only zero-terminated strings, so it is safe to use 'strcmp' to ** check hits. */ -TString *luaS_new (lua_State *L, const char *str) { - unsigned int i = point2uint(str) % STRCACHE_N; /* hash */ - int j; - TString **p = G(L)->strcache[i]; - for (j = 0; j < STRCACHE_M; j++) { - if (strcmp(str, getstr(p[j])) == 0) /* hit? */ - return p[j]; /* that is it */ - } - /* normal route */ - for (j = STRCACHE_M - 1; j > 0; j--) - p[j] = p[j - 1]; /* move out last element */ - /* new element is first in the list */ - p[0] = luaS_newlstr(L, str, strlen(str)); - return p[0]; +TString* luaS_new(lua_State* L, const char* str) +{ + unsigned int i = point2uint(str) % STRCACHE_N; /* hash */ + int j; + TString** p = G(L)->strcache[i]; + for (j = 0; j < STRCACHE_M; j++) + { + if (strcmp(str, getstr(p[j])) == 0) /* hit? */ + return p[j]; /* that is it */ + } + /* normal route */ + for (j = STRCACHE_M - 1; j > 0; j--) + p[j] = p[j - 1]; /* move out last element */ + /* new element is first in the list */ + p[0] = luaS_newlstr(L, str, strlen(str)); + return p[0]; } -Udata *luaS_newudata (lua_State *L, size_t s) { - Udata *u; - GCObject *o; - if (s > MAX_SIZE - sizeof(Udata)) - luaM_toobig(L); - o = luaC_newobj(L, LUA_TUSERDATA, sizeludata(s)); - u = gco2u(o); - u->len = s; - u->metatable = NULL; - setuservalue(L, u, luaO_nilobject); - return u; +Udata* luaS_newudata(lua_State* L, size_t s) +{ + Udata* u; + GCObject* o; + if (s > MAX_SIZE - sizeof(Udata)) + luaM_toobig(L); + o = luaC_newobj(L, LUA_TUSERDATA, sizeludata(s)); + u = gco2u(o); + u->len = s; + u->metatable = NULL; + setuservalue(L, u, luaO_nilobject); + return u; } - diff --git a/Lua/lstring.h b/Lua/lstring.h index 27efd20..a40204e 100644 --- a/Lua/lstring.h +++ b/Lua/lstring.h @@ -33,17 +33,17 @@ #define eqshrstr(a,b) check_exp((a)->tt == LUA_TSHRSTR, (a) == (b)) -LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); -LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts); -LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); -LUAI_FUNC void luaS_resize (lua_State *L, int newsize); -LUAI_FUNC void luaS_clearcache (global_State *g); -LUAI_FUNC void luaS_init (lua_State *L); -LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); -LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s); -LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); -LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); -LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l); +LUAI_FUNC unsigned int luaS_hash(const char* str, size_t l, unsigned int seed); +LUAI_FUNC unsigned int luaS_hashlongstr(TString* ts); +LUAI_FUNC int luaS_eqlngstr(TString* a, TString* b); +LUAI_FUNC void luaS_resize(lua_State* L, int newsize); +LUAI_FUNC void luaS_clearcache(global_State* g); +LUAI_FUNC void luaS_init(lua_State* L); +LUAI_FUNC void luaS_remove(lua_State* L, TString* ts); +LUAI_FUNC Udata* luaS_newudata(lua_State* L, size_t s); +LUAI_FUNC TString* luaS_newlstr(lua_State* L, const char* str, size_t l); +LUAI_FUNC TString* luaS_new(lua_State* L, const char* str); +LUAI_FUNC TString* luaS_createlngstrobj(lua_State* L, size_t l); #endif diff --git a/Lua/lstrlib.c b/Lua/lstrlib.c index c7aa755..a0c25fa 100644 --- a/Lua/lstrlib.c +++ b/Lua/lstrlib.c @@ -49,157 +49,174 @@ (sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX)) - - -static int str_len (lua_State *L) { - size_t l; - luaL_checklstring(L, 1, &l); - lua_pushinteger(L, (lua_Integer)l); - return 1; +static int str_len(lua_State* L) +{ + size_t l; + luaL_checklstring(L, 1, &l); + lua_pushinteger(L, (lua_Integer)l); + return 1; } /* translate a relative string position: negative means back from end */ -static lua_Integer posrelat (lua_Integer pos, size_t len) { - if (pos >= 0) return pos; - else if (0u - (size_t)pos > len) return 0; - else return (lua_Integer)len + pos + 1; +static lua_Integer posrelat(lua_Integer pos, size_t len) +{ + if (pos >= 0) return pos; + else if (0u - (size_t)pos > len) return 0; + else return (lua_Integer)len + pos + 1; } -static int str_sub (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - lua_Integer start = posrelat(luaL_checkinteger(L, 2), l); - lua_Integer end = posrelat(luaL_optinteger(L, 3, -1), l); - if (start < 1) start = 1; - if (end > (lua_Integer)l) end = l; - if (start <= end) - lua_pushlstring(L, s + start - 1, (size_t)(end - start) + 1); - else lua_pushliteral(L, ""); - return 1; +static int str_sub(lua_State* L) +{ + size_t l; + const char* s = luaL_checklstring(L, 1, &l); + lua_Integer start = posrelat(luaL_checkinteger(L, 2), l); + lua_Integer end = posrelat(luaL_optinteger(L, 3, -1), l); + if (start < 1) start = 1; + if (end > (lua_Integer)l) end = l; + if (start <= end) + lua_pushlstring(L, s + start - 1, (size_t)(end - start) + 1); + else + lua_pushliteral(L, ""); + return 1; } -static int str_reverse (lua_State *L) { - size_t l, i; - luaL_Buffer b; - const char *s = luaL_checklstring(L, 1, &l); - char *p = luaL_buffinitsize(L, &b, l); - for (i = 0; i < l; i++) - p[i] = s[l - i - 1]; - luaL_pushresultsize(&b, l); - return 1; +static int str_reverse(lua_State* L) +{ + size_t l, i; + luaL_Buffer b; + const char* s = luaL_checklstring(L, 1, &l); + char* p = luaL_buffinitsize(L, &b, l); + for (i = 0; i < l; i++) + p[i] = s[l - i - 1]; + luaL_pushresultsize(&b, l); + return 1; } -static int str_lower (lua_State *L) { - size_t l; - size_t i; - luaL_Buffer b; - const char *s = luaL_checklstring(L, 1, &l); - char *p = luaL_buffinitsize(L, &b, l); - for (i=0; i MAXSIZE / n) /* may overflow? */ - return luaL_error(L, "resulting string too large"); - else { - size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep; - luaL_Buffer b; - char *p = luaL_buffinitsize(L, &b, totallen); - while (n-- > 1) { /* first n-1 copies (followed by separator) */ - memcpy(p, s, l * sizeof(char)); p += l; - if (lsep > 0) { /* empty 'memcpy' is not that cheap */ - memcpy(p, sep, lsep * sizeof(char)); - p += lsep; - } - } - memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ - luaL_pushresultsize(&b, totallen); - } - return 1; +static int str_rep(lua_State* L) +{ + size_t l, lsep; + const char* s = luaL_checklstring(L, 1, &l); + lua_Integer n = luaL_checkinteger(L, 2); + const char* sep = luaL_optlstring(L, 3, "", &lsep); + if (n <= 0) + lua_pushliteral(L, ""); + else if (l + lsep < l || l + lsep > MAXSIZE / n) /* may overflow? */ + return luaL_error(L, "resulting string too large"); + else + { + size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep; + luaL_Buffer b; + char* p = luaL_buffinitsize(L, &b, totallen); + while (n-- > 1) + { + /* first n-1 copies (followed by separator) */ + memcpy(p, s, l * sizeof(char)); + p += l; + if (lsep > 0) + { + /* empty 'memcpy' is not that cheap */ + memcpy(p, sep, lsep * sizeof(char)); + p += lsep; + } + } + memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ + luaL_pushresultsize(&b, totallen); + } + return 1; } -static int str_byte (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - lua_Integer posi = posrelat(luaL_optinteger(L, 2, 1), l); - lua_Integer pose = posrelat(luaL_optinteger(L, 3, posi), l); - int n, i; - if (posi < 1) posi = 1; - if (pose > (lua_Integer)l) pose = l; - if (posi > pose) return 0; /* empty interval; return no values */ - if (pose - posi >= INT_MAX) /* arithmetic overflow? */ - return luaL_error(L, "string slice too long"); - n = (int)(pose - posi) + 1; - luaL_checkstack(L, n, "string slice too long"); - for (i=0; i (lua_Integer)l) pose = l; + if (posi > pose) return 0; /* empty interval; return no values */ + if (pose - posi >= INT_MAX) /* arithmetic overflow? */ + return luaL_error(L, "string slice too long"); + n = (int)(pose - posi) + 1; + luaL_checkstack(L, n, "string slice too long"); + for (i = 0; i < n; i++) + lua_pushinteger(L, uchar(s[posi+i-1])); + return n; } -static int str_char (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - int i; - luaL_Buffer b; - char *p = luaL_buffinitsize(L, &b, n); - for (i=1; i<=n; i++) { - lua_Integer c = luaL_checkinteger(L, i); - luaL_argcheck(L, uchar(c) == c, i, "value out of range"); - p[i - 1] = uchar(c); - } - luaL_pushresultsize(&b, n); - return 1; +static int str_char(lua_State* L) +{ + int n = lua_gettop(L); /* number of arguments */ + int i; + luaL_Buffer b; + char* p = luaL_buffinitsize(L, &b, n); + for (i = 1; i <= n; i++) + { + lua_Integer c = luaL_checkinteger(L, i); + luaL_argcheck(L, uchar(c) == c, i, "value out of range"); + p[i - 1] = uchar(c); + } + luaL_pushresultsize(&b, n); + return 1; } -static int writer (lua_State *L, const void *b, size_t size, void *B) { - (void)L; - luaL_addlstring((luaL_Buffer *) B, (const char *)b, size); - return 0; +static int writer(lua_State* L, const void* b, size_t size, void* B) +{ + (void)L; + luaL_addlstring((luaL_Buffer*)B, (const char*)b, size); + return 0; } -static int str_dump (lua_State *L) { - luaL_Buffer b; - int strip = lua_toboolean(L, 2); - luaL_checktype(L, 1, LUA_TFUNCTION); - lua_settop(L, 1); - luaL_buffinit(L,&b); - if (lua_dump(L, writer, &b, strip) != 0) - return luaL_error(L, "unable to dump given function"); - luaL_pushresult(&b); - return 1; +static int str_dump(lua_State* L) +{ + luaL_Buffer b; + int strip = lua_toboolean(L, 2); + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L, 1); + luaL_buffinit(L, &b); + if (lua_dump(L, writer, &b, strip) != 0) + return luaL_error(L, "unable to dump given function"); + luaL_pushresult(&b); + return 1; } - /* ** {====================================================== ** PATTERN MATCHING @@ -211,22 +228,24 @@ static int str_dump (lua_State *L) { #define CAP_POSITION (-2) -typedef struct MatchState { - const char *src_init; /* init of source string */ - const char *src_end; /* end ('\0') of source string */ - const char *p_end; /* end ('\0') of pattern */ - lua_State *L; - int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ - unsigned char level; /* total number of captures (finished or unfinished) */ - struct { - const char *init; - ptrdiff_t len; - } capture[LUA_MAXCAPTURES]; +typedef struct MatchState +{ + const char* src_init; /* init of source string */ + const char* src_end; /* end ('\0') of source string */ + const char* p_end; /* end ('\0') of pattern */ + lua_State* L; + int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ + unsigned char level; /* total number of captures (finished or unfinished) */ + struct + { + const char* init; + ptrdiff_t len; + } capture[LUA_MAXCAPTURES]; } MatchState; /* recursive function */ -static const char *match (MatchState *ms, const char *s, const char *p); +static const char* match(MatchState* ms, const char* s, const char* p); /* maximum recursion depth for 'match' */ @@ -239,568 +258,710 @@ static const char *match (MatchState *ms, const char *s, const char *p); #define SPECIALS "^$*+?.([%-" -static int check_capture (MatchState *ms, int l) { - l -= '1'; - if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) - return luaL_error(ms->L, "invalid capture index %%%d", l + 1); - return l; +static int check_capture(MatchState* ms, int l) +{ + l -= '1'; + if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) + return luaL_error(ms->L, "invalid capture index %%%d", l + 1); + return l; } -static int capture_to_close (MatchState *ms) { - int level = ms->level; - for (level--; level>=0; level--) - if (ms->capture[level].len == CAP_UNFINISHED) return level; - return luaL_error(ms->L, "invalid pattern capture"); +static int capture_to_close(MatchState* ms) +{ + int level = ms->level; + for (level--; level >= 0; level--) + if (ms->capture[level].len == CAP_UNFINISHED) return level; + return luaL_error(ms->L, "invalid pattern capture"); } -static const char *classend (MatchState *ms, const char *p) { - switch (*p++) { - case L_ESC: { - if (p == ms->p_end) - luaL_error(ms->L, "malformed pattern (ends with '%%')"); - return p+1; - } - case '[': { - if (*p == '^') p++; - do { /* look for a ']' */ - if (p == ms->p_end) - luaL_error(ms->L, "malformed pattern (missing ']')"); - if (*(p++) == L_ESC && p < ms->p_end) - p++; /* skip escapes (e.g. '%]') */ - } while (*p != ']'); - return p+1; - } - default: { - return p; - } - } +static const char* classend(MatchState* ms, const char* p) +{ + switch (*p++) + { + case L_ESC: + { + if (p == ms->p_end) + luaL_error(ms->L, "malformed pattern (ends with '%%')"); + return p + 1; + } + case '[': + { + if (*p == '^') p++; + do + { + /* look for a ']' */ + if (p == ms->p_end) + luaL_error(ms->L, "malformed pattern (missing ']')"); + if (*(p++) == L_ESC && p < ms->p_end) + p++; /* skip escapes (e.g. '%]') */ + } + while (*p != ']'); + return p + 1; + } + default: + { + return p; + } + } } -static int match_class (int c, int cl) { - int res; - switch (tolower(cl)) { - case 'a' : res = isalpha(c); break; - case 'c' : res = iscntrl(c); break; - case 'd' : res = isdigit(c); break; - case 'g' : res = isgraph(c); break; - case 'l' : res = islower(c); break; - case 'p' : res = ispunct(c); break; - case 's' : res = isspace(c); break; - case 'u' : res = isupper(c); break; - case 'w' : res = isalnum(c); break; - case 'x' : res = isxdigit(c); break; - case 'z' : res = (c == 0); break; /* deprecated option */ - default: return (cl == c); - } - return (islower(cl) ? res : !res); +static int match_class(int c, int cl) +{ + int res; + switch (tolower(cl)) + { + case 'a': res = isalpha(c); + break; + case 'c': res = iscntrl(c); + break; + case 'd': res = isdigit(c); + break; + case 'g': res = isgraph(c); + break; + case 'l': res = islower(c); + break; + case 'p': res = ispunct(c); + break; + case 's': res = isspace(c); + break; + case 'u': res = isupper(c); + break; + case 'w': res = isalnum(c); + break; + case 'x': res = isxdigit(c); + break; + case 'z': res = (c == 0); + break; /* deprecated option */ + default: return (cl == c); + } + return (islower(cl) ? res : !res); } -static int matchbracketclass (int c, const char *p, const char *ec) { - int sig = 1; - if (*(p+1) == '^') { - sig = 0; - p++; /* skip the '^' */ - } - while (++p < ec) { - if (*p == L_ESC) { - p++; - if (match_class(c, uchar(*p))) - return sig; - } - else if ((*(p+1) == '-') && (p+2 < ec)) { - p+=2; - if (uchar(*(p-2)) <= c && c <= uchar(*p)) - return sig; - } - else if (uchar(*p) == c) return sig; - } - return !sig; +static int matchbracketclass(int c, const char* p, const char* ec) +{ + int sig = 1; + if (*(p + 1) == '^') + { + sig = 0; + p++; /* skip the '^' */ + } + while (++p < ec) + { + if (*p == L_ESC) + { + p++; + if (match_class(c, uchar(*p))) + return sig; + } + else if ((*(p + 1) == '-') && (p + 2 < ec)) + { + p += 2; + if (uchar(*(p-2)) <= c && c <= uchar(*p)) + return sig; + } + else if (uchar(*p) == c) return sig; + } + return !sig; } -static int singlematch (MatchState *ms, const char *s, const char *p, - const char *ep) { - if (s >= ms->src_end) - return 0; - else { - int c = uchar(*s); - switch (*p) { - case '.': return 1; /* matches any char */ - case L_ESC: return match_class(c, uchar(*(p+1))); - case '[': return matchbracketclass(c, p, ep-1); - default: return (uchar(*p) == c); - } - } +static int singlematch(MatchState* ms, const char* s, const char* p, + const char* ep) +{ + if (s >= ms->src_end) + return 0; + else + { + int c = uchar(*s); + switch (*p) + { + case '.': return 1; /* matches any char */ + case L_ESC: return match_class(c, uchar(*(p+1))); + case '[': return matchbracketclass(c, p, ep - 1); + default: return (uchar(*p) == c); + } + } } -static const char *matchbalance (MatchState *ms, const char *s, - const char *p) { - if (p >= ms->p_end - 1) - luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')"); - if (*s != *p) return NULL; - else { - int b = *p; - int e = *(p+1); - int cont = 1; - while (++s < ms->src_end) { - if (*s == e) { - if (--cont == 0) return s+1; - } - else if (*s == b) cont++; - } - } - return NULL; /* string ends out of balance */ +static const char* matchbalance(MatchState* ms, const char* s, + const char* p) +{ + if (p >= ms->p_end - 1) + luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')"); + if (*s != *p) return NULL; + else + { + int b = *p; + int e = *(p + 1); + int cont = 1; + while (++s < ms->src_end) + { + if (*s == e) + { + if (--cont == 0) return s + 1; + } + else if (*s == b) cont++; + } + } + return NULL; /* string ends out of balance */ } -static const char *max_expand (MatchState *ms, const char *s, - const char *p, const char *ep) { - ptrdiff_t i = 0; /* counts maximum expand for item */ - while (singlematch(ms, s + i, p, ep)) - i++; - /* keeps trying to match with the maximum repetitions */ - while (i>=0) { - const char *res = match(ms, (s+i), ep+1); - if (res) return res; - i--; /* else didn't match; reduce 1 repetition to try again */ - } - return NULL; +static const char* max_expand(MatchState* ms, const char* s, + const char* p, const char* ep) +{ + ptrdiff_t i = 0; /* counts maximum expand for item */ + while (singlematch(ms, s + i, p, ep)) + i++; + /* keeps trying to match with the maximum repetitions */ + while (i >= 0) + { + const char* res = match(ms, (s + i), ep + 1); + if (res) return res; + i--; /* else didn't match; reduce 1 repetition to try again */ + } + return NULL; } -static const char *min_expand (MatchState *ms, const char *s, - const char *p, const char *ep) { - for (;;) { - const char *res = match(ms, s, ep+1); - if (res != NULL) - return res; - else if (singlematch(ms, s, p, ep)) - s++; /* try with one more repetition */ - else return NULL; - } +static const char* min_expand(MatchState* ms, const char* s, + const char* p, const char* ep) +{ + for (;;) + { + const char* res = match(ms, s, ep + 1); + if (res != NULL) + return res; + else if (singlematch(ms, s, p, ep)) + s++; /* try with one more repetition */ + else return NULL; + } } -static const char *start_capture (MatchState *ms, const char *s, - const char *p, int what) { - const char *res; - int level = ms->level; - if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); - ms->capture[level].init = s; - ms->capture[level].len = what; - ms->level = level+1; - if ((res=match(ms, s, p)) == NULL) /* match failed? */ - ms->level--; /* undo capture */ - return res; +static const char* start_capture(MatchState* ms, const char* s, + const char* p, int what) +{ + const char* res; + int level = ms->level; + if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); + ms->capture[level].init = s; + ms->capture[level].len = what; + ms->level = level + 1; + if ((res = match(ms, s, p)) == NULL) /* match failed? */ + ms->level--; /* undo capture */ + return res; } -static const char *end_capture (MatchState *ms, const char *s, - const char *p) { - int l = capture_to_close(ms); - const char *res; - ms->capture[l].len = s - ms->capture[l].init; /* close capture */ - if ((res = match(ms, s, p)) == NULL) /* match failed? */ - ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ - return res; +static const char* end_capture(MatchState* ms, const char* s, + const char* p) +{ + int l = capture_to_close(ms); + const char* res; + ms->capture[l].len = s - ms->capture[l].init; /* close capture */ + if ((res = match(ms, s, p)) == NULL) /* match failed? */ + ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ + return res; } -static const char *match_capture (MatchState *ms, const char *s, int l) { - size_t len; - l = check_capture(ms, l); - len = ms->capture[l].len; - if ((size_t)(ms->src_end-s) >= len && - memcmp(ms->capture[l].init, s, len) == 0) - return s+len; - else return NULL; +static const char* match_capture(MatchState* ms, const char* s, int l) +{ + size_t len; + l = check_capture(ms, l); + len = ms->capture[l].len; + if ((size_t)(ms->src_end - s) >= len && + memcmp(ms->capture[l].init, s, len) == 0) + return s + len; + else return NULL; } -static const char *match (MatchState *ms, const char *s, const char *p) { - if (ms->matchdepth-- == 0) - luaL_error(ms->L, "pattern too complex"); - init: /* using goto's to optimize tail recursion */ - if (p != ms->p_end) { /* end of pattern? */ - switch (*p) { - case '(': { /* start capture */ - if (*(p + 1) == ')') /* position capture? */ - s = start_capture(ms, s, p + 2, CAP_POSITION); - else - s = start_capture(ms, s, p + 1, CAP_UNFINISHED); - break; - } - case ')': { /* end capture */ - s = end_capture(ms, s, p + 1); - break; - } - case '$': { - if ((p + 1) != ms->p_end) /* is the '$' the last char in pattern? */ - goto dflt; /* no; go to default */ - s = (s == ms->src_end) ? s : NULL; /* check end of string */ - break; - } - case L_ESC: { /* escaped sequences not in the format class[*+?-]? */ - switch (*(p + 1)) { - case 'b': { /* balanced string? */ - s = matchbalance(ms, s, p + 2); - if (s != NULL) { - p += 4; goto init; /* return match(ms, s, p + 4); */ - } /* else fail (s == NULL) */ - break; - } - case 'f': { /* frontier? */ - const char *ep; char previous; - p += 2; - if (*p != '[') - luaL_error(ms->L, "missing '[' after '%%f' in pattern"); - ep = classend(ms, p); /* points to what is next */ - previous = (s == ms->src_init) ? '\0' : *(s - 1); - if (!matchbracketclass(uchar(previous), p, ep - 1) && - matchbracketclass(uchar(*s), p, ep - 1)) { - p = ep; goto init; /* return match(ms, s, ep); */ - } - s = NULL; /* match failed */ - break; - } - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - case '8': case '9': { /* capture results (%0-%9)? */ - s = match_capture(ms, s, uchar(*(p + 1))); - if (s != NULL) { - p += 2; goto init; /* return match(ms, s, p + 2) */ - } - break; - } - default: goto dflt; - } - break; - } - default: dflt: { /* pattern class plus optional suffix */ - const char *ep = classend(ms, p); /* points to optional suffix */ - /* does not match at least once? */ - if (!singlematch(ms, s, p, ep)) { - if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */ - p = ep + 1; goto init; /* return match(ms, s, ep + 1); */ - } - else /* '+' or no suffix */ - s = NULL; /* fail */ - } - else { /* matched once */ - switch (*ep) { /* handle optional suffix */ - case '?': { /* optional */ - const char *res; - if ((res = match(ms, s + 1, ep + 1)) != NULL) - s = res; - else { - p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */ - } - break; - } - case '+': /* 1 or more repetitions */ - s++; /* 1 match already done */ - /* FALLTHROUGH */ - case '*': /* 0 or more repetitions */ - s = max_expand(ms, s, p, ep); - break; - case '-': /* 0 or more repetitions (minimum) */ - s = min_expand(ms, s, p, ep); - break; - default: /* no suffix */ - s++; p = ep; goto init; /* return match(ms, s + 1, ep); */ - } - } - break; - } - } - } - ms->matchdepth++; - return s; +static const char* match(MatchState* ms, const char* s, const char* p) +{ + if (ms->matchdepth-- == 0) + luaL_error(ms->L, "pattern too complex"); +init: /* using goto's to optimize tail recursion */ + if (p != ms->p_end) + { + /* end of pattern? */ + switch (*p) + { + case '(': + { + /* start capture */ + if (*(p + 1) == ')') /* position capture? */ + s = start_capture(ms, s, p + 2, CAP_POSITION); + else + s = start_capture(ms, s, p + 1, CAP_UNFINISHED); + break; + } + case ')': + { + /* end capture */ + s = end_capture(ms, s, p + 1); + break; + } + case '$': + { + if ((p + 1) != ms->p_end) /* is the '$' the last char in pattern? */ + goto dflt; /* no; go to default */ + s = (s == ms->src_end) ? s : NULL; /* check end of string */ + break; + } + case L_ESC: + { + /* escaped sequences not in the format class[*+?-]? */ + switch (*(p + 1)) + { + case 'b': + { + /* balanced string? */ + s = matchbalance(ms, s, p + 2); + if (s != NULL) + { + p += 4; + goto init; /* return match(ms, s, p + 4); */ + } /* else fail (s == NULL) */ + break; + } + case 'f': + { + /* frontier? */ + const char* ep; + char previous; + p += 2; + if (*p != '[') + luaL_error(ms->L, "missing '[' after '%%f' in pattern"); + ep = classend(ms, p); /* points to what is next */ + previous = (s == ms->src_init) ? '\0' : *(s - 1); + if (!matchbracketclass(uchar(previous), p, ep - 1) && + matchbracketclass(uchar(*s), p, ep - 1)) + { + p = ep; + goto init; /* return match(ms, s, ep); */ + } + s = NULL; /* match failed */ + break; + } + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + /* capture results (%0-%9)? */ + s = match_capture(ms, s, uchar(*(p + 1))); + if (s != NULL) + { + p += 2; + goto init; /* return match(ms, s, p + 2) */ + } + break; + } + default: goto dflt; + } + break; + } + default: dflt: + { + /* pattern class plus optional suffix */ + const char* ep = classend(ms, p); /* points to optional suffix */ + /* does not match at least once? */ + if (!singlematch(ms, s, p, ep)) + { + if (*ep == '*' || *ep == '?' || *ep == '-') + { + /* accept empty? */ + p = ep + 1; + goto init; /* return match(ms, s, ep + 1); */ + } + else /* '+' or no suffix */ + s = NULL; /* fail */ + } + else + { + /* matched once */ + switch (*ep) + { + /* handle optional suffix */ + case '?': + { + /* optional */ + const char* res; + if ((res = match(ms, s + 1, ep + 1)) != NULL) + s = res; + else + { + p = ep + 1; + goto init; /* else return match(ms, s, ep + 1); */ + } + break; + } + case '+': /* 1 or more repetitions */ + s++; /* 1 match already done */ + /* FALLTHROUGH */ + case '*': /* 0 or more repetitions */ + s = max_expand(ms, s, p, ep); + break; + case '-': /* 0 or more repetitions (minimum) */ + s = min_expand(ms, s, p, ep); + break; + default: /* no suffix */ + s++; + p = ep; + goto init; /* return match(ms, s + 1, ep); */ + } + } + break; + } + } + } + ms->matchdepth++; + return s; } - -static const char *lmemfind (const char *s1, size_t l1, - const char *s2, size_t l2) { - if (l2 == 0) return s1; /* empty strings are everywhere */ - else if (l2 > l1) return NULL; /* avoids a negative 'l1' */ - else { - const char *init; /* to search for a '*s2' inside 's1' */ - l2--; /* 1st char will be checked by 'memchr' */ - l1 = l1-l2; /* 's2' cannot be found after that */ - while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { - init++; /* 1st char is already checked */ - if (memcmp(init, s2+1, l2) == 0) - return init-1; - else { /* correct 'l1' and 's1' to try again */ - l1 -= init-s1; - s1 = init; - } - } - return NULL; /* not found */ - } +static const char* lmemfind(const char* s1, size_t l1, + const char* s2, size_t l2) +{ + if (l2 == 0) return s1; /* empty strings are everywhere */ + else if (l2 > l1) return NULL; /* avoids a negative 'l1' */ + else + { + const char* init; /* to search for a '*s2' inside 's1' */ + l2--; /* 1st char will be checked by 'memchr' */ + l1 = l1 - l2; /* 's2' cannot be found after that */ + while (l1 > 0 && (init = (const char*)memchr(s1, *s2, l1)) != NULL) + { + init++; /* 1st char is already checked */ + if (memcmp(init, s2 + 1, l2) == 0) + return init - 1; + else + { + /* correct 'l1' and 's1' to try again */ + l1 -= init - s1; + s1 = init; + } + } + return NULL; /* not found */ + } } -static void push_onecapture (MatchState *ms, int i, const char *s, - const char *e) { - if (i >= ms->level) { - if (i == 0) /* ms->level == 0, too */ - lua_pushlstring(ms->L, s, e - s); /* add whole match */ - else - luaL_error(ms->L, "invalid capture index %%%d", i + 1); - } - else { - ptrdiff_t l = ms->capture[i].len; - if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); - if (l == CAP_POSITION) - lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1); - else - lua_pushlstring(ms->L, ms->capture[i].init, l); - } +static void push_onecapture(MatchState* ms, int i, const char* s, + const char* e) +{ + if (i >= ms->level) + { + if (i == 0) /* ms->level == 0, too */ + lua_pushlstring(ms->L, s, e - s); /* add whole match */ + else + luaL_error(ms->L, "invalid capture index %%%d", i + 1); + } + else + { + ptrdiff_t l = ms->capture[i].len; + if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); + if (l == CAP_POSITION) + lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1); + else + lua_pushlstring(ms->L, ms->capture[i].init, l); + } } -static int push_captures (MatchState *ms, const char *s, const char *e) { - int i; - int nlevels = (ms->level == 0 && s) ? 1 : ms->level; - luaL_checkstack(ms->L, nlevels, "too many captures"); - for (i = 0; i < nlevels; i++) - push_onecapture(ms, i, s, e); - return nlevels; /* number of strings pushed */ +static int push_captures(MatchState* ms, const char* s, const char* e) +{ + int i; + int nlevels = (ms->level == 0 && s) ? 1 : ms->level; + luaL_checkstack(ms->L, nlevels, "too many captures"); + for (i = 0; i < nlevels; i++) + push_onecapture(ms, i, s, e); + return nlevels; /* number of strings pushed */ } /* check whether pattern has no special characters */ -static int nospecials (const char *p, size_t l) { - size_t upto = 0; - do { - if (strpbrk(p + upto, SPECIALS)) - return 0; /* pattern has a special character */ - upto += strlen(p + upto) + 1; /* may have more after \0 */ - } while (upto <= l); - return 1; /* no special chars found */ +static int nospecials(const char* p, size_t l) +{ + size_t upto = 0; + do + { + if (strpbrk(p + upto, SPECIALS)) + return 0; /* pattern has a special character */ + upto += strlen(p + upto) + 1; /* may have more after \0 */ + } + while (upto <= l); + return 1; /* no special chars found */ } -static void prepstate (MatchState *ms, lua_State *L, - const char *s, size_t ls, const char *p, size_t lp) { - ms->L = L; - ms->matchdepth = MAXCCALLS; - ms->src_init = s; - ms->src_end = s + ls; - ms->p_end = p + lp; +static void prepstate(MatchState* ms, lua_State* L, + const char* s, size_t ls, const char* p, size_t lp) +{ + ms->L = L; + ms->matchdepth = MAXCCALLS; + ms->src_init = s; + ms->src_end = s + ls; + ms->p_end = p + lp; } -static void reprepstate (MatchState *ms) { - ms->level = 0; - lua_assert(ms->matchdepth == MAXCCALLS); +static void reprepstate(MatchState* ms) +{ + ms->level = 0; + lua_assert(ms->matchdepth == MAXCCALLS); } -static int str_find_aux (lua_State *L, int find) { - size_t ls, lp; - const char *s = luaL_checklstring(L, 1, &ls); - const char *p = luaL_checklstring(L, 2, &lp); - lua_Integer init = posrelat(luaL_optinteger(L, 3, 1), ls); - if (init < 1) init = 1; - else if (init > (lua_Integer)ls + 1) { /* start after string's end? */ - lua_pushnil(L); /* cannot find anything */ - return 1; - } - /* explicit request or no special characters? */ - if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) { - /* do a plain search */ - const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp); - if (s2) { - lua_pushinteger(L, (s2 - s) + 1); - lua_pushinteger(L, (s2 - s) + lp); - return 2; - } - } - else { - MatchState ms; - const char *s1 = s + init - 1; - int anchor = (*p == '^'); - if (anchor) { - p++; lp--; /* skip anchor character */ - } - prepstate(&ms, L, s, ls, p, lp); - do { - const char *res; - reprepstate(&ms); - if ((res=match(&ms, s1, p)) != NULL) { - if (find) { - lua_pushinteger(L, (s1 - s) + 1); /* start */ - lua_pushinteger(L, res - s); /* end */ - return push_captures(&ms, NULL, 0) + 2; - } - else - return push_captures(&ms, s1, res); - } - } while (s1++ < ms.src_end && !anchor); - } - lua_pushnil(L); /* not found */ - return 1; +static int str_find_aux(lua_State* L, int find) +{ + size_t ls, lp; + const char* s = luaL_checklstring(L, 1, &ls); + const char* p = luaL_checklstring(L, 2, &lp); + lua_Integer init = posrelat(luaL_optinteger(L, 3, 1), ls); + if (init < 1) init = 1; + else if (init > (lua_Integer)ls + 1) + { + /* start after string's end? */ + lua_pushnil(L); /* cannot find anything */ + return 1; + } + /* explicit request or no special characters? */ + if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) + { + /* do a plain search */ + const char* s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp); + if (s2) + { + lua_pushinteger(L, (s2 - s) + 1); + lua_pushinteger(L, (s2 - s) + lp); + return 2; + } + } + else + { + MatchState ms; + const char* s1 = s + init - 1; + int anchor = (*p == '^'); + if (anchor) + { + p++; + lp--; /* skip anchor character */ + } + prepstate(&ms, L, s, ls, p, lp); + do + { + const char* res; + reprepstate(&ms); + if ((res = match(&ms, s1, p)) != NULL) + { + if (find) + { + lua_pushinteger(L, (s1 - s) + 1); /* start */ + lua_pushinteger(L, res - s); /* end */ + return push_captures(&ms, NULL, 0) + 2; + } + else + return push_captures(&ms, s1, res); + } + } + while (s1++ < ms.src_end && !anchor); + } + lua_pushnil(L); /* not found */ + return 1; } -static int str_find (lua_State *L) { - return str_find_aux(L, 1); +static int str_find(lua_State* L) +{ + return str_find_aux(L, 1); } -static int str_match (lua_State *L) { - return str_find_aux(L, 0); +static int str_match(lua_State* L) +{ + return str_find_aux(L, 0); } /* state for 'gmatch' */ -typedef struct GMatchState { - const char *src; /* current position */ - const char *p; /* pattern */ - const char *lastmatch; /* end of last match */ - MatchState ms; /* match state */ +typedef struct GMatchState +{ + const char* src; /* current position */ + const char* p; /* pattern */ + const char* lastmatch; /* end of last match */ + MatchState ms; /* match state */ } GMatchState; -static int gmatch_aux (lua_State *L) { - GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3)); - const char *src; - gm->ms.L = L; - for (src = gm->src; src <= gm->ms.src_end; src++) { - const char *e; - reprepstate(&gm->ms); - if ((e = match(&gm->ms, src, gm->p)) != NULL && e != gm->lastmatch) { - gm->src = gm->lastmatch = e; - return push_captures(&gm->ms, src, e); - } - } - return 0; /* not found */ +static int gmatch_aux(lua_State* L) +{ + GMatchState* gm = (GMatchState*)lua_touserdata(L, lua_upvalueindex(3)); + const char* src; + gm->ms.L = L; + for (src = gm->src; src <= gm->ms.src_end; src++) + { + const char* e; + reprepstate(&gm->ms); + if ((e = match(&gm->ms, src, gm->p)) != NULL && e != gm->lastmatch) + { + gm->src = gm->lastmatch = e; + return push_captures(&gm->ms, src, e); + } + } + return 0; /* not found */ } -static int gmatch (lua_State *L) { - size_t ls, lp; - const char *s = luaL_checklstring(L, 1, &ls); - const char *p = luaL_checklstring(L, 2, &lp); - GMatchState *gm; - lua_settop(L, 2); /* keep them on closure to avoid being collected */ - gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState)); - prepstate(&gm->ms, L, s, ls, p, lp); - gm->src = s; gm->p = p; gm->lastmatch = NULL; - lua_pushcclosure(L, gmatch_aux, 3); - return 1; +static int gmatch(lua_State* L) +{ + size_t ls, lp; + const char* s = luaL_checklstring(L, 1, &ls); + const char* p = luaL_checklstring(L, 2, &lp); + GMatchState* gm; + lua_settop(L, 2); /* keep them on closure to avoid being collected */ + gm = (GMatchState*)lua_newuserdata(L, sizeof(GMatchState)); + prepstate(&gm->ms, L, s, ls, p, lp); + gm->src = s; + gm->p = p; + gm->lastmatch = NULL; + lua_pushcclosure(L, gmatch_aux, 3); + return 1; } -static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, - const char *e) { - size_t l, i; - lua_State *L = ms->L; - const char *news = lua_tolstring(L, 3, &l); - for (i = 0; i < l; i++) { - if (news[i] != L_ESC) - luaL_addchar(b, news[i]); - else { - i++; /* skip ESC */ - if (!isdigit(uchar(news[i]))) { - if (news[i] != L_ESC) - luaL_error(L, "invalid use of '%c' in replacement string", L_ESC); - luaL_addchar(b, news[i]); - } - else if (news[i] == '0') - luaL_addlstring(b, s, e - s); - else { - push_onecapture(ms, news[i] - '1', s, e); - luaL_tolstring(L, -1, NULL); /* if number, convert it to string */ - lua_remove(L, -2); /* remove original value */ - luaL_addvalue(b); /* add capture to accumulated result */ - } - } - } +static void add_s(MatchState* ms, luaL_Buffer* b, const char* s, + const char* e) +{ + size_t l, i; + lua_State* L = ms->L; + const char* news = lua_tolstring(L, 3, &l); + for (i = 0; i < l; i++) + { + if (news[i] != L_ESC) + luaL_addchar(b, news[i]); + else + { + i++; /* skip ESC */ + if (!isdigit(uchar(news[i]))) + { + if (news[i] != L_ESC) + luaL_error(L, "invalid use of '%c' in replacement string", L_ESC); + luaL_addchar(b, news[i]); + } + else if (news[i] == '0') + luaL_addlstring(b, s, e - s); + else + { + push_onecapture(ms, news[i] - '1', s, e); + luaL_tolstring(L, -1, NULL); /* if number, convert it to string */ + lua_remove(L, -2); /* remove original value */ + luaL_addvalue(b); /* add capture to accumulated result */ + } + } + } } -static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, - const char *e, int tr) { - lua_State *L = ms->L; - switch (tr) { - case LUA_TFUNCTION: { - int n; - lua_pushvalue(L, 3); - n = push_captures(ms, s, e); - lua_call(L, n, 1); - break; - } - case LUA_TTABLE: { - push_onecapture(ms, 0, s, e); - lua_gettable(L, 3); - break; - } - default: { /* LUA_TNUMBER or LUA_TSTRING */ - add_s(ms, b, s, e); - return; - } - } - if (!lua_toboolean(L, -1)) { /* nil or false? */ - lua_pop(L, 1); - lua_pushlstring(L, s, e - s); /* keep original text */ - } - else if (!lua_isstring(L, -1)) - luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); - luaL_addvalue(b); /* add result to accumulator */ +static void add_value(MatchState* ms, luaL_Buffer* b, const char* s, + const char* e, int tr) +{ + lua_State* L = ms->L; + switch (tr) + { + case LUA_TFUNCTION: + { + int n; + lua_pushvalue(L, 3); + n = push_captures(ms, s, e); + lua_call(L, n, 1); + break; + } + case LUA_TTABLE: + { + push_onecapture(ms, 0, s, e); + lua_gettable(L, 3); + break; + } + default: + { + /* LUA_TNUMBER or LUA_TSTRING */ + add_s(ms, b, s, e); + return; + } + } + if (!lua_toboolean(L, -1)) + { + /* nil or false? */ + lua_pop(L, 1); + lua_pushlstring(L, s, e - s); /* keep original text */ + } + else if (!lua_isstring(L, -1)) + luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); + luaL_addvalue(b); /* add result to accumulator */ } -static int str_gsub (lua_State *L) { - size_t srcl, lp; - const char *src = luaL_checklstring(L, 1, &srcl); /* subject */ - const char *p = luaL_checklstring(L, 2, &lp); /* pattern */ - const char *lastmatch = NULL; /* end of last match */ - int tr = lua_type(L, 3); /* replacement type */ - lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */ - int anchor = (*p == '^'); - lua_Integer n = 0; /* replacement count */ - MatchState ms; - luaL_Buffer b; - luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || - tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, - "string/function/table expected"); - luaL_buffinit(L, &b); - if (anchor) { - p++; lp--; /* skip anchor character */ - } - prepstate(&ms, L, src, srcl, p, lp); - while (n < max_s) { - const char *e; - reprepstate(&ms); /* (re)prepare state for new match */ - if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */ - n++; - add_value(&ms, &b, src, e, tr); /* add replacement to buffer */ - src = lastmatch = e; - } - else if (src < ms.src_end) /* otherwise, skip one character */ - luaL_addchar(&b, *src++); - else break; /* end of subject */ - if (anchor) break; - } - luaL_addlstring(&b, src, ms.src_end-src); - luaL_pushresult(&b); - lua_pushinteger(L, n); /* number of substitutions */ - return 2; +static int str_gsub(lua_State* L) +{ + size_t srcl, lp; + const char* src = luaL_checklstring(L, 1, &srcl); /* subject */ + const char* p = luaL_checklstring(L, 2, &lp); /* pattern */ + const char* lastmatch = NULL; /* end of last match */ + int tr = lua_type(L, 3); /* replacement type */ + lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */ + int anchor = (*p == '^'); + lua_Integer n = 0; /* replacement count */ + MatchState ms; + luaL_Buffer b; + luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || + tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, + "string/function/table expected"); + luaL_buffinit(L, &b); + if (anchor) + { + p++; + lp--; /* skip anchor character */ + } + prepstate(&ms, L, src, srcl, p, lp); + while (n < max_s) + { + const char* e; + reprepstate(&ms); /* (re)prepare state for new match */ + if ((e = match(&ms, src, p)) != NULL && e != lastmatch) + { + /* match? */ + n++; + add_value(&ms, &b, src, e, tr); /* add replacement to buffer */ + src = lastmatch = e; + } + else if (src < ms.src_end) /* otherwise, skip one character */ + luaL_addchar(&b, *src++); + else break; /* end of subject */ + if (anchor) break; + } + luaL_addlstring(&b, src, ms.src_end - src); + luaL_pushresult(&b); + lua_pushinteger(L, n); /* number of substitutions */ + return 2; } /* }====================================================== */ - /* ** {====================================================== ** STRING FORMAT @@ -830,57 +991,72 @@ static int str_gsub (lua_State *L) { /* ** Add integer part of 'x' to buffer and return new 'x' */ -static lua_Number adddigit (char *buff, int n, lua_Number x) { - lua_Number dd = l_mathop(floor)(x); /* get integer part from 'x' */ - int d = (int)dd; - buff[n] = (d < 10 ? d + '0' : d - 10 + 'a'); /* add to buffer */ - return x - dd; /* return what is left */ +static lua_Number adddigit(char* buff, int n, lua_Number x) +{ + lua_Number dd = l_mathop(floor)(x); /* get integer part from 'x' */ + int d = (int)dd; + buff[n] = (d < 10 ? d + '0' : d - 10 + 'a'); /* add to buffer */ + return x - dd; /* return what is left */ } -static int num2straux (char *buff, int sz, lua_Number x) { - /* if 'inf' or 'NaN', format it like '%g' */ - if (x != x || x == (lua_Number)HUGE_VAL || x == -(lua_Number)HUGE_VAL) - return l_sprintf(buff, sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)x); - else if (x == 0) { /* can be -0... */ - /* create "0" or "-0" followed by exponent */ - return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", (LUAI_UACNUMBER)x); - } - else { - int e; - lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */ - int n = 0; /* character count */ - if (m < 0) { /* is number negative? */ - buff[n++] = '-'; /* add signal */ - m = -m; /* make it positive */ - } - buff[n++] = '0'; buff[n++] = 'x'; /* add "0x" */ - m = adddigit(buff, n++, m * (1 << L_NBFD)); /* add first digit */ - e -= L_NBFD; /* this digit goes before the radix point */ - if (m > 0) { /* more digits? */ - buff[n++] = lua_getlocaledecpoint(); /* add radix point */ - do { /* add as many digits as needed */ - m = adddigit(buff, n++, m * 16); - } while (m > 0); - } - n += l_sprintf(buff + n, sz - n, "p%+d", e); /* add exponent */ - lua_assert(n < sz); - return n; - } +static int num2straux(char* buff, int sz, lua_Number x) +{ + /* if 'inf' or 'NaN', format it like '%g' */ + if (x != x || x == (lua_Number)HUGE_VAL || x == -(lua_Number)HUGE_VAL) + return l_sprintf(buff, sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)x); + else if (x == 0) + { + /* can be -0... */ + /* create "0" or "-0" followed by exponent */ + return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", (LUAI_UACNUMBER)x); + } + else + { + int e; + lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */ + int n = 0; /* character count */ + if (m < 0) + { + /* is number negative? */ + buff[n++] = '-'; /* add signal */ + m = -m; /* make it positive */ + } + buff[n++] = '0'; + buff[n++] = 'x'; /* add "0x" */ + m = adddigit(buff, n++, m * (1 << L_NBFD)); /* add first digit */ + e -= L_NBFD; /* this digit goes before the radix point */ + if (m > 0) + { + /* more digits? */ + buff[n++] = lua_getlocaledecpoint(); /* add radix point */ + do + { + /* add as many digits as needed */ + m = adddigit(buff, n++, m * 16); + } + while (m > 0); + } + n += l_sprintf(buff + n, sz - n, "p%+d", e); /* add exponent */ + lua_assert(n < sz); + return n; + } } -static int lua_number2strx (lua_State *L, char *buff, int sz, - const char *fmt, lua_Number x) { - int n = num2straux(buff, sz, x); - if (fmt[SIZELENMOD] == 'A') { - int i; - for (i = 0; i < n; i++) - buff[i] = toupper(uchar(buff[i])); - } - else if (fmt[SIZELENMOD] != 'a') - luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented"); - return n; +static int lua_number2strx(lua_State* L, char* buff, int sz, + const char* fmt, lua_Number x) +{ + int n = num2straux(buff, sz, x); + if (fmt[SIZELENMOD] == 'A') + { + int i; + for (i = 0; i < n; i++) + buff[i] = toupper(uchar(buff[i])); + } + else if (fmt[SIZELENMOD] != 'a') + luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented"); + return n; } #endif /* } */ @@ -905,191 +1081,236 @@ static int lua_number2strx (lua_State *L, char *buff, int sz, #define MAX_FORMAT 32 -static void addquoted (luaL_Buffer *b, const char *s, size_t len) { - luaL_addchar(b, '"'); - while (len--) { - if (*s == '"' || *s == '\\' || *s == '\n') { - luaL_addchar(b, '\\'); - luaL_addchar(b, *s); - } - else if (iscntrl(uchar(*s))) { - char buff[10]; - if (!isdigit(uchar(*(s+1)))) - l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s)); - else - l_sprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s)); - luaL_addstring(b, buff); - } - else - luaL_addchar(b, *s); - s++; - } - luaL_addchar(b, '"'); +static void addquoted(luaL_Buffer* b, const char* s, size_t len) +{ + luaL_addchar(b, '"'); + while (len--) + { + if (*s == '"' || *s == '\\' || *s == '\n') + { + luaL_addchar(b, '\\'); + luaL_addchar(b, *s); + } + else if (iscntrl(uchar(*s))) + { + char buff[10]; + if (!isdigit(uchar(*(s+1)))) + l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s)); + else + l_sprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s)); + luaL_addstring(b, buff); + } + else + luaL_addchar(b, *s); + s++; + } + luaL_addchar(b, '"'); } /* ** Ensures the 'buff' string uses a dot as the radix character. */ -static void checkdp (char *buff, int nb) { - if (memchr(buff, '.', nb) == NULL) { /* no dot? */ - char point = lua_getlocaledecpoint(); /* try locale point */ - char *ppoint = (char *)memchr(buff, point, nb); - if (ppoint) *ppoint = '.'; /* change it to a dot */ - } +static void checkdp(char* buff, int nb) +{ + if (memchr(buff, '.', nb) == NULL) + { + /* no dot? */ + char point = lua_getlocaledecpoint(); /* try locale point */ + char* ppoint = (char*)memchr(buff, point, nb); + if (ppoint) *ppoint = '.'; /* change it to a dot */ + } } -static void addliteral (lua_State *L, luaL_Buffer *b, int arg) { - switch (lua_type(L, arg)) { - case LUA_TSTRING: { - size_t len; - const char *s = lua_tolstring(L, arg, &len); - addquoted(b, s, len); - break; - } - case LUA_TNUMBER: { - char *buff = luaL_prepbuffsize(b, MAX_ITEM); - int nb; - if (!lua_isinteger(L, arg)) { /* float? */ - lua_Number n = lua_tonumber(L, arg); /* write as hexa ('%a') */ - nb = lua_number2strx(L, buff, MAX_ITEM, "%" LUA_NUMBER_FRMLEN "a", n); - checkdp(buff, nb); /* ensure it uses a dot */ - } - else { /* integers */ - lua_Integer n = lua_tointeger(L, arg); - const char *format = (n == LUA_MININTEGER) /* corner case? */ - ? "0x%" LUA_INTEGER_FRMLEN "x" /* use hexa */ - : LUA_INTEGER_FMT; /* else use default format */ - nb = l_sprintf(buff, MAX_ITEM, format, (LUAI_UACINT)n); - } - luaL_addsize(b, nb); - break; - } - case LUA_TNIL: case LUA_TBOOLEAN: { - luaL_tolstring(L, arg, NULL); - luaL_addvalue(b); - break; - } - default: { - luaL_argerror(L, arg, "value has no literal form"); - } - } +static void addliteral(lua_State* L, luaL_Buffer* b, int arg) +{ + switch (lua_type(L, arg)) + { + case LUA_TSTRING: + { + size_t len; + const char* s = lua_tolstring(L, arg, &len); + addquoted(b, s, len); + break; + } + case LUA_TNUMBER: + { + char* buff = luaL_prepbuffsize(b, MAX_ITEM); + int nb; + if (!lua_isinteger(L, arg)) + { + /* float? */ + lua_Number n = lua_tonumber(L, arg); /* write as hexa ('%a') */ + nb = lua_number2strx(L, buff, MAX_ITEM, "%" LUA_NUMBER_FRMLEN "a", n); + checkdp(buff, nb); /* ensure it uses a dot */ + } + else + { + /* integers */ + lua_Integer n = lua_tointeger(L, arg); + const char* format = (n == LUA_MININTEGER) /* corner case? */ + ? "0x%" LUA_INTEGER_FRMLEN "x" /* use hexa */ + : LUA_INTEGER_FMT; /* else use default format */ + nb = l_sprintf(buff, MAX_ITEM, format, (LUAI_UACINT)n); + } + luaL_addsize(b, nb); + break; + } + case LUA_TNIL: + case LUA_TBOOLEAN: + { + luaL_tolstring(L, arg, NULL); + luaL_addvalue(b); + break; + } + default: + { + luaL_argerror(L, arg, "value has no literal form"); + } + } } -static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { - const char *p = strfrmt; - while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ - if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char)) - luaL_error(L, "invalid format (repeated flags)"); - if (isdigit(uchar(*p))) p++; /* skip width */ - if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ - if (*p == '.') { - p++; - if (isdigit(uchar(*p))) p++; /* skip precision */ - if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ - } - if (isdigit(uchar(*p))) - luaL_error(L, "invalid format (width or precision too long)"); - *(form++) = '%'; - memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char)); - form += (p - strfrmt) + 1; - *form = '\0'; - return p; +static const char* scanformat(lua_State* L, const char* strfrmt, char* form) +{ + const char* p = strfrmt; + while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ + if ((size_t)(p - strfrmt) >= sizeof(FLAGS) / sizeof(char)) + luaL_error(L, "invalid format (repeated flags)"); + if (isdigit(uchar(*p))) p++; /* skip width */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + if (*p == '.') + { + p++; + if (isdigit(uchar(*p))) p++; /* skip precision */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + } + if (isdigit(uchar(*p))) + luaL_error(L, "invalid format (width or precision too long)"); + *(form++) = '%'; + memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char)); + form += (p - strfrmt) + 1; + *form = '\0'; + return p; } /* ** add length modifier into formats */ -static void addlenmod (char *form, const char *lenmod) { - size_t l = strlen(form); - size_t lm = strlen(lenmod); - char spec = form[l - 1]; - strcpy(form + l - 1, lenmod); - form[l + lm - 1] = spec; - form[l + lm] = '\0'; +static void addlenmod(char* form, const char* lenmod) +{ + size_t l = strlen(form); + size_t lm = strlen(lenmod); + char spec = form[l - 1]; + strcpy(form + l - 1, lenmod); + form[l + lm - 1] = spec; + form[l + lm] = '\0'; } -static int str_format (lua_State *L) { - int top = lua_gettop(L); - int arg = 1; - size_t sfl; - const char *strfrmt = luaL_checklstring(L, arg, &sfl); - const char *strfrmt_end = strfrmt+sfl; - luaL_Buffer b; - luaL_buffinit(L, &b); - while (strfrmt < strfrmt_end) { - if (*strfrmt != L_ESC) - luaL_addchar(&b, *strfrmt++); - else if (*++strfrmt == L_ESC) - luaL_addchar(&b, *strfrmt++); /* %% */ - else { /* format item */ - char form[MAX_FORMAT]; /* to store the format ('%...') */ - char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ - int nb = 0; /* number of bytes in added item */ - if (++arg > top) - luaL_argerror(L, arg, "no value"); - strfrmt = scanformat(L, strfrmt, form); - switch (*strfrmt++) { - case 'c': { - nb = l_sprintf(buff, MAX_ITEM, form, (int)luaL_checkinteger(L, arg)); - break; - } - case 'd': case 'i': - case 'o': case 'u': case 'x': case 'X': { - lua_Integer n = luaL_checkinteger(L, arg); - addlenmod(form, LUA_INTEGER_FRMLEN); - nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACINT)n); - break; - } - case 'a': case 'A': - addlenmod(form, LUA_NUMBER_FRMLEN); - nb = lua_number2strx(L, buff, MAX_ITEM, form, - luaL_checknumber(L, arg)); - break; - case 'e': case 'E': case 'f': - case 'g': case 'G': { - lua_Number n = luaL_checknumber(L, arg); - addlenmod(form, LUA_NUMBER_FRMLEN); - nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACNUMBER)n); - break; - } - case 'q': { - addliteral(L, &b, arg); - break; - } - case 's': { - size_t l; - const char *s = luaL_tolstring(L, arg, &l); - if (form[2] == '\0') /* no modifiers? */ - luaL_addvalue(&b); /* keep entire string */ - else { - luaL_argcheck(L, l == strlen(s), arg, "string contains zeros"); - if (!strchr(form, '.') && l >= 100) { - /* no precision and string is too long to be formatted */ - luaL_addvalue(&b); /* keep entire string */ - } - else { /* format the string into 'buff' */ - nb = l_sprintf(buff, MAX_ITEM, form, s); - lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ - } - } - break; - } - default: { /* also treat cases 'pnLlh' */ - return luaL_error(L, "invalid option '%%%c' to 'format'", - *(strfrmt - 1)); - } - } - lua_assert(nb < MAX_ITEM); - luaL_addsize(&b, nb); - } - } - luaL_pushresult(&b); - return 1; +static int str_format(lua_State* L) +{ + int top = lua_gettop(L); + int arg = 1; + size_t sfl; + const char* strfrmt = luaL_checklstring(L, arg, &sfl); + const char* strfrmt_end = strfrmt + sfl; + luaL_Buffer b; + luaL_buffinit(L, &b); + while (strfrmt < strfrmt_end) + { + if (*strfrmt != L_ESC) + luaL_addchar(&b, *strfrmt++); + else if (*++strfrmt == L_ESC) + luaL_addchar(&b, *strfrmt++); /* %% */ + else + { + /* format item */ + char form[MAX_FORMAT]; /* to store the format ('%...') */ + char* buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ + int nb = 0; /* number of bytes in added item */ + if (++arg > top) + luaL_argerror(L, arg, "no value"); + strfrmt = scanformat(L, strfrmt, form); + switch (*strfrmt++) + { + case 'c': + { + nb = l_sprintf(buff, MAX_ITEM, form, (int)luaL_checkinteger(L, arg)); + break; + } + case 'd': + case 'i': + case 'o': + case 'u': + case 'x': + case 'X': + { + lua_Integer n = luaL_checkinteger(L, arg); + addlenmod(form, LUA_INTEGER_FRMLEN); + nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACINT)n); + break; + } + case 'a': + case 'A': + addlenmod(form, LUA_NUMBER_FRMLEN); + nb = lua_number2strx(L, buff, MAX_ITEM, form, + luaL_checknumber(L, arg)); + break; + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + { + lua_Number n = luaL_checknumber(L, arg); + addlenmod(form, LUA_NUMBER_FRMLEN); + nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACNUMBER)n); + break; + } + case 'q': + { + addliteral(L, &b, arg); + break; + } + case 's': + { + size_t l; + const char* s = luaL_tolstring(L, arg, &l); + if (form[2] == '\0') /* no modifiers? */ + luaL_addvalue(&b); /* keep entire string */ + else + { + luaL_argcheck(L, l == strlen(s), arg, "string contains zeros"); + if (!strchr(form, '.') && l >= 100) + { + /* no precision and string is too long to be formatted */ + luaL_addvalue(&b); /* keep entire string */ + } + else + { + /* format the string into 'buff' */ + nb = l_sprintf(buff, MAX_ITEM, form, s); + lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ + } + } + break; + } + default: + { + /* also treat cases 'pnLlh' */ + return luaL_error(L, "invalid option '%%%c' to 'format'", + *(strfrmt - 1)); + } + } + lua_assert(nb < MAX_ITEM); + luaL_addsize(&b, nb); + } + } + luaL_pushresult(&b); + return 1; } /* }====================================================== */ @@ -1121,16 +1342,25 @@ static int str_format (lua_State *L) { /* dummy union to get native endianness */ -static const union { - int dummy; - char little; /* true iff machine is little endian */ +static const union +{ + int dummy; + char little; /* true iff machine is little endian */ } nativeendian = {1}; /* dummy structure to get native alignment requirements */ -struct cD { - char c; - union { double d; void *p; lua_Integer i; lua_Number n; } u; +struct cD +{ + char c; + + union + { + double d; + void* p; + lua_Integer i; + lua_Number n; + } u; }; #define MAXALIGN (offsetof(struct cD, u)) @@ -1139,37 +1369,48 @@ struct cD { /* ** Union for serializing floats */ -typedef union Ftypes { - float f; - double d; - lua_Number n; - char buff[5 * sizeof(lua_Number)]; /* enough for any float type */ +typedef union Ftypes +{ + float f; + double d; + lua_Number n; + char buff[5 * sizeof(lua_Number)]; /* enough for any float type */ } Ftypes; /* ** information to pack/unpack stuff */ -typedef struct Header { - lua_State *L; - int islittle; - int maxalign; +typedef struct Header +{ + lua_State* L; + int islittle; + int maxalign; } Header; /* ** options for pack/unpack */ -typedef enum KOption { - Kint, /* signed integers */ - Kuint, /* unsigned integers */ - Kfloat, /* floating-point numbers */ - Kchar, /* fixed-length strings */ - Kstring, /* strings with prefixed length */ - Kzstr, /* zero-terminated strings */ - Kpadding, /* padding */ - Kpaddalign, /* padding for alignment */ - Knop /* no-op (configuration or spaces) */ +typedef enum KOption +{ + Kint, + /* signed integers */ + Kuint, + /* unsigned integers */ + Kfloat, + /* floating-point numbers */ + Kchar, + /* fixed-length strings */ + Kstring, + /* strings with prefixed length */ + Kzstr, + /* zero-terminated strings */ + Kpadding, + /* padding */ + Kpaddalign, + /* padding for alignment */ + Knop /* no-op (configuration or spaces) */ } KOption; @@ -1177,18 +1418,22 @@ typedef enum KOption { ** Read an integer numeral from string 'fmt' or return 'df' if ** there is no numeral */ -static int digit (int c) { return '0' <= c && c <= '9'; } +static int digit(int c) { return '0' <= c && c <= '9'; } -static int getnum (const char **fmt, int df) { - if (!digit(**fmt)) /* no number? */ - return df; /* return default value */ - else { - int a = 0; - do { - a = a*10 + (*((*fmt)++) - '0'); - } while (digit(**fmt) && a <= ((int)MAXSIZE - 9)/10); - return a; - } +static int getnum(const char** fmt, int df) +{ + if (!digit(**fmt)) /* no number? */ + return df; /* return default value */ + else + { + int a = 0; + do + { + a = a * 10 + (*((*fmt)++) - '0'); + } + while (digit(**fmt) && a <= ((int)MAXSIZE - 9) / 10); + return a; + } } @@ -1196,63 +1441,87 @@ static int getnum (const char **fmt, int df) { ** Read an integer numeral and raises an error if it is larger ** than the maximum size for integers. */ -static int getnumlimit (Header *h, const char **fmt, int df) { - int sz = getnum(fmt, df); - if (sz > MAXINTSIZE || sz <= 0) - luaL_error(h->L, "integral size (%d) out of limits [1,%d]", - sz, MAXINTSIZE); - return sz; +static int getnumlimit(Header* h, const char** fmt, int df) +{ + int sz = getnum(fmt, df); + if (sz > MAXINTSIZE || sz <= 0) + luaL_error(h->L, "integral size (%d) out of limits [1,%d]", + sz, MAXINTSIZE); + return sz; } /* ** Initialize Header */ -static void initheader (lua_State *L, Header *h) { - h->L = L; - h->islittle = nativeendian.little; - h->maxalign = 1; +static void initheader(lua_State* L, Header* h) +{ + h->L = L; + h->islittle = nativeendian.little; + h->maxalign = 1; } /* ** Read and classify next option. 'size' is filled with option's size. */ -static KOption getoption (Header *h, const char **fmt, int *size) { - int opt = *((*fmt)++); - *size = 0; /* default */ - switch (opt) { - case 'b': *size = sizeof(char); return Kint; - case 'B': *size = sizeof(char); return Kuint; - case 'h': *size = sizeof(short); return Kint; - case 'H': *size = sizeof(short); return Kuint; - case 'l': *size = sizeof(long); return Kint; - case 'L': *size = sizeof(long); return Kuint; - case 'j': *size = sizeof(lua_Integer); return Kint; - case 'J': *size = sizeof(lua_Integer); return Kuint; - case 'T': *size = sizeof(size_t); return Kuint; - case 'f': *size = sizeof(float); return Kfloat; - case 'd': *size = sizeof(double); return Kfloat; - case 'n': *size = sizeof(lua_Number); return Kfloat; - case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint; - case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint; - case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring; - case 'c': - *size = getnum(fmt, -1); - if (*size == -1) - luaL_error(h->L, "missing size for format option 'c'"); - return Kchar; - case 'z': return Kzstr; - case 'x': *size = 1; return Kpadding; - case 'X': return Kpaddalign; - case ' ': break; - case '<': h->islittle = 1; break; - case '>': h->islittle = 0; break; - case '=': h->islittle = nativeendian.little; break; - case '!': h->maxalign = getnumlimit(h, fmt, MAXALIGN); break; - default: luaL_error(h->L, "invalid format option '%c'", opt); - } - return Knop; +static KOption getoption(Header* h, const char** fmt, int* size) +{ + int opt = *((*fmt)++); + *size = 0; /* default */ + switch (opt) + { + case 'b': *size = sizeof(char); + return Kint; + case 'B': *size = sizeof(char); + return Kuint; + case 'h': *size = sizeof(short); + return Kint; + case 'H': *size = sizeof(short); + return Kuint; + case 'l': *size = sizeof(long); + return Kint; + case 'L': *size = sizeof(long); + return Kuint; + case 'j': *size = sizeof(lua_Integer); + return Kint; + case 'J': *size = sizeof(lua_Integer); + return Kuint; + case 'T': *size = sizeof(size_t); + return Kuint; + case 'f': *size = sizeof(float); + return Kfloat; + case 'd': *size = sizeof(double); + return Kfloat; + case 'n': *size = sizeof(lua_Number); + return Kfloat; + case 'i': *size = getnumlimit(h, fmt, sizeof(int)); + return Kint; + case 'I': *size = getnumlimit(h, fmt, sizeof(int)); + return Kuint; + case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); + return Kstring; + case 'c': + *size = getnum(fmt, -1); + if (*size == -1) + luaL_error(h->L, "missing size for format option 'c'"); + return Kchar; + case 'z': return Kzstr; + case 'x': *size = 1; + return Kpadding; + case 'X': return Kpaddalign; + case ' ': break; + case '<': h->islittle = 1; + break; + case '>': h->islittle = 0; + break; + case '=': h->islittle = nativeendian.little; + break; + case '!': h->maxalign = getnumlimit(h, fmt, MAXALIGN); + break; + default: luaL_error(h->L, "invalid format option '%c'", opt); + } + return Knop; } @@ -1265,24 +1534,28 @@ static KOption getoption (Header *h, const char **fmt, int *size) { ** the maximum alignment ('maxalign'). Kchar option needs no alignment ** despite its size. */ -static KOption getdetails (Header *h, size_t totalsize, - const char **fmt, int *psize, int *ntoalign) { - KOption opt = getoption(h, fmt, psize); - int align = *psize; /* usually, alignment follows size */ - if (opt == Kpaddalign) { /* 'X' gets alignment from following option */ - if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0) - luaL_argerror(h->L, 1, "invalid next option for option 'X'"); - } - if (align <= 1 || opt == Kchar) /* need no alignment? */ - *ntoalign = 0; - else { - if (align > h->maxalign) /* enforce maximum alignment */ - align = h->maxalign; - if ((align & (align - 1)) != 0) /* is 'align' not a power of 2? */ - luaL_argerror(h->L, 1, "format asks for alignment not power of 2"); - *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1); - } - return opt; +static KOption getdetails(Header* h, size_t totalsize, + const char** fmt, int* psize, int* ntoalign) +{ + KOption opt = getoption(h, fmt, psize); + int align = *psize; /* usually, alignment follows size */ + if (opt == Kpaddalign) + { + /* 'X' gets alignment from following option */ + if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0) + luaL_argerror(h->L, 1, "invalid next option for option 'X'"); + } + if (align <= 1 || opt == Kchar) /* need no alignment? */ + *ntoalign = 0; + else + { + if (align > h->maxalign) /* enforce maximum alignment */ + align = h->maxalign; + if ((align & (align - 1)) != 0) /* is 'align' not a power of 2? */ + luaL_argerror(h->L, 1, "format asks for alignment not power of 2"); + *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1); + } + return opt; } @@ -1292,20 +1565,24 @@ static KOption getdetails (Header *h, size_t totalsize, ** the size of a Lua integer, correcting the extra sign-extension ** bytes if necessary (by default they would be zeros). */ -static void packint (luaL_Buffer *b, lua_Unsigned n, - int islittle, int size, int neg) { - char *buff = luaL_prepbuffsize(b, size); - int i; - buff[islittle ? 0 : size - 1] = (char)(n & MC); /* first byte */ - for (i = 1; i < size; i++) { - n >>= NB; - buff[islittle ? i : size - 1 - i] = (char)(n & MC); - } - if (neg && size > SZINT) { /* negative number need sign extension? */ - for (i = SZINT; i < size; i++) /* correct extra bytes */ - buff[islittle ? i : size - 1 - i] = (char)MC; - } - luaL_addsize(b, size); /* add result to buffer */ +static void packint(luaL_Buffer* b, lua_Unsigned n, + int islittle, int size, int neg) +{ + char* buff = luaL_prepbuffsize(b, size); + int i; + buff[islittle ? 0 : size - 1] = (char)(n & MC); /* first byte */ + for (i = 1; i < size; i++) + { + n >>= NB; + buff[islittle ? i : size - 1 - i] = (char)(n & MC); + } + if (neg && size > SZINT) + { + /* negative number need sign extension? */ + for (i = SZINT; i < size; i++) /* correct extra bytes */ + buff[islittle ? i : size - 1 - i] = (char)MC; + } + luaL_addsize(b, size); /* add result to buffer */ } @@ -1313,129 +1590,153 @@ static void packint (luaL_Buffer *b, lua_Unsigned n, ** Copy 'size' bytes from 'src' to 'dest', correcting endianness if ** given 'islittle' is different from native endianness. */ -static void copywithendian (volatile char *dest, volatile const char *src, - int size, int islittle) { - if (islittle == nativeendian.little) { - while (size-- != 0) - *(dest++) = *(src++); - } - else { - dest += size - 1; - while (size-- != 0) - *(dest--) = *(src++); - } +static void copywithendian(volatile char* dest, volatile const char* src, + int size, int islittle) +{ + if (islittle == nativeendian.little) + { + while (size-- != 0) + *(dest++) = *(src++); + } + else + { + dest += size - 1; + while (size-- != 0) + *(dest--) = *(src++); + } } -static int str_pack (lua_State *L) { - luaL_Buffer b; - Header h; - const char *fmt = luaL_checkstring(L, 1); /* format string */ - int arg = 1; /* current argument to pack */ - size_t totalsize = 0; /* accumulate total size of result */ - initheader(L, &h); - lua_pushnil(L); /* mark to separate arguments from string buffer */ - luaL_buffinit(L, &b); - while (*fmt != '\0') { - int size, ntoalign; - KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); - totalsize += ntoalign + size; - while (ntoalign-- > 0) - luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */ - arg++; - switch (opt) { - case Kint: { /* signed integers */ - lua_Integer n = luaL_checkinteger(L, arg); - if (size < SZINT) { /* need overflow check? */ - lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1); - luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow"); - } - packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0)); - break; - } - case Kuint: { /* unsigned integers */ - lua_Integer n = luaL_checkinteger(L, arg); - if (size < SZINT) /* need overflow check? */ - luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)), - arg, "unsigned overflow"); - packint(&b, (lua_Unsigned)n, h.islittle, size, 0); - break; - } - case Kfloat: { /* floating-point options */ - volatile Ftypes u; - char *buff = luaL_prepbuffsize(&b, size); - lua_Number n = luaL_checknumber(L, arg); /* get argument */ - if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */ - else if (size == sizeof(u.d)) u.d = (double)n; - else u.n = n; - /* move 'u' to final result, correcting endianness if needed */ - copywithendian(buff, u.buff, size, h.islittle); - luaL_addsize(&b, size); - break; - } - case Kchar: { /* fixed-size string */ - size_t len; - const char *s = luaL_checklstring(L, arg, &len); - luaL_argcheck(L, len <= (size_t)size, arg, - "string longer than given size"); - luaL_addlstring(&b, s, len); /* add string */ - while (len++ < (size_t)size) /* pad extra space */ - luaL_addchar(&b, LUAL_PACKPADBYTE); - break; - } - case Kstring: { /* strings with length count */ - size_t len; - const char *s = luaL_checklstring(L, arg, &len); - luaL_argcheck(L, size >= (int)sizeof(size_t) || - len < ((size_t)1 << (size * NB)), - arg, "string length does not fit in given size"); - packint(&b, (lua_Unsigned)len, h.islittle, size, 0); /* pack length */ - luaL_addlstring(&b, s, len); - totalsize += len; - break; - } - case Kzstr: { /* zero-terminated string */ - size_t len; - const char *s = luaL_checklstring(L, arg, &len); - luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros"); - luaL_addlstring(&b, s, len); - luaL_addchar(&b, '\0'); /* add zero at the end */ - totalsize += len + 1; - break; - } - case Kpadding: luaL_addchar(&b, LUAL_PACKPADBYTE); /* FALLTHROUGH */ - case Kpaddalign: case Knop: - arg--; /* undo increment */ - break; - } - } - luaL_pushresult(&b); - return 1; +static int str_pack(lua_State* L) +{ + luaL_Buffer b; + Header h; + const char* fmt = luaL_checkstring(L, 1); /* format string */ + int arg = 1; /* current argument to pack */ + size_t totalsize = 0; /* accumulate total size of result */ + initheader(L, &h); + lua_pushnil(L); /* mark to separate arguments from string buffer */ + luaL_buffinit(L, &b); + while (*fmt != '\0') + { + int size, ntoalign; + KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); + totalsize += ntoalign + size; + while (ntoalign-- > 0) + luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */ + arg++; + switch (opt) + { + case Kint: + { + /* signed integers */ + lua_Integer n = luaL_checkinteger(L, arg); + if (size < SZINT) + { + /* need overflow check? */ + lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1); + luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow"); + } + packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0)); + break; + } + case Kuint: + { + /* unsigned integers */ + lua_Integer n = luaL_checkinteger(L, arg); + if (size < SZINT) /* need overflow check? */ + luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)), + arg, "unsigned overflow"); + packint(&b, (lua_Unsigned)n, h.islittle, size, 0); + break; + } + case Kfloat: + { + /* floating-point options */ + volatile Ftypes u; + char* buff = luaL_prepbuffsize(&b, size); + lua_Number n = luaL_checknumber(L, arg); /* get argument */ + if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */ + else if (size == sizeof(u.d)) u.d = (double)n; + else u.n = n; + /* move 'u' to final result, correcting endianness if needed */ + copywithendian(buff, u.buff, size, h.islittle); + luaL_addsize(&b, size); + break; + } + case Kchar: + { + /* fixed-size string */ + size_t len; + const char* s = luaL_checklstring(L, arg, &len); + luaL_argcheck(L, len <= (size_t)size, arg, + "string longer than given size"); + luaL_addlstring(&b, s, len); /* add string */ + while (len++ < (size_t)size) /* pad extra space */ + luaL_addchar(&b, LUAL_PACKPADBYTE); + break; + } + case Kstring: + { + /* strings with length count */ + size_t len; + const char* s = luaL_checklstring(L, arg, &len); + luaL_argcheck(L, size >= (int)sizeof(size_t) || + len < ((size_t)1 << (size * NB)), + arg, "string length does not fit in given size"); + packint(&b, (lua_Unsigned)len, h.islittle, size, 0); /* pack length */ + luaL_addlstring(&b, s, len); + totalsize += len; + break; + } + case Kzstr: + { + /* zero-terminated string */ + size_t len; + const char* s = luaL_checklstring(L, arg, &len); + luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros"); + luaL_addlstring(&b, s, len); + luaL_addchar(&b, '\0'); /* add zero at the end */ + totalsize += len + 1; + break; + } + case Kpadding: luaL_addchar(&b, LUAL_PACKPADBYTE); /* FALLTHROUGH */ + case Kpaddalign: + case Knop: + arg--; /* undo increment */ + break; + } + } + luaL_pushresult(&b); + return 1; } -static int str_packsize (lua_State *L) { - Header h; - const char *fmt = luaL_checkstring(L, 1); /* format string */ - size_t totalsize = 0; /* accumulate total size of result */ - initheader(L, &h); - while (*fmt != '\0') { - int size, ntoalign; - KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); - size += ntoalign; /* total space used by option */ - luaL_argcheck(L, totalsize <= MAXSIZE - size, 1, - "format result too large"); - totalsize += size; - switch (opt) { - case Kstring: /* strings with length count */ - case Kzstr: /* zero-terminated string */ - luaL_argerror(L, 1, "variable-length format"); - /* call never return, but to avoid warnings: *//* FALLTHROUGH */ - default: break; - } - } - lua_pushinteger(L, (lua_Integer)totalsize); - return 1; +static int str_packsize(lua_State* L) +{ + Header h; + const char* fmt = luaL_checkstring(L, 1); /* format string */ + size_t totalsize = 0; /* accumulate total size of result */ + initheader(L, &h); + while (*fmt != '\0') + { + int size, ntoalign; + KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); + size += ntoalign; /* total space used by option */ + luaL_argcheck(L, totalsize <= MAXSIZE - size, 1, + "format result too large"); + totalsize += size; + switch (opt) + { + case Kstring: /* strings with length count */ + case Kzstr: /* zero-terminated string */ + luaL_argerror(L, 1, "variable-length format"); + /* call never return, but to avoid warnings: */ /* FALLTHROUGH */ + default: break; + } + } + lua_pushinteger(L, (lua_Integer)totalsize); + return 1; } @@ -1447,138 +1748,158 @@ static int str_packsize (lua_State *L) { ** it must check the unread bytes to see whether they do not cause an ** overflow. */ -static lua_Integer unpackint (lua_State *L, const char *str, - int islittle, int size, int issigned) { - lua_Unsigned res = 0; - int i; - int limit = (size <= SZINT) ? size : SZINT; - for (i = limit - 1; i >= 0; i--) { - res <<= NB; - res |= (lua_Unsigned)(unsigned char)str[islittle ? i : size - 1 - i]; - } - if (size < SZINT) { /* real size smaller than lua_Integer? */ - if (issigned) { /* needs sign extension? */ - lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1); - res = ((res ^ mask) - mask); /* do sign extension */ - } - } - else if (size > SZINT) { /* must check unread bytes */ - int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC; - for (i = limit; i < size; i++) { - if ((unsigned char)str[islittle ? i : size - 1 - i] != mask) - luaL_error(L, "%d-byte integer does not fit into Lua Integer", size); - } - } - return (lua_Integer)res; +static lua_Integer unpackint(lua_State* L, const char* str, + int islittle, int size, int issigned) +{ + lua_Unsigned res = 0; + int i; + int limit = (size <= SZINT) ? size : SZINT; + for (i = limit - 1; i >= 0; i--) + { + res <<= NB; + res |= (lua_Unsigned)(unsigned char)str[islittle ? i : size - 1 - i]; + } + if (size < SZINT) + { + /* real size smaller than lua_Integer? */ + if (issigned) + { + /* needs sign extension? */ + lua_Unsigned mask = (lua_Unsigned)1 << (size * NB - 1); + res = ((res ^ mask) - mask); /* do sign extension */ + } + } + else if (size > SZINT) + { + /* must check unread bytes */ + int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC; + for (i = limit; i < size; i++) + { + if ((unsigned char)str[islittle ? i : size - 1 - i] != mask) + luaL_error(L, "%d-byte integer does not fit into Lua Integer", size); + } + } + return (lua_Integer)res; } -static int str_unpack (lua_State *L) { - Header h; - const char *fmt = luaL_checkstring(L, 1); - size_t ld; - const char *data = luaL_checklstring(L, 2, &ld); - size_t pos = (size_t)posrelat(luaL_optinteger(L, 3, 1), ld) - 1; - int n = 0; /* number of results */ - luaL_argcheck(L, pos <= ld, 3, "initial position out of string"); - initheader(L, &h); - while (*fmt != '\0') { - int size, ntoalign; - KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign); - if ((size_t)ntoalign + size > ~pos || pos + ntoalign + size > ld) - luaL_argerror(L, 2, "data string too short"); - pos += ntoalign; /* skip alignment */ - /* stack space for item + next position */ - luaL_checkstack(L, 2, "too many results"); - n++; - switch (opt) { - case Kint: - case Kuint: { - lua_Integer res = unpackint(L, data + pos, h.islittle, size, - (opt == Kint)); - lua_pushinteger(L, res); - break; - } - case Kfloat: { - volatile Ftypes u; - lua_Number num; - copywithendian(u.buff, data + pos, size, h.islittle); - if (size == sizeof(u.f)) num = (lua_Number)u.f; - else if (size == sizeof(u.d)) num = (lua_Number)u.d; - else num = u.n; - lua_pushnumber(L, num); - break; - } - case Kchar: { - lua_pushlstring(L, data + pos, size); - break; - } - case Kstring: { - size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0); - luaL_argcheck(L, pos + len + size <= ld, 2, "data string too short"); - lua_pushlstring(L, data + pos + size, len); - pos += len; /* skip string */ - break; - } - case Kzstr: { - size_t len = (int)strlen(data + pos); - lua_pushlstring(L, data + pos, len); - pos += len + 1; /* skip string plus final '\0' */ - break; - } - case Kpaddalign: case Kpadding: case Knop: - n--; /* undo increment */ - break; - } - pos += size; - } - lua_pushinteger(L, pos + 1); /* next position */ - return n + 1; +static int str_unpack(lua_State* L) +{ + Header h; + const char* fmt = luaL_checkstring(L, 1); + size_t ld; + const char* data = luaL_checklstring(L, 2, &ld); + size_t pos = (size_t)posrelat(luaL_optinteger(L, 3, 1), ld) - 1; + int n = 0; /* number of results */ + luaL_argcheck(L, pos <= ld, 3, "initial position out of string"); + initheader(L, &h); + while (*fmt != '\0') + { + int size, ntoalign; + KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign); + if ((size_t)ntoalign + size > ~pos || pos + ntoalign + size > ld) + luaL_argerror(L, 2, "data string too short"); + pos += ntoalign; /* skip alignment */ + /* stack space for item + next position */ + luaL_checkstack(L, 2, "too many results"); + n++; + switch (opt) + { + case Kint: + case Kuint: + { + lua_Integer res = unpackint(L, data + pos, h.islittle, size, + (opt == Kint)); + lua_pushinteger(L, res); + break; + } + case Kfloat: + { + volatile Ftypes u; + lua_Number num; + copywithendian(u.buff, data + pos, size, h.islittle); + if (size == sizeof(u.f)) num = (lua_Number)u.f; + else if (size == sizeof(u.d)) num = (lua_Number)u.d; + else num = u.n; + lua_pushnumber(L, num); + break; + } + case Kchar: + { + lua_pushlstring(L, data + pos, size); + break; + } + case Kstring: + { + size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0); + luaL_argcheck(L, pos + len + size <= ld, 2, "data string too short"); + lua_pushlstring(L, data + pos + size, len); + pos += len; /* skip string */ + break; + } + case Kzstr: + { + size_t len = (int)strlen(data + pos); + lua_pushlstring(L, data + pos, len); + pos += len + 1; /* skip string plus final '\0' */ + break; + } + case Kpaddalign: + case Kpadding: + case Knop: + n--; /* undo increment */ + break; + } + pos += size; + } + lua_pushinteger(L, pos + 1); /* next position */ + return n + 1; } /* }====================================================== */ static const luaL_Reg strlib[] = { - {"byte", str_byte}, - {"char", str_char}, - {"dump", str_dump}, - {"find", str_find}, - {"format", str_format}, - {"gmatch", gmatch}, - {"gsub", str_gsub}, - {"len", str_len}, - {"lower", str_lower}, - {"match", str_match}, - {"rep", str_rep}, - {"reverse", str_reverse}, - {"sub", str_sub}, - {"upper", str_upper}, - {"pack", str_pack}, - {"packsize", str_packsize}, - {"unpack", str_unpack}, - {NULL, NULL} + {"byte", str_byte}, + {"char", str_char}, + {"dump", str_dump}, + {"find", str_find}, + {"format", str_format}, + {"gmatch", gmatch}, + {"gsub", str_gsub}, + {"len", str_len}, + {"lower", str_lower}, + {"match", str_match}, + {"rep", str_rep}, + {"reverse", str_reverse}, + {"sub", str_sub}, + {"upper", str_upper}, + {"pack", str_pack}, + {"packsize", str_packsize}, + {"unpack", str_unpack}, + {NULL, NULL} }; -static void createmetatable (lua_State *L) { - lua_createtable(L, 0, 1); /* table to be metatable for strings */ - lua_pushliteral(L, ""); /* dummy string */ - lua_pushvalue(L, -2); /* copy table */ - lua_setmetatable(L, -2); /* set table as metatable for strings */ - lua_pop(L, 1); /* pop dummy string */ - lua_pushvalue(L, -2); /* get string library */ - lua_setfield(L, -2, "__index"); /* metatable.__index = string */ - lua_pop(L, 1); /* pop metatable */ +static void createmetatable(lua_State* L) +{ + lua_createtable(L, 0, 1); /* table to be metatable for strings */ + lua_pushliteral(L, ""); /* dummy string */ + lua_pushvalue(L, -2); /* copy table */ + lua_setmetatable(L, -2); /* set table as metatable for strings */ + lua_pop(L, 1); /* pop dummy string */ + lua_pushvalue(L, -2); /* get string library */ + lua_setfield(L, -2, "__index"); /* metatable.__index = string */ + lua_pop(L, 1); /* pop metatable */ } /* ** Open string library */ -LUAMOD_API int luaopen_string (lua_State *L) { - luaL_newlib(L, strlib); - createmetatable(L); - return 1; +LUAMOD_API int luaopen_string(lua_State* L) +{ + luaL_newlib(L, strlib); + createmetatable(L); + return 1; } - diff --git a/Lua/ltable.c b/Lua/ltable.c index d080189..1ae8598 100644 --- a/Lua/ltable.c +++ b/Lua/ltable.c @@ -75,8 +75,8 @@ #define dummynode (&dummynode_) static const Node dummynode_ = { - {NILCONSTANT}, /* value */ - {{NILCONSTANT, 0}} /* key */ + {NILCONSTANT}, /* value */ + {{NILCONSTANT, 0}} /* key */ }; @@ -94,18 +94,23 @@ static const Node dummynode_ = { ** INT_MIN. */ #if !defined(l_hashfloat) -static int l_hashfloat (lua_Number n) { - int i; - lua_Integer ni; - n = l_mathop(frexp)(n, &i) * -cast_num(INT_MIN); - if (!lua_numbertointeger(n, &ni)) { /* is 'n' inf/-inf/NaN? */ - lua_assert(luai_numisnan(n) || l_mathop(fabs)(n) == cast_num(HUGE_VAL)); - return 0; - } - else { /* normal case */ - unsigned int u = cast(unsigned int, i) + cast(unsigned int, ni); - return cast_int(u <= cast(unsigned int, INT_MAX) ? u : ~u); - } +static int l_hashfloat(lua_Number n) +{ + int i; + lua_Integer ni; + n = l_mathop(frexp)(n, &i) * -cast_num(INT_MIN); + if (!lua_numbertointeger(n, &ni)) + { + /* is 'n' inf/-inf/NaN? */ + lua_assert(luai_numisnan(n) || l_mathop(fabs)(n) == cast_num(HUGE_VAL)); + return 0; + } + else + { + /* normal case */ + unsigned int u = cast(unsigned int, i) + cast(unsigned int, ni); + return cast_int(u <= cast(unsigned int, INT_MAX) ? u : ~u); + } } #endif @@ -114,26 +119,28 @@ static int l_hashfloat (lua_Number n) { ** returns the 'main' position of an element in a table (that is, the index ** of its hash value) */ -static Node *mainposition (const Table *t, const TValue *key) { - switch (ttype(key)) { - case LUA_TNUMINT: - return hashint(t, ivalue(key)); - case LUA_TNUMFLT: - return hashmod(t, l_hashfloat(fltvalue(key))); - case LUA_TSHRSTR: - return hashstr(t, tsvalue(key)); - case LUA_TLNGSTR: - return hashpow2(t, luaS_hashlongstr(tsvalue(key))); - case LUA_TBOOLEAN: - return hashboolean(t, bvalue(key)); - case LUA_TLIGHTUSERDATA: - return hashpointer(t, pvalue(key)); - case LUA_TLCF: - return hashpointer(t, fvalue(key)); - default: - lua_assert(!ttisdeadkey(key)); - return hashpointer(t, gcvalue(key)); - } +static Node* mainposition(const Table* t, const TValue* key) +{ + switch (ttype(key)) + { + case LUA_TNUMINT: + return hashint(t, ivalue(key)); + case LUA_TNUMFLT: + return hashmod(t, l_hashfloat(fltvalue(key))); + case LUA_TSHRSTR: + return hashstr(t, tsvalue(key)); + case LUA_TLNGSTR: + return hashpow2(t, luaS_hashlongstr(tsvalue(key))); + case LUA_TBOOLEAN: + return hashboolean(t, bvalue(key)); + case LUA_TLIGHTUSERDATA: + return hashpointer(t, pvalue(key)); + case LUA_TLCF: + return hashpointer(t, fvalue(key)); + default: + lua_assert(!ttisdeadkey(key)); + return hashpointer(t, gcvalue(key)); + } } @@ -141,13 +148,15 @@ static Node *mainposition (const Table *t, const TValue *key) { ** returns the index for 'key' if 'key' is an appropriate key to live in ** the array part of the table, 0 otherwise. */ -static unsigned int arrayindex (const TValue *key) { - if (ttisinteger(key)) { - lua_Integer k = ivalue(key); - if (0 < k && (lua_Unsigned)k <= MAXASIZE) - return cast(unsigned int, k); /* 'key' is an appropriate array index */ - } - return 0; /* 'key' did not match some condition */ +static unsigned int arrayindex(const TValue* key) +{ + if (ttisinteger(key)) + { + lua_Integer k = ivalue(key); + if (0 < k && (lua_Unsigned)k <= MAXASIZE) + return cast(unsigned int, k); /* 'key' is an appropriate array index */ + } + return 0; /* 'key' did not match some condition */ } @@ -156,50 +165,64 @@ static unsigned int arrayindex (const TValue *key) { ** elements in the array part, then elements in the hash part. The ** beginning of a traversal is signaled by 0. */ -static unsigned int findindex (lua_State *L, Table *t, StkId key) { - unsigned int i; - if (ttisnil(key)) return 0; /* first iteration */ - i = arrayindex(key); - if (i != 0 && i <= t->sizearray) /* is 'key' inside array part? */ - return i; /* yes; that's the index */ - else { - int nx; - Node *n = mainposition(t, key); - for (;;) { /* check whether 'key' is somewhere in the chain */ - /* key may be dead already, but it is ok to use it in 'next' */ - if (luaV_rawequalobj(gkey(n), key) || - (ttisdeadkey(gkey(n)) && iscollectable(key) && - deadvalue(gkey(n)) == gcvalue(key))) { - i = cast_int(n - gnode(t, 0)); /* key index in hash table */ - /* hash elements are numbered after array ones */ - return (i + 1) + t->sizearray; - } - nx = gnext(n); - if (nx == 0) - luaG_runerror(L, "invalid key to 'next'"); /* key not found */ - else n += nx; - } - } +static unsigned int findindex(lua_State* L, Table* t, StkId key) +{ + unsigned int i; + if (ttisnil(key)) return 0; /* first iteration */ + i = arrayindex(key); + if (i != 0 && i <= t->sizearray) /* is 'key' inside array part? */ + return i; /* yes; that's the index */ + else + { + int nx; + Node* n = mainposition(t, key); + for (;;) + { + /* check whether 'key' is somewhere in the chain */ + /* key may be dead already, but it is ok to use it in 'next' */ + if (luaV_rawequalobj(gkey(n), key) || + (ttisdeadkey(gkey(n)) && iscollectable(key) && + deadvalue(gkey(n)) == gcvalue(key))) + { + i = cast_int(n - gnode(t, 0)); /* key index in hash table */ + /* hash elements are numbered after array ones */ + return (i + 1) + t->sizearray; + } + nx = gnext(n); + if (nx == 0) + luaG_runerror(L, "invalid key to 'next'"); /* key not found */ + else n += nx; + } + } } -int luaH_next (lua_State *L, Table *t, StkId key) { - unsigned int i = findindex(L, t, key); /* find original element */ - for (; i < t->sizearray; i++) { /* try first array part */ - if (!ttisnil(&t->array[i])) { /* a non-nil value? */ - setivalue(key, i + 1); - setobj2s(L, key+1, &t->array[i]); - return 1; - } - } - for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */ - if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ - setobj2s(L, key, gkey(gnode(t, i))); - setobj2s(L, key+1, gval(gnode(t, i))); - return 1; - } - } - return 0; /* no more elements */ +int luaH_next(lua_State* L, Table* t, StkId key) +{ + unsigned int i = findindex(L, t, key); /* find original element */ + for (; i < t->sizearray; i++) + { + /* try first array part */ + if (!ttisnil(&t->array[i])) + { + /* a non-nil value? */ + setivalue(key, i + 1); + setobj2s(L, key+1, &t->array[i]); + return 1; + } + } + for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) + { + /* hash part */ + if (!ttisnil(gval(gnode(t, i)))) + { + /* a non-nil value? */ + setobj2s(L, key, gkey(gnode(t, i))); + setobj2s(L, key+1, gval(gnode(t, i))); + return 1; + } + } + return 0; /* no more elements */ } @@ -216,36 +239,44 @@ int luaH_next (lua_State *L, Table *t, StkId key) { ** integer keys in the table and leaves with the number of keys that ** will go to the array part; return the optimal size. */ -static unsigned int computesizes (unsigned int nums[], unsigned int *pna) { - int i; - unsigned int twotoi; /* 2^i (candidate for optimal size) */ - unsigned int a = 0; /* number of elements smaller than 2^i */ - unsigned int na = 0; /* number of elements to go to array part */ - unsigned int optimal = 0; /* optimal size for array part */ - /* loop while keys can fill more than half of total size */ - for (i = 0, twotoi = 1; *pna > twotoi / 2; i++, twotoi *= 2) { - if (nums[i] > 0) { - a += nums[i]; - if (a > twotoi/2) { /* more than half elements present? */ - optimal = twotoi; /* optimal size (till now) */ - na = a; /* all elements up to 'optimal' will go to array part */ - } - } - } - lua_assert((optimal == 0 || optimal / 2 < na) && na <= optimal); - *pna = na; - return optimal; +static unsigned int computesizes(unsigned int nums[], unsigned int* pna) +{ + int i; + unsigned int twotoi; /* 2^i (candidate for optimal size) */ + unsigned int a = 0; /* number of elements smaller than 2^i */ + unsigned int na = 0; /* number of elements to go to array part */ + unsigned int optimal = 0; /* optimal size for array part */ + /* loop while keys can fill more than half of total size */ + for (i = 0, twotoi = 1; *pna > twotoi / 2; i++, twotoi *= 2) + { + if (nums[i] > 0) + { + a += nums[i]; + if (a > twotoi / 2) + { + /* more than half elements present? */ + optimal = twotoi; /* optimal size (till now) */ + na = a; /* all elements up to 'optimal' will go to array part */ + } + } + } + lua_assert((optimal == 0 || optimal / 2 < na) && na <= optimal); + *pna = na; + return optimal; } -static int countint (const TValue *key, unsigned int *nums) { - unsigned int k = arrayindex(key); - if (k != 0) { /* is 'key' an appropriate array index? */ - nums[luaO_ceillog2(k)]++; /* count as such */ - return 1; - } - else - return 0; +static int countint(const TValue* key, unsigned int* nums) +{ + unsigned int k = arrayindex(key); + if (k != 0) + { + /* is 'key' an appropriate array index? */ + nums[luaO_ceillog2(k)]++; /* count as such */ + return 1; + } + else + return 0; } @@ -254,184 +285,208 @@ static int countint (const TValue *key, unsigned int *nums) { ** number of keys that will go into corresponding slice and return ** total number of non-nil keys. */ -static unsigned int numusearray (const Table *t, unsigned int *nums) { - int lg; - unsigned int ttlg; /* 2^lg */ - unsigned int ause = 0; /* summation of 'nums' */ - unsigned int i = 1; /* count to traverse all array keys */ - /* traverse each slice */ - for (lg = 0, ttlg = 1; lg <= MAXABITS; lg++, ttlg *= 2) { - unsigned int lc = 0; /* counter */ - unsigned int lim = ttlg; - if (lim > t->sizearray) { - lim = t->sizearray; /* adjust upper limit */ - if (i > lim) - break; /* no more elements to count */ - } - /* count elements in range (2^(lg - 1), 2^lg] */ - for (; i <= lim; i++) { - if (!ttisnil(&t->array[i-1])) - lc++; - } - nums[lg] += lc; - ause += lc; - } - return ause; +static unsigned int numusearray(const Table* t, unsigned int* nums) +{ + int lg; + unsigned int ttlg; /* 2^lg */ + unsigned int ause = 0; /* summation of 'nums' */ + unsigned int i = 1; /* count to traverse all array keys */ + /* traverse each slice */ + for (lg = 0, ttlg = 1; lg <= MAXABITS; lg++, ttlg *= 2) + { + unsigned int lc = 0; /* counter */ + unsigned int lim = ttlg; + if (lim > t->sizearray) + { + lim = t->sizearray; /* adjust upper limit */ + if (i > lim) + break; /* no more elements to count */ + } + /* count elements in range (2^(lg - 1), 2^lg] */ + for (; i <= lim; i++) + { + if (!ttisnil(&t->array[i-1])) + lc++; + } + nums[lg] += lc; + ause += lc; + } + return ause; } -static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) { - int totaluse = 0; /* total number of elements */ - int ause = 0; /* elements added to 'nums' (can go to array part) */ - int i = sizenode(t); - while (i--) { - Node *n = &t->node[i]; - if (!ttisnil(gval(n))) { - ause += countint(gkey(n), nums); - totaluse++; - } - } - *pna += ause; - return totaluse; +static int numusehash(const Table* t, unsigned int* nums, unsigned int* pna) +{ + int totaluse = 0; /* total number of elements */ + int ause = 0; /* elements added to 'nums' (can go to array part) */ + int i = sizenode(t); + while (i--) + { + Node* n = &t->node[i]; + if (!ttisnil(gval(n))) + { + ause += countint(gkey(n), nums); + totaluse++; + } + } + *pna += ause; + return totaluse; } -static void setarrayvector (lua_State *L, Table *t, unsigned int size) { - unsigned int i; - luaM_reallocvector(L, t->array, t->sizearray, size, TValue); - for (i=t->sizearray; iarray[i]); - t->sizearray = size; +static void setarrayvector(lua_State* L, Table* t, unsigned int size) +{ + unsigned int i; + luaM_reallocvector(L, t->array, t->sizearray, size, TValue); + for (i = t->sizearray; i < size; i++) + setnilvalue(&t->array[i]); + t->sizearray = size; } -static void setnodevector (lua_State *L, Table *t, unsigned int size) { - if (size == 0) { /* no elements to hash part? */ - t->node = cast(Node *, dummynode); /* use common 'dummynode' */ - t->lsizenode = 0; - t->lastfree = NULL; /* signal that it is using dummy node */ - } - else { - int i; - int lsize = luaO_ceillog2(size); - if (lsize > MAXHBITS) - luaG_runerror(L, "table overflow"); - size = twoto(lsize); - t->node = luaM_newvector(L, size, Node); - for (i = 0; i < (int)size; i++) { - Node *n = gnode(t, i); - gnext(n) = 0; - setnilvalue(wgkey(n)); - setnilvalue(gval(n)); - } - t->lsizenode = cast_byte(lsize); - t->lastfree = gnode(t, size); /* all positions are free */ - } +static void setnodevector(lua_State* L, Table* t, unsigned int size) +{ + if (size == 0) + { + /* no elements to hash part? */ + t->node = cast(Node *, dummynode); /* use common 'dummynode' */ + t->lsizenode = 0; + t->lastfree = NULL; /* signal that it is using dummy node */ + } + else + { + int i; + int lsize = luaO_ceillog2(size); + if (lsize > MAXHBITS) + luaG_runerror(L, "table overflow"); + size = twoto(lsize); + t->node = luaM_newvector(L, size, Node); + for (i = 0; i < (int)size; i++) + { + Node* n = gnode(t, i); + gnext(n) = 0; + setnilvalue(wgkey(n)); + setnilvalue(gval(n)); + } + t->lsizenode = cast_byte(lsize); + t->lastfree = gnode(t, size); /* all positions are free */ + } } -void luaH_resize (lua_State *L, Table *t, unsigned int nasize, - unsigned int nhsize) { - unsigned int i; - int j; - unsigned int oldasize = t->sizearray; - int oldhsize = allocsizenode(t); - Node *nold = t->node; /* save old hash ... */ - if (nasize > oldasize) /* array part must grow? */ - setarrayvector(L, t, nasize); - /* create new hash part with appropriate size */ - setnodevector(L, t, nhsize); - if (nasize < oldasize) { /* array part must shrink? */ - t->sizearray = nasize; - /* re-insert elements from vanishing slice */ - for (i=nasize; iarray[i])) - luaH_setint(L, t, i + 1, &t->array[i]); - } - /* shrink array */ - luaM_reallocvector(L, t->array, oldasize, nasize, TValue); - } - /* re-insert elements from hash part */ - for (j = oldhsize - 1; j >= 0; j--) { - Node *old = nold + j; - if (!ttisnil(gval(old))) { - /* doesn't need barrier/invalidate cache, as entry was - already present in the table */ - setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old)); - } - } - if (oldhsize > 0) /* not the dummy node? */ - luaM_freearray(L, nold, cast(size_t, oldhsize)); /* free old hash */ +void luaH_resize(lua_State* L, Table* t, unsigned int nasize, + unsigned int nhsize) +{ + unsigned int i; + int j; + unsigned int oldasize = t->sizearray; + int oldhsize = allocsizenode(t); + Node* nold = t->node; /* save old hash ... */ + if (nasize > oldasize) /* array part must grow? */ + setarrayvector(L, t, nasize); + /* create new hash part with appropriate size */ + setnodevector(L, t, nhsize); + if (nasize < oldasize) + { + /* array part must shrink? */ + t->sizearray = nasize; + /* re-insert elements from vanishing slice */ + for (i = nasize; i < oldasize; i++) + { + if (!ttisnil(&t->array[i])) + luaH_setint(L, t, i + 1, &t->array[i]); + } + /* shrink array */ + luaM_reallocvector(L, t->array, oldasize, nasize, TValue); + } + /* re-insert elements from hash part */ + for (j = oldhsize - 1; j >= 0; j--) + { + Node* old = nold + j; + if (!ttisnil(gval(old))) + { + /* doesn't need barrier/invalidate cache, as entry was + already present in the table */ + setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old)); + } + } + if (oldhsize > 0) /* not the dummy node? */ + luaM_freearray(L, nold, cast(size_t, oldhsize)); /* free old hash */ } -void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize) { - int nsize = allocsizenode(t); - luaH_resize(L, t, nasize, nsize); +void luaH_resizearray(lua_State* L, Table* t, unsigned int nasize) +{ + int nsize = allocsizenode(t); + luaH_resize(L, t, nasize, nsize); } /* ** nums[i] = number of keys 'k' where 2^(i - 1) < k <= 2^i */ -static void rehash (lua_State *L, Table *t, const TValue *ek) { - unsigned int asize; /* optimal size for array part */ - unsigned int na; /* number of keys in the array part */ - unsigned int nums[MAXABITS + 1]; - int i; - int totaluse; - for (i = 0; i <= MAXABITS; i++) nums[i] = 0; /* reset counts */ - na = numusearray(t, nums); /* count keys in array part */ - totaluse = na; /* all those keys are integer keys */ - totaluse += numusehash(t, nums, &na); /* count keys in hash part */ - /* count extra key */ - na += countint(ek, nums); - totaluse++; - /* compute new size for array part */ - asize = computesizes(nums, &na); - /* resize the table to new computed sizes */ - luaH_resize(L, t, asize, totaluse - na); +static void rehash(lua_State* L, Table* t, const TValue* ek) +{ + unsigned int asize; /* optimal size for array part */ + unsigned int na; /* number of keys in the array part */ + unsigned int nums[MAXABITS + 1]; + int i; + int totaluse; + for (i = 0; i <= MAXABITS; i++) nums[i] = 0; /* reset counts */ + na = numusearray(t, nums); /* count keys in array part */ + totaluse = na; /* all those keys are integer keys */ + totaluse += numusehash(t, nums, &na); /* count keys in hash part */ + /* count extra key */ + na += countint(ek, nums); + totaluse++; + /* compute new size for array part */ + asize = computesizes(nums, &na); + /* resize the table to new computed sizes */ + luaH_resize(L, t, asize, totaluse - na); } - /* ** }============================================================= */ -Table *luaH_new (lua_State *L) { - GCObject *o = luaC_newobj(L, LUA_TTABLE, sizeof(Table)); - Table *t = gco2t(o); - t->metatable = NULL; - t->flags = cast_byte(~0); - t->array = NULL; - t->sizearray = 0; - setnodevector(L, t, 0); - return t; +Table* luaH_new(lua_State* L) +{ + GCObject* o = luaC_newobj(L, LUA_TTABLE, sizeof(Table)); + Table* t = gco2t(o); + t->metatable = NULL; + t->flags = cast_byte(~0); + t->array = NULL; + t->sizearray = 0; + setnodevector(L, t, 0); + return t; } -void luaH_free (lua_State *L, Table *t) { - if (!isdummy(t)) - luaM_freearray(L, t->node, cast(size_t, sizenode(t))); - luaM_freearray(L, t->array, t->sizearray); - luaM_free(L, t); +void luaH_free(lua_State* L, Table* t) +{ + if (!isdummy(t)) + luaM_freearray(L, t->node, cast(size_t, sizenode(t))); + luaM_freearray(L, t->array, t->sizearray); + luaM_free(L, t); } -static Node *getfreepos (Table *t) { - if (!isdummy(t)) { - while (t->lastfree > t->node) { - t->lastfree--; - if (ttisnil(gkey(t->lastfree))) - return t->lastfree; - } - } - return NULL; /* could not find a free place */ +static Node* getfreepos(Table* t) +{ + if (!isdummy(t)) + { + while (t->lastfree > t->node) + { + t->lastfree--; + if (ttisnil(gkey(t->lastfree))) + return t->lastfree; + } + } + return NULL; /* could not find a free place */ } - /* ** inserts a new key into a hash table; first, check whether key's main ** position is free. If not, check whether colliding node is in its main @@ -439,98 +494,121 @@ static Node *getfreepos (Table *t) { ** put new key in its main position; otherwise (colliding node is in its main ** position), new key goes to an empty position. */ -TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { - Node *mp; - TValue aux; - if (ttisnil(key)) luaG_runerror(L, "table index is nil"); - else if (ttisfloat(key)) { - lua_Integer k; - if (luaV_tointeger(key, &k, 0)) { /* does index fit in an integer? */ - setivalue(&aux, k); - key = &aux; /* insert it as an integer */ - } - else if (luai_numisnan(fltvalue(key))) - luaG_runerror(L, "table index is NaN"); - } - mp = mainposition(t, key); - if (!ttisnil(gval(mp)) || isdummy(t)) { /* main position is taken? */ - Node *othern; - Node *f = getfreepos(t); /* get a free place */ - if (f == NULL) { /* cannot find a free place? */ - rehash(L, t, key); /* grow table */ - /* whatever called 'newkey' takes care of TM cache */ - return luaH_set(L, t, key); /* insert key into grown table */ - } - lua_assert(!isdummy(t)); - othern = mainposition(t, gkey(mp)); - if (othern != mp) { /* is colliding node out of its main position? */ - /* yes; move colliding node into free position */ - while (othern + gnext(othern) != mp) /* find previous */ - othern += gnext(othern); - gnext(othern) = cast_int(f - othern); /* rechain to point to 'f' */ - *f = *mp; /* copy colliding node into free pos. (mp->next also goes) */ - if (gnext(mp) != 0) { - gnext(f) += cast_int(mp - f); /* correct 'next' */ - gnext(mp) = 0; /* now 'mp' is free */ - } - setnilvalue(gval(mp)); - } - else { /* colliding node is in its own main position */ - /* new node will go into free position */ - if (gnext(mp) != 0) - gnext(f) = cast_int((mp + gnext(mp)) - f); /* chain new position */ - else lua_assert(gnext(f) == 0); - gnext(mp) = cast_int(f - mp); - mp = f; - } - } - setnodekey(L, &mp->i_key, key); - luaC_barrierback(L, t, key); - lua_assert(ttisnil(gval(mp))); - return gval(mp); +TValue* luaH_newkey(lua_State* L, Table* t, const TValue* key) +{ + Node* mp; + TValue aux; + if (ttisnil(key)) luaG_runerror(L, "table index is nil"); + else if (ttisfloat(key)) + { + lua_Integer k; + if (luaV_tointeger(key, &k, 0)) + { + /* does index fit in an integer? */ + setivalue(&aux, k); + key = &aux; /* insert it as an integer */ + } + else if (luai_numisnan(fltvalue(key))) + luaG_runerror(L, "table index is NaN"); + } + mp = mainposition(t, key); + if (!ttisnil(gval(mp)) || isdummy(t)) + { + /* main position is taken? */ + Node* othern; + Node* f = getfreepos(t); /* get a free place */ + if (f == NULL) + { + /* cannot find a free place? */ + rehash(L, t, key); /* grow table */ + /* whatever called 'newkey' takes care of TM cache */ + return luaH_set(L, t, key); /* insert key into grown table */ + } + lua_assert(!isdummy(t)); + othern = mainposition(t, gkey(mp)); + if (othern != mp) + { + /* is colliding node out of its main position? */ + /* yes; move colliding node into free position */ + while (othern + gnext(othern) != mp) /* find previous */ + othern += gnext(othern); + gnext(othern) = cast_int(f - othern); /* rechain to point to 'f' */ + *f = *mp; /* copy colliding node into free pos. (mp->next also goes) */ + if (gnext(mp) != 0) + { + gnext(f) += cast_int(mp - f); /* correct 'next' */ + gnext(mp) = 0; /* now 'mp' is free */ + } + setnilvalue(gval(mp)); + } + else + { + /* colliding node is in its own main position */ + /* new node will go into free position */ + if (gnext(mp) != 0) + gnext(f) = cast_int((mp + gnext(mp)) - f); /* chain new position */ + else + lua_assert(gnext(f) == 0); + gnext(mp) = cast_int(f - mp); + mp = f; + } + } + setnodekey(L, &mp->i_key, key); + luaC_barrierback(L, t, key); + lua_assert(ttisnil(gval(mp))); + return gval(mp); } /* ** search function for integers */ -const TValue *luaH_getint (Table *t, lua_Integer key) { - /* (1 <= key && key <= t->sizearray) */ - if (l_castS2U(key) - 1 < t->sizearray) - return &t->array[key - 1]; - else { - Node *n = hashint(t, key); - for (;;) { /* check whether 'key' is somewhere in the chain */ - if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key) - return gval(n); /* that's it */ - else { - int nx = gnext(n); - if (nx == 0) break; - n += nx; - } - } - return luaO_nilobject; - } +const TValue* luaH_getint(Table* t, lua_Integer key) +{ + /* (1 <= key && key <= t->sizearray) */ + if (l_castS2U(key) - 1 < t->sizearray) + return &t->array[key - 1]; + else + { + Node* n = hashint(t, key); + for (;;) + { + /* check whether 'key' is somewhere in the chain */ + if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key) + return gval(n); /* that's it */ + else + { + int nx = gnext(n); + if (nx == 0) break; + n += nx; + } + } + return luaO_nilobject; + } } /* ** search function for short strings */ -const TValue *luaH_getshortstr (Table *t, TString *key) { - Node *n = hashstr(t, key); - lua_assert(key->tt == LUA_TSHRSTR); - for (;;) { /* check whether 'key' is somewhere in the chain */ - const TValue *k = gkey(n); - if (ttisshrstring(k) && eqshrstr(tsvalue(k), key)) - return gval(n); /* that's it */ - else { - int nx = gnext(n); - if (nx == 0) - return luaO_nilobject; /* not found */ - n += nx; - } - } +const TValue* luaH_getshortstr(Table* t, TString* key) +{ + Node* n = hashstr(t, key); + lua_assert(key->tt == LUA_TSHRSTR); + for (;;) + { + /* check whether 'key' is somewhere in the chain */ + const TValue* k = gkey(n); + if (ttisshrstring(k) && eqshrstr(tsvalue(k), key)) + return gval(n); /* that's it */ + else + { + int nx = gnext(n); + if (nx == 0) + return luaO_nilobject; /* not found */ + n += nx; + } + } } @@ -538,49 +616,59 @@ const TValue *luaH_getshortstr (Table *t, TString *key) { ** "Generic" get version. (Not that generic: not valid for integers, ** which may be in array part, nor for floats with integral values.) */ -static const TValue *getgeneric (Table *t, const TValue *key) { - Node *n = mainposition(t, key); - for (;;) { /* check whether 'key' is somewhere in the chain */ - if (luaV_rawequalobj(gkey(n), key)) - return gval(n); /* that's it */ - else { - int nx = gnext(n); - if (nx == 0) - return luaO_nilobject; /* not found */ - n += nx; - } - } +static const TValue* getgeneric(Table* t, const TValue* key) +{ + Node* n = mainposition(t, key); + for (;;) + { + /* check whether 'key' is somewhere in the chain */ + if (luaV_rawequalobj(gkey(n), key)) + return gval(n); /* that's it */ + else + { + int nx = gnext(n); + if (nx == 0) + return luaO_nilobject; /* not found */ + n += nx; + } + } } -const TValue *luaH_getstr (Table *t, TString *key) { - if (key->tt == LUA_TSHRSTR) - return luaH_getshortstr(t, key); - else { /* for long strings, use generic case */ - TValue ko; - setsvalue(cast(lua_State *, NULL), &ko, key); - return getgeneric(t, &ko); - } +const TValue* luaH_getstr(Table* t, TString* key) +{ + if (key->tt == LUA_TSHRSTR) + return luaH_getshortstr(t, key); + else + { + /* for long strings, use generic case */ + TValue ko; + setsvalue(cast(lua_State *, NULL), &ko, key); + return getgeneric(t, &ko); + } } /* ** main search function */ -const TValue *luaH_get (Table *t, const TValue *key) { - switch (ttype(key)) { - case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key)); - case LUA_TNUMINT: return luaH_getint(t, ivalue(key)); - case LUA_TNIL: return luaO_nilobject; - case LUA_TNUMFLT: { - lua_Integer k; - if (luaV_tointeger(key, &k, 0)) /* index is int? */ - return luaH_getint(t, k); /* use specialized version */ - /* else... */ - } /* FALLTHROUGH */ - default: - return getgeneric(t, key); - } +const TValue* luaH_get(Table* t, const TValue* key) +{ + switch (ttype(key)) + { + case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key)); + case LUA_TNUMINT: return luaH_getint(t, ivalue(key)); + case LUA_TNIL: return luaO_nilobject; + case LUA_TNUMFLT: + { + lua_Integer k; + if (luaV_tointeger(key, &k, 0)) /* index is int? */ + return luaH_getint(t, k); /* use specialized version */ + /* else... */ + } /* FALLTHROUGH */ + default: + return getgeneric(t, key); + } } @@ -588,49 +676,57 @@ const TValue *luaH_get (Table *t, const TValue *key) { ** beware: when using this function you probably need to check a GC ** barrier and invalidate the TM cache. */ -TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { - const TValue *p = luaH_get(t, key); - if (p != luaO_nilobject) - return cast(TValue *, p); - else return luaH_newkey(L, t, key); +TValue* luaH_set(lua_State* L, Table* t, const TValue* key) +{ + const TValue* p = luaH_get(t, key); + if (p != luaO_nilobject) + return cast(TValue *, p); + else return luaH_newkey(L, t, key); } -void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { - const TValue *p = luaH_getint(t, key); - TValue *cell; - if (p != luaO_nilobject) - cell = cast(TValue *, p); - else { - TValue k; - setivalue(&k, key); - cell = luaH_newkey(L, t, &k); - } - setobj2t(L, cell, value); +void luaH_setint(lua_State* L, Table* t, lua_Integer key, TValue* value) +{ + const TValue* p = luaH_getint(t, key); + TValue* cell; + if (p != luaO_nilobject) + cell = cast(TValue *, p); + else + { + TValue k; + setivalue(&k, key); + cell = luaH_newkey(L, t, &k); + } + setobj2t(L, cell, value); } -static int unbound_search (Table *t, unsigned int j) { - unsigned int i = j; /* i is zero or a present index */ - j++; - /* find 'i' and 'j' such that i is present and j is not */ - while (!ttisnil(luaH_getint(t, j))) { - i = j; - if (j > cast(unsigned int, MAX_INT)/2) { /* overflow? */ - /* table was built with bad purposes: resort to linear search */ - i = 1; - while (!ttisnil(luaH_getint(t, i))) i++; - return i - 1; - } - j *= 2; - } - /* now do a binary search between them */ - while (j - i > 1) { - unsigned int m = (i+j)/2; - if (ttisnil(luaH_getint(t, m))) j = m; - else i = m; - } - return i; +static int unbound_search(Table* t, unsigned int j) +{ + unsigned int i = j; /* i is zero or a present index */ + j++; + /* find 'i' and 'j' such that i is present and j is not */ + while (!ttisnil(luaH_getint(t, j))) + { + i = j; + if (j > cast(unsigned int, MAX_INT) / 2) + { + /* overflow? */ + /* table was built with bad purposes: resort to linear search */ + i = 1; + while (!ttisnil(luaH_getint(t, i))) i++; + return i - 1; + } + j *= 2; + } + /* now do a binary search between them */ + while (j - i > 1) + { + unsigned int m = (i + j) / 2; + if (ttisnil(luaH_getint(t, m))) j = m; + else i = m; + } + return i; } @@ -638,26 +734,28 @@ static int unbound_search (Table *t, unsigned int j) { ** Try to find a boundary in table 't'. A 'boundary' is an integer index ** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). */ -int luaH_getn (Table *t) { - unsigned int j = t->sizearray; - if (j > 0 && ttisnil(&t->array[j - 1])) { - /* there is a boundary in the array part: (binary) search for it */ - unsigned int i = 0; - while (j - i > 1) { - unsigned int m = (i+j)/2; - if (ttisnil(&t->array[m - 1])) j = m; - else i = m; - } - return i; - } - /* else must find a boundary in hash part */ - else if (isdummy(t)) /* hash part is empty? */ - return j; /* that is easy... */ - else return unbound_search(t, j); +int luaH_getn(Table* t) +{ + unsigned int j = t->sizearray; + if (j > 0 && ttisnil(&t->array[j - 1])) + { + /* there is a boundary in the array part: (binary) search for it */ + unsigned int i = 0; + while (j - i > 1) + { + unsigned int m = (i + j) / 2; + if (ttisnil(&t->array[m - 1])) j = m; + else i = m; + } + return i; + } + /* else must find a boundary in hash part */ + else if (isdummy(t)) /* hash part is empty? */ + return j; /* that is easy... */ + else return unbound_search(t, j); } - #if defined(LUA_DEBUG) Node *luaH_mainposition (const Table *t, const TValue *key) { diff --git a/Lua/ltable.h b/Lua/ltable.h index 6da9024..b879c03 100644 --- a/Lua/ltable.h +++ b/Lua/ltable.h @@ -40,21 +40,21 @@ (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val)))) -LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); -LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, - TValue *value); -LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key); -LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); -LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); -LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key); -LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); -LUAI_FUNC Table *luaH_new (lua_State *L); -LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize, - unsigned int nhsize); -LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize); -LUAI_FUNC void luaH_free (lua_State *L, Table *t); -LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); -LUAI_FUNC int luaH_getn (Table *t); +LUAI_FUNC const TValue* luaH_getint(Table* t, lua_Integer key); +LUAI_FUNC void luaH_setint(lua_State* L, Table* t, lua_Integer key, + TValue* value); +LUAI_FUNC const TValue* luaH_getshortstr(Table* t, TString* key); +LUAI_FUNC const TValue* luaH_getstr(Table* t, TString* key); +LUAI_FUNC const TValue* luaH_get(Table* t, const TValue* key); +LUAI_FUNC TValue* luaH_newkey(lua_State* L, Table* t, const TValue* key); +LUAI_FUNC TValue* luaH_set(lua_State* L, Table* t, const TValue* key); +LUAI_FUNC Table* luaH_new(lua_State* L); +LUAI_FUNC void luaH_resize(lua_State* L, Table* t, unsigned int nasize, + unsigned int nhsize); +LUAI_FUNC void luaH_resizearray(lua_State* L, Table* t, unsigned int nasize); +LUAI_FUNC void luaH_free(lua_State* L, Table* t); +LUAI_FUNC int luaH_next(lua_State* L, Table* t, StkId key); +LUAI_FUNC int luaH_getn(Table* t); #if defined(LUA_DEBUG) diff --git a/Lua/ltablib.c b/Lua/ltablib.c index 98b2f87..7834a89 100644 --- a/Lua/ltablib.c +++ b/Lua/ltablib.c @@ -33,9 +33,10 @@ #define aux_getn(L,n,w) (checktab(L, n, (w) | TAB_L), luaL_len(L, n)) -static int checkfield (lua_State *L, const char *key, int n) { - lua_pushstring(L, key); - return (lua_rawget(L, -n) != LUA_TNIL); +static int checkfield(lua_State* L, const char* key, int n) +{ + lua_pushstring(L, key); + return (lua_rawget(L, -n) != LUA_TNIL); } @@ -43,18 +44,22 @@ static int checkfield (lua_State *L, const char *key, int n) { ** Check that 'arg' either is a table or can behave like one (that is, ** has a metatable with the required metamethods) */ -static void checktab (lua_State *L, int arg, int what) { - if (lua_type(L, arg) != LUA_TTABLE) { /* is it not a table? */ - int n = 1; /* number of elements to pop */ - if (lua_getmetatable(L, arg) && /* must have metatable */ - (!(what & TAB_R) || checkfield(L, "__index", ++n)) && - (!(what & TAB_W) || checkfield(L, "__newindex", ++n)) && - (!(what & TAB_L) || checkfield(L, "__len", ++n))) { - lua_pop(L, n); /* pop metatable and tested metamethods */ - } - else - luaL_checktype(L, arg, LUA_TTABLE); /* force an error */ - } +static void checktab(lua_State* L, int arg, int what) +{ + if (lua_type(L, arg) != LUA_TTABLE) + { + /* is it not a table? */ + int n = 1; /* number of elements to pop */ + if (lua_getmetatable(L, arg) && /* must have metatable */ + (!(what & TAB_R) || checkfield(L, "__index", ++n)) && + (!(what & TAB_W) || checkfield(L, "__newindex", ++n)) && + (!(what & TAB_L) || checkfield(L, "__len", ++n))) + { + lua_pop(L, n); /* pop metatable and tested metamethods */ + } + else + luaL_checktype(L, arg, LUA_TTABLE); /* force an error */ + } } @@ -76,46 +81,56 @@ static int maxn (lua_State *L) { #endif -static int tinsert (lua_State *L) { - lua_Integer e = aux_getn(L, 1, TAB_RW) + 1; /* first empty element */ - lua_Integer pos; /* where to insert new element */ - switch (lua_gettop(L)) { - case 2: { /* called with only 2 arguments */ - pos = e; /* insert new element at the end */ - break; - } - case 3: { - lua_Integer i; - pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */ - luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds"); - for (i = e; i > pos; i--) { /* move up elements */ - lua_geti(L, 1, i - 1); - lua_seti(L, 1, i); /* t[i] = t[i - 1] */ - } - break; - } - default: { - return luaL_error(L, "wrong number of arguments to 'insert'"); - } - } - lua_seti(L, 1, pos); /* t[pos] = v */ - return 0; +static int tinsert(lua_State* L) +{ + lua_Integer e = aux_getn(L, 1, TAB_RW) + 1; /* first empty element */ + lua_Integer pos; /* where to insert new element */ + switch (lua_gettop(L)) + { + case 2: + { + /* called with only 2 arguments */ + pos = e; /* insert new element at the end */ + break; + } + case 3: + { + lua_Integer i; + pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */ + luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds"); + for (i = e; i > pos; i--) + { + /* move up elements */ + lua_geti(L, 1, i - 1); + lua_seti(L, 1, i); /* t[i] = t[i - 1] */ + } + break; + } + default: + { + return luaL_error(L, "wrong number of arguments to 'insert'"); + } + } + lua_seti(L, 1, pos); /* t[pos] = v */ + return 0; } -static int tremove (lua_State *L) { - lua_Integer size = aux_getn(L, 1, TAB_RW); - lua_Integer pos = luaL_optinteger(L, 2, size); - if (pos != size) /* validate 'pos' if given */ - luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds"); - lua_geti(L, 1, pos); /* result = t[pos] */ - for ( ; pos < size; pos++) { - lua_geti(L, 1, pos + 1); - lua_seti(L, 1, pos); /* t[pos] = t[pos + 1] */ - } - lua_pushnil(L); - lua_seti(L, 1, pos); /* t[pos] = nil */ - return 1; +static int tremove(lua_State* L) +{ + lua_Integer size = aux_getn(L, 1, TAB_RW); + lua_Integer pos = luaL_optinteger(L, 2, size); + if (pos != size) /* validate 'pos' if given */ + luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds"); + lua_geti(L, 1, pos); /* result = t[pos] */ + for (; pos < size; pos++) + { + lua_geti(L, 1, pos + 1); + lua_seti(L, 1, pos); /* t[pos] = t[pos + 1] */ + } + lua_pushnil(L); + lua_seti(L, 1, pos); /* t[pos] = nil */ + return 1; } @@ -125,63 +140,73 @@ static int tremove (lua_State *L) { ** "possible" means destination after original range, or smaller ** than origin, or copying to another table. */ -static int tmove (lua_State *L) { - lua_Integer f = luaL_checkinteger(L, 2); - lua_Integer e = luaL_checkinteger(L, 3); - lua_Integer t = luaL_checkinteger(L, 4); - int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */ - checktab(L, 1, TAB_R); - checktab(L, tt, TAB_W); - if (e >= f) { /* otherwise, nothing to move */ - lua_Integer n, i; - luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3, - "too many elements to move"); - n = e - f + 1; /* number of elements to move */ - luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4, - "destination wrap around"); - if (t > e || t <= f || (tt != 1 && !lua_compare(L, 1, tt, LUA_OPEQ))) { - for (i = 0; i < n; i++) { - lua_geti(L, 1, f + i); - lua_seti(L, tt, t + i); - } - } - else { - for (i = n - 1; i >= 0; i--) { - lua_geti(L, 1, f + i); - lua_seti(L, tt, t + i); - } - } - } - lua_pushvalue(L, tt); /* return destination table */ - return 1; +static int tmove(lua_State* L) +{ + lua_Integer f = luaL_checkinteger(L, 2); + lua_Integer e = luaL_checkinteger(L, 3); + lua_Integer t = luaL_checkinteger(L, 4); + int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */ + checktab(L, 1, TAB_R); + checktab(L, tt, TAB_W); + if (e >= f) + { + /* otherwise, nothing to move */ + lua_Integer n, i; + luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3, + "too many elements to move"); + n = e - f + 1; /* number of elements to move */ + luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4, + "destination wrap around"); + if (t > e || t <= f || (tt != 1 && !lua_compare(L, 1, tt, LUA_OPEQ))) + { + for (i = 0; i < n; i++) + { + lua_geti(L, 1, f + i); + lua_seti(L, tt, t + i); + } + } + else + { + for (i = n - 1; i >= 0; i--) + { + lua_geti(L, 1, f + i); + lua_seti(L, tt, t + i); + } + } + } + lua_pushvalue(L, tt); /* return destination table */ + return 1; } -static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) { - lua_geti(L, 1, i); - if (!lua_isstring(L, -1)) - luaL_error(L, "invalid value (%s) at index %d in table for 'concat'", - luaL_typename(L, -1), i); - luaL_addvalue(b); +static void addfield(lua_State* L, luaL_Buffer* b, lua_Integer i) +{ + lua_geti(L, 1, i); + if (!lua_isstring(L, -1)) + luaL_error(L, "invalid value (%s) at index %d in table for 'concat'", + luaL_typename(L, -1), i); + luaL_addvalue(b); } -static int tconcat (lua_State *L) { - luaL_Buffer b; - lua_Integer last = aux_getn(L, 1, TAB_R); - size_t lsep; - const char *sep = luaL_optlstring(L, 2, "", &lsep); - lua_Integer i = luaL_optinteger(L, 3, 1); - last = luaL_optinteger(L, 4, last); - luaL_buffinit(L, &b); - for (; i < last; i++) { - addfield(L, &b, i); - luaL_addlstring(&b, sep, lsep); - } - if (i == last) /* add last value (if interval was not empty) */ - addfield(L, &b, i); - luaL_pushresult(&b); - return 1; +static int tconcat(lua_State* L) +{ + luaL_Buffer b; + lua_Integer last = aux_getn(L, 1, TAB_R); + size_t lsep; + const char* sep = luaL_optlstring(L, 2, "", &lsep); + lua_Integer i = luaL_optinteger(L, 3, 1); + last = luaL_optinteger(L, 4, last); + luaL_buffinit(L, &b); + for (; i < last; i++) + { + addfield(L, &b, i); + luaL_addlstring(&b, sep, lsep); + } + if (i == last) /* add last value (if interval was not empty) */ + addfield(L, &b, i); + luaL_pushresult(&b); + return 1; } @@ -191,38 +216,41 @@ static int tconcat (lua_State *L) { ** ======================================================= */ -static int pack (lua_State *L) { - int i; - int n = lua_gettop(L); /* number of elements to pack */ - lua_createtable(L, n, 1); /* create result table */ - lua_insert(L, 1); /* put it at index 1 */ - for (i = n; i >= 1; i--) /* assign elements */ - lua_seti(L, 1, i); - lua_pushinteger(L, n); - lua_setfield(L, 1, "n"); /* t.n = number of elements */ - return 1; /* return table */ +static int pack(lua_State* L) +{ + int i; + int n = lua_gettop(L); /* number of elements to pack */ + lua_createtable(L, n, 1); /* create result table */ + lua_insert(L, 1); /* put it at index 1 */ + for (i = n; i >= 1; i--) /* assign elements */ + lua_seti(L, 1, i); + lua_pushinteger(L, n); + lua_setfield(L, 1, "n"); /* t.n = number of elements */ + return 1; /* return table */ } -static int unpack (lua_State *L) { - lua_Unsigned n; - lua_Integer i = luaL_optinteger(L, 2, 1); - lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1)); - if (i > e) return 0; /* empty range */ - n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */ - if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, (int)(++n))) - return luaL_error(L, "too many results to unpack"); - for (; i < e; i++) { /* push arg[i..e - 1] (to avoid overflows) */ - lua_geti(L, 1, i); - } - lua_geti(L, 1, e); /* push last element */ - return (int)n; +static int unpack(lua_State* L) +{ + lua_Unsigned n; + lua_Integer i = luaL_optinteger(L, 2, 1); + lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1)); + if (i > e) return 0; /* empty range */ + n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */ + if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, (int)(++n))) + return luaL_error(L, "too many results to unpack"); + for (; i < e; i++) + { + /* push arg[i..e - 1] (to avoid overflows) */ + lua_geti(L, 1, i); + } + lua_geti(L, 1, e); /* push last element */ + return (int)n; } /* }====================================================== */ - /* ** {====================================================== ** Quicksort @@ -255,16 +283,17 @@ typedef unsigned int IdxT; ** anything without risking overflows. A safe way to use their values ** is to copy them to an array of a known type and use the array values. */ -static unsigned int l_randomizePivot (void) { - clock_t c = clock(); - time_t t = time(NULL); - unsigned int buff[sof(c) + sof(t)]; - unsigned int i, rnd = 0; - memcpy(buff, &c, sof(c) * sizeof(unsigned int)); - memcpy(buff + sof(c), &t, sof(t) * sizeof(unsigned int)); - for (i = 0; i < sof(buff); i++) - rnd += buff[i]; - return rnd; +static unsigned int l_randomizePivot(void) +{ + clock_t c = clock(); + time_t t = time(NULL); + unsigned int buff[sof(c) + sof(t)]; + unsigned int i, rnd = 0; + memcpy(buff, &c, sof(c) * sizeof(unsigned int)); + memcpy(buff + sof(c), &t, sof(t) * sizeof(unsigned int)); + for (i = 0; i < sof(buff); i++) + rnd += buff[i]; + return rnd; } #endif /* } */ @@ -274,9 +303,10 @@ static unsigned int l_randomizePivot (void) { #define RANLIMIT 100u -static void set2 (lua_State *L, IdxT i, IdxT j) { - lua_seti(L, 1, i); - lua_seti(L, 1, j); +static void set2(lua_State* L, IdxT i, IdxT j) +{ + lua_seti(L, 1, i); + lua_seti(L, 1, j); } @@ -284,19 +314,22 @@ static void set2 (lua_State *L, IdxT i, IdxT j) { ** Return true iff value at stack index 'a' is less than the value at ** index 'b' (according to the order of the sort). */ -static int sort_comp (lua_State *L, int a, int b) { - if (lua_isnil(L, 2)) /* no function? */ - return lua_compare(L, a, b, LUA_OPLT); /* a < b */ - else { /* function */ - int res; - lua_pushvalue(L, 2); /* push function */ - lua_pushvalue(L, a-1); /* -1 to compensate function */ - lua_pushvalue(L, b-2); /* -2 to compensate function and 'a' */ - lua_call(L, 2, 1); /* call function */ - res = lua_toboolean(L, -1); /* get result */ - lua_pop(L, 1); /* pop result */ - return res; - } +static int sort_comp(lua_State* L, int a, int b) +{ + if (lua_isnil(L, 2)) /* no function? */ + return lua_compare(L, a, b, LUA_OPLT); /* a < b */ + else + { + /* function */ + int res; + lua_pushvalue(L, 2); /* push function */ + lua_pushvalue(L, a - 1); /* -1 to compensate function */ + lua_pushvalue(L, b - 2); /* -2 to compensate function and 'a' */ + lua_call(L, 2, 1); /* call function */ + res = lua_toboolean(L, -1); /* get result */ + lua_pop(L, 1); /* pop result */ + return res; + } } @@ -307,35 +340,41 @@ static int sort_comp (lua_State *L, int a, int b) { ** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up] ** returns 'i'. */ -static IdxT partition (lua_State *L, IdxT lo, IdxT up) { - IdxT i = lo; /* will be incremented before first use */ - IdxT j = up - 1; /* will be decremented before first use */ - /* loop invariant: a[lo .. i] <= P <= a[j .. up] */ - for (;;) { - /* next loop: repeat ++i while a[i] < P */ - while (lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) { - if (i == up - 1) /* a[i] < P but a[up - 1] == P ?? */ - luaL_error(L, "invalid order function for sorting"); - lua_pop(L, 1); /* remove a[i] */ - } - /* after the loop, a[i] >= P and a[lo .. i - 1] < P */ - /* next loop: repeat --j while P < a[j] */ - while (lua_geti(L, 1, --j), sort_comp(L, -3, -1)) { - if (j < i) /* j < i but a[j] > P ?? */ - luaL_error(L, "invalid order function for sorting"); - lua_pop(L, 1); /* remove a[j] */ - } - /* after the loop, a[j] <= P and a[j + 1 .. up] >= P */ - if (j < i) { /* no elements out of place? */ - /* a[lo .. i - 1] <= P <= a[j + 1 .. i .. up] */ - lua_pop(L, 1); /* pop a[j] */ - /* swap pivot (a[up - 1]) with a[i] to satisfy pos-condition */ - set2(L, up - 1, i); - return i; - } - /* otherwise, swap a[i] - a[j] to restore invariant and repeat */ - set2(L, i, j); - } +static IdxT partition(lua_State* L, IdxT lo, IdxT up) +{ + IdxT i = lo; /* will be incremented before first use */ + IdxT j = up - 1; /* will be decremented before first use */ + /* loop invariant: a[lo .. i] <= P <= a[j .. up] */ + for (;;) + { + /* next loop: repeat ++i while a[i] < P */ + while (lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) + { + if (i == up - 1) /* a[i] < P but a[up - 1] == P ?? */ + luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[i] */ + } + /* after the loop, a[i] >= P and a[lo .. i - 1] < P */ + /* next loop: repeat --j while P < a[j] */ + while (lua_geti(L, 1, --j), sort_comp(L, -3, -1)) + { + if (j < i) /* j < i but a[j] > P ?? */ + luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[j] */ + } + /* after the loop, a[j] <= P and a[j + 1 .. up] >= P */ + if (j < i) + { + /* no elements out of place? */ + /* a[lo .. i - 1] <= P <= a[j + 1 .. i .. up] */ + lua_pop(L, 1); /* pop a[j] */ + /* swap pivot (a[up - 1]) with a[i] to satisfy pos-condition */ + set2(L, up - 1, i); + return i; + } + /* otherwise, swap a[i] - a[j] to restore invariant and repeat */ + set2(L, i, j); + } } @@ -343,108 +382,119 @@ static IdxT partition (lua_State *L, IdxT lo, IdxT up) { ** Choose an element in the middle (2nd-3th quarters) of [lo,up] ** "randomized" by 'rnd' */ -static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) { - IdxT r4 = (up - lo) / 4; /* range/4 */ - IdxT p = rnd % (r4 * 2) + (lo + r4); - lua_assert(lo + r4 <= p && p <= up - r4); - return p; +static IdxT choosePivot(IdxT lo, IdxT up, unsigned int rnd) +{ + IdxT r4 = (up - lo) / 4; /* range/4 */ + IdxT p = rnd % (r4 * 2) + (lo + r4); + lua_assert(lo + r4 <= p && p <= up - r4); + return p; } /* ** QuickSort algorithm (recursive function) */ -static void auxsort (lua_State *L, IdxT lo, IdxT up, - unsigned int rnd) { - while (lo < up) { /* loop for tail recursion */ - IdxT p; /* Pivot index */ - IdxT n; /* to be used later */ - /* sort elements 'lo', 'p', and 'up' */ - lua_geti(L, 1, lo); - lua_geti(L, 1, up); - if (sort_comp(L, -1, -2)) /* a[up] < a[lo]? */ - set2(L, lo, up); /* swap a[lo] - a[up] */ - else - lua_pop(L, 2); /* remove both values */ - if (up - lo == 1) /* only 2 elements? */ - return; /* already sorted */ - if (up - lo < RANLIMIT || rnd == 0) /* small interval or no randomize? */ - p = (lo + up)/2; /* middle element is a good pivot */ - else /* for larger intervals, it is worth a random pivot */ - p = choosePivot(lo, up, rnd); - lua_geti(L, 1, p); - lua_geti(L, 1, lo); - if (sort_comp(L, -2, -1)) /* a[p] < a[lo]? */ - set2(L, p, lo); /* swap a[p] - a[lo] */ - else { - lua_pop(L, 1); /* remove a[lo] */ - lua_geti(L, 1, up); - if (sort_comp(L, -1, -2)) /* a[up] < a[p]? */ - set2(L, p, up); /* swap a[up] - a[p] */ - else - lua_pop(L, 2); - } - if (up - lo == 2) /* only 3 elements? */ - return; /* already sorted */ - lua_geti(L, 1, p); /* get middle element (Pivot) */ - lua_pushvalue(L, -1); /* push Pivot */ - lua_geti(L, 1, up - 1); /* push a[up - 1] */ - set2(L, p, up - 1); /* swap Pivot (a[p]) with a[up - 1] */ - p = partition(L, lo, up); - /* a[lo .. p - 1] <= a[p] == P <= a[p + 1 .. up] */ - if (p - lo < up - p) { /* lower interval is smaller? */ - auxsort(L, lo, p - 1, rnd); /* call recursively for lower interval */ - n = p - lo; /* size of smaller interval */ - lo = p + 1; /* tail call for [p + 1 .. up] (upper interval) */ - } - else { - auxsort(L, p + 1, up, rnd); /* call recursively for upper interval */ - n = up - p; /* size of smaller interval */ - up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */ - } - if ((up - lo) / 128 > n) /* partition too imbalanced? */ - rnd = l_randomizePivot(); /* try a new randomization */ - } /* tail call auxsort(L, lo, up, rnd) */ +static void auxsort(lua_State* L, IdxT lo, IdxT up, + unsigned int rnd) +{ + while (lo < up) + { + /* loop for tail recursion */ + IdxT p; /* Pivot index */ + IdxT n; /* to be used later */ + /* sort elements 'lo', 'p', and 'up' */ + lua_geti(L, 1, lo); + lua_geti(L, 1, up); + if (sort_comp(L, -1, -2)) /* a[up] < a[lo]? */ + set2(L, lo, up); /* swap a[lo] - a[up] */ + else + lua_pop(L, 2); /* remove both values */ + if (up - lo == 1) /* only 2 elements? */ + return; /* already sorted */ + if (up - lo < RANLIMIT || rnd == 0) /* small interval or no randomize? */ + p = (lo + up) / 2; /* middle element is a good pivot */ + else /* for larger intervals, it is worth a random pivot */ + p = choosePivot(lo, up, rnd); + lua_geti(L, 1, p); + lua_geti(L, 1, lo); + if (sort_comp(L, -2, -1)) /* a[p] < a[lo]? */ + set2(L, p, lo); /* swap a[p] - a[lo] */ + else + { + lua_pop(L, 1); /* remove a[lo] */ + lua_geti(L, 1, up); + if (sort_comp(L, -1, -2)) /* a[up] < a[p]? */ + set2(L, p, up); /* swap a[up] - a[p] */ + else + lua_pop(L, 2); + } + if (up - lo == 2) /* only 3 elements? */ + return; /* already sorted */ + lua_geti(L, 1, p); /* get middle element (Pivot) */ + lua_pushvalue(L, -1); /* push Pivot */ + lua_geti(L, 1, up - 1); /* push a[up - 1] */ + set2(L, p, up - 1); /* swap Pivot (a[p]) with a[up - 1] */ + p = partition(L, lo, up); + /* a[lo .. p - 1] <= a[p] == P <= a[p + 1 .. up] */ + if (p - lo < up - p) + { + /* lower interval is smaller? */ + auxsort(L, lo, p - 1, rnd); /* call recursively for lower interval */ + n = p - lo; /* size of smaller interval */ + lo = p + 1; /* tail call for [p + 1 .. up] (upper interval) */ + } + else + { + auxsort(L, p + 1, up, rnd); /* call recursively for upper interval */ + n = up - p; /* size of smaller interval */ + up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */ + } + if ((up - lo) / 128 > n) /* partition too imbalanced? */ + rnd = l_randomizePivot(); /* try a new randomization */ + } /* tail call auxsort(L, lo, up, rnd) */ } -static int sort (lua_State *L) { - lua_Integer n = aux_getn(L, 1, TAB_RW); - if (n > 1) { /* non-trivial interval? */ - luaL_argcheck(L, n < INT_MAX, 1, "array too big"); - if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ - luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */ - lua_settop(L, 2); /* make sure there are two arguments */ - auxsort(L, 1, (IdxT)n, 0); - } - return 0; +static int sort(lua_State* L) +{ + lua_Integer n = aux_getn(L, 1, TAB_RW); + if (n > 1) + { + /* non-trivial interval? */ + luaL_argcheck(L, n < INT_MAX, 1, "array too big"); + if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ + luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */ + lua_settop(L, 2); /* make sure there are two arguments */ + auxsort(L, 1, (IdxT)n, 0); + } + return 0; } /* }====================================================== */ static const luaL_Reg tab_funcs[] = { - {"concat", tconcat}, + {"concat", tconcat}, #if defined(LUA_COMPAT_MAXN) {"maxn", maxn}, #endif - {"insert", tinsert}, - {"pack", pack}, - {"unpack", unpack}, - {"remove", tremove}, - {"move", tmove}, - {"sort", sort}, - {NULL, NULL} + {"insert", tinsert}, + {"pack", pack}, + {"unpack", unpack}, + {"remove", tremove}, + {"move", tmove}, + {"sort", sort}, + {NULL, NULL} }; -LUAMOD_API int luaopen_table (lua_State *L) { - luaL_newlib(L, tab_funcs); +LUAMOD_API int luaopen_table(lua_State* L) +{ + luaL_newlib(L, tab_funcs); #if defined(LUA_COMPAT_UNPACK) /* _G.unpack = table.unpack */ lua_getfield(L, -1, "unpack"); lua_setglobal(L, "unpack"); #endif - return 1; + return 1; } - diff --git a/Lua/ltm.c b/Lua/ltm.c index 14e5257..f0e68a7 100644 --- a/Lua/ltm.c +++ b/Lua/ltm.c @@ -26,29 +26,32 @@ static const char udatatypename[] = "userdata"; -LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = { - "no value", - "nil", "boolean", udatatypename, "number", - "string", "table", "function", udatatypename, "thread", - "proto" /* this last case is used for tests only */ +LUAI_DDEF const char* const luaT_typenames_[LUA_TOTALTAGS] = { + "no value", + "nil", "boolean", udatatypename, "number", + "string", "table", "function", udatatypename, "thread", + "proto" /* this last case is used for tests only */ }; -void luaT_init (lua_State *L) { - static const char *const luaT_eventname[] = { /* ORDER TM */ - "__index", "__newindex", - "__gc", "__mode", "__len", "__eq", - "__add", "__sub", "__mul", "__mod", "__pow", - "__div", "__idiv", - "__band", "__bor", "__bxor", "__shl", "__shr", - "__unm", "__bnot", "__lt", "__le", - "__concat", "__call" - }; - int i; - for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); - luaC_fix(L, obj2gco(G(L)->tmname[i])); /* never collect these names */ - } +void luaT_init(lua_State* L) +{ + static const char* const luaT_eventname[] = { + /* ORDER TM */ + "__index", "__newindex", + "__gc", "__mode", "__len", "__eq", + "__add", "__sub", "__mul", "__mod", "__pow", + "__div", "__idiv", + "__band", "__bor", "__bxor", "__shl", "__shr", + "__unm", "__bnot", "__lt", "__le", + "__concat", "__call" + }; + int i; + for (i = 0; i < TM_N; i++) + { + G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]); + luaC_fix(L, obj2gco(G(L)->tmname[i])); /* never collect these names */ + } } @@ -56,30 +59,35 @@ void luaT_init (lua_State *L) { ** function to be used with macro "fasttm": optimized for absence of ** tag methods */ -const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { - const TValue *tm = luaH_getshortstr(events, ename); - lua_assert(event <= TM_EQ); - if (ttisnil(tm)) { /* no tag method? */ - events->flags |= cast_byte(1u<flags |= cast_byte(1u<metatable; - break; - case LUA_TUSERDATA: - mt = uvalue(o)->metatable; - break; - default: - mt = G(L)->mt[ttnov(o)]; - } - return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : luaO_nilobject); +const TValue* luaT_gettmbyobj(lua_State* L, const TValue* o, TMS event) +{ + Table* mt; + switch (ttnov(o)) + { + case LUA_TTABLE: + mt = hvalue(o)->metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(o)->metatable; + break; + default: + mt = G(L)->mt[ttnov(o)]; + } + return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : luaO_nilobject); } @@ -87,79 +95,93 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { ** Return the name of the type of an object. For tables and userdata ** with metatable, use their '__name' metafield, if present. */ -const char *luaT_objtypename (lua_State *L, const TValue *o) { - Table *mt; - if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) || - (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) { - const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name")); - if (ttisstring(name)) /* is '__name' a string? */ - return getstr(tsvalue(name)); /* use it as type name */ - } - return ttypename(ttnov(o)); /* else use standard type name */ +const char* luaT_objtypename(lua_State* L, const TValue* o) +{ + Table* mt; + if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) || + (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) + { + const TValue* name = luaH_getshortstr(mt, luaS_new(L, "__name")); + if (ttisstring(name)) /* is '__name' a string? */ + return getstr(tsvalue(name)); /* use it as type name */ + } + return ttypename(ttnov(o)); /* else use standard type name */ } -void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, - const TValue *p2, TValue *p3, int hasres) { - ptrdiff_t result = savestack(L, p3); - StkId func = L->top; - setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ - setobj2s(L, func + 1, p1); /* 1st argument */ - setobj2s(L, func + 2, p2); /* 2nd argument */ - L->top += 3; - if (!hasres) /* no result? 'p3' is third argument */ - setobj2s(L, L->top++, p3); /* 3rd argument */ - /* metamethod may yield only when called from Lua code */ - if (isLua(L->ci)) - luaD_call(L, func, hasres); - else - luaD_callnoyield(L, func, hasres); - if (hasres) { /* if has result, move it to its place */ - p3 = restorestack(L, result); - setobjs2s(L, p3, --L->top); - } +void luaT_callTM(lua_State* L, const TValue* f, const TValue* p1, + const TValue* p2, TValue* p3, int hasres) +{ + ptrdiff_t result = savestack(L, p3); + StkId func = L->top; + setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ + setobj2s(L, func + 1, p1); /* 1st argument */ + setobj2s(L, func + 2, p2); /* 2nd argument */ + L->top += 3; + if (!hasres) /* no result? 'p3' is third argument */ + setobj2s(L, L->top++, p3); /* 3rd argument */ + /* metamethod may yield only when called from Lua code */ + if (isLua(L->ci)) + luaD_call(L, func, hasres); + else + luaD_callnoyield(L, func, hasres); + if (hasres) + { + /* if has result, move it to its place */ + p3 = restorestack(L, result); + setobjs2s(L, p3, --L->top); + } } -int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2, - StkId res, TMS event) { - const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ - if (ttisnil(tm)) - tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ - if (ttisnil(tm)) return 0; - luaT_callTM(L, tm, p1, p2, res, 1); - return 1; +int luaT_callbinTM(lua_State* L, const TValue* p1, const TValue* p2, + StkId res, TMS event) +{ + const TValue* tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ + if (ttisnil(tm)) + tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ + if (ttisnil(tm)) return 0; + luaT_callTM(L, tm, p1, p2, res, 1); + return 1; } -void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, - StkId res, TMS event) { - if (!luaT_callbinTM(L, p1, p2, res, event)) { - switch (event) { - case TM_CONCAT: - luaG_concaterror(L, p1, p2); - /* call never returns, but to avoid warnings: *//* FALLTHROUGH */ - case TM_BAND: case TM_BOR: case TM_BXOR: - case TM_SHL: case TM_SHR: case TM_BNOT: { - lua_Number dummy; - if (tonumber(p1, &dummy) && tonumber(p2, &dummy)) - luaG_tointerror(L, p1, p2); - else - luaG_opinterror(L, p1, p2, "perform bitwise operation on"); - } - /* calls never return, but to avoid warnings: *//* FALLTHROUGH */ - default: - luaG_opinterror(L, p1, p2, "perform arithmetic on"); - } - } +void luaT_trybinTM(lua_State* L, const TValue* p1, const TValue* p2, + StkId res, TMS event) +{ + if (!luaT_callbinTM(L, p1, p2, res, event)) + { + switch (event) + { + case TM_CONCAT: + luaG_concaterror(L, p1, p2); + /* call never returns, but to avoid warnings: */ /* FALLTHROUGH */ + case TM_BAND: + case TM_BOR: + case TM_BXOR: + case TM_SHL: + case TM_SHR: + case TM_BNOT: + { + lua_Number dummy; + if (tonumber(p1, &dummy) && tonumber(p2, &dummy)) + luaG_tointerror(L, p1, p2); + else + luaG_opinterror(L, p1, p2, "perform bitwise operation on"); + } + /* calls never return, but to avoid warnings: */ /* FALLTHROUGH */ + default: + luaG_opinterror(L, p1, p2, "perform arithmetic on"); + } + } } -int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, - TMS event) { - if (!luaT_callbinTM(L, p1, p2, L->top, event)) - return -1; /* no metamethod */ - else - return !l_isfalse(L->top); +int luaT_callorderTM(lua_State* L, const TValue* p1, const TValue* p2, + TMS event) +{ + if (!luaT_callbinTM(L, p1, p2, L->top, event)) + return -1; /* no metamethod */ + else + return !l_isfalse(L->top); } - diff --git a/Lua/ltm.h b/Lua/ltm.h index 63db726..09628cc 100644 --- a/Lua/ltm.h +++ b/Lua/ltm.h @@ -15,36 +15,37 @@ * WARNING: if you change the order of this enumeration, * grep "ORDER TM" and "ORDER OP" */ -typedef enum { - TM_INDEX, - TM_NEWINDEX, - TM_GC, - TM_MODE, - TM_LEN, - TM_EQ, /* last tag method with fast access */ - TM_ADD, - TM_SUB, - TM_MUL, - TM_MOD, - TM_POW, - TM_DIV, - TM_IDIV, - TM_BAND, - TM_BOR, - TM_BXOR, - TM_SHL, - TM_SHR, - TM_UNM, - TM_BNOT, - TM_LT, - TM_LE, - TM_CONCAT, - TM_CALL, - TM_N /* number of elements in the enum */ +typedef enum +{ + TM_INDEX, + TM_NEWINDEX, + TM_GC, + TM_MODE, + TM_LEN, + TM_EQ, + /* last tag method with fast access */ + TM_ADD, + TM_SUB, + TM_MUL, + TM_MOD, + TM_POW, + TM_DIV, + TM_IDIV, + TM_BAND, + TM_BOR, + TM_BXOR, + TM_SHL, + TM_SHR, + TM_UNM, + TM_BNOT, + TM_LT, + TM_LE, + TM_CONCAT, + TM_CALL, + TM_N /* number of elements in the enum */ } TMS; - #define gfasttm(g,et,e) ((et) == NULL ? NULL : \ ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) @@ -52,25 +53,24 @@ typedef enum { #define ttypename(x) luaT_typenames_[(x) + 1] -LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS]; +LUAI_DDEC const char* const luaT_typenames_[LUA_TOTALTAGS]; -LUAI_FUNC const char *luaT_objtypename (lua_State *L, const TValue *o); +LUAI_FUNC const char* luaT_objtypename(lua_State* L, const TValue* o); -LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); -LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, - TMS event); -LUAI_FUNC void luaT_init (lua_State *L); - -LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, - const TValue *p2, TValue *p3, int hasres); -LUAI_FUNC int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2, - StkId res, TMS event); -LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, - StkId res, TMS event); -LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1, - const TValue *p2, TMS event); +LUAI_FUNC const TValue* luaT_gettm(Table* events, TMS event, TString* ename); +LUAI_FUNC const TValue* luaT_gettmbyobj(lua_State* L, const TValue* o, + TMS event); +LUAI_FUNC void luaT_init(lua_State* L); +LUAI_FUNC void luaT_callTM(lua_State* L, const TValue* f, const TValue* p1, + const TValue* p2, TValue* p3, int hasres); +LUAI_FUNC int luaT_callbinTM(lua_State* L, const TValue* p1, const TValue* p2, + StkId res, TMS event); +LUAI_FUNC void luaT_trybinTM(lua_State* L, const TValue* p1, const TValue* p2, + StkId res, TMS event); +LUAI_FUNC int luaT_callorderTM(lua_State* L, const TValue* p1, + const TValue* p2, TMS event); #endif diff --git a/Lua/lua.h b/Lua/lua.h index 26c0e2d..4d6196d 100644 --- a/Lua/lua.h +++ b/Lua/lua.h @@ -74,7 +74,6 @@ typedef struct lua_State lua_State; #define LUA_NUMTAGS 9 - /* minimum Lua stack available to a C function */ #define LUA_MINSTACK 20 @@ -102,27 +101,26 @@ typedef LUA_KCONTEXT lua_KContext; /* ** Type for C functions registered with Lua */ -typedef int (*lua_CFunction) (lua_State *L); +typedef int (*lua_CFunction)(lua_State* L); /* ** Type for continuation functions */ -typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); +typedef int (*lua_KFunction)(lua_State* L, int status, lua_KContext ctx); /* ** Type for functions that read/write blocks when loading/dumping Lua chunks */ -typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); +typedef const char* (*lua_Reader)(lua_State* L, void* ud, size_t* sz); -typedef int (*lua_Writer) (lua_State *L, const void *p, size_t sz, void *ud); +typedef int (*lua_Writer)(lua_State* L, const void* p, size_t sz, void* ud); /* ** Type for memory-allocation functions */ -typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); - +typedef void* (*lua_Alloc)(void* ud, void* ptr, size_t osize, size_t nsize); /* @@ -142,51 +140,51 @@ extern const char lua_ident[]; /* ** state manipulation */ -LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); -LUA_API void (lua_close) (lua_State *L); -LUA_API lua_State *(lua_newthread) (lua_State *L); +LUA_API lua_State*(lua_newstate)(lua_Alloc f, void* ud); +LUA_API void (lua_close)(lua_State* L); +LUA_API lua_State*(lua_newthread)(lua_State* L); -LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); +LUA_API lua_CFunction (lua_atpanic)(lua_State* L, lua_CFunction panicf); -LUA_API const lua_Number *(lua_version) (lua_State *L); +LUA_API const lua_Number*(lua_version)(lua_State* L); /* ** basic stack manipulation */ -LUA_API int (lua_absindex) (lua_State *L, int idx); -LUA_API int (lua_gettop) (lua_State *L); -LUA_API void (lua_settop) (lua_State *L, int idx); -LUA_API void (lua_pushvalue) (lua_State *L, int idx); -LUA_API void (lua_rotate) (lua_State *L, int idx, int n); -LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx); -LUA_API int (lua_checkstack) (lua_State *L, int n); +LUA_API int (lua_absindex)(lua_State* L, int idx); +LUA_API int (lua_gettop)(lua_State* L); +LUA_API void (lua_settop)(lua_State* L, int idx); +LUA_API void (lua_pushvalue)(lua_State* L, int idx); +LUA_API void (lua_rotate)(lua_State* L, int idx, int n); +LUA_API void (lua_copy)(lua_State* L, int fromidx, int toidx); +LUA_API int (lua_checkstack)(lua_State* L, int n); -LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); +LUA_API void (lua_xmove)(lua_State* from, lua_State* to, int n); /* ** access functions (stack -> C) */ -LUA_API int (lua_isnumber) (lua_State *L, int idx); -LUA_API int (lua_isstring) (lua_State *L, int idx); -LUA_API int (lua_iscfunction) (lua_State *L, int idx); -LUA_API int (lua_isinteger) (lua_State *L, int idx); -LUA_API int (lua_isuserdata) (lua_State *L, int idx); -LUA_API int (lua_type) (lua_State *L, int idx); -LUA_API const char *(lua_typename) (lua_State *L, int tp); +LUA_API int (lua_isnumber)(lua_State* L, int idx); +LUA_API int (lua_isstring)(lua_State* L, int idx); +LUA_API int (lua_iscfunction)(lua_State* L, int idx); +LUA_API int (lua_isinteger)(lua_State* L, int idx); +LUA_API int (lua_isuserdata)(lua_State* L, int idx); +LUA_API int (lua_type)(lua_State* L, int idx); +LUA_API const char*(lua_typename)(lua_State* L, int tp); -LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); -LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); -LUA_API int (lua_toboolean) (lua_State *L, int idx); -LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); -LUA_API size_t (lua_rawlen) (lua_State *L, int idx); -LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); -LUA_API void *(lua_touserdata) (lua_State *L, int idx); -LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); -LUA_API const void *(lua_topointer) (lua_State *L, int idx); +LUA_API lua_Number (lua_tonumberx)(lua_State* L, int idx, int* isnum); +LUA_API lua_Integer (lua_tointegerx)(lua_State* L, int idx, int* isnum); +LUA_API int (lua_toboolean)(lua_State* L, int idx); +LUA_API const char*(lua_tolstring)(lua_State* L, int idx, size_t* len); +LUA_API size_t (lua_rawlen)(lua_State* L, int idx); +LUA_API lua_CFunction (lua_tocfunction)(lua_State* L, int idx); +LUA_API void*(lua_touserdata)(lua_State* L, int idx); +LUA_API lua_State*(lua_tothread)(lua_State* L, int idx); +LUA_API const void*(lua_topointer)(lua_State* L, int idx); /* @@ -208,89 +206,89 @@ LUA_API const void *(lua_topointer) (lua_State *L, int idx); #define LUA_OPUNM 12 #define LUA_OPBNOT 13 -LUA_API void (lua_arith) (lua_State *L, int op); +LUA_API void (lua_arith)(lua_State* L, int op); #define LUA_OPEQ 0 #define LUA_OPLT 1 #define LUA_OPLE 2 -LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); -LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); +LUA_API int (lua_rawequal)(lua_State* L, int idx1, int idx2); +LUA_API int (lua_compare)(lua_State* L, int idx1, int idx2, int op); /* ** push functions (C -> stack) */ -LUA_API void (lua_pushnil) (lua_State *L); -LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); -LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); -LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len); -LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); -LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, - va_list argp); -LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); -LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); -LUA_API void (lua_pushboolean) (lua_State *L, int b); -LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); -LUA_API int (lua_pushthread) (lua_State *L); +LUA_API void (lua_pushnil)(lua_State* L); +LUA_API void (lua_pushnumber)(lua_State* L, lua_Number n); +LUA_API void (lua_pushinteger)(lua_State* L, lua_Integer n); +LUA_API const char*(lua_pushlstring)(lua_State* L, const char* s, size_t len); +LUA_API const char*(lua_pushstring)(lua_State* L, const char* s); +LUA_API const char*(lua_pushvfstring)(lua_State* L, const char* fmt, + va_list argp); +LUA_API const char*(lua_pushfstring)(lua_State* L, const char* fmt, ...); +LUA_API void (lua_pushcclosure)(lua_State* L, lua_CFunction fn, int n); +LUA_API void (lua_pushboolean)(lua_State* L, int b); +LUA_API void (lua_pushlightuserdata)(lua_State* L, void* p); +LUA_API int (lua_pushthread)(lua_State* L); /* ** get functions (Lua -> stack) */ -LUA_API int (lua_getglobal) (lua_State *L, const char *name); -LUA_API int (lua_gettable) (lua_State *L, int idx); -LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k); -LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n); -LUA_API int (lua_rawget) (lua_State *L, int idx); -LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n); -LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p); +LUA_API int (lua_getglobal)(lua_State* L, const char* name); +LUA_API int (lua_gettable)(lua_State* L, int idx); +LUA_API int (lua_getfield)(lua_State* L, int idx, const char* k); +LUA_API int (lua_geti)(lua_State* L, int idx, lua_Integer n); +LUA_API int (lua_rawget)(lua_State* L, int idx); +LUA_API int (lua_rawgeti)(lua_State* L, int idx, lua_Integer n); +LUA_API int (lua_rawgetp)(lua_State* L, int idx, const void* p); -LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); -LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); -LUA_API int (lua_getmetatable) (lua_State *L, int objindex); -LUA_API int (lua_getuservalue) (lua_State *L, int idx); +LUA_API void (lua_createtable)(lua_State* L, int narr, int nrec); +LUA_API void*(lua_newuserdata)(lua_State* L, size_t sz); +LUA_API int (lua_getmetatable)(lua_State* L, int objindex); +LUA_API int (lua_getuservalue)(lua_State* L, int idx); /* ** set functions (stack -> Lua) */ -LUA_API void (lua_setglobal) (lua_State *L, const char *name); -LUA_API void (lua_settable) (lua_State *L, int idx); -LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); -LUA_API void (lua_seti) (lua_State *L, int idx, lua_Integer n); -LUA_API void (lua_rawset) (lua_State *L, int idx); -LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n); -LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); -LUA_API int (lua_setmetatable) (lua_State *L, int objindex); -LUA_API void (lua_setuservalue) (lua_State *L, int idx); +LUA_API void (lua_setglobal)(lua_State* L, const char* name); +LUA_API void (lua_settable)(lua_State* L, int idx); +LUA_API void (lua_setfield)(lua_State* L, int idx, const char* k); +LUA_API void (lua_seti)(lua_State* L, int idx, lua_Integer n); +LUA_API void (lua_rawset)(lua_State* L, int idx); +LUA_API void (lua_rawseti)(lua_State* L, int idx, lua_Integer n); +LUA_API void (lua_rawsetp)(lua_State* L, int idx, const void* p); +LUA_API int (lua_setmetatable)(lua_State* L, int objindex); +LUA_API void (lua_setuservalue)(lua_State* L, int idx); /* ** 'load' and 'call' functions (load and run Lua code) */ -LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, - lua_KContext ctx, lua_KFunction k); +LUA_API void (lua_callk)(lua_State* L, int nargs, int nresults, + lua_KContext ctx, lua_KFunction k); #define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) -LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, - lua_KContext ctx, lua_KFunction k); +LUA_API int (lua_pcallk)(lua_State* L, int nargs, int nresults, int errfunc, + lua_KContext ctx, lua_KFunction k); #define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) -LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, - const char *chunkname, const char *mode); +LUA_API int (lua_load)(lua_State* L, lua_Reader reader, void* dt, + const char* chunkname, const char* mode); -LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip); +LUA_API int (lua_dump)(lua_State* L, lua_Writer writer, void* data, int strip); /* ** coroutine functions */ -LUA_API int (lua_yieldk) (lua_State *L, int nresults, lua_KContext ctx, - lua_KFunction k); -LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg); -LUA_API int (lua_status) (lua_State *L); -LUA_API int (lua_isyieldable) (lua_State *L); +LUA_API int (lua_yieldk)(lua_State* L, int nresults, lua_KContext ctx, + lua_KFunction k); +LUA_API int (lua_resume)(lua_State* L, lua_State* from, int narg); +LUA_API int (lua_status)(lua_State* L); +LUA_API int (lua_isyieldable)(lua_State* L); #define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) @@ -309,25 +307,24 @@ LUA_API int (lua_isyieldable) (lua_State *L); #define LUA_GCSETSTEPMUL 7 #define LUA_GCISRUNNING 9 -LUA_API int (lua_gc) (lua_State *L, int what, int data); +LUA_API int (lua_gc)(lua_State* L, int what, int data); /* ** miscellaneous functions */ -LUA_API int (lua_error) (lua_State *L); +LUA_API int (lua_error)(lua_State* L); -LUA_API int (lua_next) (lua_State *L, int idx); +LUA_API int (lua_next)(lua_State* L, int idx); -LUA_API void (lua_concat) (lua_State *L, int n); -LUA_API void (lua_len) (lua_State *L, int idx); +LUA_API void (lua_concat)(lua_State* L, int n); +LUA_API void (lua_len)(lua_State* L, int idx); -LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s); - -LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); -LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); +LUA_API size_t (lua_stringtonumber)(lua_State* L, const char* s); +LUA_API lua_Alloc (lua_getallocf)(lua_State* L, void** ud); +LUA_API void (lua_setallocf)(lua_State* L, lua_Alloc f, void* ud); /* @@ -414,46 +411,47 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); #define LUA_MASKLINE (1 << LUA_HOOKLINE) #define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) -typedef struct lua_Debug lua_Debug; /* activation record */ +typedef struct lua_Debug lua_Debug; /* activation record */ /* Functions to be called by the debugger in specific events */ -typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); +typedef void (*lua_Hook)(lua_State* L, lua_Debug* ar); -LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); -LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); -LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n); -LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n); -LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n); -LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n); +LUA_API int (lua_getstack)(lua_State* L, int level, lua_Debug* ar); +LUA_API int (lua_getinfo)(lua_State* L, const char* what, lua_Debug* ar); +LUA_API const char*(lua_getlocal)(lua_State* L, const lua_Debug* ar, int n); +LUA_API const char*(lua_setlocal)(lua_State* L, const lua_Debug* ar, int n); +LUA_API const char*(lua_getupvalue)(lua_State* L, int funcindex, int n); +LUA_API const char*(lua_setupvalue)(lua_State* L, int funcindex, int n); -LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n); -LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1, - int fidx2, int n2); +LUA_API void*(lua_upvalueid)(lua_State* L, int fidx, int n); +LUA_API void (lua_upvaluejoin)(lua_State* L, int fidx1, int n1, + int fidx2, int n2); -LUA_API void (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); -LUA_API lua_Hook (lua_gethook) (lua_State *L); -LUA_API int (lua_gethookmask) (lua_State *L); -LUA_API int (lua_gethookcount) (lua_State *L); +LUA_API void (lua_sethook)(lua_State* L, lua_Hook func, int mask, int count); +LUA_API lua_Hook (lua_gethook)(lua_State* L); +LUA_API int (lua_gethookmask)(lua_State* L); +LUA_API int (lua_gethookcount)(lua_State* L); -struct lua_Debug { - int event; - const char *name; /* (n) */ - const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ - const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ - const char *source; /* (S) */ - int currentline; /* (l) */ - int linedefined; /* (S) */ - int lastlinedefined; /* (S) */ - unsigned char nups; /* (u) number of upvalues */ - unsigned char nparams;/* (u) number of parameters */ - char isvararg; /* (u) */ - char istailcall; /* (t) */ - char short_src[LUA_IDSIZE]; /* (S) */ - /* private part */ - struct CallInfo *i_ci; /* active function */ +struct lua_Debug +{ + int event; + const char* name; /* (n) */ + const char* namewhat; /* (n) 'global', 'local', 'field', 'method' */ + const char* what; /* (S) 'Lua', 'C', 'main', 'tail' */ + const char* source; /* (S) */ + int currentline; /* (l) */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + unsigned char nups; /* (u) number of upvalues */ + unsigned char nparams; /* (u) number of parameters */ + char isvararg; /* (u) */ + char istailcall; /* (t) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + struct CallInfo* i_ci; /* active function */ }; /* }====================================================================== */ diff --git a/Lua/luaconf.h b/Lua/luaconf.h index f37bea0..20d0173 100644 --- a/Lua/luaconf.h +++ b/Lua/luaconf.h @@ -82,7 +82,6 @@ #endif - /* @@ LUAI_BITSINT defines the (minimum) number of bits in an 'int'. */ @@ -150,8 +149,6 @@ /* }================================================================== */ - - /* ** {================================================================== ** Configuration for Paths. @@ -405,7 +402,6 @@ /* }================================================================== */ - /* ** {================================================================== ** Configuration for Numbers. @@ -505,7 +501,6 @@ #endif /* } */ - /* @@ LUA_INTEGER is the integer type used by Lua. ** @@ -766,8 +761,6 @@ #define LUA_QS LUA_QL("%s") - - /* =================================================================== */ /* @@ -776,8 +769,4 @@ */ - - - #endif - diff --git a/Lua/lualib.h b/Lua/lualib.h index 6c0bc4c..5fb5665 100644 --- a/Lua/lualib.h +++ b/Lua/lualib.h @@ -15,42 +15,41 @@ #define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR -LUAMOD_API int (luaopen_base) (lua_State *L); +LUAMOD_API int (luaopen_base)(lua_State* L); #define LUA_COLIBNAME "coroutine" -LUAMOD_API int (luaopen_coroutine) (lua_State *L); +LUAMOD_API int (luaopen_coroutine)(lua_State* L); #define LUA_TABLIBNAME "table" -LUAMOD_API int (luaopen_table) (lua_State *L); +LUAMOD_API int (luaopen_table)(lua_State* L); #define LUA_IOLIBNAME "io" -LUAMOD_API int (luaopen_io) (lua_State *L); +LUAMOD_API int (luaopen_io)(lua_State* L); #define LUA_OSLIBNAME "os" -LUAMOD_API int (luaopen_os) (lua_State *L); +LUAMOD_API int (luaopen_os)(lua_State* L); #define LUA_STRLIBNAME "string" -LUAMOD_API int (luaopen_string) (lua_State *L); +LUAMOD_API int (luaopen_string)(lua_State* L); #define LUA_UTF8LIBNAME "utf8" -LUAMOD_API int (luaopen_utf8) (lua_State *L); +LUAMOD_API int (luaopen_utf8)(lua_State* L); #define LUA_BITLIBNAME "bit32" -LUAMOD_API int (luaopen_bit32) (lua_State *L); +LUAMOD_API int (luaopen_bit32)(lua_State* L); #define LUA_MATHLIBNAME "math" -LUAMOD_API int (luaopen_math) (lua_State *L); +LUAMOD_API int (luaopen_math)(lua_State* L); #define LUA_DBLIBNAME "debug" -LUAMOD_API int (luaopen_debug) (lua_State *L); +LUAMOD_API int (luaopen_debug)(lua_State* L); #define LUA_LOADLIBNAME "package" -LUAMOD_API int (luaopen_package) (lua_State *L); +LUAMOD_API int (luaopen_package)(lua_State* L); /* open all previous libraries */ -LUALIB_API void (luaL_openlibs) (lua_State *L); - +LUALIB_API void (luaL_openlibs)(lua_State* L); #if !defined(lua_assert) diff --git a/Lua/luasocket.c b/Lua/luasocket.c index d2752a7..0976680 100644 --- a/Lua/luasocket.c +++ b/Lua/luasocket.c @@ -35,80 +35,87 @@ /*-------------------------------------------------------------------------*\ * Internal function prototypes \*-------------------------------------------------------------------------*/ -static int global_skip(lua_State *L); -static int global_unload(lua_State *L); -static int base_open(lua_State *L); +static int global_skip(lua_State* L); +static int global_unload(lua_State* L); +static int base_open(lua_State* L); /*-------------------------------------------------------------------------*\ * Modules and functions \*-------------------------------------------------------------------------*/ static const luaL_Reg mod[] = { - {"auxiliar", auxiliar_open}, - {"except", except_open}, - {"timeout", timeout_open}, - {"buffer", buffer_open}, - {"inet", inet_open}, - {"tcp", tcp_open}, - {"udp", udp_open}, - {"select", select_open}, - {NULL, NULL} + {"auxiliar", auxiliar_open}, + {"except", except_open}, + {"timeout", timeout_open}, + {"buffer", buffer_open}, + {"inet", inet_open}, + {"tcp", tcp_open}, + {"udp", udp_open}, + {"select", select_open}, + {NULL, NULL} }; static luaL_Reg func[] = { - {"skip", global_skip}, - {"__unload", global_unload}, - {NULL, NULL} + {"skip", global_skip}, + {"__unload", global_unload}, + {NULL, NULL} }; /*-------------------------------------------------------------------------*\ * Skip a few arguments \*-------------------------------------------------------------------------*/ -static int global_skip(lua_State *L) { - int amount = (int) luaL_checkinteger(L, 1); - int ret = lua_gettop(L) - amount - 1; - return ret >= 0 ? ret : 0; +static int global_skip(lua_State* L) +{ + int amount = (int)luaL_checkinteger(L, 1); + int ret = lua_gettop(L) - amount - 1; + return ret >= 0 ? ret : 0; } /*-------------------------------------------------------------------------*\ * Unloads the library \*-------------------------------------------------------------------------*/ -static int global_unload(lua_State *L) { - (void) L; - socket_close(); - return 0; +static int global_unload(lua_State* L) +{ + (void)L; + socket_close(); + return 0; } /*-------------------------------------------------------------------------*\ * Setup basic stuff. \*-------------------------------------------------------------------------*/ -static int base_open(lua_State *L) { - if (socket_open()) { - /* export functions (and leave namespace table on top of stack) */ - lua_newtable(L); - luaL_setfuncs(L, func, 0); +static int base_open(lua_State* L) +{ + if (socket_open()) + { + /* export functions (and leave namespace table on top of stack) */ + lua_newtable(L); + luaL_setfuncs(L, func, 0); #ifdef LUASOCKET_DEBUG lua_pushstring(L, "_DEBUG"); lua_pushboolean(L, 1); lua_rawset(L, -3); #endif - /* make version string available to scripts */ - lua_pushstring(L, "_VERSION"); - lua_pushstring(L, LUASOCKET_VERSION); - lua_rawset(L, -3); - return 1; - } else { - lua_pushstring(L, "unable to initialize library"); - lua_error(L); - return 0; - } + /* make version string available to scripts */ + lua_pushstring(L, "_VERSION"); + lua_pushstring(L, LUASOCKET_VERSION); + lua_rawset(L, -3); + return 1; + } + else + { + lua_pushstring(L, "unable to initialize library"); + lua_error(L); + return 0; + } } /*-------------------------------------------------------------------------*\ * Initializes all library modules. \*-------------------------------------------------------------------------*/ -LUASOCKET_API int luaopen_socket_core(lua_State *L) { - int i; - base_open(L); - for (i = 0; mod[i].name; i++) mod[i].func(L); - return 1; +LUASOCKET_API int luaopen_socket_core(lua_State* L) +{ + int i; + base_open(L); + for (i = 0; mod[i].name; i++) mod[i].func(L); + return 1; } diff --git a/Lua/luasocket.h b/Lua/luasocket.h index f75d21f..3e4389a 100644 --- a/Lua/luasocket.h +++ b/Lua/luasocket.h @@ -24,6 +24,6 @@ /*-------------------------------------------------------------------------*\ * Initializes the library. \*-------------------------------------------------------------------------*/ -LUASOCKET_API int luaopen_socket_core(lua_State *L); +LUASOCKET_API int luaopen_socket_core(lua_State* L); #endif /* LUASOCKET_H */ diff --git a/Lua/lundump.c b/Lua/lundump.c index 4080af9..ab88077 100644 --- a/Lua/lundump.c +++ b/Lua/lundump.c @@ -29,16 +29,18 @@ #endif -typedef struct { - lua_State *L; - ZIO *Z; - const char *name; +typedef struct +{ + lua_State* L; + ZIO* Z; + const char* name; } LoadState; -static l_noret error(LoadState *S, const char *why) { - luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why); - luaD_throw(S->L, LUA_ERRSYNTAX); +static l_noret error(LoadState* S, const char* why) +{ + luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why); + luaD_throw(S->L, LUA_ERRSYNTAX); } @@ -48,232 +50,256 @@ static l_noret error(LoadState *S, const char *why) { */ #define LoadVector(S,b,n) LoadBlock(S,b,(n)*sizeof((b)[0])) -static void LoadBlock (LoadState *S, void *b, size_t size) { - if (luaZ_read(S->Z, b, size) != 0) - error(S, "truncated"); +static void LoadBlock(LoadState* S, void* b, size_t size) +{ + if (luaZ_read(S->Z, b, size) != 0) + error(S, "truncated"); } #define LoadVar(S,x) LoadVector(S,&x,1) -static lu_byte LoadByte (LoadState *S) { - lu_byte x; - LoadVar(S, x); - return x; +static lu_byte LoadByte(LoadState* S) +{ + lu_byte x; + LoadVar(S, x); + return x; } -static int LoadInt (LoadState *S) { - int x; - LoadVar(S, x); - return x; +static int LoadInt(LoadState* S) +{ + int x; + LoadVar(S, x); + return x; } -static lua_Number LoadNumber (LoadState *S) { - lua_Number x; - LoadVar(S, x); - return x; +static lua_Number LoadNumber(LoadState* S) +{ + lua_Number x; + LoadVar(S, x); + return x; } -static lua_Integer LoadInteger (LoadState *S) { - lua_Integer x; - LoadVar(S, x); - return x; +static lua_Integer LoadInteger(LoadState* S) +{ + lua_Integer x; + LoadVar(S, x); + return x; } -static TString *LoadString (LoadState *S) { - size_t size = LoadByte(S); - if (size == 0xFF) - LoadVar(S, size); - if (size == 0) - return NULL; - else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ - char buff[LUAI_MAXSHORTLEN]; - LoadVector(S, buff, size); - return luaS_newlstr(S->L, buff, size); - } - else { /* long string */ - TString *ts = luaS_createlngstrobj(S->L, size); - LoadVector(S, getstr(ts), size); /* load directly in final place */ - return ts; - } +static TString* LoadString(LoadState* S) +{ + size_t size = LoadByte(S); + if (size == 0xFF) + LoadVar(S, size); + if (size == 0) + return NULL; + else if (--size <= LUAI_MAXSHORTLEN) + { + /* short string? */ + char buff[LUAI_MAXSHORTLEN]; + LoadVector(S, buff, size); + return luaS_newlstr(S->L, buff, size); + } + else + { + /* long string */ + TString* ts = luaS_createlngstrobj(S->L, size); + LoadVector(S, getstr(ts), size); /* load directly in final place */ + return ts; + } } -static void LoadCode (LoadState *S, Proto *f) { - int n = LoadInt(S); - f->code = luaM_newvector(S->L, n, Instruction); - f->sizecode = n; - LoadVector(S, f->code, n); +static void LoadCode(LoadState* S, Proto* f) +{ + int n = LoadInt(S); + f->code = luaM_newvector(S->L, n, Instruction); + f->sizecode = n; + LoadVector(S, f->code, n); } -static void LoadFunction(LoadState *S, Proto *f, TString *psource); +static void LoadFunction(LoadState* S, Proto* f, TString* psource); -static void LoadConstants (LoadState *S, Proto *f) { - int i; - int n = LoadInt(S); - f->k = luaM_newvector(S->L, n, TValue); - f->sizek = n; - for (i = 0; i < n; i++) - setnilvalue(&f->k[i]); - for (i = 0; i < n; i++) { - TValue *o = &f->k[i]; - int t = LoadByte(S); - switch (t) { - case LUA_TNIL: - setnilvalue(o); - break; - case LUA_TBOOLEAN: - setbvalue(o, LoadByte(S)); - break; - case LUA_TNUMFLT: - setfltvalue(o, LoadNumber(S)); - break; - case LUA_TNUMINT: - setivalue(o, LoadInteger(S)); - break; - case LUA_TSHRSTR: - case LUA_TLNGSTR: - setsvalue2n(S->L, o, LoadString(S)); - break; - default: - lua_assert(0); - } - } +static void LoadConstants(LoadState* S, Proto* f) +{ + int i; + int n = LoadInt(S); + f->k = luaM_newvector(S->L, n, TValue); + f->sizek = n; + for (i = 0; i < n; i++) + setnilvalue(&f->k[i]); + for (i = 0; i < n; i++) + { + TValue* o = &f->k[i]; + int t = LoadByte(S); + switch (t) + { + case LUA_TNIL: + setnilvalue(o); + break; + case LUA_TBOOLEAN: + setbvalue(o, LoadByte(S)); + break; + case LUA_TNUMFLT: + setfltvalue(o, LoadNumber(S)); + break; + case LUA_TNUMINT: + setivalue(o, LoadInteger(S)); + break; + case LUA_TSHRSTR: + case LUA_TLNGSTR: + setsvalue2n(S->L, o, LoadString(S)); + break; + default: + lua_assert(0); + } + } } -static void LoadProtos (LoadState *S, Proto *f) { - int i; - int n = LoadInt(S); - f->p = luaM_newvector(S->L, n, Proto *); - f->sizep = n; - for (i = 0; i < n; i++) - f->p[i] = NULL; - for (i = 0; i < n; i++) { - f->p[i] = luaF_newproto(S->L); - LoadFunction(S, f->p[i], f->source); - } +static void LoadProtos(LoadState* S, Proto* f) +{ + int i; + int n = LoadInt(S); + f->p = luaM_newvector(S->L, n, Proto *); + f->sizep = n; + for (i = 0; i < n; i++) + f->p[i] = NULL; + for (i = 0; i < n; i++) + { + f->p[i] = luaF_newproto(S->L); + LoadFunction(S, f->p[i], f->source); + } } -static void LoadUpvalues (LoadState *S, Proto *f) { - int i, n; - n = LoadInt(S); - f->upvalues = luaM_newvector(S->L, n, Upvaldesc); - f->sizeupvalues = n; - for (i = 0; i < n; i++) - f->upvalues[i].name = NULL; - for (i = 0; i < n; i++) { - f->upvalues[i].instack = LoadByte(S); - f->upvalues[i].idx = LoadByte(S); - } +static void LoadUpvalues(LoadState* S, Proto* f) +{ + int i, n; + n = LoadInt(S); + f->upvalues = luaM_newvector(S->L, n, Upvaldesc); + f->sizeupvalues = n; + for (i = 0; i < n; i++) + f->upvalues[i].name = NULL; + for (i = 0; i < n; i++) + { + f->upvalues[i].instack = LoadByte(S); + f->upvalues[i].idx = LoadByte(S); + } } -static void LoadDebug (LoadState *S, Proto *f) { - int i, n; - n = LoadInt(S); - f->lineinfo = luaM_newvector(S->L, n, int); - f->sizelineinfo = n; - LoadVector(S, f->lineinfo, n); - n = LoadInt(S); - f->locvars = luaM_newvector(S->L, n, LocVar); - f->sizelocvars = n; - for (i = 0; i < n; i++) - f->locvars[i].varname = NULL; - for (i = 0; i < n; i++) { - f->locvars[i].varname = LoadString(S); - f->locvars[i].startpc = LoadInt(S); - f->locvars[i].endpc = LoadInt(S); - } - n = LoadInt(S); - for (i = 0; i < n; i++) - f->upvalues[i].name = LoadString(S); +static void LoadDebug(LoadState* S, Proto* f) +{ + int i, n; + n = LoadInt(S); + f->lineinfo = luaM_newvector(S->L, n, int); + f->sizelineinfo = n; + LoadVector(S, f->lineinfo, n); + n = LoadInt(S); + f->locvars = luaM_newvector(S->L, n, LocVar); + f->sizelocvars = n; + for (i = 0; i < n; i++) + f->locvars[i].varname = NULL; + for (i = 0; i < n; i++) + { + f->locvars[i].varname = LoadString(S); + f->locvars[i].startpc = LoadInt(S); + f->locvars[i].endpc = LoadInt(S); + } + n = LoadInt(S); + for (i = 0; i < n; i++) + f->upvalues[i].name = LoadString(S); } -static void LoadFunction (LoadState *S, Proto *f, TString *psource) { - f->source = LoadString(S); - if (f->source == NULL) /* no source in dump? */ - f->source = psource; /* reuse parent's source */ - f->linedefined = LoadInt(S); - f->lastlinedefined = LoadInt(S); - f->numparams = LoadByte(S); - f->is_vararg = LoadByte(S); - f->maxstacksize = LoadByte(S); - LoadCode(S, f); - LoadConstants(S, f); - LoadUpvalues(S, f); - LoadProtos(S, f); - LoadDebug(S, f); +static void LoadFunction(LoadState* S, Proto* f, TString* psource) +{ + f->source = LoadString(S); + if (f->source == NULL) /* no source in dump? */ + f->source = psource; /* reuse parent's source */ + f->linedefined = LoadInt(S); + f->lastlinedefined = LoadInt(S); + f->numparams = LoadByte(S); + f->is_vararg = LoadByte(S); + f->maxstacksize = LoadByte(S); + LoadCode(S, f); + LoadConstants(S, f); + LoadUpvalues(S, f); + LoadProtos(S, f); + LoadDebug(S, f); } -static void checkliteral (LoadState *S, const char *s, const char *msg) { - char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */ - size_t len = strlen(s); - LoadVector(S, buff, len); - if (memcmp(s, buff, len) != 0) - error(S, msg); +static void checkliteral(LoadState* S, const char* s, const char* msg) +{ + char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */ + size_t len = strlen(s); + LoadVector(S, buff, len); + if (memcmp(s, buff, len) != 0) + error(S, msg); } -static void fchecksize (LoadState *S, size_t size, const char *tname) { - if (LoadByte(S) != size) - error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname)); +static void fchecksize(LoadState* S, size_t size, const char* tname) +{ + if (LoadByte(S) != size) + error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname)); } #define checksize(S,t) fchecksize(S,sizeof(t),#t) -static void checkHeader (LoadState *S) { - checkliteral(S, LUA_SIGNATURE + 1, "not a"); /* 1st char already checked */ - if (LoadByte(S) != LUAC_VERSION) - error(S, "version mismatch in"); - if (LoadByte(S) != LUAC_FORMAT) - error(S, "format mismatch in"); - checkliteral(S, LUAC_DATA, "corrupted"); - checksize(S, int); - checksize(S, size_t); - checksize(S, Instruction); - checksize(S, lua_Integer); - checksize(S, lua_Number); - if (LoadInteger(S) != LUAC_INT) - error(S, "endianness mismatch in"); - if (LoadNumber(S) != LUAC_NUM) - error(S, "float format mismatch in"); +static void checkHeader(LoadState* S) +{ + checkliteral(S, LUA_SIGNATURE + 1, "not a"); /* 1st char already checked */ + if (LoadByte(S) != LUAC_VERSION) + error(S, "version mismatch in"); + if (LoadByte(S) != LUAC_FORMAT) + error(S, "format mismatch in"); + checkliteral(S, LUAC_DATA, "corrupted"); + checksize(S, int); + checksize(S, size_t); + checksize(S, Instruction); + checksize(S, lua_Integer); + checksize(S, lua_Number); + if (LoadInteger(S) != LUAC_INT) + error(S, "endianness mismatch in"); + if (LoadNumber(S) != LUAC_NUM) + error(S, "float format mismatch in"); } /* ** load precompiled chunk */ -LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { - LoadState S; - LClosure *cl; - if (*name == '@' || *name == '=') - S.name = name + 1; - else if (*name == LUA_SIGNATURE[0]) - S.name = "binary string"; - else - S.name = name; - S.L = L; - S.Z = Z; - checkHeader(&S); - cl = luaF_newLclosure(L, LoadByte(&S)); - setclLvalue(L, L->top, cl); - luaD_inctop(L); - cl->p = luaF_newproto(L); - LoadFunction(&S, cl->p, NULL); - lua_assert(cl->nupvalues == cl->p->sizeupvalues); - luai_verifycode(L, buff, cl->p); - return cl; +LClosure* luaU_undump(lua_State* L, ZIO* Z, const char* name) +{ + LoadState S; + LClosure* cl; + if (*name == '@' || *name == '=') + S.name = name + 1; + else if (*name == LUA_SIGNATURE[0]) + S.name = "binary string"; + else + S.name = name; + S.L = L; + S.Z = Z; + checkHeader(&S); + cl = luaF_newLclosure(L, LoadByte(&S)); + setclLvalue(L, L->top, cl); + luaD_inctop(L); + cl->p = luaF_newproto(L); + LoadFunction(&S, cl->p, NULL); + lua_assert(cl->nupvalues == cl->p->sizeupvalues); + luai_verifycode(L, buff, cl->p); + return cl; } - diff --git a/Lua/lundump.h b/Lua/lundump.h index aa5cc82..778ba6d 100644 --- a/Lua/lundump.h +++ b/Lua/lundump.h @@ -23,10 +23,10 @@ #define LUAC_FORMAT 0 /* this is the official format */ /* load one chunk; from lundump.c */ -LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name); +LUAI_FUNC LClosure* luaU_undump(lua_State* L, ZIO* Z, const char* name); /* dump one chunk; from ldump.c */ -LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, - void* data, int strip); +LUAI_FUNC int luaU_dump(lua_State* L, const Proto* f, lua_Writer w, + void* data, int strip); #endif diff --git a/Lua/lutf8lib.c b/Lua/lutf8lib.c index de9e3dc..d2b4162 100644 --- a/Lua/lutf8lib.c +++ b/Lua/lutf8lib.c @@ -27,39 +27,44 @@ /* from strlib */ /* translate a relative string position: negative means back from end */ -static lua_Integer u_posrelat (lua_Integer pos, size_t len) { - if (pos >= 0) return pos; - else if (0u - (size_t)pos > len) return 0; - else return (lua_Integer)len + pos + 1; +static lua_Integer u_posrelat(lua_Integer pos, size_t len) +{ + if (pos >= 0) return pos; + else if (0u - (size_t)pos > len) return 0; + else return (lua_Integer)len + pos + 1; } /* ** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid. */ -static const char *utf8_decode (const char *o, int *val) { - static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF}; - const unsigned char *s = (const unsigned char *)o; - unsigned int c = s[0]; - unsigned int res = 0; /* final result */ - if (c < 0x80) /* ascii? */ - res = c; - else { - int count = 0; /* to count number of continuation bytes */ - while (c & 0x40) { /* still have continuation bytes? */ - int cc = s[++count]; /* read next byte */ - if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ - return NULL; /* invalid byte sequence */ - res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ - c <<= 1; /* to test next bit */ - } - res |= ((c & 0x7F) << (count * 5)); /* add first byte */ - if (count > 3 || res > MAXUNICODE || res <= limits[count]) - return NULL; /* invalid byte sequence */ - s += count; /* skip continuation bytes read */ - } - if (val) *val = res; - return (const char *)s + 1; /* +1 to include first byte */ +static const char* utf8_decode(const char* o, int* val) +{ + static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF}; + const unsigned char* s = (const unsigned char*)o; + unsigned int c = s[0]; + unsigned int res = 0; /* final result */ + if (c < 0x80) /* ascii? */ + res = c; + else + { + int count = 0; /* to count number of continuation bytes */ + while (c & 0x40) + { + /* still have continuation bytes? */ + int cc = s[++count]; /* read next byte */ + if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ + return NULL; /* invalid byte sequence */ + res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ + c <<= 1; /* to test next bit */ + } + res |= ((c & 0x7F) << (count * 5)); /* add first byte */ + if (count > 3 || res > MAXUNICODE || res <= limits[count]) + return NULL; /* invalid byte sequence */ + s += count; /* skip continuation bytes read */ + } + if (val) *val = res; + return (const char*)s + 1; /* +1 to include first byte */ } @@ -68,28 +73,32 @@ static const char *utf8_decode (const char *o, int *val) { ** range [i,j], or nil + current position if 's' is not well formed in ** that interval */ -static int utflen (lua_State *L) { - int n = 0; - size_t len; - const char *s = luaL_checklstring(L, 1, &len); - lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); - lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len); - luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2, - "initial position out of string"); - luaL_argcheck(L, --posj < (lua_Integer)len, 3, - "final position out of string"); - while (posi <= posj) { - const char *s1 = utf8_decode(s + posi, NULL); - if (s1 == NULL) { /* conversion error? */ - lua_pushnil(L); /* return nil ... */ - lua_pushinteger(L, posi + 1); /* ... and current position */ - return 2; - } - posi = s1 - s; - n++; - } - lua_pushinteger(L, n); - return 1; +static int utflen(lua_State* L) +{ + int n = 0; + size_t len; + const char* s = luaL_checklstring(L, 1, &len); + lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); + lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len); + luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2, + "initial position out of string"); + luaL_argcheck(L, --posj < (lua_Integer)len, 3, + "final position out of string"); + while (posi <= posj) + { + const char* s1 = utf8_decode(s + posi, NULL); + if (s1 == NULL) + { + /* conversion error? */ + lua_pushnil(L); /* return nil ... */ + lua_pushinteger(L, posi + 1); /* ... and current position */ + return 2; + } + posi = s1 - s; + n++; + } + lua_pushinteger(L, n); + return 1; } @@ -97,59 +106,65 @@ static int utflen (lua_State *L) { ** codepoint(s, [i, [j]]) -> returns codepoints for all characters ** that start in the range [i,j] */ -static int codepoint (lua_State *L) { - size_t len; - const char *s = luaL_checklstring(L, 1, &len); - lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); - lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len); - int n; - const char *se; - luaL_argcheck(L, posi >= 1, 2, "out of range"); - luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range"); - if (posi > pose) return 0; /* empty interval; return no values */ - if (pose - posi >= INT_MAX) /* (lua_Integer -> int) overflow? */ - return luaL_error(L, "string slice too long"); - n = (int)(pose - posi) + 1; - luaL_checkstack(L, n, "string slice too long"); - n = 0; - se = s + pose; - for (s += posi - 1; s < se;) { - int code; - s = utf8_decode(s, &code); - if (s == NULL) - return luaL_error(L, "invalid UTF-8 code"); - lua_pushinteger(L, code); - n++; - } - return n; +static int codepoint(lua_State* L) +{ + size_t len; + const char* s = luaL_checklstring(L, 1, &len); + lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); + lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len); + int n; + const char* se; + luaL_argcheck(L, posi >= 1, 2, "out of range"); + luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range"); + if (posi > pose) return 0; /* empty interval; return no values */ + if (pose - posi >= INT_MAX) /* (lua_Integer -> int) overflow? */ + return luaL_error(L, "string slice too long"); + n = (int)(pose - posi) + 1; + luaL_checkstack(L, n, "string slice too long"); + n = 0; + se = s + pose; + for (s += posi - 1; s < se;) + { + int code; + s = utf8_decode(s, &code); + if (s == NULL) + return luaL_error(L, "invalid UTF-8 code"); + lua_pushinteger(L, code); + n++; + } + return n; } -static void pushutfchar (lua_State *L, int arg) { - lua_Integer code = luaL_checkinteger(L, arg); - luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range"); - lua_pushfstring(L, "%U", (long)code); +static void pushutfchar(lua_State* L, int arg) +{ + lua_Integer code = luaL_checkinteger(L, arg); + luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range"); + lua_pushfstring(L, "%U", (long)code); } /* ** utfchar(n1, n2, ...) -> char(n1)..char(n2)... */ -static int utfchar (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - if (n == 1) /* optimize common case of single char */ - pushutfchar(L, 1); - else { - int i; - luaL_Buffer b; - luaL_buffinit(L, &b); - for (i = 1; i <= n; i++) { - pushutfchar(L, i); - luaL_addvalue(&b); - } - luaL_pushresult(&b); - } - return 1; +static int utfchar(lua_State* L) +{ + int n = lua_gettop(L); /* number of arguments */ + if (n == 1) /* optimize common case of single char */ + pushutfchar(L, 1); + else + { + int i; + luaL_Buffer b; + luaL_buffinit(L, &b); + for (i = 1; i <= n; i++) + { + pushutfchar(L, i); + luaL_addvalue(&b); + } + luaL_pushresult(&b); + } + return 1; } @@ -157,77 +172,95 @@ static int utfchar (lua_State *L) { ** offset(s, n, [i]) -> index where n-th character counting from ** position 'i' starts; 0 means character at 'i'. */ -static int byteoffset (lua_State *L) { - size_t len; - const char *s = luaL_checklstring(L, 1, &len); - lua_Integer n = luaL_checkinteger(L, 2); - lua_Integer posi = (n >= 0) ? 1 : len + 1; - posi = u_posrelat(luaL_optinteger(L, 3, posi), len); - luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3, - "position out of range"); - if (n == 0) { - /* find beginning of current byte sequence */ - while (posi > 0 && iscont(s + posi)) posi--; - } - else { - if (iscont(s + posi)) - luaL_error(L, "initial position is a continuation byte"); - if (n < 0) { - while (n < 0 && posi > 0) { /* move back */ - do { /* find beginning of previous character */ - posi--; - } while (posi > 0 && iscont(s + posi)); - n++; - } - } - else { - n--; /* do not move for 1st character */ - while (n > 0 && posi < (lua_Integer)len) { - do { /* find beginning of next character */ - posi++; - } while (iscont(s + posi)); /* (cannot pass final '\0') */ - n--; - } - } - } - if (n == 0) /* did it find given character? */ - lua_pushinteger(L, posi + 1); - else /* no such character */ - lua_pushnil(L); - return 1; +static int byteoffset(lua_State* L) +{ + size_t len; + const char* s = luaL_checklstring(L, 1, &len); + lua_Integer n = luaL_checkinteger(L, 2); + lua_Integer posi = (n >= 0) ? 1 : len + 1; + posi = u_posrelat(luaL_optinteger(L, 3, posi), len); + luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3, + "position out of range"); + if (n == 0) + { + /* find beginning of current byte sequence */ + while (posi > 0 && iscont(s + posi)) posi--; + } + else + { + if (iscont(s + posi)) + luaL_error(L, "initial position is a continuation byte"); + if (n < 0) + { + while (n < 0 && posi > 0) + { + /* move back */ + do + { + /* find beginning of previous character */ + posi--; + } + while (posi > 0 && iscont(s + posi)); + n++; + } + } + else + { + n--; /* do not move for 1st character */ + while (n > 0 && posi < (lua_Integer)len) + { + do + { + /* find beginning of next character */ + posi++; + } + while (iscont(s + posi)); /* (cannot pass final '\0') */ + n--; + } + } + } + if (n == 0) /* did it find given character? */ + lua_pushinteger(L, posi + 1); + else /* no such character */ + lua_pushnil(L); + return 1; } -static int iter_aux (lua_State *L) { - size_t len; - const char *s = luaL_checklstring(L, 1, &len); - lua_Integer n = lua_tointeger(L, 2) - 1; - if (n < 0) /* first iteration? */ - n = 0; /* start from here */ - else if (n < (lua_Integer)len) { - n++; /* skip current byte */ - while (iscont(s + n)) n++; /* and its continuations */ - } - if (n >= (lua_Integer)len) - return 0; /* no more codepoints */ - else { - int code; - const char *next = utf8_decode(s + n, &code); - if (next == NULL || iscont(next)) - return luaL_error(L, "invalid UTF-8 code"); - lua_pushinteger(L, n + 1); - lua_pushinteger(L, code); - return 2; - } +static int iter_aux(lua_State* L) +{ + size_t len; + const char* s = luaL_checklstring(L, 1, &len); + lua_Integer n = lua_tointeger(L, 2) - 1; + if (n < 0) /* first iteration? */ + n = 0; /* start from here */ + else if (n < (lua_Integer)len) + { + n++; /* skip current byte */ + while (iscont(s + n)) n++; /* and its continuations */ + } + if (n >= (lua_Integer)len) + return 0; /* no more codepoints */ + else + { + int code; + const char* next = utf8_decode(s + n, &code); + if (next == NULL || iscont(next)) + return luaL_error(L, "invalid UTF-8 code"); + lua_pushinteger(L, n + 1); + lua_pushinteger(L, code); + return 2; + } } -static int iter_codes (lua_State *L) { - luaL_checkstring(L, 1); - lua_pushcfunction(L, iter_aux); - lua_pushvalue(L, 1); - lua_pushinteger(L, 0); - return 3; +static int iter_codes(lua_State* L) +{ + luaL_checkstring(L, 1); + lua_pushcfunction(L, iter_aux); + lua_pushvalue(L, 1); + lua_pushinteger(L, 0); + return 3; } @@ -236,21 +269,21 @@ static int iter_codes (lua_State *L) { static const luaL_Reg funcs[] = { - {"offset", byteoffset}, - {"codepoint", codepoint}, - {"char", utfchar}, - {"len", utflen}, - {"codes", iter_codes}, - /* placeholders */ - {"charpattern", NULL}, - {NULL, NULL} + {"offset", byteoffset}, + {"codepoint", codepoint}, + {"char", utfchar}, + {"len", utflen}, + {"codes", iter_codes}, + /* placeholders */ + {"charpattern", NULL}, + {NULL, NULL} }; -LUAMOD_API int luaopen_utf8 (lua_State *L) { - luaL_newlib(L, funcs); - lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT)/sizeof(char) - 1); - lua_setfield(L, -2, "charpattern"); - return 1; +LUAMOD_API int luaopen_utf8(lua_State* L) +{ + luaL_newlib(L, funcs); + lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT) / sizeof(char) - 1); + lua_setfield(L, -2, "charpattern"); + return 1; } - diff --git a/Lua/lvm.c b/Lua/lvm.c index 84ade6b..7f6d84c 100644 --- a/Lua/lvm.c +++ b/Lua/lvm.c @@ -35,7 +35,6 @@ #define MAXTAGLOOP 2000 - /* ** 'l_intfitsf' checks whether a given integer can be converted to a ** float without rounding. Used in comparisons. Left undefined if @@ -64,24 +63,26 @@ #endif - /* ** Try to convert a value to a float. The float case is already handled ** by the macro 'tonumber'. */ -int luaV_tonumber_ (const TValue *obj, lua_Number *n) { - TValue v; - if (ttisinteger(obj)) { - *n = cast_num(ivalue(obj)); - return 1; - } - else if (cvt2num(obj) && /* string convertible to number? */ - luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { - *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */ - return 1; - } - else - return 0; /* conversion failed */ +int luaV_tonumber_(const TValue* obj, lua_Number* n) +{ + TValue v; + if (ttisinteger(obj)) + { + *n = cast_num(ivalue(obj)); + return 1; + } + else if (cvt2num(obj) && /* string convertible to number? */ + luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) + { + *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */ + return 1; + } + else + return 0; /* conversion failed */ } @@ -91,29 +92,35 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) { ** mode == 1: takes the floor of the number ** mode == 2: takes the ceil of the number */ -int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { - TValue v; - again: - if (ttisfloat(obj)) { - lua_Number n = fltvalue(obj); - lua_Number f = l_floor(n); - if (n != f) { /* not an integral value? */ - if (mode == 0) return 0; /* fails if mode demands integral value */ - else if (mode > 1) /* needs ceil? */ - f += 1; /* convert floor to ceil (remember: n != f) */ - } - return lua_numbertointeger(f, p); - } - else if (ttisinteger(obj)) { - *p = ivalue(obj); - return 1; - } - else if (cvt2num(obj) && - luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { - obj = &v; - goto again; /* convert result from 'luaO_str2num' to an integer */ - } - return 0; /* conversion failed */ +int luaV_tointeger(const TValue* obj, lua_Integer* p, int mode) +{ + TValue v; +again: + if (ttisfloat(obj)) + { + lua_Number n = fltvalue(obj); + lua_Number f = l_floor(n); + if (n != f) + { + /* not an integral value? */ + if (mode == 0) return 0; /* fails if mode demands integral value */ + else if (mode > 1) /* needs ceil? */ + f += 1; /* convert floor to ceil (remember: n != f) */ + } + return lua_numbertointeger(f, p); + } + else if (ttisinteger(obj)) + { + *p = ivalue(obj); + return 1; + } + else if (cvt2num(obj) && + luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) + { + obj = &v; + goto again; /* convert result from 'luaO_str2num' to an integer */ + } + return 0; /* conversion failed */ } @@ -132,23 +139,30 @@ int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { ** the extreme case when the initial value is LUA_MININTEGER, in which ** case the LUA_MININTEGER limit would still run the loop once. */ -static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, - int *stopnow) { - *stopnow = 0; /* usually, let loops run */ - if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) { /* not fit in integer? */ - lua_Number n; /* try to convert to float */ - if (!tonumber(obj, &n)) /* cannot convert to float? */ - return 0; /* not a number */ - if (luai_numlt(0, n)) { /* if true, float is larger than max integer */ - *p = LUA_MAXINTEGER; - if (step < 0) *stopnow = 1; - } - else { /* float is smaller than min integer */ - *p = LUA_MININTEGER; - if (step >= 0) *stopnow = 1; - } - } - return 1; +static int forlimit(const TValue* obj, lua_Integer* p, lua_Integer step, + int* stopnow) +{ + *stopnow = 0; /* usually, let loops run */ + if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) + { + /* not fit in integer? */ + lua_Number n; /* try to convert to float */ + if (!tonumber(obj, &n)) /* cannot convert to float? */ + return 0; /* not a number */ + if (luai_numlt(0, n)) + { + /* if true, float is larger than max integer */ + *p = LUA_MAXINTEGER; + if (step < 0) *stopnow = 1; + } + else + { + /* float is smaller than min integer */ + *p = LUA_MININTEGER; + if (step >= 0) *stopnow = 1; + } + } + return 1; } @@ -157,39 +171,51 @@ static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, ** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to ** t[k] entry (which must be nil). */ -void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, - const TValue *slot) { - int loop; /* counter to avoid infinite loops */ - const TValue *tm; /* metamethod */ - for (loop = 0; loop < MAXTAGLOOP; loop++) { - if (slot == NULL) { /* 't' is not a table? */ - lua_assert(!ttistable(t)); - tm = luaT_gettmbyobj(L, t, TM_INDEX); - if (ttisnil(tm)) - luaG_typeerror(L, t, "index"); /* no metamethod */ - /* else will try the metamethod */ - } - else { /* 't' is a table */ - lua_assert(ttisnil(slot)); - tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */ - if (tm == NULL) { /* no metamethod? */ - setnilvalue(val); /* result is nil */ - return; - } - /* else will try the metamethod */ - } - if (ttisfunction(tm)) { /* is metamethod a function? */ - luaT_callTM(L, tm, t, key, val, 1); /* call it */ - return; - } - t = tm; /* else try to access 'tm[key]' */ - if (luaV_fastget(L,t,key,slot,luaH_get)) { /* fast track? */ - setobj2s(L, val, slot); /* done */ - return; - } - /* else repeat (tail call 'luaV_finishget') */ - } - luaG_runerror(L, "'__index' chain too long; possible loop"); +void luaV_finishget(lua_State* L, const TValue* t, TValue* key, StkId val, + const TValue* slot) +{ + int loop; /* counter to avoid infinite loops */ + const TValue* tm; /* metamethod */ + for (loop = 0; loop < MAXTAGLOOP; loop++) + { + if (slot == NULL) + { + /* 't' is not a table? */ + lua_assert(!ttistable(t)); + tm = luaT_gettmbyobj(L, t, TM_INDEX); + if (ttisnil(tm)) + luaG_typeerror(L, t, "index"); /* no metamethod */ + /* else will try the metamethod */ + } + else + { + /* 't' is a table */ + lua_assert(ttisnil(slot)); + tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */ + if (tm == NULL) + { + /* no metamethod? */ + setnilvalue(val); /* result is nil */ + return; + } + /* else will try the metamethod */ + } + if (ttisfunction(tm)) + { + /* is metamethod a function? */ + luaT_callTM(L, tm, t, key, val, 1); /* call it */ + return; + } + t = tm; /* else try to access 'tm[key]' */ + if (luaV_fastget(L, t, key, slot, luaH_get)) + { + /* fast track? */ + setobj2s(L, val, slot); /* done */ + return; + } + /* else repeat (tail call 'luaV_finishget') */ + } + luaG_runerror(L, "'__index' chain too long; possible loop"); } @@ -200,41 +226,50 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, ** entry. (The value at 'slot' must be nil, otherwise 'luaV_fastset' ** would have done the job.) */ -void luaV_finishset (lua_State *L, const TValue *t, TValue *key, - StkId val, const TValue *slot) { - int loop; /* counter to avoid infinite loops */ - for (loop = 0; loop < MAXTAGLOOP; loop++) { - const TValue *tm; /* '__newindex' metamethod */ - if (slot != NULL) { /* is 't' a table? */ - Table *h = hvalue(t); /* save 't' table */ - lua_assert(ttisnil(slot)); /* old value must be nil */ - tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ - if (tm == NULL) { /* no metamethod? */ - if (slot == luaO_nilobject) /* no previous entry? */ - slot = luaH_newkey(L, h, key); /* create one */ - /* no metamethod and (now) there is an entry with given key */ - setobj2t(L, cast(TValue *, slot), val); /* set its new value */ - invalidateTMcache(h); - luaC_barrierback(L, h, val); - return; - } - /* else will try the metamethod */ - } - else { /* not a table; check metamethod */ - if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) - luaG_typeerror(L, t, "index"); - } - /* try the metamethod */ - if (ttisfunction(tm)) { - luaT_callTM(L, tm, t, key, val, 0); - return; - } - t = tm; /* else repeat assignment over 'tm' */ - if (luaV_fastset(L, t, key, slot, luaH_get, val)) - return; /* done */ - /* else loop */ - } - luaG_runerror(L, "'__newindex' chain too long; possible loop"); +void luaV_finishset(lua_State* L, const TValue* t, TValue* key, + StkId val, const TValue* slot) +{ + int loop; /* counter to avoid infinite loops */ + for (loop = 0; loop < MAXTAGLOOP; loop++) + { + const TValue* tm; /* '__newindex' metamethod */ + if (slot != NULL) + { + /* is 't' a table? */ + Table* h = hvalue(t); /* save 't' table */ + lua_assert(ttisnil(slot)); /* old value must be nil */ + tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ + if (tm == NULL) + { + /* no metamethod? */ + if (slot == luaO_nilobject) /* no previous entry? */ + slot = luaH_newkey(L, h, key); /* create one */ + /* no metamethod and (now) there is an entry with given key */ + setobj2t(L, cast(TValue *, slot), val); /* set its new value */ + invalidateTMcache(h); + luaC_barrierback(L, h, val); + return; + } + /* else will try the metamethod */ + } + else + { + /* not a table; check metamethod */ + if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) + luaG_typeerror(L, t, "index"); + } + /* try the metamethod */ + if (ttisfunction(tm)) + { + luaT_callTM(L, tm, t, key, val, 0); + return; + } + t = tm; /* else repeat assignment over 'tm' */ + if (luaV_fastset(L, t, key, slot, luaH_get, val)) + return; /* done */ + /* else loop */ + } + luaG_runerror(L, "'__newindex' chain too long; possible loop"); } @@ -245,26 +280,34 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key, ** and it uses 'strcoll' (to respect locales) for each segments ** of the strings. */ -static int l_strcmp (const TString *ls, const TString *rs) { - const char *l = getstr(ls); - size_t ll = tsslen(ls); - const char *r = getstr(rs); - size_t lr = tsslen(rs); - for (;;) { /* for each segment */ - int temp = strcoll(l, r); - if (temp != 0) /* not equal? */ - return temp; /* done */ - else { /* strings are equal up to a '\0' */ - size_t len = strlen(l); /* index of first '\0' in both strings */ - if (len == lr) /* 'rs' is finished? */ - return (len == ll) ? 0 : 1; /* check 'ls' */ - else if (len == ll) /* 'ls' is finished? */ - return -1; /* 'ls' is smaller than 'rs' ('rs' is not finished) */ - /* both strings longer than 'len'; go on comparing after the '\0' */ - len++; - l += len; ll -= len; r += len; lr -= len; - } - } +static int l_strcmp(const TString* ls, const TString* rs) +{ + const char* l = getstr(ls); + size_t ll = tsslen(ls); + const char* r = getstr(rs); + size_t lr = tsslen(rs); + for (;;) + { + /* for each segment */ + int temp = strcoll(l, r); + if (temp != 0) /* not equal? */ + return temp; /* done */ + else + { + /* strings are equal up to a '\0' */ + size_t len = strlen(l); /* index of first '\0' in both strings */ + if (len == lr) /* 'rs' is finished? */ + return (len == ll) ? 0 : 1; /* check 'ls' */ + else if (len == ll) /* 'ls' is finished? */ + return -1; /* 'ls' is smaller than 'rs' ('rs' is not finished) */ + /* both strings longer than 'len'; go on comparing after the '\0' */ + len++; + l += len; + ll -= len; + r += len; + lr -= len; + } + } } @@ -278,18 +321,20 @@ static int l_strcmp (const TString *ls, const TString *rs) { ** truncated is irrelevant.) When 'f' is NaN, comparisons must result ** in false. */ -static int LTintfloat (lua_Integer i, lua_Number f) { +static int LTintfloat(lua_Integer i, lua_Number f) +{ #if defined(l_intfitsf) - if (!l_intfitsf(i)) { - if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */ - return 1; /* f >= maxint + 1 > i */ - else if (f > cast_num(LUA_MININTEGER)) /* minint < f <= maxint ? */ - return (i < cast(lua_Integer, f)); /* compare them as integers */ - else /* f <= minint <= i (or 'f' is NaN) --> not(i < f) */ - return 0; - } + if (!l_intfitsf(i)) + { + if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */ + return 1; /* f >= maxint + 1 > i */ + else if (f > cast_num(LUA_MININTEGER)) /* minint < f <= maxint ? */ + return (i < cast(lua_Integer, f)); /* compare them as integers */ + else /* f <= minint <= i (or 'f' is NaN) --> not(i < f) */ + return 0; + } #endif - return luai_numlt(cast_num(i), f); /* compare them as floats */ + return luai_numlt(cast_num(i), f); /* compare them as floats */ } @@ -297,79 +342,88 @@ static int LTintfloat (lua_Integer i, lua_Number f) { ** Check whether integer 'i' is less than or equal to float 'f'. ** See comments on previous function. */ -static int LEintfloat (lua_Integer i, lua_Number f) { +static int LEintfloat(lua_Integer i, lua_Number f) +{ #if defined(l_intfitsf) - if (!l_intfitsf(i)) { - if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */ - return 1; /* f >= maxint + 1 > i */ - else if (f >= cast_num(LUA_MININTEGER)) /* minint <= f <= maxint ? */ - return (i <= cast(lua_Integer, f)); /* compare them as integers */ - else /* f < minint <= i (or 'f' is NaN) --> not(i <= f) */ - return 0; - } + if (!l_intfitsf(i)) + { + if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */ + return 1; /* f >= maxint + 1 > i */ + else if (f >= cast_num(LUA_MININTEGER)) /* minint <= f <= maxint ? */ + return (i <= cast(lua_Integer, f)); /* compare them as integers */ + else /* f < minint <= i (or 'f' is NaN) --> not(i <= f) */ + return 0; + } #endif - return luai_numle(cast_num(i), f); /* compare them as floats */ + return luai_numle(cast_num(i), f); /* compare them as floats */ } /* ** Return 'l < r', for numbers. */ -static int LTnum (const TValue *l, const TValue *r) { - if (ttisinteger(l)) { - lua_Integer li = ivalue(l); - if (ttisinteger(r)) - return li < ivalue(r); /* both are integers */ - else /* 'l' is int and 'r' is float */ - return LTintfloat(li, fltvalue(r)); /* l < r ? */ - } - else { - lua_Number lf = fltvalue(l); /* 'l' must be float */ - if (ttisfloat(r)) - return luai_numlt(lf, fltvalue(r)); /* both are float */ - else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */ - return 0; /* NaN < i is always false */ - else /* without NaN, (l < r) <--> not(r <= l) */ - return !LEintfloat(ivalue(r), lf); /* not (r <= l) ? */ - } +static int LTnum(const TValue* l, const TValue* r) +{ + if (ttisinteger(l)) + { + lua_Integer li = ivalue(l); + if (ttisinteger(r)) + return li < ivalue(r); /* both are integers */ + else /* 'l' is int and 'r' is float */ + return LTintfloat(li, fltvalue(r)); /* l < r ? */ + } + else + { + lua_Number lf = fltvalue(l); /* 'l' must be float */ + if (ttisfloat(r)) + return luai_numlt(lf, fltvalue(r)); /* both are float */ + else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */ + return 0; /* NaN < i is always false */ + else /* without NaN, (l < r) <--> not(r <= l) */ + return !LEintfloat(ivalue(r), lf); /* not (r <= l) ? */ + } } /* ** Return 'l <= r', for numbers. */ -static int LEnum (const TValue *l, const TValue *r) { - if (ttisinteger(l)) { - lua_Integer li = ivalue(l); - if (ttisinteger(r)) - return li <= ivalue(r); /* both are integers */ - else /* 'l' is int and 'r' is float */ - return LEintfloat(li, fltvalue(r)); /* l <= r ? */ - } - else { - lua_Number lf = fltvalue(l); /* 'l' must be float */ - if (ttisfloat(r)) - return luai_numle(lf, fltvalue(r)); /* both are float */ - else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */ - return 0; /* NaN <= i is always false */ - else /* without NaN, (l <= r) <--> not(r < l) */ - return !LTintfloat(ivalue(r), lf); /* not (r < l) ? */ - } +static int LEnum(const TValue* l, const TValue* r) +{ + if (ttisinteger(l)) + { + lua_Integer li = ivalue(l); + if (ttisinteger(r)) + return li <= ivalue(r); /* both are integers */ + else /* 'l' is int and 'r' is float */ + return LEintfloat(li, fltvalue(r)); /* l <= r ? */ + } + else + { + lua_Number lf = fltvalue(l); /* 'l' must be float */ + if (ttisfloat(r)) + return luai_numle(lf, fltvalue(r)); /* both are float */ + else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */ + return 0; /* NaN <= i is always false */ + else /* without NaN, (l <= r) <--> not(r < l) */ + return !LTintfloat(ivalue(r), lf); /* not (r < l) ? */ + } } /* ** Main operation less than; return 'l < r'. */ -int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { - int res; - if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */ - return LTnum(l, r); - else if (ttisstring(l) && ttisstring(r)) /* both are strings? */ - return l_strcmp(tsvalue(l), tsvalue(r)) < 0; - else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) /* no metamethod? */ - luaG_ordererror(L, l, r); /* error */ - return res; +int luaV_lessthan(lua_State* L, const TValue* l, const TValue* r) +{ + int res; + if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */ + return LTnum(l, r); + else if (ttisstring(l) && ttisstring(r)) /* both are strings? */ + return l_strcmp(tsvalue(l), tsvalue(r)) < 0; + else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) /* no metamethod? */ + luaG_ordererror(L, l, r); /* error */ + return res; } @@ -381,22 +435,25 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { ** about it (to negate the result of r= 0) /* try 'le' */ - return res; - else { /* try 'lt': */ - L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ - res = luaT_callorderTM(L, r, l, TM_LT); - L->ci->callstatus ^= CIST_LEQ; /* clear mark */ - if (res < 0) - luaG_ordererror(L, l, r); - return !res; /* result is negated */ - } +int luaV_lessequal(lua_State* L, const TValue* l, const TValue* r) +{ + int res; + if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */ + return LEnum(l, r); + else if (ttisstring(l) && ttisstring(r)) /* both are strings? */ + return l_strcmp(tsvalue(l), tsvalue(r)) <= 0; + else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* try 'le' */ + return res; + else + { + /* try 'lt': */ + L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ + res = luaT_callorderTM(L, r, l, TM_LT); + L->ci->callstatus ^= CIST_LEQ; /* clear mark */ + if (res < 0) + luaG_ordererror(L, l, r); + return !res; /* result is negated */ + } } @@ -404,49 +461,57 @@ int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { ** Main operation for equality of Lua values; return 't1 == t2'. ** L == NULL means raw equality (no metamethods) */ -int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { - const TValue *tm; - if (ttype(t1) != ttype(t2)) { /* not the same variant? */ - if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER) - return 0; /* only numbers can be equal with different variants */ - else { /* two numbers with different variants */ - lua_Integer i1, i2; /* compare them as integers */ - return (tointeger(t1, &i1) && tointeger(t2, &i2) && i1 == i2); - } - } - /* values have same type and same variant */ - switch (ttype(t1)) { - case LUA_TNIL: return 1; - case LUA_TNUMINT: return (ivalue(t1) == ivalue(t2)); - case LUA_TNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2)); - case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ - case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); - case LUA_TLCF: return fvalue(t1) == fvalue(t2); - case LUA_TSHRSTR: return eqshrstr(tsvalue(t1), tsvalue(t2)); - case LUA_TLNGSTR: return luaS_eqlngstr(tsvalue(t1), tsvalue(t2)); - case LUA_TUSERDATA: { - if (uvalue(t1) == uvalue(t2)) return 1; - else if (L == NULL) return 0; - tm = fasttm(L, uvalue(t1)->metatable, TM_EQ); - if (tm == NULL) - tm = fasttm(L, uvalue(t2)->metatable, TM_EQ); - break; /* will try TM */ - } - case LUA_TTABLE: { - if (hvalue(t1) == hvalue(t2)) return 1; - else if (L == NULL) return 0; - tm = fasttm(L, hvalue(t1)->metatable, TM_EQ); - if (tm == NULL) - tm = fasttm(L, hvalue(t2)->metatable, TM_EQ); - break; /* will try TM */ - } - default: - return gcvalue(t1) == gcvalue(t2); - } - if (tm == NULL) /* no TM? */ - return 0; /* objects are different */ - luaT_callTM(L, tm, t1, t2, L->top, 1); /* call TM */ - return !l_isfalse(L->top); +int luaV_equalobj(lua_State* L, const TValue* t1, const TValue* t2) +{ + const TValue* tm; + if (ttype(t1) != ttype(t2)) + { + /* not the same variant? */ + if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER) + return 0; /* only numbers can be equal with different variants */ + else + { + /* two numbers with different variants */ + lua_Integer i1, i2; /* compare them as integers */ + return (tointeger(t1, &i1) && tointeger(t2, &i2) && i1 == i2); + } + } + /* values have same type and same variant */ + switch (ttype(t1)) + { + case LUA_TNIL: return 1; + case LUA_TNUMINT: return (ivalue(t1) == ivalue(t2)); + case LUA_TNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2)); + case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ + case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); + case LUA_TLCF: return fvalue(t1) == fvalue(t2); + case LUA_TSHRSTR: return eqshrstr(tsvalue(t1), tsvalue(t2)); + case LUA_TLNGSTR: return luaS_eqlngstr(tsvalue(t1), tsvalue(t2)); + case LUA_TUSERDATA: + { + if (uvalue(t1) == uvalue(t2)) return 1; + else if (L == NULL) return 0; + tm = fasttm(L, uvalue(t1)->metatable, TM_EQ); + if (tm == NULL) + tm = fasttm(L, uvalue(t2)->metatable, TM_EQ); + break; /* will try TM */ + } + case LUA_TTABLE: + { + if (hvalue(t1) == hvalue(t2)) return 1; + else if (L == NULL) return 0; + tm = fasttm(L, hvalue(t1)->metatable, TM_EQ); + if (tm == NULL) + tm = fasttm(L, hvalue(t2)->metatable, TM_EQ); + break; /* will try TM */ + } + default: + return gcvalue(t1) == gcvalue(t2); + } + if (tm == NULL) /* no TM? */ + return 0; /* objects are different */ + luaT_callTM(L, tm, t1, t2, L->top, 1); /* call TM */ + return !l_isfalse(L->top); } @@ -457,13 +522,16 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { #define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0) /* copy strings in stack from top - n up to top - 1 to buffer */ -static void copy2buff (StkId top, int n, char *buff) { - size_t tl = 0; /* size already copied */ - do { - size_t l = vslen(top - n); /* length of string being copied */ - memcpy(buff + tl, svalue(top - n), l * sizeof(char)); - tl += l; - } while (--n > 0); +static void copy2buff(StkId top, int n, char* buff) +{ + size_t tl = 0; /* size already copied */ + do + { + size_t l = vslen(top - n); /* length of string being copied */ + memcpy(buff + tl, svalue(top - n), l * sizeof(char)); + tl += l; + } + while (--n > 0); } @@ -471,75 +539,93 @@ static void copy2buff (StkId top, int n, char *buff) { ** Main operation for concatenation: concat 'total' values in the stack, ** from 'L->top - total' up to 'L->top - 1'. */ -void luaV_concat (lua_State *L, int total) { - lua_assert(total >= 2); - do { - StkId top = L->top; - int n = 2; /* number of elements handled in this pass (at least 2) */ - if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1)) - luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT); - else if (isemptystr(top - 1)) /* second operand is empty? */ - cast_void(tostring(L, top - 2)); /* result is first operand */ - else if (isemptystr(top - 2)) { /* first operand is an empty string? */ - setobjs2s(L, top - 2, top - 1); /* result is second op. */ - } - else { - /* at least two non-empty string values; get as many as possible */ - size_t tl = vslen(top - 1); - TString *ts; - /* collect total length and number of strings */ - for (n = 1; n < total && tostring(L, top - n - 1); n++) { - size_t l = vslen(top - n - 1); - if (l >= (MAX_SIZE/sizeof(char)) - tl) - luaG_runerror(L, "string length overflow"); - tl += l; - } - if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */ - char buff[LUAI_MAXSHORTLEN]; - copy2buff(top, n, buff); /* copy strings to buffer */ - ts = luaS_newlstr(L, buff, tl); - } - else { /* long string; copy strings directly to final result */ - ts = luaS_createlngstrobj(L, tl); - copy2buff(top, n, getstr(ts)); - } - setsvalue2s(L, top - n, ts); /* create result */ - } - total -= n-1; /* got 'n' strings to create 1 new */ - L->top -= n-1; /* popped 'n' strings and pushed one */ - } while (total > 1); /* repeat until only 1 result left */ +void luaV_concat(lua_State* L, int total) +{ + lua_assert(total >= 2); + do + { + StkId top = L->top; + int n = 2; /* number of elements handled in this pass (at least 2) */ + if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1)) + luaT_trybinTM(L, top - 2, top - 1, top - 2, TM_CONCAT); + else if (isemptystr(top - 1)) /* second operand is empty? */ + cast_void(tostring(L, top - 2)); /* result is first operand */ + else if (isemptystr(top - 2)) + { + /* first operand is an empty string? */ + setobjs2s(L, top - 2, top - 1); /* result is second op. */ + } + else + { + /* at least two non-empty string values; get as many as possible */ + size_t tl = vslen(top - 1); + TString* ts; + /* collect total length and number of strings */ + for (n = 1; n < total && tostring(L, top - n - 1); n++) + { + size_t l = vslen(top - n - 1); + if (l >= (MAX_SIZE / sizeof(char)) - tl) + luaG_runerror(L, "string length overflow"); + tl += l; + } + if (tl <= LUAI_MAXSHORTLEN) + { + /* is result a short string? */ + char buff[LUAI_MAXSHORTLEN]; + copy2buff(top, n, buff); /* copy strings to buffer */ + ts = luaS_newlstr(L, buff, tl); + } + else + { + /* long string; copy strings directly to final result */ + ts = luaS_createlngstrobj(L, tl); + copy2buff(top, n, getstr(ts)); + } + setsvalue2s(L, top - n, ts); /* create result */ + } + total -= n - 1; /* got 'n' strings to create 1 new */ + L->top -= n - 1; /* popped 'n' strings and pushed one */ + } + while (total > 1); /* repeat until only 1 result left */ } /* ** Main operation 'ra' = #rb'. */ -void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { - const TValue *tm; - switch (ttype(rb)) { - case LUA_TTABLE: { - Table *h = hvalue(rb); - tm = fasttm(L, h->metatable, TM_LEN); - if (tm) break; /* metamethod? break switch to call it */ - setivalue(ra, luaH_getn(h)); /* else primitive len */ - return; - } - case LUA_TSHRSTR: { - setivalue(ra, tsvalue(rb)->shrlen); - return; - } - case LUA_TLNGSTR: { - setivalue(ra, tsvalue(rb)->u.lnglen); - return; - } - default: { /* try metamethod */ - tm = luaT_gettmbyobj(L, rb, TM_LEN); - if (ttisnil(tm)) /* no metamethod? */ - luaG_typeerror(L, rb, "get length of"); - break; - } - } - luaT_callTM(L, tm, rb, rb, ra, 1); +void luaV_objlen(lua_State* L, StkId ra, const TValue* rb) +{ + const TValue* tm; + switch (ttype(rb)) + { + case LUA_TTABLE: + { + Table* h = hvalue(rb); + tm = fasttm(L, h->metatable, TM_LEN); + if (tm) break; /* metamethod? break switch to call it */ + setivalue(ra, luaH_getn(h)); /* else primitive len */ + return; + } + case LUA_TSHRSTR: + { + setivalue(ra, tsvalue(rb)->shrlen); + return; + } + case LUA_TLNGSTR: + { + setivalue(ra, tsvalue(rb)->u.lnglen); + return; + } + default: + { + /* try metamethod */ + tm = luaT_gettmbyobj(L, rb, TM_LEN); + if (ttisnil(tm)) /* no metamethod? */ + luaG_typeerror(L, rb, "get length of"); + break; + } + } + luaT_callTM(L, tm, rb, rb, ra, 1); } @@ -549,18 +635,22 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { ** 'floor(q) == trunc(q)' when 'q >= 0' or when 'q' is integer, ** otherwise 'floor(q) == trunc(q) - 1'. */ -lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) { - if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */ - if (n == 0) - luaG_runerror(L, "attempt to divide by zero"); - return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */ - } - else { - lua_Integer q = m / n; /* perform C division */ - if ((m ^ n) < 0 && m % n != 0) /* 'm/n' would be negative non-integer? */ - q -= 1; /* correct result for different rounding */ - return q; - } +lua_Integer luaV_div(lua_State* L, lua_Integer m, lua_Integer n) +{ + if (l_castS2U(n) + 1u <= 1u) + { + /* special cases: -1 or 0 */ + if (n == 0) + luaG_runerror(L, "attempt to divide by zero"); + return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */ + } + else + { + lua_Integer q = m / n; /* perform C division */ + if ((m ^ n) < 0 && m % n != 0) /* 'm/n' would be negative non-integer? */ + q -= 1; /* correct result for different rounding */ + return q; + } } @@ -569,18 +659,22 @@ lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) { ** negative operands follows C99 behavior. See previous comment ** about luaV_div.) */ -lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) { - if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */ - if (n == 0) - luaG_runerror(L, "attempt to perform 'n%%0'"); - return 0; /* m % -1 == 0; avoid overflow with 0x80000...%-1 */ - } - else { - lua_Integer r = m % n; - if (r != 0 && (m ^ n) < 0) /* 'm/n' would be non-integer negative? */ - r += n; /* correct result for different rounding */ - return r; - } +lua_Integer luaV_mod(lua_State* L, lua_Integer m, lua_Integer n) +{ + if (l_castS2U(n) + 1u <= 1u) + { + /* special cases: -1 or 0 */ + if (n == 0) + luaG_runerror(L, "attempt to perform 'n%%0'"); + return 0; /* m % -1 == 0; avoid overflow with 0x80000...%-1 */ + } + else + { + lua_Integer r = m % n; + if (r != 0 && (m ^ n) < 0) /* 'm/n' would be non-integer negative? */ + r += n; /* correct result for different rounding */ + return r; + } } @@ -590,15 +684,20 @@ lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) { /* ** Shift left operation. (Shift right just negates 'y'.) */ -lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) { - if (y < 0) { /* shift right? */ - if (y <= -NBITS) return 0; - else return intop(>>, x, -y); - } - else { /* shift left */ - if (y >= NBITS) return 0; - else return intop(<<, x, y); - } +lua_Integer luaV_shiftl(lua_Integer x, lua_Integer y) +{ + if (y < 0) + { + /* shift right? */ + if (y <= -NBITS) return 0; + else return intop(>>, x, -y); + } + else + { + /* shift left */ + if (y >= NBITS) return 0; + else return intop(<<, x, y); + } } @@ -607,19 +706,24 @@ lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) { ** whether there is a cached closure with the same upvalues needed by ** new closure to be created. */ -static LClosure *getcached (Proto *p, UpVal **encup, StkId base) { - LClosure *c = p->cache; - if (c != NULL) { /* is there a cached closure? */ - int nup = p->sizeupvalues; - Upvaldesc *uv = p->upvalues; - int i; - for (i = 0; i < nup; i++) { /* check whether it has right upvalues */ - TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v; - if (c->upvals[i]->v != v) - return NULL; /* wrong upvalue; cannot reuse closure */ - } - } - return c; /* return cached closure (or NULL if no cached closure) */ +static LClosure* getcached(Proto* p, UpVal** encup, StkId base) +{ + LClosure* c = p->cache; + if (c != NULL) + { + /* is there a cached closure? */ + int nup = p->sizeupvalues; + Upvaldesc* uv = p->upvalues; + int i; + for (i = 0; i < nup; i++) + { + /* check whether it has right upvalues */ + TValue* v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v; + if (c->upvals[i]->v != v) + return NULL; /* wrong upvalue; cannot reuse closure */ + } + } + return c; /* return cached closure (or NULL if no cached closure) */ } @@ -629,90 +733,120 @@ static LClosure *getcached (Proto *p, UpVal **encup, StkId base) { ** already black (which means that 'cache' was already cleared by the ** GC). */ -static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, - StkId ra) { - int nup = p->sizeupvalues; - Upvaldesc *uv = p->upvalues; - int i; - LClosure *ncl = luaF_newLclosure(L, nup); - ncl->p = p; - setclLvalue(L, ra, ncl); /* anchor new closure in stack */ - for (i = 0; i < nup; i++) { /* fill in its upvalues */ - if (uv[i].instack) /* upvalue refers to local variable? */ - ncl->upvals[i] = luaF_findupval(L, base + uv[i].idx); - else /* get upvalue from enclosing function */ - ncl->upvals[i] = encup[uv[i].idx]; - ncl->upvals[i]->refcount++; - /* new closure is white, so we do not need a barrier here */ - } - if (!isblack(p)) /* cache will not break GC invariant? */ - p->cache = ncl; /* save it on cache for reuse */ +static void pushclosure(lua_State* L, Proto* p, UpVal** encup, StkId base, + StkId ra) +{ + int nup = p->sizeupvalues; + Upvaldesc* uv = p->upvalues; + int i; + LClosure* ncl = luaF_newLclosure(L, nup); + ncl->p = p; + setclLvalue(L, ra, ncl); /* anchor new closure in stack */ + for (i = 0; i < nup; i++) + { + /* fill in its upvalues */ + if (uv[i].instack) /* upvalue refers to local variable? */ + ncl->upvals[i] = luaF_findupval(L, base + uv[i].idx); + else /* get upvalue from enclosing function */ + ncl->upvals[i] = encup[uv[i].idx]; + ncl->upvals[i]->refcount++; + /* new closure is white, so we do not need a barrier here */ + } + if (!isblack(p)) /* cache will not break GC invariant? */ + p->cache = ncl; /* save it on cache for reuse */ } /* ** finish execution of an opcode interrupted by an yield */ -void luaV_finishOp (lua_State *L) { - CallInfo *ci = L->ci; - StkId base = ci->u.l.base; - Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ - OpCode op = GET_OPCODE(inst); - switch (op) { /* finish its execution */ - case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_IDIV: - case OP_BAND: case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: - case OP_MOD: case OP_POW: - case OP_UNM: case OP_BNOT: case OP_LEN: - case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { - setobjs2s(L, base + GETARG_A(inst), --L->top); - break; - } - case OP_LE: case OP_LT: case OP_EQ: { - int res = !l_isfalse(L->top - 1); - L->top--; - if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */ - lua_assert(op == OP_LE); - ci->callstatus ^= CIST_LEQ; /* clear mark */ - res = !res; /* negate result */ - } - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); - if (res != GETARG_A(inst)) /* condition failed? */ - ci->u.l.savedpc++; /* skip jump instruction */ - break; - } - case OP_CONCAT: { - StkId top = L->top - 1; /* top when 'luaT_trybinTM' was called */ - int b = GETARG_B(inst); /* first element to concatenate */ - int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */ - setobj2s(L, top - 2, top); /* put TM result in proper position */ - if (total > 1) { /* are there elements to concat? */ - L->top = top - 1; /* top is one after last element (at top-2) */ - luaV_concat(L, total); /* concat them (may yield again) */ - } - /* move final result to final position */ - setobj2s(L, ci->u.l.base + GETARG_A(inst), L->top - 1); - L->top = ci->top; /* restore top */ - break; - } - case OP_TFORCALL: { - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); - L->top = ci->top; /* correct top */ - break; - } - case OP_CALL: { - if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ - L->top = ci->top; /* adjust results */ - break; - } - case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: - break; - default: lua_assert(0); - } +void luaV_finishOp(lua_State* L) +{ + CallInfo* ci = L->ci; + StkId base = ci->u.l.base; + Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ + OpCode op = GET_OPCODE(inst); + switch (op) + { + /* finish its execution */ + case OP_ADD: + case OP_SUB: + case OP_MUL: + case OP_DIV: + case OP_IDIV: + case OP_BAND: + case OP_BOR: + case OP_BXOR: + case OP_SHL: + case OP_SHR: + case OP_MOD: + case OP_POW: + case OP_UNM: + case OP_BNOT: + case OP_LEN: + case OP_GETTABUP: + case OP_GETTABLE: + case OP_SELF: + { + setobjs2s(L, base + GETARG_A(inst), --L->top); + break; + } + case OP_LE: + case OP_LT: + case OP_EQ: + { + int res = !l_isfalse(L->top - 1); + L->top--; + if (ci->callstatus & CIST_LEQ) + { + /* "<=" using "<" instead? */ + lua_assert(op == OP_LE); + ci->callstatus ^= CIST_LEQ; /* clear mark */ + res = !res; /* negate result */ + } + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); + if (res != GETARG_A(inst)) /* condition failed? */ + ci->u.l.savedpc++; /* skip jump instruction */ + break; + } + case OP_CONCAT: + { + StkId top = L->top - 1; /* top when 'luaT_trybinTM' was called */ + int b = GETARG_B(inst); /* first element to concatenate */ + int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */ + setobj2s(L, top - 2, top); /* put TM result in proper position */ + if (total > 1) + { + /* are there elements to concat? */ + L->top = top - 1; /* top is one after last element (at top-2) */ + luaV_concat(L, total); /* concat them (may yield again) */ + } + /* move final result to final position */ + setobj2s(L, ci->u.l.base + GETARG_A(inst), L->top - 1); + L->top = ci->top; /* restore top */ + break; + } + case OP_TFORCALL: + { + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); + L->top = ci->top; /* correct top */ + break; + } + case OP_CALL: + { + if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ + L->top = ci->top; /* adjust results */ + break; + } + case OP_TAILCALL: + case OP_SETTABUP: + case OP_SETTABLE: + break; + default: lua_assert(0); + } } - - /* ** {================================================================== ** Function 'luaV_execute': main interpreter loop @@ -782,541 +916,661 @@ void luaV_finishOp (lua_State *L) { Protect(luaV_finishset(L,t,k,v,slot)); } - -void luaV_execute (lua_State *L) { - CallInfo *ci = L->ci; - LClosure *cl; - TValue *k; - StkId base; - ci->callstatus |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */ - newframe: /* reentry point when frame changes (call/return) */ - lua_assert(ci == L->ci); - cl = clLvalue(ci->func); /* local reference to function's closure */ - k = cl->p->k; /* local reference to function's constant table */ - base = ci->u.l.base; /* local copy of function's base */ - /* main loop of interpreter */ - for (;;) { - Instruction i; - StkId ra; - vmfetch(); - vmdispatch (GET_OPCODE(i)) { - vmcase(OP_MOVE) { - setobjs2s(L, ra, RB(i)); - vmbreak; - } - vmcase(OP_LOADK) { - TValue *rb = k + GETARG_Bx(i); - setobj2s(L, ra, rb); - vmbreak; - } - vmcase(OP_LOADKX) { - TValue *rb; - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); - rb = k + GETARG_Ax(*ci->u.l.savedpc++); - setobj2s(L, ra, rb); - vmbreak; - } - vmcase(OP_LOADBOOL) { - setbvalue(ra, GETARG_B(i)); - if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */ - vmbreak; - } - vmcase(OP_LOADNIL) { - int b = GETARG_B(i); - do { - setnilvalue(ra++); - } while (b--); - vmbreak; - } - vmcase(OP_GETUPVAL) { - int b = GETARG_B(i); - setobj2s(L, ra, cl->upvals[b]->v); - vmbreak; - } - vmcase(OP_GETTABUP) { - TValue *upval = cl->upvals[GETARG_B(i)]->v; - TValue *rc = RKC(i); - gettableProtected(L, upval, rc, ra); - vmbreak; - } - vmcase(OP_GETTABLE) { - StkId rb = RB(i); - TValue *rc = RKC(i); - gettableProtected(L, rb, rc, ra); - vmbreak; - } - vmcase(OP_SETTABUP) { - TValue *upval = cl->upvals[GETARG_A(i)]->v; - TValue *rb = RKB(i); - TValue *rc = RKC(i); - settableProtected(L, upval, rb, rc); - vmbreak; - } - vmcase(OP_SETUPVAL) { - UpVal *uv = cl->upvals[GETARG_B(i)]; - setobj(L, uv->v, ra); - luaC_upvalbarrier(L, uv); - vmbreak; - } - vmcase(OP_SETTABLE) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - settableProtected(L, ra, rb, rc); - vmbreak; - } - vmcase(OP_NEWTABLE) { - int b = GETARG_B(i); - int c = GETARG_C(i); - Table *t = luaH_new(L); - sethvalue(L, ra, t); - if (b != 0 || c != 0) - luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c)); - checkGC(L, ra + 1); - vmbreak; - } - vmcase(OP_SELF) { - const TValue *aux; - StkId rb = RB(i); - TValue *rc = RKC(i); - TString *key = tsvalue(rc); /* key must be a string */ - setobjs2s(L, ra + 1, rb); - if (luaV_fastget(L, rb, key, aux, luaH_getstr)) { - setobj2s(L, ra, aux); - } - else Protect(luaV_finishget(L, rb, rc, ra, aux)); - vmbreak; - } - vmcase(OP_ADD) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Number nb; lua_Number nc; - if (ttisinteger(rb) && ttisinteger(rc)) { - lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); - setivalue(ra, intop(+, ib, ic)); - } - else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { - setfltvalue(ra, luai_numadd(L, nb, nc)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD)); } - vmbreak; - } - vmcase(OP_SUB) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Number nb; lua_Number nc; - if (ttisinteger(rb) && ttisinteger(rc)) { - lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); - setivalue(ra, intop(-, ib, ic)); - } - else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { - setfltvalue(ra, luai_numsub(L, nb, nc)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SUB)); } - vmbreak; - } - vmcase(OP_MUL) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Number nb; lua_Number nc; - if (ttisinteger(rb) && ttisinteger(rc)) { - lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); - setivalue(ra, intop(*, ib, ic)); - } - else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { - setfltvalue(ra, luai_nummul(L, nb, nc)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MUL)); } - vmbreak; - } - vmcase(OP_DIV) { /* float division (always with floats) */ - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Number nb; lua_Number nc; - if (tonumber(rb, &nb) && tonumber(rc, &nc)) { - setfltvalue(ra, luai_numdiv(L, nb, nc)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV)); } - vmbreak; - } - vmcase(OP_BAND) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Integer ib; lua_Integer ic; - if (tointeger(rb, &ib) && tointeger(rc, &ic)) { - setivalue(ra, intop(&, ib, ic)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BAND)); } - vmbreak; - } - vmcase(OP_BOR) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Integer ib; lua_Integer ic; - if (tointeger(rb, &ib) && tointeger(rc, &ic)) { - setivalue(ra, intop(|, ib, ic)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BOR)); } - vmbreak; - } - vmcase(OP_BXOR) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Integer ib; lua_Integer ic; - if (tointeger(rb, &ib) && tointeger(rc, &ic)) { - setivalue(ra, intop(^, ib, ic)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR)); } - vmbreak; - } - vmcase(OP_SHL) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Integer ib; lua_Integer ic; - if (tointeger(rb, &ib) && tointeger(rc, &ic)) { - setivalue(ra, luaV_shiftl(ib, ic)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL)); } - vmbreak; - } - vmcase(OP_SHR) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Integer ib; lua_Integer ic; - if (tointeger(rb, &ib) && tointeger(rc, &ic)) { - setivalue(ra, luaV_shiftl(ib, -ic)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHR)); } - vmbreak; - } - vmcase(OP_MOD) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Number nb; lua_Number nc; - if (ttisinteger(rb) && ttisinteger(rc)) { - lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); - setivalue(ra, luaV_mod(L, ib, ic)); - } - else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { - lua_Number m; - luai_nummod(L, nb, nc, m); - setfltvalue(ra, m); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD)); } - vmbreak; - } - vmcase(OP_IDIV) { /* floor division */ - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Number nb; lua_Number nc; - if (ttisinteger(rb) && ttisinteger(rc)) { - lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); - setivalue(ra, luaV_div(L, ib, ic)); - } - else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { - setfltvalue(ra, luai_numidiv(L, nb, nc)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); } - vmbreak; - } - vmcase(OP_POW) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Number nb; lua_Number nc; - if (tonumber(rb, &nb) && tonumber(rc, &nc)) { - setfltvalue(ra, luai_numpow(L, nb, nc)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW)); } - vmbreak; - } - vmcase(OP_UNM) { - TValue *rb = RB(i); - lua_Number nb; - if (ttisinteger(rb)) { - lua_Integer ib = ivalue(rb); - setivalue(ra, intop(-, 0, ib)); - } - else if (tonumber(rb, &nb)) { - setfltvalue(ra, luai_numunm(L, nb)); - } - else { - Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM)); - } - vmbreak; - } - vmcase(OP_BNOT) { - TValue *rb = RB(i); - lua_Integer ib; - if (tointeger(rb, &ib)) { - setivalue(ra, intop(^, ~l_castS2U(0), ib)); - } - else { - Protect(luaT_trybinTM(L, rb, rb, ra, TM_BNOT)); - } - vmbreak; - } - vmcase(OP_NOT) { - TValue *rb = RB(i); - int res = l_isfalse(rb); /* next assignment may change this value */ - setbvalue(ra, res); - vmbreak; - } - vmcase(OP_LEN) { - Protect(luaV_objlen(L, ra, RB(i))); - vmbreak; - } - vmcase(OP_CONCAT) { - int b = GETARG_B(i); - int c = GETARG_C(i); - StkId rb; - L->top = base + c + 1; /* mark the end of concat operands */ - Protect(luaV_concat(L, c - b + 1)); - ra = RA(i); /* 'luaV_concat' may invoke TMs and move the stack */ - rb = base + b; - setobjs2s(L, ra, rb); - checkGC(L, (ra >= rb ? ra + 1 : rb)); - L->top = ci->top; /* restore top */ - vmbreak; - } - vmcase(OP_JMP) { - dojump(ci, i, 0); - vmbreak; - } - vmcase(OP_EQ) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - Protect( - if (luaV_equalobj(L, rb, rc) != GETARG_A(i)) - ci->u.l.savedpc++; - else - donextjump(ci); - ) - vmbreak; - } - vmcase(OP_LT) { - Protect( - if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) - ci->u.l.savedpc++; - else - donextjump(ci); - ) - vmbreak; - } - vmcase(OP_LE) { - Protect( - if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) - ci->u.l.savedpc++; - else - donextjump(ci); - ) - vmbreak; - } - vmcase(OP_TEST) { - if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra)) - ci->u.l.savedpc++; - else - donextjump(ci); - vmbreak; - } - vmcase(OP_TESTSET) { - TValue *rb = RB(i); - if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb)) - ci->u.l.savedpc++; - else { - setobjs2s(L, ra, rb); - donextjump(ci); - } - vmbreak; - } - vmcase(OP_CALL) { - int b = GETARG_B(i); - int nresults = GETARG_C(i) - 1; - if (b != 0) L->top = ra+b; /* else previous instruction set top */ - if (luaD_precall(L, ra, nresults)) { /* C function? */ - if (nresults >= 0) - L->top = ci->top; /* adjust results */ - Protect((void)0); /* update 'base' */ - } - else { /* Lua function */ - ci = L->ci; - goto newframe; /* restart luaV_execute over new Lua function */ - } - vmbreak; - } - vmcase(OP_TAILCALL) { - int b = GETARG_B(i); - if (b != 0) L->top = ra+b; /* else previous instruction set top */ - lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); - if (luaD_precall(L, ra, LUA_MULTRET)) { /* C function? */ - Protect((void)0); /* update 'base' */ - } - else { - /* tail call: put called frame (n) in place of caller one (o) */ - CallInfo *nci = L->ci; /* called frame */ - CallInfo *oci = nci->previous; /* caller frame */ - StkId nfunc = nci->func; /* called function */ - StkId ofunc = oci->func; /* caller function */ - /* last stack slot filled by 'precall' */ - StkId lim = nci->u.l.base + getproto(nfunc)->numparams; - int aux; - /* close all upvalues from previous call */ - if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base); - /* move new frame into old one */ - for (aux = 0; nfunc + aux < lim; aux++) - setobjs2s(L, ofunc + aux, nfunc + aux); - oci->u.l.base = ofunc + (nci->u.l.base - nfunc); /* correct base */ - oci->top = L->top = ofunc + (L->top - nfunc); /* correct top */ - oci->u.l.savedpc = nci->u.l.savedpc; - oci->callstatus |= CIST_TAIL; /* function was tail called */ - ci = L->ci = oci; /* remove new frame */ - lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize); - goto newframe; /* restart luaV_execute over new Lua function */ - } - vmbreak; - } - vmcase(OP_RETURN) { - int b = GETARG_B(i); - if (cl->p->sizep > 0) luaF_close(L, base); - b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))); - if (ci->callstatus & CIST_FRESH) /* local 'ci' still from callee */ - return; /* external invocation: return */ - else { /* invocation via reentry: continue execution */ - ci = L->ci; - if (b) L->top = ci->top; - lua_assert(isLua(ci)); - lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL); - goto newframe; /* restart luaV_execute over new Lua function */ - } - } - vmcase(OP_FORLOOP) { - if (ttisinteger(ra)) { /* integer loop? */ - lua_Integer step = ivalue(ra + 2); - lua_Integer idx = intop(+, ivalue(ra), step); /* increment index */ - lua_Integer limit = ivalue(ra + 1); - if ((0 < step) ? (idx <= limit) : (limit <= idx)) { - ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ - chgivalue(ra, idx); /* update internal index... */ - setivalue(ra + 3, idx); /* ...and external index */ - } - } - else { /* floating loop */ - lua_Number step = fltvalue(ra + 2); - lua_Number idx = luai_numadd(L, fltvalue(ra), step); /* inc. index */ - lua_Number limit = fltvalue(ra + 1); - if (luai_numlt(0, step) ? luai_numle(idx, limit) - : luai_numle(limit, idx)) { - ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ - chgfltvalue(ra, idx); /* update internal index... */ - setfltvalue(ra + 3, idx); /* ...and external index */ - } - } - vmbreak; - } - vmcase(OP_FORPREP) { - TValue *init = ra; - TValue *plimit = ra + 1; - TValue *pstep = ra + 2; - lua_Integer ilimit; - int stopnow; - if (ttisinteger(init) && ttisinteger(pstep) && - forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) { - /* all values are integer */ - lua_Integer initv = (stopnow ? 0 : ivalue(init)); - setivalue(plimit, ilimit); - setivalue(init, intop(-, initv, ivalue(pstep))); - } - else { /* try making all values floats */ - lua_Number ninit; lua_Number nlimit; lua_Number nstep; - if (!tonumber(plimit, &nlimit)) - luaG_runerror(L, "'for' limit must be a number"); - setfltvalue(plimit, nlimit); - if (!tonumber(pstep, &nstep)) - luaG_runerror(L, "'for' step must be a number"); - setfltvalue(pstep, nstep); - if (!tonumber(init, &ninit)) - luaG_runerror(L, "'for' initial value must be a number"); - setfltvalue(init, luai_numsub(L, ninit, nstep)); - } - ci->u.l.savedpc += GETARG_sBx(i); - vmbreak; - } - vmcase(OP_TFORCALL) { - StkId cb = ra + 3; /* call base */ - setobjs2s(L, cb+2, ra+2); - setobjs2s(L, cb+1, ra+1); - setobjs2s(L, cb, ra); - L->top = cb + 3; /* func. + 2 args (state and index) */ - Protect(luaD_call(L, cb, GETARG_C(i))); - L->top = ci->top; - i = *(ci->u.l.savedpc++); /* go to next instruction */ - ra = RA(i); - lua_assert(GET_OPCODE(i) == OP_TFORLOOP); - goto l_tforloop; - } - vmcase(OP_TFORLOOP) { - l_tforloop: - if (!ttisnil(ra + 1)) { /* continue loop? */ - setobjs2s(L, ra, ra + 1); /* save control variable */ - ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ - } - vmbreak; - } - vmcase(OP_SETLIST) { - int n = GETARG_B(i); - int c = GETARG_C(i); - unsigned int last; - Table *h; - if (n == 0) n = cast_int(L->top - ra) - 1; - if (c == 0) { - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); - c = GETARG_Ax(*ci->u.l.savedpc++); - } - h = hvalue(ra); - last = ((c-1)*LFIELDS_PER_FLUSH) + n; - if (last > h->sizearray) /* needs more space? */ - luaH_resizearray(L, h, last); /* preallocate it at once */ - for (; n > 0; n--) { - TValue *val = ra+n; - luaH_setint(L, h, last--, val); - luaC_barrierback(L, h, val); - } - L->top = ci->top; /* correct top (in case of previous open call) */ - vmbreak; - } - vmcase(OP_CLOSURE) { - Proto *p = cl->p->p[GETARG_Bx(i)]; - LClosure *ncl = getcached(p, cl->upvals, base); /* cached closure */ - if (ncl == NULL) /* no match? */ - pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ - else - setclLvalue(L, ra, ncl); /* push cashed closure */ - checkGC(L, ra + 1); - vmbreak; - } - vmcase(OP_VARARG) { - int b = GETARG_B(i) - 1; /* required results */ - int j; - int n = cast_int(base - ci->func) - cl->p->numparams - 1; - if (n < 0) /* less arguments than parameters? */ - n = 0; /* no vararg arguments */ - if (b < 0) { /* B == 0? */ - b = n; /* get all var. arguments */ - Protect(luaD_checkstack(L, n)); - ra = RA(i); /* previous call may change the stack */ - L->top = ra + n; - } - for (j = 0; j < b && j < n; j++) - setobjs2s(L, ra + j, base - n + j); - for (; j < b; j++) /* complete required results with nil */ - setnilvalue(ra + j); - vmbreak; - } - vmcase(OP_EXTRAARG) { - lua_assert(0); - vmbreak; - } - } - } +void luaV_execute(lua_State* L) +{ + CallInfo* ci = L->ci; + LClosure* cl; + TValue* k; + StkId base; + ci->callstatus |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */ +newframe: /* reentry point when frame changes (call/return) */ + lua_assert(ci == L->ci); + cl = clLvalue(ci->func); /* local reference to function's closure */ + k = cl->p->k; /* local reference to function's constant table */ + base = ci->u.l.base; /* local copy of function's base */ + /* main loop of interpreter */ + for (;;) + { + Instruction i; + StkId ra; + vmfetch(); + vmdispatch(GET_OPCODE(i)) + { + vmcase(OP_MOVE) + { + setobjs2s(L, ra, RB(i)); + vmbreak; + } + vmcase(OP_LOADK) + { + TValue* rb = k + GETARG_Bx(i); + setobj2s(L, ra, rb); + vmbreak; + } + vmcase(OP_LOADKX) + { + TValue* rb; + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); + rb = k + GETARG_Ax(*ci->u.l.savedpc++); + setobj2s(L, ra, rb); + vmbreak; + } + vmcase(OP_LOADBOOL) + { + setbvalue(ra, GETARG_B(i)); + if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */ + vmbreak; + } + vmcase(OP_LOADNIL) + { + int b = GETARG_B(i); + do + { + setnilvalue(ra++); + } + while (b--); + vmbreak; + } + vmcase(OP_GETUPVAL) + { + int b = GETARG_B(i); + setobj2s(L, ra, cl->upvals[b]->v); + vmbreak; + } + vmcase(OP_GETTABUP) + { + TValue* upval = cl->upvals[GETARG_B(i)]->v; + TValue* rc = RKC(i); + gettableProtected(L, upval, rc, ra); + vmbreak; + } + vmcase(OP_GETTABLE) + { + StkId rb = RB(i); + TValue* rc = RKC(i); + gettableProtected(L, rb, rc, ra); + vmbreak; + } + vmcase(OP_SETTABUP) + { + TValue* upval = cl->upvals[GETARG_A(i)]->v; + TValue* rb = RKB(i); + TValue* rc = RKC(i); + settableProtected(L, upval, rb, rc); + vmbreak; + } + vmcase(OP_SETUPVAL) + { + UpVal* uv = cl->upvals[GETARG_B(i)]; + setobj(L, uv->v, ra); + luaC_upvalbarrier(L, uv); + vmbreak; + } + vmcase(OP_SETTABLE) + { + TValue* rb = RKB(i); + TValue* rc = RKC(i); + settableProtected(L, ra, rb, rc); + vmbreak; + } + vmcase(OP_NEWTABLE) + { + int b = GETARG_B(i); + int c = GETARG_C(i); + Table* t = luaH_new(L); + sethvalue(L, ra, t); + if (b != 0 || c != 0) + luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c)); + checkGC(L, ra + 1); + vmbreak; + } + vmcase(OP_SELF) + { + const TValue* aux; + StkId rb = RB(i); + TValue* rc = RKC(i); + TString* key = tsvalue(rc); /* key must be a string */ + setobjs2s(L, ra + 1, rb); + if (luaV_fastget(L, rb, key, aux, luaH_getstr)) + { + setobj2s(L, ra, aux); + } + else Protect(luaV_finishget(L, rb, rc, ra, aux)); + vmbreak; + } + vmcase(OP_ADD) + { + TValue* rb = RKB(i); + TValue* rc = RKC(i); + lua_Number nb; + lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) + { + lua_Integer ib = ivalue(rb); + lua_Integer ic = ivalue(rc); + setivalue(ra, intop(+, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) + { + setfltvalue(ra, luai_numadd(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD)); } + vmbreak; + } + vmcase(OP_SUB) + { + TValue* rb = RKB(i); + TValue* rc = RKC(i); + lua_Number nb; + lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) + { + lua_Integer ib = ivalue(rb); + lua_Integer ic = ivalue(rc); + setivalue(ra, intop(-, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) + { + setfltvalue(ra, luai_numsub(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SUB)); } + vmbreak; + } + vmcase(OP_MUL) + { + TValue* rb = RKB(i); + TValue* rc = RKC(i); + lua_Number nb; + lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) + { + lua_Integer ib = ivalue(rb); + lua_Integer ic = ivalue(rc); + setivalue(ra, intop(*, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) + { + setfltvalue(ra, luai_nummul(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MUL)); } + vmbreak; + } + vmcase(OP_DIV) + { + /* float division (always with floats) */ + TValue* rb = RKB(i); + TValue* rc = RKC(i); + lua_Number nb; + lua_Number nc; + if (tonumber(rb, &nb) && tonumber(rc, &nc)) + { + setfltvalue(ra, luai_numdiv(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV)); } + vmbreak; + } + vmcase(OP_BAND) + { + TValue* rb = RKB(i); + TValue* rc = RKC(i); + lua_Integer ib; + lua_Integer ic; + if (tointeger(rb, &ib) && tointeger(rc, &ic)) + { + setivalue(ra, intop(&, ib, ic)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BAND)); } + vmbreak; + } + vmcase(OP_BOR) + { + TValue* rb = RKB(i); + TValue* rc = RKC(i); + lua_Integer ib; + lua_Integer ic; + if (tointeger(rb, &ib) && tointeger(rc, &ic)) + { + setivalue(ra, intop(|, ib, ic)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BOR)); } + vmbreak; + } + vmcase(OP_BXOR) + { + TValue* rb = RKB(i); + TValue* rc = RKC(i); + lua_Integer ib; + lua_Integer ic; + if (tointeger(rb, &ib) && tointeger(rc, &ic)) + { + setivalue(ra, intop(^, ib, ic)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR)); } + vmbreak; + } + vmcase(OP_SHL) + { + TValue* rb = RKB(i); + TValue* rc = RKC(i); + lua_Integer ib; + lua_Integer ic; + if (tointeger(rb, &ib) && tointeger(rc, &ic)) + { + setivalue(ra, luaV_shiftl(ib, ic)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL)); } + vmbreak; + } + vmcase(OP_SHR) + { + TValue* rb = RKB(i); + TValue* rc = RKC(i); + lua_Integer ib; + lua_Integer ic; + if (tointeger(rb, &ib) && tointeger(rc, &ic)) + { + setivalue(ra, luaV_shiftl(ib, -ic)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHR)); } + vmbreak; + } + vmcase(OP_MOD) + { + TValue* rb = RKB(i); + TValue* rc = RKC(i); + lua_Number nb; + lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) + { + lua_Integer ib = ivalue(rb); + lua_Integer ic = ivalue(rc); + setivalue(ra, luaV_mod(L, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) + { + lua_Number m; + luai_nummod(L, nb, nc, m); + setfltvalue(ra, m); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD)); } + vmbreak; + } + vmcase(OP_IDIV) + { + /* floor division */ + TValue* rb = RKB(i); + TValue* rc = RKC(i); + lua_Number nb; + lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) + { + lua_Integer ib = ivalue(rb); + lua_Integer ic = ivalue(rc); + setivalue(ra, luaV_div(L, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) + { + setfltvalue(ra, luai_numidiv(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); } + vmbreak; + } + vmcase(OP_POW) + { + TValue* rb = RKB(i); + TValue* rc = RKC(i); + lua_Number nb; + lua_Number nc; + if (tonumber(rb, &nb) && tonumber(rc, &nc)) + { + setfltvalue(ra, luai_numpow(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW)); } + vmbreak; + } + vmcase(OP_UNM) + { + TValue* rb = RB(i); + lua_Number nb; + if (ttisinteger(rb)) + { + lua_Integer ib = ivalue(rb); + setivalue(ra, intop(-, 0, ib)); + } + else if (tonumber(rb, &nb)) + { + setfltvalue(ra, luai_numunm(L, nb)); + } + else + { + Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM)); + } + vmbreak; + } + vmcase(OP_BNOT) + { + TValue* rb = RB(i); + lua_Integer ib; + if (tointeger(rb, &ib)) + { + setivalue(ra, intop(^, ~l_castS2U(0), ib)); + } + else + { + Protect(luaT_trybinTM(L, rb, rb, ra, TM_BNOT)); + } + vmbreak; + } + vmcase(OP_NOT) + { + TValue* rb = RB(i); + int res = l_isfalse(rb); /* next assignment may change this value */ + setbvalue(ra, res); + vmbreak; + } + vmcase(OP_LEN) + { + Protect(luaV_objlen(L, ra, RB(i))); + vmbreak; + } + vmcase(OP_CONCAT) + { + int b = GETARG_B(i); + int c = GETARG_C(i); + StkId rb; + L->top = base + c + 1; /* mark the end of concat operands */ + Protect(luaV_concat(L, c - b + 1)); + ra = RA(i); /* 'luaV_concat' may invoke TMs and move the stack */ + rb = base + b; + setobjs2s(L, ra, rb); + checkGC(L, (ra >= rb ? ra + 1 : rb)); + L->top = ci->top; /* restore top */ + vmbreak; + } + vmcase(OP_JMP) + { + dojump(ci, i, 0); + vmbreak; + } + vmcase(OP_EQ) + { + TValue* rb = RKB(i); + TValue* rc = RKC(i); + Protect( + if (luaV_equalobj(L, rb, rc) != GETARG_A(i)) + ci->u.l.savedpc++; + else + donextjump(ci); + ) + vmbreak; + } + vmcase(OP_LT) + { + Protect( + if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) + ci->u.l.savedpc++; + else + donextjump(ci); + ) + vmbreak; + } + vmcase(OP_LE) + { + Protect( + if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) + ci->u.l.savedpc++; + else + donextjump(ci); + ) + vmbreak; + } + vmcase(OP_TEST) + { + if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra)) + ci->u.l.savedpc++; + else + donextjump(ci); + vmbreak; + } + vmcase(OP_TESTSET) + { + TValue* rb = RB(i); + if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb)) + ci->u.l.savedpc++; + else + { + setobjs2s(L, ra, rb); + donextjump(ci); + } + vmbreak; + } + vmcase(OP_CALL) + { + int b = GETARG_B(i); + int nresults = GETARG_C(i) - 1; + if (b != 0) L->top = ra + b; /* else previous instruction set top */ + if (luaD_precall(L, ra, nresults)) + { + /* C function? */ + if (nresults >= 0) + L->top = ci->top; /* adjust results */ + Protect((void)0); /* update 'base' */ + } + else + { + /* Lua function */ + ci = L->ci; + goto newframe; /* restart luaV_execute over new Lua function */ + } + vmbreak; + } + vmcase(OP_TAILCALL) + { + int b = GETARG_B(i); + if (b != 0) L->top = ra + b; /* else previous instruction set top */ + lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); + if (luaD_precall(L, ra, LUA_MULTRET)) + { + /* C function? */ + Protect((void)0); /* update 'base' */ + } + else + { + /* tail call: put called frame (n) in place of caller one (o) */ + CallInfo* nci = L->ci; /* called frame */ + CallInfo* oci = nci->previous; /* caller frame */ + StkId nfunc = nci->func; /* called function */ + StkId ofunc = oci->func; /* caller function */ + /* last stack slot filled by 'precall' */ + StkId lim = nci->u.l.base + getproto(nfunc)->numparams; + int aux; + /* close all upvalues from previous call */ + if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base); + /* move new frame into old one */ + for (aux = 0; nfunc + aux < lim; aux++) + setobjs2s(L, ofunc + aux, nfunc + aux); + oci->u.l.base = ofunc + (nci->u.l.base - nfunc); /* correct base */ + oci->top = L->top = ofunc + (L->top - nfunc); /* correct top */ + oci->u.l.savedpc = nci->u.l.savedpc; + oci->callstatus |= CIST_TAIL; /* function was tail called */ + ci = L->ci = oci; /* remove new frame */ + lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize); + goto newframe; /* restart luaV_execute over new Lua function */ + } + vmbreak; + } + vmcase(OP_RETURN) + { + int b = GETARG_B(i); + if (cl->p->sizep > 0) luaF_close(L, base); + b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))); + if (ci->callstatus & CIST_FRESH) /* local 'ci' still from callee */ + return; /* external invocation: return */ + else + { + /* invocation via reentry: continue execution */ + ci = L->ci; + if (b) L->top = ci->top; + lua_assert(isLua(ci)); + lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL); + goto newframe; /* restart luaV_execute over new Lua function */ + } + } + vmcase(OP_FORLOOP) + { + if (ttisinteger(ra)) + { + /* integer loop? */ + lua_Integer step = ivalue(ra + 2); + lua_Integer idx = intop(+, ivalue(ra), step); /* increment index */ + lua_Integer limit = ivalue(ra + 1); + if ((0 < step) ? (idx <= limit) : (limit <= idx)) + { + ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ + chgivalue(ra, idx); /* update internal index... */ + setivalue(ra + 3, idx); /* ...and external index */ + } + } + else + { + /* floating loop */ + lua_Number step = fltvalue(ra + 2); + lua_Number idx = luai_numadd(L, fltvalue(ra), step); /* inc. index */ + lua_Number limit = fltvalue(ra + 1); + if (luai_numlt(0, step) + ? luai_numle(idx, limit) + : luai_numle(limit, idx)) + { + ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ + chgfltvalue(ra, idx); /* update internal index... */ + setfltvalue(ra + 3, idx); /* ...and external index */ + } + } + vmbreak; + } + vmcase(OP_FORPREP) + { + TValue* init = ra; + TValue* plimit = ra + 1; + TValue* pstep = ra + 2; + lua_Integer ilimit; + int stopnow; + if (ttisinteger(init) && ttisinteger(pstep) && + forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) + { + /* all values are integer */ + lua_Integer initv = (stopnow ? 0 : ivalue(init)); + setivalue(plimit, ilimit); + setivalue(init, intop(-, initv, ivalue(pstep))); + } + else + { + /* try making all values floats */ + lua_Number ninit; + lua_Number nlimit; + lua_Number nstep; + if (!tonumber(plimit, &nlimit)) + luaG_runerror(L, "'for' limit must be a number"); + setfltvalue(plimit, nlimit); + if (!tonumber(pstep, &nstep)) + luaG_runerror(L, "'for' step must be a number"); + setfltvalue(pstep, nstep); + if (!tonumber(init, &ninit)) + luaG_runerror(L, "'for' initial value must be a number"); + setfltvalue(init, luai_numsub(L, ninit, nstep)); + } + ci->u.l.savedpc += GETARG_sBx(i); + vmbreak; + } + vmcase(OP_TFORCALL) + { + StkId cb = ra + 3; /* call base */ + setobjs2s(L, cb+2, ra+2); + setobjs2s(L, cb+1, ra+1); + setobjs2s(L, cb, ra); + L->top = cb + 3; /* func. + 2 args (state and index) */ + Protect(luaD_call(L, cb, GETARG_C(i))); + L->top = ci->top; + i = *(ci->u.l.savedpc++); /* go to next instruction */ + ra = RA(i); + lua_assert(GET_OPCODE(i) == OP_TFORLOOP); + goto l_tforloop; + } + vmcase(OP_TFORLOOP) + { + l_tforloop: + if (!ttisnil(ra + 1)) + { + /* continue loop? */ + setobjs2s(L, ra, ra + 1); /* save control variable */ + ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ + } + vmbreak; + } + vmcase(OP_SETLIST) + { + int n = GETARG_B(i); + int c = GETARG_C(i); + unsigned int last; + Table* h; + if (n == 0) n = cast_int(L->top - ra) - 1; + if (c == 0) + { + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); + c = GETARG_Ax(*ci->u.l.savedpc++); + } + h = hvalue(ra); + last = ((c - 1) * LFIELDS_PER_FLUSH) + n; + if (last > h->sizearray) /* needs more space? */ + luaH_resizearray(L, h, last); /* preallocate it at once */ + for (; n > 0; n--) + { + TValue* val = ra + n; + luaH_setint(L, h, last--, val); + luaC_barrierback(L, h, val); + } + L->top = ci->top; /* correct top (in case of previous open call) */ + vmbreak; + } + vmcase(OP_CLOSURE) + { + Proto* p = cl->p->p[GETARG_Bx(i)]; + LClosure* ncl = getcached(p, cl->upvals, base); /* cached closure */ + if (ncl == NULL) /* no match? */ + pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ + else + setclLvalue(L, ra, ncl); /* push cashed closure */ + checkGC(L, ra + 1); + vmbreak; + } + vmcase(OP_VARARG) + { + int b = GETARG_B(i) - 1; /* required results */ + int j; + int n = cast_int(base - ci->func) - cl->p->numparams - 1; + if (n < 0) /* less arguments than parameters? */ + n = 0; /* no vararg arguments */ + if (b < 0) + { + /* B == 0? */ + b = n; /* get all var. arguments */ + Protect(luaD_checkstack(L, n)); + ra = RA(i); /* previous call may change the stack */ + L->top = ra + n; + } + for (j = 0; j < b && j < n; j++) + setobjs2s(L, ra + j, base - n + j); + for (; j < b; j++) /* complete required results with nil */ + setnilvalue(ra + j); + vmbreak; + } + vmcase(OP_EXTRAARG) + { + lua_assert(0); + vmbreak; + } + } + } } /* }================================================================== */ - diff --git a/Lua/lvm.h b/Lua/lvm.h index 422f871..753be47 100644 --- a/Lua/lvm.h +++ b/Lua/lvm.h @@ -92,22 +92,21 @@ luaV_finishset(L,t,k,v,slot); } - -LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); -LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); -LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); -LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); -LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode); -LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, - StkId val, const TValue *slot); -LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, - StkId val, const TValue *slot); -LUAI_FUNC void luaV_finishOp (lua_State *L); -LUAI_FUNC void luaV_execute (lua_State *L); -LUAI_FUNC void luaV_concat (lua_State *L, int total); -LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y); -LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); -LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y); -LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); +LUAI_FUNC int luaV_equalobj(lua_State* L, const TValue* t1, const TValue* t2); +LUAI_FUNC int luaV_lessthan(lua_State* L, const TValue* l, const TValue* r); +LUAI_FUNC int luaV_lessequal(lua_State* L, const TValue* l, const TValue* r); +LUAI_FUNC int luaV_tonumber_(const TValue* obj, lua_Number* n); +LUAI_FUNC int luaV_tointeger(const TValue* obj, lua_Integer* p, int mode); +LUAI_FUNC void luaV_finishget(lua_State* L, const TValue* t, TValue* key, + StkId val, const TValue* slot); +LUAI_FUNC void luaV_finishset(lua_State* L, const TValue* t, TValue* key, + StkId val, const TValue* slot); +LUAI_FUNC void luaV_finishOp(lua_State* L); +LUAI_FUNC void luaV_execute(lua_State* L); +LUAI_FUNC void luaV_concat(lua_State* L, int total); +LUAI_FUNC lua_Integer luaV_div(lua_State* L, lua_Integer x, lua_Integer y); +LUAI_FUNC lua_Integer luaV_mod(lua_State* L, lua_Integer x, lua_Integer y); +LUAI_FUNC lua_Integer luaV_shiftl(lua_Integer x, lua_Integer y); +LUAI_FUNC void luaV_objlen(lua_State* L, StkId ra, const TValue* rb); #endif diff --git a/Lua/lzio.c b/Lua/lzio.c index c9e1f49..2d0242e 100644 --- a/Lua/lzio.c +++ b/Lua/lzio.c @@ -20,49 +20,55 @@ #include "lzio.h" -int luaZ_fill (ZIO *z) { - size_t size; - lua_State *L = z->L; - const char *buff; - lua_unlock(L); - buff = z->reader(L, z->data, &size); - lua_lock(L); - if (buff == NULL || size == 0) - return EOZ; - z->n = size - 1; /* discount char being returned */ - z->p = buff; - return cast_uchar(*(z->p++)); +int luaZ_fill(ZIO* z) +{ + size_t size; + lua_State* L = z->L; + const char* buff; + lua_unlock(L); + buff = z->reader(L, z->data, &size); + lua_lock(L); + if (buff == NULL || size == 0) + return EOZ; + z->n = size - 1; /* discount char being returned */ + z->p = buff; + return cast_uchar(*(z->p++)); } -void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { - z->L = L; - z->reader = reader; - z->data = data; - z->n = 0; - z->p = NULL; +void luaZ_init(lua_State* L, ZIO* z, lua_Reader reader, void* data) +{ + z->L = L; + z->reader = reader; + z->data = data; + z->n = 0; + z->p = NULL; } /* --------------------------------------------------------------- read --- */ -size_t luaZ_read (ZIO *z, void *b, size_t n) { - while (n) { - size_t m; - if (z->n == 0) { /* no bytes in buffer? */ - if (luaZ_fill(z) == EOZ) /* try to read more */ - return n; /* no more input; return number of missing bytes */ - else { - z->n++; /* luaZ_fill consumed first byte; put it back */ - z->p--; - } - } - m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ - memcpy(b, z->p, m); - z->n -= m; - z->p += m; - b = (char *)b + m; - n -= m; - } - return 0; +size_t luaZ_read(ZIO* z, void* b, size_t n) +{ + while (n) + { + size_t m; + if (z->n == 0) + { + /* no bytes in buffer? */ + if (luaZ_fill(z) == EOZ) /* try to read more */ + return n; /* no more input; return number of missing bytes */ + else + { + z->n++; /* luaZ_fill consumed first byte; put it back */ + z->p--; + } + } + m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ + memcpy(b, z->p, m); + z->n -= m; + z->p += m; + b = (char*)b + m; + n -= m; + } + return 0; } - diff --git a/Lua/lzio.h b/Lua/lzio.h index e7b6f34..b3e4179 100644 --- a/Lua/lzio.h +++ b/Lua/lzio.h @@ -20,10 +20,11 @@ typedef struct Zio ZIO; #define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z)) -typedef struct Mbuffer { - char *buffer; - size_t n; - size_t buffsize; +typedef struct Mbuffer +{ + char* buffer; + size_t n; + size_t buffsize; } Mbuffer; #define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) @@ -44,23 +45,23 @@ typedef struct Mbuffer { #define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) -LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, - void *data); -LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */ - +LUAI_FUNC void luaZ_init(lua_State* L, ZIO* z, lua_Reader reader, + void* data); +LUAI_FUNC size_t luaZ_read(ZIO* z, void* b, size_t n); /* read next n bytes */ /* --------- Private Part ------------------ */ -struct Zio { - size_t n; /* bytes still unread */ - const char *p; /* current position in buffer */ - lua_Reader reader; /* reader function */ - void *data; /* additional data */ - lua_State *L; /* Lua state (for reader) */ +struct Zio +{ + size_t n; /* bytes still unread */ + const char* p; /* current position in buffer */ + lua_Reader reader; /* reader function */ + void* data; /* additional data */ + lua_State* L; /* Lua state (for reader) */ }; -LUAI_FUNC int luaZ_fill (ZIO *z); +LUAI_FUNC int luaZ_fill(ZIO* z); #endif diff --git a/Lua/mime.c b/Lua/mime.c index 338ecd4..c29cd1a 100644 --- a/Lua/mime.c +++ b/Lua/mime.c @@ -20,39 +20,39 @@ static const char EQCRLF[] = "=\r\n"; /*=========================================================================*\ * Internal function prototypes. \*=========================================================================*/ -static int mime_global_wrp(lua_State *L); -static int mime_global_b64(lua_State *L); -static int mime_global_unb64(lua_State *L); -static int mime_global_qp(lua_State *L); -static int mime_global_unqp(lua_State *L); -static int mime_global_qpwrp(lua_State *L); -static int mime_global_eol(lua_State *L); -static int mime_global_dot(lua_State *L); +static int mime_global_wrp(lua_State* L); +static int mime_global_b64(lua_State* L); +static int mime_global_unb64(lua_State* L); +static int mime_global_qp(lua_State* L); +static int mime_global_unqp(lua_State* L); +static int mime_global_qpwrp(lua_State* L); +static int mime_global_eol(lua_State* L); +static int mime_global_dot(lua_State* L); -static size_t dot(int c, size_t state, luaL_Buffer *buffer); -static void b64setup(UC *base); -static size_t b64encode(UC c, UC *input, size_t size, luaL_Buffer *buffer); -static size_t b64pad(const UC *input, size_t size, luaL_Buffer *buffer); -static size_t b64decode(UC c, UC *input, size_t size, luaL_Buffer *buffer); +static size_t dot(int c, size_t state, luaL_Buffer* buffer); +static void b64setup(UC* base); +static size_t b64encode(UC c, UC* input, size_t size, luaL_Buffer* buffer); +static size_t b64pad(const UC* input, size_t size, luaL_Buffer* buffer); +static size_t b64decode(UC c, UC* input, size_t size, luaL_Buffer* buffer); -static void qpsetup(UC *class, UC *unbase); -static void qpquote(UC c, luaL_Buffer *buffer); -static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer); -static size_t qpencode(UC c, UC *input, size_t size, - const char *marker, luaL_Buffer *buffer); -static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer); +static void qpsetup(UC* class, UC* unbase); +static void qpquote(UC c, luaL_Buffer* buffer); +static size_t qpdecode(UC c, UC* input, size_t size, luaL_Buffer* buffer); +static size_t qpencode(UC c, UC* input, size_t size, + const char* marker, luaL_Buffer* buffer); +static size_t qppad(UC* input, size_t size, luaL_Buffer* buffer); /* code support functions */ static luaL_Reg func[] = { - { "dot", mime_global_dot }, - { "b64", mime_global_b64 }, - { "eol", mime_global_eol }, - { "qp", mime_global_qp }, - { "qpwrp", mime_global_qpwrp }, - { "unb64", mime_global_unb64 }, - { "unqp", mime_global_unqp }, - { "wrp", mime_global_wrp }, - { NULL, NULL } + {"dot", mime_global_dot}, + {"b64", mime_global_b64}, + {"eol", mime_global_eol}, + {"qp", mime_global_qp}, + {"qpwrp", mime_global_qpwrp}, + {"unb64", mime_global_unb64}, + {"unqp", mime_global_unqp}, + {"wrp", mime_global_wrp}, + {NULL, NULL} }; /*-------------------------------------------------------------------------*\ @@ -61,13 +61,14 @@ static luaL_Reg func[] = { static UC qpclass[256]; static UC qpbase[] = "0123456789ABCDEF"; static UC qpunbase[256]; -enum {QP_PLAIN, QP_QUOTED, QP_CR, QP_IF_LAST}; + +enum { QP_PLAIN, QP_QUOTED, QP_CR, QP_IF_LAST }; /*-------------------------------------------------------------------------*\ * Base64 globals \*-------------------------------------------------------------------------*/ static const UC b64base[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static UC b64unbase[256]; /*=========================================================================*\ @@ -76,18 +77,18 @@ static UC b64unbase[256]; /*-------------------------------------------------------------------------*\ * Initializes module \*-------------------------------------------------------------------------*/ -MIME_API int luaopen_mime_core(lua_State *L) +MIME_API int luaopen_mime_core(lua_State* L) { - lua_newtable(L); - luaL_setfuncs(L, func, 0); - /* make version string available to scripts */ - lua_pushstring(L, "_VERSION"); - lua_pushstring(L, MIME_VERSION); - lua_rawset(L, -3); - /* initialize lookup tables */ - qpsetup(qpclass, qpunbase); - b64setup(b64unbase); - return 1; + lua_newtable(L); + luaL_setfuncs(L, func, 0); + /* make version string available to scripts */ + lua_pushstring(L, "_VERSION"); + lua_pushstring(L, MIME_VERSION); + lua_rawset(L, -3); + /* initialize lookup tables */ + qpsetup(qpclass, qpunbase); + b64setup(b64unbase); + return 1; } /*=========================================================================*\ @@ -100,57 +101,61 @@ MIME_API int luaopen_mime_core(lua_State *L) * 'l' is how many bytes are left for the first line of B. * 'n' is the number of bytes left in the last line of A. \*-------------------------------------------------------------------------*/ -static int mime_global_wrp(lua_State *L) +static int mime_global_wrp(lua_State* L) { - size_t size = 0; - int left = (int) luaL_checknumber(L, 1); - const UC *input = (const UC *) luaL_optlstring(L, 2, NULL, &size); - const UC *last = input + size; - int length = (int) luaL_optnumber(L, 3, 76); - luaL_Buffer buffer; - /* end of input black-hole */ - if (!input) { - /* if last line has not been terminated, add a line break */ - if (left < length) lua_pushstring(L, CRLF); - /* otherwise, we are done */ - else lua_pushnil(L); - lua_pushnumber(L, length); - return 2; - } - luaL_buffinit(L, &buffer); - while (input < last) { - switch (*input) { - case '\r': - break; - case '\n': - luaL_addstring(&buffer, CRLF); - left = length; - break; - default: - if (left <= 0) { - left = length; - luaL_addstring(&buffer, CRLF); - } - luaL_addchar(&buffer, *input); - left--; - break; - } - input++; - } - luaL_pushresult(&buffer); - lua_pushnumber(L, left); - return 2; + size_t size = 0; + int left = (int)luaL_checknumber(L, 1); + const UC* input = (const UC*)luaL_optlstring(L, 2, NULL, &size); + const UC* last = input + size; + int length = (int)luaL_optnumber(L, 3, 76); + luaL_Buffer buffer; + /* end of input black-hole */ + if (!input) + { + /* if last line has not been terminated, add a line break */ + if (left < length) lua_pushstring(L, CRLF); + /* otherwise, we are done */ + else lua_pushnil(L); + lua_pushnumber(L, length); + return 2; + } + luaL_buffinit(L, &buffer); + while (input < last) + { + switch (*input) + { + case '\r': + break; + case '\n': + luaL_addstring(&buffer, CRLF); + left = length; + break; + default: + if (left <= 0) + { + left = length; + luaL_addstring(&buffer, CRLF); + } + luaL_addchar(&buffer, *input); + left--; + break; + } + input++; + } + luaL_pushresult(&buffer); + lua_pushnumber(L, left); + return 2; } /*-------------------------------------------------------------------------*\ * Fill base64 decode map. \*-------------------------------------------------------------------------*/ -static void b64setup(UC *unbase) +static void b64setup(UC* unbase) { - int i; - for (i = 0; i <= 255; i++) unbase[i] = (UC) 255; - for (i = 0; i < 64; i++) unbase[b64base[i]] = (UC) i; - unbase['='] = 0; + int i; + for (i = 0; i <= 255; i++) unbase[i] = (UC)255; + for (i = 0; i < 64; i++) unbase[b64base[i]] = (UC)i; + unbase['='] = 0; } /*-------------------------------------------------------------------------*\ @@ -158,24 +163,30 @@ static void b64setup(UC *unbase) * Translate the 3 bytes into Base64 form and append to buffer. * Returns new number of bytes in buffer. \*-------------------------------------------------------------------------*/ -static size_t b64encode(UC c, UC *input, size_t size, - luaL_Buffer *buffer) +static size_t b64encode(UC c, UC* input, size_t size, + luaL_Buffer* buffer) { - input[size++] = c; - if (size == 3) { - UC code[4]; - unsigned long value = 0; - value += input[0]; value <<= 8; - value += input[1]; value <<= 8; - value += input[2]; - code[3] = b64base[value & 0x3f]; value >>= 6; - code[2] = b64base[value & 0x3f]; value >>= 6; - code[1] = b64base[value & 0x3f]; value >>= 6; - code[0] = b64base[value]; - luaL_addlstring(buffer, (char *) code, 4); - size = 0; - } - return size; + input[size++] = c; + if (size == 3) + { + UC code[4]; + unsigned long value = 0; + value += input[0]; + value <<= 8; + value += input[1]; + value <<= 8; + value += input[2]; + code[3] = b64base[value & 0x3f]; + value >>= 6; + code[2] = b64base[value & 0x3f]; + value >>= 6; + code[1] = b64base[value & 0x3f]; + value >>= 6; + code[0] = b64base[value]; + luaL_addlstring(buffer, (char*)code, 4); + size = 0; + } + return size; } /*-------------------------------------------------------------------------*\ @@ -183,30 +194,36 @@ static size_t b64encode(UC c, UC *input, size_t size, * Result, if any, is appended to buffer. * Returns 0. \*-------------------------------------------------------------------------*/ -static size_t b64pad(const UC *input, size_t size, - luaL_Buffer *buffer) +static size_t b64pad(const UC* input, size_t size, + luaL_Buffer* buffer) { - unsigned long value = 0; - UC code[4] = {'=', '=', '=', '='}; - switch (size) { - case 1: - value = input[0] << 4; - code[1] = b64base[value & 0x3f]; value >>= 6; - code[0] = b64base[value]; - luaL_addlstring(buffer, (char *) code, 4); - break; - case 2: - value = input[0]; value <<= 8; - value |= input[1]; value <<= 2; - code[2] = b64base[value & 0x3f]; value >>= 6; - code[1] = b64base[value & 0x3f]; value >>= 6; - code[0] = b64base[value]; - luaL_addlstring(buffer, (char *) code, 4); - break; - default: - break; - } - return 0; + unsigned long value = 0; + UC code[4] = {'=', '=', '=', '='}; + switch (size) + { + case 1: + value = input[0] << 4; + code[1] = b64base[value & 0x3f]; + value >>= 6; + code[0] = b64base[value]; + luaL_addlstring(buffer, (char*)code, 4); + break; + case 2: + value = input[0]; + value <<= 8; + value |= input[1]; + value <<= 2; + code[2] = b64base[value & 0x3f]; + value >>= 6; + code[1] = b64base[value & 0x3f]; + value >>= 6; + code[0] = b64base[value]; + luaL_addlstring(buffer, (char*)code, 4); + break; + default: + break; + } + return 0; } /*-------------------------------------------------------------------------*\ @@ -214,29 +231,36 @@ static size_t b64pad(const UC *input, size_t size, * Translate the 4 bytes from Base64 form and append to buffer. * Returns new number of bytes in buffer. \*-------------------------------------------------------------------------*/ -static size_t b64decode(UC c, UC *input, size_t size, - luaL_Buffer *buffer) +static size_t b64decode(UC c, UC* input, size_t size, + luaL_Buffer* buffer) { - /* ignore invalid characters */ - if (b64unbase[c] > 64) return size; - input[size++] = c; - /* decode atom */ - if (size == 4) { - UC decoded[3]; - int valid, value = 0; - value = b64unbase[input[0]]; value <<= 6; - value |= b64unbase[input[1]]; value <<= 6; - value |= b64unbase[input[2]]; value <<= 6; - value |= b64unbase[input[3]]; - decoded[2] = (UC) (value & 0xff); value >>= 8; - decoded[1] = (UC) (value & 0xff); value >>= 8; - decoded[0] = (UC) value; - /* take care of paddding */ - valid = (input[2] == '=') ? 1 : (input[3] == '=') ? 2 : 3; - luaL_addlstring(buffer, (char *) decoded, valid); - return 0; - /* need more data */ - } else return size; + /* ignore invalid characters */ + if (b64unbase[c] > 64) return size; + input[size++] = c; + /* decode atom */ + if (size == 4) + { + UC decoded[3]; + int valid, value = 0; + value = b64unbase[input[0]]; + value <<= 6; + value |= b64unbase[input[1]]; + value <<= 6; + value |= b64unbase[input[2]]; + value <<= 6; + value |= b64unbase[input[3]]; + decoded[2] = (UC)(value & 0xff); + value >>= 8; + decoded[1] = (UC)(value & 0xff); + value >>= 8; + decoded[0] = (UC)value; + /* take care of paddding */ + valid = (input[2] == '=') ? 1 : (input[3] == '=') ? 2 : 3; + luaL_addlstring(buffer, (char*)decoded, valid); + return 0; + /* need more data */ + } + else return size; } /*-------------------------------------------------------------------------*\ @@ -248,44 +272,46 @@ static size_t b64decode(UC c, UC *input, size_t size, * encode the result, but we can't afford that or Lua would dupplicate * every chunk we received. \*-------------------------------------------------------------------------*/ -static int mime_global_b64(lua_State *L) +static int mime_global_b64(lua_State* L) { - UC atom[3]; - size_t isize = 0, asize = 0; - const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize); - const UC *last = input + isize; - luaL_Buffer buffer; - /* end-of-input blackhole */ - if (!input) { - lua_pushnil(L); - lua_pushnil(L); - return 2; - } - /* make sure we don't confuse buffer stuff with arguments */ - lua_settop(L, 2); - /* process first part of the input */ - luaL_buffinit(L, &buffer); - while (input < last) - asize = b64encode(*input++, atom, asize, &buffer); - input = (const UC *) luaL_optlstring(L, 2, NULL, &isize); - /* if second part is nil, we are done */ - if (!input) { - size_t osize = 0; - asize = b64pad(atom, asize, &buffer); - luaL_pushresult(&buffer); - /* if the output is empty and the input is nil, return nil */ - lua_tolstring(L, -1, &osize); - if (osize == 0) lua_pushnil(L); - lua_pushnil(L); - return 2; - } - /* otherwise process the second part */ - last = input + isize; - while (input < last) - asize = b64encode(*input++, atom, asize, &buffer); - luaL_pushresult(&buffer); - lua_pushlstring(L, (char *) atom, asize); - return 2; + UC atom[3]; + size_t isize = 0, asize = 0; + const UC* input = (const UC*)luaL_optlstring(L, 1, NULL, &isize); + const UC* last = input + isize; + luaL_Buffer buffer; + /* end-of-input blackhole */ + if (!input) + { + lua_pushnil(L); + lua_pushnil(L); + return 2; + } + /* make sure we don't confuse buffer stuff with arguments */ + lua_settop(L, 2); + /* process first part of the input */ + luaL_buffinit(L, &buffer); + while (input < last) + asize = b64encode(*input++, atom, asize, &buffer); + input = (const UC*)luaL_optlstring(L, 2, NULL, &isize); + /* if second part is nil, we are done */ + if (!input) + { + size_t osize = 0; + asize = b64pad(atom, asize, &buffer); + luaL_pushresult(&buffer); + /* if the output is empty and the input is nil, return nil */ + lua_tolstring(L, -1, &osize); + if (osize == 0) lua_pushnil(L); + lua_pushnil(L); + return 2; + } + /* otherwise process the second part */ + last = input + isize; + while (input < last) + asize = b64encode(*input++, atom, asize, &buffer); + luaL_pushresult(&buffer); + lua_pushlstring(L, (char*)atom, asize); + return 2; } /*-------------------------------------------------------------------------*\ @@ -294,43 +320,45 @@ static int mime_global_b64(lua_State *L) * A is the encoded version of the largest prefix of C .. D that is * divisible by 4. B has the remaining bytes of C .. D, *without* encoding. \*-------------------------------------------------------------------------*/ -static int mime_global_unb64(lua_State *L) +static int mime_global_unb64(lua_State* L) { - UC atom[4]; - size_t isize = 0, asize = 0; - const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize); - const UC *last = input + isize; - luaL_Buffer buffer; - /* end-of-input blackhole */ - if (!input) { - lua_pushnil(L); - lua_pushnil(L); - return 2; - } - /* make sure we don't confuse buffer stuff with arguments */ - lua_settop(L, 2); - /* process first part of the input */ - luaL_buffinit(L, &buffer); - while (input < last) - asize = b64decode(*input++, atom, asize, &buffer); - input = (const UC *) luaL_optlstring(L, 2, NULL, &isize); - /* if second is nil, we are done */ - if (!input) { - size_t osize = 0; - luaL_pushresult(&buffer); - /* if the output is empty and the input is nil, return nil */ - lua_tolstring(L, -1, &osize); - if (osize == 0) lua_pushnil(L); - lua_pushnil(L); - return 2; - } - /* otherwise, process the rest of the input */ - last = input + isize; - while (input < last) - asize = b64decode(*input++, atom, asize, &buffer); - luaL_pushresult(&buffer); - lua_pushlstring(L, (char *) atom, asize); - return 2; + UC atom[4]; + size_t isize = 0, asize = 0; + const UC* input = (const UC*)luaL_optlstring(L, 1, NULL, &isize); + const UC* last = input + isize; + luaL_Buffer buffer; + /* end-of-input blackhole */ + if (!input) + { + lua_pushnil(L); + lua_pushnil(L); + return 2; + } + /* make sure we don't confuse buffer stuff with arguments */ + lua_settop(L, 2); + /* process first part of the input */ + luaL_buffinit(L, &buffer); + while (input < last) + asize = b64decode(*input++, atom, asize, &buffer); + input = (const UC*)luaL_optlstring(L, 2, NULL, &isize); + /* if second is nil, we are done */ + if (!input) + { + size_t osize = 0; + luaL_pushresult(&buffer); + /* if the output is empty and the input is nil, return nil */ + lua_tolstring(L, -1, &osize); + if (osize == 0) lua_pushnil(L); + lua_pushnil(L); + return 2; + } + /* otherwise, process the rest of the input */ + last = input + isize; + while (input < last) + asize = b64decode(*input++, atom, asize, &buffer); + luaL_pushresult(&buffer); + lua_pushlstring(L, (char*)atom, asize); + return 2; } /*-------------------------------------------------------------------------*\ @@ -349,92 +377,116 @@ static int mime_global_unb64(lua_State *L) * Split quoted-printable characters into classes * Precompute reverse map for encoding \*-------------------------------------------------------------------------*/ -static void qpsetup(UC *cl, UC *unbase) +static void qpsetup(UC* cl, UC* unbase) { - int i; - for (i = 0; i < 256; i++) cl[i] = QP_QUOTED; - for (i = 33; i <= 60; i++) cl[i] = QP_PLAIN; - for (i = 62; i <= 126; i++) cl[i] = QP_PLAIN; - cl['\t'] = QP_IF_LAST; - cl[' '] = QP_IF_LAST; - cl['\r'] = QP_CR; - for (i = 0; i < 256; i++) unbase[i] = 255; - unbase['0'] = 0; unbase['1'] = 1; unbase['2'] = 2; - unbase['3'] = 3; unbase['4'] = 4; unbase['5'] = 5; - unbase['6'] = 6; unbase['7'] = 7; unbase['8'] = 8; - unbase['9'] = 9; unbase['A'] = 10; unbase['a'] = 10; - unbase['B'] = 11; unbase['b'] = 11; unbase['C'] = 12; - unbase['c'] = 12; unbase['D'] = 13; unbase['d'] = 13; - unbase['E'] = 14; unbase['e'] = 14; unbase['F'] = 15; - unbase['f'] = 15; + int i; + for (i = 0; i < 256; i++) cl[i] = QP_QUOTED; + for (i = 33; i <= 60; i++) cl[i] = QP_PLAIN; + for (i = 62; i <= 126; i++) cl[i] = QP_PLAIN; + cl['\t'] = QP_IF_LAST; + cl[' '] = QP_IF_LAST; + cl['\r'] = QP_CR; + for (i = 0; i < 256; i++) unbase[i] = 255; + unbase['0'] = 0; + unbase['1'] = 1; + unbase['2'] = 2; + unbase['3'] = 3; + unbase['4'] = 4; + unbase['5'] = 5; + unbase['6'] = 6; + unbase['7'] = 7; + unbase['8'] = 8; + unbase['9'] = 9; + unbase['A'] = 10; + unbase['a'] = 10; + unbase['B'] = 11; + unbase['b'] = 11; + unbase['C'] = 12; + unbase['c'] = 12; + unbase['D'] = 13; + unbase['d'] = 13; + unbase['E'] = 14; + unbase['e'] = 14; + unbase['F'] = 15; + unbase['f'] = 15; } /*-------------------------------------------------------------------------*\ * Output one character in form =XX \*-------------------------------------------------------------------------*/ -static void qpquote(UC c, luaL_Buffer *buffer) +static void qpquote(UC c, luaL_Buffer* buffer) { - luaL_addchar(buffer, '='); - luaL_addchar(buffer, qpbase[c >> 4]); - luaL_addchar(buffer, qpbase[c & 0x0F]); + luaL_addchar(buffer, '='); + luaL_addchar(buffer, qpbase[c >> 4]); + luaL_addchar(buffer, qpbase[c & 0x0F]); } /*-------------------------------------------------------------------------*\ * Accumulate characters until we are sure about how to deal with them. * Once we are sure, output to the buffer, in the correct form. \*-------------------------------------------------------------------------*/ -static size_t qpencode(UC c, UC *input, size_t size, - const char *marker, luaL_Buffer *buffer) +static size_t qpencode(UC c, UC* input, size_t size, + const char* marker, luaL_Buffer* buffer) { - input[size++] = c; - /* deal with all characters we can have */ - while (size > 0) { - switch (qpclass[input[0]]) { - /* might be the CR of a CRLF sequence */ - case QP_CR: - if (size < 2) return size; - if (input[1] == '\n') { - luaL_addstring(buffer, marker); - return 0; - } else qpquote(input[0], buffer); - break; - /* might be a space and that has to be quoted if last in line */ - case QP_IF_LAST: - if (size < 3) return size; - /* if it is the last, quote it and we are done */ - if (input[1] == '\r' && input[2] == '\n') { - qpquote(input[0], buffer); - luaL_addstring(buffer, marker); - return 0; - } else luaL_addchar(buffer, input[0]); - break; - /* might have to be quoted always */ - case QP_QUOTED: - qpquote(input[0], buffer); - break; - /* might never have to be quoted */ - default: - luaL_addchar(buffer, input[0]); - break; - } - input[0] = input[1]; input[1] = input[2]; - size--; - } - return 0; + input[size++] = c; + /* deal with all characters we can have */ + while (size > 0) + { + switch (qpclass[input[0]]) + { + /* might be the CR of a CRLF sequence */ + case QP_CR: + if (size < 2) return size; + if (input[1] == '\n') + { + luaL_addstring(buffer, marker); + return 0; + } + else qpquote(input[0], buffer); + break; + /* might be a space and that has to be quoted if last in line */ + case QP_IF_LAST: + if (size < 3) return size; + /* if it is the last, quote it and we are done */ + if (input[1] == '\r' && input[2] == '\n') + { + qpquote(input[0], buffer); + luaL_addstring(buffer, marker); + return 0; + } + else + luaL_addchar(buffer, input[0]); + break; + /* might have to be quoted always */ + case QP_QUOTED: + qpquote(input[0], buffer); + break; + /* might never have to be quoted */ + default: + luaL_addchar(buffer, input[0]); + break; + } + input[0] = input[1]; + input[1] = input[2]; + size--; + } + return 0; } /*-------------------------------------------------------------------------*\ * Deal with the final characters \*-------------------------------------------------------------------------*/ -static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer) +static size_t qppad(UC* input, size_t size, luaL_Buffer* buffer) { - size_t i; - for (i = 0; i < size; i++) { - if (qpclass[input[i]] == QP_PLAIN) luaL_addchar(buffer, input[i]); - else qpquote(input[i], buffer); - } - if (size > 0) luaL_addstring(buffer, EQCRLF); - return 0; + size_t i; + for (i = 0; i < size; i++) + { + if (qpclass[input[i]] == QP_PLAIN) + luaL_addchar(buffer, input[i]); + else qpquote(input[i], buffer); + } + if (size > 0) luaL_addstring(buffer, EQCRLF); + return 0; } /*-------------------------------------------------------------------------*\ @@ -445,74 +497,79 @@ static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer) * can be encoded without doubts. * B has the remaining bytes of C .. D, *without* encoding. \*-------------------------------------------------------------------------*/ -static int mime_global_qp(lua_State *L) +static int mime_global_qp(lua_State* L) { - - size_t asize = 0, isize = 0; - UC atom[3]; - const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize); - const UC *last = input + isize; - const char *marker = luaL_optstring(L, 3, CRLF); - luaL_Buffer buffer; - /* end-of-input blackhole */ - if (!input) { - lua_pushnil(L); - lua_pushnil(L); - return 2; - } - /* make sure we don't confuse buffer stuff with arguments */ - lua_settop(L, 3); - /* process first part of input */ - luaL_buffinit(L, &buffer); - while (input < last) - asize = qpencode(*input++, atom, asize, marker, &buffer); - input = (const UC *) luaL_optlstring(L, 2, NULL, &isize); - /* if second part is nil, we are done */ - if (!input) { - asize = qppad(atom, asize, &buffer); - luaL_pushresult(&buffer); - if (!(*lua_tostring(L, -1))) lua_pushnil(L); - lua_pushnil(L); - return 2; - } - /* otherwise process rest of input */ - last = input + isize; - while (input < last) - asize = qpencode(*input++, atom, asize, marker, &buffer); - luaL_pushresult(&buffer); - lua_pushlstring(L, (char *) atom, asize); - return 2; + size_t asize = 0, isize = 0; + UC atom[3]; + const UC* input = (const UC*)luaL_optlstring(L, 1, NULL, &isize); + const UC* last = input + isize; + const char* marker = luaL_optstring(L, 3, CRLF); + luaL_Buffer buffer; + /* end-of-input blackhole */ + if (!input) + { + lua_pushnil(L); + lua_pushnil(L); + return 2; + } + /* make sure we don't confuse buffer stuff with arguments */ + lua_settop(L, 3); + /* process first part of input */ + luaL_buffinit(L, &buffer); + while (input < last) + asize = qpencode(*input++, atom, asize, marker, &buffer); + input = (const UC*)luaL_optlstring(L, 2, NULL, &isize); + /* if second part is nil, we are done */ + if (!input) + { + asize = qppad(atom, asize, &buffer); + luaL_pushresult(&buffer); + if (!(*lua_tostring(L, -1))) lua_pushnil(L); + lua_pushnil(L); + return 2; + } + /* otherwise process rest of input */ + last = input + isize; + while (input < last) + asize = qpencode(*input++, atom, asize, marker, &buffer); + luaL_pushresult(&buffer); + lua_pushlstring(L, (char*)atom, asize); + return 2; } /*-------------------------------------------------------------------------*\ * Accumulate characters until we are sure about how to deal with them. * Once we are sure, output the to the buffer, in the correct form. \*-------------------------------------------------------------------------*/ -static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer) { - int d; - input[size++] = c; - /* deal with all characters we can deal */ - switch (input[0]) { - /* if we have an escape character */ - case '=': - if (size < 3) return size; - /* eliminate soft line break */ - if (input[1] == '\r' && input[2] == '\n') return 0; - /* decode quoted representation */ - c = qpunbase[input[1]]; d = qpunbase[input[2]]; - /* if it is an invalid, do not decode */ - if (c > 15 || d > 15) luaL_addlstring(buffer, (char *)input, 3); - else luaL_addchar(buffer, (char) ((c << 4) + d)); - return 0; - case '\r': - if (size < 2) return size; - if (input[1] == '\n') luaL_addlstring(buffer, (char *)input, 2); - return 0; - default: - if (input[0] == '\t' || (input[0] > 31 && input[0] < 127)) - luaL_addchar(buffer, input[0]); - return 0; - } +static size_t qpdecode(UC c, UC* input, size_t size, luaL_Buffer* buffer) +{ + int d; + input[size++] = c; + /* deal with all characters we can deal */ + switch (input[0]) + { + /* if we have an escape character */ + case '=': + if (size < 3) return size; + /* eliminate soft line break */ + if (input[1] == '\r' && input[2] == '\n') return 0; + /* decode quoted representation */ + c = qpunbase[input[1]]; + d = qpunbase[input[2]]; + /* if it is an invalid, do not decode */ + if (c > 15 || d > 15) luaL_addlstring(buffer, (char*)input, 3); + else + luaL_addchar(buffer, (char) ((c << 4) + d)); + return 0; + case '\r': + if (size < 2) return size; + if (input[1] == '\n') luaL_addlstring(buffer, (char*)input, 2); + return 0; + default: + if (input[0] == '\t' || (input[0] > 31 && input[0] < 127)) + luaL_addchar(buffer, input[0]); + return 0; + } } /*-------------------------------------------------------------------------*\ @@ -522,40 +579,42 @@ static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer) { * can be decoded without doubts. * B has the remaining bytes of C .. D, *without* decoding. \*-------------------------------------------------------------------------*/ -static int mime_global_unqp(lua_State *L) +static int mime_global_unqp(lua_State* L) { - size_t asize = 0, isize = 0; - UC atom[3]; - const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize); - const UC *last = input + isize; - luaL_Buffer buffer; - /* end-of-input blackhole */ - if (!input) { - lua_pushnil(L); - lua_pushnil(L); - return 2; - } - /* make sure we don't confuse buffer stuff with arguments */ - lua_settop(L, 2); - /* process first part of input */ - luaL_buffinit(L, &buffer); - while (input < last) - asize = qpdecode(*input++, atom, asize, &buffer); - input = (const UC *) luaL_optlstring(L, 2, NULL, &isize); - /* if second part is nil, we are done */ - if (!input) { - luaL_pushresult(&buffer); - if (!(*lua_tostring(L, -1))) lua_pushnil(L); - lua_pushnil(L); - return 2; - } - /* otherwise process rest of input */ - last = input + isize; - while (input < last) - asize = qpdecode(*input++, atom, asize, &buffer); - luaL_pushresult(&buffer); - lua_pushlstring(L, (char *) atom, asize); - return 2; + size_t asize = 0, isize = 0; + UC atom[3]; + const UC* input = (const UC*)luaL_optlstring(L, 1, NULL, &isize); + const UC* last = input + isize; + luaL_Buffer buffer; + /* end-of-input blackhole */ + if (!input) + { + lua_pushnil(L); + lua_pushnil(L); + return 2; + } + /* make sure we don't confuse buffer stuff with arguments */ + lua_settop(L, 2); + /* process first part of input */ + luaL_buffinit(L, &buffer); + while (input < last) + asize = qpdecode(*input++, atom, asize, &buffer); + input = (const UC*)luaL_optlstring(L, 2, NULL, &isize); + /* if second part is nil, we are done */ + if (!input) + { + luaL_pushresult(&buffer); + if (!(*lua_tostring(L, -1))) lua_pushnil(L); + lua_pushnil(L); + return 2; + } + /* otherwise process rest of input */ + last = input + isize; + while (input < last) + asize = qpdecode(*input++, atom, asize, &buffer); + luaL_pushresult(&buffer); + lua_pushlstring(L, (char*)atom, asize); + return 2; } /*-------------------------------------------------------------------------*\ @@ -567,53 +626,58 @@ static int mime_global_unqp(lua_State *L) * There are two complications: lines can't be broken in the middle * of an encoded =XX, and there might be line breaks already \*-------------------------------------------------------------------------*/ -static int mime_global_qpwrp(lua_State *L) +static int mime_global_qpwrp(lua_State* L) { - size_t size = 0; - int left = (int) luaL_checknumber(L, 1); - const UC *input = (const UC *) luaL_optlstring(L, 2, NULL, &size); - const UC *last = input + size; - int length = (int) luaL_optnumber(L, 3, 76); - luaL_Buffer buffer; - /* end-of-input blackhole */ - if (!input) { - if (left < length) lua_pushstring(L, EQCRLF); - else lua_pushnil(L); - lua_pushnumber(L, length); - return 2; - } - /* process all input */ - luaL_buffinit(L, &buffer); - while (input < last) { - switch (*input) { - case '\r': - break; - case '\n': - left = length; - luaL_addstring(&buffer, CRLF); - break; - case '=': - if (left <= 3) { - left = length; - luaL_addstring(&buffer, EQCRLF); - } - luaL_addchar(&buffer, *input); - left--; - break; - default: - if (left <= 1) { - left = length; - luaL_addstring(&buffer, EQCRLF); - } - luaL_addchar(&buffer, *input); - left--; - break; - } - input++; - } - luaL_pushresult(&buffer); - lua_pushnumber(L, left); - return 2; + size_t size = 0; + int left = (int)luaL_checknumber(L, 1); + const UC* input = (const UC*)luaL_optlstring(L, 2, NULL, &size); + const UC* last = input + size; + int length = (int)luaL_optnumber(L, 3, 76); + luaL_Buffer buffer; + /* end-of-input blackhole */ + if (!input) + { + if (left < length) lua_pushstring(L, EQCRLF); + else lua_pushnil(L); + lua_pushnumber(L, length); + return 2; + } + /* process all input */ + luaL_buffinit(L, &buffer); + while (input < last) + { + switch (*input) + { + case '\r': + break; + case '\n': + left = length; + luaL_addstring(&buffer, CRLF); + break; + case '=': + if (left <= 3) + { + left = length; + luaL_addstring(&buffer, EQCRLF); + } + luaL_addchar(&buffer, *input); + left--; + break; + default: + if (left <= 1) + { + left = length; + luaL_addstring(&buffer, EQCRLF); + } + luaL_addchar(&buffer, *input); + left--; + break; + } + input++; + } + luaL_pushresult(&buffer); + lua_pushnumber(L, left); + return 2; } /*-------------------------------------------------------------------------*\ @@ -628,21 +692,28 @@ static int mime_global_qpwrp(lua_State *L) * last is the previous character \*-------------------------------------------------------------------------*/ #define eolcandidate(c) (c == '\r' || c == '\n') -static int eolprocess(int c, int last, const char *marker, - luaL_Buffer *buffer) + +static int eolprocess(int c, int last, const char* marker, + luaL_Buffer* buffer) { - if (eolcandidate(c)) { - if (eolcandidate(last)) { - if (c == last) luaL_addstring(buffer, marker); - return 0; - } else { - luaL_addstring(buffer, marker); - return c; - } - } else { - luaL_addchar(buffer, (char) c); - return 0; - } + if (eolcandidate(c)) + { + if (eolcandidate(last)) + { + if (c == last) luaL_addstring(buffer, marker); + return 0; + } + else + { + luaL_addstring(buffer, marker); + return c; + } + } + else + { + luaL_addchar(buffer, (char) c); + return 0; + } } /*-------------------------------------------------------------------------*\ @@ -652,71 +723,73 @@ static int eolprocess(int c, int last, const char *marker, * converted unambiguously. 'o' is the context returned by the previous * call. 'n' is the new context. \*-------------------------------------------------------------------------*/ -static int mime_global_eol(lua_State *L) +static int mime_global_eol(lua_State* L) { - int ctx = (int) luaL_checkinteger(L, 1); - size_t isize = 0; - const char *input = luaL_optlstring(L, 2, NULL, &isize); - const char *last = input + isize; - const char *marker = luaL_optstring(L, 3, CRLF); - luaL_Buffer buffer; - luaL_buffinit(L, &buffer); - /* end of input blackhole */ - if (!input) { - lua_pushnil(L); - lua_pushnumber(L, 0); - return 2; - } - /* process all input */ - while (input < last) - ctx = eolprocess(*input++, ctx, marker, &buffer); - luaL_pushresult(&buffer); - lua_pushnumber(L, ctx); - return 2; + int ctx = (int)luaL_checkinteger(L, 1); + size_t isize = 0; + const char* input = luaL_optlstring(L, 2, NULL, &isize); + const char* last = input + isize; + const char* marker = luaL_optstring(L, 3, CRLF); + luaL_Buffer buffer; + luaL_buffinit(L, &buffer); + /* end of input blackhole */ + if (!input) + { + lua_pushnil(L); + lua_pushnumber(L, 0); + return 2; + } + /* process all input */ + while (input < last) + ctx = eolprocess(*input++, ctx, marker, &buffer); + luaL_pushresult(&buffer); + lua_pushnumber(L, ctx); + return 2; } /*-------------------------------------------------------------------------*\ * Takes one byte and stuff it if needed. \*-------------------------------------------------------------------------*/ -static size_t dot(int c, size_t state, luaL_Buffer *buffer) +static size_t dot(int c, size_t state, luaL_Buffer* buffer) { - luaL_addchar(buffer, (char) c); - switch (c) { - case '\r': - return 1; - case '\n': - return (state == 1)? 2: 0; - case '.': - if (state == 2) - luaL_addchar(buffer, '.'); - /* Falls through. */ - default: - return 0; - } + luaL_addchar(buffer, (char) c); + switch (c) + { + case '\r': + return 1; + case '\n': + return (state == 1) ? 2 : 0; + case '.': + if (state == 2) + luaL_addchar(buffer, '.'); + /* Falls through. */ + default: + return 0; + } } /*-------------------------------------------------------------------------*\ * Incrementally applies smtp stuffing to a string * A, n = dot(l, D) \*-------------------------------------------------------------------------*/ -static int mime_global_dot(lua_State *L) +static int mime_global_dot(lua_State* L) { - size_t isize = 0, state = (size_t) luaL_checknumber(L, 1); - const char *input = luaL_optlstring(L, 2, NULL, &isize); - const char *last = input + isize; - luaL_Buffer buffer; - /* end-of-input blackhole */ - if (!input) { - lua_pushnil(L); - lua_pushnumber(L, 2); - return 2; - } - /* process all input */ - luaL_buffinit(L, &buffer); - while (input < last) - state = dot(*input++, state, &buffer); - luaL_pushresult(&buffer); - lua_pushnumber(L, (lua_Number) state); - return 2; + size_t isize = 0, state = (size_t)luaL_checknumber(L, 1); + const char* input = luaL_optlstring(L, 2, NULL, &isize); + const char* last = input + isize; + luaL_Buffer buffer; + /* end-of-input blackhole */ + if (!input) + { + lua_pushnil(L); + lua_pushnumber(L, 2); + return 2; + } + /* process all input */ + luaL_buffinit(L, &buffer); + while (input < last) + state = dot(*input++, state, &buffer); + luaL_pushresult(&buffer); + lua_pushnumber(L, (lua_Number)state); + return 2; } - diff --git a/Lua/mime.h b/Lua/mime.h index 99968a5..94a380f 100644 --- a/Lua/mime.h +++ b/Lua/mime.h @@ -1,4 +1,4 @@ -#ifndef MIME_H +#ifndef MIME_H #define MIME_H /*=========================================================================*\ * Core MIME support @@ -24,6 +24,6 @@ #define MIME_API extern #endif -MIME_API int luaopen_mime_core(lua_State *L); +MIME_API int luaopen_mime_core(lua_State* L); #endif /* MIME_H */ diff --git a/Lua/options.c b/Lua/options.c index fabfe8c..1b09d7f 100644 --- a/Lua/options.c +++ b/Lua/options.c @@ -14,16 +14,16 @@ /*=========================================================================*\ * Internal functions prototypes \*=========================================================================*/ -static int opt_setmembership(lua_State *L, p_socket ps, int level, int name); -static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name); -static int opt_setboolean(lua_State *L, p_socket ps, int level, int name); -static int opt_getboolean(lua_State *L, p_socket ps, int level, int name); -static int opt_setint(lua_State *L, p_socket ps, int level, int name); -static int opt_getint(lua_State *L, p_socket ps, int level, int name); -static int opt_set(lua_State *L, p_socket ps, int level, int name, - void *val, int len); -static int opt_get(lua_State *L, p_socket ps, int level, int name, - void *val, int* len); +static int opt_setmembership(lua_State* L, p_socket ps, int level, int name); +static int opt_ip6_setmembership(lua_State* L, p_socket ps, int level, int name); +static int opt_setboolean(lua_State* L, p_socket ps, int level, int name); +static int opt_getboolean(lua_State* L, p_socket ps, int level, int name); +static int opt_setint(lua_State* L, p_socket ps, int level, int name); +static int opt_getint(lua_State* L, p_socket ps, int level, int name); +static int opt_set(lua_State* L, p_socket ps, int level, int name, + void* val, int len); +static int opt_get(lua_State* L, p_socket ps, int level, int name, + void* val, int* len); /*=========================================================================*\ * Exported functions @@ -31,344 +31,353 @@ static int opt_get(lua_State *L, p_socket ps, int level, int name, /*-------------------------------------------------------------------------*\ * Calls appropriate option handler \*-------------------------------------------------------------------------*/ -int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps) +int opt_meth_setoption(lua_State* L, p_opt opt, p_socket ps) { - const char *name = luaL_checkstring(L, 2); /* obj, name, ... */ - while (opt->name && strcmp(name, opt->name)) - opt++; - if (!opt->func) { - char msg[57]; - sprintf(msg, "unsupported option `%.35s'", name); - luaL_argerror(L, 2, msg); - } - return opt->func(L, ps); + const char* name = luaL_checkstring(L, 2); /* obj, name, ... */ + while (opt->name && strcmp(name, opt->name)) + opt++; + if (!opt->func) + { + char msg[57]; + sprintf(msg, "unsupported option `%.35s'", name); + luaL_argerror(L, 2, msg); + } + return opt->func(L, ps); } -int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps) +int opt_meth_getoption(lua_State* L, p_opt opt, p_socket ps) { - const char *name = luaL_checkstring(L, 2); /* obj, name, ... */ - while (opt->name && strcmp(name, opt->name)) - opt++; - if (!opt->func) { - char msg[57]; - sprintf(msg, "unsupported option `%.35s'", name); - luaL_argerror(L, 2, msg); - } - return opt->func(L, ps); + const char* name = luaL_checkstring(L, 2); /* obj, name, ... */ + while (opt->name && strcmp(name, opt->name)) + opt++; + if (!opt->func) + { + char msg[57]; + sprintf(msg, "unsupported option `%.35s'", name); + luaL_argerror(L, 2, msg); + } + return opt->func(L, ps); } /* enables reuse of local address */ -int opt_set_reuseaddr(lua_State *L, p_socket ps) +int opt_set_reuseaddr(lua_State* L, p_socket ps) { - return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); + return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); } -int opt_get_reuseaddr(lua_State *L, p_socket ps) +int opt_get_reuseaddr(lua_State* L, p_socket ps) { - return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); + return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); } /* enables reuse of local port */ -int opt_set_reuseport(lua_State *L, p_socket ps) +int opt_set_reuseport(lua_State* L, p_socket ps) { - return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEPORT); + return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEPORT); } -int opt_get_reuseport(lua_State *L, p_socket ps) +int opt_get_reuseport(lua_State* L, p_socket ps) { - return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEPORT); + return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEPORT); } /* disables the Naggle algorithm */ -int opt_set_tcp_nodelay(lua_State *L, p_socket ps) +int opt_set_tcp_nodelay(lua_State* L, p_socket ps) { - return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); + return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); } -int opt_get_tcp_nodelay(lua_State *L, p_socket ps) +int opt_get_tcp_nodelay(lua_State* L, p_socket ps) { - return opt_getboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); + return opt_getboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); } -int opt_set_keepalive(lua_State *L, p_socket ps) +int opt_set_keepalive(lua_State* L, p_socket ps) { - return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); + return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); } -int opt_get_keepalive(lua_State *L, p_socket ps) +int opt_get_keepalive(lua_State* L, p_socket ps) { - return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); + return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); } -int opt_set_dontroute(lua_State *L, p_socket ps) +int opt_set_dontroute(lua_State* L, p_socket ps) { - return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE); + return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE); } -int opt_get_dontroute(lua_State *L, p_socket ps) +int opt_get_dontroute(lua_State* L, p_socket ps) { - return opt_getboolean(L, ps, SOL_SOCKET, SO_DONTROUTE); + return opt_getboolean(L, ps, SOL_SOCKET, SO_DONTROUTE); } -int opt_set_broadcast(lua_State *L, p_socket ps) +int opt_set_broadcast(lua_State* L, p_socket ps) { - return opt_setboolean(L, ps, SOL_SOCKET, SO_BROADCAST); + return opt_setboolean(L, ps, SOL_SOCKET, SO_BROADCAST); } -int opt_get_broadcast(lua_State *L, p_socket ps) +int opt_get_broadcast(lua_State* L, p_socket ps) { - return opt_getboolean(L, ps, SOL_SOCKET, SO_BROADCAST); + return opt_getboolean(L, ps, SOL_SOCKET, SO_BROADCAST); } -int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps) +int opt_set_ip6_unicast_hops(lua_State* L, p_socket ps) { - return opt_setint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); + return opt_setint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); } -int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps) +int opt_get_ip6_unicast_hops(lua_State* L, p_socket ps) { - return opt_getint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); + return opt_getint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); } -int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps) +int opt_set_ip6_multicast_hops(lua_State* L, p_socket ps) { - return opt_setint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); + return opt_setint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); } -int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps) +int opt_get_ip6_multicast_hops(lua_State* L, p_socket ps) { - return opt_getint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); + return opt_getint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); } -int opt_set_ip_multicast_loop(lua_State *L, p_socket ps) +int opt_set_ip_multicast_loop(lua_State* L, p_socket ps) { - return opt_setboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); + return opt_setboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); } -int opt_get_ip_multicast_loop(lua_State *L, p_socket ps) +int opt_get_ip_multicast_loop(lua_State* L, p_socket ps) { - return opt_getboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); + return opt_getboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); } -int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps) +int opt_set_ip6_multicast_loop(lua_State* L, p_socket ps) { - return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); + return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); } -int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps) +int opt_get_ip6_multicast_loop(lua_State* L, p_socket ps) { - return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); + return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); } -int opt_set_linger(lua_State *L, p_socket ps) +int opt_set_linger(lua_State* L, p_socket ps) { - struct linger li; /* obj, name, table */ - if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE)); - lua_pushstring(L, "on"); - lua_gettable(L, 3); - if (!lua_isboolean(L, -1)) - luaL_argerror(L, 3, "boolean 'on' field expected"); - li.l_onoff = (u_short) lua_toboolean(L, -1); - lua_pushstring(L, "timeout"); - lua_gettable(L, 3); - if (!lua_isnumber(L, -1)) - luaL_argerror(L, 3, "number 'timeout' field expected"); - li.l_linger = (u_short) lua_tonumber(L, -1); - return opt_set(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(li)); + struct linger li; /* obj, name, table */ + if (!lua_istable(L, 3)) auxiliar_typeerror(L, 3, lua_typename(L, LUA_TTABLE)); + lua_pushstring(L, "on"); + lua_gettable(L, 3); + if (!lua_isboolean(L, -1)) + luaL_argerror(L, 3, "boolean 'on' field expected"); + li.l_onoff = (u_short)lua_toboolean(L, -1); + lua_pushstring(L, "timeout"); + lua_gettable(L, 3); + if (!lua_isnumber(L, -1)) + luaL_argerror(L, 3, "number 'timeout' field expected"); + li.l_linger = (u_short)lua_tonumber(L, -1); + return opt_set(L, ps, SOL_SOCKET, SO_LINGER, (char*)&li, sizeof(li)); } -int opt_get_linger(lua_State *L, p_socket ps) +int opt_get_linger(lua_State* L, p_socket ps) { - struct linger li; /* obj, name */ - int len = sizeof(li); - int err = opt_get(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, &len); - if (err) - return err; - lua_newtable(L); - lua_pushboolean(L, li.l_onoff); - lua_setfield(L, -2, "on"); - lua_pushinteger(L, li.l_linger); - lua_setfield(L, -2, "timeout"); - return 1; + struct linger li; /* obj, name */ + int len = sizeof(li); + int err = opt_get(L, ps, SOL_SOCKET, SO_LINGER, (char*)&li, &len); + if (err) + return err; + lua_newtable(L); + lua_pushboolean(L, li.l_onoff); + lua_setfield(L, -2, "on"); + lua_pushinteger(L, li.l_linger); + lua_setfield(L, -2, "timeout"); + return 1; } -int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps) +int opt_set_ip_multicast_ttl(lua_State* L, p_socket ps) { - return opt_setint(L, ps, IPPROTO_IP, IP_MULTICAST_TTL); + return opt_setint(L, ps, IPPROTO_IP, IP_MULTICAST_TTL); } -int opt_set_ip_multicast_if(lua_State *L, p_socket ps) +int opt_set_ip_multicast_if(lua_State* L, p_socket ps) { - const char *address = luaL_checkstring(L, 3); /* obj, name, ip */ - struct in_addr val; - val.s_addr = htonl(INADDR_ANY); - if (strcmp(address, "*") && !inet_aton(address, &val)) - luaL_argerror(L, 3, "ip expected"); - return opt_set(L, ps, IPPROTO_IP, IP_MULTICAST_IF, - (char *) &val, sizeof(val)); + const char* address = luaL_checkstring(L, 3); /* obj, name, ip */ + struct in_addr val; + val.s_addr = htonl(INADDR_ANY); + if (strcmp(address, "*") && !inet_aton(address, &val)) + luaL_argerror(L, 3, "ip expected"); + return opt_set(L, ps, IPPROTO_IP, IP_MULTICAST_IF, + (char*)&val, sizeof(val)); } -int opt_get_ip_multicast_if(lua_State *L, p_socket ps) +int opt_get_ip_multicast_if(lua_State* L, p_socket ps) { - struct in_addr val; - socklen_t len = sizeof(val); - if (getsockopt(*ps, IPPROTO_IP, IP_MULTICAST_IF, (char *) &val, &len) < 0) { - lua_pushnil(L); - lua_pushstring(L, "getsockopt failed"); - return 2; - } - lua_pushstring(L, inet_ntoa(val)); - return 1; + struct in_addr val; + socklen_t len = sizeof(val); + if (getsockopt(*ps, IPPROTO_IP, IP_MULTICAST_IF, (char*)&val, &len) < 0) + { + lua_pushnil(L); + lua_pushstring(L, "getsockopt failed"); + return 2; + } + lua_pushstring(L, inet_ntoa(val)); + return 1; } -int opt_set_ip_add_membership(lua_State *L, p_socket ps) +int opt_set_ip_add_membership(lua_State* L, p_socket ps) { - return opt_setmembership(L, ps, IPPROTO_IP, IP_ADD_MEMBERSHIP); + return opt_setmembership(L, ps, IPPROTO_IP, IP_ADD_MEMBERSHIP); } -int opt_set_ip_drop_membersip(lua_State *L, p_socket ps) +int opt_set_ip_drop_membersip(lua_State* L, p_socket ps) { - return opt_setmembership(L, ps, IPPROTO_IP, IP_DROP_MEMBERSHIP); + return opt_setmembership(L, ps, IPPROTO_IP, IP_DROP_MEMBERSHIP); } -int opt_set_ip6_add_membership(lua_State *L, p_socket ps) +int opt_set_ip6_add_membership(lua_State* L, p_socket ps) { - return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP); + return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP); } -int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps) +int opt_set_ip6_drop_membersip(lua_State* L, p_socket ps) { - return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP); + return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP); } -int opt_get_ip6_v6only(lua_State *L, p_socket ps) +int opt_get_ip6_v6only(lua_State* L, p_socket ps) { - return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); + return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); } -int opt_set_ip6_v6only(lua_State *L, p_socket ps) +int opt_set_ip6_v6only(lua_State* L, p_socket ps) { - return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); + return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); } /*=========================================================================*\ * Auxiliar functions \*=========================================================================*/ -static int opt_setmembership(lua_State *L, p_socket ps, int level, int name) +static int opt_setmembership(lua_State* L, p_socket ps, int level, int name) { - struct ip_mreq val; /* obj, name, table */ - if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE)); - lua_pushstring(L, "multiaddr"); - lua_gettable(L, 3); - if (!lua_isstring(L, -1)) - luaL_argerror(L, 3, "string 'multiaddr' field expected"); - if (!inet_aton(lua_tostring(L, -1), &val.imr_multiaddr)) - luaL_argerror(L, 3, "invalid 'multiaddr' ip address"); - lua_pushstring(L, "interface"); - lua_gettable(L, 3); - if (!lua_isstring(L, -1)) - luaL_argerror(L, 3, "string 'interface' field expected"); - val.imr_interface.s_addr = htonl(INADDR_ANY); - if (strcmp(lua_tostring(L, -1), "*") && - !inet_aton(lua_tostring(L, -1), &val.imr_interface)) - luaL_argerror(L, 3, "invalid 'interface' ip address"); - return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); + struct ip_mreq val; /* obj, name, table */ + if (!lua_istable(L, 3)) auxiliar_typeerror(L, 3, lua_typename(L, LUA_TTABLE)); + lua_pushstring(L, "multiaddr"); + lua_gettable(L, 3); + if (!lua_isstring(L, -1)) + luaL_argerror(L, 3, "string 'multiaddr' field expected"); + if (!inet_aton(lua_tostring(L, -1), &val.imr_multiaddr)) + luaL_argerror(L, 3, "invalid 'multiaddr' ip address"); + lua_pushstring(L, "interface"); + lua_gettable(L, 3); + if (!lua_isstring(L, -1)) + luaL_argerror(L, 3, "string 'interface' field expected"); + val.imr_interface.s_addr = htonl(INADDR_ANY); + if (strcmp(lua_tostring(L, -1), "*") && + !inet_aton(lua_tostring(L, -1), &val.imr_interface)) + luaL_argerror(L, 3, "invalid 'interface' ip address"); + return opt_set(L, ps, level, name, (char*)&val, sizeof(val)); } -static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name) +static int opt_ip6_setmembership(lua_State* L, p_socket ps, int level, int name) { - struct ipv6_mreq val; /* obj, opt-name, table */ - memset(&val, 0, sizeof(val)); - if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE)); - lua_pushstring(L, "multiaddr"); - lua_gettable(L, 3); - if (!lua_isstring(L, -1)) - luaL_argerror(L, 3, "string 'multiaddr' field expected"); - if (!inet_pton(AF_INET6, lua_tostring(L, -1), &val.ipv6mr_multiaddr)) - luaL_argerror(L, 3, "invalid 'multiaddr' ip address"); - lua_pushstring(L, "interface"); - lua_gettable(L, 3); - /* By default we listen to interface on default route - * (sigh). However, interface= can override it. We should - * support either number, or name for it. Waiting for - * windows port of if_nametoindex */ - if (!lua_isnil(L, -1)) { - if (lua_isnumber(L, -1)) { - val.ipv6mr_interface = (unsigned int) lua_tonumber(L, -1); - } else - luaL_argerror(L, -1, "number 'interface' field expected"); - } - return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); + struct ipv6_mreq val; /* obj, opt-name, table */ + memset(&val, 0, sizeof(val)); + if (!lua_istable(L, 3)) auxiliar_typeerror(L, 3, lua_typename(L, LUA_TTABLE)); + lua_pushstring(L, "multiaddr"); + lua_gettable(L, 3); + if (!lua_isstring(L, -1)) + luaL_argerror(L, 3, "string 'multiaddr' field expected"); + if (!inet_pton(AF_INET6, lua_tostring(L, -1), &val.ipv6mr_multiaddr)) + luaL_argerror(L, 3, "invalid 'multiaddr' ip address"); + lua_pushstring(L, "interface"); + lua_gettable(L, 3); + /* By default we listen to interface on default route + * (sigh). However, interface= can override it. We should + * support either number, or name for it. Waiting for + * windows port of if_nametoindex */ + if (!lua_isnil(L, -1)) + { + if (lua_isnumber(L, -1)) + { + val.ipv6mr_interface = (unsigned int)lua_tonumber(L, -1); + } + else + luaL_argerror(L, -1, "number 'interface' field expected"); + } + return opt_set(L, ps, level, name, (char*)&val, sizeof(val)); } static -int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len) +int opt_get(lua_State* L, p_socket ps, int level, int name, void* val, int* len) { - socklen_t socklen = *len; - if (getsockopt(*ps, level, name, (char *) val, &socklen) < 0) { - lua_pushnil(L); - lua_pushstring(L, "getsockopt failed"); - return 2; - } - *len = socklen; - return 0; + socklen_t socklen = *len; + if (getsockopt(*ps, level, name, (char*)val, &socklen) < 0) + { + lua_pushnil(L); + lua_pushstring(L, "getsockopt failed"); + return 2; + } + *len = socklen; + return 0; } static -int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len) +int opt_set(lua_State* L, p_socket ps, int level, int name, void* val, int len) { - if (setsockopt(*ps, level, name, (char *) val, len) < 0) { - lua_pushnil(L); - lua_pushstring(L, "setsockopt failed"); - return 2; - } - lua_pushnumber(L, 1); - return 1; + if (setsockopt(*ps, level, name, (char*)val, len) < 0) + { + lua_pushnil(L); + lua_pushstring(L, "setsockopt failed"); + return 2; + } + lua_pushnumber(L, 1); + return 1; } -static int opt_getboolean(lua_State *L, p_socket ps, int level, int name) +static int opt_getboolean(lua_State* L, p_socket ps, int level, int name) { - int val = 0; - int len = sizeof(val); - int err = opt_get(L, ps, level, name, (char *) &val, &len); - if (err) - return err; - lua_pushboolean(L, val); - return 1; + int val = 0; + int len = sizeof(val); + int err = opt_get(L, ps, level, name, (char*)&val, &len); + if (err) + return err; + lua_pushboolean(L, val); + return 1; } -int opt_get_error(lua_State *L, p_socket ps) +int opt_get_error(lua_State* L, p_socket ps) { - int val = 0; - socklen_t len = sizeof(val); - if (getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *) &val, &len) < 0) { - lua_pushnil(L); - lua_pushstring(L, "getsockopt failed"); - return 2; - } - lua_pushstring(L, socket_strerror(val)); - return 1; + int val = 0; + socklen_t len = sizeof(val); + if (getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char*)&val, &len) < 0) + { + lua_pushnil(L); + lua_pushstring(L, "getsockopt failed"); + return 2; + } + lua_pushstring(L, socket_strerror(val)); + return 1; } -static int opt_setboolean(lua_State *L, p_socket ps, int level, int name) +static int opt_setboolean(lua_State* L, p_socket ps, int level, int name) { - int val = auxiliar_checkboolean(L, 3); /* obj, name, bool */ - return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); + int val = auxiliar_checkboolean(L, 3); /* obj, name, bool */ + return opt_set(L, ps, level, name, (char*)&val, sizeof(val)); } -static int opt_getint(lua_State *L, p_socket ps, int level, int name) +static int opt_getint(lua_State* L, p_socket ps, int level, int name) { - int val = 0; - int len = sizeof(val); - int err = opt_get(L, ps, level, name, (char *) &val, &len); - if (err) - return err; - lua_pushnumber(L, val); - return 1; + int val = 0; + int len = sizeof(val); + int err = opt_get(L, ps, level, name, (char*)&val, &len); + if (err) + return err; + lua_pushnumber(L, val); + return 1; } -static int opt_setint(lua_State *L, p_socket ps, int level, int name) +static int opt_setint(lua_State* L, p_socket ps, int level, int name) { - int val = (int) lua_tonumber(L, 3); /* obj, name, int */ - return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); + int val = (int)lua_tonumber(L, 3); /* obj, name, int */ + return opt_set(L, ps, level, name, (char*)&val, sizeof(val)); } diff --git a/Lua/options.h b/Lua/options.h index 19ba0df..7c30f4e 100644 --- a/Lua/options.h +++ b/Lua/options.h @@ -12,51 +12,53 @@ #include "socket.h" /* option registry */ -typedef struct t_opt { - const char *name; - int (*func)(lua_State *L, p_socket ps); +typedef struct t_opt +{ + const char* name; + int (*func)(lua_State* L, p_socket ps); } t_opt; -typedef t_opt *p_opt; + +typedef t_opt* p_opt; /* supported options for setoption */ -int opt_set_dontroute(lua_State *L, p_socket ps); -int opt_set_broadcast(lua_State *L, p_socket ps); -int opt_set_tcp_nodelay(lua_State *L, p_socket ps); -int opt_set_keepalive(lua_State *L, p_socket ps); -int opt_set_linger(lua_State *L, p_socket ps); -int opt_set_reuseaddr(lua_State *L, p_socket ps); -int opt_set_reuseport(lua_State *L, p_socket ps); -int opt_set_ip_multicast_if(lua_State *L, p_socket ps); -int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps); -int opt_set_ip_multicast_loop(lua_State *L, p_socket ps); -int opt_set_ip_add_membership(lua_State *L, p_socket ps); -int opt_set_ip_drop_membersip(lua_State *L, p_socket ps); -int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps); -int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps); -int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps); -int opt_set_ip6_add_membership(lua_State *L, p_socket ps); -int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps); -int opt_set_ip6_v6only(lua_State *L, p_socket ps); +int opt_set_dontroute(lua_State* L, p_socket ps); +int opt_set_broadcast(lua_State* L, p_socket ps); +int opt_set_tcp_nodelay(lua_State* L, p_socket ps); +int opt_set_keepalive(lua_State* L, p_socket ps); +int opt_set_linger(lua_State* L, p_socket ps); +int opt_set_reuseaddr(lua_State* L, p_socket ps); +int opt_set_reuseport(lua_State* L, p_socket ps); +int opt_set_ip_multicast_if(lua_State* L, p_socket ps); +int opt_set_ip_multicast_ttl(lua_State* L, p_socket ps); +int opt_set_ip_multicast_loop(lua_State* L, p_socket ps); +int opt_set_ip_add_membership(lua_State* L, p_socket ps); +int opt_set_ip_drop_membersip(lua_State* L, p_socket ps); +int opt_set_ip6_unicast_hops(lua_State* L, p_socket ps); +int opt_set_ip6_multicast_hops(lua_State* L, p_socket ps); +int opt_set_ip6_multicast_loop(lua_State* L, p_socket ps); +int opt_set_ip6_add_membership(lua_State* L, p_socket ps); +int opt_set_ip6_drop_membersip(lua_State* L, p_socket ps); +int opt_set_ip6_v6only(lua_State* L, p_socket ps); /* supported options for getoption */ -int opt_get_dontroute(lua_State *L, p_socket ps); -int opt_get_broadcast(lua_State *L, p_socket ps); -int opt_get_reuseaddr(lua_State *L, p_socket ps); -int opt_get_reuseport(lua_State *L, p_socket ps); -int opt_get_tcp_nodelay(lua_State *L, p_socket ps); -int opt_get_keepalive(lua_State *L, p_socket ps); -int opt_get_linger(lua_State *L, p_socket ps); -int opt_get_ip_multicast_loop(lua_State *L, p_socket ps); -int opt_get_ip_multicast_if(lua_State *L, p_socket ps); -int opt_get_error(lua_State *L, p_socket ps); -int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps); -int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps); -int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps); -int opt_get_ip6_v6only(lua_State *L, p_socket ps); -int opt_get_reuseport(lua_State *L, p_socket ps); +int opt_get_dontroute(lua_State* L, p_socket ps); +int opt_get_broadcast(lua_State* L, p_socket ps); +int opt_get_reuseaddr(lua_State* L, p_socket ps); +int opt_get_reuseport(lua_State* L, p_socket ps); +int opt_get_tcp_nodelay(lua_State* L, p_socket ps); +int opt_get_keepalive(lua_State* L, p_socket ps); +int opt_get_linger(lua_State* L, p_socket ps); +int opt_get_ip_multicast_loop(lua_State* L, p_socket ps); +int opt_get_ip_multicast_if(lua_State* L, p_socket ps); +int opt_get_error(lua_State* L, p_socket ps); +int opt_get_ip6_multicast_loop(lua_State* L, p_socket ps); +int opt_get_ip6_multicast_hops(lua_State* L, p_socket ps); +int opt_get_ip6_unicast_hops(lua_State* L, p_socket ps); +int opt_get_ip6_v6only(lua_State* L, p_socket ps); +int opt_get_reuseport(lua_State* L, p_socket ps); /* invokes the appropriate option handler */ -int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps); -int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps); +int opt_meth_setoption(lua_State* L, p_opt opt, p_socket ps); +int opt_meth_getoption(lua_State* L, p_opt opt, p_socket ps); #endif diff --git a/Lua/select.c b/Lua/select.c index 9d133b7..4bc8c47 100644 --- a/Lua/select.c +++ b/Lua/select.c @@ -15,20 +15,20 @@ /*=========================================================================*\ * Internal function prototypes. \*=========================================================================*/ -static t_socket getfd(lua_State *L); -static int dirty(lua_State *L); -static void collect_fd(lua_State *L, int tab, int itab, - fd_set *set, t_socket *max_fd); -static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set); -static void return_fd(lua_State *L, fd_set *set, t_socket max_fd, - int itab, int tab, int start); -static void make_assoc(lua_State *L, int tab); -static int global_select(lua_State *L); +static t_socket getfd(lua_State* L); +static int dirty(lua_State* L); +static void collect_fd(lua_State* L, int tab, int itab, + fd_set* set, t_socket* max_fd); +static int check_dirty(lua_State* L, int tab, int dtab, fd_set* set); +static void return_fd(lua_State* L, fd_set* set, t_socket max_fd, + int itab, int tab, int start); +static void make_assoc(lua_State* L, int tab); +static int global_select(lua_State* L); /* functions in library namespace */ static luaL_Reg func[] = { - {"select", global_select}, - {NULL, NULL} + {"select", global_select}, + {NULL, NULL} }; /*=========================================================================*\ @@ -37,15 +37,16 @@ static luaL_Reg func[] = { /*-------------------------------------------------------------------------*\ * Initializes module \*-------------------------------------------------------------------------*/ -int select_open(lua_State *L) { - lua_pushstring(L, "_SETSIZE"); - lua_pushinteger(L, FD_SETSIZE); - lua_rawset(L, -3); - lua_pushstring(L, "_SOCKETINVALID"); - lua_pushinteger(L, SOCKET_INVALID); - lua_rawset(L, -3); - luaL_setfuncs(L, func, 0); - return 0; +int select_open(lua_State* L) +{ + lua_pushstring(L, "_SETSIZE"); + lua_pushinteger(L, FD_SETSIZE); + lua_rawset(L, -3); + lua_pushstring(L, "_SOCKETINVALID"); + lua_pushinteger(L, SOCKET_INVALID); + lua_rawset(L, -3); + luaL_setfuncs(L, func, 0); + return 0; } /*=========================================================================*\ @@ -54,167 +55,198 @@ int select_open(lua_State *L) { /*-------------------------------------------------------------------------*\ * Waits for a set of sockets until a condition is met or timeout. \*-------------------------------------------------------------------------*/ -static int global_select(lua_State *L) { - int rtab, wtab, itab, ret, ndirty; - t_socket max_fd = SOCKET_INVALID; - fd_set rset, wset; - t_timeout tm; - double t = luaL_optnumber(L, 3, -1); - FD_ZERO(&rset); FD_ZERO(&wset); - lua_settop(L, 3); - lua_newtable(L); itab = lua_gettop(L); - lua_newtable(L); rtab = lua_gettop(L); - lua_newtable(L); wtab = lua_gettop(L); - collect_fd(L, 1, itab, &rset, &max_fd); - collect_fd(L, 2, itab, &wset, &max_fd); - ndirty = check_dirty(L, 1, rtab, &rset); - t = ndirty > 0? 0.0: t; - timeout_init(&tm, t, -1); - timeout_markstart(&tm); - ret = socket_select(max_fd+1, &rset, &wset, NULL, &tm); - if (ret > 0 || ndirty > 0) { - return_fd(L, &rset, max_fd+1, itab, rtab, ndirty); - return_fd(L, &wset, max_fd+1, itab, wtab, 0); - make_assoc(L, rtab); - make_assoc(L, wtab); - return 2; - } else if (ret == 0) { - lua_pushstring(L, "timeout"); - return 3; - } else { - luaL_error(L, "select failed"); - return 3; - } +static int global_select(lua_State* L) +{ + int rtab, wtab, itab, ret, ndirty; + t_socket max_fd = SOCKET_INVALID; + fd_set rset, wset; + t_timeout tm; + double t = luaL_optnumber(L, 3, -1); + FD_ZERO(&rset); + FD_ZERO(&wset); + lua_settop(L, 3); + lua_newtable(L); + itab = lua_gettop(L); + lua_newtable(L); + rtab = lua_gettop(L); + lua_newtable(L); + wtab = lua_gettop(L); + collect_fd(L, 1, itab, &rset, &max_fd); + collect_fd(L, 2, itab, &wset, &max_fd); + ndirty = check_dirty(L, 1, rtab, &rset); + t = ndirty > 0 ? 0.0 : t; + timeout_init(&tm, t, -1); + timeout_markstart(&tm); + ret = socket_select(max_fd + 1, &rset, &wset, NULL, &tm); + if (ret > 0 || ndirty > 0) + { + return_fd(L, &rset, max_fd + 1, itab, rtab, ndirty); + return_fd(L, &wset, max_fd + 1, itab, wtab, 0); + make_assoc(L, rtab); + make_assoc(L, wtab); + return 2; + } + else if (ret == 0) + { + lua_pushstring(L, "timeout"); + return 3; + } + else + { + luaL_error(L, "select failed"); + return 3; + } } /*=========================================================================*\ * Internal functions \*=========================================================================*/ -static t_socket getfd(lua_State *L) { - t_socket fd = SOCKET_INVALID; - lua_pushstring(L, "getfd"); - lua_gettable(L, -2); - if (!lua_isnil(L, -1)) { - lua_pushvalue(L, -2); - lua_call(L, 1, 1); - if (lua_isnumber(L, -1)) { - double numfd = lua_tonumber(L, -1); - fd = (numfd >= 0.0)? (t_socket) numfd: SOCKET_INVALID; - } - } - lua_pop(L, 1); - return fd; +static t_socket getfd(lua_State* L) +{ + t_socket fd = SOCKET_INVALID; + lua_pushstring(L, "getfd"); + lua_gettable(L, -2); + if (!lua_isnil(L, -1)) + { + lua_pushvalue(L, -2); + lua_call(L, 1, 1); + if (lua_isnumber(L, -1)) + { + double numfd = lua_tonumber(L, -1); + fd = (numfd >= 0.0) ? (t_socket)numfd : SOCKET_INVALID; + } + } + lua_pop(L, 1); + return fd; } -static int dirty(lua_State *L) { - int is = 0; - lua_pushstring(L, "dirty"); - lua_gettable(L, -2); - if (!lua_isnil(L, -1)) { - lua_pushvalue(L, -2); - lua_call(L, 1, 1); - is = lua_toboolean(L, -1); - } - lua_pop(L, 1); - return is; +static int dirty(lua_State* L) +{ + int is = 0; + lua_pushstring(L, "dirty"); + lua_gettable(L, -2); + if (!lua_isnil(L, -1)) + { + lua_pushvalue(L, -2); + lua_call(L, 1, 1); + is = lua_toboolean(L, -1); + } + lua_pop(L, 1); + return is; } -static void collect_fd(lua_State *L, int tab, int itab, - fd_set *set, t_socket *max_fd) { - int i = 1, n = 0; - /* nil is the same as an empty table */ - if (lua_isnil(L, tab)) return; - /* otherwise we need it to be a table */ - luaL_checktype(L, tab, LUA_TTABLE); - for ( ;; ) { - t_socket fd; - lua_pushnumber(L, i); - lua_gettable(L, tab); - if (lua_isnil(L, -1)) { - lua_pop(L, 1); - break; - } - /* getfd figures out if this is a socket */ - fd = getfd(L); - if (fd != SOCKET_INVALID) { - /* make sure we don't overflow the fd_set */ +static void collect_fd(lua_State* L, int tab, int itab, + fd_set* set, t_socket* max_fd) +{ + int i = 1, n = 0; + /* nil is the same as an empty table */ + if (lua_isnil(L, tab)) return; + /* otherwise we need it to be a table */ + luaL_checktype(L, tab, LUA_TTABLE); + for (;;) + { + t_socket fd; + lua_pushnumber(L, i); + lua_gettable(L, tab); + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + break; + } + /* getfd figures out if this is a socket */ + fd = getfd(L); + if (fd != SOCKET_INVALID) + { + /* make sure we don't overflow the fd_set */ #ifdef _WIN32 - if (n >= FD_SETSIZE) - luaL_argerror(L, tab, "too many sockets"); + if (n >= FD_SETSIZE) + luaL_argerror(L, tab, "too many sockets"); #else if (fd >= FD_SETSIZE) luaL_argerror(L, tab, "descriptor too large for set size"); #endif - FD_SET(fd, set); - n++; - /* keep track of the largest descriptor so far */ - if (*max_fd == SOCKET_INVALID || *max_fd < fd) - *max_fd = fd; - /* make sure we can map back from descriptor to the object */ - lua_pushnumber(L, (lua_Number) fd); - lua_pushvalue(L, -2); - lua_settable(L, itab); - } - lua_pop(L, 1); - i = i + 1; - } + FD_SET(fd, set); + n++; + /* keep track of the largest descriptor so far */ + if (*max_fd == SOCKET_INVALID || *max_fd < fd) + *max_fd = fd; + /* make sure we can map back from descriptor to the object */ + lua_pushnumber(L, (lua_Number)fd); + lua_pushvalue(L, -2); + lua_settable(L, itab); + } + lua_pop(L, 1); + i = i + 1; + } } -static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set) { - int ndirty = 0, i = 1; - if (lua_isnil(L, tab)) - return 0; - for ( ;; ) { - t_socket fd; - lua_pushnumber(L, i); - lua_gettable(L, tab); - if (lua_isnil(L, -1)) { - lua_pop(L, 1); - break; - } - fd = getfd(L); - if (fd != SOCKET_INVALID && dirty(L)) { - lua_pushnumber(L, ++ndirty); - lua_pushvalue(L, -2); - lua_settable(L, dtab); - FD_CLR(fd, set); - } - lua_pop(L, 1); - i = i + 1; - } - return ndirty; +static int check_dirty(lua_State* L, int tab, int dtab, fd_set* set) +{ + int ndirty = 0, i = 1; + if (lua_isnil(L, tab)) + return 0; + for (;;) + { + t_socket fd; + lua_pushnumber(L, i); + lua_gettable(L, tab); + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + break; + } + fd = getfd(L); + if (fd != SOCKET_INVALID && dirty(L)) + { + lua_pushnumber(L, ++ndirty); + lua_pushvalue(L, -2); + lua_settable(L, dtab); + FD_CLR(fd, set); + } + lua_pop(L, 1); + i = i + 1; + } + return ndirty; } -static void return_fd(lua_State *L, fd_set *set, t_socket max_fd, - int itab, int tab, int start) { - t_socket fd; - for (fd = 0; fd < max_fd; fd++) { - if (FD_ISSET(fd, set)) { - lua_pushnumber(L, ++start); - lua_pushnumber(L, (lua_Number) fd); - lua_gettable(L, itab); - lua_settable(L, tab); - } - } +static void return_fd(lua_State* L, fd_set* set, t_socket max_fd, + int itab, int tab, int start) +{ + t_socket fd; + for (fd = 0; fd < max_fd; fd++) + { + if (FD_ISSET(fd, set)) + { + lua_pushnumber(L, ++start); + lua_pushnumber(L, (lua_Number)fd); + lua_gettable(L, itab); + lua_settable(L, tab); + } + } } -static void make_assoc(lua_State *L, int tab) { - int i = 1, atab; - lua_newtable(L); atab = lua_gettop(L); - for ( ;; ) { - lua_pushnumber(L, i); - lua_gettable(L, tab); - if (!lua_isnil(L, -1)) { - lua_pushnumber(L, i); - lua_pushvalue(L, -2); - lua_settable(L, atab); - lua_pushnumber(L, i); - lua_settable(L, atab); - } else { - lua_pop(L, 1); - break; - } - i = i+1; - } +static void make_assoc(lua_State* L, int tab) +{ + int i = 1, atab; + lua_newtable(L); + atab = lua_gettop(L); + for (;;) + { + lua_pushnumber(L, i); + lua_gettable(L, tab); + if (!lua_isnil(L, -1)) + { + lua_pushnumber(L, i); + lua_pushvalue(L, -2); + lua_settable(L, atab); + lua_pushnumber(L, i); + lua_settable(L, atab); + } + else + { + lua_pop(L, 1); + break; + } + i = i + 1; + } } - diff --git a/Lua/select.h b/Lua/select.h index 8750200..0ff43b9 100644 --- a/Lua/select.h +++ b/Lua/select.h @@ -10,6 +10,6 @@ * true if there is data ready for reading (required for buffered input). \*=========================================================================*/ -int select_open(lua_State *L); +int select_open(lua_State* L); #endif /* SELECT_H */ diff --git a/Lua/socket.h b/Lua/socket.h index 63573de..c3ffe22 100644 --- a/Lua/socket.h +++ b/Lua/socket.h @@ -38,41 +38,41 @@ typedef struct sockaddr SA; int socket_open(void); int socket_close(void); void socket_destroy(p_socket ps); -void socket_shutdown(p_socket ps, int how); -int socket_sendto(p_socket ps, const char *data, size_t count, - size_t *sent, SA *addr, socklen_t addr_len, p_timeout tm); -int socket_recvfrom(p_socket ps, char *data, size_t count, - size_t *got, SA *addr, socklen_t *addr_len, p_timeout tm); +void socket_shutdown(p_socket ps, int how); +int socket_sendto(p_socket ps, const char* data, size_t count, + size_t* sent, SA* addr, socklen_t addr_len, p_timeout tm); +int socket_recvfrom(p_socket ps, char* data, size_t count, + size_t* got, SA* addr, socklen_t* addr_len, p_timeout tm); void socket_setnonblocking(p_socket ps); void socket_setblocking(p_socket ps); int socket_waitfd(p_socket ps, int sw, p_timeout tm); -int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, - p_timeout tm); +int socket_select(t_socket n, fd_set* rfds, fd_set* wfds, fd_set* efds, + p_timeout tm); -int socket_connect(p_socket ps, SA *addr, socklen_t addr_len, p_timeout tm); +int socket_connect(p_socket ps, SA* addr, socklen_t addr_len, p_timeout tm); int socket_create(p_socket ps, int domain, int type, int protocol); -int socket_bind(p_socket ps, SA *addr, socklen_t addr_len); +int socket_bind(p_socket ps, SA* addr, socklen_t addr_len); int socket_listen(p_socket ps, int backlog); -int socket_accept(p_socket ps, p_socket pa, SA *addr, - socklen_t *addr_len, p_timeout tm); +int socket_accept(p_socket ps, p_socket pa, SA* addr, + socklen_t* addr_len, p_timeout tm); -const char *socket_hoststrerror(int err); -const char *socket_gaistrerror(int err); -const char *socket_strerror(int err); +const char* socket_hoststrerror(int err); +const char* socket_gaistrerror(int err); +const char* socket_strerror(int err); /* these are perfect to use with the io abstraction module and the buffered input module */ -int socket_send(p_socket ps, const char *data, size_t count, - size_t *sent, p_timeout tm); -int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); -int socket_write(p_socket ps, const char *data, size_t count, - size_t *sent, p_timeout tm); -int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); -const char *socket_ioerror(p_socket ps, int err); +int socket_send(p_socket ps, const char* data, size_t count, + size_t* sent, p_timeout tm); +int socket_recv(p_socket ps, char* data, size_t count, size_t* got, p_timeout tm); +int socket_write(p_socket ps, const char* data, size_t count, + size_t* sent, p_timeout tm); +int socket_read(p_socket ps, char* data, size_t count, size_t* got, p_timeout tm); +const char* socket_ioerror(p_socket ps, int err); -int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp); -int socket_gethostbyname(const char *addr, struct hostent **hp); +int socket_gethostbyaddr(const char* addr, socklen_t len, struct hostent** hp); +int socket_gethostbyname(const char* addr, struct hostent** hp); #endif /* SOCKET_H */ diff --git a/Lua/tcp.c b/Lua/tcp.c index ef9ee6f..f8d4f74 100644 --- a/Lua/tcp.c +++ b/Lua/tcp.c @@ -17,106 +17,106 @@ /*=========================================================================*\ * Internal function prototypes \*=========================================================================*/ -static int global_create(lua_State *L); -static int global_create4(lua_State *L); -static int global_create6(lua_State *L); -static int global_connect(lua_State *L); -static int meth_connect(lua_State *L); -static int meth_listen(lua_State *L); -static int meth_getfamily(lua_State *L); -static int meth_bind(lua_State *L); -static int meth_send(lua_State *L); -static int meth_getstats(lua_State *L); -static int meth_setstats(lua_State *L); -static int meth_getsockname(lua_State *L); -static int meth_getpeername(lua_State *L); -static int meth_shutdown(lua_State *L); -static int meth_receive(lua_State *L); -static int meth_accept(lua_State *L); -static int meth_close(lua_State *L); -static int meth_getoption(lua_State *L); -static int meth_setoption(lua_State *L); -static int meth_gettimeout(lua_State *L); -static int meth_settimeout(lua_State *L); -static int meth_getfd(lua_State *L); -static int meth_setfd(lua_State *L); -static int meth_dirty(lua_State *L); +static int global_create(lua_State* L); +static int global_create4(lua_State* L); +static int global_create6(lua_State* L); +static int global_connect(lua_State* L); +static int meth_connect(lua_State* L); +static int meth_listen(lua_State* L); +static int meth_getfamily(lua_State* L); +static int meth_bind(lua_State* L); +static int meth_send(lua_State* L); +static int meth_getstats(lua_State* L); +static int meth_setstats(lua_State* L); +static int meth_getsockname(lua_State* L); +static int meth_getpeername(lua_State* L); +static int meth_shutdown(lua_State* L); +static int meth_receive(lua_State* L); +static int meth_accept(lua_State* L); +static int meth_close(lua_State* L); +static int meth_getoption(lua_State* L); +static int meth_setoption(lua_State* L); +static int meth_gettimeout(lua_State* L); +static int meth_settimeout(lua_State* L); +static int meth_getfd(lua_State* L); +static int meth_setfd(lua_State* L); +static int meth_dirty(lua_State* L); /* tcp object methods */ static luaL_Reg tcp_methods[] = { - {"__gc", meth_close}, - {"__tostring", auxiliar_tostring}, - {"accept", meth_accept}, - {"bind", meth_bind}, - {"close", meth_close}, - {"connect", meth_connect}, - {"dirty", meth_dirty}, - {"getfamily", meth_getfamily}, - {"getfd", meth_getfd}, - {"getoption", meth_getoption}, - {"getpeername", meth_getpeername}, - {"getsockname", meth_getsockname}, - {"getstats", meth_getstats}, - {"setstats", meth_setstats}, - {"listen", meth_listen}, - {"receive", meth_receive}, - {"send", meth_send}, - {"setfd", meth_setfd}, - {"setoption", meth_setoption}, - {"setpeername", meth_connect}, - {"setsockname", meth_bind}, - {"settimeout", meth_settimeout}, - {"gettimeout", meth_gettimeout}, - {"shutdown", meth_shutdown}, - {NULL, NULL} + {"__gc", meth_close}, + {"__tostring", auxiliar_tostring}, + {"accept", meth_accept}, + {"bind", meth_bind}, + {"close", meth_close}, + {"connect", meth_connect}, + {"dirty", meth_dirty}, + {"getfamily", meth_getfamily}, + {"getfd", meth_getfd}, + {"getoption", meth_getoption}, + {"getpeername", meth_getpeername}, + {"getsockname", meth_getsockname}, + {"getstats", meth_getstats}, + {"setstats", meth_setstats}, + {"listen", meth_listen}, + {"receive", meth_receive}, + {"send", meth_send}, + {"setfd", meth_setfd}, + {"setoption", meth_setoption}, + {"setpeername", meth_connect}, + {"setsockname", meth_bind}, + {"settimeout", meth_settimeout}, + {"gettimeout", meth_gettimeout}, + {"shutdown", meth_shutdown}, + {NULL, NULL} }; /* socket option handlers */ static t_opt optget[] = { - {"keepalive", opt_get_keepalive}, - {"reuseaddr", opt_get_reuseaddr}, - {"reuseport", opt_get_reuseport}, - {"tcp-nodelay", opt_get_tcp_nodelay}, - {"linger", opt_get_linger}, - {"error", opt_get_error}, - {NULL, NULL} + {"keepalive", opt_get_keepalive}, + {"reuseaddr", opt_get_reuseaddr}, + {"reuseport", opt_get_reuseport}, + {"tcp-nodelay", opt_get_tcp_nodelay}, + {"linger", opt_get_linger}, + {"error", opt_get_error}, + {NULL, NULL} }; static t_opt optset[] = { - {"keepalive", opt_set_keepalive}, - {"reuseaddr", opt_set_reuseaddr}, - {"reuseport", opt_set_reuseport}, - {"tcp-nodelay", opt_set_tcp_nodelay}, - {"ipv6-v6only", opt_set_ip6_v6only}, - {"linger", opt_set_linger}, - {NULL, NULL} + {"keepalive", opt_set_keepalive}, + {"reuseaddr", opt_set_reuseaddr}, + {"reuseport", opt_set_reuseport}, + {"tcp-nodelay", opt_set_tcp_nodelay}, + {"ipv6-v6only", opt_set_ip6_v6only}, + {"linger", opt_set_linger}, + {NULL, NULL} }; /* functions in library namespace */ static luaL_Reg func[] = { - {"tcp", global_create}, - {"tcp4", global_create4}, - {"tcp6", global_create6}, - {"connect", global_connect}, - {NULL, NULL} + {"tcp", global_create}, + {"tcp4", global_create4}, + {"tcp6", global_create6}, + {"connect", global_connect}, + {NULL, NULL} }; /*-------------------------------------------------------------------------*\ * Initializes module \*-------------------------------------------------------------------------*/ -int tcp_open(lua_State *L) +int tcp_open(lua_State* L) { - /* create classes */ - auxiliar_newclass(L, "tcp{master}", tcp_methods); - auxiliar_newclass(L, "tcp{client}", tcp_methods); - auxiliar_newclass(L, "tcp{server}", tcp_methods); - /* create class groups */ - auxiliar_add2group(L, "tcp{master}", "tcp{any}"); - auxiliar_add2group(L, "tcp{client}", "tcp{any}"); - auxiliar_add2group(L, "tcp{server}", "tcp{any}"); - /* define library functions */ - luaL_setfuncs(L, func, 0); - return 0; + /* create classes */ + auxiliar_newclass(L, "tcp{master}", tcp_methods); + auxiliar_newclass(L, "tcp{client}", tcp_methods); + auxiliar_newclass(L, "tcp{server}", tcp_methods); + /* create class groups */ + auxiliar_add2group(L, "tcp{master}", "tcp{any}"); + auxiliar_add2group(L, "tcp{client}", "tcp{any}"); + auxiliar_add2group(L, "tcp{server}", "tcp{any}"); + /* define library functions */ + luaL_setfuncs(L, func, 0); + return 0; } /*=========================================================================*\ @@ -125,237 +125,254 @@ int tcp_open(lua_State *L) /*-------------------------------------------------------------------------*\ * Just call buffered IO methods \*-------------------------------------------------------------------------*/ -static int meth_send(lua_State *L) { - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); - return buffer_meth_send(L, &tcp->buf); +static int meth_send(lua_State* L) +{ + p_tcp tcp = (p_tcp)auxiliar_checkclass(L, "tcp{client}", 1); + return buffer_meth_send(L, &tcp->buf); } -static int meth_receive(lua_State *L) { - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); - return buffer_meth_receive(L, &tcp->buf); +static int meth_receive(lua_State* L) +{ + p_tcp tcp = (p_tcp)auxiliar_checkclass(L, "tcp{client}", 1); + return buffer_meth_receive(L, &tcp->buf); } -static int meth_getstats(lua_State *L) { - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); - return buffer_meth_getstats(L, &tcp->buf); +static int meth_getstats(lua_State* L) +{ + p_tcp tcp = (p_tcp)auxiliar_checkclass(L, "tcp{client}", 1); + return buffer_meth_getstats(L, &tcp->buf); } -static int meth_setstats(lua_State *L) { - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); - return buffer_meth_setstats(L, &tcp->buf); +static int meth_setstats(lua_State* L) +{ + p_tcp tcp = (p_tcp)auxiliar_checkclass(L, "tcp{client}", 1); + return buffer_meth_setstats(L, &tcp->buf); } /*-------------------------------------------------------------------------*\ * Just call option handler \*-------------------------------------------------------------------------*/ -static int meth_getoption(lua_State *L) +static int meth_getoption(lua_State* L) { - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - return opt_meth_getoption(L, optget, &tcp->sock); + p_tcp tcp = (p_tcp)auxiliar_checkgroup(L, "tcp{any}", 1); + return opt_meth_getoption(L, optget, &tcp->sock); } -static int meth_setoption(lua_State *L) +static int meth_setoption(lua_State* L) { - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - return opt_meth_setoption(L, optset, &tcp->sock); + p_tcp tcp = (p_tcp)auxiliar_checkgroup(L, "tcp{any}", 1); + return opt_meth_setoption(L, optset, &tcp->sock); } /*-------------------------------------------------------------------------*\ * Select support methods \*-------------------------------------------------------------------------*/ -static int meth_getfd(lua_State *L) +static int meth_getfd(lua_State* L) { - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - lua_pushnumber(L, (int) tcp->sock); - return 1; + p_tcp tcp = (p_tcp)auxiliar_checkgroup(L, "tcp{any}", 1); + lua_pushnumber(L, (int)tcp->sock); + return 1; } /* this is very dangerous, but can be handy for those that are brave enough */ -static int meth_setfd(lua_State *L) +static int meth_setfd(lua_State* L) { - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - tcp->sock = (t_socket) luaL_checknumber(L, 2); - return 0; + p_tcp tcp = (p_tcp)auxiliar_checkgroup(L, "tcp{any}", 1); + tcp->sock = (t_socket)luaL_checknumber(L, 2); + return 0; } -static int meth_dirty(lua_State *L) +static int meth_dirty(lua_State* L) { - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - lua_pushboolean(L, !buffer_isempty(&tcp->buf)); - return 1; + p_tcp tcp = (p_tcp)auxiliar_checkgroup(L, "tcp{any}", 1); + lua_pushboolean(L, !buffer_isempty(&tcp->buf)); + return 1; } /*-------------------------------------------------------------------------*\ * Waits for and returns a client object attempting connection to the * server object \*-------------------------------------------------------------------------*/ -static int meth_accept(lua_State *L) +static int meth_accept(lua_State* L) { - p_tcp server = (p_tcp) auxiliar_checkclass(L, "tcp{server}", 1); - p_timeout tm = timeout_markstart(&server->tm); - t_socket sock; - const char *err = inet_tryaccept(&server->sock, server->family, &sock, tm); - /* if successful, push client socket */ - if (err == NULL) { - p_tcp clnt = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); - auxiliar_setclass(L, "tcp{client}", -1); - /* initialize structure fields */ - memset(clnt, 0, sizeof(t_tcp)); - socket_setnonblocking(&sock); - clnt->sock = sock; - io_init(&clnt->io, (p_send) socket_send, (p_recv) socket_recv, - (p_error) socket_ioerror, &clnt->sock); - timeout_init(&clnt->tm, -1, -1); - buffer_init(&clnt->buf, &clnt->io, &clnt->tm); - clnt->family = server->family; - return 1; - } else { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } + p_tcp server = (p_tcp)auxiliar_checkclass(L, "tcp{server}", 1); + p_timeout tm = timeout_markstart(&server->tm); + t_socket sock; + const char* err = inet_tryaccept(&server->sock, server->family, &sock, tm); + /* if successful, push client socket */ + if (err == NULL) + { + p_tcp clnt = (p_tcp)lua_newuserdata(L, sizeof(t_tcp)); + auxiliar_setclass(L, "tcp{client}", -1); + /* initialize structure fields */ + memset(clnt, 0, sizeof(t_tcp)); + socket_setnonblocking(&sock); + clnt->sock = sock; + io_init(&clnt->io, (p_send)socket_send, (p_recv)socket_recv, + (p_error)socket_ioerror, &clnt->sock); + timeout_init(&clnt->tm, -1, -1); + buffer_init(&clnt->buf, &clnt->io, &clnt->tm); + clnt->family = server->family; + return 1; + } + else + { + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } } /*-------------------------------------------------------------------------*\ * Binds an object to an address \*-------------------------------------------------------------------------*/ -static int meth_bind(lua_State *L) { - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1); - const char *address = luaL_checkstring(L, 2); - const char *port = luaL_checkstring(L, 3); - const char *err; - struct addrinfo bindhints; - memset(&bindhints, 0, sizeof(bindhints)); - bindhints.ai_socktype = SOCK_STREAM; - bindhints.ai_family = tcp->family; - bindhints.ai_flags = AI_PASSIVE; - err = inet_trybind(&tcp->sock, &tcp->family, address, port, &bindhints); - if (err) { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - lua_pushnumber(L, 1); - return 1; +static int meth_bind(lua_State* L) +{ + p_tcp tcp = (p_tcp)auxiliar_checkclass(L, "tcp{master}", 1); + const char* address = luaL_checkstring(L, 2); + const char* port = luaL_checkstring(L, 3); + const char* err; + struct addrinfo bindhints; + memset(&bindhints, 0, sizeof(bindhints)); + bindhints.ai_socktype = SOCK_STREAM; + bindhints.ai_family = tcp->family; + bindhints.ai_flags = AI_PASSIVE; + err = inet_trybind(&tcp->sock, &tcp->family, address, port, &bindhints); + if (err) + { + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } + lua_pushnumber(L, 1); + return 1; } /*-------------------------------------------------------------------------*\ * Turns a master tcp object into a client object. \*-------------------------------------------------------------------------*/ -static int meth_connect(lua_State *L) { - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - const char *address = luaL_checkstring(L, 2); - const char *port = luaL_checkstring(L, 3); - struct addrinfo connecthints; - const char *err; - memset(&connecthints, 0, sizeof(connecthints)); - connecthints.ai_socktype = SOCK_STREAM; - /* make sure we try to connect only to the same family */ - connecthints.ai_family = tcp->family; - timeout_markstart(&tcp->tm); - err = inet_tryconnect(&tcp->sock, &tcp->family, address, port, - &tcp->tm, &connecthints); - /* have to set the class even if it failed due to non-blocking connects */ - auxiliar_setclass(L, "tcp{client}", 1); - if (err) { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - lua_pushnumber(L, 1); - return 1; +static int meth_connect(lua_State* L) +{ + p_tcp tcp = (p_tcp)auxiliar_checkgroup(L, "tcp{any}", 1); + const char* address = luaL_checkstring(L, 2); + const char* port = luaL_checkstring(L, 3); + struct addrinfo connecthints; + const char* err; + memset(&connecthints, 0, sizeof(connecthints)); + connecthints.ai_socktype = SOCK_STREAM; + /* make sure we try to connect only to the same family */ + connecthints.ai_family = tcp->family; + timeout_markstart(&tcp->tm); + err = inet_tryconnect(&tcp->sock, &tcp->family, address, port, + &tcp->tm, &connecthints); + /* have to set the class even if it failed due to non-blocking connects */ + auxiliar_setclass(L, "tcp{client}", 1); + if (err) + { + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } + lua_pushnumber(L, 1); + return 1; } /*-------------------------------------------------------------------------*\ * Closes socket used by object \*-------------------------------------------------------------------------*/ -static int meth_close(lua_State *L) +static int meth_close(lua_State* L) { - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - socket_destroy(&tcp->sock); - lua_pushnumber(L, 1); - return 1; + p_tcp tcp = (p_tcp)auxiliar_checkgroup(L, "tcp{any}", 1); + socket_destroy(&tcp->sock); + lua_pushnumber(L, 1); + return 1; } /*-------------------------------------------------------------------------*\ * Returns family as string \*-------------------------------------------------------------------------*/ -static int meth_getfamily(lua_State *L) +static int meth_getfamily(lua_State* L) { - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - if (tcp->family == AF_INET6) { - lua_pushliteral(L, "inet6"); - return 1; - } else if (tcp->family == AF_INET) { - lua_pushliteral(L, "inet4"); - return 1; - } else { - lua_pushliteral(L, "inet4"); - return 1; - } + p_tcp tcp = (p_tcp)auxiliar_checkgroup(L, "tcp{any}", 1); + if (tcp->family == AF_INET6) + { + lua_pushliteral(L, "inet6"); + return 1; + } + else if (tcp->family == AF_INET) + { + lua_pushliteral(L, "inet4"); + return 1; + } + else + { + lua_pushliteral(L, "inet4"); + return 1; + } } /*-------------------------------------------------------------------------*\ * Puts the sockt in listen mode \*-------------------------------------------------------------------------*/ -static int meth_listen(lua_State *L) +static int meth_listen(lua_State* L) { - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1); - int backlog = (int) luaL_optnumber(L, 2, 32); - int err = socket_listen(&tcp->sock, backlog); - if (err != IO_DONE) { - lua_pushnil(L); - lua_pushstring(L, socket_strerror(err)); - return 2; - } - /* turn master object into a server object */ - auxiliar_setclass(L, "tcp{server}", 1); - lua_pushnumber(L, 1); - return 1; + p_tcp tcp = (p_tcp)auxiliar_checkclass(L, "tcp{master}", 1); + int backlog = (int)luaL_optnumber(L, 2, 32); + int err = socket_listen(&tcp->sock, backlog); + if (err != IO_DONE) + { + lua_pushnil(L); + lua_pushstring(L, socket_strerror(err)); + return 2; + } + /* turn master object into a server object */ + auxiliar_setclass(L, "tcp{server}", 1); + lua_pushnumber(L, 1); + return 1; } /*-------------------------------------------------------------------------*\ * Shuts the connection down partially \*-------------------------------------------------------------------------*/ -static int meth_shutdown(lua_State *L) +static int meth_shutdown(lua_State* L) { - /* SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2, so we can use method index directly */ - static const char* methods[] = { "receive", "send", "both", NULL }; - p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1); - int how = luaL_checkoption(L, 2, "both", methods); - socket_shutdown(&tcp->sock, how); - lua_pushnumber(L, 1); - return 1; + /* SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2, so we can use method index directly */ + static const char* methods[] = {"receive", "send", "both", NULL}; + p_tcp tcp = (p_tcp)auxiliar_checkclass(L, "tcp{client}", 1); + int how = luaL_checkoption(L, 2, "both", methods); + socket_shutdown(&tcp->sock, how); + lua_pushnumber(L, 1); + return 1; } /*-------------------------------------------------------------------------*\ * Just call inet methods \*-------------------------------------------------------------------------*/ -static int meth_getpeername(lua_State *L) +static int meth_getpeername(lua_State* L) { - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - return inet_meth_getpeername(L, &tcp->sock, tcp->family); + p_tcp tcp = (p_tcp)auxiliar_checkgroup(L, "tcp{any}", 1); + return inet_meth_getpeername(L, &tcp->sock, tcp->family); } -static int meth_getsockname(lua_State *L) +static int meth_getsockname(lua_State* L) { - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - return inet_meth_getsockname(L, &tcp->sock, tcp->family); + p_tcp tcp = (p_tcp)auxiliar_checkgroup(L, "tcp{any}", 1); + return inet_meth_getsockname(L, &tcp->sock, tcp->family); } /*-------------------------------------------------------------------------*\ * Just call tm methods \*-------------------------------------------------------------------------*/ -static int meth_settimeout(lua_State *L) +static int meth_settimeout(lua_State* L) { - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - return timeout_meth_settimeout(L, &tcp->tm); + p_tcp tcp = (p_tcp)auxiliar_checkgroup(L, "tcp{any}", 1); + return timeout_meth_settimeout(L, &tcp->tm); } -static int meth_gettimeout(lua_State *L) +static int meth_gettimeout(lua_State* L) { - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - return timeout_meth_gettimeout(L, &tcp->tm); + p_tcp tcp = (p_tcp)auxiliar_checkgroup(L, "tcp{any}", 1); + return timeout_meth_gettimeout(L, &tcp->tm); } /*=========================================================================*\ @@ -364,88 +381,98 @@ static int meth_gettimeout(lua_State *L) /*-------------------------------------------------------------------------*\ * Creates a master tcp object \*-------------------------------------------------------------------------*/ -static int tcp_create(lua_State *L, int family) { - p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); - memset(tcp, 0, sizeof(t_tcp)); - /* set its type as master object */ - auxiliar_setclass(L, "tcp{master}", -1); - /* if family is AF_UNSPEC, we leave the socket invalid and - * store AF_UNSPEC into family. This will allow it to later be - * replaced with an AF_INET6 or AF_INET socket upon first use. */ - tcp->sock = SOCKET_INVALID; - tcp->family = family; - io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv, - (p_error) socket_ioerror, &tcp->sock); - timeout_init(&tcp->tm, -1, -1); - buffer_init(&tcp->buf, &tcp->io, &tcp->tm); - if (family != AF_UNSPEC) { - const char *err = inet_trycreate(&tcp->sock, family, SOCK_STREAM, 0); - if (err != NULL) { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - socket_setnonblocking(&tcp->sock); - } - return 1; +static int tcp_create(lua_State* L, int family) +{ + p_tcp tcp = (p_tcp)lua_newuserdata(L, sizeof(t_tcp)); + memset(tcp, 0, sizeof(t_tcp)); + /* set its type as master object */ + auxiliar_setclass(L, "tcp{master}", -1); + /* if family is AF_UNSPEC, we leave the socket invalid and + * store AF_UNSPEC into family. This will allow it to later be + * replaced with an AF_INET6 or AF_INET socket upon first use. */ + tcp->sock = SOCKET_INVALID; + tcp->family = family; + io_init(&tcp->io, (p_send)socket_send, (p_recv)socket_recv, + (p_error)socket_ioerror, &tcp->sock); + timeout_init(&tcp->tm, -1, -1); + buffer_init(&tcp->buf, &tcp->io, &tcp->tm); + if (family != AF_UNSPEC) + { + const char* err = inet_trycreate(&tcp->sock, family, SOCK_STREAM, 0); + if (err != NULL) + { + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } + socket_setnonblocking(&tcp->sock); + } + return 1; } -static int global_create(lua_State *L) { - return tcp_create(L, AF_UNSPEC); +static int global_create(lua_State* L) +{ + return tcp_create(L, AF_UNSPEC); } -static int global_create4(lua_State *L) { - return tcp_create(L, AF_INET); +static int global_create4(lua_State* L) +{ + return tcp_create(L, AF_INET); } -static int global_create6(lua_State *L) { - return tcp_create(L, AF_INET6); +static int global_create6(lua_State* L) +{ + return tcp_create(L, AF_INET6); } -static int global_connect(lua_State *L) { - const char *remoteaddr = luaL_checkstring(L, 1); - const char *remoteserv = luaL_checkstring(L, 2); - const char *localaddr = luaL_optstring(L, 3, NULL); - const char *localserv = luaL_optstring(L, 4, "0"); - int family = inet_optfamily(L, 5, "unspec"); - p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); - struct addrinfo bindhints, connecthints; - const char *err = NULL; - /* initialize tcp structure */ - memset(tcp, 0, sizeof(t_tcp)); - io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv, - (p_error) socket_ioerror, &tcp->sock); - timeout_init(&tcp->tm, -1, -1); - buffer_init(&tcp->buf, &tcp->io, &tcp->tm); - tcp->sock = SOCKET_INVALID; - tcp->family = AF_UNSPEC; - /* allow user to pick local address and port */ - memset(&bindhints, 0, sizeof(bindhints)); - bindhints.ai_socktype = SOCK_STREAM; - bindhints.ai_family = family; - bindhints.ai_flags = AI_PASSIVE; - if (localaddr) { - err = inet_trybind(&tcp->sock, &tcp->family, localaddr, - localserv, &bindhints); - if (err) { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - } - /* try to connect to remote address and port */ - memset(&connecthints, 0, sizeof(connecthints)); - connecthints.ai_socktype = SOCK_STREAM; - /* make sure we try to connect only to the same family */ - connecthints.ai_family = tcp->family; - err = inet_tryconnect(&tcp->sock, &tcp->family, remoteaddr, remoteserv, - &tcp->tm, &connecthints); - if (err) { - socket_destroy(&tcp->sock); - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - auxiliar_setclass(L, "tcp{client}", -1); - return 1; +static int global_connect(lua_State* L) +{ + const char* remoteaddr = luaL_checkstring(L, 1); + const char* remoteserv = luaL_checkstring(L, 2); + const char* localaddr = luaL_optstring(L, 3, NULL); + const char* localserv = luaL_optstring(L, 4, "0"); + int family = inet_optfamily(L, 5, "unspec"); + p_tcp tcp = (p_tcp)lua_newuserdata(L, sizeof(t_tcp)); + struct addrinfo bindhints, connecthints; + const char* err = NULL; + /* initialize tcp structure */ + memset(tcp, 0, sizeof(t_tcp)); + io_init(&tcp->io, (p_send)socket_send, (p_recv)socket_recv, + (p_error)socket_ioerror, &tcp->sock); + timeout_init(&tcp->tm, -1, -1); + buffer_init(&tcp->buf, &tcp->io, &tcp->tm); + tcp->sock = SOCKET_INVALID; + tcp->family = AF_UNSPEC; + /* allow user to pick local address and port */ + memset(&bindhints, 0, sizeof(bindhints)); + bindhints.ai_socktype = SOCK_STREAM; + bindhints.ai_family = family; + bindhints.ai_flags = AI_PASSIVE; + if (localaddr) + { + err = inet_trybind(&tcp->sock, &tcp->family, localaddr, + localserv, &bindhints); + if (err) + { + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } + } + /* try to connect to remote address and port */ + memset(&connecthints, 0, sizeof(connecthints)); + connecthints.ai_socktype = SOCK_STREAM; + /* make sure we try to connect only to the same family */ + connecthints.ai_family = tcp->family; + err = inet_tryconnect(&tcp->sock, &tcp->family, remoteaddr, remoteserv, + &tcp->tm, &connecthints); + if (err) + { + socket_destroy(&tcp->sock); + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } + auxiliar_setclass(L, "tcp{client}", -1); + return 1; } diff --git a/Lua/tcp.h b/Lua/tcp.h index eded620..583ee2f 100644 --- a/Lua/tcp.h +++ b/Lua/tcp.h @@ -20,16 +20,17 @@ #include "timeout.h" #include "socket.h" -typedef struct t_tcp_ { - t_socket sock; - t_io io; - t_buffer buf; - t_timeout tm; - int family; +typedef struct t_tcp_ +{ + t_socket sock; + t_io io; + t_buffer buf; + t_timeout tm; + int family; } t_tcp; -typedef t_tcp *p_tcp; +typedef t_tcp* p_tcp; -int tcp_open(lua_State *L); +int tcp_open(lua_State* L); #endif /* TCP_H */ diff --git a/Lua/timeout.c b/Lua/timeout.c index 5a601d5..2ea4253 100644 --- a/Lua/timeout.c +++ b/Lua/timeout.c @@ -31,13 +31,13 @@ /*=========================================================================*\ * Internal function prototypes \*=========================================================================*/ -static int timeout_lua_gettime(lua_State *L); -static int timeout_lua_sleep(lua_State *L); +static int timeout_lua_gettime(lua_State* L); +static int timeout_lua_sleep(lua_State* L); static luaL_Reg func[] = { - { "gettime", timeout_lua_gettime }, - { "sleep", timeout_lua_sleep }, - { NULL, NULL } + {"gettime", timeout_lua_gettime}, + {"sleep", timeout_lua_sleep}, + {NULL, NULL} }; /*=========================================================================*\ @@ -46,9 +46,10 @@ static luaL_Reg func[] = { /*-------------------------------------------------------------------------*\ * Initialize structure \*-------------------------------------------------------------------------*/ -void timeout_init(p_timeout tm, double block, double total) { - tm->block = block; - tm->total = total; +void timeout_init(p_timeout tm, double block, double total) +{ + tm->block = block; + tm->total = total; } /*-------------------------------------------------------------------------*\ @@ -59,18 +60,26 @@ void timeout_init(p_timeout tm, double block, double total) { * Returns * the number of ms left or -1 if there is no time limit \*-------------------------------------------------------------------------*/ -double timeout_get(p_timeout tm) { - if (tm->block < 0.0 && tm->total < 0.0) { - return -1; - } else if (tm->block < 0.0) { - double t = tm->total - timeout_gettime() + tm->start; - return MAX(t, 0.0); - } else if (tm->total < 0.0) { - return tm->block; - } else { - double t = tm->total - timeout_gettime() + tm->start; - return MIN(tm->block, MAX(t, 0.0)); - } +double timeout_get(p_timeout tm) +{ + if (tm->block < 0.0 && tm->total < 0.0) + { + return -1; + } + else if (tm->block < 0.0) + { + double t = tm->total - timeout_gettime() + tm->start; + return MAX(t, 0.0); + } + else if (tm->total < 0.0) + { + return tm->block; + } + else + { + double t = tm->total - timeout_gettime() + tm->start; + return MIN(tm->block, MAX(t, 0.0)); + } } /*-------------------------------------------------------------------------*\ @@ -80,8 +89,9 @@ double timeout_get(p_timeout tm) { * Returns * start field of structure \*-------------------------------------------------------------------------*/ -double timeout_getstart(p_timeout tm) { - return tm->start; +double timeout_getstart(p_timeout tm) +{ + return tm->start; } /*-------------------------------------------------------------------------*\ @@ -92,19 +102,27 @@ double timeout_getstart(p_timeout tm) { * Returns * the number of ms left or -1 if there is no time limit \*-------------------------------------------------------------------------*/ -double timeout_getretry(p_timeout tm) { - if (tm->block < 0.0 && tm->total < 0.0) { - return -1; - } else if (tm->block < 0.0) { - double t = tm->total - timeout_gettime() + tm->start; - return MAX(t, 0.0); - } else if (tm->total < 0.0) { - double t = tm->block - timeout_gettime() + tm->start; - return MAX(t, 0.0); - } else { - double t = tm->total - timeout_gettime() + tm->start; - return MIN(tm->block, MAX(t, 0.0)); - } +double timeout_getretry(p_timeout tm) +{ + if (tm->block < 0.0 && tm->total < 0.0) + { + return -1; + } + else if (tm->block < 0.0) + { + double t = tm->total - timeout_gettime() + tm->start; + return MAX(t, 0.0); + } + else if (tm->total < 0.0) + { + double t = tm->block - timeout_gettime() + tm->start; + return MAX(t, 0.0); + } + else + { + double t = tm->total - timeout_gettime() + tm->start; + return MIN(tm->block, MAX(t, 0.0)); + } } /*-------------------------------------------------------------------------*\ @@ -112,9 +130,10 @@ double timeout_getretry(p_timeout tm) { * Input * tm: timeout control structure \*-------------------------------------------------------------------------*/ -p_timeout timeout_markstart(p_timeout tm) { - tm->start = timeout_gettime(); - return tm; +p_timeout timeout_markstart(p_timeout tm) +{ + tm->start = timeout_gettime(); + return tm; } /*-------------------------------------------------------------------------*\ @@ -123,14 +142,15 @@ p_timeout timeout_markstart(p_timeout tm) { * time in s. \*-------------------------------------------------------------------------*/ #ifdef _WIN32 -double timeout_gettime(void) { - FILETIME ft; - double t; - GetSystemTimeAsFileTime(&ft); - /* Windows file time (time since January 1, 1601 (UTC)) */ - t = ft.dwLowDateTime/1.0e7 + ft.dwHighDateTime*(4294967296.0/1.0e7); - /* convert to Unix Epoch time (time since January 1, 1970 (UTC)) */ - return (t - 11644473600.0); +double timeout_gettime(void) +{ + FILETIME ft; + double t; + GetSystemTimeAsFileTime(&ft); + /* Windows file time (time since January 1, 1601 (UTC)) */ + t = ft.dwLowDateTime / 1.0e7 + ft.dwHighDateTime * (4294967296.0 / 1.0e7); + /* convert to Unix Epoch time (time since January 1, 1970 (UTC)) */ + return (t - 11644473600.0); } #else double timeout_gettime(void) { @@ -144,9 +164,10 @@ double timeout_gettime(void) { /*-------------------------------------------------------------------------*\ * Initializes module \*-------------------------------------------------------------------------*/ -int timeout_open(lua_State *L) { - luaL_setfuncs(L, func, 0); - return 0; +int timeout_open(lua_State* L) +{ + luaL_setfuncs(L, func, 0); + return 0; } /*-------------------------------------------------------------------------*\ @@ -155,32 +176,36 @@ int timeout_open(lua_State *L) { * time: time out value in seconds * mode: "b" for block timeout, "t" for total timeout. (default: b) \*-------------------------------------------------------------------------*/ -int timeout_meth_settimeout(lua_State *L, p_timeout tm) { - double t = luaL_optnumber(L, 2, -1); - const char *mode = luaL_optstring(L, 3, "b"); - switch (*mode) { - case 'b': - tm->block = t; - break; - case 'r': case 't': - tm->total = t; - break; - default: - luaL_argcheck(L, 0, 3, "invalid timeout mode"); - break; - } - lua_pushnumber(L, 1); - return 1; +int timeout_meth_settimeout(lua_State* L, p_timeout tm) +{ + double t = luaL_optnumber(L, 2, -1); + const char* mode = luaL_optstring(L, 3, "b"); + switch (*mode) + { + case 'b': + tm->block = t; + break; + case 'r': + case 't': + tm->total = t; + break; + default: + luaL_argcheck(L, 0, 3, "invalid timeout mode"); + break; + } + lua_pushnumber(L, 1); + return 1; } /*-------------------------------------------------------------------------*\ * Gets timeout values for IO operations * Lua Output: block, total \*-------------------------------------------------------------------------*/ -int timeout_meth_gettimeout(lua_State *L, p_timeout tm) { - lua_pushnumber(L, tm->block); - lua_pushnumber(L, tm->total); - return 2; +int timeout_meth_gettimeout(lua_State* L, p_timeout tm) +{ + lua_pushnumber(L, tm->block); + lua_pushnumber(L, tm->total); + return 2; } /*=========================================================================*\ @@ -189,24 +214,24 @@ int timeout_meth_gettimeout(lua_State *L, p_timeout tm) { /*-------------------------------------------------------------------------*\ * Returns the time the system has been up, in secconds. \*-------------------------------------------------------------------------*/ -static int timeout_lua_gettime(lua_State *L) +static int timeout_lua_gettime(lua_State* L) { - lua_pushnumber(L, timeout_gettime()); - return 1; + lua_pushnumber(L, timeout_gettime()); + return 1; } /*-------------------------------------------------------------------------*\ * Sleep for n seconds. \*-------------------------------------------------------------------------*/ #ifdef _WIN32 -int timeout_lua_sleep(lua_State *L) +int timeout_lua_sleep(lua_State* L) { - double n = luaL_checknumber(L, 1); - if (n < 0.0) n = 0.0; - if (n < DBL_MAX/1000.0) n *= 1000.0; - if (n > INT_MAX) n = INT_MAX; - Sleep((int)n); - return 0; + double n = luaL_checknumber(L, 1); + if (n < 0.0) n = 0.0; + if (n < DBL_MAX / 1000.0) n *= 1000.0; + if (n > INT_MAX) n = INT_MAX; + Sleep((int)n); + return 0; } #else int timeout_lua_sleep(lua_State *L) diff --git a/Lua/timeout.h b/Lua/timeout.h index af90231..f10065f 100644 --- a/Lua/timeout.h +++ b/Lua/timeout.h @@ -7,22 +7,24 @@ #include "lua.h" /* timeout control structure */ -typedef struct t_timeout_ { - double block; /* maximum time for blocking calls */ - double total; /* total number of miliseconds for operation */ - double start; /* time of start of operation */ +typedef struct t_timeout_ +{ + double block; /* maximum time for blocking calls */ + double total; /* total number of miliseconds for operation */ + double start; /* time of start of operation */ } t_timeout; -typedef t_timeout *p_timeout; -int timeout_open(lua_State *L); +typedef t_timeout* p_timeout; + +int timeout_open(lua_State* L); void timeout_init(p_timeout tm, double block, double total); double timeout_get(p_timeout tm); double timeout_getretry(p_timeout tm); p_timeout timeout_markstart(p_timeout tm); double timeout_getstart(p_timeout tm); double timeout_gettime(void); -int timeout_meth_settimeout(lua_State *L, p_timeout tm); -int timeout_meth_gettimeout(lua_State *L, p_timeout tm); +int timeout_meth_settimeout(lua_State* L, p_timeout tm); +int timeout_meth_gettimeout(lua_State* L, p_timeout tm); #define timeout_iszero(tm) ((tm)->block == 0.0) diff --git a/Lua/udp.c b/Lua/udp.c index a47ed75..4bb045b 100644 --- a/Lua/udp.c +++ b/Lua/udp.c @@ -26,420 +26,459 @@ /*=========================================================================*\ * Internal function prototypes \*=========================================================================*/ -static int global_create(lua_State *L); -static int global_create4(lua_State *L); -static int global_create6(lua_State *L); -static int meth_send(lua_State *L); -static int meth_sendto(lua_State *L); -static int meth_receive(lua_State *L); -static int meth_receivefrom(lua_State *L); -static int meth_getfamily(lua_State *L); -static int meth_getsockname(lua_State *L); -static int meth_getpeername(lua_State *L); -static int meth_gettimeout(lua_State *L); -static int meth_setsockname(lua_State *L); -static int meth_setpeername(lua_State *L); -static int meth_close(lua_State *L); -static int meth_setoption(lua_State *L); -static int meth_getoption(lua_State *L); -static int meth_settimeout(lua_State *L); -static int meth_getfd(lua_State *L); -static int meth_setfd(lua_State *L); -static int meth_dirty(lua_State *L); +static int global_create(lua_State* L); +static int global_create4(lua_State* L); +static int global_create6(lua_State* L); +static int meth_send(lua_State* L); +static int meth_sendto(lua_State* L); +static int meth_receive(lua_State* L); +static int meth_receivefrom(lua_State* L); +static int meth_getfamily(lua_State* L); +static int meth_getsockname(lua_State* L); +static int meth_getpeername(lua_State* L); +static int meth_gettimeout(lua_State* L); +static int meth_setsockname(lua_State* L); +static int meth_setpeername(lua_State* L); +static int meth_close(lua_State* L); +static int meth_setoption(lua_State* L); +static int meth_getoption(lua_State* L); +static int meth_settimeout(lua_State* L); +static int meth_getfd(lua_State* L); +static int meth_setfd(lua_State* L); +static int meth_dirty(lua_State* L); /* udp object methods */ static luaL_Reg udp_methods[] = { - {"__gc", meth_close}, - {"__tostring", auxiliar_tostring}, - {"close", meth_close}, - {"dirty", meth_dirty}, - {"getfamily", meth_getfamily}, - {"getfd", meth_getfd}, - {"getpeername", meth_getpeername}, - {"getsockname", meth_getsockname}, - {"receive", meth_receive}, - {"receivefrom", meth_receivefrom}, - {"send", meth_send}, - {"sendto", meth_sendto}, - {"setfd", meth_setfd}, - {"setoption", meth_setoption}, - {"getoption", meth_getoption}, - {"setpeername", meth_setpeername}, - {"setsockname", meth_setsockname}, - {"settimeout", meth_settimeout}, - {"gettimeout", meth_gettimeout}, - {NULL, NULL} + {"__gc", meth_close}, + {"__tostring", auxiliar_tostring}, + {"close", meth_close}, + {"dirty", meth_dirty}, + {"getfamily", meth_getfamily}, + {"getfd", meth_getfd}, + {"getpeername", meth_getpeername}, + {"getsockname", meth_getsockname}, + {"receive", meth_receive}, + {"receivefrom", meth_receivefrom}, + {"send", meth_send}, + {"sendto", meth_sendto}, + {"setfd", meth_setfd}, + {"setoption", meth_setoption}, + {"getoption", meth_getoption}, + {"setpeername", meth_setpeername}, + {"setsockname", meth_setsockname}, + {"settimeout", meth_settimeout}, + {"gettimeout", meth_gettimeout}, + {NULL, NULL} }; /* socket options for setoption */ static t_opt optset[] = { - {"dontroute", opt_set_dontroute}, - {"broadcast", opt_set_broadcast}, - {"reuseaddr", opt_set_reuseaddr}, - {"reuseport", opt_set_reuseport}, - {"ip-multicast-if", opt_set_ip_multicast_if}, - {"ip-multicast-ttl", opt_set_ip_multicast_ttl}, - {"ip-multicast-loop", opt_set_ip_multicast_loop}, - {"ip-add-membership", opt_set_ip_add_membership}, - {"ip-drop-membership", opt_set_ip_drop_membersip}, - {"ipv6-unicast-hops", opt_set_ip6_unicast_hops}, - {"ipv6-multicast-hops", opt_set_ip6_unicast_hops}, - {"ipv6-multicast-loop", opt_set_ip6_multicast_loop}, - {"ipv6-add-membership", opt_set_ip6_add_membership}, - {"ipv6-drop-membership", opt_set_ip6_drop_membersip}, - {"ipv6-v6only", opt_set_ip6_v6only}, - {NULL, NULL} + {"dontroute", opt_set_dontroute}, + {"broadcast", opt_set_broadcast}, + {"reuseaddr", opt_set_reuseaddr}, + {"reuseport", opt_set_reuseport}, + {"ip-multicast-if", opt_set_ip_multicast_if}, + {"ip-multicast-ttl", opt_set_ip_multicast_ttl}, + {"ip-multicast-loop", opt_set_ip_multicast_loop}, + {"ip-add-membership", opt_set_ip_add_membership}, + {"ip-drop-membership", opt_set_ip_drop_membersip}, + {"ipv6-unicast-hops", opt_set_ip6_unicast_hops}, + {"ipv6-multicast-hops", opt_set_ip6_unicast_hops}, + {"ipv6-multicast-loop", opt_set_ip6_multicast_loop}, + {"ipv6-add-membership", opt_set_ip6_add_membership}, + {"ipv6-drop-membership", opt_set_ip6_drop_membersip}, + {"ipv6-v6only", opt_set_ip6_v6only}, + {NULL, NULL} }; /* socket options for getoption */ static t_opt optget[] = { - {"dontroute", opt_get_dontroute}, - {"broadcast", opt_get_broadcast}, - {"reuseaddr", opt_get_reuseaddr}, - {"reuseport", opt_get_reuseport}, - {"ip-multicast-if", opt_get_ip_multicast_if}, - {"ip-multicast-loop", opt_get_ip_multicast_loop}, - {"error", opt_get_error}, - {"ipv6-unicast-hops", opt_get_ip6_unicast_hops}, - {"ipv6-multicast-hops", opt_get_ip6_unicast_hops}, - {"ipv6-multicast-loop", opt_get_ip6_multicast_loop}, - {"ipv6-v6only", opt_get_ip6_v6only}, - {NULL, NULL} + {"dontroute", opt_get_dontroute}, + {"broadcast", opt_get_broadcast}, + {"reuseaddr", opt_get_reuseaddr}, + {"reuseport", opt_get_reuseport}, + {"ip-multicast-if", opt_get_ip_multicast_if}, + {"ip-multicast-loop", opt_get_ip_multicast_loop}, + {"error", opt_get_error}, + {"ipv6-unicast-hops", opt_get_ip6_unicast_hops}, + {"ipv6-multicast-hops", opt_get_ip6_unicast_hops}, + {"ipv6-multicast-loop", opt_get_ip6_multicast_loop}, + {"ipv6-v6only", opt_get_ip6_v6only}, + {NULL, NULL} }; /* functions in library namespace */ static luaL_Reg func[] = { - {"udp", global_create}, - {"udp4", global_create4}, - {"udp6", global_create6}, - {NULL, NULL} + {"udp", global_create}, + {"udp4", global_create4}, + {"udp6", global_create6}, + {NULL, NULL} }; /*-------------------------------------------------------------------------*\ * Initializes module \*-------------------------------------------------------------------------*/ -int udp_open(lua_State *L) { - /* create classes */ - auxiliar_newclass(L, "udp{connected}", udp_methods); - auxiliar_newclass(L, "udp{unconnected}", udp_methods); - /* create class groups */ - auxiliar_add2group(L, "udp{connected}", "udp{any}"); - auxiliar_add2group(L, "udp{unconnected}", "udp{any}"); - auxiliar_add2group(L, "udp{connected}", "select{able}"); - auxiliar_add2group(L, "udp{unconnected}", "select{able}"); - /* define library functions */ - luaL_setfuncs(L, func, 0); - /* export default UDP size */ - lua_pushliteral(L, "_DATAGRAMSIZE"); - lua_pushinteger(L, UDP_DATAGRAMSIZE); - lua_rawset(L, -3); - return 0; +int udp_open(lua_State* L) +{ + /* create classes */ + auxiliar_newclass(L, "udp{connected}", udp_methods); + auxiliar_newclass(L, "udp{unconnected}", udp_methods); + /* create class groups */ + auxiliar_add2group(L, "udp{connected}", "udp{any}"); + auxiliar_add2group(L, "udp{unconnected}", "udp{any}"); + auxiliar_add2group(L, "udp{connected}", "select{able}"); + auxiliar_add2group(L, "udp{unconnected}", "select{able}"); + /* define library functions */ + luaL_setfuncs(L, func, 0); + /* export default UDP size */ + lua_pushliteral(L, "_DATAGRAMSIZE"); + lua_pushinteger(L, UDP_DATAGRAMSIZE); + lua_rawset(L, -3); + return 0; } /*=========================================================================*\ * Lua methods \*=========================================================================*/ -static const char *udp_strerror(int err) { - /* a 'closed' error on an unconnected means the target address was not - * accepted by the transport layer */ - if (err == IO_CLOSED) return "refused"; - else return socket_strerror(err); +static const char* udp_strerror(int err) +{ + /* a 'closed' error on an unconnected means the target address was not + * accepted by the transport layer */ + if (err == IO_CLOSED) return "refused"; + else return socket_strerror(err); } /*-------------------------------------------------------------------------*\ * Send data through connected udp socket \*-------------------------------------------------------------------------*/ -static int meth_send(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{connected}", 1); - p_timeout tm = &udp->tm; - size_t count, sent = 0; - int err; - const char *data = luaL_checklstring(L, 2, &count); - timeout_markstart(tm); - err = socket_send(&udp->sock, data, count, &sent, tm); - if (err != IO_DONE) { - lua_pushnil(L); - lua_pushstring(L, udp_strerror(err)); - return 2; - } - lua_pushnumber(L, (lua_Number) sent); - return 1; +static int meth_send(lua_State* L) +{ + p_udp udp = (p_udp)auxiliar_checkclass(L, "udp{connected}", 1); + p_timeout tm = &udp->tm; + size_t count, sent = 0; + int err; + const char* data = luaL_checklstring(L, 2, &count); + timeout_markstart(tm); + err = socket_send(&udp->sock, data, count, &sent, tm); + if (err != IO_DONE) + { + lua_pushnil(L); + lua_pushstring(L, udp_strerror(err)); + return 2; + } + lua_pushnumber(L, (lua_Number)sent); + return 1; } /*-------------------------------------------------------------------------*\ * Send data through unconnected udp socket \*-------------------------------------------------------------------------*/ -static int meth_sendto(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); - size_t count, sent = 0; - const char *data = luaL_checklstring(L, 2, &count); - const char *ip = luaL_checkstring(L, 3); - const char *port = luaL_checkstring(L, 4); - p_timeout tm = &udp->tm; - int err; - struct addrinfo aihint; - struct addrinfo *ai; - memset(&aihint, 0, sizeof(aihint)); - aihint.ai_family = udp->family; - aihint.ai_socktype = SOCK_DGRAM; - aihint.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; - err = getaddrinfo(ip, port, &aihint, &ai); - if (err) { - lua_pushnil(L); - lua_pushstring(L, gai_strerrorA(err)); - return 2; - } +static int meth_sendto(lua_State* L) +{ + p_udp udp = (p_udp)auxiliar_checkclass(L, "udp{unconnected}", 1); + size_t count, sent = 0; + const char* data = luaL_checklstring(L, 2, &count); + const char* ip = luaL_checkstring(L, 3); + const char* port = luaL_checkstring(L, 4); + p_timeout tm = &udp->tm; + int err; + struct addrinfo aihint; + struct addrinfo* ai; + memset(&aihint, 0, sizeof(aihint)); + aihint.ai_family = udp->family; + aihint.ai_socktype = SOCK_DGRAM; + aihint.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; + err = getaddrinfo(ip, port, &aihint, &ai); + if (err) + { + lua_pushnil(L); + lua_pushstring(L, gai_strerrorA(err)); + return 2; + } - /* create socket if on first sendto if AF_UNSPEC was set */ - if (udp->family == AF_UNSPEC && udp->sock == SOCKET_INVALID) { - struct addrinfo *ap; - const char *errstr = NULL; - for (ap = ai; ap != NULL; ap = ap->ai_next) { - errstr = inet_trycreate(&udp->sock, ap->ai_family, SOCK_DGRAM, 0); - if (errstr == NULL) { - socket_setnonblocking(&udp->sock); - udp->family = ap->ai_family; - break; - } - } - if (errstr != NULL) { - lua_pushnil(L); - lua_pushstring(L, errstr); - freeaddrinfo(ai); - return 2; - } - } + /* create socket if on first sendto if AF_UNSPEC was set */ + if (udp->family == AF_UNSPEC && udp->sock == SOCKET_INVALID) + { + struct addrinfo* ap; + const char* errstr = NULL; + for (ap = ai; ap != NULL; ap = ap->ai_next) + { + errstr = inet_trycreate(&udp->sock, ap->ai_family, SOCK_DGRAM, 0); + if (errstr == NULL) + { + socket_setnonblocking(&udp->sock); + udp->family = ap->ai_family; + break; + } + } + if (errstr != NULL) + { + lua_pushnil(L); + lua_pushstring(L, errstr); + freeaddrinfo(ai); + return 2; + } + } - timeout_markstart(tm); - err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, - (socklen_t) ai->ai_addrlen, tm); - freeaddrinfo(ai); - if (err != IO_DONE) { - lua_pushnil(L); - lua_pushstring(L, udp_strerror(err)); - return 2; - } - lua_pushnumber(L, (lua_Number) sent); - return 1; + timeout_markstart(tm); + err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, + (socklen_t)ai->ai_addrlen, tm); + freeaddrinfo(ai); + if (err != IO_DONE) + { + lua_pushnil(L); + lua_pushstring(L, udp_strerror(err)); + return 2; + } + lua_pushnumber(L, (lua_Number)sent); + return 1; } /*-------------------------------------------------------------------------*\ * Receives data from a UDP socket \*-------------------------------------------------------------------------*/ -static int meth_receive(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - char buf[UDP_DATAGRAMSIZE]; - size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); - char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; - int err; - p_timeout tm = &udp->tm; - timeout_markstart(tm); - if (!dgram) { - lua_pushnil(L); - lua_pushliteral(L, "out of memory"); - return 2; - } - err = socket_recv(&udp->sock, dgram, wanted, &got, tm); - /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ - if (err != IO_DONE && err != IO_CLOSED) { - lua_pushnil(L); - lua_pushstring(L, udp_strerror(err)); - if (wanted > sizeof(buf)) free(dgram); - return 2; - } - lua_pushlstring(L, dgram, got); - if (wanted > sizeof(buf)) free(dgram); - return 1; +static int meth_receive(lua_State* L) +{ + p_udp udp = (p_udp)auxiliar_checkgroup(L, "udp{any}", 1); + char buf[UDP_DATAGRAMSIZE]; + size_t got, wanted = (size_t)luaL_optnumber(L, 2, sizeof(buf)); + char* dgram = wanted > sizeof(buf) ? (char*)malloc(wanted) : buf; + int err; + p_timeout tm = &udp->tm; + timeout_markstart(tm); + if (!dgram) + { + lua_pushnil(L); + lua_pushliteral(L, "out of memory"); + return 2; + } + err = socket_recv(&udp->sock, dgram, wanted, &got, tm); + /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ + if (err != IO_DONE && err != IO_CLOSED) + { + lua_pushnil(L); + lua_pushstring(L, udp_strerror(err)); + if (wanted > sizeof(buf)) free(dgram); + return 2; + } + lua_pushlstring(L, dgram, got); + if (wanted > sizeof(buf)) free(dgram); + return 1; } /*-------------------------------------------------------------------------*\ * Receives data and sender from a UDP socket \*-------------------------------------------------------------------------*/ -static int meth_receivefrom(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); - char buf[UDP_DATAGRAMSIZE]; - size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); - char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; - struct sockaddr_storage addr; - socklen_t addr_len = sizeof(addr); - char addrstr[INET6_ADDRSTRLEN]; - char portstr[6]; - int err; - p_timeout tm = &udp->tm; - timeout_markstart(tm); - if (!dgram) { - lua_pushnil(L); - lua_pushliteral(L, "out of memory"); - return 2; - } - err = socket_recvfrom(&udp->sock, dgram, wanted, &got, (SA *) &addr, - &addr_len, tm); - /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ - if (err != IO_DONE && err != IO_CLOSED) { - lua_pushnil(L); - lua_pushstring(L, udp_strerror(err)); - if (wanted > sizeof(buf)) free(dgram); - return 2; - } - err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, - INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV); - if (err) { - lua_pushnil(L); - lua_pushstring(L, gai_strerrorA(err)); - if (wanted > sizeof(buf)) free(dgram); - return 2; - } - lua_pushlstring(L, dgram, got); - lua_pushstring(L, addrstr); - lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10)); - if (wanted > sizeof(buf)) free(dgram); - return 3; +static int meth_receivefrom(lua_State* L) +{ + p_udp udp = (p_udp)auxiliar_checkclass(L, "udp{unconnected}", 1); + char buf[UDP_DATAGRAMSIZE]; + size_t got, wanted = (size_t)luaL_optnumber(L, 2, sizeof(buf)); + char* dgram = wanted > sizeof(buf) ? (char*)malloc(wanted) : buf; + struct sockaddr_storage addr; + socklen_t addr_len = sizeof(addr); + char addrstr[INET6_ADDRSTRLEN]; + char portstr[6]; + int err; + p_timeout tm = &udp->tm; + timeout_markstart(tm); + if (!dgram) + { + lua_pushnil(L); + lua_pushliteral(L, "out of memory"); + return 2; + } + err = socket_recvfrom(&udp->sock, dgram, wanted, &got, (SA*)&addr, + &addr_len, tm); + /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ + if (err != IO_DONE && err != IO_CLOSED) + { + lua_pushnil(L); + lua_pushstring(L, udp_strerror(err)); + if (wanted > sizeof(buf)) free(dgram); + return 2; + } + err = getnameinfo((struct sockaddr*)&addr, addr_len, addrstr, + INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV); + if (err) + { + lua_pushnil(L); + lua_pushstring(L, gai_strerrorA(err)); + if (wanted > sizeof(buf)) free(dgram); + return 2; + } + lua_pushlstring(L, dgram, got); + lua_pushstring(L, addrstr); + lua_pushinteger(L, (int)strtol(portstr, (char**)NULL, 10)); + if (wanted > sizeof(buf)) free(dgram); + return 3; } /*-------------------------------------------------------------------------*\ * Returns family as string \*-------------------------------------------------------------------------*/ -static int meth_getfamily(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - if (udp->family == AF_INET6) { - lua_pushliteral(L, "inet6"); - return 1; - } else { - lua_pushliteral(L, "inet4"); - return 1; - } +static int meth_getfamily(lua_State* L) +{ + p_udp udp = (p_udp)auxiliar_checkgroup(L, "udp{any}", 1); + if (udp->family == AF_INET6) + { + lua_pushliteral(L, "inet6"); + return 1; + } + else + { + lua_pushliteral(L, "inet4"); + return 1; + } } /*-------------------------------------------------------------------------*\ * Select support methods \*-------------------------------------------------------------------------*/ -static int meth_getfd(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - lua_pushnumber(L, (int) udp->sock); - return 1; +static int meth_getfd(lua_State* L) +{ + p_udp udp = (p_udp)auxiliar_checkgroup(L, "udp{any}", 1); + lua_pushnumber(L, (int)udp->sock); + return 1; } /* this is very dangerous, but can be handy for those that are brave enough */ -static int meth_setfd(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - udp->sock = (t_socket) luaL_checknumber(L, 2); - return 0; +static int meth_setfd(lua_State* L) +{ + p_udp udp = (p_udp)auxiliar_checkgroup(L, "udp{any}", 1); + udp->sock = (t_socket)luaL_checknumber(L, 2); + return 0; } -static int meth_dirty(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - (void) udp; - lua_pushboolean(L, 0); - return 1; +static int meth_dirty(lua_State* L) +{ + p_udp udp = (p_udp)auxiliar_checkgroup(L, "udp{any}", 1); + (void)udp; + lua_pushboolean(L, 0); + return 1; } /*-------------------------------------------------------------------------*\ * Just call inet methods \*-------------------------------------------------------------------------*/ -static int meth_getpeername(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{connected}", 1); - return inet_meth_getpeername(L, &udp->sock, udp->family); +static int meth_getpeername(lua_State* L) +{ + p_udp udp = (p_udp)auxiliar_checkclass(L, "udp{connected}", 1); + return inet_meth_getpeername(L, &udp->sock, udp->family); } -static int meth_getsockname(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - return inet_meth_getsockname(L, &udp->sock, udp->family); +static int meth_getsockname(lua_State* L) +{ + p_udp udp = (p_udp)auxiliar_checkgroup(L, "udp{any}", 1); + return inet_meth_getsockname(L, &udp->sock, udp->family); } /*-------------------------------------------------------------------------*\ * Just call option handler \*-------------------------------------------------------------------------*/ -static int meth_setoption(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - return opt_meth_setoption(L, optset, &udp->sock); +static int meth_setoption(lua_State* L) +{ + p_udp udp = (p_udp)auxiliar_checkgroup(L, "udp{any}", 1); + return opt_meth_setoption(L, optset, &udp->sock); } /*-------------------------------------------------------------------------*\ * Just call option handler \*-------------------------------------------------------------------------*/ -static int meth_getoption(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - return opt_meth_getoption(L, optget, &udp->sock); +static int meth_getoption(lua_State* L) +{ + p_udp udp = (p_udp)auxiliar_checkgroup(L, "udp{any}", 1); + return opt_meth_getoption(L, optget, &udp->sock); } /*-------------------------------------------------------------------------*\ * Just call tm methods \*-------------------------------------------------------------------------*/ -static int meth_settimeout(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - return timeout_meth_settimeout(L, &udp->tm); +static int meth_settimeout(lua_State* L) +{ + p_udp udp = (p_udp)auxiliar_checkgroup(L, "udp{any}", 1); + return timeout_meth_settimeout(L, &udp->tm); } -static int meth_gettimeout(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - return timeout_meth_gettimeout(L, &udp->tm); +static int meth_gettimeout(lua_State* L) +{ + p_udp udp = (p_udp)auxiliar_checkgroup(L, "udp{any}", 1); + return timeout_meth_gettimeout(L, &udp->tm); } /*-------------------------------------------------------------------------*\ * Turns a master udp object into a client object. \*-------------------------------------------------------------------------*/ -static int meth_setpeername(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - p_timeout tm = &udp->tm; - const char *address = luaL_checkstring(L, 2); - int connecting = strcmp(address, "*"); - const char *port = connecting? luaL_checkstring(L, 3): "0"; - struct addrinfo connecthints; - const char *err; - memset(&connecthints, 0, sizeof(connecthints)); - connecthints.ai_socktype = SOCK_DGRAM; - /* make sure we try to connect only to the same family */ - connecthints.ai_family = udp->family; - if (connecting) { - err = inet_tryconnect(&udp->sock, &udp->family, address, - port, tm, &connecthints); - if (err) { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - auxiliar_setclass(L, "udp{connected}", 1); - } else { - /* we ignore possible errors because Mac OS X always - * returns EAFNOSUPPORT */ - inet_trydisconnect(&udp->sock, udp->family, tm); - auxiliar_setclass(L, "udp{unconnected}", 1); - } - lua_pushnumber(L, 1); - return 1; +static int meth_setpeername(lua_State* L) +{ + p_udp udp = (p_udp)auxiliar_checkgroup(L, "udp{any}", 1); + p_timeout tm = &udp->tm; + const char* address = luaL_checkstring(L, 2); + int connecting = strcmp(address, "*"); + const char* port = connecting ? luaL_checkstring(L, 3) : "0"; + struct addrinfo connecthints; + const char* err; + memset(&connecthints, 0, sizeof(connecthints)); + connecthints.ai_socktype = SOCK_DGRAM; + /* make sure we try to connect only to the same family */ + connecthints.ai_family = udp->family; + if (connecting) + { + err = inet_tryconnect(&udp->sock, &udp->family, address, + port, tm, &connecthints); + if (err) + { + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } + auxiliar_setclass(L, "udp{connected}", 1); + } + else + { + /* we ignore possible errors because Mac OS X always + * returns EAFNOSUPPORT */ + inet_trydisconnect(&udp->sock, udp->family, tm); + auxiliar_setclass(L, "udp{unconnected}", 1); + } + lua_pushnumber(L, 1); + return 1; } /*-------------------------------------------------------------------------*\ * Closes socket used by object \*-------------------------------------------------------------------------*/ -static int meth_close(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - socket_destroy(&udp->sock); - lua_pushnumber(L, 1); - return 1; +static int meth_close(lua_State* L) +{ + p_udp udp = (p_udp)auxiliar_checkgroup(L, "udp{any}", 1); + socket_destroy(&udp->sock); + lua_pushnumber(L, 1); + return 1; } /*-------------------------------------------------------------------------*\ * Turns a master object into a server object \*-------------------------------------------------------------------------*/ -static int meth_setsockname(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); - const char *address = luaL_checkstring(L, 2); - const char *port = luaL_checkstring(L, 3); - const char *err; - struct addrinfo bindhints; - memset(&bindhints, 0, sizeof(bindhints)); - bindhints.ai_socktype = SOCK_DGRAM; - bindhints.ai_family = udp->family; - bindhints.ai_flags = AI_PASSIVE; - err = inet_trybind(&udp->sock, &udp->family, address, port, &bindhints); - if (err) { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - lua_pushnumber(L, 1); - return 1; +static int meth_setsockname(lua_State* L) +{ + p_udp udp = (p_udp)auxiliar_checkclass(L, "udp{unconnected}", 1); + const char* address = luaL_checkstring(L, 2); + const char* port = luaL_checkstring(L, 3); + const char* err; + struct addrinfo bindhints; + memset(&bindhints, 0, sizeof(bindhints)); + bindhints.ai_socktype = SOCK_DGRAM; + bindhints.ai_family = udp->family; + bindhints.ai_flags = AI_PASSIVE; + err = inet_trybind(&udp->sock, &udp->family, address, port, &bindhints); + if (err) + { + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } + lua_pushnumber(L, 1); + return 1; } /*=========================================================================*\ @@ -448,36 +487,42 @@ static int meth_setsockname(lua_State *L) { /*-------------------------------------------------------------------------*\ * Creates a master udp object \*-------------------------------------------------------------------------*/ -static int udp_create(lua_State *L, int family) { - /* allocate udp object */ - p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); - auxiliar_setclass(L, "udp{unconnected}", -1); - /* if family is AF_UNSPEC, we leave the socket invalid and - * store AF_UNSPEC into family. This will allow it to later be - * replaced with an AF_INET6 or AF_INET socket upon first use. */ - udp->sock = SOCKET_INVALID; - timeout_init(&udp->tm, -1, -1); - udp->family = family; - if (family != AF_UNSPEC) { - const char *err = inet_trycreate(&udp->sock, family, SOCK_DGRAM, 0); - if (err != NULL) { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - socket_setnonblocking(&udp->sock); - } - return 1; +static int udp_create(lua_State* L, int family) +{ + /* allocate udp object */ + p_udp udp = (p_udp)lua_newuserdata(L, sizeof(t_udp)); + auxiliar_setclass(L, "udp{unconnected}", -1); + /* if family is AF_UNSPEC, we leave the socket invalid and + * store AF_UNSPEC into family. This will allow it to later be + * replaced with an AF_INET6 or AF_INET socket upon first use. */ + udp->sock = SOCKET_INVALID; + timeout_init(&udp->tm, -1, -1); + udp->family = family; + if (family != AF_UNSPEC) + { + const char* err = inet_trycreate(&udp->sock, family, SOCK_DGRAM, 0); + if (err != NULL) + { + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } + socket_setnonblocking(&udp->sock); + } + return 1; } -static int global_create(lua_State *L) { - return udp_create(L, AF_UNSPEC); +static int global_create(lua_State* L) +{ + return udp_create(L, AF_UNSPEC); } -static int global_create4(lua_State *L) { - return udp_create(L, AF_INET); +static int global_create4(lua_State* L) +{ + return udp_create(L, AF_INET); } -static int global_create6(lua_State *L) { - return udp_create(L, AF_INET6); +static int global_create6(lua_State* L) +{ + return udp_create(L, AF_INET6); } diff --git a/Lua/udp.h b/Lua/udp.h index be9b6a5..162ae04 100644 --- a/Lua/udp.h +++ b/Lua/udp.h @@ -19,13 +19,15 @@ #define UDP_DATAGRAMSIZE 8192 -typedef struct t_udp_ { - t_socket sock; - t_timeout tm; - int family; +typedef struct t_udp_ +{ + t_socket sock; + t_timeout tm; + int family; } t_udp; -typedef t_udp *p_udp; -int udp_open(lua_State *L); +typedef t_udp* p_udp; + +int udp_open(lua_State* L); #endif /* UDP_H */ diff --git a/Lua/usocket.c b/Lua/usocket.c index cc4dd23..3239f85 100644 --- a/Lua/usocket.c +++ b/Lua/usocket.c @@ -451,4 +451,4 @@ const char *socket_gaistrerror(int err) { } } -#endif \ No newline at end of file +#endif diff --git a/Lua/usocket.h b/Lua/usocket.h index 45f2f99..1595c02 100644 --- a/Lua/usocket.h +++ b/Lua/usocket.h @@ -51,7 +51,7 @@ #endif /* !IPV6_DROP_MEMBERSHIP */ typedef int t_socket; -typedef t_socket *p_socket; +typedef t_socket* p_socket; typedef struct sockaddr_storage t_sockaddr_storage; #define SOCKET_INVALID (-1) diff --git a/Lua/wsocket.c b/Lua/wsocket.c index 1a985dc..bd58105 100644 --- a/Lua/wsocket.c +++ b/Lua/wsocket.c @@ -13,30 +13,33 @@ #include "pierror.h" /* WinSock doesn't have a strerror... */ -static const char *wstrerror(int err); +static const char* wstrerror(int err); /*-------------------------------------------------------------------------*\ * Initializes module \*-------------------------------------------------------------------------*/ -int socket_open(void) { - WSADATA wsaData; - WORD wVersionRequested = MAKEWORD(2, 0); - int err = WSAStartup(wVersionRequested, &wsaData ); - if (err != 0) return 0; - if ((LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) && - (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)) { - WSACleanup(); - return 0; - } - return 1; +int socket_open(void) +{ + WSADATA wsaData; + WORD wVersionRequested = MAKEWORD(2, 0); + int err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) return 0; + if ((LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) && + (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)) + { + WSACleanup(); + return 0; + } + return 1; } /*-------------------------------------------------------------------------*\ * Close module \*-------------------------------------------------------------------------*/ -int socket_close(void) { - WSACleanup(); - return 1; +int socket_close(void) +{ + WSACleanup(); + return 1; } /*-------------------------------------------------------------------------*\ @@ -47,143 +50,169 @@ int socket_close(void) { #define WAITFD_E 4 #define WAITFD_C (WAITFD_E|WAITFD_W) -int socket_waitfd(p_socket ps, int sw, p_timeout tm) { - int ret; - fd_set rfds, wfds, efds, *rp = NULL, *wp = NULL, *ep = NULL; - struct timeval tv, *tp = NULL; - double t; - if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ - if (sw & WAITFD_R) { - FD_ZERO(&rfds); - FD_SET(*ps, &rfds); - rp = &rfds; - } - if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; } - if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(*ps, &efds); ep = &efds; } - if ((t = timeout_get(tm)) >= 0.0) { - tv.tv_sec = (int) t; - tv.tv_usec = (int) ((t-tv.tv_sec)*1.0e6); - tp = &tv; - } - ret = select(0, rp, wp, ep, tp); - if (ret == -1) return WSAGetLastError(); - if (ret == 0) return IO_TIMEOUT; - if (sw == WAITFD_C && FD_ISSET(*ps, &efds)) return IO_CLOSED; - return IO_DONE; +int socket_waitfd(p_socket ps, int sw, p_timeout tm) +{ + int ret; + fd_set rfds, wfds, efds, *rp = NULL, *wp = NULL, *ep = NULL; + struct timeval tv, *tp = NULL; + double t; + if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ + if (sw & WAITFD_R) + { + FD_ZERO(&rfds); + FD_SET(*ps, &rfds); + rp = &rfds; + } + if (sw & WAITFD_W) + { + FD_ZERO(&wfds); + FD_SET(*ps, &wfds); + wp = &wfds; + } + if (sw & WAITFD_C) + { + FD_ZERO(&efds); + FD_SET(*ps, &efds); + ep = &efds; + } + if ((t = timeout_get(tm)) >= 0.0) + { + tv.tv_sec = (int)t; + tv.tv_usec = (int)((t - tv.tv_sec) * 1.0e6); + tp = &tv; + } + ret = select(0, rp, wp, ep, tp); + if (ret == -1) return WSAGetLastError(); + if (ret == 0) return IO_TIMEOUT; + if (sw == WAITFD_C && FD_ISSET(*ps, &efds)) return IO_CLOSED; + return IO_DONE; } /*-------------------------------------------------------------------------*\ * Select with int timeout in ms \*-------------------------------------------------------------------------*/ -int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, - p_timeout tm) { - struct timeval tv; - double t = timeout_get(tm); - tv.tv_sec = (int) t; - tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6); - if (n <= 0) { - Sleep((DWORD) (1000*t)); - return 0; - } else return select(0, rfds, wfds, efds, t >= 0.0? &tv: NULL); +int socket_select(t_socket n, fd_set* rfds, fd_set* wfds, fd_set* efds, + p_timeout tm) +{ + struct timeval tv; + double t = timeout_get(tm); + tv.tv_sec = (int)t; + tv.tv_usec = (int)((t - tv.tv_sec) * 1.0e6); + if (n <= 0) + { + Sleep((DWORD)(1000 * t)); + return 0; + } + else return select(0, rfds, wfds, efds, t >= 0.0 ? &tv : NULL); } /*-------------------------------------------------------------------------*\ * Close and inutilize socket \*-------------------------------------------------------------------------*/ -void socket_destroy(p_socket ps) { - if (*ps != SOCKET_INVALID) { - socket_setblocking(ps); /* close can take a long time on WIN32 */ - closesocket(*ps); - *ps = SOCKET_INVALID; - } +void socket_destroy(p_socket ps) +{ + if (*ps != SOCKET_INVALID) + { + socket_setblocking(ps); /* close can take a long time on WIN32 */ + closesocket(*ps); + *ps = SOCKET_INVALID; + } } /*-------------------------------------------------------------------------*\ * \*-------------------------------------------------------------------------*/ -void socket_shutdown(p_socket ps, int how) { - socket_setblocking(ps); - shutdown(*ps, how); - socket_setnonblocking(ps); +void socket_shutdown(p_socket ps, int how) +{ + socket_setblocking(ps); + shutdown(*ps, how); + socket_setnonblocking(ps); } /*-------------------------------------------------------------------------*\ * Creates and sets up a socket \*-------------------------------------------------------------------------*/ -int socket_create(p_socket ps, int domain, int type, int protocol) { - *ps = socket(domain, type, protocol); - if (*ps != SOCKET_INVALID) return IO_DONE; - else return WSAGetLastError(); +int socket_create(p_socket ps, int domain, int type, int protocol) +{ + *ps = socket(domain, type, protocol); + if (*ps != SOCKET_INVALID) return IO_DONE; + else return WSAGetLastError(); } /*-------------------------------------------------------------------------*\ * Connects or returns error message \*-------------------------------------------------------------------------*/ -int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) { - int err; - /* don't call on closed socket */ - if (*ps == SOCKET_INVALID) return IO_CLOSED; - /* ask system to connect */ - if (connect(*ps, addr, len) == 0) return IO_DONE; - /* make sure the system is trying to connect */ - err = WSAGetLastError(); - if (err != WSAEWOULDBLOCK && err != WSAEINPROGRESS) return err; - /* zero timeout case optimization */ - if (timeout_iszero(tm)) return IO_TIMEOUT; - /* we wait until something happens */ - err = socket_waitfd(ps, WAITFD_C, tm); - if (err == IO_CLOSED) { - int elen = sizeof(err); - /* give windows time to set the error (yes, disgusting) */ - Sleep(10); - /* find out why we failed */ - getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &elen); - /* we KNOW there was an error. if 'why' is 0, we will return - * "unknown error", but it's not really our fault */ - return err > 0? err: IO_UNKNOWN; - } else return err; - +int socket_connect(p_socket ps, SA* addr, socklen_t len, p_timeout tm) +{ + int err; + /* don't call on closed socket */ + if (*ps == SOCKET_INVALID) return IO_CLOSED; + /* ask system to connect */ + if (connect(*ps, addr, len) == 0) return IO_DONE; + /* make sure the system is trying to connect */ + err = WSAGetLastError(); + if (err != WSAEWOULDBLOCK && err != WSAEINPROGRESS) return err; + /* zero timeout case optimization */ + if (timeout_iszero(tm)) return IO_TIMEOUT; + /* we wait until something happens */ + err = socket_waitfd(ps, WAITFD_C, tm); + if (err == IO_CLOSED) + { + int elen = sizeof(err); + /* give windows time to set the error (yes, disgusting) */ + Sleep(10); + /* find out why we failed */ + getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char*)&err, &elen); + /* we KNOW there was an error. if 'why' is 0, we will return + * "unknown error", but it's not really our fault */ + return err > 0 ? err : IO_UNKNOWN; + } + else return err; } /*-------------------------------------------------------------------------*\ * Binds or returns error message \*-------------------------------------------------------------------------*/ -int socket_bind(p_socket ps, SA *addr, socklen_t len) { - int err = IO_DONE; - socket_setblocking(ps); - if (bind(*ps, addr, len) < 0) err = WSAGetLastError(); - socket_setnonblocking(ps); - return err; +int socket_bind(p_socket ps, SA* addr, socklen_t len) +{ + int err = IO_DONE; + socket_setblocking(ps); + if (bind(*ps, addr, len) < 0) err = WSAGetLastError(); + socket_setnonblocking(ps); + return err; } /*-------------------------------------------------------------------------*\ * \*-------------------------------------------------------------------------*/ -int socket_listen(p_socket ps, int backlog) { - int err = IO_DONE; - socket_setblocking(ps); - if (listen(*ps, backlog) < 0) err = WSAGetLastError(); - socket_setnonblocking(ps); - return err; +int socket_listen(p_socket ps, int backlog) +{ + int err = IO_DONE; + socket_setblocking(ps); + if (listen(*ps, backlog) < 0) err = WSAGetLastError(); + socket_setnonblocking(ps); + return err; } /*-------------------------------------------------------------------------*\ * Accept with timeout \*-------------------------------------------------------------------------*/ -int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, - p_timeout tm) { - if (*ps == SOCKET_INVALID) return IO_CLOSED; - for ( ;; ) { - int err; - /* try to get client socket */ - if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE; - /* find out why we failed */ - err = WSAGetLastError(); - /* if we failed because there was no connectoin, keep trying */ - if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err; - /* call select to avoid busy wait */ - if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; - } +int socket_accept(p_socket ps, p_socket pa, SA* addr, socklen_t* len, + p_timeout tm) +{ + if (*ps == SOCKET_INVALID) return IO_CLOSED; + for (;;) + { + int err; + /* try to get client socket */ + if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE; + /* find out why we failed */ + err = WSAGetLastError(); + /* if we failed because there was no connectoin, keep trying */ + if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err; + /* call select to avoid busy wait */ + if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; + } } /*-------------------------------------------------------------------------*\ @@ -192,245 +221,268 @@ int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, * this can take an awful lot of time and we will end up blocked. * Therefore, whoever calls this function should not pass a huge buffer. \*-------------------------------------------------------------------------*/ -int socket_send(p_socket ps, const char *data, size_t count, - size_t *sent, p_timeout tm) +int socket_send(p_socket ps, const char* data, size_t count, + size_t* sent, p_timeout tm) { - int err; - *sent = 0; - /* avoid making system calls on closed sockets */ - if (*ps == SOCKET_INVALID) return IO_CLOSED; - /* loop until we send something or we give up on error */ - for ( ;; ) { - /* try to send something */ - int put = send(*ps, data, (int) count, 0); - /* if we sent something, we are done */ - if (put > 0) { - *sent = put; - return IO_DONE; - } - /* deal with failure */ - err = WSAGetLastError(); - /* we can only proceed if there was no serious error */ - if (err != WSAEWOULDBLOCK) return err; - /* avoid busy wait */ - if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; - } + int err; + *sent = 0; + /* avoid making system calls on closed sockets */ + if (*ps == SOCKET_INVALID) return IO_CLOSED; + /* loop until we send something or we give up on error */ + for (;;) + { + /* try to send something */ + int put = send(*ps, data, (int)count, 0); + /* if we sent something, we are done */ + if (put > 0) + { + *sent = put; + return IO_DONE; + } + /* deal with failure */ + err = WSAGetLastError(); + /* we can only proceed if there was no serious error */ + if (err != WSAEWOULDBLOCK) return err; + /* avoid busy wait */ + if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; + } } /*-------------------------------------------------------------------------*\ * Sendto with timeout \*-------------------------------------------------------------------------*/ -int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, - SA *addr, socklen_t len, p_timeout tm) +int socket_sendto(p_socket ps, const char* data, size_t count, size_t* sent, + SA* addr, socklen_t len, p_timeout tm) { - int err; - *sent = 0; - if (*ps == SOCKET_INVALID) return IO_CLOSED; - for ( ;; ) { - int put = sendto(*ps, data, (int) count, 0, addr, len); - if (put > 0) { - *sent = put; - return IO_DONE; - } - err = WSAGetLastError(); - if (err != WSAEWOULDBLOCK) return err; - if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; - } + int err; + *sent = 0; + if (*ps == SOCKET_INVALID) return IO_CLOSED; + for (;;) + { + int put = sendto(*ps, data, (int)count, 0, addr, len); + if (put > 0) + { + *sent = put; + return IO_DONE; + } + err = WSAGetLastError(); + if (err != WSAEWOULDBLOCK) return err; + if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; + } } /*-------------------------------------------------------------------------*\ * Receive with timeout \*-------------------------------------------------------------------------*/ -int socket_recv(p_socket ps, char *data, size_t count, size_t *got, - p_timeout tm) +int socket_recv(p_socket ps, char* data, size_t count, size_t* got, + p_timeout tm) { - int err, prev = IO_DONE; - *got = 0; - if (*ps == SOCKET_INVALID) return IO_CLOSED; - for ( ;; ) { - int taken = recv(*ps, data, (int) count, 0); - if (taken > 0) { - *got = taken; - return IO_DONE; - } - if (taken == 0) return IO_CLOSED; - err = WSAGetLastError(); - /* On UDP, a connreset simply means the previous send failed. - * So we try again. - * On TCP, it means our socket is now useless, so the error passes. - * (We will loop again, exiting because the same error will happen) */ - if (err != WSAEWOULDBLOCK) { - if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; - prev = err; - } - if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; - } + int err, prev = IO_DONE; + *got = 0; + if (*ps == SOCKET_INVALID) return IO_CLOSED; + for (;;) + { + int taken = recv(*ps, data, (int)count, 0); + if (taken > 0) + { + *got = taken; + return IO_DONE; + } + if (taken == 0) return IO_CLOSED; + err = WSAGetLastError(); + /* On UDP, a connreset simply means the previous send failed. + * So we try again. + * On TCP, it means our socket is now useless, so the error passes. + * (We will loop again, exiting because the same error will happen) */ + if (err != WSAEWOULDBLOCK) + { + if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; + prev = err; + } + if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; + } } /*-------------------------------------------------------------------------*\ * Recvfrom with timeout \*-------------------------------------------------------------------------*/ -int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, - SA *addr, socklen_t *len, p_timeout tm) +int socket_recvfrom(p_socket ps, char* data, size_t count, size_t* got, + SA* addr, socklen_t* len, p_timeout tm) { - int err, prev = IO_DONE; - *got = 0; - if (*ps == SOCKET_INVALID) return IO_CLOSED; - for ( ;; ) { - int taken = recvfrom(*ps, data, (int) count, 0, addr, len); - if (taken > 0) { - *got = taken; - return IO_DONE; - } - if (taken == 0) return IO_CLOSED; - err = WSAGetLastError(); - /* On UDP, a connreset simply means the previous send failed. - * So we try again. - * On TCP, it means our socket is now useless, so the error passes. - * (We will loop again, exiting because the same error will happen) */ - if (err != WSAEWOULDBLOCK) { - if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; - prev = err; - } - if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; - } + int err, prev = IO_DONE; + *got = 0; + if (*ps == SOCKET_INVALID) return IO_CLOSED; + for (;;) + { + int taken = recvfrom(*ps, data, (int)count, 0, addr, len); + if (taken > 0) + { + *got = taken; + return IO_DONE; + } + if (taken == 0) return IO_CLOSED; + err = WSAGetLastError(); + /* On UDP, a connreset simply means the previous send failed. + * So we try again. + * On TCP, it means our socket is now useless, so the error passes. + * (We will loop again, exiting because the same error will happen) */ + if (err != WSAEWOULDBLOCK) + { + if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; + prev = err; + } + if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; + } } /*-------------------------------------------------------------------------*\ * Put socket into blocking mode \*-------------------------------------------------------------------------*/ -void socket_setblocking(p_socket ps) { - u_long argp = 0; - ioctlsocket(*ps, FIONBIO, &argp); +void socket_setblocking(p_socket ps) +{ + u_long argp = 0; + ioctlsocket(*ps, FIONBIO, &argp); } /*-------------------------------------------------------------------------*\ * Put socket into non-blocking mode \*-------------------------------------------------------------------------*/ -void socket_setnonblocking(p_socket ps) { - u_long argp = 1; - ioctlsocket(*ps, FIONBIO, &argp); +void socket_setnonblocking(p_socket ps) +{ + u_long argp = 1; + ioctlsocket(*ps, FIONBIO, &argp); } /*-------------------------------------------------------------------------*\ * DNS helpers \*-------------------------------------------------------------------------*/ -int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { - *hp = gethostbyaddr(addr, len, AF_INET); - if (*hp) return IO_DONE; - else return WSAGetLastError(); +int socket_gethostbyaddr(const char* addr, socklen_t len, struct hostent** hp) +{ + *hp = gethostbyaddr(addr, len, AF_INET); + if (*hp) return IO_DONE; + else return WSAGetLastError(); } -int socket_gethostbyname(const char *addr, struct hostent **hp) { - *hp = gethostbyname(addr); - if (*hp) return IO_DONE; - else return WSAGetLastError(); +int socket_gethostbyname(const char* addr, struct hostent** hp) +{ + *hp = gethostbyname(addr); + if (*hp) return IO_DONE; + else return WSAGetLastError(); } /*-------------------------------------------------------------------------*\ * Error translation functions \*-------------------------------------------------------------------------*/ -const char *socket_hoststrerror(int err) { - if (err <= 0) return io_strerror(err); - switch (err) { - case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; - default: return wstrerror(err); - } +const char* socket_hoststrerror(int err) +{ + if (err <= 0) return io_strerror(err); + switch (err) + { + case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; + default: return wstrerror(err); + } } -const char *socket_strerror(int err) { - if (err <= 0) return io_strerror(err); - switch (err) { - case WSAEADDRINUSE: return PIE_ADDRINUSE; - case WSAECONNREFUSED : return PIE_CONNREFUSED; - case WSAEISCONN: return PIE_ISCONN; - case WSAEACCES: return PIE_ACCESS; - case WSAECONNABORTED: return PIE_CONNABORTED; - case WSAECONNRESET: return PIE_CONNRESET; - case WSAETIMEDOUT: return PIE_TIMEDOUT; - default: return wstrerror(err); - } +const char* socket_strerror(int err) +{ + if (err <= 0) return io_strerror(err); + switch (err) + { + case WSAEADDRINUSE: return PIE_ADDRINUSE; + case WSAECONNREFUSED: return PIE_CONNREFUSED; + case WSAEISCONN: return PIE_ISCONN; + case WSAEACCES: return PIE_ACCESS; + case WSAECONNABORTED: return PIE_CONNABORTED; + case WSAECONNRESET: return PIE_CONNRESET; + case WSAETIMEDOUT: return PIE_TIMEDOUT; + default: return wstrerror(err); + } } -const char *socket_ioerror(p_socket ps, int err) { - (void) ps; - return socket_strerror(err); +const char* socket_ioerror(p_socket ps, int err) +{ + (void)ps; + return socket_strerror(err); } -static const char *wstrerror(int err) { - switch (err) { - case WSAEINTR: return "Interrupted function call"; - case WSAEACCES: return PIE_ACCESS; // "Permission denied"; - case WSAEFAULT: return "Bad address"; - case WSAEINVAL: return "Invalid argument"; - case WSAEMFILE: return "Too many open files"; - case WSAEWOULDBLOCK: return "Resource temporarily unavailable"; - case WSAEINPROGRESS: return "Operation now in progress"; - case WSAEALREADY: return "Operation already in progress"; - case WSAENOTSOCK: return "Socket operation on nonsocket"; - case WSAEDESTADDRREQ: return "Destination address required"; - case WSAEMSGSIZE: return "Message too long"; - case WSAEPROTOTYPE: return "Protocol wrong type for socket"; - case WSAENOPROTOOPT: return "Bad protocol option"; - case WSAEPROTONOSUPPORT: return "Protocol not supported"; - case WSAESOCKTNOSUPPORT: return PIE_SOCKTYPE; // "Socket type not supported"; - case WSAEOPNOTSUPP: return "Operation not supported"; - case WSAEPFNOSUPPORT: return "Protocol family not supported"; - case WSAEAFNOSUPPORT: return PIE_FAMILY; // "Address family not supported by protocol family"; - case WSAEADDRINUSE: return PIE_ADDRINUSE; // "Address already in use"; - case WSAEADDRNOTAVAIL: return "Cannot assign requested address"; - case WSAENETDOWN: return "Network is down"; - case WSAENETUNREACH: return "Network is unreachable"; - case WSAENETRESET: return "Network dropped connection on reset"; - case WSAECONNABORTED: return "Software caused connection abort"; - case WSAECONNRESET: return PIE_CONNRESET; // "Connection reset by peer"; - case WSAENOBUFS: return "No buffer space available"; - case WSAEISCONN: return PIE_ISCONN; // "Socket is already connected"; - case WSAENOTCONN: return "Socket is not connected"; - case WSAESHUTDOWN: return "Cannot send after socket shutdown"; - case WSAETIMEDOUT: return PIE_TIMEDOUT; // "Connection timed out"; - case WSAECONNREFUSED: return PIE_CONNREFUSED; // "Connection refused"; - case WSAEHOSTDOWN: return "Host is down"; - case WSAEHOSTUNREACH: return "No route to host"; - case WSAEPROCLIM: return "Too many processes"; - case WSASYSNOTREADY: return "Network subsystem is unavailable"; - case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range"; - case WSANOTINITIALISED: - return "Successful WSAStartup not yet performed"; - case WSAEDISCON: return "Graceful shutdown in progress"; - case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; // "Host not found"; - case WSATRY_AGAIN: return "Nonauthoritative host not found"; - case WSANO_RECOVERY: return PIE_FAIL; // "Nonrecoverable name lookup error"; - case WSANO_DATA: return "Valid name, no data record of requested type"; - default: return "Unknown error"; - } +static const char* wstrerror(int err) +{ + switch (err) + { + case WSAEINTR: return "Interrupted function call"; + case WSAEACCES: return PIE_ACCESS; // "Permission denied"; + case WSAEFAULT: return "Bad address"; + case WSAEINVAL: return "Invalid argument"; + case WSAEMFILE: return "Too many open files"; + case WSAEWOULDBLOCK: return "Resource temporarily unavailable"; + case WSAEINPROGRESS: return "Operation now in progress"; + case WSAEALREADY: return "Operation already in progress"; + case WSAENOTSOCK: return "Socket operation on nonsocket"; + case WSAEDESTADDRREQ: return "Destination address required"; + case WSAEMSGSIZE: return "Message too long"; + case WSAEPROTOTYPE: return "Protocol wrong type for socket"; + case WSAENOPROTOOPT: return "Bad protocol option"; + case WSAEPROTONOSUPPORT: return "Protocol not supported"; + case WSAESOCKTNOSUPPORT: return PIE_SOCKTYPE; // "Socket type not supported"; + case WSAEOPNOTSUPP: return "Operation not supported"; + case WSAEPFNOSUPPORT: return "Protocol family not supported"; + case WSAEAFNOSUPPORT: return PIE_FAMILY; // "Address family not supported by protocol family"; + case WSAEADDRINUSE: return PIE_ADDRINUSE; // "Address already in use"; + case WSAEADDRNOTAVAIL: return "Cannot assign requested address"; + case WSAENETDOWN: return "Network is down"; + case WSAENETUNREACH: return "Network is unreachable"; + case WSAENETRESET: return "Network dropped connection on reset"; + case WSAECONNABORTED: return "Software caused connection abort"; + case WSAECONNRESET: return PIE_CONNRESET; // "Connection reset by peer"; + case WSAENOBUFS: return "No buffer space available"; + case WSAEISCONN: return PIE_ISCONN; // "Socket is already connected"; + case WSAENOTCONN: return "Socket is not connected"; + case WSAESHUTDOWN: return "Cannot send after socket shutdown"; + case WSAETIMEDOUT: return PIE_TIMEDOUT; // "Connection timed out"; + case WSAECONNREFUSED: return PIE_CONNREFUSED; // "Connection refused"; + case WSAEHOSTDOWN: return "Host is down"; + case WSAEHOSTUNREACH: return "No route to host"; + case WSAEPROCLIM: return "Too many processes"; + case WSASYSNOTREADY: return "Network subsystem is unavailable"; + case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range"; + case WSANOTINITIALISED: + return "Successful WSAStartup not yet performed"; + case WSAEDISCON: return "Graceful shutdown in progress"; + case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; // "Host not found"; + case WSATRY_AGAIN: return "Nonauthoritative host not found"; + case WSANO_RECOVERY: return PIE_FAIL; // "Nonrecoverable name lookup error"; + case WSANO_DATA: return "Valid name, no data record of requested type"; + default: return "Unknown error"; + } } -const char *socket_gaistrerror(int err) { - if (err == 0) return NULL; - switch (err) { - case EAI_AGAIN: return PIE_AGAIN; - case EAI_BADFLAGS: return PIE_BADFLAGS; +const char* socket_gaistrerror(int err) +{ + if (err == 0) return NULL; + switch (err) + { + case EAI_AGAIN: return PIE_AGAIN; + case EAI_BADFLAGS: return PIE_BADFLAGS; #ifdef EAI_BADHINTS case EAI_BADHINTS: return PIE_BADHINTS; #endif - case EAI_FAIL: return PIE_FAIL; - case EAI_FAMILY: return PIE_FAMILY; - case EAI_MEMORY: return PIE_MEMORY; - case EAI_NONAME: return PIE_NONAME; + case EAI_FAIL: return PIE_FAIL; + case EAI_FAMILY: return PIE_FAMILY; + case EAI_MEMORY: return PIE_MEMORY; + case EAI_NONAME: return PIE_NONAME; #ifdef EAI_OVERFLOW case EAI_OVERFLOW: return PIE_OVERFLOW; #endif #ifdef EAI_PROTOCOL case EAI_PROTOCOL: return PIE_PROTOCOL; #endif - case EAI_SERVICE: return PIE_SERVICE; - case EAI_SOCKTYPE: return PIE_SOCKTYPE; + case EAI_SERVICE: return PIE_SERVICE; + case EAI_SOCKTYPE: return PIE_SOCKTYPE; #ifdef EAI_SYSTEM case EAI_SYSTEM: return strerror(errno); #endif - default: return gai_strerrorA(err); - } + default: return gai_strerrorA(err); + } } -#endif \ No newline at end of file +#endif diff --git a/Lua/wsocket.h b/Lua/wsocket.h index 3986640..d47323f 100644 --- a/Lua/wsocket.h +++ b/Lua/wsocket.h @@ -14,7 +14,7 @@ typedef int socklen_t; typedef SOCKADDR_STORAGE t_sockaddr_storage; typedef SOCKET t_socket; -typedef t_socket *p_socket; +typedef t_socket* p_socket; #ifndef IPV6_V6ONLY #define IPV6_V6ONLY 27