]> granicus.if.org Git - vim/commitdiff
patch 8.1.0266: parsing Ex address range is not a separate function v8.1.0266
authorBram Moolenaar <Bram@vim.org>
Fri, 10 Aug 2018 21:13:12 +0000 (23:13 +0200)
committerBram Moolenaar <Bram@vim.org>
Fri, 10 Aug 2018 21:13:12 +0000 (23:13 +0200)
Problem:    Parsing Ex address range is not a separate function.
Solution:   Refactor do_one_cmd() to separate address parsing.

src/ex_docmd.c
src/proto/ex_docmd.pro
src/version.c

index 294fbdbccc7689b25f6d4bb6c309156c71fb9b08..51aa068885ebbd873a53c3f89a56dafcf4adc047 100644 (file)
@@ -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.
@@ -2988,6 +2828,179 @@ doend:
  #pragma optimize( "", on )
 #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 "'".
index ada1a9a4ed4197f470b909d92ce94b68ab8f2954..00800e1ef5ac09625e7d03a7d2dbfcf51d64a683 100644 (file)
@@ -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);
index 9b39950b1007322a98fc60c567cc84e4be0ff442..61dfc5f76a03c420ec861a7150afd06db743ec93 100644 (file)
@@ -794,6 +794,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    266,
 /**/
     265,
 /**/