vim-patch:8.1.1241: Ex command info contains confusing information

Problem:    Ex command info contains confusing information.
Solution:   When using the NOTADR flag use ADDR_OTHER for the address type.
            Cleanup code using NOTADR.  Check for errors in
            create_cmdidxs.vim.  Adjust Makefile to see the errors.
b731689e85

Use Lua's "assert()" to make an invalid command definition
a compilation error.

Misc changes:

Remove 'RESTRICT' flag.
Neovim does not support "restricted" mode
since commit 7777532ceb.

TODO:
Do not generate files before Lua assertions
so that CMake always runs the generator script
if the previous build has an invalid command definition.
This commit is contained in:
Jan Edmund Lazo 2020-12-31 19:56:15 -05:00
parent cf3a861017
commit f3c242c13c
No known key found for this signature in database
GPG Key ID: 64915E6E9F735B15
7 changed files with 732 additions and 689 deletions

View File

@ -55,7 +55,7 @@ end
vimcmd_start = 'syn keyword vimCommand contained '
w(vimcmd_start)
local prev_cmd = nil
for _, cmd_desc in ipairs(ex_cmds) do
for _, cmd_desc in ipairs(ex_cmds.cmds) do
if lld.line_length > 850 then
w('\n' .. vimcmd_start)
end

View File

