changeset 14505:3f1a17863b73 v8.1.0266

patch 8.1.0266: parsing Ex address range is not a separate function commit https://github.com/vim/vim/commit/ee8415bc5998792fab6f4dcf289d027856e05b89 Author: Bram Moolenaar <Bram@vim.org> Date: Fri Aug 10 23:13:12 2018 +0200 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.
author Christian Brabandt <cb@256bit.org>
date Fri, 10 Aug 2018 23:15:04 +0200
parents 89b3aabf0a95
children e6ed8002bed4
files src/ex_docmd.c src/proto/ex_docmd.pro src/version.c
diffstat 3 files changed, 179 insertions(+), 163 deletions(-) [+]
line wrap: on
line diff
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -1719,7 +1719,6 @@ do_one_cmd(
     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;
@@ -2045,168 +2044,9 @@ do_one_cmd(
 	    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;
-    }
+    if (parse_cmd_address(&ea, &errormsg) == FAIL)
+	goto doend;
 
 /*
  * 5. Parse the command.
@@ -2989,6 +2829,179 @@ doend:
 #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,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
  * not be expanded between /'s and ?'s or after "'".
--- a/src/proto/ex_docmd.pro
+++ b/src/proto/ex_docmd.pro
@@ -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 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);
--- a/src/version.c
+++ b/src/version.c
@@ -795,6 +795,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    266,
+/**/
     265,
 /**/
     264,