Merged from the latest developing branch.
[MacVim.git] / src / ex_cmds2.c
blob81feac83571676e3229e3b0f5af6a2eb83defd0f
1 /* vi:set ts=8 sts=4 sw=4:
3 * VIM - Vi IMproved by Bram Moolenaar
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 */
11 * ex_cmds2.c: some more functions for command line commands
14 #if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64)
15 # include "vimio.h" /* for mch_open(), must be before vim.h */
16 #endif
18 #include "vim.h"
19 #include "version.h"
21 static void cmd_source __ARGS((char_u *fname, exarg_T *eap));
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. */
27 typedef struct scriptitem_S
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;
56 static garray_T script_items = {0, 0, sizeof(scriptitem_T), 4, NULL};
57 #define SCRIPT_ITEM(id) (((scriptitem_T *)script_items.ga_data)[(id) - 1])
59 # ifdef FEAT_PROFILE
60 /* Struct used in sn_prl_ga for every line of a script. */
61 typedef struct sn_prl_S
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;
68 # define PRL_ITEM(si, idx) (((sn_prl_T *)(si)->sn_prl_ga.ga_data)[(idx)])
69 # endif
70 #endif
72 #if defined(FEAT_EVAL) || defined(PROTO)
73 static int debug_greedy = FALSE; /* batch mode debugging: don't save
74 and restore typeahead. */
77 * do_debug(): Debug mode.
78 * Repeatedly get Ex commands, until told to continue normal execution.
80 void
81 do_debug(cmd)
82 char_u *cmd;
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
109 #ifdef ALWAYS_USE_GUI
110 /* Can't do this when there is no terminal for input/output. */
111 if (!gui.in_use)
113 /* Break as soon as possible. */
114 debug_break_level = 9999;
115 return;
117 #endif
119 /* Make sure we are in raw mode and start termcap mode. Might have side
120 * effects... */
121 settmode(TMODE_RAW);
122 starttermcap();
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 */
132 State = NORMAL;
133 #ifdef FEAT_SNIFF
134 want_sniff_request = 0; /* No K_SNIFF wanted */
135 #endif
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);
147 * Repeat getting a command and executing it.
149 for (;;)
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)
167 save_typeahead(&typeaheadbuf);
168 typeahead_saved = TRUE;
169 save_ignore_script = ignore_script;
170 ignore_script = TRUE;
173 cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL);
175 if (typeahead_saved)
177 restore_typeahead(&typeaheadbuf);
178 ignore_script = save_ignore_script;
180 # ifdef FEAT_EX_EXTRA
181 ex_normal_busy = save_ex_normal_busy;
182 # endif
184 cmdline_row = msg_row;
185 if (cmdline != NULL)
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)
193 switch (*p)
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;
215 if (last_cmd != 0)
217 /* Check that the tail matches. */
218 ++p;
219 while (*p != NUL && *p == *tail)
221 ++p;
222 ++tail;
224 if (ASCII_ISALPHA(*p))
225 last_cmd = 0;
229 if (last_cmd != 0)
231 /* Execute debug command: decided where to break next and
232 * return. */
233 switch (last_cmd)
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;
258 break;
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;
268 vim_free(cmdline);
270 lines_left = Rows - 1;
272 vim_free(cmdline);
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;
287 /* Only print the message again when typing a command before coming back
288 * here. */
289 debug_did_msg = TRUE;
293 * ":debug".
295 void
296 ex_debug(eap)
297 exarg_T *eap;
299 int debug_break_level_save = debug_break_level;
301 debug_break_level = 9999;
302 do_cmdline_cmd(eap->arg);
303 debug_break_level = debug_break_level_save;
306 static char_u *debug_breakpoint_name = NULL;
307 static linenr_T debug_breakpoint_lnum;
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().
316 static int debug_skipped;
317 static char_u *debug_skipped_name;
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.
326 void
327 dbg_check_breakpoint(eap)
328 exarg_T *eap;
330 char_u *p;
332 debug_skipped = FALSE;
333 if (debug_breakpoint_name != NULL)
335 if (!eap->skip)
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"),
346 debug_breakpoint_name + (*p == NUL ? 0 : 3),
347 (long)debug_breakpoint_lnum);
348 debug_breakpoint_name = NULL;
349 do_debug(eap->cmd);
351 else
353 debug_skipped = TRUE;
354 debug_skipped_name = debug_breakpoint_name;
355 debug_breakpoint_name = NULL;
358 else if (ex_nesting_level <= debug_break_level)
360 if (!eap->skip)
361 do_debug(eap->cmd);
362 else
364 debug_skipped = TRUE;
365 debug_skipped_name = NULL;
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.
375 dbg_check_skipped(eap)
376 exarg_T *eap;
378 int prev_got_int;
380 if (debug_skipped)
383 * Save the value of got_int and reset it. We don't want a previous
384 * interruption cause flushing the input buffer.
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;
396 return FALSE;
400 * The list of breakpoints: dbg_breakp.
401 * This is a grow-array of structs.
403 struct debuggy
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 */
413 static 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])
416 static int last_breakp = 0; /* nr of last defined breakpoint */
418 #ifdef FEAT_PROFILE
419 /* Profiling uses file and func names similar to breakpoints. */
420 static garray_T prof_ga = {0, 0, sizeof(struct debuggy), 4, NULL};
421 #endif
422 #define DBG_FUNC 1
423 #define DBG_FILE 2
425 static int dbg_parsearg __ARGS((char_u *arg, garray_T *gap));
426 static linenr_T debuggy_find __ARGS((int file,char_u *fname, linenr_T after, garray_T *gap, int *fp));
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.
434 static int
435 dbg_parsearg(arg, gap)
436 char_u *arg;
437 garray_T *gap; /* either &dbg_breakp or &prof_ga */
439 char_u *p = arg;
440 char_u *q;
441 struct debuggy *bp;
442 int here = FALSE;
444 if (ga_grow(gap, 1) == FAIL)
445 return FAIL;
446 bp = &DEBUGGY(gap, gap->ga_len);
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)
459 if (curbuf->b_ffname == NULL)
461 EMSG(_(e_noname));
462 return FAIL;
464 bp->dbg_type = DBG_FILE;
465 here = TRUE;
467 else
469 EMSG2(_(e_invarg2), p);
470 return FAIL;
472 p = skipwhite(p + 4);
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))
483 bp->dbg_lnum = getdigits(&p);
484 p = skipwhite(p);
486 else
487 bp->dbg_lnum = 0;
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))
494 EMSG2(_(e_invarg2), arg);
495 return FAIL;
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
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 != '*')
524 bp->dbg_name = fix_fname(p);
525 vim_free(p);
527 else
528 bp->dbg_name = p;
531 if (bp->dbg_name == NULL)
532 return FAIL;
533 return OK;
537 * ":breakadd".
539 void
540 ex_breakadd(eap)
541 exarg_T *eap;
543 struct debuggy *bp;
544 char_u *pat;
545 garray_T *gap;
547 gap = &dbg_breakp;
548 #ifdef FEAT_PROFILE
549 if (eap->cmdidx == CMD_profile)
550 gap = &prof_ga;
551 #endif
553 if (dbg_parsearg(eap->arg, gap) == OK)
555 bp = &DEBUGGY(gap, gap->ga_len);
556 bp->dbg_forceit = eap->forceit;
558 pat = file_pat_to_reg_pat(bp->dbg_name, NULL, NULL, FALSE);
559 if (pat != NULL)
561 bp->dbg_prog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
562 vim_free(pat);
564 if (pat == NULL || bp->dbg_prog == NULL)
565 vim_free(bp->dbg_name);
566 else
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
574 DEBUGGY(gap, gap->ga_len).dbg_nr = ++last_breakp;
575 ++debug_tick;
577 ++gap->ga_len;
583 * ":debuggreedy".
585 void
586 ex_debuggreedy(eap)
587 exarg_T *eap;
589 if (eap->addr_count == 0 || eap->line2 != 0)
590 debug_greedy = TRUE;
591 else
592 debug_greedy = FALSE;
596 * ":breakdel" and ":profdel".
598 void
599 ex_breakdel(eap)
600 exarg_T *eap;
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;
610 gap = &dbg_breakp;
611 #ifdef FEAT_PROFILE
612 if (eap->cmdidx == CMD_profdel)
613 gap = &prof_ga;
614 #endif
616 if (vim_isdigit(*eap->arg))
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)
623 todel = i;
624 break;
627 else if (*eap->arg == '*')
629 todel = 0;
630 del_all = TRUE;
632 else
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)
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))))
648 todel = i;
649 best_lnum = bpi->dbg_lnum;
652 vim_free(bp->dbg_name);
655 if (todel < 0)
656 EMSG2(_("E161: Breakpoint not found: %s"), eap->arg);
657 else
659 while (gap->ga_len > 0)
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;
675 /* If all breakpoints were removed clear the array. */
676 if (gap->ga_len == 0)
677 ga_clear(gap);
682 * ":breaklist".
684 void
685 ex_breaklist(eap)
686 exarg_T *eap UNUSED;
688 struct debuggy *bp;
689 int i;
691 if (dbg_breakp.ga_len == 0)
692 MSG(_("No breakpoints defined"));
693 else
694 for (i = 0; i < dbg_breakp.ga_len; ++i)
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);
706 * Find a breakpoint for a function or sourced file.
707 * Returns line number at which to break; zero when no matching breakpoint.
709 linenr_T
710 dbg_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 */
715 return debuggy_find(file, fname, after, &dbg_breakp, NULL);
718 #if defined(FEAT_PROFILE) || defined(PROTO)
720 * Return TRUE if profiling is on for a function or sourced file.
723 has_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 */
728 return (debuggy_find(file, fname, (linenr_T)0, &prof_ga, fp)
729 != (linenr_T)0);
731 #endif
734 * Common code for dbg_find_breakpoint() and has_profiling().
736 static linenr_T
737 debuggy_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 */
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;
751 /* Return quickly when there are no breakpoints. */
752 if (gap->ga_len == 0)
753 return (linenr_T)0;
755 /* Replace K_SNR in function name with "<SNR>". */
756 if (!file && fname[0] == K_SPECIAL)
758 name = alloc((unsigned)STRLEN(fname) + 3);
759 if (name == NULL)
760 name = fname;
761 else
763 STRCPY(name, "<SNR>");
764 STRCPY(name + 5, fname + 3);
768 for (i = 0; i < gap->ga_len; ++i)
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)))))
779 regmatch.regprog = bp->dbg_prog;
780 regmatch.rm_ic = FALSE;
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.
786 prev_got_int = got_int;
787 got_int = FALSE;
788 if (vim_regexec(&regmatch, name, (colnr_T)0))
790 lnum = bp->dbg_lnum;
791 if (fp != NULL)
792 *fp = bp->dbg_forceit;
794 got_int |= prev_got_int;
797 if (name != fname)
798 vim_free(name);
800 return lnum;
804 * Called when a breakpoint was encountered.
806 void
807 dbg_breakpoint(name, lnum)
808 char_u *name;
809 linenr_T lnum;
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;
817 # if defined(FEAT_PROFILE) || defined(FEAT_RELTIME) || defined(PROTO)
819 * Store the current time in "tm".
821 void
822 profile_start(tm)
823 proftime_T *tm;
825 # ifdef WIN3264
826 QueryPerformanceCounter(tm);
827 # else
828 gettimeofday(tm, NULL);
829 # endif
833 * Compute the elapsed time from "tm" till now and store in "tm".
835 void
836 profile_end(tm)
837 proftime_T *tm;
839 proftime_T now;
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)
850 tm->tv_usec += 1000000;
851 --tm->tv_sec;
853 # endif
857 * Subtract the time "tm2" from "tm".
859 void
860 profile_sub(tm, tm2)
861 proftime_T *tm, *tm2;
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)
870 tm->tv_usec += 1000000;
871 --tm->tv_sec;
873 # endif
877 * Return a string that represents the time in "tm".
878 * Uses a static buffer!
880 char *
881 profile_msg(tm)
882 proftime_T *tm;
884 static char buf[50];
886 # ifdef WIN3264
887 LARGE_INTEGER fr;
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;
898 * Put the time "msec" past now in "tm".
900 void
901 profile_setlimit(msec, tm)
902 long msec;
903 proftime_T *tm;
905 if (msec <= 0) /* no limit */
906 profile_zero(tm);
907 else
909 # ifdef WIN3264
910 LARGE_INTEGER fr;
912 QueryPerformanceCounter(tm);
913 QueryPerformanceFrequency(&fr);
914 tm->QuadPart += (LONGLONG)((double)msec / 1000.0 * (double)fr.QuadPart);
915 # else
916 long usec;
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
927 * Return TRUE if the current time is past "tm".
930 profile_passed_limit(tm)
931 proftime_T *tm;
933 proftime_T now;
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
950 * Set the time in "tm" to zero.
952 void
953 profile_zero(tm)
954 proftime_T *tm;
956 # ifdef WIN3264
957 tm->QuadPart = 0;
958 # else
959 tm->tv_usec = 0;
960 tm->tv_sec = 0;
961 # endif
964 # endif /* FEAT_PROFILE || FEAT_RELTIME */
966 # if defined(FEAT_PROFILE) || defined(PROTO)
968 * Functions for profiling.
970 static void script_do_profile __ARGS((scriptitem_T *si));
971 static void script_dump_profile __ARGS((FILE *fd));
972 static proftime_T prof_wait_time;
975 * Add the time "tm2" to "tm".
977 void
978 profile_add(tm, tm2)
979 proftime_T *tm, *tm2;
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)
988 tm->tv_usec -= 1000000;
989 ++tm->tv_sec;
991 # endif
995 * Add the "self" time from the total time and the children's time.
997 void
998 profile_self(self, total, children)
999 proftime_T *self, *total, *children;
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);
1017 * Get the current waittime.
1019 void
1020 profile_get_wait(tm)
1021 proftime_T *tm;
1023 *tm = prof_wait_time;
1027 * Subtract the passed waittime since "tm" from "tma".
1029 void
1030 profile_sub_wait(tm, tma)
1031 proftime_T *tm, *tma;
1033 proftime_T tm3 = prof_wait_time;
1035 profile_sub(&tm3, tm);
1036 profile_sub(tma, &tm3);
1040 * Return TRUE if "tm1" and "tm2" are equal.
1043 profile_equal(tm1, tm2)
1044 proftime_T *tm1, *tm2;
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
1054 * Return <0, 0 or >0 if "tm1" < "tm2", "tm1" == "tm2" or "tm1" > "tm2"
1057 profile_cmp(tm1, tm2)
1058 proftime_T *tm1, *tm2;
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
1069 static char_u *profile_fname = NULL;
1070 static proftime_T pause_time;
1073 * ":profile cmd args"
1075 void
1076 ex_profile(eap)
1077 exarg_T *eap;
1079 char_u *e;
1080 int len;
1082 e = skiptowhite(eap->arg);
1083 len = (int)(e - eap->arg);
1084 e = skipwhite(e);
1086 if (len == 5 && STRNCMP(eap->arg, "start", 5) == 0 && *e != NUL)
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);
1094 else if (do_profiling == PROF_NONE)
1095 EMSG(_("E750: First use :profile start <fname>"));
1096 else if (STRCMP(eap->arg, "pause") == 0)
1098 if (do_profiling == PROF_YES)
1099 profile_start(&pause_time);
1100 do_profiling = PROF_PAUSED;
1102 else if (STRCMP(eap->arg, "continue") == 0)
1104 if (do_profiling == PROF_PAUSED)
1106 profile_end(&pause_time);
1107 profile_add(&prof_wait_time, &pause_time);
1109 do_profiling = PROF_YES;
1111 else
1113 /* The rest is similar to ":breakadd". */
1114 ex_breakadd(eap);
1119 * Dump the profiling info.
1121 void
1122 profile_dump()
1124 FILE *fd;
1126 if (profile_fname != NULL)
1128 fd = mch_fopen((char *)profile_fname, "w");
1129 if (fd == NULL)
1130 EMSG2(_(e_notopen), profile_fname);
1131 else
1133 script_dump_profile(fd);
1134 func_dump_profile(fd);
1135 fclose(fd);
1141 * Start profiling script "fp".
1143 static void
1144 script_do_profile(si)
1145 scriptitem_T *si;
1147 si->sn_pr_count = 0;
1148 profile_zero(&si->sn_pr_total);
1149 profile_zero(&si->sn_pr_self);
1151 ga_init2(&si->sn_prl_ga, sizeof(sn_prl_T), 100);
1152 si->sn_prl_idx = -1;
1153 si->sn_prof_on = TRUE;
1154 si->sn_pr_nest = 0;
1158 * save time when starting to invoke another script or function.
1160 void
1161 script_prof_save(tm)
1162 proftime_T *tm; /* place to store wait time */
1164 scriptitem_T *si;
1166 if (current_SID > 0 && current_SID <= script_items.ga_len)
1168 si = &SCRIPT_ITEM(current_SID);
1169 if (si->sn_prof_on && si->sn_pr_nest++ == 0)
1170 profile_start(&si->sn_pr_child);
1172 profile_get_wait(tm);
1176 * Count time spent in children after invoking another script or function.
1178 void
1179 script_prof_restore(tm)
1180 proftime_T *tm;
1182 scriptitem_T *si;
1184 if (current_SID > 0 && current_SID <= script_items.ga_len)
1186 si = &SCRIPT_ITEM(current_SID);
1187 if (si->sn_prof_on && --si->sn_pr_nest == 0)
1189 profile_end(&si->sn_pr_child);
1190 profile_sub_wait(tm, &si->sn_pr_child); /* don't count wait time */
1191 profile_add(&si->sn_pr_children, &si->sn_pr_child);
1192 profile_add(&si->sn_prl_children, &si->sn_pr_child);
1197 static proftime_T inchar_time;
1200 * Called when starting to wait for the user to type a character.
1202 void
1203 prof_inchar_enter()
1205 profile_start(&inchar_time);
1209 * Called when finished waiting for the user to type a character.
1211 void
1212 prof_inchar_exit()
1214 profile_end(&inchar_time);
1215 profile_add(&prof_wait_time, &inchar_time);
1219 * Dump the profiling results for all scripts in file "fd".
1221 static void
1222 script_dump_profile(fd)
1223 FILE *fd;
1225 int id;
1226 scriptitem_T *si;
1227 int i;
1228 FILE *sfd;
1229 sn_prl_T *pp;
1231 for (id = 1; id <= script_items.ga_len; ++id)
1233 si = &SCRIPT_ITEM(id);
1234 if (si->sn_prof_on)
1236 fprintf(fd, "SCRIPT %s\n", si->sn_name);
1237 if (si->sn_pr_count == 1)
1238 fprintf(fd, "Sourced 1 time\n");
1239 else
1240 fprintf(fd, "Sourced %d times\n", si->sn_pr_count);
1241 fprintf(fd, "Total time: %s\n", profile_msg(&si->sn_pr_total));
1242 fprintf(fd, " Self time: %s\n", profile_msg(&si->sn_pr_self));
1243 fprintf(fd, "\n");
1244 fprintf(fd, "count total (s) self (s)\n");
1246 sfd = mch_fopen((char *)si->sn_name, "r");
1247 if (sfd == NULL)
1248 fprintf(fd, "Cannot open file!\n");
1249 else
1251 for (i = 0; i < si->sn_prl_ga.ga_len; ++i)
1253 if (vim_fgets(IObuff, IOSIZE, sfd))
1254 break;
1255 pp = &PRL_ITEM(si, i);
1256 if (pp->snp_count > 0)
1258 fprintf(fd, "%5d ", pp->snp_count);
1259 if (profile_equal(&pp->sn_prl_total, &pp->sn_prl_self))
1260 fprintf(fd, " ");
1261 else
1262 fprintf(fd, "%s ", profile_msg(&pp->sn_prl_total));
1263 fprintf(fd, "%s ", profile_msg(&pp->sn_prl_self));
1265 else
1266 fprintf(fd, " ");
1267 fprintf(fd, "%s", IObuff);
1269 fclose(sfd);
1271 fprintf(fd, "\n");
1277 * Return TRUE when a function defined in the current script should be
1278 * profiled.
1281 prof_def_func()
1283 if (current_SID > 0)
1284 return SCRIPT_ITEM(current_SID).sn_pr_force;
1285 return FALSE;
1288 # endif
1289 #endif
1292 * If 'autowrite' option set, try to write the file.
1293 * Careful: autocommands may make "buf" invalid!
1295 * return FAIL for failure, OK otherwise
1298 autowrite(buf, forceit)
1299 buf_T *buf;
1300 int forceit;
1302 int r;
1304 if (!(p_aw || p_awa) || !p_write
1305 #ifdef FEAT_QUICKFIX
1306 /* never autowrite a "nofile" or "nowrite" buffer */
1307 || bt_dontwrite(buf)
1308 #endif
1309 || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL)
1310 return FAIL;
1311 r = buf_write_all(buf, forceit);
1313 /* Writing may succeed but the buffer still changed, e.g., when there is a
1314 * conversion error. We do want to return FAIL then. */
1315 if (buf_valid(buf) && bufIsChanged(buf))
1316 r = FAIL;
1317 return r;
1321 * flush all buffers, except the ones that are readonly
1323 void
1324 autowrite_all()
1326 buf_T *buf;
1328 if (!(p_aw || p_awa) || !p_write)
1329 return;
1330 for (buf = firstbuf; buf; buf = buf->b_next)
1331 if (bufIsChanged(buf) && !buf->b_p_ro)
1333 (void)buf_write_all(buf, FALSE);
1334 #ifdef FEAT_AUTOCMD
1335 /* an autocommand may have deleted the buffer */
1336 if (!buf_valid(buf))
1337 buf = firstbuf;
1338 #endif
1343 * return TRUE if buffer was changed and cannot be abandoned.
1346 check_changed(buf, checkaw, mult_win, forceit, allbuf)
1347 buf_T *buf;
1348 int checkaw; /* do autowrite if buffer was changed */
1349 int mult_win; /* check also when several wins for the buf */
1350 int forceit;
1351 int allbuf UNUSED; /* may write all buffers */
1353 if ( !forceit
1354 && bufIsChanged(buf)
1355 && (mult_win || buf->b_nwindows <= 1)
1356 && (!checkaw || autowrite(buf, forceit) == FAIL))
1358 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1359 if ((p_confirm || cmdmod.confirm) && p_write)
1361 buf_T *buf2;
1362 int count = 0;
1364 if (allbuf)
1365 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1366 if (bufIsChanged(buf2)
1367 && (buf2->b_ffname != NULL
1368 # ifdef FEAT_BROWSE
1369 || cmdmod.browse
1370 # endif
1372 ++count;
1373 # ifdef FEAT_AUTOCMD
1374 if (!buf_valid(buf))
1375 /* Autocommand deleted buffer, oops! It's not changed now. */
1376 return FALSE;
1377 # endif
1378 dialog_changed(buf, count > 1);
1379 # ifdef FEAT_AUTOCMD
1380 if (!buf_valid(buf))
1381 /* Autocommand deleted buffer, oops! It's not changed now. */
1382 return FALSE;
1383 # endif
1384 return bufIsChanged(buf);
1386 #endif
1387 EMSG(_(e_nowrtmsg));
1388 return TRUE;
1390 return FALSE;
1393 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO)
1395 #if defined(FEAT_BROWSE) || defined(PROTO)
1397 * When wanting to write a file without a file name, ask the user for a name.
1399 void
1400 browse_save_fname(buf)
1401 buf_T *buf;
1403 if (buf->b_fname == NULL)
1405 char_u *fname;
1407 fname = do_browse(BROWSE_SAVE, (char_u *)_("Save As"),
1408 NULL, NULL, NULL, NULL, buf);
1409 if (fname != NULL)
1411 if (setfname(buf, fname, NULL, TRUE) == OK)
1412 buf->b_flags |= BF_NOTEDITED;
1413 vim_free(fname);
1417 #endif
1420 * Ask the user what to do when abondoning a changed buffer.
1421 * Must check 'write' option first!
1423 void
1424 dialog_changed(buf, checkall)
1425 buf_T *buf;
1426 int checkall; /* may abandon all changed buffers */
1428 char_u buff[IOSIZE];
1429 int ret;
1430 buf_T *buf2;
1432 dialog_msg(buff, _("Save changes to \"%s\"?"),
1433 (buf->b_fname != NULL) ?
1434 buf->b_fname : (char_u *)_("Untitled"));
1435 if (checkall)
1436 ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1);
1437 else
1438 ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
1440 if (ret == VIM_YES)
1442 #ifdef FEAT_BROWSE
1443 /* May get file name, when there is none */
1444 browse_save_fname(buf);
1445 #endif
1446 if (buf->b_fname != NULL) /* didn't hit Cancel */
1447 (void)buf_write_all(buf, FALSE);
1449 else if (ret == VIM_NO)
1451 unchanged(buf, TRUE);
1453 else if (ret == VIM_ALL)
1456 * Write all modified files that can be written.
1457 * Skip readonly buffers, these need to be confirmed
1458 * individually.
1460 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1462 if (bufIsChanged(buf2)
1463 && (buf2->b_ffname != NULL
1464 #ifdef FEAT_BROWSE
1465 || cmdmod.browse
1466 #endif
1468 && !buf2->b_p_ro)
1470 #ifdef FEAT_BROWSE
1471 /* May get file name, when there is none */
1472 browse_save_fname(buf2);
1473 #endif
1474 if (buf2->b_fname != NULL) /* didn't hit Cancel */
1475 (void)buf_write_all(buf2, FALSE);
1476 #ifdef FEAT_AUTOCMD
1477 /* an autocommand may have deleted the buffer */
1478 if (!buf_valid(buf2))
1479 buf2 = firstbuf;
1480 #endif
1484 else if (ret == VIM_DISCARDALL)
1487 * mark all buffers as unchanged
1489 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1490 unchanged(buf2, TRUE);
1493 #endif
1496 * Return TRUE if the buffer "buf" can be abandoned, either by making it
1497 * hidden, autowriting it or unloading it.
1500 can_abandon(buf, forceit)
1501 buf_T *buf;
1502 int forceit;
1504 return ( P_HID(buf)
1505 || !bufIsChanged(buf)
1506 || buf->b_nwindows > 1
1507 || autowrite(buf, forceit) == OK
1508 || forceit);
1512 * Return TRUE if any buffer was changed and cannot be abandoned.
1513 * That changed buffer becomes the current buffer.
1516 check_changed_any(hidden)
1517 int hidden; /* Only check hidden buffers */
1519 buf_T *buf;
1520 int save;
1521 #ifdef FEAT_WINDOWS
1522 win_T *wp;
1523 #endif
1525 for (;;)
1527 /* check curbuf first: if it was changed we can't abandon it */
1528 if (!hidden && curbufIsChanged())
1529 buf = curbuf;
1530 else
1532 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
1533 if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf))
1534 break;
1536 if (buf == NULL) /* No buffers changed */
1537 return FALSE;
1539 /* Try auto-writing the buffer. If this fails but the buffer no
1540 * longer exists it's not changed, that's OK. */
1541 if (check_changed(buf, p_awa, TRUE, FALSE, TRUE) && buf_valid(buf))
1542 break; /* didn't save - still changes */
1545 exiting = FALSE;
1546 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1548 * When ":confirm" used, don't give an error message.
1550 if (!(p_confirm || cmdmod.confirm))
1551 #endif
1553 /* There must be a wait_return for this message, do_buffer()
1554 * may cause a redraw. But wait_return() is a no-op when vgetc()
1555 * is busy (Quit used from window menu), then make sure we don't
1556 * cause a scroll up. */
1557 if (vgetc_busy > 0)
1559 msg_row = cmdline_row;
1560 msg_col = 0;
1561 msg_didout = FALSE;
1563 if (EMSG2(_("E162: No write since last change for buffer \"%s\""),
1564 buf_spname(buf) != NULL ? (char_u *)buf_spname(buf) :
1565 buf->b_fname))
1567 save = no_wait_return;
1568 no_wait_return = FALSE;
1569 wait_return(FALSE);
1570 no_wait_return = save;
1574 #ifdef FEAT_WINDOWS
1575 /* Try to find a window that contains the buffer. */
1576 if (buf != curbuf)
1577 for (wp = firstwin; wp != NULL; wp = wp->w_next)
1578 if (wp->w_buffer == buf)
1580 win_goto(wp);
1581 # ifdef FEAT_AUTOCMD
1582 /* Paranoia: did autocms wipe out the buffer with changes? */
1583 if (!buf_valid(buf))
1584 return TRUE;
1585 # endif
1586 break;
1588 #endif
1590 /* Open the changed buffer in the current window. */
1591 if (buf != curbuf)
1592 set_curbuf(buf, DOBUF_GOTO);
1594 return TRUE;
1598 * return FAIL if there is no file name, OK if there is one
1599 * give error message for FAIL
1602 check_fname()
1604 if (curbuf->b_ffname == NULL)
1606 EMSG(_(e_noname));
1607 return FAIL;
1609 return OK;
1613 * flush the contents of a buffer, unless it has no file name
1615 * return FAIL for failure, OK otherwise
1618 buf_write_all(buf, forceit)
1619 buf_T *buf;
1620 int forceit;
1622 int retval;
1623 #ifdef FEAT_AUTOCMD
1624 buf_T *old_curbuf = curbuf;
1625 #endif
1627 retval = (buf_write(buf, buf->b_ffname, buf->b_fname,
1628 (linenr_T)1, buf->b_ml.ml_line_count, NULL,
1629 FALSE, forceit, TRUE, FALSE));
1630 #ifdef FEAT_AUTOCMD
1631 if (curbuf != old_curbuf)
1633 msg_source(hl_attr(HLF_W));
1634 MSG(_("Warning: Entered other buffer unexpectedly (check autocommands)"));
1636 #endif
1637 return retval;
1641 * Code to handle the argument list.
1644 static char_u *do_one_arg __ARGS((char_u *str));
1645 static int do_arglist __ARGS((char_u *str, int what, int after));
1646 static void alist_check_arg_idx __ARGS((void));
1647 static int editing_arg_idx __ARGS((win_T *win));
1648 #ifdef FEAT_LISTCMDS
1649 static int alist_add_list __ARGS((int count, char_u **files, int after));
1650 #endif
1651 #define AL_SET 1
1652 #define AL_ADD 2
1653 #define AL_DEL 3
1656 * Isolate one argument, taking backticks.
1657 * Changes the argument in-place, puts a NUL after it. Backticks remain.
1658 * Return a pointer to the start of the next argument.
1660 static char_u *
1661 do_one_arg(str)
1662 char_u *str;
1664 char_u *p;
1665 int inbacktick;
1667 inbacktick = FALSE;
1668 for (p = str; *str; ++str)
1670 /* When the backslash is used for escaping the special meaning of a
1671 * character we need to keep it until wildcard expansion. */
1672 if (rem_backslash(str))
1674 *p++ = *str++;
1675 *p++ = *str;
1677 else
1679 /* An item ends at a space not in backticks */
1680 if (!inbacktick && vim_isspace(*str))
1681 break;
1682 if (*str == '`')
1683 inbacktick ^= TRUE;
1684 *p++ = *str;
1687 str = skipwhite(str);
1688 *p = NUL;
1690 return str;
1694 * Separate the arguments in "str" and return a list of pointers in the
1695 * growarray "gap".
1698 get_arglist(gap, str)
1699 garray_T *gap;
1700 char_u *str;
1702 ga_init2(gap, (int)sizeof(char_u *), 20);
1703 while (*str != NUL)
1705 if (ga_grow(gap, 1) == FAIL)
1707 ga_clear(gap);
1708 return FAIL;
1710 ((char_u **)gap->ga_data)[gap->ga_len++] = str;
1712 /* Isolate one argument, change it in-place, put a NUL after it. */
1713 str = do_one_arg(str);
1715 return OK;
1718 #if defined(FEAT_QUICKFIX) || defined(FEAT_SYN_HL) || defined(PROTO)
1720 * Parse a list of arguments (file names), expand them and return in
1721 * "fnames[fcountp]".
1722 * Return FAIL or OK.
1725 get_arglist_exp(str, fcountp, fnamesp)
1726 char_u *str;
1727 int *fcountp;
1728 char_u ***fnamesp;
1730 garray_T ga;
1731 int i;
1733 if (get_arglist(&ga, str) == FAIL)
1734 return FAIL;
1735 i = gen_expand_wildcards(ga.ga_len, (char_u **)ga.ga_data,
1736 fcountp, fnamesp, EW_FILE|EW_NOTFOUND);
1737 ga_clear(&ga);
1738 return i;
1740 #endif
1742 #if defined(FEAT_GUI) || defined(FEAT_CLIENTSERVER) || defined(PROTO)
1744 * Redefine the argument list.
1746 void
1747 set_arglist(str)
1748 char_u *str;
1750 do_arglist(str, AL_SET, 0);
1752 #endif
1755 * "what" == AL_SET: Redefine the argument list to 'str'.
1756 * "what" == AL_ADD: add files in 'str' to the argument list after "after".
1757 * "what" == AL_DEL: remove files in 'str' from the argument list.
1759 * Return FAIL for failure, OK otherwise.
1761 static int
1762 do_arglist(str, what, after)
1763 char_u *str;
1764 int what UNUSED;
1765 int after UNUSED; /* 0 means before first one */
1767 garray_T new_ga;
1768 int exp_count;
1769 char_u **exp_files;
1770 int i;
1771 #ifdef FEAT_LISTCMDS
1772 char_u *p;
1773 int match;
1774 #endif
1777 * Collect all file name arguments in "new_ga".
1779 if (get_arglist(&new_ga, str) == FAIL)
1780 return FAIL;
1782 #ifdef FEAT_LISTCMDS
1783 if (what == AL_DEL)
1785 regmatch_T regmatch;
1786 int didone;
1789 * Delete the items: use each item as a regexp and find a match in the
1790 * argument list.
1792 #ifdef CASE_INSENSITIVE_FILENAME
1793 regmatch.rm_ic = TRUE; /* Always ignore case */
1794 #else
1795 regmatch.rm_ic = FALSE; /* Never ignore case */
1796 #endif
1797 for (i = 0; i < new_ga.ga_len && !got_int; ++i)
1799 p = ((char_u **)new_ga.ga_data)[i];
1800 p = file_pat_to_reg_pat(p, NULL, NULL, FALSE);
1801 if (p == NULL)
1802 break;
1803 regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0);
1804 if (regmatch.regprog == NULL)
1806 vim_free(p);
1807 break;
1810 didone = FALSE;
1811 for (match = 0; match < ARGCOUNT; ++match)
1812 if (vim_regexec(&regmatch, alist_name(&ARGLIST[match]),
1813 (colnr_T)0))
1815 didone = TRUE;
1816 vim_free(ARGLIST[match].ae_fname);
1817 mch_memmove(ARGLIST + match, ARGLIST + match + 1,
1818 (ARGCOUNT - match - 1) * sizeof(aentry_T));
1819 --ALIST(curwin)->al_ga.ga_len;
1820 if (curwin->w_arg_idx > match)
1821 --curwin->w_arg_idx;
1822 --match;
1825 vim_free(regmatch.regprog);
1826 vim_free(p);
1827 if (!didone)
1828 EMSG2(_(e_nomatch2), ((char_u **)new_ga.ga_data)[i]);
1830 ga_clear(&new_ga);
1832 else
1833 #endif
1835 i = expand_wildcards(new_ga.ga_len, (char_u **)new_ga.ga_data,
1836 &exp_count, &exp_files, EW_DIR|EW_FILE|EW_ADDSLASH|EW_NOTFOUND);
1837 ga_clear(&new_ga);
1838 if (i == FAIL)
1839 return FAIL;
1840 if (exp_count == 0)
1842 EMSG(_(e_nomatch));
1843 return FAIL;
1846 #ifdef FEAT_LISTCMDS
1847 if (what == AL_ADD)
1849 (void)alist_add_list(exp_count, exp_files, after);
1850 vim_free(exp_files);
1852 else /* what == AL_SET */
1853 #endif
1854 alist_set(ALIST(curwin), exp_count, exp_files, FALSE, NULL, 0);
1857 alist_check_arg_idx();
1859 return OK;
1863 * Check the validity of the arg_idx for each other window.
1865 static void
1866 alist_check_arg_idx()
1868 #ifdef FEAT_WINDOWS
1869 win_T *win;
1870 tabpage_T *tp;
1872 FOR_ALL_TAB_WINDOWS(tp, win)
1873 if (win->w_alist == curwin->w_alist)
1874 check_arg_idx(win);
1875 #else
1876 check_arg_idx(curwin);
1877 #endif
1881 * Return TRUE if window "win" is editing then file at the current argument
1882 * index.
1884 static int
1885 editing_arg_idx(win)
1886 win_T *win;
1888 return !(win->w_arg_idx >= WARGCOUNT(win)
1889 || (win->w_buffer->b_fnum
1890 != WARGLIST(win)[win->w_arg_idx].ae_fnum
1891 && (win->w_buffer->b_ffname == NULL
1892 || !(fullpathcmp(
1893 alist_name(&WARGLIST(win)[win->w_arg_idx]),
1894 win->w_buffer->b_ffname, TRUE) & FPC_SAME))));
1898 * Check if window "win" is editing the w_arg_idx file in its argument list.
1900 void
1901 check_arg_idx(win)
1902 win_T *win;
1904 if (WARGCOUNT(win) > 1 && !editing_arg_idx(win))
1906 /* We are not editing the current entry in the argument list.
1907 * Set "arg_had_last" if we are editing the last one. */
1908 win->w_arg_idx_invalid = TRUE;
1909 if (win->w_arg_idx != WARGCOUNT(win) - 1
1910 && arg_had_last == FALSE
1911 #ifdef FEAT_WINDOWS
1912 && ALIST(win) == &global_alist
1913 #endif
1914 && GARGCOUNT > 0
1915 && win->w_arg_idx < GARGCOUNT
1916 && (win->w_buffer->b_fnum == GARGLIST[GARGCOUNT - 1].ae_fnum
1917 || (win->w_buffer->b_ffname != NULL
1918 && (fullpathcmp(alist_name(&GARGLIST[GARGCOUNT - 1]),
1919 win->w_buffer->b_ffname, TRUE) & FPC_SAME))))
1920 arg_had_last = TRUE;
1922 else
1924 /* We are editing the current entry in the argument list.
1925 * Set "arg_had_last" if it's also the last one */
1926 win->w_arg_idx_invalid = FALSE;
1927 if (win->w_arg_idx == WARGCOUNT(win) - 1
1928 #ifdef FEAT_WINDOWS
1929 && win->w_alist == &global_alist
1930 #endif
1932 arg_had_last = TRUE;
1937 * ":args", ":argslocal" and ":argsglobal".
1939 void
1940 ex_args(eap)
1941 exarg_T *eap;
1943 int i;
1945 if (eap->cmdidx != CMD_args)
1947 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
1948 alist_unlink(ALIST(curwin));
1949 if (eap->cmdidx == CMD_argglobal)
1950 ALIST(curwin) = &global_alist;
1951 else /* eap->cmdidx == CMD_arglocal */
1952 alist_new();
1953 #else
1954 ex_ni(eap);
1955 return;
1956 #endif
1959 if (!ends_excmd(*eap->arg))
1962 * ":args file ..": define new argument list, handle like ":next"
1963 * Also for ":argslocal file .." and ":argsglobal file ..".
1965 ex_next(eap);
1967 else
1968 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
1969 if (eap->cmdidx == CMD_args)
1970 #endif
1973 * ":args": list arguments.
1975 if (ARGCOUNT > 0)
1977 /* Overwrite the command, for a short list there is no scrolling
1978 * required and no wait_return(). */
1979 gotocmdline(TRUE);
1980 for (i = 0; i < ARGCOUNT; ++i)
1982 if (i == curwin->w_arg_idx)
1983 msg_putchar('[');
1984 msg_outtrans(alist_name(&ARGLIST[i]));
1985 if (i == curwin->w_arg_idx)
1986 msg_putchar(']');
1987 msg_putchar(' ');
1991 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
1992 else if (eap->cmdidx == CMD_arglocal)
1994 garray_T *gap = &curwin->w_alist->al_ga;
1997 * ":argslocal": make a local copy of the global argument list.
1999 if (ga_grow(gap, GARGCOUNT) == OK)
2000 for (i = 0; i < GARGCOUNT; ++i)
2001 if (GARGLIST[i].ae_fname != NULL)
2003 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fname =
2004 vim_strsave(GARGLIST[i].ae_fname);
2005 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fnum =
2006 GARGLIST[i].ae_fnum;
2007 ++gap->ga_len;
2010 #endif
2014 * ":previous", ":sprevious", ":Next" and ":sNext".
2016 void
2017 ex_previous(eap)
2018 exarg_T *eap;
2020 /* If past the last one already, go to the last one. */
2021 if (curwin->w_arg_idx - (int)eap->line2 >= ARGCOUNT)
2022 do_argfile(eap, ARGCOUNT - 1);
2023 else
2024 do_argfile(eap, curwin->w_arg_idx - (int)eap->line2);
2028 * ":rewind", ":first", ":sfirst" and ":srewind".
2030 void
2031 ex_rewind(eap)
2032 exarg_T *eap;
2034 do_argfile(eap, 0);
2038 * ":last" and ":slast".
2040 void
2041 ex_last(eap)
2042 exarg_T *eap;
2044 do_argfile(eap, ARGCOUNT - 1);
2048 * ":argument" and ":sargument".
2050 void
2051 ex_argument(eap)
2052 exarg_T *eap;
2054 int i;
2056 if (eap->addr_count > 0)
2057 i = eap->line2 - 1;
2058 else
2059 i = curwin->w_arg_idx;
2060 do_argfile(eap, i);
2064 * Edit file "argn" of the argument lists.
2066 void
2067 do_argfile(eap, argn)
2068 exarg_T *eap;
2069 int argn;
2071 int other;
2072 char_u *p;
2073 int old_arg_idx = curwin->w_arg_idx;
2075 if (argn < 0 || argn >= ARGCOUNT)
2077 if (ARGCOUNT <= 1)
2078 EMSG(_("E163: There is only one file to edit"));
2079 else if (argn < 0)
2080 EMSG(_("E164: Cannot go before first file"));
2081 else
2082 EMSG(_("E165: Cannot go beyond last file"));
2084 else
2086 setpcmark();
2087 #ifdef FEAT_GUI
2088 need_mouse_correct = TRUE;
2089 #endif
2091 #ifdef FEAT_WINDOWS
2092 /* split window or create new tab page first */
2093 if (*eap->cmd == 's' || cmdmod.tab != 0)
2095 if (win_split(0, 0) == FAIL)
2096 return;
2097 # ifdef FEAT_SCROLLBIND
2098 curwin->w_p_scb = FALSE;
2099 # endif
2101 else
2102 #endif
2105 * if 'hidden' set, only check for changed file when re-editing
2106 * the same buffer
2108 other = TRUE;
2109 if (P_HID(curbuf))
2111 p = fix_fname(alist_name(&ARGLIST[argn]));
2112 other = otherfile(p);
2113 vim_free(p);
2115 if ((!P_HID(curbuf) || !other)
2116 && check_changed(curbuf, TRUE, !other, eap->forceit, FALSE))
2117 return;
2120 curwin->w_arg_idx = argn;
2121 if (argn == ARGCOUNT - 1
2122 #ifdef FEAT_WINDOWS
2123 && curwin->w_alist == &global_alist
2124 #endif
2126 arg_had_last = TRUE;
2128 /* Edit the file; always use the last known line number.
2129 * When it fails (e.g. Abort for already edited file) restore the
2130 * argument index. */
2131 if (do_ecmd(0, alist_name(&ARGLIST[curwin->w_arg_idx]), NULL,
2132 eap, ECMD_LAST,
2133 (P_HID(curwin->w_buffer) ? ECMD_HIDE : 0)
2134 + (eap->forceit ? ECMD_FORCEIT : 0), curwin) == FAIL)
2135 curwin->w_arg_idx = old_arg_idx;
2136 /* like Vi: set the mark where the cursor is in the file. */
2137 else if (eap->cmdidx != CMD_argdo)
2138 setmark('\'');
2143 * ":next", and commands that behave like it.
2145 void
2146 ex_next(eap)
2147 exarg_T *eap;
2149 int i;
2152 * check for changed buffer now, if this fails the argument list is not
2153 * redefined.
2155 if ( P_HID(curbuf)
2156 || eap->cmdidx == CMD_snext
2157 || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
2159 if (*eap->arg != NUL) /* redefine file list */
2161 if (do_arglist(eap->arg, AL_SET, 0) == FAIL)
2162 return;
2163 i = 0;
2165 else
2166 i = curwin->w_arg_idx + (int)eap->line2;
2167 do_argfile(eap, i);
2171 #ifdef FEAT_LISTCMDS
2173 * ":argedit"
2175 void
2176 ex_argedit(eap)
2177 exarg_T *eap;
2179 int fnum;
2180 int i;
2181 char_u *s;
2183 /* Add the argument to the buffer list and get the buffer number. */
2184 fnum = buflist_add(eap->arg, BLN_LISTED);
2186 /* Check if this argument is already in the argument list. */
2187 for (i = 0; i < ARGCOUNT; ++i)
2188 if (ARGLIST[i].ae_fnum == fnum)
2189 break;
2190 if (i == ARGCOUNT)
2192 /* Can't find it, add it to the argument list. */
2193 s = vim_strsave(eap->arg);
2194 if (s == NULL)
2195 return;
2196 i = alist_add_list(1, &s,
2197 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
2198 if (i < 0)
2199 return;
2200 curwin->w_arg_idx = i;
2203 alist_check_arg_idx();
2205 /* Edit the argument. */
2206 do_argfile(eap, i);
2210 * ":argadd"
2212 void
2213 ex_argadd(eap)
2214 exarg_T *eap;
2216 do_arglist(eap->arg, AL_ADD,
2217 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
2218 #ifdef FEAT_TITLE
2219 maketitle();
2220 #endif
2224 * ":argdelete"
2226 void
2227 ex_argdelete(eap)
2228 exarg_T *eap;
2230 int i;
2231 int n;
2233 if (eap->addr_count > 0)
2235 /* ":1,4argdel": Delete all arguments in the range. */
2236 if (eap->line2 > ARGCOUNT)
2237 eap->line2 = ARGCOUNT;
2238 n = eap->line2 - eap->line1 + 1;
2239 if (*eap->arg != NUL || n <= 0)
2240 EMSG(_(e_invarg));
2241 else
2243 for (i = eap->line1; i <= eap->line2; ++i)
2244 vim_free(ARGLIST[i - 1].ae_fname);
2245 mch_memmove(ARGLIST + eap->line1 - 1, ARGLIST + eap->line2,
2246 (size_t)((ARGCOUNT - eap->line2) * sizeof(aentry_T)));
2247 ALIST(curwin)->al_ga.ga_len -= n;
2248 if (curwin->w_arg_idx >= eap->line2)
2249 curwin->w_arg_idx -= n;
2250 else if (curwin->w_arg_idx > eap->line1)
2251 curwin->w_arg_idx = eap->line1;
2254 else if (*eap->arg == NUL)
2255 EMSG(_(e_argreq));
2256 else
2257 do_arglist(eap->arg, AL_DEL, 0);
2258 #ifdef FEAT_TITLE
2259 maketitle();
2260 #endif
2264 * ":argdo", ":windo", ":bufdo", ":tabdo"
2266 void
2267 ex_listdo(eap)
2268 exarg_T *eap;
2270 int i;
2271 #ifdef FEAT_WINDOWS
2272 win_T *wp;
2273 tabpage_T *tp;
2274 #endif
2275 buf_T *buf;
2276 int next_fnum = 0;
2277 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2278 char_u *save_ei = NULL;
2279 #endif
2280 char_u *p_shm_save;
2282 #ifndef FEAT_WINDOWS
2283 if (eap->cmdidx == CMD_windo)
2285 ex_ni(eap);
2286 return;
2288 #endif
2290 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2291 if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo)
2292 /* Don't do syntax HL autocommands. Skipping the syntax file is a
2293 * great speed improvement. */
2294 save_ei = au_event_disable(",Syntax");
2295 #endif
2297 if (eap->cmdidx == CMD_windo
2298 || eap->cmdidx == CMD_tabdo
2299 || P_HID(curbuf)
2300 || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
2302 /* start at the first argument/window/buffer */
2303 i = 0;
2304 #ifdef FEAT_WINDOWS
2305 wp = firstwin;
2306 tp = first_tabpage;
2307 #endif
2308 /* set pcmark now */
2309 if (eap->cmdidx == CMD_bufdo)
2310 goto_buffer(eap, DOBUF_FIRST, FORWARD, 0);
2311 else
2312 setpcmark();
2313 listcmd_busy = TRUE; /* avoids setting pcmark below */
2315 while (!got_int)
2317 if (eap->cmdidx == CMD_argdo)
2319 /* go to argument "i" */
2320 if (i == ARGCOUNT)
2321 break;
2322 /* Don't call do_argfile() when already there, it will try
2323 * reloading the file. */
2324 if (curwin->w_arg_idx != i || !editing_arg_idx(curwin))
2326 /* Clear 'shm' to avoid that the file message overwrites
2327 * any output from the command. */
2328 p_shm_save = vim_strsave(p_shm);
2329 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
2330 do_argfile(eap, i);
2331 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
2332 vim_free(p_shm_save);
2334 if (curwin->w_arg_idx != i)
2335 break;
2336 ++i;
2338 #ifdef FEAT_WINDOWS
2339 else if (eap->cmdidx == CMD_windo)
2341 /* go to window "wp" */
2342 if (!win_valid(wp))
2343 break;
2344 win_goto(wp);
2345 if (curwin != wp)
2346 break; /* something must be wrong */
2347 wp = curwin->w_next;
2349 else if (eap->cmdidx == CMD_tabdo)
2351 /* go to window "tp" */
2352 if (!valid_tabpage(tp))
2353 break;
2354 goto_tabpage_tp(tp);
2355 tp = tp->tp_next;
2357 #endif
2358 else if (eap->cmdidx == CMD_bufdo)
2360 /* Remember the number of the next listed buffer, in case
2361 * ":bwipe" is used or autocommands do something strange. */
2362 next_fnum = -1;
2363 for (buf = curbuf->b_next; buf != NULL; buf = buf->b_next)
2364 if (buf->b_p_bl)
2366 next_fnum = buf->b_fnum;
2367 break;
2371 /* execute the command */
2372 do_cmdline(eap->arg, eap->getline, eap->cookie,
2373 DOCMD_VERBOSE + DOCMD_NOWAIT);
2375 if (eap->cmdidx == CMD_bufdo)
2377 /* Done? */
2378 if (next_fnum < 0)
2379 break;
2380 /* Check if the buffer still exists. */
2381 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
2382 if (buf->b_fnum == next_fnum)
2383 break;
2384 if (buf == NULL)
2385 break;
2387 /* Go to the next buffer. Clear 'shm' to avoid that the file
2388 * message overwrites any output from the command. */
2389 p_shm_save = vim_strsave(p_shm);
2390 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
2391 goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
2392 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
2393 vim_free(p_shm_save);
2395 /* If autocommands took us elsewhere, quit here */
2396 if (curbuf->b_fnum != next_fnum)
2397 break;
2400 if (eap->cmdidx == CMD_windo)
2402 validate_cursor(); /* cursor may have moved */
2403 #ifdef FEAT_SCROLLBIND
2404 /* required when 'scrollbind' has been set */
2405 if (curwin->w_p_scb)
2406 do_check_scrollbind(TRUE);
2407 #endif
2410 listcmd_busy = FALSE;
2413 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2414 if (save_ei != NULL)
2416 au_event_restore(save_ei);
2417 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
2418 curbuf->b_fname, TRUE, curbuf);
2420 #endif
2424 * Add files[count] to the arglist of the current window after arg "after".
2425 * The file names in files[count] must have been allocated and are taken over.
2426 * Files[] itself is not taken over.
2427 * Returns index of first added argument. Returns -1 when failed (out of mem).
2429 static int
2430 alist_add_list(count, files, after)
2431 int count;
2432 char_u **files;
2433 int after; /* where to add: 0 = before first one */
2435 int i;
2437 if (ga_grow(&ALIST(curwin)->al_ga, count) == OK)
2439 if (after < 0)
2440 after = 0;
2441 if (after > ARGCOUNT)
2442 after = ARGCOUNT;
2443 if (after < ARGCOUNT)
2444 mch_memmove(&(ARGLIST[after + count]), &(ARGLIST[after]),
2445 (ARGCOUNT - after) * sizeof(aentry_T));
2446 for (i = 0; i < count; ++i)
2448 ARGLIST[after + i].ae_fname = files[i];
2449 ARGLIST[after + i].ae_fnum = buflist_add(files[i], BLN_LISTED);
2451 ALIST(curwin)->al_ga.ga_len += count;
2452 if (curwin->w_arg_idx >= after)
2453 ++curwin->w_arg_idx;
2454 return after;
2457 for (i = 0; i < count; ++i)
2458 vim_free(files[i]);
2459 return -1;
2462 #endif /* FEAT_LISTCMDS */
2464 #ifdef FEAT_EVAL
2466 * ":compiler[!] {name}"
2468 void
2469 ex_compiler(eap)
2470 exarg_T *eap;
2472 char_u *buf;
2473 char_u *old_cur_comp = NULL;
2474 char_u *p;
2476 if (*eap->arg == NUL)
2478 /* List all compiler scripts. */
2479 do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')");
2480 /* ) keep the indenter happy... */
2482 else
2484 buf = alloc((unsigned)(STRLEN(eap->arg) + 14));
2485 if (buf != NULL)
2487 if (eap->forceit)
2489 /* ":compiler! {name}" sets global options */
2490 do_cmdline_cmd((char_u *)
2491 "command -nargs=* CompilerSet set <args>");
2493 else
2495 /* ":compiler! {name}" sets local options.
2496 * To remain backwards compatible "current_compiler" is always
2497 * used. A user's compiler plugin may set it, the distributed
2498 * plugin will then skip the settings. Afterwards set
2499 * "b:current_compiler" and restore "current_compiler".
2500 * Explicitly prepend "g:" to make it work in a function. */
2501 old_cur_comp = get_var_value((char_u *)"g:current_compiler");
2502 if (old_cur_comp != NULL)
2503 old_cur_comp = vim_strsave(old_cur_comp);
2504 do_cmdline_cmd((char_u *)
2505 "command -nargs=* CompilerSet setlocal <args>");
2507 do_unlet((char_u *)"g:current_compiler", TRUE);
2508 do_unlet((char_u *)"b:current_compiler", TRUE);
2510 sprintf((char *)buf, "compiler/%s.vim", eap->arg);
2511 if (source_runtime(buf, TRUE) == FAIL)
2512 EMSG2(_("E666: compiler not supported: %s"), eap->arg);
2513 vim_free(buf);
2515 do_cmdline_cmd((char_u *)":delcommand CompilerSet");
2517 /* Set "b:current_compiler" from "current_compiler". */
2518 p = get_var_value((char_u *)"g:current_compiler");
2519 if (p != NULL)
2520 set_internal_string_var((char_u *)"b:current_compiler", p);
2522 /* Restore "current_compiler" for ":compiler {name}". */
2523 if (!eap->forceit)
2525 if (old_cur_comp != NULL)
2527 set_internal_string_var((char_u *)"g:current_compiler",
2528 old_cur_comp);
2529 vim_free(old_cur_comp);
2531 else
2532 do_unlet((char_u *)"g:current_compiler", TRUE);
2537 #endif
2540 * ":runtime {name}"
2542 void
2543 ex_runtime(eap)
2544 exarg_T *eap;
2546 source_runtime(eap->arg, eap->forceit);
2549 static void source_callback __ARGS((char_u *fname, void *cookie));
2551 static void
2552 source_callback(fname, cookie)
2553 char_u *fname;
2554 void *cookie UNUSED;
2556 (void)do_source(fname, FALSE, DOSO_NONE);
2560 * Source the file "name" from all directories in 'runtimepath'.
2561 * "name" can contain wildcards.
2562 * When "all" is TRUE, source all files, otherwise only the first one.
2563 * return FAIL when no file could be sourced, OK otherwise.
2566 source_runtime(name, all)
2567 char_u *name;
2568 int all;
2570 return do_in_runtimepath(name, all, source_callback, NULL);
2574 * Find "name" in 'runtimepath'. When found, invoke the callback function for
2575 * it: callback(fname, "cookie")
2576 * When "all" is TRUE repeat for all matches, otherwise only the first one is
2577 * used.
2578 * Returns OK when at least one match found, FAIL otherwise.
2581 do_in_runtimepath(name, all, callback, cookie)
2582 char_u *name;
2583 int all;
2584 void (*callback)__ARGS((char_u *fname, void *ck));
2585 void *cookie;
2587 char_u *rtp;
2588 char_u *np;
2589 char_u *buf;
2590 char_u *rtp_copy;
2591 char_u *tail;
2592 int num_files;
2593 char_u **files;
2594 int i;
2595 int did_one = FALSE;
2596 #ifdef AMIGA
2597 struct Process *proc = (struct Process *)FindTask(0L);
2598 APTR save_winptr = proc->pr_WindowPtr;
2600 /* Avoid a requester here for a volume that doesn't exist. */
2601 proc->pr_WindowPtr = (APTR)-1L;
2602 #endif
2604 /* Make a copy of 'runtimepath'. Invoking the callback may change the
2605 * value. */
2606 rtp_copy = vim_strsave(p_rtp);
2607 buf = alloc(MAXPATHL);
2608 if (buf != NULL && rtp_copy != NULL)
2610 if (p_verbose > 1)
2612 verbose_enter();
2613 smsg((char_u *)_("Searching for \"%s\" in \"%s\""),
2614 (char *)name, (char *)p_rtp);
2615 verbose_leave();
2618 /* Loop over all entries in 'runtimepath'. */
2619 rtp = rtp_copy;
2620 while (*rtp != NUL && (all || !did_one))
2622 /* Copy the path from 'runtimepath' to buf[]. */
2623 copy_option_part(&rtp, buf, MAXPATHL, ",");
2624 if (STRLEN(buf) + STRLEN(name) + 2 < MAXPATHL)
2626 add_pathsep(buf);
2627 tail = buf + STRLEN(buf);
2629 /* Loop over all patterns in "name" */
2630 np = name;
2631 while (*np != NUL && (all || !did_one))
2633 /* Append the pattern from "name" to buf[]. */
2634 copy_option_part(&np, tail, (int)(MAXPATHL - (tail - buf)),
2635 "\t ");
2637 if (p_verbose > 2)
2639 verbose_enter();
2640 smsg((char_u *)_("Searching for \"%s\""), buf);
2641 verbose_leave();
2644 /* Expand wildcards, invoke the callback for each match. */
2645 if (gen_expand_wildcards(1, &buf, &num_files, &files,
2646 EW_FILE) == OK)
2648 for (i = 0; i < num_files; ++i)
2650 (*callback)(files[i], cookie);
2651 did_one = TRUE;
2652 if (!all)
2653 break;
2655 FreeWild(num_files, files);
2661 vim_free(buf);
2662 vim_free(rtp_copy);
2663 if (p_verbose > 0 && !did_one)
2665 verbose_enter();
2666 smsg((char_u *)_("not found in 'runtimepath': \"%s\""), name);
2667 verbose_leave();
2670 #ifdef AMIGA
2671 proc->pr_WindowPtr = save_winptr;
2672 #endif
2674 return did_one ? OK : FAIL;
2677 #if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD)
2679 * ":options"
2681 void
2682 ex_options(eap)
2683 exarg_T *eap UNUSED;
2685 cmd_source((char_u *)SYS_OPTWIN_FILE, NULL);
2687 #endif
2690 * ":source {fname}"
2692 void
2693 ex_source(eap)
2694 exarg_T *eap;
2696 #ifdef FEAT_BROWSE
2697 if (cmdmod.browse)
2699 char_u *fname = NULL;
2701 fname = do_browse(0, (char_u *)_("Source Vim script"), eap->arg,
2702 NULL, NULL, BROWSE_FILTER_MACROS, NULL);
2703 if (fname != NULL)
2705 cmd_source(fname, eap);
2706 vim_free(fname);
2709 else
2710 #endif
2711 cmd_source(eap->arg, eap);
2714 static void
2715 cmd_source(fname, eap)
2716 char_u *fname;
2717 exarg_T *eap;
2719 if (*fname == NUL)
2720 EMSG(_(e_argreq));
2722 else if (eap != NULL && eap->forceit)
2723 /* ":source!": read Normal mdoe commands
2724 * Need to execute the commands directly. This is required at least
2725 * for:
2726 * - ":g" command busy
2727 * - after ":argdo", ":windo" or ":bufdo"
2728 * - another command follows
2729 * - inside a loop
2731 openscript(fname, global_busy || listcmd_busy || eap->nextcmd != NULL
2732 #ifdef FEAT_EVAL
2733 || eap->cstack->cs_idx >= 0
2734 #endif
2737 /* ":source" read ex commands */
2738 else if (do_source(fname, FALSE, DOSO_NONE) == FAIL)
2739 EMSG2(_(e_notopen), fname);
2743 * ":source" and associated commands.
2746 * Structure used to store info for each sourced file.
2747 * It is shared between do_source() and getsourceline().
2748 * This is required, because it needs to be handed to do_cmdline() and
2749 * sourcing can be done recursively.
2751 struct source_cookie
2753 FILE *fp; /* opened file for sourcing */
2754 char_u *nextline; /* if not NULL: line that was read ahead */
2755 int finished; /* ":finish" used */
2756 #if defined (USE_CRNL) || defined (USE_CR)
2757 int fileformat; /* EOL_UNKNOWN, EOL_UNIX or EOL_DOS */
2758 int error; /* TRUE if LF found after CR-LF */
2759 #endif
2760 #ifdef FEAT_EVAL
2761 linenr_T breakpoint; /* next line with breakpoint or zero */
2762 char_u *fname; /* name of sourced file */
2763 int dbg_tick; /* debug_tick when breakpoint was set */
2764 int level; /* top nesting level of sourced file */
2765 #endif
2766 #ifdef FEAT_MBYTE
2767 vimconv_T conv; /* type of conversion */
2768 #endif
2771 #ifdef FEAT_EVAL
2773 * Return the address holding the next breakpoint line for a source cookie.
2775 linenr_T *
2776 source_breakpoint(cookie)
2777 void *cookie;
2779 return &((struct source_cookie *)cookie)->breakpoint;
2783 * Return the address holding the debug tick for a source cookie.
2785 int *
2786 source_dbg_tick(cookie)
2787 void *cookie;
2789 return &((struct source_cookie *)cookie)->dbg_tick;
2793 * Return the nesting level for a source cookie.
2796 source_level(cookie)
2797 void *cookie;
2799 return ((struct source_cookie *)cookie)->level;
2801 #endif
2803 static char_u *get_one_sourceline __ARGS((struct source_cookie *sp));
2805 #if (defined(WIN32) && defined(FEAT_CSCOPE)) || defined(HAVE_FD_CLOEXEC)
2806 # define USE_FOPEN_NOINH
2807 static FILE *fopen_noinh_readbin __ARGS((char *filename));
2810 * Special function to open a file without handle inheritance.
2811 * When possible the handle is closed on exec().
2813 static FILE *
2814 fopen_noinh_readbin(filename)
2815 char *filename;
2817 # ifdef WIN32
2818 int fd_tmp = mch_open(filename, O_RDONLY | O_BINARY | O_NOINHERIT, 0);
2819 # else
2820 int fd_tmp = mch_open(filename, O_RDONLY, 0);
2821 # endif
2823 if (fd_tmp == -1)
2824 return NULL;
2826 # ifdef HAVE_FD_CLOEXEC
2828 int fdflags = fcntl(fd_tmp, F_GETFD);
2829 if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0)
2830 fcntl(fd_tmp, F_SETFD, fdflags | FD_CLOEXEC);
2832 # endif
2834 return fdopen(fd_tmp, READBIN);
2836 #endif
2840 * do_source: Read the file "fname" and execute its lines as EX commands.
2842 * This function may be called recursively!
2844 * return FAIL if file could not be opened, OK otherwise
2847 do_source(fname, check_other, is_vimrc)
2848 char_u *fname;
2849 int check_other; /* check for .vimrc and _vimrc */
2850 int is_vimrc; /* DOSO_ value */
2852 struct source_cookie cookie;
2853 char_u *save_sourcing_name;
2854 linenr_T save_sourcing_lnum;
2855 char_u *p;
2856 char_u *fname_exp;
2857 char_u *firstline = NULL;
2858 int retval = FAIL;
2859 #ifdef FEAT_EVAL
2860 scid_T save_current_SID;
2861 static scid_T last_current_SID = 0;
2862 void *save_funccalp;
2863 int save_debug_break_level = debug_break_level;
2864 scriptitem_T *si = NULL;
2865 # ifdef UNIX
2866 struct stat st;
2867 int stat_ok;
2868 # endif
2869 #endif
2870 #ifdef STARTUPTIME
2871 struct timeval tv_rel;
2872 struct timeval tv_start;
2873 #endif
2874 #ifdef FEAT_PROFILE
2875 proftime_T wait_start;
2876 #endif
2878 #ifdef RISCOS
2879 p = mch_munge_fname(fname);
2880 #else
2881 p = expand_env_save(fname);
2882 #endif
2883 if (p == NULL)
2884 return retval;
2885 fname_exp = fix_fname(p);
2886 vim_free(p);
2887 if (fname_exp == NULL)
2888 return retval;
2889 if (mch_isdir(fname_exp))
2891 smsg((char_u *)_("Cannot source a directory: \"%s\""), fname);
2892 goto theend;
2895 #ifdef FEAT_AUTOCMD
2896 /* Apply SourceCmd autocommands, they should get the file and source it. */
2897 if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL)
2898 && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp,
2899 FALSE, curbuf))
2901 # ifdef FEAT_EVAL
2902 retval = aborting() ? FAIL : OK;
2903 # else
2904 retval = OK;
2905 # endif
2906 goto theend;
2909 /* Apply SourcePre autocommands, they may get the file. */
2910 apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, FALSE, curbuf);
2911 #endif
2913 #ifdef USE_FOPEN_NOINH
2914 cookie.fp = fopen_noinh_readbin((char *)fname_exp);
2915 #else
2916 cookie.fp = mch_fopen((char *)fname_exp, READBIN);
2917 #endif
2918 if (cookie.fp == NULL && check_other)
2921 * Try again, replacing file name ".vimrc" by "_vimrc" or vice versa,
2922 * and ".exrc" by "_exrc" or vice versa.
2924 p = gettail(fname_exp);
2925 if ((*p == '.' || *p == '_')
2926 && (STRICMP(p + 1, "vimrc") == 0
2927 || STRICMP(p + 1, "gvimrc") == 0
2928 || STRICMP(p + 1, "exrc") == 0))
2930 if (*p == '_')
2931 *p = '.';
2932 else
2933 *p = '_';
2934 #ifdef USE_FOPEN_NOINH
2935 cookie.fp = fopen_noinh_readbin((char *)fname_exp);
2936 #else
2937 cookie.fp = mch_fopen((char *)fname_exp, READBIN);
2938 #endif
2942 if (cookie.fp == NULL)
2944 if (p_verbose > 0)
2946 verbose_enter();
2947 if (sourcing_name == NULL)
2948 smsg((char_u *)_("could not source \"%s\""), fname);
2949 else
2950 smsg((char_u *)_("line %ld: could not source \"%s\""),
2951 sourcing_lnum, fname);
2952 verbose_leave();
2954 goto theend;
2958 * The file exists.
2959 * - In verbose mode, give a message.
2960 * - For a vimrc file, may want to set 'compatible', call vimrc_found().
2962 if (p_verbose > 1)
2964 verbose_enter();
2965 if (sourcing_name == NULL)
2966 smsg((char_u *)_("sourcing \"%s\""), fname);
2967 else
2968 smsg((char_u *)_("line %ld: sourcing \"%s\""),
2969 sourcing_lnum, fname);
2970 verbose_leave();
2972 if (is_vimrc == DOSO_VIMRC)
2973 vimrc_found(fname_exp, (char_u *)"MYVIMRC");
2974 else if (is_vimrc == DOSO_GVIMRC)
2975 vimrc_found(fname_exp, (char_u *)"MYGVIMRC");
2977 #ifdef USE_CRNL
2978 /* If no automatic file format: Set default to CR-NL. */
2979 if (*p_ffs == NUL)
2980 cookie.fileformat = EOL_DOS;
2981 else
2982 cookie.fileformat = EOL_UNKNOWN;
2983 cookie.error = FALSE;
2984 #endif
2986 #ifdef USE_CR
2987 /* If no automatic file format: Set default to CR. */
2988 if (*p_ffs == NUL)
2989 cookie.fileformat = EOL_MAC;
2990 else
2991 cookie.fileformat = EOL_UNKNOWN;
2992 cookie.error = FALSE;
2993 #endif
2995 cookie.nextline = NULL;
2996 cookie.finished = FALSE;
2998 #ifdef FEAT_EVAL
3000 * Check if this script has a breakpoint.
3002 cookie.breakpoint = dbg_find_breakpoint(TRUE, fname_exp, (linenr_T)0);
3003 cookie.fname = fname_exp;
3004 cookie.dbg_tick = debug_tick;
3006 cookie.level = ex_nesting_level;
3007 #endif
3010 * Keep the sourcing name/lnum, for recursive calls.
3012 save_sourcing_name = sourcing_name;
3013 sourcing_name = fname_exp;
3014 save_sourcing_lnum = sourcing_lnum;
3015 sourcing_lnum = 0;
3017 #ifdef FEAT_MBYTE
3018 cookie.conv.vc_type = CONV_NONE; /* no conversion */
3020 /* Read the first line so we can check for a UTF-8 BOM. */
3021 firstline = getsourceline(0, (void *)&cookie, 0);
3022 if (firstline != NULL && STRLEN(firstline) >= 3 && firstline[0] == 0xef
3023 && firstline[1] == 0xbb && firstline[2] == 0xbf)
3025 /* Found BOM; setup conversion, skip over BOM and recode the line. */
3026 convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc);
3027 p = string_convert(&cookie.conv, firstline + 3, NULL);
3028 if (p == NULL)
3029 p = vim_strsave(firstline + 3);
3030 if (p != NULL)
3032 vim_free(firstline);
3033 firstline = p;
3036 #endif
3038 #ifdef STARTUPTIME
3039 if (time_fd != NULL)
3040 time_push(&tv_rel, &tv_start);
3041 #endif
3043 #ifdef FEAT_EVAL
3044 # ifdef FEAT_PROFILE
3045 if (do_profiling == PROF_YES)
3046 prof_child_enter(&wait_start); /* entering a child now */
3047 # endif
3049 /* Don't use local function variables, if called from a function.
3050 * Also starts profiling timer for nested script. */
3051 save_funccalp = save_funccal();
3054 * Check if this script was sourced before to finds its SID.
3055 * If it's new, generate a new SID.
3057 save_current_SID = current_SID;
3058 # ifdef UNIX
3059 stat_ok = (mch_stat((char *)fname_exp, &st) >= 0);
3060 # endif
3061 for (current_SID = script_items.ga_len; current_SID > 0; --current_SID)
3063 si = &SCRIPT_ITEM(current_SID);
3064 if (si->sn_name != NULL
3065 && (
3066 # ifdef UNIX
3067 /* Compare dev/ino when possible, it catches symbolic
3068 * links. Also compare file names, the inode may change
3069 * when the file was edited. */
3070 ((stat_ok && si->sn_dev_valid)
3071 && (si->sn_dev == st.st_dev
3072 && si->sn_ino == st.st_ino)) ||
3073 # endif
3074 fnamecmp(si->sn_name, fname_exp) == 0))
3075 break;
3077 if (current_SID == 0)
3079 current_SID = ++last_current_SID;
3080 if (ga_grow(&script_items, (int)(current_SID - script_items.ga_len))
3081 == FAIL)
3082 goto almosttheend;
3083 while (script_items.ga_len < current_SID)
3085 ++script_items.ga_len;
3086 SCRIPT_ITEM(script_items.ga_len).sn_name = NULL;
3087 # ifdef FEAT_PROFILE
3088 SCRIPT_ITEM(script_items.ga_len).sn_prof_on = FALSE;
3089 # endif
3091 si = &SCRIPT_ITEM(current_SID);
3092 si->sn_name = fname_exp;
3093 fname_exp = NULL;
3094 # ifdef UNIX
3095 if (stat_ok)
3097 si->sn_dev_valid = TRUE;
3098 si->sn_dev = st.st_dev;
3099 si->sn_ino = st.st_ino;
3101 else
3102 si->sn_dev_valid = FALSE;
3103 # endif
3105 /* Allocate the local script variables to use for this script. */
3106 new_script_vars(current_SID);
3109 # ifdef FEAT_PROFILE
3110 if (do_profiling == PROF_YES)
3112 int forceit;
3114 /* Check if we do profiling for this script. */
3115 if (!si->sn_prof_on && has_profiling(TRUE, si->sn_name, &forceit))
3117 script_do_profile(si);
3118 si->sn_pr_force = forceit;
3120 if (si->sn_prof_on)
3122 ++si->sn_pr_count;
3123 profile_start(&si->sn_pr_start);
3124 profile_zero(&si->sn_pr_children);
3127 # endif
3128 #endif
3131 * Call do_cmdline, which will call getsourceline() to get the lines.
3133 do_cmdline(firstline, getsourceline, (void *)&cookie,
3134 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT);
3135 retval = OK;
3137 #ifdef FEAT_PROFILE
3138 if (do_profiling == PROF_YES)
3140 /* Get "si" again, "script_items" may have been reallocated. */
3141 si = &SCRIPT_ITEM(current_SID);
3142 if (si->sn_prof_on)
3144 profile_end(&si->sn_pr_start);
3145 profile_sub_wait(&wait_start, &si->sn_pr_start);
3146 profile_add(&si->sn_pr_total, &si->sn_pr_start);
3147 profile_self(&si->sn_pr_self, &si->sn_pr_start,
3148 &si->sn_pr_children);
3151 #endif
3153 if (got_int)
3154 EMSG(_(e_interr));
3155 sourcing_name = save_sourcing_name;
3156 sourcing_lnum = save_sourcing_lnum;
3157 if (p_verbose > 1)
3159 verbose_enter();
3160 smsg((char_u *)_("finished sourcing %s"), fname);
3161 if (sourcing_name != NULL)
3162 smsg((char_u *)_("continuing in %s"), sourcing_name);
3163 verbose_leave();
3165 #ifdef STARTUPTIME
3166 if (time_fd != NULL)
3168 vim_snprintf((char *)IObuff, IOSIZE, "sourcing %s", fname);
3169 time_msg((char *)IObuff, &tv_start);
3170 time_pop(&tv_rel);
3172 #endif
3174 #ifdef FEAT_EVAL
3176 * After a "finish" in debug mode, need to break at first command of next
3177 * sourced file.
3179 if (save_debug_break_level > ex_nesting_level
3180 && debug_break_level == ex_nesting_level)
3181 ++debug_break_level;
3182 #endif
3184 #ifdef FEAT_EVAL
3185 almosttheend:
3186 current_SID = save_current_SID;
3187 restore_funccal(save_funccalp);
3188 # ifdef FEAT_PROFILE
3189 if (do_profiling == PROF_YES)
3190 prof_child_exit(&wait_start); /* leaving a child now */
3191 # endif
3192 #endif
3193 fclose(cookie.fp);
3194 vim_free(cookie.nextline);
3195 vim_free(firstline);
3196 #ifdef FEAT_MBYTE
3197 convert_setup(&cookie.conv, NULL, NULL);
3198 #endif
3200 theend:
3201 vim_free(fname_exp);
3202 return retval;
3205 #if defined(FEAT_EVAL) || defined(PROTO)
3208 * ":scriptnames"
3210 void
3211 ex_scriptnames(eap)
3212 exarg_T *eap UNUSED;
3214 int i;
3216 for (i = 1; i <= script_items.ga_len && !got_int; ++i)
3217 if (SCRIPT_ITEM(i).sn_name != NULL)
3218 smsg((char_u *)"%3d: %s", i, SCRIPT_ITEM(i).sn_name);
3221 # if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
3223 * Fix slashes in the list of script names for 'shellslash'.
3225 void
3226 scriptnames_slash_adjust()
3228 int i;
3230 for (i = 1; i <= script_items.ga_len; ++i)
3231 if (SCRIPT_ITEM(i).sn_name != NULL)
3232 slash_adjust(SCRIPT_ITEM(i).sn_name);
3234 # endif
3237 * Get a pointer to a script name. Used for ":verbose set".
3239 char_u *
3240 get_scriptname(id)
3241 scid_T id;
3243 if (id == SID_MODELINE)
3244 return (char_u *)_("modeline");
3245 if (id == SID_CMDARG)
3246 return (char_u *)_("--cmd argument");
3247 if (id == SID_CARG)
3248 return (char_u *)_("-c argument");
3249 if (id == SID_ENV)
3250 return (char_u *)_("environment variable");
3251 if (id == SID_ERROR)
3252 return (char_u *)_("error handler");
3253 return SCRIPT_ITEM(id).sn_name;
3256 # if defined(EXITFREE) || defined(PROTO)
3257 void
3258 free_scriptnames()
3260 int i;
3262 for (i = script_items.ga_len; i > 0; --i)
3263 vim_free(SCRIPT_ITEM(i).sn_name);
3264 ga_clear(&script_items);
3266 # endif
3268 #endif
3270 #if defined(USE_CR) || defined(PROTO)
3272 # if defined(__MSL__) && (__MSL__ >= 22)
3274 * Newer version of the Metrowerks library handle DOS and UNIX files
3275 * without help.
3276 * Test with earlier versions, MSL 2.2 is the library supplied with
3277 * Codewarrior Pro 2.
3279 char *
3280 fgets_cr(s, n, stream)
3281 char *s;
3282 int n;
3283 FILE *stream;
3285 return fgets(s, n, stream);
3287 # else
3289 * Version of fgets() which also works for lines ending in a <CR> only
3290 * (Macintosh format).
3291 * For older versions of the Metrowerks library.
3292 * At least CodeWarrior 9 needed this code.
3294 char *
3295 fgets_cr(s, n, stream)
3296 char *s;
3297 int n;
3298 FILE *stream;
3300 int c = 0;
3301 int char_read = 0;
3303 while (!feof(stream) && c != '\r' && c != '\n' && char_read < n - 1)
3305 c = fgetc(stream);
3306 s[char_read++] = c;
3307 /* If the file is in DOS format, we need to skip a NL after a CR. I
3308 * thought it was the other way around, but this appears to work... */
3309 if (c == '\n')
3311 c = fgetc(stream);
3312 if (c != '\r')
3313 ungetc(c, stream);
3317 s[char_read] = 0;
3318 if (char_read == 0)
3319 return NULL;
3321 if (feof(stream) && char_read == 1)
3322 return NULL;
3324 return s;
3326 # endif
3327 #endif
3330 * Get one full line from a sourced file.
3331 * Called by do_cmdline() when it's called from do_source().
3333 * Return a pointer to the line in allocated memory.
3334 * Return NULL for end-of-file or some error.
3336 char_u *
3337 getsourceline(c, cookie, indent)
3338 int c UNUSED;
3339 void *cookie;
3340 int indent UNUSED;
3342 struct source_cookie *sp = (struct source_cookie *)cookie;
3343 char_u *line;
3344 char_u *p, *s;
3346 #ifdef FEAT_EVAL
3347 /* If breakpoints have been added/deleted need to check for it. */
3348 if (sp->dbg_tick < debug_tick)
3350 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
3351 sp->dbg_tick = debug_tick;
3353 # ifdef FEAT_PROFILE
3354 if (do_profiling == PROF_YES)
3355 script_line_end();
3356 # endif
3357 #endif
3359 * Get current line. If there is a read-ahead line, use it, otherwise get
3360 * one now.
3362 if (sp->finished)
3363 line = NULL;
3364 else if (sp->nextline == NULL)
3365 line = get_one_sourceline(sp);
3366 else
3368 line = sp->nextline;
3369 sp->nextline = NULL;
3370 ++sourcing_lnum;
3372 #ifdef FEAT_PROFILE
3373 if (line != NULL && do_profiling == PROF_YES)
3374 script_line_start();
3375 #endif
3377 /* Only concatenate lines starting with a \ when 'cpoptions' doesn't
3378 * contain the 'C' flag. */
3379 if (line != NULL && (vim_strchr(p_cpo, CPO_CONCAT) == NULL))
3381 /* compensate for the one line read-ahead */
3382 --sourcing_lnum;
3383 for (;;)
3385 sp->nextline = get_one_sourceline(sp);
3386 if (sp->nextline == NULL)
3387 break;
3388 p = skipwhite(sp->nextline);
3389 if (*p != '\\')
3390 break;
3391 s = alloc((unsigned)(STRLEN(line) + STRLEN(p)));
3392 if (s == NULL) /* out of memory */
3393 break;
3394 STRCPY(s, line);
3395 STRCAT(s, p + 1);
3396 vim_free(line);
3397 line = s;
3398 vim_free(sp->nextline);
3402 #ifdef FEAT_MBYTE
3403 if (line != NULL && sp->conv.vc_type != CONV_NONE)
3405 /* Convert the encoding of the script line. */
3406 s = string_convert(&sp->conv, line, NULL);
3407 if (s != NULL)
3409 vim_free(line);
3410 line = s;
3413 #endif
3415 #ifdef FEAT_EVAL
3416 /* Did we encounter a breakpoint? */
3417 if (sp->breakpoint != 0 && sp->breakpoint <= sourcing_lnum)
3419 dbg_breakpoint(sp->fname, sourcing_lnum);
3420 /* Find next breakpoint. */
3421 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
3422 sp->dbg_tick = debug_tick;
3424 #endif
3426 return line;
3429 static char_u *
3430 get_one_sourceline(sp)
3431 struct source_cookie *sp;
3433 garray_T ga;
3434 int len;
3435 int c;
3436 char_u *buf;
3437 #ifdef USE_CRNL
3438 int has_cr; /* CR-LF found */
3439 #endif
3440 #ifdef USE_CR
3441 char_u *scan;
3442 #endif
3443 int have_read = FALSE;
3445 /* use a growarray to store the sourced line */
3446 ga_init2(&ga, 1, 250);
3449 * Loop until there is a finished line (or end-of-file).
3451 sourcing_lnum++;
3452 for (;;)
3454 /* make room to read at least 120 (more) characters */
3455 if (ga_grow(&ga, 120) == FAIL)
3456 break;
3457 buf = (char_u *)ga.ga_data;
3459 #ifdef USE_CR
3460 if (sp->fileformat == EOL_MAC)
3462 if (fgets_cr((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
3463 sp->fp) == NULL)
3464 break;
3466 else
3467 #endif
3468 if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
3469 sp->fp) == NULL)
3470 break;
3471 len = ga.ga_len + (int)STRLEN(buf + ga.ga_len);
3472 #ifdef USE_CRNL
3473 /* Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the
3474 * CTRL-Z by its own, or after a NL. */
3475 if ( (len == 1 || (len >= 2 && buf[len - 2] == '\n'))
3476 && sp->fileformat == EOL_DOS
3477 && buf[len - 1] == Ctrl_Z)
3479 buf[len - 1] = NUL;
3480 break;
3482 #endif
3484 #ifdef USE_CR
3485 /* If the read doesn't stop on a new line, and there's
3486 * some CR then we assume a Mac format */
3487 if (sp->fileformat == EOL_UNKNOWN)
3489 if (buf[len - 1] != '\n' && vim_strchr(buf, '\r') != NULL)
3490 sp->fileformat = EOL_MAC;
3491 else
3492 sp->fileformat = EOL_UNIX;
3495 if (sp->fileformat == EOL_MAC)
3497 scan = vim_strchr(buf, '\r');
3499 if (scan != NULL)
3501 *scan = '\n';
3502 if (*(scan + 1) != 0)
3504 *(scan + 1) = 0;
3505 fseek(sp->fp, (long)(scan - buf - len + 1), SEEK_CUR);
3508 len = STRLEN(buf);
3510 #endif
3512 have_read = TRUE;
3513 ga.ga_len = len;
3515 /* If the line was longer than the buffer, read more. */
3516 if (ga.ga_maxlen - ga.ga_len == 1 && buf[len - 1] != '\n')
3517 continue;
3519 if (len >= 1 && buf[len - 1] == '\n') /* remove trailing NL */
3521 #ifdef USE_CRNL
3522 has_cr = (len >= 2 && buf[len - 2] == '\r');
3523 if (sp->fileformat == EOL_UNKNOWN)
3525 if (has_cr)
3526 sp->fileformat = EOL_DOS;
3527 else
3528 sp->fileformat = EOL_UNIX;
3531 if (sp->fileformat == EOL_DOS)
3533 if (has_cr) /* replace trailing CR */
3535 buf[len - 2] = '\n';
3536 --len;
3537 --ga.ga_len;
3539 else /* lines like ":map xx yy^M" will have failed */
3541 if (!sp->error)
3543 msg_source(hl_attr(HLF_W));
3544 EMSG(_("W15: Warning: Wrong line separator, ^M may be missing"));
3546 sp->error = TRUE;
3547 sp->fileformat = EOL_UNIX;
3550 #endif
3551 /* The '\n' is escaped if there is an odd number of ^V's just
3552 * before it, first set "c" just before the 'V's and then check
3553 * len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo */
3554 for (c = len - 2; c >= 0 && buf[c] == Ctrl_V; c--)
3556 if ((len & 1) != (c & 1)) /* escaped NL, read more */
3558 sourcing_lnum++;
3559 continue;
3562 buf[len - 1] = NUL; /* remove the NL */
3566 * Check for ^C here now and then, so recursive :so can be broken.
3568 line_breakcheck();
3569 break;
3572 if (have_read)
3573 return (char_u *)ga.ga_data;
3575 vim_free(ga.ga_data);
3576 return NULL;
3579 #if defined(FEAT_PROFILE) || defined(PROTO)
3581 * Called when starting to read a script line.
3582 * "sourcing_lnum" must be correct!
3583 * When skipping lines it may not actually be executed, but we won't find out
3584 * until later and we need to store the time now.
3586 void
3587 script_line_start()
3589 scriptitem_T *si;
3590 sn_prl_T *pp;
3592 if (current_SID <= 0 || current_SID > script_items.ga_len)
3593 return;
3594 si = &SCRIPT_ITEM(current_SID);
3595 if (si->sn_prof_on && sourcing_lnum >= 1)
3597 /* Grow the array before starting the timer, so that the time spent
3598 * here isn't counted. */
3599 ga_grow(&si->sn_prl_ga, (int)(sourcing_lnum - si->sn_prl_ga.ga_len));
3600 si->sn_prl_idx = sourcing_lnum - 1;
3601 while (si->sn_prl_ga.ga_len <= si->sn_prl_idx
3602 && si->sn_prl_ga.ga_len < si->sn_prl_ga.ga_maxlen)
3604 /* Zero counters for a line that was not used before. */
3605 pp = &PRL_ITEM(si, si->sn_prl_ga.ga_len);
3606 pp->snp_count = 0;
3607 profile_zero(&pp->sn_prl_total);
3608 profile_zero(&pp->sn_prl_self);
3609 ++si->sn_prl_ga.ga_len;
3611 si->sn_prl_execed = FALSE;
3612 profile_start(&si->sn_prl_start);
3613 profile_zero(&si->sn_prl_children);
3614 profile_get_wait(&si->sn_prl_wait);
3619 * Called when actually executing a function line.
3621 void
3622 script_line_exec()
3624 scriptitem_T *si;
3626 if (current_SID <= 0 || current_SID > script_items.ga_len)
3627 return;
3628 si = &SCRIPT_ITEM(current_SID);
3629 if (si->sn_prof_on && si->sn_prl_idx >= 0)
3630 si->sn_prl_execed = TRUE;
3634 * Called when done with a function line.
3636 void
3637 script_line_end()
3639 scriptitem_T *si;
3640 sn_prl_T *pp;
3642 if (current_SID <= 0 || current_SID > script_items.ga_len)
3643 return;
3644 si = &SCRIPT_ITEM(current_SID);
3645 if (si->sn_prof_on && si->sn_prl_idx >= 0
3646 && si->sn_prl_idx < si->sn_prl_ga.ga_len)
3648 if (si->sn_prl_execed)
3650 pp = &PRL_ITEM(si, si->sn_prl_idx);
3651 ++pp->snp_count;
3652 profile_end(&si->sn_prl_start);
3653 profile_sub_wait(&si->sn_prl_wait, &si->sn_prl_start);
3654 profile_add(&pp->sn_prl_total, &si->sn_prl_start);
3655 profile_self(&pp->sn_prl_self, &si->sn_prl_start,
3656 &si->sn_prl_children);
3658 si->sn_prl_idx = -1;
3661 #endif
3664 * ":scriptencoding": Set encoding conversion for a sourced script.
3665 * Without the multi-byte feature it's simply ignored.
3667 void
3668 ex_scriptencoding(eap)
3669 exarg_T *eap UNUSED;
3671 #ifdef FEAT_MBYTE
3672 struct source_cookie *sp;
3673 char_u *name;
3675 if (!getline_equal(eap->getline, eap->cookie, getsourceline))
3677 EMSG(_("E167: :scriptencoding used outside of a sourced file"));
3678 return;
3681 if (*eap->arg != NUL)
3683 name = enc_canonize(eap->arg);
3684 if (name == NULL) /* out of memory */
3685 return;
3687 else
3688 name = eap->arg;
3690 /* Setup for conversion from the specified encoding to 'encoding'. */
3691 sp = (struct source_cookie *)getline_cookie(eap->getline, eap->cookie);
3692 convert_setup(&sp->conv, name, p_enc);
3694 if (name != eap->arg)
3695 vim_free(name);
3696 #endif
3699 #if defined(FEAT_EVAL) || defined(PROTO)
3701 * ":finish": Mark a sourced file as finished.
3703 void
3704 ex_finish(eap)
3705 exarg_T *eap;
3707 if (getline_equal(eap->getline, eap->cookie, getsourceline))
3708 do_finish(eap, FALSE);
3709 else
3710 EMSG(_("E168: :finish used outside of a sourced file"));
3714 * Mark a sourced file as finished. Possibly makes the ":finish" pending.
3715 * Also called for a pending finish at the ":endtry" or after returning from
3716 * an extra do_cmdline(). "reanimate" is used in the latter case.
3718 void
3719 do_finish(eap, reanimate)
3720 exarg_T *eap;
3721 int reanimate;
3723 int idx;
3725 if (reanimate)
3726 ((struct source_cookie *)getline_cookie(eap->getline,
3727 eap->cookie))->finished = FALSE;
3730 * Cleanup (and inactivate) conditionals, but stop when a try conditional
3731 * not in its finally clause (which then is to be executed next) is found.
3732 * In this case, make the ":finish" pending for execution at the ":endtry".
3733 * Otherwise, finish normally.
3735 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
3736 if (idx >= 0)
3738 eap->cstack->cs_pending[idx] = CSTP_FINISH;
3739 report_make_pending(CSTP_FINISH, NULL);
3741 else
3742 ((struct source_cookie *)getline_cookie(eap->getline,
3743 eap->cookie))->finished = TRUE;
3748 * Return TRUE when a sourced file had the ":finish" command: Don't give error
3749 * message for missing ":endif".
3750 * Return FALSE when not sourcing a file.
3753 source_finished(fgetline, cookie)
3754 char_u *(*fgetline) __ARGS((int, void *, int));
3755 void *cookie;
3757 return (getline_equal(fgetline, cookie, getsourceline)
3758 && ((struct source_cookie *)getline_cookie(
3759 fgetline, cookie))->finished);
3761 #endif
3763 #if defined(FEAT_LISTCMDS) || defined(PROTO)
3765 * ":checktime [buffer]"
3767 void
3768 ex_checktime(eap)
3769 exarg_T *eap;
3771 buf_T *buf;
3772 int save_no_check_timestamps = no_check_timestamps;
3774 no_check_timestamps = 0;
3775 if (eap->addr_count == 0) /* default is all buffers */
3776 check_timestamps(FALSE);
3777 else
3779 buf = buflist_findnr((int)eap->line2);
3780 if (buf != NULL) /* cannot happen? */
3781 (void)buf_check_timestamp(buf, FALSE);
3783 no_check_timestamps = save_no_check_timestamps;
3785 #endif
3787 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3788 && (defined(FEAT_EVAL) || defined(FEAT_MULTI_LANG))
3789 static char *get_locale_val __ARGS((int what));
3791 static char *
3792 get_locale_val(what)
3793 int what;
3795 char *loc;
3797 /* Obtain the locale value from the libraries. For DJGPP this is
3798 * redefined and it doesn't use the arguments. */
3799 loc = setlocale(what, NULL);
3801 # ifdef WIN32
3802 if (loc != NULL)
3804 char_u *p;
3806 /* setocale() returns something like "LC_COLLATE=<name>;LC_..." when
3807 * one of the values (e.g., LC_CTYPE) differs. */
3808 p = vim_strchr(loc, '=');
3809 if (p != NULL)
3811 loc = ++p;
3812 while (*p != NUL) /* remove trailing newline */
3814 if (*p < ' ' || *p == ';')
3816 *p = NUL;
3817 break;
3819 ++p;
3823 # endif
3825 return loc;
3827 #endif
3830 #ifdef WIN32
3832 * On MS-Windows locale names are strings like "German_Germany.1252", but
3833 * gettext expects "de". Try to translate one into another here for a few
3834 * supported languages.
3836 static char_u *
3837 gettext_lang(char_u *name)
3839 int i;
3840 static char *(mtable[]) = {
3841 "afrikaans", "af",
3842 "czech", "cs",
3843 "dutch", "nl",
3844 "german", "de",
3845 "english_united kingdom", "en_GB",
3846 "spanish", "es",
3847 "french", "fr",
3848 "italian", "it",
3849 "japanese", "ja",
3850 "korean", "ko",
3851 "norwegian", "no",
3852 "polish", "pl",
3853 "russian", "ru",
3854 "slovak", "sk",
3855 "swedish", "sv",
3856 "ukrainian", "uk",
3857 "chinese_china", "zh_CN",
3858 "chinese_taiwan", "zh_TW",
3859 NULL};
3861 for (i = 0; mtable[i] != NULL; i += 2)
3862 if (STRNICMP(mtable[i], name, STRLEN(mtable[i])) == 0)
3863 return mtable[i + 1];
3864 return name;
3866 #endif
3868 #if defined(FEAT_MULTI_LANG) || defined(PROTO)
3870 * Obtain the current messages language. Used to set the default for
3871 * 'helplang'. May return NULL or an empty string.
3873 char_u *
3874 get_mess_lang()
3876 char_u *p;
3878 # if (defined(HAVE_LOCALE_H) || defined(X_LOCALE))
3879 # if defined(LC_MESSAGES)
3880 p = (char_u *)get_locale_val(LC_MESSAGES);
3881 # else
3882 /* This is necessary for Win32, where LC_MESSAGES is not defined and $LANG
3883 * may be set to the LCID number. LC_COLLATE is the best guess, LC_TIME
3884 * and LC_MONETARY may be set differently for a Japanese working in the
3885 * US. */
3886 p = (char_u *)get_locale_val(LC_COLLATE);
3887 # endif
3888 # else
3889 p = mch_getenv((char_u *)"LC_ALL");
3890 if (p == NULL || *p == NUL)
3892 p = mch_getenv((char_u *)"LC_MESSAGES");
3893 if (p == NULL || *p == NUL)
3894 p = mch_getenv((char_u *)"LANG");
3896 # endif
3897 # ifdef WIN32
3898 p = gettext_lang(p);
3899 # endif
3900 return p;
3902 #endif
3904 /* Complicated #if; matches with where get_mess_env() is used below. */
3905 #if (defined(FEAT_EVAL) && !((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3906 && defined(LC_MESSAGES))) \
3907 || ((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3908 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)) \
3909 && !defined(LC_MESSAGES))
3910 static char_u *get_mess_env __ARGS((void));
3913 * Get the language used for messages from the environment.
3915 static char_u *
3916 get_mess_env()
3918 char_u *p;
3920 p = mch_getenv((char_u *)"LC_ALL");
3921 if (p == NULL || *p == NUL)
3923 p = mch_getenv((char_u *)"LC_MESSAGES");
3924 if (p == NULL || *p == NUL)
3926 p = mch_getenv((char_u *)"LANG");
3927 if (p != NULL && VIM_ISDIGIT(*p))
3928 p = NULL; /* ignore something like "1043" */
3929 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
3930 if (p == NULL || *p == NUL)
3931 p = (char_u *)get_locale_val(LC_CTYPE);
3932 # endif
3935 return p;
3937 #endif
3939 #if defined(FEAT_EVAL) || defined(PROTO)
3942 * Set the "v:lang" variable according to the current locale setting.
3943 * Also do "v:lc_time"and "v:ctype".
3945 void
3946 set_lang_var()
3948 char_u *loc;
3950 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
3951 loc = (char_u *)get_locale_val(LC_CTYPE);
3952 # else
3953 /* setlocale() not supported: use the default value */
3954 loc = (char_u *)"C";
3955 # endif
3956 set_vim_var_string(VV_CTYPE, loc, -1);
3958 /* When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall
3959 * back to LC_CTYPE if it's empty. */
3960 # if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) && defined(LC_MESSAGES)
3961 loc = (char_u *)get_locale_val(LC_MESSAGES);
3962 # else
3963 loc = get_mess_env();
3964 # endif
3965 set_vim_var_string(VV_LANG, loc, -1);
3967 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
3968 loc = (char_u *)get_locale_val(LC_TIME);
3969 # endif
3970 set_vim_var_string(VV_LC_TIME, loc, -1);
3972 #endif
3974 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3975 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE))
3977 * ":language": Set the language (locale).
3979 void
3980 ex_language(eap)
3981 exarg_T *eap;
3983 char *loc;
3984 char_u *p;
3985 char_u *name;
3986 int what = LC_ALL;
3987 char *whatstr = "";
3988 #ifdef LC_MESSAGES
3989 # define VIM_LC_MESSAGES LC_MESSAGES
3990 #else
3991 # define VIM_LC_MESSAGES 6789
3992 #endif
3994 name = eap->arg;
3996 /* Check for "messages {name}", "ctype {name}" or "time {name}" argument.
3997 * Allow abbreviation, but require at least 3 characters to avoid
3998 * confusion with a two letter language name "me" or "ct". */
3999 p = skiptowhite(eap->arg);
4000 if ((*p == NUL || vim_iswhite(*p)) && p - eap->arg >= 3)
4002 if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0)
4004 what = VIM_LC_MESSAGES;
4005 name = skipwhite(p);
4006 whatstr = "messages ";
4008 else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0)
4010 what = LC_CTYPE;
4011 name = skipwhite(p);
4012 whatstr = "ctype ";
4014 else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0)
4016 what = LC_TIME;
4017 name = skipwhite(p);
4018 whatstr = "time ";
4022 if (*name == NUL)
4024 #ifndef LC_MESSAGES
4025 if (what == VIM_LC_MESSAGES)
4026 p = get_mess_env();
4027 else
4028 #endif
4029 p = (char_u *)setlocale(what, NULL);
4030 if (p == NULL || *p == NUL)
4031 p = (char_u *)"Unknown";
4032 smsg((char_u *)_("Current %slanguage: \"%s\""), whatstr, p);
4034 else
4036 #ifndef LC_MESSAGES
4037 if (what == VIM_LC_MESSAGES)
4038 loc = "";
4039 else
4040 #endif
4042 loc = setlocale(what, (char *)name);
4043 #if defined(FEAT_FLOAT) && defined(LC_NUMERIC)
4044 /* Make sure strtod() uses a decimal point, not a comma. */
4045 setlocale(LC_NUMERIC, "C");
4046 #endif
4048 if (loc == NULL)
4049 EMSG2(_("E197: Cannot set language to \"%s\""), name);
4050 else
4052 #ifdef HAVE_NL_MSG_CAT_CNTR
4053 /* Need to do this for GNU gettext, otherwise cached translations
4054 * will be used again. */
4055 extern int _nl_msg_cat_cntr;
4057 ++_nl_msg_cat_cntr;
4058 #endif
4059 /* Reset $LC_ALL, otherwise it would overrule everything. */
4060 vim_setenv((char_u *)"LC_ALL", (char_u *)"");
4062 if (what != LC_TIME)
4064 /* Tell gettext() what to translate to. It apparently doesn't
4065 * use the currently effective locale. Also do this when
4066 * FEAT_GETTEXT isn't defined, so that shell commands use this
4067 * value. */
4068 if (what == LC_ALL)
4070 vim_setenv((char_u *)"LANG", name);
4071 # ifdef WIN32
4072 /* Apparently MS-Windows printf() may cause a crash when
4073 * we give it 8-bit text while it's expecting text in the
4074 * current locale. This call avoids that. */
4075 setlocale(LC_CTYPE, "C");
4076 # endif
4078 if (what != LC_CTYPE)
4080 char_u *mname;
4081 #ifdef WIN32
4082 mname = gettext_lang(name);
4083 #else
4084 mname = name;
4085 #endif
4086 vim_setenv((char_u *)"LC_MESSAGES", mname);
4087 #ifdef FEAT_MULTI_LANG
4088 set_helplang_default(mname);
4089 #endif
4092 /* Set $LC_CTYPE, because it overrules $LANG, and
4093 * gtk_set_locale() calls setlocale() again. gnome_init()
4094 * sets $LC_CTYPE to "en_US" (that's a bug!). */
4095 if (what != VIM_LC_MESSAGES)
4096 vim_setenv((char_u *)"LC_CTYPE", name);
4097 # ifdef FEAT_GUI_GTK
4098 /* Let GTK know what locale we're using. Not sure this is
4099 * really needed... */
4100 if (gui.in_use)
4101 (void)gtk_set_locale();
4102 # endif
4105 # ifdef FEAT_EVAL
4106 /* Set v:lang, v:lc_time and v:ctype to the final result. */
4107 set_lang_var();
4108 # endif
4113 # if defined(FEAT_CMDL_COMPL) || defined(PROTO)
4115 * Function given to ExpandGeneric() to obtain the possible arguments of the
4116 * ":language" command.
4118 char_u *
4119 get_lang_arg(xp, idx)
4120 expand_T *xp UNUSED;
4121 int idx;
4123 if (idx == 0)
4124 return (char_u *)"messages";
4125 if (idx == 1)
4126 return (char_u *)"ctype";
4127 if (idx == 2)
4128 return (char_u *)"time";
4129 return NULL;
4131 # endif
4133 #endif