diff options
| author | b-r-o-c-k <brockmammen@gmail.com> | 2018-04-14 14:17:51 -0500 | 
|---|---|---|
| committer | b-r-o-c-k <brockmammen@gmail.com> | 2018-04-14 14:17:51 -0500 | 
| commit | ad999eaa775d7d4b0cacedb30c6ea3a0ee699a6f (patch) | |
| tree | 92de2079e80f5f289dd87a54af123cb7d90c3058 /src/nvim/lua/executor.c | |
| parent | 78bc52ea5397c092d01cd08296fe1dc85d998329 (diff) | |
| parent | ef4feab0e75be19c5f41d70a001db980b72090f5 (diff) | |
| download | rneovim-ad999eaa775d7d4b0cacedb30c6ea3a0ee699a6f.tar.gz rneovim-ad999eaa775d7d4b0cacedb30c6ea3a0ee699a6f.tar.bz2 rneovim-ad999eaa775d7d4b0cacedb30c6ea3a0ee699a6f.zip  | |
Merge branch 'master' into s-dash-stdin
Diffstat (limited to 'src/nvim/lua/executor.c')
| -rw-r--r-- | src/nvim/lua/executor.c | 438 | 
1 files changed, 147 insertions, 291 deletions
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 8e7b8a1824..02eabb9c89 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -40,66 +40,6 @@ typedef struct {  /// Name of the run code for use in messages  #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  ///  /// @param  lstate  Lua interpreter state. @@ -163,123 +103,6 @@ static int nlua_stricmp(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL    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  ///  /// Called by lua interpreter itself to initialize state. @@ -327,7 +150,7 @@ static lua_State *nlua_init(void)      preserve_exit();    }    luaL_openlibs(lstate); -  NLUA_CALL_C_FUNCTION_0(lstate, nlua_state_init, 0); +  nlua_state_init(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)    FUNC_ATTR_NONNULL_ALL  { -  NLUA_CALL_C_FUNCTION_2(nlua_enter(), nlua_exec_lua_string, 0, -                         (void *)&str, ret_tv); -} +  lua_State *const lstate = nlua_enter(); -/// Evaluate lua string -/// -/// 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 (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, (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; +  if (lua_pcall(lstate, 0, 1, 0)) { +    nlua_error(lstate, _("E5105: Error while calling lua chunk: %.*s")); +    return;    } -  *retval = nlua_pop_Object(lstate, err); - -  return 0; +  nlua_pop_typval(lstate, ret_tv);  }  /// 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)    FUNC_ATTR_NONNULL_ALL  { -  NLUA_CALL_C_FUNCTION_3(nlua_enter(), nlua_eval_lua_string, 0, -                         (void *)&str, arg, ret_tv); +  lua_State *const lstate = nlua_enter(); + +  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 @@ -632,10 +403,29 @@ void executor_eval_lua(const String str, typval_T *const arg,  /// @return Return value of the execution.  Object executor_exec_lua_api(const String str, const Array args, Error *err)  { -  Object retval = NIL; -  NLUA_CALL_C_FUNCTION_4(nlua_enter(), nlua_exec_lua_string_api, 0, -                         (void *)&str, (void *)&args, &retval, err); -  return retval; +  lua_State *const lstate = nlua_enter(); + +  if (luaL_loadbuffer(lstate, str.data, str.size, "<nvim>")) { +    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"));      return;    } -  const String cmd = { -    .size = STRLEN(eap->arg), -    .data = (char *)eap->arg, -  }; -  const linenr_T range[] = { eap->line1, eap->line2 }; -  NLUA_CALL_C_FUNCTION_2(nlua_enter(), nlua_exec_luado_string, 0, -                         (void *)&cmd, (void *)range); +  const char *const cmd = (const char *)eap->arg; +  const size_t cmd_len = strlen(cmd); + +  lua_State *const lstate = nlua_enter(); + +#define DOSTART "return function(line, linenr) " +#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 @@ -688,6 +535,15 @@ void ex_luado(exarg_T *const eap)  void ex_luafile(exarg_T *const eap)    FUNC_ATTR_NONNULL_ALL  { -  NLUA_CALL_C_FUNCTION_1(nlua_enter(), nlua_exec_lua_file, 0, -                         (void *)eap->arg); +  lua_State *const lstate = nlua_enter(); + +  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; +  }  }  | 
