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