xref: /vim-8.2.3635/src/ex_docmd.c (revision ea2d8d25)
1 /* vi:set ts=8 sts=4 sw=4 noet:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 
10 /*
11  * ex_docmd.c: functions for executing an Ex command line.
12  */
13 
14 #include "vim.h"
15 
16 static int	quitmore = 0;
17 static int	ex_pressedreturn = FALSE;
18 #ifndef FEAT_PRINTER
19 # define ex_hardcopy	ex_ni
20 #endif
21 
22 #ifdef FEAT_EVAL
23 static char_u	*do_one_cmd(char_u **, int, cstack_T *, char_u *(*fgetline)(int, void *, int, int), void *cookie);
24 #else
25 static char_u	*do_one_cmd(char_u **, int, char_u *(*fgetline)(int, void *, int, int), void *cookie);
26 static int	if_level = 0;		// depth in :if
27 #endif
28 static void	append_command(char_u *cmd);
29 
30 #ifndef FEAT_MENU
31 # define ex_emenu		ex_ni
32 # define ex_menu		ex_ni
33 # define ex_menutranslate	ex_ni
34 #endif
35 static void	ex_autocmd(exarg_T *eap);
36 static void	ex_doautocmd(exarg_T *eap);
37 static void	ex_bunload(exarg_T *eap);
38 static void	ex_buffer(exarg_T *eap);
39 static void	ex_bmodified(exarg_T *eap);
40 static void	ex_bnext(exarg_T *eap);
41 static void	ex_bprevious(exarg_T *eap);
42 static void	ex_brewind(exarg_T *eap);
43 static void	ex_blast(exarg_T *eap);
44 static char_u	*getargcmd(char_u **);
45 static int	getargopt(exarg_T *eap);
46 #ifndef FEAT_QUICKFIX
47 # define ex_make		ex_ni
48 # define ex_cbuffer		ex_ni
49 # define ex_cc			ex_ni
50 # define ex_cnext		ex_ni
51 # define ex_cbelow		ex_ni
52 # define ex_cfile		ex_ni
53 # define qf_list		ex_ni
54 # define qf_age			ex_ni
55 # define qf_history		ex_ni
56 # define ex_helpgrep		ex_ni
57 # define ex_vimgrep		ex_ni
58 #endif
59 #if !defined(FEAT_QUICKFIX)
60 # define ex_cclose		ex_ni
61 # define ex_copen		ex_ni
62 # define ex_cwindow		ex_ni
63 # define ex_cbottom		ex_ni
64 #endif
65 #if !defined(FEAT_QUICKFIX) || !defined(FEAT_EVAL)
66 # define ex_cexpr		ex_ni
67 #endif
68 
69 static linenr_T get_address(exarg_T *, char_u **, cmd_addr_T addr_type, int skip, int silent, int to_other_file, int address_count);
70 static void	get_flags(exarg_T *eap);
71 #if !defined(FEAT_PERL) \
72 	|| !defined(FEAT_PYTHON) || !defined(FEAT_PYTHON3) \
73 	|| !defined(FEAT_TCL) \
74 	|| !defined(FEAT_RUBY) \
75 	|| !defined(FEAT_LUA) \
76 	|| !defined(FEAT_MZSCHEME)
77 # define HAVE_EX_SCRIPT_NI
78 static void	ex_script_ni(exarg_T *eap);
79 #endif
80 static char	*invalid_range(exarg_T *eap);
81 static void	correct_range(exarg_T *eap);
82 #ifdef FEAT_QUICKFIX
83 static char_u	*replace_makeprg(exarg_T *eap, char_u *p, char_u **cmdlinep);
84 #endif
85 static char_u	*repl_cmdline(exarg_T *eap, char_u *src, int srclen, char_u *repl, char_u **cmdlinep);
86 static void	ex_highlight(exarg_T *eap);
87 static void	ex_colorscheme(exarg_T *eap);
88 static void	ex_cquit(exarg_T *eap);
89 static void	ex_quit_all(exarg_T *eap);
90 static void	ex_close(exarg_T *eap);
91 static void	ex_win_close(int forceit, win_T *win, tabpage_T *tp);
92 static void	ex_only(exarg_T *eap);
93 static void	ex_resize(exarg_T *eap);
94 static void	ex_stag(exarg_T *eap);
95 static void	ex_tabclose(exarg_T *eap);
96 static void	ex_tabonly(exarg_T *eap);
97 static void	ex_tabnext(exarg_T *eap);
98 static void	ex_tabmove(exarg_T *eap);
99 static void	ex_tabs(exarg_T *eap);
100 #if defined(FEAT_QUICKFIX)
101 static void	ex_pclose(exarg_T *eap);
102 static void	ex_ptag(exarg_T *eap);
103 static void	ex_pedit(exarg_T *eap);
104 #else
105 # define ex_pclose		ex_ni
106 # define ex_ptag		ex_ni
107 # define ex_pedit		ex_ni
108 #endif
109 static void	ex_hide(exarg_T *eap);
110 static void	ex_stop(exarg_T *eap);
111 static void	ex_exit(exarg_T *eap);
112 static void	ex_print(exarg_T *eap);
113 #ifdef FEAT_BYTEOFF
114 static void	ex_goto(exarg_T *eap);
115 #else
116 # define ex_goto		ex_ni
117 #endif
118 static void	ex_shell(exarg_T *eap);
119 static void	ex_preserve(exarg_T *eap);
120 static void	ex_recover(exarg_T *eap);
121 static void	ex_mode(exarg_T *eap);
122 static void	ex_wrongmodifier(exarg_T *eap);
123 static void	ex_find(exarg_T *eap);
124 static void	ex_open(exarg_T *eap);
125 static void	ex_edit(exarg_T *eap);
126 #ifndef FEAT_GUI
127 # define ex_gui			ex_nogui
128 static void	ex_nogui(exarg_T *eap);
129 #endif
130 #if defined(FEAT_GUI_MSWIN) && defined(FEAT_MENU) && defined(FEAT_TEAROFF)
131 static void	ex_tearoff(exarg_T *eap);
132 #else
133 # define ex_tearoff		ex_ni
134 #endif
135 #if (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK) \
136 	|| defined(FEAT_TERM_POPUP_MENU)) && defined(FEAT_MENU)
137 static void	ex_popup(exarg_T *eap);
138 #else
139 # define ex_popup		ex_ni
140 #endif
141 #ifndef FEAT_GUI_MSWIN
142 # define ex_simalt		ex_ni
143 #endif
144 #if !defined(FEAT_GUI_MSWIN) && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_MOTIF)
145 # define gui_mch_find_dialog	ex_ni
146 # define gui_mch_replace_dialog ex_ni
147 #endif
148 #if !defined(FEAT_GUI_GTK)
149 # define ex_helpfind		ex_ni
150 #endif
151 #ifndef FEAT_CSCOPE
152 # define ex_cscope		ex_ni
153 # define ex_scscope		ex_ni
154 # define ex_cstag		ex_ni
155 #endif
156 #ifndef FEAT_SYN_HL
157 # define ex_syntax		ex_ni
158 # define ex_ownsyntax		ex_ni
159 #endif
160 #if !defined(FEAT_SYN_HL) || !defined(FEAT_PROFILE)
161 # define ex_syntime		ex_ni
162 #endif
163 #ifndef FEAT_SPELL
164 # define ex_spell		ex_ni
165 # define ex_mkspell		ex_ni
166 # define ex_spelldump		ex_ni
167 # define ex_spellinfo		ex_ni
168 # define ex_spellrepall		ex_ni
169 #endif
170 #ifndef FEAT_PERSISTENT_UNDO
171 # define ex_rundo		ex_ni
172 # define ex_wundo		ex_ni
173 #endif
174 #ifndef FEAT_LUA
175 # define ex_lua			ex_script_ni
176 # define ex_luado		ex_ni
177 # define ex_luafile		ex_ni
178 #endif
179 #ifndef FEAT_MZSCHEME
180 # define ex_mzscheme		ex_script_ni
181 # define ex_mzfile		ex_ni
182 #endif
183 #ifndef FEAT_PERL
184 # define ex_perl		ex_script_ni
185 # define ex_perldo		ex_ni
186 #endif
187 #ifndef FEAT_PYTHON
188 # define ex_python		ex_script_ni
189 # define ex_pydo		ex_ni
190 # define ex_pyfile		ex_ni
191 #endif
192 #ifndef FEAT_PYTHON3
193 # define ex_py3			ex_script_ni
194 # define ex_py3do		ex_ni
195 # define ex_py3file		ex_ni
196 #endif
197 #if !defined(FEAT_PYTHON) && !defined(FEAT_PYTHON3)
198 # define ex_pyx			ex_script_ni
199 # define ex_pyxdo		ex_ni
200 # define ex_pyxfile		ex_ni
201 #endif
202 #ifndef FEAT_TCL
203 # define ex_tcl			ex_script_ni
204 # define ex_tcldo		ex_ni
205 # define ex_tclfile		ex_ni
206 #endif
207 #ifndef FEAT_RUBY
208 # define ex_ruby		ex_script_ni
209 # define ex_rubydo		ex_ni
210 # define ex_rubyfile		ex_ni
211 #endif
212 #ifndef FEAT_KEYMAP
213 # define ex_loadkeymap		ex_ni
214 #endif
215 static void	ex_swapname(exarg_T *eap);
216 static void	ex_syncbind(exarg_T *eap);
217 static void	ex_read(exarg_T *eap);
218 static void	ex_pwd(exarg_T *eap);
219 static void	ex_equal(exarg_T *eap);
220 static void	ex_sleep(exarg_T *eap);
221 static void	ex_winsize(exarg_T *eap);
222 static void	ex_wincmd(exarg_T *eap);
223 #if defined(FEAT_GUI) || defined(UNIX) || defined(VMS) || defined(MSWIN)
224 static void	ex_winpos(exarg_T *eap);
225 #else
226 # define ex_winpos	    ex_ni
227 #endif
228 static void	ex_operators(exarg_T *eap);
229 static void	ex_put(exarg_T *eap);
230 static void	ex_copymove(exarg_T *eap);
231 static void	ex_submagic(exarg_T *eap);
232 static void	ex_join(exarg_T *eap);
233 static void	ex_at(exarg_T *eap);
234 static void	ex_bang(exarg_T *eap);
235 static void	ex_undo(exarg_T *eap);
236 #ifdef FEAT_PERSISTENT_UNDO
237 static void	ex_wundo(exarg_T *eap);
238 static void	ex_rundo(exarg_T *eap);
239 #endif
240 static void	ex_redo(exarg_T *eap);
241 static void	ex_later(exarg_T *eap);
242 static void	ex_redir(exarg_T *eap);
243 static void	ex_redrawstatus(exarg_T *eap);
244 static void	ex_redrawtabline(exarg_T *eap);
245 static void	close_redir(void);
246 static void	ex_mark(exarg_T *eap);
247 static void	ex_startinsert(exarg_T *eap);
248 static void	ex_stopinsert(exarg_T *eap);
249 #ifdef FEAT_FIND_ID
250 static void	ex_checkpath(exarg_T *eap);
251 static void	ex_findpat(exarg_T *eap);
252 #else
253 # define ex_findpat		ex_ni
254 # define ex_checkpath		ex_ni
255 #endif
256 #if defined(FEAT_FIND_ID) && defined(FEAT_QUICKFIX)
257 static void	ex_psearch(exarg_T *eap);
258 #else
259 # define ex_psearch		ex_ni
260 #endif
261 static void	ex_tag(exarg_T *eap);
262 static void	ex_tag_cmd(exarg_T *eap, char_u *name);
263 #ifndef FEAT_EVAL
264 # define ex_break		ex_ni
265 # define ex_breakadd		ex_ni
266 # define ex_breakdel		ex_ni
267 # define ex_breaklist		ex_ni
268 # define ex_call		ex_ni
269 # define ex_catch		ex_ni
270 # define ex_compiler		ex_ni
271 # define ex_continue		ex_ni
272 # define ex_debug		ex_ni
273 # define ex_debuggreedy		ex_ni
274 # define ex_def			ex_ni
275 # define ex_defcompile		ex_ni
276 # define ex_delfunction		ex_ni
277 # define ex_disassemble		ex_ni
278 # define ex_echo		ex_ni
279 # define ex_echohl		ex_ni
280 # define ex_else		ex_ni
281 # define ex_endfunction		ex_ni
282 # define ex_endif		ex_ni
283 # define ex_endtry		ex_ni
284 # define ex_endwhile		ex_ni
285 # define ex_eval		ex_ni
286 # define ex_execute		ex_ni
287 # define ex_finally		ex_ni
288 # define ex_finish		ex_ni
289 # define ex_function		ex_ni
290 # define ex_if			ex_ni
291 # define ex_let			ex_ni
292 # define ex_lockvar		ex_ni
293 # define ex_oldfiles		ex_ni
294 # define ex_options		ex_ni
295 # define ex_packadd		ex_ni
296 # define ex_packloadall		ex_ni
297 # define ex_return		ex_ni
298 # define ex_scriptnames		ex_ni
299 # define ex_throw		ex_ni
300 # define ex_try			ex_ni
301 # define ex_unlet		ex_ni
302 # define ex_unlockvar		ex_ni
303 # define ex_vim9script		ex_ni
304 # define ex_while		ex_ni
305 # define ex_import		ex_ni
306 # define ex_export		ex_ni
307 #endif
308 #ifndef FEAT_SESSION
309 # define ex_loadview		ex_ni
310 #endif
311 #ifndef FEAT_VIMINFO
312 # define ex_viminfo		ex_ni
313 #endif
314 static void	ex_behave(exarg_T *eap);
315 static void	ex_filetype(exarg_T *eap);
316 static void	ex_setfiletype(exarg_T *eap);
317 #ifndef FEAT_DIFF
318 # define ex_diffoff		ex_ni
319 # define ex_diffpatch		ex_ni
320 # define ex_diffgetput		ex_ni
321 # define ex_diffsplit		ex_ni
322 # define ex_diffthis		ex_ni
323 # define ex_diffupdate		ex_ni
324 #endif
325 static void	ex_digraphs(exarg_T *eap);
326 #ifdef FEAT_SEARCH_EXTRA
327 static void	ex_nohlsearch(exarg_T *eap);
328 #else
329 # define ex_nohlsearch		ex_ni
330 # define ex_match		ex_ni
331 #endif
332 #ifdef FEAT_CRYPT
333 static void	ex_X(exarg_T *eap);
334 #else
335 # define ex_X			ex_ni
336 #endif
337 #ifdef FEAT_FOLDING
338 static void	ex_fold(exarg_T *eap);
339 static void	ex_foldopen(exarg_T *eap);
340 static void	ex_folddo(exarg_T *eap);
341 #else
342 # define ex_fold		ex_ni
343 # define ex_foldopen		ex_ni
344 # define ex_folddo		ex_ni
345 #endif
346 #if !(defined(HAVE_LOCALE_H) || defined(X_LOCALE))
347 # define ex_language		ex_ni
348 #endif
349 #ifndef FEAT_SIGNS
350 # define ex_sign		ex_ni
351 #endif
352 #ifndef FEAT_NETBEANS_INTG
353 # define ex_nbclose		ex_ni
354 # define ex_nbkey		ex_ni
355 # define ex_nbstart		ex_ni
356 #endif
357 
358 #ifndef FEAT_JUMPLIST
359 # define ex_jumps		ex_ni
360 # define ex_clearjumps		ex_ni
361 # define ex_changes		ex_ni
362 #endif
363 
364 #ifndef FEAT_PROFILE
365 # define ex_profile		ex_ni
366 #endif
367 #ifndef FEAT_TERMINAL
368 # define ex_terminal		ex_ni
369 #endif
370 #if !defined(FEAT_X11) || !defined(FEAT_XCLIPBOARD)
371 # define ex_xrestore		ex_ni
372 #endif
373 #if !defined(FEAT_PROP_POPUP)
374 # define ex_popupclear		ex_ni
375 #endif
376 
377 /*
378  * Declare cmdnames[].
379  */
380 #define DO_DECLARE_EXCMD
381 #include "ex_cmds.h"
382 #include "ex_cmdidxs.h"
383 
384 static char_u dollar_command[2] = {'$', 0};
385 
386 
387 #ifdef FEAT_EVAL
388 // Struct for storing a line inside a while/for loop
389 typedef struct
390 {
391     char_u	*line;		// command line
392     linenr_T	lnum;		// sourcing_lnum of the line
393 } wcmd_T;
394 
395 /*
396  * Structure used to store info for line position in a while or for loop.
397  * This is required, because do_one_cmd() may invoke ex_function(), which
398  * reads more lines that may come from the while/for loop.
399  */
400 struct loop_cookie
401 {
402     garray_T	*lines_gap;		// growarray with line info
403     int		current_line;		// last read line from growarray
404     int		repeating;		// TRUE when looping a second time
405     // When "repeating" is FALSE use "getline" and "cookie" to get lines
406     char_u	*(*getline)(int, void *, int, int);
407     void	*cookie;
408 };
409 
410 static char_u	*get_loop_line(int c, void *cookie, int indent, int do_concat);
411 static int	store_loop_line(garray_T *gap, char_u *line);
412 static void	free_cmdlines(garray_T *gap);
413 
414 // Struct to save a few things while debugging.  Used in do_cmdline() only.
415 struct dbg_stuff
416 {
417     int		trylevel;
418     int		force_abort;
419     except_T	*caught_stack;
420     char_u	*vv_exception;
421     char_u	*vv_throwpoint;
422     int		did_emsg;
423     int		got_int;
424     int		did_throw;
425     int		need_rethrow;
426     int		check_cstack;
427     except_T	*current_exception;
428 };
429 
430     static void
431 save_dbg_stuff(struct dbg_stuff *dsp)
432 {
433     dsp->trylevel	= trylevel;		trylevel = 0;
434     dsp->force_abort	= force_abort;		force_abort = FALSE;
435     dsp->caught_stack	= caught_stack;		caught_stack = NULL;
436     dsp->vv_exception	= v_exception(NULL);
437     dsp->vv_throwpoint	= v_throwpoint(NULL);
438 
439     // Necessary for debugging an inactive ":catch", ":finally", ":endtry"
440     dsp->did_emsg	= did_emsg;		did_emsg     = FALSE;
441     dsp->got_int	= got_int;		got_int	     = FALSE;
442     dsp->did_throw	= did_throw;		did_throw    = FALSE;
443     dsp->need_rethrow	= need_rethrow;		need_rethrow = FALSE;
444     dsp->check_cstack	= check_cstack;		check_cstack = FALSE;
445     dsp->current_exception = current_exception;	current_exception = NULL;
446 }
447 
448     static void
449 restore_dbg_stuff(struct dbg_stuff *dsp)
450 {
451     suppress_errthrow = FALSE;
452     trylevel = dsp->trylevel;
453     force_abort = dsp->force_abort;
454     caught_stack = dsp->caught_stack;
455     (void)v_exception(dsp->vv_exception);
456     (void)v_throwpoint(dsp->vv_throwpoint);
457     did_emsg = dsp->did_emsg;
458     got_int = dsp->got_int;
459     did_throw = dsp->did_throw;
460     need_rethrow = dsp->need_rethrow;
461     check_cstack = dsp->check_cstack;
462     current_exception = dsp->current_exception;
463 }
464 #endif
465 
466 /*
467  * do_exmode(): Repeatedly get commands for the "Ex" mode, until the ":vi"
468  * command is given.
469  */
470     void
471 do_exmode(
472     int		improved)	    // TRUE for "improved Ex" mode
473 {
474     int		save_msg_scroll;
475     int		prev_msg_row;
476     linenr_T	prev_line;
477     varnumber_T	changedtick;
478 
479     if (improved)
480 	exmode_active = EXMODE_VIM;
481     else
482 	exmode_active = EXMODE_NORMAL;
483     State = NORMAL;
484 
485     // When using ":global /pat/ visual" and then "Q" we return to continue
486     // the :global command.
487     if (global_busy)
488 	return;
489 
490     save_msg_scroll = msg_scroll;
491     ++RedrawingDisabled;	    // don't redisplay the window
492     ++no_wait_return;		    // don't wait for return
493 #ifdef FEAT_GUI
494     // Ignore scrollbar and mouse events in Ex mode
495     ++hold_gui_events;
496 #endif
497 
498     msg(_("Entering Ex mode.  Type \"visual\" to go to Normal mode."));
499     while (exmode_active)
500     {
501 	// Check for a ":normal" command and no more characters left.
502 	if (ex_normal_busy > 0 && typebuf.tb_len == 0)
503 	{
504 	    exmode_active = FALSE;
505 	    break;
506 	}
507 	msg_scroll = TRUE;
508 	need_wait_return = FALSE;
509 	ex_pressedreturn = FALSE;
510 	ex_no_reprint = FALSE;
511 	changedtick = CHANGEDTICK(curbuf);
512 	prev_msg_row = msg_row;
513 	prev_line = curwin->w_cursor.lnum;
514 	if (improved)
515 	{
516 	    cmdline_row = msg_row;
517 	    do_cmdline(NULL, getexline, NULL, 0);
518 	}
519 	else
520 	    do_cmdline(NULL, getexmodeline, NULL, DOCMD_NOWAIT);
521 	lines_left = Rows - 1;
522 
523 	if ((prev_line != curwin->w_cursor.lnum
524 		   || changedtick != CHANGEDTICK(curbuf)) && !ex_no_reprint)
525 	{
526 	    if (curbuf->b_ml.ml_flags & ML_EMPTY)
527 		emsg(_(e_emptybuf));
528 	    else
529 	    {
530 		if (ex_pressedreturn)
531 		{
532 		    // go up one line, to overwrite the ":<CR>" line, so the
533 		    // output doesn't contain empty lines.
534 		    msg_row = prev_msg_row;
535 		    if (prev_msg_row == Rows - 1)
536 			msg_row--;
537 		}
538 		msg_col = 0;
539 		print_line_no_prefix(curwin->w_cursor.lnum, FALSE, FALSE);
540 		msg_clr_eos();
541 	    }
542 	}
543 	else if (ex_pressedreturn && !ex_no_reprint)	// must be at EOF
544 	{
545 	    if (curbuf->b_ml.ml_flags & ML_EMPTY)
546 		emsg(_(e_emptybuf));
547 	    else
548 		emsg(_("E501: At end-of-file"));
549 	}
550     }
551 
552 #ifdef FEAT_GUI
553     --hold_gui_events;
554 #endif
555     --RedrawingDisabled;
556     --no_wait_return;
557     update_screen(CLEAR);
558     need_wait_return = FALSE;
559     msg_scroll = save_msg_scroll;
560 }
561 
562 /*
563  * Print the executed command for when 'verbose' is set.
564  * When "lnum" is 0 only print the command.
565  */
566     static void
567 msg_verbose_cmd(linenr_T lnum, char_u *cmd)
568 {
569     ++no_wait_return;
570     verbose_enter_scroll();
571 
572     if (lnum == 0)
573 	smsg(_("Executing: %s"), cmd);
574     else
575 	smsg(_("line %ld: %s"), (long)lnum, cmd);
576     if (msg_silent == 0)
577 	msg_puts("\n");   // don't overwrite this
578 
579     verbose_leave_scroll();
580     --no_wait_return;
581 }
582 
583 /*
584  * Execute a simple command line.  Used for translated commands like "*".
585  */
586     int
587 do_cmdline_cmd(char_u *cmd)
588 {
589     return do_cmdline(cmd, NULL, NULL,
590 				   DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
591 }
592 
593 /*
594  * do_cmdline(): execute one Ex command line
595  *
596  * 1. Execute "cmdline" when it is not NULL.
597  *    If "cmdline" is NULL, or more lines are needed, fgetline() is used.
598  * 2. Split up in parts separated with '|'.
599  *
600  * This function can be called recursively!
601  *
602  * flags:
603  * DOCMD_VERBOSE  - The command will be included in the error message.
604  * DOCMD_NOWAIT   - Don't call wait_return() and friends.
605  * DOCMD_REPEAT   - Repeat execution until fgetline() returns NULL.
606  * DOCMD_KEYTYPED - Don't reset KeyTyped.
607  * DOCMD_EXCRESET - Reset the exception environment (used for debugging).
608  * DOCMD_KEEPLINE - Store first typed line (for repeating with ".").
609  *
610  * return FAIL if cmdline could not be executed, OK otherwise
611  */
612     int
613 do_cmdline(
614     char_u	*cmdline,
615     char_u	*(*fgetline)(int, void *, int, int),
616     void	*cookie,		// argument for fgetline()
617     int		flags)
618 {
619     char_u	*next_cmdline;		// next cmd to execute
620     char_u	*cmdline_copy = NULL;	// copy of cmd line
621     int		used_getline = FALSE;	// used "fgetline" to obtain command
622     static int	recursive = 0;		// recursive depth
623     int		msg_didout_before_start = 0;
624     int		count = 0;		// line number count
625     int		did_inc = FALSE;	// incremented RedrawingDisabled
626     int		retval = OK;
627 #ifdef FEAT_EVAL
628     cstack_T	cstack;			// conditional stack
629     garray_T	lines_ga;		// keep lines for ":while"/":for"
630     int		current_line = 0;	// active line in lines_ga
631     int		current_line_before = 0;
632     char_u	*fname = NULL;		// function or script name
633     linenr_T	*breakpoint = NULL;	// ptr to breakpoint field in cookie
634     int		*dbg_tick = NULL;	// ptr to dbg_tick field in cookie
635     struct dbg_stuff debug_saved;	// saved things for debug mode
636     int		initial_trylevel;
637     msglist_T	**saved_msg_list = NULL;
638     msglist_T	*private_msg_list;
639 
640     // "fgetline" and "cookie" passed to do_one_cmd()
641     char_u	*(*cmd_getline)(int, void *, int, int);
642     void	*cmd_cookie;
643     struct loop_cookie cmd_loop_cookie;
644     void	*real_cookie;
645     int		getline_is_func;
646 #else
647 # define cmd_getline fgetline
648 # define cmd_cookie cookie
649 #endif
650     static int	call_depth = 0;		// recursiveness
651 #ifdef FEAT_EVAL
652     ESTACK_CHECK_DECLARATION
653 
654     // For every pair of do_cmdline()/do_one_cmd() calls, use an extra memory
655     // location for storing error messages to be converted to an exception.
656     // This ensures that the do_errthrow() call in do_one_cmd() does not
657     // combine the messages stored by an earlier invocation of do_one_cmd()
658     // with the command name of the later one.  This would happen when
659     // BufWritePost autocommands are executed after a write error.
660     saved_msg_list = msg_list;
661     msg_list = &private_msg_list;
662     private_msg_list = NULL;
663 #endif
664 
665     // It's possible to create an endless loop with ":execute", catch that
666     // here.  The value of 200 allows nested function calls, ":source", etc.
667     // Allow 200 or 'maxfuncdepth', whatever is larger.
668     if (call_depth >= 200
669 #ifdef FEAT_EVAL
670 	    && call_depth >= p_mfd
671 #endif
672 	    )
673     {
674 	emsg(_("E169: Command too recursive"));
675 #ifdef FEAT_EVAL
676 	// When converting to an exception, we do not include the command name
677 	// since this is not an error of the specific command.
678 	do_errthrow((cstack_T *)NULL, (char_u *)NULL);
679 	msg_list = saved_msg_list;
680 #endif
681 	return FAIL;
682     }
683     ++call_depth;
684 
685 #ifdef FEAT_EVAL
686     cstack.cs_idx = -1;
687     cstack.cs_looplevel = 0;
688     cstack.cs_trylevel = 0;
689     cstack.cs_emsg_silent_list = NULL;
690     cstack.cs_lflags = 0;
691     ga_init2(&lines_ga, (int)sizeof(wcmd_T), 10);
692 
693     real_cookie = getline_cookie(fgetline, cookie);
694 
695     // Inside a function use a higher nesting level.
696     getline_is_func = getline_equal(fgetline, cookie, get_func_line);
697     if (getline_is_func && ex_nesting_level == func_level(real_cookie))
698 	++ex_nesting_level;
699 
700     // Get the function or script name and the address where the next breakpoint
701     // line and the debug tick for a function or script are stored.
702     if (getline_is_func)
703     {
704 	fname = func_name(real_cookie);
705 	breakpoint = func_breakpoint(real_cookie);
706 	dbg_tick = func_dbg_tick(real_cookie);
707     }
708     else if (getline_equal(fgetline, cookie, getsourceline))
709     {
710 	fname = SOURCING_NAME;
711 	breakpoint = source_breakpoint(real_cookie);
712 	dbg_tick = source_dbg_tick(real_cookie);
713     }
714 
715     /*
716      * Initialize "force_abort"  and "suppress_errthrow" at the top level.
717      */
718     if (!recursive)
719     {
720 	force_abort = FALSE;
721 	suppress_errthrow = FALSE;
722     }
723 
724     /*
725      * If requested, store and reset the global values controlling the
726      * exception handling (used when debugging).  Otherwise clear it to avoid
727      * a bogus compiler warning when the optimizer uses inline functions...
728      */
729     if (flags & DOCMD_EXCRESET)
730 	save_dbg_stuff(&debug_saved);
731     else
732 	CLEAR_FIELD(debug_saved);
733 
734     initial_trylevel = trylevel;
735 
736     /*
737      * "did_throw" will be set to TRUE when an exception is being thrown.
738      */
739     did_throw = FALSE;
740 #endif
741     /*
742      * "did_emsg" will be set to TRUE when emsg() is used, in which case we
743      * cancel the whole command line, and any if/endif or loop.
744      * If force_abort is set, we cancel everything.
745      */
746     did_emsg = FALSE;
747 
748     /*
749      * KeyTyped is only set when calling vgetc().  Reset it here when not
750      * calling vgetc() (sourced command lines).
751      */
752     if (!(flags & DOCMD_KEYTYPED)
753 			       && !getline_equal(fgetline, cookie, getexline))
754 	KeyTyped = FALSE;
755 
756     /*
757      * Continue executing command lines:
758      * - when inside an ":if", ":while" or ":for"
759      * - for multiple commands on one line, separated with '|'
760      * - when repeating until there are no more lines (for ":source")
761      */
762     next_cmdline = cmdline;
763     do
764     {
765 #ifdef FEAT_EVAL
766 	getline_is_func = getline_equal(fgetline, cookie, get_func_line);
767 #endif
768 
769 	// stop skipping cmds for an error msg after all endif/while/for
770 	if (next_cmdline == NULL
771 #ifdef FEAT_EVAL
772 		&& !force_abort
773 		&& cstack.cs_idx < 0
774 		&& !(getline_is_func && func_has_abort(real_cookie))
775 #endif
776 							)
777 	    did_emsg = FALSE;
778 
779 	/*
780 	 * 1. If repeating a line in a loop, get a line from lines_ga.
781 	 * 2. If no line given: Get an allocated line with fgetline().
782 	 * 3. If a line is given: Make a copy, so we can mess with it.
783 	 */
784 
785 #ifdef FEAT_EVAL
786 	// 1. If repeating, get a previous line from lines_ga.
787 	if (cstack.cs_looplevel > 0 && current_line < lines_ga.ga_len)
788 	{
789 	    // Each '|' separated command is stored separately in lines_ga, to
790 	    // be able to jump to it.  Don't use next_cmdline now.
791 	    VIM_CLEAR(cmdline_copy);
792 
793 	    // Check if a function has returned or, unless it has an unclosed
794 	    // try conditional, aborted.
795 	    if (getline_is_func)
796 	    {
797 # ifdef FEAT_PROFILE
798 		if (do_profiling == PROF_YES)
799 		    func_line_end(real_cookie);
800 # endif
801 		if (func_has_ended(real_cookie))
802 		{
803 		    retval = FAIL;
804 		    break;
805 		}
806 	    }
807 #ifdef FEAT_PROFILE
808 	    else if (do_profiling == PROF_YES
809 			    && getline_equal(fgetline, cookie, getsourceline))
810 		script_line_end();
811 #endif
812 
813 	    // Check if a sourced file hit a ":finish" command.
814 	    if (source_finished(fgetline, cookie))
815 	    {
816 		retval = FAIL;
817 		break;
818 	    }
819 
820 	    // If breakpoints have been added/deleted need to check for it.
821 	    if (breakpoint != NULL && dbg_tick != NULL
822 						   && *dbg_tick != debug_tick)
823 	    {
824 		*breakpoint = dbg_find_breakpoint(
825 				getline_equal(fgetline, cookie, getsourceline),
826 							fname, SOURCING_LNUM);
827 		*dbg_tick = debug_tick;
828 	    }
829 
830 	    next_cmdline = ((wcmd_T *)(lines_ga.ga_data))[current_line].line;
831 	    SOURCING_LNUM = ((wcmd_T *)(lines_ga.ga_data))[current_line].lnum;
832 
833 	    // Did we encounter a breakpoint?
834 	    if (breakpoint != NULL && *breakpoint != 0
835 					      && *breakpoint <= SOURCING_LNUM)
836 	    {
837 		dbg_breakpoint(fname, SOURCING_LNUM);
838 		// Find next breakpoint.
839 		*breakpoint = dbg_find_breakpoint(
840 			       getline_equal(fgetline, cookie, getsourceline),
841 							fname, SOURCING_LNUM);
842 		*dbg_tick = debug_tick;
843 	    }
844 # ifdef FEAT_PROFILE
845 	    if (do_profiling == PROF_YES)
846 	    {
847 		if (getline_is_func)
848 		    func_line_start(real_cookie);
849 		else if (getline_equal(fgetline, cookie, getsourceline))
850 		    script_line_start();
851 	    }
852 # endif
853 	}
854 #endif
855 
856 	// 2. If no line given, get an allocated line with fgetline().
857 	if (next_cmdline == NULL)
858 	{
859 	    /*
860 	     * Need to set msg_didout for the first line after an ":if",
861 	     * otherwise the ":if" will be overwritten.
862 	     */
863 	    if (count == 1 && getline_equal(fgetline, cookie, getexline))
864 		msg_didout = TRUE;
865 	    if (fgetline == NULL || (next_cmdline = fgetline(':', cookie,
866 #ifdef FEAT_EVAL
867 		    cstack.cs_idx < 0 ? 0 : (cstack.cs_idx + 1) * 2
868 #else
869 		    0
870 #endif
871 		    , TRUE)) == NULL)
872 	    {
873 		// Don't call wait_return for aborted command line.  The NULL
874 		// returned for the end of a sourced file or executed function
875 		// doesn't do this.
876 		if (KeyTyped && !(flags & DOCMD_REPEAT))
877 		    need_wait_return = FALSE;
878 		retval = FAIL;
879 		break;
880 	    }
881 	    used_getline = TRUE;
882 
883 	    /*
884 	     * Keep the first typed line.  Clear it when more lines are typed.
885 	     */
886 	    if (flags & DOCMD_KEEPLINE)
887 	    {
888 		vim_free(repeat_cmdline);
889 		if (count == 0)
890 		    repeat_cmdline = vim_strsave(next_cmdline);
891 		else
892 		    repeat_cmdline = NULL;
893 	    }
894 	}
895 
896 	// 3. Make a copy of the command so we can mess with it.
897 	else if (cmdline_copy == NULL)
898 	{
899 	    next_cmdline = vim_strsave(next_cmdline);
900 	    if (next_cmdline == NULL)
901 	    {
902 		emsg(_(e_outofmem));
903 		retval = FAIL;
904 		break;
905 	    }
906 	}
907 	cmdline_copy = next_cmdline;
908 
909 #ifdef FEAT_EVAL
910 	/*
911 	 * Inside a while/for loop, and when the command looks like a ":while"
912 	 * or ":for", the line is stored, because we may need it later when
913 	 * looping.
914 	 *
915 	 * When there is a '|' and another command, it is stored separately,
916 	 * because we need to be able to jump back to it from an
917 	 * :endwhile/:endfor.
918 	 *
919 	 * Pass a different "fgetline" function to do_one_cmd() below,
920 	 * that it stores lines in or reads them from "lines_ga".  Makes it
921 	 * possible to define a function inside a while/for loop and handles
922 	 * line continuation.
923 	 */
924 	if ((cstack.cs_looplevel > 0 || has_loop_cmd(next_cmdline)))
925 	{
926 	    cmd_getline = get_loop_line;
927 	    cmd_cookie = (void *)&cmd_loop_cookie;
928 	    cmd_loop_cookie.lines_gap = &lines_ga;
929 	    cmd_loop_cookie.current_line = current_line;
930 	    cmd_loop_cookie.getline = fgetline;
931 	    cmd_loop_cookie.cookie = cookie;
932 	    cmd_loop_cookie.repeating = (current_line < lines_ga.ga_len);
933 
934 	    // Save the current line when encountering it the first time.
935 	    if (current_line == lines_ga.ga_len
936 		    && store_loop_line(&lines_ga, next_cmdline) == FAIL)
937 	    {
938 		retval = FAIL;
939 		break;
940 	    }
941 	    current_line_before = current_line;
942 	}
943 	else
944 	{
945 	    cmd_getline = fgetline;
946 	    cmd_cookie = cookie;
947 	}
948 
949 	did_endif = FALSE;
950 #endif
951 
952 	if (count++ == 0)
953 	{
954 	    /*
955 	     * All output from the commands is put below each other, without
956 	     * waiting for a return. Don't do this when executing commands
957 	     * from a script or when being called recursive (e.g. for ":e
958 	     * +command file").
959 	     */
960 	    if (!(flags & DOCMD_NOWAIT) && !recursive)
961 	    {
962 		msg_didout_before_start = msg_didout;
963 		msg_didany = FALSE; // no output yet
964 		msg_start();
965 		msg_scroll = TRUE;  // put messages below each other
966 		++no_wait_return;   // don't wait for return until finished
967 		++RedrawingDisabled;
968 		did_inc = TRUE;
969 	    }
970 	}
971 
972 	if ((p_verbose >= 15 && SOURCING_NAME != NULL) || p_verbose >= 16)
973 	    msg_verbose_cmd(SOURCING_LNUM, cmdline_copy);
974 
975 	/*
976 	 * 2. Execute one '|' separated command.
977 	 *    do_one_cmd() will return NULL if there is no trailing '|'.
978 	 *    "cmdline_copy" can change, e.g. for '%' and '#' expansion.
979 	 */
980 	++recursive;
981 	next_cmdline = do_one_cmd(&cmdline_copy, flags & DOCMD_VERBOSE,
982 #ifdef FEAT_EVAL
983 				&cstack,
984 #endif
985 				cmd_getline, cmd_cookie);
986 	--recursive;
987 
988 #ifdef FEAT_EVAL
989 	if (cmd_cookie == (void *)&cmd_loop_cookie)
990 	    // Use "current_line" from "cmd_loop_cookie", it may have been
991 	    // incremented when defining a function.
992 	    current_line = cmd_loop_cookie.current_line;
993 #endif
994 
995 	if (next_cmdline == NULL)
996 	{
997 	    VIM_CLEAR(cmdline_copy);
998 
999 	    /*
1000 	     * If the command was typed, remember it for the ':' register.
1001 	     * Do this AFTER executing the command to make :@: work.
1002 	     */
1003 	    if (getline_equal(fgetline, cookie, getexline)
1004 						  && new_last_cmdline != NULL)
1005 	    {
1006 		vim_free(last_cmdline);
1007 		last_cmdline = new_last_cmdline;
1008 		new_last_cmdline = NULL;
1009 	    }
1010 	}
1011 	else
1012 	{
1013 	    // need to copy the command after the '|' to cmdline_copy, for the
1014 	    // next do_one_cmd()
1015 	    STRMOVE(cmdline_copy, next_cmdline);
1016 	    next_cmdline = cmdline_copy;
1017 	}
1018 
1019 
1020 #ifdef FEAT_EVAL
1021 	// reset did_emsg for a function that is not aborted by an error
1022 	if (did_emsg && !force_abort
1023 		&& getline_equal(fgetline, cookie, get_func_line)
1024 					      && !func_has_abort(real_cookie))
1025 	    did_emsg = FALSE;
1026 
1027 	if (cstack.cs_looplevel > 0)
1028 	{
1029 	    ++current_line;
1030 
1031 	    /*
1032 	     * An ":endwhile", ":endfor" and ":continue" is handled here.
1033 	     * If we were executing commands, jump back to the ":while" or
1034 	     * ":for".
1035 	     * If we were not executing commands, decrement cs_looplevel.
1036 	     */
1037 	    if (cstack.cs_lflags & (CSL_HAD_CONT | CSL_HAD_ENDLOOP))
1038 	    {
1039 		cstack.cs_lflags &= ~(CSL_HAD_CONT | CSL_HAD_ENDLOOP);
1040 
1041 		// Jump back to the matching ":while" or ":for".  Be careful
1042 		// not to use a cs_line[] from an entry that isn't a ":while"
1043 		// or ":for": It would make "current_line" invalid and can
1044 		// cause a crash.
1045 		if (!did_emsg && !got_int && !did_throw
1046 			&& cstack.cs_idx >= 0
1047 			&& (cstack.cs_flags[cstack.cs_idx]
1048 						      & (CSF_WHILE | CSF_FOR))
1049 			&& cstack.cs_line[cstack.cs_idx] >= 0
1050 			&& (cstack.cs_flags[cstack.cs_idx] & CSF_ACTIVE))
1051 		{
1052 		    current_line = cstack.cs_line[cstack.cs_idx];
1053 						// remember we jumped there
1054 		    cstack.cs_lflags |= CSL_HAD_LOOP;
1055 		    line_breakcheck();		// check if CTRL-C typed
1056 
1057 		    // Check for the next breakpoint at or after the ":while"
1058 		    // or ":for".
1059 		    if (breakpoint != NULL)
1060 		    {
1061 			*breakpoint = dbg_find_breakpoint(
1062 			       getline_equal(fgetline, cookie, getsourceline),
1063 									fname,
1064 			   ((wcmd_T *)lines_ga.ga_data)[current_line].lnum-1);
1065 			*dbg_tick = debug_tick;
1066 		    }
1067 		}
1068 		else
1069 		{
1070 		    // can only get here with ":endwhile" or ":endfor"
1071 		    if (cstack.cs_idx >= 0)
1072 			rewind_conditionals(&cstack, cstack.cs_idx - 1,
1073 				   CSF_WHILE | CSF_FOR, &cstack.cs_looplevel);
1074 		}
1075 	    }
1076 
1077 	    /*
1078 	     * For a ":while" or ":for" we need to remember the line number.
1079 	     */
1080 	    else if (cstack.cs_lflags & CSL_HAD_LOOP)
1081 	    {
1082 		cstack.cs_lflags &= ~CSL_HAD_LOOP;
1083 		cstack.cs_line[cstack.cs_idx] = current_line_before;
1084 	    }
1085 	}
1086 
1087 	// Check for the next breakpoint after a watchexpression
1088 	if (breakpoint != NULL && has_watchexpr())
1089 	{
1090 	    *breakpoint = dbg_find_breakpoint(FALSE, fname, SOURCING_LNUM);
1091 	    *dbg_tick = debug_tick;
1092 	}
1093 
1094 	/*
1095 	 * When not inside any ":while" loop, clear remembered lines.
1096 	 */
1097 	if (cstack.cs_looplevel == 0)
1098 	{
1099 	    if (lines_ga.ga_len > 0)
1100 	    {
1101 		SOURCING_LNUM =
1102 		       ((wcmd_T *)lines_ga.ga_data)[lines_ga.ga_len - 1].lnum;
1103 		free_cmdlines(&lines_ga);
1104 	    }
1105 	    current_line = 0;
1106 	}
1107 
1108 	/*
1109 	 * A ":finally" makes did_emsg, got_int, and did_throw pending for
1110 	 * being restored at the ":endtry".  Reset them here and set the
1111 	 * ACTIVE and FINALLY flags, so that the finally clause gets executed.
1112 	 * This includes the case where a missing ":endif", ":endwhile" or
1113 	 * ":endfor" was detected by the ":finally" itself.
1114 	 */
1115 	if (cstack.cs_lflags & CSL_HAD_FINA)
1116 	{
1117 	    cstack.cs_lflags &= ~CSL_HAD_FINA;
1118 	    report_make_pending(cstack.cs_pending[cstack.cs_idx]
1119 		    & (CSTP_ERROR | CSTP_INTERRUPT | CSTP_THROW),
1120 		    did_throw ? (void *)current_exception : NULL);
1121 	    did_emsg = got_int = did_throw = FALSE;
1122 	    cstack.cs_flags[cstack.cs_idx] |= CSF_ACTIVE | CSF_FINALLY;
1123 	}
1124 
1125 	// Update global "trylevel" for recursive calls to do_cmdline() from
1126 	// within this loop.
1127 	trylevel = initial_trylevel + cstack.cs_trylevel;
1128 
1129 	/*
1130 	 * If the outermost try conditional (across function calls and sourced
1131 	 * files) is aborted because of an error, an interrupt, or an uncaught
1132 	 * exception, cancel everything.  If it is left normally, reset
1133 	 * force_abort to get the non-EH compatible abortion behavior for
1134 	 * the rest of the script.
1135 	 */
1136 	if (trylevel == 0 && !did_emsg && !got_int && !did_throw)
1137 	    force_abort = FALSE;
1138 
1139 	// Convert an interrupt to an exception if appropriate.
1140 	(void)do_intthrow(&cstack);
1141 #endif // FEAT_EVAL
1142 
1143     }
1144     /*
1145      * Continue executing command lines when:
1146      * - no CTRL-C typed, no aborting error, no exception thrown or try
1147      *   conditionals need to be checked for executing finally clauses or
1148      *   catching an interrupt exception
1149      * - didn't get an error message or lines are not typed
1150      * - there is a command after '|', inside a :if, :while, :for or :try, or
1151      *   looping for ":source" command or function call.
1152      */
1153     while (!((got_int
1154 #ifdef FEAT_EVAL
1155 		    || (did_emsg && force_abort) || did_throw
1156 #endif
1157 	     )
1158 #ifdef FEAT_EVAL
1159 		&& cstack.cs_trylevel == 0
1160 #endif
1161 	    )
1162 	    && !(did_emsg
1163 #ifdef FEAT_EVAL
1164 		// Keep going when inside try/catch, so that the error can be
1165 		// deal with, except when it is a syntax error, it may cause
1166 		// the :endtry to be missed.
1167 		&& (cstack.cs_trylevel == 0 || did_emsg_syntax)
1168 #endif
1169 		&& used_getline
1170 			    && (getline_equal(fgetline, cookie, getexmodeline)
1171 			       || getline_equal(fgetline, cookie, getexline)))
1172 	    && (next_cmdline != NULL
1173 #ifdef FEAT_EVAL
1174 			|| cstack.cs_idx >= 0
1175 #endif
1176 			|| (flags & DOCMD_REPEAT)));
1177 
1178     vim_free(cmdline_copy);
1179     did_emsg_syntax = FALSE;
1180 #ifdef FEAT_EVAL
1181     free_cmdlines(&lines_ga);
1182     ga_clear(&lines_ga);
1183 
1184     if (cstack.cs_idx >= 0)
1185     {
1186 	/*
1187 	 * If a sourced file or executed function ran to its end, report the
1188 	 * unclosed conditional.
1189 	 */
1190 	if (!got_int && !did_throw
1191 		&& ((getline_equal(fgetline, cookie, getsourceline)
1192 			&& !source_finished(fgetline, cookie))
1193 		    || (getline_equal(fgetline, cookie, get_func_line)
1194 					    && !func_has_ended(real_cookie))))
1195 	{
1196 	    if (cstack.cs_flags[cstack.cs_idx] & CSF_TRY)
1197 		emsg(_(e_endtry));
1198 	    else if (cstack.cs_flags[cstack.cs_idx] & CSF_WHILE)
1199 		emsg(_(e_endwhile));
1200 	    else if (cstack.cs_flags[cstack.cs_idx] & CSF_FOR)
1201 		emsg(_(e_endfor));
1202 	    else
1203 		emsg(_(e_endif));
1204 	}
1205 
1206 	/*
1207 	 * Reset "trylevel" in case of a ":finish" or ":return" or a missing
1208 	 * ":endtry" in a sourced file or executed function.  If the try
1209 	 * conditional is in its finally clause, ignore anything pending.
1210 	 * If it is in a catch clause, finish the caught exception.
1211 	 * Also cleanup any "cs_forinfo" structures.
1212 	 */
1213 	do
1214 	{
1215 	    int idx = cleanup_conditionals(&cstack, 0, TRUE);
1216 
1217 	    if (idx >= 0)
1218 		--idx;	    // remove try block not in its finally clause
1219 	    rewind_conditionals(&cstack, idx, CSF_WHILE | CSF_FOR,
1220 							&cstack.cs_looplevel);
1221 	}
1222 	while (cstack.cs_idx >= 0);
1223 	trylevel = initial_trylevel;
1224     }
1225 
1226     // If a missing ":endtry", ":endwhile", ":endfor", or ":endif" or a memory
1227     // lack was reported above and the error message is to be converted to an
1228     // exception, do this now after rewinding the cstack.
1229     do_errthrow(&cstack, getline_equal(fgetline, cookie, get_func_line)
1230 				  ? (char_u *)"endfunction" : (char_u *)NULL);
1231 
1232     if (trylevel == 0)
1233     {
1234 	/*
1235 	 * When an exception is being thrown out of the outermost try
1236 	 * conditional, discard the uncaught exception, disable the conversion
1237 	 * of interrupts or errors to exceptions, and ensure that no more
1238 	 * commands are executed.
1239 	 */
1240 	if (did_throw)
1241 	{
1242 	    void	*p = NULL;
1243 	    msglist_T	*messages = NULL, *next;
1244 
1245 	    /*
1246 	     * If the uncaught exception is a user exception, report it as an
1247 	     * error.  If it is an error exception, display the saved error
1248 	     * message now.  For an interrupt exception, do nothing; the
1249 	     * interrupt message is given elsewhere.
1250 	     */
1251 	    switch (current_exception->type)
1252 	    {
1253 		case ET_USER:
1254 		    vim_snprintf((char *)IObuff, IOSIZE,
1255 			    _("E605: Exception not caught: %s"),
1256 			    current_exception->value);
1257 		    p = vim_strsave(IObuff);
1258 		    break;
1259 		case ET_ERROR:
1260 		    messages = current_exception->messages;
1261 		    current_exception->messages = NULL;
1262 		    break;
1263 		case ET_INTERRUPT:
1264 		    break;
1265 	    }
1266 
1267 	    estack_push(ETYPE_EXCEPT, current_exception->throw_name,
1268 						current_exception->throw_lnum);
1269 	    ESTACK_CHECK_SETUP
1270 	    current_exception->throw_name = NULL;
1271 
1272 	    discard_current_exception();	// uses IObuff if 'verbose'
1273 	    suppress_errthrow = TRUE;
1274 	    force_abort = TRUE;
1275 
1276 	    if (messages != NULL)
1277 	    {
1278 		do
1279 		{
1280 		    next = messages->next;
1281 		    emsg(messages->msg);
1282 		    vim_free(messages->msg);
1283 		    vim_free(messages->sfile);
1284 		    vim_free(messages);
1285 		    messages = next;
1286 		}
1287 		while (messages != NULL);
1288 	    }
1289 	    else if (p != NULL)
1290 	    {
1291 		emsg(p);
1292 		vim_free(p);
1293 	    }
1294 	    vim_free(SOURCING_NAME);
1295 	    ESTACK_CHECK_NOW
1296 	    estack_pop();
1297 	}
1298 
1299 	/*
1300 	 * On an interrupt or an aborting error not converted to an exception,
1301 	 * disable the conversion of errors to exceptions.  (Interrupts are not
1302 	 * converted anymore, here.) This enables also the interrupt message
1303 	 * when force_abort is set and did_emsg unset in case of an interrupt
1304 	 * from a finally clause after an error.
1305 	 */
1306 	else if (got_int || (did_emsg && force_abort))
1307 	    suppress_errthrow = TRUE;
1308     }
1309 
1310     /*
1311      * The current cstack will be freed when do_cmdline() returns.  An uncaught
1312      * exception will have to be rethrown in the previous cstack.  If a function
1313      * has just returned or a script file was just finished and the previous
1314      * cstack belongs to the same function or, respectively, script file, it
1315      * will have to be checked for finally clauses to be executed due to the
1316      * ":return" or ":finish".  This is done in do_one_cmd().
1317      */
1318     if (did_throw)
1319 	need_rethrow = TRUE;
1320     if ((getline_equal(fgetline, cookie, getsourceline)
1321 		&& ex_nesting_level > source_level(real_cookie))
1322 	    || (getline_equal(fgetline, cookie, get_func_line)
1323 		&& ex_nesting_level > func_level(real_cookie) + 1))
1324     {
1325 	if (!did_throw)
1326 	    check_cstack = TRUE;
1327     }
1328     else
1329     {
1330 	// When leaving a function, reduce nesting level.
1331 	if (getline_equal(fgetline, cookie, get_func_line))
1332 	    --ex_nesting_level;
1333 	/*
1334 	 * Go to debug mode when returning from a function in which we are
1335 	 * single-stepping.
1336 	 */
1337 	if ((getline_equal(fgetline, cookie, getsourceline)
1338 		    || getline_equal(fgetline, cookie, get_func_line))
1339 		&& ex_nesting_level + 1 <= debug_break_level)
1340 	    do_debug(getline_equal(fgetline, cookie, getsourceline)
1341 		    ? (char_u *)_("End of sourced file")
1342 		    : (char_u *)_("End of function"));
1343     }
1344 
1345     /*
1346      * Restore the exception environment (done after returning from the
1347      * debugger).
1348      */
1349     if (flags & DOCMD_EXCRESET)
1350 	restore_dbg_stuff(&debug_saved);
1351 
1352     msg_list = saved_msg_list;
1353 
1354     // Cleanup if "cs_emsg_silent_list" remains.
1355     if (cstack.cs_emsg_silent_list != NULL)
1356     {
1357 	eslist_T *elem, *temp;
1358 
1359 	for (elem = cstack.cs_emsg_silent_list; elem != NULL; elem = temp)
1360 	{
1361 	    temp = elem->next;
1362 	    vim_free(elem);
1363 	}
1364     }
1365 #endif // FEAT_EVAL
1366 
1367     /*
1368      * If there was too much output to fit on the command line, ask the user to
1369      * hit return before redrawing the screen. With the ":global" command we do
1370      * this only once after the command is finished.
1371      */
1372     if (did_inc)
1373     {
1374 	--RedrawingDisabled;
1375 	--no_wait_return;
1376 	msg_scroll = FALSE;
1377 
1378 	/*
1379 	 * When just finished an ":if"-":else" which was typed, no need to
1380 	 * wait for hit-return.  Also for an error situation.
1381 	 */
1382 	if (retval == FAIL
1383 #ifdef FEAT_EVAL
1384 		|| (did_endif && KeyTyped && !did_emsg)
1385 #endif
1386 					    )
1387 	{
1388 	    need_wait_return = FALSE;
1389 	    msg_didany = FALSE;		// don't wait when restarting edit
1390 	}
1391 	else if (need_wait_return)
1392 	{
1393 	    /*
1394 	     * The msg_start() above clears msg_didout. The wait_return we do
1395 	     * here should not overwrite the command that may be shown before
1396 	     * doing that.
1397 	     */
1398 	    msg_didout |= msg_didout_before_start;
1399 	    wait_return(FALSE);
1400 	}
1401     }
1402 
1403 #ifdef FEAT_EVAL
1404     did_endif = FALSE;  // in case do_cmdline used recursively
1405 #else
1406     /*
1407      * Reset if_level, in case a sourced script file contains more ":if" than
1408      * ":endif" (could be ":if x | foo | endif").
1409      */
1410     if_level = 0;
1411 #endif
1412 
1413     --call_depth;
1414     return retval;
1415 }
1416 
1417 #ifdef FEAT_EVAL
1418 /*
1419  * Obtain a line when inside a ":while" or ":for" loop.
1420  */
1421     static char_u *
1422 get_loop_line(int c, void *cookie, int indent, int do_concat)
1423 {
1424     struct loop_cookie	*cp = (struct loop_cookie *)cookie;
1425     wcmd_T		*wp;
1426     char_u		*line;
1427 
1428     if (cp->current_line + 1 >= cp->lines_gap->ga_len)
1429     {
1430 	if (cp->repeating)
1431 	    return NULL;	// trying to read past ":endwhile"/":endfor"
1432 
1433 	// First time inside the ":while"/":for": get line normally.
1434 	if (cp->getline == NULL)
1435 	    line = getcmdline(c, 0L, indent, do_concat);
1436 	else
1437 	    line = cp->getline(c, cp->cookie, indent, do_concat);
1438 	if (line != NULL && store_loop_line(cp->lines_gap, line) == OK)
1439 	    ++cp->current_line;
1440 
1441 	return line;
1442     }
1443 
1444     KeyTyped = FALSE;
1445     ++cp->current_line;
1446     wp = (wcmd_T *)(cp->lines_gap->ga_data) + cp->current_line;
1447     SOURCING_LNUM = wp->lnum;
1448     return vim_strsave(wp->line);
1449 }
1450 
1451 /*
1452  * Store a line in "gap" so that a ":while" loop can execute it again.
1453  */
1454     static int
1455 store_loop_line(garray_T *gap, char_u *line)
1456 {
1457     if (ga_grow(gap, 1) == FAIL)
1458 	return FAIL;
1459     ((wcmd_T *)(gap->ga_data))[gap->ga_len].line = vim_strsave(line);
1460     ((wcmd_T *)(gap->ga_data))[gap->ga_len].lnum = SOURCING_LNUM;
1461     ++gap->ga_len;
1462     return OK;
1463 }
1464 
1465 /*
1466  * Free the lines stored for a ":while" or ":for" loop.
1467  */
1468     static void
1469 free_cmdlines(garray_T *gap)
1470 {
1471     while (gap->ga_len > 0)
1472     {
1473 	vim_free(((wcmd_T *)(gap->ga_data))[gap->ga_len - 1].line);
1474 	--gap->ga_len;
1475     }
1476 }
1477 #endif
1478 
1479 /*
1480  * If "fgetline" is get_loop_line(), return TRUE if the getline it uses equals
1481  * "func".  * Otherwise return TRUE when "fgetline" equals "func".
1482  */
1483     int
1484 getline_equal(
1485     char_u	*(*fgetline)(int, void *, int, int),
1486     void	*cookie UNUSED,		// argument for fgetline()
1487     char_u	*(*func)(int, void *, int, int))
1488 {
1489 #ifdef FEAT_EVAL
1490     char_u		*(*gp)(int, void *, int, int);
1491     struct loop_cookie *cp;
1492 
1493     // When "fgetline" is "get_loop_line()" use the "cookie" to find the
1494     // function that's originally used to obtain the lines.  This may be
1495     // nested several levels.
1496     gp = fgetline;
1497     cp = (struct loop_cookie *)cookie;
1498     while (gp == get_loop_line)
1499     {
1500 	gp = cp->getline;
1501 	cp = cp->cookie;
1502     }
1503     return gp == func;
1504 #else
1505     return fgetline == func;
1506 #endif
1507 }
1508 
1509 /*
1510  * If "fgetline" is get_loop_line(), return the cookie used by the original
1511  * getline function.  Otherwise return "cookie".
1512  */
1513     void *
1514 getline_cookie(
1515     char_u	*(*fgetline)(int, void *, int, int) UNUSED,
1516     void	*cookie)		// argument for fgetline()
1517 {
1518 #ifdef FEAT_EVAL
1519     char_u		*(*gp)(int, void *, int, int);
1520     struct loop_cookie  *cp;
1521 
1522     // When "fgetline" is "get_loop_line()" use the "cookie" to find the
1523     // cookie that's originally used to obtain the lines.  This may be nested
1524     // several levels.
1525     gp = fgetline;
1526     cp = (struct loop_cookie *)cookie;
1527     while (gp == get_loop_line)
1528     {
1529 	gp = cp->getline;
1530 	cp = cp->cookie;
1531     }
1532     return cp;
1533 #else
1534     return cookie;
1535 #endif
1536 }
1537 
1538 #if defined(FEAT_EVAL) || defined(PROT)
1539 /*
1540  * Get the next line source line without advancing.
1541  */
1542     char_u *
1543 getline_peek(
1544     char_u	*(*fgetline)(int, void *, int, int) UNUSED,
1545     void	*cookie)		// argument for fgetline()
1546 {
1547     char_u		*(*gp)(int, void *, int, int);
1548     struct loop_cookie  *cp;
1549     wcmd_T		*wp;
1550 
1551     // When "fgetline" is "get_loop_line()" use the "cookie" to find the
1552     // cookie that's originally used to obtain the lines.  This may be nested
1553     // several levels.
1554     gp = fgetline;
1555     cp = (struct loop_cookie *)cookie;
1556     while (gp == get_loop_line)
1557     {
1558 	if (cp->current_line + 1 < cp->lines_gap->ga_len)
1559 	{
1560 	    // executing lines a second time, use the stored copy
1561 	    wp = (wcmd_T *)(cp->lines_gap->ga_data) + cp->current_line + 1;
1562 	    return wp->line;
1563 	}
1564 	gp = cp->getline;
1565 	cp = cp->cookie;
1566     }
1567     if (gp == getsourceline)
1568 	return source_nextline(cp);
1569     return NULL;
1570 }
1571 #endif
1572 
1573 
1574 /*
1575  * Helper function to apply an offset for buffer commands, i.e. ":bdelete",
1576  * ":bwipeout", etc.
1577  * Returns the buffer number.
1578  */
1579     static int
1580 compute_buffer_local_count(int addr_type, int lnum, int offset)
1581 {
1582     buf_T   *buf;
1583     buf_T   *nextbuf;
1584     int     count = offset;
1585 
1586     buf = firstbuf;
1587     while (buf->b_next != NULL && buf->b_fnum < lnum)
1588 	buf = buf->b_next;
1589     while (count != 0)
1590     {
1591 	count += (offset < 0) ? 1 : -1;
1592 	nextbuf = (offset < 0) ? buf->b_prev : buf->b_next;
1593 	if (nextbuf == NULL)
1594 	    break;
1595 	buf = nextbuf;
1596 	if (addr_type == ADDR_LOADED_BUFFERS)
1597 	    // skip over unloaded buffers
1598 	    while (buf->b_ml.ml_mfp == NULL)
1599 	    {
1600 		nextbuf = (offset < 0) ? buf->b_prev : buf->b_next;
1601 		if (nextbuf == NULL)
1602 		    break;
1603 		buf = nextbuf;
1604 	    }
1605     }
1606     // we might have gone too far, last buffer is not loadedd
1607     if (addr_type == ADDR_LOADED_BUFFERS)
1608 	while (buf->b_ml.ml_mfp == NULL)
1609 	{
1610 	    nextbuf = (offset >= 0) ? buf->b_prev : buf->b_next;
1611 	    if (nextbuf == NULL)
1612 		break;
1613 	    buf = nextbuf;
1614 	}
1615     return buf->b_fnum;
1616 }
1617 
1618 /*
1619  * Return the window number of "win".
1620  * When "win" is NULL return the number of windows.
1621  */
1622     static int
1623 current_win_nr(win_T *win)
1624 {
1625     win_T	*wp;
1626     int		nr = 0;
1627 
1628     FOR_ALL_WINDOWS(wp)
1629     {
1630 	++nr;
1631 	if (wp == win)
1632 	    break;
1633     }
1634     return nr;
1635 }
1636 
1637     static int
1638 current_tab_nr(tabpage_T *tab)
1639 {
1640     tabpage_T	*tp;
1641     int		nr = 0;
1642 
1643     FOR_ALL_TABPAGES(tp)
1644     {
1645 	++nr;
1646 	if (tp == tab)
1647 	    break;
1648     }
1649     return nr;
1650 }
1651 
1652     static int
1653 comment_start(char_u *p, int starts_with_colon UNUSED)
1654 {
1655 #ifdef FEAT_EVAL
1656     if (in_vim9script())
1657 	return p[0] == '#' && p[1] != '{' && !starts_with_colon;
1658 #endif
1659     return *p == '"';
1660 }
1661 
1662 # define CURRENT_WIN_NR current_win_nr(curwin)
1663 # define LAST_WIN_NR current_win_nr(NULL)
1664 # define CURRENT_TAB_NR current_tab_nr(curtab)
1665 # define LAST_TAB_NR current_tab_nr(NULL)
1666 
1667 /*
1668  * Execute one Ex command.
1669  *
1670  * If 'sourcing' is TRUE, the command will be included in the error message.
1671  *
1672  * 1. skip comment lines and leading space
1673  * 2. handle command modifiers
1674  * 3. find the command
1675  * 4. parse range
1676  * 5. Parse the command.
1677  * 6. parse arguments
1678  * 7. switch on command name
1679  *
1680  * Note: "fgetline" can be NULL.
1681  *
1682  * This function may be called recursively!
1683  */
1684 #if (_MSC_VER == 1200)
1685 /*
1686  * Avoid optimisation bug in VC++ version 6.0
1687  */
1688  #pragma optimize( "g", off )
1689 #endif
1690     static char_u *
1691 do_one_cmd(
1692     char_u	**cmdlinep,
1693     int		sourcing,
1694 #ifdef FEAT_EVAL
1695     cstack_T	*cstack,
1696 #endif
1697     char_u	*(*fgetline)(int, void *, int, int),
1698     void	*cookie)		// argument for fgetline()
1699 {
1700     char_u	*p;
1701     linenr_T	lnum;
1702     long	n;
1703     char	*errormsg = NULL;	// error message
1704     char_u	*after_modifier = NULL;
1705     exarg_T	ea;			// Ex command arguments
1706     int		save_msg_scroll = msg_scroll;
1707     cmdmod_T	save_cmdmod;
1708     int		save_reg_executing = reg_executing;
1709     int		ni;			// set when Not Implemented
1710     char_u	*cmd;
1711     int		starts_with_colon = FALSE;
1712 #ifdef FEAT_EVAL
1713     int		may_have_range;
1714     int		vim9script = in_vim9script();
1715 #endif
1716 
1717     CLEAR_FIELD(ea);
1718     ea.line1 = 1;
1719     ea.line2 = 1;
1720 #ifdef FEAT_EVAL
1721     ++ex_nesting_level;
1722 #endif
1723 
1724     // When the last file has not been edited :q has to be typed twice.
1725     if (quitmore
1726 #ifdef FEAT_EVAL
1727 	    // avoid that a function call in 'statusline' does this
1728 	    && !getline_equal(fgetline, cookie, get_func_line)
1729 #endif
1730 	    // avoid that an autocommand, e.g. QuitPre, does this
1731 	    && !getline_equal(fgetline, cookie, getnextac))
1732 	--quitmore;
1733 
1734     /*
1735      * Reset browse, confirm, etc..  They are restored when returning, for
1736      * recursive calls.
1737      */
1738     save_cmdmod = cmdmod;
1739 
1740     // "#!anything" is handled like a comment.
1741     if ((*cmdlinep)[0] == '#' && (*cmdlinep)[1] == '!')
1742 	goto doend;
1743 
1744 /*
1745  * 1. Skip comment lines and leading white space and colons.
1746  * 2. Handle command modifiers.
1747  */
1748     // The "ea" structure holds the arguments that can be used.
1749     ea.cmd = *cmdlinep;
1750     ea.cmdlinep = cmdlinep;
1751     ea.getline = fgetline;
1752     ea.cookie = cookie;
1753 #ifdef FEAT_EVAL
1754     ea.cstack = cstack;
1755     starts_with_colon = *skipwhite(ea.cmd) == ':';
1756 #endif
1757     if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
1758 	goto doend;
1759 
1760     after_modifier = ea.cmd;
1761 
1762 #ifdef FEAT_EVAL
1763     ea.skip = did_emsg || got_int || did_throw || (cstack->cs_idx >= 0
1764 			 && !(cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE));
1765 #else
1766     ea.skip = (if_level > 0);
1767 #endif
1768 
1769 /*
1770  * 3. Skip over the range to find the command.  Let "p" point to after it.
1771  *
1772  * We need the command to know what kind of range it uses.
1773  */
1774     cmd = ea.cmd;
1775 #ifdef FEAT_EVAL
1776     // In Vim9 script a colon is required before the range.
1777     may_have_range = !vim9script || starts_with_colon;
1778     if (may_have_range)
1779 #endif
1780 	ea.cmd = skip_range(ea.cmd, NULL);
1781     if (*ea.cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL)
1782 	ea.cmd = skipwhite(ea.cmd + 1);
1783 
1784 #ifdef FEAT_EVAL
1785     if (vim9script && !starts_with_colon)
1786     {
1787 	if (ea.cmd == cmd + 1 && *cmd == '$')
1788 	    // should be "$VAR = val"
1789 	    --ea.cmd;
1790 	else if (ea.cmd > cmd)
1791 	{
1792 	    emsg(_(e_colon_required));
1793 	    goto doend;
1794 	}
1795 	p = find_ex_command(&ea, NULL, lookup_scriptvar, NULL);
1796     }
1797     else
1798 #endif
1799 	p = find_ex_command(&ea, NULL, NULL, NULL);
1800 
1801 #ifdef FEAT_EVAL
1802 # ifdef FEAT_PROFILE
1803     // Count this line for profiling if skip is TRUE.
1804     if (do_profiling == PROF_YES
1805 	    && (!ea.skip || cstack->cs_idx == 0 || (cstack->cs_idx > 0
1806 		     && (cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE))))
1807     {
1808 	int skip = did_emsg || got_int || did_throw;
1809 
1810 	if (ea.cmdidx == CMD_catch)
1811 	    skip = !skip && !(cstack->cs_idx >= 0
1812 			  && (cstack->cs_flags[cstack->cs_idx] & CSF_THROWN)
1813 			  && !(cstack->cs_flags[cstack->cs_idx] & CSF_CAUGHT));
1814 	else if (ea.cmdidx == CMD_else || ea.cmdidx == CMD_elseif)
1815 	    skip = skip || !(cstack->cs_idx >= 0
1816 			  && !(cstack->cs_flags[cstack->cs_idx]
1817 						  & (CSF_ACTIVE | CSF_TRUE)));
1818 	else if (ea.cmdidx == CMD_finally)
1819 	    skip = FALSE;
1820 	else if (ea.cmdidx != CMD_endif
1821 		&& ea.cmdidx != CMD_endfor
1822 		&& ea.cmdidx != CMD_endtry
1823 		&& ea.cmdidx != CMD_endwhile)
1824 	    skip = ea.skip;
1825 
1826 	if (!skip)
1827 	{
1828 	    if (getline_equal(fgetline, cookie, get_func_line))
1829 		func_line_exec(getline_cookie(fgetline, cookie));
1830 	    else if (getline_equal(fgetline, cookie, getsourceline))
1831 		script_line_exec();
1832 	}
1833     }
1834 # endif
1835 
1836     // May go to debug mode.  If this happens and the ">quit" debug command is
1837     // used, throw an interrupt exception and skip the next command.
1838     dbg_check_breakpoint(&ea);
1839     if (!ea.skip && got_int)
1840     {
1841 	ea.skip = TRUE;
1842 	(void)do_intthrow(cstack);
1843     }
1844 #endif
1845 
1846 /*
1847  * 4. parse a range specifier of the form: addr [,addr] [;addr] ..
1848  *
1849  * where 'addr' is:
1850  *
1851  * %	      (entire file)
1852  * $  [+-NUM]
1853  * 'x [+-NUM] (where x denotes a currently defined mark)
1854  * .  [+-NUM]
1855  * [+-NUM]..
1856  * NUM
1857  *
1858  * The ea.cmd pointer is updated to point to the first character following the
1859  * range spec. If an initial address is found, but no second, the upper bound
1860  * is equal to the lower.
1861  */
1862 
1863     // ea.addr_type for user commands is set by find_ucmd
1864     if (!IS_USER_CMDIDX(ea.cmdidx))
1865     {
1866 	if (ea.cmdidx != CMD_SIZE)
1867 	    ea.addr_type = cmdnames[(int)ea.cmdidx].cmd_addr_type;
1868 	else
1869 	    ea.addr_type = ADDR_LINES;
1870 
1871 	// :wincmd range depends on the argument.
1872 	if (ea.cmdidx == CMD_wincmd && p != NULL)
1873 	    get_wincmd_addr_type(skipwhite(p), &ea);
1874 #ifdef FEAT_QUICKFIX
1875 	// :.cc in quickfix window uses line number
1876 	if ((ea.cmdidx == CMD_cc || ea.cmdidx == CMD_ll) && bt_quickfix(curbuf))
1877 	    ea.addr_type = ADDR_OTHER;
1878 #endif
1879     }
1880 
1881     ea.cmd = cmd;
1882 #ifdef FEAT_EVAL
1883     if (may_have_range)
1884 #endif
1885 	if (parse_cmd_address(&ea, &errormsg, FALSE) == FAIL)
1886 	    goto doend;
1887 
1888 /*
1889  * 5. Parse the command.
1890  */
1891 
1892     /*
1893      * Skip ':' and any white space
1894      */
1895     ea.cmd = skipwhite(ea.cmd);
1896     while (*ea.cmd == ':')
1897 	ea.cmd = skipwhite(ea.cmd + 1);
1898 
1899     /*
1900      * If we got a line, but no command, then go to the line.
1901      * If we find a '|' or '\n' we set ea.nextcmd.
1902      */
1903     if (*ea.cmd == NUL || comment_start(ea.cmd, starts_with_colon)
1904 			       || (ea.nextcmd = check_nextcmd(ea.cmd)) != NULL)
1905     {
1906 	/*
1907 	 * strange vi behaviour:
1908 	 * ":3"		jumps to line 3
1909 	 * ":3|..."	prints line 3
1910 	 * ":|"		prints current line
1911 	 */
1912 	if (ea.skip)	    // skip this if inside :if
1913 	    goto doend;
1914 	if (*ea.cmd == '|' || (exmode_active && ea.line1 != ea.line2))
1915 	{
1916 	    ea.cmdidx = CMD_print;
1917 	    ea.argt = EX_RANGE+EX_COUNT+EX_TRLBAR;
1918 	    if ((errormsg = invalid_range(&ea)) == NULL)
1919 	    {
1920 		correct_range(&ea);
1921 		ex_print(&ea);
1922 	    }
1923 	}
1924 	else if (ea.addr_count != 0)
1925 	{
1926 	    if (ea.line2 > curbuf->b_ml.ml_line_count)
1927 	    {
1928 		// With '-' in 'cpoptions' a line number past the file is an
1929 		// error, otherwise put it at the end of the file.
1930 		if (vim_strchr(p_cpo, CPO_MINUS) != NULL)
1931 		    ea.line2 = -1;
1932 		else
1933 		    ea.line2 = curbuf->b_ml.ml_line_count;
1934 	    }
1935 
1936 	    if (ea.line2 < 0)
1937 		errormsg = _(e_invrange);
1938 	    else
1939 	    {
1940 		if (ea.line2 == 0)
1941 		    curwin->w_cursor.lnum = 1;
1942 		else
1943 		    curwin->w_cursor.lnum = ea.line2;
1944 		beginline(BL_SOL | BL_FIX);
1945 	    }
1946 	}
1947 	goto doend;
1948     }
1949 
1950     // If this looks like an undefined user command and there are CmdUndefined
1951     // autocommands defined, trigger the matching autocommands.
1952     if (p != NULL && ea.cmdidx == CMD_SIZE && !ea.skip
1953 	    && ASCII_ISUPPER(*ea.cmd)
1954 	    && has_cmdundefined())
1955     {
1956 	int ret;
1957 
1958 	p = ea.cmd;
1959 	while (ASCII_ISALNUM(*p))
1960 	    ++p;
1961 	p = vim_strnsave(ea.cmd, p - ea.cmd);
1962 	ret = apply_autocmds(EVENT_CMDUNDEFINED, p, p, TRUE, NULL);
1963 	vim_free(p);
1964 	// If the autocommands did something and didn't cause an error, try
1965 	// finding the command again.
1966 	p = (ret
1967 #ifdef FEAT_EVAL
1968 		&& !aborting()
1969 #endif
1970 		) ? find_ex_command(&ea, NULL, NULL, NULL) : ea.cmd;
1971     }
1972 
1973     if (p == NULL)
1974     {
1975 	if (!ea.skip)
1976 	    errormsg = _("E464: Ambiguous use of user-defined command");
1977 	goto doend;
1978     }
1979     // Check for wrong commands.
1980     if (*p == '!' && ea.cmd[1] == 0151 && ea.cmd[0] == 78
1981 	    && !IS_USER_CMDIDX(ea.cmdidx))
1982     {
1983 	errormsg = uc_fun_cmd();
1984 	goto doend;
1985     }
1986 
1987     if (ea.cmdidx == CMD_SIZE)
1988     {
1989 	if (!ea.skip)
1990 	{
1991 	    STRCPY(IObuff, _("E492: Not an editor command"));
1992 	    if (!sourcing)
1993 	    {
1994 		// If the modifier was parsed OK the error must be in the
1995 		// following command
1996 		if (after_modifier != NULL)
1997 		    append_command(after_modifier);
1998 		else
1999 		    append_command(*cmdlinep);
2000 	    }
2001 	    errormsg = (char *)IObuff;
2002 	    did_emsg_syntax = TRUE;
2003 	}
2004 	goto doend;
2005     }
2006 
2007     ni = (!IS_USER_CMDIDX(ea.cmdidx)
2008 	    && (cmdnames[ea.cmdidx].cmd_func == ex_ni
2009 #ifdef HAVE_EX_SCRIPT_NI
2010 	     || cmdnames[ea.cmdidx].cmd_func == ex_script_ni
2011 #endif
2012 	     ));
2013 
2014 #ifndef FEAT_EVAL
2015     /*
2016      * When the expression evaluation is disabled, recognize the ":if" and
2017      * ":endif" commands and ignore everything in between it.
2018      */
2019     if (ea.cmdidx == CMD_if)
2020 	++if_level;
2021     if (if_level)
2022     {
2023 	if (ea.cmdidx == CMD_endif)
2024 	    --if_level;
2025 	goto doend;
2026     }
2027 
2028 #endif
2029 
2030     // forced commands
2031     if (*p == '!' && ea.cmdidx != CMD_substitute
2032 	    && ea.cmdidx != CMD_smagic && ea.cmdidx != CMD_snomagic)
2033     {
2034 	++p;
2035 	ea.forceit = TRUE;
2036     }
2037     else
2038 	ea.forceit = FALSE;
2039 
2040 /*
2041  * 6. Parse arguments.  Then check for errors.
2042  */
2043     if (!IS_USER_CMDIDX(ea.cmdidx))
2044 	ea.argt = (long)cmdnames[(int)ea.cmdidx].cmd_argt;
2045 
2046     if (!ea.skip)
2047     {
2048 #ifdef HAVE_SANDBOX
2049 	if (sandbox != 0 && !(ea.argt & EX_SBOXOK))
2050 	{
2051 	    // Command not allowed in sandbox.
2052 	    errormsg = _(e_sandbox);
2053 	    goto doend;
2054 	}
2055 #endif
2056 	if (restricted != 0 && (ea.argt & EX_RESTRICT))
2057 	{
2058 	    errormsg = _("E981: Command not allowed in rvim");
2059 	    goto doend;
2060 	}
2061 	if (!curbuf->b_p_ma && (ea.argt & EX_MODIFY))
2062 	{
2063 	    // Command not allowed in non-'modifiable' buffer
2064 	    errormsg = _(e_modifiable);
2065 	    goto doend;
2066 	}
2067 
2068 	if (!IS_USER_CMDIDX(ea.cmdidx))
2069 	{
2070 #ifdef FEAT_CMDWIN
2071 	    if (cmdwin_type != 0 && !(ea.argt & EX_CMDWIN))
2072 	    {
2073 		// Command not allowed in the command line window
2074 		errormsg = _(e_cmdwin);
2075 		goto doend;
2076 	    }
2077 #endif
2078 	    if (text_locked() && !(ea.argt & EX_LOCK_OK))
2079 	    {
2080 		// Command not allowed when text is locked
2081 		errormsg = _(get_text_locked_msg());
2082 		goto doend;
2083 	    }
2084 	}
2085 
2086 	// Disallow editing another buffer when "curbuf_lock" is set.
2087 	// Do allow ":checktime" (it is postponed).
2088 	// Do allow ":edit" (check for an argument later).
2089 	// Do allow ":file" with no arguments (check for an argument later).
2090 	if (!(ea.argt & EX_CMDWIN)
2091 		&& ea.cmdidx != CMD_checktime
2092 		&& ea.cmdidx != CMD_edit
2093 		&& ea.cmdidx != CMD_file
2094 		&& !IS_USER_CMDIDX(ea.cmdidx)
2095 		&& curbuf_locked())
2096 	    goto doend;
2097 
2098 	if (!ni && !(ea.argt & EX_RANGE) && ea.addr_count > 0)
2099 	{
2100 	    // no range allowed
2101 	    errormsg = _(e_norange);
2102 	    goto doend;
2103 	}
2104     }
2105 
2106     if (!ni && !(ea.argt & EX_BANG) && ea.forceit)	// no <!> allowed
2107     {
2108 	errormsg = _(e_nobang);
2109 	goto doend;
2110     }
2111 
2112     /*
2113      * Don't complain about the range if it is not used
2114      * (could happen if line_count is accidentally set to 0).
2115      */
2116     if (!ea.skip && !ni && (ea.argt & EX_RANGE))
2117     {
2118 	/*
2119 	 * If the range is backwards, ask for confirmation and, if given, swap
2120 	 * ea.line1 & ea.line2 so it's forwards again.
2121 	 * When global command is busy, don't ask, will fail below.
2122 	 */
2123 	if (!global_busy && ea.line1 > ea.line2)
2124 	{
2125 	    if (msg_silent == 0)
2126 	    {
2127 		if (sourcing || exmode_active)
2128 		{
2129 		    errormsg = _("E493: Backwards range given");
2130 		    goto doend;
2131 		}
2132 		if (ask_yesno((char_u *)
2133 			_("Backwards range given, OK to swap"), FALSE) != 'y')
2134 		    goto doend;
2135 	    }
2136 	    lnum = ea.line1;
2137 	    ea.line1 = ea.line2;
2138 	    ea.line2 = lnum;
2139 	}
2140 	if ((errormsg = invalid_range(&ea)) != NULL)
2141 	    goto doend;
2142     }
2143 
2144     if ((ea.addr_type == ADDR_OTHER) && ea.addr_count == 0)
2145 	// default is 1, not cursor
2146 	ea.line2 = 1;
2147 
2148     correct_range(&ea);
2149 
2150 #ifdef FEAT_FOLDING
2151     if (((ea.argt & EX_WHOLEFOLD) || ea.addr_count >= 2) && !global_busy
2152 	    && ea.addr_type == ADDR_LINES)
2153     {
2154 	// Put the first line at the start of a closed fold, put the last line
2155 	// at the end of a closed fold.
2156 	(void)hasFolding(ea.line1, &ea.line1, NULL);
2157 	(void)hasFolding(ea.line2, NULL, &ea.line2);
2158     }
2159 #endif
2160 
2161 #ifdef FEAT_QUICKFIX
2162     /*
2163      * For the ":make" and ":grep" commands we insert the 'makeprg'/'grepprg'
2164      * option here, so things like % get expanded.
2165      */
2166     p = replace_makeprg(&ea, p, cmdlinep);
2167     if (p == NULL)
2168 	goto doend;
2169 #endif
2170 
2171     /*
2172      * Skip to start of argument.
2173      * Don't do this for the ":!" command, because ":!! -l" needs the space.
2174      */
2175     if (ea.cmdidx == CMD_bang)
2176 	ea.arg = p;
2177     else
2178 	ea.arg = skipwhite(p);
2179 
2180     // ":file" cannot be run with an argument when "curbuf_lock" is set
2181     if (ea.cmdidx == CMD_file && *ea.arg != NUL && curbuf_locked())
2182 	goto doend;
2183 
2184     /*
2185      * Check for "++opt=val" argument.
2186      * Must be first, allow ":w ++enc=utf8 !cmd"
2187      */
2188     if (ea.argt & EX_ARGOPT)
2189 	while (ea.arg[0] == '+' && ea.arg[1] == '+')
2190 	    if (getargopt(&ea) == FAIL && !ni)
2191 	    {
2192 		errormsg = _(e_invarg);
2193 		goto doend;
2194 	    }
2195 
2196     if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update)
2197     {
2198 	if (*ea.arg == '>')			// append
2199 	{
2200 	    if (*++ea.arg != '>')		// typed wrong
2201 	    {
2202 		errormsg = _("E494: Use w or w>>");
2203 		goto doend;
2204 	    }
2205 	    ea.arg = skipwhite(ea.arg + 1);
2206 	    ea.append = TRUE;
2207 	}
2208 	else if (*ea.arg == '!' && ea.cmdidx == CMD_write)  // :w !filter
2209 	{
2210 	    ++ea.arg;
2211 	    ea.usefilter = TRUE;
2212 	}
2213     }
2214 
2215     if (ea.cmdidx == CMD_read)
2216     {
2217 	if (ea.forceit)
2218 	{
2219 	    ea.usefilter = TRUE;		// :r! filter if ea.forceit
2220 	    ea.forceit = FALSE;
2221 	}
2222 	else if (*ea.arg == '!')		// :r !filter
2223 	{
2224 	    ++ea.arg;
2225 	    ea.usefilter = TRUE;
2226 	}
2227     }
2228 
2229     if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift)
2230     {
2231 	ea.amount = 1;
2232 	while (*ea.arg == *ea.cmd)		// count number of '>' or '<'
2233 	{
2234 	    ++ea.arg;
2235 	    ++ea.amount;
2236 	}
2237 	ea.arg = skipwhite(ea.arg);
2238     }
2239 
2240     /*
2241      * Check for "+command" argument, before checking for next command.
2242      * Don't do this for ":read !cmd" and ":write !cmd".
2243      */
2244     if ((ea.argt & EX_CMDARG) && !ea.usefilter)
2245 	ea.do_ecmd_cmd = getargcmd(&ea.arg);
2246 
2247     /*
2248      * Check for '|' to separate commands and '"' or '#' to start comments.
2249      * Don't do this for ":read !cmd" and ":write !cmd".
2250      */
2251     if ((ea.argt & EX_TRLBAR) && !ea.usefilter)
2252 	separate_nextcmd(&ea);
2253 
2254     /*
2255      * Check for <newline> to end a shell command.
2256      * Also do this for ":read !cmd", ":write !cmd" and ":global".
2257      * Any others?
2258      */
2259     else if (ea.cmdidx == CMD_bang
2260 	    || ea.cmdidx == CMD_terminal
2261 	    || ea.cmdidx == CMD_global
2262 	    || ea.cmdidx == CMD_vglobal
2263 	    || ea.usefilter)
2264     {
2265 	for (p = ea.arg; *p; ++p)
2266 	{
2267 	    // Remove one backslash before a newline, so that it's possible to
2268 	    // pass a newline to the shell and also a newline that is preceded
2269 	    // with a backslash.  This makes it impossible to end a shell
2270 	    // command in a backslash, but that doesn't appear useful.
2271 	    // Halving the number of backslashes is incompatible with previous
2272 	    // versions.
2273 	    if (*p == '\\' && p[1] == '\n')
2274 		STRMOVE(p, p + 1);
2275 	    else if (*p == '\n')
2276 	    {
2277 		ea.nextcmd = p + 1;
2278 		*p = NUL;
2279 		break;
2280 	    }
2281 	}
2282     }
2283 
2284     if ((ea.argt & EX_DFLALL) && ea.addr_count == 0)
2285     {
2286 	buf_T	    *buf;
2287 
2288 	ea.line1 = 1;
2289 	switch (ea.addr_type)
2290 	{
2291 	    case ADDR_LINES:
2292 	    case ADDR_OTHER:
2293 		ea.line2 = curbuf->b_ml.ml_line_count;
2294 		break;
2295 	    case ADDR_LOADED_BUFFERS:
2296 		buf = firstbuf;
2297 		while (buf->b_next != NULL && buf->b_ml.ml_mfp == NULL)
2298 		    buf = buf->b_next;
2299 		ea.line1 = buf->b_fnum;
2300 		buf = lastbuf;
2301 		while (buf->b_prev != NULL && buf->b_ml.ml_mfp == NULL)
2302 		    buf = buf->b_prev;
2303 		ea.line2 = buf->b_fnum;
2304 		break;
2305 	    case ADDR_BUFFERS:
2306 		ea.line1 = firstbuf->b_fnum;
2307 		ea.line2 = lastbuf->b_fnum;
2308 		break;
2309 	    case ADDR_WINDOWS:
2310 		ea.line2 = LAST_WIN_NR;
2311 		break;
2312 	    case ADDR_TABS:
2313 		ea.line2 = LAST_TAB_NR;
2314 		break;
2315 	    case ADDR_TABS_RELATIVE:
2316 		ea.line2 = 1;
2317 		break;
2318 	    case ADDR_ARGUMENTS:
2319 		if (ARGCOUNT == 0)
2320 		    ea.line1 = ea.line2 = 0;
2321 		else
2322 		    ea.line2 = ARGCOUNT;
2323 		break;
2324 	    case ADDR_QUICKFIX_VALID:
2325 #ifdef FEAT_QUICKFIX
2326 		ea.line2 = qf_get_valid_size(&ea);
2327 		if (ea.line2 == 0)
2328 		    ea.line2 = 1;
2329 #endif
2330 		break;
2331 	    case ADDR_NONE:
2332 	    case ADDR_UNSIGNED:
2333 	    case ADDR_QUICKFIX:
2334 		iemsg(_("INTERNAL: Cannot use EX_DFLALL with ADDR_NONE, ADDR_UNSIGNED or ADDR_QUICKFIX"));
2335 		break;
2336 	}
2337     }
2338 
2339     // accept numbered register only when no count allowed (:put)
2340     if (       (ea.argt & EX_REGSTR)
2341 	    && *ea.arg != NUL
2342 	       // Do not allow register = for user commands
2343 	    && (!IS_USER_CMDIDX(ea.cmdidx) || *ea.arg != '=')
2344 	    && !((ea.argt & EX_COUNT) && VIM_ISDIGIT(*ea.arg)))
2345     {
2346 #ifndef FEAT_CLIPBOARD
2347 	// check these explicitly for a more specific error message
2348 	if (*ea.arg == '*' || *ea.arg == '+')
2349 	{
2350 	    errormsg = _(e_invalidreg);
2351 	    goto doend;
2352 	}
2353 #endif
2354 	if (valid_yank_reg(*ea.arg, (ea.cmdidx != CMD_put
2355 					      && !IS_USER_CMDIDX(ea.cmdidx))))
2356 	{
2357 	    ea.regname = *ea.arg++;
2358 #ifdef FEAT_EVAL
2359 	    // for '=' register: accept the rest of the line as an expression
2360 	    if (ea.arg[-1] == '=' && ea.arg[0] != NUL)
2361 	    {
2362 		set_expr_line(vim_strsave(ea.arg));
2363 		ea.arg += STRLEN(ea.arg);
2364 	    }
2365 #endif
2366 	    ea.arg = skipwhite(ea.arg);
2367 	}
2368     }
2369 
2370     /*
2371      * Check for a count.  When accepting a EX_BUFNAME, don't use "123foo" as a
2372      * count, it's a buffer name.
2373      */
2374     if ((ea.argt & EX_COUNT) && VIM_ISDIGIT(*ea.arg)
2375 	    && (!(ea.argt & EX_BUFNAME) || *(p = skipdigits(ea.arg)) == NUL
2376 							  || VIM_ISWHITE(*p)))
2377     {
2378 	n = getdigits(&ea.arg);
2379 	ea.arg = skipwhite(ea.arg);
2380 	if (n <= 0 && !ni && (ea.argt & EX_ZEROR) == 0)
2381 	{
2382 	    errormsg = _(e_zerocount);
2383 	    goto doend;
2384 	}
2385 	if (ea.addr_type != ADDR_LINES)	// e.g. :buffer 2, :sleep 3
2386 	{
2387 	    ea.line2 = n;
2388 	    if (ea.addr_count == 0)
2389 		ea.addr_count = 1;
2390 	}
2391 	else
2392 	{
2393 	    ea.line1 = ea.line2;
2394 	    ea.line2 += n - 1;
2395 	    ++ea.addr_count;
2396 	    /*
2397 	     * Be vi compatible: no error message for out of range.
2398 	     */
2399 	    if (ea.line2 > curbuf->b_ml.ml_line_count)
2400 		ea.line2 = curbuf->b_ml.ml_line_count;
2401 	}
2402     }
2403 
2404     /*
2405      * Check for flags: 'l', 'p' and '#'.
2406      */
2407     if (ea.argt & EX_FLAGS)
2408 	get_flags(&ea);
2409     if (!ni && !(ea.argt & EX_EXTRA) && *ea.arg != NUL
2410 	    && *ea.arg != '"' && (*ea.arg != '|' || (ea.argt & EX_TRLBAR) == 0))
2411     {
2412 	// no arguments allowed but there is something
2413 	errormsg = ex_errmsg(e_trailing_arg, ea.arg);
2414 	goto doend;
2415     }
2416 
2417     if (!ni && (ea.argt & EX_NEEDARG) && *ea.arg == NUL)
2418     {
2419 	errormsg = _(e_argreq);
2420 	goto doend;
2421     }
2422 
2423 #ifdef FEAT_EVAL
2424     /*
2425      * Skip the command when it's not going to be executed.
2426      * The commands like :if, :endif, etc. always need to be executed.
2427      * Also make an exception for commands that handle a trailing command
2428      * themselves.
2429      */
2430     if (ea.skip)
2431     {
2432 	switch (ea.cmdidx)
2433 	{
2434 	    // commands that need evaluation
2435 	    case CMD_while:
2436 	    case CMD_endwhile:
2437 	    case CMD_for:
2438 	    case CMD_endfor:
2439 	    case CMD_if:
2440 	    case CMD_elseif:
2441 	    case CMD_else:
2442 	    case CMD_endif:
2443 	    case CMD_try:
2444 	    case CMD_catch:
2445 	    case CMD_finally:
2446 	    case CMD_endtry:
2447 	    case CMD_function:
2448 	    case CMD_def:
2449 				break;
2450 
2451 	    // Commands that handle '|' themselves.  Check: A command should
2452 	    // either have the EX_TRLBAR flag, appear in this list or appear in
2453 	    // the list at ":help :bar".
2454 	    case CMD_aboveleft:
2455 	    case CMD_and:
2456 	    case CMD_belowright:
2457 	    case CMD_botright:
2458 	    case CMD_browse:
2459 	    case CMD_call:
2460 	    case CMD_confirm:
2461 	    case CMD_const:
2462 	    case CMD_delfunction:
2463 	    case CMD_djump:
2464 	    case CMD_dlist:
2465 	    case CMD_dsearch:
2466 	    case CMD_dsplit:
2467 	    case CMD_echo:
2468 	    case CMD_echoerr:
2469 	    case CMD_echomsg:
2470 	    case CMD_echon:
2471 	    case CMD_eval:
2472 	    case CMD_execute:
2473 	    case CMD_filter:
2474 	    case CMD_help:
2475 	    case CMD_hide:
2476 	    case CMD_ijump:
2477 	    case CMD_ilist:
2478 	    case CMD_isearch:
2479 	    case CMD_isplit:
2480 	    case CMD_keepalt:
2481 	    case CMD_keepjumps:
2482 	    case CMD_keepmarks:
2483 	    case CMD_keeppatterns:
2484 	    case CMD_leftabove:
2485 	    case CMD_let:
2486 	    case CMD_lockmarks:
2487 	    case CMD_lockvar:
2488 	    case CMD_lua:
2489 	    case CMD_match:
2490 	    case CMD_mzscheme:
2491 	    case CMD_noautocmd:
2492 	    case CMD_noswapfile:
2493 	    case CMD_perl:
2494 	    case CMD_psearch:
2495 	    case CMD_python:
2496 	    case CMD_py3:
2497 	    case CMD_python3:
2498 	    case CMD_return:
2499 	    case CMD_rightbelow:
2500 	    case CMD_ruby:
2501 	    case CMD_silent:
2502 	    case CMD_smagic:
2503 	    case CMD_snomagic:
2504 	    case CMD_substitute:
2505 	    case CMD_syntax:
2506 	    case CMD_tab:
2507 	    case CMD_tcl:
2508 	    case CMD_throw:
2509 	    case CMD_tilde:
2510 	    case CMD_topleft:
2511 	    case CMD_unlet:
2512 	    case CMD_unlockvar:
2513 	    case CMD_verbose:
2514 	    case CMD_vertical:
2515 	    case CMD_wincmd:
2516 				break;
2517 
2518 	    default:		goto doend;
2519 	}
2520     }
2521 #endif
2522 
2523     if (ea.argt & EX_XFILE)
2524     {
2525 	if (expand_filename(&ea, cmdlinep, &errormsg) == FAIL)
2526 	    goto doend;
2527     }
2528 
2529     /*
2530      * Accept buffer name.  Cannot be used at the same time with a buffer
2531      * number.  Don't do this for a user command.
2532      */
2533     if ((ea.argt & EX_BUFNAME) && *ea.arg != NUL && ea.addr_count == 0
2534 	    && !IS_USER_CMDIDX(ea.cmdidx))
2535     {
2536 	/*
2537 	 * :bdelete, :bwipeout and :bunload take several arguments, separated
2538 	 * by spaces: find next space (skipping over escaped characters).
2539 	 * The others take one argument: ignore trailing spaces.
2540 	 */
2541 	if (ea.cmdidx == CMD_bdelete || ea.cmdidx == CMD_bwipeout
2542 						  || ea.cmdidx == CMD_bunload)
2543 	    p = skiptowhite_esc(ea.arg);
2544 	else
2545 	{
2546 	    p = ea.arg + STRLEN(ea.arg);
2547 	    while (p > ea.arg && VIM_ISWHITE(p[-1]))
2548 		--p;
2549 	}
2550 	ea.line2 = buflist_findpat(ea.arg, p, (ea.argt & EX_BUFUNL) != 0,
2551 								FALSE, FALSE);
2552 	if (ea.line2 < 0)	    // failed
2553 	    goto doend;
2554 	ea.addr_count = 1;
2555 	ea.arg = skipwhite(p);
2556     }
2557 
2558     // The :try command saves the emsg_silent flag, reset it here when
2559     // ":silent! try" was used, it should only apply to :try itself.
2560     if (ea.cmdidx == CMD_try && ea.did_esilent > 0)
2561     {
2562 	emsg_silent -= ea.did_esilent;
2563 	if (emsg_silent < 0)
2564 	    emsg_silent = 0;
2565 	ea.did_esilent = 0;
2566     }
2567 
2568 /*
2569  * 7. Execute the command.
2570  */
2571 
2572     if (IS_USER_CMDIDX(ea.cmdidx))
2573     {
2574 	/*
2575 	 * Execute a user-defined command.
2576 	 */
2577 	do_ucmd(&ea);
2578     }
2579     else
2580     {
2581 	/*
2582 	 * Call the function to execute the builtin command.
2583 	 */
2584 	ea.errmsg = NULL;
2585 	(cmdnames[ea.cmdidx].cmd_func)(&ea);
2586 	if (ea.errmsg != NULL)
2587 	    errormsg = ea.errmsg;
2588     }
2589 
2590 #ifdef FEAT_EVAL
2591     // Set flag that any command was executed, used by ex_vim9script().
2592     if (getline_equal(ea.getline, ea.cookie, getsourceline)
2593 						    && current_sctx.sc_sid > 0)
2594 	SCRIPT_ITEM(current_sctx.sc_sid)->sn_had_command = TRUE;
2595 
2596     /*
2597      * If the command just executed called do_cmdline(), any throw or ":return"
2598      * or ":finish" encountered there must also check the cstack of the still
2599      * active do_cmdline() that called this do_one_cmd().  Rethrow an uncaught
2600      * exception, or reanimate a returned function or finished script file and
2601      * return or finish it again.
2602      */
2603     if (need_rethrow)
2604 	do_throw(cstack);
2605     else if (check_cstack)
2606     {
2607 	if (source_finished(fgetline, cookie))
2608 	    do_finish(&ea, TRUE);
2609 	else if (getline_equal(fgetline, cookie, get_func_line)
2610 						   && current_func_returned())
2611 	    do_return(&ea, TRUE, FALSE, NULL);
2612     }
2613     need_rethrow = check_cstack = FALSE;
2614 #endif
2615 
2616 doend:
2617     if (curwin->w_cursor.lnum == 0)	// can happen with zero line number
2618     {
2619 	curwin->w_cursor.lnum = 1;
2620 	curwin->w_cursor.col = 0;
2621     }
2622 
2623     if (errormsg != NULL && *errormsg != NUL && !did_emsg)
2624     {
2625 	if (sourcing)
2626 	{
2627 	    if (errormsg != (char *)IObuff)
2628 	    {
2629 		STRCPY(IObuff, errormsg);
2630 		errormsg = (char *)IObuff;
2631 	    }
2632 	    append_command(*cmdlinep);
2633 	}
2634 	emsg(errormsg);
2635     }
2636 #ifdef FEAT_EVAL
2637     do_errthrow(cstack,
2638 	    (ea.cmdidx != CMD_SIZE && !IS_USER_CMDIDX(ea.cmdidx))
2639 			? cmdnames[(int)ea.cmdidx].cmd_name : (char_u *)NULL);
2640 #endif
2641 
2642     undo_cmdmod(&ea, save_msg_scroll);
2643     cmdmod = save_cmdmod;
2644     reg_executing = save_reg_executing;
2645 
2646 #ifdef HAVE_SANDBOX
2647     if (ea.did_sandbox)
2648 	--sandbox;
2649 #endif
2650 
2651     if (ea.nextcmd && *ea.nextcmd == NUL)	// not really a next command
2652 	ea.nextcmd = NULL;
2653 
2654 #ifdef FEAT_EVAL
2655     --ex_nesting_level;
2656     vim_free(ea.cmdline_tofree);
2657 #endif
2658 
2659     return ea.nextcmd;
2660 }
2661 #if (_MSC_VER == 1200)
2662  #pragma optimize( "", on )
2663 #endif
2664 
2665 static char ex_error_buf[MSG_BUF_LEN];
2666 
2667 /*
2668  * Return an error message with argument included.
2669  * Uses a static buffer, only the last error will be kept.
2670  * "msg" will be translated, caller should use N_().
2671  */
2672      char *
2673 ex_errmsg(char *msg, char_u *arg)
2674 {
2675     vim_snprintf(ex_error_buf, MSG_BUF_LEN, _(msg), arg);
2676     return ex_error_buf;
2677 }
2678 
2679 /*
2680  * Parse and skip over command modifiers:
2681  * - update eap->cmd
2682  * - store flags in "cmdmod".
2683  * - Set ex_pressedreturn for an empty command line.
2684  * - set msg_silent for ":silent"
2685  * - set 'eventignore' to "all" for ":noautocmd"
2686  * - set p_verbose for ":verbose"
2687  * - Increment "sandbox" for ":sandbox"
2688  * When "skip_only" is TRUE the global variables are not changed, except for
2689  * "cmdmod".
2690  * Return FAIL when the command is not to be executed.
2691  * May set "errormsg" to an error message.
2692  */
2693     int
2694 parse_command_modifiers(exarg_T *eap, char **errormsg, int skip_only)
2695 {
2696     char_u  *p;
2697     int	    starts_with_colon = FALSE;
2698 
2699     CLEAR_FIELD(cmdmod);
2700     eap->verbose_save = -1;
2701     eap->save_msg_silent = -1;
2702 
2703     // Repeat until no more command modifiers are found.
2704     for (;;)
2705     {
2706 	while (*eap->cmd == ' ' || *eap->cmd == '\t' || *eap->cmd == ':')
2707 	{
2708 	    if (*eap->cmd == ':')
2709 		starts_with_colon = TRUE;
2710 	    ++eap->cmd;
2711 	}
2712 
2713 	// in ex mode, an empty line works like :+
2714 	if (*eap->cmd == NUL && exmode_active
2715 		   && (getline_equal(eap->getline, eap->cookie, getexmodeline)
2716 		       || getline_equal(eap->getline, eap->cookie, getexline))
2717 			&& curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
2718 	{
2719 	    eap->cmd = (char_u *)"+";
2720 	    if (!skip_only)
2721 		ex_pressedreturn = TRUE;
2722 	}
2723 
2724 	// ignore comment and empty lines
2725 	if (comment_start(eap->cmd, starts_with_colon))
2726 	    return FAIL;
2727 	if (*eap->cmd == NUL)
2728 	{
2729 	    if (!skip_only)
2730 		ex_pressedreturn = TRUE;
2731 	    return FAIL;
2732 	}
2733 
2734 	p = skip_range(eap->cmd, NULL);
2735 	switch (*p)
2736 	{
2737 	    // When adding an entry, also modify cmd_exists().
2738 	    case 'a':	if (!checkforcmd(&eap->cmd, "aboveleft", 3))
2739 			    break;
2740 			cmdmod.split |= WSP_ABOVE;
2741 			continue;
2742 
2743 	    case 'b':	if (checkforcmd(&eap->cmd, "belowright", 3))
2744 			{
2745 			    cmdmod.split |= WSP_BELOW;
2746 			    continue;
2747 			}
2748 			if (checkforcmd(&eap->cmd, "browse", 3))
2749 			{
2750 #ifdef FEAT_BROWSE_CMD
2751 			    cmdmod.browse = TRUE;
2752 #endif
2753 			    continue;
2754 			}
2755 			if (!checkforcmd(&eap->cmd, "botright", 2))
2756 			    break;
2757 			cmdmod.split |= WSP_BOT;
2758 			continue;
2759 
2760 	    case 'c':	if (!checkforcmd(&eap->cmd, "confirm", 4))
2761 			    break;
2762 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
2763 			cmdmod.confirm = TRUE;
2764 #endif
2765 			continue;
2766 
2767 	    case 'k':	if (checkforcmd(&eap->cmd, "keepmarks", 3))
2768 			{
2769 			    cmdmod.keepmarks = TRUE;
2770 			    continue;
2771 			}
2772 			if (checkforcmd(&eap->cmd, "keepalt", 5))
2773 			{
2774 			    cmdmod.keepalt = TRUE;
2775 			    continue;
2776 			}
2777 			if (checkforcmd(&eap->cmd, "keeppatterns", 5))
2778 			{
2779 			    cmdmod.keeppatterns = TRUE;
2780 			    continue;
2781 			}
2782 			if (!checkforcmd(&eap->cmd, "keepjumps", 5))
2783 			    break;
2784 			cmdmod.keepjumps = TRUE;
2785 			continue;
2786 
2787 	    case 'f':	// only accept ":filter {pat} cmd"
2788 			{
2789 			    char_u *reg_pat;
2790 
2791 			    if (!checkforcmd(&p, "filter", 4)
2792 						|| *p == NUL || ends_excmd(*p))
2793 				break;
2794 			    if (*p == '!')
2795 			    {
2796 				cmdmod.filter_force = TRUE;
2797 				p = skipwhite(p + 1);
2798 				if (*p == NUL || ends_excmd(*p))
2799 				    break;
2800 			    }
2801 #ifdef FEAT_EVAL
2802 			    // Avoid that "filter(arg)" is recognized.
2803 			    if (in_vim9script() && !VIM_ISWHITE(*p))
2804 				break;
2805 #endif
2806 			    if (skip_only)
2807 				p = skip_vimgrep_pat(p, NULL, NULL);
2808 			    else
2809 				// NOTE: This puts a NUL after the pattern.
2810 				p = skip_vimgrep_pat(p, &reg_pat, NULL);
2811 			    if (p == NULL || *p == NUL)
2812 				break;
2813 			    if (!skip_only)
2814 			    {
2815 				cmdmod.filter_regmatch.regprog =
2816 						vim_regcomp(reg_pat, RE_MAGIC);
2817 				if (cmdmod.filter_regmatch.regprog == NULL)
2818 				    break;
2819 			    }
2820 			    eap->cmd = p;
2821 			    continue;
2822 			}
2823 
2824 			// ":hide" and ":hide | cmd" are not modifiers
2825 	    case 'h':	if (p != eap->cmd || !checkforcmd(&p, "hide", 3)
2826 					       || *p == NUL || ends_excmd(*p))
2827 			    break;
2828 			eap->cmd = p;
2829 			cmdmod.hide = TRUE;
2830 			continue;
2831 
2832 	    case 'l':	if (checkforcmd(&eap->cmd, "lockmarks", 3))
2833 			{
2834 			    cmdmod.lockmarks = TRUE;
2835 			    continue;
2836 			}
2837 
2838 			if (!checkforcmd(&eap->cmd, "leftabove", 5))
2839 			    break;
2840 			cmdmod.split |= WSP_ABOVE;
2841 			continue;
2842 
2843 	    case 'n':	if (checkforcmd(&eap->cmd, "noautocmd", 3))
2844 			{
2845 			    if (cmdmod.save_ei == NULL && !skip_only)
2846 			    {
2847 				// Set 'eventignore' to "all". Restore the
2848 				// existing option value later.
2849 				cmdmod.save_ei = vim_strsave(p_ei);
2850 				set_string_option_direct((char_u *)"ei", -1,
2851 					 (char_u *)"all", OPT_FREE, SID_NONE);
2852 			    }
2853 			    continue;
2854 			}
2855 			if (!checkforcmd(&eap->cmd, "noswapfile", 3))
2856 			    break;
2857 			cmdmod.noswapfile = TRUE;
2858 			continue;
2859 
2860 	    case 'r':	if (!checkforcmd(&eap->cmd, "rightbelow", 6))
2861 			    break;
2862 			cmdmod.split |= WSP_BELOW;
2863 			continue;
2864 
2865 	    case 's':	if (checkforcmd(&eap->cmd, "sandbox", 3))
2866 			{
2867 #ifdef HAVE_SANDBOX
2868 			    if (!skip_only)
2869 			    {
2870 				if (!eap->did_sandbox)
2871 				    ++sandbox;
2872 				eap->did_sandbox = TRUE;
2873 			    }
2874 #endif
2875 			    continue;
2876 			}
2877 			if (!checkforcmd(&eap->cmd, "silent", 3))
2878 			    break;
2879 			if (!skip_only)
2880 			{
2881 			    if (eap->save_msg_silent == -1)
2882 				eap->save_msg_silent = msg_silent;
2883 			    ++msg_silent;
2884 			}
2885 			if (*eap->cmd == '!' && !VIM_ISWHITE(eap->cmd[-1]))
2886 			{
2887 			    // ":silent!", but not "silent !cmd"
2888 			    eap->cmd = skipwhite(eap->cmd + 1);
2889 			    if (!skip_only)
2890 			    {
2891 				++emsg_silent;
2892 				++eap->did_esilent;
2893 			    }
2894 			}
2895 			continue;
2896 
2897 	    case 't':	if (checkforcmd(&p, "tab", 3))
2898 			{
2899 			    if (!skip_only)
2900 			    {
2901 				long tabnr = get_address(eap, &eap->cmd,
2902 						    ADDR_TABS, eap->skip,
2903 						    skip_only, FALSE, 1);
2904 				if (tabnr == MAXLNUM)
2905 				    cmdmod.tab = tabpage_index(curtab) + 1;
2906 				else
2907 				{
2908 				    if (tabnr < 0 || tabnr > LAST_TAB_NR)
2909 				    {
2910 					*errormsg = _(e_invrange);
2911 					return FAIL;
2912 				    }
2913 				    cmdmod.tab = tabnr + 1;
2914 				}
2915 			    }
2916 			    eap->cmd = p;
2917 			    continue;
2918 			}
2919 			if (!checkforcmd(&eap->cmd, "topleft", 2))
2920 			    break;
2921 			cmdmod.split |= WSP_TOP;
2922 			continue;
2923 
2924 	    case 'u':	if (!checkforcmd(&eap->cmd, "unsilent", 3))
2925 			    break;
2926 			if (!skip_only)
2927 			{
2928 			    if (eap->save_msg_silent == -1)
2929 				eap->save_msg_silent = msg_silent;
2930 			    msg_silent = 0;
2931 			}
2932 			continue;
2933 
2934 	    case 'v':	if (checkforcmd(&eap->cmd, "vertical", 4))
2935 			{
2936 			    cmdmod.split |= WSP_VERT;
2937 			    continue;
2938 			}
2939 			if (!checkforcmd(&p, "verbose", 4))
2940 			    break;
2941 			if (!skip_only)
2942 			{
2943 			    if (eap->verbose_save < 0)
2944 				eap->verbose_save = p_verbose;
2945 			    if (vim_isdigit(*eap->cmd))
2946 				p_verbose = atoi((char *)eap->cmd);
2947 			    else
2948 				p_verbose = 1;
2949 			}
2950 			eap->cmd = p;
2951 			continue;
2952 	}
2953 	break;
2954     }
2955 
2956     return OK;
2957 }
2958 
2959 /*
2960  * Undo and free contents of "cmdmod".
2961  */
2962     void
2963 undo_cmdmod(exarg_T *eap, int save_msg_scroll)
2964 {
2965     if (eap->verbose_save >= 0)
2966 	p_verbose = eap->verbose_save;
2967 
2968     if (cmdmod.save_ei != NULL)
2969     {
2970 	// Restore 'eventignore' to the value before ":noautocmd".
2971 	set_string_option_direct((char_u *)"ei", -1, cmdmod.save_ei,
2972 							  OPT_FREE, SID_NONE);
2973 	free_string_option(cmdmod.save_ei);
2974     }
2975 
2976     if (cmdmod.filter_regmatch.regprog != NULL)
2977 	vim_regfree(cmdmod.filter_regmatch.regprog);
2978 
2979     if (eap->save_msg_silent != -1)
2980     {
2981 	// messages could be enabled for a serious error, need to check if the
2982 	// counters don't become negative
2983 	if (!did_emsg || msg_silent > eap->save_msg_silent)
2984 	    msg_silent = eap->save_msg_silent;
2985 	emsg_silent -= eap->did_esilent;
2986 	if (emsg_silent < 0)
2987 	    emsg_silent = 0;
2988 	// Restore msg_scroll, it's set by file I/O commands, even when no
2989 	// message is actually displayed.
2990 	msg_scroll = save_msg_scroll;
2991 
2992 	// "silent reg" or "silent echo x" inside "redir" leaves msg_col
2993 	// somewhere in the line.  Put it back in the first column.
2994 	if (redirecting())
2995 	    msg_col = 0;
2996     }
2997 }
2998 
2999 /*
3000  * Parse the address range, if any, in "eap".
3001  * May set the last search pattern, unless "silent" is TRUE.
3002  * Return FAIL and set "errormsg" or return OK.
3003  */
3004     int
3005 parse_cmd_address(exarg_T *eap, char **errormsg, int silent)
3006 {
3007     int		address_count = 1;
3008     linenr_T	lnum;
3009 
3010     // Repeat for all ',' or ';' separated addresses.
3011     for (;;)
3012     {
3013 	eap->line1 = eap->line2;
3014 	switch (eap->addr_type)
3015 	{
3016 	    case ADDR_LINES:
3017 	    case ADDR_OTHER:
3018 		// Default is the cursor line number.  Avoid using an invalid
3019 		// line number though.
3020 		if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
3021 		    eap->line2 = curbuf->b_ml.ml_line_count;
3022 		else
3023 		    eap->line2 = curwin->w_cursor.lnum;
3024 		break;
3025 	    case ADDR_WINDOWS:
3026 		eap->line2 = CURRENT_WIN_NR;
3027 		break;
3028 	    case ADDR_ARGUMENTS:
3029 		eap->line2 = curwin->w_arg_idx + 1;
3030 		if (eap->line2 > ARGCOUNT)
3031 		    eap->line2 = ARGCOUNT;
3032 		break;
3033 	    case ADDR_LOADED_BUFFERS:
3034 	    case ADDR_BUFFERS:
3035 		eap->line2 = curbuf->b_fnum;
3036 		break;
3037 	    case ADDR_TABS:
3038 		eap->line2 = CURRENT_TAB_NR;
3039 		break;
3040 	    case ADDR_TABS_RELATIVE:
3041 	    case ADDR_UNSIGNED:
3042 		eap->line2 = 1;
3043 		break;
3044 	    case ADDR_QUICKFIX:
3045 #ifdef FEAT_QUICKFIX
3046 		eap->line2 = qf_get_cur_idx(eap);
3047 #endif
3048 		break;
3049 	    case ADDR_QUICKFIX_VALID:
3050 #ifdef FEAT_QUICKFIX
3051 		eap->line2 = qf_get_cur_valid_idx(eap);
3052 #endif
3053 		break;
3054 	    case ADDR_NONE:
3055 		// Will give an error later if a range is found.
3056 		break;
3057 	}
3058 	eap->cmd = skipwhite(eap->cmd);
3059 	lnum = get_address(eap, &eap->cmd, eap->addr_type, eap->skip, silent,
3060 					eap->addr_count == 0, address_count++);
3061 	if (eap->cmd == NULL)	// error detected
3062 	    return FAIL;
3063 	if (lnum == MAXLNUM)
3064 	{
3065 	    if (*eap->cmd == '%')   // '%' - all lines
3066 	    {
3067 		++eap->cmd;
3068 		switch (eap->addr_type)
3069 		{
3070 		    case ADDR_LINES:
3071 		    case ADDR_OTHER:
3072 			eap->line1 = 1;
3073 			eap->line2 = curbuf->b_ml.ml_line_count;
3074 			break;
3075 		    case ADDR_LOADED_BUFFERS:
3076 			{
3077 			    buf_T	*buf = firstbuf;
3078 
3079 			    while (buf->b_next != NULL
3080 						  && buf->b_ml.ml_mfp == NULL)
3081 				buf = buf->b_next;
3082 			    eap->line1 = buf->b_fnum;
3083 			    buf = lastbuf;
3084 			    while (buf->b_prev != NULL
3085 						  && buf->b_ml.ml_mfp == NULL)
3086 				buf = buf->b_prev;
3087 			    eap->line2 = buf->b_fnum;
3088 			    break;
3089 			}
3090 		    case ADDR_BUFFERS:
3091 			eap->line1 = firstbuf->b_fnum;
3092 			eap->line2 = lastbuf->b_fnum;
3093 			break;
3094 		    case ADDR_WINDOWS:
3095 		    case ADDR_TABS:
3096 			if (IS_USER_CMDIDX(eap->cmdidx))
3097 			{
3098 			    eap->line1 = 1;
3099 			    eap->line2 = eap->addr_type == ADDR_WINDOWS
3100 						  ? LAST_WIN_NR : LAST_TAB_NR;
3101 			}
3102 			else
3103 			{
3104 			    // there is no Vim command which uses '%' and
3105 			    // ADDR_WINDOWS or ADDR_TABS
3106 			    *errormsg = _(e_invrange);
3107 			    return FAIL;
3108 			}
3109 			break;
3110 		    case ADDR_TABS_RELATIVE:
3111 		    case ADDR_UNSIGNED:
3112 		    case ADDR_QUICKFIX:
3113 			*errormsg = _(e_invrange);
3114 			return FAIL;
3115 		    case ADDR_ARGUMENTS:
3116 			if (ARGCOUNT == 0)
3117 			    eap->line1 = eap->line2 = 0;
3118 			else
3119 			{
3120 			    eap->line1 = 1;
3121 			    eap->line2 = ARGCOUNT;
3122 			}
3123 			break;
3124 		    case ADDR_QUICKFIX_VALID:
3125 #ifdef FEAT_QUICKFIX
3126 			eap->line1 = 1;
3127 			eap->line2 = qf_get_valid_size(eap);
3128 			if (eap->line2 == 0)
3129 			    eap->line2 = 1;
3130 #endif
3131 			break;
3132 		    case ADDR_NONE:
3133 			// Will give an error later if a range is found.
3134 			break;
3135 		}
3136 		++eap->addr_count;
3137 	    }
3138 	    else if (*eap->cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL)
3139 	    {
3140 		pos_T	    *fp;
3141 
3142 		// '*' - visual area
3143 		if (eap->addr_type != ADDR_LINES)
3144 		{
3145 		    *errormsg = _(e_invrange);
3146 		    return FAIL;
3147 		}
3148 
3149 		++eap->cmd;
3150 		if (!eap->skip)
3151 		{
3152 		    fp = getmark('<', FALSE);
3153 		    if (check_mark(fp) == FAIL)
3154 			return FAIL;
3155 		    eap->line1 = fp->lnum;
3156 		    fp = getmark('>', FALSE);
3157 		    if (check_mark(fp) == FAIL)
3158 			return FAIL;
3159 		    eap->line2 = fp->lnum;
3160 		    ++eap->addr_count;
3161 		}
3162 	    }
3163 	}
3164 	else
3165 	    eap->line2 = lnum;
3166 	eap->addr_count++;
3167 
3168 	if (*eap->cmd == ';')
3169 	{
3170 	    if (!eap->skip)
3171 	    {
3172 		curwin->w_cursor.lnum = eap->line2;
3173 		// Don't leave the cursor on an illegal line or column, but do
3174 		// accept zero as address, so 0;/PATTERN/ works correctly.
3175 		if (eap->line2 > 0)
3176 		    check_cursor();
3177 	    }
3178 	}
3179 	else if (*eap->cmd != ',')
3180 	    break;
3181 	++eap->cmd;
3182     }
3183 
3184     // One address given: set start and end lines.
3185     if (eap->addr_count == 1)
3186     {
3187 	eap->line1 = eap->line2;
3188 	// ... but only implicit: really no address given
3189 	if (lnum == MAXLNUM)
3190 	    eap->addr_count = 0;
3191     }
3192     return OK;
3193 }
3194 
3195 /*
3196  * Check for an Ex command with optional tail.
3197  * If there is a match advance "pp" to the argument and return TRUE.
3198  */
3199     int
3200 checkforcmd(
3201     char_u	**pp,		// start of command
3202     char	*cmd,		// name of command
3203     int		len)		// required length
3204 {
3205     int		i;
3206 
3207     for (i = 0; cmd[i] != NUL; ++i)
3208 	if (((char_u *)cmd)[i] != (*pp)[i])
3209 	    break;
3210     if (i >= len && !isalpha((*pp)[i]))
3211     {
3212 	*pp = skipwhite(*pp + i);
3213 	return TRUE;
3214     }
3215     return FALSE;
3216 }
3217 
3218 /*
3219  * Append "cmd" to the error message in IObuff.
3220  * Takes care of limiting the length and handling 0xa0, which would be
3221  * invisible otherwise.
3222  */
3223     static void
3224 append_command(char_u *cmd)
3225 {
3226     char_u *s = cmd;
3227     char_u *d;
3228 
3229     STRCAT(IObuff, ": ");
3230     d = IObuff + STRLEN(IObuff);
3231     while (*s != NUL && d - IObuff < IOSIZE - 7)
3232     {
3233 	if (enc_utf8 ? (s[0] == 0xc2 && s[1] == 0xa0) : *s == 0xa0)
3234 	{
3235 	    s += enc_utf8 ? 2 : 1;
3236 	    STRCPY(d, "<a0>");
3237 	    d += 4;
3238 	}
3239 	else
3240 	    MB_COPY_CHAR(s, d);
3241     }
3242     *d = NUL;
3243 }
3244 
3245 /*
3246  * Find an Ex command by its name, either built-in or user.
3247  * Start of the name can be found at eap->cmd.
3248  * Sets eap->cmdidx and returns a pointer to char after the command name.
3249  * "full" is set to TRUE if the whole command name matched.
3250  *
3251  * If "lookup" is not NULL recognize expression without "eval" or "call" and
3252  * assignment without "let".  Sets eap->cmdidx to the command while returning
3253  * "eap->cmd".
3254  *
3255  * Returns NULL for an ambiguous user command.
3256  */
3257     char_u *
3258 find_ex_command(
3259 	exarg_T *eap,
3260 	int	*full UNUSED,
3261 	void	*(*lookup)(char_u *, size_t, cctx_T *) UNUSED,
3262 	cctx_T	*cctx UNUSED)
3263 {
3264     int		len;
3265     char_u	*p;
3266     int		i;
3267 
3268 #ifdef FEAT_EVAL
3269     /*
3270      * Recognize a Vim9 script function/method call and assignment:
3271      * "lvar = value", "lvar(arg)", "[1, 2 3]->Func()"
3272      */
3273     p = eap->cmd;
3274     if (lookup != NULL)
3275     {
3276 	// Skip over first char for "&opt = val", "$ENV = val" and "@r = val".
3277 	char_u *pskip = (*eap->cmd == '&' || *eap->cmd == '$'
3278 				|| *eap->cmd == '@') ? eap->cmd + 1 : eap->cmd;
3279 
3280 	if (vim_strchr((char_u *)"{('[\"", *p) != NULL
3281 	       || ((p = to_name_const_end(pskip)) > eap->cmd && *p != NUL))
3282 	{
3283 	    int oplen;
3284 	    int heredoc;
3285 
3286 	    if (
3287 		// "(..." is an expression.
3288 		// "funcname(" is always a function call.
3289 		*p == '('
3290 		    || (p == eap->cmd
3291 			? (
3292 			    // "{..." is an dict expression.
3293 			    *eap->cmd == '{'
3294 			    // "'string'->func()" is an expression.
3295 			 || *eap->cmd == '\''
3296 			    // '"string"->func()' is an expression.
3297 			 || *eap->cmd == '"'
3298 			    // "g:varname" is an expression.
3299 			 || eap->cmd[1] == ':'
3300 			    )
3301 			: (
3302 			    // "varname[]" is an expression.
3303 			    *p == '['
3304 			    // "varname->func()" is an expression.
3305 			 || (*p == '-' && p[1] == '>')
3306 			    // "varname.expr" is an expression.
3307 			 || (*p == '.' && ASCII_ISALPHA(p[1]))
3308 			 )))
3309 	    {
3310 		eap->cmdidx = CMD_eval;
3311 		return eap->cmd;
3312 	    }
3313 
3314 	    // "[...]->Method()" is a list expression, but "[a, b] = Func()" is
3315 	    // an assignment.
3316 	    // If there is no line break inside the "[...]" then "p" is
3317 	    // advanced to after the "]" by to_name_const_end(): check if a "="
3318 	    // follows.
3319 	    // If "[...]" has a line break "p" still points at the "[" and it
3320 	    // can't be an assignment.
3321 	    if (*eap->cmd == '[')
3322 	    {
3323 		p = to_name_const_end(eap->cmd);
3324 		if (p == eap->cmd || *skipwhite(p) != '=')
3325 		{
3326 		    eap->cmdidx = CMD_eval;
3327 		    return eap->cmd;
3328 		}
3329 		if (p > eap->cmd && *skipwhite(p) == '=')
3330 		{
3331 		    eap->cmdidx = CMD_let;
3332 		    return eap->cmd;
3333 		}
3334 	    }
3335 
3336 	    // Recognize an assignment if we recognize the variable name:
3337 	    // "g:var = expr"
3338 	    // "var = expr"  where "var" is a local var name.
3339 	    oplen = assignment_len(skipwhite(p), &heredoc);
3340 	    if (oplen > 0)
3341 	    {
3342 		if (((p - eap->cmd) > 2 && eap->cmd[1] == ':')
3343 			|| *eap->cmd == '&'
3344 			|| *eap->cmd == '$'
3345 			|| *eap->cmd == '@'
3346 			|| lookup(eap->cmd, p - eap->cmd, cctx) != NULL)
3347 		{
3348 		    eap->cmdidx = CMD_let;
3349 		    return eap->cmd;
3350 		}
3351 	    }
3352 
3353 	    // Recognize using a type for a w:, b:, t: or g: variable:
3354 	    // "w:varname: number = 123".
3355 	    if (eap->cmd[1] == ':' && *p == ':')
3356 	    {
3357 		eap->cmdidx = CMD_eval;
3358 		return eap->cmd;
3359 	    }
3360 	}
3361     }
3362 #endif
3363 
3364     /*
3365      * Isolate the command and search for it in the command table.
3366      * Exceptions:
3367      * - the 'k' command can directly be followed by any character.
3368      * - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
3369      *	    but :sre[wind] is another command, as are :scr[iptnames],
3370      *	    :scs[cope], :sim[alt], :sig[ns] and :sil[ent].
3371      * - the "d" command can directly be followed by 'l' or 'p' flag.
3372      */
3373     p = eap->cmd;
3374     if (*p == 'k')
3375     {
3376 	eap->cmdidx = CMD_k;
3377 	++p;
3378     }
3379     else if (p[0] == 's'
3380 	    && ((p[1] == 'c' && (p[2] == NUL || (p[2] != 's' && p[2] != 'r'
3381 			&& (p[3] == NUL || (p[3] != 'i' && p[4] != 'p')))))
3382 		|| p[1] == 'g'
3383 		|| (p[1] == 'i' && p[2] != 'm' && p[2] != 'l' && p[2] != 'g')
3384 		|| p[1] == 'I'
3385 		|| (p[1] == 'r' && p[2] != 'e')))
3386     {
3387 	eap->cmdidx = CMD_substitute;
3388 	++p;
3389     }
3390     else
3391     {
3392 	while (ASCII_ISALPHA(*p))
3393 	    ++p;
3394 	// for python 3.x support ":py3", ":python3", ":py3file", etc.
3395 	if (eap->cmd[0] == 'p' && eap->cmd[1] == 'y')
3396 	{
3397 	    while (ASCII_ISALNUM(*p))
3398 		++p;
3399 	}
3400 	else if (*p == '9' && STRNCMP("vim9", eap->cmd, 4) == 0)
3401 	{
3402 	    // include "9" for "vim9script"
3403 	    ++p;
3404 	    while (ASCII_ISALPHA(*p))
3405 		++p;
3406 	}
3407 
3408 	// check for non-alpha command
3409 	if (p == eap->cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL)
3410 	    ++p;
3411 	len = (int)(p - eap->cmd);
3412 	if (*eap->cmd == 'd' && (p[-1] == 'l' || p[-1] == 'p'))
3413 	{
3414 	    // Check for ":dl", ":dell", etc. to ":deletel": that's
3415 	    // :delete with the 'l' flag.  Same for 'p'.
3416 	    for (i = 0; i < len; ++i)
3417 		if (eap->cmd[i] != ((char_u *)"delete")[i])
3418 		    break;
3419 	    if (i == len - 1)
3420 	    {
3421 		--len;
3422 		if (p[-1] == 'l')
3423 		    eap->flags |= EXFLAG_LIST;
3424 		else
3425 		    eap->flags |= EXFLAG_PRINT;
3426 	    }
3427 	}
3428 
3429 	if (ASCII_ISLOWER(eap->cmd[0]))
3430 	{
3431 	    int c1 = eap->cmd[0];
3432 	    int c2 = len == 1 ? NUL : eap->cmd[1];
3433 
3434 	    if (command_count != (int)CMD_SIZE)
3435 	    {
3436 		iemsg(_("E943: Command table needs to be updated, run 'make cmdidxs'"));
3437 		getout(1);
3438 	    }
3439 
3440 	    // Use a precomputed index for fast look-up in cmdnames[]
3441 	    // taking into account the first 2 letters of eap->cmd.
3442 	    eap->cmdidx = cmdidxs1[CharOrdLow(c1)];
3443 	    if (ASCII_ISLOWER(c2))
3444 		eap->cmdidx += cmdidxs2[CharOrdLow(c1)][CharOrdLow(c2)];
3445 	}
3446 	else if (ASCII_ISUPPER(eap->cmd[0]))
3447 	    eap->cmdidx = CMD_Next;
3448 	else
3449 	    eap->cmdidx = CMD_bang;
3450 
3451 	for ( ; (int)eap->cmdidx < (int)CMD_SIZE;
3452 			       eap->cmdidx = (cmdidx_T)((int)eap->cmdidx + 1))
3453 	    if (STRNCMP(cmdnames[(int)eap->cmdidx].cmd_name, (char *)eap->cmd,
3454 							    (size_t)len) == 0)
3455 	    {
3456 #ifdef FEAT_EVAL
3457 		if (full != NULL
3458 			   && cmdnames[(int)eap->cmdidx].cmd_name[len] == NUL)
3459 		    *full = TRUE;
3460 #endif
3461 		break;
3462 	    }
3463 
3464 	// Look for a user defined command as a last resort.  Let ":Print" be
3465 	// overruled by a user defined command.
3466 	if ((eap->cmdidx == CMD_SIZE || eap->cmdidx == CMD_Print)
3467 		&& *eap->cmd >= 'A' && *eap->cmd <= 'Z')
3468 	{
3469 	    // User defined commands may contain digits.
3470 	    while (ASCII_ISALNUM(*p))
3471 		++p;
3472 	    p = find_ucmd(eap, p, full, NULL, NULL);
3473 	}
3474 	if (p == eap->cmd)
3475 	    eap->cmdidx = CMD_SIZE;
3476     }
3477 
3478     return p;
3479 }
3480 
3481 #if defined(FEAT_EVAL) || defined(PROTO)
3482 static struct cmdmod
3483 {
3484     char	*name;
3485     int		minlen;
3486     int		has_count;  // :123verbose  :3tab
3487 } cmdmods[] = {
3488     {"aboveleft", 3, FALSE},
3489     {"belowright", 3, FALSE},
3490     {"botright", 2, FALSE},
3491     {"browse", 3, FALSE},
3492     {"confirm", 4, FALSE},
3493     {"filter", 4, FALSE},
3494     {"hide", 3, FALSE},
3495     {"keepalt", 5, FALSE},
3496     {"keepjumps", 5, FALSE},
3497     {"keepmarks", 3, FALSE},
3498     {"keeppatterns", 5, FALSE},
3499     {"leftabove", 5, FALSE},
3500     {"lockmarks", 3, FALSE},
3501     {"noautocmd", 3, FALSE},
3502     {"noswapfile", 3, FALSE},
3503     {"rightbelow", 6, FALSE},
3504     {"sandbox", 3, FALSE},
3505     {"silent", 3, FALSE},
3506     {"tab", 3, TRUE},
3507     {"topleft", 2, FALSE},
3508     {"unsilent", 3, FALSE},
3509     {"verbose", 4, TRUE},
3510     {"vertical", 4, FALSE},
3511 };
3512 
3513 /*
3514  * Return length of a command modifier (including optional count).
3515  * Return zero when it's not a modifier.
3516  */
3517     int
3518 modifier_len(char_u *cmd)
3519 {
3520     int		i, j;
3521     char_u	*p = cmd;
3522 
3523     if (VIM_ISDIGIT(*cmd))
3524 	p = skipwhite(skipdigits(cmd));
3525     for (i = 0; i < (int)(sizeof(cmdmods) / sizeof(struct cmdmod)); ++i)
3526     {
3527 	for (j = 0; p[j] != NUL; ++j)
3528 	    if (p[j] != cmdmods[i].name[j])
3529 		break;
3530 	if (!ASCII_ISALPHA(p[j]) && j >= cmdmods[i].minlen
3531 					&& (p == cmd || cmdmods[i].has_count))
3532 	    return j + (int)(p - cmd);
3533     }
3534     return 0;
3535 }
3536 
3537 /*
3538  * Return > 0 if an Ex command "name" exists.
3539  * Return 2 if there is an exact match.
3540  * Return 3 if there is an ambiguous match.
3541  */
3542     int
3543 cmd_exists(char_u *name)
3544 {
3545     exarg_T	ea;
3546     int		full = FALSE;
3547     int		i;
3548     int		j;
3549     char_u	*p;
3550 
3551     // Check command modifiers.
3552     for (i = 0; i < (int)(sizeof(cmdmods) / sizeof(struct cmdmod)); ++i)
3553     {
3554 	for (j = 0; name[j] != NUL; ++j)
3555 	    if (name[j] != cmdmods[i].name[j])
3556 		break;
3557 	if (name[j] == NUL && j >= cmdmods[i].minlen)
3558 	    return (cmdmods[i].name[j] == NUL ? 2 : 1);
3559     }
3560 
3561     // Check built-in commands and user defined commands.
3562     // For ":2match" and ":3match" we need to skip the number.
3563     ea.cmd = (*name == '2' || *name == '3') ? name + 1 : name;
3564     ea.cmdidx = (cmdidx_T)0;
3565     p = find_ex_command(&ea, &full, NULL, NULL);
3566     if (p == NULL)
3567 	return 3;
3568     if (vim_isdigit(*name) && ea.cmdidx != CMD_match)
3569 	return 0;
3570     if (*skipwhite(p) != NUL)
3571 	return 0;	// trailing garbage
3572     return (ea.cmdidx == CMD_SIZE ? 0 : (full ? 2 : 1));
3573 }
3574 #endif
3575 
3576     cmdidx_T
3577 excmd_get_cmdidx(char_u *cmd, int len)
3578 {
3579     cmdidx_T idx;
3580 
3581     for (idx = (cmdidx_T)0; (int)idx < (int)CMD_SIZE;
3582 	    idx = (cmdidx_T)((int)idx + 1))
3583 	if (STRNCMP(cmdnames[(int)idx].cmd_name, cmd, (size_t)len) == 0)
3584 	    break;
3585 
3586     return idx;
3587 }
3588 
3589     long
3590 excmd_get_argt(cmdidx_T idx)
3591 {
3592     return (long)cmdnames[(int)idx].cmd_argt;
3593 }
3594 
3595 /*
3596  * Skip a range specifier of the form: addr [,addr] [;addr] ..
3597  *
3598  * Backslashed delimiters after / or ? will be skipped, and commands will
3599  * not be expanded between /'s and ?'s or after "'".
3600  *
3601  * Also skip white space and ":" characters after the range.
3602  * Returns the "cmd" pointer advanced to beyond the range.
3603  */
3604     char_u *
3605 skip_range(
3606     char_u	*cmd,
3607     int		*ctx)	// pointer to xp_context or NULL
3608 {
3609     unsigned	delim;
3610 
3611     while (vim_strchr((char_u *)" \t0123456789.$%'/?-+,;\\", *cmd) != NULL)
3612     {
3613 	if (*cmd == '\\')
3614 	{
3615 	    if (cmd[1] == '?' || cmd[1] == '/' || cmd[1] == '&')
3616 		++cmd;
3617 	    else
3618 		break;
3619 	}
3620 	else if (*cmd == '\'')
3621 	{
3622 	    if (*++cmd == NUL && ctx != NULL)
3623 		*ctx = EXPAND_NOTHING;
3624 	}
3625 	else if (*cmd == '/' || *cmd == '?')
3626 	{
3627 	    delim = *cmd++;
3628 	    while (*cmd != NUL && *cmd != delim)
3629 		if (*cmd++ == '\\' && *cmd != NUL)
3630 		    ++cmd;
3631 	    if (*cmd == NUL && ctx != NULL)
3632 		*ctx = EXPAND_NOTHING;
3633 	}
3634 	if (*cmd != NUL)
3635 	    ++cmd;
3636     }
3637 
3638     // Skip ":" and white space.
3639     while (*cmd == ':')
3640 	cmd = skipwhite(cmd + 1);
3641 
3642     return cmd;
3643 }
3644 
3645     static void
3646 addr_error(cmd_addr_T addr_type)
3647 {
3648     if (addr_type == ADDR_NONE)
3649 	emsg(_(e_norange));
3650     else
3651 	emsg(_(e_invrange));
3652 }
3653 
3654 /*
3655  * Get a single EX address.
3656  *
3657  * Set ptr to the next character after the part that was interpreted.
3658  * Set ptr to NULL when an error is encountered.
3659  * This may set the last used search pattern.
3660  *
3661  * Return MAXLNUM when no Ex address was found.
3662  */
3663     static linenr_T
3664 get_address(
3665     exarg_T	*eap UNUSED,
3666     char_u	**ptr,
3667     cmd_addr_T	addr_type,
3668     int		skip,		// only skip the address, don't use it
3669     int		silent,		// no errors or side effects
3670     int		to_other_file,  // flag: may jump to other file
3671     int		address_count UNUSED) // 1 for first address, >1 after comma
3672 {
3673     int		c;
3674     int		i;
3675     long	n;
3676     char_u	*cmd;
3677     pos_T	pos;
3678     pos_T	*fp;
3679     linenr_T	lnum;
3680     buf_T	*buf;
3681 
3682     cmd = skipwhite(*ptr);
3683     lnum = MAXLNUM;
3684     do
3685     {
3686 	switch (*cmd)
3687 	{
3688 	    case '.':			    // '.' - Cursor position
3689 		++cmd;
3690 		switch (addr_type)
3691 		{
3692 		    case ADDR_LINES:
3693 		    case ADDR_OTHER:
3694 			lnum = curwin->w_cursor.lnum;
3695 			break;
3696 		    case ADDR_WINDOWS:
3697 			lnum = CURRENT_WIN_NR;
3698 			break;
3699 		    case ADDR_ARGUMENTS:
3700 			lnum = curwin->w_arg_idx + 1;
3701 			break;
3702 		    case ADDR_LOADED_BUFFERS:
3703 		    case ADDR_BUFFERS:
3704 			lnum = curbuf->b_fnum;
3705 			break;
3706 		    case ADDR_TABS:
3707 			lnum = CURRENT_TAB_NR;
3708 			break;
3709 		    case ADDR_NONE:
3710 		    case ADDR_TABS_RELATIVE:
3711 		    case ADDR_UNSIGNED:
3712 			addr_error(addr_type);
3713 			cmd = NULL;
3714 			goto error;
3715 			break;
3716 		    case ADDR_QUICKFIX:
3717 #ifdef FEAT_QUICKFIX
3718 			lnum = qf_get_cur_idx(eap);
3719 #endif
3720 			break;
3721 		    case ADDR_QUICKFIX_VALID:
3722 #ifdef FEAT_QUICKFIX
3723 			lnum = qf_get_cur_valid_idx(eap);
3724 #endif
3725 			break;
3726 		}
3727 		break;
3728 
3729 	    case '$':			    // '$' - last line
3730 		++cmd;
3731 		switch (addr_type)
3732 		{
3733 		    case ADDR_LINES:
3734 		    case ADDR_OTHER:
3735 			lnum = curbuf->b_ml.ml_line_count;
3736 			break;
3737 		    case ADDR_WINDOWS:
3738 			lnum = LAST_WIN_NR;
3739 			break;
3740 		    case ADDR_ARGUMENTS:
3741 			lnum = ARGCOUNT;
3742 			break;
3743 		    case ADDR_LOADED_BUFFERS:
3744 			buf = lastbuf;
3745 			while (buf->b_ml.ml_mfp == NULL)
3746 			{
3747 			    if (buf->b_prev == NULL)
3748 				break;
3749 			    buf = buf->b_prev;
3750 			}
3751 			lnum = buf->b_fnum;
3752 			break;
3753 		    case ADDR_BUFFERS:
3754 			lnum = lastbuf->b_fnum;
3755 			break;
3756 		    case ADDR_TABS:
3757 			lnum = LAST_TAB_NR;
3758 			break;
3759 		    case ADDR_NONE:
3760 		    case ADDR_TABS_RELATIVE:
3761 		    case ADDR_UNSIGNED:
3762 			addr_error(addr_type);
3763 			cmd = NULL;
3764 			goto error;
3765 			break;
3766 		    case ADDR_QUICKFIX:
3767 #ifdef FEAT_QUICKFIX
3768 			lnum = qf_get_size(eap);
3769 			if (lnum == 0)
3770 			    lnum = 1;
3771 #endif
3772 			break;
3773 		    case ADDR_QUICKFIX_VALID:
3774 #ifdef FEAT_QUICKFIX
3775 			lnum = qf_get_valid_size(eap);
3776 			if (lnum == 0)
3777 			    lnum = 1;
3778 #endif
3779 			break;
3780 		}
3781 		break;
3782 
3783 	    case '\'':			    // ''' - mark
3784 		if (*++cmd == NUL)
3785 		{
3786 		    cmd = NULL;
3787 		    goto error;
3788 		}
3789 		if (addr_type != ADDR_LINES)
3790 		{
3791 		    addr_error(addr_type);
3792 		    cmd = NULL;
3793 		    goto error;
3794 		}
3795 		if (skip)
3796 		    ++cmd;
3797 		else
3798 		{
3799 		    // Only accept a mark in another file when it is
3800 		    // used by itself: ":'M".
3801 		    fp = getmark(*cmd, to_other_file && cmd[1] == NUL);
3802 		    ++cmd;
3803 		    if (fp == (pos_T *)-1)
3804 			// Jumped to another file.
3805 			lnum = curwin->w_cursor.lnum;
3806 		    else
3807 		    {
3808 			if (check_mark(fp) == FAIL)
3809 			{
3810 			    cmd = NULL;
3811 			    goto error;
3812 			}
3813 			lnum = fp->lnum;
3814 		    }
3815 		}
3816 		break;
3817 
3818 	    case '/':
3819 	    case '?':			// '/' or '?' - search
3820 		c = *cmd++;
3821 		if (addr_type != ADDR_LINES)
3822 		{
3823 		    addr_error(addr_type);
3824 		    cmd = NULL;
3825 		    goto error;
3826 		}
3827 		if (skip)	// skip "/pat/"
3828 		{
3829 		    cmd = skip_regexp(cmd, c, (int)p_magic);
3830 		    if (*cmd == c)
3831 			++cmd;
3832 		}
3833 		else
3834 		{
3835 		    int flags;
3836 
3837 		    pos = curwin->w_cursor; // save curwin->w_cursor
3838 
3839 		    // When '/' or '?' follows another address, start from
3840 		    // there.
3841 		    if (lnum != MAXLNUM)
3842 			curwin->w_cursor.lnum = lnum;
3843 
3844 		    // Start a forward search at the end of the line (unless
3845 		    // before the first line).
3846 		    // Start a backward search at the start of the line.
3847 		    // This makes sure we never match in the current
3848 		    // line, and can match anywhere in the
3849 		    // next/previous line.
3850 		    if (c == '/' && curwin->w_cursor.lnum > 0)
3851 			curwin->w_cursor.col = MAXCOL;
3852 		    else
3853 			curwin->w_cursor.col = 0;
3854 		    searchcmdlen = 0;
3855 		    flags = silent ? 0 : SEARCH_HIS | SEARCH_MSG;
3856 		    if (!do_search(NULL, c, c, cmd, 1L, flags, NULL))
3857 		    {
3858 			curwin->w_cursor = pos;
3859 			cmd = NULL;
3860 			goto error;
3861 		    }
3862 		    lnum = curwin->w_cursor.lnum;
3863 		    curwin->w_cursor = pos;
3864 		    // adjust command string pointer
3865 		    cmd += searchcmdlen;
3866 		}
3867 		break;
3868 
3869 	    case '\\':		    // "\?", "\/" or "\&", repeat search
3870 		++cmd;
3871 		if (addr_type != ADDR_LINES)
3872 		{
3873 		    addr_error(addr_type);
3874 		    cmd = NULL;
3875 		    goto error;
3876 		}
3877 		if (*cmd == '&')
3878 		    i = RE_SUBST;
3879 		else if (*cmd == '?' || *cmd == '/')
3880 		    i = RE_SEARCH;
3881 		else
3882 		{
3883 		    emsg(_(e_backslash));
3884 		    cmd = NULL;
3885 		    goto error;
3886 		}
3887 
3888 		if (!skip)
3889 		{
3890 		    /*
3891 		     * When search follows another address, start from
3892 		     * there.
3893 		     */
3894 		    if (lnum != MAXLNUM)
3895 			pos.lnum = lnum;
3896 		    else
3897 			pos.lnum = curwin->w_cursor.lnum;
3898 
3899 		    /*
3900 		     * Start the search just like for the above
3901 		     * do_search().
3902 		     */
3903 		    if (*cmd != '?')
3904 			pos.col = MAXCOL;
3905 		    else
3906 			pos.col = 0;
3907 		    pos.coladd = 0;
3908 		    if (searchit(curwin, curbuf, &pos, NULL,
3909 				*cmd == '?' ? BACKWARD : FORWARD,
3910 				(char_u *)"", 1L, SEARCH_MSG, i, NULL) != FAIL)
3911 			lnum = pos.lnum;
3912 		    else
3913 		    {
3914 			cmd = NULL;
3915 			goto error;
3916 		    }
3917 		}
3918 		++cmd;
3919 		break;
3920 
3921 	    default:
3922 		if (VIM_ISDIGIT(*cmd))	// absolute line number
3923 		    lnum = getdigits(&cmd);
3924 	}
3925 
3926 	for (;;)
3927 	{
3928 	    cmd = skipwhite(cmd);
3929 	    if (*cmd != '-' && *cmd != '+' && !VIM_ISDIGIT(*cmd))
3930 		break;
3931 
3932 	    if (lnum == MAXLNUM)
3933 	    {
3934 		switch (addr_type)
3935 		{
3936 		    case ADDR_LINES:
3937 		    case ADDR_OTHER:
3938 			// "+1" is same as ".+1"
3939 			lnum = curwin->w_cursor.lnum;
3940 			break;
3941 		    case ADDR_WINDOWS:
3942 			lnum = CURRENT_WIN_NR;
3943 			break;
3944 		    case ADDR_ARGUMENTS:
3945 			lnum = curwin->w_arg_idx + 1;
3946 			break;
3947 		    case ADDR_LOADED_BUFFERS:
3948 		    case ADDR_BUFFERS:
3949 			lnum = curbuf->b_fnum;
3950 			break;
3951 		    case ADDR_TABS:
3952 			lnum = CURRENT_TAB_NR;
3953 			break;
3954 		    case ADDR_TABS_RELATIVE:
3955 			lnum = 1;
3956 			break;
3957 		    case ADDR_QUICKFIX:
3958 #ifdef FEAT_QUICKFIX
3959 			lnum = qf_get_cur_idx(eap);
3960 #endif
3961 			break;
3962 		    case ADDR_QUICKFIX_VALID:
3963 #ifdef FEAT_QUICKFIX
3964 			lnum = qf_get_cur_valid_idx(eap);
3965 #endif
3966 			break;
3967 		    case ADDR_NONE:
3968 		    case ADDR_UNSIGNED:
3969 			lnum = 0;
3970 			break;
3971 		}
3972 	    }
3973 
3974 	    if (VIM_ISDIGIT(*cmd))
3975 		i = '+';		// "number" is same as "+number"
3976 	    else
3977 		i = *cmd++;
3978 	    if (!VIM_ISDIGIT(*cmd))	// '+' is '+1', but '+0' is not '+1'
3979 		n = 1;
3980 	    else
3981 		n = getdigits(&cmd);
3982 
3983 	    if (addr_type == ADDR_TABS_RELATIVE)
3984 	    {
3985 		emsg(_(e_invrange));
3986 		cmd = NULL;
3987 		goto error;
3988 	    }
3989 	    else if (addr_type == ADDR_LOADED_BUFFERS
3990 		    || addr_type == ADDR_BUFFERS)
3991 		lnum = compute_buffer_local_count(
3992 				    addr_type, lnum, (i == '-') ? -1 * n : n);
3993 	    else
3994 	    {
3995 #ifdef FEAT_FOLDING
3996 		// Relative line addressing, need to adjust for folded lines
3997 		// now, but only do it after the first address.
3998 		if (addr_type == ADDR_LINES && (i == '-' || i == '+')
3999 			&& address_count >= 2)
4000 		    (void)hasFolding(lnum, NULL, &lnum);
4001 #endif
4002 		if (i == '-')
4003 		    lnum -= n;
4004 		else
4005 		    lnum += n;
4006 	    }
4007 	}
4008     } while (*cmd == '/' || *cmd == '?');
4009 
4010 error:
4011     *ptr = cmd;
4012     return lnum;
4013 }
4014 
4015 /*
4016  * Get flags from an Ex command argument.
4017  */
4018     static void
4019 get_flags(exarg_T *eap)
4020 {
4021     while (vim_strchr((char_u *)"lp#", *eap->arg) != NULL)
4022     {
4023 	if (*eap->arg == 'l')
4024 	    eap->flags |= EXFLAG_LIST;
4025 	else if (*eap->arg == 'p')
4026 	    eap->flags |= EXFLAG_PRINT;
4027 	else
4028 	    eap->flags |= EXFLAG_NR;
4029 	eap->arg = skipwhite(eap->arg + 1);
4030     }
4031 }
4032 
4033 /*
4034  * Function called for command which is Not Implemented.  NI!
4035  */
4036     void
4037 ex_ni(exarg_T *eap)
4038 {
4039     if (!eap->skip)
4040 	eap->errmsg =
4041 		_("E319: Sorry, the command is not available in this version");
4042 }
4043 
4044 #ifdef HAVE_EX_SCRIPT_NI
4045 /*
4046  * Function called for script command which is Not Implemented.  NI!
4047  * Skips over ":perl <<EOF" constructs.
4048  */
4049     static void
4050 ex_script_ni(exarg_T *eap)
4051 {
4052     if (!eap->skip)
4053 	ex_ni(eap);
4054     else
4055 	vim_free(script_get(eap, eap->arg));
4056 }
4057 #endif
4058 
4059 /*
4060  * Check range in Ex command for validity.
4061  * Return NULL when valid, error message when invalid.
4062  */
4063     static char *
4064 invalid_range(exarg_T *eap)
4065 {
4066     buf_T	*buf;
4067 
4068     if (       eap->line1 < 0
4069 	    || eap->line2 < 0
4070 	    || eap->line1 > eap->line2)
4071 	return _(e_invrange);
4072 
4073     if (eap->argt & EX_RANGE)
4074     {
4075 	switch (eap->addr_type)
4076 	{
4077 	    case ADDR_LINES:
4078 		if (eap->line2 > curbuf->b_ml.ml_line_count
4079 #ifdef FEAT_DIFF
4080 			    + (eap->cmdidx == CMD_diffget)
4081 #endif
4082 		   )
4083 		    return _(e_invrange);
4084 		break;
4085 	    case ADDR_ARGUMENTS:
4086 		// add 1 if ARGCOUNT is 0
4087 		if (eap->line2 > ARGCOUNT + (!ARGCOUNT))
4088 		    return _(e_invrange);
4089 		break;
4090 	    case ADDR_BUFFERS:
4091 		// Only a boundary check, not whether the buffers actually
4092 		// exist.
4093 		if (eap->line1 < 1 || eap->line2 > get_highest_fnum())
4094 		    return _(e_invrange);
4095 		break;
4096 	    case ADDR_LOADED_BUFFERS:
4097 		buf = firstbuf;
4098 		while (buf->b_ml.ml_mfp == NULL)
4099 		{
4100 		    if (buf->b_next == NULL)
4101 			return _(e_invrange);
4102 		    buf = buf->b_next;
4103 		}
4104 		if (eap->line1 < buf->b_fnum)
4105 		    return _(e_invrange);
4106 		buf = lastbuf;
4107 		while (buf->b_ml.ml_mfp == NULL)
4108 		{
4109 		    if (buf->b_prev == NULL)
4110 			return _(e_invrange);
4111 		    buf = buf->b_prev;
4112 		}
4113 		if (eap->line2 > buf->b_fnum)
4114 		    return _(e_invrange);
4115 		break;
4116 	    case ADDR_WINDOWS:
4117 		if (eap->line2 > LAST_WIN_NR)
4118 		    return _(e_invrange);
4119 		break;
4120 	    case ADDR_TABS:
4121 		if (eap->line2 > LAST_TAB_NR)
4122 		    return _(e_invrange);
4123 		break;
4124 	    case ADDR_TABS_RELATIVE:
4125 	    case ADDR_OTHER:
4126 		// Any range is OK.
4127 		break;
4128 	    case ADDR_QUICKFIX:
4129 #ifdef FEAT_QUICKFIX
4130 		// No error for value that is too big, will use the last entry.
4131 		if (eap->line2 <= 0)
4132 		    return _(e_invrange);
4133 #endif
4134 		break;
4135 	    case ADDR_QUICKFIX_VALID:
4136 #ifdef FEAT_QUICKFIX
4137 		if ((eap->line2 != 1 && eap->line2 > qf_get_valid_size(eap))
4138 			|| eap->line2 < 0)
4139 		    return _(e_invrange);
4140 #endif
4141 		break;
4142 	    case ADDR_UNSIGNED:
4143 		if (eap->line2 < 0)
4144 		    return _(e_invrange);
4145 		break;
4146 	    case ADDR_NONE:
4147 		// Will give an error elsewhere.
4148 		break;
4149 	}
4150     }
4151     return NULL;
4152 }
4153 
4154 /*
4155  * Correct the range for zero line number, if required.
4156  */
4157     static void
4158 correct_range(exarg_T *eap)
4159 {
4160     if (!(eap->argt & EX_ZEROR))	    // zero in range not allowed
4161     {
4162 	if (eap->line1 == 0)
4163 	    eap->line1 = 1;
4164 	if (eap->line2 == 0)
4165 	    eap->line2 = 1;
4166     }
4167 }
4168 
4169 #ifdef FEAT_QUICKFIX
4170 /*
4171  * For a ":vimgrep" or ":vimgrepadd" command return a pointer past the
4172  * pattern.  Otherwise return eap->arg.
4173  */
4174     static char_u *
4175 skip_grep_pat(exarg_T *eap)
4176 {
4177     char_u	*p = eap->arg;
4178 
4179     if (*p != NUL && (eap->cmdidx == CMD_vimgrep || eap->cmdidx == CMD_lvimgrep
4180 		|| eap->cmdidx == CMD_vimgrepadd
4181 		|| eap->cmdidx == CMD_lvimgrepadd
4182 		|| grep_internal(eap->cmdidx)))
4183     {
4184 	p = skip_vimgrep_pat(p, NULL, NULL);
4185 	if (p == NULL)
4186 	    p = eap->arg;
4187     }
4188     return p;
4189 }
4190 
4191 /*
4192  * For the ":make" and ":grep" commands insert the 'makeprg'/'grepprg' option
4193  * in the command line, so that things like % get expanded.
4194  */
4195     static char_u *
4196 replace_makeprg(exarg_T *eap, char_u *p, char_u **cmdlinep)
4197 {
4198     char_u	*new_cmdline;
4199     char_u	*program;
4200     char_u	*pos;
4201     char_u	*ptr;
4202     int		len;
4203     int		i;
4204 
4205     /*
4206      * Don't do it when ":vimgrep" is used for ":grep".
4207      */
4208     if ((eap->cmdidx == CMD_make || eap->cmdidx == CMD_lmake
4209 		     || eap->cmdidx == CMD_grep || eap->cmdidx == CMD_lgrep
4210 		     || eap->cmdidx == CMD_grepadd
4211 		     || eap->cmdidx == CMD_lgrepadd)
4212 	    && !grep_internal(eap->cmdidx))
4213     {
4214 	if (eap->cmdidx == CMD_grep || eap->cmdidx == CMD_lgrep
4215 	    || eap->cmdidx == CMD_grepadd || eap->cmdidx == CMD_lgrepadd)
4216 	{
4217 	    if (*curbuf->b_p_gp == NUL)
4218 		program = p_gp;
4219 	    else
4220 		program = curbuf->b_p_gp;
4221 	}
4222 	else
4223 	{
4224 	    if (*curbuf->b_p_mp == NUL)
4225 		program = p_mp;
4226 	    else
4227 		program = curbuf->b_p_mp;
4228 	}
4229 
4230 	p = skipwhite(p);
4231 
4232 	if ((pos = (char_u *)strstr((char *)program, "$*")) != NULL)
4233 	{
4234 	    // replace $* by given arguments
4235 	    i = 1;
4236 	    while ((pos = (char_u *)strstr((char *)pos + 2, "$*")) != NULL)
4237 		++i;
4238 	    len = (int)STRLEN(p);
4239 	    new_cmdline = alloc(STRLEN(program) + i * (len - 2) + 1);
4240 	    if (new_cmdline == NULL)
4241 		return NULL;			// out of memory
4242 	    ptr = new_cmdline;
4243 	    while ((pos = (char_u *)strstr((char *)program, "$*")) != NULL)
4244 	    {
4245 		i = (int)(pos - program);
4246 		STRNCPY(ptr, program, i);
4247 		STRCPY(ptr += i, p);
4248 		ptr += len;
4249 		program = pos + 2;
4250 	    }
4251 	    STRCPY(ptr, program);
4252 	}
4253 	else
4254 	{
4255 	    new_cmdline = alloc(STRLEN(program) + STRLEN(p) + 2);
4256 	    if (new_cmdline == NULL)
4257 		return NULL;			// out of memory
4258 	    STRCPY(new_cmdline, program);
4259 	    STRCAT(new_cmdline, " ");
4260 	    STRCAT(new_cmdline, p);
4261 	}
4262 	msg_make(p);
4263 
4264 	// 'eap->cmd' is not set here, because it is not used at CMD_make
4265 	vim_free(*cmdlinep);
4266 	*cmdlinep = new_cmdline;
4267 	p = new_cmdline;
4268     }
4269     return p;
4270 }
4271 #endif
4272 
4273 /*
4274  * Expand file name in Ex command argument.
4275  * When an error is detected, "errormsgp" is set to a non-NULL pointer.
4276  * Return FAIL for failure, OK otherwise.
4277  */
4278     int
4279 expand_filename(
4280     exarg_T	*eap,
4281     char_u	**cmdlinep,
4282     char	**errormsgp)
4283 {
4284     int		has_wildcards;	// need to expand wildcards
4285     char_u	*repl;
4286     int		srclen;
4287     char_u	*p;
4288     int		n;
4289     int		escaped;
4290 
4291 #ifdef FEAT_QUICKFIX
4292     // Skip a regexp pattern for ":vimgrep[add] pat file..."
4293     p = skip_grep_pat(eap);
4294 #else
4295     p = eap->arg;
4296 #endif
4297 
4298     /*
4299      * Decide to expand wildcards *before* replacing '%', '#', etc.  If
4300      * the file name contains a wildcard it should not cause expanding.
4301      * (it will be expanded anyway if there is a wildcard before replacing).
4302      */
4303     has_wildcards = mch_has_wildcard(p);
4304     while (*p != NUL)
4305     {
4306 #ifdef FEAT_EVAL
4307 	// Skip over `=expr`, wildcards in it are not expanded.
4308 	if (p[0] == '`' && p[1] == '=')
4309 	{
4310 	    p += 2;
4311 	    (void)skip_expr(&p);
4312 	    if (*p == '`')
4313 		++p;
4314 	    continue;
4315 	}
4316 #endif
4317 	/*
4318 	 * Quick check if this cannot be the start of a special string.
4319 	 * Also removes backslash before '%', '#' and '<'.
4320 	 */
4321 	if (vim_strchr((char_u *)"%#<", *p) == NULL)
4322 	{
4323 	    ++p;
4324 	    continue;
4325 	}
4326 
4327 	/*
4328 	 * Try to find a match at this position.
4329 	 */
4330 	repl = eval_vars(p, eap->arg, &srclen, &(eap->do_ecmd_lnum),
4331 							 errormsgp, &escaped);
4332 	if (*errormsgp != NULL)		// error detected
4333 	    return FAIL;
4334 	if (repl == NULL)		// no match found
4335 	{
4336 	    p += srclen;
4337 	    continue;
4338 	}
4339 
4340 	// Wildcards won't be expanded below, the replacement is taken
4341 	// literally.  But do expand "~/file", "~user/file" and "$HOME/file".
4342 	if (vim_strchr(repl, '$') != NULL || vim_strchr(repl, '~') != NULL)
4343 	{
4344 	    char_u *l = repl;
4345 
4346 	    repl = expand_env_save(repl);
4347 	    vim_free(l);
4348 	}
4349 
4350 	// Need to escape white space et al. with a backslash.
4351 	// Don't do this for:
4352 	// - replacement that already has been escaped: "##"
4353 	// - shell commands (may have to use quotes instead).
4354 	// - non-unix systems when there is a single argument (spaces don't
4355 	//   separate arguments then).
4356 	if (!eap->usefilter
4357 		&& !escaped
4358 		&& eap->cmdidx != CMD_bang
4359 		&& eap->cmdidx != CMD_grep
4360 		&& eap->cmdidx != CMD_grepadd
4361 		&& eap->cmdidx != CMD_hardcopy
4362 		&& eap->cmdidx != CMD_lgrep
4363 		&& eap->cmdidx != CMD_lgrepadd
4364 		&& eap->cmdidx != CMD_lmake
4365 		&& eap->cmdidx != CMD_make
4366 		&& eap->cmdidx != CMD_terminal
4367 #ifndef UNIX
4368 		&& !(eap->argt & EX_NOSPC)
4369 #endif
4370 		)
4371 	{
4372 	    char_u	*l;
4373 #ifdef BACKSLASH_IN_FILENAME
4374 	    // Don't escape a backslash here, because rem_backslash() doesn't
4375 	    // remove it later.
4376 	    static char_u *nobslash = (char_u *)" \t\"|";
4377 # define ESCAPE_CHARS nobslash
4378 #else
4379 # define ESCAPE_CHARS escape_chars
4380 #endif
4381 
4382 	    for (l = repl; *l; ++l)
4383 		if (vim_strchr(ESCAPE_CHARS, *l) != NULL)
4384 		{
4385 		    l = vim_strsave_escaped(repl, ESCAPE_CHARS);
4386 		    if (l != NULL)
4387 		    {
4388 			vim_free(repl);
4389 			repl = l;
4390 		    }
4391 		    break;
4392 		}
4393 	}
4394 
4395 	// For a shell command a '!' must be escaped.
4396 	if ((eap->usefilter || eap->cmdidx == CMD_bang
4397 						|| eap->cmdidx == CMD_terminal)
4398 			    && vim_strpbrk(repl, (char_u *)"!") != NULL)
4399 	{
4400 	    char_u	*l;
4401 
4402 	    l = vim_strsave_escaped(repl, (char_u *)"!");
4403 	    if (l != NULL)
4404 	    {
4405 		vim_free(repl);
4406 		repl = l;
4407 	    }
4408 	}
4409 
4410 	p = repl_cmdline(eap, p, srclen, repl, cmdlinep);
4411 	vim_free(repl);
4412 	if (p == NULL)
4413 	    return FAIL;
4414     }
4415 
4416     /*
4417      * One file argument: Expand wildcards.
4418      * Don't do this with ":r !command" or ":w !command".
4419      */
4420     if ((eap->argt & EX_NOSPC) && !eap->usefilter)
4421     {
4422 	/*
4423 	 * May do this twice:
4424 	 * 1. Replace environment variables.
4425 	 * 2. Replace any other wildcards, remove backslashes.
4426 	 */
4427 	for (n = 1; n <= 2; ++n)
4428 	{
4429 	    if (n == 2)
4430 	    {
4431 		/*
4432 		 * Halve the number of backslashes (this is Vi compatible).
4433 		 * For Unix and OS/2, when wildcards are expanded, this is
4434 		 * done by ExpandOne() below.
4435 		 */
4436 #if defined(UNIX)
4437 		if (!has_wildcards)
4438 #endif
4439 		    backslash_halve(eap->arg);
4440 	    }
4441 
4442 	    if (has_wildcards)
4443 	    {
4444 		if (n == 1)
4445 		{
4446 		    /*
4447 		     * First loop: May expand environment variables.  This
4448 		     * can be done much faster with expand_env() than with
4449 		     * something else (e.g., calling a shell).
4450 		     * After expanding environment variables, check again
4451 		     * if there are still wildcards present.
4452 		     */
4453 		    if (vim_strchr(eap->arg, '$') != NULL
4454 			    || vim_strchr(eap->arg, '~') != NULL)
4455 		    {
4456 			expand_env_esc(eap->arg, NameBuff, MAXPATHL,
4457 							    TRUE, TRUE, NULL);
4458 			has_wildcards = mch_has_wildcard(NameBuff);
4459 			p = NameBuff;
4460 		    }
4461 		    else
4462 			p = NULL;
4463 		}
4464 		else // n == 2
4465 		{
4466 		    expand_T	xpc;
4467 		    int		options = WILD_LIST_NOTFOUND
4468 					       | WILD_NOERROR | WILD_ADD_SLASH;
4469 
4470 		    ExpandInit(&xpc);
4471 		    xpc.xp_context = EXPAND_FILES;
4472 		    if (p_wic)
4473 			options += WILD_ICASE;
4474 		    p = ExpandOne(&xpc, eap->arg, NULL,
4475 						   options, WILD_EXPAND_FREE);
4476 		    if (p == NULL)
4477 			return FAIL;
4478 		}
4479 		if (p != NULL)
4480 		{
4481 		    (void)repl_cmdline(eap, eap->arg, (int)STRLEN(eap->arg),
4482 								 p, cmdlinep);
4483 		    if (n == 2)	// p came from ExpandOne()
4484 			vim_free(p);
4485 		}
4486 	    }
4487 	}
4488     }
4489     return OK;
4490 }
4491 
4492 /*
4493  * Replace part of the command line, keeping eap->cmd, eap->arg and
4494  * eap->nextcmd correct.
4495  * "src" points to the part that is to be replaced, of length "srclen".
4496  * "repl" is the replacement string.
4497  * Returns a pointer to the character after the replaced string.
4498  * Returns NULL for failure.
4499  */
4500     static char_u *
4501 repl_cmdline(
4502     exarg_T	*eap,
4503     char_u	*src,
4504     int		srclen,
4505     char_u	*repl,
4506     char_u	**cmdlinep)
4507 {
4508     int		len;
4509     int		i;
4510     char_u	*new_cmdline;
4511 
4512     /*
4513      * The new command line is build in new_cmdline[].
4514      * First allocate it.
4515      * Careful: a "+cmd" argument may have been NUL terminated.
4516      */
4517     len = (int)STRLEN(repl);
4518     i = (int)(src - *cmdlinep) + (int)STRLEN(src + srclen) + len + 3;
4519     if (eap->nextcmd != NULL)
4520 	i += (int)STRLEN(eap->nextcmd);// add space for next command
4521     if ((new_cmdline = alloc(i)) == NULL)
4522 	return NULL;			// out of memory!
4523 
4524     /*
4525      * Copy the stuff before the expanded part.
4526      * Copy the expanded stuff.
4527      * Copy what came after the expanded part.
4528      * Copy the next commands, if there are any.
4529      */
4530     i = (int)(src - *cmdlinep);	// length of part before match
4531     mch_memmove(new_cmdline, *cmdlinep, (size_t)i);
4532 
4533     mch_memmove(new_cmdline + i, repl, (size_t)len);
4534     i += len;				// remember the end of the string
4535     STRCPY(new_cmdline + i, src + srclen);
4536     src = new_cmdline + i;		// remember where to continue
4537 
4538     if (eap->nextcmd != NULL)		// append next command
4539     {
4540 	i = (int)STRLEN(new_cmdline) + 1;
4541 	STRCPY(new_cmdline + i, eap->nextcmd);
4542 	eap->nextcmd = new_cmdline + i;
4543     }
4544     eap->cmd = new_cmdline + (eap->cmd - *cmdlinep);
4545     eap->arg = new_cmdline + (eap->arg - *cmdlinep);
4546     if (eap->do_ecmd_cmd != NULL && eap->do_ecmd_cmd != dollar_command)
4547 	eap->do_ecmd_cmd = new_cmdline + (eap->do_ecmd_cmd - *cmdlinep);
4548     vim_free(*cmdlinep);
4549     *cmdlinep = new_cmdline;
4550 
4551     return src;
4552 }
4553 
4554 /*
4555  * Check for '|' to separate commands and '"' to start comments.
4556  */
4557     void
4558 separate_nextcmd(exarg_T *eap)
4559 {
4560     char_u	*p;
4561 
4562 #ifdef FEAT_QUICKFIX
4563     p = skip_grep_pat(eap);
4564 #else
4565     p = eap->arg;
4566 #endif
4567 
4568     for ( ; *p; MB_PTR_ADV(p))
4569     {
4570 	if (*p == Ctrl_V)
4571 	{
4572 	    if (eap->argt & (EX_CTRLV | EX_XFILE))
4573 		++p;		// skip CTRL-V and next char
4574 	    else
4575 				// remove CTRL-V and skip next char
4576 		STRMOVE(p, p + 1);
4577 	    if (*p == NUL)		// stop at NUL after CTRL-V
4578 		break;
4579 	}
4580 
4581 #ifdef FEAT_EVAL
4582 	// Skip over `=expr` when wildcards are expanded.
4583 	else if (p[0] == '`' && p[1] == '=' && (eap->argt & EX_XFILE))
4584 	{
4585 	    p += 2;
4586 	    (void)skip_expr(&p);
4587 	}
4588 #endif
4589 
4590 	// Check for '"': start of comment or '|': next command
4591 	// :@" and :*" do not start a comment!
4592 	// :redir @" doesn't either.
4593 	else if ((*p == '"'
4594 #ifdef FEAT_EVAL
4595 		    && !in_vim9script()
4596 #endif
4597 		    && !(eap->argt & EX_NOTRLCOM)
4598 		    && ((eap->cmdidx != CMD_at && eap->cmdidx != CMD_star)
4599 							      || p != eap->arg)
4600 		    && (eap->cmdidx != CMD_redir
4601 					 || p != eap->arg + 1 || p[-1] != '@'))
4602 #ifdef FEAT_EVAL
4603 		|| (*p == '#'
4604 		    && in_vim9script()
4605 		    && p[1] != '{'
4606 		    && p > eap->cmd && VIM_ISWHITE(p[-1]))
4607 #endif
4608 		|| *p == '|' || *p == '\n')
4609 	{
4610 	    /*
4611 	     * We remove the '\' before the '|', unless EX_CTRLV is used
4612 	     * AND 'b' is present in 'cpoptions'.
4613 	     */
4614 	    if ((vim_strchr(p_cpo, CPO_BAR) == NULL
4615 			      || !(eap->argt & EX_CTRLV)) && *(p - 1) == '\\')
4616 	    {
4617 		STRMOVE(p - 1, p);	// remove the '\'
4618 		--p;
4619 	    }
4620 	    else
4621 	    {
4622 		eap->nextcmd = check_nextcmd(p);
4623 		*p = NUL;
4624 		break;
4625 	    }
4626 	}
4627     }
4628 
4629     if (!(eap->argt & EX_NOTRLCOM))	// remove trailing spaces
4630 	del_trailing_spaces(eap->arg);
4631 }
4632 
4633 /*
4634  * get + command from ex argument
4635  */
4636     static char_u *
4637 getargcmd(char_u **argp)
4638 {
4639     char_u *arg = *argp;
4640     char_u *command = NULL;
4641 
4642     if (*arg == '+')	    // +[command]
4643     {
4644 	++arg;
4645 	if (vim_isspace(*arg) || *arg == NUL)
4646 	    command = dollar_command;
4647 	else
4648 	{
4649 	    command = arg;
4650 	    arg = skip_cmd_arg(command, TRUE);
4651 	    if (*arg != NUL)
4652 		*arg++ = NUL;		// terminate command with NUL
4653 	}
4654 
4655 	arg = skipwhite(arg);	// skip over spaces
4656 	*argp = arg;
4657     }
4658     return command;
4659 }
4660 
4661 /*
4662  * Find end of "+command" argument.  Skip over "\ " and "\\".
4663  */
4664     char_u *
4665 skip_cmd_arg(
4666     char_u *p,
4667     int	   rembs)	// TRUE to halve the number of backslashes
4668 {
4669     while (*p && !vim_isspace(*p))
4670     {
4671 	if (*p == '\\' && p[1] != NUL)
4672 	{
4673 	    if (rembs)
4674 		STRMOVE(p, p + 1);
4675 	    else
4676 		++p;
4677 	}
4678 	MB_PTR_ADV(p);
4679     }
4680     return p;
4681 }
4682 
4683     int
4684 get_bad_opt(char_u *p, exarg_T *eap)
4685 {
4686     if (STRICMP(p, "keep") == 0)
4687 	eap->bad_char = BAD_KEEP;
4688     else if (STRICMP(p, "drop") == 0)
4689 	eap->bad_char = BAD_DROP;
4690     else if (MB_BYTE2LEN(*p) == 1 && p[1] == NUL)
4691 	eap->bad_char = *p;
4692     else
4693 	return FAIL;
4694     return OK;
4695 }
4696 
4697 /*
4698  * Get "++opt=arg" argument.
4699  * Return FAIL or OK.
4700  */
4701     static int
4702 getargopt(exarg_T *eap)
4703 {
4704     char_u	*arg = eap->arg + 2;
4705     int		*pp = NULL;
4706     int		bad_char_idx;
4707     char_u	*p;
4708 
4709     // ":edit ++[no]bin[ary] file"
4710     if (STRNCMP(arg, "bin", 3) == 0 || STRNCMP(arg, "nobin", 5) == 0)
4711     {
4712 	if (*arg == 'n')
4713 	{
4714 	    arg += 2;
4715 	    eap->force_bin = FORCE_NOBIN;
4716 	}
4717 	else
4718 	    eap->force_bin = FORCE_BIN;
4719 	if (!checkforcmd(&arg, "binary", 3))
4720 	    return FAIL;
4721 	eap->arg = skipwhite(arg);
4722 	return OK;
4723     }
4724 
4725     // ":read ++edit file"
4726     if (STRNCMP(arg, "edit", 4) == 0)
4727     {
4728 	eap->read_edit = TRUE;
4729 	eap->arg = skipwhite(arg + 4);
4730 	return OK;
4731     }
4732 
4733     if (STRNCMP(arg, "ff", 2) == 0)
4734     {
4735 	arg += 2;
4736 	pp = &eap->force_ff;
4737     }
4738     else if (STRNCMP(arg, "fileformat", 10) == 0)
4739     {
4740 	arg += 10;
4741 	pp = &eap->force_ff;
4742     }
4743     else if (STRNCMP(arg, "enc", 3) == 0)
4744     {
4745 	if (STRNCMP(arg, "encoding", 8) == 0)
4746 	    arg += 8;
4747 	else
4748 	    arg += 3;
4749 	pp = &eap->force_enc;
4750     }
4751     else if (STRNCMP(arg, "bad", 3) == 0)
4752     {
4753 	arg += 3;
4754 	pp = &bad_char_idx;
4755     }
4756 
4757     if (pp == NULL || *arg != '=')
4758 	return FAIL;
4759 
4760     ++arg;
4761     *pp = (int)(arg - eap->cmd);
4762     arg = skip_cmd_arg(arg, FALSE);
4763     eap->arg = skipwhite(arg);
4764     *arg = NUL;
4765 
4766     if (pp == &eap->force_ff)
4767     {
4768 	if (check_ff_value(eap->cmd + eap->force_ff) == FAIL)
4769 	    return FAIL;
4770 	eap->force_ff = eap->cmd[eap->force_ff];
4771     }
4772     else if (pp == &eap->force_enc)
4773     {
4774 	// Make 'fileencoding' lower case.
4775 	for (p = eap->cmd + eap->force_enc; *p != NUL; ++p)
4776 	    *p = TOLOWER_ASC(*p);
4777     }
4778     else
4779     {
4780 	// Check ++bad= argument.  Must be a single-byte character, "keep" or
4781 	// "drop".
4782 	if (get_bad_opt(eap->cmd + bad_char_idx, eap) == FAIL)
4783 	    return FAIL;
4784     }
4785 
4786     return OK;
4787 }
4788 
4789     static void
4790 ex_autocmd(exarg_T *eap)
4791 {
4792     /*
4793      * Disallow autocommands from .exrc and .vimrc in current
4794      * directory for security reasons.
4795      */
4796     if (secure)
4797     {
4798 	secure = 2;
4799 	eap->errmsg = _(e_curdir);
4800     }
4801     else if (eap->cmdidx == CMD_autocmd)
4802 	do_autocmd(eap->arg, eap->forceit);
4803     else
4804 	do_augroup(eap->arg, eap->forceit);
4805 }
4806 
4807 /*
4808  * ":doautocmd": Apply the automatic commands to the current buffer.
4809  */
4810     static void
4811 ex_doautocmd(exarg_T *eap)
4812 {
4813     char_u	*arg = eap->arg;
4814     int		call_do_modelines = check_nomodeline(&arg);
4815     int		did_aucmd;
4816 
4817     (void)do_doautocmd(arg, TRUE, &did_aucmd);
4818     // Only when there is no <nomodeline>.
4819     if (call_do_modelines && did_aucmd)
4820 	do_modelines(0);
4821 }
4822 
4823 /*
4824  * :[N]bunload[!] [N] [bufname] unload buffer
4825  * :[N]bdelete[!] [N] [bufname] delete buffer from buffer list
4826  * :[N]bwipeout[!] [N] [bufname] delete buffer really
4827  */
4828     static void
4829 ex_bunload(exarg_T *eap)
4830 {
4831     if (ERROR_IF_ANY_POPUP_WINDOW)
4832 	return;
4833     eap->errmsg = do_bufdel(
4834 	    eap->cmdidx == CMD_bdelete ? DOBUF_DEL
4835 		: eap->cmdidx == CMD_bwipeout ? DOBUF_WIPE
4836 		: DOBUF_UNLOAD, eap->arg,
4837 	    eap->addr_count, (int)eap->line1, (int)eap->line2, eap->forceit);
4838 }
4839 
4840 /*
4841  * :[N]buffer [N]	to buffer N
4842  * :[N]sbuffer [N]	to buffer N
4843  */
4844     static void
4845 ex_buffer(exarg_T *eap)
4846 {
4847     if (ERROR_IF_ANY_POPUP_WINDOW)
4848 	return;
4849     if (*eap->arg)
4850 	eap->errmsg = ex_errmsg(e_trailing_arg, eap->arg);
4851     else
4852     {
4853 	if (eap->addr_count == 0)	// default is current buffer
4854 	    goto_buffer(eap, DOBUF_CURRENT, FORWARD, 0);
4855 	else
4856 	    goto_buffer(eap, DOBUF_FIRST, FORWARD, (int)eap->line2);
4857 	if (eap->do_ecmd_cmd != NULL)
4858 	    do_cmdline_cmd(eap->do_ecmd_cmd);
4859     }
4860 }
4861 
4862 /*
4863  * :[N]bmodified [N]	to next mod. buffer
4864  * :[N]sbmodified [N]	to next mod. buffer
4865  */
4866     static void
4867 ex_bmodified(exarg_T *eap)
4868 {
4869     goto_buffer(eap, DOBUF_MOD, FORWARD, (int)eap->line2);
4870     if (eap->do_ecmd_cmd != NULL)
4871 	do_cmdline_cmd(eap->do_ecmd_cmd);
4872 }
4873 
4874 /*
4875  * :[N]bnext [N]	to next buffer
4876  * :[N]sbnext [N]	split and to next buffer
4877  */
4878     static void
4879 ex_bnext(exarg_T *eap)
4880 {
4881     if (ERROR_IF_ANY_POPUP_WINDOW)
4882 	return;
4883 
4884     goto_buffer(eap, DOBUF_CURRENT, FORWARD, (int)eap->line2);
4885     if (eap->do_ecmd_cmd != NULL)
4886 	do_cmdline_cmd(eap->do_ecmd_cmd);
4887 }
4888 
4889 /*
4890  * :[N]bNext [N]	to previous buffer
4891  * :[N]bprevious [N]	to previous buffer
4892  * :[N]sbNext [N]	split and to previous buffer
4893  * :[N]sbprevious [N]	split and to previous buffer
4894  */
4895     static void
4896 ex_bprevious(exarg_T *eap)
4897 {
4898     if (ERROR_IF_ANY_POPUP_WINDOW)
4899 	return;
4900 
4901     goto_buffer(eap, DOBUF_CURRENT, BACKWARD, (int)eap->line2);
4902     if (eap->do_ecmd_cmd != NULL)
4903 	do_cmdline_cmd(eap->do_ecmd_cmd);
4904 }
4905 
4906 /*
4907  * :brewind		to first buffer
4908  * :bfirst		to first buffer
4909  * :sbrewind		split and to first buffer
4910  * :sbfirst		split and to first buffer
4911  */
4912     static void
4913 ex_brewind(exarg_T *eap)
4914 {
4915     if (ERROR_IF_ANY_POPUP_WINDOW)
4916 	return;
4917 
4918     goto_buffer(eap, DOBUF_FIRST, FORWARD, 0);
4919     if (eap->do_ecmd_cmd != NULL)
4920 	do_cmdline_cmd(eap->do_ecmd_cmd);
4921 }
4922 
4923 /*
4924  * :blast		to last buffer
4925  * :sblast		split and to last buffer
4926  */
4927     static void
4928 ex_blast(exarg_T *eap)
4929 {
4930     if (ERROR_IF_ANY_POPUP_WINDOW)
4931 	return;
4932 
4933     goto_buffer(eap, DOBUF_LAST, BACKWARD, 0);
4934     if (eap->do_ecmd_cmd != NULL)
4935 	do_cmdline_cmd(eap->do_ecmd_cmd);
4936 }
4937 
4938 /*
4939  * Check if "c" ends an Ex command.
4940  * In Vim9 script does not check for white space before # or #{.
4941  */
4942     int
4943 ends_excmd(int c)
4944 {
4945     int comment_char = '"';
4946 
4947 #ifdef FEAT_EVAL
4948     if (in_vim9script())
4949 	comment_char = '#';
4950 #endif
4951     return (c == NUL || c == '|' || c == comment_char || c == '\n');
4952 }
4953 
4954 /*
4955  * Like ends_excmd() but checks that a # in Vim9 script either has "cmd" equal
4956  * to "cmd_start" or has a white space character before it.
4957  */
4958     int
4959 ends_excmd2(char_u *cmd_start UNUSED, char_u *cmd)
4960 {
4961     int c = *cmd;
4962 
4963     if (c == NUL || c == '|' || c == '\n')
4964 	return TRUE;
4965 #ifdef FEAT_EVAL
4966     if (in_vim9script())
4967 	return c == '#' && cmd[1] != '{'
4968 				 && (cmd == cmd_start || VIM_ISWHITE(cmd[-1]));
4969 #endif
4970     return c == '"';
4971 }
4972 
4973 #if defined(FEAT_SYN_HL) || defined(FEAT_SEARCH_EXTRA) || defined(FEAT_EVAL) \
4974 	|| defined(PROTO)
4975 /*
4976  * Return the next command, after the first '|' or '\n'.
4977  * Return NULL if not found.
4978  */
4979     char_u *
4980 find_nextcmd(char_u *p)
4981 {
4982     while (*p != '|' && *p != '\n')
4983     {
4984 	if (*p == NUL)
4985 	    return NULL;
4986 	++p;
4987     }
4988     return (p + 1);
4989 }
4990 #endif
4991 
4992 /*
4993  * Check if *p is a separator between Ex commands, skipping over white space.
4994  * Return NULL if it isn't, the following character if it is.
4995  */
4996     char_u *
4997 check_nextcmd(char_u *p)
4998 {
4999     char_u *s = skipwhite(p);
5000 
5001     if (*s == '|' || *s == '\n')
5002 	return (s + 1);
5003     else
5004 	return NULL;
5005 }
5006 
5007 /*
5008  * - if there are more files to edit
5009  * - and this is the last window
5010  * - and forceit not used
5011  * - and not repeated twice on a row
5012  *    return FAIL and give error message if 'message' TRUE
5013  * return OK otherwise
5014  */
5015     static int
5016 check_more(
5017     int message,	    // when FALSE check only, no messages
5018     int forceit)
5019 {
5020     int	    n = ARGCOUNT - curwin->w_arg_idx - 1;
5021 
5022     if (!forceit && only_one_window()
5023 	    && ARGCOUNT > 1 && !arg_had_last && n >= 0 && quitmore == 0)
5024     {
5025 	if (message)
5026 	{
5027 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
5028 	    if ((p_confirm || cmdmod.confirm) && curbuf->b_fname != NULL)
5029 	    {
5030 		char_u	buff[DIALOG_MSG_SIZE];
5031 
5032 		vim_snprintf((char *)buff, DIALOG_MSG_SIZE,
5033 			NGETTEXT("%d more file to edit.  Quit anyway?",
5034 			    "%d more files to edit.  Quit anyway?", n), n);
5035 		if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 1) == VIM_YES)
5036 		    return OK;
5037 		return FAIL;
5038 	    }
5039 #endif
5040 	    semsg(NGETTEXT("E173: %d more file to edit",
5041 			"E173: %d more files to edit", n), n);
5042 	    quitmore = 2;	    // next try to quit is allowed
5043 	}
5044 	return FAIL;
5045     }
5046     return OK;
5047 }
5048 
5049 /*
5050  * Function given to ExpandGeneric() to obtain the list of command names.
5051  */
5052     char_u *
5053 get_command_name(expand_T *xp UNUSED, int idx)
5054 {
5055     if (idx >= (int)CMD_SIZE)
5056 	return get_user_command_name(idx);
5057     return cmdnames[idx].cmd_name;
5058 }
5059 
5060     static void
5061 ex_colorscheme(exarg_T *eap)
5062 {
5063     if (*eap->arg == NUL)
5064     {
5065 #ifdef FEAT_EVAL
5066 	char_u *expr = vim_strsave((char_u *)"g:colors_name");
5067 	char_u *p = NULL;
5068 
5069 	if (expr != NULL)
5070 	{
5071 	    ++emsg_off;
5072 	    p = eval_to_string(expr, FALSE);
5073 	    --emsg_off;
5074 	    vim_free(expr);
5075 	}
5076 	if (p != NULL)
5077 	{
5078 	    msg((char *)p);
5079 	    vim_free(p);
5080 	}
5081 	else
5082 	    msg("default");
5083 #else
5084 	msg(_("unknown"));
5085 #endif
5086     }
5087     else if (load_colors(eap->arg) == FAIL)
5088 	semsg(_("E185: Cannot find color scheme '%s'"), eap->arg);
5089 
5090 #ifdef FEAT_VTP
5091     else if (has_vtp_working())
5092     {
5093 	// background color change requires clear + redraw
5094 	update_screen(CLEAR);
5095 	redrawcmd();
5096     }
5097 #endif
5098 }
5099 
5100     static void
5101 ex_highlight(exarg_T *eap)
5102 {
5103     if (*eap->arg == NUL && eap->cmd[2] == '!')
5104 	msg(_("Greetings, Vim user!"));
5105     do_highlight(eap->arg, eap->forceit, FALSE);
5106 }
5107 
5108 
5109 /*
5110  * Call this function if we thought we were going to exit, but we won't
5111  * (because of an error).  May need to restore the terminal mode.
5112  */
5113     void
5114 not_exiting(void)
5115 {
5116     exiting = FALSE;
5117     settmode(TMODE_RAW);
5118 }
5119 
5120     static int
5121 before_quit_autocmds(win_T *wp, int quit_all, int forceit)
5122 {
5123     apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, wp->w_buffer);
5124 
5125     // Bail out when autocommands closed the window.
5126     // Refuse to quit when the buffer in the last window is being closed (can
5127     // only happen in autocommands).
5128     if (!win_valid(wp)
5129 	    || curbuf_locked()
5130 	    || (wp->w_buffer->b_nwindows == 1 && wp->w_buffer->b_locked > 0))
5131 	return TRUE;
5132 
5133     if (quit_all || (check_more(FALSE, forceit) == OK && only_one_window()))
5134     {
5135 	apply_autocmds(EVENT_EXITPRE, NULL, NULL, FALSE, curbuf);
5136 	// Refuse to quit when locked or when the window was closed or the
5137 	// buffer in the last window is being closed (can only happen in
5138 	// autocommands).
5139 	if (!win_valid(wp) || curbuf_locked()
5140 			  || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0))
5141 	    return TRUE;
5142     }
5143 
5144     return FALSE;
5145 }
5146 
5147 /*
5148  * ":quit": quit current window, quit Vim if the last window is closed.
5149  * ":{nr}quit": quit window {nr}
5150  * Also used when closing a terminal window that's the last one.
5151  */
5152     void
5153 ex_quit(exarg_T *eap)
5154 {
5155     win_T	*wp;
5156 
5157 #ifdef FEAT_CMDWIN
5158     if (cmdwin_type != 0)
5159     {
5160 	cmdwin_result = Ctrl_C;
5161 	return;
5162     }
5163 #endif
5164     // Don't quit while editing the command line.
5165     if (text_locked())
5166     {
5167 	text_locked_msg();
5168 	return;
5169     }
5170     if (eap->addr_count > 0)
5171     {
5172 	int	wnr = eap->line2;
5173 
5174 	for (wp = firstwin; wp->w_next != NULL; wp = wp->w_next)
5175 	    if (--wnr <= 0)
5176 		break;
5177     }
5178     else
5179 	wp = curwin;
5180 
5181     // Refuse to quit when locked.
5182     if (curbuf_locked())
5183 	return;
5184 
5185     // Trigger QuitPre and maybe ExitPre
5186     if (before_quit_autocmds(wp, FALSE, eap->forceit))
5187 	return;
5188 
5189 #ifdef FEAT_NETBEANS_INTG
5190     netbeansForcedQuit = eap->forceit;
5191 #endif
5192 
5193     /*
5194      * If there are more files or windows we won't exit.
5195      */
5196     if (check_more(FALSE, eap->forceit) == OK && only_one_window())
5197 	exiting = TRUE;
5198     if ((!buf_hide(wp->w_buffer)
5199 		&& check_changed(wp->w_buffer, (p_awa ? CCGD_AW : 0)
5200 				       | (eap->forceit ? CCGD_FORCEIT : 0)
5201 				       | CCGD_EXCMD))
5202 	    || check_more(TRUE, eap->forceit) == FAIL
5203 	    || (only_one_window() && check_changed_any(eap->forceit, TRUE)))
5204     {
5205 	not_exiting();
5206     }
5207     else
5208     {
5209 	// quit last window
5210 	// Note: only_one_window() returns true, even so a help window is
5211 	// still open. In that case only quit, if no address has been
5212 	// specified. Example:
5213 	// :h|wincmd w|1q     - don't quit
5214 	// :h|wincmd w|q      - quit
5215 	if (only_one_window() && (ONE_WINDOW || eap->addr_count == 0))
5216 	    getout(0);
5217 	not_exiting();
5218 #ifdef FEAT_GUI
5219 	need_mouse_correct = TRUE;
5220 #endif
5221 	// close window; may free buffer
5222 	win_close(wp, !buf_hide(wp->w_buffer) || eap->forceit);
5223     }
5224 }
5225 
5226 /*
5227  * ":cquit".
5228  */
5229     static void
5230 ex_cquit(exarg_T *eap UNUSED)
5231 {
5232     // this does not always pass on the exit code to the Manx compiler. why?
5233     getout(eap->addr_count > 0 ? (int)eap->line2 : EXIT_FAILURE);
5234 }
5235 
5236 /*
5237  * ":qall": try to quit all windows
5238  */
5239     static void
5240 ex_quit_all(exarg_T *eap)
5241 {
5242 # ifdef FEAT_CMDWIN
5243     if (cmdwin_type != 0)
5244     {
5245 	if (eap->forceit)
5246 	    cmdwin_result = K_XF1;	// ex_window() takes care of this
5247 	else
5248 	    cmdwin_result = K_XF2;
5249 	return;
5250     }
5251 # endif
5252 
5253     // Don't quit while editing the command line.
5254     if (text_locked())
5255     {
5256 	text_locked_msg();
5257 	return;
5258     }
5259 
5260     if (before_quit_autocmds(curwin, TRUE, eap->forceit))
5261 	return;
5262 
5263     exiting = TRUE;
5264     if (eap->forceit || !check_changed_any(FALSE, FALSE))
5265 	getout(0);
5266     not_exiting();
5267 }
5268 
5269 /*
5270  * ":close": close current window, unless it is the last one
5271  */
5272     static void
5273 ex_close(exarg_T *eap)
5274 {
5275     win_T	*win;
5276     int		winnr = 0;
5277 #ifdef FEAT_CMDWIN
5278     if (cmdwin_type != 0)
5279 	cmdwin_result = Ctrl_C;
5280     else
5281 #endif
5282 	if (!text_locked() && !curbuf_locked())
5283 	{
5284 	    if (eap->addr_count == 0)
5285 		ex_win_close(eap->forceit, curwin, NULL);
5286 	    else
5287 	    {
5288 		FOR_ALL_WINDOWS(win)
5289 		{
5290 		    winnr++;
5291 		    if (winnr == eap->line2)
5292 			break;
5293 		}
5294 		if (win == NULL)
5295 		    win = lastwin;
5296 		ex_win_close(eap->forceit, win, NULL);
5297 	    }
5298 	}
5299 }
5300 
5301 #ifdef FEAT_QUICKFIX
5302 /*
5303  * ":pclose": Close any preview window.
5304  */
5305     static void
5306 ex_pclose(exarg_T *eap)
5307 {
5308     win_T	*win;
5309 
5310     // First close any normal window.
5311     FOR_ALL_WINDOWS(win)
5312 	if (win->w_p_pvw)
5313 	{
5314 	    ex_win_close(eap->forceit, win, NULL);
5315 	    return;
5316 	}
5317 # ifdef FEAT_PROP_POPUP
5318     // Also when 'previewpopup' is empty, it might have been cleared.
5319     popup_close_preview();
5320 # endif
5321 }
5322 #endif
5323 
5324 /*
5325  * Close window "win" and take care of handling closing the last window for a
5326  * modified buffer.
5327  */
5328     static void
5329 ex_win_close(
5330     int		forceit,
5331     win_T	*win,
5332     tabpage_T	*tp)		// NULL or the tab page "win" is in
5333 {
5334     int		need_hide;
5335     buf_T	*buf = win->w_buffer;
5336 
5337     // Never close the autocommand window.
5338     if (win == aucmd_win)
5339     {
5340 	emsg(_(e_autocmd_close));
5341 	return;
5342     }
5343 
5344     need_hide = (bufIsChanged(buf) && buf->b_nwindows <= 1);
5345     if (need_hide && !buf_hide(buf) && !forceit)
5346     {
5347 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
5348 	if ((p_confirm || cmdmod.confirm) && p_write)
5349 	{
5350 	    bufref_T bufref;
5351 
5352 	    set_bufref(&bufref, buf);
5353 	    dialog_changed(buf, FALSE);
5354 	    if (bufref_valid(&bufref) && bufIsChanged(buf))
5355 		return;
5356 	    need_hide = FALSE;
5357 	}
5358 	else
5359 #endif
5360 	{
5361 	    no_write_message();
5362 	    return;
5363 	}
5364     }
5365 
5366 #ifdef FEAT_GUI
5367     need_mouse_correct = TRUE;
5368 #endif
5369 
5370     // free buffer when not hiding it or when it's a scratch buffer
5371     if (tp == NULL)
5372 	win_close(win, !need_hide && !buf_hide(buf));
5373     else
5374 	win_close_othertab(win, !need_hide && !buf_hide(buf), tp);
5375 }
5376 
5377 /*
5378  * Handle the argument for a tabpage related ex command.
5379  * Returns a tabpage number.
5380  * When an error is encountered then eap->errmsg is set.
5381  */
5382     static int
5383 get_tabpage_arg(exarg_T *eap)
5384 {
5385     int tab_number;
5386     int unaccept_arg0 = (eap->cmdidx == CMD_tabmove) ? 0 : 1;
5387 
5388     if (eap->arg && *eap->arg != NUL)
5389     {
5390 	char_u *p = eap->arg;
5391 	char_u *p_save;
5392 	int    relative = 0; // argument +N/-N means: go to N places to the
5393 			     // right/left relative to the current position.
5394 
5395 	if (*p == '-')
5396 	{
5397 	    relative = -1;
5398 	    p++;
5399 	}
5400 	else if (*p == '+')
5401 	{
5402 	    relative = 1;
5403 	    p++;
5404 	}
5405 
5406 	p_save = p;
5407 	tab_number = getdigits(&p);
5408 
5409 	if (relative == 0)
5410 	{
5411 	    if (STRCMP(p, "$") == 0)
5412 		tab_number = LAST_TAB_NR;
5413 	    else if (p == p_save || *p_save == '-' || *p != NUL
5414 		    || tab_number > LAST_TAB_NR)
5415 	    {
5416 		// No numbers as argument.
5417 		eap->errmsg = ex_errmsg(e_invarg2, eap->arg);
5418 		goto theend;
5419 	    }
5420 	}
5421 	else
5422 	{
5423 	    if (*p_save == NUL)
5424 		tab_number = 1;
5425 	    else if (p == p_save || *p_save == '-' || *p != NUL
5426 		    || tab_number == 0)
5427 	    {
5428 		// No numbers as argument.
5429 		eap->errmsg = ex_errmsg(e_invarg2, eap->arg);
5430 		goto theend;
5431 	    }
5432 	    tab_number = tab_number * relative + tabpage_index(curtab);
5433 	    if (!unaccept_arg0 && relative == -1)
5434 		--tab_number;
5435 	}
5436 	if (tab_number < unaccept_arg0 || tab_number > LAST_TAB_NR)
5437 	    eap->errmsg = ex_errmsg(e_invarg2, eap->arg);
5438     }
5439     else if (eap->addr_count > 0)
5440     {
5441 	if (unaccept_arg0 && eap->line2 == 0)
5442 	{
5443 	    eap->errmsg = _(e_invrange);
5444 	    tab_number = 0;
5445 	}
5446 	else
5447 	{
5448 	    tab_number = eap->line2;
5449 	    if (!unaccept_arg0 && *skipwhite(*eap->cmdlinep) == '-')
5450 	    {
5451 		--tab_number;
5452 		if (tab_number < unaccept_arg0)
5453 		    eap->errmsg = _(e_invrange);
5454 	    }
5455 	}
5456     }
5457     else
5458     {
5459 	switch (eap->cmdidx)
5460 	{
5461 	case CMD_tabnext:
5462 	    tab_number = tabpage_index(curtab) + 1;
5463 	    if (tab_number > LAST_TAB_NR)
5464 		tab_number = 1;
5465 	    break;
5466 	case CMD_tabmove:
5467 	    tab_number = LAST_TAB_NR;
5468 	    break;
5469 	default:
5470 	    tab_number = tabpage_index(curtab);
5471 	}
5472     }
5473 
5474 theend:
5475     return tab_number;
5476 }
5477 
5478 /*
5479  * ":tabclose": close current tab page, unless it is the last one.
5480  * ":tabclose N": close tab page N.
5481  */
5482     static void
5483 ex_tabclose(exarg_T *eap)
5484 {
5485     tabpage_T	*tp;
5486     int		tab_number;
5487 
5488 # ifdef FEAT_CMDWIN
5489     if (cmdwin_type != 0)
5490 	cmdwin_result = K_IGNORE;
5491     else
5492 # endif
5493 	if (first_tabpage->tp_next == NULL)
5494 	    emsg(_("E784: Cannot close last tab page"));
5495 	else
5496 	{
5497 	    tab_number = get_tabpage_arg(eap);
5498 	    if (eap->errmsg == NULL)
5499 	    {
5500 		tp = find_tabpage(tab_number);
5501 		if (tp == NULL)
5502 		{
5503 		    beep_flush();
5504 		    return;
5505 		}
5506 		if (tp != curtab)
5507 		{
5508 		    tabpage_close_other(tp, eap->forceit);
5509 		    return;
5510 		}
5511 		else if (!text_locked() && !curbuf_locked())
5512 		    tabpage_close(eap->forceit);
5513 	    }
5514 	}
5515 }
5516 
5517 /*
5518  * ":tabonly": close all tab pages except the current one
5519  */
5520     static void
5521 ex_tabonly(exarg_T *eap)
5522 {
5523     tabpage_T	*tp;
5524     int		done;
5525     int		tab_number;
5526 
5527 # ifdef FEAT_CMDWIN
5528     if (cmdwin_type != 0)
5529 	cmdwin_result = K_IGNORE;
5530     else
5531 # endif
5532 	if (first_tabpage->tp_next == NULL)
5533 	    msg(_("Already only one tab page"));
5534 	else
5535 	{
5536 	    tab_number = get_tabpage_arg(eap);
5537 	    if (eap->errmsg == NULL)
5538 	    {
5539 		goto_tabpage(tab_number);
5540 		// Repeat this up to a 1000 times, because autocommands may
5541 		// mess up the lists.
5542 		for (done = 0; done < 1000; ++done)
5543 		{
5544 		    FOR_ALL_TABPAGES(tp)
5545 			if (tp->tp_topframe != topframe)
5546 			{
5547 			    tabpage_close_other(tp, eap->forceit);
5548 			    // if we failed to close it quit
5549 			    if (valid_tabpage(tp))
5550 				done = 1000;
5551 			    // start over, "tp" is now invalid
5552 			    break;
5553 			}
5554 		    if (first_tabpage->tp_next == NULL)
5555 			break;
5556 		}
5557 	    }
5558 	}
5559 }
5560 
5561 /*
5562  * Close the current tab page.
5563  */
5564     void
5565 tabpage_close(int forceit)
5566 {
5567     // First close all the windows but the current one.  If that worked then
5568     // close the last window in this tab, that will close it.
5569     if (!ONE_WINDOW)
5570 	close_others(TRUE, forceit);
5571     if (ONE_WINDOW)
5572 	ex_win_close(forceit, curwin, NULL);
5573 # ifdef FEAT_GUI
5574     need_mouse_correct = TRUE;
5575 # endif
5576 }
5577 
5578 /*
5579  * Close tab page "tp", which is not the current tab page.
5580  * Note that autocommands may make "tp" invalid.
5581  * Also takes care of the tab pages line disappearing when closing the
5582  * last-but-one tab page.
5583  */
5584     void
5585 tabpage_close_other(tabpage_T *tp, int forceit)
5586 {
5587     int		done = 0;
5588     win_T	*wp;
5589     int		h = tabline_height();
5590 
5591     // Limit to 1000 windows, autocommands may add a window while we close
5592     // one.  OK, so I'm paranoid...
5593     while (++done < 1000)
5594     {
5595 	wp = tp->tp_firstwin;
5596 	ex_win_close(forceit, wp, tp);
5597 
5598 	// Autocommands may delete the tab page under our fingers and we may
5599 	// fail to close a window with a modified buffer.
5600 	if (!valid_tabpage(tp) || tp->tp_firstwin == wp)
5601 	    break;
5602     }
5603 
5604     apply_autocmds(EVENT_TABCLOSED, NULL, NULL, FALSE, curbuf);
5605 
5606     redraw_tabline = TRUE;
5607     if (h != tabline_height())
5608 	shell_new_rows();
5609 }
5610 
5611 /*
5612  * ":only".
5613  */
5614     static void
5615 ex_only(exarg_T *eap)
5616 {
5617     win_T   *wp;
5618     int	    wnr;
5619 # ifdef FEAT_GUI
5620     need_mouse_correct = TRUE;
5621 # endif
5622     if (eap->addr_count > 0)
5623     {
5624 	wnr = eap->line2;
5625 	for (wp = firstwin; --wnr > 0; )
5626 	{
5627 	    if (wp->w_next == NULL)
5628 		break;
5629 	    else
5630 		wp = wp->w_next;
5631 	}
5632 	win_goto(wp);
5633     }
5634     close_others(TRUE, eap->forceit);
5635 }
5636 
5637     static void
5638 ex_hide(exarg_T *eap UNUSED)
5639 {
5640     // ":hide" or ":hide | cmd": hide current window
5641     if (!eap->skip)
5642     {
5643 #ifdef FEAT_GUI
5644 	need_mouse_correct = TRUE;
5645 #endif
5646 	if (eap->addr_count == 0)
5647 	    win_close(curwin, FALSE);	// don't free buffer
5648 	else
5649 	{
5650 	    int	winnr = 0;
5651 	    win_T	*win;
5652 
5653 	    FOR_ALL_WINDOWS(win)
5654 	    {
5655 		winnr++;
5656 		if (winnr == eap->line2)
5657 		    break;
5658 	    }
5659 	    if (win == NULL)
5660 		win = lastwin;
5661 	    win_close(win, FALSE);
5662 	}
5663     }
5664 }
5665 
5666 /*
5667  * ":stop" and ":suspend": Suspend Vim.
5668  */
5669     static void
5670 ex_stop(exarg_T *eap)
5671 {
5672     /*
5673      * Disallow suspending for "rvim".
5674      */
5675     if (!check_restricted())
5676     {
5677 	if (!eap->forceit)
5678 	    autowrite_all();
5679 	windgoto((int)Rows - 1, 0);
5680 	out_char('\n');
5681 	out_flush();
5682 	stoptermcap();
5683 	out_flush();		// needed for SUN to restore xterm buffer
5684 #ifdef FEAT_TITLE
5685 	mch_restore_title(SAVE_RESTORE_BOTH);	// restore window titles
5686 #endif
5687 	ui_suspend();		// call machine specific function
5688 #ifdef FEAT_TITLE
5689 	maketitle();
5690 	resettitle();		// force updating the title
5691 #endif
5692 	starttermcap();
5693 	scroll_start();		// scroll screen before redrawing
5694 	redraw_later_clear();
5695 	shell_resized();	// may have resized window
5696     }
5697 }
5698 
5699 /*
5700  * ":exit", ":xit" and ":wq": Write file and quite the current window.
5701  */
5702     static void
5703 ex_exit(exarg_T *eap)
5704 {
5705 #ifdef FEAT_EVAL
5706     if (not_in_vim9(eap) == FAIL)
5707 	return;
5708 #endif
5709 #ifdef FEAT_CMDWIN
5710     if (cmdwin_type != 0)
5711     {
5712 	cmdwin_result = Ctrl_C;
5713 	return;
5714     }
5715 #endif
5716     // Don't quit while editing the command line.
5717     if (text_locked())
5718     {
5719 	text_locked_msg();
5720 	return;
5721     }
5722 
5723     if (before_quit_autocmds(curwin, FALSE, eap->forceit))
5724 	return;
5725 
5726     /*
5727      * if more files or windows we won't exit
5728      */
5729     if (check_more(FALSE, eap->forceit) == OK && only_one_window())
5730 	exiting = TRUE;
5731     if (       ((eap->cmdidx == CMD_wq
5732 		    || curbufIsChanged())
5733 		&& do_write(eap) == FAIL)
5734 	    || check_more(TRUE, eap->forceit) == FAIL
5735 	    || (only_one_window() && check_changed_any(eap->forceit, FALSE)))
5736     {
5737 	not_exiting();
5738     }
5739     else
5740     {
5741 	if (only_one_window())	    // quit last window, exit Vim
5742 	    getout(0);
5743 	not_exiting();
5744 # ifdef FEAT_GUI
5745 	need_mouse_correct = TRUE;
5746 # endif
5747 	// Quit current window, may free the buffer.
5748 	win_close(curwin, !buf_hide(curwin->w_buffer));
5749     }
5750 }
5751 
5752 /*
5753  * ":print", ":list", ":number".
5754  */
5755     static void
5756 ex_print(exarg_T *eap)
5757 {
5758     if (curbuf->b_ml.ml_flags & ML_EMPTY)
5759 	emsg(_(e_emptybuf));
5760     else
5761     {
5762 	for ( ;!got_int; ui_breakcheck())
5763 	{
5764 	    print_line(eap->line1,
5765 		    (eap->cmdidx == CMD_number || eap->cmdidx == CMD_pound
5766 						 || (eap->flags & EXFLAG_NR)),
5767 		    eap->cmdidx == CMD_list || (eap->flags & EXFLAG_LIST));
5768 	    if (++eap->line1 > eap->line2)
5769 		break;
5770 	    out_flush();	    // show one line at a time
5771 	}
5772 	setpcmark();
5773 	// put cursor at last line
5774 	curwin->w_cursor.lnum = eap->line2;
5775 	beginline(BL_SOL | BL_FIX);
5776     }
5777 
5778     ex_no_reprint = TRUE;
5779 }
5780 
5781 #ifdef FEAT_BYTEOFF
5782     static void
5783 ex_goto(exarg_T *eap)
5784 {
5785     goto_byte(eap->line2);
5786 }
5787 #endif
5788 
5789 /*
5790  * ":shell".
5791  */
5792     static void
5793 ex_shell(exarg_T *eap UNUSED)
5794 {
5795     do_shell(NULL, 0);
5796 }
5797 
5798 #if defined(HAVE_DROP_FILE) || defined(PROTO)
5799 
5800 static int drop_busy = FALSE;
5801 static int drop_filec;
5802 static char_u **drop_filev = NULL;
5803 static int drop_split;
5804 static void (*drop_callback)(void *);
5805 static void *drop_cookie;
5806 
5807     static void
5808 handle_drop_internal(void)
5809 {
5810     exarg_T	ea;
5811     int		save_msg_scroll = msg_scroll;
5812 
5813     // Setting the argument list may cause screen updates and being called
5814     // recursively.  Avoid that by setting drop_busy.
5815     drop_busy = TRUE;
5816 
5817     // Check whether the current buffer is changed. If so, we will need
5818     // to split the current window or data could be lost.
5819     // We don't need to check if the 'hidden' option is set, as in this
5820     // case the buffer won't be lost.
5821     if (!buf_hide(curbuf) && !drop_split)
5822     {
5823 	++emsg_off;
5824 	drop_split = check_changed(curbuf, CCGD_AW);
5825 	--emsg_off;
5826     }
5827     if (drop_split)
5828     {
5829 	if (win_split(0, 0) == FAIL)
5830 	    return;
5831 	RESET_BINDING(curwin);
5832 
5833 	// When splitting the window, create a new alist.  Otherwise the
5834 	// existing one is overwritten.
5835 	alist_unlink(curwin->w_alist);
5836 	alist_new();
5837     }
5838 
5839     /*
5840      * Set up the new argument list.
5841      */
5842     alist_set(ALIST(curwin), drop_filec, drop_filev, FALSE, NULL, 0);
5843 
5844     /*
5845      * Move to the first file.
5846      */
5847     // Fake up a minimal "next" command for do_argfile()
5848     CLEAR_FIELD(ea);
5849     ea.cmd = (char_u *)"next";
5850     do_argfile(&ea, 0);
5851 
5852     // do_ecmd() may set need_start_insertmode, but since we never left Insert
5853     // mode that is not needed here.
5854     need_start_insertmode = FALSE;
5855 
5856     // Restore msg_scroll, otherwise a following command may cause scrolling
5857     // unexpectedly.  The screen will be redrawn by the caller, thus
5858     // msg_scroll being set by displaying a message is irrelevant.
5859     msg_scroll = save_msg_scroll;
5860 
5861     if (drop_callback != NULL)
5862 	drop_callback(drop_cookie);
5863 
5864     drop_filev = NULL;
5865     drop_busy = FALSE;
5866 }
5867 
5868 /*
5869  * Handle a file drop. The code is here because a drop is *nearly* like an
5870  * :args command, but not quite (we have a list of exact filenames, so we
5871  * don't want to (a) parse a command line, or (b) expand wildcards). So the
5872  * code is very similar to :args and hence needs access to a lot of the static
5873  * functions in this file.
5874  *
5875  * The "filev" list must have been allocated using alloc(), as should each item
5876  * in the list. This function takes over responsibility for freeing the "filev"
5877  * list.
5878  */
5879     void
5880 handle_drop(
5881     int		filec,		// the number of files dropped
5882     char_u	**filev,	// the list of files dropped
5883     int		split,		// force splitting the window
5884     void	(*callback)(void *), // to be called after setting the argument
5885 				     // list
5886     void	*cookie)	// argument for "callback" (allocated)
5887 {
5888     // Cannot handle recursive drops, finish the pending one.
5889     if (drop_busy)
5890     {
5891 	FreeWild(filec, filev);
5892 	vim_free(cookie);
5893 	return;
5894     }
5895 
5896     // When calling handle_drop() more than once in a row we only use the last
5897     // one.
5898     if (drop_filev != NULL)
5899     {
5900 	FreeWild(drop_filec, drop_filev);
5901 	vim_free(drop_cookie);
5902     }
5903 
5904     drop_filec = filec;
5905     drop_filev = filev;
5906     drop_split = split;
5907     drop_callback = callback;
5908     drop_cookie = cookie;
5909 
5910     // Postpone this when:
5911     // - editing the command line
5912     // - not possible to change the current buffer
5913     // - updating the screen
5914     // As it may change buffers and window structures that are in use and cause
5915     // freed memory to be used.
5916     if (text_locked() || curbuf_locked() || updating_screen)
5917 	return;
5918 
5919     handle_drop_internal();
5920 }
5921 
5922 /*
5923  * To be called when text is unlocked, curbuf is unlocked or updating_screen is
5924  * reset: Handle a postponed drop.
5925  */
5926     void
5927 handle_any_postponed_drop(void)
5928 {
5929     if (!drop_busy && drop_filev != NULL
5930 	     && !text_locked() && !curbuf_locked() && !updating_screen)
5931 	handle_drop_internal();
5932 }
5933 #endif
5934 
5935 /*
5936  * ":preserve".
5937  */
5938     static void
5939 ex_preserve(exarg_T *eap UNUSED)
5940 {
5941     curbuf->b_flags |= BF_PRESERVED;
5942     ml_preserve(curbuf, TRUE);
5943 }
5944 
5945 /*
5946  * ":recover".
5947  */
5948     static void
5949 ex_recover(exarg_T *eap)
5950 {
5951     // Set recoverymode right away to avoid the ATTENTION prompt.
5952     recoverymode = TRUE;
5953     if (!check_changed(curbuf, (p_awa ? CCGD_AW : 0)
5954 			     | CCGD_MULTWIN
5955 			     | (eap->forceit ? CCGD_FORCEIT : 0)
5956 			     | CCGD_EXCMD)
5957 
5958 	    && (*eap->arg == NUL
5959 			     || setfname(curbuf, eap->arg, NULL, TRUE) == OK))
5960 	ml_recover(TRUE);
5961     recoverymode = FALSE;
5962 }
5963 
5964 /*
5965  * Command modifier used in a wrong way.
5966  */
5967     static void
5968 ex_wrongmodifier(exarg_T *eap)
5969 {
5970     eap->errmsg = _(e_invcmd);
5971 }
5972 
5973 /*
5974  * :sview [+command] file	split window with new file, read-only
5975  * :split [[+command] file]	split window with current or new file
5976  * :vsplit [[+command] file]	split window vertically with current or new file
5977  * :new [[+command] file]	split window with no or new file
5978  * :vnew [[+command] file]	split vertically window with no or new file
5979  * :sfind [+command] file	split window with file in 'path'
5980  *
5981  * :tabedit			open new Tab page with empty window
5982  * :tabedit [+command] file	open new Tab page and edit "file"
5983  * :tabnew [[+command] file]	just like :tabedit
5984  * :tabfind [+command] file	open new Tab page and find "file"
5985  */
5986     void
5987 ex_splitview(exarg_T *eap)
5988 {
5989     win_T	*old_curwin = curwin;
5990 #if defined(FEAT_SEARCHPATH) || defined(FEAT_BROWSE)
5991     char_u	*fname = NULL;
5992 #endif
5993 #ifdef FEAT_BROWSE
5994     int		browse_flag = cmdmod.browse;
5995 #endif
5996     int		use_tab = eap->cmdidx == CMD_tabedit
5997 		       || eap->cmdidx == CMD_tabfind
5998 		       || eap->cmdidx == CMD_tabnew;
5999 
6000     if (ERROR_IF_ANY_POPUP_WINDOW)
6001 	return;
6002 
6003 #ifdef FEAT_GUI
6004     need_mouse_correct = TRUE;
6005 #endif
6006 
6007 #ifdef FEAT_QUICKFIX
6008     // A ":split" in the quickfix window works like ":new".  Don't want two
6009     // quickfix windows.  But it's OK when doing ":tab split".
6010     if (bt_quickfix(curbuf) && cmdmod.tab == 0)
6011     {
6012 	if (eap->cmdidx == CMD_split)
6013 	    eap->cmdidx = CMD_new;
6014 	if (eap->cmdidx == CMD_vsplit)
6015 	    eap->cmdidx = CMD_vnew;
6016     }
6017 #endif
6018 
6019 #ifdef FEAT_SEARCHPATH
6020     if (eap->cmdidx == CMD_sfind || eap->cmdidx == CMD_tabfind)
6021     {
6022 	fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg),
6023 					  FNAME_MESS, TRUE, curbuf->b_ffname);
6024 	if (fname == NULL)
6025 	    goto theend;
6026 	eap->arg = fname;
6027     }
6028 # ifdef FEAT_BROWSE
6029     else
6030 # endif
6031 #endif
6032 #ifdef FEAT_BROWSE
6033     if (cmdmod.browse
6034 	    && eap->cmdidx != CMD_vnew
6035 	    && eap->cmdidx != CMD_new)
6036     {
6037 	if (
6038 # ifdef FEAT_GUI
6039 	    !gui.in_use &&
6040 # endif
6041 		au_has_group((char_u *)"FileExplorer"))
6042 	{
6043 	    // No browsing supported but we do have the file explorer:
6044 	    // Edit the directory.
6045 	    if (*eap->arg == NUL || !mch_isdir(eap->arg))
6046 		eap->arg = (char_u *)".";
6047 	}
6048 	else
6049 	{
6050 	    fname = do_browse(0, (char_u *)(use_tab
6051 			? _("Edit File in new tab page")
6052 			: _("Edit File in new window")),
6053 					  eap->arg, NULL, NULL, NULL, curbuf);
6054 	    if (fname == NULL)
6055 		goto theend;
6056 	    eap->arg = fname;
6057 	}
6058     }
6059     cmdmod.browse = FALSE;	// Don't browse again in do_ecmd().
6060 #endif
6061 
6062     /*
6063      * Either open new tab page or split the window.
6064      */
6065     if (use_tab)
6066     {
6067 	if (win_new_tabpage(cmdmod.tab != 0 ? cmdmod.tab
6068 			 : eap->addr_count == 0 ? 0
6069 					       : (int)eap->line2 + 1) != FAIL)
6070 	{
6071 	    do_exedit(eap, old_curwin);
6072 
6073 	    // set the alternate buffer for the window we came from
6074 	    if (curwin != old_curwin
6075 		    && win_valid(old_curwin)
6076 		    && old_curwin->w_buffer != curbuf
6077 		    && !cmdmod.keepalt)
6078 		old_curwin->w_alt_fnum = curbuf->b_fnum;
6079 	}
6080     }
6081     else if (win_split(eap->addr_count > 0 ? (int)eap->line2 : 0,
6082 				     *eap->cmd == 'v' ? WSP_VERT : 0) != FAIL)
6083     {
6084 	// Reset 'scrollbind' when editing another file, but keep it when
6085 	// doing ":split" without arguments.
6086 	if (*eap->arg != NUL
6087 # ifdef FEAT_BROWSE
6088 		|| cmdmod.browse
6089 # endif
6090 	   )
6091 	    RESET_BINDING(curwin);
6092 	else
6093 	    do_check_scrollbind(FALSE);
6094 	do_exedit(eap, old_curwin);
6095     }
6096 
6097 # ifdef FEAT_BROWSE
6098     cmdmod.browse = browse_flag;
6099 # endif
6100 
6101 # if defined(FEAT_SEARCHPATH) || defined(FEAT_BROWSE)
6102 theend:
6103     vim_free(fname);
6104 # endif
6105 }
6106 
6107 /*
6108  * Open a new tab page.
6109  */
6110     void
6111 tabpage_new(void)
6112 {
6113     exarg_T	ea;
6114 
6115     CLEAR_FIELD(ea);
6116     ea.cmdidx = CMD_tabnew;
6117     ea.cmd = (char_u *)"tabn";
6118     ea.arg = (char_u *)"";
6119     ex_splitview(&ea);
6120 }
6121 
6122 /*
6123  * :tabnext command
6124  */
6125     static void
6126 ex_tabnext(exarg_T *eap)
6127 {
6128     int tab_number;
6129 
6130     if (ERROR_IF_POPUP_WINDOW)
6131 	return;
6132     switch (eap->cmdidx)
6133     {
6134 	case CMD_tabfirst:
6135 	case CMD_tabrewind:
6136 	    goto_tabpage(1);
6137 	    break;
6138 	case CMD_tablast:
6139 	    goto_tabpage(9999);
6140 	    break;
6141 	case CMD_tabprevious:
6142 	case CMD_tabNext:
6143 	    if (eap->arg && *eap->arg != NUL)
6144 	    {
6145 		char_u *p = eap->arg;
6146 		char_u *p_save = p;
6147 
6148 		tab_number = getdigits(&p);
6149 		if (p == p_save || *p_save == '-' || *p != NUL
6150 			    || tab_number == 0)
6151 		{
6152 		    // No numbers as argument.
6153 		    eap->errmsg = ex_errmsg(e_invarg2, eap->arg);
6154 		    return;
6155 		}
6156 	    }
6157 	    else
6158 	    {
6159 		if (eap->addr_count == 0)
6160 		    tab_number = 1;
6161 		else
6162 		{
6163 		    tab_number = eap->line2;
6164 		    if (tab_number < 1)
6165 		    {
6166 			eap->errmsg = _(e_invrange);
6167 			return;
6168 		    }
6169 		}
6170 	    }
6171 	    goto_tabpage(-tab_number);
6172 	    break;
6173 	default: // CMD_tabnext
6174 	    tab_number = get_tabpage_arg(eap);
6175 	    if (eap->errmsg == NULL)
6176 		goto_tabpage(tab_number);
6177 	    break;
6178     }
6179 }
6180 
6181 /*
6182  * :tabmove command
6183  */
6184     static void
6185 ex_tabmove(exarg_T *eap)
6186 {
6187     int tab_number;
6188 
6189     tab_number = get_tabpage_arg(eap);
6190     if (eap->errmsg == NULL)
6191 	tabpage_move(tab_number);
6192 }
6193 
6194 /*
6195  * :tabs command: List tabs and their contents.
6196  */
6197     static void
6198 ex_tabs(exarg_T *eap UNUSED)
6199 {
6200     tabpage_T	*tp;
6201     win_T	*wp;
6202     int		tabcount = 1;
6203 
6204     msg_start();
6205     msg_scroll = TRUE;
6206     for (tp = first_tabpage; tp != NULL && !got_int; tp = tp->tp_next)
6207     {
6208 	msg_putchar('\n');
6209 	vim_snprintf((char *)IObuff, IOSIZE, _("Tab page %d"), tabcount++);
6210 	msg_outtrans_attr(IObuff, HL_ATTR(HLF_T));
6211 	out_flush();	    // output one line at a time
6212 	ui_breakcheck();
6213 
6214 	if (tp  == curtab)
6215 	    wp = firstwin;
6216 	else
6217 	    wp = tp->tp_firstwin;
6218 	for ( ; wp != NULL && !got_int; wp = wp->w_next)
6219 	{
6220 	    msg_putchar('\n');
6221 	    msg_putchar(wp == curwin ? '>' : ' ');
6222 	    msg_putchar(' ');
6223 	    msg_putchar(bufIsChanged(wp->w_buffer) ? '+' : ' ');
6224 	    msg_putchar(' ');
6225 	    if (buf_spname(wp->w_buffer) != NULL)
6226 		vim_strncpy(IObuff, buf_spname(wp->w_buffer), IOSIZE - 1);
6227 	    else
6228 		home_replace(wp->w_buffer, wp->w_buffer->b_fname,
6229 							IObuff, IOSIZE, TRUE);
6230 	    msg_outtrans(IObuff);
6231 	    out_flush();	    // output one line at a time
6232 	    ui_breakcheck();
6233 	}
6234     }
6235 }
6236 
6237 /*
6238  * ":mode": Set screen mode.
6239  * If no argument given, just get the screen size and redraw.
6240  */
6241     static void
6242 ex_mode(exarg_T *eap)
6243 {
6244     if (*eap->arg == NUL)
6245 	shell_resized();
6246     else
6247 	emsg(_(e_screenmode));
6248 }
6249 
6250 /*
6251  * ":resize".
6252  * set, increment or decrement current window height
6253  */
6254     static void
6255 ex_resize(exarg_T *eap)
6256 {
6257     int		n;
6258     win_T	*wp = curwin;
6259 
6260     if (eap->addr_count > 0)
6261     {
6262 	n = eap->line2;
6263 	for (wp = firstwin; wp->w_next != NULL && --n > 0; wp = wp->w_next)
6264 	    ;
6265     }
6266 
6267 # ifdef FEAT_GUI
6268     need_mouse_correct = TRUE;
6269 # endif
6270     n = atol((char *)eap->arg);
6271     if (cmdmod.split & WSP_VERT)
6272     {
6273 	if (*eap->arg == '-' || *eap->arg == '+')
6274 	    n += curwin->w_width;
6275 	else if (n == 0 && eap->arg[0] == NUL)	// default is very wide
6276 	    n = 9999;
6277 	win_setwidth_win((int)n, wp);
6278     }
6279     else
6280     {
6281 	if (*eap->arg == '-' || *eap->arg == '+')
6282 	    n += curwin->w_height;
6283 	else if (n == 0 && eap->arg[0] == NUL)	// default is very high
6284 	    n = 9999;
6285 	win_setheight_win((int)n, wp);
6286     }
6287 }
6288 
6289 /*
6290  * ":find [+command] <file>" command.
6291  */
6292     static void
6293 ex_find(exarg_T *eap)
6294 {
6295 #ifdef FEAT_SEARCHPATH
6296     char_u	*fname;
6297     int		count;
6298 
6299     fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg), FNAME_MESS,
6300 						      TRUE, curbuf->b_ffname);
6301     if (eap->addr_count > 0)
6302     {
6303 	// Repeat finding the file "count" times.  This matters when it
6304 	// appears several times in the path.
6305 	count = eap->line2;
6306 	while (fname != NULL && --count > 0)
6307 	{
6308 	    vim_free(fname);
6309 	    fname = find_file_in_path(NULL, 0, FNAME_MESS,
6310 						     FALSE, curbuf->b_ffname);
6311 	}
6312     }
6313 
6314     if (fname != NULL)
6315     {
6316 	eap->arg = fname;
6317 #endif
6318 	do_exedit(eap, NULL);
6319 #ifdef FEAT_SEARCHPATH
6320 	vim_free(fname);
6321     }
6322 #endif
6323 }
6324 
6325 /*
6326  * ":open" simulation: for now just work like ":visual".
6327  */
6328     static void
6329 ex_open(exarg_T *eap)
6330 {
6331     regmatch_T	regmatch;
6332     char_u	*p;
6333 
6334     curwin->w_cursor.lnum = eap->line2;
6335     beginline(BL_SOL | BL_FIX);
6336     if (*eap->arg == '/')
6337     {
6338 	// ":open /pattern/": put cursor in column found with pattern
6339 	++eap->arg;
6340 	p = skip_regexp(eap->arg, '/', p_magic);
6341 	*p = NUL;
6342 	regmatch.regprog = vim_regcomp(eap->arg, p_magic ? RE_MAGIC : 0);
6343 	if (regmatch.regprog != NULL)
6344 	{
6345 	    regmatch.rm_ic = p_ic;
6346 	    p = ml_get_curline();
6347 	    if (vim_regexec(&regmatch, p, (colnr_T)0))
6348 		curwin->w_cursor.col = (colnr_T)(regmatch.startp[0] - p);
6349 	    else
6350 		emsg(_(e_nomatch));
6351 	    vim_regfree(regmatch.regprog);
6352 	}
6353 	// Move to the NUL, ignore any other arguments.
6354 	eap->arg += STRLEN(eap->arg);
6355     }
6356     check_cursor();
6357 
6358     eap->cmdidx = CMD_visual;
6359     do_exedit(eap, NULL);
6360 }
6361 
6362 /*
6363  * ":edit", ":badd", ":visual".
6364  */
6365     static void
6366 ex_edit(exarg_T *eap)
6367 {
6368     do_exedit(eap, NULL);
6369 }
6370 
6371 /*
6372  * ":edit <file>" command and alike.
6373  */
6374     void
6375 do_exedit(
6376     exarg_T	*eap,
6377     win_T	*old_curwin)	    // curwin before doing a split or NULL
6378 {
6379     int		n;
6380     int		need_hide;
6381     int		exmode_was = exmode_active;
6382 
6383     if ((eap->cmdidx != CMD_pedit && ERROR_IF_POPUP_WINDOW)
6384 						 || ERROR_IF_TERM_POPUP_WINDOW)
6385 	return;
6386     /*
6387      * ":vi" command ends Ex mode.
6388      */
6389     if (exmode_active && (eap->cmdidx == CMD_visual
6390 						|| eap->cmdidx == CMD_view))
6391     {
6392 	exmode_active = FALSE;
6393 	ex_pressedreturn = FALSE;
6394 	if (*eap->arg == NUL)
6395 	{
6396 	    // Special case:  ":global/pat/visual\NLvi-commands"
6397 	    if (global_busy)
6398 	    {
6399 		int	rd = RedrawingDisabled;
6400 		int	nwr = no_wait_return;
6401 		int	ms = msg_scroll;
6402 #ifdef FEAT_GUI
6403 		int	he = hold_gui_events;
6404 #endif
6405 
6406 		if (eap->nextcmd != NULL)
6407 		{
6408 		    stuffReadbuff(eap->nextcmd);
6409 		    eap->nextcmd = NULL;
6410 		}
6411 
6412 		if (exmode_was != EXMODE_VIM)
6413 		    settmode(TMODE_RAW);
6414 		RedrawingDisabled = 0;
6415 		no_wait_return = 0;
6416 		need_wait_return = FALSE;
6417 		msg_scroll = 0;
6418 #ifdef FEAT_GUI
6419 		hold_gui_events = 0;
6420 #endif
6421 		must_redraw = CLEAR;
6422 		pending_exmode_active = TRUE;
6423 
6424 		main_loop(FALSE, TRUE);
6425 
6426 		pending_exmode_active = FALSE;
6427 		RedrawingDisabled = rd;
6428 		no_wait_return = nwr;
6429 		msg_scroll = ms;
6430 #ifdef FEAT_GUI
6431 		hold_gui_events = he;
6432 #endif
6433 	    }
6434 	    return;
6435 	}
6436     }
6437 
6438     if ((eap->cmdidx == CMD_new
6439 		|| eap->cmdidx == CMD_tabnew
6440 		|| eap->cmdidx == CMD_tabedit
6441 		|| eap->cmdidx == CMD_vnew) && *eap->arg == NUL)
6442     {
6443 	// ":new" or ":tabnew" without argument: edit an new empty buffer
6444 	setpcmark();
6445 	(void)do_ecmd(0, NULL, NULL, eap, ECMD_ONE,
6446 		      ECMD_HIDE + (eap->forceit ? ECMD_FORCEIT : 0),
6447 		      old_curwin == NULL ? curwin : NULL);
6448     }
6449     else if ((eap->cmdidx != CMD_split && eap->cmdidx != CMD_vsplit)
6450 	    || *eap->arg != NUL
6451 #ifdef FEAT_BROWSE
6452 	    || cmdmod.browse
6453 #endif
6454 	    )
6455     {
6456 	// Can't edit another file when "curbuf_lock" is set.  Only ":edit"
6457 	// can bring us here, others are stopped earlier.
6458 	if (*eap->arg != NUL && curbuf_locked())
6459 	    return;
6460 
6461 	n = readonlymode;
6462 	if (eap->cmdidx == CMD_view || eap->cmdidx == CMD_sview)
6463 	    readonlymode = TRUE;
6464 	else if (eap->cmdidx == CMD_enew)
6465 	    readonlymode = FALSE;   // 'readonly' doesn't make sense in an
6466 				    // empty buffer
6467 	setpcmark();
6468 	if (do_ecmd(0, (eap->cmdidx == CMD_enew ? NULL : eap->arg),
6469 		    NULL, eap,
6470 		    // ":edit" goes to first line if Vi compatible
6471 		    (*eap->arg == NUL && eap->do_ecmd_lnum == 0
6472 				      && vim_strchr(p_cpo, CPO_GOTO1) != NULL)
6473 					       ? ECMD_ONE : eap->do_ecmd_lnum,
6474 		    (buf_hide(curbuf) ? ECMD_HIDE : 0)
6475 		    + (eap->forceit ? ECMD_FORCEIT : 0)
6476 		      // after a split we can use an existing buffer
6477 		    + (old_curwin != NULL ? ECMD_OLDBUF : 0)
6478 		    + (eap->cmdidx == CMD_badd ? ECMD_ADDBUF : 0 )
6479 		    , old_curwin == NULL ? curwin : NULL) == FAIL)
6480 	{
6481 	    // Editing the file failed.  If the window was split, close it.
6482 	    if (old_curwin != NULL)
6483 	    {
6484 		need_hide = (curbufIsChanged() && curbuf->b_nwindows <= 1);
6485 		if (!need_hide || buf_hide(curbuf))
6486 		{
6487 #if defined(FEAT_EVAL)
6488 		    cleanup_T   cs;
6489 
6490 		    // Reset the error/interrupt/exception state here so that
6491 		    // aborting() returns FALSE when closing a window.
6492 		    enter_cleanup(&cs);
6493 #endif
6494 #ifdef FEAT_GUI
6495 		    need_mouse_correct = TRUE;
6496 #endif
6497 		    win_close(curwin, !need_hide && !buf_hide(curbuf));
6498 
6499 #if defined(FEAT_EVAL)
6500 		    // Restore the error/interrupt/exception state if not
6501 		    // discarded by a new aborting error, interrupt, or
6502 		    // uncaught exception.
6503 		    leave_cleanup(&cs);
6504 #endif
6505 		}
6506 	    }
6507 	}
6508 	else if (readonlymode && curbuf->b_nwindows == 1)
6509 	{
6510 	    // When editing an already visited buffer, 'readonly' won't be set
6511 	    // but the previous value is kept.  With ":view" and ":sview" we
6512 	    // want the  file to be readonly, except when another window is
6513 	    // editing the same buffer.
6514 	    curbuf->b_p_ro = TRUE;
6515 	}
6516 	readonlymode = n;
6517     }
6518     else
6519     {
6520 	if (eap->do_ecmd_cmd != NULL)
6521 	    do_cmdline_cmd(eap->do_ecmd_cmd);
6522 #ifdef FEAT_TITLE
6523 	n = curwin->w_arg_idx_invalid;
6524 #endif
6525 	check_arg_idx(curwin);
6526 #ifdef FEAT_TITLE
6527 	if (n != curwin->w_arg_idx_invalid)
6528 	    maketitle();
6529 #endif
6530     }
6531 
6532     /*
6533      * if ":split file" worked, set alternate file name in old window to new
6534      * file
6535      */
6536     if (old_curwin != NULL
6537 	    && *eap->arg != NUL
6538 	    && curwin != old_curwin
6539 	    && win_valid(old_curwin)
6540 	    && old_curwin->w_buffer != curbuf
6541 	    && !cmdmod.keepalt)
6542 	old_curwin->w_alt_fnum = curbuf->b_fnum;
6543 
6544     ex_no_reprint = TRUE;
6545 }
6546 
6547 #ifndef FEAT_GUI
6548 /*
6549  * ":gui" and ":gvim" when there is no GUI.
6550  */
6551     static void
6552 ex_nogui(exarg_T *eap)
6553 {
6554     eap->errmsg = _(e_nogvim);
6555 }
6556 #endif
6557 
6558 #if defined(FEAT_GUI_MSWIN) && defined(FEAT_MENU) && defined(FEAT_TEAROFF)
6559     static void
6560 ex_tearoff(exarg_T *eap)
6561 {
6562     gui_make_tearoff(eap->arg);
6563 }
6564 #endif
6565 
6566 #if (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK) \
6567 	|| defined(FEAT_TERM_POPUP_MENU)) && defined(FEAT_MENU)
6568     static void
6569 ex_popup(exarg_T *eap)
6570 {
6571 # if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK)
6572     if (gui.in_use)
6573 	gui_make_popup(eap->arg, eap->forceit);
6574 #  ifdef FEAT_TERM_POPUP_MENU
6575     else
6576 #  endif
6577 # endif
6578 # ifdef FEAT_TERM_POPUP_MENU
6579 	pum_make_popup(eap->arg, eap->forceit);
6580 # endif
6581 }
6582 #endif
6583 
6584     static void
6585 ex_swapname(exarg_T *eap UNUSED)
6586 {
6587     if (curbuf->b_ml.ml_mfp == NULL || curbuf->b_ml.ml_mfp->mf_fname == NULL)
6588 	msg(_("No swap file"));
6589     else
6590 	msg((char *)curbuf->b_ml.ml_mfp->mf_fname);
6591 }
6592 
6593 /*
6594  * ":syncbind" forces all 'scrollbind' windows to have the same relative
6595  * offset.
6596  * (1998-11-02 16:21:01  R. Edward Ralston <[email protected]>)
6597  */
6598     static void
6599 ex_syncbind(exarg_T *eap UNUSED)
6600 {
6601     win_T	*wp;
6602     win_T	*save_curwin = curwin;
6603     buf_T	*save_curbuf = curbuf;
6604     long	topline;
6605     long	y;
6606     linenr_T	old_linenr = curwin->w_cursor.lnum;
6607 
6608     setpcmark();
6609 
6610     /*
6611      * determine max topline
6612      */
6613     if (curwin->w_p_scb)
6614     {
6615 	topline = curwin->w_topline;
6616 	FOR_ALL_WINDOWS(wp)
6617 	{
6618 	    if (wp->w_p_scb && wp->w_buffer)
6619 	    {
6620 		y = wp->w_buffer->b_ml.ml_line_count - get_scrolloff_value();
6621 		if (topline > y)
6622 		    topline = y;
6623 	    }
6624 	}
6625 	if (topline < 1)
6626 	    topline = 1;
6627     }
6628     else
6629     {
6630 	topline = 1;
6631     }
6632 
6633 
6634     /*
6635      * Set all scrollbind windows to the same topline.
6636      */
6637     FOR_ALL_WINDOWS(curwin)
6638     {
6639 	if (curwin->w_p_scb)
6640 	{
6641 	    curbuf = curwin->w_buffer;
6642 	    y = topline - curwin->w_topline;
6643 	    if (y > 0)
6644 		scrollup(y, TRUE);
6645 	    else
6646 		scrolldown(-y, TRUE);
6647 	    curwin->w_scbind_pos = topline;
6648 	    redraw_later(VALID);
6649 	    cursor_correct();
6650 	    curwin->w_redr_status = TRUE;
6651 	}
6652     }
6653     curwin = save_curwin;
6654     curbuf = save_curbuf;
6655     if (curwin->w_p_scb)
6656     {
6657 	did_syncbind = TRUE;
6658 	checkpcmark();
6659 	if (old_linenr != curwin->w_cursor.lnum)
6660 	{
6661 	    char_u ctrl_o[2];
6662 
6663 	    ctrl_o[0] = Ctrl_O;
6664 	    ctrl_o[1] = 0;
6665 	    ins_typebuf(ctrl_o, REMAP_NONE, 0, TRUE, FALSE);
6666 	}
6667     }
6668 }
6669 
6670 
6671     static void
6672 ex_read(exarg_T *eap)
6673 {
6674     int		i;
6675     int		empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
6676     linenr_T	lnum;
6677 
6678     if (eap->usefilter)			// :r!cmd
6679 	do_bang(1, eap, FALSE, FALSE, TRUE);
6680     else
6681     {
6682 	if (u_save(eap->line2, (linenr_T)(eap->line2 + 1)) == FAIL)
6683 	    return;
6684 
6685 #ifdef FEAT_BROWSE
6686 	if (cmdmod.browse)
6687 	{
6688 	    char_u *browseFile;
6689 
6690 	    browseFile = do_browse(0, (char_u *)_("Append File"), eap->arg,
6691 						    NULL, NULL, NULL, curbuf);
6692 	    if (browseFile != NULL)
6693 	    {
6694 		i = readfile(browseFile, NULL,
6695 			  eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0);
6696 		vim_free(browseFile);
6697 	    }
6698 	    else
6699 		i = OK;
6700 	}
6701 	else
6702 #endif
6703 	     if (*eap->arg == NUL)
6704 	{
6705 	    if (check_fname() == FAIL)	// check for no file name
6706 		return;
6707 	    i = readfile(curbuf->b_ffname, curbuf->b_fname,
6708 			  eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0);
6709 	}
6710 	else
6711 	{
6712 	    if (vim_strchr(p_cpo, CPO_ALTREAD) != NULL)
6713 		(void)setaltfname(eap->arg, eap->arg, (linenr_T)1);
6714 	    i = readfile(eap->arg, NULL,
6715 			  eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0);
6716 
6717 	}
6718 	if (i != OK)
6719 	{
6720 #if defined(FEAT_EVAL)
6721 	    if (!aborting())
6722 #endif
6723 		semsg(_(e_notopen), eap->arg);
6724 	}
6725 	else
6726 	{
6727 	    if (empty && exmode_active)
6728 	    {
6729 		// Delete the empty line that remains.  Historically ex does
6730 		// this but vi doesn't.
6731 		if (eap->line2 == 0)
6732 		    lnum = curbuf->b_ml.ml_line_count;
6733 		else
6734 		    lnum = 1;
6735 		if (*ml_get(lnum) == NUL && u_savedel(lnum, 1L) == OK)
6736 		{
6737 		    ml_delete(lnum);
6738 		    if (curwin->w_cursor.lnum > 1
6739 					     && curwin->w_cursor.lnum >= lnum)
6740 			--curwin->w_cursor.lnum;
6741 		    deleted_lines_mark(lnum, 1L);
6742 		}
6743 	    }
6744 	    redraw_curbuf_later(VALID);
6745 	}
6746     }
6747 }
6748 
6749 static char_u	*prev_dir = NULL;
6750 
6751 #if defined(EXITFREE) || defined(PROTO)
6752     void
6753 free_cd_dir(void)
6754 {
6755     VIM_CLEAR(prev_dir);
6756     VIM_CLEAR(globaldir);
6757 }
6758 #endif
6759 
6760 /*
6761  * Get the previous directory for the given chdir scope.
6762  */
6763     static char_u *
6764 get_prevdir(cdscope_T scope)
6765 {
6766     if (scope == CDSCOPE_WINDOW)
6767 	return curwin->w_prevdir;
6768     else if (scope == CDSCOPE_TABPAGE)
6769 	return curtab->tp_prevdir;
6770     return prev_dir;
6771 }
6772 
6773 /*
6774  * Deal with the side effects of changing the current directory.
6775  * When 'scope' is CDSCOPE_TABPAGE then this was after an ":tcd" command.
6776  * When 'scope' is CDSCOPE_WINDOW then this was after an ":lcd" command.
6777  */
6778     void
6779 post_chdir(cdscope_T scope)
6780 {
6781     if (scope != CDSCOPE_WINDOW)
6782 	// Clear tab local directory for both :cd and :tcd
6783 	VIM_CLEAR(curtab->tp_localdir);
6784     VIM_CLEAR(curwin->w_localdir);
6785     if (scope != CDSCOPE_GLOBAL)
6786     {
6787 	char_u	*pdir = get_prevdir(scope);
6788 
6789 	// If still in the global directory, need to remember current
6790 	// directory as the global directory.
6791 	if (globaldir == NULL && pdir != NULL)
6792 	    globaldir = vim_strsave(pdir);
6793 
6794 	// Remember this local directory for the window.
6795 	if (mch_dirname(NameBuff, MAXPATHL) == OK)
6796 	{
6797 	    if (scope == CDSCOPE_TABPAGE)
6798 		curtab->tp_localdir = vim_strsave(NameBuff);
6799 	    else
6800 		curwin->w_localdir = vim_strsave(NameBuff);
6801 	}
6802     }
6803     else
6804     {
6805 	// We are now in the global directory, no need to remember its name.
6806 	VIM_CLEAR(globaldir);
6807     }
6808 
6809     shorten_fnames(TRUE);
6810 }
6811 
6812 /*
6813  * Change directory function used by :cd/:tcd/:lcd Ex commands and the
6814  * chdir() function.
6815  * scope == CDSCOPE_WINDOW: changes the window-local directory
6816  * scope == CDSCOPE_TABPAGE: changes the tab-local directory
6817  * Otherwise: changes the global directory
6818  * Returns TRUE if the directory is successfully changed.
6819  */
6820     int
6821 changedir_func(
6822 	char_u		*new_dir,
6823 	int		forceit,
6824 	cdscope_T	scope)
6825 {
6826     char_u	*tofree;
6827     char_u	*pdir = NULL;
6828     int		dir_differs;
6829     int		retval = FALSE;
6830 
6831     if (new_dir == NULL || allbuf_locked())
6832 	return FALSE;
6833 
6834     if (vim_strchr(p_cpo, CPO_CHDIR) != NULL && curbufIsChanged() && !forceit)
6835     {
6836 	emsg(_("E747: Cannot change directory, buffer is modified (add ! to override)"));
6837 	return FALSE;
6838     }
6839 
6840     // ":cd -": Change to previous directory
6841     if (STRCMP(new_dir, "-") == 0)
6842     {
6843 	pdir = get_prevdir(scope);
6844 	if (pdir == NULL)
6845 	{
6846 	    emsg(_("E186: No previous directory"));
6847 	    return FALSE;
6848 	}
6849 	new_dir = pdir;
6850     }
6851 
6852     // Free the previous directory
6853     tofree = get_prevdir(scope);
6854 
6855     // Save current directory for next ":cd -"
6856     if (mch_dirname(NameBuff, MAXPATHL) == OK)
6857 	pdir = vim_strsave(NameBuff);
6858     else
6859 	pdir = NULL;
6860     if (scope == CDSCOPE_WINDOW)
6861 	curwin->w_prevdir = pdir;
6862     else if (scope == CDSCOPE_TABPAGE)
6863 	curtab->tp_prevdir = pdir;
6864     else
6865 	prev_dir = pdir;
6866 
6867 #if defined(UNIX) || defined(VMS)
6868     // for UNIX ":cd" means: go to home directory
6869     if (*new_dir == NUL)
6870     {
6871 	// use NameBuff for home directory name
6872 # ifdef VMS
6873 	char_u	*p;
6874 
6875 	p = mch_getenv((char_u *)"SYS$LOGIN");
6876 	if (p == NULL || *p == NUL)	// empty is the same as not set
6877 	    NameBuff[0] = NUL;
6878 	else
6879 	    vim_strncpy(NameBuff, p, MAXPATHL - 1);
6880 # else
6881 	expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);
6882 # endif
6883 	new_dir = NameBuff;
6884     }
6885 #endif
6886     dir_differs = new_dir == NULL || pdir == NULL
6887 	|| pathcmp((char *)pdir, (char *)new_dir, -1) != 0;
6888     if (new_dir == NULL || (dir_differs && vim_chdir(new_dir)))
6889 	emsg(_(e_failed));
6890     else
6891     {
6892 	char_u  *acmd_fname;
6893 
6894 	post_chdir(scope);
6895 
6896 	if (dir_differs)
6897 	{
6898 	    if (scope == CDSCOPE_WINDOW)
6899 		acmd_fname = (char_u *)"window";
6900 	    else if (scope == CDSCOPE_TABPAGE)
6901 		acmd_fname = (char_u *)"tabpage";
6902 	    else
6903 		acmd_fname = (char_u *)"global";
6904 	    apply_autocmds(EVENT_DIRCHANGED, acmd_fname, new_dir, FALSE,
6905 								curbuf);
6906 	}
6907 	retval = TRUE;
6908     }
6909     vim_free(tofree);
6910 
6911     return retval;
6912 }
6913 
6914 /*
6915  * ":cd", ":tcd", ":lcd", ":chdir" ":tchdir" and ":lchdir".
6916  */
6917     void
6918 ex_cd(exarg_T *eap)
6919 {
6920     char_u	*new_dir;
6921 
6922     new_dir = eap->arg;
6923 #if !defined(UNIX) && !defined(VMS)
6924     // for non-UNIX ":cd" means: print current directory
6925     if (*new_dir == NUL)
6926 	ex_pwd(NULL);
6927     else
6928 #endif
6929     {
6930 	cdscope_T	scope = CDSCOPE_GLOBAL;
6931 
6932 	if (eap->cmdidx == CMD_lcd || eap->cmdidx == CMD_lchdir)
6933 	    scope = CDSCOPE_WINDOW;
6934 	else if (eap->cmdidx == CMD_tcd || eap->cmdidx == CMD_tchdir)
6935 	    scope = CDSCOPE_TABPAGE;
6936 
6937 	if (changedir_func(new_dir, eap->forceit, scope))
6938 	{
6939 	    // Echo the new current directory if the command was typed.
6940 	    if (KeyTyped || p_verbose >= 5)
6941 		ex_pwd(eap);
6942 	}
6943     }
6944 }
6945 
6946 /*
6947  * ":pwd".
6948  */
6949     static void
6950 ex_pwd(exarg_T *eap UNUSED)
6951 {
6952     if (mch_dirname(NameBuff, MAXPATHL) == OK)
6953     {
6954 #ifdef BACKSLASH_IN_FILENAME
6955 	slash_adjust(NameBuff);
6956 #endif
6957 	if (p_verbose > 0)
6958 	{
6959 	    char *context = "global";
6960 
6961 	    if (curwin->w_localdir != NULL)
6962 		context = "window";
6963 	    else if (curtab->tp_localdir != NULL)
6964 		context = "tabpage";
6965 	    smsg("[%s] %s", context, (char *)NameBuff);
6966 	}
6967 	else
6968 	    msg((char *)NameBuff);
6969     }
6970     else
6971 	emsg(_("E187: Unknown"));
6972 }
6973 
6974 /*
6975  * ":=".
6976  */
6977     static void
6978 ex_equal(exarg_T *eap)
6979 {
6980     smsg("%ld", (long)eap->line2);
6981     ex_may_print(eap);
6982 }
6983 
6984     static void
6985 ex_sleep(exarg_T *eap)
6986 {
6987     int		n;
6988     long	len;
6989 
6990     if (cursor_valid())
6991     {
6992 	n = W_WINROW(curwin) + curwin->w_wrow - msg_scrolled;
6993 	if (n >= 0)
6994 	    windgoto((int)n, curwin->w_wincol + curwin->w_wcol);
6995     }
6996 
6997     len = eap->line2;
6998     switch (*eap->arg)
6999     {
7000 	case 'm': break;
7001 	case NUL: len *= 1000L; break;
7002 	default: semsg(_(e_invarg2), eap->arg); return;
7003     }
7004     do_sleep(len);
7005 }
7006 
7007 /*
7008  * Sleep for "msec" milliseconds, but keep checking for a CTRL-C every second.
7009  */
7010     void
7011 do_sleep(long msec)
7012 {
7013     long	done = 0;
7014     long	wait_now;
7015 # ifdef ELAPSED_FUNC
7016     elapsed_T	start_tv;
7017 
7018     // Remember at what time we started, so that we know how much longer we
7019     // should wait after waiting for a bit.
7020     ELAPSED_INIT(start_tv);
7021 # endif
7022 
7023     cursor_on();
7024     out_flush_cursor(FALSE, FALSE);
7025     while (!got_int && done < msec)
7026     {
7027 	wait_now = msec - done > 1000L ? 1000L : msec - done;
7028 #ifdef FEAT_TIMERS
7029 	{
7030 	    long    due_time = check_due_timer();
7031 
7032 	    if (due_time > 0 && due_time < wait_now)
7033 		wait_now = due_time;
7034 	}
7035 #endif
7036 #ifdef FEAT_JOB_CHANNEL
7037 	if (has_any_channel() && wait_now > 20L)
7038 	    wait_now = 20L;
7039 #endif
7040 #ifdef FEAT_SOUND
7041 	if (has_any_sound_callback() && wait_now > 20L)
7042 	    wait_now = 20L;
7043 #endif
7044 	ui_delay(wait_now, TRUE);
7045 
7046 #ifdef FEAT_JOB_CHANNEL
7047 	if (has_any_channel())
7048 	    ui_breakcheck_force(TRUE);
7049 	else
7050 #endif
7051 	    ui_breakcheck();
7052 #ifdef MESSAGE_QUEUE
7053 	// Process the netbeans and clientserver messages that may have been
7054 	// received in the call to ui_breakcheck() when the GUI is in use. This
7055 	// may occur when running a test case.
7056 	parse_queued_messages();
7057 #endif
7058 
7059 # ifdef ELAPSED_FUNC
7060 	// actual time passed
7061 	done = ELAPSED_FUNC(start_tv);
7062 # else
7063 	// guestimate time passed (will actually be more)
7064 	done += wait_now;
7065 # endif
7066     }
7067 
7068     // If CTRL-C was typed to interrupt the sleep, drop the CTRL-C from the
7069     // input buffer, otherwise a following call to input() fails.
7070     if (got_int)
7071 	(void)vpeekc();
7072 }
7073 
7074 /*
7075  * ":winsize" command (obsolete).
7076  */
7077     static void
7078 ex_winsize(exarg_T *eap)
7079 {
7080     int		w, h;
7081     char_u	*arg = eap->arg;
7082     char_u	*p;
7083 
7084     w = getdigits(&arg);
7085     arg = skipwhite(arg);
7086     p = arg;
7087     h = getdigits(&arg);
7088     if (*p != NUL && *arg == NUL)
7089 	set_shellsize(w, h, TRUE);
7090     else
7091 	emsg(_("E465: :winsize requires two number arguments"));
7092 }
7093 
7094     static void
7095 ex_wincmd(exarg_T *eap)
7096 {
7097     int		xchar = NUL;
7098     char_u	*p;
7099 
7100     if (*eap->arg == 'g' || *eap->arg == Ctrl_G)
7101     {
7102 	// CTRL-W g and CTRL-W CTRL-G  have an extra command character
7103 	if (eap->arg[1] == NUL)
7104 	{
7105 	    emsg(_(e_invarg));
7106 	    return;
7107 	}
7108 	xchar = eap->arg[1];
7109 	p = eap->arg + 2;
7110     }
7111     else
7112 	p = eap->arg + 1;
7113 
7114     eap->nextcmd = check_nextcmd(p);
7115     p = skipwhite(p);
7116     if (*p != NUL && *p != (
7117 #ifdef FEAT_EVAL
7118 	    in_vim9script() ? '#' :
7119 #endif
7120 		'"')
7121 	    && eap->nextcmd == NULL)
7122 	emsg(_(e_invarg));
7123     else if (!eap->skip)
7124     {
7125 	// Pass flags on for ":vertical wincmd ]".
7126 	postponed_split_flags = cmdmod.split;
7127 	postponed_split_tab = cmdmod.tab;
7128 	do_window(*eap->arg, eap->addr_count > 0 ? eap->line2 : 0L, xchar);
7129 	postponed_split_flags = 0;
7130 	postponed_split_tab = 0;
7131     }
7132 }
7133 
7134 #if defined(FEAT_GUI) || defined(UNIX) || defined(VMS) || defined(MSWIN)
7135 /*
7136  * ":winpos".
7137  */
7138     static void
7139 ex_winpos(exarg_T *eap)
7140 {
7141     int		x, y;
7142     char_u	*arg = eap->arg;
7143     char_u	*p;
7144 
7145     if (*arg == NUL)
7146     {
7147 # if defined(FEAT_GUI) || defined(MSWIN)
7148 #  ifdef VIMDLL
7149 	if (gui.in_use ? gui_mch_get_winpos(&x, &y) != FAIL :
7150 		mch_get_winpos(&x, &y) != FAIL)
7151 #  elif defined(FEAT_GUI)
7152 	if (gui.in_use && gui_mch_get_winpos(&x, &y) != FAIL)
7153 #  else
7154 	if (mch_get_winpos(&x, &y) != FAIL)
7155 #  endif
7156 	{
7157 	    sprintf((char *)IObuff, _("Window position: X %d, Y %d"), x, y);
7158 	    msg((char *)IObuff);
7159 	}
7160 	else
7161 # endif
7162 	    emsg(_("E188: Obtaining window position not implemented for this platform"));
7163     }
7164     else
7165     {
7166 	x = getdigits(&arg);
7167 	arg = skipwhite(arg);
7168 	p = arg;
7169 	y = getdigits(&arg);
7170 	if (*p == NUL || *arg != NUL)
7171 	{
7172 	    emsg(_("E466: :winpos requires two number arguments"));
7173 	    return;
7174 	}
7175 # ifdef FEAT_GUI
7176 	if (gui.in_use)
7177 	    gui_mch_set_winpos(x, y);
7178 	else if (gui.starting)
7179 	{
7180 	    // Remember the coordinates for when the window is opened.
7181 	    gui_win_x = x;
7182 	    gui_win_y = y;
7183 	}
7184 #  if defined(HAVE_TGETENT) || defined(VIMDLL)
7185 	else
7186 #  endif
7187 # endif
7188 # if defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))
7189 	    mch_set_winpos(x, y);
7190 # endif
7191 # ifdef HAVE_TGETENT
7192 	if (*T_CWP)
7193 	    term_set_winpos(x, y);
7194 # endif
7195     }
7196 }
7197 #endif
7198 
7199 /*
7200  * Handle command that work like operators: ":delete", ":yank", ":>" and ":<".
7201  */
7202     static void
7203 ex_operators(exarg_T *eap)
7204 {
7205     oparg_T	oa;
7206 
7207     clear_oparg(&oa);
7208     oa.regname = eap->regname;
7209     oa.start.lnum = eap->line1;
7210     oa.end.lnum = eap->line2;
7211     oa.line_count = eap->line2 - eap->line1 + 1;
7212     oa.motion_type = MLINE;
7213     virtual_op = FALSE;
7214     if (eap->cmdidx != CMD_yank)	// position cursor for undo
7215     {
7216 	setpcmark();
7217 	curwin->w_cursor.lnum = eap->line1;
7218 	beginline(BL_SOL | BL_FIX);
7219     }
7220 
7221     if (VIsual_active)
7222 	end_visual_mode();
7223 
7224     switch (eap->cmdidx)
7225     {
7226 	case CMD_delete:
7227 	    oa.op_type = OP_DELETE;
7228 	    op_delete(&oa);
7229 	    break;
7230 
7231 	case CMD_yank:
7232 	    oa.op_type = OP_YANK;
7233 	    (void)op_yank(&oa, FALSE, TRUE);
7234 	    break;
7235 
7236 	default:    // CMD_rshift or CMD_lshift
7237 	    if (
7238 #ifdef FEAT_RIGHTLEFT
7239 		(eap->cmdidx == CMD_rshift) ^ curwin->w_p_rl
7240 #else
7241 		eap->cmdidx == CMD_rshift
7242 #endif
7243 						)
7244 		oa.op_type = OP_RSHIFT;
7245 	    else
7246 		oa.op_type = OP_LSHIFT;
7247 	    op_shift(&oa, FALSE, eap->amount);
7248 	    break;
7249     }
7250     virtual_op = MAYBE;
7251     ex_may_print(eap);
7252 }
7253 
7254 /*
7255  * ":put".
7256  */
7257     static void
7258 ex_put(exarg_T *eap)
7259 {
7260     // ":0put" works like ":1put!".
7261     if (eap->line2 == 0)
7262     {
7263 	eap->line2 = 1;
7264 	eap->forceit = TRUE;
7265     }
7266     curwin->w_cursor.lnum = eap->line2;
7267     do_put(eap->regname, eap->forceit ? BACKWARD : FORWARD, 1L,
7268 						       PUT_LINE|PUT_CURSLINE);
7269 }
7270 
7271 /*
7272  * Handle ":copy" and ":move".
7273  */
7274     static void
7275 ex_copymove(exarg_T *eap)
7276 {
7277     long	n;
7278 
7279     n = get_address(eap, &eap->arg, eap->addr_type, FALSE, FALSE, FALSE, 1);
7280     if (eap->arg == NULL)	    // error detected
7281     {
7282 	eap->nextcmd = NULL;
7283 	return;
7284     }
7285     get_flags(eap);
7286 
7287     /*
7288      * move or copy lines from 'eap->line1'-'eap->line2' to below line 'n'
7289      */
7290     if (n == MAXLNUM || n < 0 || n > curbuf->b_ml.ml_line_count)
7291     {
7292 	emsg(_(e_invrange));
7293 	return;
7294     }
7295 
7296     if (eap->cmdidx == CMD_move)
7297     {
7298 	if (do_move(eap->line1, eap->line2, n) == FAIL)
7299 	    return;
7300     }
7301     else
7302 	ex_copy(eap->line1, eap->line2, n);
7303     u_clearline();
7304     beginline(BL_SOL | BL_FIX);
7305     ex_may_print(eap);
7306 }
7307 
7308 /*
7309  * Print the current line if flags were given to the Ex command.
7310  */
7311     void
7312 ex_may_print(exarg_T *eap)
7313 {
7314     if (eap->flags != 0)
7315     {
7316 	print_line(curwin->w_cursor.lnum, (eap->flags & EXFLAG_NR),
7317 						  (eap->flags & EXFLAG_LIST));
7318 	ex_no_reprint = TRUE;
7319     }
7320 }
7321 
7322 /*
7323  * ":smagic" and ":snomagic".
7324  */
7325     static void
7326 ex_submagic(exarg_T *eap)
7327 {
7328     int		magic_save = p_magic;
7329 
7330     p_magic = (eap->cmdidx == CMD_smagic);
7331     do_sub(eap);
7332     p_magic = magic_save;
7333 }
7334 
7335 /*
7336  * ":join".
7337  */
7338     static void
7339 ex_join(exarg_T *eap)
7340 {
7341     curwin->w_cursor.lnum = eap->line1;
7342     if (eap->line1 == eap->line2)
7343     {
7344 	if (eap->addr_count >= 2)   // :2,2join does nothing
7345 	    return;
7346 	if (eap->line2 == curbuf->b_ml.ml_line_count)
7347 	{
7348 	    beep_flush();
7349 	    return;
7350 	}
7351 	++eap->line2;
7352     }
7353     (void)do_join(eap->line2 - eap->line1 + 1, !eap->forceit, TRUE, TRUE, TRUE);
7354     beginline(BL_WHITE | BL_FIX);
7355     ex_may_print(eap);
7356 }
7357 
7358 /*
7359  * ":[addr]@r" or ":[addr]*r": execute register
7360  */
7361     static void
7362 ex_at(exarg_T *eap)
7363 {
7364     int		c;
7365     int		prev_len = typebuf.tb_len;
7366 
7367     curwin->w_cursor.lnum = eap->line2;
7368     check_cursor_col();
7369 
7370 #ifdef USE_ON_FLY_SCROLL
7371     dont_scroll = TRUE;		// disallow scrolling here
7372 #endif
7373 
7374     // get the register name.  No name means to use the previous one
7375     c = *eap->arg;
7376     if (c == NUL || (c == '*' && *eap->cmd == '*'))
7377 	c = '@';
7378     // Put the register in the typeahead buffer with the "silent" flag.
7379     if (do_execreg(c, TRUE, vim_strchr(p_cpo, CPO_EXECBUF) != NULL, TRUE)
7380 								      == FAIL)
7381     {
7382 	beep_flush();
7383     }
7384     else
7385     {
7386 	int	save_efr = exec_from_reg;
7387 
7388 	exec_from_reg = TRUE;
7389 
7390 	/*
7391 	 * Execute from the typeahead buffer.
7392 	 * Continue until the stuff buffer is empty and all added characters
7393 	 * have been consumed.
7394 	 */
7395 	while (!stuff_empty() || typebuf.tb_len > prev_len)
7396 	    (void)do_cmdline(NULL, getexline, NULL, DOCMD_NOWAIT|DOCMD_VERBOSE);
7397 
7398 	exec_from_reg = save_efr;
7399     }
7400 }
7401 
7402 /*
7403  * ":!".
7404  */
7405     static void
7406 ex_bang(exarg_T *eap)
7407 {
7408     do_bang(eap->addr_count, eap, eap->forceit, TRUE, TRUE);
7409 }
7410 
7411 /*
7412  * ":undo".
7413  */
7414     static void
7415 ex_undo(exarg_T *eap)
7416 {
7417     if (eap->addr_count == 1)	    // :undo 123
7418 	undo_time(eap->line2, FALSE, FALSE, TRUE);
7419     else
7420 	u_undo(1);
7421 }
7422 
7423 #ifdef FEAT_PERSISTENT_UNDO
7424     static void
7425 ex_wundo(exarg_T *eap)
7426 {
7427     char_u hash[UNDO_HASH_SIZE];
7428 
7429     u_compute_hash(hash);
7430     u_write_undo(eap->arg, eap->forceit, curbuf, hash);
7431 }
7432 
7433     static void
7434 ex_rundo(exarg_T *eap)
7435 {
7436     char_u hash[UNDO_HASH_SIZE];
7437 
7438     u_compute_hash(hash);
7439     u_read_undo(eap->arg, hash, NULL);
7440 }
7441 #endif
7442 
7443 /*
7444  * ":redo".
7445  */
7446     static void
7447 ex_redo(exarg_T *eap UNUSED)
7448 {
7449     u_redo(1);
7450 }
7451 
7452 /*
7453  * ":earlier" and ":later".
7454  */
7455     static void
7456 ex_later(exarg_T *eap)
7457 {
7458     long	count = 0;
7459     int		sec = FALSE;
7460     int		file = FALSE;
7461     char_u	*p = eap->arg;
7462 
7463     if (*p == NUL)
7464 	count = 1;
7465     else if (isdigit(*p))
7466     {
7467 	count = getdigits(&p);
7468 	switch (*p)
7469 	{
7470 	    case 's': ++p; sec = TRUE; break;
7471 	    case 'm': ++p; sec = TRUE; count *= 60; break;
7472 	    case 'h': ++p; sec = TRUE; count *= 60 * 60; break;
7473 	    case 'd': ++p; sec = TRUE; count *= 24 * 60 * 60; break;
7474 	    case 'f': ++p; file = TRUE; break;
7475 	}
7476     }
7477 
7478     if (*p != NUL)
7479 	semsg(_(e_invarg2), eap->arg);
7480     else
7481 	undo_time(eap->cmdidx == CMD_earlier ? -count : count,
7482 							    sec, file, FALSE);
7483 }
7484 
7485 /*
7486  * ":redir": start/stop redirection.
7487  */
7488     static void
7489 ex_redir(exarg_T *eap)
7490 {
7491     char	*mode;
7492     char_u	*fname;
7493     char_u	*arg = eap->arg;
7494 
7495 #ifdef FEAT_EVAL
7496     if (redir_execute)
7497     {
7498 	emsg(_("E930: Cannot use :redir inside execute()"));
7499 	return;
7500     }
7501 #endif
7502 
7503     if (STRICMP(eap->arg, "END") == 0)
7504 	close_redir();
7505     else
7506     {
7507 	if (*arg == '>')
7508 	{
7509 	    ++arg;
7510 	    if (*arg == '>')
7511 	    {
7512 		++arg;
7513 		mode = "a";
7514 	    }
7515 	    else
7516 		mode = "w";
7517 	    arg = skipwhite(arg);
7518 
7519 	    close_redir();
7520 
7521 	    // Expand environment variables and "~/".
7522 	    fname = expand_env_save(arg);
7523 	    if (fname == NULL)
7524 		return;
7525 #ifdef FEAT_BROWSE
7526 	    if (cmdmod.browse)
7527 	    {
7528 		char_u	*browseFile;
7529 
7530 		browseFile = do_browse(BROWSE_SAVE,
7531 			(char_u *)_("Save Redirection"),
7532 			fname, NULL, NULL,
7533 			(char_u *)_(BROWSE_FILTER_ALL_FILES), curbuf);
7534 		if (browseFile == NULL)
7535 		    return;		// operation cancelled
7536 		vim_free(fname);
7537 		fname = browseFile;
7538 		eap->forceit = TRUE;	// since dialog already asked
7539 	    }
7540 #endif
7541 
7542 	    redir_fd = open_exfile(fname, eap->forceit, mode);
7543 	    vim_free(fname);
7544 	}
7545 #ifdef FEAT_EVAL
7546 	else if (*arg == '@')
7547 	{
7548 	    // redirect to a register a-z (resp. A-Z for appending)
7549 	    close_redir();
7550 	    ++arg;
7551 	    if (ASCII_ISALPHA(*arg)
7552 # ifdef FEAT_CLIPBOARD
7553 		    || *arg == '*'
7554 		    || *arg == '+'
7555 # endif
7556 		    || *arg == '"')
7557 	    {
7558 		redir_reg = *arg++;
7559 		if (*arg == '>' && arg[1] == '>')  // append
7560 		    arg += 2;
7561 		else
7562 		{
7563 		    // Can use both "@a" and "@a>".
7564 		    if (*arg == '>')
7565 			arg++;
7566 		    // Make register empty when not using @A-@Z and the
7567 		    // command is valid.
7568 		    if (*arg == NUL && !isupper(redir_reg))
7569 			write_reg_contents(redir_reg, (char_u *)"", -1, FALSE);
7570 		}
7571 	    }
7572 	    if (*arg != NUL)
7573 	    {
7574 		redir_reg = 0;
7575 		semsg(_(e_invarg2), eap->arg);
7576 	    }
7577 	}
7578 	else if (*arg == '=' && arg[1] == '>')
7579 	{
7580 	    int append;
7581 
7582 	    // redirect to a variable
7583 	    close_redir();
7584 	    arg += 2;
7585 
7586 	    if (*arg == '>')
7587 	    {
7588 		++arg;
7589 		append = TRUE;
7590 	    }
7591 	    else
7592 		append = FALSE;
7593 
7594 	    if (var_redir_start(skipwhite(arg), append) == OK)
7595 		redir_vname = 1;
7596 	}
7597 #endif
7598 
7599 	// TODO: redirect to a buffer
7600 
7601 	else
7602 	    semsg(_(e_invarg2), eap->arg);
7603     }
7604 
7605     // Make sure redirection is not off.  Can happen for cmdline completion
7606     // that indirectly invokes a command to catch its output.
7607     if (redir_fd != NULL
7608 #ifdef FEAT_EVAL
7609 			  || redir_reg || redir_vname
7610 #endif
7611 							)
7612 	redir_off = FALSE;
7613 }
7614 
7615 /*
7616  * ":redraw": force redraw
7617  */
7618     void
7619 ex_redraw(exarg_T *eap)
7620 {
7621     int		r = RedrawingDisabled;
7622     int		p = p_lz;
7623 
7624     RedrawingDisabled = 0;
7625     p_lz = FALSE;
7626     validate_cursor();
7627     update_topline();
7628     update_screen(eap->forceit ? CLEAR : VIsual_active ? INVERTED : 0);
7629 #ifdef FEAT_TITLE
7630     if (need_maketitle)
7631 	maketitle();
7632 #endif
7633 #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
7634 # ifdef VIMDLL
7635     if (!gui.in_use)
7636 # endif
7637 	resize_console_buf();
7638 #endif
7639     RedrawingDisabled = r;
7640     p_lz = p;
7641 
7642     // Reset msg_didout, so that a message that's there is overwritten.
7643     msg_didout = FALSE;
7644     msg_col = 0;
7645 
7646     // No need to wait after an intentional redraw.
7647     need_wait_return = FALSE;
7648 
7649     out_flush();
7650 }
7651 
7652 /*
7653  * ":redrawstatus": force redraw of status line(s)
7654  */
7655     static void
7656 ex_redrawstatus(exarg_T *eap UNUSED)
7657 {
7658     int		r = RedrawingDisabled;
7659     int		p = p_lz;
7660 
7661     RedrawingDisabled = 0;
7662     p_lz = FALSE;
7663     if (eap->forceit)
7664 	status_redraw_all();
7665     else
7666 	status_redraw_curbuf();
7667     update_screen(VIsual_active ? INVERTED : 0);
7668     RedrawingDisabled = r;
7669     p_lz = p;
7670     out_flush();
7671 }
7672 
7673 /*
7674  * ":redrawtabline": force redraw of the tabline
7675  */
7676     static void
7677 ex_redrawtabline(exarg_T *eap UNUSED)
7678 {
7679     int		r = RedrawingDisabled;
7680     int		p = p_lz;
7681 
7682     RedrawingDisabled = 0;
7683     p_lz = FALSE;
7684 
7685     draw_tabline();
7686 
7687     RedrawingDisabled = r;
7688     p_lz = p;
7689     out_flush();
7690 }
7691 
7692     static void
7693 close_redir(void)
7694 {
7695     if (redir_fd != NULL)
7696     {
7697 	fclose(redir_fd);
7698 	redir_fd = NULL;
7699     }
7700 #ifdef FEAT_EVAL
7701     redir_reg = 0;
7702     if (redir_vname)
7703     {
7704 	var_redir_stop();
7705 	redir_vname = 0;
7706     }
7707 #endif
7708 }
7709 
7710 #if (defined(FEAT_SESSION) || defined(FEAT_EVAL)) || defined(PROTO)
7711     int
7712 vim_mkdir_emsg(char_u *name, int prot UNUSED)
7713 {
7714     if (vim_mkdir(name, prot) != 0)
7715     {
7716 	semsg(_("E739: Cannot create directory: %s"), name);
7717 	return FAIL;
7718     }
7719     return OK;
7720 }
7721 #endif
7722 
7723 /*
7724  * Open a file for writing for an Ex command, with some checks.
7725  * Return file descriptor, or NULL on failure.
7726  */
7727     FILE *
7728 open_exfile(
7729     char_u	*fname,
7730     int		forceit,
7731     char	*mode)	    // "w" for create new file or "a" for append
7732 {
7733     FILE	*fd;
7734 
7735 #ifdef UNIX
7736     // with Unix it is possible to open a directory
7737     if (mch_isdir(fname))
7738     {
7739 	semsg(_(e_isadir2), fname);
7740 	return NULL;
7741     }
7742 #endif
7743     if (!forceit && *mode != 'a' && vim_fexists(fname))
7744     {
7745 	semsg(_("E189: \"%s\" exists (add ! to override)"), fname);
7746 	return NULL;
7747     }
7748 
7749     if ((fd = mch_fopen((char *)fname, mode)) == NULL)
7750 	semsg(_("E190: Cannot open \"%s\" for writing"), fname);
7751 
7752     return fd;
7753 }
7754 
7755 /*
7756  * ":mark" and ":k".
7757  */
7758     static void
7759 ex_mark(exarg_T *eap)
7760 {
7761     pos_T	pos;
7762 
7763     if (*eap->arg == NUL)		// No argument?
7764 	emsg(_(e_argreq));
7765     else if (eap->arg[1] != NUL)	// more than one character?
7766 	semsg(_(e_trailing_arg), eap->arg);
7767     else
7768     {
7769 	pos = curwin->w_cursor;		// save curwin->w_cursor
7770 	curwin->w_cursor.lnum = eap->line2;
7771 	beginline(BL_WHITE | BL_FIX);
7772 	if (setmark(*eap->arg) == FAIL)	// set mark
7773 	    emsg(_("E191: Argument must be a letter or forward/backward quote"));
7774 	curwin->w_cursor = pos;		// restore curwin->w_cursor
7775     }
7776 }
7777 
7778 /*
7779  * Update w_topline, w_leftcol and the cursor position.
7780  */
7781     void
7782 update_topline_cursor(void)
7783 {
7784     check_cursor();		// put cursor on valid line
7785     update_topline();
7786     if (!curwin->w_p_wrap)
7787 	validate_cursor();
7788     update_curswant();
7789 }
7790 
7791 /*
7792  * Save the current State and go to Normal mode.
7793  * Return TRUE if the typeahead could be saved.
7794  */
7795     int
7796 save_current_state(save_state_T *sst)
7797 {
7798     sst->save_msg_scroll = msg_scroll;
7799     sst->save_restart_edit = restart_edit;
7800     sst->save_msg_didout = msg_didout;
7801     sst->save_State = State;
7802     sst->save_insertmode = p_im;
7803     sst->save_finish_op = finish_op;
7804     sst->save_opcount = opcount;
7805     sst->save_reg_executing = reg_executing;
7806 
7807     msg_scroll = FALSE;	    // no msg scrolling in Normal mode
7808     restart_edit = 0;	    // don't go to Insert mode
7809     p_im = FALSE;	    // don't use 'insertmode'
7810 
7811     /*
7812      * Save the current typeahead.  This is required to allow using ":normal"
7813      * from an event handler and makes sure we don't hang when the argument
7814      * ends with half a command.
7815      */
7816     save_typeahead(&sst->tabuf);
7817     return sst->tabuf.typebuf_valid;
7818 }
7819 
7820     void
7821 restore_current_state(save_state_T *sst)
7822 {
7823     // Restore the previous typeahead.
7824     restore_typeahead(&sst->tabuf);
7825 
7826     msg_scroll = sst->save_msg_scroll;
7827     restart_edit = sst->save_restart_edit;
7828     p_im = sst->save_insertmode;
7829     finish_op = sst->save_finish_op;
7830     opcount = sst->save_opcount;
7831     reg_executing = sst->save_reg_executing;
7832     msg_didout |= sst->save_msg_didout;	// don't reset msg_didout now
7833 
7834     // Restore the state (needed when called from a function executed for
7835     // 'indentexpr'). Update the mouse and cursor, they may have changed.
7836     State = sst->save_State;
7837 #ifdef CURSOR_SHAPE
7838     ui_cursor_shape();		// may show different cursor shape
7839 #endif
7840 }
7841 
7842 /*
7843  * ":normal[!] {commands}": Execute normal mode commands.
7844  */
7845     void
7846 ex_normal(exarg_T *eap)
7847 {
7848     save_state_T save_state;
7849     char_u	*arg = NULL;
7850     int		l;
7851     char_u	*p;
7852 
7853     if (ex_normal_lock > 0)
7854     {
7855 	emsg(_(e_secure));
7856 	return;
7857     }
7858     if (ex_normal_busy >= p_mmd)
7859     {
7860 	emsg(_("E192: Recursive use of :normal too deep"));
7861 	return;
7862     }
7863 
7864     /*
7865      * vgetc() expects a CSI and K_SPECIAL to have been escaped.  Don't do
7866      * this for the K_SPECIAL leading byte, otherwise special keys will not
7867      * work.
7868      */
7869     if (has_mbyte)
7870     {
7871 	int	len = 0;
7872 
7873 	// Count the number of characters to be escaped.
7874 	for (p = eap->arg; *p != NUL; ++p)
7875 	{
7876 #ifdef FEAT_GUI
7877 	    if (*p == CSI)  // leadbyte CSI
7878 		len += 2;
7879 #endif
7880 	    for (l = (*mb_ptr2len)(p) - 1; l > 0; --l)
7881 		if (*++p == K_SPECIAL	  // trailbyte K_SPECIAL or CSI
7882 #ifdef FEAT_GUI
7883 			|| *p == CSI
7884 #endif
7885 			)
7886 		    len += 2;
7887 	}
7888 	if (len > 0)
7889 	{
7890 	    arg = alloc(STRLEN(eap->arg) + len + 1);
7891 	    if (arg != NULL)
7892 	    {
7893 		len = 0;
7894 		for (p = eap->arg; *p != NUL; ++p)
7895 		{
7896 		    arg[len++] = *p;
7897 #ifdef FEAT_GUI
7898 		    if (*p == CSI)
7899 		    {
7900 			arg[len++] = KS_EXTRA;
7901 			arg[len++] = (int)KE_CSI;
7902 		    }
7903 #endif
7904 		    for (l = (*mb_ptr2len)(p) - 1; l > 0; --l)
7905 		    {
7906 			arg[len++] = *++p;
7907 			if (*p == K_SPECIAL)
7908 			{
7909 			    arg[len++] = KS_SPECIAL;
7910 			    arg[len++] = KE_FILLER;
7911 			}
7912 #ifdef FEAT_GUI
7913 			else if (*p == CSI)
7914 			{
7915 			    arg[len++] = KS_EXTRA;
7916 			    arg[len++] = (int)KE_CSI;
7917 			}
7918 #endif
7919 		    }
7920 		    arg[len] = NUL;
7921 		}
7922 	    }
7923 	}
7924     }
7925 
7926     ++ex_normal_busy;
7927     if (save_current_state(&save_state))
7928     {
7929 	/*
7930 	 * Repeat the :normal command for each line in the range.  When no
7931 	 * range given, execute it just once, without positioning the cursor
7932 	 * first.
7933 	 */
7934 	do
7935 	{
7936 	    if (eap->addr_count != 0)
7937 	    {
7938 		curwin->w_cursor.lnum = eap->line1++;
7939 		curwin->w_cursor.col = 0;
7940 		check_cursor_moved(curwin);
7941 	    }
7942 
7943 	    exec_normal_cmd(arg != NULL
7944 		     ? arg
7945 		     : eap->arg, eap->forceit ? REMAP_NONE : REMAP_YES, FALSE);
7946 	}
7947 	while (eap->addr_count > 0 && eap->line1 <= eap->line2 && !got_int);
7948     }
7949 
7950     // Might not return to the main loop when in an event handler.
7951     update_topline_cursor();
7952 
7953     restore_current_state(&save_state);
7954     --ex_normal_busy;
7955     setmouse();
7956 #ifdef CURSOR_SHAPE
7957     ui_cursor_shape();		// may show different cursor shape
7958 #endif
7959 
7960     vim_free(arg);
7961 }
7962 
7963 /*
7964  * ":startinsert", ":startreplace" and ":startgreplace"
7965  */
7966     static void
7967 ex_startinsert(exarg_T *eap)
7968 {
7969     if (eap->forceit)
7970     {
7971 	// cursor line can be zero on startup
7972 	if (!curwin->w_cursor.lnum)
7973 	    curwin->w_cursor.lnum = 1;
7974 	set_cursor_for_append_to_line();
7975     }
7976 #ifdef FEAT_TERMINAL
7977     // Ignore this when running in an active terminal.
7978     if (term_job_running(curbuf->b_term))
7979 	return;
7980 #endif
7981 
7982     // Ignore the command when already in Insert mode.  Inserting an
7983     // expression register that invokes a function can do this.
7984     if (State & INSERT)
7985 	return;
7986 
7987     if (eap->cmdidx == CMD_startinsert)
7988 	restart_edit = 'a';
7989     else if (eap->cmdidx == CMD_startreplace)
7990 	restart_edit = 'R';
7991     else
7992 	restart_edit = 'V';
7993 
7994     if (!eap->forceit)
7995     {
7996 	if (eap->cmdidx == CMD_startinsert)
7997 	    restart_edit = 'i';
7998 	curwin->w_curswant = 0;	    // avoid MAXCOL
7999     }
8000 }
8001 
8002 /*
8003  * ":stopinsert"
8004  */
8005     static void
8006 ex_stopinsert(exarg_T *eap UNUSED)
8007 {
8008     restart_edit = 0;
8009     stop_insert_mode = TRUE;
8010     clearmode();
8011 }
8012 
8013 /*
8014  * Execute normal mode command "cmd".
8015  * "remap" can be REMAP_NONE or REMAP_YES.
8016  */
8017     void
8018 exec_normal_cmd(char_u *cmd, int remap, int silent)
8019 {
8020     // Stuff the argument into the typeahead buffer.
8021     ins_typebuf(cmd, remap, 0, TRUE, silent);
8022     exec_normal(FALSE, FALSE, FALSE);
8023 }
8024 
8025 /*
8026  * Execute normal_cmd() until there is no typeahead left.
8027  * When "use_vpeekc" is TRUE use vpeekc() to check for available chars.
8028  */
8029     void
8030 exec_normal(int was_typed, int use_vpeekc, int may_use_terminal_loop UNUSED)
8031 {
8032     oparg_T	oa;
8033     int		c;
8034 
8035     // When calling vpeekc() from feedkeys() it will return Ctrl_C when there
8036     // is nothing to get, so also check for Ctrl_C.
8037     clear_oparg(&oa);
8038     finish_op = FALSE;
8039     while ((!stuff_empty()
8040 		|| ((was_typed || !typebuf_typed()) && typebuf.tb_len > 0)
8041 		|| (use_vpeekc && (c = vpeekc()) != NUL && c != Ctrl_C))
8042 	    && !got_int)
8043     {
8044 	update_topline_cursor();
8045 #ifdef FEAT_TERMINAL
8046 	if (may_use_terminal_loop && term_use_loop()
8047 		&& oa.op_type == OP_NOP && oa.regname == NUL
8048 		&& !VIsual_active)
8049 	{
8050 	    // If terminal_loop() returns OK we got a key that is handled
8051 	    // in Normal model.  With FAIL we first need to position the
8052 	    // cursor and the screen needs to be redrawn.
8053 	    if (terminal_loop(TRUE) == OK)
8054 		normal_cmd(&oa, TRUE);
8055 	}
8056 	else
8057 #endif
8058 	    // execute a Normal mode cmd
8059 	    normal_cmd(&oa, TRUE);
8060     }
8061 }
8062 
8063 #ifdef FEAT_FIND_ID
8064     static void
8065 ex_checkpath(exarg_T *eap)
8066 {
8067     find_pattern_in_path(NULL, 0, 0, FALSE, FALSE, CHECK_PATH, 1L,
8068 				   eap->forceit ? ACTION_SHOW_ALL : ACTION_SHOW,
8069 					      (linenr_T)1, (linenr_T)MAXLNUM);
8070 }
8071 
8072 #if defined(FEAT_QUICKFIX)
8073 /*
8074  * ":psearch"
8075  */
8076     static void
8077 ex_psearch(exarg_T *eap)
8078 {
8079     g_do_tagpreview = p_pvh;
8080     ex_findpat(eap);
8081     g_do_tagpreview = 0;
8082 }
8083 #endif
8084 
8085     static void
8086 ex_findpat(exarg_T *eap)
8087 {
8088     int		whole = TRUE;
8089     long	n;
8090     char_u	*p;
8091     int		action;
8092 
8093     switch (cmdnames[eap->cmdidx].cmd_name[2])
8094     {
8095 	case 'e':	// ":psearch", ":isearch" and ":dsearch"
8096 		if (cmdnames[eap->cmdidx].cmd_name[0] == 'p')
8097 		    action = ACTION_GOTO;
8098 		else
8099 		    action = ACTION_SHOW;
8100 		break;
8101 	case 'i':	// ":ilist" and ":dlist"
8102 		action = ACTION_SHOW_ALL;
8103 		break;
8104 	case 'u':	// ":ijump" and ":djump"
8105 		action = ACTION_GOTO;
8106 		break;
8107 	default:	// ":isplit" and ":dsplit"
8108 		action = ACTION_SPLIT;
8109 		break;
8110     }
8111 
8112     n = 1;
8113     if (vim_isdigit(*eap->arg))	// get count
8114     {
8115 	n = getdigits(&eap->arg);
8116 	eap->arg = skipwhite(eap->arg);
8117     }
8118     if (*eap->arg == '/')   // Match regexp, not just whole words
8119     {
8120 	whole = FALSE;
8121 	++eap->arg;
8122 	p = skip_regexp(eap->arg, '/', p_magic);
8123 	if (*p)
8124 	{
8125 	    *p++ = NUL;
8126 	    p = skipwhite(p);
8127 
8128 	    // Check for trailing illegal characters
8129 	    if (!ends_excmd2(eap->arg, p))
8130 		eap->errmsg = ex_errmsg(e_trailing_arg, p);
8131 	    else
8132 		eap->nextcmd = check_nextcmd(p);
8133 	}
8134     }
8135     if (!eap->skip)
8136 	find_pattern_in_path(eap->arg, 0, (int)STRLEN(eap->arg),
8137 			    whole, !eap->forceit,
8138 			    *eap->cmd == 'd' ?	FIND_DEFINE : FIND_ANY,
8139 			    n, action, eap->line1, eap->line2);
8140 }
8141 #endif
8142 
8143 
8144 #ifdef FEAT_QUICKFIX
8145 /*
8146  * ":ptag", ":ptselect", ":ptjump", ":ptnext", etc.
8147  */
8148     static void
8149 ex_ptag(exarg_T *eap)
8150 {
8151     g_do_tagpreview = p_pvh;  // will be reset to 0 in ex_tag_cmd()
8152     ex_tag_cmd(eap, cmdnames[eap->cmdidx].cmd_name + 1);
8153 }
8154 
8155 /*
8156  * ":pedit"
8157  */
8158     static void
8159 ex_pedit(exarg_T *eap)
8160 {
8161     win_T	*curwin_save = curwin;
8162 
8163     if (ERROR_IF_ANY_POPUP_WINDOW)
8164 	return;
8165 
8166     // Open the preview window or popup and make it the current window.
8167     g_do_tagpreview = p_pvh;
8168     prepare_tagpreview(TRUE, TRUE, FALSE);
8169 
8170     // Edit the file.
8171     do_exedit(eap, NULL);
8172 
8173     if (curwin != curwin_save && win_valid(curwin_save))
8174     {
8175 	// Return cursor to where we were
8176 	validate_cursor();
8177 	redraw_later(VALID);
8178 	win_enter(curwin_save, TRUE);
8179     }
8180 # ifdef FEAT_PROP_POPUP
8181     else if (WIN_IS_POPUP(curwin))
8182     {
8183 	// can't keep focus in popup window
8184 	win_enter(firstwin, TRUE);
8185     }
8186 # endif
8187     g_do_tagpreview = 0;
8188 }
8189 #endif
8190 
8191 /*
8192  * ":stag", ":stselect" and ":stjump".
8193  */
8194     static void
8195 ex_stag(exarg_T *eap)
8196 {
8197     postponed_split = -1;
8198     postponed_split_flags = cmdmod.split;
8199     postponed_split_tab = cmdmod.tab;
8200     ex_tag_cmd(eap, cmdnames[eap->cmdidx].cmd_name + 1);
8201     postponed_split_flags = 0;
8202     postponed_split_tab = 0;
8203 }
8204 
8205 /*
8206  * ":tag", ":tselect", ":tjump", ":tnext", etc.
8207  */
8208     static void
8209 ex_tag(exarg_T *eap)
8210 {
8211     ex_tag_cmd(eap, cmdnames[eap->cmdidx].cmd_name);
8212 }
8213 
8214     static void
8215 ex_tag_cmd(exarg_T *eap, char_u *name)
8216 {
8217     int		cmd;
8218 
8219     switch (name[1])
8220     {
8221 	case 'j': cmd = DT_JUMP;	// ":tjump"
8222 		  break;
8223 	case 's': cmd = DT_SELECT;	// ":tselect"
8224 		  break;
8225 	case 'p': cmd = DT_PREV;	// ":tprevious"
8226 		  break;
8227 	case 'N': cmd = DT_PREV;	// ":tNext"
8228 		  break;
8229 	case 'n': cmd = DT_NEXT;	// ":tnext"
8230 		  break;
8231 	case 'o': cmd = DT_POP;		// ":pop"
8232 		  break;
8233 	case 'f':			// ":tfirst"
8234 	case 'r': cmd = DT_FIRST;	// ":trewind"
8235 		  break;
8236 	case 'l': cmd = DT_LAST;	// ":tlast"
8237 		  break;
8238 	default:			// ":tag"
8239 #ifdef FEAT_CSCOPE
8240 		  if (p_cst && *eap->arg != NUL)
8241 		  {
8242 		      ex_cstag(eap);
8243 		      return;
8244 		  }
8245 #endif
8246 		  cmd = DT_TAG;
8247 		  break;
8248     }
8249 
8250     if (name[0] == 'l')
8251     {
8252 #ifndef FEAT_QUICKFIX
8253 	ex_ni(eap);
8254 	return;
8255 #else
8256 	cmd = DT_LTAG;
8257 #endif
8258     }
8259 
8260     do_tag(eap->arg, cmd, eap->addr_count > 0 ? (int)eap->line2 : 1,
8261 							  eap->forceit, TRUE);
8262 }
8263 
8264 /*
8265  * Check "str" for starting with a special cmdline variable.
8266  * If found return one of the SPEC_ values and set "*usedlen" to the length of
8267  * the variable.  Otherwise return -1 and "*usedlen" is unchanged.
8268  */
8269     int
8270 find_cmdline_var(char_u *src, int *usedlen)
8271 {
8272     int		len;
8273     int		i;
8274     static char *(spec_str[]) = {
8275 		    "%",
8276 #define SPEC_PERC   0
8277 		    "#",
8278 #define SPEC_HASH   (SPEC_PERC + 1)
8279 		    "<cword>",		// cursor word
8280 #define SPEC_CWORD  (SPEC_HASH + 1)
8281 		    "<cWORD>",		// cursor WORD
8282 #define SPEC_CCWORD (SPEC_CWORD + 1)
8283 		    "<cexpr>",		// expr under cursor
8284 #define SPEC_CEXPR  (SPEC_CCWORD + 1)
8285 		    "<cfile>",		// cursor path name
8286 #define SPEC_CFILE  (SPEC_CEXPR + 1)
8287 		    "<sfile>",		// ":so" file name
8288 #define SPEC_SFILE  (SPEC_CFILE + 1)
8289 		    "<slnum>",		// ":so" file line number
8290 #define SPEC_SLNUM  (SPEC_SFILE + 1)
8291 		    "<stack>",		// call stack
8292 #define SPEC_STACK  (SPEC_SLNUM + 1)
8293 		    "<afile>",		// autocommand file name
8294 #define SPEC_AFILE  (SPEC_STACK + 1)
8295 		    "<abuf>",		// autocommand buffer number
8296 #define SPEC_ABUF   (SPEC_AFILE + 1)
8297 		    "<amatch>",		// autocommand match name
8298 #define SPEC_AMATCH (SPEC_ABUF + 1)
8299 		    "<sflnum>",		// script file line number
8300 #define SPEC_SFLNUM  (SPEC_AMATCH + 1)
8301 #ifdef FEAT_CLIENTSERVER
8302 		    "<client>"
8303 # define SPEC_CLIENT (SPEC_SFLNUM + 1)
8304 #endif
8305     };
8306 
8307     for (i = 0; i < (int)(sizeof(spec_str) / sizeof(char *)); ++i)
8308     {
8309 	len = (int)STRLEN(spec_str[i]);
8310 	if (STRNCMP(src, spec_str[i], len) == 0)
8311 	{
8312 	    *usedlen = len;
8313 	    return i;
8314 	}
8315     }
8316     return -1;
8317 }
8318 
8319 /*
8320  * Evaluate cmdline variables.
8321  *
8322  * change '%'	    to curbuf->b_ffname
8323  *	  '#'	    to curwin->w_altfile
8324  *	  '<cword>' to word under the cursor
8325  *	  '<cWORD>' to WORD under the cursor
8326  *	  '<cexpr>' to C-expression under the cursor
8327  *	  '<cfile>' to path name under the cursor
8328  *	  '<sfile>' to sourced file name
8329  *	  '<slnum>' to sourced file line number
8330  *	  '<afile>' to file name for autocommand
8331  *	  '<abuf>'  to buffer number for autocommand
8332  *	  '<amatch>' to matching name for autocommand
8333  *
8334  * When an error is detected, "errormsg" is set to a non-NULL pointer (may be
8335  * "" for error without a message) and NULL is returned.
8336  * Returns an allocated string if a valid match was found.
8337  * Returns NULL if no match was found.	"usedlen" then still contains the
8338  * number of characters to skip.
8339  */
8340     char_u *
8341 eval_vars(
8342     char_u	*src,		// pointer into commandline
8343     char_u	*srcstart,	// beginning of valid memory for src
8344     int		*usedlen,	// characters after src that are used
8345     linenr_T	*lnump,		// line number for :e command, or NULL
8346     char	**errormsg,	// pointer to error message
8347     int		*escaped)	// return value has escaped white space (can
8348 				// be NULL)
8349 {
8350     int		i;
8351     char_u	*s;
8352     char_u	*result;
8353     char_u	*resultbuf = NULL;
8354     int		resultlen;
8355     buf_T	*buf;
8356     int		valid = VALID_HEAD + VALID_PATH;    // assume valid result
8357     int		spec_idx;
8358     int		tilde_file = FALSE;
8359     int		skip_mod = FALSE;
8360     char_u	strbuf[30];
8361 
8362     *errormsg = NULL;
8363     if (escaped != NULL)
8364 	*escaped = FALSE;
8365 
8366     /*
8367      * Check if there is something to do.
8368      */
8369     spec_idx = find_cmdline_var(src, usedlen);
8370     if (spec_idx < 0)	// no match
8371     {
8372 	*usedlen = 1;
8373 	return NULL;
8374     }
8375 
8376     /*
8377      * Skip when preceded with a backslash "\%" and "\#".
8378      * Note: In "\\%" the % is also not recognized!
8379      */
8380     if (src > srcstart && src[-1] == '\\')
8381     {
8382 	*usedlen = 0;
8383 	STRMOVE(src - 1, src);	// remove backslash
8384 	return NULL;
8385     }
8386 
8387     /*
8388      * word or WORD under cursor
8389      */
8390     if (spec_idx == SPEC_CWORD || spec_idx == SPEC_CCWORD
8391 						     || spec_idx == SPEC_CEXPR)
8392     {
8393 	resultlen = find_ident_under_cursor(&result,
8394 		spec_idx == SPEC_CWORD ? (FIND_IDENT | FIND_STRING)
8395 	      : spec_idx == SPEC_CEXPR ? (FIND_IDENT | FIND_STRING | FIND_EVAL)
8396 	      : FIND_STRING);
8397 	if (resultlen == 0)
8398 	{
8399 	    *errormsg = "";
8400 	    return NULL;
8401 	}
8402     }
8403 
8404     /*
8405      * '#': Alternate file name
8406      * '%': Current file name
8407      *	    File name under the cursor
8408      *	    File name for autocommand
8409      *	and following modifiers
8410      */
8411     else
8412     {
8413 	switch (spec_idx)
8414 	{
8415 	case SPEC_PERC:		// '%': current file
8416 		if (curbuf->b_fname == NULL)
8417 		{
8418 		    result = (char_u *)"";
8419 		    valid = 0;	    // Must have ":p:h" to be valid
8420 		}
8421 		else
8422 		{
8423 		    result = curbuf->b_fname;
8424 		    tilde_file = STRCMP(result, "~") == 0;
8425 		}
8426 		break;
8427 
8428 	case SPEC_HASH:		// '#' or "#99": alternate file
8429 		if (src[1] == '#')  // "##": the argument list
8430 		{
8431 		    result = arg_all();
8432 		    resultbuf = result;
8433 		    *usedlen = 2;
8434 		    if (escaped != NULL)
8435 			*escaped = TRUE;
8436 		    skip_mod = TRUE;
8437 		    break;
8438 		}
8439 		s = src + 1;
8440 		if (*s == '<')		// "#<99" uses v:oldfiles
8441 		    ++s;
8442 		i = (int)getdigits(&s);
8443 		if (s == src + 2 && src[1] == '-')
8444 		    // just a minus sign, don't skip over it
8445 		    s--;
8446 		*usedlen = (int)(s - src); // length of what we expand
8447 
8448 		if (src[1] == '<' && i != 0)
8449 		{
8450 		    if (*usedlen < 2)
8451 		    {
8452 			// Should we give an error message for #<text?
8453 			*usedlen = 1;
8454 			return NULL;
8455 		    }
8456 #ifdef FEAT_EVAL
8457 		    result = list_find_str(get_vim_var_list(VV_OLDFILES),
8458 								     (long)i);
8459 		    if (result == NULL)
8460 		    {
8461 			*errormsg = "";
8462 			return NULL;
8463 		    }
8464 #else
8465 		    *errormsg = _("E809: #< is not available without the +eval feature");
8466 		    return NULL;
8467 #endif
8468 		}
8469 		else
8470 		{
8471 		    if (i == 0 && src[1] == '<' && *usedlen > 1)
8472 			*usedlen = 1;
8473 		    buf = buflist_findnr(i);
8474 		    if (buf == NULL)
8475 		    {
8476 			*errormsg = _("E194: No alternate file name to substitute for '#'");
8477 			return NULL;
8478 		    }
8479 		    if (lnump != NULL)
8480 			*lnump = ECMD_LAST;
8481 		    if (buf->b_fname == NULL)
8482 		    {
8483 			result = (char_u *)"";
8484 			valid = 0;	    // Must have ":p:h" to be valid
8485 		    }
8486 		    else
8487 		    {
8488 			result = buf->b_fname;
8489 			tilde_file = STRCMP(result, "~") == 0;
8490 		    }
8491 		}
8492 		break;
8493 
8494 #ifdef FEAT_SEARCHPATH
8495 	case SPEC_CFILE:	// file name under cursor
8496 		result = file_name_at_cursor(FNAME_MESS|FNAME_HYP, 1L, NULL);
8497 		if (result == NULL)
8498 		{
8499 		    *errormsg = "";
8500 		    return NULL;
8501 		}
8502 		resultbuf = result;	    // remember allocated string
8503 		break;
8504 #endif
8505 
8506 	case SPEC_AFILE:	// file name for autocommand
8507 		result = autocmd_fname;
8508 		if (result != NULL && !autocmd_fname_full)
8509 		{
8510 		    // Still need to turn the fname into a full path.  It is
8511 		    // postponed to avoid a delay when <afile> is not used.
8512 		    autocmd_fname_full = TRUE;
8513 		    result = FullName_save(autocmd_fname, FALSE);
8514 		    vim_free(autocmd_fname);
8515 		    autocmd_fname = result;
8516 		}
8517 		if (result == NULL)
8518 		{
8519 		    *errormsg = _("E495: no autocommand file name to substitute for \"<afile>\"");
8520 		    return NULL;
8521 		}
8522 		result = shorten_fname1(result);
8523 		break;
8524 
8525 	case SPEC_ABUF:		// buffer number for autocommand
8526 		if (autocmd_bufnr <= 0)
8527 		{
8528 		    *errormsg = _("E496: no autocommand buffer number to substitute for \"<abuf>\"");
8529 		    return NULL;
8530 		}
8531 		sprintf((char *)strbuf, "%d", autocmd_bufnr);
8532 		result = strbuf;
8533 		break;
8534 
8535 	case SPEC_AMATCH:	// match name for autocommand
8536 		result = autocmd_match;
8537 		if (result == NULL)
8538 		{
8539 		    *errormsg = _("E497: no autocommand match name to substitute for \"<amatch>\"");
8540 		    return NULL;
8541 		}
8542 		break;
8543 
8544 	case SPEC_SFILE:	// file name for ":so" command
8545 	case SPEC_STACK:	// call stack
8546 		result = estack_sfile(spec_idx == SPEC_SFILE);
8547 		if (result == NULL)
8548 		{
8549 		    *errormsg = spec_idx == SPEC_SFILE
8550 			? _("E498: no :source file name to substitute for \"<sfile>\"")
8551 			: _("E489: no call stack to substitute for \"<stack>\"");
8552 		    return NULL;
8553 		}
8554 		resultbuf = result;	    // remember allocated string
8555 		break;
8556 
8557 	case SPEC_SLNUM:	// line in file for ":so" command
8558 		if (SOURCING_NAME == NULL || SOURCING_LNUM == 0)
8559 		{
8560 		    *errormsg = _("E842: no line number to use for \"<slnum>\"");
8561 		    return NULL;
8562 		}
8563 		sprintf((char *)strbuf, "%ld", SOURCING_LNUM);
8564 		result = strbuf;
8565 		break;
8566 
8567 #ifdef FEAT_EVAL
8568 	case SPEC_SFLNUM:	// line in script file
8569 		if (current_sctx.sc_lnum + SOURCING_LNUM == 0)
8570 		{
8571 		    *errormsg = _("E961: no line number to use for \"<sflnum>\"");
8572 		    return NULL;
8573 		}
8574 		sprintf((char *)strbuf, "%ld",
8575 				 (long)(current_sctx.sc_lnum + SOURCING_LNUM));
8576 		result = strbuf;
8577 		break;
8578 #endif
8579 
8580 #ifdef FEAT_CLIENTSERVER
8581 	case SPEC_CLIENT:	// Source of last submitted input
8582 		sprintf((char *)strbuf, PRINTF_HEX_LONG_U,
8583 							(long_u)clientWindow);
8584 		result = strbuf;
8585 		break;
8586 #endif
8587 
8588 	default:
8589 		result = (char_u *)""; // avoid gcc warning
8590 		break;
8591 	}
8592 
8593 	resultlen = (int)STRLEN(result);	// length of new string
8594 	if (src[*usedlen] == '<')	// remove the file name extension
8595 	{
8596 	    ++*usedlen;
8597 	    if ((s = vim_strrchr(result, '.')) != NULL && s >= gettail(result))
8598 		resultlen = (int)(s - result);
8599 	}
8600 	else if (!skip_mod)
8601 	{
8602 	    valid |= modify_fname(src, tilde_file, usedlen, &result, &resultbuf,
8603 								  &resultlen);
8604 	    if (result == NULL)
8605 	    {
8606 		*errormsg = "";
8607 		return NULL;
8608 	    }
8609 	}
8610     }
8611 
8612     if (resultlen == 0 || valid != VALID_HEAD + VALID_PATH)
8613     {
8614 	if (valid != VALID_HEAD + VALID_PATH)
8615 	    // xgettext:no-c-format
8616 	    *errormsg = _("E499: Empty file name for '%' or '#', only works with \":p:h\"");
8617 	else
8618 	    *errormsg = _("E500: Evaluates to an empty string");
8619 	result = NULL;
8620     }
8621     else
8622 	result = vim_strnsave(result, resultlen);
8623     vim_free(resultbuf);
8624     return result;
8625 }
8626 
8627 /*
8628  * Expand the <sfile> string in "arg".
8629  *
8630  * Returns an allocated string, or NULL for any error.
8631  */
8632     char_u *
8633 expand_sfile(char_u *arg)
8634 {
8635     char	*errormsg;
8636     int		len;
8637     char_u	*result;
8638     char_u	*newres;
8639     char_u	*repl;
8640     int		srclen;
8641     char_u	*p;
8642 
8643     result = vim_strsave(arg);
8644     if (result == NULL)
8645 	return NULL;
8646 
8647     for (p = result; *p; )
8648     {
8649 	if (STRNCMP(p, "<sfile>", 7) != 0)
8650 	    ++p;
8651 	else
8652 	{
8653 	    // replace "<sfile>" with the sourced file name, and do ":" stuff
8654 	    repl = eval_vars(p, result, &srclen, NULL, &errormsg, NULL);
8655 	    if (errormsg != NULL)
8656 	    {
8657 		if (*errormsg)
8658 		    emsg(errormsg);
8659 		vim_free(result);
8660 		return NULL;
8661 	    }
8662 	    if (repl == NULL)		// no match (cannot happen)
8663 	    {
8664 		p += srclen;
8665 		continue;
8666 	    }
8667 	    len = (int)STRLEN(result) - srclen + (int)STRLEN(repl) + 1;
8668 	    newres = alloc(len);
8669 	    if (newres == NULL)
8670 	    {
8671 		vim_free(repl);
8672 		vim_free(result);
8673 		return NULL;
8674 	    }
8675 	    mch_memmove(newres, result, (size_t)(p - result));
8676 	    STRCPY(newres + (p - result), repl);
8677 	    len = (int)STRLEN(newres);
8678 	    STRCAT(newres, p + srclen);
8679 	    vim_free(repl);
8680 	    vim_free(result);
8681 	    result = newres;
8682 	    p = newres + len;		// continue after the match
8683 	}
8684     }
8685 
8686     return result;
8687 }
8688 
8689 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO)
8690 /*
8691  * Make a dialog message in "buff[DIALOG_MSG_SIZE]".
8692  * "format" must contain "%s".
8693  */
8694     void
8695 dialog_msg(char_u *buff, char *format, char_u *fname)
8696 {
8697     if (fname == NULL)
8698 	fname = (char_u *)_("Untitled");
8699     vim_snprintf((char *)buff, DIALOG_MSG_SIZE, format, fname);
8700 }
8701 #endif
8702 
8703 /*
8704  * ":behave {mswin,xterm}"
8705  */
8706     static void
8707 ex_behave(exarg_T *eap)
8708 {
8709     if (STRCMP(eap->arg, "mswin") == 0)
8710     {
8711 	set_option_value((char_u *)"selection", 0L, (char_u *)"exclusive", 0);
8712 	set_option_value((char_u *)"selectmode", 0L, (char_u *)"mouse,key", 0);
8713 	set_option_value((char_u *)"mousemodel", 0L, (char_u *)"popup", 0);
8714 	set_option_value((char_u *)"keymodel", 0L,
8715 					     (char_u *)"startsel,stopsel", 0);
8716     }
8717     else if (STRCMP(eap->arg, "xterm") == 0)
8718     {
8719 	set_option_value((char_u *)"selection", 0L, (char_u *)"inclusive", 0);
8720 	set_option_value((char_u *)"selectmode", 0L, (char_u *)"", 0);
8721 	set_option_value((char_u *)"mousemodel", 0L, (char_u *)"extend", 0);
8722 	set_option_value((char_u *)"keymodel", 0L, (char_u *)"", 0);
8723     }
8724     else
8725 	semsg(_(e_invarg2), eap->arg);
8726 }
8727 
8728 static int filetype_detect = FALSE;
8729 static int filetype_plugin = FALSE;
8730 static int filetype_indent = FALSE;
8731 
8732 /*
8733  * ":filetype [plugin] [indent] {on,off,detect}"
8734  * on: Load the filetype.vim file to install autocommands for file types.
8735  * off: Load the ftoff.vim file to remove all autocommands for file types.
8736  * plugin on: load filetype.vim and ftplugin.vim
8737  * plugin off: load ftplugof.vim
8738  * indent on: load filetype.vim and indent.vim
8739  * indent off: load indoff.vim
8740  */
8741     static void
8742 ex_filetype(exarg_T *eap)
8743 {
8744     char_u	*arg = eap->arg;
8745     int		plugin = FALSE;
8746     int		indent = FALSE;
8747 
8748     if (*eap->arg == NUL)
8749     {
8750 	// Print current status.
8751 	smsg("filetype detection:%s  plugin:%s  indent:%s",
8752 		filetype_detect ? "ON" : "OFF",
8753 		filetype_plugin ? (filetype_detect ? "ON" : "(on)") : "OFF",
8754 		filetype_indent ? (filetype_detect ? "ON" : "(on)") : "OFF");
8755 	return;
8756     }
8757 
8758     // Accept "plugin" and "indent" in any order.
8759     for (;;)
8760     {
8761 	if (STRNCMP(arg, "plugin", 6) == 0)
8762 	{
8763 	    plugin = TRUE;
8764 	    arg = skipwhite(arg + 6);
8765 	    continue;
8766 	}
8767 	if (STRNCMP(arg, "indent", 6) == 0)
8768 	{
8769 	    indent = TRUE;
8770 	    arg = skipwhite(arg + 6);
8771 	    continue;
8772 	}
8773 	break;
8774     }
8775     if (STRCMP(arg, "on") == 0 || STRCMP(arg, "detect") == 0)
8776     {
8777 	if (*arg == 'o' || !filetype_detect)
8778 	{
8779 	    source_runtime((char_u *)FILETYPE_FILE, DIP_ALL);
8780 	    filetype_detect = TRUE;
8781 	    if (plugin)
8782 	    {
8783 		source_runtime((char_u *)FTPLUGIN_FILE, DIP_ALL);
8784 		filetype_plugin = TRUE;
8785 	    }
8786 	    if (indent)
8787 	    {
8788 		source_runtime((char_u *)INDENT_FILE, DIP_ALL);
8789 		filetype_indent = TRUE;
8790 	    }
8791 	}
8792 	if (*arg == 'd')
8793 	{
8794 	    (void)do_doautocmd((char_u *)"filetypedetect BufRead", TRUE, NULL);
8795 	    do_modelines(0);
8796 	}
8797     }
8798     else if (STRCMP(arg, "off") == 0)
8799     {
8800 	if (plugin || indent)
8801 	{
8802 	    if (plugin)
8803 	    {
8804 		source_runtime((char_u *)FTPLUGOF_FILE, DIP_ALL);
8805 		filetype_plugin = FALSE;
8806 	    }
8807 	    if (indent)
8808 	    {
8809 		source_runtime((char_u *)INDOFF_FILE, DIP_ALL);
8810 		filetype_indent = FALSE;
8811 	    }
8812 	}
8813 	else
8814 	{
8815 	    source_runtime((char_u *)FTOFF_FILE, DIP_ALL);
8816 	    filetype_detect = FALSE;
8817 	}
8818     }
8819     else
8820 	semsg(_(e_invarg2), arg);
8821 }
8822 
8823 /*
8824  * ":setfiletype [FALLBACK] {name}"
8825  */
8826     static void
8827 ex_setfiletype(exarg_T *eap)
8828 {
8829     if (!did_filetype)
8830     {
8831 	char_u *arg = eap->arg;
8832 
8833 	if (STRNCMP(arg, "FALLBACK ", 9) == 0)
8834 	    arg += 9;
8835 
8836 	set_option_value((char_u *)"filetype", 0L, arg, OPT_LOCAL);
8837 	if (arg != eap->arg)
8838 	    did_filetype = FALSE;
8839     }
8840 }
8841 
8842     static void
8843 ex_digraphs(exarg_T *eap UNUSED)
8844 {
8845 #ifdef FEAT_DIGRAPHS
8846     if (*eap->arg != NUL)
8847 	putdigraph(eap->arg);
8848     else
8849 	listdigraphs(eap->forceit);
8850 #else
8851     emsg(_("E196: No digraphs in this version"));
8852 #endif
8853 }
8854 
8855 #if defined(FEAT_SEARCH_EXTRA) || defined(PROTO)
8856     void
8857 set_no_hlsearch(int flag)
8858 {
8859     no_hlsearch = flag;
8860 # ifdef FEAT_EVAL
8861     set_vim_var_nr(VV_HLSEARCH, !no_hlsearch && p_hls);
8862 # endif
8863 }
8864 
8865 /*
8866  * ":nohlsearch"
8867  */
8868     static void
8869 ex_nohlsearch(exarg_T *eap UNUSED)
8870 {
8871     set_no_hlsearch(TRUE);
8872     redraw_all_later(SOME_VALID);
8873 }
8874 #endif
8875 
8876 #ifdef FEAT_CRYPT
8877 /*
8878  * ":X": Get crypt key
8879  */
8880     static void
8881 ex_X(exarg_T *eap UNUSED)
8882 {
8883     crypt_check_current_method();
8884     (void)crypt_get_key(TRUE, TRUE);
8885 }
8886 #endif
8887 
8888 #ifdef FEAT_FOLDING
8889     static void
8890 ex_fold(exarg_T *eap)
8891 {
8892     if (foldManualAllowed(TRUE))
8893 	foldCreate(eap->line1, eap->line2);
8894 }
8895 
8896     static void
8897 ex_foldopen(exarg_T *eap)
8898 {
8899     opFoldRange(eap->line1, eap->line2, eap->cmdidx == CMD_foldopen,
8900 							 eap->forceit, FALSE);
8901 }
8902 
8903     static void
8904 ex_folddo(exarg_T *eap)
8905 {
8906     linenr_T	lnum;
8907 
8908 # ifdef FEAT_CLIPBOARD
8909     start_global_changes();
8910 # endif
8911 
8912     // First set the marks for all lines closed/open.
8913     for (lnum = eap->line1; lnum <= eap->line2; ++lnum)
8914 	if (hasFolding(lnum, NULL, NULL) == (eap->cmdidx == CMD_folddoclosed))
8915 	    ml_setmarked(lnum);
8916 
8917     // Execute the command on the marked lines.
8918     global_exe(eap->arg);
8919     ml_clearmarked();	   // clear rest of the marks
8920 # ifdef FEAT_CLIPBOARD
8921     end_global_changes();
8922 # endif
8923 }
8924 #endif
8925 
8926 #if defined(FEAT_QUICKFIX) || defined(PROTO)
8927 /*
8928  * Returns TRUE if the supplied Ex cmdidx is for a location list command
8929  * instead of a quickfix command.
8930  */
8931     int
8932 is_loclist_cmd(int cmdidx)
8933 {
8934     if (cmdidx < 0 || cmdidx >= CMD_SIZE)
8935 	return FALSE;
8936     return cmdnames[cmdidx].cmd_name[0] == 'l';
8937 }
8938 #endif
8939 
8940 #if defined(FEAT_TIMERS) || defined(PROTO)
8941     int
8942 get_pressedreturn(void)
8943 {
8944     return ex_pressedreturn;
8945 }
8946 
8947     void
8948 set_pressedreturn(int val)
8949 {
8950      ex_pressedreturn = val;
8951 }
8952 #endif
8953