Skip to content

Commit ee8415b

Browse files
committed
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.
1 parent 0ee81cb commit ee8415b

3 files changed

Lines changed: 179 additions & 163 deletions

File tree

src/ex_docmd.c

Lines changed: 176 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -1719,7 +1719,6 @@ do_one_cmd(
17191719
cmdmod_T save_cmdmod;
17201720
int ni; /* set when Not Implemented */
17211721
char_u *cmd;
1722-
int address_count = 1;
17231722

17241723
vim_memset(&ea, 0, sizeof(ea));
17251724
ea.line1 = 1;
@@ -2045,168 +2044,9 @@ do_one_cmd(
20452044
get_wincmd_addr_type(skipwhite(p), &ea);
20462045
}
20472046

2048-
/* repeat for all ',' or ';' separated addresses */
20492047
ea.cmd = cmd;
2050-
for (;;)
2051-
{
2052-
ea.line1 = ea.line2;
2053-
switch (ea.addr_type)
2054-
{
2055-
case ADDR_LINES:
2056-
/* default is current line number */
2057-
ea.line2 = curwin->w_cursor.lnum;
2058-
break;
2059-
case ADDR_WINDOWS:
2060-
ea.line2 = CURRENT_WIN_NR;
2061-
break;
2062-
case ADDR_ARGUMENTS:
2063-
ea.line2 = curwin->w_arg_idx + 1;
2064-
if (ea.line2 > ARGCOUNT)
2065-
ea.line2 = ARGCOUNT;
2066-
break;
2067-
case ADDR_LOADED_BUFFERS:
2068-
case ADDR_BUFFERS:
2069-
ea.line2 = curbuf->b_fnum;
2070-
break;
2071-
case ADDR_TABS:
2072-
ea.line2 = CURRENT_TAB_NR;
2073-
break;
2074-
case ADDR_TABS_RELATIVE:
2075-
ea.line2 = 1;
2076-
break;
2077-
#ifdef FEAT_QUICKFIX
2078-
case ADDR_QUICKFIX:
2079-
ea.line2 = qf_get_cur_valid_idx(&ea);
2080-
break;
2081-
#endif
2082-
}
2083-
ea.cmd = skipwhite(ea.cmd);
2084-
lnum = get_address(&ea, &ea.cmd, ea.addr_type, ea.skip,
2085-
ea.addr_count == 0, address_count++);
2086-
if (ea.cmd == NULL) /* error detected */
2087-
goto doend;
2088-
if (lnum == MAXLNUM)
2089-
{
2090-
if (*ea.cmd == '%') /* '%' - all lines */
2091-
{
2092-
++ea.cmd;
2093-
switch (ea.addr_type)
2094-
{
2095-
case ADDR_LINES:
2096-
ea.line1 = 1;
2097-
ea.line2 = curbuf->b_ml.ml_line_count;
2098-
break;
2099-
case ADDR_LOADED_BUFFERS:
2100-
{
2101-
buf_T *buf = firstbuf;
2102-
2103-
while (buf->b_next != NULL
2104-
&& buf->b_ml.ml_mfp == NULL)
2105-
buf = buf->b_next;
2106-
ea.line1 = buf->b_fnum;
2107-
buf = lastbuf;
2108-
while (buf->b_prev != NULL
2109-
&& buf->b_ml.ml_mfp == NULL)
2110-
buf = buf->b_prev;
2111-
ea.line2 = buf->b_fnum;
2112-
break;
2113-
}
2114-
case ADDR_BUFFERS:
2115-
ea.line1 = firstbuf->b_fnum;
2116-
ea.line2 = lastbuf->b_fnum;
2117-
break;
2118-
case ADDR_WINDOWS:
2119-
case ADDR_TABS:
2120-
if (IS_USER_CMDIDX(ea.cmdidx))
2121-
{
2122-
ea.line1 = 1;
2123-
ea.line2 = ea.addr_type == ADDR_WINDOWS
2124-
? LAST_WIN_NR : LAST_TAB_NR;
2125-
}
2126-
else
2127-
{
2128-
/* there is no Vim command which uses '%' and
2129-
* ADDR_WINDOWS or ADDR_TABS */
2130-
errormsg = (char_u *)_(e_invrange);
2131-
goto doend;
2132-
}
2133-
break;
2134-
case ADDR_TABS_RELATIVE:
2135-
errormsg = (char_u *)_(e_invrange);
2136-
goto doend;
2137-
break;
2138-
case ADDR_ARGUMENTS:
2139-
if (ARGCOUNT == 0)
2140-
ea.line1 = ea.line2 = 0;
2141-
else
2142-
{
2143-
ea.line1 = 1;
2144-
ea.line2 = ARGCOUNT;
2145-
}
2146-
break;
2147-
#ifdef FEAT_QUICKFIX
2148-
case ADDR_QUICKFIX:
2149-
ea.line1 = 1;
2150-
ea.line2 = qf_get_size(&ea);
2151-
if (ea.line2 == 0)
2152-
ea.line2 = 1;
2153-
break;
2154-
#endif
2155-
}
2156-
++ea.addr_count;
2157-
}
2158-
/* '*' - visual area */
2159-
else if (*ea.cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL)
2160-
{
2161-
pos_T *fp;
2162-
2163-
if (ea.addr_type != ADDR_LINES)
2164-
{
2165-
errormsg = (char_u *)_(e_invrange);
2166-
goto doend;
2167-
}
2168-
2169-
++ea.cmd;
2170-
if (!ea.skip)
2171-
{
2172-
fp = getmark('<', FALSE);
2173-
if (check_mark(fp) == FAIL)
2174-
goto doend;
2175-
ea.line1 = fp->lnum;
2176-
fp = getmark('>', FALSE);
2177-
if (check_mark(fp) == FAIL)
2178-
goto doend;
2179-
ea.line2 = fp->lnum;
2180-
++ea.addr_count;
2181-
}
2182-
}
2183-
}
2184-
else
2185-
ea.line2 = lnum;
2186-
ea.addr_count++;
2187-
2188-
if (*ea.cmd == ';')
2189-
{
2190-
if (!ea.skip)
2191-
{
2192-
curwin->w_cursor.lnum = ea.line2;
2193-
/* don't leave the cursor on an illegal line or column */
2194-
check_cursor();
2195-
}
2196-
}
2197-
else if (*ea.cmd != ',')
2198-
break;
2199-
++ea.cmd;
2200-
}
2201-
2202-
/* One address given: set start and end lines */
2203-
if (ea.addr_count == 1)
2204-
{
2205-
ea.line1 = ea.line2;
2206-
/* ... but only implicit: really no address given */
2207-
if (lnum == MAXLNUM)
2208-
ea.addr_count = 0;
2209-
}
2048+
if (parse_cmd_address(&ea, &errormsg) == FAIL)
2049+
goto doend;
22102050

22112051
/*
22122052
* 5. Parse the command.
@@ -2988,6 +2828,179 @@ do_one_cmd(
29882828
#pragma optimize( "", on )
29892829
#endif
29902830

2831+
/*
2832+
* Parse the address range, if any, in "eap".
2833+
* Return FAIL and set "errormsg" or return OK.
2834+
*/
2835+
int
2836+
parse_cmd_address(exarg_T *eap, char_u **errormsg)
2837+
{
2838+
int address_count = 1;
2839+
linenr_T lnum;
2840+
2841+
// Repeat for all ',' or ';' separated addresses.
2842+
for (;;)
2843+
{
2844+
eap->line1 = eap->line2;
2845+
switch (eap->addr_type)
2846+
{
2847+
case ADDR_LINES:
2848+
// default is current line number
2849+
eap->line2 = curwin->w_cursor.lnum;
2850+
break;
2851+
case ADDR_WINDOWS:
2852+
eap->line2 = CURRENT_WIN_NR;
2853+
break;
2854+
case ADDR_ARGUMENTS:
2855+
eap->line2 = curwin->w_arg_idx + 1;
2856+
if (eap->line2 > ARGCOUNT)
2857+
eap->line2 = ARGCOUNT;
2858+
break;
2859+
case ADDR_LOADED_BUFFERS:
2860+
case ADDR_BUFFERS:
2861+
eap->line2 = curbuf->b_fnum;
2862+
break;
2863+
case ADDR_TABS:
2864+
eap->line2 = CURRENT_TAB_NR;
2865+
break;
2866+
case ADDR_TABS_RELATIVE:
2867+
eap->line2 = 1;
2868+
break;
2869+
#ifdef FEAT_QUICKFIX
2870+
case ADDR_QUICKFIX:
2871+
eap->line2 = qf_get_cur_valid_idx(eap);
2872+
break;
2873+
#endif
2874+
}
2875+
eap->cmd = skipwhite(eap->cmd);
2876+
lnum = get_address(eap, &eap->cmd, eap->addr_type, eap->skip,
2877+
eap->addr_count == 0, address_count++);
2878+
if (eap->cmd == NULL) // error detected
2879+
return FAIL;
2880+
if (lnum == MAXLNUM)
2881+
{
2882+
if (*eap->cmd == '%') // '%' - all lines
2883+
{
2884+
++eap->cmd;
2885+
switch (eap->addr_type)
2886+
{
2887+
case ADDR_LINES:
2888+
eap->line1 = 1;
2889+
eap->line2 = curbuf->b_ml.ml_line_count;
2890+
break;
2891+
case ADDR_LOADED_BUFFERS:
2892+
{
2893+
buf_T *buf = firstbuf;
2894+
2895+
while (buf->b_next != NULL
2896+
&& buf->b_ml.ml_mfp == NULL)
2897+
buf = buf->b_next;
2898+
eap->line1 = buf->b_fnum;
2899+
buf = lastbuf;
2900+
while (buf->b_prev != NULL
2901+
&& buf->b_ml.ml_mfp == NULL)
2902+
buf = buf->b_prev;
2903+
eap->line2 = buf->b_fnum;
2904+
break;
2905+
}
2906+
case ADDR_BUFFERS:
2907+
eap->line1 = firstbuf->b_fnum;
2908+
eap->line2 = lastbuf->b_fnum;
2909+
break;
2910+
case ADDR_WINDOWS:
2911+
case ADDR_TABS:
2912+
if (IS_USER_CMDIDX(eap->cmdidx))
2913+
{
2914+
eap->line1 = 1;
2915+
eap->line2 = eap->addr_type == ADDR_WINDOWS
2916+
? LAST_WIN_NR : LAST_TAB_NR;
2917+
}
2918+
else
2919+
{
2920+
// there is no Vim command which uses '%' and
2921+
// ADDR_WINDOWS or ADDR_TABS
2922+
*errormsg = (char_u *)_(e_invrange);
2923+
return FAIL;
2924+
}
2925+
break;
2926+
case ADDR_TABS_RELATIVE:
2927+
*errormsg = (char_u *)_(e_invrange);
2928+
return FAIL;
2929+
case ADDR_ARGUMENTS:
2930+
if (ARGCOUNT == 0)
2931+
eap->line1 = eap->line2 = 0;
2932+
else
2933+
{
2934+
eap->line1 = 1;
2935+
eap->line2 = ARGCOUNT;
2936+
}
2937+
break;
2938+
#ifdef FEAT_QUICKFIX
2939+
case ADDR_QUICKFIX:
2940+
eap->line1 = 1;
2941+
eap->line2 = qf_get_size(eap);
2942+
if (eap->line2 == 0)
2943+
eap->line2 = 1;
2944+
break;
2945+
#endif
2946+
}
2947+
++eap->addr_count;
2948+
}
2949+
else if (*eap->cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL)
2950+
{
2951+
pos_T *fp;
2952+
2953+
// '*' - visual area
2954+
if (eap->addr_type != ADDR_LINES)
2955+
{
2956+
*errormsg = (char_u *)_(e_invrange);
2957+
return FAIL;
2958+
}
2959+
2960+
++eap->cmd;
2961+
if (!eap->skip)
2962+
{
2963+
fp = getmark('<', FALSE);
2964+
if (check_mark(fp) == FAIL)
2965+
return FAIL;
2966+
eap->line1 = fp->lnum;
2967+
fp = getmark('>', FALSE);
2968+
if (check_mark(fp) == FAIL)
2969+
return FAIL;
2970+
eap->line2 = fp->lnum;
2971+
++eap->addr_count;
2972+
}
2973+
}
2974+
}
2975+
else
2976+
eap->line2 = lnum;
2977+
eap->addr_count++;
2978+
2979+
if (*eap->cmd == ';')
2980+
{
2981+
if (!eap->skip)
2982+
{
2983+
curwin->w_cursor.lnum = eap->line2;
2984+
// don't leave the cursor on an illegal line or column
2985+
check_cursor();
2986+
}
2987+
}
2988+
else if (*eap->cmd != ',')
2989+
break;
2990+
++eap->cmd;
2991+
}
2992+
2993+
// One address given: set start and end lines.
2994+
if (eap->addr_count == 1)
2995+
{
2996+
eap->line1 = eap->line2;
2997+
// ... but only implicit: really no address given
2998+
if (lnum == MAXLNUM)
2999+
eap->addr_count = 0;
3000+
}
3001+
return OK;
3002+
}
3003+
29913004
/*
29923005
* Check for an Ex command with optional tail.
29933006
* If there is a match advance "pp" to the argument and return TRUE.
@@ -4292,7 +4305,7 @@ set_one_cmd_context(
42924305
}
42934306

42944307
/*
4295-
* skip a range specifier of the form: addr [,addr] [;addr] ..
4308+
* Skip a range specifier of the form: addr [,addr] [;addr] ..
42964309
*
42974310
* Backslashed delimiters after / or ? will be skipped, and commands will
42984311
* not be expanded between /'s and ?'s or after "'".

src/proto/ex_docmd.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ int do_cmdline_cmd(char_u *cmd);
44
int do_cmdline(char_u *cmdline, char_u *(*fgetline)(int, void *, int), void *cookie, int flags);
55
int getline_equal(char_u *(*fgetline)(int, void *, int), void *cookie, char_u *(*func)(int, void *, int));
66
void *getline_cookie(char_u *(*fgetline)(int, void *, int), void *cookie);
7+
int parse_cmd_address(exarg_T *eap, char_u **errormsg);
78
int checkforcmd(char_u **pp, char *cmd, int len);
89
int modifier_len(char_u *cmd);
910
int cmd_exists(char_u *name);

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,8 @@ static char *(features[]) =
794794

795795
static int included_patches[] =
796796
{ /* Add new patch number below this line */
797+
/**/
798+
266,
797799
/**/
798800
265,
799801
/**/

0 commit comments

Comments
 (0)