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