Skip to content

Commit f66ad53

Browse files
committed
Merge remote-tracking branch 'vim/master'
2 parents 027327a + ee8415b commit f66ad53

4 files changed

Lines changed: 524 additions & 445 deletions

File tree

src/ex_docmd.c

Lines changed: 176 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -1726,7 +1726,6 @@ do_one_cmd(
17261726
cmdmod_T save_cmdmod;
17271727
int ni; /* set when Not Implemented */
17281728
char_u *cmd;
1729-
int address_count = 1;
17301729

17311730
vim_memset(&ea, 0, sizeof(ea));
17321731
ea.line1 = 1;
@@ -2052,168 +2051,9 @@ do_one_cmd(
20522051
get_wincmd_addr_type(skipwhite(p), &ea);
20532052
}
20542053

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

22182058
/*
22192059
* 5. Parse the command.
@@ -2995,6 +2835,179 @@ do_one_cmd(
29952835
#pragma optimize( "", on )
29962836
#endif
29972837

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

43104323
/*
4311-
* skip a range specifier of the form: addr [,addr] [;addr] ..
4324+
* Skip a range specifier of the form: addr [,addr] [;addr] ..
43124325
*
43134326
* Backslashed delimiters after / or ? will be skipped, and commands will
43144327
* not be expanded between /'s and ?'s or after "'".

0 commit comments

Comments
 (0)