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