Merge branch 'feat/rel-line-numbers'
[vim_extended.git] / src / ex_cmds2.c
blob91f8d6ffb59a79e8c5833ab7effd78634a8c5c03
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
1491 * Ask the user what to do when abondoning a changed buffer.
1492 * Must check 'write' option first!
1494 void
1495 dialog_changed(buf, checkall)
1496 buf_T *buf;
1497 int checkall; /* may abandon all changed buffers */
1499 char_u buff[IOSIZE];
1500 int ret;
1501 buf_T *buf2;
1503 dialog_msg(buff, _("Save changes to \"%s\"?"),
1504 (buf->b_fname != NULL) ?
1505 buf->b_fname : (char_u *)_("Untitled"));
1506 if (checkall)
1507 ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1);
1508 else
1509 ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
1511 if (ret == VIM_YES)
1513 #ifdef FEAT_BROWSE
1514 /* May get file name, when there is none */
1515 browse_save_fname(buf);
1516 #endif
1517 if (buf->b_fname != NULL) /* didn't hit Cancel */
1518 (void)buf_write_all(buf, FALSE);
1520 else if (ret == VIM_NO)
1522 unchanged(buf, TRUE);
1524 else if (ret == VIM_ALL)
1527 * Write all modified files that can be written.
1528 * Skip readonly buffers, these need to be confirmed
1529 * individually.
1531 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1533 if (bufIsChanged(buf2)
1534 && (buf2->b_ffname != NULL
1535 #ifdef FEAT_BROWSE
1536 || cmdmod.browse
1537 #endif
1539 && !buf2->b_p_ro)
1541 #ifdef FEAT_BROWSE
1542 /* May get file name, when there is none */
1543 browse_save_fname(buf2);
1544 #endif
1545 if (buf2->b_fname != NULL) /* didn't hit Cancel */
1546 (void)buf_write_all(buf2, FALSE);
1547 #ifdef FEAT_AUTOCMD
1548 /* an autocommand may have deleted the buffer */
1549 if (!buf_valid(buf2))
1550 buf2 = firstbuf;
1551 #endif
1555 else if (ret == VIM_DISCARDALL)
1558 * mark all buffers as unchanged
1560 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1561 unchanged(buf2, TRUE);
1564 #endif
1567 * Return TRUE if the buffer "buf" can be abandoned, either by making it
1568 * hidden, autowriting it or unloading it.
1571 can_abandon(buf, forceit)
1572 buf_T *buf;
1573 int forceit;
1575 return ( P_HID(buf)
1576 || !bufIsChanged(buf)
1577 || buf->b_nwindows > 1
1578 || autowrite(buf, forceit) == OK
1579 || forceit);
1583 * Return TRUE if any buffer was changed and cannot be abandoned.
1584 * That changed buffer becomes the current buffer.
1587 check_changed_any(hidden)
1588 int hidden; /* Only check hidden buffers */
1590 buf_T *buf;
1591 int save;
1592 #ifdef FEAT_WINDOWS
1593 win_T *wp;
1594 #endif
1595 char_u *bname;
1597 for (;;)
1599 /* check curbuf first: if it was changed we can't abandon it */
1600 if (!hidden && curbufIsChanged())
1601 buf = curbuf;
1602 else
1604 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
1605 if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf))
1606 break;
1608 if (buf == NULL) /* No buffers changed */
1609 return FALSE;
1611 /* Try auto-writing the buffer. If this fails but the buffer no
1612 * longer exists it's not changed, that's OK. */
1613 if (check_changed(buf, p_awa, TRUE, FALSE, TRUE) && buf_valid(buf))
1614 break; /* didn't save - still changes */
1617 exiting = FALSE;
1618 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1620 * When ":confirm" used, don't give an error message.
1622 if (!(p_confirm || cmdmod.confirm))
1623 #endif
1625 /* There must be a wait_return for this message, do_buffer()
1626 * may cause a redraw. But wait_return() is a no-op when vgetc()
1627 * is busy (Quit used from window menu), then make sure we don't
1628 * cause a scroll up. */
1629 if (vgetc_busy > 0)
1631 msg_row = cmdline_row;
1632 msg_col = 0;
1633 msg_didout = FALSE;
1635 if (EMSG2(_("E162: No write since last change for buffer \"%s\""),
1636 (bname = (char_u *)buf_spname(buf)) != NULL ? bname :
1637 buf->b_fname))
1639 save = no_wait_return;
1640 no_wait_return = FALSE;
1641 wait_return(FALSE);
1642 no_wait_return = save;
1644 vim_free(bname);
1647 #ifdef FEAT_WINDOWS
1648 /* Try to find a window that contains the buffer. */
1649 if (buf != curbuf)
1650 for (wp = firstwin; wp != NULL; wp = wp->w_next)
1651 if (wp->w_buffer == buf)
1653 win_goto(wp);
1654 # ifdef FEAT_AUTOCMD
1655 /* Paranoia: did autocms wipe out the buffer with changes? */
1656 if (!buf_valid(buf))
1657 return TRUE;
1658 # endif
1659 break;
1661 #endif
1663 /* Open the changed buffer in the current window. */
1664 if (buf != curbuf)
1665 set_curbuf(buf, DOBUF_GOTO);
1667 return TRUE;
1671 * return FAIL if there is no file name, OK if there is one
1672 * give error message for FAIL
1675 check_fname()
1677 if (curbuf->b_ffname == NULL)
1679 EMSG(_(e_noname));
1680 return FAIL;
1682 return OK;
1686 * flush the contents of a buffer, unless it has no file name
1688 * return FAIL for failure, OK otherwise
1691 buf_write_all(buf, forceit)
1692 buf_T *buf;
1693 int forceit;
1695 int retval;
1696 #ifdef FEAT_AUTOCMD
1697 buf_T *old_curbuf = curbuf;
1698 #endif
1700 retval = (buf_write(buf, buf->b_ffname, buf->b_fname,
1701 (linenr_T)1, buf->b_ml.ml_line_count, NULL,
1702 FALSE, forceit, TRUE, FALSE));
1703 #ifdef FEAT_PERSISTENT_UNDO
1704 if (retval == OK && buf->b_p_udf)
1706 u_wundo(buf->b_ffname, buf);
1708 #endif
1709 #ifdef FEAT_AUTOCMD
1710 if (curbuf != old_curbuf)
1712 msg_source(hl_attr(HLF_W));
1713 MSG(_("Warning: Entered other buffer unexpectedly (check autocommands)"));
1715 #endif
1716 return retval;
1720 * Code to handle the argument list.
1723 static char_u *do_one_arg __ARGS((char_u *str));
1724 static int do_arglist __ARGS((char_u *str, int what, int after));
1725 static void alist_check_arg_idx __ARGS((void));
1726 static int editing_arg_idx __ARGS((win_T *win));
1727 #ifdef FEAT_LISTCMDS
1728 static int alist_add_list __ARGS((int count, char_u **files, int after));
1729 #endif
1730 #define AL_SET 1
1731 #define AL_ADD 2
1732 #define AL_DEL 3
1735 * Isolate one argument, taking backticks.
1736 * Changes the argument in-place, puts a NUL after it. Backticks remain.
1737 * Return a pointer to the start of the next argument.
1739 static char_u *
1740 do_one_arg(str)
1741 char_u *str;
1743 char_u *p;
1744 int inbacktick;
1746 inbacktick = FALSE;
1747 for (p = str; *str; ++str)
1749 /* When the backslash is used for escaping the special meaning of a
1750 * character we need to keep it until wildcard expansion. */
1751 if (rem_backslash(str))
1753 *p++ = *str++;
1754 *p++ = *str;
1756 else
1758 /* An item ends at a space not in backticks */
1759 if (!inbacktick && vim_isspace(*str))
1760 break;
1761 if (*str == '`')
1762 inbacktick ^= TRUE;
1763 *p++ = *str;
1766 str = skipwhite(str);
1767 *p = NUL;
1769 return str;
1773 * Separate the arguments in "str" and return a list of pointers in the
1774 * growarray "gap".
1777 get_arglist(gap, str)
1778 garray_T *gap;
1779 char_u *str;
1781 ga_init2(gap, (int)sizeof(char_u *), 20);
1782 while (*str != NUL)
1784 if (ga_grow(gap, 1) == FAIL)
1786 ga_clear(gap);
1787 return FAIL;
1789 ((char_u **)gap->ga_data)[gap->ga_len++] = str;
1791 /* Isolate one argument, change it in-place, put a NUL after it. */
1792 str = do_one_arg(str);
1794 return OK;
1797 #if defined(FEAT_QUICKFIX) || defined(FEAT_SYN_HL) || defined(PROTO)
1799 * Parse a list of arguments (file names), expand them and return in
1800 * "fnames[fcountp]".
1801 * Return FAIL or OK.
1804 get_arglist_exp(str, fcountp, fnamesp)
1805 char_u *str;
1806 int *fcountp;
1807 char_u ***fnamesp;
1809 garray_T ga;
1810 int i;
1812 if (get_arglist(&ga, str) == FAIL)
1813 return FAIL;
1814 i = gen_expand_wildcards(ga.ga_len, (char_u **)ga.ga_data,
1815 fcountp, fnamesp, EW_FILE|EW_NOTFOUND);
1816 ga_clear(&ga);
1817 return i;
1819 #endif
1821 #if defined(FEAT_GUI) || defined(FEAT_CLIENTSERVER) || defined(PROTO)
1823 * Redefine the argument list.
1825 void
1826 set_arglist(str)
1827 char_u *str;
1829 do_arglist(str, AL_SET, 0);
1831 #endif
1834 * "what" == AL_SET: Redefine the argument list to 'str'.
1835 * "what" == AL_ADD: add files in 'str' to the argument list after "after".
1836 * "what" == AL_DEL: remove files in 'str' from the argument list.
1838 * Return FAIL for failure, OK otherwise.
1840 static int
1841 do_arglist(str, what, after)
1842 char_u *str;
1843 int what UNUSED;
1844 int after UNUSED; /* 0 means before first one */
1846 garray_T new_ga;
1847 int exp_count;
1848 char_u **exp_files;
1849 int i;
1850 #ifdef FEAT_LISTCMDS
1851 char_u *p;
1852 int match;
1853 #endif
1856 * Collect all file name arguments in "new_ga".
1858 if (get_arglist(&new_ga, str) == FAIL)
1859 return FAIL;
1861 #ifdef FEAT_LISTCMDS
1862 if (what == AL_DEL)
1864 regmatch_T regmatch;
1865 int didone;
1868 * Delete the items: use each item as a regexp and find a match in the
1869 * argument list.
1871 #ifdef CASE_INSENSITIVE_FILENAME
1872 regmatch.rm_ic = TRUE; /* Always ignore case */
1873 #else
1874 regmatch.rm_ic = FALSE; /* Never ignore case */
1875 #endif
1876 for (i = 0; i < new_ga.ga_len && !got_int; ++i)
1878 p = ((char_u **)new_ga.ga_data)[i];
1879 p = file_pat_to_reg_pat(p, NULL, NULL, FALSE);
1880 if (p == NULL)
1881 break;
1882 regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0);
1883 if (regmatch.regprog == NULL)
1885 vim_free(p);
1886 break;
1889 didone = FALSE;
1890 for (match = 0; match < ARGCOUNT; ++match)
1891 if (vim_regexec(&regmatch, alist_name(&ARGLIST[match]),
1892 (colnr_T)0))
1894 didone = TRUE;
1895 vim_free(ARGLIST[match].ae_fname);
1896 mch_memmove(ARGLIST + match, ARGLIST + match + 1,
1897 (ARGCOUNT - match - 1) * sizeof(aentry_T));
1898 --ALIST(curwin)->al_ga.ga_len;
1899 if (curwin->w_arg_idx > match)
1900 --curwin->w_arg_idx;
1901 --match;
1904 vim_free(regmatch.regprog);
1905 vim_free(p);
1906 if (!didone)
1907 EMSG2(_(e_nomatch2), ((char_u **)new_ga.ga_data)[i]);
1909 ga_clear(&new_ga);
1911 else
1912 #endif
1914 i = expand_wildcards(new_ga.ga_len, (char_u **)new_ga.ga_data,
1915 &exp_count, &exp_files, EW_DIR|EW_FILE|EW_ADDSLASH|EW_NOTFOUND);
1916 ga_clear(&new_ga);
1917 if (i == FAIL)
1918 return FAIL;
1919 if (exp_count == 0)
1921 EMSG(_(e_nomatch));
1922 return FAIL;
1925 #ifdef FEAT_LISTCMDS
1926 if (what == AL_ADD)
1928 (void)alist_add_list(exp_count, exp_files, after);
1929 vim_free(exp_files);
1931 else /* what == AL_SET */
1932 #endif
1933 alist_set(ALIST(curwin), exp_count, exp_files, FALSE, NULL, 0);
1936 alist_check_arg_idx();
1938 return OK;
1942 * Check the validity of the arg_idx for each other window.
1944 static void
1945 alist_check_arg_idx()
1947 #ifdef FEAT_WINDOWS
1948 win_T *win;
1949 tabpage_T *tp;
1951 FOR_ALL_TAB_WINDOWS(tp, win)
1952 if (win->w_alist == curwin->w_alist)
1953 check_arg_idx(win);
1954 #else
1955 check_arg_idx(curwin);
1956 #endif
1960 * Return TRUE if window "win" is editing then file at the current argument
1961 * index.
1963 static int
1964 editing_arg_idx(win)
1965 win_T *win;
1967 return !(win->w_arg_idx >= WARGCOUNT(win)
1968 || (win->w_buffer->b_fnum
1969 != WARGLIST(win)[win->w_arg_idx].ae_fnum
1970 && (win->w_buffer->b_ffname == NULL
1971 || !(fullpathcmp(
1972 alist_name(&WARGLIST(win)[win->w_arg_idx]),
1973 win->w_buffer->b_ffname, TRUE) & FPC_SAME))));
1977 * Check if window "win" is editing the w_arg_idx file in its argument list.
1979 void
1980 check_arg_idx(win)
1981 win_T *win;
1983 if (WARGCOUNT(win) > 1 && !editing_arg_idx(win))
1985 /* We are not editing the current entry in the argument list.
1986 * Set "arg_had_last" if we are editing the last one. */
1987 win->w_arg_idx_invalid = TRUE;
1988 if (win->w_arg_idx != WARGCOUNT(win) - 1
1989 && arg_had_last == FALSE
1990 #ifdef FEAT_WINDOWS
1991 && ALIST(win) == &global_alist
1992 #endif
1993 && GARGCOUNT > 0
1994 && win->w_arg_idx < GARGCOUNT
1995 && (win->w_buffer->b_fnum == GARGLIST[GARGCOUNT - 1].ae_fnum
1996 || (win->w_buffer->b_ffname != NULL
1997 && (fullpathcmp(alist_name(&GARGLIST[GARGCOUNT - 1]),
1998 win->w_buffer->b_ffname, TRUE) & FPC_SAME))))
1999 arg_had_last = TRUE;
2001 else
2003 /* We are editing the current entry in the argument list.
2004 * Set "arg_had_last" if it's also the last one */
2005 win->w_arg_idx_invalid = FALSE;
2006 if (win->w_arg_idx == WARGCOUNT(win) - 1
2007 #ifdef FEAT_WINDOWS
2008 && win->w_alist == &global_alist
2009 #endif
2011 arg_had_last = TRUE;
2016 * ":args", ":argslocal" and ":argsglobal".
2018 void
2019 ex_args(eap)
2020 exarg_T *eap;
2022 int i;
2024 if (eap->cmdidx != CMD_args)
2026 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
2027 alist_unlink(ALIST(curwin));
2028 if (eap->cmdidx == CMD_argglobal)
2029 ALIST(curwin) = &global_alist;
2030 else /* eap->cmdidx == CMD_arglocal */
2031 alist_new();
2032 #else
2033 ex_ni(eap);
2034 return;
2035 #endif
2038 if (!ends_excmd(*eap->arg))
2041 * ":args file ..": define new argument list, handle like ":next"
2042 * Also for ":argslocal file .." and ":argsglobal file ..".
2044 ex_next(eap);
2046 else
2047 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
2048 if (eap->cmdidx == CMD_args)
2049 #endif
2052 * ":args": list arguments.
2054 if (ARGCOUNT > 0)
2056 /* Overwrite the command, for a short list there is no scrolling
2057 * required and no wait_return(). */
2058 gotocmdline(TRUE);
2059 for (i = 0; i < ARGCOUNT; ++i)
2061 if (i == curwin->w_arg_idx)
2062 msg_putchar('[');
2063 msg_outtrans(alist_name(&ARGLIST[i]));
2064 if (i == curwin->w_arg_idx)
2065 msg_putchar(']');
2066 msg_putchar(' ');
2070 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
2071 else if (eap->cmdidx == CMD_arglocal)
2073 garray_T *gap = &curwin->w_alist->al_ga;
2076 * ":argslocal": make a local copy of the global argument list.
2078 if (ga_grow(gap, GARGCOUNT) == OK)
2079 for (i = 0; i < GARGCOUNT; ++i)
2080 if (GARGLIST[i].ae_fname != NULL)
2082 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fname =
2083 vim_strsave(GARGLIST[i].ae_fname);
2084 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fnum =
2085 GARGLIST[i].ae_fnum;
2086 ++gap->ga_len;
2089 #endif
2093 * ":previous", ":sprevious", ":Next" and ":sNext".
2095 void
2096 ex_previous(eap)
2097 exarg_T *eap;
2099 /* If past the last one already, go to the last one. */
2100 if (curwin->w_arg_idx - (int)eap->line2 >= ARGCOUNT)
2101 do_argfile(eap, ARGCOUNT - 1);
2102 else
2103 do_argfile(eap, curwin->w_arg_idx - (int)eap->line2);
2107 * ":rewind", ":first", ":sfirst" and ":srewind".
2109 void
2110 ex_rewind(eap)
2111 exarg_T *eap;
2113 do_argfile(eap, 0);
2117 * ":last" and ":slast".
2119 void
2120 ex_last(eap)
2121 exarg_T *eap;
2123 do_argfile(eap, ARGCOUNT - 1);
2127 * ":argument" and ":sargument".
2129 void
2130 ex_argument(eap)
2131 exarg_T *eap;
2133 int i;
2135 if (eap->addr_count > 0)
2136 i = eap->line2 - 1;
2137 else
2138 i = curwin->w_arg_idx;
2139 do_argfile(eap, i);
2143 * Edit file "argn" of the argument lists.
2145 void
2146 do_argfile(eap, argn)
2147 exarg_T *eap;
2148 int argn;
2150 int other;
2151 char_u *p;
2152 int old_arg_idx = curwin->w_arg_idx;
2154 if (argn < 0 || argn >= ARGCOUNT)
2156 if (ARGCOUNT <= 1)
2157 EMSG(_("E163: There is only one file to edit"));
2158 else if (argn < 0)
2159 EMSG(_("E164: Cannot go before first file"));
2160 else
2161 EMSG(_("E165: Cannot go beyond last file"));
2163 else
2165 setpcmark();
2166 #ifdef FEAT_GUI
2167 need_mouse_correct = TRUE;
2168 #endif
2170 #ifdef FEAT_WINDOWS
2171 /* split window or create new tab page first */
2172 if (*eap->cmd == 's' || cmdmod.tab != 0)
2174 if (win_split(0, 0) == FAIL)
2175 return;
2176 # ifdef FEAT_SCROLLBIND
2177 curwin->w_p_scb = FALSE;
2178 # endif
2180 else
2181 #endif
2184 * if 'hidden' set, only check for changed file when re-editing
2185 * the same buffer
2187 other = TRUE;
2188 if (P_HID(curbuf))
2190 p = fix_fname(alist_name(&ARGLIST[argn]));
2191 other = otherfile(p);
2192 vim_free(p);
2194 if ((!P_HID(curbuf) || !other)
2195 && check_changed(curbuf, TRUE, !other, eap->forceit, FALSE))
2196 return;
2199 curwin->w_arg_idx = argn;
2200 if (argn == ARGCOUNT - 1
2201 #ifdef FEAT_WINDOWS
2202 && curwin->w_alist == &global_alist
2203 #endif
2205 arg_had_last = TRUE;
2207 /* Edit the file; always use the last known line number.
2208 * When it fails (e.g. Abort for already edited file) restore the
2209 * argument index. */
2210 if (do_ecmd(0, alist_name(&ARGLIST[curwin->w_arg_idx]), NULL,
2211 eap, ECMD_LAST,
2212 (P_HID(curwin->w_buffer) ? ECMD_HIDE : 0)
2213 + (eap->forceit ? ECMD_FORCEIT : 0), curwin) == FAIL)
2214 curwin->w_arg_idx = old_arg_idx;
2215 /* like Vi: set the mark where the cursor is in the file. */
2216 else if (eap->cmdidx != CMD_argdo)
2217 setmark('\'');
2222 * ":next", and commands that behave like it.
2224 void
2225 ex_next(eap)
2226 exarg_T *eap;
2228 int i;
2231 * check for changed buffer now, if this fails the argument list is not
2232 * redefined.
2234 if ( P_HID(curbuf)
2235 || eap->cmdidx == CMD_snext
2236 || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
2238 if (*eap->arg != NUL) /* redefine file list */
2240 if (do_arglist(eap->arg, AL_SET, 0) == FAIL)
2241 return;
2242 i = 0;
2244 else
2245 i = curwin->w_arg_idx + (int)eap->line2;
2246 do_argfile(eap, i);
2250 #ifdef FEAT_LISTCMDS
2252 * ":argedit"
2254 void
2255 ex_argedit(eap)
2256 exarg_T *eap;
2258 int fnum;
2259 int i;
2260 char_u *s;
2262 /* Add the argument to the buffer list and get the buffer number. */
2263 fnum = buflist_add(eap->arg, BLN_LISTED);
2265 /* Check if this argument is already in the argument list. */
2266 for (i = 0; i < ARGCOUNT; ++i)
2267 if (ARGLIST[i].ae_fnum == fnum)
2268 break;
2269 if (i == ARGCOUNT)
2271 /* Can't find it, add it to the argument list. */
2272 s = vim_strsave(eap->arg);
2273 if (s == NULL)
2274 return;
2275 i = alist_add_list(1, &s,
2276 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
2277 if (i < 0)
2278 return;
2279 curwin->w_arg_idx = i;
2282 alist_check_arg_idx();
2284 /* Edit the argument. */
2285 do_argfile(eap, i);
2289 * ":argadd"
2291 void
2292 ex_argadd(eap)
2293 exarg_T *eap;
2295 do_arglist(eap->arg, AL_ADD,
2296 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
2297 #ifdef FEAT_TITLE
2298 maketitle();
2299 #endif
2303 * ":argdelete"
2305 void
2306 ex_argdelete(eap)
2307 exarg_T *eap;
2309 int i;
2310 int n;
2312 if (eap->addr_count > 0)
2314 /* ":1,4argdel": Delete all arguments in the range. */
2315 if (eap->line2 > ARGCOUNT)
2316 eap->line2 = ARGCOUNT;
2317 n = eap->line2 - eap->line1 + 1;
2318 if (*eap->arg != NUL || n <= 0)
2319 EMSG(_(e_invarg));
2320 else
2322 for (i = eap->line1; i <= eap->line2; ++i)
2323 vim_free(ARGLIST[i - 1].ae_fname);
2324 mch_memmove(ARGLIST + eap->line1 - 1, ARGLIST + eap->line2,
2325 (size_t)((ARGCOUNT - eap->line2) * sizeof(aentry_T)));
2326 ALIST(curwin)->al_ga.ga_len -= n;
2327 if (curwin->w_arg_idx >= eap->line2)
2328 curwin->w_arg_idx -= n;
2329 else if (curwin->w_arg_idx > eap->line1)
2330 curwin->w_arg_idx = eap->line1;
2333 else if (*eap->arg == NUL)
2334 EMSG(_(e_argreq));
2335 else
2336 do_arglist(eap->arg, AL_DEL, 0);
2337 #ifdef FEAT_TITLE
2338 maketitle();
2339 #endif
2343 * ":argdo", ":windo", ":bufdo", ":tabdo"
2345 void
2346 ex_listdo(eap)
2347 exarg_T *eap;
2349 int i;
2350 #ifdef FEAT_WINDOWS
2351 win_T *wp;
2352 tabpage_T *tp;
2353 #endif
2354 buf_T *buf;
2355 int next_fnum = 0;
2356 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2357 char_u *save_ei = NULL;
2358 #endif
2359 char_u *p_shm_save;
2361 #ifndef FEAT_WINDOWS
2362 if (eap->cmdidx == CMD_windo)
2364 ex_ni(eap);
2365 return;
2367 #endif
2369 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2370 if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo)
2371 /* Don't do syntax HL autocommands. Skipping the syntax file is a
2372 * great speed improvement. */
2373 save_ei = au_event_disable(",Syntax");
2374 #endif
2376 if (eap->cmdidx == CMD_windo
2377 || eap->cmdidx == CMD_tabdo
2378 || P_HID(curbuf)
2379 || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
2381 /* start at the first argument/window/buffer */
2382 i = 0;
2383 #ifdef FEAT_WINDOWS
2384 wp = firstwin;
2385 tp = first_tabpage;
2386 #endif
2387 /* set pcmark now */
2388 if (eap->cmdidx == CMD_bufdo)
2389 goto_buffer(eap, DOBUF_FIRST, FORWARD, 0);
2390 else
2391 setpcmark();
2392 listcmd_busy = TRUE; /* avoids setting pcmark below */
2394 while (!got_int)
2396 if (eap->cmdidx == CMD_argdo)
2398 /* go to argument "i" */
2399 if (i == ARGCOUNT)
2400 break;
2401 /* Don't call do_argfile() when already there, it will try
2402 * reloading the file. */
2403 if (curwin->w_arg_idx != i || !editing_arg_idx(curwin))
2405 /* Clear 'shm' to avoid that the file message overwrites
2406 * any output from the command. */
2407 p_shm_save = vim_strsave(p_shm);
2408 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
2409 do_argfile(eap, i);
2410 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
2411 vim_free(p_shm_save);
2413 if (curwin->w_arg_idx != i)
2414 break;
2415 ++i;
2417 #ifdef FEAT_WINDOWS
2418 else if (eap->cmdidx == CMD_windo)
2420 /* go to window "wp" */
2421 if (!win_valid(wp))
2422 break;
2423 win_goto(wp);
2424 if (curwin != wp)
2425 break; /* something must be wrong */
2426 wp = curwin->w_next;
2428 else if (eap->cmdidx == CMD_tabdo)
2430 /* go to window "tp" */
2431 if (!valid_tabpage(tp))
2432 break;
2433 goto_tabpage_tp(tp);
2434 tp = tp->tp_next;
2436 #endif
2437 else if (eap->cmdidx == CMD_bufdo)
2439 /* Remember the number of the next listed buffer, in case
2440 * ":bwipe" is used or autocommands do something strange. */
2441 next_fnum = -1;
2442 for (buf = curbuf->b_next; buf != NULL; buf = buf->b_next)
2443 if (buf->b_p_bl)
2445 next_fnum = buf->b_fnum;
2446 break;
2450 /* execute the command */
2451 do_cmdline(eap->arg, eap->getline, eap->cookie,
2452 DOCMD_VERBOSE + DOCMD_NOWAIT);
2454 if (eap->cmdidx == CMD_bufdo)
2456 /* Done? */
2457 if (next_fnum < 0)
2458 break;
2459 /* Check if the buffer still exists. */
2460 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
2461 if (buf->b_fnum == next_fnum)
2462 break;
2463 if (buf == NULL)
2464 break;
2466 /* Go to the next buffer. Clear 'shm' to avoid that the file
2467 * message overwrites any output from the command. */
2468 p_shm_save = vim_strsave(p_shm);
2469 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
2470 goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
2471 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
2472 vim_free(p_shm_save);
2474 /* If autocommands took us elsewhere, quit here */
2475 if (curbuf->b_fnum != next_fnum)
2476 break;
2479 if (eap->cmdidx == CMD_windo)
2481 validate_cursor(); /* cursor may have moved */
2482 #ifdef FEAT_SCROLLBIND
2483 /* required when 'scrollbind' has been set */
2484 if (curwin->w_p_scb)
2485 do_check_scrollbind(TRUE);
2486 #endif
2489 listcmd_busy = FALSE;
2492 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2493 if (save_ei != NULL)
2495 au_event_restore(save_ei);
2496 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
2497 curbuf->b_fname, TRUE, curbuf);
2499 #endif
2503 * Add files[count] to the arglist of the current window after arg "after".
2504 * The file names in files[count] must have been allocated and are taken over.
2505 * Files[] itself is not taken over.
2506 * Returns index of first added argument. Returns -1 when failed (out of mem).
2508 static int
2509 alist_add_list(count, files, after)
2510 int count;
2511 char_u **files;
2512 int after; /* where to add: 0 = before first one */
2514 int i;
2516 if (ga_grow(&ALIST(curwin)->al_ga, count) == OK)
2518 if (after < 0)
2519 after = 0;
2520 if (after > ARGCOUNT)
2521 after = ARGCOUNT;
2522 if (after < ARGCOUNT)
2523 mch_memmove(&(ARGLIST[after + count]), &(ARGLIST[after]),
2524 (ARGCOUNT - after) * sizeof(aentry_T));
2525 for (i = 0; i < count; ++i)
2527 ARGLIST[after + i].ae_fname = files[i];
2528 ARGLIST[after + i].ae_fnum = buflist_add(files[i], BLN_LISTED);
2530 ALIST(curwin)->al_ga.ga_len += count;
2531 if (curwin->w_arg_idx >= after)
2532 ++curwin->w_arg_idx;
2533 return after;
2536 for (i = 0; i < count; ++i)
2537 vim_free(files[i]);
2538 return -1;
2541 #endif /* FEAT_LISTCMDS */
2543 #ifdef FEAT_EVAL
2545 * ":compiler[!] {name}"
2547 void
2548 ex_compiler(eap)
2549 exarg_T *eap;
2551 char_u *buf;
2552 char_u *old_cur_comp = NULL;
2553 char_u *p;
2555 if (*eap->arg == NUL)
2557 /* List all compiler scripts. */
2558 do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')");
2559 /* ) keep the indenter happy... */
2561 else
2563 buf = alloc((unsigned)(STRLEN(eap->arg) + 14));
2564 if (buf != NULL)
2566 if (eap->forceit)
2568 /* ":compiler! {name}" sets global options */
2569 do_cmdline_cmd((char_u *)
2570 "command -nargs=* CompilerSet set <args>");
2572 else
2574 /* ":compiler! {name}" sets local options.
2575 * To remain backwards compatible "current_compiler" is always
2576 * used. A user's compiler plugin may set it, the distributed
2577 * plugin will then skip the settings. Afterwards set
2578 * "b:current_compiler" and restore "current_compiler".
2579 * Explicitly prepend "g:" to make it work in a function. */
2580 old_cur_comp = get_var_value((char_u *)"g:current_compiler");
2581 if (old_cur_comp != NULL)
2582 old_cur_comp = vim_strsave(old_cur_comp);
2583 do_cmdline_cmd((char_u *)
2584 "command -nargs=* CompilerSet setlocal <args>");
2586 do_unlet((char_u *)"g:current_compiler", TRUE);
2587 do_unlet((char_u *)"b:current_compiler", TRUE);
2589 sprintf((char *)buf, "compiler/%s.vim", eap->arg);
2590 if (source_runtime(buf, TRUE) == FAIL)
2591 EMSG2(_("E666: compiler not supported: %s"), eap->arg);
2592 vim_free(buf);
2594 do_cmdline_cmd((char_u *)":delcommand CompilerSet");
2596 /* Set "b:current_compiler" from "current_compiler". */
2597 p = get_var_value((char_u *)"g:current_compiler");
2598 if (p != NULL)
2599 set_internal_string_var((char_u *)"b:current_compiler", p);
2601 /* Restore "current_compiler" for ":compiler {name}". */
2602 if (!eap->forceit)
2604 if (old_cur_comp != NULL)
2606 set_internal_string_var((char_u *)"g:current_compiler",
2607 old_cur_comp);
2608 vim_free(old_cur_comp);
2610 else
2611 do_unlet((char_u *)"g:current_compiler", TRUE);
2616 #endif
2619 * ":runtime {name}"
2621 void
2622 ex_runtime(eap)
2623 exarg_T *eap;
2625 source_runtime(eap->arg, eap->forceit);
2628 static void source_callback __ARGS((char_u *fname, void *cookie));
2630 static void
2631 source_callback(fname, cookie)
2632 char_u *fname;
2633 void *cookie UNUSED;
2635 (void)do_source(fname, FALSE, DOSO_NONE);
2639 * Source the file "name" from all directories in 'runtimepath'.
2640 * "name" can contain wildcards.
2641 * When "all" is TRUE, source all files, otherwise only the first one.
2642 * return FAIL when no file could be sourced, OK otherwise.
2645 source_runtime(name, all)
2646 char_u *name;
2647 int all;
2649 return do_in_runtimepath(name, all, source_callback, NULL);
2653 * Find "name" in 'runtimepath'. When found, invoke the callback function for
2654 * it: callback(fname, "cookie")
2655 * When "all" is TRUE repeat for all matches, otherwise only the first one is
2656 * used.
2657 * Returns OK when at least one match found, FAIL otherwise.
2660 do_in_runtimepath(name, all, callback, cookie)
2661 char_u *name;
2662 int all;
2663 void (*callback)__ARGS((char_u *fname, void *ck));
2664 void *cookie;
2666 char_u *rtp;
2667 char_u *np;
2668 char_u *buf;
2669 char_u *rtp_copy;
2670 char_u *tail;
2671 int num_files;
2672 char_u **files;
2673 int i;
2674 int did_one = FALSE;
2675 #ifdef AMIGA
2676 struct Process *proc = (struct Process *)FindTask(0L);
2677 APTR save_winptr = proc->pr_WindowPtr;
2679 /* Avoid a requester here for a volume that doesn't exist. */
2680 proc->pr_WindowPtr = (APTR)-1L;
2681 #endif
2683 /* Make a copy of 'runtimepath'. Invoking the callback may change the
2684 * value. */
2685 rtp_copy = vim_strsave(p_rtp);
2686 buf = alloc(MAXPATHL);
2687 if (buf != NULL && rtp_copy != NULL)
2689 if (p_verbose > 1)
2691 verbose_enter();
2692 smsg((char_u *)_("Searching for \"%s\" in \"%s\""),
2693 (char *)name, (char *)p_rtp);
2694 verbose_leave();
2697 /* Loop over all entries in 'runtimepath'. */
2698 rtp = rtp_copy;
2699 while (*rtp != NUL && (all || !did_one))
2701 /* Copy the path from 'runtimepath' to buf[]. */
2702 copy_option_part(&rtp, buf, MAXPATHL, ",");
2703 if (STRLEN(buf) + STRLEN(name) + 2 < MAXPATHL)
2705 add_pathsep(buf);
2706 tail = buf + STRLEN(buf);
2708 /* Loop over all patterns in "name" */
2709 np = name;
2710 while (*np != NUL && (all || !did_one))
2712 /* Append the pattern from "name" to buf[]. */
2713 copy_option_part(&np, tail, (int)(MAXPATHL - (tail - buf)),
2714 "\t ");
2716 if (p_verbose > 2)
2718 verbose_enter();
2719 smsg((char_u *)_("Searching for \"%s\""), buf);
2720 verbose_leave();
2723 /* Expand wildcards, invoke the callback for each match. */
2724 if (gen_expand_wildcards(1, &buf, &num_files, &files,
2725 EW_FILE) == OK)
2727 for (i = 0; i < num_files; ++i)
2729 (*callback)(files[i], cookie);
2730 did_one = TRUE;
2731 if (!all)
2732 break;
2734 FreeWild(num_files, files);
2740 vim_free(buf);
2741 vim_free(rtp_copy);
2742 if (p_verbose > 0 && !did_one)
2744 verbose_enter();
2745 smsg((char_u *)_("not found in 'runtimepath': \"%s\""), name);
2746 verbose_leave();
2749 #ifdef AMIGA
2750 proc->pr_WindowPtr = save_winptr;
2751 #endif
2753 return did_one ? OK : FAIL;
2756 #if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD)
2758 * ":options"
2760 void
2761 ex_options(eap)
2762 exarg_T *eap UNUSED;
2764 cmd_source((char_u *)SYS_OPTWIN_FILE, NULL);
2766 #endif
2769 * ":source {fname}"
2771 void
2772 ex_source(eap)
2773 exarg_T *eap;
2775 #ifdef FEAT_BROWSE
2776 if (cmdmod.browse)
2778 char_u *fname = NULL;
2780 fname = do_browse(0, (char_u *)_("Source Vim script"), eap->arg,
2781 NULL, NULL, BROWSE_FILTER_MACROS, NULL);
2782 if (fname != NULL)
2784 cmd_source(fname, eap);
2785 vim_free(fname);
2788 else
2789 #endif
2790 cmd_source(eap->arg, eap);
2793 static void
2794 cmd_source(fname, eap)
2795 char_u *fname;
2796 exarg_T *eap;
2798 if (*fname == NUL)
2799 EMSG(_(e_argreq));
2801 else if (eap != NULL && eap->forceit)
2802 /* ":source!": read Normal mdoe commands
2803 * Need to execute the commands directly. This is required at least
2804 * for:
2805 * - ":g" command busy
2806 * - after ":argdo", ":windo" or ":bufdo"
2807 * - another command follows
2808 * - inside a loop
2810 openscript(fname, global_busy || listcmd_busy || eap->nextcmd != NULL
2811 #ifdef FEAT_EVAL
2812 || eap->cstack->cs_idx >= 0
2813 #endif
2816 /* ":source" read ex commands */
2817 else if (do_source(fname, FALSE, DOSO_NONE) == FAIL)
2818 EMSG2(_(e_notopen), fname);
2822 * ":source" and associated commands.
2825 * Structure used to store info for each sourced file.
2826 * It is shared between do_source() and getsourceline().
2827 * This is required, because it needs to be handed to do_cmdline() and
2828 * sourcing can be done recursively.
2830 struct source_cookie
2832 FILE *fp; /* opened file for sourcing */
2833 char_u *nextline; /* if not NULL: line that was read ahead */
2834 int finished; /* ":finish" used */
2835 #if defined (USE_CRNL) || defined (USE_CR)
2836 int fileformat; /* EOL_UNKNOWN, EOL_UNIX or EOL_DOS */
2837 int error; /* TRUE if LF found after CR-LF */
2838 #endif
2839 #ifdef FEAT_EVAL
2840 linenr_T breakpoint; /* next line with breakpoint or zero */
2841 char_u *fname; /* name of sourced file */
2842 int dbg_tick; /* debug_tick when breakpoint was set */
2843 int level; /* top nesting level of sourced file */
2844 #endif
2845 #ifdef FEAT_MBYTE
2846 vimconv_T conv; /* type of conversion */
2847 #endif
2850 #ifdef FEAT_EVAL
2852 * Return the address holding the next breakpoint line for a source cookie.
2854 linenr_T *
2855 source_breakpoint(cookie)
2856 void *cookie;
2858 return &((struct source_cookie *)cookie)->breakpoint;
2862 * Return the address holding the debug tick for a source cookie.
2864 int *
2865 source_dbg_tick(cookie)
2866 void *cookie;
2868 return &((struct source_cookie *)cookie)->dbg_tick;
2872 * Return the nesting level for a source cookie.
2875 source_level(cookie)
2876 void *cookie;
2878 return ((struct source_cookie *)cookie)->level;
2880 #endif
2882 static char_u *get_one_sourceline __ARGS((struct source_cookie *sp));
2884 #if (defined(WIN32) && defined(FEAT_CSCOPE)) || defined(HAVE_FD_CLOEXEC)
2885 # define USE_FOPEN_NOINH
2886 static FILE *fopen_noinh_readbin __ARGS((char *filename));
2889 * Special function to open a file without handle inheritance.
2890 * When possible the handle is closed on exec().
2892 static FILE *
2893 fopen_noinh_readbin(filename)
2894 char *filename;
2896 # ifdef WIN32
2897 int fd_tmp = mch_open(filename, O_RDONLY | O_BINARY | O_NOINHERIT, 0);
2898 # else
2899 int fd_tmp = mch_open(filename, O_RDONLY, 0);
2900 # endif
2902 if (fd_tmp == -1)
2903 return NULL;
2905 # ifdef HAVE_FD_CLOEXEC
2907 int fdflags = fcntl(fd_tmp, F_GETFD);
2908 if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0)
2909 fcntl(fd_tmp, F_SETFD, fdflags | FD_CLOEXEC);
2911 # endif
2913 return fdopen(fd_tmp, READBIN);
2915 #endif
2919 * do_source: Read the file "fname" and execute its lines as EX commands.
2921 * This function may be called recursively!
2923 * return FAIL if file could not be opened, OK otherwise
2926 do_source(fname, check_other, is_vimrc)
2927 char_u *fname;
2928 int check_other; /* check for .vimrc and _vimrc */
2929 int is_vimrc; /* DOSO_ value */
2931 struct source_cookie cookie;
2932 char_u *save_sourcing_name;
2933 linenr_T save_sourcing_lnum;
2934 char_u *p;
2935 char_u *fname_exp;
2936 char_u *firstline = NULL;
2937 int retval = FAIL;
2938 #ifdef FEAT_EVAL
2939 scid_T save_current_SID;
2940 static scid_T last_current_SID = 0;
2941 void *save_funccalp;
2942 int save_debug_break_level = debug_break_level;
2943 scriptitem_T *si = NULL;
2944 # ifdef UNIX
2945 struct stat st;
2946 int stat_ok;
2947 # endif
2948 #endif
2949 #ifdef STARTUPTIME
2950 struct timeval tv_rel;
2951 struct timeval tv_start;
2952 #endif
2953 #ifdef FEAT_PROFILE
2954 proftime_T wait_start;
2955 #endif
2957 #ifdef RISCOS
2958 p = mch_munge_fname(fname);
2959 #else
2960 p = expand_env_save(fname);
2961 #endif
2962 if (p == NULL)
2963 return retval;
2964 fname_exp = fix_fname(p);
2965 vim_free(p);
2966 if (fname_exp == NULL)
2967 return retval;
2968 if (mch_isdir(fname_exp))
2970 smsg((char_u *)_("Cannot source a directory: \"%s\""), fname);
2971 goto theend;
2974 #ifdef FEAT_AUTOCMD
2975 /* Apply SourceCmd autocommands, they should get the file and source it. */
2976 if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL)
2977 && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp,
2978 FALSE, curbuf))
2980 # ifdef FEAT_EVAL
2981 retval = aborting() ? FAIL : OK;
2982 # else
2983 retval = OK;
2984 # endif
2985 goto theend;
2988 /* Apply SourcePre autocommands, they may get the file. */
2989 apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, FALSE, curbuf);
2990 #endif
2992 #ifdef USE_FOPEN_NOINH
2993 cookie.fp = fopen_noinh_readbin((char *)fname_exp);
2994 #else
2995 cookie.fp = mch_fopen((char *)fname_exp, READBIN);
2996 #endif
2997 if (cookie.fp == NULL && check_other)
3000 * Try again, replacing file name ".vimrc" by "_vimrc" or vice versa,
3001 * and ".exrc" by "_exrc" or vice versa.
3003 p = gettail(fname_exp);
3004 if ((*p == '.' || *p == '_')
3005 && (STRICMP(p + 1, "vimrc") == 0
3006 || STRICMP(p + 1, "gvimrc") == 0
3007 || STRICMP(p + 1, "exrc") == 0))
3009 if (*p == '_')
3010 *p = '.';
3011 else
3012 *p = '_';
3013 #ifdef USE_FOPEN_NOINH
3014 cookie.fp = fopen_noinh_readbin((char *)fname_exp);
3015 #else
3016 cookie.fp = mch_fopen((char *)fname_exp, READBIN);
3017 #endif
3021 if (cookie.fp == NULL)
3023 if (p_verbose > 0)
3025 verbose_enter();
3026 if (sourcing_name == NULL)
3027 smsg((char_u *)_("could not source \"%s\""), fname);
3028 else
3029 smsg((char_u *)_("line %ld: could not source \"%s\""),
3030 sourcing_lnum, fname);
3031 verbose_leave();
3033 goto theend;
3037 * The file exists.
3038 * - In verbose mode, give a message.
3039 * - For a vimrc file, may want to set 'compatible', call vimrc_found().
3041 if (p_verbose > 1)
3043 verbose_enter();
3044 if (sourcing_name == NULL)
3045 smsg((char_u *)_("sourcing \"%s\""), fname);
3046 else
3047 smsg((char_u *)_("line %ld: sourcing \"%s\""),
3048 sourcing_lnum, fname);
3049 verbose_leave();
3051 if (is_vimrc == DOSO_VIMRC)
3052 vimrc_found(fname_exp, (char_u *)"MYVIMRC");
3053 else if (is_vimrc == DOSO_GVIMRC)
3054 vimrc_found(fname_exp, (char_u *)"MYGVIMRC");
3056 #ifdef USE_CRNL
3057 /* If no automatic file format: Set default to CR-NL. */
3058 if (*p_ffs == NUL)
3059 cookie.fileformat = EOL_DOS;
3060 else
3061 cookie.fileformat = EOL_UNKNOWN;
3062 cookie.error = FALSE;
3063 #endif
3065 #ifdef USE_CR
3066 /* If no automatic file format: Set default to CR. */
3067 if (*p_ffs == NUL)
3068 cookie.fileformat = EOL_MAC;
3069 else
3070 cookie.fileformat = EOL_UNKNOWN;
3071 cookie.error = FALSE;
3072 #endif
3074 cookie.nextline = NULL;
3075 cookie.finished = FALSE;
3077 #ifdef FEAT_EVAL
3079 * Check if this script has a breakpoint.
3081 cookie.breakpoint = dbg_find_breakpoint(TRUE, fname_exp, (linenr_T)0);
3082 cookie.fname = fname_exp;
3083 cookie.dbg_tick = debug_tick;
3085 cookie.level = ex_nesting_level;
3086 #endif
3089 * Keep the sourcing name/lnum, for recursive calls.
3091 save_sourcing_name = sourcing_name;
3092 sourcing_name = fname_exp;
3093 save_sourcing_lnum = sourcing_lnum;
3094 sourcing_lnum = 0;
3096 #ifdef FEAT_MBYTE
3097 cookie.conv.vc_type = CONV_NONE; /* no conversion */
3099 /* Read the first line so we can check for a UTF-8 BOM. */
3100 firstline = getsourceline(0, (void *)&cookie, 0);
3101 if (firstline != NULL && STRLEN(firstline) >= 3 && firstline[0] == 0xef
3102 && firstline[1] == 0xbb && firstline[2] == 0xbf)
3104 /* Found BOM; setup conversion, skip over BOM and recode the line. */
3105 convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc);
3106 p = string_convert(&cookie.conv, firstline + 3, NULL);
3107 if (p == NULL)
3108 p = vim_strsave(firstline + 3);
3109 if (p != NULL)
3111 vim_free(firstline);
3112 firstline = p;
3115 #endif
3117 #ifdef STARTUPTIME
3118 if (time_fd != NULL)
3119 time_push(&tv_rel, &tv_start);
3120 #endif
3122 #ifdef FEAT_EVAL
3123 # ifdef FEAT_PROFILE
3124 if (do_profiling == PROF_YES)
3125 prof_child_enter(&wait_start); /* entering a child now */
3126 # endif
3128 /* Don't use local function variables, if called from a function.
3129 * Also starts profiling timer for nested script. */
3130 save_funccalp = save_funccal();
3133 * Check if this script was sourced before to finds its SID.
3134 * If it's new, generate a new SID.
3136 save_current_SID = current_SID;
3137 # ifdef UNIX
3138 stat_ok = (mch_stat((char *)fname_exp, &st) >= 0);
3139 # endif
3140 for (current_SID = script_items.ga_len; current_SID > 0; --current_SID)
3142 si = &SCRIPT_ITEM(current_SID);
3143 if (si->sn_name != NULL
3144 && (
3145 # ifdef UNIX
3146 /* Compare dev/ino when possible, it catches symbolic
3147 * links. Also compare file names, the inode may change
3148 * when the file was edited. */
3149 ((stat_ok && si->sn_dev_valid)
3150 && (si->sn_dev == st.st_dev
3151 && si->sn_ino == st.st_ino)) ||
3152 # endif
3153 fnamecmp(si->sn_name, fname_exp) == 0))
3154 break;
3156 if (current_SID == 0)
3158 current_SID = ++last_current_SID;
3159 if (ga_grow(&script_items, (int)(current_SID - script_items.ga_len))
3160 == FAIL)
3161 goto almosttheend;
3162 while (script_items.ga_len < current_SID)
3164 ++script_items.ga_len;
3165 SCRIPT_ITEM(script_items.ga_len).sn_name = NULL;
3166 # ifdef FEAT_PROFILE
3167 SCRIPT_ITEM(script_items.ga_len).sn_prof_on = FALSE;
3168 # endif
3170 si = &SCRIPT_ITEM(current_SID);
3171 si->sn_name = fname_exp;
3172 fname_exp = NULL;
3173 # ifdef UNIX
3174 if (stat_ok)
3176 si->sn_dev_valid = TRUE;
3177 si->sn_dev = st.st_dev;
3178 si->sn_ino = st.st_ino;
3180 else
3181 si->sn_dev_valid = FALSE;
3182 # endif
3184 /* Allocate the local script variables to use for this script. */
3185 new_script_vars(current_SID);
3188 # ifdef FEAT_PROFILE
3189 if (do_profiling == PROF_YES)
3191 int forceit;
3193 /* Check if we do profiling for this script. */
3194 if (!si->sn_prof_on && has_profiling(TRUE, si->sn_name, &forceit))
3196 script_do_profile(si);
3197 si->sn_pr_force = forceit;
3199 if (si->sn_prof_on)
3201 ++si->sn_pr_count;
3202 profile_start(&si->sn_pr_start);
3203 profile_zero(&si->sn_pr_children);
3206 # endif
3207 #endif
3210 * Call do_cmdline, which will call getsourceline() to get the lines.
3212 do_cmdline(firstline, getsourceline, (void *)&cookie,
3213 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT);
3214 retval = OK;
3216 #ifdef FEAT_PROFILE
3217 if (do_profiling == PROF_YES)
3219 /* Get "si" again, "script_items" may have been reallocated. */
3220 si = &SCRIPT_ITEM(current_SID);
3221 if (si->sn_prof_on)
3223 profile_end(&si->sn_pr_start);
3224 profile_sub_wait(&wait_start, &si->sn_pr_start);
3225 profile_add(&si->sn_pr_total, &si->sn_pr_start);
3226 profile_self(&si->sn_pr_self, &si->sn_pr_start,
3227 &si->sn_pr_children);
3230 #endif
3232 if (got_int)
3233 EMSG(_(e_interr));
3234 sourcing_name = save_sourcing_name;
3235 sourcing_lnum = save_sourcing_lnum;
3236 if (p_verbose > 1)
3238 verbose_enter();
3239 smsg((char_u *)_("finished sourcing %s"), fname);
3240 if (sourcing_name != NULL)
3241 smsg((char_u *)_("continuing in %s"), sourcing_name);
3242 verbose_leave();
3244 #ifdef STARTUPTIME
3245 if (time_fd != NULL)
3247 vim_snprintf((char *)IObuff, IOSIZE, "sourcing %s", fname);
3248 time_msg((char *)IObuff, &tv_start);
3249 time_pop(&tv_rel);
3251 #endif
3253 #ifdef FEAT_EVAL
3255 * After a "finish" in debug mode, need to break at first command of next
3256 * sourced file.
3258 if (save_debug_break_level > ex_nesting_level
3259 && debug_break_level == ex_nesting_level)
3260 ++debug_break_level;
3261 #endif
3263 #ifdef FEAT_EVAL
3264 almosttheend:
3265 current_SID = save_current_SID;
3266 restore_funccal(save_funccalp);
3267 # ifdef FEAT_PROFILE
3268 if (do_profiling == PROF_YES)
3269 prof_child_exit(&wait_start); /* leaving a child now */
3270 # endif
3271 #endif
3272 fclose(cookie.fp);
3273 vim_free(cookie.nextline);
3274 vim_free(firstline);
3275 #ifdef FEAT_MBYTE
3276 convert_setup(&cookie.conv, NULL, NULL);
3277 #endif
3279 theend:
3280 vim_free(fname_exp);
3281 return retval;
3284 #if defined(FEAT_EVAL) || defined(PROTO)
3287 * ":scriptnames"
3289 void
3290 ex_scriptnames(eap)
3291 exarg_T *eap UNUSED;
3293 int i;
3295 for (i = 1; i <= script_items.ga_len && !got_int; ++i)
3296 if (SCRIPT_ITEM(i).sn_name != NULL)
3297 smsg((char_u *)"%3d: %s", i, SCRIPT_ITEM(i).sn_name);
3300 # if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
3302 * Fix slashes in the list of script names for 'shellslash'.
3304 void
3305 scriptnames_slash_adjust()
3307 int i;
3309 for (i = 1; i <= script_items.ga_len; ++i)
3310 if (SCRIPT_ITEM(i).sn_name != NULL)
3311 slash_adjust(SCRIPT_ITEM(i).sn_name);
3313 # endif
3316 * Get a pointer to a script name. Used for ":verbose set".
3318 char_u *
3319 get_scriptname(id)
3320 scid_T id;
3322 if (id == SID_MODELINE)
3323 return (char_u *)_("modeline");
3324 if (id == SID_CMDARG)
3325 return (char_u *)_("--cmd argument");
3326 if (id == SID_CARG)
3327 return (char_u *)_("-c argument");
3328 if (id == SID_ENV)
3329 return (char_u *)_("environment variable");
3330 if (id == SID_ERROR)
3331 return (char_u *)_("error handler");
3332 return SCRIPT_ITEM(id).sn_name;
3335 # if defined(EXITFREE) || defined(PROTO)
3336 void
3337 free_scriptnames()
3339 int i;
3341 for (i = script_items.ga_len; i > 0; --i)
3342 vim_free(SCRIPT_ITEM(i).sn_name);
3343 ga_clear(&script_items);
3345 # endif
3347 #endif
3349 #if defined(USE_CR) || defined(PROTO)
3351 # if defined(__MSL__) && (__MSL__ >= 22)
3353 * Newer version of the Metrowerks library handle DOS and UNIX files
3354 * without help.
3355 * Test with earlier versions, MSL 2.2 is the library supplied with
3356 * Codewarrior Pro 2.
3358 char *
3359 fgets_cr(s, n, stream)
3360 char *s;
3361 int n;
3362 FILE *stream;
3364 return fgets(s, n, stream);
3366 # else
3368 * Version of fgets() which also works for lines ending in a <CR> only
3369 * (Macintosh format).
3370 * For older versions of the Metrowerks library.
3371 * At least CodeWarrior 9 needed this code.
3373 char *
3374 fgets_cr(s, n, stream)
3375 char *s;
3376 int n;
3377 FILE *stream;
3379 int c = 0;
3380 int char_read = 0;
3382 while (!feof(stream) && c != '\r' && c != '\n' && char_read < n - 1)
3384 c = fgetc(stream);
3385 s[char_read++] = c;
3386 /* If the file is in DOS format, we need to skip a NL after a CR. I
3387 * thought it was the other way around, but this appears to work... */
3388 if (c == '\n')
3390 c = fgetc(stream);
3391 if (c != '\r')
3392 ungetc(c, stream);
3396 s[char_read] = 0;
3397 if (char_read == 0)
3398 return NULL;
3400 if (feof(stream) && char_read == 1)
3401 return NULL;
3403 return s;
3405 # endif
3406 #endif
3409 * Get one full line from a sourced file.
3410 * Called by do_cmdline() when it's called from do_source().
3412 * Return a pointer to the line in allocated memory.
3413 * Return NULL for end-of-file or some error.
3415 char_u *
3416 getsourceline(c, cookie, indent)
3417 int c UNUSED;
3418 void *cookie;
3419 int indent UNUSED;
3421 struct source_cookie *sp = (struct source_cookie *)cookie;
3422 char_u *line;
3423 char_u *p, *s;
3425 #ifdef FEAT_EVAL
3426 /* If breakpoints have been added/deleted need to check for it. */
3427 if (sp->dbg_tick < debug_tick)
3429 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
3430 sp->dbg_tick = debug_tick;
3432 # ifdef FEAT_PROFILE
3433 if (do_profiling == PROF_YES)
3434 script_line_end();
3435 # endif
3436 #endif
3438 * Get current line. If there is a read-ahead line, use it, otherwise get
3439 * one now.
3441 if (sp->finished)
3442 line = NULL;
3443 else if (sp->nextline == NULL)
3444 line = get_one_sourceline(sp);
3445 else
3447 line = sp->nextline;
3448 sp->nextline = NULL;
3449 ++sourcing_lnum;
3451 #ifdef FEAT_PROFILE
3452 if (line != NULL && do_profiling == PROF_YES)
3453 script_line_start();
3454 #endif
3456 /* Only concatenate lines starting with a \ when 'cpoptions' doesn't
3457 * contain the 'C' flag. */
3458 if (line != NULL && (vim_strchr(p_cpo, CPO_CONCAT) == NULL))
3460 /* compensate for the one line read-ahead */
3461 --sourcing_lnum;
3462 for (;;)
3464 sp->nextline = get_one_sourceline(sp);
3465 if (sp->nextline == NULL)
3466 break;
3467 p = skipwhite(sp->nextline);
3468 if (*p != '\\')
3469 break;
3470 s = alloc((unsigned)(STRLEN(line) + STRLEN(p)));
3471 if (s == NULL) /* out of memory */
3472 break;
3473 STRCPY(s, line);
3474 STRCAT(s, p + 1);
3475 vim_free(line);
3476 line = s;
3477 vim_free(sp->nextline);
3481 #ifdef FEAT_MBYTE
3482 if (line != NULL && sp->conv.vc_type != CONV_NONE)
3484 /* Convert the encoding of the script line. */
3485 s = string_convert(&sp->conv, line, NULL);
3486 if (s != NULL)
3488 vim_free(line);
3489 line = s;
3492 #endif
3494 #ifdef FEAT_EVAL
3495 /* Did we encounter a breakpoint? */
3496 if (sp->breakpoint != 0 && sp->breakpoint <= sourcing_lnum)
3498 dbg_breakpoint(sp->fname, sourcing_lnum);
3499 /* Find next breakpoint. */
3500 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
3501 sp->dbg_tick = debug_tick;
3503 #endif
3505 return line;
3508 static char_u *
3509 get_one_sourceline(sp)
3510 struct source_cookie *sp;
3512 garray_T ga;
3513 int len;
3514 int c;
3515 char_u *buf;
3516 #ifdef USE_CRNL
3517 int has_cr; /* CR-LF found */
3518 #endif
3519 #ifdef USE_CR
3520 char_u *scan;
3521 #endif
3522 int have_read = FALSE;
3524 /* use a growarray to store the sourced line */
3525 ga_init2(&ga, 1, 250);
3528 * Loop until there is a finished line (or end-of-file).
3530 sourcing_lnum++;
3531 for (;;)
3533 /* make room to read at least 120 (more) characters */
3534 if (ga_grow(&ga, 120) == FAIL)
3535 break;
3536 buf = (char_u *)ga.ga_data;
3538 #ifdef USE_CR
3539 if (sp->fileformat == EOL_MAC)
3541 if (fgets_cr((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
3542 sp->fp) == NULL)
3543 break;
3545 else
3546 #endif
3547 if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
3548 sp->fp) == NULL)
3549 break;
3550 len = ga.ga_len + (int)STRLEN(buf + ga.ga_len);
3551 #ifdef USE_CRNL
3552 /* Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the
3553 * CTRL-Z by its own, or after a NL. */
3554 if ( (len == 1 || (len >= 2 && buf[len - 2] == '\n'))
3555 && sp->fileformat == EOL_DOS
3556 && buf[len - 1] == Ctrl_Z)
3558 buf[len - 1] = NUL;
3559 break;
3561 #endif
3563 #ifdef USE_CR
3564 /* If the read doesn't stop on a new line, and there's
3565 * some CR then we assume a Mac format */
3566 if (sp->fileformat == EOL_UNKNOWN)
3568 if (buf[len - 1] != '\n' && vim_strchr(buf, '\r') != NULL)
3569 sp->fileformat = EOL_MAC;
3570 else
3571 sp->fileformat = EOL_UNIX;
3574 if (sp->fileformat == EOL_MAC)
3576 scan = vim_strchr(buf, '\r');
3578 if (scan != NULL)
3580 *scan = '\n';
3581 if (*(scan + 1) != 0)
3583 *(scan + 1) = 0;
3584 fseek(sp->fp, (long)(scan - buf - len + 1), SEEK_CUR);
3587 len = STRLEN(buf);
3589 #endif
3591 have_read = TRUE;
3592 ga.ga_len = len;
3594 /* If the line was longer than the buffer, read more. */
3595 if (ga.ga_maxlen - ga.ga_len == 1 && buf[len - 1] != '\n')
3596 continue;
3598 if (len >= 1 && buf[len - 1] == '\n') /* remove trailing NL */
3600 #ifdef USE_CRNL
3601 has_cr = (len >= 2 && buf[len - 2] == '\r');
3602 if (sp->fileformat == EOL_UNKNOWN)
3604 if (has_cr)
3605 sp->fileformat = EOL_DOS;
3606 else
3607 sp->fileformat = EOL_UNIX;
3610 if (sp->fileformat == EOL_DOS)
3612 if (has_cr) /* replace trailing CR */
3614 buf[len - 2] = '\n';
3615 --len;
3616 --ga.ga_len;
3618 else /* lines like ":map xx yy^M" will have failed */
3620 if (!sp->error)
3622 msg_source(hl_attr(HLF_W));
3623 EMSG(_("W15: Warning: Wrong line separator, ^M may be missing"));
3625 sp->error = TRUE;
3626 sp->fileformat = EOL_UNIX;
3629 #endif
3630 /* The '\n' is escaped if there is an odd number of ^V's just
3631 * before it, first set "c" just before the 'V's and then check
3632 * len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo */
3633 for (c = len - 2; c >= 0 && buf[c] == Ctrl_V; c--)
3635 if ((len & 1) != (c & 1)) /* escaped NL, read more */
3637 sourcing_lnum++;
3638 continue;
3641 buf[len - 1] = NUL; /* remove the NL */
3645 * Check for ^C here now and then, so recursive :so can be broken.
3647 line_breakcheck();
3648 break;
3651 if (have_read)
3652 return (char_u *)ga.ga_data;
3654 vim_free(ga.ga_data);
3655 return NULL;
3658 #if defined(FEAT_PROFILE) || defined(PROTO)
3660 * Called when starting to read a script line.
3661 * "sourcing_lnum" must be correct!
3662 * When skipping lines it may not actually be executed, but we won't find out
3663 * until later and we need to store the time now.
3665 void
3666 script_line_start()
3668 scriptitem_T *si;
3669 sn_prl_T *pp;
3671 if (current_SID <= 0 || current_SID > script_items.ga_len)
3672 return;
3673 si = &SCRIPT_ITEM(current_SID);
3674 if (si->sn_prof_on && sourcing_lnum >= 1)
3676 /* Grow the array before starting the timer, so that the time spent
3677 * here isn't counted. */
3678 ga_grow(&si->sn_prl_ga, (int)(sourcing_lnum - si->sn_prl_ga.ga_len));
3679 si->sn_prl_idx = sourcing_lnum - 1;
3680 while (si->sn_prl_ga.ga_len <= si->sn_prl_idx
3681 && si->sn_prl_ga.ga_len < si->sn_prl_ga.ga_maxlen)
3683 /* Zero counters for a line that was not used before. */
3684 pp = &PRL_ITEM(si, si->sn_prl_ga.ga_len);
3685 pp->snp_count = 0;
3686 profile_zero(&pp->sn_prl_total);
3687 profile_zero(&pp->sn_prl_self);
3688 ++si->sn_prl_ga.ga_len;
3690 si->sn_prl_execed = FALSE;
3691 profile_start(&si->sn_prl_start);
3692 profile_zero(&si->sn_prl_children);
3693 profile_get_wait(&si->sn_prl_wait);
3698 * Called when actually executing a function line.
3700 void
3701 script_line_exec()
3703 scriptitem_T *si;
3705 if (current_SID <= 0 || current_SID > script_items.ga_len)
3706 return;
3707 si = &SCRIPT_ITEM(current_SID);
3708 if (si->sn_prof_on && si->sn_prl_idx >= 0)
3709 si->sn_prl_execed = TRUE;
3713 * Called when done with a function line.
3715 void
3716 script_line_end()
3718 scriptitem_T *si;
3719 sn_prl_T *pp;
3721 if (current_SID <= 0 || current_SID > script_items.ga_len)
3722 return;
3723 si = &SCRIPT_ITEM(current_SID);
3724 if (si->sn_prof_on && si->sn_prl_idx >= 0
3725 && si->sn_prl_idx < si->sn_prl_ga.ga_len)
3727 if (si->sn_prl_execed)
3729 pp = &PRL_ITEM(si, si->sn_prl_idx);
3730 ++pp->snp_count;
3731 profile_end(&si->sn_prl_start);
3732 profile_sub_wait(&si->sn_prl_wait, &si->sn_prl_start);
3733 profile_add(&pp->sn_prl_total, &si->sn_prl_start);
3734 profile_self(&pp->sn_prl_self, &si->sn_prl_start,
3735 &si->sn_prl_children);
3737 si->sn_prl_idx = -1;
3740 #endif
3743 * ":scriptencoding": Set encoding conversion for a sourced script.
3744 * Without the multi-byte feature it's simply ignored.
3746 void
3747 ex_scriptencoding(eap)
3748 exarg_T *eap UNUSED;
3750 #ifdef FEAT_MBYTE
3751 struct source_cookie *sp;
3752 char_u *name;
3754 if (!getline_equal(eap->getline, eap->cookie, getsourceline))
3756 EMSG(_("E167: :scriptencoding used outside of a sourced file"));
3757 return;
3760 if (*eap->arg != NUL)
3762 name = enc_canonize(eap->arg);
3763 if (name == NULL) /* out of memory */
3764 return;
3766 else
3767 name = eap->arg;
3769 /* Setup for conversion from the specified encoding to 'encoding'. */
3770 sp = (struct source_cookie *)getline_cookie(eap->getline, eap->cookie);
3771 convert_setup(&sp->conv, name, p_enc);
3773 if (name != eap->arg)
3774 vim_free(name);
3775 #endif
3778 #if defined(FEAT_EVAL) || defined(PROTO)
3780 * ":finish": Mark a sourced file as finished.
3782 void
3783 ex_finish(eap)
3784 exarg_T *eap;
3786 if (getline_equal(eap->getline, eap->cookie, getsourceline))
3787 do_finish(eap, FALSE);
3788 else
3789 EMSG(_("E168: :finish used outside of a sourced file"));
3793 * Mark a sourced file as finished. Possibly makes the ":finish" pending.
3794 * Also called for a pending finish at the ":endtry" or after returning from
3795 * an extra do_cmdline(). "reanimate" is used in the latter case.
3797 void
3798 do_finish(eap, reanimate)
3799 exarg_T *eap;
3800 int reanimate;
3802 int idx;
3804 if (reanimate)
3805 ((struct source_cookie *)getline_cookie(eap->getline,
3806 eap->cookie))->finished = FALSE;
3809 * Cleanup (and inactivate) conditionals, but stop when a try conditional
3810 * not in its finally clause (which then is to be executed next) is found.
3811 * In this case, make the ":finish" pending for execution at the ":endtry".
3812 * Otherwise, finish normally.
3814 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
3815 if (idx >= 0)
3817 eap->cstack->cs_pending[idx] = CSTP_FINISH;
3818 report_make_pending(CSTP_FINISH, NULL);
3820 else
3821 ((struct source_cookie *)getline_cookie(eap->getline,
3822 eap->cookie))->finished = TRUE;
3827 * Return TRUE when a sourced file had the ":finish" command: Don't give error
3828 * message for missing ":endif".
3829 * Return FALSE when not sourcing a file.
3832 source_finished(fgetline, cookie)
3833 char_u *(*fgetline) __ARGS((int, void *, int));
3834 void *cookie;
3836 return (getline_equal(fgetline, cookie, getsourceline)
3837 && ((struct source_cookie *)getline_cookie(
3838 fgetline, cookie))->finished);
3840 #endif
3842 #if defined(FEAT_LISTCMDS) || defined(PROTO)
3844 * ":checktime [buffer]"
3846 void
3847 ex_checktime(eap)
3848 exarg_T *eap;
3850 buf_T *buf;
3851 int save_no_check_timestamps = no_check_timestamps;
3853 no_check_timestamps = 0;
3854 if (eap->addr_count == 0) /* default is all buffers */
3855 check_timestamps(FALSE);
3856 else
3858 buf = buflist_findnr((int)eap->line2);
3859 if (buf != NULL) /* cannot happen? */
3860 (void)buf_check_timestamp(buf, FALSE);
3862 no_check_timestamps = save_no_check_timestamps;
3864 #endif
3866 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3867 && (defined(FEAT_EVAL) || defined(FEAT_MULTI_LANG))
3868 static char *get_locale_val __ARGS((int what));
3870 static char *
3871 get_locale_val(what)
3872 int what;
3874 char *loc;
3876 /* Obtain the locale value from the libraries. For DJGPP this is
3877 * redefined and it doesn't use the arguments. */
3878 loc = setlocale(what, NULL);
3880 # ifdef WIN32
3881 if (loc != NULL)
3883 char_u *p;
3885 /* setocale() returns something like "LC_COLLATE=<name>;LC_..." when
3886 * one of the values (e.g., LC_CTYPE) differs. */
3887 p = vim_strchr(loc, '=');
3888 if (p != NULL)
3890 loc = ++p;
3891 while (*p != NUL) /* remove trailing newline */
3893 if (*p < ' ' || *p == ';')
3895 *p = NUL;
3896 break;
3898 ++p;
3902 # endif
3904 return loc;
3906 #endif
3909 #ifdef WIN32
3911 * On MS-Windows locale names are strings like "German_Germany.1252", but
3912 * gettext expects "de". Try to translate one into another here for a few
3913 * supported languages.
3915 static char_u *
3916 gettext_lang(char_u *name)
3918 int i;
3919 static char *(mtable[]) = {
3920 "afrikaans", "af",
3921 "czech", "cs",
3922 "dutch", "nl",
3923 "german", "de",
3924 "english_united kingdom", "en_GB",
3925 "spanish", "es",
3926 "french", "fr",
3927 "italian", "it",
3928 "japanese", "ja",
3929 "korean", "ko",
3930 "norwegian", "no",
3931 "polish", "pl",
3932 "russian", "ru",
3933 "slovak", "sk",
3934 "swedish", "sv",
3935 "ukrainian", "uk",
3936 "chinese_china", "zh_CN",
3937 "chinese_taiwan", "zh_TW",
3938 NULL};
3940 for (i = 0; mtable[i] != NULL; i += 2)
3941 if (STRNICMP(mtable[i], name, STRLEN(mtable[i])) == 0)
3942 return mtable[i + 1];
3943 return name;
3945 #endif
3947 #if defined(FEAT_MULTI_LANG) || defined(PROTO)
3949 * Obtain the current messages language. Used to set the default for
3950 * 'helplang'. May return NULL or an empty string.
3952 char_u *
3953 get_mess_lang()
3955 char_u *p;
3957 # if (defined(HAVE_LOCALE_H) || defined(X_LOCALE))
3958 # if defined(LC_MESSAGES)
3959 p = (char_u *)get_locale_val(LC_MESSAGES);
3960 # else
3961 /* This is necessary for Win32, where LC_MESSAGES is not defined and $LANG
3962 * may be set to the LCID number. LC_COLLATE is the best guess, LC_TIME
3963 * and LC_MONETARY may be set differently for a Japanese working in the
3964 * US. */
3965 p = (char_u *)get_locale_val(LC_COLLATE);
3966 # endif
3967 # else
3968 p = mch_getenv((char_u *)"LC_ALL");
3969 if (p == NULL || *p == NUL)
3971 p = mch_getenv((char_u *)"LC_MESSAGES");
3972 if (p == NULL || *p == NUL)
3973 p = mch_getenv((char_u *)"LANG");
3975 # endif
3976 # ifdef WIN32
3977 p = gettext_lang(p);
3978 # endif
3979 return p;
3981 #endif
3983 /* Complicated #if; matches with where get_mess_env() is used below. */
3984 #if (defined(FEAT_EVAL) && !((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3985 && defined(LC_MESSAGES))) \
3986 || ((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3987 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)) \
3988 && !defined(LC_MESSAGES))
3989 static char_u *get_mess_env __ARGS((void));
3992 * Get the language used for messages from the environment.
3994 static char_u *
3995 get_mess_env()
3997 char_u *p;
3999 p = mch_getenv((char_u *)"LC_ALL");
4000 if (p == NULL || *p == NUL)
4002 p = mch_getenv((char_u *)"LC_MESSAGES");
4003 if (p == NULL || *p == NUL)
4005 p = mch_getenv((char_u *)"LANG");
4006 if (p != NULL && VIM_ISDIGIT(*p))
4007 p = NULL; /* ignore something like "1043" */
4008 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
4009 if (p == NULL || *p == NUL)
4010 p = (char_u *)get_locale_val(LC_CTYPE);
4011 # endif
4014 return p;
4016 #endif
4018 #if defined(FEAT_EVAL) || defined(PROTO)
4021 * Set the "v:lang" variable according to the current locale setting.
4022 * Also do "v:lc_time"and "v:ctype".
4024 void
4025 set_lang_var()
4027 char_u *loc;
4029 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
4030 loc = (char_u *)get_locale_val(LC_CTYPE);
4031 # else
4032 /* setlocale() not supported: use the default value */
4033 loc = (char_u *)"C";
4034 # endif
4035 set_vim_var_string(VV_CTYPE, loc, -1);
4037 /* When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall
4038 * back to LC_CTYPE if it's empty. */
4039 # if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) && defined(LC_MESSAGES)
4040 loc = (char_u *)get_locale_val(LC_MESSAGES);
4041 # else
4042 loc = get_mess_env();
4043 # endif
4044 set_vim_var_string(VV_LANG, loc, -1);
4046 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
4047 loc = (char_u *)get_locale_val(LC_TIME);
4048 # endif
4049 set_vim_var_string(VV_LC_TIME, loc, -1);
4051 #endif
4053 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
4054 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE))
4056 * ":language": Set the language (locale).
4058 void
4059 ex_language(eap)
4060 exarg_T *eap;
4062 char *loc;
4063 char_u *p;
4064 char_u *name;
4065 int what = LC_ALL;
4066 char *whatstr = "";
4067 #ifdef LC_MESSAGES
4068 # define VIM_LC_MESSAGES LC_MESSAGES
4069 #else
4070 # define VIM_LC_MESSAGES 6789
4071 #endif
4073 name = eap->arg;
4075 /* Check for "messages {name}", "ctype {name}" or "time {name}" argument.
4076 * Allow abbreviation, but require at least 3 characters to avoid
4077 * confusion with a two letter language name "me" or "ct". */
4078 p = skiptowhite(eap->arg);
4079 if ((*p == NUL || vim_iswhite(*p)) && p - eap->arg >= 3)
4081 if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0)
4083 what = VIM_LC_MESSAGES;
4084 name = skipwhite(p);
4085 whatstr = "messages ";
4087 else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0)
4089 what = LC_CTYPE;
4090 name = skipwhite(p);
4091 whatstr = "ctype ";
4093 else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0)
4095 what = LC_TIME;
4096 name = skipwhite(p);
4097 whatstr = "time ";
4101 if (*name == NUL)
4103 #ifndef LC_MESSAGES
4104 if (what == VIM_LC_MESSAGES)
4105 p = get_mess_env();
4106 else
4107 #endif
4108 p = (char_u *)setlocale(what, NULL);
4109 if (p == NULL || *p == NUL)
4110 p = (char_u *)"Unknown";
4111 smsg((char_u *)_("Current %slanguage: \"%s\""), whatstr, p);
4113 else
4115 #ifndef LC_MESSAGES
4116 if (what == VIM_LC_MESSAGES)
4117 loc = "";
4118 else
4119 #endif
4121 loc = setlocale(what, (char *)name);
4122 #if defined(FEAT_FLOAT) && defined(LC_NUMERIC)
4123 /* Make sure strtod() uses a decimal point, not a comma. */
4124 setlocale(LC_NUMERIC, "C");
4125 #endif
4127 if (loc == NULL)
4128 EMSG2(_("E197: Cannot set language to \"%s\""), name);
4129 else
4131 #ifdef HAVE_NL_MSG_CAT_CNTR
4132 /* Need to do this for GNU gettext, otherwise cached translations
4133 * will be used again. */
4134 extern int _nl_msg_cat_cntr;
4136 ++_nl_msg_cat_cntr;
4137 #endif
4138 /* Reset $LC_ALL, otherwise it would overrule everything. */
4139 vim_setenv((char_u *)"LC_ALL", (char_u *)"");
4141 if (what != LC_TIME)
4143 /* Tell gettext() what to translate to. It apparently doesn't
4144 * use the currently effective locale. Also do this when
4145 * FEAT_GETTEXT isn't defined, so that shell commands use this
4146 * value. */
4147 if (what == LC_ALL)
4149 vim_setenv((char_u *)"LANG", name);
4150 # ifdef WIN32
4151 /* Apparently MS-Windows printf() may cause a crash when
4152 * we give it 8-bit text while it's expecting text in the
4153 * current locale. This call avoids that. */
4154 setlocale(LC_CTYPE, "C");
4155 # endif
4157 if (what != LC_CTYPE)
4159 char_u *mname;
4160 #ifdef WIN32
4161 mname = gettext_lang(name);
4162 #else
4163 mname = name;
4164 #endif
4165 vim_setenv((char_u *)"LC_MESSAGES", mname);
4166 #ifdef FEAT_MULTI_LANG
4167 set_helplang_default(mname);
4168 #endif
4171 /* Set $LC_CTYPE, because it overrules $LANG, and
4172 * gtk_set_locale() calls setlocale() again. gnome_init()
4173 * sets $LC_CTYPE to "en_US" (that's a bug!). */
4174 if (what != VIM_LC_MESSAGES)
4175 vim_setenv((char_u *)"LC_CTYPE", name);
4176 # ifdef FEAT_GUI_GTK
4177 /* Let GTK know what locale we're using. Not sure this is
4178 * really needed... */
4179 if (gui.in_use)
4180 (void)gtk_set_locale();
4181 # endif
4184 # ifdef FEAT_EVAL
4185 /* Set v:lang, v:lc_time and v:ctype to the final result. */
4186 set_lang_var();
4187 # endif
4192 # if defined(FEAT_CMDL_COMPL) || defined(PROTO)
4194 * Function given to ExpandGeneric() to obtain the possible arguments of the
4195 * ":language" command.
4197 char_u *
4198 get_lang_arg(xp, idx)
4199 expand_T *xp UNUSED;
4200 int idx;
4202 if (idx == 0)
4203 return (char_u *)"messages";
4204 if (idx == 1)
4205 return (char_u *)"ctype";
4206 if (idx == 2)
4207 return (char_u *)"time";
4208 return NULL;
4210 # endif
4212 #endif