diff --git a/src/nvim/eval.c b/src/nvim/eval.c index ddafe1981f..e309c93544 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -9151,10 +9151,7 @@ char_u *v_throwpoint(char_u *oldval) */ char_u *set_cmdarg(exarg_T *eap, char_u *oldarg) { - char_u *oldval; - char_u *newval; - - oldval = vimvars[VV_CMDARG].vv_str; + char_u *oldval = vimvars[VV_CMDARG].vv_str; if (eap == NULL) { xfree(oldval); vimvars[VV_CMDARG].vv_str = oldarg; @@ -9170,14 +9167,18 @@ char_u *set_cmdarg(exarg_T *eap, char_u *oldarg) if (eap->read_edit) len += 7; - if (eap->force_ff != 0) - len += STRLEN(eap->cmd + eap->force_ff) + 6; - if (eap->force_enc != 0) + if (eap->force_ff != 0) { + len += 10; // " ++ff=unix" + } + if (eap->force_enc != 0) { len += STRLEN(eap->cmd + eap->force_enc) + 7; - if (eap->bad_char != 0) - len += 7 + 4; /* " ++bad=" + "keep" or "drop" */ + } + if (eap->bad_char != 0) { + len += 7 + 4; // " ++bad=" + "keep" or "drop" + } - newval = xmalloc(len + 1); + const size_t newval_len = len + 1; + char_u *newval = xmalloc(newval_len); if (eap->force_bin == FORCE_BIN) sprintf((char *)newval, " ++bin"); @@ -9189,18 +9190,23 @@ char_u *set_cmdarg(exarg_T *eap, char_u *oldarg) if (eap->read_edit) STRCAT(newval, " ++edit"); - if (eap->force_ff != 0) - sprintf((char *)newval + STRLEN(newval), " ++ff=%s", - eap->cmd + eap->force_ff); - if (eap->force_enc != 0) - sprintf((char *)newval + STRLEN(newval), " ++enc=%s", - eap->cmd + eap->force_enc); - if (eap->bad_char == BAD_KEEP) + if (eap->force_ff != 0) { + snprintf((char *)newval + STRLEN(newval), newval_len, " ++ff=%s", + eap->force_ff == 'u' ? "unix" : + eap->force_ff == 'd' ? "dos" : "mac"); + } + if (eap->force_enc != 0) { + snprintf((char *)newval + STRLEN(newval), newval_len, " ++enc=%s", + eap->cmd + eap->force_enc); + } + if (eap->bad_char == BAD_KEEP) { STRCPY(newval + STRLEN(newval), " ++bad=keep"); - else if (eap->bad_char == BAD_DROP) + } else if (eap->bad_char == BAD_DROP) { STRCPY(newval + STRLEN(newval), " ++bad=drop"); - else if (eap->bad_char != 0) - sprintf((char *)newval + STRLEN(newval), " ++bad=%c", eap->bad_char); + } else if (eap->bad_char != 0) { + snprintf((char *)newval + STRLEN(newval), newval_len, " ++bad=%c", + eap->bad_char); + } vimvars[VV_CMDARG].vv_str = newval; return oldval; } diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h index 4a40cc54b4..d25d81658c 100644 --- a/src/nvim/ex_cmds_defs.h +++ b/src/nvim/ex_cmds_defs.h @@ -160,7 +160,7 @@ struct exarg { int regname; ///< register name (NUL if none) int force_bin; ///< 0, FORCE_BIN or FORCE_NOBIN int read_edit; ///< ++edit argument - int force_ff; ///< ++ff= argument (index in cmd[]) + int force_ff; ///< ++ff= argument (first char of argument) int force_enc; ///< ++enc= argument (index in cmd[]) int bad_char; ///< BAD_KEEP, BAD_DROP or replacement byte int useridx; ///< user command index diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index b8b98c4f0d..ead0922c5a 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -4538,6 +4538,19 @@ skip_cmd_arg ( return p; } +int get_bad_opt(const char_u *p, exarg_T *eap) + FUNC_ATTR_NONNULL_ALL +{ + if (STRICMP(p, "keep") == 0) { + eap->bad_char = BAD_KEEP; + } else if (STRICMP(p, "drop") == 0) { + eap->bad_char = BAD_DROP; + } else if (MB_BYTE2LEN(*p) == 1 && p[1] == NUL) { + eap->bad_char = *p; + } + return FAIL; +} + /* * Get "++opt=arg" argument. * Return FAIL or OK. @@ -4596,8 +4609,10 @@ static int getargopt(exarg_T *eap) *arg = NUL; if (pp == &eap->force_ff) { - if (check_ff_value(eap->cmd + eap->force_ff) == FAIL) + if (check_ff_value(eap->cmd + eap->force_ff) == FAIL) { return FAIL; + } + eap->force_ff = eap->cmd[eap->force_ff]; } else if (pp == &eap->force_enc) { /* Make 'fileencoding' lower case. */ for (p = eap->cmd + eap->force_enc; *p != NUL; ++p) @@ -4605,15 +4620,9 @@ static int getargopt(exarg_T *eap) } else { /* Check ++bad= argument. Must be a single-byte character, "keep" or * "drop". */ - p = eap->cmd + bad_char_idx; - if (STRICMP(p, "keep") == 0) - eap->bad_char = BAD_KEEP; - else if (STRICMP(p, "drop") == 0) - eap->bad_char = BAD_DROP; - else if (MB_BYTE2LEN(*p) == 1 && p[1] == NUL) - eap->bad_char = *p; - else + if (get_bad_opt(eap->cmd + bad_char_idx, eap) == FAIL) { return FAIL; + } } return OK; diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 84c328f0c4..e5845e0749 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -2032,14 +2032,16 @@ readfile_linenr( * Fill "*eap" to force the 'fileencoding', 'fileformat' and 'binary to be * equal to the buffer "buf". Used for calling readfile(). */ -void prep_exarg(exarg_T *eap, buf_T *buf) +void prep_exarg(exarg_T *eap, const buf_T *buf) + FUNC_ATTR_NONNULL_ALL { - eap->cmd = xmalloc(STRLEN(buf->b_p_ff) + STRLEN(buf->b_p_fenc) + 15); + const size_t cmd_len = 15 + STRLEN(buf->b_p_fenc); + eap->cmd = xmalloc(cmd_len); - sprintf((char *)eap->cmd, "e ++ff=%s ++enc=%s", buf->b_p_ff, buf->b_p_fenc); - eap->force_enc = 14 + (int)STRLEN(buf->b_p_ff); + snprintf((char *)eap->cmd, cmd_len, "e ++enc=%s", buf->b_p_fenc); + eap->force_enc = 8; eap->bad_char = buf->b_bad_char; - eap->force_ff = 7; + eap->force_ff = *buf->b_p_ff; eap->force_bin = buf->b_p_bin ? FORCE_BIN : FORCE_NOBIN; eap->read_edit = FALSE; diff --git a/src/nvim/option.c b/src/nvim/option.c index 100902897a..478c9a0ff8 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -7294,12 +7294,13 @@ int get_fileformat(buf_T *buf) /// argument. /// /// @param eap can be NULL! -int get_fileformat_force(buf_T *buf, exarg_T *eap) +int get_fileformat_force(const buf_T *buf, const exarg_T *eap) + FUNC_ATTR_NONNULL_ARG(1) { int c; if (eap != NULL && eap->force_ff != 0) { - c = eap->cmd[eap->force_ff]; + c = eap->force_ff; } else { if ((eap != NULL && eap->force_bin != 0) ? (eap->force_bin == FORCE_BIN) : buf->b_p_bin) {