From f07772f19e29cf44a14c108935afb5668e38fac3 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Thu, 19 Aug 2021 16:59:36 +0100 Subject: vi: changes to handling of -c and EXINIT Rewrite handling of command line arguments so any number of -c commands will be processed. Previously only two -c commands were allowed (or one if EXINIT was set). Process commands from EXINIT before the first file is read into memory, as specified by POSIX. function old new delta run_cmds - 77 +77 .rodata 108410 108411 +1 vi_main 305 268 -37 edit_file 816 764 -52 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/2 up/down: 78/-89) Total: -11 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- editors/vi.c | 123 +++++++++++++++++++++++++++++++---------------------------- 1 file changed, 65 insertions(+), 58 deletions(-) (limited to 'editors') diff --git a/editors/vi.c b/editors/vi.c index 3e1bd0820..cc4f6bde7 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -201,6 +201,7 @@ // the CRASHME code is unmaintained, and doesn't currently build #define ENABLE_FEATURE_VI_CRASHME 0 +#define IF_FEATURE_VI_CRASHME(...) #if ENABLE_LOCALE_SUPPORT @@ -403,7 +404,7 @@ struct globals { int cindex; // saved character index for up/down motion smallint keep_index; // retain saved character index #if ENABLE_FEATURE_VI_COLON - char *initial_cmds[3]; // currently 2 entries, NULL terminated + llist_t *initial_cmds; #endif // Should be just enough to hold a key sequence, // but CRASHME mode uses it as generated command buffer too @@ -4708,6 +4709,21 @@ static void crash_test() } #endif +#if ENABLE_FEATURE_VI_COLON +static void run_cmds(char *p) +{ + while (p) { + char *q = p; + p = strchr(q, '\n'); + if (p) + while (*p == '\n') + *p++ = '\0'; + if (strlen(q) < MAX_INPUT_LEN) + colon(q); + } +} +#endif + static void edit_file(char *fn) { #if ENABLE_FEATURE_VI_YANKMARK @@ -4778,25 +4794,8 @@ static void edit_file(char *fn) #endif #if ENABLE_FEATURE_VI_COLON - { - char *p, *q; - int n = 0; - - while ((p = initial_cmds[n]) != NULL) { - do { - q = p; - p = strchr(q, '\n'); - if (p) - while (*p == '\n') - *p++ = '\0'; - if (*q) - colon(q); - } while (p); - free(initial_cmds[n]); - initial_cmds[n] = NULL; - n++; - } - } + while (initial_cmds) + run_cmds((char *)llist_pop(&initial_cmds)); #endif redraw(FALSE); // dont force every col re-draw //------This is the main Vi cmd handling loop ----------------------- @@ -4859,10 +4858,29 @@ static void edit_file(char *fn) #undef cur_line } +#define VI_OPTSTR \ + IF_FEATURE_VI_CRASHME("C") \ + IF_FEATURE_VI_COLON("c:*") \ + "Hh" \ + IF_FEATURE_VI_READONLY("R") + +enum { + IF_FEATURE_VI_CRASHME(OPTBIT_C,) + IF_FEATURE_VI_COLON(OPTBIT_c,) + OPTBIT_H, + OPTBIT_h, + IF_FEATURE_VI_READONLY(OPTBIT_R,) + OPT_C = IF_FEATURE_VI_CRASHME( (1 << OPTBIT_C)) + 0, + OPT_c = IF_FEATURE_VI_COLON( (1 << OPTBIT_c)) + 0, + OPT_H = 1 << OPTBIT_H, + OPT_h = 1 << OPTBIT_h, + OPT_R = IF_FEATURE_VI_READONLY( (1 << OPTBIT_R)) + 0, +}; + int vi_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int vi_main(int argc, char **argv) { - int c; + int opts; INIT_G(); @@ -4886,50 +4904,39 @@ int vi_main(int argc, char **argv) // 0: all of our options are disabled by default in vim //vi_setops = 0; - // 1- process EXINIT variable from environment - // 2- if EXINIT is unset process $HOME/.exrc file (not inplemented yet) - // 3- process command line args -#if ENABLE_FEATURE_VI_COLON - { - char *p = getenv("EXINIT"); - if (p && *p) - initial_cmds[0] = xstrndup(p, MAX_INPUT_LEN); - } -#endif - while ((c = getopt(argc, argv, -#if ENABLE_FEATURE_VI_CRASHME - "C" -#endif - "RHh" IF_FEATURE_VI_COLON("c:"))) != -1) { - switch (c) { + opts = getopt32(argv, VI_OPTSTR IF_FEATURE_VI_COLON(, &initial_cmds)); + #if ENABLE_FEATURE_VI_CRASHME - case 'C': - crashme = 1; - break; + if (opts & OPT_C) + crashme = 1; #endif -#if ENABLE_FEATURE_VI_READONLY - case 'R': // Read-only flag - SET_READONLY_MODE(readonly_mode); - break; -#endif -#if ENABLE_FEATURE_VI_COLON - case 'c': // cmd line vi command - if (*optarg) - initial_cmds[initial_cmds[0] != NULL] = xstrndup(optarg, MAX_INPUT_LEN); - break; -#endif - case 'H': - show_help(); - // fall through - default: - bb_show_usage(); - return 1; - } + if (opts & OPT_R) + SET_READONLY_MODE(readonly_mode); + if (opts & OPT_H) + show_help(); + if (opts & (OPT_H | OPT_h)) { + bb_show_usage(); + return 1; } argv += optind; cmdline_filecnt = argc - optind; + // 1- process EXINIT variable from environment + // 2- if EXINIT is unset process $HOME/.exrc file (not implemented yet) + // 3- process command line args +#if ENABLE_FEATURE_VI_COLON + { + const char *exinit = getenv("EXINIT"); + + if (exinit) { + char *cmds = xstrdup(exinit); + init_text_buffer(NULL); + run_cmds(cmds); + free(cmds); + } + } +#endif // "Save cursor, use alternate screen buffer, clear screen" write1(ESC"[?1049h"); // This is the main file handling loop -- cgit v1.2.1