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 <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Ron Yorston 2021-08-19 16:59:36 +01:00 committed by Denys Vlasenko
parent 29b53ef03f
commit f07772f19e

View File

@ -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,
opts = getopt32(argv, VI_OPTSTR IF_FEATURE_VI_COLON(, &initial_cmds));
#if ENABLE_FEATURE_VI_CRASHME
"C"
if (opts & OPT_C)
crashme = 1;
#endif
"RHh" IF_FEATURE_VI_COLON("c:"))) != -1) {
switch (c) {
#if ENABLE_FEATURE_VI_CRASHME
case 'C':
crashme = 1;
break;
#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