diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/bit.c | 191 | ||||
| -rw-r--r-- | src/bit.h | 3 | ||||
| -rwxr-xr-x | src/nvim/CMakeLists.txt | 12 | ||||
| -rw-r--r-- | src/nvim/lua/stdlib.c | 11 | 
4 files changed, 214 insertions, 3 deletions
| diff --git a/src/bit.c b/src/bit.c new file mode 100644 index 0000000000..85d2414582 --- /dev/null +++ b/src/bit.c @@ -0,0 +1,191 @@ +/* +** Lua BitOp -- a bit operations library for Lua 5.1/5.2. +** http://bitop.luajit.org/ +** +** Copyright (C) 2008-2012 Mike Pall. All rights reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +** [ MIT license: http://www.opensource.org/licenses/mit-license.php ] +*/ + +#define LUA_BITOP_VERSION	"1.0.2" + +#define LUA_LIB +#include "lua.h" +#include "lauxlib.h" + +#include "bit.h" + +#ifdef _MSC_VER +/* MSVC is stuck in the last century and doesn't have C99's stdint.h. */ +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +#else +#include <stdint.h> +#endif + +typedef int32_t SBits; +typedef uint32_t UBits; + +typedef union { +  lua_Number n; +#ifdef LUA_NUMBER_DOUBLE +  uint64_t b; +#else +  UBits b; +#endif +} BitNum; + +/* Convert argument to bit type. */ +static UBits barg(lua_State *L, int idx) +{ +  BitNum bn; +  UBits b; +#if LUA_VERSION_NUM < 502 +  bn.n = lua_tonumber(L, idx); +#else +  bn.n = luaL_checknumber(L, idx); +#endif +#if defined(LUA_NUMBER_DOUBLE) +  bn.n += 6755399441055744.0;  /* 2^52+2^51 */ +#ifdef SWAPPED_DOUBLE +  b = (UBits)(bn.b >> 32); +#else +  b = (UBits)bn.b; +#endif +#elif defined(LUA_NUMBER_INT) || defined(LUA_NUMBER_LONG) || \ +      defined(LUA_NUMBER_LONGLONG) || defined(LUA_NUMBER_LONG_LONG) || \ +      defined(LUA_NUMBER_LLONG) +  if (sizeof(UBits) == sizeof(lua_Number)) +    b = bn.b; +  else +    b = (UBits)(SBits)bn.n; +#elif defined(LUA_NUMBER_FLOAT) +#error "A 'float' lua_Number type is incompatible with this library" +#else +#error "Unknown number type, check LUA_NUMBER_* in luaconf.h" +#endif +#if LUA_VERSION_NUM < 502 +  if (b == 0 && !lua_isnumber(L, idx)) { +    luaL_typerror(L, idx, "number"); +  } +#endif +  return b; +} + +/* Return bit type. */ +#define BRET(b)  lua_pushnumber(L, (lua_Number)(SBits)(b)); return 1; + +static int bit_tobit(lua_State *L) { BRET(barg(L, 1)) } +static int bit_bnot(lua_State *L) { BRET(~barg(L, 1)) } + +#define BIT_OP(func, opr) \ +  static int func(lua_State *L) { int i; UBits b = barg(L, 1); \ +    for (i = lua_gettop(L); i > 1; i--) b opr barg(L, i); BRET(b) } +BIT_OP(bit_band, &=) +BIT_OP(bit_bor, |=) +BIT_OP(bit_bxor, ^=) + +#define bshl(b, n)  (b << n) +#define bshr(b, n)  (b >> n) +#define bsar(b, n)  ((SBits)b >> n) +#define brol(b, n)  ((b << n) | (b >> (32-n))) +#define bror(b, n)  ((b << (32-n)) | (b >> n)) +#define BIT_SH(func, fn) \ +  static int func(lua_State *L) { \ +    UBits b = barg(L, 1); UBits n = barg(L, 2) & 31; BRET(fn(b, n)) } +BIT_SH(bit_lshift, bshl) +BIT_SH(bit_rshift, bshr) +BIT_SH(bit_arshift, bsar) +BIT_SH(bit_rol, brol) +BIT_SH(bit_ror, bror) + +static int bit_bswap(lua_State *L) +{ +  UBits b = barg(L, 1); +  b = (b >> 24) | ((b >> 8) & 0xff00) | ((b & 0xff00) << 8) | (b << 24); +  BRET(b) +} + +static int bit_tohex(lua_State *L) +{ +  UBits b = barg(L, 1); +  SBits n = lua_isnone(L, 2) ? 8 : (SBits)barg(L, 2); +  const char *hexdigits = "0123456789abcdef"; +  char buf[8]; +  int i; +  if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; } +  if (n > 8) n = 8; +  for (i = (int)n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; } +  lua_pushlstring(L, buf, (size_t)n); +  return 1; +} + +static const struct luaL_Reg bit_funcs[] = { +  { "tobit",	bit_tobit }, +  { "bnot",	bit_bnot }, +  { "band",	bit_band }, +  { "bor",	bit_bor }, +  { "bxor",	bit_bxor }, +  { "lshift",	bit_lshift }, +  { "rshift",	bit_rshift }, +  { "arshift",	bit_arshift }, +  { "rol",	bit_rol }, +  { "ror",	bit_ror }, +  { "bswap",	bit_bswap }, +  { "tohex",	bit_tohex }, +  { NULL, NULL } +}; + +/* Signed right-shifts are implementation-defined per C89/C99. +** But the de facto standard are arithmetic right-shifts on two's +** complement CPUs. This behaviour is required here, so test for it. +*/ +#define BAD_SAR		(bsar(-8, 2) != (SBits)-2) + +LUALIB_API int luaopen_bit(lua_State *L) +{ +  UBits b; +  lua_pushnumber(L, (lua_Number)1437217655L); +  b = barg(L, -1); +  if (b != (UBits)1437217655L || BAD_SAR) {  /* Perform a simple self-test. */ +    const char *msg = "compiled with incompatible luaconf.h"; +#ifdef LUA_NUMBER_DOUBLE +#ifdef _WIN32 +    if (b == (UBits)1610612736L) +      msg = "use D3DCREATE_FPU_PRESERVE with DirectX"; +#endif +    if (b == (UBits)1127743488L) +      msg = "not compiled with SWAPPED_DOUBLE"; +#endif +    if (BAD_SAR) +      msg = "arithmetic right-shift broken"; +    luaL_error(L, "bit library self-test failed (%s)", msg); +  } +#if LUA_VERSION_NUM < 502 +  luaL_register(L, "bit", bit_funcs); +#else +  luaL_newlib(L, bit_funcs); +#endif +  return 1; +} + diff --git a/src/bit.h b/src/bit.h new file mode 100644 index 0000000000..7e54e6d519 --- /dev/null +++ b/src/bit.h @@ -0,0 +1,3 @@ +#include <lua.h> + +int luaopen_bit(lua_State *L); diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 329e831b2e..8884273649 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -367,6 +367,12 @@ glob_wrapper(NVIM_HEADERS *.h)  glob_wrapper(EXTERNAL_SOURCES ../xdiff/*.c ../mpack/*.c ../cjson/*.c ../klib/*.c)  glob_wrapper(EXTERNAL_HEADERS ../xdiff/*.h ../mpack/*.h ../cjson/*.h ../klib/*.h) +if(PREFER_LUA) +  # luajit not used, use a vendored copy of the bit module +  list(APPEND EXTERNAL_SOURCES ${PROJECT_SOURCE_DIR}/src/bit.c) +  target_compile_definitions(main_lib INTERFACE NVIM_VENDOR_BIT) +endif() +  foreach(subdir          os          api @@ -425,7 +431,7 @@ if(MSVC)      ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -wd4090 -wd4244 -wd4267")  else()    set_source_files_properties( -    ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion -Wno-missing-noreturn -Wno-missing-format-attribute -Wno-double-promotion -Wno-strict-prototypes") +    ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion -Wno-missing-noreturn -Wno-missing-format-attribute -Wno-double-promotion -Wno-strict-prototypes -Wno-misleading-indentation")  endif()  # Log level (MIN_LOG_LEVEL in log.h) @@ -684,8 +690,8 @@ if(UNIX)    endif()  endif() -if(NOT LUAJIT_FOUND) -  message(STATUS "luajit not found, skipping unit tests") +if(PREFER_LUA) +  message(STATUS "luajit not used, skipping unit tests")  else()    glob_wrapper(UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c)    target_sources(nvim PRIVATE $<$<CONFIG:Debug>:${UNIT_TEST_FIXTURES}>) diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c index 5aeff4de98..d9682ff63d 100644 --- a/src/nvim/lua/stdlib.c +++ b/src/nvim/lua/stdlib.c @@ -11,6 +11,10 @@  #include <string.h>  #include <sys/types.h> +#ifdef NVIM_VENDOR_BIT +# include "bit.h" +#endif +  #include "auto/config.h"  #include "cjson/lua_cjson.h"  #include "mpack/lmpack.h" @@ -596,6 +600,13 @@ void nlua_state_add_stdlib(lua_State *const lstate, bool is_thread)    // vim.json    lua_cjson_new(lstate);    lua_setfield(lstate, -2, "json"); + +#ifdef NVIM_VENDOR_BIT +  // if building with puc lua, use internal fallback for require'bit' +  int top = lua_gettop(lstate); +  luaopen_bit(lstate); +  lua_settop(lstate, top); +#endif  }  /// like luaL_error, but allow cleanup | 
