xref: /vim-8.2.3635/src/ex_cmds2.c (revision fb094e14)
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_cmds2.c: some more functions for command line commands
12  */
13 
14 #include "vim.h"
15 #include "version.h"
16 
17 static void	cmd_source(char_u *fname, exarg_T *eap);
18 
19 #ifdef FEAT_EVAL
20 /* Growarray to store info about already sourced scripts.
21  * For Unix also store the dev/ino, so that we don't have to stat() each
22  * script when going through the list. */
23 typedef struct scriptitem_S
24 {
25     char_u	*sn_name;
26 # ifdef UNIX
27     int		sn_dev_valid;
28     dev_t	sn_dev;
29     ino_t	sn_ino;
30 # endif
31 # ifdef FEAT_PROFILE
32     int		sn_prof_on;	/* TRUE when script is/was profiled */
33     int		sn_pr_force;	/* forceit: profile functions in this script */
34     proftime_T	sn_pr_child;	/* time set when going into first child */
35     int		sn_pr_nest;	/* nesting for sn_pr_child */
36     /* profiling the script as a whole */
37     int		sn_pr_count;	/* nr of times sourced */
38     proftime_T	sn_pr_total;	/* time spent in script + children */
39     proftime_T	sn_pr_self;	/* time spent in script itself */
40     proftime_T	sn_pr_start;	/* time at script start */
41     proftime_T	sn_pr_children; /* time in children after script start */
42     /* profiling the script per line */
43     garray_T	sn_prl_ga;	/* things stored for every line */
44     proftime_T	sn_prl_start;	/* start time for current line */
45     proftime_T	sn_prl_children; /* time spent in children for this line */
46     proftime_T	sn_prl_wait;	/* wait start time for current line */
47     int		sn_prl_idx;	/* index of line being timed; -1 if none */
48     int		sn_prl_execed;	/* line being timed was executed */
49 # endif
50 } scriptitem_T;
51 
52 static garray_T script_items = {0, 0, sizeof(scriptitem_T), 4, NULL};
53 #define SCRIPT_ITEM(id) (((scriptitem_T *)script_items.ga_data)[(id) - 1])
54 
55 # ifdef FEAT_PROFILE
56 /* Struct used in sn_prl_ga for every line of a script. */
57 typedef struct sn_prl_S
58 {
59     int		snp_count;	/* nr of times line was executed */
60     proftime_T	sn_prl_total;	/* time spent in a line + children */
61     proftime_T	sn_prl_self;	/* time spent in a line itself */
62 } sn_prl_T;
63 
64 #  define PRL_ITEM(si, idx)	(((sn_prl_T *)(si)->sn_prl_ga.ga_data)[(idx)])
65 # endif
66 #endif
67 
68 #if defined(FEAT_EVAL) || defined(PROTO)
69 static int debug_greedy = FALSE;	/* batch mode debugging: don't save
70 					   and restore typeahead. */
71 static int get_maxbacktrace_level(void);
72 static void do_setdebugtracelevel(char_u *arg);
73 static void do_checkbacktracelevel(void);
74 static void do_showbacktrace(char_u *cmd);
75 
76 /*
77  * do_debug(): Debug mode.
78  * Repeatedly get Ex commands, until told to continue normal execution.
79  */
80     void
81 do_debug(char_u *cmd)
82 {
83     int		save_msg_scroll = msg_scroll;
84     int		save_State = State;
85     int		save_did_emsg = did_emsg;
86     int		save_cmd_silent = cmd_silent;
87     int		save_msg_silent = msg_silent;
88     int		save_emsg_silent = emsg_silent;
89     int		save_redir_off = redir_off;
90     tasave_T	typeaheadbuf;
91     int		typeahead_saved = FALSE;
92     int		save_ignore_script = 0;
93     int		save_ex_normal_busy;
94     int		n;
95     char_u	*cmdline = NULL;
96     char_u	*p;
97     char	*tail = NULL;
98     static int	last_cmd = 0;
99 #define CMD_CONT	1
100 #define CMD_NEXT	2
101 #define CMD_STEP	3
102 #define CMD_FINISH	4
103 #define CMD_QUIT	5
104 #define CMD_INTERRUPT	6
105 #define CMD_BACKTRACE	7
106 #define CMD_FRAME	8
107 #define CMD_UP		9
108 #define CMD_DOWN	10
109 
110 #ifdef ALWAYS_USE_GUI
111     /* Can't do this when there is no terminal for input/output. */
112     if (!gui.in_use)
113     {
114 	/* Break as soon as possible. */
115 	debug_break_level = 9999;
116 	return;
117     }
118 #endif
119 
120     /* Make sure we are in raw mode and start termcap mode.  Might have side
121      * effects... */
122     settmode(TMODE_RAW);
123     starttermcap();
124 
125     ++RedrawingDisabled;	/* don't redisplay the window */
126     ++no_wait_return;		/* don't wait for return */
127     did_emsg = FALSE;		/* don't use error from debugged stuff */
128     cmd_silent = FALSE;		/* display commands */
129     msg_silent = FALSE;		/* display messages */
130     emsg_silent = FALSE;	/* display error messages */
131     redir_off = TRUE;		/* don't redirect debug commands */
132 
133     State = NORMAL;
134     debug_mode = TRUE;
135 
136     if (!debug_did_msg)
137 	MSG(_("Entering Debug mode.  Type \"cont\" to continue."));
138     if (sourcing_name != NULL)
139 	msg(sourcing_name);
140     if (sourcing_lnum != 0)
141 	smsg((char_u *)_("line %ld: %s"), (long)sourcing_lnum, cmd);
142     else
143 	smsg((char_u *)_("cmd: %s"), cmd);
144 
145     /*
146      * Repeat getting a command and executing it.
147      */
148     for (;;)
149     {
150 	msg_scroll = TRUE;
151 	need_wait_return = FALSE;
152 
153 	/* Save the current typeahead buffer and replace it with an empty one.
154 	 * This makes sure we get input from the user here and don't interfere
155 	 * with the commands being executed.  Reset "ex_normal_busy" to avoid
156 	 * the side effects of using ":normal". Save the stuff buffer and make
157 	 * it empty. Set ignore_script to avoid reading from script input. */
158 	save_ex_normal_busy = ex_normal_busy;
159 	ex_normal_busy = 0;
160 	if (!debug_greedy)
161 	{
162 	    save_typeahead(&typeaheadbuf);
163 	    typeahead_saved = TRUE;
164 	    save_ignore_script = ignore_script;
165 	    ignore_script = TRUE;
166 	}
167 
168 	vim_free(cmdline);
169 	cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL);
170 
171 	if (typeahead_saved)
172 	{
173 	    restore_typeahead(&typeaheadbuf);
174 	    ignore_script = save_ignore_script;
175 	}
176 	ex_normal_busy = save_ex_normal_busy;
177 
178 	cmdline_row = msg_row;
179 	msg_starthere();
180 	if (cmdline != NULL)
181 	{
182 	    /* If this is a debug command, set "last_cmd".
183 	     * If not, reset "last_cmd".
184 	     * For a blank line use previous command. */
185 	    p = skipwhite(cmdline);
186 	    if (*p != NUL)
187 	    {
188 		switch (*p)
189 		{
190 		    case 'c': last_cmd = CMD_CONT;
191 			      tail = "ont";
192 			      break;
193 		    case 'n': last_cmd = CMD_NEXT;
194 			      tail = "ext";
195 			      break;
196 		    case 's': last_cmd = CMD_STEP;
197 			      tail = "tep";
198 			      break;
199 		    case 'f':
200 			      last_cmd = 0;
201 			      if (p[1] == 'r')
202 			      {
203 				  last_cmd = CMD_FRAME;
204 				  tail = "rame";
205 			      }
206 			      else
207 			      {
208 				  last_cmd = CMD_FINISH;
209 				  tail = "inish";
210 			      }
211 			      break;
212 		    case 'q': last_cmd = CMD_QUIT;
213 			      tail = "uit";
214 			      break;
215 		    case 'i': last_cmd = CMD_INTERRUPT;
216 			      tail = "nterrupt";
217 			      break;
218 		    case 'b': last_cmd = CMD_BACKTRACE;
219 			      if (p[1] == 't')
220 				  tail = "t";
221 			      else
222 				  tail = "acktrace";
223 			      break;
224 		    case 'w': last_cmd = CMD_BACKTRACE;
225 			      tail = "here";
226 			      break;
227 		    case 'u': last_cmd = CMD_UP;
228 			      tail = "p";
229 			      break;
230 		    case 'd': last_cmd = CMD_DOWN;
231 			      tail = "own";
232 			      break;
233 		    default: last_cmd = 0;
234 		}
235 		if (last_cmd != 0)
236 		{
237 		    /* Check that the tail matches. */
238 		    ++p;
239 		    while (*p != NUL && *p == *tail)
240 		    {
241 			++p;
242 			++tail;
243 		    }
244 		    if (ASCII_ISALPHA(*p) && last_cmd != CMD_FRAME)
245 			last_cmd = 0;
246 		}
247 	    }
248 
249 	    if (last_cmd != 0)
250 	    {
251 		/* Execute debug command: decided where to break next and
252 		 * return. */
253 		switch (last_cmd)
254 		{
255 		    case CMD_CONT:
256 			debug_break_level = -1;
257 			break;
258 		    case CMD_NEXT:
259 			debug_break_level = ex_nesting_level;
260 			break;
261 		    case CMD_STEP:
262 			debug_break_level = 9999;
263 			break;
264 		    case CMD_FINISH:
265 			debug_break_level = ex_nesting_level - 1;
266 			break;
267 		    case CMD_QUIT:
268 			got_int = TRUE;
269 			debug_break_level = -1;
270 			break;
271 		    case CMD_INTERRUPT:
272 			got_int = TRUE;
273 			debug_break_level = 9999;
274 			/* Do not repeat ">interrupt" cmd, continue stepping. */
275 			last_cmd = CMD_STEP;
276 			break;
277 		    case CMD_BACKTRACE:
278 			do_showbacktrace(cmd);
279 			continue;
280 		    case CMD_FRAME:
281 			if (*p == NUL)
282 			{
283 			    do_showbacktrace(cmd);
284 			}
285 			else
286 			{
287 			    p = skipwhite(p);
288 			    do_setdebugtracelevel(p);
289 			}
290 			continue;
291 		    case CMD_UP:
292 			debug_backtrace_level++;
293 			do_checkbacktracelevel();
294 			continue;
295 		    case CMD_DOWN:
296 			debug_backtrace_level--;
297 			do_checkbacktracelevel();
298 			continue;
299 		}
300 		/* Going out reset backtrace_level */
301 		debug_backtrace_level = 0;
302 		break;
303 	    }
304 
305 	    /* don't debug this command */
306 	    n = debug_break_level;
307 	    debug_break_level = -1;
308 	    (void)do_cmdline(cmdline, getexline, NULL,
309 						DOCMD_VERBOSE|DOCMD_EXCRESET);
310 	    debug_break_level = n;
311 	}
312 	lines_left = Rows - 1;
313     }
314     vim_free(cmdline);
315 
316     --RedrawingDisabled;
317     --no_wait_return;
318     redraw_all_later(NOT_VALID);
319     need_wait_return = FALSE;
320     msg_scroll = save_msg_scroll;
321     lines_left = Rows - 1;
322     State = save_State;
323     debug_mode = FALSE;
324     did_emsg = save_did_emsg;
325     cmd_silent = save_cmd_silent;
326     msg_silent = save_msg_silent;
327     emsg_silent = save_emsg_silent;
328     redir_off = save_redir_off;
329 
330     /* Only print the message again when typing a command before coming back
331      * here. */
332     debug_did_msg = TRUE;
333 }
334 
335     static int
336 get_maxbacktrace_level(void)
337 {
338     char	*p, *q;
339     int		maxbacktrace = 0;
340 
341     if (sourcing_name != NULL)
342     {
343 	p = (char *)sourcing_name;
344 	while ((q = strstr(p, "..")) != NULL)
345 	{
346 	    p = q + 2;
347 	    maxbacktrace++;
348 	}
349     }
350     return maxbacktrace;
351 }
352 
353     static void
354 do_setdebugtracelevel(char_u *arg)
355 {
356     int level;
357 
358     level = atoi((char *)arg);
359     if (*arg == '+' || level < 0)
360 	debug_backtrace_level += level;
361     else
362 	debug_backtrace_level = level;
363 
364     do_checkbacktracelevel();
365 }
366 
367     static void
368 do_checkbacktracelevel(void)
369 {
370     if (debug_backtrace_level < 0)
371     {
372 	debug_backtrace_level = 0;
373 	MSG(_("frame is zero"));
374     }
375     else
376     {
377 	int max = get_maxbacktrace_level();
378 
379 	if (debug_backtrace_level > max)
380 	{
381 	    debug_backtrace_level = max;
382 	    smsg((char_u *)_("frame at highest level: %d"), max);
383 	}
384     }
385 }
386 
387     static void
388 do_showbacktrace(char_u *cmd)
389 {
390     char    *cur;
391     char    *next;
392     int	    i = 0;
393     int	    max = get_maxbacktrace_level();
394 
395     if (sourcing_name != NULL)
396     {
397 	cur = (char *)sourcing_name;
398 	while (!got_int)
399 	{
400 	    next = strstr(cur, "..");
401 	    if (next != NULL)
402 		*next = NUL;
403 	    if (i == max - debug_backtrace_level)
404 		smsg((char_u *)"->%d %s", max - i, cur);
405 	    else
406 		smsg((char_u *)"  %d %s", max - i, cur);
407 	    ++i;
408 	    if (next == NULL)
409 		break;
410 	    *next = '.';
411 	    cur = next + 2;
412 	}
413     }
414     if (sourcing_lnum != 0)
415        smsg((char_u *)_("line %ld: %s"), (long)sourcing_lnum, cmd);
416     else
417        smsg((char_u *)_("cmd: %s"), cmd);
418 }
419 
420 /*
421  * ":debug".
422  */
423     void
424 ex_debug(exarg_T *eap)
425 {
426     int		debug_break_level_save = debug_break_level;
427 
428     debug_break_level = 9999;
429     do_cmdline_cmd(eap->arg);
430     debug_break_level = debug_break_level_save;
431 }
432 
433 static char_u	*debug_breakpoint_name = NULL;
434 static linenr_T	debug_breakpoint_lnum;
435 
436 /*
437  * When debugging or a breakpoint is set on a skipped command, no debug prompt
438  * is shown by do_one_cmd().  This situation is indicated by debug_skipped, and
439  * debug_skipped_name is then set to the source name in the breakpoint case.  If
440  * a skipped command decides itself that a debug prompt should be displayed, it
441  * can do so by calling dbg_check_skipped().
442  */
443 static int	debug_skipped;
444 static char_u	*debug_skipped_name;
445 
446 /*
447  * Go to debug mode when a breakpoint was encountered or "ex_nesting_level" is
448  * at or below the break level.  But only when the line is actually
449  * executed.  Return TRUE and set breakpoint_name for skipped commands that
450  * decide to execute something themselves.
451  * Called from do_one_cmd() before executing a command.
452  */
453     void
454 dbg_check_breakpoint(exarg_T *eap)
455 {
456     char_u	*p;
457 
458     debug_skipped = FALSE;
459     if (debug_breakpoint_name != NULL)
460     {
461 	if (!eap->skip)
462 	{
463 	    /* replace K_SNR with "<SNR>" */
464 	    if (debug_breakpoint_name[0] == K_SPECIAL
465 		    && debug_breakpoint_name[1] == KS_EXTRA
466 		    && debug_breakpoint_name[2] == (int)KE_SNR)
467 		p = (char_u *)"<SNR>";
468 	    else
469 		p = (char_u *)"";
470 	    smsg((char_u *)_("Breakpoint in \"%s%s\" line %ld"),
471 		    p,
472 		    debug_breakpoint_name + (*p == NUL ? 0 : 3),
473 		    (long)debug_breakpoint_lnum);
474 	    debug_breakpoint_name = NULL;
475 	    do_debug(eap->cmd);
476 	}
477 	else
478 	{
479 	    debug_skipped = TRUE;
480 	    debug_skipped_name = debug_breakpoint_name;
481 	    debug_breakpoint_name = NULL;
482 	}
483     }
484     else if (ex_nesting_level <= debug_break_level)
485     {
486 	if (!eap->skip)
487 	    do_debug(eap->cmd);
488 	else
489 	{
490 	    debug_skipped = TRUE;
491 	    debug_skipped_name = NULL;
492 	}
493     }
494 }
495 
496 /*
497  * Go to debug mode if skipped by dbg_check_breakpoint() because eap->skip was
498  * set.  Return TRUE when the debug mode is entered this time.
499  */
500     int
501 dbg_check_skipped(exarg_T *eap)
502 {
503     int		prev_got_int;
504 
505     if (debug_skipped)
506     {
507 	/*
508 	 * Save the value of got_int and reset it.  We don't want a previous
509 	 * interruption cause flushing the input buffer.
510 	 */
511 	prev_got_int = got_int;
512 	got_int = FALSE;
513 	debug_breakpoint_name = debug_skipped_name;
514 	/* eap->skip is TRUE */
515 	eap->skip = FALSE;
516 	(void)dbg_check_breakpoint(eap);
517 	eap->skip = TRUE;
518 	got_int |= prev_got_int;
519 	return TRUE;
520     }
521     return FALSE;
522 }
523 
524 /*
525  * The list of breakpoints: dbg_breakp.
526  * This is a grow-array of structs.
527  */
528 struct debuggy
529 {
530     int		dbg_nr;		/* breakpoint number */
531     int		dbg_type;	/* DBG_FUNC or DBG_FILE */
532     char_u	*dbg_name;	/* function or file name */
533     regprog_T	*dbg_prog;	/* regexp program */
534     linenr_T	dbg_lnum;	/* line number in function or file */
535     int		dbg_forceit;	/* ! used */
536 };
537 
538 static garray_T dbg_breakp = {0, 0, sizeof(struct debuggy), 4, NULL};
539 #define BREAKP(idx)		(((struct debuggy *)dbg_breakp.ga_data)[idx])
540 #define DEBUGGY(gap, idx)	(((struct debuggy *)gap->ga_data)[idx])
541 static int last_breakp = 0;	/* nr of last defined breakpoint */
542 
543 #ifdef FEAT_PROFILE
544 /* Profiling uses file and func names similar to breakpoints. */
545 static garray_T prof_ga = {0, 0, sizeof(struct debuggy), 4, NULL};
546 #endif
547 #define DBG_FUNC	1
548 #define DBG_FILE	2
549 
550 static int dbg_parsearg(char_u *arg, garray_T *gap);
551 static linenr_T debuggy_find(int file,char_u *fname, linenr_T after, garray_T *gap, int *fp);
552 
553 /*
554  * Parse the arguments of ":profile", ":breakadd" or ":breakdel" and put them
555  * in the entry just after the last one in dbg_breakp.  Note that "dbg_name"
556  * is allocated.
557  * Returns FAIL for failure.
558  */
559     static int
560 dbg_parsearg(
561     char_u	*arg,
562     garray_T	*gap)	    /* either &dbg_breakp or &prof_ga */
563 {
564     char_u	*p = arg;
565     char_u	*q;
566     struct debuggy *bp;
567     int		here = FALSE;
568 
569     if (ga_grow(gap, 1) == FAIL)
570 	return FAIL;
571     bp = &DEBUGGY(gap, gap->ga_len);
572 
573     /* Find "func" or "file". */
574     if (STRNCMP(p, "func", 4) == 0)
575 	bp->dbg_type = DBG_FUNC;
576     else if (STRNCMP(p, "file", 4) == 0)
577 	bp->dbg_type = DBG_FILE;
578     else if (
579 #ifdef FEAT_PROFILE
580 	    gap != &prof_ga &&
581 #endif
582 	    STRNCMP(p, "here", 4) == 0)
583     {
584 	if (curbuf->b_ffname == NULL)
585 	{
586 	    EMSG(_(e_noname));
587 	    return FAIL;
588 	}
589 	bp->dbg_type = DBG_FILE;
590 	here = TRUE;
591     }
592     else
593     {
594 	EMSG2(_(e_invarg2), p);
595 	return FAIL;
596     }
597     p = skipwhite(p + 4);
598 
599     /* Find optional line number. */
600     if (here)
601 	bp->dbg_lnum = curwin->w_cursor.lnum;
602     else if (
603 #ifdef FEAT_PROFILE
604 	    gap != &prof_ga &&
605 #endif
606 	    VIM_ISDIGIT(*p))
607     {
608 	bp->dbg_lnum = getdigits(&p);
609 	p = skipwhite(p);
610     }
611     else
612 	bp->dbg_lnum = 0;
613 
614     /* Find the function or file name.  Don't accept a function name with (). */
615     if ((!here && *p == NUL)
616 	    || (here && *p != NUL)
617 	    || (bp->dbg_type == DBG_FUNC && strstr((char *)p, "()") != NULL))
618     {
619 	EMSG2(_(e_invarg2), arg);
620 	return FAIL;
621     }
622 
623     if (bp->dbg_type == DBG_FUNC)
624 	bp->dbg_name = vim_strsave(p);
625     else if (here)
626 	bp->dbg_name = vim_strsave(curbuf->b_ffname);
627     else
628     {
629 	/* Expand the file name in the same way as do_source().  This means
630 	 * doing it twice, so that $DIR/file gets expanded when $DIR is
631 	 * "~/dir". */
632 	q = expand_env_save(p);
633 	if (q == NULL)
634 	    return FAIL;
635 	p = expand_env_save(q);
636 	vim_free(q);
637 	if (p == NULL)
638 	    return FAIL;
639 	if (*p != '*')
640 	{
641 	    bp->dbg_name = fix_fname(p);
642 	    vim_free(p);
643 	}
644 	else
645 	    bp->dbg_name = p;
646     }
647 
648     if (bp->dbg_name == NULL)
649 	return FAIL;
650     return OK;
651 }
652 
653 /*
654  * ":breakadd".
655  */
656     void
657 ex_breakadd(exarg_T *eap)
658 {
659     struct debuggy *bp;
660     char_u	*pat;
661     garray_T	*gap;
662 
663     gap = &dbg_breakp;
664 #ifdef FEAT_PROFILE
665     if (eap->cmdidx == CMD_profile)
666 	gap = &prof_ga;
667 #endif
668 
669     if (dbg_parsearg(eap->arg, gap) == OK)
670     {
671 	bp = &DEBUGGY(gap, gap->ga_len);
672 	bp->dbg_forceit = eap->forceit;
673 
674 	pat = file_pat_to_reg_pat(bp->dbg_name, NULL, NULL, FALSE);
675 	if (pat != NULL)
676 	{
677 	    bp->dbg_prog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
678 	    vim_free(pat);
679 	}
680 	if (pat == NULL || bp->dbg_prog == NULL)
681 	    vim_free(bp->dbg_name);
682 	else
683 	{
684 	    if (bp->dbg_lnum == 0)	/* default line number is 1 */
685 		bp->dbg_lnum = 1;
686 #ifdef FEAT_PROFILE
687 	    if (eap->cmdidx != CMD_profile)
688 #endif
689 	    {
690 		DEBUGGY(gap, gap->ga_len).dbg_nr = ++last_breakp;
691 		++debug_tick;
692 	    }
693 	    ++gap->ga_len;
694 	}
695     }
696 }
697 
698 /*
699  * ":debuggreedy".
700  */
701     void
702 ex_debuggreedy(exarg_T *eap)
703 {
704     if (eap->addr_count == 0 || eap->line2 != 0)
705 	debug_greedy = TRUE;
706     else
707 	debug_greedy = FALSE;
708 }
709 
710 /*
711  * ":breakdel" and ":profdel".
712  */
713     void
714 ex_breakdel(exarg_T *eap)
715 {
716     struct debuggy *bp, *bpi;
717     int		nr;
718     int		todel = -1;
719     int		del_all = FALSE;
720     int		i;
721     linenr_T	best_lnum = 0;
722     garray_T	*gap;
723 
724     gap = &dbg_breakp;
725     if (eap->cmdidx == CMD_profdel)
726     {
727 #ifdef FEAT_PROFILE
728 	gap = &prof_ga;
729 #else
730 	ex_ni(eap);
731 	return;
732 #endif
733     }
734 
735     if (vim_isdigit(*eap->arg))
736     {
737 	/* ":breakdel {nr}" */
738 	nr = atol((char *)eap->arg);
739 	for (i = 0; i < gap->ga_len; ++i)
740 	    if (DEBUGGY(gap, i).dbg_nr == nr)
741 	    {
742 		todel = i;
743 		break;
744 	    }
745     }
746     else if (*eap->arg == '*')
747     {
748 	todel = 0;
749 	del_all = TRUE;
750     }
751     else
752     {
753 	/* ":breakdel {func|file} [lnum] {name}" */
754 	if (dbg_parsearg(eap->arg, gap) == FAIL)
755 	    return;
756 	bp = &DEBUGGY(gap, gap->ga_len);
757 	for (i = 0; i < gap->ga_len; ++i)
758 	{
759 	    bpi = &DEBUGGY(gap, i);
760 	    if (bp->dbg_type == bpi->dbg_type
761 		    && STRCMP(bp->dbg_name, bpi->dbg_name) == 0
762 		    && (bp->dbg_lnum == bpi->dbg_lnum
763 			|| (bp->dbg_lnum == 0
764 			    && (best_lnum == 0
765 				|| bpi->dbg_lnum < best_lnum))))
766 	    {
767 		todel = i;
768 		best_lnum = bpi->dbg_lnum;
769 	    }
770 	}
771 	vim_free(bp->dbg_name);
772     }
773 
774     if (todel < 0)
775 	EMSG2(_("E161: Breakpoint not found: %s"), eap->arg);
776     else
777     {
778 	while (gap->ga_len > 0)
779 	{
780 	    vim_free(DEBUGGY(gap, todel).dbg_name);
781 	    vim_regfree(DEBUGGY(gap, todel).dbg_prog);
782 	    --gap->ga_len;
783 	    if (todel < gap->ga_len)
784 		mch_memmove(&DEBUGGY(gap, todel), &DEBUGGY(gap, todel + 1),
785 			      (gap->ga_len - todel) * sizeof(struct debuggy));
786 #ifdef FEAT_PROFILE
787 	    if (eap->cmdidx == CMD_breakdel)
788 #endif
789 		++debug_tick;
790 	    if (!del_all)
791 		break;
792 	}
793 
794 	/* If all breakpoints were removed clear the array. */
795 	if (gap->ga_len == 0)
796 	    ga_clear(gap);
797     }
798 }
799 
800 /*
801  * ":breaklist".
802  */
803     void
804 ex_breaklist(exarg_T *eap UNUSED)
805 {
806     struct debuggy *bp;
807     int		i;
808 
809     if (dbg_breakp.ga_len == 0)
810 	MSG(_("No breakpoints defined"));
811     else
812 	for (i = 0; i < dbg_breakp.ga_len; ++i)
813 	{
814 	    bp = &BREAKP(i);
815 	    if (bp->dbg_type == DBG_FILE)
816 		home_replace(NULL, bp->dbg_name, NameBuff, MAXPATHL, TRUE);
817 	    smsg((char_u *)_("%3d  %s %s  line %ld"),
818 		    bp->dbg_nr,
819 		    bp->dbg_type == DBG_FUNC ? "func" : "file",
820 		    bp->dbg_type == DBG_FUNC ? bp->dbg_name : NameBuff,
821 		    (long)bp->dbg_lnum);
822 	}
823 }
824 
825 /*
826  * Find a breakpoint for a function or sourced file.
827  * Returns line number at which to break; zero when no matching breakpoint.
828  */
829     linenr_T
830 dbg_find_breakpoint(
831     int		file,	    /* TRUE for a file, FALSE for a function */
832     char_u	*fname,	    /* file or function name */
833     linenr_T	after)	    /* after this line number */
834 {
835     return debuggy_find(file, fname, after, &dbg_breakp, NULL);
836 }
837 
838 #if defined(FEAT_PROFILE) || defined(PROTO)
839 /*
840  * Return TRUE if profiling is on for a function or sourced file.
841  */
842     int
843 has_profiling(
844     int		file,	    /* TRUE for a file, FALSE for a function */
845     char_u	*fname,	    /* file or function name */
846     int		*fp)	    /* return: forceit */
847 {
848     return (debuggy_find(file, fname, (linenr_T)0, &prof_ga, fp)
849 							      != (linenr_T)0);
850 }
851 #endif
852 
853 /*
854  * Common code for dbg_find_breakpoint() and has_profiling().
855  */
856     static linenr_T
857 debuggy_find(
858     int		file,	    /* TRUE for a file, FALSE for a function */
859     char_u	*fname,	    /* file or function name */
860     linenr_T	after,	    /* after this line number */
861     garray_T	*gap,	    /* either &dbg_breakp or &prof_ga */
862     int		*fp)	    /* if not NULL: return forceit */
863 {
864     struct debuggy *bp;
865     int		i;
866     linenr_T	lnum = 0;
867     char_u	*name = fname;
868     int		prev_got_int;
869 
870     /* Return quickly when there are no breakpoints. */
871     if (gap->ga_len == 0)
872 	return (linenr_T)0;
873 
874     /* Replace K_SNR in function name with "<SNR>". */
875     if (!file && fname[0] == K_SPECIAL)
876     {
877 	name = alloc((unsigned)STRLEN(fname) + 3);
878 	if (name == NULL)
879 	    name = fname;
880 	else
881 	{
882 	    STRCPY(name, "<SNR>");
883 	    STRCPY(name + 5, fname + 3);
884 	}
885     }
886 
887     for (i = 0; i < gap->ga_len; ++i)
888     {
889 	/* Skip entries that are not useful or are for a line that is beyond
890 	 * an already found breakpoint. */
891 	bp = &DEBUGGY(gap, i);
892 	if (((bp->dbg_type == DBG_FILE) == file && (
893 #ifdef FEAT_PROFILE
894 		gap == &prof_ga ||
895 #endif
896 		(bp->dbg_lnum > after && (lnum == 0 || bp->dbg_lnum < lnum)))))
897 	{
898 	    /*
899 	     * Save the value of got_int and reset it.  We don't want a
900 	     * previous interruption cancel matching, only hitting CTRL-C
901 	     * while matching should abort it.
902 	     */
903 	    prev_got_int = got_int;
904 	    got_int = FALSE;
905 	    if (vim_regexec_prog(&bp->dbg_prog, FALSE, name, (colnr_T)0))
906 	    {
907 		lnum = bp->dbg_lnum;
908 		if (fp != NULL)
909 		    *fp = bp->dbg_forceit;
910 	    }
911 	    got_int |= prev_got_int;
912 	}
913     }
914     if (name != fname)
915 	vim_free(name);
916 
917     return lnum;
918 }
919 
920 /*
921  * Called when a breakpoint was encountered.
922  */
923     void
924 dbg_breakpoint(char_u *name, linenr_T lnum)
925 {
926     /* We need to check if this line is actually executed in do_one_cmd() */
927     debug_breakpoint_name = name;
928     debug_breakpoint_lnum = lnum;
929 }
930 
931 
932 # if defined(FEAT_PROFILE) || defined(FEAT_RELTIME) || defined(PROTO)
933 /*
934  * Store the current time in "tm".
935  */
936     void
937 profile_start(proftime_T *tm)
938 {
939 # ifdef WIN3264
940     QueryPerformanceCounter(tm);
941 # else
942     gettimeofday(tm, NULL);
943 # endif
944 }
945 
946 /*
947  * Compute the elapsed time from "tm" till now and store in "tm".
948  */
949     void
950 profile_end(proftime_T *tm)
951 {
952     proftime_T now;
953 
954 # ifdef WIN3264
955     QueryPerformanceCounter(&now);
956     tm->QuadPart = now.QuadPart - tm->QuadPart;
957 # else
958     gettimeofday(&now, NULL);
959     tm->tv_usec = now.tv_usec - tm->tv_usec;
960     tm->tv_sec = now.tv_sec - tm->tv_sec;
961     if (tm->tv_usec < 0)
962     {
963 	tm->tv_usec += 1000000;
964 	--tm->tv_sec;
965     }
966 # endif
967 }
968 
969 /*
970  * Subtract the time "tm2" from "tm".
971  */
972     void
973 profile_sub(proftime_T *tm, proftime_T *tm2)
974 {
975 # ifdef WIN3264
976     tm->QuadPart -= tm2->QuadPart;
977 # else
978     tm->tv_usec -= tm2->tv_usec;
979     tm->tv_sec -= tm2->tv_sec;
980     if (tm->tv_usec < 0)
981     {
982 	tm->tv_usec += 1000000;
983 	--tm->tv_sec;
984     }
985 # endif
986 }
987 
988 /*
989  * Return a string that represents the time in "tm".
990  * Uses a static buffer!
991  */
992     char *
993 profile_msg(proftime_T *tm)
994 {
995     static char buf[50];
996 
997 # ifdef WIN3264
998     LARGE_INTEGER   fr;
999 
1000     QueryPerformanceFrequency(&fr);
1001     sprintf(buf, "%10.6lf", (double)tm->QuadPart / (double)fr.QuadPart);
1002 # else
1003     sprintf(buf, "%3ld.%06ld", (long)tm->tv_sec, (long)tm->tv_usec);
1004 # endif
1005     return buf;
1006 }
1007 
1008 # if defined(FEAT_FLOAT) || defined(PROTO)
1009 /*
1010  * Return a float that represents the time in "tm".
1011  */
1012     float_T
1013 profile_float(proftime_T *tm)
1014 {
1015 #  ifdef WIN3264
1016     LARGE_INTEGER   fr;
1017 
1018     QueryPerformanceFrequency(&fr);
1019     return (float_T)tm->QuadPart / (float_T)fr.QuadPart;
1020 #  else
1021     return (float_T)tm->tv_sec + (float_T)tm->tv_usec / 1000000.0;
1022 #  endif
1023 }
1024 # endif
1025 
1026 /*
1027  * Put the time "msec" past now in "tm".
1028  */
1029     void
1030 profile_setlimit(long msec, proftime_T *tm)
1031 {
1032     if (msec <= 0)   /* no limit */
1033 	profile_zero(tm);
1034     else
1035     {
1036 # ifdef WIN3264
1037 	LARGE_INTEGER   fr;
1038 
1039 	QueryPerformanceCounter(tm);
1040 	QueryPerformanceFrequency(&fr);
1041 	tm->QuadPart += (LONGLONG)((double)msec / 1000.0 * (double)fr.QuadPart);
1042 # else
1043 	long	    usec;
1044 
1045 	gettimeofday(tm, NULL);
1046 	usec = (long)tm->tv_usec + (long)msec * 1000;
1047 	tm->tv_usec = usec % 1000000L;
1048 	tm->tv_sec += usec / 1000000L;
1049 # endif
1050     }
1051 }
1052 
1053 /*
1054  * Return TRUE if the current time is past "tm".
1055  */
1056     int
1057 profile_passed_limit(proftime_T *tm)
1058 {
1059     proftime_T	now;
1060 
1061 # ifdef WIN3264
1062     if (tm->QuadPart == 0)  /* timer was not set */
1063 	return FALSE;
1064     QueryPerformanceCounter(&now);
1065     return (now.QuadPart > tm->QuadPart);
1066 # else
1067     if (tm->tv_sec == 0)    /* timer was not set */
1068 	return FALSE;
1069     gettimeofday(&now, NULL);
1070     return (now.tv_sec > tm->tv_sec
1071 	    || (now.tv_sec == tm->tv_sec && now.tv_usec > tm->tv_usec));
1072 # endif
1073 }
1074 
1075 /*
1076  * Set the time in "tm" to zero.
1077  */
1078     void
1079 profile_zero(proftime_T *tm)
1080 {
1081 # ifdef WIN3264
1082     tm->QuadPart = 0;
1083 # else
1084     tm->tv_usec = 0;
1085     tm->tv_sec = 0;
1086 # endif
1087 }
1088 
1089 # endif  /* FEAT_PROFILE || FEAT_RELTIME */
1090 
1091 # if defined(FEAT_TIMERS) || defined(PROTO)
1092 static timer_T	*first_timer = NULL;
1093 static long	last_timer_id = 0;
1094 
1095     static long
1096 timer_time_left(timer_T *timer, proftime_T *now)
1097 {
1098 #  ifdef WIN3264
1099     LARGE_INTEGER fr;
1100 
1101     if (now->QuadPart > timer->tr_due.QuadPart)
1102 	return 0;
1103     QueryPerformanceFrequency(&fr);
1104     return (long)(((double)(timer->tr_due.QuadPart - now->QuadPart)
1105 		   / (double)fr.QuadPart) * 1000);
1106 #  else
1107     if (now->tv_sec > timer->tr_due.tv_sec)
1108 	return 0;
1109     return (timer->tr_due.tv_sec - now->tv_sec) * 1000
1110 	+ (timer->tr_due.tv_usec - now->tv_usec) / 1000;
1111 #  endif
1112 }
1113 
1114 /*
1115  * Insert a timer in the list of timers.
1116  */
1117     static void
1118 insert_timer(timer_T *timer)
1119 {
1120     timer->tr_next = first_timer;
1121     timer->tr_prev = NULL;
1122     if (first_timer != NULL)
1123 	first_timer->tr_prev = timer;
1124     first_timer = timer;
1125     did_add_timer = TRUE;
1126 }
1127 
1128 /*
1129  * Take a timer out of the list of timers.
1130  */
1131     static void
1132 remove_timer(timer_T *timer)
1133 {
1134     if (timer->tr_prev == NULL)
1135 	first_timer = timer->tr_next;
1136     else
1137 	timer->tr_prev->tr_next = timer->tr_next;
1138     if (timer->tr_next != NULL)
1139 	timer->tr_next->tr_prev = timer->tr_prev;
1140 }
1141 
1142     static void
1143 free_timer(timer_T *timer)
1144 {
1145     free_callback(timer->tr_callback, timer->tr_partial);
1146     vim_free(timer);
1147 }
1148 
1149 /*
1150  * Create a timer and return it.  NULL if out of memory.
1151  * Caller should set the callback.
1152  */
1153     timer_T *
1154 create_timer(long msec, int repeat)
1155 {
1156     timer_T	*timer = (timer_T *)alloc_clear(sizeof(timer_T));
1157     long	prev_id = last_timer_id;
1158 
1159     if (timer == NULL)
1160 	return NULL;
1161     if (++last_timer_id <= prev_id)
1162 	/* Overflow!  Might cause duplicates... */
1163 	last_timer_id = 0;
1164     timer->tr_id = last_timer_id;
1165     insert_timer(timer);
1166     if (repeat != 0)
1167 	timer->tr_repeat = repeat - 1;
1168     timer->tr_interval = msec;
1169 
1170     profile_setlimit(msec, &timer->tr_due);
1171     return timer;
1172 }
1173 
1174 /*
1175  * Invoke the callback of "timer".
1176  */
1177     static void
1178 timer_callback(timer_T *timer)
1179 {
1180     typval_T	rettv;
1181     int		dummy;
1182     typval_T	argv[2];
1183 
1184     argv[0].v_type = VAR_NUMBER;
1185     argv[0].vval.v_number = (varnumber_T)timer->tr_id;
1186     argv[1].v_type = VAR_UNKNOWN;
1187 
1188     call_func(timer->tr_callback, (int)STRLEN(timer->tr_callback),
1189 			&rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE,
1190 			timer->tr_partial, NULL);
1191     clear_tv(&rettv);
1192 }
1193 
1194 /*
1195  * Call timers that are due.
1196  * Return the time in msec until the next timer is due.
1197  * Returns -1 if there are no pending timers.
1198  */
1199     long
1200 check_due_timer(void)
1201 {
1202     timer_T	*timer;
1203     timer_T	*timer_next;
1204     long	this_due;
1205     long	next_due = -1;
1206     proftime_T	now;
1207     int		did_one = FALSE;
1208     int		need_update_screen = FALSE;
1209     long	current_id = last_timer_id;
1210 
1211     /* Don't run any timers while exiting or dealing with an error. */
1212     if (exiting || aborting())
1213 	return next_due;
1214 
1215     profile_start(&now);
1216     for (timer = first_timer; timer != NULL && !got_int; timer = timer_next)
1217     {
1218 	timer_next = timer->tr_next;
1219 
1220 	if (timer->tr_id == -1 || timer->tr_firing || timer->tr_paused)
1221 	    continue;
1222 	this_due = timer_time_left(timer, &now);
1223 	if (this_due <= 1)
1224 	{
1225 	    int save_timer_busy = timer_busy;
1226 	    int save_vgetc_busy = vgetc_busy;
1227 	    int save_did_emsg = did_emsg;
1228 	    int save_called_emsg = called_emsg;
1229 	    int	save_must_redraw = must_redraw;
1230 	    int	save_trylevel = trylevel;
1231 	    int save_did_throw = did_throw;
1232 	    int save_ex_pressedreturn = get_pressedreturn();
1233 	    except_T *save_current_exception = current_exception;
1234 
1235 	    /* Create a scope for running the timer callback, ignoring most of
1236 	     * the current scope, such as being inside a try/catch. */
1237 	    timer_busy = timer_busy > 0 || vgetc_busy > 0;
1238 	    vgetc_busy = 0;
1239 	    called_emsg = FALSE;
1240 	    did_emsg = FALSE;
1241 	    did_uncaught_emsg = FALSE;
1242 	    must_redraw = 0;
1243 	    trylevel = 0;
1244 	    did_throw = FALSE;
1245 	    current_exception = NULL;
1246 
1247 	    timer->tr_firing = TRUE;
1248 	    timer_callback(timer);
1249 	    timer->tr_firing = FALSE;
1250 
1251 	    timer_next = timer->tr_next;
1252 	    did_one = TRUE;
1253 	    timer_busy = save_timer_busy;
1254 	    vgetc_busy = save_vgetc_busy;
1255 	    if (did_uncaught_emsg)
1256 		++timer->tr_emsg_count;
1257 	    did_emsg = save_did_emsg;
1258 	    called_emsg = save_called_emsg;
1259 	    trylevel = save_trylevel;
1260 	    did_throw = save_did_throw;
1261 	    current_exception = save_current_exception;
1262 	    if (must_redraw != 0)
1263 		need_update_screen = TRUE;
1264 	    must_redraw = must_redraw > save_must_redraw
1265 					      ? must_redraw : save_must_redraw;
1266 	    set_pressedreturn(save_ex_pressedreturn);
1267 
1268 	    /* Only fire the timer again if it repeats and stop_timer() wasn't
1269 	     * called while inside the callback (tr_id == -1). */
1270 	    if (timer->tr_repeat != 0 && timer->tr_id != -1
1271 		    && timer->tr_emsg_count < 3)
1272 	    {
1273 		profile_setlimit(timer->tr_interval, &timer->tr_due);
1274 		this_due = timer_time_left(timer, &now);
1275 		if (this_due < 1)
1276 		    this_due = 1;
1277 		if (timer->tr_repeat > 0)
1278 		    --timer->tr_repeat;
1279 	    }
1280 	    else
1281 	    {
1282 		this_due = -1;
1283 		remove_timer(timer);
1284 		free_timer(timer);
1285 	    }
1286 	}
1287 	if (this_due > 0 && (next_due == -1 || next_due > this_due))
1288 	    next_due = this_due;
1289     }
1290 
1291     if (did_one)
1292 	redraw_after_callback(need_update_screen);
1293 
1294     return current_id != last_timer_id ? 1 : next_due;
1295 }
1296 
1297 /*
1298  * Find a timer by ID.  Returns NULL if not found;
1299  */
1300     timer_T *
1301 find_timer(long id)
1302 {
1303     timer_T *timer;
1304 
1305     if (id >= 0)
1306     {
1307 	for (timer = first_timer; timer != NULL; timer = timer->tr_next)
1308 	    if (timer->tr_id == id)
1309 		return timer;
1310     }
1311     return NULL;
1312 }
1313 
1314 
1315 /*
1316  * Stop a timer and delete it.
1317  */
1318     void
1319 stop_timer(timer_T *timer)
1320 {
1321     if (timer->tr_firing)
1322 	/* Free the timer after the callback returns. */
1323 	timer->tr_id = -1;
1324     else
1325     {
1326 	remove_timer(timer);
1327 	free_timer(timer);
1328     }
1329 }
1330 
1331     void
1332 stop_all_timers(void)
1333 {
1334     timer_T *timer;
1335     timer_T *timer_next;
1336 
1337     for (timer = first_timer; timer != NULL; timer = timer_next)
1338     {
1339 	timer_next = timer->tr_next;
1340 	stop_timer(timer);
1341     }
1342 }
1343 
1344     void
1345 add_timer_info(typval_T *rettv, timer_T *timer)
1346 {
1347     list_T	*list = rettv->vval.v_list;
1348     dict_T	*dict = dict_alloc();
1349     dictitem_T	*di;
1350     long	remaining;
1351     proftime_T	now;
1352 
1353     if (dict == NULL)
1354 	return;
1355     list_append_dict(list, dict);
1356 
1357     dict_add_nr_str(dict, "id", timer->tr_id, NULL);
1358     dict_add_nr_str(dict, "time", (long)timer->tr_interval, NULL);
1359 
1360     profile_start(&now);
1361     remaining = timer_time_left(timer, &now);
1362     dict_add_nr_str(dict, "remaining", (long)remaining, NULL);
1363 
1364     dict_add_nr_str(dict, "repeat",
1365 	       (long)(timer->tr_repeat < 0 ? -1 : timer->tr_repeat + 1), NULL);
1366     dict_add_nr_str(dict, "paused", (long)(timer->tr_paused), NULL);
1367 
1368     di = dictitem_alloc((char_u *)"callback");
1369     if (di != NULL)
1370     {
1371 	if (dict_add(dict, di) == FAIL)
1372 	    vim_free(di);
1373 	else if (timer->tr_partial != NULL)
1374 	{
1375 	    di->di_tv.v_type = VAR_PARTIAL;
1376 	    di->di_tv.vval.v_partial = timer->tr_partial;
1377 	    ++timer->tr_partial->pt_refcount;
1378 	}
1379 	else
1380 	{
1381 	    di->di_tv.v_type = VAR_FUNC;
1382 	    di->di_tv.vval.v_string = vim_strsave(timer->tr_callback);
1383 	}
1384 	di->di_tv.v_lock = 0;
1385     }
1386 }
1387 
1388     void
1389 add_timer_info_all(typval_T *rettv)
1390 {
1391     timer_T *timer;
1392 
1393     for (timer = first_timer; timer != NULL; timer = timer->tr_next)
1394 	if (timer->tr_id != -1)
1395 	    add_timer_info(rettv, timer);
1396 }
1397 
1398 /*
1399  * Mark references in partials of timers.
1400  */
1401     int
1402 set_ref_in_timer(int copyID)
1403 {
1404     int		abort = FALSE;
1405     timer_T	*timer;
1406     typval_T	tv;
1407 
1408     for (timer = first_timer; timer != NULL; timer = timer->tr_next)
1409     {
1410 	if (timer->tr_partial != NULL)
1411 	{
1412 	    tv.v_type = VAR_PARTIAL;
1413 	    tv.vval.v_partial = timer->tr_partial;
1414 	}
1415 	else
1416 	{
1417 	    tv.v_type = VAR_FUNC;
1418 	    tv.vval.v_string = timer->tr_callback;
1419 	}
1420 	abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
1421     }
1422     return abort;
1423 }
1424 
1425 #  if defined(EXITFREE) || defined(PROTO)
1426     void
1427 timer_free_all()
1428 {
1429     timer_T *timer;
1430 
1431     while (first_timer != NULL)
1432     {
1433 	timer = first_timer;
1434 	remove_timer(timer);
1435 	free_timer(timer);
1436     }
1437 }
1438 #  endif
1439 # endif
1440 
1441 #if defined(FEAT_SYN_HL) && defined(FEAT_RELTIME) && defined(FEAT_FLOAT)
1442 # if defined(HAVE_MATH_H)
1443 #  include <math.h>
1444 # endif
1445 
1446 /*
1447  * Divide the time "tm" by "count" and store in "tm2".
1448  */
1449     void
1450 profile_divide(proftime_T *tm, int count, proftime_T *tm2)
1451 {
1452     if (count == 0)
1453 	profile_zero(tm2);
1454     else
1455     {
1456 # ifdef WIN3264
1457 	tm2->QuadPart = tm->QuadPart / count;
1458 # else
1459 	double usec = (tm->tv_sec * 1000000.0 + tm->tv_usec) / count;
1460 
1461 	tm2->tv_sec = floor(usec / 1000000.0);
1462 	tm2->tv_usec = vim_round(usec - (tm2->tv_sec * 1000000.0));
1463 # endif
1464     }
1465 }
1466 #endif
1467 
1468 # if defined(FEAT_PROFILE) || defined(PROTO)
1469 /*
1470  * Functions for profiling.
1471  */
1472 static void script_do_profile(scriptitem_T *si);
1473 static void script_dump_profile(FILE *fd);
1474 static proftime_T prof_wait_time;
1475 
1476 /*
1477  * Add the time "tm2" to "tm".
1478  */
1479     void
1480 profile_add(proftime_T *tm, proftime_T *tm2)
1481 {
1482 # ifdef WIN3264
1483     tm->QuadPart += tm2->QuadPart;
1484 # else
1485     tm->tv_usec += tm2->tv_usec;
1486     tm->tv_sec += tm2->tv_sec;
1487     if (tm->tv_usec >= 1000000)
1488     {
1489 	tm->tv_usec -= 1000000;
1490 	++tm->tv_sec;
1491     }
1492 # endif
1493 }
1494 
1495 /*
1496  * Add the "self" time from the total time and the children's time.
1497  */
1498     void
1499 profile_self(proftime_T *self, proftime_T *total, proftime_T *children)
1500 {
1501     /* Check that the result won't be negative.  Can happen with recursive
1502      * calls. */
1503 #ifdef WIN3264
1504     if (total->QuadPart <= children->QuadPart)
1505 	return;
1506 #else
1507     if (total->tv_sec < children->tv_sec
1508 	    || (total->tv_sec == children->tv_sec
1509 		&& total->tv_usec <= children->tv_usec))
1510 	return;
1511 #endif
1512     profile_add(self, total);
1513     profile_sub(self, children);
1514 }
1515 
1516 /*
1517  * Get the current waittime.
1518  */
1519     void
1520 profile_get_wait(proftime_T *tm)
1521 {
1522     *tm = prof_wait_time;
1523 }
1524 
1525 /*
1526  * Subtract the passed waittime since "tm" from "tma".
1527  */
1528     void
1529 profile_sub_wait(proftime_T *tm, proftime_T *tma)
1530 {
1531     proftime_T tm3 = prof_wait_time;
1532 
1533     profile_sub(&tm3, tm);
1534     profile_sub(tma, &tm3);
1535 }
1536 
1537 /*
1538  * Return TRUE if "tm1" and "tm2" are equal.
1539  */
1540     int
1541 profile_equal(proftime_T *tm1, proftime_T *tm2)
1542 {
1543 # ifdef WIN3264
1544     return (tm1->QuadPart == tm2->QuadPart);
1545 # else
1546     return (tm1->tv_usec == tm2->tv_usec && tm1->tv_sec == tm2->tv_sec);
1547 # endif
1548 }
1549 
1550 /*
1551  * Return <0, 0 or >0 if "tm1" < "tm2", "tm1" == "tm2" or "tm1" > "tm2"
1552  */
1553     int
1554 profile_cmp(const proftime_T *tm1, const proftime_T *tm2)
1555 {
1556 # ifdef WIN3264
1557     return (int)(tm2->QuadPart - tm1->QuadPart);
1558 # else
1559     if (tm1->tv_sec == tm2->tv_sec)
1560 	return tm2->tv_usec - tm1->tv_usec;
1561     return tm2->tv_sec - tm1->tv_sec;
1562 # endif
1563 }
1564 
1565 static char_u	*profile_fname = NULL;
1566 static proftime_T pause_time;
1567 
1568 /*
1569  * ":profile cmd args"
1570  */
1571     void
1572 ex_profile(exarg_T *eap)
1573 {
1574     char_u	*e;
1575     int		len;
1576 
1577     e = skiptowhite(eap->arg);
1578     len = (int)(e - eap->arg);
1579     e = skipwhite(e);
1580 
1581     if (len == 5 && STRNCMP(eap->arg, "start", 5) == 0 && *e != NUL)
1582     {
1583 	vim_free(profile_fname);
1584 	profile_fname = expand_env_save_opt(e, TRUE);
1585 	do_profiling = PROF_YES;
1586 	profile_zero(&prof_wait_time);
1587 	set_vim_var_nr(VV_PROFILING, 1L);
1588     }
1589     else if (do_profiling == PROF_NONE)
1590 	EMSG(_("E750: First use \":profile start {fname}\""));
1591     else if (STRCMP(eap->arg, "pause") == 0)
1592     {
1593 	if (do_profiling == PROF_YES)
1594 	    profile_start(&pause_time);
1595 	do_profiling = PROF_PAUSED;
1596     }
1597     else if (STRCMP(eap->arg, "continue") == 0)
1598     {
1599 	if (do_profiling == PROF_PAUSED)
1600 	{
1601 	    profile_end(&pause_time);
1602 	    profile_add(&prof_wait_time, &pause_time);
1603 	}
1604 	do_profiling = PROF_YES;
1605     }
1606     else
1607     {
1608 	/* The rest is similar to ":breakadd". */
1609 	ex_breakadd(eap);
1610     }
1611 }
1612 
1613 /* Command line expansion for :profile. */
1614 static enum
1615 {
1616     PEXP_SUBCMD,	/* expand :profile sub-commands */
1617     PEXP_FUNC		/* expand :profile func {funcname} */
1618 } pexpand_what;
1619 
1620 static char *pexpand_cmds[] = {
1621 			"start",
1622 #define PROFCMD_START	0
1623 			"pause",
1624 #define PROFCMD_PAUSE	1
1625 			"continue",
1626 #define PROFCMD_CONTINUE 2
1627 			"func",
1628 #define PROFCMD_FUNC	3
1629 			"file",
1630 #define PROFCMD_FILE	4
1631 			NULL
1632 #define PROFCMD_LAST	5
1633 };
1634 
1635 /*
1636  * Function given to ExpandGeneric() to obtain the profile command
1637  * specific expansion.
1638  */
1639     char_u *
1640 get_profile_name(expand_T *xp UNUSED, int idx)
1641 {
1642     switch (pexpand_what)
1643     {
1644     case PEXP_SUBCMD:
1645 	return (char_u *)pexpand_cmds[idx];
1646     /* case PEXP_FUNC: TODO */
1647     default:
1648 	return NULL;
1649     }
1650 }
1651 
1652 /*
1653  * Handle command line completion for :profile command.
1654  */
1655     void
1656 set_context_in_profile_cmd(expand_T *xp, char_u *arg)
1657 {
1658     char_u	*end_subcmd;
1659 
1660     /* Default: expand subcommands. */
1661     xp->xp_context = EXPAND_PROFILE;
1662     pexpand_what = PEXP_SUBCMD;
1663     xp->xp_pattern = arg;
1664 
1665     end_subcmd = skiptowhite(arg);
1666     if (*end_subcmd == NUL)
1667 	return;
1668 
1669     if (end_subcmd - arg == 5 && STRNCMP(arg, "start", 5) == 0)
1670     {
1671 	xp->xp_context = EXPAND_FILES;
1672 	xp->xp_pattern = skipwhite(end_subcmd);
1673 	return;
1674     }
1675 
1676     /* TODO: expand function names after "func" */
1677     xp->xp_context = EXPAND_NOTHING;
1678 }
1679 
1680 /*
1681  * Dump the profiling info.
1682  */
1683     void
1684 profile_dump(void)
1685 {
1686     FILE	*fd;
1687 
1688     if (profile_fname != NULL)
1689     {
1690 	fd = mch_fopen((char *)profile_fname, "w");
1691 	if (fd == NULL)
1692 	    EMSG2(_(e_notopen), profile_fname);
1693 	else
1694 	{
1695 	    script_dump_profile(fd);
1696 	    func_dump_profile(fd);
1697 	    fclose(fd);
1698 	}
1699     }
1700 }
1701 
1702 /*
1703  * Start profiling script "fp".
1704  */
1705     static void
1706 script_do_profile(scriptitem_T *si)
1707 {
1708     si->sn_pr_count = 0;
1709     profile_zero(&si->sn_pr_total);
1710     profile_zero(&si->sn_pr_self);
1711 
1712     ga_init2(&si->sn_prl_ga, sizeof(sn_prl_T), 100);
1713     si->sn_prl_idx = -1;
1714     si->sn_prof_on = TRUE;
1715     si->sn_pr_nest = 0;
1716 }
1717 
1718 /*
1719  * Save time when starting to invoke another script or function.
1720  */
1721     void
1722 script_prof_save(
1723     proftime_T	*tm)	    /* place to store wait time */
1724 {
1725     scriptitem_T    *si;
1726 
1727     if (current_SID > 0 && current_SID <= script_items.ga_len)
1728     {
1729 	si = &SCRIPT_ITEM(current_SID);
1730 	if (si->sn_prof_on && si->sn_pr_nest++ == 0)
1731 	    profile_start(&si->sn_pr_child);
1732     }
1733     profile_get_wait(tm);
1734 }
1735 
1736 /*
1737  * Count time spent in children after invoking another script or function.
1738  */
1739     void
1740 script_prof_restore(proftime_T *tm)
1741 {
1742     scriptitem_T    *si;
1743 
1744     if (current_SID > 0 && current_SID <= script_items.ga_len)
1745     {
1746 	si = &SCRIPT_ITEM(current_SID);
1747 	if (si->sn_prof_on && --si->sn_pr_nest == 0)
1748 	{
1749 	    profile_end(&si->sn_pr_child);
1750 	    profile_sub_wait(tm, &si->sn_pr_child); /* don't count wait time */
1751 	    profile_add(&si->sn_pr_children, &si->sn_pr_child);
1752 	    profile_add(&si->sn_prl_children, &si->sn_pr_child);
1753 	}
1754     }
1755 }
1756 
1757 static proftime_T inchar_time;
1758 
1759 /*
1760  * Called when starting to wait for the user to type a character.
1761  */
1762     void
1763 prof_inchar_enter(void)
1764 {
1765     profile_start(&inchar_time);
1766 }
1767 
1768 /*
1769  * Called when finished waiting for the user to type a character.
1770  */
1771     void
1772 prof_inchar_exit(void)
1773 {
1774     profile_end(&inchar_time);
1775     profile_add(&prof_wait_time, &inchar_time);
1776 }
1777 
1778 /*
1779  * Dump the profiling results for all scripts in file "fd".
1780  */
1781     static void
1782 script_dump_profile(FILE *fd)
1783 {
1784     int		    id;
1785     scriptitem_T    *si;
1786     int		    i;
1787     FILE	    *sfd;
1788     sn_prl_T	    *pp;
1789 
1790     for (id = 1; id <= script_items.ga_len; ++id)
1791     {
1792 	si = &SCRIPT_ITEM(id);
1793 	if (si->sn_prof_on)
1794 	{
1795 	    fprintf(fd, "SCRIPT  %s\n", si->sn_name);
1796 	    if (si->sn_pr_count == 1)
1797 		fprintf(fd, "Sourced 1 time\n");
1798 	    else
1799 		fprintf(fd, "Sourced %d times\n", si->sn_pr_count);
1800 	    fprintf(fd, "Total time: %s\n", profile_msg(&si->sn_pr_total));
1801 	    fprintf(fd, " Self time: %s\n", profile_msg(&si->sn_pr_self));
1802 	    fprintf(fd, "\n");
1803 	    fprintf(fd, "count  total (s)   self (s)\n");
1804 
1805 	    sfd = mch_fopen((char *)si->sn_name, "r");
1806 	    if (sfd == NULL)
1807 		fprintf(fd, "Cannot open file!\n");
1808 	    else
1809 	    {
1810 		/* Keep going till the end of file, so that trailing
1811 		 * continuation lines are listed. */
1812 		for (i = 0; ; ++i)
1813 		{
1814 		    if (vim_fgets(IObuff, IOSIZE, sfd))
1815 			break;
1816 		    if (i < si->sn_prl_ga.ga_len
1817 				     && (pp = &PRL_ITEM(si, i))->snp_count > 0)
1818 		    {
1819 			fprintf(fd, "%5d ", pp->snp_count);
1820 			if (profile_equal(&pp->sn_prl_total, &pp->sn_prl_self))
1821 			    fprintf(fd, "           ");
1822 			else
1823 			    fprintf(fd, "%s ", profile_msg(&pp->sn_prl_total));
1824 			fprintf(fd, "%s ", profile_msg(&pp->sn_prl_self));
1825 		    }
1826 		    else
1827 			fprintf(fd, "                            ");
1828 		    fprintf(fd, "%s", IObuff);
1829 		}
1830 		fclose(sfd);
1831 	    }
1832 	    fprintf(fd, "\n");
1833 	}
1834     }
1835 }
1836 
1837 /*
1838  * Return TRUE when a function defined in the current script should be
1839  * profiled.
1840  */
1841     int
1842 prof_def_func(void)
1843 {
1844     if (current_SID > 0)
1845 	return SCRIPT_ITEM(current_SID).sn_pr_force;
1846     return FALSE;
1847 }
1848 
1849 # endif
1850 #endif
1851 
1852 /*
1853  * If 'autowrite' option set, try to write the file.
1854  * Careful: autocommands may make "buf" invalid!
1855  *
1856  * return FAIL for failure, OK otherwise
1857  */
1858     int
1859 autowrite(buf_T *buf, int forceit)
1860 {
1861     int		r;
1862     bufref_T	bufref;
1863 
1864     if (!(p_aw || p_awa) || !p_write
1865 #ifdef FEAT_QUICKFIX
1866 	    /* never autowrite a "nofile" or "nowrite" buffer */
1867 	    || bt_dontwrite(buf)
1868 #endif
1869 	    || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL)
1870 	return FAIL;
1871     set_bufref(&bufref, buf);
1872     r = buf_write_all(buf, forceit);
1873 
1874     /* Writing may succeed but the buffer still changed, e.g., when there is a
1875      * conversion error.  We do want to return FAIL then. */
1876     if (bufref_valid(&bufref) && bufIsChanged(buf))
1877 	r = FAIL;
1878     return r;
1879 }
1880 
1881 /*
1882  * flush all buffers, except the ones that are readonly
1883  */
1884     void
1885 autowrite_all(void)
1886 {
1887     buf_T	*buf;
1888 
1889     if (!(p_aw || p_awa) || !p_write)
1890 	return;
1891     FOR_ALL_BUFFERS(buf)
1892 	if (bufIsChanged(buf) && !buf->b_p_ro)
1893 	{
1894 #ifdef FEAT_AUTOCMD
1895 	    bufref_T	bufref;
1896 
1897 	    set_bufref(&bufref, buf);
1898 #endif
1899 	    (void)buf_write_all(buf, FALSE);
1900 #ifdef FEAT_AUTOCMD
1901 	    /* an autocommand may have deleted the buffer */
1902 	    if (!bufref_valid(&bufref))
1903 		buf = firstbuf;
1904 #endif
1905 	}
1906 }
1907 
1908 /*
1909  * Return TRUE if buffer was changed and cannot be abandoned.
1910  * For flags use the CCGD_ values.
1911  */
1912     int
1913 check_changed(buf_T *buf, int flags)
1914 {
1915     int		forceit = (flags & CCGD_FORCEIT);
1916 #ifdef FEAT_AUTOCMD
1917     bufref_T	bufref;
1918 
1919     set_bufref(&bufref, buf);
1920 #endif
1921 
1922     if (       !forceit
1923 	    && bufIsChanged(buf)
1924 	    && ((flags & CCGD_MULTWIN) || buf->b_nwindows <= 1)
1925 	    && (!(flags & CCGD_AW) || autowrite(buf, forceit) == FAIL))
1926     {
1927 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1928 	if ((p_confirm || cmdmod.confirm) && p_write)
1929 	{
1930 	    buf_T	*buf2;
1931 	    int		count = 0;
1932 
1933 	    if (flags & CCGD_ALLBUF)
1934 		FOR_ALL_BUFFERS(buf2)
1935 		    if (bufIsChanged(buf2)
1936 				     && (buf2->b_ffname != NULL
1937 # ifdef FEAT_BROWSE
1938 					 || cmdmod.browse
1939 # endif
1940 					))
1941 			++count;
1942 # ifdef FEAT_AUTOCMD
1943 	    if (!bufref_valid(&bufref))
1944 		/* Autocommand deleted buffer, oops!  It's not changed now. */
1945 		return FALSE;
1946 # endif
1947 	    dialog_changed(buf, count > 1);
1948 # ifdef FEAT_AUTOCMD
1949 	    if (!bufref_valid(&bufref))
1950 		/* Autocommand deleted buffer, oops!  It's not changed now. */
1951 		return FALSE;
1952 # endif
1953 	    return bufIsChanged(buf);
1954 	}
1955 #endif
1956 	if (flags & CCGD_EXCMD)
1957 	    no_write_message();
1958 	else
1959 	    no_write_message_nobang();
1960 	return TRUE;
1961     }
1962     return FALSE;
1963 }
1964 
1965 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO)
1966 
1967 #if defined(FEAT_BROWSE) || defined(PROTO)
1968 /*
1969  * When wanting to write a file without a file name, ask the user for a name.
1970  */
1971     void
1972 browse_save_fname(buf_T *buf)
1973 {
1974     if (buf->b_fname == NULL)
1975     {
1976 	char_u *fname;
1977 
1978 	fname = do_browse(BROWSE_SAVE, (char_u *)_("Save As"),
1979 						 NULL, NULL, NULL, NULL, buf);
1980 	if (fname != NULL)
1981 	{
1982 	    if (setfname(buf, fname, NULL, TRUE) == OK)
1983 		buf->b_flags |= BF_NOTEDITED;
1984 	    vim_free(fname);
1985 	}
1986     }
1987 }
1988 #endif
1989 
1990 /*
1991  * Ask the user what to do when abandoning a changed buffer.
1992  * Must check 'write' option first!
1993  */
1994     void
1995 dialog_changed(
1996     buf_T	*buf,
1997     int		checkall)	/* may abandon all changed buffers */
1998 {
1999     char_u	buff[DIALOG_MSG_SIZE];
2000     int		ret;
2001     buf_T	*buf2;
2002     exarg_T     ea;
2003 
2004     dialog_msg(buff, _("Save changes to \"%s\"?"), buf->b_fname);
2005     if (checkall)
2006 	ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1);
2007     else
2008 	ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
2009 
2010     /* Init ea pseudo-structure, this is needed for the check_overwrite()
2011      * function. */
2012     ea.append = ea.forceit = FALSE;
2013 
2014     if (ret == VIM_YES)
2015     {
2016 #ifdef FEAT_BROWSE
2017 	/* May get file name, when there is none */
2018 	browse_save_fname(buf);
2019 #endif
2020 	if (buf->b_fname != NULL && check_overwrite(&ea, buf,
2021 				    buf->b_fname, buf->b_ffname, FALSE) == OK)
2022 	    /* didn't hit Cancel */
2023 	    (void)buf_write_all(buf, FALSE);
2024     }
2025     else if (ret == VIM_NO)
2026     {
2027 	unchanged(buf, TRUE);
2028     }
2029     else if (ret == VIM_ALL)
2030     {
2031 	/*
2032 	 * Write all modified files that can be written.
2033 	 * Skip readonly buffers, these need to be confirmed
2034 	 * individually.
2035 	 */
2036 	FOR_ALL_BUFFERS(buf2)
2037 	{
2038 	    if (bufIsChanged(buf2)
2039 		    && (buf2->b_ffname != NULL
2040 #ifdef FEAT_BROWSE
2041 			|| cmdmod.browse
2042 #endif
2043 			)
2044 		    && !buf2->b_p_ro)
2045 	    {
2046 #ifdef FEAT_AUTOCMD
2047 		bufref_T bufref;
2048 
2049 		set_bufref(&bufref, buf2);
2050 #endif
2051 #ifdef FEAT_BROWSE
2052 		/* May get file name, when there is none */
2053 		browse_save_fname(buf2);
2054 #endif
2055 		if (buf2->b_fname != NULL && check_overwrite(&ea, buf2,
2056 				  buf2->b_fname, buf2->b_ffname, FALSE) == OK)
2057 		    /* didn't hit Cancel */
2058 		    (void)buf_write_all(buf2, FALSE);
2059 #ifdef FEAT_AUTOCMD
2060 		/* an autocommand may have deleted the buffer */
2061 		if (!bufref_valid(&bufref))
2062 		    buf2 = firstbuf;
2063 #endif
2064 	    }
2065 	}
2066     }
2067     else if (ret == VIM_DISCARDALL)
2068     {
2069 	/*
2070 	 * mark all buffers as unchanged
2071 	 */
2072 	FOR_ALL_BUFFERS(buf2)
2073 	    unchanged(buf2, TRUE);
2074     }
2075 }
2076 #endif
2077 
2078 /*
2079  * Return TRUE if the buffer "buf" can be abandoned, either by making it
2080  * hidden, autowriting it or unloading it.
2081  */
2082     int
2083 can_abandon(buf_T *buf, int forceit)
2084 {
2085     return (	   buf_hide(buf)
2086 		|| !bufIsChanged(buf)
2087 		|| buf->b_nwindows > 1
2088 		|| autowrite(buf, forceit) == OK
2089 		|| forceit);
2090 }
2091 
2092 static void add_bufnum(int *bufnrs, int *bufnump, int nr);
2093 
2094 /*
2095  * Add a buffer number to "bufnrs", unless it's already there.
2096  */
2097     static void
2098 add_bufnum(int *bufnrs, int *bufnump, int nr)
2099 {
2100     int i;
2101 
2102     for (i = 0; i < *bufnump; ++i)
2103 	if (bufnrs[i] == nr)
2104 	    return;
2105     bufnrs[*bufnump] = nr;
2106     *bufnump = *bufnump + 1;
2107 }
2108 
2109 /*
2110  * Return TRUE if any buffer was changed and cannot be abandoned.
2111  * That changed buffer becomes the current buffer.
2112  * When "unload" is true the current buffer is unloaded instead of making it
2113  * hidden.  This is used for ":q!".
2114  */
2115     int
2116 check_changed_any(
2117     int		hidden,		/* Only check hidden buffers */
2118     int		unload)
2119 {
2120     int		ret = FALSE;
2121     buf_T	*buf;
2122     int		save;
2123     int		i;
2124     int		bufnum = 0;
2125     int		bufcount = 0;
2126     int		*bufnrs;
2127     tabpage_T   *tp;
2128     win_T	*wp;
2129 
2130     FOR_ALL_BUFFERS(buf)
2131 	++bufcount;
2132 
2133     if (bufcount == 0)
2134 	return FALSE;
2135 
2136     bufnrs = (int *)alloc(sizeof(int) * bufcount);
2137     if (bufnrs == NULL)
2138 	return FALSE;
2139 
2140     /* curbuf */
2141     bufnrs[bufnum++] = curbuf->b_fnum;
2142     /* buf in curtab */
2143     FOR_ALL_WINDOWS(wp)
2144 	if (wp->w_buffer != curbuf)
2145 	    add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum);
2146 
2147     /* buf in other tab */
2148     FOR_ALL_TABPAGES(tp)
2149 	if (tp != curtab)
2150 	    for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next)
2151 		add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum);
2152     /* any other buf */
2153     FOR_ALL_BUFFERS(buf)
2154 	add_bufnum(bufnrs, &bufnum, buf->b_fnum);
2155 
2156     for (i = 0; i < bufnum; ++i)
2157     {
2158 	buf = buflist_findnr(bufnrs[i]);
2159 	if (buf == NULL)
2160 	    continue;
2161 	if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf))
2162 	{
2163 	    bufref_T bufref;
2164 
2165 	    set_bufref(&bufref, buf);
2166 	    /* Try auto-writing the buffer.  If this fails but the buffer no
2167 	    * longer exists it's not changed, that's OK. */
2168 	    if (check_changed(buf, (p_awa ? CCGD_AW : 0)
2169 				 | CCGD_MULTWIN
2170 				 | CCGD_ALLBUF) && bufref_valid(&bufref))
2171 		break;	    /* didn't save - still changes */
2172 	}
2173     }
2174 
2175     if (i >= bufnum)
2176 	goto theend;
2177 
2178     ret = TRUE;
2179     exiting = FALSE;
2180 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
2181     /*
2182      * When ":confirm" used, don't give an error message.
2183      */
2184     if (!(p_confirm || cmdmod.confirm))
2185 #endif
2186     {
2187 	/* There must be a wait_return for this message, do_buffer()
2188 	 * may cause a redraw.  But wait_return() is a no-op when vgetc()
2189 	 * is busy (Quit used from window menu), then make sure we don't
2190 	 * cause a scroll up. */
2191 	if (vgetc_busy > 0)
2192 	{
2193 	    msg_row = cmdline_row;
2194 	    msg_col = 0;
2195 	    msg_didout = FALSE;
2196 	}
2197 	if (
2198 #ifdef FEAT_TERMINAL
2199 		term_job_running(buf->b_term)
2200 		    ? EMSG2(_("E947: Job still running in buffer \"%s\""),
2201 								  buf->b_fname)
2202 		    :
2203 #endif
2204 		EMSG2(_("E162: No write since last change for buffer \"%s\""),
2205 		    buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname))
2206 	{
2207 	    save = no_wait_return;
2208 	    no_wait_return = FALSE;
2209 	    wait_return(FALSE);
2210 	    no_wait_return = save;
2211 	}
2212     }
2213 
2214     /* Try to find a window that contains the buffer. */
2215     if (buf != curbuf)
2216 	FOR_ALL_TAB_WINDOWS(tp, wp)
2217 	    if (wp->w_buffer == buf)
2218 	    {
2219 #ifdef FEAT_AUTOCMD
2220 		bufref_T bufref;
2221 
2222 		set_bufref(&bufref, buf);
2223 #endif
2224 		goto_tabpage_win(tp, wp);
2225 #ifdef FEAT_AUTOCMD
2226 		/* Paranoia: did autocms wipe out the buffer with changes? */
2227 		if (!bufref_valid(&bufref))
2228 		{
2229 		    goto theend;
2230 		}
2231 #endif
2232 		goto buf_found;
2233 	    }
2234 buf_found:
2235 
2236     /* Open the changed buffer in the current window. */
2237     if (buf != curbuf)
2238 	set_curbuf(buf, unload ? DOBUF_UNLOAD : DOBUF_GOTO);
2239 
2240 theend:
2241     vim_free(bufnrs);
2242     return ret;
2243 }
2244 
2245 /*
2246  * return FAIL if there is no file name, OK if there is one
2247  * give error message for FAIL
2248  */
2249     int
2250 check_fname(void)
2251 {
2252     if (curbuf->b_ffname == NULL)
2253     {
2254 	EMSG(_(e_noname));
2255 	return FAIL;
2256     }
2257     return OK;
2258 }
2259 
2260 /*
2261  * flush the contents of a buffer, unless it has no file name
2262  *
2263  * return FAIL for failure, OK otherwise
2264  */
2265     int
2266 buf_write_all(buf_T *buf, int forceit)
2267 {
2268     int	    retval;
2269 #ifdef FEAT_AUTOCMD
2270     buf_T	*old_curbuf = curbuf;
2271 #endif
2272 
2273     retval = (buf_write(buf, buf->b_ffname, buf->b_fname,
2274 				   (linenr_T)1, buf->b_ml.ml_line_count, NULL,
2275 						  FALSE, forceit, TRUE, FALSE));
2276 #ifdef FEAT_AUTOCMD
2277     if (curbuf != old_curbuf)
2278     {
2279 	msg_source(HL_ATTR(HLF_W));
2280 	MSG(_("Warning: Entered other buffer unexpectedly (check autocommands)"));
2281     }
2282 #endif
2283     return retval;
2284 }
2285 
2286 /*
2287  * Code to handle the argument list.
2288  */
2289 
2290 static char_u	*do_one_arg(char_u *str);
2291 static int	do_arglist(char_u *str, int what, int after);
2292 static void	alist_check_arg_idx(void);
2293 static int	editing_arg_idx(win_T *win);
2294 #ifdef FEAT_LISTCMDS
2295 static int	alist_add_list(int count, char_u **files, int after);
2296 #endif
2297 #define AL_SET	1
2298 #define AL_ADD	2
2299 #define AL_DEL	3
2300 
2301 /*
2302  * Isolate one argument, taking backticks.
2303  * Changes the argument in-place, puts a NUL after it.  Backticks remain.
2304  * Return a pointer to the start of the next argument.
2305  */
2306     static char_u *
2307 do_one_arg(char_u *str)
2308 {
2309     char_u	*p;
2310     int		inbacktick;
2311 
2312     inbacktick = FALSE;
2313     for (p = str; *str; ++str)
2314     {
2315 	/* When the backslash is used for escaping the special meaning of a
2316 	 * character we need to keep it until wildcard expansion. */
2317 	if (rem_backslash(str))
2318 	{
2319 	    *p++ = *str++;
2320 	    *p++ = *str;
2321 	}
2322 	else
2323 	{
2324 	    /* An item ends at a space not in backticks */
2325 	    if (!inbacktick && vim_isspace(*str))
2326 		break;
2327 	    if (*str == '`')
2328 		inbacktick ^= TRUE;
2329 	    *p++ = *str;
2330 	}
2331     }
2332     str = skipwhite(str);
2333     *p = NUL;
2334 
2335     return str;
2336 }
2337 
2338 /*
2339  * Separate the arguments in "str" and return a list of pointers in the
2340  * growarray "gap".
2341  */
2342     static int
2343 get_arglist(garray_T *gap, char_u *str, int escaped)
2344 {
2345     ga_init2(gap, (int)sizeof(char_u *), 20);
2346     while (*str != NUL)
2347     {
2348 	if (ga_grow(gap, 1) == FAIL)
2349 	{
2350 	    ga_clear(gap);
2351 	    return FAIL;
2352 	}
2353 	((char_u **)gap->ga_data)[gap->ga_len++] = str;
2354 
2355 	/* If str is escaped, don't handle backslashes or spaces */
2356 	if (!escaped)
2357 	    return OK;
2358 
2359 	/* Isolate one argument, change it in-place, put a NUL after it. */
2360 	str = do_one_arg(str);
2361     }
2362     return OK;
2363 }
2364 
2365 #if defined(FEAT_QUICKFIX) || defined(FEAT_SYN_HL) || defined(PROTO)
2366 /*
2367  * Parse a list of arguments (file names), expand them and return in
2368  * "fnames[fcountp]".  When "wig" is TRUE, removes files matching 'wildignore'.
2369  * Return FAIL or OK.
2370  */
2371     int
2372 get_arglist_exp(
2373     char_u	*str,
2374     int		*fcountp,
2375     char_u	***fnamesp,
2376     int		wig)
2377 {
2378     garray_T	ga;
2379     int		i;
2380 
2381     if (get_arglist(&ga, str, TRUE) == FAIL)
2382 	return FAIL;
2383     if (wig == TRUE)
2384 	i = expand_wildcards(ga.ga_len, (char_u **)ga.ga_data,
2385 					fcountp, fnamesp, EW_FILE|EW_NOTFOUND);
2386     else
2387 	i = gen_expand_wildcards(ga.ga_len, (char_u **)ga.ga_data,
2388 					fcountp, fnamesp, EW_FILE|EW_NOTFOUND);
2389 
2390     ga_clear(&ga);
2391     return i;
2392 }
2393 #endif
2394 
2395 #if defined(FEAT_GUI) || defined(FEAT_CLIENTSERVER) || defined(PROTO)
2396 /*
2397  * Redefine the argument list.
2398  */
2399     void
2400 set_arglist(char_u *str)
2401 {
2402     do_arglist(str, AL_SET, 0);
2403 }
2404 #endif
2405 
2406 /*
2407  * "what" == AL_SET: Redefine the argument list to 'str'.
2408  * "what" == AL_ADD: add files in 'str' to the argument list after "after".
2409  * "what" == AL_DEL: remove files in 'str' from the argument list.
2410  *
2411  * Return FAIL for failure, OK otherwise.
2412  */
2413     static int
2414 do_arglist(
2415     char_u	*str,
2416     int		what,
2417     int		after UNUSED)		/* 0 means before first one */
2418 {
2419     garray_T	new_ga;
2420     int		exp_count;
2421     char_u	**exp_files;
2422     int		i;
2423 #ifdef FEAT_LISTCMDS
2424     char_u	*p;
2425     int		match;
2426 #endif
2427     int		arg_escaped = TRUE;
2428 
2429     /*
2430      * Set default argument for ":argadd" command.
2431      */
2432     if (what == AL_ADD && *str == NUL)
2433     {
2434 	if (curbuf->b_ffname == NULL)
2435 	    return FAIL;
2436 	str = curbuf->b_fname;
2437 	arg_escaped = FALSE;
2438     }
2439 
2440     /*
2441      * Collect all file name arguments in "new_ga".
2442      */
2443     if (get_arglist(&new_ga, str, arg_escaped) == FAIL)
2444 	return FAIL;
2445 
2446 #ifdef FEAT_LISTCMDS
2447     if (what == AL_DEL)
2448     {
2449 	regmatch_T	regmatch;
2450 	int		didone;
2451 
2452 	/*
2453 	 * Delete the items: use each item as a regexp and find a match in the
2454 	 * argument list.
2455 	 */
2456 	regmatch.rm_ic = p_fic;	/* ignore case when 'fileignorecase' is set */
2457 	for (i = 0; i < new_ga.ga_len && !got_int; ++i)
2458 	{
2459 	    p = ((char_u **)new_ga.ga_data)[i];
2460 	    p = file_pat_to_reg_pat(p, NULL, NULL, FALSE);
2461 	    if (p == NULL)
2462 		break;
2463 	    regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0);
2464 	    if (regmatch.regprog == NULL)
2465 	    {
2466 		vim_free(p);
2467 		break;
2468 	    }
2469 
2470 	    didone = FALSE;
2471 	    for (match = 0; match < ARGCOUNT; ++match)
2472 		if (vim_regexec(&regmatch, alist_name(&ARGLIST[match]),
2473 								  (colnr_T)0))
2474 		{
2475 		    didone = TRUE;
2476 		    vim_free(ARGLIST[match].ae_fname);
2477 		    mch_memmove(ARGLIST + match, ARGLIST + match + 1,
2478 			    (ARGCOUNT - match - 1) * sizeof(aentry_T));
2479 		    --ALIST(curwin)->al_ga.ga_len;
2480 		    if (curwin->w_arg_idx > match)
2481 			--curwin->w_arg_idx;
2482 		    --match;
2483 		}
2484 
2485 	    vim_regfree(regmatch.regprog);
2486 	    vim_free(p);
2487 	    if (!didone)
2488 		EMSG2(_(e_nomatch2), ((char_u **)new_ga.ga_data)[i]);
2489 	}
2490 	ga_clear(&new_ga);
2491     }
2492     else
2493 #endif
2494     {
2495 	i = expand_wildcards(new_ga.ga_len, (char_u **)new_ga.ga_data,
2496 		&exp_count, &exp_files, EW_DIR|EW_FILE|EW_ADDSLASH|EW_NOTFOUND);
2497 	ga_clear(&new_ga);
2498 	if (i == FAIL || exp_count == 0)
2499 	{
2500 	    EMSG(_(e_nomatch));
2501 	    return FAIL;
2502 	}
2503 
2504 #ifdef FEAT_LISTCMDS
2505 	if (what == AL_ADD)
2506 	{
2507 	    (void)alist_add_list(exp_count, exp_files, after);
2508 	    vim_free(exp_files);
2509 	}
2510 	else /* what == AL_SET */
2511 #endif
2512 	    alist_set(ALIST(curwin), exp_count, exp_files, FALSE, NULL, 0);
2513     }
2514 
2515     alist_check_arg_idx();
2516 
2517     return OK;
2518 }
2519 
2520 /*
2521  * Check the validity of the arg_idx for each other window.
2522  */
2523     static void
2524 alist_check_arg_idx(void)
2525 {
2526     win_T	*win;
2527     tabpage_T	*tp;
2528 
2529     FOR_ALL_TAB_WINDOWS(tp, win)
2530 	if (win->w_alist == curwin->w_alist)
2531 	    check_arg_idx(win);
2532 }
2533 
2534 /*
2535  * Return TRUE if window "win" is editing the file at the current argument
2536  * index.
2537  */
2538     static int
2539 editing_arg_idx(win_T *win)
2540 {
2541     return !(win->w_arg_idx >= WARGCOUNT(win)
2542 		|| (win->w_buffer->b_fnum
2543 				      != WARGLIST(win)[win->w_arg_idx].ae_fnum
2544 		    && (win->w_buffer->b_ffname == NULL
2545 			 || !(fullpathcmp(
2546 				 alist_name(&WARGLIST(win)[win->w_arg_idx]),
2547 				win->w_buffer->b_ffname, TRUE) & FPC_SAME))));
2548 }
2549 
2550 /*
2551  * Check if window "win" is editing the w_arg_idx file in its argument list.
2552  */
2553     void
2554 check_arg_idx(win_T *win)
2555 {
2556     if (WARGCOUNT(win) > 1 && !editing_arg_idx(win))
2557     {
2558 	/* We are not editing the current entry in the argument list.
2559 	 * Set "arg_had_last" if we are editing the last one. */
2560 	win->w_arg_idx_invalid = TRUE;
2561 	if (win->w_arg_idx != WARGCOUNT(win) - 1
2562 		&& arg_had_last == FALSE
2563 		&& ALIST(win) == &global_alist
2564 		&& GARGCOUNT > 0
2565 		&& win->w_arg_idx < GARGCOUNT
2566 		&& (win->w_buffer->b_fnum == GARGLIST[GARGCOUNT - 1].ae_fnum
2567 		    || (win->w_buffer->b_ffname != NULL
2568 			&& (fullpathcmp(alist_name(&GARGLIST[GARGCOUNT - 1]),
2569 				win->w_buffer->b_ffname, TRUE) & FPC_SAME))))
2570 	    arg_had_last = TRUE;
2571     }
2572     else
2573     {
2574 	/* We are editing the current entry in the argument list.
2575 	 * Set "arg_had_last" if it's also the last one */
2576 	win->w_arg_idx_invalid = FALSE;
2577 	if (win->w_arg_idx == WARGCOUNT(win) - 1
2578 					      && win->w_alist == &global_alist)
2579 	    arg_had_last = TRUE;
2580     }
2581 }
2582 
2583 /*
2584  * ":args", ":argslocal" and ":argsglobal".
2585  */
2586     void
2587 ex_args(exarg_T *eap)
2588 {
2589     int		i;
2590 
2591     if (eap->cmdidx != CMD_args)
2592     {
2593 #if defined(FEAT_LISTCMDS)
2594 	alist_unlink(ALIST(curwin));
2595 	if (eap->cmdidx == CMD_argglobal)
2596 	    ALIST(curwin) = &global_alist;
2597 	else /* eap->cmdidx == CMD_arglocal */
2598 	    alist_new();
2599 #else
2600 	ex_ni(eap);
2601 	return;
2602 #endif
2603     }
2604 
2605     if (!ends_excmd(*eap->arg))
2606     {
2607 	/*
2608 	 * ":args file ..": define new argument list, handle like ":next"
2609 	 * Also for ":argslocal file .." and ":argsglobal file ..".
2610 	 */
2611 	ex_next(eap);
2612     }
2613     else
2614 #if defined(FEAT_LISTCMDS)
2615 	if (eap->cmdidx == CMD_args)
2616 #endif
2617     {
2618 	/*
2619 	 * ":args": list arguments.
2620 	 */
2621 	if (ARGCOUNT > 0)
2622 	{
2623 	    /* Overwrite the command, for a short list there is no scrolling
2624 	     * required and no wait_return(). */
2625 	    gotocmdline(TRUE);
2626 	    for (i = 0; i < ARGCOUNT; ++i)
2627 	    {
2628 		if (i == curwin->w_arg_idx)
2629 		    msg_putchar('[');
2630 		msg_outtrans(alist_name(&ARGLIST[i]));
2631 		if (i == curwin->w_arg_idx)
2632 		    msg_putchar(']');
2633 		msg_putchar(' ');
2634 	    }
2635 	}
2636     }
2637 #if defined(FEAT_LISTCMDS)
2638     else if (eap->cmdidx == CMD_arglocal)
2639     {
2640 	garray_T	*gap = &curwin->w_alist->al_ga;
2641 
2642 	/*
2643 	 * ":argslocal": make a local copy of the global argument list.
2644 	 */
2645 	if (ga_grow(gap, GARGCOUNT) == OK)
2646 	    for (i = 0; i < GARGCOUNT; ++i)
2647 		if (GARGLIST[i].ae_fname != NULL)
2648 		{
2649 		    AARGLIST(curwin->w_alist)[gap->ga_len].ae_fname =
2650 					    vim_strsave(GARGLIST[i].ae_fname);
2651 		    AARGLIST(curwin->w_alist)[gap->ga_len].ae_fnum =
2652 							  GARGLIST[i].ae_fnum;
2653 		    ++gap->ga_len;
2654 		}
2655     }
2656 #endif
2657 }
2658 
2659 /*
2660  * ":previous", ":sprevious", ":Next" and ":sNext".
2661  */
2662     void
2663 ex_previous(exarg_T *eap)
2664 {
2665     /* If past the last one already, go to the last one. */
2666     if (curwin->w_arg_idx - (int)eap->line2 >= ARGCOUNT)
2667 	do_argfile(eap, ARGCOUNT - 1);
2668     else
2669 	do_argfile(eap, curwin->w_arg_idx - (int)eap->line2);
2670 }
2671 
2672 /*
2673  * ":rewind", ":first", ":sfirst" and ":srewind".
2674  */
2675     void
2676 ex_rewind(exarg_T *eap)
2677 {
2678     do_argfile(eap, 0);
2679 }
2680 
2681 /*
2682  * ":last" and ":slast".
2683  */
2684     void
2685 ex_last(exarg_T *eap)
2686 {
2687     do_argfile(eap, ARGCOUNT - 1);
2688 }
2689 
2690 /*
2691  * ":argument" and ":sargument".
2692  */
2693     void
2694 ex_argument(exarg_T *eap)
2695 {
2696     int		i;
2697 
2698     if (eap->addr_count > 0)
2699 	i = eap->line2 - 1;
2700     else
2701 	i = curwin->w_arg_idx;
2702     do_argfile(eap, i);
2703 }
2704 
2705 /*
2706  * Edit file "argn" of the argument lists.
2707  */
2708     void
2709 do_argfile(exarg_T *eap, int argn)
2710 {
2711     int		other;
2712     char_u	*p;
2713     int		old_arg_idx = curwin->w_arg_idx;
2714 
2715     if (argn < 0 || argn >= ARGCOUNT)
2716     {
2717 	if (ARGCOUNT <= 1)
2718 	    EMSG(_("E163: There is only one file to edit"));
2719 	else if (argn < 0)
2720 	    EMSG(_("E164: Cannot go before first file"));
2721 	else
2722 	    EMSG(_("E165: Cannot go beyond last file"));
2723     }
2724     else
2725     {
2726 	setpcmark();
2727 #ifdef FEAT_GUI
2728 	need_mouse_correct = TRUE;
2729 #endif
2730 
2731 	/* split window or create new tab page first */
2732 	if (*eap->cmd == 's' || cmdmod.tab != 0)
2733 	{
2734 	    if (win_split(0, 0) == FAIL)
2735 		return;
2736 	    RESET_BINDING(curwin);
2737 	}
2738 	else
2739 	{
2740 	    /*
2741 	     * if 'hidden' set, only check for changed file when re-editing
2742 	     * the same buffer
2743 	     */
2744 	    other = TRUE;
2745 	    if (buf_hide(curbuf))
2746 	    {
2747 		p = fix_fname(alist_name(&ARGLIST[argn]));
2748 		other = otherfile(p);
2749 		vim_free(p);
2750 	    }
2751 	    if ((!buf_hide(curbuf) || !other)
2752 		  && check_changed(curbuf, CCGD_AW
2753 					 | (other ? 0 : CCGD_MULTWIN)
2754 					 | (eap->forceit ? CCGD_FORCEIT : 0)
2755 					 | CCGD_EXCMD))
2756 		return;
2757 	}
2758 
2759 	curwin->w_arg_idx = argn;
2760 	if (argn == ARGCOUNT - 1 && curwin->w_alist == &global_alist)
2761 	    arg_had_last = TRUE;
2762 
2763 	/* Edit the file; always use the last known line number.
2764 	 * When it fails (e.g. Abort for already edited file) restore the
2765 	 * argument index. */
2766 	if (do_ecmd(0, alist_name(&ARGLIST[curwin->w_arg_idx]), NULL,
2767 		      eap, ECMD_LAST,
2768 		      (buf_hide(curwin->w_buffer) ? ECMD_HIDE : 0)
2769 			 + (eap->forceit ? ECMD_FORCEIT : 0), curwin) == FAIL)
2770 	    curwin->w_arg_idx = old_arg_idx;
2771 	/* like Vi: set the mark where the cursor is in the file. */
2772 	else if (eap->cmdidx != CMD_argdo)
2773 	    setmark('\'');
2774     }
2775 }
2776 
2777 /*
2778  * ":next", and commands that behave like it.
2779  */
2780     void
2781 ex_next(exarg_T *eap)
2782 {
2783     int		i;
2784 
2785     /*
2786      * check for changed buffer now, if this fails the argument list is not
2787      * redefined.
2788      */
2789     if (       buf_hide(curbuf)
2790 	    || eap->cmdidx == CMD_snext
2791 	    || !check_changed(curbuf, CCGD_AW
2792 				    | (eap->forceit ? CCGD_FORCEIT : 0)
2793 				    | CCGD_EXCMD))
2794     {
2795 	if (*eap->arg != NUL)		    /* redefine file list */
2796 	{
2797 	    if (do_arglist(eap->arg, AL_SET, 0) == FAIL)
2798 		return;
2799 	    i = 0;
2800 	}
2801 	else
2802 	    i = curwin->w_arg_idx + (int)eap->line2;
2803 	do_argfile(eap, i);
2804     }
2805 }
2806 
2807 #if defined(FEAT_LISTCMDS) || defined(PROTO)
2808 /*
2809  * ":argedit"
2810  */
2811     void
2812 ex_argedit(exarg_T *eap)
2813 {
2814     int i = eap->addr_count ? (int)eap->line2 : curwin->w_arg_idx + 1;
2815 
2816     if (do_arglist(eap->arg, AL_ADD, i) == FAIL)
2817 	return;
2818 #ifdef FEAT_TITLE
2819     maketitle();
2820 #endif
2821 
2822     if (curwin->w_arg_idx == 0 && (curbuf->b_ml.ml_flags & ML_EMPTY)
2823 	    && curbuf->b_ffname == NULL)
2824 	i = 0;
2825     /* Edit the argument. */
2826     if (i < ARGCOUNT)
2827 	do_argfile(eap, i);
2828 }
2829 
2830 /*
2831  * ":argadd"
2832  */
2833     void
2834 ex_argadd(exarg_T *eap)
2835 {
2836     do_arglist(eap->arg, AL_ADD,
2837 	       eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
2838 #ifdef FEAT_TITLE
2839     maketitle();
2840 #endif
2841 }
2842 
2843 /*
2844  * ":argdelete"
2845  */
2846     void
2847 ex_argdelete(exarg_T *eap)
2848 {
2849     int		i;
2850     int		n;
2851 
2852     if (eap->addr_count > 0)
2853     {
2854 	/* ":1,4argdel": Delete all arguments in the range. */
2855 	if (eap->line2 > ARGCOUNT)
2856 	    eap->line2 = ARGCOUNT;
2857 	n = eap->line2 - eap->line1 + 1;
2858 	if (*eap->arg != NUL)
2859 	    /* Can't have both a range and an argument. */
2860 	    EMSG(_(e_invarg));
2861 	else if (n <= 0)
2862 	{
2863 	    /* Don't give an error for ":%argdel" if the list is empty. */
2864 	    if (eap->line1 != 1 || eap->line2 != 0)
2865 		EMSG(_(e_invrange));
2866 	}
2867 	else
2868 	{
2869 	    for (i = eap->line1; i <= eap->line2; ++i)
2870 		vim_free(ARGLIST[i - 1].ae_fname);
2871 	    mch_memmove(ARGLIST + eap->line1 - 1, ARGLIST + eap->line2,
2872 			(size_t)((ARGCOUNT - eap->line2) * sizeof(aentry_T)));
2873 	    ALIST(curwin)->al_ga.ga_len -= n;
2874 	    if (curwin->w_arg_idx >= eap->line2)
2875 		curwin->w_arg_idx -= n;
2876 	    else if (curwin->w_arg_idx > eap->line1)
2877 		curwin->w_arg_idx = eap->line1;
2878 	    if (ARGCOUNT == 0)
2879 		curwin->w_arg_idx = 0;
2880 	    else if (curwin->w_arg_idx >= ARGCOUNT)
2881 		curwin->w_arg_idx = ARGCOUNT - 1;
2882 	}
2883     }
2884     else if (*eap->arg == NUL)
2885 	EMSG(_(e_argreq));
2886     else
2887 	do_arglist(eap->arg, AL_DEL, 0);
2888 #ifdef FEAT_TITLE
2889     maketitle();
2890 #endif
2891 }
2892 
2893 /*
2894  * ":argdo", ":windo", ":bufdo", ":tabdo", ":cdo", ":ldo", ":cfdo" and ":lfdo"
2895  */
2896     void
2897 ex_listdo(exarg_T *eap)
2898 {
2899     int		i;
2900     win_T	*wp;
2901     tabpage_T	*tp;
2902     buf_T	*buf = curbuf;
2903     int		next_fnum = 0;
2904 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2905     char_u	*save_ei = NULL;
2906 #endif
2907     char_u	*p_shm_save;
2908 #ifdef FEAT_QUICKFIX
2909     int		qf_size = 0;
2910     int		qf_idx;
2911 #endif
2912 
2913 #ifndef FEAT_QUICKFIX
2914     if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo ||
2915 	    eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
2916     {
2917 	ex_ni(eap);
2918 	return;
2919     }
2920 #endif
2921 
2922 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2923     if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo)
2924 	/* Don't do syntax HL autocommands.  Skipping the syntax file is a
2925 	 * great speed improvement. */
2926 	save_ei = au_event_disable(",Syntax");
2927 #endif
2928 #ifdef FEAT_CLIPBOARD
2929     start_global_changes();
2930 #endif
2931 
2932     if (eap->cmdidx == CMD_windo
2933 	    || eap->cmdidx == CMD_tabdo
2934 	    || buf_hide(curbuf)
2935 	    || !check_changed(curbuf, CCGD_AW
2936 				    | (eap->forceit ? CCGD_FORCEIT : 0)
2937 				    | CCGD_EXCMD))
2938     {
2939 	i = 0;
2940 	/* start at the eap->line1 argument/window/buffer */
2941 	wp = firstwin;
2942 	tp = first_tabpage;
2943 	switch (eap->cmdidx)
2944 	{
2945 	    case CMD_windo:
2946 		for ( ; wp != NULL && i + 1 < eap->line1; wp = wp->w_next)
2947 		    i++;
2948 		break;
2949 	    case CMD_tabdo:
2950 		for( ; tp != NULL && i + 1 < eap->line1; tp = tp->tp_next)
2951 		    i++;
2952 		break;
2953 	    case CMD_argdo:
2954 		i = eap->line1 - 1;
2955 		break;
2956 	    default:
2957 		break;
2958 	}
2959 	/* set pcmark now */
2960 	if (eap->cmdidx == CMD_bufdo)
2961 	{
2962 	    /* Advance to the first listed buffer after "eap->line1". */
2963 	    for (buf = firstbuf; buf != NULL && (buf->b_fnum < eap->line1
2964 					  || !buf->b_p_bl); buf = buf->b_next)
2965 		if (buf->b_fnum > eap->line2)
2966 		{
2967 		    buf = NULL;
2968 		    break;
2969 		}
2970 	    if (buf != NULL)
2971 		goto_buffer(eap, DOBUF_FIRST, FORWARD, buf->b_fnum);
2972 	}
2973 #ifdef FEAT_QUICKFIX
2974 	else if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo
2975 		|| eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
2976 	{
2977 	    qf_size = qf_get_size(eap);
2978 	    if (qf_size <= 0 || eap->line1 > qf_size)
2979 		buf = NULL;
2980 	    else
2981 	    {
2982 		ex_cc(eap);
2983 
2984 		buf = curbuf;
2985 		i = eap->line1 - 1;
2986 		if (eap->addr_count <= 0)
2987 		    /* default is all the quickfix/location list entries */
2988 		    eap->line2 = qf_size;
2989 	    }
2990 	}
2991 #endif
2992 	else
2993 	    setpcmark();
2994 	listcmd_busy = TRUE;	    /* avoids setting pcmark below */
2995 
2996 	while (!got_int && buf != NULL)
2997 	{
2998 	    if (eap->cmdidx == CMD_argdo)
2999 	    {
3000 		/* go to argument "i" */
3001 		if (i == ARGCOUNT)
3002 		    break;
3003 		/* Don't call do_argfile() when already there, it will try
3004 		 * reloading the file. */
3005 		if (curwin->w_arg_idx != i || !editing_arg_idx(curwin))
3006 		{
3007 		    /* Clear 'shm' to avoid that the file message overwrites
3008 		     * any output from the command. */
3009 		    p_shm_save = vim_strsave(p_shm);
3010 		    set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
3011 		    do_argfile(eap, i);
3012 		    set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
3013 		    vim_free(p_shm_save);
3014 		}
3015 		if (curwin->w_arg_idx != i)
3016 		    break;
3017 	    }
3018 	    else if (eap->cmdidx == CMD_windo)
3019 	    {
3020 		/* go to window "wp" */
3021 		if (!win_valid(wp))
3022 		    break;
3023 		win_goto(wp);
3024 		if (curwin != wp)
3025 		    break;  /* something must be wrong */
3026 		wp = curwin->w_next;
3027 	    }
3028 	    else if (eap->cmdidx == CMD_tabdo)
3029 	    {
3030 		/* go to window "tp" */
3031 		if (!valid_tabpage(tp))
3032 		    break;
3033 		goto_tabpage_tp(tp, TRUE, TRUE);
3034 		tp = tp->tp_next;
3035 	    }
3036 	    else if (eap->cmdidx == CMD_bufdo)
3037 	    {
3038 		/* Remember the number of the next listed buffer, in case
3039 		 * ":bwipe" is used or autocommands do something strange. */
3040 		next_fnum = -1;
3041 		for (buf = curbuf->b_next; buf != NULL; buf = buf->b_next)
3042 		    if (buf->b_p_bl)
3043 		    {
3044 			next_fnum = buf->b_fnum;
3045 			break;
3046 		    }
3047 	    }
3048 
3049 	    ++i;
3050 
3051 	    /* execute the command */
3052 	    do_cmdline(eap->arg, eap->getline, eap->cookie,
3053 						DOCMD_VERBOSE + DOCMD_NOWAIT);
3054 
3055 	    if (eap->cmdidx == CMD_bufdo)
3056 	    {
3057 		/* Done? */
3058 		if (next_fnum < 0 || next_fnum > eap->line2)
3059 		    break;
3060 		/* Check if the buffer still exists. */
3061 		FOR_ALL_BUFFERS(buf)
3062 		    if (buf->b_fnum == next_fnum)
3063 			break;
3064 		if (buf == NULL)
3065 		    break;
3066 
3067 		/* Go to the next buffer.  Clear 'shm' to avoid that the file
3068 		 * message overwrites any output from the command. */
3069 		p_shm_save = vim_strsave(p_shm);
3070 		set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
3071 		goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
3072 		set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
3073 		vim_free(p_shm_save);
3074 
3075 		/* If autocommands took us elsewhere, quit here. */
3076 		if (curbuf->b_fnum != next_fnum)
3077 		    break;
3078 	    }
3079 
3080 #ifdef FEAT_QUICKFIX
3081 	    if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo
3082 		    || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
3083 	    {
3084 		if (i >= qf_size || i >= eap->line2)
3085 		    break;
3086 
3087 		qf_idx = qf_get_cur_idx(eap);
3088 
3089 		ex_cnext(eap);
3090 
3091 		/* If jumping to the next quickfix entry fails, quit here */
3092 		if (qf_get_cur_idx(eap) == qf_idx)
3093 		    break;
3094 	    }
3095 #endif
3096 
3097 	    if (eap->cmdidx == CMD_windo)
3098 	    {
3099 		validate_cursor();	/* cursor may have moved */
3100 #ifdef FEAT_SCROLLBIND
3101 		/* required when 'scrollbind' has been set */
3102 		if (curwin->w_p_scb)
3103 		    do_check_scrollbind(TRUE);
3104 #endif
3105 	    }
3106 
3107 	    if (eap->cmdidx == CMD_windo || eap->cmdidx == CMD_tabdo)
3108 		if (i+1 > eap->line2)
3109 		    break;
3110 	    if (eap->cmdidx == CMD_argdo && i >= eap->line2)
3111 		break;
3112 	}
3113 	listcmd_busy = FALSE;
3114     }
3115 
3116 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
3117     if (save_ei != NULL)
3118     {
3119 	au_event_restore(save_ei);
3120 	apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
3121 					       curbuf->b_fname, TRUE, curbuf);
3122     }
3123 #endif
3124 #ifdef FEAT_CLIPBOARD
3125     end_global_changes();
3126 #endif
3127 }
3128 
3129 /*
3130  * Add files[count] to the arglist of the current window after arg "after".
3131  * The file names in files[count] must have been allocated and are taken over.
3132  * Files[] itself is not taken over.
3133  * Returns index of first added argument.  Returns -1 when failed (out of mem).
3134  */
3135     static int
3136 alist_add_list(
3137     int		count,
3138     char_u	**files,
3139     int		after)	    /* where to add: 0 = before first one */
3140 {
3141     int		i;
3142     int		old_argcount = ARGCOUNT;
3143 
3144     if (ga_grow(&ALIST(curwin)->al_ga, count) == OK)
3145     {
3146 	if (after < 0)
3147 	    after = 0;
3148 	if (after > ARGCOUNT)
3149 	    after = ARGCOUNT;
3150 	if (after < ARGCOUNT)
3151 	    mch_memmove(&(ARGLIST[after + count]), &(ARGLIST[after]),
3152 				       (ARGCOUNT - after) * sizeof(aentry_T));
3153 	for (i = 0; i < count; ++i)
3154 	{
3155 	    ARGLIST[after + i].ae_fname = files[i];
3156 	    ARGLIST[after + i].ae_fnum = buflist_add(files[i], BLN_LISTED);
3157 	}
3158 	ALIST(curwin)->al_ga.ga_len += count;
3159 	if (old_argcount > 0 && curwin->w_arg_idx >= after)
3160 	    curwin->w_arg_idx += count;
3161 	return after;
3162     }
3163 
3164     for (i = 0; i < count; ++i)
3165 	vim_free(files[i]);
3166     return -1;
3167 }
3168 
3169 #endif /* FEAT_LISTCMDS */
3170 
3171 #ifdef FEAT_EVAL
3172 /*
3173  * ":compiler[!] {name}"
3174  */
3175     void
3176 ex_compiler(exarg_T *eap)
3177 {
3178     char_u	*buf;
3179     char_u	*old_cur_comp = NULL;
3180     char_u	*p;
3181 
3182     if (*eap->arg == NUL)
3183     {
3184 	/* List all compiler scripts. */
3185 	do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')");
3186 					/* ) keep the indenter happy... */
3187     }
3188     else
3189     {
3190 	buf = alloc((unsigned)(STRLEN(eap->arg) + 14));
3191 	if (buf != NULL)
3192 	{
3193 	    if (eap->forceit)
3194 	    {
3195 		/* ":compiler! {name}" sets global options */
3196 		do_cmdline_cmd((char_u *)
3197 				   "command -nargs=* CompilerSet set <args>");
3198 	    }
3199 	    else
3200 	    {
3201 		/* ":compiler! {name}" sets local options.
3202 		 * To remain backwards compatible "current_compiler" is always
3203 		 * used.  A user's compiler plugin may set it, the distributed
3204 		 * plugin will then skip the settings.  Afterwards set
3205 		 * "b:current_compiler" and restore "current_compiler".
3206 		 * Explicitly prepend "g:" to make it work in a function. */
3207 		old_cur_comp = get_var_value((char_u *)"g:current_compiler");
3208 		if (old_cur_comp != NULL)
3209 		    old_cur_comp = vim_strsave(old_cur_comp);
3210 		do_cmdline_cmd((char_u *)
3211 			      "command -nargs=* CompilerSet setlocal <args>");
3212 	    }
3213 	    do_unlet((char_u *)"g:current_compiler", TRUE);
3214 	    do_unlet((char_u *)"b:current_compiler", TRUE);
3215 
3216 	    sprintf((char *)buf, "compiler/%s.vim", eap->arg);
3217 	    if (source_runtime(buf, DIP_ALL) == FAIL)
3218 		EMSG2(_("E666: compiler not supported: %s"), eap->arg);
3219 	    vim_free(buf);
3220 
3221 	    do_cmdline_cmd((char_u *)":delcommand CompilerSet");
3222 
3223 	    /* Set "b:current_compiler" from "current_compiler". */
3224 	    p = get_var_value((char_u *)"g:current_compiler");
3225 	    if (p != NULL)
3226 		set_internal_string_var((char_u *)"b:current_compiler", p);
3227 
3228 	    /* Restore "current_compiler" for ":compiler {name}". */
3229 	    if (!eap->forceit)
3230 	    {
3231 		if (old_cur_comp != NULL)
3232 		{
3233 		    set_internal_string_var((char_u *)"g:current_compiler",
3234 								old_cur_comp);
3235 		    vim_free(old_cur_comp);
3236 		}
3237 		else
3238 		    do_unlet((char_u *)"g:current_compiler", TRUE);
3239 	    }
3240 	}
3241     }
3242 }
3243 #endif
3244 
3245 /*
3246  * ":runtime [what] {name}"
3247  */
3248     void
3249 ex_runtime(exarg_T *eap)
3250 {
3251     char_u  *arg = eap->arg;
3252     char_u  *p = skiptowhite(arg);
3253     int	    len = (int)(p - arg);
3254     int	    flags = eap->forceit ? DIP_ALL : 0;
3255 
3256     if (STRNCMP(arg, "START", len) == 0)
3257     {
3258 	flags += DIP_START + DIP_NORTP;
3259 	arg = skipwhite(arg + len);
3260     }
3261     else if (STRNCMP(arg, "OPT", len) == 0)
3262     {
3263 	flags += DIP_OPT + DIP_NORTP;
3264 	arg = skipwhite(arg + len);
3265     }
3266     else if (STRNCMP(arg, "PACK", len) == 0)
3267     {
3268 	flags += DIP_START + DIP_OPT + DIP_NORTP;
3269 	arg = skipwhite(arg + len);
3270     }
3271     else if (STRNCMP(arg, "ALL", len) == 0)
3272     {
3273 	flags += DIP_START + DIP_OPT;
3274 	arg = skipwhite(arg + len);
3275     }
3276 
3277     source_runtime(arg, flags);
3278 }
3279 
3280     static void
3281 source_callback(char_u *fname, void *cookie UNUSED)
3282 {
3283     (void)do_source(fname, FALSE, DOSO_NONE);
3284 }
3285 
3286 /*
3287  * Find the file "name" in all directories in "path" and invoke
3288  * "callback(fname, cookie)".
3289  * "name" can contain wildcards.
3290  * When "flags" has DIP_ALL: source all files, otherwise only the first one.
3291  * When "flags" has DIP_DIR: find directories instead of files.
3292  * When "flags" has DIP_ERR: give an error message if there is no match.
3293  *
3294  * return FAIL when no file could be sourced, OK otherwise.
3295  */
3296     int
3297 do_in_path(
3298     char_u	*path,
3299     char_u	*name,
3300     int		flags,
3301     void	(*callback)(char_u *fname, void *ck),
3302     void	*cookie)
3303 {
3304     char_u	*rtp;
3305     char_u	*np;
3306     char_u	*buf;
3307     char_u	*rtp_copy;
3308     char_u	*tail;
3309     int		num_files;
3310     char_u	**files;
3311     int		i;
3312     int		did_one = FALSE;
3313 #ifdef AMIGA
3314     struct Process	*proc = (struct Process *)FindTask(0L);
3315     APTR		save_winptr = proc->pr_WindowPtr;
3316 
3317     /* Avoid a requester here for a volume that doesn't exist. */
3318     proc->pr_WindowPtr = (APTR)-1L;
3319 #endif
3320 
3321     /* Make a copy of 'runtimepath'.  Invoking the callback may change the
3322      * value. */
3323     rtp_copy = vim_strsave(path);
3324     buf = alloc(MAXPATHL);
3325     if (buf != NULL && rtp_copy != NULL)
3326     {
3327 	if (p_verbose > 1 && name != NULL)
3328 	{
3329 	    verbose_enter();
3330 	    smsg((char_u *)_("Searching for \"%s\" in \"%s\""),
3331 						 (char *)name, (char *)path);
3332 	    verbose_leave();
3333 	}
3334 
3335 	/* Loop over all entries in 'runtimepath'. */
3336 	rtp = rtp_copy;
3337 	while (*rtp != NUL && ((flags & DIP_ALL) || !did_one))
3338 	{
3339 	    size_t buflen;
3340 
3341 	    /* Copy the path from 'runtimepath' to buf[]. */
3342 	    copy_option_part(&rtp, buf, MAXPATHL, ",");
3343 	    buflen = STRLEN(buf);
3344 
3345 	    /* Skip after or non-after directories. */
3346 	    if (flags & (DIP_NOAFTER | DIP_AFTER))
3347 	    {
3348 		int is_after = buflen >= 5
3349 				     && STRCMP(buf + buflen - 5, "after") == 0;
3350 
3351 		if ((is_after && (flags & DIP_NOAFTER))
3352 			|| (!is_after && (flags & DIP_AFTER)))
3353 		    continue;
3354 	    }
3355 
3356 	    if (name == NULL)
3357 	    {
3358 		(*callback)(buf, (void *) &cookie);
3359 		if (!did_one)
3360 		    did_one = (cookie == NULL);
3361 	    }
3362 	    else if (buflen + STRLEN(name) + 2 < MAXPATHL)
3363 	    {
3364 		add_pathsep(buf);
3365 		tail = buf + STRLEN(buf);
3366 
3367 		/* Loop over all patterns in "name" */
3368 		np = name;
3369 		while (*np != NUL && ((flags & DIP_ALL) || !did_one))
3370 		{
3371 		    /* Append the pattern from "name" to buf[]. */
3372 		    copy_option_part(&np, tail, (int)(MAXPATHL - (tail - buf)),
3373 								       "\t ");
3374 
3375 		    if (p_verbose > 2)
3376 		    {
3377 			verbose_enter();
3378 			smsg((char_u *)_("Searching for \"%s\""), buf);
3379 			verbose_leave();
3380 		    }
3381 
3382 		    /* Expand wildcards, invoke the callback for each match. */
3383 		    if (gen_expand_wildcards(1, &buf, &num_files, &files,
3384 				  (flags & DIP_DIR) ? EW_DIR : EW_FILE) == OK)
3385 		    {
3386 			for (i = 0; i < num_files; ++i)
3387 			{
3388 			    (*callback)(files[i], cookie);
3389 			    did_one = TRUE;
3390 			    if (!(flags & DIP_ALL))
3391 				break;
3392 			}
3393 			FreeWild(num_files, files);
3394 		    }
3395 		}
3396 	    }
3397 	}
3398     }
3399     vim_free(buf);
3400     vim_free(rtp_copy);
3401     if (!did_one && name != NULL)
3402     {
3403 	char *basepath = path == p_rtp ? "runtimepath" : "packpath";
3404 
3405 	if (flags & DIP_ERR)
3406 	    EMSG3(_(e_dirnotf), basepath, name);
3407 	else if (p_verbose > 0)
3408 	{
3409 	    verbose_enter();
3410 	    smsg((char_u *)_("not found in '%s': \"%s\""), basepath, name);
3411 	    verbose_leave();
3412 	}
3413     }
3414 
3415 #ifdef AMIGA
3416     proc->pr_WindowPtr = save_winptr;
3417 #endif
3418 
3419     return did_one ? OK : FAIL;
3420 }
3421 
3422 /*
3423  * Find "name" in "path".  When found, invoke the callback function for
3424  * it: callback(fname, "cookie")
3425  * When "flags" has DIP_ALL repeat for all matches, otherwise only the first
3426  * one is used.
3427  * Returns OK when at least one match found, FAIL otherwise.
3428  *
3429  * If "name" is NULL calls callback for each entry in "path". Cookie is
3430  * passed by reference in this case, setting it to NULL indicates that callback
3431  * has done its job.
3432  */
3433     static int
3434 do_in_path_and_pp(
3435     char_u	*path,
3436     char_u	*name,
3437     int		flags,
3438     void	(*callback)(char_u *fname, void *ck),
3439     void	*cookie)
3440 {
3441     int		done = FAIL;
3442     char_u	*s;
3443     int		len;
3444     char	*start_dir = "pack/*/start/*/%s";
3445     char	*opt_dir = "pack/*/opt/*/%s";
3446 
3447     if ((flags & DIP_NORTP) == 0)
3448 	done = do_in_path(path, name, flags, callback, cookie);
3449 
3450     if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_START))
3451     {
3452 	len = (int)(STRLEN(start_dir) + STRLEN(name));
3453 	s = alloc(len);
3454 	if (s == NULL)
3455 	    return FAIL;
3456 	vim_snprintf((char *)s, len, start_dir, name);
3457 	done = do_in_path(p_pp, s, flags, callback, cookie);
3458 	vim_free(s);
3459     }
3460 
3461     if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_OPT))
3462     {
3463 	len = (int)(STRLEN(opt_dir) + STRLEN(name));
3464 	s = alloc(len);
3465 	if (s == NULL)
3466 	    return FAIL;
3467 	vim_snprintf((char *)s, len, opt_dir, name);
3468 	done = do_in_path(p_pp, s, flags, callback, cookie);
3469 	vim_free(s);
3470     }
3471 
3472     return done;
3473 }
3474 
3475 /*
3476  * Just like do_in_path_and_pp(), using 'runtimepath' for "path".
3477  */
3478     int
3479 do_in_runtimepath(
3480     char_u	*name,
3481     int		flags,
3482     void	(*callback)(char_u *fname, void *ck),
3483     void	*cookie)
3484 {
3485     return do_in_path_and_pp(p_rtp, name, flags, callback, cookie);
3486 }
3487 
3488 /*
3489  * Source the file "name" from all directories in 'runtimepath'.
3490  * "name" can contain wildcards.
3491  * When "flags" has DIP_ALL: source all files, otherwise only the first one.
3492  *
3493  * return FAIL when no file could be sourced, OK otherwise.
3494  */
3495     int
3496 source_runtime(char_u *name, int flags)
3497 {
3498     return source_in_path(p_rtp, name, flags);
3499 }
3500 
3501 /*
3502  * Just like source_runtime(), but use "path" instead of 'runtimepath'.
3503  */
3504     int
3505 source_in_path(char_u *path, char_u *name, int flags)
3506 {
3507     return do_in_path_and_pp(path, name, flags, source_callback, NULL);
3508 }
3509 
3510 
3511 /*
3512  * Expand wildcards in "pat" and invoke do_source() for each match.
3513  */
3514     static void
3515 source_all_matches(char_u *pat)
3516 {
3517     int	    num_files;
3518     char_u  **files;
3519     int	    i;
3520 
3521     if (gen_expand_wildcards(1, &pat, &num_files, &files, EW_FILE) == OK)
3522     {
3523 	for (i = 0; i < num_files; ++i)
3524 	    (void)do_source(files[i], FALSE, DOSO_NONE);
3525 	FreeWild(num_files, files);
3526     }
3527 }
3528 
3529 /* used for "cookie" of add_pack_plugin() */
3530 static int APP_ADD_DIR;
3531 static int APP_LOAD;
3532 static int APP_BOTH;
3533 
3534     static void
3535 add_pack_plugin(char_u *fname, void *cookie)
3536 {
3537     char_u  *p4, *p3, *p2, *p1, *p;
3538     char_u  *insp;
3539     int	    c;
3540     char_u  *new_rtp;
3541     int	    keep;
3542     size_t  oldlen;
3543     size_t  addlen;
3544     char_u  *afterdir;
3545     size_t  afterlen = 0;
3546     char_u  *ffname = fix_fname(fname);
3547     size_t  fname_len;
3548     char_u  *buf = NULL;
3549     char_u  *rtp_ffname;
3550     int	    match;
3551 
3552     if (ffname == NULL)
3553 	return;
3554     if (cookie != &APP_LOAD && strstr((char *)p_rtp, (char *)ffname) == NULL)
3555     {
3556 	/* directory is not yet in 'runtimepath', add it */
3557 	p4 = p3 = p2 = p1 = get_past_head(ffname);
3558 	for (p = p1; *p; MB_PTR_ADV(p))
3559 	    if (vim_ispathsep_nocolon(*p))
3560 	    {
3561 		p4 = p3; p3 = p2; p2 = p1; p1 = p;
3562 	    }
3563 
3564 	/* now we have:
3565 	 * rtp/pack/name/start/name
3566 	 *    p4   p3   p2    p1
3567 	 *
3568 	 * find the part up to "pack" in 'runtimepath' */
3569 	c = *p4;
3570 	*p4 = NUL;
3571 
3572 	/* Find "ffname" in "p_rtp", ignoring '/' vs '\' differences. */
3573 	fname_len = STRLEN(ffname);
3574 	insp = p_rtp;
3575 	buf = alloc(MAXPATHL);
3576 	if (buf == NULL)
3577 	    goto theend;
3578 	while (*insp != NUL)
3579 	{
3580 	    copy_option_part(&insp, buf, MAXPATHL, ",");
3581 	    add_pathsep(buf);
3582 	    rtp_ffname = fix_fname(buf);
3583 	    if (rtp_ffname == NULL)
3584 		goto theend;
3585 	    match = vim_fnamencmp(rtp_ffname, ffname, fname_len) == 0;
3586 	    vim_free(rtp_ffname);
3587 	    if (match)
3588 		break;
3589 	}
3590 
3591 	if (*insp == NUL)
3592 	    /* not found, append at the end */
3593 	    insp = p_rtp + STRLEN(p_rtp);
3594 	else
3595 	    /* append after the matching directory. */
3596 	    --insp;
3597 	*p4 = c;
3598 
3599 	/* check if rtp/pack/name/start/name/after exists */
3600 	afterdir = concat_fnames(ffname, (char_u *)"after", TRUE);
3601 	if (afterdir != NULL && mch_isdir(afterdir))
3602 	    afterlen = STRLEN(afterdir) + 1; /* add one for comma */
3603 
3604 	oldlen = STRLEN(p_rtp);
3605 	addlen = STRLEN(ffname) + 1; /* add one for comma */
3606 	new_rtp = alloc((int)(oldlen + addlen + afterlen + 1));
3607 							  /* add one for NUL */
3608 	if (new_rtp == NULL)
3609 	    goto theend;
3610 	keep = (int)(insp - p_rtp);
3611 	mch_memmove(new_rtp, p_rtp, keep);
3612 	new_rtp[keep] = ',';
3613 	mch_memmove(new_rtp + keep + 1, ffname, addlen);
3614 	if (p_rtp[keep] != NUL)
3615 	    mch_memmove(new_rtp + keep + addlen, p_rtp + keep,
3616 							   oldlen - keep + 1);
3617 	if (afterlen > 0)
3618 	{
3619 	    STRCAT(new_rtp, ",");
3620 	    STRCAT(new_rtp, afterdir);
3621 	}
3622 	set_option_value((char_u *)"rtp", 0L, new_rtp, 0);
3623 	vim_free(new_rtp);
3624 	vim_free(afterdir);
3625     }
3626 
3627     if (cookie != &APP_ADD_DIR)
3628     {
3629 	static char *plugpat = "%s/plugin/**/*.vim";
3630 	static char *ftpat = "%s/ftdetect/*.vim";
3631 	int	    len;
3632 	char_u	    *pat;
3633 
3634 	len = (int)STRLEN(ffname) + (int)STRLEN(ftpat);
3635 	pat = alloc(len);
3636 	if (pat == NULL)
3637 	    goto theend;
3638 	vim_snprintf((char *)pat, len, plugpat, ffname);
3639 	source_all_matches(pat);
3640 
3641 #ifdef FEAT_AUTOCMD
3642 	{
3643 	    char_u *cmd = vim_strsave((char_u *)"g:did_load_filetypes");
3644 
3645 	    /* If runtime/filetype.vim wasn't loaded yet, the scripts will be
3646 	     * found when it loads. */
3647 	    if (cmd != NULL && eval_to_number(cmd) > 0)
3648 	    {
3649 		do_cmdline_cmd((char_u *)"augroup filetypedetect");
3650 		vim_snprintf((char *)pat, len, ftpat, ffname);
3651 		source_all_matches(pat);
3652 		do_cmdline_cmd((char_u *)"augroup END");
3653 	    }
3654 	    vim_free(cmd);
3655 	}
3656 #endif
3657 	vim_free(pat);
3658     }
3659 
3660 theend:
3661     vim_free(buf);
3662     vim_free(ffname);
3663 }
3664 
3665 /*
3666  * Add all packages in the "start" directory to 'runtimepath'.
3667  */
3668     void
3669 add_pack_start_dirs(void)
3670 {
3671     do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR,
3672 					       add_pack_plugin, &APP_ADD_DIR);
3673 }
3674 
3675 /*
3676  * Load plugins from all packages in the "start" directory.
3677  */
3678     void
3679 load_start_packages(void)
3680 {
3681     did_source_packages = TRUE;
3682     do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR,
3683 						  add_pack_plugin, &APP_LOAD);
3684 }
3685 
3686 /*
3687  * ":packloadall"
3688  * Find plugins in the package directories and source them.
3689  */
3690     void
3691 ex_packloadall(exarg_T *eap)
3692 {
3693     if (!did_source_packages || eap->forceit)
3694     {
3695 	/* First do a round to add all directories to 'runtimepath', then load
3696 	 * the plugins. This allows for plugins to use an autoload directory
3697 	 * of another plugin. */
3698 	add_pack_start_dirs();
3699 	load_start_packages();
3700     }
3701 }
3702 
3703 /*
3704  * ":packadd[!] {name}"
3705  */
3706     void
3707 ex_packadd(exarg_T *eap)
3708 {
3709     static char *plugpat = "pack/*/opt/%s";
3710     int		len;
3711     char	*pat;
3712 
3713     len = (int)STRLEN(plugpat) + (int)STRLEN(eap->arg);
3714     pat = (char *)alloc(len);
3715     if (pat == NULL)
3716 	return;
3717     vim_snprintf(pat, len, plugpat, eap->arg);
3718     do_in_path(p_pp, (char_u *)pat, DIP_ALL + DIP_DIR + DIP_ERR,
3719 		    add_pack_plugin, eap->forceit ? &APP_ADD_DIR : &APP_BOTH);
3720     vim_free(pat);
3721 }
3722 
3723 #if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD)
3724 /*
3725  * ":options"
3726  */
3727     void
3728 ex_options(
3729     exarg_T	*eap UNUSED)
3730 {
3731     vim_setenv((char_u *)"OPTWIN_CMD", (char_u *)(cmdmod.tab ? "tab" : ""));
3732     cmd_source((char_u *)SYS_OPTWIN_FILE, NULL);
3733 }
3734 #endif
3735 
3736 #if defined(FEAT_PYTHON3) || defined(FEAT_PYTHON) || defined(PROTO)
3737 
3738 # if (defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)) || defined(PROTO)
3739 /*
3740  * Detect Python 3 or 2, and initialize 'pyxversion'.
3741  */
3742     void
3743 init_pyxversion(void)
3744 {
3745     if (p_pyx == 0)
3746     {
3747 	if (python3_enabled(FALSE))
3748 	    p_pyx = 3;
3749 	else if (python_enabled(FALSE))
3750 	    p_pyx = 2;
3751     }
3752 }
3753 # endif
3754 
3755 /*
3756  * Does a file contain one of the following strings at the beginning of any
3757  * line?
3758  * "#!(any string)python2"  => returns 2
3759  * "#!(any string)python3"  => returns 3
3760  * "# requires python 2.x"  => returns 2
3761  * "# requires python 3.x"  => returns 3
3762  * otherwise return 0.
3763  */
3764     static int
3765 requires_py_version(char_u *filename)
3766 {
3767     FILE    *file;
3768     int	    requires_py_version = 0;
3769     int	    i, lines;
3770 
3771     lines = (int)p_mls;
3772     if (lines < 0)
3773 	lines = 5;
3774 
3775     file = mch_fopen((char *)filename, "r");
3776     if (file != NULL)
3777     {
3778 	for (i = 0; i < lines; i++)
3779 	{
3780 	    if (vim_fgets(IObuff, IOSIZE, file))
3781 		break;
3782 	    if (i == 0 && IObuff[0] == '#' && IObuff[1] == '!')
3783 	    {
3784 		/* Check shebang. */
3785 		if (strstr((char *)IObuff + 2, "python2") != NULL)
3786 		{
3787 		    requires_py_version = 2;
3788 		    break;
3789 		}
3790 		if (strstr((char *)IObuff + 2, "python3") != NULL)
3791 		{
3792 		    requires_py_version = 3;
3793 		    break;
3794 		}
3795 	    }
3796 	    IObuff[21] = '\0';
3797 	    if (STRCMP("# requires python 2.x", IObuff) == 0)
3798 	    {
3799 		requires_py_version = 2;
3800 		break;
3801 	    }
3802 	    if (STRCMP("# requires python 3.x", IObuff) == 0)
3803 	    {
3804 		requires_py_version = 3;
3805 		break;
3806 	    }
3807 	}
3808 	fclose(file);
3809     }
3810     return requires_py_version;
3811 }
3812 
3813 
3814 /*
3815  * Source a python file using the requested python version.
3816  */
3817     static void
3818 source_pyx_file(exarg_T *eap, char_u *fname)
3819 {
3820     exarg_T ex;
3821     int	    v = requires_py_version(fname);
3822 
3823 # if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
3824     init_pyxversion();
3825 # endif
3826     if (v == 0)
3827     {
3828 # if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
3829 	/* user didn't choose a preference, 'pyx' is used */
3830 	v = p_pyx;
3831 # elif defined(FEAT_PYTHON)
3832 	v = 2;
3833 # elif defined(FEAT_PYTHON3)
3834 	v = 3;
3835 # endif
3836     }
3837 
3838     /*
3839      * now source, if required python version is not supported show
3840      * unobtrusive message.
3841      */
3842     if (eap == NULL)
3843 	vim_memset(&ex, 0, sizeof(ex));
3844     else
3845 	ex = *eap;
3846     ex.arg = fname;
3847     ex.cmd = (char_u *)(v == 2 ? "pyfile" : "pyfile3");
3848 
3849     if (v == 2)
3850     {
3851 # ifdef FEAT_PYTHON
3852 	ex_pyfile(&ex);
3853 # else
3854 	vim_snprintf((char *)IObuff, IOSIZE,
3855 		_("W20: Required python version 2.x not supported, ignoring file: %s"),
3856 		fname);
3857 	MSG(IObuff);
3858 # endif
3859 	return;
3860     }
3861     else
3862     {
3863 # ifdef FEAT_PYTHON3
3864 	ex_py3file(&ex);
3865 # else
3866 	vim_snprintf((char *)IObuff, IOSIZE,
3867 		_("W21: Required python version 3.x not supported, ignoring file: %s"),
3868 		fname);
3869 	MSG(IObuff);
3870 # endif
3871 	return;
3872     }
3873 }
3874 
3875 /*
3876  * ":pyxfile {fname}"
3877  */
3878     void
3879 ex_pyxfile(exarg_T *eap)
3880 {
3881     source_pyx_file(eap, eap->arg);
3882 }
3883 
3884 /*
3885  * ":pyx"
3886  */
3887     void
3888 ex_pyx(exarg_T *eap)
3889 {
3890 # if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
3891     init_pyxversion();
3892     if (p_pyx == 2)
3893 	ex_python(eap);
3894     else
3895 	ex_py3(eap);
3896 # elif defined(FEAT_PYTHON)
3897     ex_python(eap);
3898 # elif defined(FEAT_PYTHON3)
3899     ex_py3(eap);
3900 # endif
3901 }
3902 
3903 /*
3904  * ":pyxdo"
3905  */
3906     void
3907 ex_pyxdo(exarg_T *eap)
3908 {
3909 # if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
3910     init_pyxversion();
3911     if (p_pyx == 2)
3912 	ex_pydo(eap);
3913     else
3914 	ex_py3do(eap);
3915 # elif defined(FEAT_PYTHON)
3916     ex_pydo(eap);
3917 # elif defined(FEAT_PYTHON3)
3918     ex_py3do(eap);
3919 # endif
3920 }
3921 
3922 #endif
3923 
3924 /*
3925  * ":source {fname}"
3926  */
3927     void
3928 ex_source(exarg_T *eap)
3929 {
3930 #ifdef FEAT_BROWSE
3931     if (cmdmod.browse)
3932     {
3933 	char_u *fname = NULL;
3934 
3935 	fname = do_browse(0, (char_u *)_("Source Vim script"), eap->arg,
3936 				      NULL, NULL, BROWSE_FILTER_MACROS, NULL);
3937 	if (fname != NULL)
3938 	{
3939 	    cmd_source(fname, eap);
3940 	    vim_free(fname);
3941 	}
3942     }
3943     else
3944 #endif
3945 	cmd_source(eap->arg, eap);
3946 }
3947 
3948     static void
3949 cmd_source(char_u *fname, exarg_T *eap)
3950 {
3951     if (*fname == NUL)
3952 	EMSG(_(e_argreq));
3953 
3954     else if (eap != NULL && eap->forceit)
3955 	/* ":source!": read Normal mode commands
3956 	 * Need to execute the commands directly.  This is required at least
3957 	 * for:
3958 	 * - ":g" command busy
3959 	 * - after ":argdo", ":windo" or ":bufdo"
3960 	 * - another command follows
3961 	 * - inside a loop
3962 	 */
3963 	openscript(fname, global_busy || listcmd_busy || eap->nextcmd != NULL
3964 #ifdef FEAT_EVAL
3965 						 || eap->cstack->cs_idx >= 0
3966 #endif
3967 						 );
3968 
3969     /* ":source" read ex commands */
3970     else if (do_source(fname, FALSE, DOSO_NONE) == FAIL)
3971 	EMSG2(_(e_notopen), fname);
3972 }
3973 
3974 /*
3975  * ":source" and associated commands.
3976  */
3977 /*
3978  * Structure used to store info for each sourced file.
3979  * It is shared between do_source() and getsourceline().
3980  * This is required, because it needs to be handed to do_cmdline() and
3981  * sourcing can be done recursively.
3982  */
3983 struct source_cookie
3984 {
3985     FILE	*fp;		/* opened file for sourcing */
3986     char_u      *nextline;      /* if not NULL: line that was read ahead */
3987     int		finished;	/* ":finish" used */
3988 #if defined(USE_CRNL) || defined(USE_CR)
3989     int		fileformat;	/* EOL_UNKNOWN, EOL_UNIX or EOL_DOS */
3990     int		error;		/* TRUE if LF found after CR-LF */
3991 #endif
3992 #ifdef FEAT_EVAL
3993     linenr_T	breakpoint;	/* next line with breakpoint or zero */
3994     char_u	*fname;		/* name of sourced file */
3995     int		dbg_tick;	/* debug_tick when breakpoint was set */
3996     int		level;		/* top nesting level of sourced file */
3997 #endif
3998 #ifdef FEAT_MBYTE
3999     vimconv_T	conv;		/* type of conversion */
4000 #endif
4001 };
4002 
4003 #ifdef FEAT_EVAL
4004 /*
4005  * Return the address holding the next breakpoint line for a source cookie.
4006  */
4007     linenr_T *
4008 source_breakpoint(void *cookie)
4009 {
4010     return &((struct source_cookie *)cookie)->breakpoint;
4011 }
4012 
4013 /*
4014  * Return the address holding the debug tick for a source cookie.
4015  */
4016     int *
4017 source_dbg_tick(void *cookie)
4018 {
4019     return &((struct source_cookie *)cookie)->dbg_tick;
4020 }
4021 
4022 /*
4023  * Return the nesting level for a source cookie.
4024  */
4025     int
4026 source_level(void *cookie)
4027 {
4028     return ((struct source_cookie *)cookie)->level;
4029 }
4030 #endif
4031 
4032 static char_u *get_one_sourceline(struct source_cookie *sp);
4033 
4034 #if (defined(WIN32) && defined(FEAT_CSCOPE)) || defined(HAVE_FD_CLOEXEC)
4035 # define USE_FOPEN_NOINH
4036 static FILE *fopen_noinh_readbin(char *filename);
4037 
4038 /*
4039  * Special function to open a file without handle inheritance.
4040  * When possible the handle is closed on exec().
4041  */
4042     static FILE *
4043 fopen_noinh_readbin(char *filename)
4044 {
4045 # ifdef WIN32
4046     int	fd_tmp = mch_open(filename, O_RDONLY | O_BINARY | O_NOINHERIT, 0);
4047 # else
4048     int	fd_tmp = mch_open(filename, O_RDONLY, 0);
4049 # endif
4050 
4051     if (fd_tmp == -1)
4052 	return NULL;
4053 
4054 # ifdef HAVE_FD_CLOEXEC
4055     {
4056 	int fdflags = fcntl(fd_tmp, F_GETFD);
4057 	if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0)
4058 	    (void)fcntl(fd_tmp, F_SETFD, fdflags | FD_CLOEXEC);
4059     }
4060 # endif
4061 
4062     return fdopen(fd_tmp, READBIN);
4063 }
4064 #endif
4065 
4066 
4067 /*
4068  * do_source: Read the file "fname" and execute its lines as EX commands.
4069  *
4070  * This function may be called recursively!
4071  *
4072  * return FAIL if file could not be opened, OK otherwise
4073  */
4074     int
4075 do_source(
4076     char_u	*fname,
4077     int		check_other,	    /* check for .vimrc and _vimrc */
4078     int		is_vimrc)	    /* DOSO_ value */
4079 {
4080     struct source_cookie    cookie;
4081     char_u		    *save_sourcing_name;
4082     linenr_T		    save_sourcing_lnum;
4083     char_u		    *p;
4084     char_u		    *fname_exp;
4085     char_u		    *firstline = NULL;
4086     int			    retval = FAIL;
4087 #ifdef FEAT_EVAL
4088     scid_T		    save_current_SID;
4089     static scid_T	    last_current_SID = 0;
4090     void		    *save_funccalp;
4091     int			    save_debug_break_level = debug_break_level;
4092     scriptitem_T	    *si = NULL;
4093 # ifdef UNIX
4094     stat_T		    st;
4095     int			    stat_ok;
4096 # endif
4097 #endif
4098 #ifdef STARTUPTIME
4099     struct timeval	    tv_rel;
4100     struct timeval	    tv_start;
4101 #endif
4102 #ifdef FEAT_PROFILE
4103     proftime_T		    wait_start;
4104 #endif
4105 
4106     p = expand_env_save(fname);
4107     if (p == NULL)
4108 	return retval;
4109     fname_exp = fix_fname(p);
4110     vim_free(p);
4111     if (fname_exp == NULL)
4112 	return retval;
4113     if (mch_isdir(fname_exp))
4114     {
4115 	smsg((char_u *)_("Cannot source a directory: \"%s\""), fname);
4116 	goto theend;
4117     }
4118 
4119 #ifdef FEAT_AUTOCMD
4120     /* Apply SourceCmd autocommands, they should get the file and source it. */
4121     if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL)
4122 	    && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp,
4123 							       FALSE, curbuf))
4124     {
4125 # ifdef FEAT_EVAL
4126 	retval = aborting() ? FAIL : OK;
4127 # else
4128 	retval = OK;
4129 # endif
4130 	goto theend;
4131     }
4132 
4133     /* Apply SourcePre autocommands, they may get the file. */
4134     apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, FALSE, curbuf);
4135 #endif
4136 
4137 #ifdef USE_FOPEN_NOINH
4138     cookie.fp = fopen_noinh_readbin((char *)fname_exp);
4139 #else
4140     cookie.fp = mch_fopen((char *)fname_exp, READBIN);
4141 #endif
4142     if (cookie.fp == NULL && check_other)
4143     {
4144 	/*
4145 	 * Try again, replacing file name ".vimrc" by "_vimrc" or vice versa,
4146 	 * and ".exrc" by "_exrc" or vice versa.
4147 	 */
4148 	p = gettail(fname_exp);
4149 	if ((*p == '.' || *p == '_')
4150 		&& (STRICMP(p + 1, "vimrc") == 0
4151 		    || STRICMP(p + 1, "gvimrc") == 0
4152 		    || STRICMP(p + 1, "exrc") == 0))
4153 	{
4154 	    if (*p == '_')
4155 		*p = '.';
4156 	    else
4157 		*p = '_';
4158 #ifdef USE_FOPEN_NOINH
4159 	    cookie.fp = fopen_noinh_readbin((char *)fname_exp);
4160 #else
4161 	    cookie.fp = mch_fopen((char *)fname_exp, READBIN);
4162 #endif
4163 	}
4164     }
4165 
4166     if (cookie.fp == NULL)
4167     {
4168 	if (p_verbose > 0)
4169 	{
4170 	    verbose_enter();
4171 	    if (sourcing_name == NULL)
4172 		smsg((char_u *)_("could not source \"%s\""), fname);
4173 	    else
4174 		smsg((char_u *)_("line %ld: could not source \"%s\""),
4175 							sourcing_lnum, fname);
4176 	    verbose_leave();
4177 	}
4178 	goto theend;
4179     }
4180 
4181     /*
4182      * The file exists.
4183      * - In verbose mode, give a message.
4184      * - For a vimrc file, may want to set 'compatible', call vimrc_found().
4185      */
4186     if (p_verbose > 1)
4187     {
4188 	verbose_enter();
4189 	if (sourcing_name == NULL)
4190 	    smsg((char_u *)_("sourcing \"%s\""), fname);
4191 	else
4192 	    smsg((char_u *)_("line %ld: sourcing \"%s\""),
4193 							sourcing_lnum, fname);
4194 	verbose_leave();
4195     }
4196     if (is_vimrc == DOSO_VIMRC)
4197 	vimrc_found(fname_exp, (char_u *)"MYVIMRC");
4198     else if (is_vimrc == DOSO_GVIMRC)
4199 	vimrc_found(fname_exp, (char_u *)"MYGVIMRC");
4200 
4201 #ifdef USE_CRNL
4202     /* If no automatic file format: Set default to CR-NL. */
4203     if (*p_ffs == NUL)
4204 	cookie.fileformat = EOL_DOS;
4205     else
4206 	cookie.fileformat = EOL_UNKNOWN;
4207     cookie.error = FALSE;
4208 #endif
4209 
4210 #ifdef USE_CR
4211     /* If no automatic file format: Set default to CR. */
4212     if (*p_ffs == NUL)
4213 	cookie.fileformat = EOL_MAC;
4214     else
4215 	cookie.fileformat = EOL_UNKNOWN;
4216     cookie.error = FALSE;
4217 #endif
4218 
4219     cookie.nextline = NULL;
4220     cookie.finished = FALSE;
4221 
4222 #ifdef FEAT_EVAL
4223     /*
4224      * Check if this script has a breakpoint.
4225      */
4226     cookie.breakpoint = dbg_find_breakpoint(TRUE, fname_exp, (linenr_T)0);
4227     cookie.fname = fname_exp;
4228     cookie.dbg_tick = debug_tick;
4229 
4230     cookie.level = ex_nesting_level;
4231 #endif
4232 
4233     /*
4234      * Keep the sourcing name/lnum, for recursive calls.
4235      */
4236     save_sourcing_name = sourcing_name;
4237     sourcing_name = fname_exp;
4238     save_sourcing_lnum = sourcing_lnum;
4239     sourcing_lnum = 0;
4240 
4241 #ifdef STARTUPTIME
4242     if (time_fd != NULL)
4243 	time_push(&tv_rel, &tv_start);
4244 #endif
4245 
4246 #ifdef FEAT_EVAL
4247 # ifdef FEAT_PROFILE
4248     if (do_profiling == PROF_YES)
4249 	prof_child_enter(&wait_start);		/* entering a child now */
4250 # endif
4251 
4252     /* Don't use local function variables, if called from a function.
4253      * Also starts profiling timer for nested script. */
4254     save_funccalp = save_funccal();
4255 
4256     /*
4257      * Check if this script was sourced before to finds its SID.
4258      * If it's new, generate a new SID.
4259      */
4260     save_current_SID = current_SID;
4261 # ifdef UNIX
4262     stat_ok = (mch_stat((char *)fname_exp, &st) >= 0);
4263 # endif
4264     for (current_SID = script_items.ga_len; current_SID > 0; --current_SID)
4265     {
4266 	si = &SCRIPT_ITEM(current_SID);
4267 	if (si->sn_name != NULL
4268 		&& (
4269 # ifdef UNIX
4270 		    /* Compare dev/ino when possible, it catches symbolic
4271 		     * links.  Also compare file names, the inode may change
4272 		     * when the file was edited. */
4273 		    ((stat_ok && si->sn_dev_valid)
4274 			&& (si->sn_dev == st.st_dev
4275 			    && si->sn_ino == st.st_ino)) ||
4276 # endif
4277 		fnamecmp(si->sn_name, fname_exp) == 0))
4278 	    break;
4279     }
4280     if (current_SID == 0)
4281     {
4282 	current_SID = ++last_current_SID;
4283 	if (ga_grow(&script_items, (int)(current_SID - script_items.ga_len))
4284 								      == FAIL)
4285 	    goto almosttheend;
4286 	while (script_items.ga_len < current_SID)
4287 	{
4288 	    ++script_items.ga_len;
4289 	    SCRIPT_ITEM(script_items.ga_len).sn_name = NULL;
4290 # ifdef FEAT_PROFILE
4291 	    SCRIPT_ITEM(script_items.ga_len).sn_prof_on = FALSE;
4292 # endif
4293 	}
4294 	si = &SCRIPT_ITEM(current_SID);
4295 	si->sn_name = fname_exp;
4296 	fname_exp = NULL;
4297 # ifdef UNIX
4298 	if (stat_ok)
4299 	{
4300 	    si->sn_dev_valid = TRUE;
4301 	    si->sn_dev = st.st_dev;
4302 	    si->sn_ino = st.st_ino;
4303 	}
4304 	else
4305 	    si->sn_dev_valid = FALSE;
4306 # endif
4307 
4308 	/* Allocate the local script variables to use for this script. */
4309 	new_script_vars(current_SID);
4310     }
4311 
4312 # ifdef FEAT_PROFILE
4313     if (do_profiling == PROF_YES)
4314     {
4315 	int	forceit;
4316 
4317 	/* Check if we do profiling for this script. */
4318 	if (!si->sn_prof_on && has_profiling(TRUE, si->sn_name, &forceit))
4319 	{
4320 	    script_do_profile(si);
4321 	    si->sn_pr_force = forceit;
4322 	}
4323 	if (si->sn_prof_on)
4324 	{
4325 	    ++si->sn_pr_count;
4326 	    profile_start(&si->sn_pr_start);
4327 	    profile_zero(&si->sn_pr_children);
4328 	}
4329     }
4330 # endif
4331 #endif
4332 
4333 #ifdef FEAT_MBYTE
4334     cookie.conv.vc_type = CONV_NONE;		/* no conversion */
4335 
4336     /* Read the first line so we can check for a UTF-8 BOM. */
4337     firstline = getsourceline(0, (void *)&cookie, 0);
4338     if (firstline != NULL && STRLEN(firstline) >= 3 && firstline[0] == 0xef
4339 			      && firstline[1] == 0xbb && firstline[2] == 0xbf)
4340     {
4341 	/* Found BOM; setup conversion, skip over BOM and recode the line. */
4342 	convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc);
4343 	p = string_convert(&cookie.conv, firstline + 3, NULL);
4344 	if (p == NULL)
4345 	    p = vim_strsave(firstline + 3);
4346 	if (p != NULL)
4347 	{
4348 	    vim_free(firstline);
4349 	    firstline = p;
4350 	}
4351     }
4352 #endif
4353 
4354     /*
4355      * Call do_cmdline, which will call getsourceline() to get the lines.
4356      */
4357     do_cmdline(firstline, getsourceline, (void *)&cookie,
4358 				     DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT);
4359     retval = OK;
4360 
4361 #ifdef FEAT_PROFILE
4362     if (do_profiling == PROF_YES)
4363     {
4364 	/* Get "si" again, "script_items" may have been reallocated. */
4365 	si = &SCRIPT_ITEM(current_SID);
4366 	if (si->sn_prof_on)
4367 	{
4368 	    profile_end(&si->sn_pr_start);
4369 	    profile_sub_wait(&wait_start, &si->sn_pr_start);
4370 	    profile_add(&si->sn_pr_total, &si->sn_pr_start);
4371 	    profile_self(&si->sn_pr_self, &si->sn_pr_start,
4372 							 &si->sn_pr_children);
4373 	}
4374     }
4375 #endif
4376 
4377     if (got_int)
4378 	EMSG(_(e_interr));
4379     sourcing_name = save_sourcing_name;
4380     sourcing_lnum = save_sourcing_lnum;
4381     if (p_verbose > 1)
4382     {
4383 	verbose_enter();
4384 	smsg((char_u *)_("finished sourcing %s"), fname);
4385 	if (sourcing_name != NULL)
4386 	    smsg((char_u *)_("continuing in %s"), sourcing_name);
4387 	verbose_leave();
4388     }
4389 #ifdef STARTUPTIME
4390     if (time_fd != NULL)
4391     {
4392 	vim_snprintf((char *)IObuff, IOSIZE, "sourcing %s", fname);
4393 	time_msg((char *)IObuff, &tv_start);
4394 	time_pop(&tv_rel);
4395     }
4396 #endif
4397 
4398 #ifdef FEAT_EVAL
4399     /*
4400      * After a "finish" in debug mode, need to break at first command of next
4401      * sourced file.
4402      */
4403     if (save_debug_break_level > ex_nesting_level
4404 	    && debug_break_level == ex_nesting_level)
4405 	++debug_break_level;
4406 #endif
4407 
4408 #ifdef FEAT_EVAL
4409 almosttheend:
4410     current_SID = save_current_SID;
4411     restore_funccal(save_funccalp);
4412 # ifdef FEAT_PROFILE
4413     if (do_profiling == PROF_YES)
4414 	prof_child_exit(&wait_start);		/* leaving a child now */
4415 # endif
4416 #endif
4417     fclose(cookie.fp);
4418     vim_free(cookie.nextline);
4419     vim_free(firstline);
4420 #ifdef FEAT_MBYTE
4421     convert_setup(&cookie.conv, NULL, NULL);
4422 #endif
4423 
4424 theend:
4425     vim_free(fname_exp);
4426     return retval;
4427 }
4428 
4429 #if defined(FEAT_EVAL) || defined(PROTO)
4430 
4431 /*
4432  * ":scriptnames"
4433  */
4434     void
4435 ex_scriptnames(exarg_T *eap UNUSED)
4436 {
4437     int i;
4438 
4439     for (i = 1; i <= script_items.ga_len && !got_int; ++i)
4440 	if (SCRIPT_ITEM(i).sn_name != NULL)
4441 	{
4442 	    home_replace(NULL, SCRIPT_ITEM(i).sn_name,
4443 						    NameBuff, MAXPATHL, TRUE);
4444 	    smsg((char_u *)"%3d: %s", i, NameBuff);
4445 	}
4446 }
4447 
4448 # if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
4449 /*
4450  * Fix slashes in the list of script names for 'shellslash'.
4451  */
4452     void
4453 scriptnames_slash_adjust(void)
4454 {
4455     int i;
4456 
4457     for (i = 1; i <= script_items.ga_len; ++i)
4458 	if (SCRIPT_ITEM(i).sn_name != NULL)
4459 	    slash_adjust(SCRIPT_ITEM(i).sn_name);
4460 }
4461 # endif
4462 
4463 /*
4464  * Get a pointer to a script name.  Used for ":verbose set".
4465  */
4466     char_u *
4467 get_scriptname(scid_T id)
4468 {
4469     if (id == SID_MODELINE)
4470 	return (char_u *)_("modeline");
4471     if (id == SID_CMDARG)
4472 	return (char_u *)_("--cmd argument");
4473     if (id == SID_CARG)
4474 	return (char_u *)_("-c argument");
4475     if (id == SID_ENV)
4476 	return (char_u *)_("environment variable");
4477     if (id == SID_ERROR)
4478 	return (char_u *)_("error handler");
4479     return SCRIPT_ITEM(id).sn_name;
4480 }
4481 
4482 # if defined(EXITFREE) || defined(PROTO)
4483     void
4484 free_scriptnames(void)
4485 {
4486     int			i;
4487 
4488     for (i = script_items.ga_len; i > 0; --i)
4489 	vim_free(SCRIPT_ITEM(i).sn_name);
4490     ga_clear(&script_items);
4491 }
4492 # endif
4493 
4494 #endif
4495 
4496 #if defined(USE_CR) || defined(PROTO)
4497 
4498 # if defined(__MSL__) && (__MSL__ >= 22)
4499 /*
4500  * Newer version of the Metrowerks library handle DOS and UNIX files
4501  * without help.
4502  * Test with earlier versions, MSL 2.2 is the library supplied with
4503  * Codewarrior Pro 2.
4504  */
4505     char *
4506 fgets_cr(char *s, int n, FILE *stream)
4507 {
4508     return fgets(s, n, stream);
4509 }
4510 # else
4511 /*
4512  * Version of fgets() which also works for lines ending in a <CR> only
4513  * (Macintosh format).
4514  * For older versions of the Metrowerks library.
4515  * At least CodeWarrior 9 needed this code.
4516  */
4517     char *
4518 fgets_cr(char *s, int n, FILE *stream)
4519 {
4520     int	c = 0;
4521     int char_read = 0;
4522 
4523     while (!feof(stream) && c != '\r' && c != '\n' && char_read < n - 1)
4524     {
4525 	c = fgetc(stream);
4526 	s[char_read++] = c;
4527 	/* If the file is in DOS format, we need to skip a NL after a CR.  I
4528 	 * thought it was the other way around, but this appears to work... */
4529 	if (c == '\n')
4530 	{
4531 	    c = fgetc(stream);
4532 	    if (c != '\r')
4533 		ungetc(c, stream);
4534 	}
4535     }
4536 
4537     s[char_read] = 0;
4538     if (char_read == 0)
4539 	return NULL;
4540 
4541     if (feof(stream) && char_read == 1)
4542 	return NULL;
4543 
4544     return s;
4545 }
4546 # endif
4547 #endif
4548 
4549 /*
4550  * Get one full line from a sourced file.
4551  * Called by do_cmdline() when it's called from do_source().
4552  *
4553  * Return a pointer to the line in allocated memory.
4554  * Return NULL for end-of-file or some error.
4555  */
4556     char_u *
4557 getsourceline(int c UNUSED, void *cookie, int indent UNUSED)
4558 {
4559     struct source_cookie *sp = (struct source_cookie *)cookie;
4560     char_u		*line;
4561     char_u		*p;
4562 
4563 #ifdef FEAT_EVAL
4564     /* If breakpoints have been added/deleted need to check for it. */
4565     if (sp->dbg_tick < debug_tick)
4566     {
4567 	sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
4568 	sp->dbg_tick = debug_tick;
4569     }
4570 # ifdef FEAT_PROFILE
4571     if (do_profiling == PROF_YES)
4572 	script_line_end();
4573 # endif
4574 #endif
4575     /*
4576      * Get current line.  If there is a read-ahead line, use it, otherwise get
4577      * one now.
4578      */
4579     if (sp->finished)
4580 	line = NULL;
4581     else if (sp->nextline == NULL)
4582 	line = get_one_sourceline(sp);
4583     else
4584     {
4585 	line = sp->nextline;
4586 	sp->nextline = NULL;
4587 	++sourcing_lnum;
4588     }
4589 #ifdef FEAT_PROFILE
4590     if (line != NULL && do_profiling == PROF_YES)
4591 	script_line_start();
4592 #endif
4593 
4594     /* Only concatenate lines starting with a \ when 'cpoptions' doesn't
4595      * contain the 'C' flag. */
4596     if (line != NULL && (vim_strchr(p_cpo, CPO_CONCAT) == NULL))
4597     {
4598 	/* compensate for the one line read-ahead */
4599 	--sourcing_lnum;
4600 
4601 	/* Get the next line and concatenate it when it starts with a
4602 	 * backslash. We always need to read the next line, keep it in
4603 	 * sp->nextline. */
4604 	sp->nextline = get_one_sourceline(sp);
4605 	if (sp->nextline != NULL && *(p = skipwhite(sp->nextline)) == '\\')
4606 	{
4607 	    garray_T    ga;
4608 
4609 	    ga_init2(&ga, (int)sizeof(char_u), 400);
4610 	    ga_concat(&ga, line);
4611 	    ga_concat(&ga, p + 1);
4612 	    for (;;)
4613 	    {
4614 		vim_free(sp->nextline);
4615 		sp->nextline = get_one_sourceline(sp);
4616 		if (sp->nextline == NULL)
4617 		    break;
4618 		p = skipwhite(sp->nextline);
4619 		if (*p != '\\')
4620 		    break;
4621 		/* Adjust the growsize to the current length to speed up
4622 		 * concatenating many lines. */
4623 		if (ga.ga_len > 400)
4624 		{
4625 		    if (ga.ga_len > 8000)
4626 			ga.ga_growsize = 8000;
4627 		    else
4628 			ga.ga_growsize = ga.ga_len;
4629 		}
4630 		ga_concat(&ga, p + 1);
4631 	    }
4632 	    ga_append(&ga, NUL);
4633 	    vim_free(line);
4634 	    line = ga.ga_data;
4635 	}
4636     }
4637 
4638 #ifdef FEAT_MBYTE
4639     if (line != NULL && sp->conv.vc_type != CONV_NONE)
4640     {
4641 	char_u	*s;
4642 
4643 	/* Convert the encoding of the script line. */
4644 	s = string_convert(&sp->conv, line, NULL);
4645 	if (s != NULL)
4646 	{
4647 	    vim_free(line);
4648 	    line = s;
4649 	}
4650     }
4651 #endif
4652 
4653 #ifdef FEAT_EVAL
4654     /* Did we encounter a breakpoint? */
4655     if (sp->breakpoint != 0 && sp->breakpoint <= sourcing_lnum)
4656     {
4657 	dbg_breakpoint(sp->fname, sourcing_lnum);
4658 	/* Find next breakpoint. */
4659 	sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
4660 	sp->dbg_tick = debug_tick;
4661     }
4662 #endif
4663 
4664     return line;
4665 }
4666 
4667     static char_u *
4668 get_one_sourceline(struct source_cookie *sp)
4669 {
4670     garray_T		ga;
4671     int			len;
4672     int			c;
4673     char_u		*buf;
4674 #ifdef USE_CRNL
4675     int			has_cr;		/* CR-LF found */
4676 #endif
4677 #ifdef USE_CR
4678     char_u		*scan;
4679 #endif
4680     int			have_read = FALSE;
4681 
4682     /* use a growarray to store the sourced line */
4683     ga_init2(&ga, 1, 250);
4684 
4685     /*
4686      * Loop until there is a finished line (or end-of-file).
4687      */
4688     sourcing_lnum++;
4689     for (;;)
4690     {
4691 	/* make room to read at least 120 (more) characters */
4692 	if (ga_grow(&ga, 120) == FAIL)
4693 	    break;
4694 	buf = (char_u *)ga.ga_data;
4695 
4696 #ifdef USE_CR
4697 	if (sp->fileformat == EOL_MAC)
4698 	{
4699 	    if (fgets_cr((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
4700 							      sp->fp) == NULL)
4701 		break;
4702 	}
4703 	else
4704 #endif
4705 	    if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
4706 							      sp->fp) == NULL)
4707 		break;
4708 	len = ga.ga_len + (int)STRLEN(buf + ga.ga_len);
4709 #ifdef USE_CRNL
4710 	/* Ignore a trailing CTRL-Z, when in Dos mode.	Only recognize the
4711 	 * CTRL-Z by its own, or after a NL. */
4712 	if (	   (len == 1 || (len >= 2 && buf[len - 2] == '\n'))
4713 		&& sp->fileformat == EOL_DOS
4714 		&& buf[len - 1] == Ctrl_Z)
4715 	{
4716 	    buf[len - 1] = NUL;
4717 	    break;
4718 	}
4719 #endif
4720 
4721 #ifdef USE_CR
4722 	/* If the read doesn't stop on a new line, and there's
4723 	 * some CR then we assume a Mac format */
4724 	if (sp->fileformat == EOL_UNKNOWN)
4725 	{
4726 	    if (buf[len - 1] != '\n' && vim_strchr(buf, '\r') != NULL)
4727 		sp->fileformat = EOL_MAC;
4728 	    else
4729 		sp->fileformat = EOL_UNIX;
4730 	}
4731 
4732 	if (sp->fileformat == EOL_MAC)
4733 	{
4734 	    scan = vim_strchr(buf, '\r');
4735 
4736 	    if (scan != NULL)
4737 	    {
4738 		*scan = '\n';
4739 		if (*(scan + 1) != 0)
4740 		{
4741 		    *(scan + 1) = 0;
4742 		    fseek(sp->fp, (long)(scan - buf - len + 1), SEEK_CUR);
4743 		}
4744 	    }
4745 	    len = STRLEN(buf);
4746 	}
4747 #endif
4748 
4749 	have_read = TRUE;
4750 	ga.ga_len = len;
4751 
4752 	/* If the line was longer than the buffer, read more. */
4753 	if (ga.ga_maxlen - ga.ga_len == 1 && buf[len - 1] != '\n')
4754 	    continue;
4755 
4756 	if (len >= 1 && buf[len - 1] == '\n')	/* remove trailing NL */
4757 	{
4758 #ifdef USE_CRNL
4759 	    has_cr = (len >= 2 && buf[len - 2] == '\r');
4760 	    if (sp->fileformat == EOL_UNKNOWN)
4761 	    {
4762 		if (has_cr)
4763 		    sp->fileformat = EOL_DOS;
4764 		else
4765 		    sp->fileformat = EOL_UNIX;
4766 	    }
4767 
4768 	    if (sp->fileformat == EOL_DOS)
4769 	    {
4770 		if (has_cr)	    /* replace trailing CR */
4771 		{
4772 		    buf[len - 2] = '\n';
4773 		    --len;
4774 		    --ga.ga_len;
4775 		}
4776 		else	    /* lines like ":map xx yy^M" will have failed */
4777 		{
4778 		    if (!sp->error)
4779 		    {
4780 			msg_source(HL_ATTR(HLF_W));
4781 			EMSG(_("W15: Warning: Wrong line separator, ^M may be missing"));
4782 		    }
4783 		    sp->error = TRUE;
4784 		    sp->fileformat = EOL_UNIX;
4785 		}
4786 	    }
4787 #endif
4788 	    /* The '\n' is escaped if there is an odd number of ^V's just
4789 	     * before it, first set "c" just before the 'V's and then check
4790 	     * len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo */
4791 	    for (c = len - 2; c >= 0 && buf[c] == Ctrl_V; c--)
4792 		;
4793 	    if ((len & 1) != (c & 1))	/* escaped NL, read more */
4794 	    {
4795 		sourcing_lnum++;
4796 		continue;
4797 	    }
4798 
4799 	    buf[len - 1] = NUL;		/* remove the NL */
4800 	}
4801 
4802 	/*
4803 	 * Check for ^C here now and then, so recursive :so can be broken.
4804 	 */
4805 	line_breakcheck();
4806 	break;
4807     }
4808 
4809     if (have_read)
4810 	return (char_u *)ga.ga_data;
4811 
4812     vim_free(ga.ga_data);
4813     return NULL;
4814 }
4815 
4816 #if defined(FEAT_PROFILE) || defined(PROTO)
4817 /*
4818  * Called when starting to read a script line.
4819  * "sourcing_lnum" must be correct!
4820  * When skipping lines it may not actually be executed, but we won't find out
4821  * until later and we need to store the time now.
4822  */
4823     void
4824 script_line_start(void)
4825 {
4826     scriptitem_T    *si;
4827     sn_prl_T	    *pp;
4828 
4829     if (current_SID <= 0 || current_SID > script_items.ga_len)
4830 	return;
4831     si = &SCRIPT_ITEM(current_SID);
4832     if (si->sn_prof_on && sourcing_lnum >= 1)
4833     {
4834 	/* Grow the array before starting the timer, so that the time spent
4835 	 * here isn't counted. */
4836 	(void)ga_grow(&si->sn_prl_ga,
4837 				  (int)(sourcing_lnum - si->sn_prl_ga.ga_len));
4838 	si->sn_prl_idx = sourcing_lnum - 1;
4839 	while (si->sn_prl_ga.ga_len <= si->sn_prl_idx
4840 		&& si->sn_prl_ga.ga_len < si->sn_prl_ga.ga_maxlen)
4841 	{
4842 	    /* Zero counters for a line that was not used before. */
4843 	    pp = &PRL_ITEM(si, si->sn_prl_ga.ga_len);
4844 	    pp->snp_count = 0;
4845 	    profile_zero(&pp->sn_prl_total);
4846 	    profile_zero(&pp->sn_prl_self);
4847 	    ++si->sn_prl_ga.ga_len;
4848 	}
4849 	si->sn_prl_execed = FALSE;
4850 	profile_start(&si->sn_prl_start);
4851 	profile_zero(&si->sn_prl_children);
4852 	profile_get_wait(&si->sn_prl_wait);
4853     }
4854 }
4855 
4856 /*
4857  * Called when actually executing a function line.
4858  */
4859     void
4860 script_line_exec(void)
4861 {
4862     scriptitem_T    *si;
4863 
4864     if (current_SID <= 0 || current_SID > script_items.ga_len)
4865 	return;
4866     si = &SCRIPT_ITEM(current_SID);
4867     if (si->sn_prof_on && si->sn_prl_idx >= 0)
4868 	si->sn_prl_execed = TRUE;
4869 }
4870 
4871 /*
4872  * Called when done with a script line.
4873  */
4874     void
4875 script_line_end(void)
4876 {
4877     scriptitem_T    *si;
4878     sn_prl_T	    *pp;
4879 
4880     if (current_SID <= 0 || current_SID > script_items.ga_len)
4881 	return;
4882     si = &SCRIPT_ITEM(current_SID);
4883     if (si->sn_prof_on && si->sn_prl_idx >= 0
4884 				     && si->sn_prl_idx < si->sn_prl_ga.ga_len)
4885     {
4886 	if (si->sn_prl_execed)
4887 	{
4888 	    pp = &PRL_ITEM(si, si->sn_prl_idx);
4889 	    ++pp->snp_count;
4890 	    profile_end(&si->sn_prl_start);
4891 	    profile_sub_wait(&si->sn_prl_wait, &si->sn_prl_start);
4892 	    profile_add(&pp->sn_prl_total, &si->sn_prl_start);
4893 	    profile_self(&pp->sn_prl_self, &si->sn_prl_start,
4894 							&si->sn_prl_children);
4895 	}
4896 	si->sn_prl_idx = -1;
4897     }
4898 }
4899 #endif
4900 
4901 /*
4902  * ":scriptencoding": Set encoding conversion for a sourced script.
4903  * Without the multi-byte feature it's simply ignored.
4904  */
4905     void
4906 ex_scriptencoding(exarg_T *eap UNUSED)
4907 {
4908 #ifdef FEAT_MBYTE
4909     struct source_cookie	*sp;
4910     char_u			*name;
4911 
4912     if (!getline_equal(eap->getline, eap->cookie, getsourceline))
4913     {
4914 	EMSG(_("E167: :scriptencoding used outside of a sourced file"));
4915 	return;
4916     }
4917 
4918     if (*eap->arg != NUL)
4919     {
4920 	name = enc_canonize(eap->arg);
4921 	if (name == NULL)	/* out of memory */
4922 	    return;
4923     }
4924     else
4925 	name = eap->arg;
4926 
4927     /* Setup for conversion from the specified encoding to 'encoding'. */
4928     sp = (struct source_cookie *)getline_cookie(eap->getline, eap->cookie);
4929     convert_setup(&sp->conv, name, p_enc);
4930 
4931     if (name != eap->arg)
4932 	vim_free(name);
4933 #endif
4934 }
4935 
4936 #if defined(FEAT_EVAL) || defined(PROTO)
4937 /*
4938  * ":finish": Mark a sourced file as finished.
4939  */
4940     void
4941 ex_finish(exarg_T *eap)
4942 {
4943     if (getline_equal(eap->getline, eap->cookie, getsourceline))
4944 	do_finish(eap, FALSE);
4945     else
4946 	EMSG(_("E168: :finish used outside of a sourced file"));
4947 }
4948 
4949 /*
4950  * Mark a sourced file as finished.  Possibly makes the ":finish" pending.
4951  * Also called for a pending finish at the ":endtry" or after returning from
4952  * an extra do_cmdline().  "reanimate" is used in the latter case.
4953  */
4954     void
4955 do_finish(exarg_T *eap, int reanimate)
4956 {
4957     int		idx;
4958 
4959     if (reanimate)
4960 	((struct source_cookie *)getline_cookie(eap->getline,
4961 					      eap->cookie))->finished = FALSE;
4962 
4963     /*
4964      * Cleanup (and inactivate) conditionals, but stop when a try conditional
4965      * not in its finally clause (which then is to be executed next) is found.
4966      * In this case, make the ":finish" pending for execution at the ":endtry".
4967      * Otherwise, finish normally.
4968      */
4969     idx = cleanup_conditionals(eap->cstack, 0, TRUE);
4970     if (idx >= 0)
4971     {
4972 	eap->cstack->cs_pending[idx] = CSTP_FINISH;
4973 	report_make_pending(CSTP_FINISH, NULL);
4974     }
4975     else
4976 	((struct source_cookie *)getline_cookie(eap->getline,
4977 					       eap->cookie))->finished = TRUE;
4978 }
4979 
4980 
4981 /*
4982  * Return TRUE when a sourced file had the ":finish" command: Don't give error
4983  * message for missing ":endif".
4984  * Return FALSE when not sourcing a file.
4985  */
4986     int
4987 source_finished(
4988     char_u	*(*fgetline)(int, void *, int),
4989     void	*cookie)
4990 {
4991     return (getline_equal(fgetline, cookie, getsourceline)
4992 	    && ((struct source_cookie *)getline_cookie(
4993 						fgetline, cookie))->finished);
4994 }
4995 #endif
4996 
4997 #if defined(FEAT_LISTCMDS) || defined(PROTO)
4998 /*
4999  * ":checktime [buffer]"
5000  */
5001     void
5002 ex_checktime(exarg_T *eap)
5003 {
5004     buf_T	*buf;
5005     int		save_no_check_timestamps = no_check_timestamps;
5006 
5007     no_check_timestamps = 0;
5008     if (eap->addr_count == 0)	/* default is all buffers */
5009 	check_timestamps(FALSE);
5010     else
5011     {
5012 	buf = buflist_findnr((int)eap->line2);
5013 	if (buf != NULL)	/* cannot happen? */
5014 	    (void)buf_check_timestamp(buf, FALSE);
5015     }
5016     no_check_timestamps = save_no_check_timestamps;
5017 }
5018 #endif
5019 
5020 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
5021 	&& (defined(FEAT_EVAL) || defined(FEAT_MULTI_LANG))
5022 # define HAVE_GET_LOCALE_VAL
5023 static char_u *get_locale_val(int what);
5024 
5025     static char_u *
5026 get_locale_val(int what)
5027 {
5028     char_u	*loc;
5029 
5030     /* Obtain the locale value from the libraries. */
5031     loc = (char_u *)setlocale(what, NULL);
5032 
5033 # ifdef WIN32
5034     if (loc != NULL)
5035     {
5036 	char_u	*p;
5037 
5038 	/* setocale() returns something like "LC_COLLATE=<name>;LC_..." when
5039 	 * one of the values (e.g., LC_CTYPE) differs. */
5040 	p = vim_strchr(loc, '=');
5041 	if (p != NULL)
5042 	{
5043 	    loc = ++p;
5044 	    while (*p != NUL)	/* remove trailing newline */
5045 	    {
5046 		if (*p < ' ' || *p == ';')
5047 		{
5048 		    *p = NUL;
5049 		    break;
5050 		}
5051 		++p;
5052 	    }
5053 	}
5054     }
5055 # endif
5056 
5057     return loc;
5058 }
5059 #endif
5060 
5061 
5062 #ifdef WIN32
5063 /*
5064  * On MS-Windows locale names are strings like "German_Germany.1252", but
5065  * gettext expects "de".  Try to translate one into another here for a few
5066  * supported languages.
5067  */
5068     static char_u *
5069 gettext_lang(char_u *name)
5070 {
5071     int		i;
5072     static char *(mtable[]) = {
5073 			"afrikaans",	"af",
5074 			"czech",	"cs",
5075 			"dutch",	"nl",
5076 			"german",	"de",
5077 			"english_united kingdom", "en_GB",
5078 			"spanish",	"es",
5079 			"french",	"fr",
5080 			"italian",	"it",
5081 			"japanese",	"ja",
5082 			"korean",	"ko",
5083 			"norwegian",	"no",
5084 			"polish",	"pl",
5085 			"russian",	"ru",
5086 			"slovak",	"sk",
5087 			"swedish",	"sv",
5088 			"ukrainian",	"uk",
5089 			"chinese_china", "zh_CN",
5090 			"chinese_taiwan", "zh_TW",
5091 			NULL};
5092 
5093     for (i = 0; mtable[i] != NULL; i += 2)
5094 	if (STRNICMP(mtable[i], name, STRLEN(mtable[i])) == 0)
5095 	    return (char_u *)mtable[i + 1];
5096     return name;
5097 }
5098 #endif
5099 
5100 #if defined(FEAT_MULTI_LANG) || defined(PROTO)
5101 /*
5102  * Obtain the current messages language.  Used to set the default for
5103  * 'helplang'.  May return NULL or an empty string.
5104  */
5105     char_u *
5106 get_mess_lang(void)
5107 {
5108     char_u *p;
5109 
5110 # ifdef HAVE_GET_LOCALE_VAL
5111 #  if defined(LC_MESSAGES)
5112     p = get_locale_val(LC_MESSAGES);
5113 #  else
5114     /* This is necessary for Win32, where LC_MESSAGES is not defined and $LANG
5115      * may be set to the LCID number.  LC_COLLATE is the best guess, LC_TIME
5116      * and LC_MONETARY may be set differently for a Japanese working in the
5117      * US. */
5118     p = get_locale_val(LC_COLLATE);
5119 #  endif
5120 # else
5121     p = mch_getenv((char_u *)"LC_ALL");
5122     if (p == NULL || *p == NUL)
5123     {
5124 	p = mch_getenv((char_u *)"LC_MESSAGES");
5125 	if (p == NULL || *p == NUL)
5126 	    p = mch_getenv((char_u *)"LANG");
5127     }
5128 # endif
5129 # ifdef WIN32
5130     p = gettext_lang(p);
5131 # endif
5132     return p;
5133 }
5134 #endif
5135 
5136 /* Complicated #if; matches with where get_mess_env() is used below. */
5137 #if (defined(FEAT_EVAL) && !((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
5138 	    && defined(LC_MESSAGES))) \
5139 	|| ((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
5140 		&& (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)) \
5141 		&& !defined(LC_MESSAGES))
5142 static char_u *get_mess_env(void);
5143 
5144 /*
5145  * Get the language used for messages from the environment.
5146  */
5147     static char_u *
5148 get_mess_env(void)
5149 {
5150     char_u	*p;
5151 
5152     p = mch_getenv((char_u *)"LC_ALL");
5153     if (p == NULL || *p == NUL)
5154     {
5155 	p = mch_getenv((char_u *)"LC_MESSAGES");
5156 	if (p == NULL || *p == NUL)
5157 	{
5158 	    p = mch_getenv((char_u *)"LANG");
5159 	    if (p != NULL && VIM_ISDIGIT(*p))
5160 		p = NULL;		/* ignore something like "1043" */
5161 # ifdef HAVE_GET_LOCALE_VAL
5162 	    if (p == NULL || *p == NUL)
5163 		p = get_locale_val(LC_CTYPE);
5164 # endif
5165 	}
5166     }
5167     return p;
5168 }
5169 #endif
5170 
5171 #if defined(FEAT_EVAL) || defined(PROTO)
5172 
5173 /*
5174  * Set the "v:lang" variable according to the current locale setting.
5175  * Also do "v:lc_time"and "v:ctype".
5176  */
5177     void
5178 set_lang_var(void)
5179 {
5180     char_u	*loc;
5181 
5182 # ifdef HAVE_GET_LOCALE_VAL
5183     loc = get_locale_val(LC_CTYPE);
5184 # else
5185     /* setlocale() not supported: use the default value */
5186     loc = (char_u *)"C";
5187 # endif
5188     set_vim_var_string(VV_CTYPE, loc, -1);
5189 
5190     /* When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall
5191      * back to LC_CTYPE if it's empty. */
5192 # if defined(HAVE_GET_LOCALE_VAL) && defined(LC_MESSAGES)
5193     loc = get_locale_val(LC_MESSAGES);
5194 # else
5195     loc = get_mess_env();
5196 # endif
5197     set_vim_var_string(VV_LANG, loc, -1);
5198 
5199 # ifdef HAVE_GET_LOCALE_VAL
5200     loc = get_locale_val(LC_TIME);
5201 # endif
5202     set_vim_var_string(VV_LC_TIME, loc, -1);
5203 }
5204 #endif
5205 
5206 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
5207 	&& (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE))
5208 /*
5209  * ":language":  Set the language (locale).
5210  */
5211     void
5212 ex_language(exarg_T *eap)
5213 {
5214     char	*loc;
5215     char_u	*p;
5216     char_u	*name;
5217     int		what = LC_ALL;
5218     char	*whatstr = "";
5219 #ifdef LC_MESSAGES
5220 # define VIM_LC_MESSAGES LC_MESSAGES
5221 #else
5222 # define VIM_LC_MESSAGES 6789
5223 #endif
5224 
5225     name = eap->arg;
5226 
5227     /* Check for "messages {name}", "ctype {name}" or "time {name}" argument.
5228      * Allow abbreviation, but require at least 3 characters to avoid
5229      * confusion with a two letter language name "me" or "ct". */
5230     p = skiptowhite(eap->arg);
5231     if ((*p == NUL || VIM_ISWHITE(*p)) && p - eap->arg >= 3)
5232     {
5233 	if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0)
5234 	{
5235 	    what = VIM_LC_MESSAGES;
5236 	    name = skipwhite(p);
5237 	    whatstr = "messages ";
5238 	}
5239 	else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0)
5240 	{
5241 	    what = LC_CTYPE;
5242 	    name = skipwhite(p);
5243 	    whatstr = "ctype ";
5244 	}
5245 	else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0)
5246 	{
5247 	    what = LC_TIME;
5248 	    name = skipwhite(p);
5249 	    whatstr = "time ";
5250 	}
5251     }
5252 
5253     if (*name == NUL)
5254     {
5255 #ifndef LC_MESSAGES
5256 	if (what == VIM_LC_MESSAGES)
5257 	    p = get_mess_env();
5258 	else
5259 #endif
5260 	    p = (char_u *)setlocale(what, NULL);
5261 	if (p == NULL || *p == NUL)
5262 	    p = (char_u *)"Unknown";
5263 	smsg((char_u *)_("Current %slanguage: \"%s\""), whatstr, p);
5264     }
5265     else
5266     {
5267 #ifndef LC_MESSAGES
5268 	if (what == VIM_LC_MESSAGES)
5269 	    loc = "";
5270 	else
5271 #endif
5272 	{
5273 	    loc = setlocale(what, (char *)name);
5274 #if defined(FEAT_FLOAT) && defined(LC_NUMERIC)
5275 	    /* Make sure strtod() uses a decimal point, not a comma. */
5276 	    setlocale(LC_NUMERIC, "C");
5277 #endif
5278 	}
5279 	if (loc == NULL)
5280 	    EMSG2(_("E197: Cannot set language to \"%s\""), name);
5281 	else
5282 	{
5283 #ifdef HAVE_NL_MSG_CAT_CNTR
5284 	    /* Need to do this for GNU gettext, otherwise cached translations
5285 	     * will be used again. */
5286 	    extern int _nl_msg_cat_cntr;
5287 
5288 	    ++_nl_msg_cat_cntr;
5289 #endif
5290 	    /* Reset $LC_ALL, otherwise it would overrule everything. */
5291 	    vim_setenv((char_u *)"LC_ALL", (char_u *)"");
5292 
5293 	    if (what != LC_TIME)
5294 	    {
5295 		/* Tell gettext() what to translate to.  It apparently doesn't
5296 		 * use the currently effective locale.  Also do this when
5297 		 * FEAT_GETTEXT isn't defined, so that shell commands use this
5298 		 * value. */
5299 		if (what == LC_ALL)
5300 		{
5301 		    vim_setenv((char_u *)"LANG", name);
5302 
5303 		    /* Clear $LANGUAGE because GNU gettext uses it. */
5304 		    vim_setenv((char_u *)"LANGUAGE", (char_u *)"");
5305 # ifdef WIN32
5306 		    /* Apparently MS-Windows printf() may cause a crash when
5307 		     * we give it 8-bit text while it's expecting text in the
5308 		     * current locale.  This call avoids that. */
5309 		    setlocale(LC_CTYPE, "C");
5310 # endif
5311 		}
5312 		if (what != LC_CTYPE)
5313 		{
5314 		    char_u	*mname;
5315 #ifdef WIN32
5316 		    mname = gettext_lang(name);
5317 #else
5318 		    mname = name;
5319 #endif
5320 		    vim_setenv((char_u *)"LC_MESSAGES", mname);
5321 #ifdef FEAT_MULTI_LANG
5322 		    set_helplang_default(mname);
5323 #endif
5324 		}
5325 	    }
5326 
5327 # ifdef FEAT_EVAL
5328 	    /* Set v:lang, v:lc_time and v:ctype to the final result. */
5329 	    set_lang_var();
5330 # endif
5331 # ifdef FEAT_TITLE
5332 	    maketitle();
5333 # endif
5334 	}
5335     }
5336 }
5337 
5338 # if defined(FEAT_CMDL_COMPL) || defined(PROTO)
5339 
5340 static char_u	**locales = NULL;	/* Array of all available locales */
5341 
5342 #  ifndef WIN32
5343 static int	did_init_locales = FALSE;
5344 
5345 /* Return an array of strings for all available locales + NULL for the
5346  * last element.  Return NULL in case of error. */
5347     static char_u **
5348 find_locales(void)
5349 {
5350     garray_T	locales_ga;
5351     char_u	*loc;
5352 
5353     /* Find all available locales by running command "locale -a".  If this
5354      * doesn't work we won't have completion. */
5355     char_u *locale_a = get_cmd_output((char_u *)"locale -a",
5356 						    NULL, SHELL_SILENT, NULL);
5357     if (locale_a == NULL)
5358 	return NULL;
5359     ga_init2(&locales_ga, sizeof(char_u *), 20);
5360 
5361     /* Transform locale_a string where each locale is separated by "\n"
5362      * into an array of locale strings. */
5363     loc = (char_u *)strtok((char *)locale_a, "\n");
5364 
5365     while (loc != NULL)
5366     {
5367 	if (ga_grow(&locales_ga, 1) == FAIL)
5368 	    break;
5369 	loc = vim_strsave(loc);
5370 	if (loc == NULL)
5371 	    break;
5372 
5373 	((char_u **)locales_ga.ga_data)[locales_ga.ga_len++] = loc;
5374 	loc = (char_u *)strtok(NULL, "\n");
5375     }
5376     vim_free(locale_a);
5377     if (ga_grow(&locales_ga, 1) == FAIL)
5378     {
5379 	ga_clear(&locales_ga);
5380 	return NULL;
5381     }
5382     ((char_u **)locales_ga.ga_data)[locales_ga.ga_len] = NULL;
5383     return (char_u **)locales_ga.ga_data;
5384 }
5385 #  endif
5386 
5387 /*
5388  * Lazy initialization of all available locales.
5389  */
5390     static void
5391 init_locales(void)
5392 {
5393 #  ifndef WIN32
5394     if (!did_init_locales)
5395     {
5396 	did_init_locales = TRUE;
5397 	locales = find_locales();
5398     }
5399 #  endif
5400 }
5401 
5402 #  if defined(EXITFREE) || defined(PROTO)
5403     void
5404 free_locales(void)
5405 {
5406     int			i;
5407     if (locales != NULL)
5408     {
5409 	for (i = 0; locales[i] != NULL; i++)
5410 	    vim_free(locales[i]);
5411 	vim_free(locales);
5412 	locales = NULL;
5413     }
5414 }
5415 #  endif
5416 
5417 /*
5418  * Function given to ExpandGeneric() to obtain the possible arguments of the
5419  * ":language" command.
5420  */
5421     char_u *
5422 get_lang_arg(expand_T *xp UNUSED, int idx)
5423 {
5424     if (idx == 0)
5425 	return (char_u *)"messages";
5426     if (idx == 1)
5427 	return (char_u *)"ctype";
5428     if (idx == 2)
5429 	return (char_u *)"time";
5430 
5431     init_locales();
5432     if (locales == NULL)
5433 	return NULL;
5434     return locales[idx - 3];
5435 }
5436 
5437 /*
5438  * Function given to ExpandGeneric() to obtain the available locales.
5439  */
5440     char_u *
5441 get_locales(expand_T *xp UNUSED, int idx)
5442 {
5443     init_locales();
5444     if (locales == NULL)
5445 	return NULL;
5446     return locales[idx];
5447 }
5448 # endif
5449 
5450 #endif
5451