@@ -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