diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2023-11-29 22:40:31 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2023-11-29 22:40:31 +0000 |
commit | 339e2d15cc26fe86988ea06468d912a46c8d6f29 (patch) | |
tree | a6167fc8fcfc6ae2dc102f57b2473858eac34063 /src/nvim/main.c | |
parent | 067dc73729267c0262438a6fdd66e586f8496946 (diff) | |
parent | 4a8bf24ac690004aedf5540fa440e788459e5e34 (diff) | |
download | rneovim-339e2d15cc26fe86988ea06468d912a46c8d6f29.tar.gz rneovim-339e2d15cc26fe86988ea06468d912a46c8d6f29.tar.bz2 rneovim-339e2d15cc26fe86988ea06468d912a46c8d6f29.zip |
Merge remote-tracking branch 'upstream/master' into fix_repeatcmdline
Diffstat (limited to 'src/nvim/main.c')
-rw-r--r-- | src/nvim/main.c | 332 |
1 files changed, 188 insertions, 144 deletions
diff --git a/src/nvim/main.c b/src/nvim/main.c index bbe877356d..6585bd1df7 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1,7 +1,9 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - -#define EXTERN +// Make sure extern symbols are exported on Windows +#ifdef WIN32 +# define EXTERN __declspec(dllexport) +#else +# define EXTERN +#endif #include <assert.h> #include <limits.h> #include <msgpack/pack.h> @@ -10,10 +12,18 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#ifdef ENABLE_ASAN_UBSAN +# include <sanitizer/asan_interface.h> +# include <sanitizer/ubsan_interface.h> +#endif -#include "auto/config.h" +#include "auto/config.h" // IWYU pragma: keep +#include "nvim/api/extmark.h" +#include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" +#include "nvim/api/ui.h" #include "nvim/arglist.h" -#include "nvim/ascii.h" +#include "nvim/ascii_defs.h" #include "nvim/autocmd.h" #include "nvim/buffer.h" #include "nvim/buffer_defs.h" @@ -24,14 +34,17 @@ #include "nvim/drawscreen.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" -#include "nvim/eval/typval_defs.h" +#include "nvim/eval/userfunc.h" +#include "nvim/event/loop.h" #include "nvim/event/multiqueue.h" +#include "nvim/event/process.h" #include "nvim/event/stream.h" #include "nvim/ex_cmds.h" #include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" #include "nvim/fileio.h" #include "nvim/fold.h" +#include "nvim/func_attr.h" #include "nvim/garray.h" #include "nvim/getchar.h" #include "nvim/gettext.h" @@ -41,60 +54,52 @@ #include "nvim/highlight.h" #include "nvim/highlight_group.h" #include "nvim/keycodes.h" -#include "nvim/locale.h" #include "nvim/log.h" #include "nvim/lua/executor.h" -#include "nvim/macros.h" +#include "nvim/lua/secure.h" +#include "nvim/macros_defs.h" #include "nvim/main.h" #include "nvim/mark.h" -#include "nvim/memfile_defs.h" #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/mouse.h" #include "nvim/move.h" +#include "nvim/msgpack_rpc/channel.h" +#include "nvim/msgpack_rpc/helpers.h" +#include "nvim/msgpack_rpc/server.h" #include "nvim/normal.h" #include "nvim/ops.h" #include "nvim/option.h" -#include "nvim/option_defs.h" +#include "nvim/option_vars.h" #include "nvim/optionstr.h" #include "nvim/os/fileio.h" +#include "nvim/os/fs.h" #include "nvim/os/input.h" +#include "nvim/os/lang.h" #include "nvim/os/os.h" +#include "nvim/os/signal.h" #include "nvim/os/stdpaths_defs.h" -#include "nvim/os/time.h" #include "nvim/path.h" #include "nvim/popupmenu.h" -#include "nvim/pos.h" #include "nvim/profile.h" #include "nvim/quickfix.h" #include "nvim/runtime.h" #include "nvim/shada.h" -#include "nvim/sign.h" #include "nvim/statusline.h" #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/terminal.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" #include "nvim/ui.h" #include "nvim/ui_client.h" #include "nvim/ui_compositor.h" #include "nvim/version.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" #include "nvim/window.h" #ifdef MSWIN # include "nvim/os/os_win_console.h" #endif -#include "nvim/api/extmark.h" -#include "nvim/api/private/defs.h" -#include "nvim/api/private/helpers.h" -#include "nvim/api/ui.h" -#include "nvim/event/loop.h" -#include "nvim/event/process.h" -#include "nvim/msgpack_rpc/channel.h" -#include "nvim/msgpack_rpc/helpers.h" -#include "nvim/msgpack_rpc/server.h" -#include "nvim/os/signal.h" // values for "window_layout" enum { @@ -167,10 +172,9 @@ bool event_teardown(void) /// Performs early initialization. /// -/// Needed for unit tests. Must be called after `time_init()`. +/// Needed for unit tests. void early_init(mparm_T *paramp) { - env_init(); estack_init(); cmdline_init(); eval_init(); // init global variables @@ -182,19 +186,24 @@ void early_init(mparm_T *paramp) #ifdef MSWIN OSVERSIONINFO ovi; ovi.dwOSVersionInfoSize = sizeof(ovi); + // Disable warning about GetVersionExA being deprecated. There doesn't seem to be a convenient + // replacement that doesn't add a ton of extra code as of writing this. +# ifdef _MSC_VER +# pragma warning(suppress : 4996) + GetVersionEx(&ovi); +# else GetVersionEx(&ovi); +# endif snprintf(windowsVersion, sizeof(windowsVersion), "%d.%d", (int)ovi.dwMajorVersion, (int)ovi.dwMinorVersion); #endif TIME_MSG("early init"); -#if defined(HAVE_LOCALE_H) // Setup to use the current locale (for ctype() and many other things). // NOTE: Translated messages with encodings other than latin1 will not // work until set_init_1() has been called! init_locale(); -#endif // tabpage local options (p_ch) must be set before allocating first tabpage. set_init_tablocal(); @@ -214,8 +223,6 @@ void early_init(mparm_T *paramp) TIME_MSG("inits 1"); set_lang_var(); // set v:lang and v:ctype - - init_signs(); } #ifdef MAKE_LIB @@ -239,20 +246,28 @@ int main(int argc, char **argv) argv0 = argv[0]; + if (!appname_is_valid()) { + os_errmsg("$NVIM_APPNAME must be a name or relative path.\n"); + exit(1); + } + + if (argc > 1 && STRICMP(argv[1], "-ll") == 0) { + if (argc == 2) { + print_mainerr(err_arg_missing, argv[1]); + exit(1); + } + nlua_run_script(argv, argc, 3); + } + char *fname = NULL; // file name from command line mparm_T params; // various parameters passed between // main() and other functions. char *cwd = NULL; // current working dir on startup - time_init(); // Many variables are in `params` so that we can pass them around easily. // `argc` and `argv` are also copied, so that they can be changed. init_params(¶ms, argc, argv); - // Since os_open is called during the init_startuptime, we need to call - // fs_init before it. - fs_init(); - init_startuptime(¶ms); // Need to find "--clean" before actually parsing arguments. @@ -286,6 +301,16 @@ int main(int argc, char **argv) } } + if (GARGCOUNT > 0) { + fname = get_fname(¶ms, cwd); + } + + // Recovery mode without a file name: List swap files. + // In this case, no UI is needed. + if (recoverymode && fname == NULL) { + headless_mode = true; + } + #ifdef MSWIN // on windows we use CONIN special file, thus we don't know this yet. bool has_term = true; @@ -312,21 +337,11 @@ int main(int argc, char **argv) uint64_t rv = ui_client_start_server(params.argc, params.argv); if (!rv) { os_errmsg("Failed to start Nvim server!\n"); - getout(1); + os_exit(1); } ui_client_channel_id = rv; } - if (GARGCOUNT > 0) { - fname = get_fname(¶ms, cwd); - } - - // Recovery mode without a file name: List swap files. - // In this case, no UI is needed. - if (recoverymode && fname == NULL) { - headless_mode = true; - } - TIME_MSG("expanding arguments"); if (params.diff_mode && params.window_count == -1) { @@ -335,7 +350,7 @@ int main(int argc, char **argv) // Don't redraw until much later. RedrawingDisabled++; - setbuf(stdout, NULL); + setbuf(stdout, NULL); // NOLINT(bugprone-unsafe-functions) full_screen = !silent_mode; @@ -348,7 +363,7 @@ int main(int argc, char **argv) } assert(p_ch >= 0 && Rows >= p_ch && Rows - p_ch <= INT_MAX); - cmdline_row = (int)(Rows - p_ch); + cmdline_row = Rows - (int)p_ch; msg_row = cmdline_row; default_grid_alloc(); // allocate screen buffers set_init_2(headless_mode); @@ -372,13 +387,15 @@ int main(int argc, char **argv) if (ui_client_channel_id) { ui_client_run(remote_ui); // NORETURN } + assert(!ui_client_channel_id && !use_builtin_ui); // Wait for UIs to set up Nvim or show early messages // and prompts (--cmd, swapfile dialog, …). bool use_remote_ui = (embedded_mode && !headless_mode); + bool listen_and_embed = params.listen_addr != NULL; if (use_remote_ui) { TIME_MSG("waiting for UI"); - remote_ui_wait_for_attach(); + remote_ui_wait_for_attach(!listen_and_embed); TIME_MSG("done waiting for UI"); firstwin->w_prev_height = firstwin->w_height; // may have changed } @@ -396,19 +413,9 @@ int main(int argc, char **argv) open_script_files(¶ms); - // Default mappings (incl. menus) - Error err = ERROR_INIT; - Object o = NLUA_EXEC_STATIC("return vim._init_default_mappings()", - (Array)ARRAY_DICT_INIT, &err); - assert(!ERROR_SET(&err)); - api_clear_error(&err); - assert(o.type == kObjectTypeNil); - api_free_object(o); - - TIME_MSG("init default mappings"); + nlua_init_defaults(); - init_default_autocmds(); - TIME_MSG("init default autocommands"); + TIME_MSG("init default mappings & autocommands"); bool vimrc_none = strequal(params.use_vimrc, "NONE"); @@ -432,8 +439,7 @@ int main(int argc, char **argv) // If using the runtime (-u is not NONE), enable syntax & filetype plugins. if (!vimrc_none || params.clean) { - // Sources filetype.lua and filetype.vim unless the user explicitly disabled it with :filetype - // off. + // Sources filetype.lua unless the user explicitly disabled it with :filetype off. filetype_maybe_enable(); // Sources syntax/syntax.vim. We do this *after* the user startup scripts so that users can // disable syntax highlighting with `:syntax off` if they wish. @@ -449,7 +455,7 @@ int main(int argc, char **argv) // Recovery mode without a file name: List swap files. // Uses the 'dir' option, therefore it must be after the initializations. if (recoverymode && fname == NULL) { - recover_names(NULL, true, 0, NULL); + recover_names(NULL, true, NULL, 0, NULL); os_exit(0); } @@ -572,16 +578,16 @@ int main(int argc, char **argv) // 'autochdir' has been postponed. do_autochdir(); - set_vim_var_nr(VV_VIM_DID_ENTER, 1L); + set_vim_var_nr(VV_VIM_DID_ENTER, 1); apply_autocmds(EVENT_VIMENTER, NULL, NULL, false, curbuf); TIME_MSG("VimEnter autocommands"); - if (use_remote_ui || use_builtin_ui) { - do_autocmd_uienter(use_remote_ui ? CHAN_STDIO : 0, true); + if (use_remote_ui) { + do_autocmd_uienter_all(); TIME_MSG("UIEnter autocommands"); } #ifdef MSWIN - if (use_builtin_ui) { + if (use_remote_ui) { os_icon_init(); } os_title_save(); @@ -597,7 +603,7 @@ int main(int argc, char **argv) // scrollbind, sync the scrollbind now. if (curwin->w_p_diff && curwin->w_p_scb) { update_topline(curwin); - check_scrollbind((linenr_T)0, 0L); + check_scrollbind(0, 0); TIME_MSG("diff scrollbinding"); } @@ -613,8 +619,14 @@ int main(int argc, char **argv) } if (params.luaf != NULL) { + // Like "--cmd", "+", "-c" and "-S", don't truncate messages. + msg_scroll = true; bool lua_ok = nlua_exec_file(params.luaf); TIME_MSG("executing Lua -l script"); + if (msg_didout) { + msg_putchar('\n'); + msg_didout = false; + } getout(lua_ok ? 0 : 1); } @@ -637,6 +649,9 @@ void os_exit(int r) if (ui_client_channel_id) { ui_client_stop(); + if (r == 0) { + r = ui_client_exit_status; + } } else { ui_flush(); ui_call_stop(); @@ -663,6 +678,7 @@ void os_exit(int r) void getout(int exitval) FUNC_ATTR_NORETURN { + assert(!ui_client_channel_id); exiting = true; // On error during Ex mode, exit with a non-zero code. @@ -673,8 +689,8 @@ void getout(int exitval) set_vim_var_nr(VV_EXITING, exitval); - // Position the cursor on the last screen line, below all the text - ui_cursor_goto(Rows - 1, 0); + // Invoked all deferred functions in the function stack. + invoke_all_defer(); // Optionally print hashtable efficiency. hash_debug_results(); @@ -686,7 +702,7 @@ void getout(int exitval) for (const tabpage_T *tp = first_tabpage; tp != NULL; tp = next_tp) { next_tp = tp->tp_next; FOR_ALL_WINDOWS_IN_TAB(wp, tp) { - if (wp->w_buffer == NULL) { + if (wp->w_buffer == NULL || !buf_valid(wp->w_buffer)) { // Autocmd must have close the buffer already, skip. continue; } @@ -761,9 +777,6 @@ void getout(int exitval) wait_return(false); } - // Position the cursor again, the autocommands may have moved it - ui_cursor_goto(Rows - 1, 0); - // Apply 'titleold'. if (p_title && *p_titleold != NUL) { ui_call_set_title(cstr_as_string(p_titleold)); @@ -782,10 +795,11 @@ void getout(int exitval) os_exit(exitval); } -/// Preserve files, print contents of `IObuff`, and exit 1. +/// Preserve files, print contents of `errmsg`, and exit 1. +/// @param errmsg If NULL, this function will not print anything. /// /// May be called from deadly_signal(). -void preserve_exit(void) +void preserve_exit(const char *errmsg) FUNC_ATTR_NORETURN { // 'true' when we are sure to exit, e.g., after a deadly signal @@ -803,16 +817,26 @@ void preserve_exit(void) really_exiting = true; // Ignore SIGHUP while we are already exiting. #9274 signal_reject_deadly(); - os_errmsg(IObuff); - os_errmsg("\n"); - ui_flush(); + + if (ui_client_channel_id) { + // For TUI: exit alternate screen so that the error messages can be seen. + ui_client_stop(); + } + if (errmsg != NULL) { + os_errmsg(errmsg); + os_errmsg("\n"); + } + if (ui_client_channel_id) { + os_exit(1); + } ml_close_notmod(); // close all not-modified buffers FOR_ALL_BUFFERS(buf) { if (buf->b_ml.ml_mfp != NULL && buf->b_ml.ml_mfp->mf_fname != NULL) { - os_errmsg("Vim: preserving files...\r\n"); - ui_flush(); + if (errmsg != NULL) { + os_errmsg("Vim: preserving files...\r\n"); + } ml_sync_all(false, false, true); // preserve all swap files break; } @@ -820,7 +844,9 @@ void preserve_exit(void) ml_close_all(false); // close all memfiles, without deleting - os_errmsg("Vim: Finished.\r\n"); + if (errmsg != NULL) { + os_errmsg("Vim: Finished.\r\n"); + } getout(1); } @@ -840,7 +866,7 @@ void preserve_exit(void) static int get_number_arg(const char *p, int *idx, int def) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { - if (ascii_isdigit(p[*idx])) { // -V522 + if (ascii_isdigit(p[*idx])) { def = atoi(&(p[*idx])); while (ascii_isdigit(p[*idx])) { *idx = *idx + 1; @@ -888,6 +914,11 @@ static void remote_request(mparm_T *params, int remote_args, char *server_addr, os_errmsg(connect_error); os_errmsg("\n"); os_exit(1); + } else if (strequal(server_addr, os_getenv("NVIM"))) { + os_errmsg("Cannot attach UI of :terminal child to its parent. "); + os_errmsg("(Unset $NVIM to skip this check)"); + os_errmsg("\n"); + os_exit(1); } ui_client_channel_id = chan; @@ -895,9 +926,8 @@ static void remote_request(mparm_T *params, int remote_args, char *server_addr, } Array args = ARRAY_DICT_INIT; - String arg_s; for (int t_argc = remote_args; t_argc < argc; t_argc++) { - arg_s = cstr_to_string(argv[t_argc]); + String arg_s = cstr_to_string(argv[t_argc]); ADD(args, STRING_OBJ(arg_s)); } @@ -927,7 +957,7 @@ static void remote_request(mparm_T *params, int remote_args, char *server_addr, TriState tabbed = kNone; for (size_t i = 0; i < rvobj.data.dictionary.size; i++) { - if (strcmp(rvobj.data.dictionary.items[i].key.data, "errmsg") == 0) { + if (strequal(rvobj.data.dictionary.items[i].key.data, "errmsg")) { if (rvobj.data.dictionary.items[i].value.type != kObjectTypeString) { os_errmsg("vim._cs_remote returned an unexpected type for 'errmsg'\n"); os_exit(2); @@ -935,13 +965,19 @@ static void remote_request(mparm_T *params, int remote_args, char *server_addr, os_errmsg(rvobj.data.dictionary.items[i].value.data.string.data); os_errmsg("\n"); os_exit(2); - } else if (strcmp(rvobj.data.dictionary.items[i].key.data, "tabbed") == 0) { + } else if (strequal(rvobj.data.dictionary.items[i].key.data, "result")) { + if (rvobj.data.dictionary.items[i].value.type != kObjectTypeString) { + os_errmsg("vim._cs_remote returned an unexpected type for 'result'\n"); + os_exit(2); + } + os_msg(rvobj.data.dictionary.items[i].value.data.string.data); + } else if (strequal(rvobj.data.dictionary.items[i].key.data, "tabbed")) { if (rvobj.data.dictionary.items[i].value.type != kObjectTypeBoolean) { os_errmsg("vim._cs_remote returned an unexpected type for 'tabbed'\n"); os_exit(2); } tabbed = rvobj.data.dictionary.items[i].value.data.boolean ? kTrue : kFalse; - } else if (strcmp(rvobj.data.dictionary.items[i].key.data, "should_exit") == 0) { + } else if (strequal(rvobj.data.dictionary.items[i].key.data, "should_exit")) { if (rvobj.data.dictionary.items[i].value.type != kObjectTypeBoolean) { os_errmsg("vim._cs_remote returned an unexpected type for 'should_exit'\n"); os_exit(2); @@ -984,7 +1020,7 @@ static void command_line_scan(mparm_T *parmp) int argv_idx; // index in argv[n][] bool had_minmin = false; // found "--" argument int want_argument; // option argument with argument - long n; + int n; argc--; argv++; @@ -1035,6 +1071,10 @@ static void command_line_scan(mparm_T *parmp) version(); os_exit(0); } else if (STRICMP(argv[0] + argv_idx, "api-info") == 0) { +#ifdef MSWIN + // set stdout to binary to avoid crlf in --api-info output + _setmode(STDOUT_FILENO, _O_BINARY); +#endif FileDescriptor fp; const int fof_ret = file_open_fd(&fp, STDOUT_FILENO, kFileWriteOnly); @@ -1082,7 +1122,7 @@ static void command_line_scan(mparm_T *parmp) } else if (STRNICMP(argv[0] + argv_idx, "clean", 5) == 0) { parmp->use_vimrc = "NONE"; parmp->clean = true; - set_option_value_give_err("shadafile", 0L, "NONE", 0); + set_option_value_give_err("shadafile", STATIC_CSTR_AS_OPTVAL("NONE"), 0); } else if (STRNICMP(argv[0] + argv_idx, "luamod-dev", 9) == 0) { nlua_disable_preload = true; } else { @@ -1096,7 +1136,7 @@ static void command_line_scan(mparm_T *parmp) } break; case 'A': // "-A" start in Arabic mode. - set_option_value_give_err("arabic", 1L, NULL, 0); + set_option_value_give_err("arabic", BOOLEAN_OPTVAL(true), 0); break; case 'b': // "-b" binary mode. // Needs to be effective before expanding file names, because @@ -1125,9 +1165,9 @@ static void command_line_scan(mparm_T *parmp) case 'h': // "-h" give help message usage(); os_exit(0); - case 'H': // "-H" start in Hebrew mode: rl + hkmap set. - p_hkmap = true; - set_option_value_give_err("rl", 1L, NULL, 0); + case 'H': // "-H" start in Hebrew mode: rl + keymap=hebrew set. + set_option_value_give_err("keymap", STATIC_CSTR_AS_OPTVAL("hebrew"), 0); + set_option_value_give_err("rl", BOOLEAN_OPTVAL(true), 0); break; case 'M': // "-M" no changes or writing of files reset_modifiable(); @@ -1207,7 +1247,7 @@ static void command_line_scan(mparm_T *parmp) // default is 10: a little bit verbose p_verbose = get_number_arg(argv[0], &argv_idx, 10); if (argv[0][argv_idx] != NUL) { - set_option_value_give_err("verbosefile", 0L, argv[0] + argv_idx, 0); + set_option_value_give_err("verbosefile", CSTR_AS_OPTVAL(argv[0] + argv_idx), 0); argv_idx = (int)strlen(argv[0]); } break; @@ -1215,7 +1255,7 @@ static void command_line_scan(mparm_T *parmp) // "-w {scriptout}" write to script if (ascii_isdigit((argv[0])[argv_idx])) { n = get_number_arg(argv[0], &argv_idx, 10); - set_option_value_give_err("window", n, NULL, 0); + set_option_value_give_err("window", NUMBER_OPTVAL((OptInt)n), 0); break; } want_argument = true; @@ -1311,7 +1351,7 @@ static void command_line_scan(mparm_T *parmp) break; case 'i': // "-i {shada}" use for shada - set_option_value_give_err("shadafile", 0L, argv[0], 0); + set_option_value_give_err("shadafile", CSTR_AS_OPTVAL(argv[0]), 0); break; case 'l': // "-l" Lua script: args after "-l". @@ -1321,11 +1361,11 @@ static void command_line_scan(mparm_T *parmp) parmp->no_swap_file = true; parmp->use_vimrc = parmp->use_vimrc ? parmp->use_vimrc : "NONE"; if (p_shadafile == NULL || *p_shadafile == NUL) { - set_option_value_give_err("shadafile", 0L, "NONE", 0); + set_option_value_give_err("shadafile", STATIC_CSTR_AS_OPTVAL("NONE"), 0); } parmp->luaf = argv[0]; argc--; - if (argc > 0) { // Lua args after "-l <file>". + if (argc >= 0) { // Lua args after "-l <file>". parmp->lua_arg0 = parmp->argc - argc; argc = 0; } @@ -1357,7 +1397,7 @@ scripterror: if (ascii_isdigit(*(argv[0]))) { argv_idx = 0; n = get_number_arg(argv[0], &argv_idx, 10); - set_option_value_give_err("window", n, NULL, 0); + set_option_value_give_err("window", NUMBER_OPTVAL((OptInt)n), 0); argv_idx = -1; break; } @@ -1448,7 +1488,7 @@ static void init_startuptime(mparm_T *paramp) { for (int i = 1; i < paramp->argc - 1; i++) { if (STRICMP(paramp->argv[i], "--startuptime") == 0) { - time_fd = os_fopen(paramp->argv[i + 1], "a"); + time_fd = fopen(paramp->argv[i + 1], "a"); time_start("--- NVIM STARTING ---"); break; } @@ -1532,6 +1572,7 @@ static void handle_tag(char *tagname) // If the user doesn't want to edit the file then we quit here. if (swap_exists_did_quit) { + ui_call_error_exit(1); getout(1); } } @@ -1570,7 +1611,7 @@ static void open_script_files(mparm_T *parmp) scriptin[0] = file_open_new(&error, parmp->scriptin, kFileReadOnly|kFileNonBlocking, 0); if (scriptin[0] == NULL) { - vim_snprintf((char *)IObuff, IOSIZE, + vim_snprintf(IObuff, IOSIZE, _("Cannot open for reading: \"%s\": %s\n"), parmp->scriptin, os_strerror(error)); os_errmsg(IObuff); @@ -1595,9 +1636,6 @@ static void open_script_files(mparm_T *parmp) // Also does recovery if "recoverymode" set. static void create_windows(mparm_T *parmp) { - int dorewind; - int done = 0; - // Create the number of windows that was requested. if (parmp->window_count == -1) { // was not set parmp->window_count = 1; @@ -1633,6 +1671,7 @@ static void create_windows(mparm_T *parmp) } do_modelines(0); // do modelines } else { + int done = 0; // Open a buffer for windows that don't have one yet. // Commands in the vimrc might have loaded a file or split the window. // Watch out for autocommands that delete a window. @@ -1640,7 +1679,7 @@ static void create_windows(mparm_T *parmp) // Don't execute Win/Buf Enter/Leave autocommands here autocmd_no_enter++; autocmd_no_leave++; - dorewind = true; + int dorewind = true; while (done++ < 1000) { if (dorewind) { if (parmp->window_layout == WIN_TABS) { @@ -1677,6 +1716,7 @@ static void create_windows(mparm_T *parmp) if (got_int || only_one_window()) { // abort selected or quit and only one window did_emsg = false; // avoid hit-enter prompt + ui_call_error_exit(1); getout(1); } // We can't close the window, it would disturb what @@ -1712,7 +1752,6 @@ static void create_windows(mparm_T *parmp) static void edit_buffers(mparm_T *parmp, char *cwd) { int arg_idx; // index in argument list - int i; bool advance = true; win_T *win; char *p_shm_save = NULL; @@ -1728,7 +1767,7 @@ static void edit_buffers(mparm_T *parmp, char *cwd) } arg_idx = 1; - for (i = 1; i < parmp->window_count; i++) { + for (int i = 1; i < parmp->window_count; i++) { if (cwd != NULL) { os_chdir(cwd); } @@ -1754,7 +1793,7 @@ static void edit_buffers(mparm_T *parmp, char *cwd) p_shm_save = xstrdup(p_shm); snprintf(buf, sizeof(buf), "F%s", p_shm); - set_option_value_give_err("shm", 0L, buf, 0); + set_option_value_give_err("shm", CSTR_AS_OPTVAL(buf), 0); } } else { if (curwin->w_next == NULL) { // just checking @@ -1780,6 +1819,7 @@ static void edit_buffers(mparm_T *parmp, char *cwd) if (got_int || only_one_window()) { // abort selected and only one window did_emsg = false; // avoid hit-enter prompt + ui_call_error_exit(1); getout(1); } win_close(curwin, true, false); @@ -1798,7 +1838,7 @@ static void edit_buffers(mparm_T *parmp, char *cwd) } if (p_shm_save != NULL) { - set_option_value_give_err("shm", 0L, p_shm_save, 0); + set_option_value_give_err("shm", CSTR_AS_OPTVAL(p_shm_save), 0); xfree(p_shm_save); } @@ -1831,7 +1871,6 @@ static void exe_pre_commands(mparm_T *parmp) { char **cmds = parmp->pre_commands; int cnt = parmp->n_pre_commands; - int i; if (cnt <= 0) { return; @@ -1840,7 +1879,7 @@ static void exe_pre_commands(mparm_T *parmp) curwin->w_cursor.lnum = 0; // just in case.. estack_push(ETYPE_ARGS, _("pre-vimrc command line"), 0); current_sctx.sc_sid = SID_CMDARG; - for (i = 0; i < cnt; i++) { + for (int i = 0; i < cnt; i++) { do_cmdline_cmd(cmds[i]); } estack_pop(); @@ -1851,8 +1890,6 @@ static void exe_pre_commands(mparm_T *parmp) // Execute "+", "-c" and "-S" arguments. static void exe_commands(mparm_T *parmp) { - int i; - // We start commands on line 0, make "vim +/pat file" match a // pattern on line 1. But don't move the cursor when an autocommand // with g`" was used. @@ -1863,7 +1900,7 @@ static void exe_commands(mparm_T *parmp) estack_push(ETYPE_ARGS, "command line", 0); current_sctx.sc_sid = SID_CARG; current_sctx.sc_seq = 0; - for (i = 0; i < parmp->n_commands; i++) { + for (int i = 0; i < parmp->n_commands; i++) { do_cmdline_cmd(parmp->commands[i]); if (parmp->cmds_tofree[i]) { xfree(parmp->commands[i]); @@ -1915,7 +1952,7 @@ static void do_system_initialization(void) dir_len += 1; } memcpy(vimrc + dir_len, path_tail, sizeof(path_tail)); - if (do_source(vimrc, false, DOSO_NONE) != FAIL) { + if (do_source(vimrc, false, DOSO_NONE, NULL) != FAIL) { xfree(vimrc); xfree(config_dirs); return; @@ -1927,7 +1964,7 @@ static void do_system_initialization(void) #ifdef SYS_VIMRC_FILE // Get system wide defaults, if the file name is defined. - (void)do_source(SYS_VIMRC_FILE, false, DOSO_NONE); + (void)do_source(SYS_VIMRC_FILE, false, DOSO_NONE, NULL); #endif } @@ -1956,7 +1993,7 @@ static bool do_user_initialization(void) // init.lua if (os_path_exists(init_lua_path) - && do_source(init_lua_path, true, DOSO_VIMRC)) { + && do_source(init_lua_path, true, DOSO_VIMRC, NULL)) { if (os_path_exists(user_vimrc)) { semsg(_("E5422: Conflicting configs: \"%s\" \"%s\""), init_lua_path, user_vimrc); @@ -1970,7 +2007,7 @@ static bool do_user_initialization(void) xfree(init_lua_path); // init.vim - if (do_source(user_vimrc, true, DOSO_VIMRC) != FAIL) { + if (do_source(user_vimrc, true, DOSO_VIMRC, NULL) != FAIL) { do_exrc = p_exrc; if (do_exrc) { do_exrc = (path_full_compare(VIMRC_FILE, user_vimrc, false, true) != kEqualFiles); @@ -1996,7 +2033,7 @@ static bool do_user_initialization(void) memmove(vimrc, dir, dir_len); vimrc[dir_len] = PATHSEP; memmove(vimrc + dir_len + 1, path_tail, sizeof(path_tail)); - if (do_source(vimrc, true, DOSO_VIMRC) != FAIL) { + if (do_source(vimrc, true, DOSO_VIMRC, NULL) != FAIL) { do_exrc = p_exrc; if (do_exrc) { do_exrc = (path_full_compare(VIMRC_FILE, vimrc, false, true) != kEqualFiles); @@ -2062,7 +2099,7 @@ static void source_startup_scripts(const mparm_T *const parmp) || strequal(parmp->use_vimrc, "NORC")) { // Do nothing. } else { - if (do_source(parmp->use_vimrc, false, DOSO_NONE) != OK) { + if (do_source(parmp->use_vimrc, false, DOSO_NONE, NULL) != OK) { semsg(_("E282: Cannot read from \"%s\""), parmp->use_vimrc); } } @@ -2095,7 +2132,7 @@ static int execute_env(char *env) current_sctx.sc_sid = SID_ENV; current_sctx.sc_seq = 0; current_sctx.sc_lnum = 0; - do_cmdline_cmd((char *)initstr); + do_cmdline_cmd(initstr); estack_pop(); current_sctx = save_current_sctx; @@ -2111,6 +2148,12 @@ static int execute_env(char *env) static void mainerr(const char *errstr, const char *str) FUNC_ATTR_NORETURN { + print_mainerr(errstr, str); + os_exit(1); +} + +static void print_mainerr(const char *errstr, const char *str) +{ char *prgname = path_tail(argv0); signal_stop(); // kill us with CTRL-C here, if you like @@ -2120,14 +2163,12 @@ static void mainerr(const char *errstr, const char *str) os_errmsg(_(errstr)); if (str != NULL) { os_errmsg(": \""); - os_errmsg((char *)str); + os_errmsg(str); os_errmsg("\""); } os_errmsg(_("\nMore info with \"")); os_errmsg(prgname); os_errmsg(" -h\"\n"); - - os_exit(1); } /// Prints version information for "nvim -v" or "nvim --version". @@ -2147,43 +2188,33 @@ static void usage(void) signal_stop(); // kill us with CTRL-C here, if you like os_msg(_("Usage:\n")); - os_msg(_(" nvim [options] [file ...] Edit file(s)\n")); - os_msg(_(" nvim [options] -t <tag> Edit file where tag is defined\n")); - os_msg(_(" nvim [options] -q [errorfile] Edit file with first error\n")); + os_msg(_(" nvim [options] [file ...]\n")); os_msg(_("\nOptions:\n")); - os_msg(_(" -- Only file names after this\n")); - os_msg(_(" + Start at end of file\n")); os_msg(_(" --cmd <cmd> Execute <cmd> before any config\n")); os_msg(_(" +<cmd>, -c <cmd> Execute <cmd> after config and first file\n")); os_msg(_(" -l <script> [args...] Execute Lua <script> (with optional args)\n")); + os_msg(_(" -S <session> Source <session> after loading the first file\n")); + os_msg(_(" -s <scriptin> Read Normal mode commands from <scriptin>\n")); + os_msg(_(" -u <config> Use this config file\n")); os_msg("\n"); - os_msg(_(" -b Binary mode\n")); os_msg(_(" -d Diff mode\n")); - os_msg(_(" -e, -E Ex mode\n")); os_msg(_(" -es, -Es Silent (batch) mode\n")); os_msg(_(" -h, --help Print this help message\n")); os_msg(_(" -i <shada> Use this shada file\n")); - os_msg(_(" -m Modifications (writing files) not allowed\n")); - os_msg(_(" -M Modifications in text not allowed\n")); os_msg(_(" -n No swap file, use memory only\n")); os_msg(_(" -o[N] Open N windows (default: one per file)\n")); os_msg(_(" -O[N] Open N vertical windows (default: one per file)\n")); os_msg(_(" -p[N] Open N tab pages (default: one per file)\n")); - os_msg(_(" -r, -L List swap files\n")); - os_msg(_(" -r <file> Recover edit state for this file\n")); - os_msg(_(" -R Read-only mode\n")); - os_msg(_(" -S <session> Source <session> after loading the first file\n")); - os_msg(_(" -s <scriptin> Read Normal mode commands from <scriptin>\n")); - os_msg(_(" -u <config> Use this config file\n")); + os_msg(_(" -R Read-only (view) mode\n")); os_msg(_(" -v, --version Print version information\n")); os_msg(_(" -V[N][file] Verbose [level][file]\n")); os_msg("\n"); + os_msg(_(" -- Only file names after this\n")); os_msg(_(" --api-info Write msgpack-encoded API metadata to stdout\n")); os_msg(_(" --clean \"Factory defaults\" (skip user config and plugins, shada)\n")); os_msg(_(" --embed Use stdin/stdout as a msgpack-rpc channel\n")); os_msg(_(" --headless Don't start a user interface\n")); os_msg(_(" --listen <address> Serve RPC API from this address\n")); - os_msg(_(" --noplugin Don't load plugins\n")); os_msg(_(" --remote[-subcommand] Execute commands remotely on a server\n")); os_msg(_(" --server <address> Specify RPC server to send commands to\n")); os_msg(_(" --startuptime <file> Write startup timing messages to <file>\n")); @@ -2196,7 +2227,20 @@ static void usage(void) static void check_swap_exists_action(void) { if (swap_exists_action == SEA_QUIT) { + ui_call_error_exit(1); getout(1); } handle_swap_exists(NULL); } + +#ifdef ENABLE_ASAN_UBSAN +const char *__ubsan_default_options(void) +{ + return "print_stacktrace=1"; +} + +const char *__asan_default_options(void) +{ + return "handle_abort=1,handle_sigill=1"; +} +#endif |