Patch 8.1.0266
Problem: Parsing Ex address range is not a separate function.
Solution: Refactor do_one_cmd() to separate address parsing.
Files: src/ex_docmd.c, src/proto/ex_docmd.pro
*** ../vim-8.1.0265/src/ex_docmd.c 2018-08-07 22:30:26.670240840 +0200
--- src/ex_docmd.c 2018-08-10 23:08:38.139696671 +0200
***************
*** 1719,1725 ****
cmdmod_T save_cmdmod;
int ni; /* set when Not
Implemented */
char_u *cmd;
- int address_count = 1;
vim_memset(&ea, 0, sizeof(ea));
ea.line1 = 1;
--- 1719,1724 ----
***************
*** 2045,2212 ****
get_wincmd_addr_type(skipwhite(p), &ea);
}
- /* repeat for all ',' or ';' separated addresses */
ea.cmd = cmd;
! for (;;)
! {
! 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.
--- 2044,2052 ----
get_wincmd_addr_type(skipwhite(p), &ea);
}
ea.cmd = cmd;
! if (parse_cmd_address(&ea, &errormsg) == FAIL)
! goto doend;
/*
* 5. Parse the command.
***************
*** 2989,2994 ****
--- 2829,3007 ----
#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.
* If there is a match advance "pp" to the argument and return TRUE.
*/
***************
*** 4292,4298 ****
}
/*
! * skip a range specifier of the form: addr [,addr] [;addr] ..
*
* Backslashed delimiters after / or ? will be skipped, and commands will
* not be expanded between /'s and ?'s or after "'".
--- 4305,4311 ----
}
/*
! * Skip a range specifier of the form: addr [,addr] [;addr] ..
*
* Backslashed delimiters after / or ? will be skipped, and commands will
* not be expanded between /'s and ?'s or after "'".
*** ../vim-8.1.0265/src/proto/ex_docmd.pro 2018-07-29 17:35:19.493750319
+0200
--- src/proto/ex_docmd.pro 2018-08-10 23:08:41.983672969 +0200
***************
*** 4,9 ****
--- 4,10 ----
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));
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 modifier_len(char_u *cmd);
int cmd_exists(char_u *name);
*** ../vim-8.1.0265/src/version.c 2018-08-10 22:07:28.821903829 +0200
--- src/version.c 2018-08-10 22:39:25.770183225 +0200
***************
*** 796,797 ****
--- 796,799 ----
{ /* Add new patch number below this line */
+ /**/
+ 266,
/**/
--
Permission is granted to read this message out aloud on Kings Cross Road,
London, under the condition that the orator is properly dressed.
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.