@ -1032,14 +1032,15 @@ void free_prev_shellcmd(void)
* Bangs in the argument are replaced with the previously entered command.
* Remember the argument.
*/
void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
void do_bang(int addr_count, exarg_T *eap, bool forceit,
bool do_in, bool do_out)
FUNC_ATTR_NONNULL_ALL
{
char_u *arg = eap->arg; /* command */
linenr_T line1 = eap->line1; /* start of range */
linenr_T line2 = eap->line2; /* end of range */
char_u *newcmd = NULL; /* the new command */
int free_newcmd = FALSE; /* need to free() newcmd */
int ins_prevcmd;
char_u *arg = eap->arg; // command
linenr_T line1 = eap->line1; // start of range
linenr_T line2 = eap->line2; // end of range
char_u *newcmd = NULL; // the new command
bool free_newcmd = false; // need to free() newcmd
char_u *t;
char_u *p;
char_u *trailarg;
@ -1064,7 +1065,7 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
* Try to find an embedded bang, like in :!<cmd> ! [args]
* (:!! is indicated by the 'forceit' variable)
*/
ins_prevcmd = forceit;
bool ins_prevcmd = forceit;
trailarg = arg;
do {
len = (int)STRLEN(trailarg) + 1;
@ -1101,7 +1102,7 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
else {
trailarg = p;
*trailarg++ = NUL;
ins_prevcmd = TRUE;
ins_prevcmd = true;
break;
}
}
@ -1131,7 +1132,7 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
STRCPY(newcmd, p_shq);
STRCAT(newcmd, prevcmd);
STRCAT(newcmd, p_shq);
free_newcmd = TRUE;
free_newcmd = true;
}
if (addr_count == 0) { /* :! */
/* echo the command */
@ -1164,15 +1165,15 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
// do this.
// Alternatively, if on Unix and redirecting input or output, but not both,
// and the 'shelltemp' option isn't set, use pipes.
// We use input redirection if do_in is TRUE.
// We use output redirection if do_out is TRUE.
// We use input redirection if do_in is true.
// We use output redirection if do_out is true.
static void do_filter(
linenr_T line1,
linenr_T line2,
exarg_T *eap, /* for forced 'ff' and 'fenc' */
char_u *cmd,
int do_in,
int do_out)
bool do_in,
bool do_out)
{
char_u *itmp = NULL;
char_u *otmp = NULL;
@ -1669,10 +1670,17 @@ void ex_update(exarg_T *eap)
*/
void ex_write(exarg_T *eap)
{
if (eap->usefilter) /* input lines to shell command */
do_bang(1, eap, FALSE, TRUE, FALSE);
else
if (eap->cmdidx == CMD_saveas) {
// :saveas does not take a range, uses all lines.
eap->line1 = 1;
eap->line2 = curbuf->b_ml.ml_line_count;
}
if (eap->usefilter) { // input lines to shell command
do_bang(1, eap, false, true, false);
} else {
(void)do_write(eap);
}
}
/*

File diff suppressed because it is too large Load Diff

View File

@ -51,17 +51,16 @@
#define NOTRLCOM 0x800 // no trailing comment allowed
#define ZEROR 0x1000 // zero line number allowed
#define USECTRLV 0x2000 // do not remove CTRL-V from argument
#define NOTADR 0x4000 // number before command is not an address
#define EDITCMD 0x8000 // allow "+command" argument
#define BUFNAME 0x10000 // accepts buffer name
#define BUFUNL 0x20000 // accepts unlisted buffer too
#define ARGOPT 0x40000 // allow "++opt=val" argument
#define SBOXOK 0x80000 // allowed in the sandbox
#define CMDWIN 0x100000 // allowed in cmdline window; when missing
#define EDITCMD 0x4000 // allow "+command" argument
#define BUFNAME 0x8000 // accepts buffer name
#define BUFUNL 0x10000L // accepts unlisted buffer too
#define ARGOPT 0x20000L // allow "++opt=val" argument
#define SBOXOK 0x40000L // allowed in the sandbox
#define CMDWIN 0x80000L // allowed in cmdline window; when missing
// disallows editing another buffer when
// curbuf_lock is set
#define MODIFY 0x200000 // forbidden in non-'modifiable' buffer
#define EXFLAGS 0x400000 // allow flags after count in argument
#define MODIFY 0x100000L // forbidden in non-'modifiable' buffer
#define EXFLAGS 0x200000L // allow flags after count in argument
#define FILES (XFILE | EXTRA) // multiple extra files allowed
#define WORD1 (EXTRA | NOSPC) // one extra word allowed
#define FILE1 (FILES | NOSPC) // 1 file allowed, defaults to current file
@ -153,7 +152,7 @@ struct exarg {
int addr_count; ///< the number of addresses given
linenr_T line1; ///< the first line number
linenr_T line2; ///< the second line number or count
int addr_type; ///< type of the count/range
cmd_addr_T addr_type; ///< type of the count/range
int flags; ///< extra flags after count: EXFLAG_
char_u *do_ecmd_cmd; ///< +command arg to be used in edited file
linenr_T do_ecmd_lnum; ///< the line number in an edited file

View File

@ -1086,7 +1086,10 @@ static int compute_buffer_local_count(int addr_type, int lnum, int offset)
return buf->b_fnum;
}
static int current_win_nr(win_T *win)
// Return the window number of "win".
// When "win" is NULL return the number of windows.
static int current_win_nr(const win_T *win)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
int nr = 0;
@ -1163,7 +1166,7 @@ static void get_wincmd_addr_type(char_u *arg, exarg_T *eap)
case 'd':
case Ctrl_D:
// window size or any count
eap->addr_type = ADDR_LINES; // -V1037
eap->addr_type = ADDR_OTHER; // -V1037
break;
case Ctrl_HAT:
@ -1199,7 +1202,7 @@ static void get_wincmd_addr_type(char_u *arg, exarg_T *eap)
case '=':
case CAR:
// no count
eap->addr_type = 0;
eap->addr_type = ADDR_NONE;
break;
}
}
@ -1490,9 +1493,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
ea.forceit = false;
}
/*
* 6. Parse arguments.
*/
// 6. Parse arguments. Then check for errors.
if (!IS_USER_CMDIDX(ea.cmdidx)) {
ea.argt = cmdnames[(int)ea.cmdidx].cmd_argt;
}
@ -1547,12 +1548,10 @@ static char_u * do_one_cmd(char_u **cmdlinep,
* Don't complain about the range if it is not used
* (could happen if line_count is accidentally set to 0).
*/
if (!ea.skip && !ni) {
/*
* If the range is backwards, ask for confirmation and, if given, swap
* ea.line1 & ea.line2 so it's forwards again.
* When global command is busy, don't ask, will fail below.
*/
if (!ea.skip && !ni && (ea.argt & RANGE)) {
// If the range is backwards, ask for confirmation and, if given, swap
// ea.line1 & ea.line2 so it's forwards again.
// When global command is busy, don't ask, will fail below.
if (!global_busy && ea.line1 > ea.line2) {
if (msg_silent == 0) {
if ((flags & DOCMD_VERBOSE) || exmode_active) {
@ -1571,8 +1570,10 @@ static char_u * do_one_cmd(char_u **cmdlinep,
goto doend;
}
if ((ea.argt & NOTADR) && ea.addr_count == 0) /* default is 1, not cursor */
if ((ea.addr_type == ADDR_OTHER) && ea.addr_count == 0) {
// default is 1, not cursor
ea.line2 = 1;
}
correct_range(&ea);
@ -1694,6 +1695,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
ea.line1 = 1;
switch (ea.addr_type) {
case ADDR_LINES:
case ADDR_OTHER:
ea.line2 = curbuf->b_ml.ml_line_count;
break;
case ADDR_LOADED_BUFFERS:
@ -1771,7 +1773,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
errormsg = (char_u *)_(e_zerocount);
goto doend;
}
if (ea.argt & NOTADR) { /* e.g. :buffer 2, :sleep 3 */
if (ea.addr_type != ADDR_LINES) { // e.g. :buffer 2, :sleep 3
ea.line2 = n;
if (ea.addr_count == 0)
ea.addr_count = 1;
@ -1780,8 +1782,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
ea.line2 += n - 1;
++ea.addr_count;
// Be vi compatible: no error message for out of range.
if (ea.addr_type == ADDR_LINES
&& ea.line2 > curbuf->b_ml.ml_line_count) {
if (ea.line2 > curbuf->b_ml.ml_line_count) {
ea.line2 = curbuf->b_ml.ml_line_count;
}
}
@ -2325,6 +2326,7 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent)
eap->line1 = eap->line2;
switch (eap->addr_type) {
case ADDR_LINES:
case ADDR_OTHER:
// default is current line number
eap->line2 = curwin->w_cursor.lnum;
break;
@ -2365,6 +2367,7 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent)
eap->cmd++;
switch (eap->addr_type) {
case ADDR_LINES:
case ADDR_OTHER:
eap->line1 = 1;
eap->line2 = curbuf->b_ml.ml_line_count;
break;
@ -2400,7 +2403,6 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent)
}
break;
case ADDR_TABS_RELATIVE:
case ADDR_OTHER:
*errormsg = (char_u *)_(e_invrange);
return FAIL;
case ADDR_ARGUMENTS:
@ -3723,7 +3725,7 @@ static linenr_T get_address(exarg_T *eap,
int address_count) // 1 for first, >1 after comma
FUNC_ATTR_NONNULL_ALL
{
const int addr_type = addr_type_arg;
const cmd_addr_T addr_type = addr_type_arg;
int c;
int i;
long n;
@ -3741,6 +3743,7 @@ static linenr_T get_address(exarg_T *eap,
++cmd;
switch (addr_type) {
case ADDR_LINES:
case ADDR_OTHER:
lnum = curwin->w_cursor.lnum;
break;
case ADDR_WINDOWS:
@ -3772,6 +3775,7 @@ static linenr_T get_address(exarg_T *eap,
++cmd;
switch (addr_type) {
case ADDR_LINES:
case ADDR_OTHER:
lnum = curbuf->b_ml.ml_line_count;
break;
case ADDR_WINDOWS:
@ -3939,7 +3943,9 @@ static linenr_T get_address(exarg_T *eap,
if (lnum == MAXLNUM) {
switch (addr_type) {
case ADDR_LINES:
lnum = curwin->w_cursor.lnum; /* "+1" is same as ".+1" */
case ADDR_OTHER:
// "+1" is same as ".+1"
lnum = curwin->w_cursor.lnum;
break;
case ADDR_WINDOWS:
lnum = CURRENT_WIN_NR;
@ -4052,11 +4058,10 @@ static char_u *invalid_range(exarg_T *eap)
}
if (eap->argt & RANGE) {
switch(eap->addr_type) {
switch (eap->addr_type) {
case ADDR_LINES:
if (!(eap->argt & NOTADR)
&& eap->line2 > curbuf->b_ml.ml_line_count
+ (eap->cmdidx == CMD_diffget)) {
if (eap->line2 > (curbuf->b_ml.ml_line_count
+ (eap->cmdidx == CMD_diffget))) {
return (char_u *)_(e_invrange);
}
break;
@ -4105,7 +4110,8 @@ static char_u *invalid_range(exarg_T *eap)
}
break;
case ADDR_TABS_RELATIVE:
// Do nothing
case ADDR_OTHER:
// Any range is OK.
break;
case ADDR_QUICKFIX:
assert(eap->line2 >= 0);
@ -5376,7 +5382,7 @@ two_count:
}
*def = getdigits_long(&p, true, 0);
*argt |= (ZEROR | NOTADR);
*argt |= ZEROR;
if (p != val + vallen || vallen == 0) {
invalid_count:
@ -5384,8 +5390,16 @@ invalid_count:
return FAIL;
}
}
// default for -range is using buffer lines
if (*addr_type_arg == ADDR_NONE) {
*addr_type_arg = ADDR_LINES;
}
} else if (STRNICMP(attr, "count", attrlen) == 0) {
*argt |= (COUNT | ZEROR | RANGE | NOTADR);
*argt |= (COUNT | ZEROR | RANGE);
// default for -count is using any number
if (*addr_type_arg == ADDR_NONE) {
*addr_type_arg = ADDR_OTHER;
}
if (val != NULL) {
p = val;
@ -5416,11 +5430,11 @@ invalid_count:
EMSG(_("E179: argument required for -addr"));
return FAIL;
}
if (parse_addr_type_arg(val, (int)vallen, argt, addr_type_arg) == FAIL) {
if (parse_addr_type_arg(val, (int)vallen, addr_type_arg) == FAIL) {
return FAIL;
}
if (*addr_type_arg != ADDR_LINES) {
*argt |= (ZEROR | NOTADR);
*argt |= ZEROR;
}
} else {
char_u ch = attr[len];
@ -5447,7 +5461,7 @@ static void ex_command(exarg_T *eap)
int flags = 0;
int compl = EXPAND_NOTHING;
char_u *compl_arg = NULL;
cmd_addr_T addr_type_arg = ADDR_LINES;
cmd_addr_T addr_type_arg = ADDR_NONE;
int has_attr = (eap->arg[0] == '-');
int name_len;
@ -6105,8 +6119,7 @@ char_u *get_user_cmd_complete(expand_T *xp, int idx)
/*
* Parse address type argument
*/
int parse_addr_type_arg(char_u *value, int vallen, uint32_t *argt,
cmd_addr_T *addr_type_arg)
int parse_addr_type_arg(char_u *value, int vallen, cmd_addr_T *addr_type_arg)
FUNC_ATTR_NONNULL_ALL
{
int i, a, b;
@ -6129,9 +6142,6 @@ int parse_addr_type_arg(char_u *value, int vallen, uint32_t *argt,
return FAIL;
}
if (*addr_type_arg != ADDR_LINES)
*argt |= NOTADR;
return OK;
}
@ -7423,11 +7433,12 @@ static void ex_read(exarg_T *eap)
int empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
linenr_T lnum;
if (eap->usefilter) /* :r!cmd */
do_bang(1, eap, FALSE, FALSE, TRUE);
else {
if (u_save(eap->line2, (linenr_T)(eap->line2 + 1)) == FAIL)
if (eap->usefilter) { // :r!cmd
do_bang(1, eap, false, false, true);
} else {
if (u_save(eap->line2, (linenr_T)(eap->line2 + 1)) == FAIL) {
return;
}
if (*eap->arg == NUL) {
if (check_fname() == FAIL) /* check for no file name */
@ -7897,7 +7908,7 @@ static void ex_at(exarg_T *eap)
*/
static void ex_bang(exarg_T *eap)
{
do_bang(eap->addr_count, eap, eap->forceit, TRUE, TRUE);
do_bang(eap->addr_count, eap, eap->forceit, true, true);
}
/*

View File

@ -22,7 +22,10 @@ local defsfname = autodir .. '/ex_cmds_defs.generated.h'
local enumfile = io.open(enumfname, 'w')
local defsfile = io.open(defsfname, 'w')
local defs = require('ex_cmds')
local bit = require 'bit'
local ex_cmds = require('ex_cmds')
local defs = ex_cmds.cmds
local flags = ex_cmds.flags
local byte_a = string.byte('a')
local byte_z = string.byte('z')
@ -51,6 +54,17 @@ static CommandDefinition cmdnames[%u] = {
]], #defs, #defs))
local cmds, cmdidxs1, cmdidxs2 = {}, {}, {}
for _, cmd in ipairs(defs) do
if bit.band(cmd.flags, flags.RANGE) == flags.RANGE then
assert(cmd.addr_type ~= 'ADDR_NONE',
string.format('ex_cmds.lua:%s: Using RANGE with ADDR_NONE\n', cmd.command))
else
assert(cmd.addr_type == 'ADDR_NONE',
string.format('ex_cmds.lua:%s: Missing ADDR_NONE\n', cmd.command))
end
if bit.band(cmd.flags, flags.DFLALL) == flags.DFLALL then
assert(cmd.addr_type ~= 'ADDR_OTHER' and cmd.addr_type ~= 'ADDR_NONE',
string.format('ex_cmds.lua:%s: Missing misplaced DFLALL\n', cmd.command))
end
local enumname = cmd.enum or ('CMD_' .. cmd.command)
local byte_cmd = cmd.command:sub(1, 1):byte()
if byte_a <= byte_cmd and byte_cmd <= byte_z then

View File

@ -393,9 +393,13 @@ func Test_addr_all()
call assert_equal(len(gettabinfo()), g:a2)
bwipe
command! -addr=other DoSomething echo 'nothing'
command! -addr=other DoSomething let g:a1 = <line1> | let g:a2 = <line2>
DoSomething
call assert_fails('%DoSomething')
call assert_equal(line('.'), g:a1)
call assert_equal(line('.'), g:a2)
%DoSomething
call assert_equal(1, g:a1)
call assert_equal(line('$'), g:a2)
delcommand DoSomething
endfunc
@ -421,7 +425,7 @@ func Test_command_list()
\ execute('command DoCmd'))
command! -count=2 DoCmd :
call assert_equal("\n Name Args Address Complete Definition"
\ .. "\n DoCmd 0 2c :",
\ .. "\n DoCmd 0 2c ? :",
\ execute('command DoCmd'))
" Test with various -addr= argument values.