Merge branch 'vim'
[MacVim.git] / src / ex_cmds2.c
blob58b0b52d731f2a04f049a4233aa765337a73e0e2
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);
1118 /* Command line expansion for :profile. */
1119 static enum
1121 PEXP_SUBCMD, /* expand :profile sub-commands */
1122 PEXP_FUNC, /* expand :profile func {funcname} */
1123 } pexpand_what;
1125 static char *pexpand_cmds[] = {
1126 "start",
1127 #define PROFCMD_START 0
1128 "pause",
1129 #define PROFCMD_PAUSE 1
1130 "continue",
1131 #define PROFCMD_CONTINUE 2
1132 "func",
1133 #define PROFCMD_FUNC 3
1134 "file",
1135 #define PROFCMD_FILE 4
1136 NULL
1137 #define PROFCMD_LAST 5
1141 * Function given to ExpandGeneric() to obtain the profile command
1142 * specific expansion.
1144 char_u *
1145 get_profile_name(xp, idx)
1146 expand_T *xp UNUSED;
1147 int idx;
1149 switch (pexpand_what)
1151 case PEXP_SUBCMD:
1152 return (char_u *)pexpand_cmds[idx];
1153 /* case PEXP_FUNC: TODO */
1154 default:
1155 return NULL;
1160 * Handle command line completion for :profile command.
1162 void
1163 set_context_in_profile_cmd(xp, arg)
1164 expand_T *xp;
1165 char_u *arg;
1167 char_u *end_subcmd;
1169 /* Default: expand subcommands. */
1170 xp->xp_context = EXPAND_PROFILE;
1171 pexpand_what = PEXP_SUBCMD;
1172 xp->xp_pattern = arg;
1174 end_subcmd = skiptowhite(arg);
1175 if (*end_subcmd == NUL)
1176 return;
1178 if (end_subcmd - arg == 5 && STRNCMP(arg, "start", 5) == 0)
1180 xp->xp_context = EXPAND_FILES;
1181 xp->xp_pattern = skipwhite(end_subcmd);
1182 return;
1185 /* TODO: expand function names after "func" */
1186 xp->xp_context = EXPAND_NOTHING;
1190 * Dump the profiling info.
1192 void
1193 profile_dump()
1195 FILE *fd;
1197 if (profile_fname != NULL)
1199 fd = mch_fopen((char *)profile_fname, "w");
1200 if (fd == NULL)
1201 EMSG2(_(e_notopen), profile_fname);
1202 else
1204 script_dump_profile(fd);
1205 func_dump_profile(fd);
1206 fclose(fd);
1212 * Start profiling script "fp".
1214 static void
1215 script_do_profile(si)
1216 scriptitem_T *si;
1218 si->sn_pr_count = 0;
1219 profile_zero(&si->sn_pr_total);
1220 profile_zero(&si->sn_pr_self);
1222 ga_init2(&si->sn_prl_ga, sizeof(sn_prl_T), 100);
1223 si->sn_prl_idx = -1;
1224 si->sn_prof_on = TRUE;
1225 si->sn_pr_nest = 0;
1229 * save time when starting to invoke another script or function.
1231 void
1232 script_prof_save(tm)
1233 proftime_T *tm; /* place to store wait time */
1235 scriptitem_T *si;
1237 if (current_SID > 0 && current_SID <= script_items.ga_len)
1239 si = &SCRIPT_ITEM(current_SID);
1240 if (si->sn_prof_on && si->sn_pr_nest++ == 0)
1241 profile_start(&si->sn_pr_child);
1243 profile_get_wait(tm);
1247 * Count time spent in children after invoking another script or function.
1249 void
1250 script_prof_restore(tm)
1251 proftime_T *tm;
1253 scriptitem_T *si;
1255 if (current_SID > 0 && current_SID <= script_items.ga_len)
1257 si = &SCRIPT_ITEM(current_SID);
1258 if (si->sn_prof_on && --si->sn_pr_nest == 0)
1260 profile_end(&si->sn_pr_child);
1261 profile_sub_wait(tm, &si->sn_pr_child); /* don't count wait time */
1262 profile_add(&si->sn_pr_children, &si->sn_pr_child);
1263 profile_add(&si->sn_prl_children, &si->sn_pr_child);
1268 static proftime_T inchar_time;
1271 * Called when starting to wait for the user to type a character.
1273 void
1274 prof_inchar_enter()
1276 profile_start(&inchar_time);
1280 * Called when finished waiting for the user to type a character.
1282 void
1283 prof_inchar_exit()
1285 profile_end(&inchar_time);
1286 profile_add(&prof_wait_time, &inchar_time);
1290 * Dump the profiling results for all scripts in file "fd".
1292 static void
1293 script_dump_profile(fd)
1294 FILE *fd;
1296 int id;
1297 scriptitem_T *si;
1298 int i;
1299 FILE *sfd;
1300 sn_prl_T *pp;
1302 for (id = 1; id <= script_items.ga_len; ++id)
1304 si = &SCRIPT_ITEM(id);
1305 if (si->sn_prof_on)
1307 fprintf(fd, "SCRIPT %s\n", si->sn_name);
1308 if (si->sn_pr_count == 1)
1309 fprintf(fd, "Sourced 1 time\n");
1310 else
1311 fprintf(fd, "Sourced %d times\n", si->sn_pr_count);
1312 fprintf(fd, "Total time: %s\n", profile_msg(&si->sn_pr_total));
1313 fprintf(fd, " Self time: %s\n", profile_msg(&si->sn_pr_self));
1314 fprintf(fd, "\n");
1315 fprintf(fd, "count total (s) self (s)\n");
1317 sfd = mch_fopen((char *)si->sn_name, "r");
1318 if (sfd == NULL)
1319 fprintf(fd, "Cannot open file!\n");
1320 else
1322 for (i = 0; i < si->sn_prl_ga.ga_len; ++i)
1324 if (vim_fgets(IObuff, IOSIZE, sfd))
1325 break;
1326 pp = &PRL_ITEM(si, i);
1327 if (pp->snp_count > 0)
1329 fprintf(fd, "%5d ", pp->snp_count);
1330 if (profile_equal(&pp->sn_prl_total, &pp->sn_prl_self))
1331 fprintf(fd, " ");
1332 else
1333 fprintf(fd, "%s ", profile_msg(&pp->sn_prl_total));
1334 fprintf(fd, "%s ", profile_msg(&pp->sn_prl_self));
1336 else
1337 fprintf(fd, " ");
1338 fprintf(fd, "%s", IObuff);
1340 fclose(sfd);
1342 fprintf(fd, "\n");
1348 * Return TRUE when a function defined in the current script should be
1349 * profiled.
1352 prof_def_func()
1354 if (current_SID > 0)
1355 return SCRIPT_ITEM(current_SID).sn_pr_force;
1356 return FALSE;
1359 # endif
1360 #endif
1363 * If 'autowrite' option set, try to write the file.
1364 * Careful: autocommands may make "buf" invalid!
1366 * return FAIL for failure, OK otherwise
1369 autowrite(buf, forceit)
1370 buf_T *buf;
1371 int forceit;
1373 int r;
1375 if (!(p_aw || p_awa) || !p_write
1376 #ifdef FEAT_QUICKFIX
1377 /* never autowrite a "nofile" or "nowrite" buffer */
1378 || bt_dontwrite(buf)
1379 #endif
1380 || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL)
1381 return FAIL;
1382 r = buf_write_all(buf, forceit);
1384 /* Writing may succeed but the buffer still changed, e.g., when there is a
1385 * conversion error. We do want to return FAIL then. */
1386 if (buf_valid(buf) && bufIsChanged(buf))
1387 r = FAIL;
1388 return r;
1392 * flush all buffers, except the ones that are readonly
1394 void
1395 autowrite_all()
1397 buf_T *buf;
1399 if (!(p_aw || p_awa) || !p_write)
1400 return;
1401 for (buf = firstbuf; buf; buf = buf->b_next)
1402 if (bufIsChanged(buf) && !buf->b_p_ro)
1404 (void)buf_write_all(buf, FALSE);
1405 #ifdef FEAT_AUTOCMD
1406 /* an autocommand may have deleted the buffer */
1407 if (!buf_valid(buf))
1408 buf = firstbuf;
1409 #endif
1414 * return TRUE if buffer was changed and cannot be abandoned.
1417 check_changed(buf, checkaw, mult_win, forceit, allbuf)
1418 buf_T *buf;
1419 int checkaw; /* do autowrite if buffer was changed */
1420 int mult_win; /* check also when several wins for the buf */
1421 int forceit;
1422 int allbuf UNUSED; /* may write all buffers */
1424 if ( !forceit
1425 && bufIsChanged(buf)
1426 && (mult_win || buf->b_nwindows <= 1)
1427 && (!checkaw || autowrite(buf, forceit) == FAIL))
1429 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1430 if ((p_confirm || cmdmod.confirm) && p_write)
1432 buf_T *buf2;
1433 int count = 0;
1435 if (allbuf)
1436 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1437 if (bufIsChanged(buf2)
1438 && (buf2->b_ffname != NULL
1439 # ifdef FEAT_BROWSE
1440 || cmdmod.browse
1441 # endif
1443 ++count;
1444 # ifdef FEAT_AUTOCMD
1445 if (!buf_valid(buf))
1446 /* Autocommand deleted buffer, oops! It's not changed now. */
1447 return FALSE;
1448 # endif
1449 dialog_changed(buf, count > 1);
1450 # ifdef FEAT_AUTOCMD
1451 if (!buf_valid(buf))
1452 /* Autocommand deleted buffer, oops! It's not changed now. */
1453 return FALSE;
1454 # endif
1455 return bufIsChanged(buf);
1457 #endif
1458 EMSG(_(e_nowrtmsg));
1459 return TRUE;
1461 return FALSE;
1464 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO)
1466 #if defined(FEAT_BROWSE) || defined(PROTO)
1468 * When wanting to write a file without a file name, ask the user for a name.
1470 void
1471 browse_save_fname(buf)
1472 buf_T *buf;
1474 if (buf->b_fname == NULL)
1476 char_u *fname;
1478 fname = do_browse(BROWSE_SAVE, (char_u *)_("Save As"),
1479 NULL, NULL, NULL, NULL, buf);
1480 if (fname != NULL)
1482 if (setfname(buf, fname, NULL, TRUE) == OK)
1483 buf->b_flags |= BF_NOTEDITED;
1484 vim_free(fname);
1488 #endif
1490 #ifdef FEAT_GUI_MACVIM
1492 * "Save changes" dialog that conforms to the Apple HIG.
1495 vim_dialog_save_changes(buf)
1496 buf_T *buf;
1498 char_u buff[IOSIZE];
1500 dialog_msg(buff, _("Do you want to save the changes you made in the "
1501 "document \"%s\"?"), buf->b_fname);
1502 switch (do_dialog(VIM_QUESTION, buff,
1503 (char_u*) _("Your changes will be lost if you don't save "
1504 "them."),
1505 (buf->b_fname != NULL)
1506 ? (char_u *)_("&Save\n&Cancel\n&Don't Save")
1507 : (char_u *)_("&Save...\n&Cancel\n&Don't Save"),
1508 1, NULL))
1510 case 1: return VIM_YES;
1511 case 3: return VIM_NO;
1514 return VIM_CANCEL;
1518 * "Save all changes" dialog that tries to emulate the above "Save changes"
1519 * dialog for the case of several modified buffers.
1522 vim_dialog_save_all_changes(buf)
1523 buf_T *buf;
1525 char_u buff[IOSIZE];
1527 dialog_msg(buff, _("There are several documents with unsaved changes. "
1528 "Do you want to save the changes you made in the "
1529 "document \"%s\"?"), buf->b_fname);
1530 switch (do_dialog(VIM_QUESTION, buff,
1531 (char_u*) _("Your changes will be lost if you don't save "
1532 "them."),
1533 (char_u *)_("&Save\n&Don't Save\nS&ave All\nD&iscard All\n"
1534 "&Cancel"),
1535 1, NULL))
1537 case 1: return VIM_YES;
1538 case 2: return VIM_NO;
1539 case 3: return VIM_ALL;
1540 case 4: return VIM_DISCARDALL;
1543 return VIM_CANCEL;
1545 #endif
1548 * Ask the user what to do when abondoning a changed buffer.
1549 * Must check 'write' option first!
1551 void
1552 dialog_changed(buf, checkall)
1553 buf_T *buf;
1554 int checkall; /* may abandon all changed buffers */
1556 char_u buff[IOSIZE];
1557 int ret;
1558 buf_T *buf2;
1560 #ifdef FEAT_GUI_MACVIM
1561 /* Save dialogs on Mac OS X are standardized so in case the GUI is enabled
1562 * and "c" isn't in 'guioptions' we use a OS X specific dialog. */
1563 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
1565 if (checkall)
1566 ret = vim_dialog_save_all_changes(buf);
1567 else
1568 ret = vim_dialog_save_changes(buf);
1570 else
1572 #endif
1573 dialog_msg(buff, _("Save changes to \"%s\"?"),
1574 (buf->b_fname != NULL) ?
1575 buf->b_fname : (char_u *)_("Untitled"));
1576 if (checkall)
1577 ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1);
1578 else
1579 ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
1580 #ifdef FEAT_GUI_MACVIM
1582 #endif
1584 if (ret == VIM_YES)
1586 #ifdef FEAT_BROWSE
1587 /* May get file name, when there is none */
1588 browse_save_fname(buf);
1589 #endif
1590 if (buf->b_fname != NULL) /* didn't hit Cancel */
1591 (void)buf_write_all(buf, FALSE);
1593 else if (ret == VIM_NO)
1595 unchanged(buf, TRUE);
1597 else if (ret == VIM_ALL)
1600 * Write all modified files that can be written.
1601 * Skip readonly buffers, these need to be confirmed
1602 * individually.
1604 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1606 if (bufIsChanged(buf2)
1607 && (buf2->b_ffname != NULL
1608 #ifdef FEAT_BROWSE
1609 || cmdmod.browse
1610 #endif
1612 && !buf2->b_p_ro)
1614 #ifdef FEAT_BROWSE
1615 /* May get file name, when there is none */
1616 browse_save_fname(buf2);
1617 #endif
1618 if (buf2->b_fname != NULL) /* didn't hit Cancel */
1619 (void)buf_write_all(buf2, FALSE);
1620 #ifdef FEAT_AUTOCMD
1621 /* an autocommand may have deleted the buffer */
1622 if (!buf_valid(buf2))
1623 buf2 = firstbuf;
1624 #endif
1628 else if (ret == VIM_DISCARDALL)
1631 * mark all buffers as unchanged
1633 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1634 unchanged(buf2, TRUE);
1637 #endif
1640 * Return TRUE if the buffer "buf" can be abandoned, either by making it
1641 * hidden, autowriting it or unloading it.
1644 can_abandon(buf, forceit)
1645 buf_T *buf;
1646 int forceit;
1648 return ( P_HID(buf)
1649 || !bufIsChanged(buf)
1650 || buf->b_nwindows > 1
1651 || autowrite(buf, forceit) == OK
1652 || forceit);
1656 * Return TRUE if any buffer was changed and cannot be abandoned.
1657 * That changed buffer becomes the current buffer.
1660 check_changed_any(hidden)
1661 int hidden; /* Only check hidden buffers */
1663 buf_T *buf;
1664 int save;
1665 #ifdef FEAT_WINDOWS
1666 win_T *wp;
1667 #endif
1669 for (;;)
1671 /* check curbuf first: if it was changed we can't abandon it */
1672 if (!hidden && curbufIsChanged())
1673 buf = curbuf;
1674 else
1676 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
1677 if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf))
1678 break;
1680 if (buf == NULL) /* No buffers changed */
1681 return FALSE;
1683 /* Try auto-writing the buffer. If this fails but the buffer no
1684 * longer exists it's not changed, that's OK. */
1685 if (check_changed(buf, p_awa, TRUE, FALSE, TRUE) && buf_valid(buf))
1686 break; /* didn't save - still changes */
1689 exiting = FALSE;
1690 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1692 * When ":confirm" used, don't give an error message.
1694 if (!(p_confirm || cmdmod.confirm))
1695 #endif
1697 /* There must be a wait_return for this message, do_buffer()
1698 * may cause a redraw. But wait_return() is a no-op when vgetc()
1699 * is busy (Quit used from window menu), then make sure we don't
1700 * cause a scroll up. */
1701 if (vgetc_busy > 0)
1703 msg_row = cmdline_row;
1704 msg_col = 0;
1705 msg_didout = FALSE;
1707 if (EMSG2(_("E162: No write since last change for buffer \"%s\""),
1708 buf_spname(buf) != NULL ? (char_u *)buf_spname(buf) :
1709 buf->b_fname))
1711 save = no_wait_return;
1712 no_wait_return = FALSE;
1713 wait_return(FALSE);
1714 no_wait_return = save;
1718 #ifdef FEAT_WINDOWS
1719 /* Try to find a window that contains the buffer. */
1720 if (buf != curbuf)
1721 for (wp = firstwin; wp != NULL; wp = wp->w_next)
1722 if (wp->w_buffer == buf)
1724 win_goto(wp);
1725 # ifdef FEAT_AUTOCMD
1726 /* Paranoia: did autocms wipe out the buffer with changes? */
1727 if (!buf_valid(buf))
1728 return TRUE;
1729 # endif
1730 break;
1732 #endif
1734 /* Open the changed buffer in the current window. */
1735 if (buf != curbuf)
1736 set_curbuf(buf, DOBUF_GOTO);
1738 return TRUE;
1742 * return FAIL if there is no file name, OK if there is one
1743 * give error message for FAIL
1746 check_fname()
1748 if (curbuf->b_ffname == NULL)
1750 EMSG(_(e_noname));
1751 return FAIL;
1753 return OK;
1757 * flush the contents of a buffer, unless it has no file name
1759 * return FAIL for failure, OK otherwise
1762 buf_write_all(buf, forceit)
1763 buf_T *buf;
1764 int forceit;
1766 int retval;
1767 #ifdef FEAT_AUTOCMD
1768 buf_T *old_curbuf = curbuf;
1769 #endif
1771 retval = (buf_write(buf, buf->b_ffname, buf->b_fname,
1772 (linenr_T)1, buf->b_ml.ml_line_count, NULL,
1773 FALSE, forceit, TRUE, FALSE));
1774 #ifdef FEAT_AUTOCMD
1775 if (curbuf != old_curbuf)
1777 msg_source(hl_attr(HLF_W));
1778 MSG(_("Warning: Entered other buffer unexpectedly (check autocommands)"));
1780 #endif
1781 return retval;
1785 * Code to handle the argument list.
1788 static char_u *do_one_arg __ARGS((char_u *str));
1789 static int do_arglist __ARGS((char_u *str, int what, int after));
1790 static void alist_check_arg_idx __ARGS((void));
1791 static int editing_arg_idx __ARGS((win_T *win));
1792 #ifdef FEAT_LISTCMDS
1793 static int alist_add_list __ARGS((int count, char_u **files, int after));
1794 #endif
1795 #define AL_SET 1
1796 #define AL_ADD 2
1797 #define AL_DEL 3
1800 * Isolate one argument, taking backticks.
1801 * Changes the argument in-place, puts a NUL after it. Backticks remain.
1802 * Return a pointer to the start of the next argument.
1804 static char_u *
1805 do_one_arg(str)
1806 char_u *str;
1808 char_u *p;
1809 int inbacktick;
1811 inbacktick = FALSE;
1812 for (p = str; *str; ++str)
1814 /* When the backslash is used for escaping the special meaning of a
1815 * character we need to keep it until wildcard expansion. */
1816 if (rem_backslash(str))
1818 *p++ = *str++;
1819 *p++ = *str;
1821 else
1823 /* An item ends at a space not in backticks */
1824 if (!inbacktick && vim_isspace(*str))
1825 break;
1826 if (*str == '`')
1827 inbacktick ^= TRUE;
1828 *p++ = *str;
1831 str = skipwhite(str);
1832 *p = NUL;
1834 return str;
1838 * Separate the arguments in "str" and return a list of pointers in the
1839 * growarray "gap".
1842 get_arglist(gap, str)
1843 garray_T *gap;
1844 char_u *str;
1846 ga_init2(gap, (int)sizeof(char_u *), 20);
1847 while (*str != NUL)
1849 if (ga_grow(gap, 1) == FAIL)
1851 ga_clear(gap);
1852 return FAIL;
1854 ((char_u **)gap->ga_data)[gap->ga_len++] = str;
1856 /* Isolate one argument, change it in-place, put a NUL after it. */
1857 str = do_one_arg(str);
1859 return OK;
1862 #if defined(FEAT_QUICKFIX) || defined(FEAT_SYN_HL) || defined(PROTO)
1864 * Parse a list of arguments (file names), expand them and return in
1865 * "fnames[fcountp]".
1866 * Return FAIL or OK.
1869 get_arglist_exp(str, fcountp, fnamesp)
1870 char_u *str;
1871 int *fcountp;
1872 char_u ***fnamesp;
1874 garray_T ga;
1875 int i;
1877 if (get_arglist(&ga, str) == FAIL)
1878 return FAIL;
1879 i = gen_expand_wildcards(ga.ga_len, (char_u **)ga.ga_data,
1880 fcountp, fnamesp, EW_FILE|EW_NOTFOUND);
1881 ga_clear(&ga);
1882 return i;
1884 #endif
1886 #if defined(FEAT_GUI) || defined(FEAT_CLIENTSERVER) || defined(PROTO)
1888 * Redefine the argument list.
1890 void
1891 set_arglist(str)
1892 char_u *str;
1894 do_arglist(str, AL_SET, 0);
1896 #endif
1899 * "what" == AL_SET: Redefine the argument list to 'str'.
1900 * "what" == AL_ADD: add files in 'str' to the argument list after "after".
1901 * "what" == AL_DEL: remove files in 'str' from the argument list.
1903 * Return FAIL for failure, OK otherwise.
1905 static int
1906 do_arglist(str, what, after)
1907 char_u *str;
1908 int what UNUSED;
1909 int after UNUSED; /* 0 means before first one */
1911 garray_T new_ga;
1912 int exp_count;
1913 char_u **exp_files;
1914 int i;
1915 #ifdef FEAT_LISTCMDS
1916 char_u *p;
1917 int match;
1918 #endif
1921 * Collect all file name arguments in "new_ga".
1923 if (get_arglist(&new_ga, str) == FAIL)
1924 return FAIL;
1926 #ifdef FEAT_LISTCMDS
1927 if (what == AL_DEL)
1929 regmatch_T regmatch;
1930 int didone;
1933 * Delete the items: use each item as a regexp and find a match in the
1934 * argument list.
1936 #ifdef CASE_INSENSITIVE_FILENAME
1937 regmatch.rm_ic = TRUE; /* Always ignore case */
1938 #else
1939 regmatch.rm_ic = FALSE; /* Never ignore case */
1940 #endif
1941 for (i = 0; i < new_ga.ga_len && !got_int; ++i)
1943 p = ((char_u **)new_ga.ga_data)[i];
1944 p = file_pat_to_reg_pat(p, NULL, NULL, FALSE);
1945 if (p == NULL)
1946 break;
1947 regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0);
1948 if (regmatch.regprog == NULL)
1950 vim_free(p);
1951 break;
1954 didone = FALSE;
1955 for (match = 0; match < ARGCOUNT; ++match)
1956 if (vim_regexec(&regmatch, alist_name(&ARGLIST[match]),
1957 (colnr_T)0))
1959 didone = TRUE;
1960 vim_free(ARGLIST[match].ae_fname);
1961 mch_memmove(ARGLIST + match, ARGLIST + match + 1,
1962 (ARGCOUNT - match - 1) * sizeof(aentry_T));
1963 --ALIST(curwin)->al_ga.ga_len;
1964 if (curwin->w_arg_idx > match)
1965 --curwin->w_arg_idx;
1966 --match;
1969 vim_free(regmatch.regprog);
1970 vim_free(p);
1971 if (!didone)
1972 EMSG2(_(e_nomatch2), ((char_u **)new_ga.ga_data)[i]);
1974 ga_clear(&new_ga);
1976 else
1977 #endif
1979 i = expand_wildcards(new_ga.ga_len, (char_u **)new_ga.ga_data,
1980 &exp_count, &exp_files, EW_DIR|EW_FILE|EW_ADDSLASH|EW_NOTFOUND);
1981 ga_clear(&new_ga);
1982 if (i == FAIL)
1983 return FAIL;
1984 if (exp_count == 0)
1986 EMSG(_(e_nomatch));
1987 return FAIL;
1990 #ifdef FEAT_LISTCMDS
1991 if (what == AL_ADD)
1993 (void)alist_add_list(exp_count, exp_files, after);
1994 vim_free(exp_files);
1996 else /* what == AL_SET */
1997 #endif
1998 alist_set(ALIST(curwin), exp_count, exp_files, FALSE, NULL, 0);
2001 alist_check_arg_idx();
2003 return OK;
2007 * Check the validity of the arg_idx for each other window.
2009 static void
2010 alist_check_arg_idx()
2012 #ifdef FEAT_WINDOWS
2013 win_T *win;
2014 tabpage_T *tp;
2016 FOR_ALL_TAB_WINDOWS(tp, win)
2017 if (win->w_alist == curwin->w_alist)
2018 check_arg_idx(win);
2019 #else
2020 check_arg_idx(curwin);
2021 #endif
2025 * Return TRUE if window "win" is editing then file at the current argument
2026 * index.
2028 static int
2029 editing_arg_idx(win)
2030 win_T *win;
2032 return !(win->w_arg_idx >= WARGCOUNT(win)
2033 || (win->w_buffer->b_fnum
2034 != WARGLIST(win)[win->w_arg_idx].ae_fnum
2035 && (win->w_buffer->b_ffname == NULL
2036 || !(fullpathcmp(
2037 alist_name(&WARGLIST(win)[win->w_arg_idx]),
2038 win->w_buffer->b_ffname, TRUE) & FPC_SAME))));
2042 * Check if window "win" is editing the w_arg_idx file in its argument list.
2044 void
2045 check_arg_idx(win)
2046 win_T *win;
2048 if (WARGCOUNT(win) > 1 && !editing_arg_idx(win))
2050 /* We are not editing the current entry in the argument list.
2051 * Set "arg_had_last" if we are editing the last one. */
2052 win->w_arg_idx_invalid = TRUE;
2053 if (win->w_arg_idx != WARGCOUNT(win) - 1
2054 && arg_had_last == FALSE
2055 #ifdef FEAT_WINDOWS
2056 && ALIST(win) == &global_alist
2057 #endif
2058 && GARGCOUNT > 0
2059 && win->w_arg_idx < GARGCOUNT
2060 && (win->w_buffer->b_fnum == GARGLIST[GARGCOUNT - 1].ae_fnum
2061 || (win->w_buffer->b_ffname != NULL
2062 && (fullpathcmp(alist_name(&GARGLIST[GARGCOUNT - 1]),
2063 win->w_buffer->b_ffname, TRUE) & FPC_SAME))))
2064 arg_had_last = TRUE;
2066 else
2068 /* We are editing the current entry in the argument list.
2069 * Set "arg_had_last" if it's also the last one */
2070 win->w_arg_idx_invalid = FALSE;
2071 if (win->w_arg_idx == WARGCOUNT(win) - 1
2072 #ifdef FEAT_WINDOWS
2073 && win->w_alist == &global_alist
2074 #endif
2076 arg_had_last = TRUE;
2081 * ":args", ":argslocal" and ":argsglobal".
2083 void
2084 ex_args(eap)
2085 exarg_T *eap;
2087 int i;
2089 if (eap->cmdidx != CMD_args)
2091 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
2092 alist_unlink(ALIST(curwin));
2093 if (eap->cmdidx == CMD_argglobal)
2094 ALIST(curwin) = &global_alist;
2095 else /* eap->cmdidx == CMD_arglocal */
2096 alist_new();
2097 #else
2098 ex_ni(eap);
2099 return;
2100 #endif
2103 if (!ends_excmd(*eap->arg))
2106 * ":args file ..": define new argument list, handle like ":next"
2107 * Also for ":argslocal file .." and ":argsglobal file ..".
2109 ex_next(eap);
2111 else
2112 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
2113 if (eap->cmdidx == CMD_args)
2114 #endif
2117 * ":args": list arguments.
2119 if (ARGCOUNT > 0)
2121 /* Overwrite the command, for a short list there is no scrolling
2122 * required and no wait_return(). */
2123 gotocmdline(TRUE);
2124 for (i = 0; i < ARGCOUNT; ++i)
2126 if (i == curwin->w_arg_idx)
2127 msg_putchar('[');
2128 msg_outtrans(alist_name(&ARGLIST[i]));
2129 if (i == curwin->w_arg_idx)
2130 msg_putchar(']');
2131 msg_putchar(' ');
2135 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
2136 else if (eap->cmdidx == CMD_arglocal)
2138 garray_T *gap = &curwin->w_alist->al_ga;
2141 * ":argslocal": make a local copy of the global argument list.
2143 if (ga_grow(gap, GARGCOUNT) == OK)
2144 for (i = 0; i < GARGCOUNT; ++i)
2145 if (GARGLIST[i].ae_fname != NULL)
2147 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fname =
2148 vim_strsave(GARGLIST[i].ae_fname);
2149 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fnum =
2150 GARGLIST[i].ae_fnum;
2151 ++gap->ga_len;
2154 #endif
2158 * ":previous", ":sprevious", ":Next" and ":sNext".
2160 void
2161 ex_previous(eap)
2162 exarg_T *eap;
2164 /* If past the last one already, go to the last one. */
2165 if (curwin->w_arg_idx - (int)eap->line2 >= ARGCOUNT)
2166 do_argfile(eap, ARGCOUNT - 1);
2167 else
2168 do_argfile(eap, curwin->w_arg_idx - (int)eap->line2);
2172 * ":rewind", ":first", ":sfirst" and ":srewind".
2174 void
2175 ex_rewind(eap)
2176 exarg_T *eap;
2178 do_argfile(eap, 0);
2182 * ":last" and ":slast".
2184 void
2185 ex_last(eap)
2186 exarg_T *eap;
2188 do_argfile(eap, ARGCOUNT - 1);
2192 * ":argument" and ":sargument".
2194 void
2195 ex_argument(eap)
2196 exarg_T *eap;
2198 int i;
2200 if (eap->addr_count > 0)
2201 i = eap->line2 - 1;
2202 else
2203 i = curwin->w_arg_idx;
2204 do_argfile(eap, i);
2208 * Edit file "argn" of the argument lists.
2210 void
2211 do_argfile(eap, argn)
2212 exarg_T *eap;
2213 int argn;
2215 int other;
2216 char_u *p;
2217 int old_arg_idx = curwin->w_arg_idx;
2219 if (argn < 0 || argn >= ARGCOUNT)
2221 if (ARGCOUNT <= 1)
2222 EMSG(_("E163: There is only one file to edit"));
2223 else if (argn < 0)
2224 EMSG(_("E164: Cannot go before first file"));
2225 else
2226 EMSG(_("E165: Cannot go beyond last file"));
2228 else
2230 setpcmark();
2231 #ifdef FEAT_GUI
2232 need_mouse_correct = TRUE;
2233 #endif
2235 #ifdef FEAT_WINDOWS
2236 /* split window or create new tab page first */
2237 if (*eap->cmd == 's' || cmdmod.tab != 0)
2239 if (win_split(0, 0) == FAIL)
2240 return;
2241 # ifdef FEAT_SCROLLBIND
2242 curwin->w_p_scb = FALSE;
2243 # endif
2245 else
2246 #endif
2249 * if 'hidden' set, only check for changed file when re-editing
2250 * the same buffer
2252 other = TRUE;
2253 if (P_HID(curbuf))
2255 p = fix_fname(alist_name(&ARGLIST[argn]));
2256 other = otherfile(p);
2257 vim_free(p);
2259 if ((!P_HID(curbuf) || !other)
2260 && check_changed(curbuf, TRUE, !other, eap->forceit, FALSE))
2261 return;
2264 curwin->w_arg_idx = argn;
2265 if (argn == ARGCOUNT - 1
2266 #ifdef FEAT_WINDOWS
2267 && curwin->w_alist == &global_alist
2268 #endif
2270 arg_had_last = TRUE;
2272 /* Edit the file; always use the last known line number.
2273 * When it fails (e.g. Abort for already edited file) restore the
2274 * argument index. */
2275 if (do_ecmd(0, alist_name(&ARGLIST[curwin->w_arg_idx]), NULL,
2276 eap, ECMD_LAST,
2277 (P_HID(curwin->w_buffer) ? ECMD_HIDE : 0)
2278 + (eap->forceit ? ECMD_FORCEIT : 0), curwin) == FAIL)
2279 curwin->w_arg_idx = old_arg_idx;
2280 /* like Vi: set the mark where the cursor is in the file. */
2281 else if (eap->cmdidx != CMD_argdo)
2282 setmark('\'');
2287 * ":next", and commands that behave like it.
2289 void
2290 ex_next(eap)
2291 exarg_T *eap;
2293 int i;
2296 * check for changed buffer now, if this fails the argument list is not
2297 * redefined.
2299 if ( P_HID(curbuf)
2300 || eap->cmdidx == CMD_snext
2301 || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
2303 if (*eap->arg != NUL) /* redefine file list */
2305 if (do_arglist(eap->arg, AL_SET, 0) == FAIL)
2306 return;
2307 i = 0;
2309 else
2310 i = curwin->w_arg_idx + (int)eap->line2;
2311 do_argfile(eap, i);
2315 #ifdef FEAT_LISTCMDS
2317 * ":argedit"
2319 void
2320 ex_argedit(eap)
2321 exarg_T *eap;
2323 int fnum;
2324 int i;
2325 char_u *s;
2327 /* Add the argument to the buffer list and get the buffer number. */
2328 fnum = buflist_add(eap->arg, BLN_LISTED);
2330 /* Check if this argument is already in the argument list. */
2331 for (i = 0; i < ARGCOUNT; ++i)
2332 if (ARGLIST[i].ae_fnum == fnum)
2333 break;
2334 if (i == ARGCOUNT)
2336 /* Can't find it, add it to the argument list. */
2337 s = vim_strsave(eap->arg);
2338 if (s == NULL)
2339 return;
2340 i = alist_add_list(1, &s,
2341 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
2342 if (i < 0)
2343 return;
2344 curwin->w_arg_idx = i;
2347 alist_check_arg_idx();
2349 /* Edit the argument. */
2350 do_argfile(eap, i);
2354 * ":argadd"
2356 void
2357 ex_argadd(eap)
2358 exarg_T *eap;
2360 do_arglist(eap->arg, AL_ADD,
2361 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
2362 #ifdef FEAT_TITLE
2363 maketitle();
2364 #endif
2368 * ":argdelete"
2370 void
2371 ex_argdelete(eap)
2372 exarg_T *eap;
2374 int i;
2375 int n;
2377 if (eap->addr_count > 0)
2379 /* ":1,4argdel": Delete all arguments in the range. */
2380 if (eap->line2 > ARGCOUNT)
2381 eap->line2 = ARGCOUNT;
2382 n = eap->line2 - eap->line1 + 1;
2383 if (*eap->arg != NUL || n <= 0)
2384 EMSG(_(e_invarg));
2385 else
2387 for (i = eap->line1; i <= eap->line2; ++i)
2388 vim_free(ARGLIST[i - 1].ae_fname);
2389 mch_memmove(ARGLIST + eap->line1 - 1, ARGLIST + eap->line2,
2390 (size_t)((ARGCOUNT - eap->line2) * sizeof(aentry_T)));
2391 ALIST(curwin)->al_ga.ga_len -= n;
2392 if (curwin->w_arg_idx >= eap->line2)
2393 curwin->w_arg_idx -= n;
2394 else if (curwin->w_arg_idx > eap->line1)
2395 curwin->w_arg_idx = eap->line1;
2398 else if (*eap->arg == NUL)
2399 EMSG(_(e_argreq));
2400 else
2401 do_arglist(eap->arg, AL_DEL, 0);
2402 #ifdef FEAT_TITLE
2403 maketitle();
2404 #endif
2408 * ":argdo", ":windo", ":bufdo", ":tabdo"
2410 void
2411 ex_listdo(eap)
2412 exarg_T *eap;
2414 int i;
2415 #ifdef FEAT_WINDOWS
2416 win_T *wp;
2417 tabpage_T *tp;
2418 #endif
2419 buf_T *buf;
2420 int next_fnum = 0;
2421 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2422 char_u *save_ei = NULL;
2423 #endif
2424 char_u *p_shm_save;
2426 #ifndef FEAT_WINDOWS
2427 if (eap->cmdidx == CMD_windo)
2429 ex_ni(eap);
2430 return;
2432 #endif
2434 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2435 if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo)
2436 /* Don't do syntax HL autocommands. Skipping the syntax file is a
2437 * great speed improvement. */
2438 save_ei = au_event_disable(",Syntax");
2439 #endif
2441 if (eap->cmdidx == CMD_windo
2442 || eap->cmdidx == CMD_tabdo
2443 || P_HID(curbuf)
2444 || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
2446 /* start at the first argument/window/buffer */
2447 i = 0;
2448 #ifdef FEAT_WINDOWS
2449 wp = firstwin;
2450 tp = first_tabpage;
2451 #endif
2452 /* set pcmark now */
2453 if (eap->cmdidx == CMD_bufdo)
2454 goto_buffer(eap, DOBUF_FIRST, FORWARD, 0);
2455 else
2456 setpcmark();
2457 listcmd_busy = TRUE; /* avoids setting pcmark below */
2459 while (!got_int)
2461 if (eap->cmdidx == CMD_argdo)
2463 /* go to argument "i" */
2464 if (i == ARGCOUNT)
2465 break;
2466 /* Don't call do_argfile() when already there, it will try
2467 * reloading the file. */
2468 if (curwin->w_arg_idx != i || !editing_arg_idx(curwin))
2470 /* Clear 'shm' to avoid that the file message overwrites
2471 * any output from the command. */
2472 p_shm_save = vim_strsave(p_shm);
2473 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
2474 do_argfile(eap, i);
2475 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
2476 vim_free(p_shm_save);
2478 if (curwin->w_arg_idx != i)
2479 break;
2480 ++i;
2482 #ifdef FEAT_WINDOWS
2483 else if (eap->cmdidx == CMD_windo)
2485 /* go to window "wp" */
2486 if (!win_valid(wp))
2487 break;
2488 win_goto(wp);
2489 if (curwin != wp)
2490 break; /* something must be wrong */
2491 wp = curwin->w_next;
2493 else if (eap->cmdidx == CMD_tabdo)
2495 /* go to window "tp" */
2496 if (!valid_tabpage(tp))
2497 break;
2498 goto_tabpage_tp(tp);
2499 tp = tp->tp_next;
2501 #endif
2502 else if (eap->cmdidx == CMD_bufdo)
2504 /* Remember the number of the next listed buffer, in case
2505 * ":bwipe" is used or autocommands do something strange. */
2506 next_fnum = -1;
2507 for (buf = curbuf->b_next; buf != NULL; buf = buf->b_next)
2508 if (buf->b_p_bl)
2510 next_fnum = buf->b_fnum;
2511 break;
2515 /* execute the command */
2516 do_cmdline(eap->arg, eap->getline, eap->cookie,
2517 DOCMD_VERBOSE + DOCMD_NOWAIT);
2519 if (eap->cmdidx == CMD_bufdo)
2521 /* Done? */
2522 if (next_fnum < 0)
2523 break;
2524 /* Check if the buffer still exists. */
2525 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
2526 if (buf->b_fnum == next_fnum)
2527 break;
2528 if (buf == NULL)
2529 break;
2531 /* Go to the next buffer. Clear 'shm' to avoid that the file
2532 * message overwrites any output from the command. */
2533 p_shm_save = vim_strsave(p_shm);
2534 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
2535 goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
2536 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
2537 vim_free(p_shm_save);
2539 /* If autocommands took us elsewhere, quit here */
2540 if (curbuf->b_fnum != next_fnum)
2541 break;
2544 if (eap->cmdidx == CMD_windo)
2546 validate_cursor(); /* cursor may have moved */
2547 #ifdef FEAT_SCROLLBIND
2548 /* required when 'scrollbind' has been set */
2549 if (curwin->w_p_scb)
2550 do_check_scrollbind(TRUE);
2551 #endif
2554 listcmd_busy = FALSE;
2557 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2558 if (save_ei != NULL)
2560 au_event_restore(save_ei);
2561 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
2562 curbuf->b_fname, TRUE, curbuf);
2564 #endif
2568 * Add files[count] to the arglist of the current window after arg "after".
2569 * The file names in files[count] must have been allocated and are taken over.
2570 * Files[] itself is not taken over.
2571 * Returns index of first added argument. Returns -1 when failed (out of mem).
2573 static int
2574 alist_add_list(count, files, after)
2575 int count;
2576 char_u **files;
2577 int after; /* where to add: 0 = before first one */
2579 int i;
2581 if (ga_grow(&ALIST(curwin)->al_ga, count) == OK)
2583 if (after < 0)
2584 after = 0;
2585 if (after > ARGCOUNT)
2586 after = ARGCOUNT;
2587 if (after < ARGCOUNT)
2588 mch_memmove(&(ARGLIST[after + count]), &(ARGLIST[after]),
2589 (ARGCOUNT - after) * sizeof(aentry_T));
2590 for (i = 0; i < count; ++i)
2592 ARGLIST[after + i].ae_fname = files[i];
2593 ARGLIST[after + i].ae_fnum = buflist_add(files[i], BLN_LISTED);
2595 ALIST(curwin)->al_ga.ga_len += count;
2596 if (curwin->w_arg_idx >= after)
2597 ++curwin->w_arg_idx;
2598 return after;
2601 for (i = 0; i < count; ++i)
2602 vim_free(files[i]);
2603 return -1;
2606 #endif /* FEAT_LISTCMDS */
2608 #ifdef FEAT_EVAL
2610 * ":compiler[!] {name}"
2612 void
2613 ex_compiler(eap)
2614 exarg_T *eap;
2616 char_u *buf;
2617 char_u *old_cur_comp = NULL;
2618 char_u *p;
2620 if (*eap->arg == NUL)
2622 /* List all compiler scripts. */
2623 do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')");
2624 /* ) keep the indenter happy... */
2626 else
2628 buf = alloc((unsigned)(STRLEN(eap->arg) + 14));
2629 if (buf != NULL)
2631 if (eap->forceit)
2633 /* ":compiler! {name}" sets global options */
2634 do_cmdline_cmd((char_u *)
2635 "command -nargs=* CompilerSet set <args>");
2637 else
2639 /* ":compiler! {name}" sets local options.
2640 * To remain backwards compatible "current_compiler" is always
2641 * used. A user's compiler plugin may set it, the distributed
2642 * plugin will then skip the settings. Afterwards set
2643 * "b:current_compiler" and restore "current_compiler".
2644 * Explicitly prepend "g:" to make it work in a function. */
2645 old_cur_comp = get_var_value((char_u *)"g:current_compiler");
2646 if (old_cur_comp != NULL)
2647 old_cur_comp = vim_strsave(old_cur_comp);
2648 do_cmdline_cmd((char_u *)
2649 "command -nargs=* CompilerSet setlocal <args>");
2651 do_unlet((char_u *)"g:current_compiler", TRUE);
2652 do_unlet((char_u *)"b:current_compiler", TRUE);
2654 sprintf((char *)buf, "compiler/%s.vim", eap->arg);
2655 if (source_runtime(buf, TRUE) == FAIL)
2656 EMSG2(_("E666: compiler not supported: %s"), eap->arg);
2657 vim_free(buf);
2659 do_cmdline_cmd((char_u *)":delcommand CompilerSet");
2661 /* Set "b:current_compiler" from "current_compiler". */
2662 p = get_var_value((char_u *)"g:current_compiler");
2663 if (p != NULL)
2664 set_internal_string_var((char_u *)"b:current_compiler", p);
2666 /* Restore "current_compiler" for ":compiler {name}". */
2667 if (!eap->forceit)
2669 if (old_cur_comp != NULL)
2671 set_internal_string_var((char_u *)"g:current_compiler",
2672 old_cur_comp);
2673 vim_free(old_cur_comp);
2675 else
2676 do_unlet((char_u *)"g:current_compiler", TRUE);
2681 #endif
2684 * ":runtime {name}"
2686 void
2687 ex_runtime(eap)
2688 exarg_T *eap;
2690 source_runtime(eap->arg, eap->forceit);
2693 static void source_callback __ARGS((char_u *fname, void *cookie));
2695 static void
2696 source_callback(fname, cookie)
2697 char_u *fname;
2698 void *cookie UNUSED;
2700 (void)do_source(fname, FALSE, DOSO_NONE);
2704 * Source the file "name" from all directories in 'runtimepath'.
2705 * "name" can contain wildcards.
2706 * When "all" is TRUE, source all files, otherwise only the first one.
2707 * return FAIL when no file could be sourced, OK otherwise.
2710 source_runtime(name, all)
2711 char_u *name;
2712 int all;
2714 return do_in_runtimepath(name, all, source_callback, NULL);
2718 * Find "name" in 'runtimepath'. When found, invoke the callback function for
2719 * it: callback(fname, "cookie")
2720 * When "all" is TRUE repeat for all matches, otherwise only the first one is
2721 * used.
2722 * Returns OK when at least one match found, FAIL otherwise.
2725 do_in_runtimepath(name, all, callback, cookie)
2726 char_u *name;
2727 int all;
2728 void (*callback)__ARGS((char_u *fname, void *ck));
2729 void *cookie;
2731 char_u *rtp;
2732 char_u *np;
2733 char_u *buf;
2734 char_u *rtp_copy;
2735 char_u *tail;
2736 int num_files;
2737 char_u **files;
2738 int i;
2739 int did_one = FALSE;
2740 #ifdef AMIGA
2741 struct Process *proc = (struct Process *)FindTask(0L);
2742 APTR save_winptr = proc->pr_WindowPtr;
2744 /* Avoid a requester here for a volume that doesn't exist. */
2745 proc->pr_WindowPtr = (APTR)-1L;
2746 #endif
2748 /* Make a copy of 'runtimepath'. Invoking the callback may change the
2749 * value. */
2750 rtp_copy = vim_strsave(p_rtp);
2751 buf = alloc(MAXPATHL);
2752 if (buf != NULL && rtp_copy != NULL)
2754 if (p_verbose > 1)
2756 verbose_enter();
2757 smsg((char_u *)_("Searching for \"%s\" in \"%s\""),
2758 (char *)name, (char *)p_rtp);
2759 verbose_leave();
2762 /* Loop over all entries in 'runtimepath'. */
2763 rtp = rtp_copy;
2764 while (*rtp != NUL && (all || !did_one))
2766 /* Copy the path from 'runtimepath' to buf[]. */
2767 copy_option_part(&rtp, buf, MAXPATHL, ",");
2768 if (STRLEN(buf) + STRLEN(name) + 2 < MAXPATHL)
2770 add_pathsep(buf);
2771 tail = buf + STRLEN(buf);
2773 /* Loop over all patterns in "name" */
2774 np = name;
2775 while (*np != NUL && (all || !did_one))
2777 /* Append the pattern from "name" to buf[]. */
2778 copy_option_part(&np, tail, (int)(MAXPATHL - (tail - buf)),
2779 "\t ");
2781 if (p_verbose > 2)
2783 verbose_enter();
2784 smsg((char_u *)_("Searching for \"%s\""), buf);
2785 verbose_leave();
2788 /* Expand wildcards, invoke the callback for each match. */
2789 if (gen_expand_wildcards(1, &buf, &num_files, &files,
2790 EW_FILE) == OK)
2792 for (i = 0; i < num_files; ++i)
2794 (*callback)(files[i], cookie);
2795 did_one = TRUE;
2796 if (!all)
2797 break;
2799 FreeWild(num_files, files);
2805 vim_free(buf);
2806 vim_free(rtp_copy);
2807 if (p_verbose > 0 && !did_one)
2809 verbose_enter();
2810 smsg((char_u *)_("not found in 'runtimepath': \"%s\""), name);
2811 verbose_leave();
2814 #ifdef AMIGA
2815 proc->pr_WindowPtr = save_winptr;
2816 #endif
2818 return did_one ? OK : FAIL;
2821 #if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD)
2823 * ":options"
2825 void
2826 ex_options(eap)
2827 exarg_T *eap UNUSED;
2829 cmd_source((char_u *)SYS_OPTWIN_FILE, NULL);
2831 #endif
2834 * ":source {fname}"
2836 void
2837 ex_source(eap)
2838 exarg_T *eap;
2840 #ifdef FEAT_BROWSE
2841 if (cmdmod.browse)
2843 char_u *fname = NULL;
2845 fname = do_browse(0, (char_u *)_("Source Vim script"), eap->arg,
2846 NULL, NULL, BROWSE_FILTER_MACROS, NULL);
2847 if (fname != NULL)
2849 cmd_source(fname, eap);
2850 vim_free(fname);
2853 else
2854 #endif
2855 cmd_source(eap->arg, eap);
2858 static void
2859 cmd_source(fname, eap)
2860 char_u *fname;
2861 exarg_T *eap;
2863 if (*fname == NUL)
2864 EMSG(_(e_argreq));
2866 else if (eap != NULL && eap->forceit)
2867 /* ":source!": read Normal mdoe commands
2868 * Need to execute the commands directly. This is required at least
2869 * for:
2870 * - ":g" command busy
2871 * - after ":argdo", ":windo" or ":bufdo"
2872 * - another command follows
2873 * - inside a loop
2875 openscript(fname, global_busy || listcmd_busy || eap->nextcmd != NULL
2876 #ifdef FEAT_EVAL
2877 || eap->cstack->cs_idx >= 0
2878 #endif
2881 /* ":source" read ex commands */
2882 else if (do_source(fname, FALSE, DOSO_NONE) == FAIL)
2883 EMSG2(_(e_notopen), fname);
2887 * ":source" and associated commands.
2890 * Structure used to store info for each sourced file.
2891 * It is shared between do_source() and getsourceline().
2892 * This is required, because it needs to be handed to do_cmdline() and
2893 * sourcing can be done recursively.
2895 struct source_cookie
2897 FILE *fp; /* opened file for sourcing */
2898 char_u *nextline; /* if not NULL: line that was read ahead */
2899 int finished; /* ":finish" used */
2900 #if defined (USE_CRNL) || defined (USE_CR)
2901 int fileformat; /* EOL_UNKNOWN, EOL_UNIX or EOL_DOS */
2902 int error; /* TRUE if LF found after CR-LF */
2903 #endif
2904 #ifdef FEAT_EVAL
2905 linenr_T breakpoint; /* next line with breakpoint or zero */
2906 char_u *fname; /* name of sourced file */
2907 int dbg_tick; /* debug_tick when breakpoint was set */
2908 int level; /* top nesting level of sourced file */
2909 #endif
2910 #ifdef FEAT_MBYTE
2911 vimconv_T conv; /* type of conversion */
2912 #endif
2915 #ifdef FEAT_EVAL
2917 * Return the address holding the next breakpoint line for a source cookie.
2919 linenr_T *
2920 source_breakpoint(cookie)
2921 void *cookie;
2923 return &((struct source_cookie *)cookie)->breakpoint;
2927 * Return the address holding the debug tick for a source cookie.
2929 int *
2930 source_dbg_tick(cookie)
2931 void *cookie;
2933 return &((struct source_cookie *)cookie)->dbg_tick;
2937 * Return the nesting level for a source cookie.
2940 source_level(cookie)
2941 void *cookie;
2943 return ((struct source_cookie *)cookie)->level;
2945 #endif
2947 static char_u *get_one_sourceline __ARGS((struct source_cookie *sp));
2949 #if (defined(WIN32) && defined(FEAT_CSCOPE)) || defined(HAVE_FD_CLOEXEC)
2950 # define USE_FOPEN_NOINH
2951 static FILE *fopen_noinh_readbin __ARGS((char *filename));
2954 * Special function to open a file without handle inheritance.
2955 * When possible the handle is closed on exec().
2957 static FILE *
2958 fopen_noinh_readbin(filename)
2959 char *filename;
2961 # ifdef WIN32
2962 int fd_tmp = mch_open(filename, O_RDONLY | O_BINARY | O_NOINHERIT, 0);
2963 # else
2964 int fd_tmp = mch_open(filename, O_RDONLY, 0);
2965 # endif
2967 if (fd_tmp == -1)
2968 return NULL;
2970 # ifdef HAVE_FD_CLOEXEC
2972 int fdflags = fcntl(fd_tmp, F_GETFD);
2973 if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0)
2974 fcntl(fd_tmp, F_SETFD, fdflags | FD_CLOEXEC);
2976 # endif
2978 return fdopen(fd_tmp, READBIN);
2980 #endif
2984 * do_source: Read the file "fname" and execute its lines as EX commands.
2986 * This function may be called recursively!
2988 * return FAIL if file could not be opened, OK otherwise
2991 do_source(fname, check_other, is_vimrc)
2992 char_u *fname;
2993 int check_other; /* check for .vimrc and _vimrc */
2994 int is_vimrc; /* DOSO_ value */
2996 struct source_cookie cookie;
2997 char_u *save_sourcing_name;
2998 linenr_T save_sourcing_lnum;
2999 char_u *p;
3000 char_u *fname_exp;
3001 char_u *firstline = NULL;
3002 int retval = FAIL;
3003 #ifdef FEAT_EVAL
3004 scid_T save_current_SID;
3005 static scid_T last_current_SID = 0;
3006 void *save_funccalp;
3007 int save_debug_break_level = debug_break_level;
3008 scriptitem_T *si = NULL;
3009 # ifdef UNIX
3010 struct stat st;
3011 int stat_ok;
3012 # endif
3013 #endif
3014 #ifdef STARTUPTIME
3015 struct timeval tv_rel;
3016 struct timeval tv_start;
3017 #endif
3018 #ifdef FEAT_PROFILE
3019 proftime_T wait_start;
3020 #endif
3022 #ifdef RISCOS
3023 p = mch_munge_fname(fname);
3024 #else
3025 p = expand_env_save(fname);
3026 #endif
3027 if (p == NULL)
3028 return retval;
3029 fname_exp = fix_fname(p);
3030 vim_free(p);
3031 if (fname_exp == NULL)
3032 return retval;
3033 if (mch_isdir(fname_exp))
3035 smsg((char_u *)_("Cannot source a directory: \"%s\""), fname);
3036 goto theend;
3039 #ifdef FEAT_AUTOCMD
3040 /* Apply SourceCmd autocommands, they should get the file and source it. */
3041 if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL)
3042 && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp,
3043 FALSE, curbuf))
3045 # ifdef FEAT_EVAL
3046 retval = aborting() ? FAIL : OK;
3047 # else
3048 retval = OK;
3049 # endif
3050 goto theend;
3053 /* Apply SourcePre autocommands, they may get the file. */
3054 apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, FALSE, curbuf);
3055 #endif
3057 #ifdef USE_FOPEN_NOINH
3058 cookie.fp = fopen_noinh_readbin((char *)fname_exp);
3059 #else
3060 cookie.fp = mch_fopen((char *)fname_exp, READBIN);
3061 #endif
3062 if (cookie.fp == NULL && check_other)
3065 * Try again, replacing file name ".vimrc" by "_vimrc" or vice versa,
3066 * and ".exrc" by "_exrc" or vice versa.
3068 p = gettail(fname_exp);
3069 if ((*p == '.' || *p == '_')
3070 && (STRICMP(p + 1, "vimrc") == 0
3071 || STRICMP(p + 1, "gvimrc") == 0
3072 || STRICMP(p + 1, "exrc") == 0))
3074 if (*p == '_')
3075 *p = '.';
3076 else
3077 *p = '_';
3078 #ifdef USE_FOPEN_NOINH
3079 cookie.fp = fopen_noinh_readbin((char *)fname_exp);
3080 #else
3081 cookie.fp = mch_fopen((char *)fname_exp, READBIN);
3082 #endif
3086 if (cookie.fp == NULL)
3088 if (p_verbose > 0)
3090 verbose_enter();
3091 if (sourcing_name == NULL)
3092 smsg((char_u *)_("could not source \"%s\""), fname);
3093 else
3094 smsg((char_u *)_("line %ld: could not source \"%s\""),
3095 sourcing_lnum, fname);
3096 verbose_leave();
3098 goto theend;
3102 * The file exists.
3103 * - In verbose mode, give a message.
3104 * - For a vimrc file, may want to set 'compatible', call vimrc_found().
3106 if (p_verbose > 1)
3108 verbose_enter();
3109 if (sourcing_name == NULL)
3110 smsg((char_u *)_("sourcing \"%s\""), fname);
3111 else
3112 smsg((char_u *)_("line %ld: sourcing \"%s\""),
3113 sourcing_lnum, fname);
3114 verbose_leave();
3116 if (is_vimrc == DOSO_VIMRC)
3117 vimrc_found(fname_exp, (char_u *)"MYVIMRC");
3118 else if (is_vimrc == DOSO_GVIMRC)
3119 vimrc_found(fname_exp, (char_u *)"MYGVIMRC");
3121 #ifdef USE_CRNL
3122 /* If no automatic file format: Set default to CR-NL. */
3123 if (*p_ffs == NUL)
3124 cookie.fileformat = EOL_DOS;
3125 else
3126 cookie.fileformat = EOL_UNKNOWN;
3127 cookie.error = FALSE;
3128 #endif
3130 #ifdef USE_CR
3131 /* If no automatic file format: Set default to CR. */
3132 if (*p_ffs == NUL)
3133 cookie.fileformat = EOL_MAC;
3134 else
3135 cookie.fileformat = EOL_UNKNOWN;
3136 cookie.error = FALSE;
3137 #endif
3139 cookie.nextline = NULL;
3140 cookie.finished = FALSE;
3142 #ifdef FEAT_EVAL
3144 * Check if this script has a breakpoint.
3146 cookie.breakpoint = dbg_find_breakpoint(TRUE, fname_exp, (linenr_T)0);
3147 cookie.fname = fname_exp;
3148 cookie.dbg_tick = debug_tick;
3150 cookie.level = ex_nesting_level;
3151 #endif
3154 * Keep the sourcing name/lnum, for recursive calls.
3156 save_sourcing_name = sourcing_name;
3157 sourcing_name = fname_exp;
3158 save_sourcing_lnum = sourcing_lnum;
3159 sourcing_lnum = 0;
3161 #ifdef FEAT_MBYTE
3162 cookie.conv.vc_type = CONV_NONE; /* no conversion */
3164 /* Read the first line so we can check for a UTF-8 BOM. */
3165 firstline = getsourceline(0, (void *)&cookie, 0);
3166 if (firstline != NULL && STRLEN(firstline) >= 3 && firstline[0] == 0xef
3167 && firstline[1] == 0xbb && firstline[2] == 0xbf)
3169 /* Found BOM; setup conversion, skip over BOM and recode the line. */
3170 convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc);
3171 p = string_convert(&cookie.conv, firstline + 3, NULL);
3172 if (p == NULL)
3173 p = vim_strsave(firstline + 3);
3174 if (p != NULL)
3176 vim_free(firstline);
3177 firstline = p;
3180 #endif
3182 #ifdef STARTUPTIME
3183 if (time_fd != NULL)
3184 time_push(&tv_rel, &tv_start);
3185 #endif
3187 #ifdef FEAT_EVAL
3188 # ifdef FEAT_PROFILE
3189 if (do_profiling == PROF_YES)
3190 prof_child_enter(&wait_start); /* entering a child now */
3191 # endif
3193 /* Don't use local function variables, if called from a function.
3194 * Also starts profiling timer for nested script. */
3195 save_funccalp = save_funccal();
3198 * Check if this script was sourced before to finds its SID.
3199 * If it's new, generate a new SID.
3201 save_current_SID = current_SID;
3202 # ifdef UNIX
3203 stat_ok = (mch_stat((char *)fname_exp, &st) >= 0);
3204 # endif
3205 for (current_SID = script_items.ga_len; current_SID > 0; --current_SID)
3207 si = &SCRIPT_ITEM(current_SID);
3208 if (si->sn_name != NULL
3209 && (
3210 # ifdef UNIX
3211 /* Compare dev/ino when possible, it catches symbolic
3212 * links. Also compare file names, the inode may change
3213 * when the file was edited. */
3214 ((stat_ok && si->sn_dev_valid)
3215 && (si->sn_dev == st.st_dev
3216 && si->sn_ino == st.st_ino)) ||
3217 # endif
3218 fnamecmp(si->sn_name, fname_exp) == 0))
3219 break;
3221 if (current_SID == 0)
3223 current_SID = ++last_current_SID;
3224 if (ga_grow(&script_items, (int)(current_SID - script_items.ga_len))
3225 == FAIL)
3226 goto almosttheend;
3227 while (script_items.ga_len < current_SID)
3229 ++script_items.ga_len;
3230 SCRIPT_ITEM(script_items.ga_len).sn_name = NULL;
3231 # ifdef FEAT_PROFILE
3232 SCRIPT_ITEM(script_items.ga_len).sn_prof_on = FALSE;
3233 # endif
3235 si = &SCRIPT_ITEM(current_SID);
3236 si->sn_name = fname_exp;
3237 fname_exp = NULL;
3238 # ifdef UNIX
3239 if (stat_ok)
3241 si->sn_dev_valid = TRUE;
3242 si->sn_dev = st.st_dev;
3243 si->sn_ino = st.st_ino;
3245 else
3246 si->sn_dev_valid = FALSE;
3247 # endif
3249 /* Allocate the local script variables to use for this script. */
3250 new_script_vars(current_SID);
3253 # ifdef FEAT_PROFILE
3254 if (do_profiling == PROF_YES)
3256 int forceit;
3258 /* Check if we do profiling for this script. */
3259 if (!si->sn_prof_on && has_profiling(TRUE, si->sn_name, &forceit))
3261 script_do_profile(si);
3262 si->sn_pr_force = forceit;
3264 if (si->sn_prof_on)
3266 ++si->sn_pr_count;
3267 profile_start(&si->sn_pr_start);
3268 profile_zero(&si->sn_pr_children);
3271 # endif
3272 #endif
3275 * Call do_cmdline, which will call getsourceline() to get the lines.
3277 do_cmdline(firstline, getsourceline, (void *)&cookie,
3278 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT);
3279 retval = OK;
3281 #ifdef FEAT_PROFILE
3282 if (do_profiling == PROF_YES)
3284 /* Get "si" again, "script_items" may have been reallocated. */
3285 si = &SCRIPT_ITEM(current_SID);
3286 if (si->sn_prof_on)
3288 profile_end(&si->sn_pr_start);
3289 profile_sub_wait(&wait_start, &si->sn_pr_start);
3290 profile_add(&si->sn_pr_total, &si->sn_pr_start);
3291 profile_self(&si->sn_pr_self, &si->sn_pr_start,
3292 &si->sn_pr_children);
3295 #endif
3297 if (got_int)
3298 EMSG(_(e_interr));
3299 sourcing_name = save_sourcing_name;
3300 sourcing_lnum = save_sourcing_lnum;
3301 if (p_verbose > 1)
3303 verbose_enter();
3304 smsg((char_u *)_("finished sourcing %s"), fname);
3305 if (sourcing_name != NULL)
3306 smsg((char_u *)_("continuing in %s"), sourcing_name);
3307 verbose_leave();
3309 #ifdef STARTUPTIME
3310 if (time_fd != NULL)
3312 vim_snprintf((char *)IObuff, IOSIZE, "sourcing %s", fname);
3313 time_msg((char *)IObuff, &tv_start);
3314 time_pop(&tv_rel);
3316 #endif
3318 #ifdef FEAT_EVAL
3320 * After a "finish" in debug mode, need to break at first command of next
3321 * sourced file.
3323 if (save_debug_break_level > ex_nesting_level
3324 && debug_break_level == ex_nesting_level)
3325 ++debug_break_level;
3326 #endif
3328 #ifdef FEAT_EVAL
3329 almosttheend:
3330 current_SID = save_current_SID;
3331 restore_funccal(save_funccalp);
3332 # ifdef FEAT_PROFILE
3333 if (do_profiling == PROF_YES)
3334 prof_child_exit(&wait_start); /* leaving a child now */
3335 # endif
3336 #endif
3337 fclose(cookie.fp);
3338 vim_free(cookie.nextline);
3339 vim_free(firstline);
3340 #ifdef FEAT_MBYTE
3341 convert_setup(&cookie.conv, NULL, NULL);
3342 #endif
3344 theend:
3345 vim_free(fname_exp);
3346 return retval;
3349 #if defined(FEAT_EVAL) || defined(PROTO)
3352 * ":scriptnames"
3354 void
3355 ex_scriptnames(eap)
3356 exarg_T *eap UNUSED;
3358 int i;
3360 for (i = 1; i <= script_items.ga_len && !got_int; ++i)
3361 if (SCRIPT_ITEM(i).sn_name != NULL)
3362 smsg((char_u *)"%3d: %s", i, SCRIPT_ITEM(i).sn_name);
3365 # if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
3367 * Fix slashes in the list of script names for 'shellslash'.
3369 void
3370 scriptnames_slash_adjust()
3372 int i;
3374 for (i = 1; i <= script_items.ga_len; ++i)
3375 if (SCRIPT_ITEM(i).sn_name != NULL)
3376 slash_adjust(SCRIPT_ITEM(i).sn_name);
3378 # endif
3381 * Get a pointer to a script name. Used for ":verbose set".
3383 char_u *
3384 get_scriptname(id)
3385 scid_T id;
3387 if (id == SID_MODELINE)
3388 return (char_u *)_("modeline");
3389 if (id == SID_CMDARG)
3390 return (char_u *)_("--cmd argument");
3391 if (id == SID_CARG)
3392 return (char_u *)_("-c argument");
3393 if (id == SID_ENV)
3394 return (char_u *)_("environment variable");
3395 if (id == SID_ERROR)
3396 return (char_u *)_("error handler");
3397 return SCRIPT_ITEM(id).sn_name;
3400 # if defined(EXITFREE) || defined(PROTO)
3401 void
3402 free_scriptnames()
3404 int i;
3406 for (i = script_items.ga_len; i > 0; --i)
3407 vim_free(SCRIPT_ITEM(i).sn_name);
3408 ga_clear(&script_items);
3410 # endif
3412 #endif
3414 #if defined(USE_CR) || defined(PROTO)
3416 # if defined(__MSL__) && (__MSL__ >= 22)
3418 * Newer version of the Metrowerks library handle DOS and UNIX files
3419 * without help.
3420 * Test with earlier versions, MSL 2.2 is the library supplied with
3421 * Codewarrior Pro 2.
3423 char *
3424 fgets_cr(s, n, stream)
3425 char *s;
3426 int n;
3427 FILE *stream;
3429 return fgets(s, n, stream);
3431 # else
3433 * Version of fgets() which also works for lines ending in a <CR> only
3434 * (Macintosh format).
3435 * For older versions of the Metrowerks library.
3436 * At least CodeWarrior 9 needed this code.
3438 char *
3439 fgets_cr(s, n, stream)
3440 char *s;
3441 int n;
3442 FILE *stream;
3444 int c = 0;
3445 int char_read = 0;
3447 while (!feof(stream) && c != '\r' && c != '\n' && char_read < n - 1)
3449 c = fgetc(stream);
3450 s[char_read++] = c;
3451 /* If the file is in DOS format, we need to skip a NL after a CR. I
3452 * thought it was the other way around, but this appears to work... */
3453 if (c == '\n')
3455 c = fgetc(stream);
3456 if (c != '\r')
3457 ungetc(c, stream);
3461 s[char_read] = 0;
3462 if (char_read == 0)
3463 return NULL;
3465 if (feof(stream) && char_read == 1)
3466 return NULL;
3468 return s;
3470 # endif
3471 #endif
3474 * Get one full line from a sourced file.
3475 * Called by do_cmdline() when it's called from do_source().
3477 * Return a pointer to the line in allocated memory.
3478 * Return NULL for end-of-file or some error.
3480 char_u *
3481 getsourceline(c, cookie, indent)
3482 int c UNUSED;
3483 void *cookie;
3484 int indent UNUSED;
3486 struct source_cookie *sp = (struct source_cookie *)cookie;
3487 char_u *line;
3488 char_u *p, *s;
3490 #ifdef FEAT_EVAL
3491 /* If breakpoints have been added/deleted need to check for it. */
3492 if (sp->dbg_tick < debug_tick)
3494 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
3495 sp->dbg_tick = debug_tick;
3497 # ifdef FEAT_PROFILE
3498 if (do_profiling == PROF_YES)
3499 script_line_end();
3500 # endif
3501 #endif
3503 * Get current line. If there is a read-ahead line, use it, otherwise get
3504 * one now.
3506 if (sp->finished)
3507 line = NULL;
3508 else if (sp->nextline == NULL)
3509 line = get_one_sourceline(sp);
3510 else
3512 line = sp->nextline;
3513 sp->nextline = NULL;
3514 ++sourcing_lnum;
3516 #ifdef FEAT_PROFILE
3517 if (line != NULL && do_profiling == PROF_YES)
3518 script_line_start();
3519 #endif
3521 /* Only concatenate lines starting with a \ when 'cpoptions' doesn't
3522 * contain the 'C' flag. */
3523 if (line != NULL && (vim_strchr(p_cpo, CPO_CONCAT) == NULL))
3525 /* compensate for the one line read-ahead */
3526 --sourcing_lnum;
3527 for (;;)
3529 sp->nextline = get_one_sourceline(sp);
3530 if (sp->nextline == NULL)
3531 break;
3532 p = skipwhite(sp->nextline);
3533 if (*p != '\\')
3534 break;
3535 s = alloc((unsigned)(STRLEN(line) + STRLEN(p)));
3536 if (s == NULL) /* out of memory */
3537 break;
3538 STRCPY(s, line);
3539 STRCAT(s, p + 1);
3540 vim_free(line);
3541 line = s;
3542 vim_free(sp->nextline);
3546 #ifdef FEAT_MBYTE
3547 if (line != NULL && sp->conv.vc_type != CONV_NONE)
3549 /* Convert the encoding of the script line. */
3550 s = string_convert(&sp->conv, line, NULL);
3551 if (s != NULL)
3553 vim_free(line);
3554 line = s;
3557 #endif
3559 #ifdef FEAT_EVAL
3560 /* Did we encounter a breakpoint? */
3561 if (sp->breakpoint != 0 && sp->breakpoint <= sourcing_lnum)
3563 dbg_breakpoint(sp->fname, sourcing_lnum);
3564 /* Find next breakpoint. */
3565 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
3566 sp->dbg_tick = debug_tick;
3568 #endif
3570 return line;
3573 static char_u *
3574 get_one_sourceline(sp)
3575 struct source_cookie *sp;
3577 garray_T ga;
3578 int len;
3579 int c;
3580 char_u *buf;
3581 #ifdef USE_CRNL
3582 int has_cr; /* CR-LF found */
3583 #endif
3584 #ifdef USE_CR
3585 char_u *scan;
3586 #endif
3587 int have_read = FALSE;
3589 /* use a growarray to store the sourced line */
3590 ga_init2(&ga, 1, 250);
3593 * Loop until there is a finished line (or end-of-file).
3595 sourcing_lnum++;
3596 for (;;)
3598 /* make room to read at least 120 (more) characters */
3599 if (ga_grow(&ga, 120) == FAIL)
3600 break;
3601 buf = (char_u *)ga.ga_data;
3603 #ifdef USE_CR
3604 if (sp->fileformat == EOL_MAC)
3606 if (fgets_cr((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
3607 sp->fp) == NULL)
3608 break;
3610 else
3611 #endif
3612 if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
3613 sp->fp) == NULL)
3614 break;
3615 len = ga.ga_len + (int)STRLEN(buf + ga.ga_len);
3616 #ifdef USE_CRNL
3617 /* Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the
3618 * CTRL-Z by its own, or after a NL. */
3619 if ( (len == 1 || (len >= 2 && buf[len - 2] == '\n'))
3620 && sp->fileformat == EOL_DOS
3621 && buf[len - 1] == Ctrl_Z)
3623 buf[len - 1] = NUL;
3624 break;
3626 #endif
3628 #ifdef USE_CR
3629 /* If the read doesn't stop on a new line, and there's
3630 * some CR then we assume a Mac format */
3631 if (sp->fileformat == EOL_UNKNOWN)
3633 if (buf[len - 1] != '\n' && vim_strchr(buf, '\r') != NULL)
3634 sp->fileformat = EOL_MAC;
3635 else
3636 sp->fileformat = EOL_UNIX;
3639 if (sp->fileformat == EOL_MAC)
3641 scan = vim_strchr(buf, '\r');
3643 if (scan != NULL)
3645 *scan = '\n';
3646 if (*(scan + 1) != 0)
3648 *(scan + 1) = 0;
3649 fseek(sp->fp, (long)(scan - buf - len + 1), SEEK_CUR);
3652 len = STRLEN(buf);
3654 #endif
3656 have_read = TRUE;
3657 ga.ga_len = len;
3659 /* If the line was longer than the buffer, read more. */
3660 if (ga.ga_maxlen - ga.ga_len == 1 && buf[len - 1] != '\n')
3661 continue;
3663 if (len >= 1 && buf[len - 1] == '\n') /* remove trailing NL */
3665 #ifdef USE_CRNL
3666 has_cr = (len >= 2 && buf[len - 2] == '\r');
3667 if (sp->fileformat == EOL_UNKNOWN)
3669 if (has_cr)
3670 sp->fileformat = EOL_DOS;
3671 else
3672 sp->fileformat = EOL_UNIX;
3675 if (sp->fileformat == EOL_DOS)
3677 if (has_cr) /* replace trailing CR */
3679 buf[len - 2] = '\n';
3680 --len;
3681 --ga.ga_len;
3683 else /* lines like ":map xx yy^M" will have failed */
3685 if (!sp->error)
3687 msg_source(hl_attr(HLF_W));
3688 EMSG(_("W15: Warning: Wrong line separator, ^M may be missing"));
3690 sp->error = TRUE;
3691 sp->fileformat = EOL_UNIX;
3694 #endif
3695 /* The '\n' is escaped if there is an odd number of ^V's just
3696 * before it, first set "c" just before the 'V's and then check
3697 * len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo */
3698 for (c = len - 2; c >= 0 && buf[c] == Ctrl_V; c--)
3700 if ((len & 1) != (c & 1)) /* escaped NL, read more */
3702 sourcing_lnum++;
3703 continue;
3706 buf[len - 1] = NUL; /* remove the NL */
3710 * Check for ^C here now and then, so recursive :so can be broken.
3712 line_breakcheck();
3713 break;
3716 if (have_read)
3717 return (char_u *)ga.ga_data;
3719 vim_free(ga.ga_data);
3720 return NULL;
3723 #if defined(FEAT_PROFILE) || defined(PROTO)
3725 * Called when starting to read a script line.
3726 * "sourcing_lnum" must be correct!
3727 * When skipping lines it may not actually be executed, but we won't find out
3728 * until later and we need to store the time now.
3730 void
3731 script_line_start()
3733 scriptitem_T *si;
3734 sn_prl_T *pp;
3736 if (current_SID <= 0 || current_SID > script_items.ga_len)
3737 return;
3738 si = &SCRIPT_ITEM(current_SID);
3739 if (si->sn_prof_on && sourcing_lnum >= 1)
3741 /* Grow the array before starting the timer, so that the time spent
3742 * here isn't counted. */
3743 ga_grow(&si->sn_prl_ga, (int)(sourcing_lnum - si->sn_prl_ga.ga_len));
3744 si->sn_prl_idx = sourcing_lnum - 1;
3745 while (si->sn_prl_ga.ga_len <= si->sn_prl_idx
3746 && si->sn_prl_ga.ga_len < si->sn_prl_ga.ga_maxlen)
3748 /* Zero counters for a line that was not used before. */
3749 pp = &PRL_ITEM(si, si->sn_prl_ga.ga_len);
3750 pp->snp_count = 0;
3751 profile_zero(&pp->sn_prl_total);
3752 profile_zero(&pp->sn_prl_self);
3753 ++si->sn_prl_ga.ga_len;
3755 si->sn_prl_execed = FALSE;
3756 profile_start(&si->sn_prl_start);
3757 profile_zero(&si->sn_prl_children);
3758 profile_get_wait(&si->sn_prl_wait);
3763 * Called when actually executing a function line.
3765 void
3766 script_line_exec()
3768 scriptitem_T *si;
3770 if (current_SID <= 0 || current_SID > script_items.ga_len)
3771 return;
3772 si = &SCRIPT_ITEM(current_SID);
3773 if (si->sn_prof_on && si->sn_prl_idx >= 0)
3774 si->sn_prl_execed = TRUE;
3778 * Called when done with a function line.
3780 void
3781 script_line_end()
3783 scriptitem_T *si;
3784 sn_prl_T *pp;
3786 if (current_SID <= 0 || current_SID > script_items.ga_len)
3787 return;
3788 si = &SCRIPT_ITEM(current_SID);
3789 if (si->sn_prof_on && si->sn_prl_idx >= 0
3790 && si->sn_prl_idx < si->sn_prl_ga.ga_len)
3792 if (si->sn_prl_execed)
3794 pp = &PRL_ITEM(si, si->sn_prl_idx);
3795 ++pp->snp_count;
3796 profile_end(&si->sn_prl_start);
3797 profile_sub_wait(&si->sn_prl_wait, &si->sn_prl_start);
3798 profile_add(&pp->sn_prl_total, &si->sn_prl_start);
3799 profile_self(&pp->sn_prl_self, &si->sn_prl_start,
3800 &si->sn_prl_children);
3802 si->sn_prl_idx = -1;
3805 #endif
3808 * ":scriptencoding": Set encoding conversion for a sourced script.
3809 * Without the multi-byte feature it's simply ignored.
3811 void
3812 ex_scriptencoding(eap)
3813 exarg_T *eap UNUSED;
3815 #ifdef FEAT_MBYTE
3816 struct source_cookie *sp;
3817 char_u *name;
3819 if (!getline_equal(eap->getline, eap->cookie, getsourceline))
3821 EMSG(_("E167: :scriptencoding used outside of a sourced file"));
3822 return;
3825 if (*eap->arg != NUL)
3827 name = enc_canonize(eap->arg);
3828 if (name == NULL) /* out of memory */
3829 return;
3831 else
3832 name = eap->arg;
3834 /* Setup for conversion from the specified encoding to 'encoding'. */
3835 sp = (struct source_cookie *)getline_cookie(eap->getline, eap->cookie);
3836 convert_setup(&sp->conv, name, p_enc);
3838 if (name != eap->arg)
3839 vim_free(name);
3840 #endif
3843 #if defined(FEAT_EVAL) || defined(PROTO)
3845 * ":finish": Mark a sourced file as finished.
3847 void
3848 ex_finish(eap)
3849 exarg_T *eap;
3851 if (getline_equal(eap->getline, eap->cookie, getsourceline))
3852 do_finish(eap, FALSE);
3853 else
3854 EMSG(_("E168: :finish used outside of a sourced file"));
3858 * Mark a sourced file as finished. Possibly makes the ":finish" pending.
3859 * Also called for a pending finish at the ":endtry" or after returning from
3860 * an extra do_cmdline(). "reanimate" is used in the latter case.
3862 void
3863 do_finish(eap, reanimate)
3864 exarg_T *eap;
3865 int reanimate;
3867 int idx;
3869 if (reanimate)
3870 ((struct source_cookie *)getline_cookie(eap->getline,
3871 eap->cookie))->finished = FALSE;
3874 * Cleanup (and inactivate) conditionals, but stop when a try conditional
3875 * not in its finally clause (which then is to be executed next) is found.
3876 * In this case, make the ":finish" pending for execution at the ":endtry".
3877 * Otherwise, finish normally.
3879 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
3880 if (idx >= 0)
3882 eap->cstack->cs_pending[idx] = CSTP_FINISH;
3883 report_make_pending(CSTP_FINISH, NULL);
3885 else
3886 ((struct source_cookie *)getline_cookie(eap->getline,
3887 eap->cookie))->finished = TRUE;
3892 * Return TRUE when a sourced file had the ":finish" command: Don't give error
3893 * message for missing ":endif".
3894 * Return FALSE when not sourcing a file.
3897 source_finished(fgetline, cookie)
3898 char_u *(*fgetline) __ARGS((int, void *, int));
3899 void *cookie;
3901 return (getline_equal(fgetline, cookie, getsourceline)
3902 && ((struct source_cookie *)getline_cookie(
3903 fgetline, cookie))->finished);
3905 #endif
3907 #if defined(FEAT_LISTCMDS) || defined(PROTO)
3909 * ":checktime [buffer]"
3911 void
3912 ex_checktime(eap)
3913 exarg_T *eap;
3915 buf_T *buf;
3916 int save_no_check_timestamps = no_check_timestamps;
3918 no_check_timestamps = 0;
3919 if (eap->addr_count == 0) /* default is all buffers */
3920 check_timestamps(FALSE);
3921 else
3923 buf = buflist_findnr((int)eap->line2);
3924 if (buf != NULL) /* cannot happen? */
3925 (void)buf_check_timestamp(buf, FALSE);
3927 no_check_timestamps = save_no_check_timestamps;
3929 #endif
3931 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3932 && (defined(FEAT_EVAL) || defined(FEAT_MULTI_LANG))
3933 static char *get_locale_val __ARGS((int what));
3935 static char *
3936 get_locale_val(what)
3937 int what;
3939 char *loc;
3941 /* Obtain the locale value from the libraries. For DJGPP this is
3942 * redefined and it doesn't use the arguments. */
3943 loc = setlocale(what, NULL);
3945 # ifdef WIN32
3946 if (loc != NULL)
3948 char_u *p;
3950 /* setocale() returns something like "LC_COLLATE=<name>;LC_..." when
3951 * one of the values (e.g., LC_CTYPE) differs. */
3952 p = vim_strchr(loc, '=');
3953 if (p != NULL)
3955 loc = ++p;
3956 while (*p != NUL) /* remove trailing newline */
3958 if (*p < ' ' || *p == ';')
3960 *p = NUL;
3961 break;
3963 ++p;
3967 # endif
3969 return loc;
3971 #endif
3974 #ifdef WIN32
3976 * On MS-Windows locale names are strings like "German_Germany.1252", but
3977 * gettext expects "de". Try to translate one into another here for a few
3978 * supported languages.
3980 static char_u *
3981 gettext_lang(char_u *name)
3983 int i;
3984 static char *(mtable[]) = {
3985 "afrikaans", "af",
3986 "czech", "cs",
3987 "dutch", "nl",
3988 "german", "de",
3989 "english_united kingdom", "en_GB",
3990 "spanish", "es",
3991 "french", "fr",
3992 "italian", "it",
3993 "japanese", "ja",
3994 "korean", "ko",
3995 "norwegian", "no",
3996 "polish", "pl",
3997 "russian", "ru",
3998 "slovak", "sk",
3999 "swedish", "sv",
4000 "ukrainian", "uk",
4001 "chinese_china", "zh_CN",
4002 "chinese_taiwan", "zh_TW",
4003 NULL};
4005 for (i = 0; mtable[i] != NULL; i += 2)
4006 if (STRNICMP(mtable[i], name, STRLEN(mtable[i])) == 0)
4007 return mtable[i + 1];
4008 return name;
4010 #endif
4012 #if defined(FEAT_MULTI_LANG) || defined(PROTO)
4014 * Obtain the current messages language. Used to set the default for
4015 * 'helplang'. May return NULL or an empty string.
4017 char_u *
4018 get_mess_lang()
4020 char_u *p;
4022 # if (defined(HAVE_LOCALE_H) || defined(X_LOCALE))
4023 # if defined(LC_MESSAGES)
4024 p = (char_u *)get_locale_val(LC_MESSAGES);
4025 # else
4026 /* This is necessary for Win32, where LC_MESSAGES is not defined and $LANG
4027 * may be set to the LCID number. LC_COLLATE is the best guess, LC_TIME
4028 * and LC_MONETARY may be set differently for a Japanese working in the
4029 * US. */
4030 p = (char_u *)get_locale_val(LC_COLLATE);
4031 # endif
4032 # else
4033 p = mch_getenv((char_u *)"LC_ALL");
4034 if (p == NULL || *p == NUL)
4036 p = mch_getenv((char_u *)"LC_MESSAGES");
4037 if (p == NULL || *p == NUL)
4038 p = mch_getenv((char_u *)"LANG");
4040 # endif
4041 # ifdef WIN32
4042 p = gettext_lang(p);
4043 # endif
4044 return p;
4046 #endif
4048 /* Complicated #if; matches with where get_mess_env() is used below. */
4049 #if (defined(FEAT_EVAL) && !((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
4050 && defined(LC_MESSAGES))) \
4051 || ((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
4052 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)) \
4053 && !defined(LC_MESSAGES))
4054 static char_u *get_mess_env __ARGS((void));
4057 * Get the language used for messages from the environment.
4059 static char_u *
4060 get_mess_env()
4062 char_u *p;
4064 p = mch_getenv((char_u *)"LC_ALL");
4065 if (p == NULL || *p == NUL)
4067 p = mch_getenv((char_u *)"LC_MESSAGES");
4068 if (p == NULL || *p == NUL)
4070 p = mch_getenv((char_u *)"LANG");
4071 if (p != NULL && VIM_ISDIGIT(*p))
4072 p = NULL; /* ignore something like "1043" */
4073 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
4074 if (p == NULL || *p == NUL)
4075 p = (char_u *)get_locale_val(LC_CTYPE);
4076 # endif
4079 return p;
4081 #endif
4083 #if defined(FEAT_EVAL) || defined(PROTO)
4086 * Set the "v:lang" variable according to the current locale setting.
4087 * Also do "v:lc_time"and "v:ctype".
4089 void
4090 set_lang_var()
4092 char_u *loc;
4094 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
4095 loc = (char_u *)get_locale_val(LC_CTYPE);
4096 # else
4097 /* setlocale() not supported: use the default value */
4098 loc = (char_u *)"C";
4099 # endif
4100 set_vim_var_string(VV_CTYPE, loc, -1);
4102 /* When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall
4103 * back to LC_CTYPE if it's empty. */
4104 # if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) && defined(LC_MESSAGES)
4105 loc = (char_u *)get_locale_val(LC_MESSAGES);
4106 # else
4107 loc = get_mess_env();
4108 # endif
4109 set_vim_var_string(VV_LANG, loc, -1);
4111 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
4112 loc = (char_u *)get_locale_val(LC_TIME);
4113 # endif
4114 set_vim_var_string(VV_LC_TIME, loc, -1);
4116 #endif
4118 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
4119 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE))
4121 * ":language": Set the language (locale).
4123 void
4124 ex_language(eap)
4125 exarg_T *eap;
4127 char *loc;
4128 char_u *p;
4129 char_u *name;
4130 int what = LC_ALL;
4131 char *whatstr = "";
4132 #ifdef LC_MESSAGES
4133 # define VIM_LC_MESSAGES LC_MESSAGES
4134 #else
4135 # define VIM_LC_MESSAGES 6789
4136 #endif
4138 name = eap->arg;
4140 /* Check for "messages {name}", "ctype {name}" or "time {name}" argument.
4141 * Allow abbreviation, but require at least 3 characters to avoid
4142 * confusion with a two letter language name "me" or "ct". */
4143 p = skiptowhite(eap->arg);
4144 if ((*p == NUL || vim_iswhite(*p)) && p - eap->arg >= 3)
4146 if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0)
4148 what = VIM_LC_MESSAGES;
4149 name = skipwhite(p);
4150 whatstr = "messages ";
4152 else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0)
4154 what = LC_CTYPE;
4155 name = skipwhite(p);
4156 whatstr = "ctype ";
4158 else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0)
4160 what = LC_TIME;
4161 name = skipwhite(p);
4162 whatstr = "time ";
4166 if (*name == NUL)
4168 #ifndef LC_MESSAGES
4169 if (what == VIM_LC_MESSAGES)
4170 p = get_mess_env();
4171 else
4172 #endif
4173 p = (char_u *)setlocale(what, NULL);
4174 if (p == NULL || *p == NUL)
4175 p = (char_u *)"Unknown";
4176 smsg((char_u *)_("Current %slanguage: \"%s\""), whatstr, p);
4178 else
4180 #ifndef LC_MESSAGES
4181 if (what == VIM_LC_MESSAGES)
4182 loc = "";
4183 else
4184 #endif
4186 loc = setlocale(what, (char *)name);
4187 #if defined(FEAT_FLOAT) && defined(LC_NUMERIC)
4188 /* Make sure strtod() uses a decimal point, not a comma. */
4189 setlocale(LC_NUMERIC, "C");
4190 #endif
4192 if (loc == NULL)
4193 EMSG2(_("E197: Cannot set language to \"%s\""), name);
4194 else
4196 #ifdef HAVE_NL_MSG_CAT_CNTR
4197 /* Need to do this for GNU gettext, otherwise cached translations
4198 * will be used again. */
4199 extern int _nl_msg_cat_cntr;
4201 ++_nl_msg_cat_cntr;
4202 #endif
4203 /* Reset $LC_ALL, otherwise it would overrule everything. */
4204 vim_setenv((char_u *)"LC_ALL", (char_u *)"");
4206 if (what != LC_TIME)
4208 /* Tell gettext() what to translate to. It apparently doesn't
4209 * use the currently effective locale. Also do this when
4210 * FEAT_GETTEXT isn't defined, so that shell commands use this
4211 * value. */
4212 if (what == LC_ALL)
4214 vim_setenv((char_u *)"LANG", name);
4215 # ifdef WIN32
4216 /* Apparently MS-Windows printf() may cause a crash when
4217 * we give it 8-bit text while it's expecting text in the
4218 * current locale. This call avoids that. */
4219 setlocale(LC_CTYPE, "C");
4220 # endif
4222 if (what != LC_CTYPE)
4224 char_u *mname;
4225 #ifdef WIN32
4226 mname = gettext_lang(name);
4227 #else
4228 mname = name;
4229 #endif
4230 vim_setenv((char_u *)"LC_MESSAGES", mname);
4231 #ifdef FEAT_MULTI_LANG
4232 set_helplang_default(mname);
4233 #endif
4236 /* Set $LC_CTYPE, because it overrules $LANG, and
4237 * gtk_set_locale() calls setlocale() again. gnome_init()
4238 * sets $LC_CTYPE to "en_US" (that's a bug!). */
4239 if (what != VIM_LC_MESSAGES)
4240 vim_setenv((char_u *)"LC_CTYPE", name);
4241 # ifdef FEAT_GUI_GTK
4242 /* Let GTK know what locale we're using. Not sure this is
4243 * really needed... */
4244 if (gui.in_use)
4245 (void)gtk_set_locale();
4246 # endif
4249 # ifdef FEAT_EVAL
4250 /* Set v:lang, v:lc_time and v:ctype to the final result. */
4251 set_lang_var();
4252 # endif
4257 # if defined(FEAT_CMDL_COMPL) || defined(PROTO)
4259 * Function given to ExpandGeneric() to obtain the possible arguments of the
4260 * ":language" command.
4262 char_u *
4263 get_lang_arg(xp, idx)
4264 expand_T *xp UNUSED;
4265 int idx;
4267 if (idx == 0)
4268 return (char_u *)"messages";
4269 if (idx == 1)
4270 return (char_u *)"ctype";
4271 if (idx == 2)
4272 return (char_u *)"time";
4273 return NULL;
4275 # endif
4277 #endif