├── .gitignore ├── content ├── jump.wav ├── player.ase ├── CF_Logo_Pixel.png └── hit_effect_2.png ├── .gitmodules ├── msvc2022.cmd ├── src ├── main.lua └── main.cpp ├── lua ├── lprefix.h ├── lundump.h ├── lopnames.h ├── lzio.h ├── linit.c ├── lualib.h ├── lfunc.h ├── lzio.c ├── ljumptab.h ├── lstring.h ├── ldebug.h ├── lapi.h ├── lctype.h ├── lctype.c ├── llex.h ├── onelua.c ├── ltm.h ├── ldo.h ├── lmem.h ├── lcode.h ├── ltests.h ├── lopcodes.c ├── lvm.h ├── lcorolib.c ├── lparser.h ├── ltable.h ├── lmem.c ├── llimits.h ├── ldump.c ├── lauxlib.h ├── lutf8lib.c ├── ltm.c ├── lgc.h ├── lfunc.c ├── lstring.c ├── lundump.c ├── lstate.c ├── loslib.c └── ltablib.c ├── CMakeLists.txt └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | build_*/ 2 | .DS_Store -------------------------------------------------------------------------------- /content/jump.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RandyGaul/CF_Lua/HEAD/content/jump.wav -------------------------------------------------------------------------------- /content/player.ase: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RandyGaul/CF_Lua/HEAD/content/player.ase -------------------------------------------------------------------------------- /content/CF_Logo_Pixel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RandyGaul/CF_Lua/HEAD/content/CF_Logo_Pixel.png -------------------------------------------------------------------------------- /content/hit_effect_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RandyGaul/CF_Lua/HEAD/content/hit_effect_2.png -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "cute_framework"] 2 | path = cute_framework 3 | url = https://github.com/RandyGaul/cute_framework 4 | -------------------------------------------------------------------------------- /msvc2022.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | mkdir build_msvc_2022 > nul 2> nul 3 | cmake -G "Visual Studio 17 2022" -A x64 -Bbuild_msvc_2022 . --compile-no-warning-as-error 4 | -------------------------------------------------------------------------------- /src/main.lua: -------------------------------------------------------------------------------- 1 | function main() 2 | make_app("cute imgui image test", default_display(), 0, 0, 640, 480, APP_OPTIONS_WINDOW_POS_CENTERED_BIT | APP_OPTIONS_RESIZABLE_BIT, argv0) 3 | app_init_imgui() 4 | mount_directory_as("../content", "/") 5 | 6 | sprite = make_demo_sprite() 7 | assert(sprite) 8 | 9 | while app_is_running() do 10 | app_update() 11 | draw_sprite(sprite) 12 | 13 | draw_text("Press space", 0,200, -1) 14 | 15 | imgui_begin("Room Editor", true) 16 | imgui_button("click me") 17 | check = imgui_checkbox("yo", check) 18 | imgui_sprite_button("cf", sprite) 19 | imgui_end() 20 | 21 | app_draw_onto_screen(true) 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lua/lprefix.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lprefix.h $ 3 | ** Definitions for Lua code that must come before any other header file 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lprefix_h 8 | #define lprefix_h 9 | 10 | 11 | /* 12 | ** Allows POSIX/XSI stuff 13 | */ 14 | #if !defined(LUA_USE_C89) /* { */ 15 | 16 | #if !defined(_XOPEN_SOURCE) 17 | #define _XOPEN_SOURCE 600 18 | #elif _XOPEN_SOURCE == 0 19 | #undef _XOPEN_SOURCE /* use -D_XOPEN_SOURCE=0 to undefine it */ 20 | #endif 21 | 22 | /* 23 | ** Allows manipulation of large files in gcc and some other compilers 24 | */ 25 | #if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS) 26 | #define _LARGEFILE_SOURCE 1 27 | #define _FILE_OFFSET_BITS 64 28 | #endif 29 | 30 | #endif /* } */ 31 | 32 | 33 | /* 34 | ** Windows stuff 35 | */ 36 | #if defined(_WIN32) /* { */ 37 | 38 | #if !defined(_CRT_SECURE_NO_WARNINGS) 39 | #define _CRT_SECURE_NO_WARNINGS /* avoid warnings about ISO C functions */ 40 | #endif 41 | 42 | #endif /* } */ 43 | 44 | #endif 45 | 46 | -------------------------------------------------------------------------------- /lua/lundump.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lundump.h $ 3 | ** load precompiled Lua chunks 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lundump_h 8 | #define lundump_h 9 | 10 | #include 11 | 12 | #include "llimits.h" 13 | #include "lobject.h" 14 | #include "lzio.h" 15 | 16 | 17 | /* data to catch conversion errors */ 18 | #define LUAC_DATA "\x19\x93\r\n\x1a\n" 19 | 20 | #define LUAC_INT 0x5678 21 | #define LUAC_NUM cast_num(370.5) 22 | 23 | /* 24 | ** Encode major-minor version in one byte, one nibble for each 25 | */ 26 | #define LUAC_VERSION (LUA_VERSION_MAJOR_N*16+LUA_VERSION_MINOR_N) 27 | 28 | #define LUAC_FORMAT 0 /* this is the official format */ 29 | 30 | 31 | /* load one chunk; from lundump.c */ 32 | LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name, 33 | int fixed); 34 | 35 | /* dump one chunk; from ldump.c */ 36 | LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, 37 | void* data, int strip); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(CF_Lua) 3 | 4 | set(CMAKE_CXX_STANDARD 20) 5 | 6 | # Make sure all binaries are placed into the same build folder. 7 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) 8 | 9 | set(CUTE_FRAMEWORK_STATIC ON) 10 | set(CF_FRAMEWORK_BUILD_SAMPLES OFF) 11 | set(CF_FRAMEWORK_BUILD_TESTS OFF) 12 | 13 | add_subdirectory(cute_framework) 14 | FetchContent_Declare( 15 | box2d 16 | GIT_REPOSITORY https://github.com/erincatto/box2d 17 | GIT_TAG b864f533c3d851d5c7b55fd6fb4bac00466ff854 18 | ) 19 | FetchContent_MakeAvailable(box2d) 20 | 21 | set_target_properties(box2d PROPERTIES CMAKE_COMPILE_WARNING_AS_ERROR OFF) 22 | 23 | # Define the Lua library 24 | add_library(Lua 25 | lua/onelua.c 26 | ) 27 | 28 | # Add source for the game. 29 | add_executable( 30 | CF_Lua 31 | src/bind.h 32 | src/main.cpp 33 | ) 34 | 35 | target_include_directories(CF_Lua PUBLIC $) 36 | target_include_directories(CF_Lua PUBLIC $) 37 | target_include_directories(CF_Lua PUBLIC $) 38 | 39 | target_link_libraries(CF_Lua cute) 40 | target_link_libraries(CF_Lua Lua) 41 | target_link_libraries(CF_Lua box2d) 42 | 43 | # For convenience set MSVC debugger's working directory in the build folder. 44 | # Also ask MSVC to make CF_Lua the startup project. 45 | if (MSVC) 46 | set_property(TARGET CF_Lua PROPERTY VS_DEBUGGER_WORKING_DIRECTORY $) 47 | set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT CF_Lua) 48 | endif() 49 | -------------------------------------------------------------------------------- /lua/lopnames.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lopnames.h $ 3 | ** Opcode names 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #if !defined(lopnames_h) 8 | #define lopnames_h 9 | 10 | #include 11 | 12 | 13 | /* ORDER OP */ 14 | 15 | static const char *const opnames[] = { 16 | "MOVE", 17 | "LOADI", 18 | "LOADF", 19 | "LOADK", 20 | "LOADKX", 21 | "LOADFALSE", 22 | "LFALSESKIP", 23 | "LOADTRUE", 24 | "LOADNIL", 25 | "GETUPVAL", 26 | "SETUPVAL", 27 | "GETTABUP", 28 | "GETTABLE", 29 | "GETI", 30 | "GETFIELD", 31 | "SETTABUP", 32 | "SETTABLE", 33 | "SETI", 34 | "SETFIELD", 35 | "NEWTABLE", 36 | "SELF", 37 | "ADDI", 38 | "ADDK", 39 | "SUBK", 40 | "MULK", 41 | "MODK", 42 | "POWK", 43 | "DIVK", 44 | "IDIVK", 45 | "BANDK", 46 | "BORK", 47 | "BXORK", 48 | "SHRI", 49 | "SHLI", 50 | "ADD", 51 | "SUB", 52 | "MUL", 53 | "MOD", 54 | "POW", 55 | "DIV", 56 | "IDIV", 57 | "BAND", 58 | "BOR", 59 | "BXOR", 60 | "SHL", 61 | "SHR", 62 | "MMBIN", 63 | "MMBINI", 64 | "MMBINK", 65 | "UNM", 66 | "BNOT", 67 | "NOT", 68 | "LEN", 69 | "CONCAT", 70 | "CLOSE", 71 | "TBC", 72 | "JMP", 73 | "EQ", 74 | "LT", 75 | "LE", 76 | "EQK", 77 | "EQI", 78 | "LTI", 79 | "LEI", 80 | "GTI", 81 | "GEI", 82 | "TEST", 83 | "TESTSET", 84 | "CALL", 85 | "TAILCALL", 86 | "RETURN", 87 | "RETURN0", 88 | "RETURN1", 89 | "FORLOOP", 90 | "FORPREP", 91 | "TFORPREP", 92 | "TFORCALL", 93 | "TFORLOOP", 94 | "SETLIST", 95 | "CLOSURE", 96 | "VARARG", 97 | "VARARGPREP", 98 | "EXTRAARG", 99 | NULL 100 | }; 101 | 102 | #endif 103 | 104 | -------------------------------------------------------------------------------- /lua/lzio.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lzio.h $ 3 | ** Buffered streams 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #ifndef lzio_h 9 | #define lzio_h 10 | 11 | #include "lua.h" 12 | 13 | #include "lmem.h" 14 | 15 | 16 | #define EOZ (-1) /* end of stream */ 17 | 18 | typedef struct Zio ZIO; 19 | 20 | #define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z)) 21 | 22 | 23 | typedef struct Mbuffer { 24 | char *buffer; 25 | size_t n; 26 | size_t buffsize; 27 | } Mbuffer; 28 | 29 | #define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) 30 | 31 | #define luaZ_buffer(buff) ((buff)->buffer) 32 | #define luaZ_sizebuffer(buff) ((buff)->buffsize) 33 | #define luaZ_bufflen(buff) ((buff)->n) 34 | 35 | #define luaZ_buffremove(buff,i) ((buff)->n -= (i)) 36 | #define luaZ_resetbuffer(buff) ((buff)->n = 0) 37 | 38 | 39 | #define luaZ_resizebuffer(L, buff, size) \ 40 | ((buff)->buffer = luaM_reallocvchar(L, (buff)->buffer, \ 41 | (buff)->buffsize, size), \ 42 | (buff)->buffsize = size) 43 | 44 | #define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) 45 | 46 | 47 | LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, 48 | void *data); 49 | LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */ 50 | 51 | LUAI_FUNC const void *luaZ_getaddr (ZIO* z, size_t n); 52 | 53 | 54 | /* --------- Private Part ------------------ */ 55 | 56 | struct Zio { 57 | size_t n; /* bytes still unread */ 58 | const char *p; /* current position in buffer */ 59 | lua_Reader reader; /* reader function */ 60 | void *data; /* additional data */ 61 | lua_State *L; /* Lua state (for reader) */ 62 | }; 63 | 64 | 65 | LUAI_FUNC int luaZ_fill (ZIO *z); 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /lua/linit.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: linit.c $ 3 | ** Initialization of libraries for lua.c and other clients 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #define linit_c 9 | #define LUA_LIB 10 | 11 | 12 | #include "lprefix.h" 13 | 14 | 15 | #include 16 | 17 | #include "lua.h" 18 | 19 | #include "lualib.h" 20 | #include "lauxlib.h" 21 | #include "llimits.h" 22 | 23 | 24 | /* 25 | ** Standard Libraries. (Must be listed in the same ORDER of their 26 | ** respective constants LUA_K.) 27 | */ 28 | static const luaL_Reg stdlibs[] = { 29 | {LUA_GNAME, luaopen_base}, 30 | {LUA_LOADLIBNAME, luaopen_package}, 31 | {LUA_COLIBNAME, luaopen_coroutine}, 32 | {LUA_DBLIBNAME, luaopen_debug}, 33 | {LUA_IOLIBNAME, luaopen_io}, 34 | {LUA_MATHLIBNAME, luaopen_math}, 35 | {LUA_OSLIBNAME, luaopen_os}, 36 | {LUA_STRLIBNAME, luaopen_string}, 37 | {LUA_TABLIBNAME, luaopen_table}, 38 | {LUA_UTF8LIBNAME, luaopen_utf8}, 39 | {NULL, NULL} 40 | }; 41 | 42 | 43 | /* 44 | ** require and preload selected standard libraries 45 | */ 46 | LUALIB_API void luaL_openselectedlibs (lua_State *L, int load, int preload) { 47 | int mask; 48 | const luaL_Reg *lib; 49 | luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); 50 | for (lib = stdlibs, mask = 1; lib->name != NULL; lib++, mask <<= 1) { 51 | if (load & mask) { /* selected? */ 52 | luaL_requiref(L, lib->name, lib->func, 1); /* require library */ 53 | lua_pop(L, 1); /* remove result from the stack */ 54 | } 55 | else if (preload & mask) { /* selected? */ 56 | lua_pushcfunction(L, lib->func); 57 | lua_setfield(L, -2, lib->name); /* add library to PRELOAD table */ 58 | } 59 | } 60 | lua_assert((mask >> 1) == LUA_UTF8LIBK); 61 | lua_pop(L, 1); /* remove PRELOAD table */ 62 | } 63 | 64 | -------------------------------------------------------------------------------- /lua/lualib.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lualib.h $ 3 | ** Lua standard libraries 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #ifndef lualib_h 9 | #define lualib_h 10 | 11 | #include "lua.h" 12 | 13 | 14 | /* version suffix for environment variable names */ 15 | #define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR 16 | 17 | #define LUA_GLIBK 1 18 | LUAMOD_API int (luaopen_base) (lua_State *L); 19 | 20 | #define LUA_LOADLIBNAME "package" 21 | #define LUA_LOADLIBK (LUA_GLIBK << 1) 22 | LUAMOD_API int (luaopen_package) (lua_State *L); 23 | 24 | 25 | #define LUA_COLIBNAME "coroutine" 26 | #define LUA_COLIBK (LUA_LOADLIBK << 1) 27 | LUAMOD_API int (luaopen_coroutine) (lua_State *L); 28 | 29 | #define LUA_DBLIBNAME "debug" 30 | #define LUA_DBLIBK (LUA_COLIBK << 1) 31 | LUAMOD_API int (luaopen_debug) (lua_State *L); 32 | 33 | #define LUA_IOLIBNAME "io" 34 | #define LUA_IOLIBK (LUA_DBLIBK << 1) 35 | LUAMOD_API int (luaopen_io) (lua_State *L); 36 | 37 | #define LUA_MATHLIBNAME "math" 38 | #define LUA_MATHLIBK (LUA_IOLIBK << 1) 39 | LUAMOD_API int (luaopen_math) (lua_State *L); 40 | 41 | #define LUA_OSLIBNAME "os" 42 | #define LUA_OSLIBK (LUA_MATHLIBK << 1) 43 | LUAMOD_API int (luaopen_os) (lua_State *L); 44 | 45 | #define LUA_STRLIBNAME "string" 46 | #define LUA_STRLIBK (LUA_OSLIBK << 1) 47 | LUAMOD_API int (luaopen_string) (lua_State *L); 48 | 49 | #define LUA_TABLIBNAME "table" 50 | #define LUA_TABLIBK (LUA_STRLIBK << 1) 51 | LUAMOD_API int (luaopen_table) (lua_State *L); 52 | 53 | #define LUA_UTF8LIBNAME "utf8" 54 | #define LUA_UTF8LIBK (LUA_TABLIBK << 1) 55 | LUAMOD_API int (luaopen_utf8) (lua_State *L); 56 | 57 | 58 | /* open selected libraries */ 59 | LUALIB_API void (luaL_openselectedlibs) (lua_State *L, int load, int preload); 60 | 61 | /* open all libraries */ 62 | #define luaL_openlibs(L) luaL_openselectedlibs(L, ~0, 0) 63 | 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /lua/lfunc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lfunc.h $ 3 | ** Auxiliary functions to manipulate prototypes and closures 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lfunc_h 8 | #define lfunc_h 9 | 10 | 11 | #include "lobject.h" 12 | 13 | 14 | #define sizeCclosure(n) (cast_int(offsetof(CClosure, upvalue)) + \ 15 | cast_int(sizeof(TValue)) * (n)) 16 | 17 | #define sizeLclosure(n) (cast_int(offsetof(LClosure, upvals)) + \ 18 | cast_int(sizeof(TValue *)) * (n)) 19 | 20 | 21 | /* test whether thread is in 'twups' list */ 22 | #define isintwups(L) (L->twups != L) 23 | 24 | 25 | /* 26 | ** maximum number of upvalues in a closure (both C and Lua). (Value 27 | ** must fit in a VM register.) 28 | */ 29 | #define MAXUPVAL 255 30 | 31 | 32 | #define upisopen(up) ((up)->v.p != &(up)->u.value) 33 | 34 | 35 | #define uplevel(up) check_exp(upisopen(up), cast(StkId, (up)->v.p)) 36 | 37 | 38 | /* 39 | ** maximum number of misses before giving up the cache of closures 40 | ** in prototypes 41 | */ 42 | #define MAXMISS 10 43 | 44 | 45 | 46 | /* special status to close upvalues preserving the top of the stack */ 47 | #define CLOSEKTOP (-1) 48 | 49 | 50 | LUAI_FUNC Proto *luaF_newproto (lua_State *L); 51 | LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nupvals); 52 | LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nupvals); 53 | LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); 54 | LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); 55 | LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level); 56 | LUAI_FUNC void luaF_closeupval (lua_State *L, StkId level); 57 | LUAI_FUNC StkId luaF_close (lua_State *L, StkId level, int status, int yy); 58 | LUAI_FUNC void luaF_unlinkupval (UpVal *uv); 59 | LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); 60 | LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, 61 | int pc); 62 | 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /lua/lzio.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lzio.c $ 3 | ** Buffered streams 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lzio_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "lapi.h" 18 | #include "llimits.h" 19 | #include "lmem.h" 20 | #include "lstate.h" 21 | #include "lzio.h" 22 | 23 | 24 | int luaZ_fill (ZIO *z) { 25 | size_t size; 26 | lua_State *L = z->L; 27 | const char *buff; 28 | lua_unlock(L); 29 | buff = z->reader(L, z->data, &size); 30 | lua_lock(L); 31 | if (buff == NULL || size == 0) 32 | return EOZ; 33 | z->n = size - 1; /* discount char being returned */ 34 | z->p = buff; 35 | return cast_uchar(*(z->p++)); 36 | } 37 | 38 | 39 | void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { 40 | z->L = L; 41 | z->reader = reader; 42 | z->data = data; 43 | z->n = 0; 44 | z->p = NULL; 45 | } 46 | 47 | 48 | /* --------------------------------------------------------------- read --- */ 49 | 50 | static int checkbuffer (ZIO *z) { 51 | if (z->n == 0) { /* no bytes in buffer? */ 52 | if (luaZ_fill(z) == EOZ) /* try to read more */ 53 | return 0; /* no more input */ 54 | else { 55 | z->n++; /* luaZ_fill consumed first byte; put it back */ 56 | z->p--; 57 | } 58 | } 59 | return 1; /* now buffer has something */ 60 | } 61 | 62 | 63 | size_t luaZ_read (ZIO *z, void *b, size_t n) { 64 | while (n) { 65 | size_t m; 66 | if (!checkbuffer(z)) 67 | return n; /* no more input; return number of missing bytes */ 68 | m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ 69 | memcpy(b, z->p, m); 70 | z->n -= m; 71 | z->p += m; 72 | b = (char *)b + m; 73 | n -= m; 74 | } 75 | return 0; 76 | } 77 | 78 | 79 | const void *luaZ_getaddr (ZIO* z, size_t n) { 80 | const void *res; 81 | if (!checkbuffer(z)) 82 | return NULL; /* no more input */ 83 | if (z->n < n) /* not enough bytes? */ 84 | return NULL; /* block not whole; cannot give an address */ 85 | res = z->p; /* get block address */ 86 | z->n -= n; /* consume these bytes */ 87 | z->p += n; 88 | return res; 89 | } 90 | -------------------------------------------------------------------------------- /lua/ljumptab.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ljumptab.h $ 3 | ** Jump Table for the Lua interpreter 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #undef vmdispatch 9 | #undef vmcase 10 | #undef vmbreak 11 | 12 | #define vmdispatch(x) goto *disptab[x]; 13 | 14 | #define vmcase(l) L_##l: 15 | 16 | #define vmbreak vmfetch(); vmdispatch(GET_OPCODE(i)); 17 | 18 | 19 | static const void *const disptab[NUM_OPCODES] = { 20 | 21 | #if 0 22 | ** you can update the following list with this command: 23 | ** 24 | ** sed -n '/^OP_/\!d; s/OP_/\&\&L_OP_/ ; s/,.*/,/ ; s/\/.*// ; p' lopcodes.h 25 | ** 26 | #endif 27 | 28 | &&L_OP_MOVE, 29 | &&L_OP_LOADI, 30 | &&L_OP_LOADF, 31 | &&L_OP_LOADK, 32 | &&L_OP_LOADKX, 33 | &&L_OP_LOADFALSE, 34 | &&L_OP_LFALSESKIP, 35 | &&L_OP_LOADTRUE, 36 | &&L_OP_LOADNIL, 37 | &&L_OP_GETUPVAL, 38 | &&L_OP_SETUPVAL, 39 | &&L_OP_GETTABUP, 40 | &&L_OP_GETTABLE, 41 | &&L_OP_GETI, 42 | &&L_OP_GETFIELD, 43 | &&L_OP_SETTABUP, 44 | &&L_OP_SETTABLE, 45 | &&L_OP_SETI, 46 | &&L_OP_SETFIELD, 47 | &&L_OP_NEWTABLE, 48 | &&L_OP_SELF, 49 | &&L_OP_ADDI, 50 | &&L_OP_ADDK, 51 | &&L_OP_SUBK, 52 | &&L_OP_MULK, 53 | &&L_OP_MODK, 54 | &&L_OP_POWK, 55 | &&L_OP_DIVK, 56 | &&L_OP_IDIVK, 57 | &&L_OP_BANDK, 58 | &&L_OP_BORK, 59 | &&L_OP_BXORK, 60 | &&L_OP_SHRI, 61 | &&L_OP_SHLI, 62 | &&L_OP_ADD, 63 | &&L_OP_SUB, 64 | &&L_OP_MUL, 65 | &&L_OP_MOD, 66 | &&L_OP_POW, 67 | &&L_OP_DIV, 68 | &&L_OP_IDIV, 69 | &&L_OP_BAND, 70 | &&L_OP_BOR, 71 | &&L_OP_BXOR, 72 | &&L_OP_SHL, 73 | &&L_OP_SHR, 74 | &&L_OP_MMBIN, 75 | &&L_OP_MMBINI, 76 | &&L_OP_MMBINK, 77 | &&L_OP_UNM, 78 | &&L_OP_BNOT, 79 | &&L_OP_NOT, 80 | &&L_OP_LEN, 81 | &&L_OP_CONCAT, 82 | &&L_OP_CLOSE, 83 | &&L_OP_TBC, 84 | &&L_OP_JMP, 85 | &&L_OP_EQ, 86 | &&L_OP_LT, 87 | &&L_OP_LE, 88 | &&L_OP_EQK, 89 | &&L_OP_EQI, 90 | &&L_OP_LTI, 91 | &&L_OP_LEI, 92 | &&L_OP_GTI, 93 | &&L_OP_GEI, 94 | &&L_OP_TEST, 95 | &&L_OP_TESTSET, 96 | &&L_OP_CALL, 97 | &&L_OP_TAILCALL, 98 | &&L_OP_RETURN, 99 | &&L_OP_RETURN0, 100 | &&L_OP_RETURN1, 101 | &&L_OP_FORLOOP, 102 | &&L_OP_FORPREP, 103 | &&L_OP_TFORPREP, 104 | &&L_OP_TFORCALL, 105 | &&L_OP_TFORLOOP, 106 | &&L_OP_SETLIST, 107 | &&L_OP_CLOSURE, 108 | &&L_OP_VARARG, 109 | &&L_OP_VARARGPREP, 110 | &&L_OP_EXTRAARG 111 | 112 | }; 113 | -------------------------------------------------------------------------------- /lua/lstring.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lstring.h $ 3 | ** String table (keep all strings handled by Lua) 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lstring_h 8 | #define lstring_h 9 | 10 | #include "lgc.h" 11 | #include "lobject.h" 12 | #include "lstate.h" 13 | 14 | 15 | /* 16 | ** Memory-allocation error message must be preallocated (it cannot 17 | ** be created after memory is exhausted) 18 | */ 19 | #define MEMERRMSG "not enough memory" 20 | 21 | 22 | /* 23 | ** Maximum length for short strings, that is, strings that are 24 | ** internalized. (Cannot be smaller than reserved words or tags for 25 | ** metamethods, as these strings must be internalized; 26 | ** #("function") = 8, #("__newindex") = 10.) 27 | */ 28 | #if !defined(LUAI_MAXSHORTLEN) 29 | #define LUAI_MAXSHORTLEN 40 30 | #endif 31 | 32 | 33 | /* 34 | ** Size of a short TString: Size of the header plus space for the string 35 | ** itself (including final '\0'). 36 | */ 37 | #define sizestrshr(l) \ 38 | (offsetof(TString, contents) + ((l) + 1) * sizeof(char)) 39 | 40 | 41 | #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ 42 | (sizeof(s)/sizeof(char))-1)) 43 | 44 | 45 | /* 46 | ** test whether a string is a reserved word 47 | */ 48 | #define isreserved(s) ((s)->tt == LUA_VSHRSTR && (s)->extra > 0) 49 | 50 | 51 | /* 52 | ** equality for short strings, which are always internalized 53 | */ 54 | #define eqshrstr(a,b) check_exp((a)->tt == LUA_VSHRSTR, (a) == (b)) 55 | 56 | 57 | LUAI_FUNC unsigned luaS_hash (const char *str, size_t l, unsigned seed); 58 | LUAI_FUNC unsigned luaS_hashlongstr (TString *ts); 59 | LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); 60 | LUAI_FUNC void luaS_resize (lua_State *L, int newsize); 61 | LUAI_FUNC void luaS_clearcache (global_State *g); 62 | LUAI_FUNC void luaS_init (lua_State *L); 63 | LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); 64 | LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue); 65 | LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); 66 | LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); 67 | LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l); 68 | LUAI_FUNC TString *luaS_newextlstr (lua_State *L, 69 | const char *s, size_t len, lua_Alloc falloc, void *ud); 70 | LUAI_FUNC size_t luaS_sizelngstr (size_t len, int kind); 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /lua/ldebug.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ldebug.h $ 3 | ** Auxiliary functions from Debug Interface module 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ldebug_h 8 | #define ldebug_h 9 | 10 | 11 | #include "lstate.h" 12 | 13 | 14 | #define pcRel(pc, p) (cast_int((pc) - (p)->code) - 1) 15 | 16 | 17 | /* Active Lua function (given call info) */ 18 | #define ci_func(ci) (clLvalue(s2v((ci)->func.p))) 19 | 20 | 21 | #define resethookcount(L) (L->hookcount = L->basehookcount) 22 | 23 | /* 24 | ** mark for entries in 'lineinfo' array that has absolute information in 25 | ** 'abslineinfo' array 26 | */ 27 | #define ABSLINEINFO (-0x80) 28 | 29 | 30 | /* 31 | ** MAXimum number of successive Instructions WiTHout ABSolute line 32 | ** information. (A power of two allows fast divisions.) 33 | */ 34 | #if !defined(MAXIWTHABS) 35 | #define MAXIWTHABS 128 36 | #endif 37 | 38 | 39 | LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc); 40 | LUAI_FUNC const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, 41 | StkId *pos); 42 | LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, 43 | const char *opname); 44 | LUAI_FUNC l_noret luaG_callerror (lua_State *L, const TValue *o); 45 | LUAI_FUNC l_noret luaG_forerror (lua_State *L, const TValue *o, 46 | const char *what); 47 | LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1, 48 | const TValue *p2); 49 | LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1, 50 | const TValue *p2, 51 | const char *msg); 52 | LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1, 53 | const TValue *p2); 54 | LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, 55 | const TValue *p2); 56 | LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); 57 | LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg, 58 | TString *src, int line); 59 | LUAI_FUNC l_noret luaG_errormsg (lua_State *L); 60 | LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc); 61 | LUAI_FUNC int luaG_tracecall (lua_State *L); 62 | 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /lua/lapi.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lapi.h $ 3 | ** Auxiliary functions from Lua API 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lapi_h 8 | #define lapi_h 9 | 10 | 11 | #include "llimits.h" 12 | #include "lstate.h" 13 | 14 | 15 | #if defined(LUA_USE_APICHECK) 16 | #include 17 | #define api_check(l,e,msg) assert(e) 18 | #else /* for testing */ 19 | #define api_check(l,e,msg) ((void)(l), lua_assert((e) && msg)) 20 | #endif 21 | 22 | 23 | 24 | /* Increments 'L->top.p', checking for stack overflows */ 25 | #define api_incr_top(L) \ 26 | (L->top.p++, api_check(L, L->top.p <= L->ci->top.p, "stack overflow")) 27 | 28 | 29 | /* 30 | ** macros that are executed whenever program enters the Lua core 31 | ** ('lua_lock') and leaves the core ('lua_unlock') 32 | */ 33 | #if !defined(lua_lock) 34 | #define lua_lock(L) ((void) 0) 35 | #define lua_unlock(L) ((void) 0) 36 | #endif 37 | 38 | 39 | 40 | /* 41 | ** If a call returns too many multiple returns, the callee may not have 42 | ** stack space to accommodate all results. In this case, this macro 43 | ** increases its stack space ('L->ci->top.p'). 44 | */ 45 | #define adjustresults(L,nres) \ 46 | { if ((nres) <= LUA_MULTRET && L->ci->top.p < L->top.p) \ 47 | L->ci->top.p = L->top.p; } 48 | 49 | 50 | /* Ensure the stack has at least 'n' elements */ 51 | #define api_checknelems(L,n) \ 52 | api_check(L, (n) < (L->top.p - L->ci->func.p), \ 53 | "not enough elements in the stack") 54 | 55 | 56 | /* Ensure the stack has at least 'n' elements to be popped. (Some 57 | ** functions only update a slot after checking it for popping, but that 58 | ** is only an optimization for a pop followed by a push.) 59 | */ 60 | #define api_checkpop(L,n) \ 61 | api_check(L, (n) < L->top.p - L->ci->func.p && \ 62 | L->tbclist.p < L->top.p - (n), \ 63 | "not enough free elements in the stack") 64 | 65 | 66 | /* 67 | ** To reduce the overhead of returning from C functions, the presence of 68 | ** to-be-closed variables in these functions is coded in the CallInfo's 69 | ** field 'nresults', in a way that functions with no to-be-closed variables 70 | ** with zero, one, or "all" wanted results have no overhead. Functions 71 | ** with other number of wanted results, as well as functions with 72 | ** variables to be closed, have an extra check. 73 | */ 74 | 75 | #define hastocloseCfunc(n) ((n) < LUA_MULTRET) 76 | 77 | /* Map [-1, inf) (range of 'nresults') into (-inf, -2] */ 78 | #define codeNresults(n) (-(n) - 3) 79 | #define decodeNresults(n) (-(n) - 3) 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /lua/lctype.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lctype.h $ 3 | ** 'ctype' functions for Lua 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lctype_h 8 | #define lctype_h 9 | 10 | #include "lua.h" 11 | 12 | 13 | /* 14 | ** WARNING: the functions defined here do not necessarily correspond 15 | ** to the similar functions in the standard C ctype.h. They are 16 | ** optimized for the specific needs of Lua. 17 | */ 18 | 19 | #if !defined(LUA_USE_CTYPE) 20 | 21 | #if 'A' == 65 && '0' == 48 22 | /* ASCII case: can use its own tables; faster and fixed */ 23 | #define LUA_USE_CTYPE 0 24 | #else 25 | /* must use standard C ctype */ 26 | #define LUA_USE_CTYPE 1 27 | #endif 28 | 29 | #endif 30 | 31 | 32 | #if !LUA_USE_CTYPE /* { */ 33 | 34 | #include 35 | 36 | #include "llimits.h" 37 | 38 | 39 | #define ALPHABIT 0 40 | #define DIGITBIT 1 41 | #define PRINTBIT 2 42 | #define SPACEBIT 3 43 | #define XDIGITBIT 4 44 | 45 | 46 | #define MASK(B) (1 << (B)) 47 | 48 | 49 | /* 50 | ** add 1 to char to allow index -1 (EOZ) 51 | */ 52 | #define testprop(c,p) (luai_ctype_[(c)+1] & (p)) 53 | 54 | /* 55 | ** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_' 56 | */ 57 | #define lislalpha(c) testprop(c, MASK(ALPHABIT)) 58 | #define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT))) 59 | #define lisdigit(c) testprop(c, MASK(DIGITBIT)) 60 | #define lisspace(c) testprop(c, MASK(SPACEBIT)) 61 | #define lisprint(c) testprop(c, MASK(PRINTBIT)) 62 | #define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) 63 | 64 | 65 | /* 66 | ** In ASCII, this 'ltolower' is correct for alphabetic characters and 67 | ** for '.'. That is enough for Lua needs. ('check_exp' ensures that 68 | ** the character either is an upper-case letter or is unchanged by 69 | ** the transformation, which holds for lower-case letters and '.'.) 70 | */ 71 | #define ltolower(c) \ 72 | check_exp(('A' <= (c) && (c) <= 'Z') || (c) == ((c) | ('A' ^ 'a')), \ 73 | (c) | ('A' ^ 'a')) 74 | 75 | 76 | /* one entry for each character and for -1 (EOZ) */ 77 | LUAI_DDEC(const lu_byte luai_ctype_[UCHAR_MAX + 2];) 78 | 79 | 80 | #else /* }{ */ 81 | 82 | /* 83 | ** use standard C ctypes 84 | */ 85 | 86 | #include 87 | 88 | 89 | #define lislalpha(c) (isalpha(c) || (c) == '_') 90 | #define lislalnum(c) (isalnum(c) || (c) == '_') 91 | #define lisdigit(c) (isdigit(c)) 92 | #define lisspace(c) (isspace(c)) 93 | #define lisprint(c) (isprint(c)) 94 | #define lisxdigit(c) (isxdigit(c)) 95 | 96 | #define ltolower(c) (tolower(c)) 97 | 98 | #endif /* } */ 99 | 100 | #endif 101 | 102 | -------------------------------------------------------------------------------- /lua/lctype.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lctype.c $ 3 | ** 'ctype' functions for Lua 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lctype_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include "lctype.h" 14 | 15 | #if !LUA_USE_CTYPE /* { */ 16 | 17 | #include 18 | 19 | 20 | #if defined (LUA_UCID) /* accept UniCode IDentifiers? */ 21 | /* consider all non-ascii codepoints to be alphabetic */ 22 | #define NONA 0x01 23 | #else 24 | #define NONA 0x00 /* default */ 25 | #endif 26 | 27 | 28 | LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = { 29 | 0x00, /* EOZ */ 30 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ 31 | 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 32 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ 33 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 34 | 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ 35 | 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 36 | 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ 37 | 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 38 | 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ 39 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 40 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ 41 | 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, 42 | 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ 43 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 44 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ 45 | 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, 46 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* 8. */ 47 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, 48 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* 9. */ 49 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, 50 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* a. */ 51 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, 52 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* b. */ 53 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, 54 | 0x00, 0x00, NONA, NONA, NONA, NONA, NONA, NONA, /* c. */ 55 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, 56 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* d. */ 57 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, 58 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* e. */ 59 | NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, 60 | NONA, NONA, NONA, NONA, NONA, 0x00, 0x00, 0x00, /* f. */ 61 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 62 | }; 63 | 64 | #endif /* } */ 65 | -------------------------------------------------------------------------------- /lua/llex.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: llex.h $ 3 | ** Lexical Analyzer 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef llex_h 8 | #define llex_h 9 | 10 | #include 11 | 12 | #include "lobject.h" 13 | #include "lzio.h" 14 | 15 | 16 | /* 17 | ** Single-char tokens (terminal symbols) are represented by their own 18 | ** numeric code. Other tokens start at the following value. 19 | */ 20 | #define FIRST_RESERVED (UCHAR_MAX + 1) 21 | 22 | 23 | #if !defined(LUA_ENV) 24 | #define LUA_ENV "_ENV" 25 | #endif 26 | 27 | 28 | /* 29 | * WARNING: if you change the order of this enumeration, 30 | * grep "ORDER RESERVED" 31 | */ 32 | enum RESERVED { 33 | /* terminal symbols denoted by reserved words */ 34 | TK_AND = FIRST_RESERVED, TK_BREAK, 35 | TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, 36 | TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, 37 | TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, 38 | /* other terminal symbols */ 39 | TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, 40 | TK_SHL, TK_SHR, 41 | TK_DBCOLON, TK_EOS, 42 | TK_FLT, TK_INT, TK_NAME, TK_STRING 43 | }; 44 | 45 | /* number of reserved words */ 46 | #define NUM_RESERVED (cast_int(TK_WHILE-FIRST_RESERVED + 1)) 47 | 48 | 49 | typedef union { 50 | lua_Number r; 51 | lua_Integer i; 52 | TString *ts; 53 | } SemInfo; /* semantics information */ 54 | 55 | 56 | typedef struct Token { 57 | int token; 58 | SemInfo seminfo; 59 | } Token; 60 | 61 | 62 | /* state of the lexer plus state of the parser when shared by all 63 | functions */ 64 | typedef struct LexState { 65 | int current; /* current character (charint) */ 66 | int linenumber; /* input line counter */ 67 | int lastline; /* line of last token 'consumed' */ 68 | Token t; /* current token */ 69 | Token lookahead; /* look ahead token */ 70 | struct FuncState *fs; /* current function (parser) */ 71 | struct lua_State *L; 72 | ZIO *z; /* input stream */ 73 | Mbuffer *buff; /* buffer for tokens */ 74 | Table *h; /* to avoid collection/reuse strings */ 75 | struct Dyndata *dyd; /* dynamic structures used by the parser */ 76 | TString *source; /* current source name */ 77 | TString *envn; /* environment variable name */ 78 | } LexState; 79 | 80 | 81 | LUAI_FUNC void luaX_init (lua_State *L); 82 | LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, 83 | TString *source, int firstchar); 84 | LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); 85 | LUAI_FUNC void luaX_next (LexState *ls); 86 | LUAI_FUNC int luaX_lookahead (LexState *ls); 87 | LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); 88 | LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); 89 | 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /lua/onelua.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Lua core, libraries, and interpreter in a single file. 3 | ** Compiling just this file generates a complete Lua stand-alone 4 | ** program: 5 | ** 6 | ** $ gcc -O2 -std=c99 -o lua onelua.c -lm 7 | ** 8 | ** or 9 | ** 10 | ** $ gcc -O2 -std=c89 -DLUA_USE_C89 -o lua onelua.c -lm 11 | ** 12 | */ 13 | 14 | /* default is to build the full interpreter */ 15 | #ifndef MAKE_LIB 16 | #ifndef MAKE_LUAC 17 | //#ifndef MAKE_LUA 18 | //#define MAKE_LUA 19 | //#endif 20 | #endif 21 | #endif 22 | 23 | 24 | /* 25 | ** Choose suitable platform-specific features. Default is no 26 | ** platform-specific features. Some of these options may need extra 27 | ** libraries such as -ldl -lreadline -lncurses 28 | */ 29 | #if 0 30 | #define LUA_USE_LINUX 31 | #define LUA_USE_MACOSX 32 | #define LUA_USE_POSIX 33 | #define LUA_ANSI 34 | #endif 35 | 36 | 37 | /* no need to change anything below this line ----------------------------- */ 38 | 39 | #include "lprefix.h" 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | 57 | 58 | /* setup for luaconf.h */ 59 | #define LUA_CORE 60 | #define LUA_LIB 61 | #define ltable_c 62 | #define lvm_c 63 | #include "luaconf.h" 64 | 65 | /* do not export internal symbols */ 66 | #undef LUAI_FUNC 67 | #undef LUAI_DDEC 68 | #undef LUAI_DDEF 69 | #define LUAI_FUNC static 70 | #define LUAI_DDEC(def) /* empty */ 71 | #define LUAI_DDEF static 72 | 73 | /* core -- used by all */ 74 | #include "lzio.c" 75 | #include "lctype.c" 76 | #include "lopcodes.c" 77 | #include "lmem.c" 78 | #include "lundump.c" 79 | #include "ldump.c" 80 | #include "lstate.c" 81 | #include "lgc.c" 82 | #include "llex.c" 83 | #include "lcode.c" 84 | #include "lparser.c" 85 | #include "ldebug.c" 86 | #include "lfunc.c" 87 | #include "lobject.c" 88 | #include "ltm.c" 89 | #include "lstring.c" 90 | #include "ltable.c" 91 | #include "ldo.c" 92 | #include "lvm.c" 93 | #include "lapi.c" 94 | 95 | /* auxiliary library -- used by all */ 96 | #include "lauxlib.c" 97 | 98 | /* standard library -- not used by luac */ 99 | #ifndef MAKE_LUAC 100 | #include "lbaselib.c" 101 | #include "lcorolib.c" 102 | #include "ldblib.c" 103 | #include "liolib.c" 104 | #include "lmathlib.c" 105 | #include "loadlib.c" 106 | #include "loslib.c" 107 | #include "lstrlib.c" 108 | #include "ltablib.c" 109 | #include "lutf8lib.c" 110 | #include "linit.c" 111 | #endif 112 | 113 | /* lua */ 114 | #ifdef MAKE_LUA 115 | #include "lua.c" 116 | #endif 117 | 118 | /* luac */ 119 | #ifdef MAKE_LUAC 120 | #include "luac.c" 121 | #endif 122 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | lua_State* L; 4 | 5 | #include 6 | #include 7 | 8 | void dump_lua_api() 9 | { 10 | printf("Constants:\n"); 11 | for (const REF_Constant* c = REF_Constant::head(); c; c = c->next) { 12 | printf("\t%s\n", c->name); 13 | } 14 | printf("\nGlobal Variables:\n"); 15 | for (const REF_Global* g = REF_Global::head(); g; g = g->next) { 16 | printf("\t%s\n", g->name); 17 | } 18 | printf("\nFunctions:\n"); 19 | for (const REF_Function* fn = REF_Function::head(); fn; fn = fn->next) { 20 | printf("\t%s(", fn->name()); 21 | const REF_FunctionSignature& sig = fn->sig(); 22 | for (int i = 0; i < sig.param_count; i++) { 23 | const REF_Type* type = sig.params[i]; 24 | int flattened_count = type->flattened_count(); 25 | 26 | for (int j = 0; j < flattened_count; ++j) { 27 | printf("%s%s", (i == 0 && j == 0) ? "" : ", ", type->flattened_type()->name()); 28 | } 29 | } 30 | printf(")\n"); 31 | } 32 | for (const REF_WrapBinder* w = REF_WrapBinder::head(); w; w = w->next) { 33 | printf("\t%s\n", w->name); 34 | } 35 | } 36 | REF_FUNCTION(dump_lua_api); 37 | 38 | // ------------------------------------------------------------------------------------------------- 39 | // Main 40 | 41 | void mount_directory_as(const char* to_mount, const char* dir) 42 | { 43 | Path path = fs_get_base_directory(); 44 | path.normalize(); 45 | path += to_mount; 46 | fs_mount(path.c_str(), dir); 47 | } 48 | 49 | REF_FUNCTION(mount_directory_as); 50 | 51 | void assert_traceback(const char* string) 52 | { 53 | luaL_traceback(L, L, string, 1); 54 | const char* error_and_stack_trace = lua_tostring(L, -1); 55 | String s = error_and_stack_trace; 56 | lua_pop(L, 1); 57 | REF_CallLuaFunction(L, "REF_ErrorHandler", { }, s.c_str()); 58 | } 59 | 60 | int b2_assert_override(const char* condition, const char* fileName, int lineNumber) 61 | { 62 | String s = String::fmt("BOX2D ASSERTION: %s, %s, line %d\n", condition, fileName, lineNumber); 63 | assert_traceback(s.c_str()); 64 | return 1; 65 | } 66 | 67 | void cf_assert_override(bool expr, const char* message, const char* file, int line) 68 | { 69 | if (!expr) { 70 | String s = String::fmt("CF_ASSERT(%s) : %s, line %d\n", message, file, line); 71 | assert_traceback(s.c_str()); 72 | } 73 | } 74 | 75 | #define WIN32_LEAN_AND_MEAN 76 | #include 77 | 78 | void wait_for_debugger() 79 | { 80 | while (!IsDebuggerPresent()) { 81 | printf("Waiting for debugger to attach...\n"); 82 | Sleep(500); 83 | } 84 | } 85 | REF_FUNCTION(wait_for_debugger); 86 | 87 | #include // chdir 88 | 89 | int main(int argc, char* argv[]) 90 | { 91 | b2SetAssertFcn(b2_assert_override); 92 | cf_set_assert_handler(cf_assert_override); 93 | 94 | ::L = luaL_newstate(); 95 | luaL_openlibs(L); 96 | REF_BindLua(L); 97 | 98 | if (argc < 2) { 99 | printf("You should supply the path to your `main.lua` file as the first command line parameter.\n"); 100 | printf("Now assuming you've run from MSVC's Debug/Release folder for testing CF_Lua development.\n"); 101 | } 102 | 103 | const char* path_to_main_lua = argc < 2 ? "../../src/main.lua" : argv[1]; 104 | if (luaL_dofile(L, path_to_main_lua)) { 105 | fprintf(stderr, lua_tostring(L, -1)); 106 | return -1; 107 | } 108 | 109 | REF_CallLuaFunction(L, "main"); 110 | lua_close(L); 111 | 112 | return 0; 113 | } 114 | -------------------------------------------------------------------------------- /lua/ltm.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltm.h $ 3 | ** Tag methods 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ltm_h 8 | #define ltm_h 9 | 10 | 11 | #include "lobject.h" 12 | 13 | 14 | /* 15 | * WARNING: if you change the order of this enumeration, 16 | * grep "ORDER TM" and "ORDER OP" 17 | */ 18 | typedef enum { 19 | TM_INDEX, 20 | TM_NEWINDEX, 21 | TM_GC, 22 | TM_MODE, 23 | TM_LEN, 24 | TM_EQ, /* last tag method with fast access */ 25 | TM_ADD, 26 | TM_SUB, 27 | TM_MUL, 28 | TM_MOD, 29 | TM_POW, 30 | TM_DIV, 31 | TM_IDIV, 32 | TM_BAND, 33 | TM_BOR, 34 | TM_BXOR, 35 | TM_SHL, 36 | TM_SHR, 37 | TM_UNM, 38 | TM_BNOT, 39 | TM_LT, 40 | TM_LE, 41 | TM_CONCAT, 42 | TM_CALL, 43 | TM_CLOSE, 44 | TM_N /* number of elements in the enum */ 45 | } TMS; 46 | 47 | 48 | /* 49 | ** Mask with 1 in all fast-access methods. A 1 in any of these bits 50 | ** in the flag of a (meta)table means the metatable does not have the 51 | ** corresponding metamethod field. (Bit 6 of the flag indicates that 52 | ** the table is using the dummy node; bit 7 is used for 'isrealasize'.) 53 | */ 54 | #define maskflags (~(~0u << (TM_EQ + 1))) 55 | 56 | 57 | /* 58 | ** Test whether there is no tagmethod. 59 | ** (Because tagmethods use raw accesses, the result may be an "empty" nil.) 60 | */ 61 | #define notm(tm) ttisnil(tm) 62 | 63 | #define checknoTM(mt,e) ((mt) == NULL || (mt)->flags & (1u<<(e))) 64 | 65 | #define gfasttm(g,mt,e) \ 66 | (checknoTM(mt, e) ? NULL : luaT_gettm(mt, e, (g)->tmname[e])) 67 | 68 | #define fasttm(l,mt,e) gfasttm(G(l), mt, e) 69 | 70 | #define ttypename(x) luaT_typenames_[(x) + 1] 71 | 72 | LUAI_DDEC(const char *const luaT_typenames_[LUA_TOTALTYPES];) 73 | 74 | 75 | LUAI_FUNC const char *luaT_objtypename (lua_State *L, const TValue *o); 76 | 77 | LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); 78 | LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, 79 | TMS event); 80 | LUAI_FUNC void luaT_init (lua_State *L); 81 | 82 | LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, 83 | const TValue *p2, const TValue *p3); 84 | LUAI_FUNC int luaT_callTMres (lua_State *L, const TValue *f, 85 | const TValue *p1, const TValue *p2, StkId p3); 86 | LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, 87 | StkId res, TMS event); 88 | LUAI_FUNC void luaT_tryconcatTM (lua_State *L); 89 | LUAI_FUNC void luaT_trybinassocTM (lua_State *L, const TValue *p1, 90 | const TValue *p2, int inv, StkId res, TMS event); 91 | LUAI_FUNC void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2, 92 | int inv, StkId res, TMS event); 93 | LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1, 94 | const TValue *p2, TMS event); 95 | LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, 96 | int inv, int isfloat, TMS event); 97 | 98 | LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, 99 | struct CallInfo *ci, const Proto *p); 100 | LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci, 101 | StkId where, int wanted); 102 | 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lua Bindings for CF and Box2D 2 | 3 | This repo provides bindings to Lua for [CF](https://github.com/RandyGaul/cute_framework) and Box2D. An executable file is generated called `CF_Lua` (feel free to rename this to whatever you like). You pass in a path to your `main.lua` file as the only command line parameter. The executable will start up your Lua script and call the `main` function. From there it's just a matter of calling into CF functions from Lua. All of the functions/constants are bound in `wrap_cf.cpp`, and you may view all bound functions/constants by calling `dump_lua_api` from within Lua. 4 | 5 | Make sure to do `git submodule update --init --recursive` once you clone the repo. 6 | 7 | # Special Cases 8 | 9 | Arrays - When calling a C function and passing arrays over to C, do *NOT* send in the length of the array. The array length gets automatically handled by the binding system. 10 | 11 | Callbacks - Passing callbacks to C is done by sending a *string of the function name* in Lua, not the function itself. Example for fixed updates: 12 | 13 | ```lua 14 | function update() 15 | -- do my fixed update here 16 | end 17 | 18 | function draw() end 19 | 20 | while app_is_running() do 21 | app_update("update") 22 | draw() 23 | end 24 | ``` 25 | 26 | Math types are all flattened. Each type has no keys, and is just a bunch of values. For example, 2d vectors (b2Vec2 and v2) are flattened into two floats. If we call a function in C that accepts some vectors, we must pass in each float explicitly from Lua. Example: 27 | 28 | ```lua 29 | draw_push_color(r,g,b,a) 30 | -- as opposed to 31 | color = {r=r,g=g,b=b,a=a} 32 | draw_push_color(color) 33 | ``` 34 | 35 | Otherwise there aren't too many quirks, and 99% of functions match 1:1 with the C function signatures. 36 | 37 | Smalltalk made a cool hotreloader, you can check it out here: https://gist.github.com/waldnercharles/a3e314afccfac40ce4fbf42b83093c54 38 | 39 | 40 | # Binding New Stuff 41 | 42 | You have CF and Box2D bindings as examples to follow if you ever want to add new stuff to Lua from C. This includes any other C library. It's possible to bind C++ libraries as well, but they need to either written in C-style or wrapped in a C API. 43 | 44 | C++ APIs themselves are notoriously overcomplicated and don't map well to other languages. For this reason, I recommend to only stick to APIs that expose simple structs/pointers/handles. Bind.h has a ton of notes at the top of the header about how to bind and expose new things to Lua. 45 | 46 | 47 | # Building 48 | 49 | I'm using latest version of VS2022. Unfortunately older versions won't work because Box2D authored their C API with the absolute newest features from C, meaning older versions of MSVC just won't compile. This is the _Atomic keyword. Just download/update to the latest version of MSVC and it will compile. 50 | 51 | To compile with CMake it's easiest to just use msvc2202.cmd from the command line, and then look into build_msv_c2022 folder to open CF_Lua.sln. CMake should automatically fetch the latest Box2D and CF versions and then build it all together. From there, it's just a matter of messing around in main.lua. 52 | 53 | I haven't made an elegant or well-written main.lua file yet. I'm just testing stuff out at low-level, but it does show drawing sprites, polylines, making some rigid bodies and static geometry. And I did also hook up debug drawing to Box2D. 54 | 55 | To get going, I'd recommend to consider wrapping the CF/Box2D Lua functions inside your own Lua wrappers. This would be a good way to tweak the API and get in optional arguments and stuff. 56 | -------------------------------------------------------------------------------- /lua/ldo.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ldo.h $ 3 | ** Stack and Call structure of Lua 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ldo_h 8 | #define ldo_h 9 | 10 | 11 | #include "llimits.h" 12 | #include "lobject.h" 13 | #include "lstate.h" 14 | #include "lzio.h" 15 | 16 | 17 | /* 18 | ** Macro to check stack size and grow stack if needed. Parameters 19 | ** 'pre'/'pos' allow the macro to preserve a pointer into the 20 | ** stack across reallocations, doing the work only when needed. 21 | ** It also allows the running of one GC step when the stack is 22 | ** reallocated. 23 | ** 'condmovestack' is used in heavy tests to force a stack reallocation 24 | ** at every check. 25 | */ 26 | 27 | #if !defined(HARDSTACKTESTS) 28 | #define condmovestack(L,pre,pos) ((void)0) 29 | #else 30 | /* realloc stack keeping its size */ 31 | #define condmovestack(L,pre,pos) \ 32 | { int sz_ = stacksize(L); pre; luaD_reallocstack((L), sz_, 0); pos; } 33 | #endif 34 | 35 | #define luaD_checkstackaux(L,n,pre,pos) \ 36 | if (l_unlikely(L->stack_last.p - L->top.p <= (n))) \ 37 | { pre; luaD_growstack(L, n, 1); pos; } \ 38 | else { condmovestack(L,pre,pos); } 39 | 40 | /* In general, 'pre'/'pos' are empty (nothing to save) */ 41 | #define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0) 42 | 43 | 44 | 45 | #define savestack(L,pt) (cast_charp(pt) - cast_charp(L->stack.p)) 46 | #define restorestack(L,n) cast(StkId, cast_charp(L->stack.p) + (n)) 47 | 48 | 49 | /* macro to check stack size, preserving 'p' */ 50 | #define checkstackp(L,n,p) \ 51 | luaD_checkstackaux(L, n, \ 52 | ptrdiff_t t__ = savestack(L, p), /* save 'p' */ \ 53 | p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ 54 | 55 | 56 | /* 57 | ** Maximum depth for nested C calls, syntactical nested non-terminals, 58 | ** and other features implemented through recursion in C. (Value must 59 | ** fit in a 16-bit unsigned integer. It must also be compatible with 60 | ** the size of the C stack.) 61 | */ 62 | #if !defined(LUAI_MAXCCALLS) 63 | #define LUAI_MAXCCALLS 200 64 | #endif 65 | 66 | 67 | /* type of protected functions, to be ran by 'runprotected' */ 68 | typedef void (*Pfunc) (lua_State *L, void *ud); 69 | 70 | LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); 71 | LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, 72 | const char *mode); 73 | LUAI_FUNC void luaD_hook (lua_State *L, int event, int line, 74 | int fTransfer, int nTransfer); 75 | LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci); 76 | LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, 77 | int narg1, int delta); 78 | LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults); 79 | LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); 80 | LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); 81 | LUAI_FUNC int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status); 82 | LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, 83 | ptrdiff_t oldtop, ptrdiff_t ef); 84 | LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, int nres); 85 | LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror); 86 | LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror); 87 | LUAI_FUNC void luaD_shrinkstack (lua_State *L); 88 | LUAI_FUNC void luaD_inctop (lua_State *L); 89 | 90 | LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); 91 | LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); 92 | 93 | #endif 94 | 95 | -------------------------------------------------------------------------------- /lua/lmem.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lmem.h $ 3 | ** Interface to Memory Manager 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lmem_h 8 | #define lmem_h 9 | 10 | 11 | #include 12 | 13 | #include "llimits.h" 14 | #include "lua.h" 15 | 16 | 17 | #define luaM_error(L) luaD_throw(L, LUA_ERRMEM) 18 | 19 | 20 | /* 21 | ** This macro tests whether it is safe to multiply 'n' by the size of 22 | ** type 't' without overflows. Because 'e' is always constant, it avoids 23 | ** the runtime division MAX_SIZET/(e). 24 | ** (The macro is somewhat complex to avoid warnings: The 'sizeof' 25 | ** comparison avoids a runtime comparison when overflow cannot occur. 26 | ** The compiler should be able to optimize the real test by itself, but 27 | ** when it does it, it may give a warning about "comparison is always 28 | ** false due to limited range of data type"; the +1 tricks the compiler, 29 | ** avoiding this warning but also this optimization.) 30 | */ 31 | #define luaM_testsize(n,e) \ 32 | (sizeof(n) >= sizeof(size_t) && cast_sizet((n)) + 1 > MAX_SIZET/(e)) 33 | 34 | #define luaM_checksize(L,n,e) \ 35 | (luaM_testsize(n,e) ? luaM_toobig(L) : cast_void(0)) 36 | 37 | 38 | /* 39 | ** Computes the minimum between 'n' and 'MAX_SIZET/sizeof(t)', so that 40 | ** the result is not larger than 'n' and cannot overflow a 'size_t' 41 | ** when multiplied by the size of type 't'. (Assumes that 'n' is an 42 | ** 'int' or 'unsigned int' and that 'int' is not larger than 'size_t'.) 43 | */ 44 | #define luaM_limitN(n,t) \ 45 | ((cast_sizet(n) <= MAX_SIZET/sizeof(t)) ? (n) : \ 46 | cast_uint((MAX_SIZET/sizeof(t)))) 47 | 48 | 49 | /* 50 | ** Arrays of chars do not need any test 51 | */ 52 | #define luaM_reallocvchar(L,b,on,n) \ 53 | cast_charp(luaM_saferealloc_(L, (b), (on)*sizeof(char), (n)*sizeof(char))) 54 | 55 | #define luaM_freemem(L, b, s) luaM_free_(L, (b), (s)) 56 | #define luaM_free(L, b) luaM_free_(L, (b), sizeof(*(b))) 57 | #define luaM_freearray(L, b, n) luaM_free_(L, (b), (n)*sizeof(*(b))) 58 | 59 | #define luaM_new(L,t) cast(t*, luaM_malloc_(L, sizeof(t), 0)) 60 | #define luaM_newvector(L,n,t) cast(t*, luaM_malloc_(L, (n)*sizeof(t), 0)) 61 | #define luaM_newvectorchecked(L,n,t) \ 62 | (luaM_checksize(L,n,sizeof(t)), luaM_newvector(L,n,t)) 63 | 64 | #define luaM_newobject(L,tag,s) luaM_malloc_(L, (s), tag) 65 | 66 | #define luaM_newblock(L, size) luaM_newvector(L, size, char) 67 | 68 | #define luaM_growvector(L,v,nelems,size,t,limit,e) \ 69 | ((v)=cast(t *, luaM_growaux_(L,v,nelems,&(size),sizeof(t), \ 70 | luaM_limitN(limit,t),e))) 71 | 72 | #define luaM_reallocvector(L, v,oldn,n,t) \ 73 | (cast(t *, luaM_realloc_(L, v, cast_sizet(oldn) * sizeof(t), \ 74 | cast_sizet(n) * sizeof(t)))) 75 | 76 | #define luaM_shrinkvector(L,v,size,fs,t) \ 77 | ((v)=cast(t *, luaM_shrinkvector_(L, v, &(size), fs, sizeof(t)))) 78 | 79 | LUAI_FUNC l_noret luaM_toobig (lua_State *L); 80 | 81 | /* not to be called directly */ 82 | LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, 83 | size_t size); 84 | LUAI_FUNC void *luaM_saferealloc_ (lua_State *L, void *block, size_t oldsize, 85 | size_t size); 86 | LUAI_FUNC void luaM_free_ (lua_State *L, void *block, size_t osize); 87 | LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int nelems, 88 | int *size, int size_elem, int limit, 89 | const char *what); 90 | LUAI_FUNC void *luaM_shrinkvector_ (lua_State *L, void *block, int *nelem, 91 | int final_n, int size_elem); 92 | LUAI_FUNC void *luaM_malloc_ (lua_State *L, size_t size, int tag); 93 | 94 | #endif 95 | 96 | -------------------------------------------------------------------------------- /lua/lcode.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lcode.h $ 3 | ** Code generator for Lua 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lcode_h 8 | #define lcode_h 9 | 10 | #include "llex.h" 11 | #include "lobject.h" 12 | #include "lopcodes.h" 13 | #include "lparser.h" 14 | 15 | 16 | /* 17 | ** Marks the end of a patch list. It is an invalid value both as an absolute 18 | ** address, and as a list link (would link an element to itself). 19 | */ 20 | #define NO_JUMP (-1) 21 | 22 | 23 | /* 24 | ** grep "ORDER OPR" if you change these enums (ORDER OP) 25 | */ 26 | typedef enum BinOpr { 27 | /* arithmetic operators */ 28 | OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW, 29 | OPR_DIV, OPR_IDIV, 30 | /* bitwise operators */ 31 | OPR_BAND, OPR_BOR, OPR_BXOR, 32 | OPR_SHL, OPR_SHR, 33 | /* string operator */ 34 | OPR_CONCAT, 35 | /* comparison operators */ 36 | OPR_EQ, OPR_LT, OPR_LE, 37 | OPR_NE, OPR_GT, OPR_GE, 38 | /* logical operators */ 39 | OPR_AND, OPR_OR, 40 | OPR_NOBINOPR 41 | } BinOpr; 42 | 43 | 44 | /* true if operation is foldable (that is, it is arithmetic or bitwise) */ 45 | #define foldbinop(op) ((op) <= OPR_SHR) 46 | 47 | 48 | #define luaK_codeABC(fs,o,a,b,c) luaK_codeABCk(fs,o,a,b,c,0) 49 | 50 | 51 | typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; 52 | 53 | 54 | /* get (pointer to) instruction of given 'expdesc' */ 55 | #define getinstruction(fs,e) ((fs)->f->code[(e)->u.info]) 56 | 57 | 58 | #define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) 59 | 60 | #define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) 61 | 62 | LUAI_FUNC int luaK_code (FuncState *fs, Instruction i); 63 | LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned Bx); 64 | LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A, 65 | int B, int C, int k); 66 | LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v); 67 | LUAI_FUNC void luaK_fixline (FuncState *fs, int line); 68 | LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); 69 | LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); 70 | LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); 71 | LUAI_FUNC void luaK_int (FuncState *fs, int reg, lua_Integer n); 72 | LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); 73 | LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); 74 | LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e); 75 | LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); 76 | LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); 77 | LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); 78 | LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); 79 | LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); 80 | LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e); 81 | LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); 82 | LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); 83 | LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); 84 | LUAI_FUNC int luaK_jump (FuncState *fs); 85 | LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); 86 | LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); 87 | LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); 88 | LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); 89 | LUAI_FUNC int luaK_getlabel (FuncState *fs); 90 | LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); 91 | LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); 92 | LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, 93 | expdesc *v2, int line); 94 | LUAI_FUNC void luaK_settablesize (FuncState *fs, int pc, 95 | int ra, int asize, int hsize); 96 | LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); 97 | LUAI_FUNC void luaK_finish (FuncState *fs); 98 | LUAI_FUNC l_noret luaK_semerror (LexState *ls, const char *msg); 99 | 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /lua/ltests.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltests.h $ 3 | ** Internal Header for Debugging of the Lua Implementation 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ltests_h 8 | #define ltests_h 9 | 10 | 11 | #include 12 | #include 13 | 14 | /* test Lua with compatibility code */ 15 | #define LUA_COMPAT_MATHLIB 16 | #define LUA_COMPAT_LT_LE 17 | 18 | 19 | #define LUA_DEBUG 20 | 21 | 22 | /* turn on assertions */ 23 | #define LUAI_ASSERT 24 | 25 | 26 | /* to avoid warnings, and to make sure value is really unused */ 27 | #define UNUSED(x) (x=0, (void)(x)) 28 | 29 | 30 | /* test for sizes in 'l_sprintf' (make sure whole buffer is available) */ 31 | #undef l_sprintf 32 | #if !defined(LUA_USE_C89) 33 | #define l_sprintf(s,sz,f,i) (memset(s,0xAB,sz), snprintf(s,sz,f,i)) 34 | #else 35 | #define l_sprintf(s,sz,f,i) (memset(s,0xAB,sz), sprintf(s,f,i)) 36 | #endif 37 | 38 | 39 | /* get a chance to test code without jump tables */ 40 | #define LUA_USE_JUMPTABLE 0 41 | 42 | 43 | /* use 32-bit integers in random generator */ 44 | #define LUA_RAND32 45 | 46 | 47 | /* memory-allocator control variables */ 48 | typedef struct Memcontrol { 49 | int failnext; 50 | unsigned long numblocks; 51 | unsigned long total; 52 | unsigned long maxmem; 53 | unsigned long memlimit; 54 | unsigned long countlimit; 55 | unsigned long objcount[LUA_NUMTYPES]; 56 | } Memcontrol; 57 | 58 | LUA_API Memcontrol l_memcontrol; 59 | 60 | 61 | /* 62 | ** generic variable for debug tricks 63 | */ 64 | extern void *l_Trick; 65 | 66 | 67 | 68 | /* 69 | ** Function to traverse and check all memory used by Lua 70 | */ 71 | LUAI_FUNC int lua_checkmemory (lua_State *L); 72 | 73 | /* 74 | ** Function to print an object GC-friendly 75 | */ 76 | struct GCObject; 77 | LUAI_FUNC void lua_printobj (lua_State *L, struct GCObject *o); 78 | 79 | 80 | /* test for lock/unlock */ 81 | 82 | struct L_EXTRA { int lock; int *plock; }; 83 | #undef LUA_EXTRASPACE 84 | #define LUA_EXTRASPACE sizeof(struct L_EXTRA) 85 | #define getlock(l) cast(struct L_EXTRA*, lua_getextraspace(l)) 86 | #define luai_userstateopen(l) \ 87 | (getlock(l)->lock = 0, getlock(l)->plock = &(getlock(l)->lock)) 88 | #define luai_userstateclose(l) \ 89 | lua_assert(getlock(l)->lock == 1 && getlock(l)->plock == &(getlock(l)->lock)) 90 | #define luai_userstatethread(l,l1) \ 91 | lua_assert(getlock(l1)->plock == getlock(l)->plock) 92 | #define luai_userstatefree(l,l1) \ 93 | lua_assert(getlock(l)->plock == getlock(l1)->plock) 94 | #define lua_lock(l) lua_assert((*getlock(l)->plock)++ == 0) 95 | #define lua_unlock(l) lua_assert(--(*getlock(l)->plock) == 0) 96 | 97 | 98 | 99 | LUA_API int luaB_opentests (lua_State *L); 100 | 101 | LUA_API void *debug_realloc (void *ud, void *block, 102 | size_t osize, size_t nsize); 103 | 104 | #if defined(lua_c) 105 | #define luaL_newstate() \ 106 | lua_newstate(debug_realloc, &l_memcontrol, luaL_makeseed(NULL)) 107 | #define luai_openlibs(L) \ 108 | { luaL_openlibs(L); \ 109 | luaL_requiref(L, "T", luaB_opentests, 1); \ 110 | lua_pop(L, 1); } 111 | #endif 112 | 113 | 114 | 115 | /* change some sizes to give some bugs a chance */ 116 | 117 | #undef LUAL_BUFFERSIZE 118 | #define LUAL_BUFFERSIZE 23 119 | #define MINSTRTABSIZE 2 120 | #define MAXIWTHABS 3 121 | 122 | #define STRCACHE_N 23 123 | #define STRCACHE_M 5 124 | 125 | #undef LUAI_USER_ALIGNMENT_T 126 | #define LUAI_USER_ALIGNMENT_T union { char b[sizeof(void*) * 8]; } 127 | 128 | 129 | /* 130 | ** This one is not compatible with tests for opcode optimizations, 131 | ** as it blocks some optimizations 132 | #define MAXINDEXRK 0 133 | */ 134 | 135 | 136 | /* make stack-overflow tests run faster */ 137 | #undef LUAI_MAXSTACK 138 | #define LUAI_MAXSTACK 50000 139 | 140 | 141 | /* test mode uses more stack space */ 142 | #undef LUAI_MAXCCALLS 143 | #define LUAI_MAXCCALLS 180 144 | 145 | 146 | /* force Lua to use its own implementations */ 147 | #undef lua_strx2number 148 | #undef lua_number2strx 149 | 150 | 151 | #endif 152 | 153 | -------------------------------------------------------------------------------- /lua/lopcodes.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lopcodes.c $ 3 | ** Opcodes for Lua virtual machine 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lopcodes_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include "lopcodes.h" 14 | 15 | 16 | /* ORDER OP */ 17 | 18 | LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { 19 | /* MM OT IT T A mode opcode */ 20 | opmode(0, 0, 0, 0, 1, iABC) /* OP_MOVE */ 21 | ,opmode(0, 0, 0, 0, 1, iAsBx) /* OP_LOADI */ 22 | ,opmode(0, 0, 0, 0, 1, iAsBx) /* OP_LOADF */ 23 | ,opmode(0, 0, 0, 0, 1, iABx) /* OP_LOADK */ 24 | ,opmode(0, 0, 0, 0, 1, iABx) /* OP_LOADKX */ 25 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LOADFALSE */ 26 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LFALSESKIP */ 27 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LOADTRUE */ 28 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LOADNIL */ 29 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETUPVAL */ 30 | ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETUPVAL */ 31 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETTABUP */ 32 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETTABLE */ 33 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETI */ 34 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETFIELD */ 35 | ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETTABUP */ 36 | ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETTABLE */ 37 | ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETI */ 38 | ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETFIELD */ 39 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_NEWTABLE */ 40 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SELF */ 41 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADDI */ 42 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADDK */ 43 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SUBK */ 44 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MULK */ 45 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MODK */ 46 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_POWK */ 47 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_DIVK */ 48 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_IDIVK */ 49 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BANDK */ 50 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BORK */ 51 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BXORK */ 52 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHRI */ 53 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHLI */ 54 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADD */ 55 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SUB */ 56 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MUL */ 57 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MOD */ 58 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_POW */ 59 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_DIV */ 60 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_IDIV */ 61 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BAND */ 62 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BOR */ 63 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BXOR */ 64 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHL */ 65 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHR */ 66 | ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBIN */ 67 | ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBINI*/ 68 | ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBINK*/ 69 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_UNM */ 70 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BNOT */ 71 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_NOT */ 72 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LEN */ 73 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_CONCAT */ 74 | ,opmode(0, 0, 0, 0, 0, iABC) /* OP_CLOSE */ 75 | ,opmode(0, 0, 0, 0, 0, iABC) /* OP_TBC */ 76 | ,opmode(0, 0, 0, 0, 0, isJ) /* OP_JMP */ 77 | ,opmode(0, 0, 0, 1, 0, iABC) /* OP_EQ */ 78 | ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LT */ 79 | ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LE */ 80 | ,opmode(0, 0, 0, 1, 0, iABC) /* OP_EQK */ 81 | ,opmode(0, 0, 0, 1, 0, iABC) /* OP_EQI */ 82 | ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LTI */ 83 | ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LEI */ 84 | ,opmode(0, 0, 0, 1, 0, iABC) /* OP_GTI */ 85 | ,opmode(0, 0, 0, 1, 0, iABC) /* OP_GEI */ 86 | ,opmode(0, 0, 0, 1, 0, iABC) /* OP_TEST */ 87 | ,opmode(0, 0, 0, 1, 1, iABC) /* OP_TESTSET */ 88 | ,opmode(0, 1, 1, 0, 1, iABC) /* OP_CALL */ 89 | ,opmode(0, 1, 1, 0, 1, iABC) /* OP_TAILCALL */ 90 | ,opmode(0, 0, 1, 0, 0, iABC) /* OP_RETURN */ 91 | ,opmode(0, 0, 0, 0, 0, iABC) /* OP_RETURN0 */ 92 | ,opmode(0, 0, 0, 0, 0, iABC) /* OP_RETURN1 */ 93 | ,opmode(0, 0, 0, 0, 1, iABx) /* OP_FORLOOP */ 94 | ,opmode(0, 0, 0, 0, 1, iABx) /* OP_FORPREP */ 95 | ,opmode(0, 0, 0, 0, 0, iABx) /* OP_TFORPREP */ 96 | ,opmode(0, 0, 0, 0, 0, iABC) /* OP_TFORCALL */ 97 | ,opmode(0, 0, 0, 0, 1, iABx) /* OP_TFORLOOP */ 98 | ,opmode(0, 0, 1, 0, 0, iABC) /* OP_SETLIST */ 99 | ,opmode(0, 0, 0, 0, 1, iABx) /* OP_CLOSURE */ 100 | ,opmode(0, 1, 0, 0, 1, iABC) /* OP_VARARG */ 101 | ,opmode(0, 0, 1, 0, 1, iABC) /* OP_VARARGPREP */ 102 | ,opmode(0, 0, 0, 0, 0, iAx) /* OP_EXTRAARG */ 103 | }; 104 | 105 | -------------------------------------------------------------------------------- /lua/lvm.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lvm.h $ 3 | ** Lua virtual machine 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lvm_h 8 | #define lvm_h 9 | 10 | 11 | #include "ldo.h" 12 | #include "lobject.h" 13 | #include "ltm.h" 14 | 15 | 16 | #if !defined(LUA_NOCVTN2S) 17 | #define cvt2str(o) ttisnumber(o) 18 | #else 19 | #define cvt2str(o) 0 /* no conversion from numbers to strings */ 20 | #endif 21 | 22 | 23 | #if !defined(LUA_NOCVTS2N) 24 | #define cvt2num(o) ttisstring(o) 25 | #else 26 | #define cvt2num(o) 0 /* no conversion from strings to numbers */ 27 | #endif 28 | 29 | 30 | /* 31 | ** You can define LUA_FLOORN2I if you want to convert floats to integers 32 | ** by flooring them (instead of raising an error if they are not 33 | ** integral values) 34 | */ 35 | #if !defined(LUA_FLOORN2I) 36 | #define LUA_FLOORN2I F2Ieq 37 | #endif 38 | 39 | 40 | /* 41 | ** Rounding modes for float->integer coercion 42 | */ 43 | typedef enum { 44 | F2Ieq, /* no rounding; accepts only integral values */ 45 | F2Ifloor, /* takes the floor of the number */ 46 | F2Iceil /* takes the ceil of the number */ 47 | } F2Imod; 48 | 49 | 50 | /* convert an object to a float (including string coercion) */ 51 | #define tonumber(o,n) \ 52 | (ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n)) 53 | 54 | 55 | /* convert an object to a float (without string coercion) */ 56 | #define tonumberns(o,n) \ 57 | (ttisfloat(o) ? ((n) = fltvalue(o), 1) : \ 58 | (ttisinteger(o) ? ((n) = cast_num(ivalue(o)), 1) : 0)) 59 | 60 | 61 | /* convert an object to an integer (including string coercion) */ 62 | #define tointeger(o,i) \ 63 | (l_likely(ttisinteger(o)) ? (*(i) = ivalue(o), 1) \ 64 | : luaV_tointeger(o,i,LUA_FLOORN2I)) 65 | 66 | 67 | /* convert an object to an integer (without string coercion) */ 68 | #define tointegerns(o,i) \ 69 | (l_likely(ttisinteger(o)) ? (*(i) = ivalue(o), 1) \ 70 | : luaV_tointegerns(o,i,LUA_FLOORN2I)) 71 | 72 | 73 | #define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2)) 74 | 75 | #define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) 76 | 77 | 78 | /* 79 | ** fast track for 'gettable' 80 | */ 81 | #define luaV_fastget(t,k,res,f, tag) \ 82 | (tag = (!ttistable(t) ? LUA_VNOTABLE : f(hvalue(t), k, res))) 83 | 84 | 85 | /* 86 | ** Special case of 'luaV_fastget' for integers, inlining the fast case 87 | ** of 'luaH_getint'. 88 | */ 89 | #define luaV_fastgeti(t,k,res,tag) \ 90 | if (!ttistable(t)) tag = LUA_VNOTABLE; \ 91 | else { luaH_fastgeti(hvalue(t), k, res, tag); } 92 | 93 | 94 | #define luaV_fastset(t,k,val,hres,f) \ 95 | (hres = (!ttistable(t) ? HNOTATABLE : f(hvalue(t), k, val))) 96 | 97 | #define luaV_fastseti(t,k,val,hres) \ 98 | if (!ttistable(t)) hres = HNOTATABLE; \ 99 | else { luaH_fastseti(hvalue(t), k, val, hres); } 100 | 101 | 102 | /* 103 | ** Finish a fast set operation (when fast set succeeds). 104 | */ 105 | #define luaV_finishfastset(L,t,v) luaC_barrierback(L, gcvalue(t), v) 106 | 107 | 108 | /* 109 | ** Shift right is the same as shift left with a negative 'y' 110 | */ 111 | #define luaV_shiftr(x,y) luaV_shiftl(x,intop(-, 0, y)) 112 | 113 | 114 | 115 | LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); 116 | LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); 117 | LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); 118 | LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); 119 | LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, F2Imod mode); 120 | LUAI_FUNC int luaV_tointegerns (const TValue *obj, lua_Integer *p, 121 | F2Imod mode); 122 | LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode); 123 | LUAI_FUNC int luaV_finishget (lua_State *L, const TValue *t, TValue *key, 124 | StkId val, int tag); 125 | LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, 126 | TValue *val, int aux); 127 | LUAI_FUNC void luaV_finishOp (lua_State *L); 128 | LUAI_FUNC void luaV_execute (lua_State *L, CallInfo *ci); 129 | LUAI_FUNC void luaV_concat (lua_State *L, int total); 130 | LUAI_FUNC lua_Integer luaV_idiv (lua_State *L, lua_Integer x, lua_Integer y); 131 | LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); 132 | LUAI_FUNC lua_Number luaV_modf (lua_State *L, lua_Number x, lua_Number y); 133 | LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y); 134 | LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); 135 | 136 | #endif 137 | -------------------------------------------------------------------------------- /lua/lcorolib.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lcorolib.c $ 3 | ** Coroutine Library 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lcorolib_c 8 | #define LUA_LIB 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "lauxlib.h" 18 | #include "lualib.h" 19 | #include "llimits.h" 20 | 21 | 22 | static lua_State *getco (lua_State *L) { 23 | lua_State *co = lua_tothread(L, 1); 24 | luaL_argexpected(L, co, 1, "thread"); 25 | return co; 26 | } 27 | 28 | 29 | /* 30 | ** Resumes a coroutine. Returns the number of results for non-error 31 | ** cases or -1 for errors. 32 | */ 33 | static int auxresume (lua_State *L, lua_State *co, int narg) { 34 | int status, nres; 35 | if (l_unlikely(!lua_checkstack(co, narg))) { 36 | lua_pushliteral(L, "too many arguments to resume"); 37 | return -1; /* error flag */ 38 | } 39 | lua_xmove(L, co, narg); 40 | status = lua_resume(co, L, narg, &nres); 41 | if (l_likely(status == LUA_OK || status == LUA_YIELD)) { 42 | if (l_unlikely(!lua_checkstack(L, nres + 1))) { 43 | lua_pop(co, nres); /* remove results anyway */ 44 | lua_pushliteral(L, "too many results to resume"); 45 | return -1; /* error flag */ 46 | } 47 | lua_xmove(co, L, nres); /* move yielded values */ 48 | return nres; 49 | } 50 | else { 51 | lua_xmove(co, L, 1); /* move error message */ 52 | return -1; /* error flag */ 53 | } 54 | } 55 | 56 | 57 | static int luaB_coresume (lua_State *L) { 58 | lua_State *co = getco(L); 59 | int r; 60 | r = auxresume(L, co, lua_gettop(L) - 1); 61 | if (l_unlikely(r < 0)) { 62 | lua_pushboolean(L, 0); 63 | lua_insert(L, -2); 64 | return 2; /* return false + error message */ 65 | } 66 | else { 67 | lua_pushboolean(L, 1); 68 | lua_insert(L, -(r + 1)); 69 | return r + 1; /* return true + 'resume' returns */ 70 | } 71 | } 72 | 73 | 74 | static int luaB_auxwrap (lua_State *L) { 75 | lua_State *co = lua_tothread(L, lua_upvalueindex(1)); 76 | int r = auxresume(L, co, lua_gettop(L)); 77 | if (l_unlikely(r < 0)) { /* error? */ 78 | int stat = lua_status(co); 79 | if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */ 80 | stat = lua_closethread(co, L); /* close its tbc variables */ 81 | lua_assert(stat != LUA_OK); 82 | lua_xmove(co, L, 1); /* move error message to the caller */ 83 | } 84 | if (stat != LUA_ERRMEM && /* not a memory error and ... */ 85 | lua_type(L, -1) == LUA_TSTRING) { /* ... error object is a string? */ 86 | luaL_where(L, 1); /* add extra info, if available */ 87 | lua_insert(L, -2); 88 | lua_concat(L, 2); 89 | } 90 | return lua_error(L); /* propagate error */ 91 | } 92 | return r; 93 | } 94 | 95 | 96 | static int luaB_cocreate (lua_State *L) { 97 | lua_State *NL; 98 | luaL_checktype(L, 1, LUA_TFUNCTION); 99 | NL = lua_newthread(L); 100 | lua_pushvalue(L, 1); /* move function to top */ 101 | lua_xmove(L, NL, 1); /* move function from L to NL */ 102 | return 1; 103 | } 104 | 105 | 106 | static int luaB_cowrap (lua_State *L) { 107 | luaB_cocreate(L); 108 | lua_pushcclosure(L, luaB_auxwrap, 1); 109 | return 1; 110 | } 111 | 112 | 113 | static int luaB_yield (lua_State *L) { 114 | return lua_yield(L, lua_gettop(L)); 115 | } 116 | 117 | 118 | #define COS_RUN 0 119 | #define COS_DEAD 1 120 | #define COS_YIELD 2 121 | #define COS_NORM 3 122 | 123 | 124 | static const char *const statname[] = 125 | {"running", "dead", "suspended", "normal"}; 126 | 127 | 128 | static int auxstatus (lua_State *L, lua_State *co) { 129 | if (L == co) return COS_RUN; 130 | else { 131 | switch (lua_status(co)) { 132 | case LUA_YIELD: 133 | return COS_YIELD; 134 | case LUA_OK: { 135 | lua_Debug ar; 136 | if (lua_getstack(co, 0, &ar)) /* does it have frames? */ 137 | return COS_NORM; /* it is running */ 138 | else if (lua_gettop(co) == 0) 139 | return COS_DEAD; 140 | else 141 | return COS_YIELD; /* initial state */ 142 | } 143 | default: /* some error occurred */ 144 | return COS_DEAD; 145 | } 146 | } 147 | } 148 | 149 | 150 | static int luaB_costatus (lua_State *L) { 151 | lua_State *co = getco(L); 152 | lua_pushstring(L, statname[auxstatus(L, co)]); 153 | return 1; 154 | } 155 | 156 | 157 | static int luaB_yieldable (lua_State *L) { 158 | lua_State *co = lua_isnone(L, 1) ? L : getco(L); 159 | lua_pushboolean(L, lua_isyieldable(co)); 160 | return 1; 161 | } 162 | 163 | 164 | static int luaB_corunning (lua_State *L) { 165 | int ismain = lua_pushthread(L); 166 | lua_pushboolean(L, ismain); 167 | return 2; 168 | } 169 | 170 | 171 | static int luaB_close (lua_State *L) { 172 | lua_State *co = getco(L); 173 | int status = auxstatus(L, co); 174 | switch (status) { 175 | case COS_DEAD: case COS_YIELD: { 176 | status = lua_closethread(co, L); 177 | if (status == LUA_OK) { 178 | lua_pushboolean(L, 1); 179 | return 1; 180 | } 181 | else { 182 | lua_pushboolean(L, 0); 183 | lua_xmove(co, L, 1); /* move error message */ 184 | return 2; 185 | } 186 | } 187 | default: /* normal or running coroutine */ 188 | return luaL_error(L, "cannot close a %s coroutine", statname[status]); 189 | } 190 | } 191 | 192 | 193 | static const luaL_Reg co_funcs[] = { 194 | {"create", luaB_cocreate}, 195 | {"resume", luaB_coresume}, 196 | {"running", luaB_corunning}, 197 | {"status", luaB_costatus}, 198 | {"wrap", luaB_cowrap}, 199 | {"yield", luaB_yield}, 200 | {"isyieldable", luaB_yieldable}, 201 | {"close", luaB_close}, 202 | {NULL, NULL} 203 | }; 204 | 205 | 206 | 207 | LUAMOD_API int luaopen_coroutine (lua_State *L) { 208 | luaL_newlib(L, co_funcs); 209 | return 1; 210 | } 211 | 212 | -------------------------------------------------------------------------------- /lua/lparser.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lparser.h $ 3 | ** Lua Parser 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lparser_h 8 | #define lparser_h 9 | 10 | #include "llimits.h" 11 | #include "lobject.h" 12 | #include "lzio.h" 13 | 14 | 15 | /* 16 | ** Expression and variable descriptor. 17 | ** Code generation for variables and expressions can be delayed to allow 18 | ** optimizations; An 'expdesc' structure describes a potentially-delayed 19 | ** variable/expression. It has a description of its "main" value plus a 20 | ** list of conditional jumps that can also produce its value (generated 21 | ** by short-circuit operators 'and'/'or'). 22 | */ 23 | 24 | /* kinds of variables/expressions */ 25 | typedef enum { 26 | VVOID, /* when 'expdesc' describes the last expression of a list, 27 | this kind means an empty list (so, no expression) */ 28 | VNIL, /* constant nil */ 29 | VTRUE, /* constant true */ 30 | VFALSE, /* constant false */ 31 | VK, /* constant in 'k'; info = index of constant in 'k' */ 32 | VKFLT, /* floating constant; nval = numerical float value */ 33 | VKINT, /* integer constant; ival = numerical integer value */ 34 | VKSTR, /* string constant; strval = TString address; 35 | (string is fixed by the lexer) */ 36 | VNONRELOC, /* expression has its value in a fixed register; 37 | info = result register */ 38 | VLOCAL, /* local variable; var.ridx = register index; 39 | var.vidx = relative index in 'actvar.arr' */ 40 | VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */ 41 | VCONST, /* compile-time variable; 42 | info = absolute index in 'actvar.arr' */ 43 | VINDEXED, /* indexed variable; 44 | ind.t = table register; 45 | ind.idx = key's R index */ 46 | VINDEXUP, /* indexed upvalue; 47 | ind.t = table upvalue; 48 | ind.idx = key's K index */ 49 | VINDEXI, /* indexed variable with constant integer; 50 | ind.t = table register; 51 | ind.idx = key's value */ 52 | VINDEXSTR, /* indexed variable with literal string; 53 | ind.t = table register; 54 | ind.idx = key's K index */ 55 | VJMP, /* expression is a test/comparison; 56 | info = pc of corresponding jump instruction */ 57 | VRELOC, /* expression can put result in any register; 58 | info = instruction pc */ 59 | VCALL, /* expression is a function call; info = instruction pc */ 60 | VVARARG /* vararg expression; info = instruction pc */ 61 | } expkind; 62 | 63 | 64 | #define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXSTR) 65 | #define vkisindexed(k) (VINDEXED <= (k) && (k) <= VINDEXSTR) 66 | 67 | 68 | typedef struct expdesc { 69 | expkind k; 70 | union { 71 | lua_Integer ival; /* for VKINT */ 72 | lua_Number nval; /* for VKFLT */ 73 | TString *strval; /* for VKSTR */ 74 | int info; /* for generic use */ 75 | struct { /* for indexed variables */ 76 | short idx; /* index (R or "long" K) */ 77 | lu_byte t; /* table (register or upvalue) */ 78 | } ind; 79 | struct { /* for local variables */ 80 | lu_byte ridx; /* register holding the variable */ 81 | unsigned short vidx; /* compiler index (in 'actvar.arr') */ 82 | } var; 83 | } u; 84 | int t; /* patch list of 'exit when true' */ 85 | int f; /* patch list of 'exit when false' */ 86 | } expdesc; 87 | 88 | 89 | /* kinds of variables */ 90 | #define VDKREG 0 /* regular */ 91 | #define RDKCONST 1 /* constant */ 92 | #define RDKTOCLOSE 2 /* to-be-closed */ 93 | #define RDKCTC 3 /* compile-time constant */ 94 | 95 | /* description of an active local variable */ 96 | typedef union Vardesc { 97 | struct { 98 | TValuefields; /* constant value (if it is a compile-time constant) */ 99 | lu_byte kind; 100 | lu_byte ridx; /* register holding the variable */ 101 | short pidx; /* index of the variable in the Proto's 'locvars' array */ 102 | TString *name; /* variable name */ 103 | } vd; 104 | TValue k; /* constant value (if any) */ 105 | } Vardesc; 106 | 107 | 108 | 109 | /* description of pending goto statements and label statements */ 110 | typedef struct Labeldesc { 111 | TString *name; /* label identifier */ 112 | int pc; /* position in code */ 113 | int line; /* line where it appeared */ 114 | lu_byte nactvar; /* number of active variables in that position */ 115 | lu_byte close; /* goto that escapes upvalues */ 116 | } Labeldesc; 117 | 118 | 119 | /* list of labels or gotos */ 120 | typedef struct Labellist { 121 | Labeldesc *arr; /* array */ 122 | int n; /* number of entries in use */ 123 | int size; /* array size */ 124 | } Labellist; 125 | 126 | 127 | /* dynamic structures used by the parser */ 128 | typedef struct Dyndata { 129 | struct { /* list of all active local variables */ 130 | Vardesc *arr; 131 | int n; 132 | int size; 133 | } actvar; 134 | Labellist gt; /* list of pending gotos */ 135 | Labellist label; /* list of active labels */ 136 | } Dyndata; 137 | 138 | 139 | /* control of blocks */ 140 | struct BlockCnt; /* defined in lparser.c */ 141 | 142 | 143 | /* state needed to generate code for a given function */ 144 | typedef struct FuncState { 145 | Proto *f; /* current function header */ 146 | struct FuncState *prev; /* enclosing function */ 147 | struct LexState *ls; /* lexical state */ 148 | struct BlockCnt *bl; /* chain of current blocks */ 149 | int pc; /* next position to code (equivalent to 'ncode') */ 150 | int lasttarget; /* 'label' of last 'jump label' */ 151 | int previousline; /* last line that was saved in 'lineinfo' */ 152 | int nk; /* number of elements in 'k' */ 153 | int np; /* number of elements in 'p' */ 154 | int nabslineinfo; /* number of elements in 'abslineinfo' */ 155 | int firstlocal; /* index of first local var (in Dyndata array) */ 156 | int firstlabel; /* index of first label (in 'dyd->label->arr') */ 157 | short ndebugvars; /* number of elements in 'f->locvars' */ 158 | lu_byte nactvar; /* number of active local variables */ 159 | lu_byte nups; /* number of upvalues */ 160 | lu_byte freereg; /* first free register */ 161 | lu_byte iwthabs; /* instructions issued since last absolute line info */ 162 | lu_byte needclose; /* function needs to close upvalues when returning */ 163 | } FuncState; 164 | 165 | 166 | LUAI_FUNC int luaY_nvarstack (FuncState *fs); 167 | LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, 168 | Dyndata *dyd, const char *name, int firstchar); 169 | 170 | 171 | #endif 172 | -------------------------------------------------------------------------------- /lua/ltable.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltable.h $ 3 | ** Lua tables (hash) 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ltable_h 8 | #define ltable_h 9 | 10 | #include "lobject.h" 11 | 12 | 13 | #define gnode(t,i) (&(t)->node[i]) 14 | #define gval(n) (&(n)->i_val) 15 | #define gnext(n) ((n)->u.next) 16 | 17 | 18 | /* 19 | ** Clear all bits of fast-access metamethods, which means that the table 20 | ** may have any of these metamethods. (First access that fails after the 21 | ** clearing will set the bit again.) 22 | */ 23 | #define invalidateTMcache(t) ((t)->flags &= ~maskflags) 24 | 25 | 26 | /* 27 | ** Bit BITDUMMY set in 'flags' means the table is using the dummy node 28 | ** for its hash part. 29 | */ 30 | 31 | #define BITDUMMY (1 << 6) 32 | #define NOTBITDUMMY cast_byte(~BITDUMMY) 33 | #define isdummy(t) ((t)->flags & BITDUMMY) 34 | 35 | #define setnodummy(t) ((t)->flags &= NOTBITDUMMY) 36 | #define setdummy(t) ((t)->flags |= BITDUMMY) 37 | 38 | 39 | 40 | /* allocated size for hash nodes */ 41 | #define allocsizenode(t) (isdummy(t) ? 0 : sizenode(t)) 42 | 43 | 44 | /* returns the Node, given the value of a table entry */ 45 | #define nodefromval(v) cast(Node *, (v)) 46 | 47 | 48 | 49 | #define luaH_fastgeti(t,k,res,tag) \ 50 | { Table *h = t; lua_Unsigned u = l_castS2U(k) - 1u; \ 51 | if ((u < h->alimit)) { \ 52 | tag = *getArrTag(h, u); \ 53 | if (!tagisempty(tag)) { farr2val(h, u, tag, res); }} \ 54 | else { tag = luaH_getint(h, (k), res); }} 55 | 56 | 57 | #define luaH_fastseti(t,k,val,hres) \ 58 | { Table *h = t; lua_Unsigned u = l_castS2U(k) - 1u; \ 59 | if ((u < h->alimit)) { \ 60 | lu_byte *tag = getArrTag(h, u); \ 61 | if (tagisempty(*tag)) hres = ~cast_int(u); \ 62 | else { fval2arr(h, u, tag, val); hres = HOK; }} \ 63 | else { hres = luaH_psetint(h, k, val); }} 64 | 65 | 66 | /* results from pset */ 67 | #define HOK 0 68 | #define HNOTFOUND 1 69 | #define HNOTATABLE 2 70 | #define HFIRSTNODE 3 71 | 72 | /* 73 | ** 'luaH_get*' operations set 'res', unless the value is absent, and 74 | ** return the tag of the result. 75 | ** The 'luaH_pset*' (pre-set) operations set the given value and return 76 | ** HOK, unless the original value is absent. In that case, if the key 77 | ** is really absent, they return HNOTFOUND. Otherwise, if there is a 78 | ** slot with that key but with no value, 'luaH_pset*' return an encoding 79 | ** of where the key is (usually called 'hres'). (pset cannot set that 80 | ** value because there might be a metamethod.) If the slot is in the 81 | ** hash part, the encoding is (HFIRSTNODE + hash index); if the slot is 82 | ** in the array part, the encoding is (~array index), a negative value. 83 | ** The value HNOTATABLE is used by the fast macros to signal that the 84 | ** value being indexed is not a table. 85 | ** (The size for the array part is limited by the maximum power of two 86 | ** that fits in an unsigned integer; that is INT_MAX+1. So, the C-index 87 | ** ranges from 0, which encodes to -1, to INT_MAX, which encodes to 88 | ** INT_MIN. The size of the hash part is limited by the maximum power of 89 | ** two that fits in a signed integer; that is (INT_MAX+1)/2. So, it is 90 | ** safe to add HFIRSTNODE to any index there.) 91 | */ 92 | 93 | 94 | /* 95 | ** The array part of a table is represented by an inverted array of 96 | ** values followed by an array of tags, to avoid wasting space with 97 | ** padding. The 'array' pointer points to the junction of the two 98 | ** arrays, so that values are indexed with negative indices and tags 99 | ** with non-negative indices. 100 | 101 | Values Tags 102 | -------------------------------------------------------- 103 | ... | Value 1 | Value 0 |0|1|... 104 | -------------------------------------------------------- 105 | ^ t->array 106 | 107 | ** All accesses to 't->array' should be through the macros 'getArrTag' 108 | ** and 'getArrVal'. 109 | */ 110 | 111 | /* Computes the address of the tag for the abstract C-index 'k' */ 112 | #define getArrTag(t,k) (cast(lu_byte*, (t)->array) + (k)) 113 | 114 | /* Computes the address of the value for the abstract C-index 'k' */ 115 | #define getArrVal(t,k) ((t)->array - 1 - (k)) 116 | 117 | 118 | /* 119 | ** Move TValues to/from arrays, using C indices 120 | */ 121 | #define arr2obj(h,k,val) \ 122 | ((val)->tt_ = *getArrTag(h,(k)), (val)->value_ = *getArrVal(h,(k))) 123 | 124 | #define obj2arr(h,k,val) \ 125 | (*getArrTag(h,(k)) = (val)->tt_, *getArrVal(h,(k)) = (val)->value_) 126 | 127 | 128 | /* 129 | ** Often, we need to check the tag of a value before moving it. The 130 | ** following macros also move TValues to/from arrays, but receive the 131 | ** precomputed tag value or address as an extra argument. 132 | */ 133 | #define farr2val(h,k,tag,res) \ 134 | ((res)->tt_ = tag, (res)->value_ = *getArrVal(h,(k))) 135 | 136 | #define fval2arr(h,k,tag,val) \ 137 | (*tag = (val)->tt_, *getArrVal(h,(k)) = (val)->value_) 138 | 139 | 140 | LUAI_FUNC int luaH_get (Table *t, const TValue *key, TValue *res); 141 | LUAI_FUNC int luaH_getshortstr (Table *t, TString *key, TValue *res); 142 | LUAI_FUNC int luaH_getstr (Table *t, TString *key, TValue *res); 143 | LUAI_FUNC int luaH_getint (Table *t, lua_Integer key, TValue *res); 144 | 145 | /* Special get for metamethods */ 146 | LUAI_FUNC const TValue *luaH_Hgetshortstr (Table *t, TString *key); 147 | 148 | LUAI_FUNC TString *luaH_getstrkey (Table *t, TString *key); 149 | 150 | LUAI_FUNC int luaH_psetint (Table *t, lua_Integer key, TValue *val); 151 | LUAI_FUNC int luaH_psetshortstr (Table *t, TString *key, TValue *val); 152 | LUAI_FUNC int luaH_psetstr (Table *t, TString *key, TValue *val); 153 | LUAI_FUNC int luaH_pset (Table *t, const TValue *key, TValue *val); 154 | 155 | LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, 156 | TValue *value); 157 | LUAI_FUNC void luaH_set (lua_State *L, Table *t, const TValue *key, 158 | TValue *value); 159 | 160 | LUAI_FUNC void luaH_finishset (lua_State *L, Table *t, const TValue *key, 161 | TValue *value, int hres); 162 | LUAI_FUNC Table *luaH_new (lua_State *L); 163 | LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned nasize, 164 | unsigned nhsize); 165 | LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned nasize); 166 | LUAI_FUNC void luaH_free (lua_State *L, Table *t); 167 | LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); 168 | LUAI_FUNC lua_Unsigned luaH_getn (Table *t); 169 | LUAI_FUNC unsigned luaH_realasize (const Table *t); 170 | 171 | 172 | #if defined(LUA_DEBUG) 173 | LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); 174 | #endif 175 | 176 | 177 | #endif 178 | -------------------------------------------------------------------------------- /lua/lmem.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lmem.c $ 3 | ** Interface to Memory Manager 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lmem_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "ldebug.h" 18 | #include "ldo.h" 19 | #include "lgc.h" 20 | #include "lmem.h" 21 | #include "lobject.h" 22 | #include "lstate.h" 23 | 24 | 25 | 26 | /* 27 | ** About the realloc function: 28 | ** void *frealloc (void *ud, void *ptr, size_t osize, size_t nsize); 29 | ** ('osize' is the old size, 'nsize' is the new size) 30 | ** 31 | ** - frealloc(ud, p, x, 0) frees the block 'p' and returns NULL. 32 | ** Particularly, frealloc(ud, NULL, 0, 0) does nothing, 33 | ** which is equivalent to free(NULL) in ISO C. 34 | ** 35 | ** - frealloc(ud, NULL, x, s) creates a new block of size 's' 36 | ** (no matter 'x'). Returns NULL if it cannot create the new block. 37 | ** 38 | ** - otherwise, frealloc(ud, b, x, y) reallocates the block 'b' from 39 | ** size 'x' to size 'y'. Returns NULL if it cannot reallocate the 40 | ** block to the new size. 41 | */ 42 | 43 | 44 | /* 45 | ** Macro to call the allocation function. 46 | */ 47 | #define callfrealloc(g,block,os,ns) ((*g->frealloc)(g->ud, block, os, ns)) 48 | 49 | 50 | /* 51 | ** When an allocation fails, it will try again after an emergency 52 | ** collection, except when it cannot run a collection. The GC should 53 | ** not be called while the state is not fully built, as the collector 54 | ** is not yet fully initialized. Also, it should not be called when 55 | ** 'gcstopem' is true, because then the interpreter is in the middle of 56 | ** a collection step. 57 | */ 58 | #define cantryagain(g) (completestate(g) && !g->gcstopem) 59 | 60 | 61 | 62 | 63 | #if defined(EMERGENCYGCTESTS) 64 | /* 65 | ** First allocation will fail except when freeing a block (frees never 66 | ** fail) and when it cannot try again; this fail will trigger 'tryagain' 67 | ** and a full GC cycle at every allocation. 68 | */ 69 | static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { 70 | if (ns > 0 && cantryagain(g)) 71 | return NULL; /* fail */ 72 | else /* normal allocation */ 73 | return callfrealloc(g, block, os, ns); 74 | } 75 | #else 76 | #define firsttry(g,block,os,ns) callfrealloc(g, block, os, ns) 77 | #endif 78 | 79 | 80 | 81 | 82 | 83 | /* 84 | ** {================================================================== 85 | ** Functions to allocate/deallocate arrays for the Parser 86 | ** =================================================================== 87 | */ 88 | 89 | /* 90 | ** Minimum size for arrays during parsing, to avoid overhead of 91 | ** reallocating to size 1, then 2, and then 4. All these arrays 92 | ** will be reallocated to exact sizes or erased when parsing ends. 93 | */ 94 | #define MINSIZEARRAY 4 95 | 96 | 97 | void *luaM_growaux_ (lua_State *L, void *block, int nelems, int *psize, 98 | int size_elems, int limit, const char *what) { 99 | void *newblock; 100 | int size = *psize; 101 | if (nelems + 1 <= size) /* does one extra element still fit? */ 102 | return block; /* nothing to be done */ 103 | if (size >= limit / 2) { /* cannot double it? */ 104 | if (l_unlikely(size >= limit)) /* cannot grow even a little? */ 105 | luaG_runerror(L, "too many %s (limit is %d)", what, limit); 106 | size = limit; /* still have at least one free place */ 107 | } 108 | else { 109 | size *= 2; 110 | if (size < MINSIZEARRAY) 111 | size = MINSIZEARRAY; /* minimum size */ 112 | } 113 | lua_assert(nelems + 1 <= size && size <= limit); 114 | /* 'limit' ensures that multiplication will not overflow */ 115 | newblock = luaM_saferealloc_(L, block, cast_sizet(*psize) * size_elems, 116 | cast_sizet(size) * size_elems); 117 | *psize = size; /* update only when everything else is OK */ 118 | return newblock; 119 | } 120 | 121 | 122 | /* 123 | ** In prototypes, the size of the array is also its number of 124 | ** elements (to save memory). So, if it cannot shrink an array 125 | ** to its number of elements, the only option is to raise an 126 | ** error. 127 | */ 128 | void *luaM_shrinkvector_ (lua_State *L, void *block, int *size, 129 | int final_n, int size_elem) { 130 | void *newblock; 131 | size_t oldsize = cast_sizet((*size) * size_elem); 132 | size_t newsize = cast_sizet(final_n * size_elem); 133 | lua_assert(newsize <= oldsize); 134 | newblock = luaM_saferealloc_(L, block, oldsize, newsize); 135 | *size = final_n; 136 | return newblock; 137 | } 138 | 139 | /* }================================================================== */ 140 | 141 | 142 | l_noret luaM_toobig (lua_State *L) { 143 | luaG_runerror(L, "memory allocation error: block too big"); 144 | } 145 | 146 | 147 | /* 148 | ** Free memory 149 | */ 150 | void luaM_free_ (lua_State *L, void *block, size_t osize) { 151 | global_State *g = G(L); 152 | lua_assert((osize == 0) == (block == NULL)); 153 | callfrealloc(g, block, osize, 0); 154 | g->totalbytes -= osize; 155 | } 156 | 157 | 158 | /* 159 | ** In case of allocation fail, this function will do an emergency 160 | ** collection to free some memory and then try the allocation again. 161 | */ 162 | static void *tryagain (lua_State *L, void *block, 163 | size_t osize, size_t nsize) { 164 | global_State *g = G(L); 165 | if (cantryagain(g)) { 166 | luaC_fullgc(L, 1); /* try to free some memory... */ 167 | return callfrealloc(g, block, osize, nsize); /* try again */ 168 | } 169 | else return NULL; /* cannot run an emergency collection */ 170 | } 171 | 172 | 173 | /* 174 | ** Generic allocation routine. 175 | */ 176 | void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { 177 | void *newblock; 178 | global_State *g = G(L); 179 | lua_assert((osize == 0) == (block == NULL)); 180 | newblock = firsttry(g, block, osize, nsize); 181 | if (l_unlikely(newblock == NULL && nsize > 0)) { 182 | newblock = tryagain(L, block, osize, nsize); 183 | if (newblock == NULL) /* still no memory? */ 184 | return NULL; /* do not update 'totalbytes' */ 185 | } 186 | lua_assert((nsize == 0) == (newblock == NULL)); 187 | g->totalbytes += nsize - osize; 188 | return newblock; 189 | } 190 | 191 | 192 | void *luaM_saferealloc_ (lua_State *L, void *block, size_t osize, 193 | size_t nsize) { 194 | void *newblock = luaM_realloc_(L, block, osize, nsize); 195 | if (l_unlikely(newblock == NULL && nsize > 0)) /* allocation failed? */ 196 | luaM_error(L); 197 | return newblock; 198 | } 199 | 200 | 201 | void *luaM_malloc_ (lua_State *L, size_t size, int tag) { 202 | if (size == 0) 203 | return NULL; /* that's all */ 204 | else { 205 | global_State *g = G(L); 206 | void *newblock = firsttry(g, NULL, tag, size); 207 | if (l_unlikely(newblock == NULL)) { 208 | newblock = tryagain(L, NULL, tag, size); 209 | if (newblock == NULL) 210 | luaM_error(L); 211 | } 212 | g->totalbytes += size; 213 | return newblock; 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /lua/llimits.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: llimits.h $ 3 | ** Limits, basic types, and some other 'installation-dependent' definitions 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef llimits_h 8 | #define llimits_h 9 | 10 | 11 | #include 12 | #include 13 | 14 | 15 | #include "lua.h" 16 | 17 | 18 | /* 19 | ** 'lu_mem' is an unsigned integer big enough to count the total memory 20 | ** used by Lua (in bytes). 'l_obj' is a signed integer big enough to 21 | ** count the total number of objects used by Lua. (It is signed due 22 | ** to the use of debt in several computations.) Usually, 'size_t' and 23 | ** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines. 24 | */ 25 | #if defined(LUAI_MEM) /* { external definitions? */ 26 | typedef LUAI_UMEM lu_mem; 27 | typedef LUAI_MEM l_obj; 28 | #elif LUAI_IS32INT /* }{ */ 29 | typedef size_t lu_mem; 30 | typedef ptrdiff_t l_obj; 31 | #else /* 16-bit ints */ /* }{ */ 32 | typedef unsigned long lu_mem; 33 | typedef long l_obj; 34 | #endif /* } */ 35 | 36 | #define MAX_LOBJ \ 37 | cast(l_obj, (cast(lu_mem, 1) << (sizeof(l_obj) * CHAR_BIT - 1)) - 1) 38 | 39 | 40 | /* chars used as small naturals (so that 'char' is reserved for characters) */ 41 | typedef unsigned char lu_byte; 42 | typedef signed char ls_byte; 43 | 44 | 45 | /* maximum value for size_t */ 46 | #define MAX_SIZET ((size_t)(~(size_t)0)) 47 | 48 | /* 49 | ** Maximum size for strings and userdata visible for Lua; should be 50 | ** representable as a lua_Integer and as a size_t. 51 | */ 52 | #define MAX_SIZE (sizeof(size_t) < sizeof(lua_Integer) ? MAX_SIZET \ 53 | : cast_sizet(LUA_MAXINTEGER)) 54 | 55 | /* 56 | ** floor of the log2 of the maximum signed value for integral type 't'. 57 | ** (That is, maximum 'n' such that '2^n' fits in the given signed type.) 58 | */ 59 | #define log2maxs(t) cast_int(sizeof(t) * 8 - 2) 60 | 61 | 62 | /* 63 | ** test whether an unsigned value is a power of 2 (or zero) 64 | */ 65 | #define ispow2(x) (((x) & ((x) - 1)) == 0) 66 | 67 | 68 | /* number of chars of a literal string without the ending \0 */ 69 | #define LL(x) (sizeof(x)/sizeof(char) - 1) 70 | 71 | 72 | /* 73 | ** conversion of pointer to unsigned integer: this is for hashing only; 74 | ** there is no problem if the integer cannot hold the whole pointer 75 | ** value. (In strict ISO C this may cause undefined behavior, but no 76 | ** actual machine seems to bother.) 77 | */ 78 | #if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \ 79 | __STDC_VERSION__ >= 199901L 80 | #include 81 | #if defined(UINTPTR_MAX) /* even in C99 this type is optional */ 82 | #define L_P2I uintptr_t 83 | #else /* no 'intptr'? */ 84 | #define L_P2I uintmax_t /* use the largest available integer */ 85 | #endif 86 | #else /* C89 option */ 87 | #define L_P2I size_t 88 | #endif 89 | 90 | #define point2uint(p) cast_uint((L_P2I)(p) & UINT_MAX) 91 | 92 | 93 | 94 | /* types of 'usual argument conversions' for lua_Number and lua_Integer */ 95 | typedef LUAI_UACNUMBER l_uacNumber; 96 | typedef LUAI_UACINT l_uacInt; 97 | 98 | 99 | /* 100 | ** Internal assertions for in-house debugging 101 | */ 102 | #if defined LUAI_ASSERT 103 | #undef NDEBUG 104 | #include 105 | #define lua_assert(c) assert(c) 106 | #endif 107 | 108 | #if defined(lua_assert) 109 | #define check_exp(c,e) (lua_assert(c), (e)) 110 | /* to avoid problems with conditions too long */ 111 | #define lua_longassert(c) ((c) ? (void)0 : lua_assert(0)) 112 | #else 113 | #define lua_assert(c) ((void)0) 114 | #define check_exp(c,e) (e) 115 | #define lua_longassert(c) ((void)0) 116 | #endif 117 | 118 | 119 | /* macro to avoid warnings about unused variables */ 120 | #if !defined(UNUSED) 121 | #define UNUSED(x) ((void)(x)) 122 | #endif 123 | 124 | 125 | /* type casts (a macro highlights casts in the code) */ 126 | #define cast(t, exp) ((t)(exp)) 127 | 128 | #define cast_void(i) cast(void, (i)) 129 | #define cast_voidp(i) cast(void *, (i)) 130 | #define cast_num(i) cast(lua_Number, (i)) 131 | #define cast_int(i) cast(int, (i)) 132 | #define cast_uint(i) cast(unsigned int, (i)) 133 | #define cast_byte(i) cast(lu_byte, (i)) 134 | #define cast_uchar(i) cast(unsigned char, (i)) 135 | #define cast_char(i) cast(char, (i)) 136 | #define cast_charp(i) cast(char *, (i)) 137 | #define cast_sizet(i) cast(size_t, (i)) 138 | 139 | 140 | /* cast a signed lua_Integer to lua_Unsigned */ 141 | #if !defined(l_castS2U) 142 | #define l_castS2U(i) ((lua_Unsigned)(i)) 143 | #endif 144 | 145 | /* 146 | ** cast a lua_Unsigned to a signed lua_Integer; this cast is 147 | ** not strict ISO C, but two-complement architectures should 148 | ** work fine. 149 | */ 150 | #if !defined(l_castU2S) 151 | #define l_castU2S(i) ((lua_Integer)(i)) 152 | #endif 153 | 154 | 155 | /* 156 | ** non-return type 157 | */ 158 | #if !defined(l_noret) 159 | 160 | #if defined(__GNUC__) 161 | #define l_noret void __attribute__((noreturn)) 162 | #elif defined(_MSC_VER) && _MSC_VER >= 1200 163 | #define l_noret void __declspec(noreturn) 164 | #else 165 | #define l_noret void 166 | #endif 167 | 168 | #endif 169 | 170 | 171 | /* 172 | ** Inline functions 173 | */ 174 | #if !defined(LUA_USE_C89) 175 | #define l_inline inline 176 | #elif defined(__GNUC__) 177 | #define l_inline __inline__ 178 | #else 179 | #define l_inline /* empty */ 180 | #endif 181 | 182 | #define l_sinline static l_inline 183 | 184 | 185 | /* 186 | ** An unsigned with (at least) 4 bytes 187 | */ 188 | #if LUAI_IS32INT 189 | typedef unsigned int l_uint32; 190 | #else 191 | typedef unsigned long l_uint32; 192 | #endif 193 | 194 | 195 | /* 196 | ** The luai_num* macros define the primitive operations over numbers. 197 | */ 198 | 199 | /* floor division (defined as 'floor(a/b)') */ 200 | #if !defined(luai_numidiv) 201 | #define luai_numidiv(L,a,b) ((void)L, l_floor(luai_numdiv(L,a,b))) 202 | #endif 203 | 204 | /* float division */ 205 | #if !defined(luai_numdiv) 206 | #define luai_numdiv(L,a,b) ((a)/(b)) 207 | #endif 208 | 209 | /* 210 | ** modulo: defined as 'a - floor(a/b)*b'; the direct computation 211 | ** using this definition has several problems with rounding errors, 212 | ** so it is better to use 'fmod'. 'fmod' gives the result of 213 | ** 'a - trunc(a/b)*b', and therefore must be corrected when 214 | ** 'trunc(a/b) ~= floor(a/b)'. That happens when the division has a 215 | ** non-integer negative result: non-integer result is equivalent to 216 | ** a non-zero remainder 'm'; negative result is equivalent to 'a' and 217 | ** 'b' with different signs, or 'm' and 'b' with different signs 218 | ** (as the result 'm' of 'fmod' has the same sign of 'a'). 219 | */ 220 | #if !defined(luai_nummod) 221 | #define luai_nummod(L,a,b,m) \ 222 | { (void)L; (m) = l_mathop(fmod)(a,b); \ 223 | if (((m) > 0) ? (b) < 0 : ((m) < 0 && (b) > 0)) (m) += (b); } 224 | #endif 225 | 226 | /* exponentiation */ 227 | #if !defined(luai_numpow) 228 | #define luai_numpow(L,a,b) \ 229 | ((void)L, (b == 2) ? (a)*(a) : l_mathop(pow)(a,b)) 230 | #endif 231 | 232 | /* the others are quite standard operations */ 233 | #if !defined(luai_numadd) 234 | #define luai_numadd(L,a,b) ((a)+(b)) 235 | #define luai_numsub(L,a,b) ((a)-(b)) 236 | #define luai_nummul(L,a,b) ((a)*(b)) 237 | #define luai_numunm(L,a) (-(a)) 238 | #define luai_numeq(a,b) ((a)==(b)) 239 | #define luai_numlt(a,b) ((a)<(b)) 240 | #define luai_numle(a,b) ((a)<=(b)) 241 | #define luai_numgt(a,b) ((a)>(b)) 242 | #define luai_numge(a,b) ((a)>=(b)) 243 | #define luai_numisnan(a) (!luai_numeq((a), (a))) 244 | #endif 245 | 246 | 247 | /* 248 | ** {================================================================== 249 | ** "Abstraction Layer" for basic report of messages and errors 250 | ** =================================================================== 251 | */ 252 | 253 | /* print a string */ 254 | #if !defined(lua_writestring) 255 | #define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) 256 | #endif 257 | 258 | /* print a newline and flush the output */ 259 | #if !defined(lua_writeline) 260 | #define lua_writeline() (lua_writestring("\n", 1), fflush(stdout)) 261 | #endif 262 | 263 | /* print an error message */ 264 | #if !defined(lua_writestringerror) 265 | #define lua_writestringerror(s,p) \ 266 | (fprintf(stderr, (s), (p)), fflush(stderr)) 267 | #endif 268 | 269 | /* }================================================================== */ 270 | 271 | #endif 272 | 273 | -------------------------------------------------------------------------------- /lua/ldump.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ldump.c $ 3 | ** save precompiled Lua chunks 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define ldump_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | #include 15 | 16 | #include "lua.h" 17 | 18 | #include "lapi.h" 19 | #include "lgc.h" 20 | #include "lobject.h" 21 | #include "lstate.h" 22 | #include "ltable.h" 23 | #include "lundump.h" 24 | 25 | 26 | typedef struct { 27 | lua_State *L; 28 | lua_Writer writer; 29 | void *data; 30 | lu_mem offset; /* current position relative to beginning of dump */ 31 | int strip; 32 | int status; 33 | Table *h; /* table to track saved strings */ 34 | lua_Integer nstr; /* counter for counting saved strings */ 35 | } DumpState; 36 | 37 | 38 | /* 39 | ** All high-level dumps go through dumpVector; you can change it to 40 | ** change the endianness of the result 41 | */ 42 | #define dumpVector(D,v,n) dumpBlock(D,v,(n)*sizeof((v)[0])) 43 | 44 | #define dumpLiteral(D, s) dumpBlock(D,s,sizeof(s) - sizeof(char)) 45 | 46 | 47 | /* 48 | ** Dump the block of memory pointed by 'b' with given 'size'. 49 | ** 'b' should not be NULL, except for the last call signaling the end 50 | ** of the dump. 51 | */ 52 | static void dumpBlock (DumpState *D, const void *b, size_t size) { 53 | if (D->status == 0) { /* do not write anything after an error */ 54 | lua_unlock(D->L); 55 | D->status = (*D->writer)(D->L, b, size, D->data); 56 | lua_lock(D->L); 57 | D->offset += size; 58 | } 59 | } 60 | 61 | 62 | /* 63 | ** Dump enough zeros to ensure that current position is a multiple of 64 | ** 'align'. 65 | */ 66 | static void dumpAlign (DumpState *D, int align) { 67 | int padding = align - (D->offset % align); 68 | if (padding < align) { /* padding == align means no padding */ 69 | static lua_Integer paddingContent = 0; 70 | lua_assert(cast_uint(align) <= sizeof(lua_Integer)); 71 | dumpBlock(D, &paddingContent, padding); 72 | } 73 | lua_assert(D->offset % align == 0); 74 | } 75 | 76 | 77 | #define dumpVar(D,x) dumpVector(D,&x,1) 78 | 79 | 80 | static void dumpByte (DumpState *D, int y) { 81 | lu_byte x = (lu_byte)y; 82 | dumpVar(D, x); 83 | } 84 | 85 | 86 | /* 87 | ** size for 'dumpVarint' buffer: each byte can store up to 7 bits. 88 | ** (The "+6" rounds up the division.) 89 | */ 90 | #define DIBS ((sizeof(size_t) * CHAR_BIT + 6) / 7) 91 | 92 | /* 93 | ** Dumps an unsigned integer using the MSB Varint encoding 94 | */ 95 | static void dumpVarint (DumpState *D, size_t x) { 96 | lu_byte buff[DIBS]; 97 | int n = 1; 98 | buff[DIBS - 1] = x & 0x7f; /* fill least-significant byte */ 99 | while ((x >>= 7) != 0) /* fill other bytes in reverse order */ 100 | buff[DIBS - (++n)] = (x & 0x7f) | 0x80; 101 | dumpVector(D, buff + DIBS - n, n); 102 | } 103 | 104 | 105 | static void dumpSize (DumpState *D, size_t sz) { 106 | dumpVarint(D, sz); 107 | } 108 | 109 | static void dumpInt (DumpState *D, int x) { 110 | lua_assert(x >= 0); 111 | dumpVarint(D, cast(size_t, x)); 112 | } 113 | 114 | 115 | static void dumpNumber (DumpState *D, lua_Number x) { 116 | dumpVar(D, x); 117 | } 118 | 119 | 120 | static void dumpInteger (DumpState *D, lua_Integer x) { 121 | dumpVar(D, x); 122 | } 123 | 124 | 125 | /* 126 | ** Dump a String. First dump its "size": size==0 means NULL; 127 | ** size==1 is followed by an index and means "reuse saved string with 128 | ** that index"; size>=2 is followed by the string contents with real 129 | ** size==size-2 and means that string, which will be saved with 130 | ** the next available index. 131 | */ 132 | static void dumpString (DumpState *D, TString *ts) { 133 | if (ts == NULL) 134 | dumpSize(D, 0); 135 | else { 136 | TValue idx; 137 | int tag = luaH_getstr(D->h, ts, &idx); 138 | if (!tagisempty(tag)) { /* string already saved? */ 139 | dumpSize(D, 1); /* reuse a saved string */ 140 | dumpSize(D, cast_sizet(ivalue(&idx))); /* index of saved string */ 141 | } 142 | else { /* must write and save the string */ 143 | TValue key, value; /* to save the string in the hash */ 144 | size_t size; 145 | const char *s = getlstr(ts, size); 146 | dumpSize(D, size + 2); 147 | dumpVector(D, s, size + 1); /* include ending '\0' */ 148 | D->nstr++; /* one more saved string */ 149 | setsvalue(D->L, &key, ts); /* the string is the key */ 150 | setivalue(&value, D->nstr); /* its index is the value */ 151 | luaH_set(D->L, D->h, &key, &value); /* h[ts] = nstr */ 152 | /* integer value does not need barrier */ 153 | } 154 | } 155 | } 156 | 157 | 158 | static void dumpCode (DumpState *D, const Proto *f) { 159 | dumpInt(D, f->sizecode); 160 | dumpAlign(D, sizeof(f->code[0])); 161 | lua_assert(f->code != NULL); 162 | dumpVector(D, f->code, f->sizecode); 163 | } 164 | 165 | 166 | static void dumpFunction (DumpState *D, const Proto *f); 167 | 168 | static void dumpConstants (DumpState *D, const Proto *f) { 169 | int i; 170 | int n = f->sizek; 171 | dumpInt(D, n); 172 | for (i = 0; i < n; i++) { 173 | const TValue *o = &f->k[i]; 174 | int tt = ttypetag(o); 175 | dumpByte(D, tt); 176 | switch (tt) { 177 | case LUA_VNUMFLT: 178 | dumpNumber(D, fltvalue(o)); 179 | break; 180 | case LUA_VNUMINT: 181 | dumpInteger(D, ivalue(o)); 182 | break; 183 | case LUA_VSHRSTR: 184 | case LUA_VLNGSTR: 185 | dumpString(D, tsvalue(o)); 186 | break; 187 | default: 188 | lua_assert(tt == LUA_VNIL || tt == LUA_VFALSE || tt == LUA_VTRUE); 189 | } 190 | } 191 | } 192 | 193 | 194 | static void dumpProtos (DumpState *D, const Proto *f) { 195 | int i; 196 | int n = f->sizep; 197 | dumpInt(D, n); 198 | for (i = 0; i < n; i++) 199 | dumpFunction(D, f->p[i]); 200 | } 201 | 202 | 203 | static void dumpUpvalues (DumpState *D, const Proto *f) { 204 | int i, n = f->sizeupvalues; 205 | dumpInt(D, n); 206 | for (i = 0; i < n; i++) { 207 | dumpByte(D, f->upvalues[i].instack); 208 | dumpByte(D, f->upvalues[i].idx); 209 | dumpByte(D, f->upvalues[i].kind); 210 | } 211 | } 212 | 213 | 214 | static void dumpDebug (DumpState *D, const Proto *f) { 215 | int i, n; 216 | n = (D->strip) ? 0 : f->sizelineinfo; 217 | dumpInt(D, n); 218 | if (f->lineinfo != NULL) 219 | dumpVector(D, f->lineinfo, n); 220 | n = (D->strip) ? 0 : f->sizeabslineinfo; 221 | dumpInt(D, n); 222 | if (n > 0) { 223 | /* 'abslineinfo' is an array of structures of int's */ 224 | dumpAlign(D, sizeof(int)); 225 | dumpVector(D, f->abslineinfo, n); 226 | } 227 | n = (D->strip) ? 0 : f->sizelocvars; 228 | dumpInt(D, n); 229 | for (i = 0; i < n; i++) { 230 | dumpString(D, f->locvars[i].varname); 231 | dumpInt(D, f->locvars[i].startpc); 232 | dumpInt(D, f->locvars[i].endpc); 233 | } 234 | n = (D->strip) ? 0 : f->sizeupvalues; 235 | dumpInt(D, n); 236 | for (i = 0; i < n; i++) 237 | dumpString(D, f->upvalues[i].name); 238 | } 239 | 240 | 241 | static void dumpFunction (DumpState *D, const Proto *f) { 242 | dumpInt(D, f->linedefined); 243 | dumpInt(D, f->lastlinedefined); 244 | dumpByte(D, f->numparams); 245 | dumpByte(D, f->flag); 246 | dumpByte(D, f->maxstacksize); 247 | dumpCode(D, f); 248 | dumpConstants(D, f); 249 | dumpUpvalues(D, f); 250 | dumpProtos(D, f); 251 | dumpString(D, D->strip ? NULL : f->source); 252 | dumpDebug(D, f); 253 | } 254 | 255 | 256 | static void dumpHeader (DumpState *D) { 257 | dumpLiteral(D, LUA_SIGNATURE); 258 | dumpByte(D, LUAC_VERSION); 259 | dumpByte(D, LUAC_FORMAT); 260 | dumpLiteral(D, LUAC_DATA); 261 | dumpByte(D, sizeof(Instruction)); 262 | dumpByte(D, sizeof(lua_Integer)); 263 | dumpByte(D, sizeof(lua_Number)); 264 | dumpInteger(D, LUAC_INT); 265 | dumpNumber(D, LUAC_NUM); 266 | } 267 | 268 | 269 | /* 270 | ** dump Lua function as precompiled chunk 271 | */ 272 | int luaU_dump (lua_State *L, const Proto *f, lua_Writer w, void *data, 273 | int strip) { 274 | DumpState D; 275 | D.h = luaH_new(L); /* aux. table to keep strings already dumped */ 276 | sethvalue2s(L, L->top.p, D.h); /* anchor it */ 277 | L->top.p++; 278 | D.L = L; 279 | D.writer = w; 280 | D.offset = 0; 281 | D.data = data; 282 | D.strip = strip; 283 | D.status = 0; 284 | D.nstr = 0; 285 | dumpHeader(&D); 286 | dumpByte(&D, f->sizeupvalues); 287 | dumpFunction(&D, f); 288 | dumpBlock(&D, NULL, 0); /* signal end of dump */ 289 | return D.status; 290 | } 291 | 292 | -------------------------------------------------------------------------------- /lua/lauxlib.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lauxlib.h $ 3 | ** Auxiliary functions for building Lua libraries 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #ifndef lauxlib_h 9 | #define lauxlib_h 10 | 11 | 12 | #include 13 | #include 14 | 15 | #include "luaconf.h" 16 | #include "lua.h" 17 | 18 | 19 | /* global table */ 20 | #define LUA_GNAME "_G" 21 | 22 | 23 | typedef struct luaL_Buffer luaL_Buffer; 24 | 25 | 26 | /* extra error code for 'luaL_loadfilex' */ 27 | #define LUA_ERRFILE (LUA_ERRERR+1) 28 | 29 | 30 | /* key, in the registry, for table of loaded modules */ 31 | #define LUA_LOADED_TABLE "_LOADED" 32 | 33 | 34 | /* key, in the registry, for table of preloaded loaders */ 35 | #define LUA_PRELOAD_TABLE "_PRELOAD" 36 | 37 | 38 | typedef struct luaL_Reg { 39 | const char *name; 40 | lua_CFunction func; 41 | } luaL_Reg; 42 | 43 | 44 | #define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number)) 45 | 46 | LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz); 47 | #define luaL_checkversion(L) \ 48 | luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES) 49 | 50 | LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); 51 | LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); 52 | LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); 53 | LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg); 54 | LUALIB_API int (luaL_typeerror) (lua_State *L, int arg, const char *tname); 55 | LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg, 56 | size_t *l); 57 | LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg, 58 | const char *def, size_t *l); 59 | LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg); 60 | LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def); 61 | 62 | LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg); 63 | LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg, 64 | lua_Integer def); 65 | 66 | LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); 67 | LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t); 68 | LUALIB_API void (luaL_checkany) (lua_State *L, int arg); 69 | 70 | LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); 71 | LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); 72 | LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); 73 | LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); 74 | 75 | LUALIB_API void (luaL_where) (lua_State *L, int lvl); 76 | LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); 77 | 78 | LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def, 79 | const char *const lst[]); 80 | 81 | LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); 82 | LUALIB_API int (luaL_execresult) (lua_State *L, int stat); 83 | 84 | 85 | /* predefined references */ 86 | #define LUA_NOREF (-2) 87 | #define LUA_REFNIL (-1) 88 | 89 | LUALIB_API int (luaL_ref) (lua_State *L, int t); 90 | LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); 91 | 92 | LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, 93 | const char *mode); 94 | 95 | #define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) 96 | 97 | LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, 98 | const char *name, const char *mode); 99 | LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); 100 | 101 | LUALIB_API lua_State *(luaL_newstate) (void); 102 | 103 | LUALIB_API unsigned luaL_makeseed (lua_State *L); 104 | 105 | LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx); 106 | 107 | LUALIB_API void (luaL_addgsub) (luaL_Buffer *b, const char *s, 108 | const char *p, const char *r); 109 | LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, 110 | const char *p, const char *r); 111 | 112 | LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); 113 | 114 | LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); 115 | 116 | LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, 117 | const char *msg, int level); 118 | 119 | LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, 120 | lua_CFunction openf, int glb); 121 | 122 | /* 123 | ** =============================================================== 124 | ** some useful macros 125 | ** =============================================================== 126 | */ 127 | 128 | 129 | #define luaL_newlibtable(L,l) \ 130 | lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) 131 | 132 | #define luaL_newlib(L,l) \ 133 | (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) 134 | 135 | #define luaL_argcheck(L, cond,arg,extramsg) \ 136 | ((void)(luai_likely(cond) || luaL_argerror(L, (arg), (extramsg)))) 137 | 138 | #define luaL_argexpected(L,cond,arg,tname) \ 139 | ((void)(luai_likely(cond) || luaL_typeerror(L, (arg), (tname)))) 140 | 141 | #define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) 142 | #define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) 143 | 144 | #define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) 145 | 146 | #define luaL_dofile(L, fn) \ 147 | (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) 148 | 149 | #define luaL_dostring(L, s) \ 150 | (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) 151 | 152 | #define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) 153 | 154 | #define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) 155 | 156 | #define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) 157 | 158 | 159 | /* 160 | ** Perform arithmetic operations on lua_Integer values with wrap-around 161 | ** semantics, as the Lua core does. 162 | */ 163 | #define luaL_intop(op,v1,v2) \ 164 | ((lua_Integer)((lua_Unsigned)(v1) op (lua_Unsigned)(v2))) 165 | 166 | 167 | /* push the value used to represent failure/error */ 168 | #define luaL_pushfail(L) lua_pushnil(L) 169 | 170 | 171 | 172 | /* 173 | ** {====================================================== 174 | ** Generic Buffer manipulation 175 | ** ======================================================= 176 | */ 177 | 178 | struct luaL_Buffer { 179 | char *b; /* buffer address */ 180 | size_t size; /* buffer size */ 181 | size_t n; /* number of characters in buffer */ 182 | lua_State *L; 183 | union { 184 | LUAI_MAXALIGN; /* ensure maximum alignment for buffer */ 185 | char b[LUAL_BUFFERSIZE]; /* initial buffer */ 186 | } init; 187 | }; 188 | 189 | 190 | #define luaL_bufflen(bf) ((bf)->n) 191 | #define luaL_buffaddr(bf) ((bf)->b) 192 | 193 | 194 | #define luaL_addchar(B,c) \ 195 | ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ 196 | ((B)->b[(B)->n++] = (c))) 197 | 198 | #define luaL_addsize(B,s) ((B)->n += (s)) 199 | 200 | #define luaL_buffsub(B,s) ((B)->n -= (s)) 201 | 202 | LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); 203 | LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); 204 | LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); 205 | LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); 206 | LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); 207 | LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); 208 | LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); 209 | LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); 210 | 211 | #define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) 212 | 213 | /* }====================================================== */ 214 | 215 | 216 | 217 | /* 218 | ** {====================================================== 219 | ** File handles for IO library 220 | ** ======================================================= 221 | */ 222 | 223 | /* 224 | ** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and 225 | ** initial structure 'luaL_Stream' (it may contain other fields 226 | ** after that initial structure). 227 | */ 228 | 229 | #define LUA_FILEHANDLE "FILE*" 230 | 231 | 232 | typedef struct luaL_Stream { 233 | FILE *f; /* stream (NULL for incompletely created streams) */ 234 | lua_CFunction closef; /* to close stream (NULL for closed streams) */ 235 | } luaL_Stream; 236 | 237 | /* }====================================================== */ 238 | 239 | 240 | /* 241 | ** {============================================================ 242 | ** Compatibility with deprecated conversions 243 | ** ============================================================= 244 | */ 245 | #if defined(LUA_COMPAT_APIINTCASTS) 246 | 247 | #define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a)) 248 | #define luaL_optunsigned(L,a,d) \ 249 | ((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d))) 250 | 251 | #define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) 252 | #define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) 253 | 254 | #define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) 255 | #define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) 256 | 257 | #endif 258 | /* }============================================================ */ 259 | 260 | 261 | 262 | #endif 263 | 264 | 265 | -------------------------------------------------------------------------------- /lua/lutf8lib.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lutf8lib.c $ 3 | ** Standard library for UTF-8 manipulation 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lutf8lib_c 8 | #define LUA_LIB 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "lua.h" 19 | 20 | #include "lauxlib.h" 21 | #include "lualib.h" 22 | #include "llimits.h" 23 | 24 | 25 | #define MAXUNICODE 0x10FFFFu 26 | 27 | #define MAXUTF 0x7FFFFFFFu 28 | 29 | 30 | #define MSGInvalid "invalid UTF-8 code" 31 | 32 | 33 | #define iscont(c) (((c) & 0xC0) == 0x80) 34 | #define iscontp(p) iscont(*(p)) 35 | 36 | 37 | /* from strlib */ 38 | /* translate a relative string position: negative means back from end */ 39 | static lua_Integer u_posrelat (lua_Integer pos, size_t len) { 40 | if (pos >= 0) return pos; 41 | else if (0u - (size_t)pos > len) return 0; 42 | else return (lua_Integer)len + pos + 1; 43 | } 44 | 45 | 46 | /* 47 | ** Decode one UTF-8 sequence, returning NULL if byte sequence is 48 | ** invalid. The array 'limits' stores the minimum value for each 49 | ** sequence length, to check for overlong representations. Its first 50 | ** entry forces an error for non-ascii bytes with no continuation 51 | ** bytes (count == 0). 52 | */ 53 | static const char *utf8_decode (const char *s, l_uint32 *val, int strict) { 54 | static const l_uint32 limits[] = 55 | {~(l_uint32)0, 0x80, 0x800, 0x10000u, 0x200000u, 0x4000000u}; 56 | unsigned int c = (unsigned char)s[0]; 57 | l_uint32 res = 0; /* final result */ 58 | if (c < 0x80) /* ascii? */ 59 | res = c; 60 | else { 61 | int count = 0; /* to count number of continuation bytes */ 62 | for (; c & 0x40; c <<= 1) { /* while it needs continuation bytes... */ 63 | unsigned int cc = (unsigned char)s[++count]; /* read next byte */ 64 | if (!iscont(cc)) /* not a continuation byte? */ 65 | return NULL; /* invalid byte sequence */ 66 | res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ 67 | } 68 | res |= ((l_uint32)(c & 0x7F) << (count * 5)); /* add first byte */ 69 | if (count > 5 || res > MAXUTF || res < limits[count]) 70 | return NULL; /* invalid byte sequence */ 71 | s += count; /* skip continuation bytes read */ 72 | } 73 | if (strict) { 74 | /* check for invalid code points; too large or surrogates */ 75 | if (res > MAXUNICODE || (0xD800u <= res && res <= 0xDFFFu)) 76 | return NULL; 77 | } 78 | if (val) *val = res; 79 | return s + 1; /* +1 to include first byte */ 80 | } 81 | 82 | 83 | /* 84 | ** utf8len(s [, i [, j [, lax]]]) --> number of characters that 85 | ** start in the range [i,j], or nil + current position if 's' is not 86 | ** well formed in that interval 87 | */ 88 | static int utflen (lua_State *L) { 89 | lua_Integer n = 0; /* counter for the number of characters */ 90 | size_t len; /* string length in bytes */ 91 | const char *s = luaL_checklstring(L, 1, &len); 92 | lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); 93 | lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len); 94 | int lax = lua_toboolean(L, 4); 95 | luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2, 96 | "initial position out of bounds"); 97 | luaL_argcheck(L, --posj < (lua_Integer)len, 3, 98 | "final position out of bounds"); 99 | while (posi <= posj) { 100 | const char *s1 = utf8_decode(s + posi, NULL, !lax); 101 | if (s1 == NULL) { /* conversion error? */ 102 | luaL_pushfail(L); /* return fail ... */ 103 | lua_pushinteger(L, posi + 1); /* ... and current position */ 104 | return 2; 105 | } 106 | posi = s1 - s; 107 | n++; 108 | } 109 | lua_pushinteger(L, n); 110 | return 1; 111 | } 112 | 113 | 114 | /* 115 | ** codepoint(s, [i, [j [, lax]]]) -> returns codepoints for all 116 | ** characters that start in the range [i,j] 117 | */ 118 | static int codepoint (lua_State *L) { 119 | size_t len; 120 | const char *s = luaL_checklstring(L, 1, &len); 121 | lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); 122 | lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len); 123 | int lax = lua_toboolean(L, 4); 124 | int n; 125 | const char *se; 126 | luaL_argcheck(L, posi >= 1, 2, "out of bounds"); 127 | luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of bounds"); 128 | if (posi > pose) return 0; /* empty interval; return no values */ 129 | if (pose - posi >= INT_MAX) /* (lua_Integer -> int) overflow? */ 130 | return luaL_error(L, "string slice too long"); 131 | n = (int)(pose - posi) + 1; /* upper bound for number of returns */ 132 | luaL_checkstack(L, n, "string slice too long"); 133 | n = 0; /* count the number of returns */ 134 | se = s + pose; /* string end */ 135 | for (s += posi - 1; s < se;) { 136 | l_uint32 code; 137 | s = utf8_decode(s, &code, !lax); 138 | if (s == NULL) 139 | return luaL_error(L, MSGInvalid); 140 | lua_pushinteger(L, code); 141 | n++; 142 | } 143 | return n; 144 | } 145 | 146 | 147 | static void pushutfchar (lua_State *L, int arg) { 148 | lua_Unsigned code = (lua_Unsigned)luaL_checkinteger(L, arg); 149 | luaL_argcheck(L, code <= MAXUTF, arg, "value out of range"); 150 | lua_pushfstring(L, "%U", (long)code); 151 | } 152 | 153 | 154 | /* 155 | ** utfchar(n1, n2, ...) -> char(n1)..char(n2)... 156 | */ 157 | static int utfchar (lua_State *L) { 158 | int n = lua_gettop(L); /* number of arguments */ 159 | if (n == 1) /* optimize common case of single char */ 160 | pushutfchar(L, 1); 161 | else { 162 | int i; 163 | luaL_Buffer b; 164 | luaL_buffinit(L, &b); 165 | for (i = 1; i <= n; i++) { 166 | pushutfchar(L, i); 167 | luaL_addvalue(&b); 168 | } 169 | luaL_pushresult(&b); 170 | } 171 | return 1; 172 | } 173 | 174 | 175 | /* 176 | ** offset(s, n, [i]) -> indices where n-th character counting from 177 | ** position 'i' starts and ends; 0 means character at 'i'. 178 | */ 179 | static int byteoffset (lua_State *L) { 180 | size_t len; 181 | const char *s = luaL_checklstring(L, 1, &len); 182 | lua_Integer n = luaL_checkinteger(L, 2); 183 | lua_Integer posi = (n >= 0) ? 1 : len + 1; 184 | posi = u_posrelat(luaL_optinteger(L, 3, posi), len); 185 | luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3, 186 | "position out of bounds"); 187 | if (n == 0) { 188 | /* find beginning of current byte sequence */ 189 | while (posi > 0 && iscontp(s + posi)) posi--; 190 | } 191 | else { 192 | if (iscontp(s + posi)) 193 | return luaL_error(L, "initial position is a continuation byte"); 194 | if (n < 0) { 195 | while (n < 0 && posi > 0) { /* move back */ 196 | do { /* find beginning of previous character */ 197 | posi--; 198 | } while (posi > 0 && iscontp(s + posi)); 199 | n++; 200 | } 201 | } 202 | else { 203 | n--; /* do not move for 1st character */ 204 | while (n > 0 && posi < (lua_Integer)len) { 205 | do { /* find beginning of next character */ 206 | posi++; 207 | } while (iscontp(s + posi)); /* (cannot pass final '\0') */ 208 | n--; 209 | } 210 | } 211 | } 212 | if (n != 0) { /* did not find given character? */ 213 | luaL_pushfail(L); 214 | return 1; 215 | } 216 | lua_pushinteger(L, posi + 1); /* initial position */ 217 | if ((s[posi] & 0x80) != 0) { /* multi-byte character? */ 218 | do { 219 | posi++; 220 | } while (iscontp(s + posi + 1)); /* skip to final byte */ 221 | } 222 | /* else one-byte character: final position is the initial one */ 223 | lua_pushinteger(L, posi + 1); /* 'posi' now is the final position */ 224 | return 2; 225 | } 226 | 227 | 228 | static int iter_aux (lua_State *L, int strict) { 229 | size_t len; 230 | const char *s = luaL_checklstring(L, 1, &len); 231 | lua_Unsigned n = (lua_Unsigned)lua_tointeger(L, 2); 232 | if (n < len) { 233 | while (iscontp(s + n)) n++; /* go to next character */ 234 | } 235 | if (n >= len) /* (also handles original 'n' being negative) */ 236 | return 0; /* no more codepoints */ 237 | else { 238 | l_uint32 code; 239 | const char *next = utf8_decode(s + n, &code, strict); 240 | if (next == NULL || iscontp(next)) 241 | return luaL_error(L, MSGInvalid); 242 | lua_pushinteger(L, n + 1); 243 | lua_pushinteger(L, code); 244 | return 2; 245 | } 246 | } 247 | 248 | 249 | static int iter_auxstrict (lua_State *L) { 250 | return iter_aux(L, 1); 251 | } 252 | 253 | static int iter_auxlax (lua_State *L) { 254 | return iter_aux(L, 0); 255 | } 256 | 257 | 258 | static int iter_codes (lua_State *L) { 259 | int lax = lua_toboolean(L, 2); 260 | const char *s = luaL_checkstring(L, 1); 261 | luaL_argcheck(L, !iscontp(s), 1, MSGInvalid); 262 | lua_pushcfunction(L, lax ? iter_auxlax : iter_auxstrict); 263 | lua_pushvalue(L, 1); 264 | lua_pushinteger(L, 0); 265 | return 3; 266 | } 267 | 268 | 269 | /* pattern to match a single UTF-8 character */ 270 | #define UTF8PATT "[\0-\x7F\xC2-\xFD][\x80-\xBF]*" 271 | 272 | 273 | static const luaL_Reg funcs[] = { 274 | {"offset", byteoffset}, 275 | {"codepoint", codepoint}, 276 | {"char", utfchar}, 277 | {"len", utflen}, 278 | {"codes", iter_codes}, 279 | /* placeholders */ 280 | {"charpattern", NULL}, 281 | {NULL, NULL} 282 | }; 283 | 284 | 285 | LUAMOD_API int luaopen_utf8 (lua_State *L) { 286 | luaL_newlib(L, funcs); 287 | lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT)/sizeof(char) - 1); 288 | lua_setfield(L, -2, "charpattern"); 289 | return 1; 290 | } 291 | 292 | -------------------------------------------------------------------------------- /lua/ltm.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltm.c $ 3 | ** Tag methods 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define ltm_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "ldebug.h" 18 | #include "ldo.h" 19 | #include "lgc.h" 20 | #include "lobject.h" 21 | #include "lstate.h" 22 | #include "lstring.h" 23 | #include "ltable.h" 24 | #include "ltm.h" 25 | #include "lvm.h" 26 | 27 | 28 | static const char udatatypename[] = "userdata"; 29 | 30 | LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTYPES] = { 31 | "no value", 32 | "nil", "boolean", udatatypename, "number", 33 | "string", "table", "function", udatatypename, "thread", 34 | "upvalue", "proto" /* these last cases are used for tests only */ 35 | }; 36 | 37 | 38 | void luaT_init (lua_State *L) { 39 | static const char *const luaT_eventname[] = { /* ORDER TM */ 40 | "__index", "__newindex", 41 | "__gc", "__mode", "__len", "__eq", 42 | "__add", "__sub", "__mul", "__mod", "__pow", 43 | "__div", "__idiv", 44 | "__band", "__bor", "__bxor", "__shl", "__shr", 45 | "__unm", "__bnot", "__lt", "__le", 46 | "__concat", "__call", "__close" 47 | }; 48 | int i; 49 | for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); 51 | luaC_fix(L, obj2gco(G(L)->tmname[i])); /* never collect these names */ 52 | } 53 | } 54 | 55 | 56 | /* 57 | ** function to be used with macro "fasttm": optimized for absence of 58 | ** tag methods 59 | */ 60 | const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { 61 | const TValue *tm = luaH_Hgetshortstr(events, ename); 62 | lua_assert(event <= TM_EQ); 63 | if (notm(tm)) { /* no tag method? */ 64 | events->flags |= cast_byte(1u<metatable; 76 | break; 77 | case LUA_TUSERDATA: 78 | mt = uvalue(o)->metatable; 79 | break; 80 | default: 81 | mt = G(L)->mt[ttype(o)]; 82 | } 83 | return (mt ? luaH_Hgetshortstr(mt, G(L)->tmname[event]) : &G(L)->nilvalue); 84 | } 85 | 86 | 87 | /* 88 | ** Return the name of the type of an object. For tables and userdata 89 | ** with metatable, use their '__name' metafield, if present. 90 | */ 91 | const char *luaT_objtypename (lua_State *L, const TValue *o) { 92 | Table *mt; 93 | if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) || 94 | (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) { 95 | const TValue *name = luaH_Hgetshortstr(mt, luaS_new(L, "__name")); 96 | if (ttisstring(name)) /* is '__name' a string? */ 97 | return getstr(tsvalue(name)); /* use it as type name */ 98 | } 99 | return ttypename(ttype(o)); /* else use standard type name */ 100 | } 101 | 102 | 103 | void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, 104 | const TValue *p2, const TValue *p3) { 105 | StkId func = L->top.p; 106 | setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ 107 | setobj2s(L, func + 1, p1); /* 1st argument */ 108 | setobj2s(L, func + 2, p2); /* 2nd argument */ 109 | setobj2s(L, func + 3, p3); /* 3rd argument */ 110 | L->top.p = func + 4; 111 | /* metamethod may yield only when called from Lua code */ 112 | if (isLuacode(L->ci)) 113 | luaD_call(L, func, 0); 114 | else 115 | luaD_callnoyield(L, func, 0); 116 | } 117 | 118 | 119 | int luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1, 120 | const TValue *p2, StkId res) { 121 | ptrdiff_t result = savestack(L, res); 122 | StkId func = L->top.p; 123 | setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ 124 | setobj2s(L, func + 1, p1); /* 1st argument */ 125 | setobj2s(L, func + 2, p2); /* 2nd argument */ 126 | L->top.p += 3; 127 | /* metamethod may yield only when called from Lua code */ 128 | if (isLuacode(L->ci)) 129 | luaD_call(L, func, 1); 130 | else 131 | luaD_callnoyield(L, func, 1); 132 | res = restorestack(L, result); 133 | setobjs2s(L, res, --L->top.p); /* move result to its place */ 134 | return ttypetag(s2v(res)); /* return tag of the result */ 135 | } 136 | 137 | 138 | static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2, 139 | StkId res, TMS event) { 140 | const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ 141 | if (notm(tm)) 142 | tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ 143 | if (notm(tm)) 144 | return -1; /* tag method not found */ 145 | else /* call tag method and return the tag of the result */ 146 | return luaT_callTMres(L, tm, p1, p2, res); 147 | } 148 | 149 | 150 | void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, 151 | StkId res, TMS event) { 152 | if (l_unlikely(callbinTM(L, p1, p2, res, event) < 0)) { 153 | switch (event) { 154 | case TM_BAND: case TM_BOR: case TM_BXOR: 155 | case TM_SHL: case TM_SHR: case TM_BNOT: { 156 | if (ttisnumber(p1) && ttisnumber(p2)) 157 | luaG_tointerror(L, p1, p2); 158 | else 159 | luaG_opinterror(L, p1, p2, "perform bitwise operation on"); 160 | } 161 | /* calls never return, but to avoid warnings: *//* FALLTHROUGH */ 162 | default: 163 | luaG_opinterror(L, p1, p2, "perform arithmetic on"); 164 | } 165 | } 166 | } 167 | 168 | 169 | /* 170 | ** The use of 'p1' after 'callbinTM' is safe because, when a tag 171 | ** method is not found, 'callbinTM' cannot change the stack. 172 | */ 173 | void luaT_tryconcatTM (lua_State *L) { 174 | StkId p1 = L->top.p - 2; /* first argument */ 175 | if (l_unlikely(callbinTM(L, s2v(p1), s2v(p1 + 1), p1, TM_CONCAT) < 0)) 176 | luaG_concaterror(L, s2v(p1), s2v(p1 + 1)); 177 | } 178 | 179 | 180 | void luaT_trybinassocTM (lua_State *L, const TValue *p1, const TValue *p2, 181 | int flip, StkId res, TMS event) { 182 | if (flip) 183 | luaT_trybinTM(L, p2, p1, res, event); 184 | else 185 | luaT_trybinTM(L, p1, p2, res, event); 186 | } 187 | 188 | 189 | void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2, 190 | int flip, StkId res, TMS event) { 191 | TValue aux; 192 | setivalue(&aux, i2); 193 | luaT_trybinassocTM(L, p1, &aux, flip, res, event); 194 | } 195 | 196 | 197 | /* 198 | ** Calls an order tag method. 199 | ** For lessequal, LUA_COMPAT_LT_LE keeps compatibility with old 200 | ** behavior: if there is no '__le', try '__lt', based on l <= r iff 201 | ** !(r < l) (assuming a total order). If the metamethod yields during 202 | ** this substitution, the continuation has to know about it (to negate 203 | ** the result of rtop.p, event); /* try original event */ 209 | if (tag >= 0) /* found tag method? */ 210 | return !tagisfalse(tag); 211 | #if defined(LUA_COMPAT_LT_LE) 212 | else if (event == TM_LE) { 213 | /* try '!(p2 < p1)' for '(p1 <= p2)' */ 214 | L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ 215 | tag = callbinTM(L, p2, p1, L->top.p, TM_LT); 216 | L->ci->callstatus ^= CIST_LEQ; /* clear mark */ 217 | if (tag >= 0) /* found tag method? */ 218 | return tagisfalse(tag); 219 | } 220 | #endif 221 | luaG_ordererror(L, p1, p2); /* no metamethod found */ 222 | return 0; /* to avoid warnings */ 223 | } 224 | 225 | 226 | int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, 227 | int flip, int isfloat, TMS event) { 228 | TValue aux; const TValue *p2; 229 | if (isfloat) { 230 | setfltvalue(&aux, cast_num(v2)); 231 | } 232 | else 233 | setivalue(&aux, v2); 234 | if (flip) { /* arguments were exchanged? */ 235 | p2 = p1; p1 = &aux; /* correct them */ 236 | } 237 | else 238 | p2 = &aux; 239 | return luaT_callorderTM(L, p1, p2, event); 240 | } 241 | 242 | 243 | void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci, 244 | const Proto *p) { 245 | int i; 246 | int actual = cast_int(L->top.p - ci->func.p) - 1; /* number of arguments */ 247 | int nextra = actual - nfixparams; /* number of extra arguments */ 248 | ci->u.l.nextraargs = nextra; 249 | luaD_checkstack(L, p->maxstacksize + 1); 250 | /* copy function to the top of the stack */ 251 | setobjs2s(L, L->top.p++, ci->func.p); 252 | /* move fixed parameters to the top of the stack */ 253 | for (i = 1; i <= nfixparams; i++) { 254 | setobjs2s(L, L->top.p++, ci->func.p + i); 255 | setnilvalue(s2v(ci->func.p + i)); /* erase original parameter (for GC) */ 256 | } 257 | ci->func.p += actual + 1; 258 | ci->top.p += actual + 1; 259 | lua_assert(L->top.p <= ci->top.p && ci->top.p <= L->stack_last.p); 260 | } 261 | 262 | 263 | void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) { 264 | int i; 265 | int nextra = ci->u.l.nextraargs; 266 | if (wanted < 0) { 267 | wanted = nextra; /* get all extra arguments available */ 268 | checkstackp(L, nextra, where); /* ensure stack space */ 269 | L->top.p = where + nextra; /* next instruction will need top */ 270 | } 271 | for (i = 0; i < wanted && i < nextra; i++) 272 | setobjs2s(L, where + i, ci->func.p - nextra + i); 273 | for (; i < wanted; i++) /* complete required results with nil */ 274 | setnilvalue(s2v(where + i)); 275 | } 276 | 277 | -------------------------------------------------------------------------------- /lua/lgc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lgc.h $ 3 | ** Garbage Collector 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lgc_h 8 | #define lgc_h 9 | 10 | 11 | #include 12 | 13 | 14 | #include "lobject.h" 15 | #include "lstate.h" 16 | 17 | /* 18 | ** Collectable objects may have one of three colors: white, which means 19 | ** the object is not marked; gray, which means the object is marked, but 20 | ** its references may be not marked; and black, which means that the 21 | ** object and all its references are marked. The main invariant of the 22 | ** garbage collector, while marking objects, is that a black object can 23 | ** never point to a white one. Moreover, any gray object must be in a 24 | ** "gray list" (gray, grayagain, weak, allweak, ephemeron) so that it 25 | ** can be visited again before finishing the collection cycle. (Open 26 | ** upvalues are an exception to this rule.) These lists have no meaning 27 | ** when the invariant is not being enforced (e.g., sweep phase). 28 | */ 29 | 30 | 31 | /* 32 | ** Possible states of the Garbage Collector 33 | */ 34 | #define GCSpropagate 0 35 | #define GCSenteratomic 1 36 | #define GCSatomic 2 37 | #define GCSswpallgc 3 38 | #define GCSswpfinobj 4 39 | #define GCSswptobefnz 5 40 | #define GCSswpend 6 41 | #define GCScallfin 7 42 | #define GCSpause 8 43 | 44 | 45 | #define issweepphase(g) \ 46 | (GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend) 47 | 48 | 49 | /* 50 | ** macro to tell when main invariant (white objects cannot point to black 51 | ** ones) must be kept. During a collection, the sweep 52 | ** phase may break the invariant, as objects turned white may point to 53 | ** still-black objects. The invariant is restored when sweep ends and 54 | ** all objects are white again. 55 | */ 56 | 57 | #define keepinvariant(g) ((g)->gcstate <= GCSatomic) 58 | 59 | 60 | /* 61 | ** some useful bit tricks 62 | */ 63 | #define resetbits(x,m) ((x) &= cast_byte(~(m))) 64 | #define setbits(x,m) ((x) |= (m)) 65 | #define testbits(x,m) ((x) & (m)) 66 | #define bitmask(b) (1<<(b)) 67 | #define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) 68 | #define l_setbit(x,b) setbits(x, bitmask(b)) 69 | #define resetbit(x,b) resetbits(x, bitmask(b)) 70 | #define testbit(x,b) testbits(x, bitmask(b)) 71 | 72 | 73 | /* 74 | ** Layout for bit use in 'marked' field. First three bits are 75 | ** used for object "age" in generational mode. Last bit is used 76 | ** by tests. 77 | */ 78 | #define WHITE0BIT 3 /* object is white (type 0) */ 79 | #define WHITE1BIT 4 /* object is white (type 1) */ 80 | #define BLACKBIT 5 /* object is black */ 81 | #define FINALIZEDBIT 6 /* object has been marked for finalization */ 82 | 83 | #define TESTBIT 7 84 | 85 | 86 | 87 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) 88 | 89 | 90 | #define iswhite(x) testbits((x)->marked, WHITEBITS) 91 | #define isblack(x) testbit((x)->marked, BLACKBIT) 92 | #define isgray(x) /* neither white nor black */ \ 93 | (!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT))) 94 | 95 | #define tofinalize(x) testbit((x)->marked, FINALIZEDBIT) 96 | 97 | #define otherwhite(g) ((g)->currentwhite ^ WHITEBITS) 98 | #define isdeadm(ow,m) ((m) & (ow)) 99 | #define isdead(g,v) isdeadm(otherwhite(g), (v)->marked) 100 | 101 | #define changewhite(x) ((x)->marked ^= WHITEBITS) 102 | #define nw2black(x) \ 103 | check_exp(!iswhite(x), l_setbit((x)->marked, BLACKBIT)) 104 | 105 | #define luaC_white(g) cast_byte((g)->currentwhite & WHITEBITS) 106 | 107 | 108 | /* object age in generational mode */ 109 | #define G_NEW 0 /* created in current cycle */ 110 | #define G_SURVIVAL 1 /* created in previous cycle */ 111 | #define G_OLD0 2 /* marked old by frw. barrier in this cycle */ 112 | #define G_OLD1 3 /* first full cycle as old */ 113 | #define G_OLD 4 /* really old object (not to be visited) */ 114 | #define G_TOUCHED1 5 /* old object touched this cycle */ 115 | #define G_TOUCHED2 6 /* old object touched in previous cycle */ 116 | 117 | #define AGEBITS 7 /* all age bits (111) */ 118 | 119 | #define getage(o) ((o)->marked & AGEBITS) 120 | #define setage(o,a) ((o)->marked = cast_byte(((o)->marked & (~AGEBITS)) | a)) 121 | #define isold(o) (getage(o) > G_SURVIVAL) 122 | 123 | 124 | /* 125 | ** In generational mode, objects are created 'new'. After surviving one 126 | ** cycle, they become 'survival'. Both 'new' and 'survival' can point 127 | ** to any other object, as they are traversed at the end of the cycle. 128 | ** We call them both 'young' objects. 129 | ** If a survival object survives another cycle, it becomes 'old1'. 130 | ** 'old1' objects can still point to survival objects (but not to 131 | ** new objects), so they still must be traversed. After another cycle 132 | ** (that, being old, 'old1' objects will "survive" no matter what) 133 | ** finally the 'old1' object becomes really 'old', and then they 134 | ** are no more traversed. 135 | ** 136 | ** To keep its invariants, the generational mode uses the same barriers 137 | ** also used by the incremental mode. If a young object is caught in a 138 | ** forward barrier, it cannot become old immediately, because it can 139 | ** still point to other young objects. Instead, it becomes 'old0', 140 | ** which in the next cycle becomes 'old1'. So, 'old0' objects is 141 | ** old but can point to new and survival objects; 'old1' is old 142 | ** but cannot point to new objects; and 'old' cannot point to any 143 | ** young object. 144 | ** 145 | ** If any old object ('old0', 'old1', 'old') is caught in a back 146 | ** barrier, it becomes 'touched1' and goes into a gray list, to be 147 | ** visited at the end of the cycle. There it evolves to 'touched2', 148 | ** which can point to survivals but not to new objects. In yet another 149 | ** cycle then it becomes 'old' again. 150 | ** 151 | ** The generational mode must also control the colors of objects, 152 | ** because of the barriers. While the mutator is running, young objects 153 | ** are kept white. 'old', 'old1', and 'touched2' objects are kept black, 154 | ** as they cannot point to new objects; exceptions are threads and open 155 | ** upvalues, which age to 'old1' and 'old' but are kept gray. 'old0' 156 | ** objects may be gray or black, as in the incremental mode. 'touched1' 157 | ** objects are kept gray, as they must be visited again at the end of 158 | ** the cycle. 159 | */ 160 | 161 | 162 | /* Default Values for GC parameters */ 163 | 164 | /* 165 | ** Minor collections will shift to major ones after LUAI_MINORMAJOR% 166 | ** objects become old. 167 | */ 168 | #define LUAI_MINORMAJOR 100 169 | 170 | /* 171 | ** Major collections will shift to minor ones after a collection 172 | ** collects at least LUAI_MAJORMINOR% of the new objects. 173 | */ 174 | #define LUAI_MAJORMINOR 50 175 | 176 | /* 177 | ** A young (minor) collection will run after creating LUAI_GENMINORMUL% 178 | ** new objects. 179 | */ 180 | #define LUAI_GENMINORMUL 25 181 | 182 | 183 | /* incremental */ 184 | 185 | /* Number of objects must be LUAI_GCPAUSE% before starting new cycle */ 186 | #define LUAI_GCPAUSE 200 187 | 188 | /* Step multiplier. (Roughly, the collector handles LUAI_GCMUL% objects 189 | for each new allocated object.) */ 190 | #define LUAI_GCMUL 200 191 | 192 | /* How many objects to allocate before next GC step */ 193 | #define LUAI_GCSTEPSIZE 250 194 | 195 | 196 | #define setgcparam(g,p,v) (g->gcparams[LUA_GCP##p] = luaO_codeparam(v)) 197 | #define applygcparam(g,p,x) luaO_applyparam(g->gcparams[LUA_GCP##p], x) 198 | 199 | /* 200 | ** Control when GC is running: 201 | */ 202 | #define GCSTPUSR 1 /* bit true when GC stopped by user */ 203 | #define GCSTPGC 2 /* bit true when GC stopped by itself */ 204 | #define GCSTPCLS 4 /* bit true when closing Lua state */ 205 | #define gcrunning(g) ((g)->gcstp == 0) 206 | 207 | 208 | /* 209 | ** Does one step of collection when debt becomes zero. 'pre'/'pos' 210 | ** allows some adjustments to be done only when needed. macro 211 | ** 'condchangemem' is used only for heavy tests (forcing a full 212 | ** GC cycle on every opportunity) 213 | */ 214 | 215 | #if !defined(HARDMEMTESTS) 216 | #define condchangemem(L,pre,pos) ((void)0) 217 | #else 218 | #define condchangemem(L,pre,pos) \ 219 | { if (gcrunning(G(L))) { pre; luaC_fullgc(L, 0); pos; } } 220 | #endif 221 | 222 | #define luaC_condGC(L,pre,pos) \ 223 | { if (G(L)->GCdebt <= 0) { pre; luaC_step(L); pos;}; \ 224 | condchangemem(L,pre,pos); } 225 | 226 | /* more often than not, 'pre'/'pos' are empty */ 227 | #define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0) 228 | 229 | 230 | #define luaC_objbarrier(L,p,o) ( \ 231 | (isblack(p) && iswhite(o)) ? \ 232 | luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0)) 233 | 234 | #define luaC_barrier(L,p,v) ( \ 235 | iscollectable(v) ? luaC_objbarrier(L,p,gcvalue(v)) : cast_void(0)) 236 | 237 | #define luaC_objbarrierback(L,p,o) ( \ 238 | (isblack(p) && iswhite(o)) ? luaC_barrierback_(L,p) : cast_void(0)) 239 | 240 | #define luaC_barrierback(L,p,v) ( \ 241 | iscollectable(v) ? luaC_objbarrierback(L, p, gcvalue(v)) : cast_void(0)) 242 | 243 | LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); 244 | LUAI_FUNC void luaC_freeallobjects (lua_State *L); 245 | LUAI_FUNC void luaC_step (lua_State *L); 246 | LUAI_FUNC void luaC_runtilstate (lua_State *L, int state, int fast); 247 | LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); 248 | LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); 249 | LUAI_FUNC GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, 250 | size_t offset); 251 | LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); 252 | LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); 253 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); 254 | LUAI_FUNC void luaC_changemode (lua_State *L, int newmode); 255 | 256 | 257 | #endif 258 | -------------------------------------------------------------------------------- /lua/lfunc.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lfunc.c $ 3 | ** Auxiliary functions to manipulate prototypes and closures 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lfunc_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "ldebug.h" 18 | #include "ldo.h" 19 | #include "lfunc.h" 20 | #include "lgc.h" 21 | #include "lmem.h" 22 | #include "lobject.h" 23 | #include "lstate.h" 24 | 25 | 26 | 27 | CClosure *luaF_newCclosure (lua_State *L, int nupvals) { 28 | GCObject *o = luaC_newobj(L, LUA_VCCL, sizeCclosure(nupvals)); 29 | CClosure *c = gco2ccl(o); 30 | c->nupvalues = cast_byte(nupvals); 31 | return c; 32 | } 33 | 34 | 35 | LClosure *luaF_newLclosure (lua_State *L, int nupvals) { 36 | GCObject *o = luaC_newobj(L, LUA_VLCL, sizeLclosure(nupvals)); 37 | LClosure *c = gco2lcl(o); 38 | c->p = NULL; 39 | c->nupvalues = cast_byte(nupvals); 40 | while (nupvals--) c->upvals[nupvals] = NULL; 41 | return c; 42 | } 43 | 44 | 45 | /* 46 | ** fill a closure with new closed upvalues 47 | */ 48 | void luaF_initupvals (lua_State *L, LClosure *cl) { 49 | int i; 50 | for (i = 0; i < cl->nupvalues; i++) { 51 | GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal)); 52 | UpVal *uv = gco2upv(o); 53 | uv->v.p = &uv->u.value; /* make it closed */ 54 | setnilvalue(uv->v.p); 55 | cl->upvals[i] = uv; 56 | luaC_objbarrier(L, cl, uv); 57 | } 58 | } 59 | 60 | 61 | /* 62 | ** Create a new upvalue at the given level, and link it to the list of 63 | ** open upvalues of 'L' after entry 'prev'. 64 | **/ 65 | static UpVal *newupval (lua_State *L, StkId level, UpVal **prev) { 66 | GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal)); 67 | UpVal *uv = gco2upv(o); 68 | UpVal *next = *prev; 69 | uv->v.p = s2v(level); /* current value lives in the stack */ 70 | uv->u.open.next = next; /* link it to list of open upvalues */ 71 | uv->u.open.previous = prev; 72 | if (next) 73 | next->u.open.previous = &uv->u.open.next; 74 | *prev = uv; 75 | if (!isintwups(L)) { /* thread not in list of threads with upvalues? */ 76 | L->twups = G(L)->twups; /* link it to the list */ 77 | G(L)->twups = L; 78 | } 79 | return uv; 80 | } 81 | 82 | 83 | /* 84 | ** Find and reuse, or create if it does not exist, an upvalue 85 | ** at the given level. 86 | */ 87 | UpVal *luaF_findupval (lua_State *L, StkId level) { 88 | UpVal **pp = &L->openupval; 89 | UpVal *p; 90 | lua_assert(isintwups(L) || L->openupval == NULL); 91 | while ((p = *pp) != NULL && uplevel(p) >= level) { /* search for it */ 92 | lua_assert(!isdead(G(L), p)); 93 | if (uplevel(p) == level) /* corresponding upvalue? */ 94 | return p; /* return it */ 95 | pp = &p->u.open.next; 96 | } 97 | /* not found: create a new upvalue after 'pp' */ 98 | return newupval(L, level, pp); 99 | } 100 | 101 | 102 | /* 103 | ** Call closing method for object 'obj' with error message 'err'. The 104 | ** boolean 'yy' controls whether the call is yieldable. 105 | ** (This function assumes EXTRA_STACK.) 106 | */ 107 | static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) { 108 | StkId top = L->top.p; 109 | const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); 110 | setobj2s(L, top, tm); /* will call metamethod... */ 111 | setobj2s(L, top + 1, obj); /* with 'self' as the 1st argument */ 112 | setobj2s(L, top + 2, err); /* and error msg. as 2nd argument */ 113 | L->top.p = top + 3; /* add function and arguments */ 114 | if (yy) 115 | luaD_call(L, top, 0); 116 | else 117 | luaD_callnoyield(L, top, 0); 118 | } 119 | 120 | 121 | /* 122 | ** Check whether object at given level has a close metamethod and raise 123 | ** an error if not. 124 | */ 125 | static void checkclosemth (lua_State *L, StkId level) { 126 | const TValue *tm = luaT_gettmbyobj(L, s2v(level), TM_CLOSE); 127 | if (ttisnil(tm)) { /* no metamethod? */ 128 | int idx = cast_int(level - L->ci->func.p); /* variable index */ 129 | const char *vname = luaG_findlocal(L, L->ci, idx, NULL); 130 | if (vname == NULL) vname = "?"; 131 | luaG_runerror(L, "variable '%s' got a non-closable value", vname); 132 | } 133 | } 134 | 135 | 136 | /* 137 | ** Prepare and call a closing method. 138 | ** If status is CLOSEKTOP, the call to the closing method will be pushed 139 | ** at the top of the stack. Otherwise, values can be pushed right after 140 | ** the 'level' of the upvalue being closed, as everything after that 141 | ** won't be used again. 142 | */ 143 | static void prepcallclosemth (lua_State *L, StkId level, int status, int yy) { 144 | TValue *uv = s2v(level); /* value being closed */ 145 | TValue *errobj; 146 | if (status == CLOSEKTOP) 147 | errobj = &G(L)->nilvalue; /* error object is nil */ 148 | else { /* 'luaD_seterrorobj' will set top to level + 2 */ 149 | errobj = s2v(level + 1); /* error object goes after 'uv' */ 150 | luaD_seterrorobj(L, status, level + 1); /* set error object */ 151 | } 152 | callclosemethod(L, uv, errobj, yy); 153 | } 154 | 155 | 156 | /* 157 | ** Maximum value for deltas in 'tbclist', dependent on the type 158 | ** of delta. (This macro assumes that an 'L' is in scope where it 159 | ** is used.) 160 | */ 161 | #define MAXDELTA \ 162 | ((256ul << ((sizeof(L->stack.p->tbclist.delta) - 1) * 8)) - 1) 163 | 164 | 165 | /* 166 | ** Insert a variable in the list of to-be-closed variables. 167 | */ 168 | void luaF_newtbcupval (lua_State *L, StkId level) { 169 | lua_assert(level > L->tbclist.p); 170 | if (l_isfalse(s2v(level))) 171 | return; /* false doesn't need to be closed */ 172 | checkclosemth(L, level); /* value must have a close method */ 173 | while (cast_uint(level - L->tbclist.p) > MAXDELTA) { 174 | L->tbclist.p += MAXDELTA; /* create a dummy node at maximum delta */ 175 | L->tbclist.p->tbclist.delta = 0; 176 | } 177 | level->tbclist.delta = cast(unsigned short, level - L->tbclist.p); 178 | L->tbclist.p = level; 179 | } 180 | 181 | 182 | void luaF_unlinkupval (UpVal *uv) { 183 | lua_assert(upisopen(uv)); 184 | *uv->u.open.previous = uv->u.open.next; 185 | if (uv->u.open.next) 186 | uv->u.open.next->u.open.previous = uv->u.open.previous; 187 | } 188 | 189 | 190 | /* 191 | ** Close all upvalues up to the given stack level. 192 | */ 193 | void luaF_closeupval (lua_State *L, StkId level) { 194 | UpVal *uv; 195 | StkId upl; /* stack index pointed by 'uv' */ 196 | while ((uv = L->openupval) != NULL && (upl = uplevel(uv)) >= level) { 197 | TValue *slot = &uv->u.value; /* new position for value */ 198 | lua_assert(uplevel(uv) < L->top.p); 199 | luaF_unlinkupval(uv); /* remove upvalue from 'openupval' list */ 200 | setobj(L, slot, uv->v.p); /* move value to upvalue slot */ 201 | uv->v.p = slot; /* now current value lives here */ 202 | if (!iswhite(uv)) { /* neither white nor dead? */ 203 | nw2black(uv); /* closed upvalues cannot be gray */ 204 | luaC_barrier(L, uv, slot); 205 | } 206 | } 207 | } 208 | 209 | 210 | /* 211 | ** Remove first element from the tbclist plus its dummy nodes. 212 | */ 213 | static void poptbclist (lua_State *L) { 214 | StkId tbc = L->tbclist.p; 215 | lua_assert(tbc->tbclist.delta > 0); /* first element cannot be dummy */ 216 | tbc -= tbc->tbclist.delta; 217 | while (tbc > L->stack.p && tbc->tbclist.delta == 0) 218 | tbc -= MAXDELTA; /* remove dummy nodes */ 219 | L->tbclist.p = tbc; 220 | } 221 | 222 | 223 | /* 224 | ** Close all upvalues and to-be-closed variables up to the given stack 225 | ** level. Return restored 'level'. 226 | */ 227 | StkId luaF_close (lua_State *L, StkId level, int status, int yy) { 228 | ptrdiff_t levelrel = savestack(L, level); 229 | luaF_closeupval(L, level); /* first, close the upvalues */ 230 | while (L->tbclist.p >= level) { /* traverse tbc's down to that level */ 231 | StkId tbc = L->tbclist.p; /* get variable index */ 232 | poptbclist(L); /* remove it from list */ 233 | prepcallclosemth(L, tbc, status, yy); /* close variable */ 234 | level = restorestack(L, levelrel); 235 | } 236 | return level; 237 | } 238 | 239 | 240 | Proto *luaF_newproto (lua_State *L) { 241 | GCObject *o = luaC_newobj(L, LUA_VPROTO, sizeof(Proto)); 242 | Proto *f = gco2p(o); 243 | f->k = NULL; 244 | f->sizek = 0; 245 | f->p = NULL; 246 | f->sizep = 0; 247 | f->code = NULL; 248 | f->sizecode = 0; 249 | f->lineinfo = NULL; 250 | f->sizelineinfo = 0; 251 | f->abslineinfo = NULL; 252 | f->sizeabslineinfo = 0; 253 | f->upvalues = NULL; 254 | f->sizeupvalues = 0; 255 | f->numparams = 0; 256 | f->flag = 0; 257 | f->maxstacksize = 0; 258 | f->locvars = NULL; 259 | f->sizelocvars = 0; 260 | f->linedefined = 0; 261 | f->lastlinedefined = 0; 262 | f->source = NULL; 263 | return f; 264 | } 265 | 266 | 267 | void luaF_freeproto (lua_State *L, Proto *f) { 268 | if (!(f->flag & PF_FIXED)) { 269 | luaM_freearray(L, f->code, f->sizecode); 270 | luaM_freearray(L, f->lineinfo, f->sizelineinfo); 271 | luaM_freearray(L, f->abslineinfo, f->sizeabslineinfo); 272 | } 273 | luaM_freearray(L, f->p, f->sizep); 274 | luaM_freearray(L, f->k, f->sizek); 275 | luaM_freearray(L, f->locvars, f->sizelocvars); 276 | luaM_freearray(L, f->upvalues, f->sizeupvalues); 277 | luaM_free(L, f); 278 | } 279 | 280 | 281 | /* 282 | ** Look for n-th local variable at line 'line' in function 'func'. 283 | ** Returns NULL if not found. 284 | */ 285 | const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { 286 | int i; 287 | for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { 288 | if (pc < f->locvars[i].endpc) { /* is variable active? */ 289 | local_number--; 290 | if (local_number == 0) 291 | return getstr(f->locvars[i].varname); 292 | } 293 | } 294 | return NULL; /* not found */ 295 | } 296 | 297 | -------------------------------------------------------------------------------- /lua/lstring.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lstring.c $ 3 | ** String table (keeps all strings handled by Lua) 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lstring_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "ldebug.h" 18 | #include "ldo.h" 19 | #include "lmem.h" 20 | #include "lobject.h" 21 | #include "lstate.h" 22 | #include "lstring.h" 23 | 24 | 25 | /* 26 | ** Maximum size for string table. 27 | */ 28 | #define MAXSTRTB cast_int(luaM_limitN(INT_MAX, TString*)) 29 | 30 | /* 31 | ** Initial size for the string table (must be power of 2). 32 | ** The Lua core alone registers ~50 strings (reserved words + 33 | ** metaevent keys + a few others). Libraries would typically add 34 | ** a few dozens more. 35 | */ 36 | #if !defined(MINSTRTABSIZE) 37 | #define MINSTRTABSIZE 128 38 | #endif 39 | 40 | 41 | /* 42 | ** equality for long strings 43 | */ 44 | int luaS_eqlngstr (TString *a, TString *b) { 45 | size_t len = a->u.lnglen; 46 | lua_assert(a->tt == LUA_VLNGSTR && b->tt == LUA_VLNGSTR); 47 | return (a == b) || /* same instance or... */ 48 | ((len == b->u.lnglen) && /* equal length and ... */ 49 | (memcmp(getlngstr(a), getlngstr(b), len) == 0)); /* equal contents */ 50 | } 51 | 52 | 53 | unsigned luaS_hash (const char *str, size_t l, unsigned seed) { 54 | unsigned int h = seed ^ cast_uint(l); 55 | for (; l > 0; l--) 56 | h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1])); 57 | return h; 58 | } 59 | 60 | 61 | unsigned luaS_hashlongstr (TString *ts) { 62 | lua_assert(ts->tt == LUA_VLNGSTR); 63 | if (ts->extra == 0) { /* no hash? */ 64 | size_t len = ts->u.lnglen; 65 | ts->hash = luaS_hash(getlngstr(ts), len, ts->hash); 66 | ts->extra = 1; /* now it has its hash */ 67 | } 68 | return ts->hash; 69 | } 70 | 71 | 72 | static void tablerehash (TString **vect, int osize, int nsize) { 73 | int i; 74 | for (i = osize; i < nsize; i++) /* clear new elements */ 75 | vect[i] = NULL; 76 | for (i = 0; i < osize; i++) { /* rehash old part of the array */ 77 | TString *p = vect[i]; 78 | vect[i] = NULL; 79 | while (p) { /* for each string in the list */ 80 | TString *hnext = p->u.hnext; /* save next */ 81 | unsigned int h = lmod(p->hash, nsize); /* new position */ 82 | p->u.hnext = vect[h]; /* chain it into array */ 83 | vect[h] = p; 84 | p = hnext; 85 | } 86 | } 87 | } 88 | 89 | 90 | /* 91 | ** Resize the string table. If allocation fails, keep the current size. 92 | ** (This can degrade performance, but any non-zero size should work 93 | ** correctly.) 94 | */ 95 | void luaS_resize (lua_State *L, int nsize) { 96 | stringtable *tb = &G(L)->strt; 97 | int osize = tb->size; 98 | TString **newvect; 99 | if (nsize < osize) /* shrinking table? */ 100 | tablerehash(tb->hash, osize, nsize); /* depopulate shrinking part */ 101 | newvect = luaM_reallocvector(L, tb->hash, osize, nsize, TString*); 102 | if (l_unlikely(newvect == NULL)) { /* reallocation failed? */ 103 | if (nsize < osize) /* was it shrinking table? */ 104 | tablerehash(tb->hash, nsize, osize); /* restore to original size */ 105 | /* leave table as it was */ 106 | } 107 | else { /* allocation succeeded */ 108 | tb->hash = newvect; 109 | tb->size = nsize; 110 | if (nsize > osize) 111 | tablerehash(newvect, osize, nsize); /* rehash for new size */ 112 | } 113 | } 114 | 115 | 116 | /* 117 | ** Clear API string cache. (Entries cannot be empty, so fill them with 118 | ** a non-collectable string.) 119 | */ 120 | void luaS_clearcache (global_State *g) { 121 | int i, j; 122 | for (i = 0; i < STRCACHE_N; i++) 123 | for (j = 0; j < STRCACHE_M; j++) { 124 | if (iswhite(g->strcache[i][j])) /* will entry be collected? */ 125 | g->strcache[i][j] = g->memerrmsg; /* replace it with something fixed */ 126 | } 127 | } 128 | 129 | 130 | /* 131 | ** Initialize the string table and the string cache 132 | */ 133 | void luaS_init (lua_State *L) { 134 | global_State *g = G(L); 135 | int i, j; 136 | stringtable *tb = &G(L)->strt; 137 | tb->hash = luaM_newvector(L, MINSTRTABSIZE, TString*); 138 | tablerehash(tb->hash, 0, MINSTRTABSIZE); /* clear array */ 139 | tb->size = MINSTRTABSIZE; 140 | /* pre-create memory-error message */ 141 | g->memerrmsg = luaS_newliteral(L, MEMERRMSG); 142 | luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */ 143 | for (i = 0; i < STRCACHE_N; i++) /* fill cache with valid strings */ 144 | for (j = 0; j < STRCACHE_M; j++) 145 | g->strcache[i][j] = g->memerrmsg; 146 | } 147 | 148 | 149 | size_t luaS_sizelngstr (size_t len, int kind) { 150 | switch (kind) { 151 | case LSTRREG: /* regular long string */ 152 | /* don't need 'falloc'/'ud', but need space for content */ 153 | return offsetof(TString, falloc) + (len + 1) * sizeof(char); 154 | case LSTRFIX: /* fixed external long string */ 155 | /* don't need 'falloc'/'ud' */ 156 | return offsetof(TString, falloc); 157 | default: /* external long string with deallocation */ 158 | lua_assert(kind == LSTRMEM); 159 | return sizeof(TString); 160 | } 161 | } 162 | 163 | 164 | /* 165 | ** creates a new string object 166 | */ 167 | static TString *createstrobj (lua_State *L, size_t totalsize, int tag, 168 | unsigned h) { 169 | TString *ts; 170 | GCObject *o; 171 | o = luaC_newobj(L, tag, totalsize); 172 | ts = gco2ts(o); 173 | ts->hash = h; 174 | ts->extra = 0; 175 | return ts; 176 | } 177 | 178 | 179 | TString *luaS_createlngstrobj (lua_State *L, size_t l) { 180 | size_t totalsize = luaS_sizelngstr(l, LSTRREG); 181 | TString *ts = createstrobj(L, totalsize, LUA_VLNGSTR, G(L)->seed); 182 | ts->u.lnglen = l; 183 | ts->shrlen = LSTRREG; /* signals that it is a regular long string */ 184 | ts->contents = cast_charp(ts) + offsetof(TString, falloc); 185 | ts->contents[l] = '\0'; /* ending 0 */ 186 | return ts; 187 | } 188 | 189 | 190 | void luaS_remove (lua_State *L, TString *ts) { 191 | stringtable *tb = &G(L)->strt; 192 | TString **p = &tb->hash[lmod(ts->hash, tb->size)]; 193 | while (*p != ts) /* find previous element */ 194 | p = &(*p)->u.hnext; 195 | *p = (*p)->u.hnext; /* remove element from its list */ 196 | tb->nuse--; 197 | } 198 | 199 | 200 | static void growstrtab (lua_State *L, stringtable *tb) { 201 | if (l_unlikely(tb->nuse == INT_MAX)) { /* too many strings? */ 202 | luaC_fullgc(L, 1); /* try to free some... */ 203 | if (tb->nuse == INT_MAX) /* still too many? */ 204 | luaM_error(L); /* cannot even create a message... */ 205 | } 206 | if (tb->size <= MAXSTRTB / 2) /* can grow string table? */ 207 | luaS_resize(L, tb->size * 2); 208 | } 209 | 210 | 211 | /* 212 | ** Checks whether short string exists and reuses it or creates a new one. 213 | */ 214 | static TString *internshrstr (lua_State *L, const char *str, size_t l) { 215 | TString *ts; 216 | global_State *g = G(L); 217 | stringtable *tb = &g->strt; 218 | unsigned int h = luaS_hash(str, l, g->seed); 219 | TString **list = &tb->hash[lmod(h, tb->size)]; 220 | lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */ 221 | for (ts = *list; ts != NULL; ts = ts->u.hnext) { 222 | if (l == cast_uint(ts->shrlen) && 223 | (memcmp(str, getshrstr(ts), l * sizeof(char)) == 0)) { 224 | /* found! */ 225 | if (isdead(g, ts)) /* dead (but not collected yet)? */ 226 | changewhite(ts); /* resurrect it */ 227 | return ts; 228 | } 229 | } 230 | /* else must create a new string */ 231 | if (tb->nuse >= tb->size) { /* need to grow string table? */ 232 | growstrtab(L, tb); 233 | list = &tb->hash[lmod(h, tb->size)]; /* rehash with new size */ 234 | } 235 | ts = createstrobj(L, sizestrshr(l), LUA_VSHRSTR, h); 236 | ts->shrlen = cast_byte(l); 237 | getshrstr(ts)[l] = '\0'; /* ending 0 */ 238 | memcpy(getshrstr(ts), str, l * sizeof(char)); 239 | ts->u.hnext = *list; 240 | *list = ts; 241 | tb->nuse++; 242 | return ts; 243 | } 244 | 245 | 246 | /* 247 | ** new string (with explicit length) 248 | */ 249 | TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { 250 | if (l <= LUAI_MAXSHORTLEN) /* short string? */ 251 | return internshrstr(L, str, l); 252 | else { 253 | TString *ts; 254 | if (l_unlikely(l * sizeof(char) >= (MAX_SIZE - sizeof(TString)))) 255 | luaM_toobig(L); 256 | ts = luaS_createlngstrobj(L, l); 257 | memcpy(getlngstr(ts), str, l * sizeof(char)); 258 | return ts; 259 | } 260 | } 261 | 262 | 263 | /* 264 | ** Create or reuse a zero-terminated string, first checking in the 265 | ** cache (using the string address as a key). The cache can contain 266 | ** only zero-terminated strings, so it is safe to use 'strcmp' to 267 | ** check hits. 268 | */ 269 | TString *luaS_new (lua_State *L, const char *str) { 270 | unsigned int i = point2uint(str) % STRCACHE_N; /* hash */ 271 | int j; 272 | TString **p = G(L)->strcache[i]; 273 | for (j = 0; j < STRCACHE_M; j++) { 274 | if (strcmp(str, getstr(p[j])) == 0) /* hit? */ 275 | return p[j]; /* that is it */ 276 | } 277 | /* normal route */ 278 | for (j = STRCACHE_M - 1; j > 0; j--) 279 | p[j] = p[j - 1]; /* move out last element */ 280 | /* new element is first in the list */ 281 | p[0] = luaS_newlstr(L, str, strlen(str)); 282 | return p[0]; 283 | } 284 | 285 | 286 | Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue) { 287 | Udata *u; 288 | int i; 289 | GCObject *o; 290 | if (l_unlikely(s > MAX_SIZE - udatamemoffset(nuvalue))) 291 | luaM_toobig(L); 292 | o = luaC_newobj(L, LUA_VUSERDATA, sizeudata(nuvalue, s)); 293 | u = gco2u(o); 294 | u->len = s; 295 | u->nuvalue = nuvalue; 296 | u->metatable = NULL; 297 | for (i = 0; i < nuvalue; i++) 298 | setnilvalue(&u->uv[i].uv); 299 | return u; 300 | } 301 | 302 | 303 | struct NewExt { 304 | int kind; 305 | const char *s; 306 | size_t len; 307 | TString *ts; /* output */ 308 | }; 309 | 310 | 311 | static void f_newext (lua_State *L, void *ud) { 312 | struct NewExt *ne = cast(struct NewExt *, ud); 313 | size_t size = luaS_sizelngstr(0, ne->kind); 314 | ne->ts = createstrobj(L, size, LUA_VLNGSTR, G(L)->seed); 315 | } 316 | 317 | 318 | static void f_pintern (lua_State *L, void *ud) { 319 | struct NewExt *ne = cast(struct NewExt *, ud); 320 | ne->ts = internshrstr(L, ne->s, ne->len); 321 | } 322 | 323 | 324 | TString *luaS_newextlstr (lua_State *L, 325 | const char *s, size_t len, lua_Alloc falloc, void *ud) { 326 | struct NewExt ne; 327 | if (len <= LUAI_MAXSHORTLEN) { /* short string? */ 328 | ne.s = s; ne.len = len; 329 | if (!falloc) 330 | f_pintern(L, &ne); /* just internalize string */ 331 | else { 332 | int status = luaD_rawrunprotected(L, f_pintern, &ne); 333 | (*falloc)(ud, cast_voidp(s), len + 1, 0); /* free external string */ 334 | if (status != LUA_OK) /* memory error? */ 335 | luaM_error(L); /* re-raise memory error */ 336 | } 337 | return ne.ts; 338 | } 339 | /* "normal" case: long strings */ 340 | if (!falloc) { 341 | ne.kind = LSTRFIX; 342 | f_newext(L, &ne); /* just create header */ 343 | } 344 | else { 345 | ne.kind = LSTRMEM; 346 | if (luaD_rawrunprotected(L, f_newext, &ne) != LUA_OK) { /* mem. error? */ 347 | (*falloc)(ud, cast_voidp(s), len + 1, 0); /* free external string */ 348 | luaM_error(L); /* re-raise memory error */ 349 | } 350 | ne.ts->falloc = falloc; 351 | ne.ts->ud = ud; 352 | } 353 | ne.ts->shrlen = ne.kind; 354 | ne.ts->u.lnglen = len; 355 | ne.ts->contents = cast_charp(s); 356 | return ne.ts; 357 | } 358 | 359 | 360 | -------------------------------------------------------------------------------- /lua/lundump.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lundump.c $ 3 | ** load precompiled Lua chunks 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lundump_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | #include 15 | 16 | #include "lua.h" 17 | 18 | #include "ldebug.h" 19 | #include "ldo.h" 20 | #include "lfunc.h" 21 | #include "lmem.h" 22 | #include "lobject.h" 23 | #include "lstring.h" 24 | #include "ltable.h" 25 | #include "lundump.h" 26 | #include "lzio.h" 27 | 28 | 29 | #if !defined(luai_verifycode) 30 | #define luai_verifycode(L,f) /* empty */ 31 | #endif 32 | 33 | 34 | typedef struct { 35 | lua_State *L; 36 | ZIO *Z; 37 | const char *name; 38 | Table *h; /* list for string reuse */ 39 | lu_mem offset; /* current position relative to beginning of dump */ 40 | lua_Integer nstr; /* number of strings in the list */ 41 | lu_byte fixed; /* dump is fixed in memory */ 42 | } LoadState; 43 | 44 | 45 | static l_noret error (LoadState *S, const char *why) { 46 | luaO_pushfstring(S->L, "%s: bad binary format (%s)", S->name, why); 47 | luaD_throw(S->L, LUA_ERRSYNTAX); 48 | } 49 | 50 | 51 | /* 52 | ** All high-level loads go through loadVector; you can change it to 53 | ** adapt to the endianness of the input 54 | */ 55 | #define loadVector(S,b,n) loadBlock(S,b,(n)*sizeof((b)[0])) 56 | 57 | static void loadBlock (LoadState *S, void *b, size_t size) { 58 | if (luaZ_read(S->Z, b, size) != 0) 59 | error(S, "truncated chunk"); 60 | S->offset += size; 61 | } 62 | 63 | 64 | static void loadAlign (LoadState *S, int align) { 65 | int padding = align - (S->offset % align); 66 | if (padding < align) { /* apd == align means no padding */ 67 | lua_Integer paddingContent; 68 | loadBlock(S, &paddingContent, padding); 69 | lua_assert(S->offset % align == 0); 70 | } 71 | } 72 | 73 | 74 | #define getaddr(S,n,t) cast(t *, getaddr_(S,(n) * sizeof(t))) 75 | 76 | static const void *getaddr_ (LoadState *S, size_t size) { 77 | const void *block = luaZ_getaddr(S->Z, size); 78 | S->offset += size; 79 | if (block == NULL) 80 | error(S, "truncated fixed buffer"); 81 | return block; 82 | } 83 | 84 | 85 | #define loadVar(S,x) loadVector(S,&x,1) 86 | 87 | 88 | static lu_byte loadByte (LoadState *S) { 89 | int b = zgetc(S->Z); 90 | if (b == EOZ) 91 | error(S, "truncated chunk"); 92 | S->offset++; 93 | return cast_byte(b); 94 | } 95 | 96 | 97 | static size_t loadVarint (LoadState *S, size_t limit) { 98 | size_t x = 0; 99 | int b; 100 | limit >>= 7; 101 | do { 102 | b = loadByte(S); 103 | if (x > limit) 104 | error(S, "integer overflow"); 105 | x = (x << 7) | (b & 0x7f); 106 | } while ((b & 0x80) != 0); 107 | return x; 108 | } 109 | 110 | 111 | static size_t loadSize (LoadState *S) { 112 | return loadVarint(S, MAX_SIZE); 113 | } 114 | 115 | 116 | static int loadInt (LoadState *S) { 117 | return cast_int(loadVarint(S, cast_sizet(INT_MAX))); 118 | } 119 | 120 | 121 | static lua_Number loadNumber (LoadState *S) { 122 | lua_Number x; 123 | loadVar(S, x); 124 | return x; 125 | } 126 | 127 | 128 | static lua_Integer loadInteger (LoadState *S) { 129 | lua_Integer x; 130 | loadVar(S, x); 131 | return x; 132 | } 133 | 134 | 135 | /* 136 | ** Load a nullable string into slot 'sl' from prototype 'p'. The 137 | ** assignment to the slot and the barrier must be performed before any 138 | ** possible GC activity, to anchor the string. (Both 'loadVector' and 139 | ** 'luaH_setint' can call the GC.) 140 | */ 141 | static void loadString (LoadState *S, Proto *p, TString **sl) { 142 | lua_State *L = S->L; 143 | TString *ts; 144 | TValue sv; 145 | size_t size = loadSize(S); 146 | if (size == 0) { /* no string? */ 147 | lua_assert(*sl == NULL); /* must be prefilled */ 148 | return; 149 | } 150 | else if (size == 1) { /* previously saved string? */ 151 | lua_Integer idx = cast(lua_Integer, loadSize(S)); /* get its index */ 152 | TValue stv; 153 | luaH_getint(S->h, idx, &stv); /* get its value */ 154 | *sl = ts = tsvalue(&stv); 155 | luaC_objbarrier(L, p, ts); 156 | return; /* do not save it again */ 157 | } 158 | else if ((size -= 2) <= LUAI_MAXSHORTLEN) { /* short string? */ 159 | char buff[LUAI_MAXSHORTLEN + 1]; /* extra space for '\0' */ 160 | loadVector(S, buff, size + 1); /* load string into buffer */ 161 | *sl = ts = luaS_newlstr(L, buff, size); /* create string */ 162 | luaC_objbarrier(L, p, ts); 163 | } 164 | else if (S->fixed) { /* for a fixed buffer, use a fixed string */ 165 | const char *s = getaddr(S, size + 1, char); /* get content address */ 166 | *sl = ts = luaS_newextlstr(L, s, size, NULL, NULL); 167 | luaC_objbarrier(L, p, ts); 168 | } 169 | else { /* create internal copy */ 170 | *sl = ts = luaS_createlngstrobj(L, size); /* create string */ 171 | luaC_objbarrier(L, p, ts); 172 | loadVector(S, getlngstr(ts), size + 1); /* load directly in final place */ 173 | } 174 | /* add string to list of saved strings */ 175 | S->nstr++; 176 | setsvalue(L, &sv, ts); 177 | luaH_setint(L, S->h, S->nstr, &sv); 178 | luaC_objbarrierback(L, obj2gco(S->h), ts); 179 | } 180 | 181 | 182 | static void loadCode (LoadState *S, Proto *f) { 183 | int n = loadInt(S); 184 | loadAlign(S, sizeof(f->code[0])); 185 | if (S->fixed) { 186 | f->code = getaddr(S, n, Instruction); 187 | f->sizecode = n; 188 | } 189 | else { 190 | f->code = luaM_newvectorchecked(S->L, n, Instruction); 191 | f->sizecode = n; 192 | loadVector(S, f->code, n); 193 | } 194 | } 195 | 196 | 197 | static void loadFunction(LoadState *S, Proto *f); 198 | 199 | 200 | static void loadConstants (LoadState *S, Proto *f) { 201 | int i; 202 | int n = loadInt(S); 203 | f->k = luaM_newvectorchecked(S->L, n, TValue); 204 | f->sizek = n; 205 | for (i = 0; i < n; i++) 206 | setnilvalue(&f->k[i]); 207 | for (i = 0; i < n; i++) { 208 | TValue *o = &f->k[i]; 209 | int t = loadByte(S); 210 | switch (t) { 211 | case LUA_VNIL: 212 | setnilvalue(o); 213 | break; 214 | case LUA_VFALSE: 215 | setbfvalue(o); 216 | break; 217 | case LUA_VTRUE: 218 | setbtvalue(o); 219 | break; 220 | case LUA_VNUMFLT: 221 | setfltvalue(o, loadNumber(S)); 222 | break; 223 | case LUA_VNUMINT: 224 | setivalue(o, loadInteger(S)); 225 | break; 226 | case LUA_VSHRSTR: 227 | case LUA_VLNGSTR: { 228 | lua_assert(f->source == NULL); 229 | loadString(S, f, &f->source); /* use 'source' to anchor string */ 230 | if (f->source == NULL) 231 | error(S, "bad format for constant string"); 232 | setsvalue2n(S->L, o, f->source); /* save it in the right place */ 233 | f->source = NULL; 234 | break; 235 | } 236 | default: lua_assert(0); 237 | } 238 | } 239 | } 240 | 241 | 242 | static void loadProtos (LoadState *S, Proto *f) { 243 | int i; 244 | int n = loadInt(S); 245 | f->p = luaM_newvectorchecked(S->L, n, Proto *); 246 | f->sizep = n; 247 | for (i = 0; i < n; i++) 248 | f->p[i] = NULL; 249 | for (i = 0; i < n; i++) { 250 | f->p[i] = luaF_newproto(S->L); 251 | luaC_objbarrier(S->L, f, f->p[i]); 252 | loadFunction(S, f->p[i]); 253 | } 254 | } 255 | 256 | 257 | /* 258 | ** Load the upvalues for a function. The names must be filled first, 259 | ** because the filling of the other fields can raise read errors and 260 | ** the creation of the error message can call an emergency collection; 261 | ** in that case all prototypes must be consistent for the GC. 262 | */ 263 | static void loadUpvalues (LoadState *S, Proto *f) { 264 | int i, n; 265 | n = loadInt(S); 266 | f->upvalues = luaM_newvectorchecked(S->L, n, Upvaldesc); 267 | f->sizeupvalues = n; 268 | for (i = 0; i < n; i++) /* make array valid for GC */ 269 | f->upvalues[i].name = NULL; 270 | for (i = 0; i < n; i++) { /* following calls can raise errors */ 271 | f->upvalues[i].instack = loadByte(S); 272 | f->upvalues[i].idx = loadByte(S); 273 | f->upvalues[i].kind = loadByte(S); 274 | } 275 | } 276 | 277 | 278 | static void loadDebug (LoadState *S, Proto *f) { 279 | int i, n; 280 | n = loadInt(S); 281 | if (S->fixed) { 282 | f->lineinfo = getaddr(S, n, ls_byte); 283 | f->sizelineinfo = n; 284 | } 285 | else { 286 | f->lineinfo = luaM_newvectorchecked(S->L, n, ls_byte); 287 | f->sizelineinfo = n; 288 | loadVector(S, f->lineinfo, n); 289 | } 290 | n = loadInt(S); 291 | if (n > 0) { 292 | loadAlign(S, sizeof(int)); 293 | if (S->fixed) { 294 | f->abslineinfo = getaddr(S, n, AbsLineInfo); 295 | f->sizeabslineinfo = n; 296 | } 297 | else { 298 | f->abslineinfo = luaM_newvectorchecked(S->L, n, AbsLineInfo); 299 | f->sizeabslineinfo = n; 300 | loadVector(S, f->abslineinfo, n); 301 | } 302 | } 303 | n = loadInt(S); 304 | f->locvars = luaM_newvectorchecked(S->L, n, LocVar); 305 | f->sizelocvars = n; 306 | for (i = 0; i < n; i++) 307 | f->locvars[i].varname = NULL; 308 | for (i = 0; i < n; i++) { 309 | loadString(S, f, &f->locvars[i].varname); 310 | f->locvars[i].startpc = loadInt(S); 311 | f->locvars[i].endpc = loadInt(S); 312 | } 313 | n = loadInt(S); 314 | if (n != 0) /* does it have debug information? */ 315 | n = f->sizeupvalues; /* must be this many */ 316 | for (i = 0; i < n; i++) 317 | loadString(S, f, &f->upvalues[i].name); 318 | } 319 | 320 | 321 | static void loadFunction (LoadState *S, Proto *f) { 322 | f->linedefined = loadInt(S); 323 | f->lastlinedefined = loadInt(S); 324 | f->numparams = loadByte(S); 325 | f->flag = loadByte(S) & PF_ISVARARG; /* get only the meaningful flags */ 326 | if (S->fixed) 327 | f->flag |= PF_FIXED; /* signal that code is fixed */ 328 | f->maxstacksize = loadByte(S); 329 | loadCode(S, f); 330 | loadConstants(S, f); 331 | loadUpvalues(S, f); 332 | loadProtos(S, f); 333 | loadString(S, f, &f->source); 334 | loadDebug(S, f); 335 | } 336 | 337 | 338 | static void checkliteral (LoadState *S, const char *s, const char *msg) { 339 | char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */ 340 | size_t len = strlen(s); 341 | loadVector(S, buff, len); 342 | if (memcmp(s, buff, len) != 0) 343 | error(S, msg); 344 | } 345 | 346 | 347 | static void fchecksize (LoadState *S, size_t size, const char *tname) { 348 | if (loadByte(S) != size) 349 | error(S, luaO_pushfstring(S->L, "%s size mismatch", tname)); 350 | } 351 | 352 | 353 | #define checksize(S,t) fchecksize(S,sizeof(t),#t) 354 | 355 | static void checkHeader (LoadState *S) { 356 | /* skip 1st char (already read and checked) */ 357 | checkliteral(S, &LUA_SIGNATURE[1], "not a binary chunk"); 358 | if (loadByte(S) != LUAC_VERSION) 359 | error(S, "version mismatch"); 360 | if (loadByte(S) != LUAC_FORMAT) 361 | error(S, "format mismatch"); 362 | checkliteral(S, LUAC_DATA, "corrupted chunk"); 363 | checksize(S, Instruction); 364 | checksize(S, lua_Integer); 365 | checksize(S, lua_Number); 366 | if (loadInteger(S) != LUAC_INT) 367 | error(S, "integer format mismatch"); 368 | if (loadNumber(S) != LUAC_NUM) 369 | error(S, "float format mismatch"); 370 | } 371 | 372 | 373 | /* 374 | ** Load precompiled chunk. 375 | */ 376 | LClosure *luaU_undump (lua_State *L, ZIO *Z, const char *name, int fixed) { 377 | LoadState S; 378 | LClosure *cl; 379 | if (*name == '@' || *name == '=') 380 | S.name = name + 1; 381 | else if (*name == LUA_SIGNATURE[0]) 382 | S.name = "binary string"; 383 | else 384 | S.name = name; 385 | S.L = L; 386 | S.Z = Z; 387 | S.fixed = fixed; 388 | S.offset = 1; /* fist byte was already read */ 389 | checkHeader(&S); 390 | cl = luaF_newLclosure(L, loadByte(&S)); 391 | setclLvalue2s(L, L->top.p, cl); 392 | luaD_inctop(L); 393 | S.h = luaH_new(L); /* create list of saved strings */ 394 | S.nstr = 0; 395 | sethvalue2s(L, L->top.p, S.h); /* anchor it */ 396 | luaD_inctop(L); 397 | cl->p = luaF_newproto(L); 398 | luaC_objbarrier(L, cl, cl->p); 399 | loadFunction(&S, cl->p); 400 | lua_assert(cl->nupvalues == cl->p->sizeupvalues); 401 | luai_verifycode(L, cl->p); 402 | L->top.p--; /* pop table */ 403 | return cl; 404 | } 405 | 406 | -------------------------------------------------------------------------------- /lua/lstate.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lstate.c $ 3 | ** Global State 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lstate_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | #include 15 | 16 | #include "lua.h" 17 | 18 | #include "lapi.h" 19 | #include "ldebug.h" 20 | #include "ldo.h" 21 | #include "lfunc.h" 22 | #include "lgc.h" 23 | #include "llex.h" 24 | #include "lmem.h" 25 | #include "lstate.h" 26 | #include "lstring.h" 27 | #include "ltable.h" 28 | #include "ltm.h" 29 | 30 | 31 | 32 | /* 33 | ** thread state + extra space 34 | */ 35 | typedef struct LX { 36 | lu_byte extra_[LUA_EXTRASPACE]; 37 | lua_State l; 38 | } LX; 39 | 40 | 41 | /* 42 | ** Main thread combines a thread state and the global state 43 | */ 44 | typedef struct LG { 45 | LX l; 46 | global_State g; 47 | } LG; 48 | 49 | 50 | 51 | #define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) 52 | 53 | 54 | /* 55 | ** these macros allow user-specific actions when a thread is 56 | ** created/deleted 57 | */ 58 | #if !defined(luai_userstateopen) 59 | #define luai_userstateopen(L) ((void)L) 60 | #endif 61 | 62 | #if !defined(luai_userstateclose) 63 | #define luai_userstateclose(L) ((void)L) 64 | #endif 65 | 66 | #if !defined(luai_userstatethread) 67 | #define luai_userstatethread(L,L1) ((void)L) 68 | #endif 69 | 70 | #if !defined(luai_userstatefree) 71 | #define luai_userstatefree(L,L1) ((void)L) 72 | #endif 73 | 74 | 75 | /* 76 | ** set GCdebt to a new value keeping the real number of allocated 77 | ** objects (totalobjs - GCdebt) invariant and avoiding overflows in 78 | ** 'totalobjs'. 79 | */ 80 | void luaE_setdebt (global_State *g, l_obj debt) { 81 | l_obj tb = gettotalobjs(g); 82 | lua_assert(tb > 0); 83 | if (debt > MAX_LOBJ - tb) 84 | debt = MAX_LOBJ - tb; /* will make 'totalobjs == MAX_LMEM' */ 85 | g->totalobjs = tb + debt; 86 | g->GCdebt = debt; 87 | } 88 | 89 | 90 | CallInfo *luaE_extendCI (lua_State *L) { 91 | CallInfo *ci; 92 | lua_assert(L->ci->next == NULL); 93 | ci = luaM_new(L, CallInfo); 94 | lua_assert(L->ci->next == NULL); 95 | L->ci->next = ci; 96 | ci->previous = L->ci; 97 | ci->next = NULL; 98 | ci->u.l.trap = 0; 99 | L->nci++; 100 | return ci; 101 | } 102 | 103 | 104 | /* 105 | ** free all CallInfo structures not in use by a thread 106 | */ 107 | static void freeCI (lua_State *L) { 108 | CallInfo *ci = L->ci; 109 | CallInfo *next = ci->next; 110 | ci->next = NULL; 111 | while ((ci = next) != NULL) { 112 | next = ci->next; 113 | luaM_free(L, ci); 114 | L->nci--; 115 | } 116 | } 117 | 118 | 119 | /* 120 | ** free half of the CallInfo structures not in use by a thread, 121 | ** keeping the first one. 122 | */ 123 | void luaE_shrinkCI (lua_State *L) { 124 | CallInfo *ci = L->ci->next; /* first free CallInfo */ 125 | CallInfo *next; 126 | if (ci == NULL) 127 | return; /* no extra elements */ 128 | while ((next = ci->next) != NULL) { /* two extra elements? */ 129 | CallInfo *next2 = next->next; /* next's next */ 130 | ci->next = next2; /* remove next from the list */ 131 | L->nci--; 132 | luaM_free(L, next); /* free next */ 133 | if (next2 == NULL) 134 | break; /* no more elements */ 135 | else { 136 | next2->previous = ci; 137 | ci = next2; /* continue */ 138 | } 139 | } 140 | } 141 | 142 | 143 | /* 144 | ** Called when 'getCcalls(L)' larger or equal to LUAI_MAXCCALLS. 145 | ** If equal, raises an overflow error. If value is larger than 146 | ** LUAI_MAXCCALLS (which means it is handling an overflow) but 147 | ** not much larger, does not report an error (to allow overflow 148 | ** handling to work). 149 | */ 150 | void luaE_checkcstack (lua_State *L) { 151 | if (getCcalls(L) == LUAI_MAXCCALLS) 152 | luaG_runerror(L, "C stack overflow"); 153 | else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11)) 154 | luaD_throw(L, LUA_ERRERR); /* error while handling stack error */ 155 | } 156 | 157 | 158 | LUAI_FUNC void luaE_incCstack (lua_State *L) { 159 | L->nCcalls++; 160 | if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) 161 | luaE_checkcstack(L); 162 | } 163 | 164 | 165 | static void stack_init (lua_State *L1, lua_State *L) { 166 | int i; CallInfo *ci; 167 | /* initialize stack array */ 168 | L1->stack.p = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); 169 | L1->tbclist.p = L1->stack.p; 170 | for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++) 171 | setnilvalue(s2v(L1->stack.p + i)); /* erase new stack */ 172 | L1->top.p = L1->stack.p; 173 | L1->stack_last.p = L1->stack.p + BASIC_STACK_SIZE; 174 | /* initialize first ci */ 175 | ci = &L1->base_ci; 176 | ci->next = ci->previous = NULL; 177 | ci->callstatus = CIST_C; 178 | ci->func.p = L1->top.p; 179 | ci->u.c.k = NULL; 180 | ci->nresults = 0; 181 | setnilvalue(s2v(L1->top.p)); /* 'function' entry for this 'ci' */ 182 | L1->top.p++; 183 | ci->top.p = L1->top.p + LUA_MINSTACK; 184 | L1->ci = ci; 185 | } 186 | 187 | 188 | static void freestack (lua_State *L) { 189 | if (L->stack.p == NULL) 190 | return; /* stack not completely built yet */ 191 | L->ci = &L->base_ci; /* free the entire 'ci' list */ 192 | freeCI(L); 193 | lua_assert(L->nci == 0); 194 | luaM_freearray(L, L->stack.p, stacksize(L) + EXTRA_STACK); /* free stack */ 195 | } 196 | 197 | 198 | /* 199 | ** Create registry table and its predefined values 200 | */ 201 | static void init_registry (lua_State *L, global_State *g) { 202 | /* create registry */ 203 | TValue aux; 204 | Table *registry = luaH_new(L); 205 | sethvalue(L, &g->l_registry, registry); 206 | luaH_resize(L, registry, LUA_RIDX_LAST, 0); 207 | /* registry[1] = false */ 208 | setbfvalue(&aux); 209 | luaH_setint(L, registry, 1, &aux); 210 | /* registry[LUA_RIDX_MAINTHREAD] = L */ 211 | setthvalue(L, &aux, L); 212 | luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &aux); 213 | /* registry[LUA_RIDX_GLOBALS] = new table (table of globals) */ 214 | sethvalue(L, &aux, luaH_new(L)); 215 | luaH_setint(L, registry, LUA_RIDX_GLOBALS, &aux); 216 | } 217 | 218 | 219 | /* 220 | ** open parts of the state that may cause memory-allocation errors. 221 | */ 222 | static void f_luaopen (lua_State *L, void *ud) { 223 | global_State *g = G(L); 224 | UNUSED(ud); 225 | stack_init(L, L); /* init stack */ 226 | init_registry(L, g); 227 | luaS_init(L); 228 | luaT_init(L); 229 | luaX_init(L); 230 | g->gcstp = 0; /* allow gc */ 231 | setnilvalue(&g->nilvalue); /* now state is complete */ 232 | luai_userstateopen(L); 233 | } 234 | 235 | 236 | /* 237 | ** preinitialize a thread with consistent values without allocating 238 | ** any memory (to avoid errors) 239 | */ 240 | static void preinit_thread (lua_State *L, global_State *g) { 241 | G(L) = g; 242 | L->stack.p = NULL; 243 | L->ci = NULL; 244 | L->nci = 0; 245 | L->twups = L; /* thread has no upvalues */ 246 | L->nCcalls = 0; 247 | L->errorJmp = NULL; 248 | L->hook = NULL; 249 | L->hookmask = 0; 250 | L->basehookcount = 0; 251 | L->allowhook = 1; 252 | resethookcount(L); 253 | L->openupval = NULL; 254 | L->status = LUA_OK; 255 | L->errfunc = 0; 256 | L->oldpc = 0; 257 | } 258 | 259 | 260 | static void close_state (lua_State *L) { 261 | global_State *g = G(L); 262 | if (!completestate(g)) /* closing a partially built state? */ 263 | luaC_freeallobjects(L); /* just collect its objects */ 264 | else { /* closing a fully built state */ 265 | L->ci = &L->base_ci; /* unwind CallInfo list */ 266 | luaD_closeprotected(L, 1, LUA_OK); /* close all upvalues */ 267 | luaC_freeallobjects(L); /* collect all objects */ 268 | luai_userstateclose(L); 269 | } 270 | luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); 271 | freestack(L); 272 | lua_assert(g->totalbytes == sizeof(LG)); 273 | lua_assert(gettotalobjs(g) == 1); 274 | (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ 275 | } 276 | 277 | 278 | LUA_API lua_State *lua_newthread (lua_State *L) { 279 | global_State *g = G(L); 280 | GCObject *o; 281 | lua_State *L1; 282 | lua_lock(L); 283 | luaC_checkGC(L); 284 | /* create new thread */ 285 | o = luaC_newobjdt(L, LUA_TTHREAD, sizeof(LX), offsetof(LX, l)); 286 | L1 = gco2th(o); 287 | /* anchor it on L stack */ 288 | setthvalue2s(L, L->top.p, L1); 289 | api_incr_top(L); 290 | preinit_thread(L1, g); 291 | L1->hookmask = L->hookmask; 292 | L1->basehookcount = L->basehookcount; 293 | L1->hook = L->hook; 294 | resethookcount(L1); 295 | /* initialize L1 extra space */ 296 | memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread), 297 | LUA_EXTRASPACE); 298 | luai_userstatethread(L, L1); 299 | stack_init(L1, L); /* init stack */ 300 | lua_unlock(L); 301 | return L1; 302 | } 303 | 304 | 305 | void luaE_freethread (lua_State *L, lua_State *L1) { 306 | LX *l = fromstate(L1); 307 | luaF_closeupval(L1, L1->stack.p); /* close all upvalues */ 308 | lua_assert(L1->openupval == NULL); 309 | luai_userstatefree(L, L1); 310 | freestack(L1); 311 | luaM_free(L, l); 312 | } 313 | 314 | 315 | int luaE_resetthread (lua_State *L, int status) { 316 | CallInfo *ci = L->ci = &L->base_ci; /* unwind CallInfo list */ 317 | setnilvalue(s2v(L->stack.p)); /* 'function' entry for basic 'ci' */ 318 | ci->func.p = L->stack.p; 319 | ci->callstatus = CIST_C; 320 | if (status == LUA_YIELD) 321 | status = LUA_OK; 322 | L->status = LUA_OK; /* so it can run __close metamethods */ 323 | status = luaD_closeprotected(L, 1, status); 324 | if (status != LUA_OK) /* errors? */ 325 | luaD_seterrorobj(L, status, L->stack.p + 1); 326 | else 327 | L->top.p = L->stack.p + 1; 328 | ci->top.p = L->top.p + LUA_MINSTACK; 329 | luaD_reallocstack(L, cast_int(ci->top.p - L->stack.p), 0); 330 | return status; 331 | } 332 | 333 | 334 | LUA_API int lua_closethread (lua_State *L, lua_State *from) { 335 | int status; 336 | lua_lock(L); 337 | L->nCcalls = (from) ? getCcalls(from) : 0; 338 | status = luaE_resetthread(L, L->status); 339 | lua_unlock(L); 340 | return status; 341 | } 342 | 343 | 344 | LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned seed) { 345 | int i; 346 | lua_State *L; 347 | global_State *g; 348 | LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG))); 349 | if (l == NULL) return NULL; 350 | L = &l->l.l; 351 | g = &l->g; 352 | L->tt = LUA_VTHREAD; 353 | g->currentwhite = bitmask(WHITE0BIT); 354 | L->marked = luaC_white(g); 355 | preinit_thread(L, g); 356 | g->allgc = obj2gco(L); /* by now, only object is the main thread */ 357 | L->next = NULL; 358 | incnny(L); /* main thread is always non yieldable */ 359 | g->frealloc = f; 360 | g->ud = ud; 361 | g->warnf = NULL; 362 | g->ud_warn = NULL; 363 | g->mainthread = L; 364 | g->seed = seed; 365 | g->gcstp = GCSTPGC; /* no GC while building state */ 366 | g->strt.size = g->strt.nuse = 0; 367 | g->strt.hash = NULL; 368 | setnilvalue(&g->l_registry); 369 | g->panic = NULL; 370 | g->gcstate = GCSpause; 371 | g->gckind = KGC_INC; 372 | g->gcstopem = 0; 373 | g->gcemergency = 0; 374 | g->finobj = g->tobefnz = g->fixedgc = NULL; 375 | g->firstold1 = g->survival = g->old1 = g->reallyold = NULL; 376 | g->finobjsur = g->finobjold1 = g->finobjrold = NULL; 377 | g->sweepgc = NULL; 378 | g->gray = g->grayagain = NULL; 379 | g->weak = g->ephemeron = g->allweak = NULL; 380 | g->twups = NULL; 381 | g->totalbytes = sizeof(LG); 382 | g->totalobjs = 1; 383 | g->marked = 0; 384 | g->GCdebt = 0; 385 | setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */ 386 | setgcparam(g, PAUSE, LUAI_GCPAUSE); 387 | setgcparam(g, STEPMUL, LUAI_GCMUL); 388 | setgcparam(g, STEPSIZE, LUAI_GCSTEPSIZE); 389 | setgcparam(g, MINORMUL, LUAI_GENMINORMUL); 390 | setgcparam(g, MINORMAJOR, LUAI_MINORMAJOR); 391 | setgcparam(g, MAJORMINOR, LUAI_MAJORMINOR); 392 | for (i=0; i < LUA_NUMTYPES; i++) g->mt[i] = NULL; 393 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { 394 | /* memory allocation error: free partial state */ 395 | close_state(L); 396 | L = NULL; 397 | } 398 | return L; 399 | } 400 | 401 | 402 | LUA_API void lua_close (lua_State *L) { 403 | lua_lock(L); 404 | L = G(L)->mainthread; /* only the main thread can be closed */ 405 | close_state(L); 406 | } 407 | 408 | 409 | void luaE_warning (lua_State *L, const char *msg, int tocont) { 410 | lua_WarnFunction wf = G(L)->warnf; 411 | if (wf != NULL) 412 | wf(G(L)->ud_warn, msg, tocont); 413 | } 414 | 415 | 416 | /* 417 | ** Generate a warning from an error message 418 | */ 419 | void luaE_warnerror (lua_State *L, const char *where) { 420 | TValue *errobj = s2v(L->top.p - 1); /* error object */ 421 | const char *msg = (ttisstring(errobj)) 422 | ? getstr(tsvalue(errobj)) 423 | : "error object is not a string"; 424 | /* produce warning "error in %s (%s)" (where, msg) */ 425 | luaE_warning(L, "error in ", 1); 426 | luaE_warning(L, where, 1); 427 | luaE_warning(L, " (", 1); 428 | luaE_warning(L, msg, 1); 429 | luaE_warning(L, ")", 0); 430 | } 431 | 432 | -------------------------------------------------------------------------------- /lua/loslib.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: loslib.c $ 3 | ** Standard Operating System library 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define loslib_c 8 | #define LUA_LIB 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "lua.h" 20 | 21 | #include "lauxlib.h" 22 | #include "lualib.h" 23 | #include "llimits.h" 24 | 25 | 26 | /* 27 | ** {================================================================== 28 | ** List of valid conversion specifiers for the 'strftime' function; 29 | ** options are grouped by length; group of length 2 start with '||'. 30 | ** =================================================================== 31 | */ 32 | #if !defined(LUA_STRFTIMEOPTIONS) /* { */ 33 | 34 | #if defined(LUA_USE_WINDOWS) 35 | #define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYzZ%" \ 36 | "||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */ 37 | #elif defined(LUA_USE_C89) /* ANSI C 89 (only 1-char options) */ 38 | #define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYZ%" 39 | #else /* C99 specification */ 40 | #define LUA_STRFTIMEOPTIONS "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \ 41 | "||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */ 42 | #endif 43 | 44 | #endif /* } */ 45 | /* }================================================================== */ 46 | 47 | 48 | /* 49 | ** {================================================================== 50 | ** Configuration for time-related stuff 51 | ** =================================================================== 52 | */ 53 | 54 | /* 55 | ** type to represent time_t in Lua 56 | */ 57 | #if !defined(LUA_NUMTIME) /* { */ 58 | 59 | #define l_timet lua_Integer 60 | #define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t)) 61 | #define l_gettime(L,arg) luaL_checkinteger(L, arg) 62 | 63 | #else /* }{ */ 64 | 65 | #define l_timet lua_Number 66 | #define l_pushtime(L,t) lua_pushnumber(L,(lua_Number)(t)) 67 | #define l_gettime(L,arg) luaL_checknumber(L, arg) 68 | 69 | #endif /* } */ 70 | 71 | 72 | #if !defined(l_gmtime) /* { */ 73 | /* 74 | ** By default, Lua uses gmtime/localtime, except when POSIX is available, 75 | ** where it uses gmtime_r/localtime_r 76 | */ 77 | 78 | #if defined(LUA_USE_POSIX) /* { */ 79 | 80 | #define l_gmtime(t,r) gmtime_r(t,r) 81 | #define l_localtime(t,r) localtime_r(t,r) 82 | 83 | #else /* }{ */ 84 | 85 | /* ISO C definitions */ 86 | #define l_gmtime(t,r) ((void)(r)->tm_sec, gmtime(t)) 87 | #define l_localtime(t,r) ((void)(r)->tm_sec, localtime(t)) 88 | 89 | #endif /* } */ 90 | 91 | #endif /* } */ 92 | 93 | /* }================================================================== */ 94 | 95 | 96 | /* 97 | ** {================================================================== 98 | ** Configuration for 'tmpnam': 99 | ** By default, Lua uses tmpnam except when POSIX is available, where 100 | ** it uses mkstemp. 101 | ** =================================================================== 102 | */ 103 | #if !defined(lua_tmpnam) /* { */ 104 | 105 | #if defined(LUA_USE_POSIX) /* { */ 106 | 107 | #include 108 | 109 | #define LUA_TMPNAMBUFSIZE 32 110 | 111 | #if !defined(LUA_TMPNAMTEMPLATE) 112 | #define LUA_TMPNAMTEMPLATE "/tmp/lua_XXXXXX" 113 | #endif 114 | 115 | #define lua_tmpnam(b,e) { \ 116 | strcpy(b, LUA_TMPNAMTEMPLATE); \ 117 | e = mkstemp(b); \ 118 | if (e != -1) close(e); \ 119 | e = (e == -1); } 120 | 121 | #else /* }{ */ 122 | 123 | /* ISO C definitions */ 124 | #define LUA_TMPNAMBUFSIZE L_tmpnam 125 | #define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } 126 | 127 | #endif /* } */ 128 | 129 | #endif /* } */ 130 | /* }================================================================== */ 131 | 132 | 133 | #if !defined(l_system) 134 | #if defined(LUA_USE_IOS) 135 | /* Despite claiming to be ISO C, iOS does not implement 'system'. */ 136 | #define l_system(cmd) ((cmd) == NULL ? 0 : -1) 137 | #else 138 | #define l_system(cmd) system(cmd) /* default definition */ 139 | #endif 140 | #endif 141 | 142 | 143 | static int os_execute (lua_State *L) { 144 | const char *cmd = luaL_optstring(L, 1, NULL); 145 | int stat; 146 | errno = 0; 147 | stat = l_system(cmd); 148 | if (cmd != NULL) 149 | return luaL_execresult(L, stat); 150 | else { 151 | lua_pushboolean(L, stat); /* true if there is a shell */ 152 | return 1; 153 | } 154 | } 155 | 156 | 157 | static int os_remove (lua_State *L) { 158 | const char *filename = luaL_checkstring(L, 1); 159 | errno = 0; 160 | return luaL_fileresult(L, remove(filename) == 0, filename); 161 | } 162 | 163 | 164 | static int os_rename (lua_State *L) { 165 | const char *fromname = luaL_checkstring(L, 1); 166 | const char *toname = luaL_checkstring(L, 2); 167 | errno = 0; 168 | return luaL_fileresult(L, rename(fromname, toname) == 0, NULL); 169 | } 170 | 171 | 172 | static int os_tmpname (lua_State *L) { 173 | char buff[LUA_TMPNAMBUFSIZE]; 174 | int err; 175 | lua_tmpnam(buff, err); 176 | if (l_unlikely(err)) 177 | return luaL_error(L, "unable to generate a unique filename"); 178 | lua_pushstring(L, buff); 179 | return 1; 180 | } 181 | 182 | 183 | static int os_getenv (lua_State *L) { 184 | lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ 185 | return 1; 186 | } 187 | 188 | 189 | static int os_clock (lua_State *L) { 190 | lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); 191 | return 1; 192 | } 193 | 194 | 195 | /* 196 | ** {====================================================== 197 | ** Time/Date operations 198 | ** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, 199 | ** wday=%w+1, yday=%j, isdst=? } 200 | ** ======================================================= 201 | */ 202 | 203 | /* 204 | ** About the overflow check: an overflow cannot occur when time 205 | ** is represented by a lua_Integer, because either lua_Integer is 206 | ** large enough to represent all int fields or it is not large enough 207 | ** to represent a time that cause a field to overflow. However, if 208 | ** times are represented as doubles and lua_Integer is int, then the 209 | ** time 0x1.e1853b0d184f6p+55 would cause an overflow when adding 1900 210 | ** to compute the year. 211 | */ 212 | static void setfield (lua_State *L, const char *key, int value, int delta) { 213 | #if (defined(LUA_NUMTIME) && LUA_MAXINTEGER <= INT_MAX) 214 | if (l_unlikely(value > LUA_MAXINTEGER - delta)) 215 | luaL_error(L, "field '%s' is out-of-bound", key); 216 | #endif 217 | lua_pushinteger(L, (lua_Integer)value + delta); 218 | lua_setfield(L, -2, key); 219 | } 220 | 221 | 222 | static void setboolfield (lua_State *L, const char *key, int value) { 223 | if (value < 0) /* undefined? */ 224 | return; /* does not set field */ 225 | lua_pushboolean(L, value); 226 | lua_setfield(L, -2, key); 227 | } 228 | 229 | 230 | /* 231 | ** Set all fields from structure 'tm' in the table on top of the stack 232 | */ 233 | static void setallfields (lua_State *L, struct tm *stm) { 234 | setfield(L, "year", stm->tm_year, 1900); 235 | setfield(L, "month", stm->tm_mon, 1); 236 | setfield(L, "day", stm->tm_mday, 0); 237 | setfield(L, "hour", stm->tm_hour, 0); 238 | setfield(L, "min", stm->tm_min, 0); 239 | setfield(L, "sec", stm->tm_sec, 0); 240 | setfield(L, "yday", stm->tm_yday, 1); 241 | setfield(L, "wday", stm->tm_wday, 1); 242 | setboolfield(L, "isdst", stm->tm_isdst); 243 | } 244 | 245 | 246 | static int getboolfield (lua_State *L, const char *key) { 247 | int res; 248 | res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1); 249 | lua_pop(L, 1); 250 | return res; 251 | } 252 | 253 | 254 | static int getfield (lua_State *L, const char *key, int d, int delta) { 255 | int isnum; 256 | int t = lua_getfield(L, -1, key); /* get field and its type */ 257 | lua_Integer res = lua_tointegerx(L, -1, &isnum); 258 | if (!isnum) { /* field is not an integer? */ 259 | if (l_unlikely(t != LUA_TNIL)) /* some other value? */ 260 | return luaL_error(L, "field '%s' is not an integer", key); 261 | else if (l_unlikely(d < 0)) /* absent field; no default? */ 262 | return luaL_error(L, "field '%s' missing in date table", key); 263 | res = d; 264 | } 265 | else { 266 | if (!(res >= 0 ? res - delta <= INT_MAX : INT_MIN + delta <= res)) 267 | return luaL_error(L, "field '%s' is out-of-bound", key); 268 | res -= delta; 269 | } 270 | lua_pop(L, 1); 271 | return (int)res; 272 | } 273 | 274 | 275 | static const char *checkoption (lua_State *L, const char *conv, 276 | ptrdiff_t convlen, char *buff) { 277 | const char *option = LUA_STRFTIMEOPTIONS; 278 | int oplen = 1; /* length of options being checked */ 279 | for (; *option != '\0' && oplen <= convlen; option += oplen) { 280 | if (*option == '|') /* next block? */ 281 | oplen++; /* will check options with next length (+1) */ 282 | else if (memcmp(conv, option, oplen) == 0) { /* match? */ 283 | memcpy(buff, conv, oplen); /* copy valid option to buffer */ 284 | buff[oplen] = '\0'; 285 | return conv + oplen; /* return next item */ 286 | } 287 | } 288 | luaL_argerror(L, 1, 289 | lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); 290 | return conv; /* to avoid warnings */ 291 | } 292 | 293 | 294 | static time_t l_checktime (lua_State *L, int arg) { 295 | l_timet t = l_gettime(L, arg); 296 | luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds"); 297 | return (time_t)t; 298 | } 299 | 300 | 301 | /* maximum size for an individual 'strftime' item */ 302 | #define SIZETIMEFMT 250 303 | 304 | 305 | static int os_date (lua_State *L) { 306 | size_t slen; 307 | const char *s = luaL_optlstring(L, 1, "%c", &slen); 308 | time_t t = luaL_opt(L, l_checktime, 2, time(NULL)); 309 | const char *se = s + slen; /* 's' end */ 310 | struct tm tmr, *stm; 311 | if (*s == '!') { /* UTC? */ 312 | stm = l_gmtime(&t, &tmr); 313 | s++; /* skip '!' */ 314 | } 315 | else 316 | stm = l_localtime(&t, &tmr); 317 | if (stm == NULL) /* invalid date? */ 318 | return luaL_error(L, 319 | "date result cannot be represented in this installation"); 320 | if (strcmp(s, "*t") == 0) { 321 | lua_createtable(L, 0, 9); /* 9 = number of fields */ 322 | setallfields(L, stm); 323 | } 324 | else { 325 | char cc[4]; /* buffer for individual conversion specifiers */ 326 | luaL_Buffer b; 327 | cc[0] = '%'; 328 | luaL_buffinit(L, &b); 329 | while (s < se) { 330 | if (*s != '%') /* not a conversion specifier? */ 331 | luaL_addchar(&b, *s++); 332 | else { 333 | size_t reslen; 334 | char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT); 335 | s++; /* skip '%' */ 336 | s = checkoption(L, s, se - s, cc + 1); /* copy specifier to 'cc' */ 337 | reslen = strftime(buff, SIZETIMEFMT, cc, stm); 338 | luaL_addsize(&b, reslen); 339 | } 340 | } 341 | luaL_pushresult(&b); 342 | } 343 | return 1; 344 | } 345 | 346 | 347 | static int os_time (lua_State *L) { 348 | time_t t; 349 | if (lua_isnoneornil(L, 1)) /* called without args? */ 350 | t = time(NULL); /* get current time */ 351 | else { 352 | struct tm ts; 353 | luaL_checktype(L, 1, LUA_TTABLE); 354 | lua_settop(L, 1); /* make sure table is at the top */ 355 | ts.tm_year = getfield(L, "year", -1, 1900); 356 | ts.tm_mon = getfield(L, "month", -1, 1); 357 | ts.tm_mday = getfield(L, "day", -1, 0); 358 | ts.tm_hour = getfield(L, "hour", 12, 0); 359 | ts.tm_min = getfield(L, "min", 0, 0); 360 | ts.tm_sec = getfield(L, "sec", 0, 0); 361 | ts.tm_isdst = getboolfield(L, "isdst"); 362 | t = mktime(&ts); 363 | setallfields(L, &ts); /* update fields with normalized values */ 364 | } 365 | if (t != (time_t)(l_timet)t || t == (time_t)(-1)) 366 | return luaL_error(L, 367 | "time result cannot be represented in this installation"); 368 | l_pushtime(L, t); 369 | return 1; 370 | } 371 | 372 | 373 | static int os_difftime (lua_State *L) { 374 | time_t t1 = l_checktime(L, 1); 375 | time_t t2 = l_checktime(L, 2); 376 | lua_pushnumber(L, (lua_Number)difftime(t1, t2)); 377 | return 1; 378 | } 379 | 380 | /* }====================================================== */ 381 | 382 | 383 | static int os_setlocale (lua_State *L) { 384 | static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, 385 | LC_NUMERIC, LC_TIME}; 386 | static const char *const catnames[] = {"all", "collate", "ctype", "monetary", 387 | "numeric", "time", NULL}; 388 | const char *l = luaL_optstring(L, 1, NULL); 389 | int op = luaL_checkoption(L, 2, "all", catnames); 390 | lua_pushstring(L, setlocale(cat[op], l)); 391 | return 1; 392 | } 393 | 394 | 395 | static int os_exit (lua_State *L) { 396 | int status; 397 | if (lua_isboolean(L, 1)) 398 | status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE); 399 | else 400 | status = (int)luaL_optinteger(L, 1, EXIT_SUCCESS); 401 | if (lua_toboolean(L, 2)) 402 | lua_close(L); 403 | if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */ 404 | return 0; 405 | } 406 | 407 | 408 | static const luaL_Reg syslib[] = { 409 | {"clock", os_clock}, 410 | {"date", os_date}, 411 | {"difftime", os_difftime}, 412 | {"execute", os_execute}, 413 | {"exit", os_exit}, 414 | {"getenv", os_getenv}, 415 | {"remove", os_remove}, 416 | {"rename", os_rename}, 417 | {"setlocale", os_setlocale}, 418 | {"time", os_time}, 419 | {"tmpname", os_tmpname}, 420 | {NULL, NULL} 421 | }; 422 | 423 | /* }====================================================== */ 424 | 425 | 426 | 427 | LUAMOD_API int luaopen_os (lua_State *L) { 428 | luaL_newlib(L, syslib); 429 | return 1; 430 | } 431 | 432 | -------------------------------------------------------------------------------- /lua/ltablib.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltablib.c $ 3 | ** Library for Table Manipulation 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define ltablib_c 8 | #define LUA_LIB 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "lua.h" 18 | 19 | #include "lauxlib.h" 20 | #include "lualib.h" 21 | #include "llimits.h" 22 | 23 | 24 | /* 25 | ** Operations that an object must define to mimic a table 26 | ** (some functions only need some of them) 27 | */ 28 | #define TAB_R 1 /* read */ 29 | #define TAB_W 2 /* write */ 30 | #define TAB_L 4 /* length */ 31 | #define TAB_RW (TAB_R | TAB_W) /* read/write */ 32 | 33 | 34 | #define aux_getn(L,n,w) (checktab(L, n, (w) | TAB_L), luaL_len(L, n)) 35 | 36 | 37 | static int checkfield (lua_State *L, const char *key, int n) { 38 | lua_pushstring(L, key); 39 | return (lua_rawget(L, -n) != LUA_TNIL); 40 | } 41 | 42 | 43 | /* 44 | ** Check that 'arg' either is a table or can behave like one (that is, 45 | ** has a metatable with the required metamethods) 46 | */ 47 | static void checktab (lua_State *L, int arg, int what) { 48 | if (lua_type(L, arg) != LUA_TTABLE) { /* is it not a table? */ 49 | int n = 1; /* number of elements to pop */ 50 | if (lua_getmetatable(L, arg) && /* must have metatable */ 51 | (!(what & TAB_R) || checkfield(L, "__index", ++n)) && 52 | (!(what & TAB_W) || checkfield(L, "__newindex", ++n)) && 53 | (!(what & TAB_L) || checkfield(L, "__len", ++n))) { 54 | lua_pop(L, n); /* pop metatable and tested metamethods */ 55 | } 56 | else 57 | luaL_checktype(L, arg, LUA_TTABLE); /* force an error */ 58 | } 59 | } 60 | 61 | 62 | static int tcreate (lua_State *L) { 63 | lua_Unsigned sizeseq = (lua_Unsigned)luaL_checkinteger(L, 1); 64 | lua_Unsigned sizerest = (lua_Unsigned)luaL_optinteger(L, 2, 0); 65 | luaL_argcheck(L, sizeseq <= UINT_MAX, 1, "out of range"); 66 | luaL_argcheck(L, sizerest <= UINT_MAX, 2, "out of range"); 67 | lua_createtable(L, (unsigned)sizeseq, (unsigned)sizerest); 68 | return 1; 69 | } 70 | 71 | 72 | static int tinsert (lua_State *L) { 73 | lua_Integer pos; /* where to insert new element */ 74 | lua_Integer e = aux_getn(L, 1, TAB_RW); 75 | e = luaL_intop(+, e, 1); /* first empty element */ 76 | switch (lua_gettop(L)) { 77 | case 2: { /* called with only 2 arguments */ 78 | pos = e; /* insert new element at the end */ 79 | break; 80 | } 81 | case 3: { 82 | lua_Integer i; 83 | pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */ 84 | /* check whether 'pos' is in [1, e] */ 85 | luaL_argcheck(L, (lua_Unsigned)pos - 1u < (lua_Unsigned)e, 2, 86 | "position out of bounds"); 87 | for (i = e; i > pos; i--) { /* move up elements */ 88 | lua_geti(L, 1, i - 1); 89 | lua_seti(L, 1, i); /* t[i] = t[i - 1] */ 90 | } 91 | break; 92 | } 93 | default: { 94 | return luaL_error(L, "wrong number of arguments to 'insert'"); 95 | } 96 | } 97 | lua_seti(L, 1, pos); /* t[pos] = v */ 98 | return 0; 99 | } 100 | 101 | 102 | static int tremove (lua_State *L) { 103 | lua_Integer size = aux_getn(L, 1, TAB_RW); 104 | lua_Integer pos = luaL_optinteger(L, 2, size); 105 | if (pos != size) /* validate 'pos' if given */ 106 | /* check whether 'pos' is in [1, size + 1] */ 107 | luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 2, 108 | "position out of bounds"); 109 | lua_geti(L, 1, pos); /* result = t[pos] */ 110 | for ( ; pos < size; pos++) { 111 | lua_geti(L, 1, pos + 1); 112 | lua_seti(L, 1, pos); /* t[pos] = t[pos + 1] */ 113 | } 114 | lua_pushnil(L); 115 | lua_seti(L, 1, pos); /* remove entry t[pos] */ 116 | return 1; 117 | } 118 | 119 | 120 | /* 121 | ** Copy elements (1[f], ..., 1[e]) into (tt[t], tt[t+1], ...). Whenever 122 | ** possible, copy in increasing order, which is better for rehashing. 123 | ** "possible" means destination after original range, or smaller 124 | ** than origin, or copying to another table. 125 | */ 126 | static int tmove (lua_State *L) { 127 | lua_Integer f = luaL_checkinteger(L, 2); 128 | lua_Integer e = luaL_checkinteger(L, 3); 129 | lua_Integer t = luaL_checkinteger(L, 4); 130 | int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */ 131 | checktab(L, 1, TAB_R); 132 | checktab(L, tt, TAB_W); 133 | if (e >= f) { /* otherwise, nothing to move */ 134 | lua_Integer n, i; 135 | luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3, 136 | "too many elements to move"); 137 | n = e - f + 1; /* number of elements to move */ 138 | luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4, 139 | "destination wrap around"); 140 | if (t > e || t <= f || (tt != 1 && !lua_compare(L, 1, tt, LUA_OPEQ))) { 141 | for (i = 0; i < n; i++) { 142 | lua_geti(L, 1, f + i); 143 | lua_seti(L, tt, t + i); 144 | } 145 | } 146 | else { 147 | for (i = n - 1; i >= 0; i--) { 148 | lua_geti(L, 1, f + i); 149 | lua_seti(L, tt, t + i); 150 | } 151 | } 152 | } 153 | lua_pushvalue(L, tt); /* return destination table */ 154 | return 1; 155 | } 156 | 157 | 158 | static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) { 159 | lua_geti(L, 1, i); 160 | if (l_unlikely(!lua_isstring(L, -1))) 161 | luaL_error(L, "invalid value (%s) at index %I in table for 'concat'", 162 | luaL_typename(L, -1), (LUAI_UACINT)i); 163 | luaL_addvalue(b); 164 | } 165 | 166 | 167 | static int tconcat (lua_State *L) { 168 | luaL_Buffer b; 169 | lua_Integer last = aux_getn(L, 1, TAB_R); 170 | size_t lsep; 171 | const char *sep = luaL_optlstring(L, 2, "", &lsep); 172 | lua_Integer i = luaL_optinteger(L, 3, 1); 173 | last = luaL_optinteger(L, 4, last); 174 | luaL_buffinit(L, &b); 175 | for (; i < last; i++) { 176 | addfield(L, &b, i); 177 | luaL_addlstring(&b, sep, lsep); 178 | } 179 | if (i == last) /* add last value (if interval was not empty) */ 180 | addfield(L, &b, i); 181 | luaL_pushresult(&b); 182 | return 1; 183 | } 184 | 185 | 186 | /* 187 | ** {====================================================== 188 | ** Pack/unpack 189 | ** ======================================================= 190 | */ 191 | 192 | static int tpack (lua_State *L) { 193 | int i; 194 | int n = lua_gettop(L); /* number of elements to pack */ 195 | lua_createtable(L, n, 1); /* create result table */ 196 | lua_insert(L, 1); /* put it at index 1 */ 197 | for (i = n; i >= 1; i--) /* assign elements */ 198 | lua_seti(L, 1, i); 199 | lua_pushinteger(L, n); 200 | lua_setfield(L, 1, "n"); /* t.n = number of elements */ 201 | return 1; /* return table */ 202 | } 203 | 204 | 205 | static int tunpack (lua_State *L) { 206 | lua_Unsigned n; 207 | lua_Integer i = luaL_optinteger(L, 2, 1); 208 | lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1)); 209 | if (i > e) return 0; /* empty range */ 210 | n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */ 211 | if (l_unlikely(n >= (unsigned int)INT_MAX || 212 | !lua_checkstack(L, (int)(++n)))) 213 | return luaL_error(L, "too many results to unpack"); 214 | for (; i < e; i++) { /* push arg[i..e - 1] (to avoid overflows) */ 215 | lua_geti(L, 1, i); 216 | } 217 | lua_geti(L, 1, e); /* push last element */ 218 | return (int)n; 219 | } 220 | 221 | /* }====================================================== */ 222 | 223 | 224 | 225 | /* 226 | ** {====================================================== 227 | ** Quicksort 228 | ** (based on 'Algorithms in MODULA-3', Robert Sedgewick; 229 | ** Addison-Wesley, 1993.) 230 | ** ======================================================= 231 | */ 232 | 233 | 234 | /* type for array indices */ 235 | typedef unsigned int IdxT; 236 | 237 | 238 | /* 239 | ** Produce a "random" 'unsigned int' to randomize pivot choice. This 240 | ** macro is used only when 'sort' detects a big imbalance in the result 241 | ** of a partition. (If you don't want/need this "randomness", ~0 is a 242 | ** good choice.) 243 | */ 244 | #if !defined(l_randomizePivot) 245 | #define l_randomizePivot(L) luaL_makeseed(L) 246 | #endif /* } */ 247 | 248 | 249 | /* arrays larger than 'RANLIMIT' may use randomized pivots */ 250 | #define RANLIMIT 100u 251 | 252 | 253 | static void set2 (lua_State *L, IdxT i, IdxT j) { 254 | lua_seti(L, 1, i); 255 | lua_seti(L, 1, j); 256 | } 257 | 258 | 259 | /* 260 | ** Return true iff value at stack index 'a' is less than the value at 261 | ** index 'b' (according to the order of the sort). 262 | */ 263 | static int sort_comp (lua_State *L, int a, int b) { 264 | if (lua_isnil(L, 2)) /* no function? */ 265 | return lua_compare(L, a, b, LUA_OPLT); /* a < b */ 266 | else { /* function */ 267 | int res; 268 | lua_pushvalue(L, 2); /* push function */ 269 | lua_pushvalue(L, a-1); /* -1 to compensate function */ 270 | lua_pushvalue(L, b-2); /* -2 to compensate function and 'a' */ 271 | lua_call(L, 2, 1); /* call function */ 272 | res = lua_toboolean(L, -1); /* get result */ 273 | lua_pop(L, 1); /* pop result */ 274 | return res; 275 | } 276 | } 277 | 278 | 279 | /* 280 | ** Does the partition: Pivot P is at the top of the stack. 281 | ** precondition: a[lo] <= P == a[up-1] <= a[up], 282 | ** so it only needs to do the partition from lo + 1 to up - 2. 283 | ** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up] 284 | ** returns 'i'. 285 | */ 286 | static IdxT partition (lua_State *L, IdxT lo, IdxT up) { 287 | IdxT i = lo; /* will be incremented before first use */ 288 | IdxT j = up - 1; /* will be decremented before first use */ 289 | /* loop invariant: a[lo .. i] <= P <= a[j .. up] */ 290 | for (;;) { 291 | /* next loop: repeat ++i while a[i] < P */ 292 | while ((void)lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) { 293 | if (l_unlikely(i == up - 1)) /* a[i] < P but a[up - 1] == P ?? */ 294 | luaL_error(L, "invalid order function for sorting"); 295 | lua_pop(L, 1); /* remove a[i] */ 296 | } 297 | /* after the loop, a[i] >= P and a[lo .. i - 1] < P */ 298 | /* next loop: repeat --j while P < a[j] */ 299 | while ((void)lua_geti(L, 1, --j), sort_comp(L, -3, -1)) { 300 | if (l_unlikely(j < i)) /* j < i but a[j] > P ?? */ 301 | luaL_error(L, "invalid order function for sorting"); 302 | lua_pop(L, 1); /* remove a[j] */ 303 | } 304 | /* after the loop, a[j] <= P and a[j + 1 .. up] >= P */ 305 | if (j < i) { /* no elements out of place? */ 306 | /* a[lo .. i - 1] <= P <= a[j + 1 .. i .. up] */ 307 | lua_pop(L, 1); /* pop a[j] */ 308 | /* swap pivot (a[up - 1]) with a[i] to satisfy pos-condition */ 309 | set2(L, up - 1, i); 310 | return i; 311 | } 312 | /* otherwise, swap a[i] - a[j] to restore invariant and repeat */ 313 | set2(L, i, j); 314 | } 315 | } 316 | 317 | 318 | /* 319 | ** Choose an element in the middle (2nd-3th quarters) of [lo,up] 320 | ** "randomized" by 'rnd' 321 | */ 322 | static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) { 323 | IdxT r4 = (up - lo) / 4; /* range/4 */ 324 | IdxT p = (rnd ^ lo ^ up) % (r4 * 2) + (lo + r4); 325 | lua_assert(lo + r4 <= p && p <= up - r4); 326 | return p; 327 | } 328 | 329 | 330 | /* 331 | ** Quicksort algorithm (recursive function) 332 | */ 333 | static void auxsort (lua_State *L, IdxT lo, IdxT up, unsigned rnd) { 334 | while (lo < up) { /* loop for tail recursion */ 335 | IdxT p; /* Pivot index */ 336 | IdxT n; /* to be used later */ 337 | /* sort elements 'lo', 'p', and 'up' */ 338 | lua_geti(L, 1, lo); 339 | lua_geti(L, 1, up); 340 | if (sort_comp(L, -1, -2)) /* a[up] < a[lo]? */ 341 | set2(L, lo, up); /* swap a[lo] - a[up] */ 342 | else 343 | lua_pop(L, 2); /* remove both values */ 344 | if (up - lo == 1) /* only 2 elements? */ 345 | return; /* already sorted */ 346 | if (up - lo < RANLIMIT || rnd == 0) /* small interval or no randomize? */ 347 | p = (lo + up)/2; /* middle element is a good pivot */ 348 | else /* for larger intervals, it is worth a random pivot */ 349 | p = choosePivot(lo, up, rnd); 350 | lua_geti(L, 1, p); 351 | lua_geti(L, 1, lo); 352 | if (sort_comp(L, -2, -1)) /* a[p] < a[lo]? */ 353 | set2(L, p, lo); /* swap a[p] - a[lo] */ 354 | else { 355 | lua_pop(L, 1); /* remove a[lo] */ 356 | lua_geti(L, 1, up); 357 | if (sort_comp(L, -1, -2)) /* a[up] < a[p]? */ 358 | set2(L, p, up); /* swap a[up] - a[p] */ 359 | else 360 | lua_pop(L, 2); 361 | } 362 | if (up - lo == 2) /* only 3 elements? */ 363 | return; /* already sorted */ 364 | lua_geti(L, 1, p); /* get middle element (Pivot) */ 365 | lua_pushvalue(L, -1); /* push Pivot */ 366 | lua_geti(L, 1, up - 1); /* push a[up - 1] */ 367 | set2(L, p, up - 1); /* swap Pivot (a[p]) with a[up - 1] */ 368 | p = partition(L, lo, up); 369 | /* a[lo .. p - 1] <= a[p] == P <= a[p + 1 .. up] */ 370 | if (p - lo < up - p) { /* lower interval is smaller? */ 371 | auxsort(L, lo, p - 1, rnd); /* call recursively for lower interval */ 372 | n = p - lo; /* size of smaller interval */ 373 | lo = p + 1; /* tail call for [p + 1 .. up] (upper interval) */ 374 | } 375 | else { 376 | auxsort(L, p + 1, up, rnd); /* call recursively for upper interval */ 377 | n = up - p; /* size of smaller interval */ 378 | up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */ 379 | } 380 | if ((up - lo) / 128 > n) /* partition too imbalanced? */ 381 | rnd = l_randomizePivot(L); /* try a new randomization */ 382 | } /* tail call auxsort(L, lo, up, rnd) */ 383 | } 384 | 385 | 386 | static int sort (lua_State *L) { 387 | lua_Integer n = aux_getn(L, 1, TAB_RW); 388 | if (n > 1) { /* non-trivial interval? */ 389 | luaL_argcheck(L, n < INT_MAX, 1, "array too big"); 390 | if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ 391 | luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */ 392 | lua_settop(L, 2); /* make sure there are two arguments */ 393 | auxsort(L, 1, (IdxT)n, 0); 394 | } 395 | return 0; 396 | } 397 | 398 | /* }====================================================== */ 399 | 400 | 401 | static const luaL_Reg tab_funcs[] = { 402 | {"concat", tconcat}, 403 | {"create", tcreate}, 404 | {"insert", tinsert}, 405 | {"pack", tpack}, 406 | {"unpack", tunpack}, 407 | {"remove", tremove}, 408 | {"move", tmove}, 409 | {"sort", sort}, 410 | {NULL, NULL} 411 | }; 412 | 413 | 414 | LUAMOD_API int luaopen_table (lua_State *L) { 415 | luaL_newlib(L, tab_funcs); 416 | return 1; 417 | } 418 | 419 | --------------------------------------------------------------------------------