mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	lua/executor: Remove all places where lightuserdata is used
Should fix problems with luajit+arm64. Fixes #7879 Ref LuaJIT/LuaJIT#230
This commit is contained in:
		| @@ -40,66 +40,6 @@ typedef struct { | |||||||
| /// Name of the run code for use in messages | /// Name of the run code for use in messages | ||||||
| #define NLUA_EVAL_NAME "<VimL compiled string>" | #define NLUA_EVAL_NAME "<VimL compiled string>" | ||||||
|  |  | ||||||
| /// Call C function which does not expect any arguments |  | ||||||
| /// |  | ||||||
| /// @param  function  Called function |  | ||||||
| /// @param  numret    Number of returned arguments |  | ||||||
| #define NLUA_CALL_C_FUNCTION_0(lstate, function, numret) \ |  | ||||||
|     do { \ |  | ||||||
|       lua_pushcfunction(lstate, &function); \ |  | ||||||
|       lua_call(lstate, 0, numret); \ |  | ||||||
|     } while (0) |  | ||||||
| /// Call C function which expects one argument |  | ||||||
| /// |  | ||||||
| /// @param  function  Called function |  | ||||||
| /// @param  numret    Number of returned arguments |  | ||||||
| /// @param  a…        Supplied argument (should be a void* pointer) |  | ||||||
| #define NLUA_CALL_C_FUNCTION_1(lstate, function, numret, a1) \ |  | ||||||
|     do { \ |  | ||||||
|       lua_pushcfunction(lstate, &function); \ |  | ||||||
|       lua_pushlightuserdata(lstate, a1); \ |  | ||||||
|       lua_call(lstate, 1, numret); \ |  | ||||||
|     } while (0) |  | ||||||
| /// Call C function which expects two arguments |  | ||||||
| /// |  | ||||||
| /// @param  function  Called function |  | ||||||
| /// @param  numret    Number of returned arguments |  | ||||||
| /// @param  a…        Supplied argument (should be a void* pointer) |  | ||||||
| #define NLUA_CALL_C_FUNCTION_2(lstate, function, numret, a1, a2) \ |  | ||||||
|     do { \ |  | ||||||
|       lua_pushcfunction(lstate, &function); \ |  | ||||||
|       lua_pushlightuserdata(lstate, a1); \ |  | ||||||
|       lua_pushlightuserdata(lstate, a2); \ |  | ||||||
|       lua_call(lstate, 2, numret); \ |  | ||||||
|     } while (0) |  | ||||||
| /// Call C function which expects three arguments |  | ||||||
| /// |  | ||||||
| /// @param  function  Called function |  | ||||||
| /// @param  numret    Number of returned arguments |  | ||||||
| /// @param  a…        Supplied argument (should be a void* pointer) |  | ||||||
| #define NLUA_CALL_C_FUNCTION_3(lstate, function, numret, a1, a2, a3) \ |  | ||||||
|     do { \ |  | ||||||
|       lua_pushcfunction(lstate, &function); \ |  | ||||||
|       lua_pushlightuserdata(lstate, a1); \ |  | ||||||
|       lua_pushlightuserdata(lstate, a2); \ |  | ||||||
|       lua_pushlightuserdata(lstate, a3); \ |  | ||||||
|       lua_call(lstate, 3, numret); \ |  | ||||||
|     } while (0) |  | ||||||
| /// Call C function which expects five arguments |  | ||||||
| /// |  | ||||||
| /// @param  function  Called function |  | ||||||
| /// @param  numret    Number of returned arguments |  | ||||||
| /// @param  a…        Supplied argument (should be a void* pointer) |  | ||||||
| #define NLUA_CALL_C_FUNCTION_4(lstate, function, numret, a1, a2, a3, a4) \ |  | ||||||
|     do { \ |  | ||||||
|       lua_pushcfunction(lstate, &function); \ |  | ||||||
|       lua_pushlightuserdata(lstate, a1); \ |  | ||||||
|       lua_pushlightuserdata(lstate, a2); \ |  | ||||||
|       lua_pushlightuserdata(lstate, a3); \ |  | ||||||
|       lua_pushlightuserdata(lstate, a4); \ |  | ||||||
|       lua_call(lstate, 4, numret); \ |  | ||||||
|     } while (0) |  | ||||||
|  |  | ||||||
| /// Convert lua error into a Vim error message | /// Convert lua error into a Vim error message | ||||||
| /// | /// | ||||||
| /// @param  lstate  Lua interpreter state. | /// @param  lstate  Lua interpreter state. | ||||||
| @@ -163,123 +103,6 @@ static int nlua_stricmp(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL | |||||||
|   return 1; |   return 1; | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Evaluate lua string |  | ||||||
| /// |  | ||||||
| /// Expects two values on the stack: string to evaluate, pointer to the |  | ||||||
| /// location where result is saved. Always returns nothing (from the lua point |  | ||||||
| /// of view). |  | ||||||
| static int nlua_exec_lua_string(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL |  | ||||||
| { |  | ||||||
|   const String *const str = (const String *)lua_touserdata(lstate, 1); |  | ||||||
|   typval_T *const ret_tv = (typval_T *)lua_touserdata(lstate, 2); |  | ||||||
|   lua_pop(lstate, 2); |  | ||||||
|  |  | ||||||
|   if (luaL_loadbuffer(lstate, str->data, str->size, NLUA_EVAL_NAME)) { |  | ||||||
|     nlua_error(lstate, _("E5104: Error while creating lua chunk: %.*s")); |  | ||||||
|     return 0; |  | ||||||
|   } |  | ||||||
|   if (lua_pcall(lstate, 0, 1, 0)) { |  | ||||||
|     nlua_error(lstate, _("E5105: Error while calling lua chunk: %.*s")); |  | ||||||
|     return 0; |  | ||||||
|   } |  | ||||||
|   if (!nlua_pop_typval(lstate, ret_tv)) { |  | ||||||
|     return 0; |  | ||||||
|   } |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Evaluate lua string for each line in range |  | ||||||
| /// |  | ||||||
| /// Expects two values on the stack: string to evaluate and pointer to integer |  | ||||||
| /// array with line range. Always returns nothing (from the lua point of view). |  | ||||||
| static int nlua_exec_luado_string(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL |  | ||||||
| { |  | ||||||
|   const String *const str = (const String *)lua_touserdata(lstate, 1); |  | ||||||
|   const linenr_T *const range = (const linenr_T *)lua_touserdata(lstate, 2); |  | ||||||
|   lua_pop(lstate, 2); |  | ||||||
|  |  | ||||||
| #define DOSTART "return function(line, linenr) " |  | ||||||
| #define DOEND " end" |  | ||||||
|   const size_t lcmd_len = (str->size |  | ||||||
|                            + (sizeof(DOSTART) - 1) |  | ||||||
|                            + (sizeof(DOEND) - 1)); |  | ||||||
|   char *lcmd; |  | ||||||
|   if (lcmd_len < IOSIZE) { |  | ||||||
|     lcmd = (char *)IObuff; |  | ||||||
|   } else { |  | ||||||
|     lcmd = xmalloc(lcmd_len + 1); |  | ||||||
|   } |  | ||||||
|   memcpy(lcmd, DOSTART, sizeof(DOSTART) - 1); |  | ||||||
|   memcpy(lcmd + sizeof(DOSTART) - 1, str->data, str->size); |  | ||||||
|   memcpy(lcmd + sizeof(DOSTART) - 1 + str->size, DOEND, sizeof(DOEND) - 1); |  | ||||||
| #undef DOSTART |  | ||||||
| #undef DOEND |  | ||||||
|  |  | ||||||
|   if (luaL_loadbuffer(lstate, lcmd, lcmd_len, NLUA_EVAL_NAME)) { |  | ||||||
|     nlua_error(lstate, _("E5109: Error while creating lua chunk: %.*s")); |  | ||||||
|     if (lcmd_len >= IOSIZE) { |  | ||||||
|       xfree(lcmd); |  | ||||||
|     } |  | ||||||
|     return 0; |  | ||||||
|   } |  | ||||||
|   if (lcmd_len >= IOSIZE) { |  | ||||||
|     xfree(lcmd); |  | ||||||
|   } |  | ||||||
|   if (lua_pcall(lstate, 0, 1, 0)) { |  | ||||||
|     nlua_error(lstate, _("E5110: Error while creating lua function: %.*s")); |  | ||||||
|     return 0; |  | ||||||
|   } |  | ||||||
|   for (linenr_T l = range[0]; l <= range[1]; l++) { |  | ||||||
|     if (l > curbuf->b_ml.ml_line_count) { |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|     lua_pushvalue(lstate, -1); |  | ||||||
|     lua_pushstring(lstate, (const char *)ml_get_buf(curbuf, l, false)); |  | ||||||
|     lua_pushnumber(lstate, (lua_Number)l); |  | ||||||
|     if (lua_pcall(lstate, 2, 1, 0)) { |  | ||||||
|       nlua_error(lstate, _("E5111: Error while calling lua function: %.*s")); |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|     if (lua_isstring(lstate, -1)) { |  | ||||||
|       size_t new_line_len; |  | ||||||
|       const char *const new_line = lua_tolstring(lstate, -1, &new_line_len); |  | ||||||
|       char *const new_line_transformed = xmemdupz(new_line, new_line_len); |  | ||||||
|       for (size_t i = 0; i < new_line_len; i++) { |  | ||||||
|         if (new_line_transformed[i] == NUL) { |  | ||||||
|           new_line_transformed[i] = '\n'; |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       ml_replace(l, (char_u *)new_line_transformed, false); |  | ||||||
|       changed_bytes(l, 0); |  | ||||||
|     } |  | ||||||
|     lua_pop(lstate, 1); |  | ||||||
|   } |  | ||||||
|   lua_pop(lstate, 1); |  | ||||||
|   check_cursor(); |  | ||||||
|   update_screen(NOT_VALID); |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Evaluate lua file |  | ||||||
| /// |  | ||||||
| /// Expects one value on the stack: file to evaluate. Always returns nothing |  | ||||||
| /// (from the lua point of view). |  | ||||||
| static int nlua_exec_lua_file(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL |  | ||||||
| { |  | ||||||
|   const char *const filename = (const char *)lua_touserdata(lstate, 1); |  | ||||||
|   lua_pop(lstate, 1); |  | ||||||
|  |  | ||||||
|   if (luaL_loadfile(lstate, filename)) { |  | ||||||
|     nlua_error(lstate, _("E5112: Error while creating lua chunk: %.*s")); |  | ||||||
|     return 0; |  | ||||||
|   } |  | ||||||
|   if (lua_pcall(lstate, 0, 0, 0)) { |  | ||||||
|     nlua_error(lstate, _("E5113: Error while calling lua chunk: %.*s")); |  | ||||||
|     return 0; |  | ||||||
|   } |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Initialize lua interpreter state | /// Initialize lua interpreter state | ||||||
| /// | /// | ||||||
| /// Called by lua interpreter itself to initialize state. | /// Called by lua interpreter itself to initialize state. | ||||||
| @@ -327,7 +150,7 @@ static lua_State *nlua_init(void) | |||||||
|     preserve_exit(); |     preserve_exit(); | ||||||
|   } |   } | ||||||
|   luaL_openlibs(lstate); |   luaL_openlibs(lstate); | ||||||
|   NLUA_CALL_C_FUNCTION_0(lstate, nlua_state_init, 0); |   nlua_state_init(lstate); | ||||||
|   return lstate; |   return lstate; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -378,108 +201,18 @@ static lua_State *nlua_enter(void) | |||||||
| void executor_exec_lua(const String str, typval_T *const ret_tv) | void executor_exec_lua(const String str, typval_T *const ret_tv) | ||||||
|   FUNC_ATTR_NONNULL_ALL |   FUNC_ATTR_NONNULL_ALL | ||||||
| { | { | ||||||
|   NLUA_CALL_C_FUNCTION_2(nlua_enter(), nlua_exec_lua_string, 0, |   lua_State *const lstate = nlua_enter(); | ||||||
|                          (void *)&str, ret_tv); |  | ||||||
|  |   if (luaL_loadbuffer(lstate, str.data, str.size, NLUA_EVAL_NAME)) { | ||||||
|  |     nlua_error(lstate, _("E5104: Error while creating lua chunk: %.*s")); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   if (lua_pcall(lstate, 0, 1, 0)) { | ||||||
|  |     nlua_error(lstate, _("E5105: Error while calling lua chunk: %.*s")); | ||||||
|  |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| /// Evaluate lua string |   nlua_pop_typval(lstate, ret_tv); | ||||||
| /// |  | ||||||
| /// Used for luaeval(). Expects three values on the stack: |  | ||||||
| /// |  | ||||||
| /// 1. String to evaluate. |  | ||||||
| /// 2. _A value. |  | ||||||
| /// 3. Pointer to location where result is saved. |  | ||||||
| /// |  | ||||||
| /// @param[in,out]  lstate  Lua interpreter state. |  | ||||||
| static int nlua_eval_lua_string(lua_State *const lstate) |  | ||||||
|   FUNC_ATTR_NONNULL_ALL |  | ||||||
| { |  | ||||||
|   const String *const str = (const String *)lua_touserdata(lstate, 1); |  | ||||||
|   typval_T *const arg = (typval_T *)lua_touserdata(lstate, 2); |  | ||||||
|   typval_T *const ret_tv = (typval_T *)lua_touserdata(lstate, 3); |  | ||||||
|   lua_pop(lstate, 3); |  | ||||||
|  |  | ||||||
|   garray_T str_ga; |  | ||||||
|   ga_init(&str_ga, 1, 80); |  | ||||||
| #define EVALHEADER "local _A=select(1,...) return (" |  | ||||||
|   const size_t lcmd_len = sizeof(EVALHEADER) - 1 + str->size + 1; |  | ||||||
|   char *lcmd; |  | ||||||
|   if (lcmd_len < IOSIZE) { |  | ||||||
|     lcmd = (char *)IObuff; |  | ||||||
|   } else { |  | ||||||
|     lcmd = xmalloc(lcmd_len); |  | ||||||
|   } |  | ||||||
|   memcpy(lcmd, EVALHEADER, sizeof(EVALHEADER) - 1); |  | ||||||
|   memcpy(lcmd + sizeof(EVALHEADER) - 1, str->data, str->size); |  | ||||||
|   lcmd[lcmd_len - 1] = ')'; |  | ||||||
| #undef EVALHEADER |  | ||||||
|   if (luaL_loadbuffer(lstate, lcmd, lcmd_len, NLUA_EVAL_NAME)) { |  | ||||||
|     nlua_error(lstate, |  | ||||||
|                _("E5107: Error while creating lua chunk for luaeval(): %.*s")); |  | ||||||
|     if (lcmd != (char *)IObuff) { |  | ||||||
|       xfree(lcmd); |  | ||||||
|     } |  | ||||||
|     return 0; |  | ||||||
|   } |  | ||||||
|   if (lcmd != (char *)IObuff) { |  | ||||||
|     xfree(lcmd); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   if (arg == NULL || arg->v_type == VAR_UNKNOWN) { |  | ||||||
|     lua_pushnil(lstate); |  | ||||||
|   } else { |  | ||||||
|     nlua_push_typval(lstate, arg); |  | ||||||
|   } |  | ||||||
|   if (lua_pcall(lstate, 1, 1, 0)) { |  | ||||||
|     nlua_error(lstate, |  | ||||||
|                _("E5108: Error while calling lua chunk for luaeval(): %.*s")); |  | ||||||
|     return 0; |  | ||||||
|   } |  | ||||||
|   if (!nlua_pop_typval(lstate, ret_tv)) { |  | ||||||
|     return 0; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Evaluate lua string |  | ||||||
| /// |  | ||||||
| /// Expects four values on the stack: string to evaluate, pointer to args array, |  | ||||||
| /// and locations where result and error are saved, respectively. Always |  | ||||||
| /// returns nothing (from the lua point of view). |  | ||||||
| static int nlua_exec_lua_string_api(lua_State *const lstate) |  | ||||||
|   FUNC_ATTR_NONNULL_ALL |  | ||||||
| { |  | ||||||
|   const String *str = (const String *)lua_touserdata(lstate, 1); |  | ||||||
|   const Array *args = (const Array *)lua_touserdata(lstate, 2); |  | ||||||
|   Object *retval = (Object *)lua_touserdata(lstate, 3); |  | ||||||
|   Error *err = (Error *)lua_touserdata(lstate, 4); |  | ||||||
|  |  | ||||||
|   lua_pop(lstate, 4); |  | ||||||
|  |  | ||||||
|   if (luaL_loadbuffer(lstate, str->data, str->size, "<nvim>")) { |  | ||||||
|     size_t len; |  | ||||||
|     const char *str = lua_tolstring(lstate, -1, &len); |  | ||||||
|     api_set_error(err, kErrorTypeValidation, |  | ||||||
|                   "Error loading lua: %.*s", (int)len, str); |  | ||||||
|     return 0; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   for (size_t i = 0; i < args->size; i++) { |  | ||||||
|     nlua_push_Object(lstate, args->items[i]); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   if (lua_pcall(lstate, (int)args->size, 1, 0)) { |  | ||||||
|     size_t len; |  | ||||||
|     const char *str = lua_tolstring(lstate, -1, &len); |  | ||||||
|     api_set_error(err, kErrorTypeException, |  | ||||||
|                   "Error executing lua: %.*s", (int)len, str); |  | ||||||
|     return 0; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   *retval = nlua_pop_Object(lstate, err); |  | ||||||
|  |  | ||||||
|   return 0; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Print as a Vim message | /// Print as a Vim message | ||||||
| @@ -617,8 +350,46 @@ void executor_eval_lua(const String str, typval_T *const arg, | |||||||
|                        typval_T *const ret_tv) |                        typval_T *const ret_tv) | ||||||
|   FUNC_ATTR_NONNULL_ALL |   FUNC_ATTR_NONNULL_ALL | ||||||
| { | { | ||||||
|   NLUA_CALL_C_FUNCTION_3(nlua_enter(), nlua_eval_lua_string, 0, |   lua_State *const lstate = nlua_enter(); | ||||||
|                          (void *)&str, arg, ret_tv); |  | ||||||
|  |   garray_T str_ga; | ||||||
|  |   ga_init(&str_ga, 1, 80); | ||||||
|  | #define EVALHEADER "local _A=select(1,...) return (" | ||||||
|  |   const size_t lcmd_len = sizeof(EVALHEADER) - 1 + str.size + 1; | ||||||
|  |   char *lcmd; | ||||||
|  |   if (lcmd_len < IOSIZE) { | ||||||
|  |     lcmd = (char *)IObuff; | ||||||
|  |   } else { | ||||||
|  |     lcmd = xmalloc(lcmd_len); | ||||||
|  |   } | ||||||
|  |   memcpy(lcmd, EVALHEADER, sizeof(EVALHEADER) - 1); | ||||||
|  |   memcpy(lcmd + sizeof(EVALHEADER) - 1, str.data, str.size); | ||||||
|  |   lcmd[lcmd_len - 1] = ')'; | ||||||
|  | #undef EVALHEADER | ||||||
|  |   if (luaL_loadbuffer(lstate, lcmd, lcmd_len, NLUA_EVAL_NAME)) { | ||||||
|  |     nlua_error(lstate, | ||||||
|  |                _("E5107: Error while creating lua chunk for luaeval(): %.*s")); | ||||||
|  |     if (lcmd != (char *)IObuff) { | ||||||
|  |       xfree(lcmd); | ||||||
|  |     } | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   if (lcmd != (char *)IObuff) { | ||||||
|  |     xfree(lcmd); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (arg->v_type == VAR_UNKNOWN) { | ||||||
|  |     lua_pushnil(lstate); | ||||||
|  |   } else { | ||||||
|  |     nlua_push_typval(lstate, arg); | ||||||
|  |   } | ||||||
|  |   if (lua_pcall(lstate, 1, 1, 0)) { | ||||||
|  |     nlua_error(lstate, | ||||||
|  |                _("E5108: Error while calling lua chunk for luaeval(): %.*s")); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   nlua_pop_typval(lstate, ret_tv); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Execute lua string | /// Execute lua string | ||||||
| @@ -632,10 +403,29 @@ void executor_eval_lua(const String str, typval_T *const arg, | |||||||
| /// @return Return value of the execution. | /// @return Return value of the execution. | ||||||
| Object executor_exec_lua_api(const String str, const Array args, Error *err) | Object executor_exec_lua_api(const String str, const Array args, Error *err) | ||||||
| { | { | ||||||
|   Object retval = NIL; |   lua_State *const lstate = nlua_enter(); | ||||||
|   NLUA_CALL_C_FUNCTION_4(nlua_enter(), nlua_exec_lua_string_api, 0, |  | ||||||
|                          (void *)&str, (void *)&args, &retval, err); |   if (luaL_loadbuffer(lstate, str.data, str.size, "<nvim>")) { | ||||||
|   return retval; |     size_t len; | ||||||
|  |     const char *errstr = lua_tolstring(lstate, -1, &len); | ||||||
|  |     api_set_error(err, kErrorTypeValidation, | ||||||
|  |                   "Error loading lua: %.*s", (int)len, errstr); | ||||||
|  |     return NIL; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   for (size_t i = 0; i < args.size; i++) { | ||||||
|  |     nlua_push_Object(lstate, args.items[i]); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (lua_pcall(lstate, (int)args.size, 1, 0)) { | ||||||
|  |     size_t len; | ||||||
|  |     const char *errstr = lua_tolstring(lstate, -1, &len); | ||||||
|  |     api_set_error(err, kErrorTypeException, | ||||||
|  |                   "Error executing lua: %.*s", (int)len, errstr); | ||||||
|  |     return NIL; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return nlua_pop_Object(lstate, err); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -671,13 +461,70 @@ void ex_luado(exarg_T *const eap) | |||||||
|     EMSG(_("cannot save undo information")); |     EMSG(_("cannot save undo information")); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|   const String cmd = { |   const char *const cmd = (const char *)eap->arg; | ||||||
|     .size = STRLEN(eap->arg), |   const size_t cmd_len = strlen(cmd); | ||||||
|     .data = (char *)eap->arg, |  | ||||||
|   }; |   lua_State *const lstate = nlua_enter(); | ||||||
|   const linenr_T range[] = { eap->line1, eap->line2 }; |  | ||||||
|   NLUA_CALL_C_FUNCTION_2(nlua_enter(), nlua_exec_luado_string, 0, | #define DOSTART "return function(line, linenr) " | ||||||
|                          (void *)&cmd, (void *)range); | #define DOEND " end" | ||||||
|  |   const size_t lcmd_len = (cmd_len | ||||||
|  |                            + (sizeof(DOSTART) - 1) | ||||||
|  |                            + (sizeof(DOEND) - 1)); | ||||||
|  |   char *lcmd; | ||||||
|  |   if (lcmd_len < IOSIZE) { | ||||||
|  |     lcmd = (char *)IObuff; | ||||||
|  |   } else { | ||||||
|  |     lcmd = xmalloc(lcmd_len + 1); | ||||||
|  |   } | ||||||
|  |   memcpy(lcmd, DOSTART, sizeof(DOSTART) - 1); | ||||||
|  |   memcpy(lcmd + sizeof(DOSTART) - 1, cmd, cmd_len); | ||||||
|  |   memcpy(lcmd + sizeof(DOSTART) - 1 + cmd_len, DOEND, sizeof(DOEND) - 1); | ||||||
|  | #undef DOSTART | ||||||
|  | #undef DOEND | ||||||
|  |  | ||||||
|  |   if (luaL_loadbuffer(lstate, lcmd, lcmd_len, NLUA_EVAL_NAME)) { | ||||||
|  |     nlua_error(lstate, _("E5109: Error while creating lua chunk: %.*s")); | ||||||
|  |     if (lcmd_len >= IOSIZE) { | ||||||
|  |       xfree(lcmd); | ||||||
|  |     } | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   if (lcmd_len >= IOSIZE) { | ||||||
|  |     xfree(lcmd); | ||||||
|  |   } | ||||||
|  |   if (lua_pcall(lstate, 0, 1, 0)) { | ||||||
|  |     nlua_error(lstate, _("E5110: Error while creating lua function: %.*s")); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   for (linenr_T l = eap->line1; l <= eap->line2; l++) { | ||||||
|  |     if (l > curbuf->b_ml.ml_line_count) { | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |     lua_pushvalue(lstate, -1); | ||||||
|  |     lua_pushstring(lstate, (const char *)ml_get_buf(curbuf, l, false)); | ||||||
|  |     lua_pushnumber(lstate, (lua_Number)l); | ||||||
|  |     if (lua_pcall(lstate, 2, 1, 0)) { | ||||||
|  |       nlua_error(lstate, _("E5111: Error while calling lua function: %.*s")); | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |     if (lua_isstring(lstate, -1)) { | ||||||
|  |       size_t new_line_len; | ||||||
|  |       const char *const new_line = lua_tolstring(lstate, -1, &new_line_len); | ||||||
|  |       char *const new_line_transformed = xmemdupz(new_line, new_line_len); | ||||||
|  |       for (size_t i = 0; i < new_line_len; i++) { | ||||||
|  |         if (new_line_transformed[i] == NUL) { | ||||||
|  |           new_line_transformed[i] = '\n'; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       ml_replace(l, (char_u *)new_line_transformed, false); | ||||||
|  |       changed_bytes(l, 0); | ||||||
|  |     } | ||||||
|  |     lua_pop(lstate, 1); | ||||||
|  |   } | ||||||
|  |   lua_pop(lstate, 1); | ||||||
|  |   check_cursor(); | ||||||
|  |   update_screen(NOT_VALID); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Run lua file | /// Run lua file | ||||||
| @@ -688,6 +535,15 @@ void ex_luado(exarg_T *const eap) | |||||||
| void ex_luafile(exarg_T *const eap) | void ex_luafile(exarg_T *const eap) | ||||||
|   FUNC_ATTR_NONNULL_ALL |   FUNC_ATTR_NONNULL_ALL | ||||||
| { | { | ||||||
|   NLUA_CALL_C_FUNCTION_1(nlua_enter(), nlua_exec_lua_file, 0, |   lua_State *const lstate = nlua_enter(); | ||||||
|                          (void *)eap->arg); |  | ||||||
|  |   if (luaL_loadfile(lstate, (const char *)eap->arg)) { | ||||||
|  |     nlua_error(lstate, _("E5112: Error while creating lua chunk: %.*s")); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (lua_pcall(lstate, 0, 0, 0)) { | ||||||
|  |     nlua_error(lstate, _("E5113: Error while calling lua chunk: %.*s")); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 ZyX
					ZyX