mirror of
https://github.com/vim/vim.git
synced 2025-10-02 05:04:20 -04:00
patch 8.1.0266: parsing Ex address range is not a separate function
Problem: Parsing Ex address range is not a separate function. Solution: Refactor do_one_cmd() to separate address parsing.
This commit is contained in:
339
src/ex_docmd.c
339
src/ex_docmd.c
@@ -1719,7 +1719,6 @@ do_one_cmd(
|
|||||||
cmdmod_T save_cmdmod;
|
cmdmod_T save_cmdmod;
|
||||||
int ni; /* set when Not Implemented */
|
int ni; /* set when Not Implemented */
|
||||||
char_u *cmd;
|
char_u *cmd;
|
||||||
int address_count = 1;
|
|
||||||
|
|
||||||
vim_memset(&ea, 0, sizeof(ea));
|
vim_memset(&ea, 0, sizeof(ea));
|
||||||
ea.line1 = 1;
|
ea.line1 = 1;
|
||||||
@@ -2045,168 +2044,9 @@ do_one_cmd(
|
|||||||
get_wincmd_addr_type(skipwhite(p), &ea);
|
get_wincmd_addr_type(skipwhite(p), &ea);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* repeat for all ',' or ';' separated addresses */
|
|
||||||
ea.cmd = cmd;
|
ea.cmd = cmd;
|
||||||
for (;;)
|
if (parse_cmd_address(&ea, &errormsg) == FAIL)
|
||||||
{
|
goto doend;
|
||||||
ea.line1 = ea.line2;
|
|
||||||
switch (ea.addr_type)
|
|
||||||
{
|
|
||||||
case ADDR_LINES:
|
|
||||||
/* default is current line number */
|
|
||||||
ea.line2 = curwin->w_cursor.lnum;
|
|
||||||
break;
|
|
||||||
case ADDR_WINDOWS:
|
|
||||||
ea.line2 = CURRENT_WIN_NR;
|
|
||||||
break;
|
|
||||||
case ADDR_ARGUMENTS:
|
|
||||||
ea.line2 = curwin->w_arg_idx + 1;
|
|
||||||
if (ea.line2 > ARGCOUNT)
|
|
||||||
ea.line2 = ARGCOUNT;
|
|
||||||
break;
|
|
||||||
case ADDR_LOADED_BUFFERS:
|
|
||||||
case ADDR_BUFFERS:
|
|
||||||
ea.line2 = curbuf->b_fnum;
|
|
||||||
break;
|
|
||||||
case ADDR_TABS:
|
|
||||||
ea.line2 = CURRENT_TAB_NR;
|
|
||||||
break;
|
|
||||||
case ADDR_TABS_RELATIVE:
|
|
||||||
ea.line2 = 1;
|
|
||||||
break;
|
|
||||||
#ifdef FEAT_QUICKFIX
|
|
||||||
case ADDR_QUICKFIX:
|
|
||||||
ea.line2 = qf_get_cur_valid_idx(&ea);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
ea.cmd = skipwhite(ea.cmd);
|
|
||||||
lnum = get_address(&ea, &ea.cmd, ea.addr_type, ea.skip,
|
|
||||||
ea.addr_count == 0, address_count++);
|
|
||||||
if (ea.cmd == NULL) /* error detected */
|
|
||||||
goto doend;
|
|
||||||
if (lnum == MAXLNUM)
|
|
||||||
{
|
|
||||||
if (*ea.cmd == '%') /* '%' - all lines */
|
|
||||||
{
|
|
||||||
++ea.cmd;
|
|
||||||
switch (ea.addr_type)
|
|
||||||
{
|
|
||||||
case ADDR_LINES:
|
|
||||||
ea.line1 = 1;
|
|
||||||
ea.line2 = curbuf->b_ml.ml_line_count;
|
|
||||||
break;
|
|
||||||
case ADDR_LOADED_BUFFERS:
|
|
||||||
{
|
|
||||||
buf_T *buf = firstbuf;
|
|
||||||
|
|
||||||
while (buf->b_next != NULL
|
|
||||||
&& buf->b_ml.ml_mfp == NULL)
|
|
||||||
buf = buf->b_next;
|
|
||||||
ea.line1 = buf->b_fnum;
|
|
||||||
buf = lastbuf;
|
|
||||||
while (buf->b_prev != NULL
|
|
||||||
&& buf->b_ml.ml_mfp == NULL)
|
|
||||||
buf = buf->b_prev;
|
|
||||||
ea.line2 = buf->b_fnum;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ADDR_BUFFERS:
|
|
||||||
ea.line1 = firstbuf->b_fnum;
|
|
||||||
ea.line2 = lastbuf->b_fnum;
|
|
||||||
break;
|
|
||||||
case ADDR_WINDOWS:
|
|
||||||
case ADDR_TABS:
|
|
||||||
if (IS_USER_CMDIDX(ea.cmdidx))
|
|
||||||
{
|
|
||||||
ea.line1 = 1;
|
|
||||||
ea.line2 = ea.addr_type == ADDR_WINDOWS
|
|
||||||
? LAST_WIN_NR : LAST_TAB_NR;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* there is no Vim command which uses '%' and
|
|
||||||
* ADDR_WINDOWS or ADDR_TABS */
|
|
||||||
errormsg = (char_u *)_(e_invrange);
|
|
||||||
goto doend;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ADDR_TABS_RELATIVE:
|
|
||||||
errormsg = (char_u *)_(e_invrange);
|
|
||||||
goto doend;
|
|
||||||
break;
|
|
||||||
case ADDR_ARGUMENTS:
|
|
||||||
if (ARGCOUNT == 0)
|
|
||||||
ea.line1 = ea.line2 = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ea.line1 = 1;
|
|
||||||
ea.line2 = ARGCOUNT;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#ifdef FEAT_QUICKFIX
|
|
||||||
case ADDR_QUICKFIX:
|
|
||||||
ea.line1 = 1;
|
|
||||||
ea.line2 = qf_get_size(&ea);
|
|
||||||
if (ea.line2 == 0)
|
|
||||||
ea.line2 = 1;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
++ea.addr_count;
|
|
||||||
}
|
|
||||||
/* '*' - visual area */
|
|
||||||
else if (*ea.cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL)
|
|
||||||
{
|
|
||||||
pos_T *fp;
|
|
||||||
|
|
||||||
if (ea.addr_type != ADDR_LINES)
|
|
||||||
{
|
|
||||||
errormsg = (char_u *)_(e_invrange);
|
|
||||||
goto doend;
|
|
||||||
}
|
|
||||||
|
|
||||||
++ea.cmd;
|
|
||||||
if (!ea.skip)
|
|
||||||
{
|
|
||||||
fp = getmark('<', FALSE);
|
|
||||||
if (check_mark(fp) == FAIL)
|
|
||||||
goto doend;
|
|
||||||
ea.line1 = fp->lnum;
|
|
||||||
fp = getmark('>', FALSE);
|
|
||||||
if (check_mark(fp) == FAIL)
|
|
||||||
goto doend;
|
|
||||||
ea.line2 = fp->lnum;
|
|
||||||
++ea.addr_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ea.line2 = lnum;
|
|
||||||
ea.addr_count++;
|
|
||||||
|
|
||||||
if (*ea.cmd == ';')
|
|
||||||
{
|
|
||||||
if (!ea.skip)
|
|
||||||
{
|
|
||||||
curwin->w_cursor.lnum = ea.line2;
|
|
||||||
/* don't leave the cursor on an illegal line or column */
|
|
||||||
check_cursor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (*ea.cmd != ',')
|
|
||||||
break;
|
|
||||||
++ea.cmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* One address given: set start and end lines */
|
|
||||||
if (ea.addr_count == 1)
|
|
||||||
{
|
|
||||||
ea.line1 = ea.line2;
|
|
||||||
/* ... but only implicit: really no address given */
|
|
||||||
if (lnum == MAXLNUM)
|
|
||||||
ea.addr_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 5. Parse the command.
|
* 5. Parse the command.
|
||||||
@@ -2988,6 +2828,179 @@ doend:
|
|||||||
#pragma optimize( "", on )
|
#pragma optimize( "", on )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse the address range, if any, in "eap".
|
||||||
|
* Return FAIL and set "errormsg" or return OK.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
parse_cmd_address(exarg_T *eap, char_u **errormsg)
|
||||||
|
{
|
||||||
|
int address_count = 1;
|
||||||
|
linenr_T lnum;
|
||||||
|
|
||||||
|
// Repeat for all ',' or ';' separated addresses.
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
eap->line1 = eap->line2;
|
||||||
|
switch (eap->addr_type)
|
||||||
|
{
|
||||||
|
case ADDR_LINES:
|
||||||
|
// default is current line number
|
||||||
|
eap->line2 = curwin->w_cursor.lnum;
|
||||||
|
break;
|
||||||
|
case ADDR_WINDOWS:
|
||||||
|
eap->line2 = CURRENT_WIN_NR;
|
||||||
|
break;
|
||||||
|
case ADDR_ARGUMENTS:
|
||||||
|
eap->line2 = curwin->w_arg_idx + 1;
|
||||||
|
if (eap->line2 > ARGCOUNT)
|
||||||
|
eap->line2 = ARGCOUNT;
|
||||||
|
break;
|
||||||
|
case ADDR_LOADED_BUFFERS:
|
||||||
|
case ADDR_BUFFERS:
|
||||||
|
eap->line2 = curbuf->b_fnum;
|
||||||
|
break;
|
||||||
|
case ADDR_TABS:
|
||||||
|
eap->line2 = CURRENT_TAB_NR;
|
||||||
|
break;
|
||||||
|
case ADDR_TABS_RELATIVE:
|
||||||
|
eap->line2 = 1;
|
||||||
|
break;
|
||||||
|
#ifdef FEAT_QUICKFIX
|
||||||
|
case ADDR_QUICKFIX:
|
||||||
|
eap->line2 = qf_get_cur_valid_idx(eap);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
eap->cmd = skipwhite(eap->cmd);
|
||||||
|
lnum = get_address(eap, &eap->cmd, eap->addr_type, eap->skip,
|
||||||
|
eap->addr_count == 0, address_count++);
|
||||||
|
if (eap->cmd == NULL) // error detected
|
||||||
|
return FAIL;
|
||||||
|
if (lnum == MAXLNUM)
|
||||||
|
{
|
||||||
|
if (*eap->cmd == '%') // '%' - all lines
|
||||||
|
{
|
||||||
|
++eap->cmd;
|
||||||
|
switch (eap->addr_type)
|
||||||
|
{
|
||||||
|
case ADDR_LINES:
|
||||||
|
eap->line1 = 1;
|
||||||
|
eap->line2 = curbuf->b_ml.ml_line_count;
|
||||||
|
break;
|
||||||
|
case ADDR_LOADED_BUFFERS:
|
||||||
|
{
|
||||||
|
buf_T *buf = firstbuf;
|
||||||
|
|
||||||
|
while (buf->b_next != NULL
|
||||||
|
&& buf->b_ml.ml_mfp == NULL)
|
||||||
|
buf = buf->b_next;
|
||||||
|
eap->line1 = buf->b_fnum;
|
||||||
|
buf = lastbuf;
|
||||||
|
while (buf->b_prev != NULL
|
||||||
|
&& buf->b_ml.ml_mfp == NULL)
|
||||||
|
buf = buf->b_prev;
|
||||||
|
eap->line2 = buf->b_fnum;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ADDR_BUFFERS:
|
||||||
|
eap->line1 = firstbuf->b_fnum;
|
||||||
|
eap->line2 = lastbuf->b_fnum;
|
||||||
|
break;
|
||||||
|
case ADDR_WINDOWS:
|
||||||
|
case ADDR_TABS:
|
||||||
|
if (IS_USER_CMDIDX(eap->cmdidx))
|
||||||
|
{
|
||||||
|
eap->line1 = 1;
|
||||||
|
eap->line2 = eap->addr_type == ADDR_WINDOWS
|
||||||
|
? LAST_WIN_NR : LAST_TAB_NR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// there is no Vim command which uses '%' and
|
||||||
|
// ADDR_WINDOWS or ADDR_TABS
|
||||||
|
*errormsg = (char_u *)_(e_invrange);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ADDR_TABS_RELATIVE:
|
||||||
|
*errormsg = (char_u *)_(e_invrange);
|
||||||
|
return FAIL;
|
||||||
|
case ADDR_ARGUMENTS:
|
||||||
|
if (ARGCOUNT == 0)
|
||||||
|
eap->line1 = eap->line2 = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eap->line1 = 1;
|
||||||
|
eap->line2 = ARGCOUNT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#ifdef FEAT_QUICKFIX
|
||||||
|
case ADDR_QUICKFIX:
|
||||||
|
eap->line1 = 1;
|
||||||
|
eap->line2 = qf_get_size(eap);
|
||||||
|
if (eap->line2 == 0)
|
||||||
|
eap->line2 = 1;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
++eap->addr_count;
|
||||||
|
}
|
||||||
|
else if (*eap->cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL)
|
||||||
|
{
|
||||||
|
pos_T *fp;
|
||||||
|
|
||||||
|
// '*' - visual area
|
||||||
|
if (eap->addr_type != ADDR_LINES)
|
||||||
|
{
|
||||||
|
*errormsg = (char_u *)_(e_invrange);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
++eap->cmd;
|
||||||
|
if (!eap->skip)
|
||||||
|
{
|
||||||
|
fp = getmark('<', FALSE);
|
||||||
|
if (check_mark(fp) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
eap->line1 = fp->lnum;
|
||||||
|
fp = getmark('>', FALSE);
|
||||||
|
if (check_mark(fp) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
eap->line2 = fp->lnum;
|
||||||
|
++eap->addr_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
eap->line2 = lnum;
|
||||||
|
eap->addr_count++;
|
||||||
|
|
||||||
|
if (*eap->cmd == ';')
|
||||||
|
{
|
||||||
|
if (!eap->skip)
|
||||||
|
{
|
||||||
|
curwin->w_cursor.lnum = eap->line2;
|
||||||
|
// don't leave the cursor on an illegal line or column
|
||||||
|
check_cursor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (*eap->cmd != ',')
|
||||||
|
break;
|
||||||
|
++eap->cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// One address given: set start and end lines.
|
||||||
|
if (eap->addr_count == 1)
|
||||||
|
{
|
||||||
|
eap->line1 = eap->line2;
|
||||||
|
// ... but only implicit: really no address given
|
||||||
|
if (lnum == MAXLNUM)
|
||||||
|
eap->addr_count = 0;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for an Ex command with optional tail.
|
* Check for an Ex command with optional tail.
|
||||||
* If there is a match advance "pp" to the argument and return TRUE.
|
* If there is a match advance "pp" to the argument and return TRUE.
|
||||||
@@ -4292,7 +4305,7 @@ set_one_cmd_context(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* skip a range specifier of the form: addr [,addr] [;addr] ..
|
* Skip a range specifier of the form: addr [,addr] [;addr] ..
|
||||||
*
|
*
|
||||||
* Backslashed delimiters after / or ? will be skipped, and commands will
|
* Backslashed delimiters after / or ? will be skipped, and commands will
|
||||||
* not be expanded between /'s and ?'s or after "'".
|
* not be expanded between /'s and ?'s or after "'".
|
||||||
|
@@ -4,6 +4,7 @@ int do_cmdline_cmd(char_u *cmd);
|
|||||||
int do_cmdline(char_u *cmdline, char_u *(*fgetline)(int, void *, int), void *cookie, int flags);
|
int do_cmdline(char_u *cmdline, char_u *(*fgetline)(int, void *, int), void *cookie, int flags);
|
||||||
int getline_equal(char_u *(*fgetline)(int, void *, int), void *cookie, char_u *(*func)(int, void *, int));
|
int getline_equal(char_u *(*fgetline)(int, void *, int), void *cookie, char_u *(*func)(int, void *, int));
|
||||||
void *getline_cookie(char_u *(*fgetline)(int, void *, int), void *cookie);
|
void *getline_cookie(char_u *(*fgetline)(int, void *, int), void *cookie);
|
||||||
|
int parse_cmd_address(exarg_T *eap, char_u **errormsg);
|
||||||
int checkforcmd(char_u **pp, char *cmd, int len);
|
int checkforcmd(char_u **pp, char *cmd, int len);
|
||||||
int modifier_len(char_u *cmd);
|
int modifier_len(char_u *cmd);
|
||||||
int cmd_exists(char_u *name);
|
int cmd_exists(char_u *name);
|
||||||
|
@@ -794,6 +794,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
266,
|
||||||
/**/
|
/**/
|
||||||
265,
|
265,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user