Merged from the latest developing branch.
[MacVim/KaoriYa.git] / src / ex_cmds2.c
blob884220ef35e0736e2f682936ad51b825a7821c0b
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(WIN32) && defined(FEAT_CSCOPE)
15 # include "vimio.h"
16 #endif
18 #include "vim.h"
20 #if defined(WIN32) && defined(FEAT_CSCOPE)
21 # include <fcntl.h>
22 #endif
24 #include "version.h"
26 static void cmd_source __ARGS((char_u *fname, exarg_T *eap));
28 #ifdef FEAT_EVAL
29 /* Growarray to store info about already sourced scripts.
30 * For Unix also store the dev/ino, so that we don't have to stat() each
31 * script when going through the list. */
32 typedef struct scriptitem_S
34 char_u *sn_name;
35 # ifdef UNIX
36 int sn_dev;
37 ino_t sn_ino;
38 # endif
39 # ifdef FEAT_PROFILE
40 int sn_prof_on; /* TRUE when script is/was profiled */
41 int sn_pr_force; /* forceit: profile functions in this script */
42 proftime_T sn_pr_child; /* time set when going into first child */
43 int sn_pr_nest; /* nesting for sn_pr_child */
44 /* profiling the script as a whole */
45 int sn_pr_count; /* nr of times sourced */
46 proftime_T sn_pr_total; /* time spend in script + children */
47 proftime_T sn_pr_self; /* time spend in script itself */
48 proftime_T sn_pr_start; /* time at script start */
49 proftime_T sn_pr_children; /* time in children after script start */
50 /* profiling the script per line */
51 garray_T sn_prl_ga; /* things stored for every line */
52 proftime_T sn_prl_start; /* start time for current line */
53 proftime_T sn_prl_children; /* time spent in children for this line */
54 proftime_T sn_prl_wait; /* wait start time for current line */
55 int sn_prl_idx; /* index of line being timed; -1 if none */
56 int sn_prl_execed; /* line being timed was executed */
57 # endif
58 } scriptitem_T;
60 static garray_T script_items = {0, 0, sizeof(scriptitem_T), 4, NULL};
61 #define SCRIPT_ITEM(id) (((scriptitem_T *)script_items.ga_data)[(id) - 1])
63 # ifdef FEAT_PROFILE
64 /* Struct used in sn_prl_ga for every line of a script. */
65 typedef struct sn_prl_S
67 int snp_count; /* nr of times line was executed */
68 proftime_T sn_prl_total; /* time spend in a line + children */
69 proftime_T sn_prl_self; /* time spend in a line itself */
70 } sn_prl_T;
72 # define PRL_ITEM(si, idx) (((sn_prl_T *)(si)->sn_prl_ga.ga_data)[(idx)])
73 # endif
74 #endif
76 #if defined(FEAT_EVAL) || defined(PROTO)
77 static int debug_greedy = FALSE; /* batch mode debugging: don't save
78 and restore typeahead. */
81 * do_debug(): Debug mode.
82 * Repeatedly get Ex commands, until told to continue normal execution.
84 void
85 do_debug(cmd)
86 char_u *cmd;
88 int save_msg_scroll = msg_scroll;
89 int save_State = State;
90 int save_did_emsg = did_emsg;
91 int save_cmd_silent = cmd_silent;
92 int save_msg_silent = msg_silent;
93 int save_emsg_silent = emsg_silent;
94 int save_redir_off = redir_off;
95 tasave_T typeaheadbuf;
96 int typeahead_saved = FALSE;
97 int save_ignore_script;
98 # ifdef FEAT_EX_EXTRA
99 int save_ex_normal_busy;
100 # endif
101 int n;
102 char_u *cmdline = NULL;
103 char_u *p;
104 char *tail = NULL;
105 static int last_cmd = 0;
106 #define CMD_CONT 1
107 #define CMD_NEXT 2
108 #define CMD_STEP 3
109 #define CMD_FINISH 4
110 #define CMD_QUIT 5
111 #define CMD_INTERRUPT 6
113 #ifdef ALWAYS_USE_GUI
114 /* Can't do this when there is no terminal for input/output. */
115 if (!gui.in_use)
117 /* Break as soon as possible. */
118 debug_break_level = 9999;
119 return;
121 #endif
123 /* Make sure we are in raw mode and start termcap mode. Might have side
124 * effects... */
125 settmode(TMODE_RAW);
126 starttermcap();
128 ++RedrawingDisabled; /* don't redisplay the window */
129 ++no_wait_return; /* don't wait for return */
130 did_emsg = FALSE; /* don't use error from debugged stuff */
131 cmd_silent = FALSE; /* display commands */
132 msg_silent = FALSE; /* display messages */
133 emsg_silent = FALSE; /* display error messages */
134 redir_off = TRUE; /* don't redirect debug commands */
136 State = NORMAL;
137 #ifdef FEAT_SNIFF
138 want_sniff_request = 0; /* No K_SNIFF wanted */
139 #endif
141 if (!debug_did_msg)
142 MSG(_("Entering Debug mode. Type \"cont\" to continue."));
143 if (sourcing_name != NULL)
144 msg(sourcing_name);
145 if (sourcing_lnum != 0)
146 smsg((char_u *)_("line %ld: %s"), (long)sourcing_lnum, cmd);
147 else
148 smsg((char_u *)_("cmd: %s"), cmd);
151 * Repeat getting a command and executing it.
153 for (;;)
155 msg_scroll = TRUE;
156 need_wait_return = FALSE;
157 #ifdef FEAT_SNIFF
158 ProcessSniffRequests();
159 #endif
160 /* Save the current typeahead buffer and replace it with an empty one.
161 * This makes sure we get input from the user here and don't interfere
162 * with the commands being executed. Reset "ex_normal_busy" to avoid
163 * the side effects of using ":normal". Save the stuff buffer and make
164 * it empty. Set ignore_script to avoid reading from script input. */
165 # ifdef FEAT_EX_EXTRA
166 save_ex_normal_busy = ex_normal_busy;
167 ex_normal_busy = 0;
168 # endif
169 if (!debug_greedy)
171 save_typeahead(&typeaheadbuf);
172 typeahead_saved = TRUE;
173 save_ignore_script = ignore_script;
174 ignore_script = TRUE;
177 cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL);
179 if (typeahead_saved)
181 restore_typeahead(&typeaheadbuf);
182 ignore_script = save_ignore_script;
184 # ifdef FEAT_EX_EXTRA
185 ex_normal_busy = save_ex_normal_busy;
186 # endif
188 cmdline_row = msg_row;
189 if (cmdline != NULL)
191 /* If this is a debug command, set "last_cmd".
192 * If not, reset "last_cmd".
193 * For a blank line use previous command. */
194 p = skipwhite(cmdline);
195 if (*p != NUL)
197 switch (*p)
199 case 'c': last_cmd = CMD_CONT;
200 tail = "ont";
201 break;
202 case 'n': last_cmd = CMD_NEXT;
203 tail = "ext";
204 break;
205 case 's': last_cmd = CMD_STEP;
206 tail = "tep";
207 break;
208 case 'f': last_cmd = CMD_FINISH;
209 tail = "inish";
210 break;
211 case 'q': last_cmd = CMD_QUIT;
212 tail = "uit";
213 break;
214 case 'i': last_cmd = CMD_INTERRUPT;
215 tail = "nterrupt";
216 break;
217 default: last_cmd = 0;
219 if (last_cmd != 0)
221 /* Check that the tail matches. */
222 ++p;
223 while (*p != NUL && *p == *tail)
225 ++p;
226 ++tail;
228 if (ASCII_ISALPHA(*p))
229 last_cmd = 0;
233 if (last_cmd != 0)
235 /* Execute debug command: decided where to break next and
236 * return. */
237 switch (last_cmd)
239 case CMD_CONT:
240 debug_break_level = -1;
241 break;
242 case CMD_NEXT:
243 debug_break_level = ex_nesting_level;
244 break;
245 case CMD_STEP:
246 debug_break_level = 9999;
247 break;
248 case CMD_FINISH:
249 debug_break_level = ex_nesting_level - 1;
250 break;
251 case CMD_QUIT:
252 got_int = TRUE;
253 debug_break_level = -1;
254 break;
255 case CMD_INTERRUPT:
256 got_int = TRUE;
257 debug_break_level = 9999;
258 /* Do not repeat ">interrupt" cmd, continue stepping. */
259 last_cmd = CMD_STEP;
260 break;
262 break;
265 /* don't debug this command */
266 n = debug_break_level;
267 debug_break_level = -1;
268 (void)do_cmdline(cmdline, getexline, NULL,
269 DOCMD_VERBOSE|DOCMD_EXCRESET);
270 debug_break_level = n;
272 vim_free(cmdline);
274 lines_left = Rows - 1;
276 vim_free(cmdline);
278 --RedrawingDisabled;
279 --no_wait_return;
280 redraw_all_later(NOT_VALID);
281 need_wait_return = FALSE;
282 msg_scroll = save_msg_scroll;
283 lines_left = Rows - 1;
284 State = save_State;
285 did_emsg = save_did_emsg;
286 cmd_silent = save_cmd_silent;
287 msg_silent = save_msg_silent;
288 emsg_silent = save_emsg_silent;
289 redir_off = save_redir_off;
291 /* Only print the message again when typing a command before coming back
292 * here. */
293 debug_did_msg = TRUE;
297 * ":debug".
299 void
300 ex_debug(eap)
301 exarg_T *eap;
303 int debug_break_level_save = debug_break_level;
305 debug_break_level = 9999;
306 do_cmdline_cmd(eap->arg);
307 debug_break_level = debug_break_level_save;
310 static char_u *debug_breakpoint_name = NULL;
311 static linenr_T debug_breakpoint_lnum;
314 * When debugging or a breakpoint is set on a skipped command, no debug prompt
315 * is shown by do_one_cmd(). This situation is indicated by debug_skipped, and
316 * debug_skipped_name is then set to the source name in the breakpoint case. If
317 * a skipped command decides itself that a debug prompt should be displayed, it
318 * can do so by calling dbg_check_skipped().
320 static int debug_skipped;
321 static char_u *debug_skipped_name;
324 * Go to debug mode when a breakpoint was encountered or "ex_nesting_level" is
325 * at or below the break level. But only when the line is actually
326 * executed. Return TRUE and set breakpoint_name for skipped commands that
327 * decide to execute something themselves.
328 * Called from do_one_cmd() before executing a command.
330 void
331 dbg_check_breakpoint(eap)
332 exarg_T *eap;
334 char_u *p;
336 debug_skipped = FALSE;
337 if (debug_breakpoint_name != NULL)
339 if (!eap->skip)
341 /* replace K_SNR with "<SNR>" */
342 if (debug_breakpoint_name[0] == K_SPECIAL
343 && debug_breakpoint_name[1] == KS_EXTRA
344 && debug_breakpoint_name[2] == (int)KE_SNR)
345 p = (char_u *)"<SNR>";
346 else
347 p = (char_u *)"";
348 smsg((char_u *)_("Breakpoint in \"%s%s\" line %ld"),
350 debug_breakpoint_name + (*p == NUL ? 0 : 3),
351 (long)debug_breakpoint_lnum);
352 debug_breakpoint_name = NULL;
353 do_debug(eap->cmd);
355 else
357 debug_skipped = TRUE;
358 debug_skipped_name = debug_breakpoint_name;
359 debug_breakpoint_name = NULL;
362 else if (ex_nesting_level <= debug_break_level)
364 if (!eap->skip)
365 do_debug(eap->cmd);
366 else
368 debug_skipped = TRUE;
369 debug_skipped_name = NULL;
375 * Go to debug mode if skipped by dbg_check_breakpoint() because eap->skip was
376 * set. Return TRUE when the debug mode is entered this time.
379 dbg_check_skipped(eap)
380 exarg_T *eap;
382 int prev_got_int;
384 if (debug_skipped)
387 * Save the value of got_int and reset it. We don't want a previous
388 * interruption cause flushing the input buffer.
390 prev_got_int = got_int;
391 got_int = FALSE;
392 debug_breakpoint_name = debug_skipped_name;
393 /* eap->skip is TRUE */
394 eap->skip = FALSE;
395 (void)dbg_check_breakpoint(eap);
396 eap->skip = TRUE;
397 got_int |= prev_got_int;
398 return TRUE;
400 return FALSE;
404 * The list of breakpoints: dbg_breakp.
405 * This is a grow-array of structs.
407 struct debuggy
409 int dbg_nr; /* breakpoint number */
410 int dbg_type; /* DBG_FUNC or DBG_FILE */
411 char_u *dbg_name; /* function or file name */
412 regprog_T *dbg_prog; /* regexp program */
413 linenr_T dbg_lnum; /* line number in function or file */
414 int dbg_forceit; /* ! used */
417 static garray_T dbg_breakp = {0, 0, sizeof(struct debuggy), 4, NULL};
418 #define BREAKP(idx) (((struct debuggy *)dbg_breakp.ga_data)[idx])
419 #define DEBUGGY(gap, idx) (((struct debuggy *)gap->ga_data)[idx])
420 static int last_breakp = 0; /* nr of last defined breakpoint */
422 #ifdef FEAT_PROFILE
423 /* Profiling uses file and func names similar to breakpoints. */
424 static garray_T prof_ga = {0, 0, sizeof(struct debuggy), 4, NULL};
425 #endif
426 #define DBG_FUNC 1
427 #define DBG_FILE 2
429 static int dbg_parsearg __ARGS((char_u *arg, garray_T *gap));
430 static linenr_T debuggy_find __ARGS((int file,char_u *fname, linenr_T after, garray_T *gap, int *fp));
433 * Parse the arguments of ":profile", ":breakadd" or ":breakdel" and put them
434 * in the entry just after the last one in dbg_breakp. Note that "dbg_name"
435 * is allocated.
436 * Returns FAIL for failure.
438 static int
439 dbg_parsearg(arg, gap)
440 char_u *arg;
441 garray_T *gap; /* either &dbg_breakp or &prof_ga */
443 char_u *p = arg;
444 char_u *q;
445 struct debuggy *bp;
446 int here = FALSE;
448 if (ga_grow(gap, 1) == FAIL)
449 return FAIL;
450 bp = &DEBUGGY(gap, gap->ga_len);
452 /* Find "func" or "file". */
453 if (STRNCMP(p, "func", 4) == 0)
454 bp->dbg_type = DBG_FUNC;
455 else if (STRNCMP(p, "file", 4) == 0)
456 bp->dbg_type = DBG_FILE;
457 else if (
458 #ifdef FEAT_PROFILE
459 gap != &prof_ga &&
460 #endif
461 STRNCMP(p, "here", 4) == 0)
463 if (curbuf->b_ffname == NULL)
465 EMSG(_(e_noname));
466 return FAIL;
468 bp->dbg_type = DBG_FILE;
469 here = TRUE;
471 else
473 EMSG2(_(e_invarg2), p);
474 return FAIL;
476 p = skipwhite(p + 4);
478 /* Find optional line number. */
479 if (here)
480 bp->dbg_lnum = curwin->w_cursor.lnum;
481 else if (
482 #ifdef FEAT_PROFILE
483 gap != &prof_ga &&
484 #endif
485 VIM_ISDIGIT(*p))
487 bp->dbg_lnum = getdigits(&p);
488 p = skipwhite(p);
490 else
491 bp->dbg_lnum = 0;
493 /* Find the function or file name. Don't accept a function name with (). */
494 if ((!here && *p == NUL)
495 || (here && *p != NUL)
496 || (bp->dbg_type == DBG_FUNC && strstr((char *)p, "()") != NULL))
498 EMSG2(_(e_invarg2), arg);
499 return FAIL;
502 if (bp->dbg_type == DBG_FUNC)
503 bp->dbg_name = vim_strsave(p);
504 else if (here)
505 bp->dbg_name = vim_strsave(curbuf->b_ffname);
506 else
508 /* Expand the file name in the same way as do_source(). This means
509 * doing it twice, so that $DIR/file gets expanded when $DIR is
510 * "~/dir". */
511 #ifdef RISCOS
512 q = mch_munge_fname(p);
513 #else
514 q = expand_env_save(p);
515 #endif
516 if (q == NULL)
517 return FAIL;
518 #ifdef RISCOS
519 p = mch_munge_fname(q);
520 #else
521 p = expand_env_save(q);
522 #endif
523 vim_free(q);
524 if (p == NULL)
525 return FAIL;
526 if (*p != '*')
528 bp->dbg_name = fix_fname(p);
529 vim_free(p);
531 else
532 bp->dbg_name = p;
535 if (bp->dbg_name == NULL)
536 return FAIL;
537 return OK;
541 * ":breakadd".
543 void
544 ex_breakadd(eap)
545 exarg_T *eap;
547 struct debuggy *bp;
548 char_u *pat;
549 garray_T *gap;
551 gap = &dbg_breakp;
552 #ifdef FEAT_PROFILE
553 if (eap->cmdidx == CMD_profile)
554 gap = &prof_ga;
555 #endif
557 if (dbg_parsearg(eap->arg, gap) == OK)
559 bp = &DEBUGGY(gap, gap->ga_len);
560 bp->dbg_forceit = eap->forceit;
562 pat = file_pat_to_reg_pat(bp->dbg_name, NULL, NULL, FALSE);
563 if (pat != NULL)
565 bp->dbg_prog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
566 vim_free(pat);
568 if (pat == NULL || bp->dbg_prog == NULL)
569 vim_free(bp->dbg_name);
570 else
572 if (bp->dbg_lnum == 0) /* default line number is 1 */
573 bp->dbg_lnum = 1;
574 #ifdef FEAT_PROFILE
575 if (eap->cmdidx != CMD_profile)
576 #endif
578 DEBUGGY(gap, gap->ga_len).dbg_nr = ++last_breakp;
579 ++debug_tick;
581 ++gap->ga_len;
587 * ":debuggreedy".
589 void
590 ex_debuggreedy(eap)
591 exarg_T *eap;
593 if (eap->addr_count == 0 || eap->line2 != 0)
594 debug_greedy = TRUE;
595 else
596 debug_greedy = FALSE;
600 * ":breakdel" and ":profdel".
602 void
603 ex_breakdel(eap)
604 exarg_T *eap;
606 struct debuggy *bp, *bpi;
607 int nr;
608 int todel = -1;
609 int del_all = FALSE;
610 int i;
611 linenr_T best_lnum = 0;
612 garray_T *gap;
614 gap = &dbg_breakp;
615 #ifdef FEAT_PROFILE
616 if (eap->cmdidx == CMD_profdel)
617 gap = &prof_ga;
618 #endif
620 if (vim_isdigit(*eap->arg))
622 /* ":breakdel {nr}" */
623 nr = atol((char *)eap->arg);
624 for (i = 0; i < gap->ga_len; ++i)
625 if (DEBUGGY(gap, i).dbg_nr == nr)
627 todel = i;
628 break;
631 else if (*eap->arg == '*')
633 todel = 0;
634 del_all = TRUE;
636 else
638 /* ":breakdel {func|file} [lnum] {name}" */
639 if (dbg_parsearg(eap->arg, gap) == FAIL)
640 return;
641 bp = &DEBUGGY(gap, gap->ga_len);
642 for (i = 0; i < gap->ga_len; ++i)
644 bpi = &DEBUGGY(gap, i);
645 if (bp->dbg_type == bpi->dbg_type
646 && STRCMP(bp->dbg_name, bpi->dbg_name) == 0
647 && (bp->dbg_lnum == bpi->dbg_lnum
648 || (bp->dbg_lnum == 0
649 && (best_lnum == 0
650 || bpi->dbg_lnum < best_lnum))))
652 todel = i;
653 best_lnum = bpi->dbg_lnum;
656 vim_free(bp->dbg_name);
659 if (todel < 0)
660 EMSG2(_("E161: Breakpoint not found: %s"), eap->arg);
661 else
663 while (gap->ga_len > 0)
665 vim_free(DEBUGGY(gap, todel).dbg_name);
666 vim_free(DEBUGGY(gap, todel).dbg_prog);
667 --gap->ga_len;
668 if (todel < gap->ga_len)
669 mch_memmove(&DEBUGGY(gap, todel), &DEBUGGY(gap, todel + 1),
670 (gap->ga_len - todel) * sizeof(struct debuggy));
671 #ifdef FEAT_PROFILE
672 if (eap->cmdidx == CMD_breakdel)
673 #endif
674 ++debug_tick;
675 if (!del_all)
676 break;
679 /* If all breakpoints were removed clear the array. */
680 if (gap->ga_len == 0)
681 ga_clear(gap);
686 * ":breaklist".
688 /*ARGSUSED*/
689 void
690 ex_breaklist(eap)
691 exarg_T *eap;
693 struct debuggy *bp;
694 int i;
696 if (dbg_breakp.ga_len == 0)
697 MSG(_("No breakpoints defined"));
698 else
699 for (i = 0; i < dbg_breakp.ga_len; ++i)
701 bp = &BREAKP(i);
702 smsg((char_u *)_("%3d %s %s line %ld"),
703 bp->dbg_nr,
704 bp->dbg_type == DBG_FUNC ? "func" : "file",
705 bp->dbg_name,
706 (long)bp->dbg_lnum);
711 * Find a breakpoint for a function or sourced file.
712 * Returns line number at which to break; zero when no matching breakpoint.
714 linenr_T
715 dbg_find_breakpoint(file, fname, after)
716 int file; /* TRUE for a file, FALSE for a function */
717 char_u *fname; /* file or function name */
718 linenr_T after; /* after this line number */
720 return debuggy_find(file, fname, after, &dbg_breakp, NULL);
723 #if defined(FEAT_PROFILE) || defined(PROTO)
725 * Return TRUE if profiling is on for a function or sourced file.
728 has_profiling(file, fname, fp)
729 int file; /* TRUE for a file, FALSE for a function */
730 char_u *fname; /* file or function name */
731 int *fp; /* return: forceit */
733 return (debuggy_find(file, fname, (linenr_T)0, &prof_ga, fp)
734 != (linenr_T)0);
736 #endif
739 * Common code for dbg_find_breakpoint() and has_profiling().
741 static linenr_T
742 debuggy_find(file, fname, after, gap, fp)
743 int file; /* TRUE for a file, FALSE for a function */
744 char_u *fname; /* file or function name */
745 linenr_T after; /* after this line number */
746 garray_T *gap; /* either &dbg_breakp or &prof_ga */
747 int *fp; /* if not NULL: return forceit */
749 struct debuggy *bp;
750 int i;
751 linenr_T lnum = 0;
752 regmatch_T regmatch;
753 char_u *name = fname;
754 int prev_got_int;
756 /* Return quickly when there are no breakpoints. */
757 if (gap->ga_len == 0)
758 return (linenr_T)0;
760 /* Replace K_SNR in function name with "<SNR>". */
761 if (!file && fname[0] == K_SPECIAL)
763 name = alloc((unsigned)STRLEN(fname) + 3);
764 if (name == NULL)
765 name = fname;
766 else
768 STRCPY(name, "<SNR>");
769 STRCPY(name + 5, fname + 3);
773 for (i = 0; i < gap->ga_len; ++i)
775 /* Skip entries that are not useful or are for a line that is beyond
776 * an already found breakpoint. */
777 bp = &DEBUGGY(gap, i);
778 if (((bp->dbg_type == DBG_FILE) == file && (
779 #ifdef FEAT_PROFILE
780 gap == &prof_ga ||
781 #endif
782 (bp->dbg_lnum > after && (lnum == 0 || bp->dbg_lnum < lnum)))))
784 regmatch.regprog = bp->dbg_prog;
785 regmatch.rm_ic = FALSE;
787 * Save the value of got_int and reset it. We don't want a
788 * previous interruption cancel matching, only hitting CTRL-C
789 * while matching should abort it.
791 prev_got_int = got_int;
792 got_int = FALSE;
793 if (vim_regexec(&regmatch, name, (colnr_T)0))
795 lnum = bp->dbg_lnum;
796 if (fp != NULL)
797 *fp = bp->dbg_forceit;
799 got_int |= prev_got_int;
802 if (name != fname)
803 vim_free(name);
805 return lnum;
809 * Called when a breakpoint was encountered.
811 void
812 dbg_breakpoint(name, lnum)
813 char_u *name;
814 linenr_T lnum;
816 /* We need to check if this line is actually executed in do_one_cmd() */
817 debug_breakpoint_name = name;
818 debug_breakpoint_lnum = lnum;
822 # if defined(FEAT_PROFILE) || defined(FEAT_RELTIME) || defined(PROTO)
824 * Store the current time in "tm".
826 void
827 profile_start(tm)
828 proftime_T *tm;
830 # ifdef WIN3264
831 QueryPerformanceCounter(tm);
832 # else
833 gettimeofday(tm, NULL);
834 # endif
838 * Compute the elapsed time from "tm" till now and store in "tm".
840 void
841 profile_end(tm)
842 proftime_T *tm;
844 proftime_T now;
846 # ifdef WIN3264
847 QueryPerformanceCounter(&now);
848 tm->QuadPart = now.QuadPart - tm->QuadPart;
849 # else
850 gettimeofday(&now, NULL);
851 tm->tv_usec = now.tv_usec - tm->tv_usec;
852 tm->tv_sec = now.tv_sec - tm->tv_sec;
853 if (tm->tv_usec < 0)
855 tm->tv_usec += 1000000;
856 --tm->tv_sec;
858 # endif
862 * Subtract the time "tm2" from "tm".
864 void
865 profile_sub(tm, tm2)
866 proftime_T *tm, *tm2;
868 # ifdef WIN3264
869 tm->QuadPart -= tm2->QuadPart;
870 # else
871 tm->tv_usec -= tm2->tv_usec;
872 tm->tv_sec -= tm2->tv_sec;
873 if (tm->tv_usec < 0)
875 tm->tv_usec += 1000000;
876 --tm->tv_sec;
878 # endif
882 * Return a string that represents the time in "tm".
883 * Uses a static buffer!
885 char *
886 profile_msg(tm)
887 proftime_T *tm;
889 static char buf[50];
891 # ifdef WIN3264
892 LARGE_INTEGER fr;
894 QueryPerformanceFrequency(&fr);
895 sprintf(buf, "%10.6lf", (double)tm->QuadPart / (double)fr.QuadPart);
896 # else
897 sprintf(buf, "%3ld.%06ld", (long)tm->tv_sec, (long)tm->tv_usec);
898 #endif
899 return buf;
902 # endif /* FEAT_PROFILE || FEAT_RELTIME */
904 # if defined(FEAT_PROFILE) || defined(PROTO)
906 * Functions for profiling.
908 static void script_do_profile __ARGS((scriptitem_T *si));
909 static void script_dump_profile __ARGS((FILE *fd));
910 static proftime_T prof_wait_time;
913 * Set the time in "tm" to zero.
915 void
916 profile_zero(tm)
917 proftime_T *tm;
919 # ifdef WIN3264
920 tm->QuadPart = 0;
921 # else
922 tm->tv_usec = 0;
923 tm->tv_sec = 0;
924 # endif
928 * Add the time "tm2" to "tm".
930 void
931 profile_add(tm, tm2)
932 proftime_T *tm, *tm2;
934 # ifdef WIN3264
935 tm->QuadPart += tm2->QuadPart;
936 # else
937 tm->tv_usec += tm2->tv_usec;
938 tm->tv_sec += tm2->tv_sec;
939 if (tm->tv_usec >= 1000000)
941 tm->tv_usec -= 1000000;
942 ++tm->tv_sec;
944 # endif
948 * Add the "self" time from the total time and the children's time.
950 void
951 profile_self(self, total, children)
952 proftime_T *self, *total, *children;
954 /* Check that the result won't be negative. Can happen with recursive
955 * calls. */
956 #ifdef WIN3264
957 if (total->QuadPart <= children->QuadPart)
958 return;
959 #else
960 if (total->tv_sec < children->tv_sec
961 || (total->tv_sec == children->tv_sec
962 && total->tv_usec <= children->tv_usec))
963 return;
964 #endif
965 profile_add(self, total);
966 profile_sub(self, children);
970 * Get the current waittime.
972 void
973 profile_get_wait(tm)
974 proftime_T *tm;
976 *tm = prof_wait_time;
980 * Subtract the passed waittime since "tm" from "tma".
982 void
983 profile_sub_wait(tm, tma)
984 proftime_T *tm, *tma;
986 proftime_T tm3 = prof_wait_time;
988 profile_sub(&tm3, tm);
989 profile_sub(tma, &tm3);
993 * Return TRUE if "tm1" and "tm2" are equal.
996 profile_equal(tm1, tm2)
997 proftime_T *tm1, *tm2;
999 # ifdef WIN3264
1000 return (tm1->QuadPart == tm2->QuadPart);
1001 # else
1002 return (tm1->tv_usec == tm2->tv_usec && tm1->tv_sec == tm2->tv_sec);
1003 # endif
1007 * Return <0, 0 or >0 if "tm1" < "tm2", "tm1" == "tm2" or "tm1" > "tm2"
1010 profile_cmp(tm1, tm2)
1011 proftime_T *tm1, *tm2;
1013 # ifdef WIN3264
1014 return (int)(tm2->QuadPart - tm1->QuadPart);
1015 # else
1016 if (tm1->tv_sec == tm2->tv_sec)
1017 return tm2->tv_usec - tm1->tv_usec;
1018 return tm2->tv_sec - tm1->tv_sec;
1019 # endif
1022 static char_u *profile_fname = NULL;
1023 static proftime_T pause_time;
1026 * ":profile cmd args"
1028 void
1029 ex_profile(eap)
1030 exarg_T *eap;
1032 char_u *e;
1033 int len;
1035 e = skiptowhite(eap->arg);
1036 len = (int)(e - eap->arg);
1037 e = skipwhite(e);
1039 if (len == 5 && STRNCMP(eap->arg, "start", 5) == 0 && *e != NUL)
1041 vim_free(profile_fname);
1042 profile_fname = vim_strsave(e);
1043 do_profiling = PROF_YES;
1044 profile_zero(&prof_wait_time);
1045 set_vim_var_nr(VV_PROFILING, 1L);
1047 else if (do_profiling == PROF_NONE)
1048 EMSG(_("E750: First use :profile start <fname>"));
1049 else if (STRCMP(eap->arg, "pause") == 0)
1051 if (do_profiling == PROF_YES)
1052 profile_start(&pause_time);
1053 do_profiling = PROF_PAUSED;
1055 else if (STRCMP(eap->arg, "continue") == 0)
1057 if (do_profiling == PROF_PAUSED)
1059 profile_end(&pause_time);
1060 profile_add(&prof_wait_time, &pause_time);
1062 do_profiling = PROF_YES;
1064 else
1066 /* The rest is similar to ":breakadd". */
1067 ex_breakadd(eap);
1072 * Dump the profiling info.
1074 void
1075 profile_dump()
1077 FILE *fd;
1079 if (profile_fname != NULL)
1081 fd = mch_fopen((char *)profile_fname, "w");
1082 if (fd == NULL)
1083 EMSG2(_(e_notopen), profile_fname);
1084 else
1086 script_dump_profile(fd);
1087 func_dump_profile(fd);
1088 fclose(fd);
1094 * Start profiling script "fp".
1096 static void
1097 script_do_profile(si)
1098 scriptitem_T *si;
1100 si->sn_pr_count = 0;
1101 profile_zero(&si->sn_pr_total);
1102 profile_zero(&si->sn_pr_self);
1104 ga_init2(&si->sn_prl_ga, sizeof(sn_prl_T), 100);
1105 si->sn_prl_idx = -1;
1106 si->sn_prof_on = TRUE;
1107 si->sn_pr_nest = 0;
1111 * save time when starting to invoke another script or function.
1113 void
1114 script_prof_save(tm)
1115 proftime_T *tm; /* place to store wait time */
1117 scriptitem_T *si;
1119 if (current_SID > 0 && current_SID <= script_items.ga_len)
1121 si = &SCRIPT_ITEM(current_SID);
1122 if (si->sn_prof_on && si->sn_pr_nest++ == 0)
1123 profile_start(&si->sn_pr_child);
1125 profile_get_wait(tm);
1129 * Count time spent in children after invoking another script or function.
1131 void
1132 script_prof_restore(tm)
1133 proftime_T *tm;
1135 scriptitem_T *si;
1137 if (current_SID > 0 && current_SID <= script_items.ga_len)
1139 si = &SCRIPT_ITEM(current_SID);
1140 if (si->sn_prof_on && --si->sn_pr_nest == 0)
1142 profile_end(&si->sn_pr_child);
1143 profile_sub_wait(tm, &si->sn_pr_child); /* don't count wait time */
1144 profile_add(&si->sn_pr_children, &si->sn_pr_child);
1145 profile_add(&si->sn_prl_children, &si->sn_pr_child);
1150 static proftime_T inchar_time;
1153 * Called when starting to wait for the user to type a character.
1155 void
1156 prof_inchar_enter()
1158 profile_start(&inchar_time);
1162 * Called when finished waiting for the user to type a character.
1164 void
1165 prof_inchar_exit()
1167 profile_end(&inchar_time);
1168 profile_add(&prof_wait_time, &inchar_time);
1172 * Dump the profiling results for all scripts in file "fd".
1174 static void
1175 script_dump_profile(fd)
1176 FILE *fd;
1178 int id;
1179 scriptitem_T *si;
1180 int i;
1181 FILE *sfd;
1182 sn_prl_T *pp;
1184 for (id = 1; id <= script_items.ga_len; ++id)
1186 si = &SCRIPT_ITEM(id);
1187 if (si->sn_prof_on)
1189 fprintf(fd, "SCRIPT %s\n", si->sn_name);
1190 if (si->sn_pr_count == 1)
1191 fprintf(fd, "Sourced 1 time\n");
1192 else
1193 fprintf(fd, "Sourced %d times\n", si->sn_pr_count);
1194 fprintf(fd, "Total time: %s\n", profile_msg(&si->sn_pr_total));
1195 fprintf(fd, " Self time: %s\n", profile_msg(&si->sn_pr_self));
1196 fprintf(fd, "\n");
1197 fprintf(fd, "count total (s) self (s)\n");
1199 sfd = mch_fopen((char *)si->sn_name, "r");
1200 if (sfd == NULL)
1201 fprintf(fd, "Cannot open file!\n");
1202 else
1204 for (i = 0; i < si->sn_prl_ga.ga_len; ++i)
1206 if (vim_fgets(IObuff, IOSIZE, sfd))
1207 break;
1208 pp = &PRL_ITEM(si, i);
1209 if (pp->snp_count > 0)
1211 fprintf(fd, "%5d ", pp->snp_count);
1212 if (profile_equal(&pp->sn_prl_total, &pp->sn_prl_self))
1213 fprintf(fd, " ");
1214 else
1215 fprintf(fd, "%s ", profile_msg(&pp->sn_prl_total));
1216 fprintf(fd, "%s ", profile_msg(&pp->sn_prl_self));
1218 else
1219 fprintf(fd, " ");
1220 fprintf(fd, "%s", IObuff);
1222 fclose(sfd);
1224 fprintf(fd, "\n");
1230 * Return TRUE when a function defined in the current script should be
1231 * profiled.
1234 prof_def_func()
1236 if (current_SID > 0)
1237 return SCRIPT_ITEM(current_SID).sn_pr_force;
1238 return FALSE;
1241 # endif
1242 #endif
1245 * If 'autowrite' option set, try to write the file.
1246 * Careful: autocommands may make "buf" invalid!
1248 * return FAIL for failure, OK otherwise
1251 autowrite(buf, forceit)
1252 buf_T *buf;
1253 int forceit;
1255 int r;
1257 if (!(p_aw || p_awa) || !p_write
1258 #ifdef FEAT_QUICKFIX
1259 /* never autowrite a "nofile" or "nowrite" buffer */
1260 || bt_dontwrite(buf)
1261 #endif
1262 || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL)
1263 return FAIL;
1264 r = buf_write_all(buf, forceit);
1266 /* Writing may succeed but the buffer still changed, e.g., when there is a
1267 * conversion error. We do want to return FAIL then. */
1268 if (buf_valid(buf) && bufIsChanged(buf))
1269 r = FAIL;
1270 return r;
1274 * flush all buffers, except the ones that are readonly
1276 void
1277 autowrite_all()
1279 buf_T *buf;
1281 if (!(p_aw || p_awa) || !p_write)
1282 return;
1283 for (buf = firstbuf; buf; buf = buf->b_next)
1284 if (bufIsChanged(buf) && !buf->b_p_ro)
1286 (void)buf_write_all(buf, FALSE);
1287 #ifdef FEAT_AUTOCMD
1288 /* an autocommand may have deleted the buffer */
1289 if (!buf_valid(buf))
1290 buf = firstbuf;
1291 #endif
1296 * return TRUE if buffer was changed and cannot be abandoned.
1298 /*ARGSUSED*/
1300 check_changed(buf, checkaw, mult_win, forceit, allbuf)
1301 buf_T *buf;
1302 int checkaw; /* do autowrite if buffer was changed */
1303 int mult_win; /* check also when several wins for the buf */
1304 int forceit;
1305 int allbuf; /* may write all buffers */
1307 if ( !forceit
1308 && bufIsChanged(buf)
1309 && (mult_win || buf->b_nwindows <= 1)
1310 && (!checkaw || autowrite(buf, forceit) == FAIL))
1312 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1313 if ((p_confirm || cmdmod.confirm) && p_write)
1315 buf_T *buf2;
1316 int count = 0;
1318 if (allbuf)
1319 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1320 if (bufIsChanged(buf2)
1321 && (buf2->b_ffname != NULL
1322 # ifdef FEAT_BROWSE
1323 || cmdmod.browse
1324 # endif
1326 ++count;
1327 # ifdef FEAT_AUTOCMD
1328 if (!buf_valid(buf))
1329 /* Autocommand deleted buffer, oops! It's not changed now. */
1330 return FALSE;
1331 # endif
1332 dialog_changed(buf, count > 1);
1333 # ifdef FEAT_AUTOCMD
1334 if (!buf_valid(buf))
1335 /* Autocommand deleted buffer, oops! It's not changed now. */
1336 return FALSE;
1337 # endif
1338 return bufIsChanged(buf);
1340 #endif
1341 EMSG(_(e_nowrtmsg));
1342 return TRUE;
1344 return FALSE;
1347 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO)
1349 #if defined(FEAT_BROWSE) || defined(PROTO)
1351 * When wanting to write a file without a file name, ask the user for a name.
1353 void
1354 browse_save_fname(buf)
1355 buf_T *buf;
1357 if (buf->b_fname == NULL)
1359 char_u *fname;
1361 fname = do_browse(BROWSE_SAVE, (char_u *)_("Save As"),
1362 NULL, NULL, NULL, NULL, buf);
1363 if (fname != NULL)
1365 if (setfname(buf, fname, NULL, TRUE) == OK)
1366 buf->b_flags |= BF_NOTEDITED;
1367 vim_free(fname);
1371 #endif
1374 * Ask the user what to do when abondoning a changed buffer.
1375 * Must check 'write' option first!
1377 void
1378 dialog_changed(buf, checkall)
1379 buf_T *buf;
1380 int checkall; /* may abandon all changed buffers */
1382 char_u buff[IOSIZE];
1383 int ret;
1384 buf_T *buf2;
1386 dialog_msg(buff, _("Save changes to \"%s\"?"),
1387 (buf->b_fname != NULL) ?
1388 buf->b_fname : (char_u *)_("Untitled"));
1389 if (checkall)
1390 ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1);
1391 else
1392 ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
1394 if (ret == VIM_YES)
1396 #ifdef FEAT_BROWSE
1397 /* May get file name, when there is none */
1398 browse_save_fname(buf);
1399 #endif
1400 if (buf->b_fname != NULL) /* didn't hit Cancel */
1401 (void)buf_write_all(buf, FALSE);
1403 else if (ret == VIM_NO)
1405 unchanged(buf, TRUE);
1407 else if (ret == VIM_ALL)
1410 * Write all modified files that can be written.
1411 * Skip readonly buffers, these need to be confirmed
1412 * individually.
1414 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1416 if (bufIsChanged(buf2)
1417 && (buf2->b_ffname != NULL
1418 #ifdef FEAT_BROWSE
1419 || cmdmod.browse
1420 #endif
1422 && !buf2->b_p_ro)
1424 #ifdef FEAT_BROWSE
1425 /* May get file name, when there is none */
1426 browse_save_fname(buf2);
1427 #endif
1428 if (buf2->b_fname != NULL) /* didn't hit Cancel */
1429 (void)buf_write_all(buf2, FALSE);
1430 #ifdef FEAT_AUTOCMD
1431 /* an autocommand may have deleted the buffer */
1432 if (!buf_valid(buf2))
1433 buf2 = firstbuf;
1434 #endif
1438 else if (ret == VIM_DISCARDALL)
1441 * mark all buffers as unchanged
1443 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1444 unchanged(buf2, TRUE);
1447 #endif
1450 * Return TRUE if the buffer "buf" can be abandoned, either by making it
1451 * hidden, autowriting it or unloading it.
1454 can_abandon(buf, forceit)
1455 buf_T *buf;
1456 int forceit;
1458 return ( P_HID(buf)
1459 || !bufIsChanged(buf)
1460 || buf->b_nwindows > 1
1461 || autowrite(buf, forceit) == OK
1462 || forceit);
1466 * Return TRUE if any buffer was changed and cannot be abandoned.
1467 * That changed buffer becomes the current buffer.
1470 check_changed_any(hidden)
1471 int hidden; /* Only check hidden buffers */
1473 buf_T *buf;
1474 int save;
1475 #ifdef FEAT_WINDOWS
1476 win_T *wp;
1477 #endif
1479 for (;;)
1481 /* check curbuf first: if it was changed we can't abandon it */
1482 if (!hidden && curbufIsChanged())
1483 buf = curbuf;
1484 else
1486 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
1487 if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf))
1488 break;
1490 if (buf == NULL) /* No buffers changed */
1491 return FALSE;
1493 /* Try auto-writing the buffer. If this fails but the buffer no
1494 * longer exists it's not changed, that's OK. */
1495 if (check_changed(buf, p_awa, TRUE, FALSE, TRUE) && buf_valid(buf))
1496 break; /* didn't save - still changes */
1499 exiting = FALSE;
1500 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1502 * When ":confirm" used, don't give an error message.
1504 if (!(p_confirm || cmdmod.confirm))
1505 #endif
1507 /* There must be a wait_return for this message, do_buffer()
1508 * may cause a redraw. But wait_return() is a no-op when vgetc()
1509 * is busy (Quit used from window menu), then make sure we don't
1510 * cause a scroll up. */
1511 if (vgetc_busy > 0)
1513 msg_row = cmdline_row;
1514 msg_col = 0;
1515 msg_didout = FALSE;
1517 if (EMSG2(_("E162: No write since last change for buffer \"%s\""),
1518 buf_spname(buf) != NULL ? (char_u *)buf_spname(buf) :
1519 buf->b_fname))
1521 save = no_wait_return;
1522 no_wait_return = FALSE;
1523 wait_return(FALSE);
1524 no_wait_return = save;
1528 #ifdef FEAT_WINDOWS
1529 /* Try to find a window that contains the buffer. */
1530 if (buf != curbuf)
1531 for (wp = firstwin; wp != NULL; wp = wp->w_next)
1532 if (wp->w_buffer == buf)
1534 win_goto(wp);
1535 # ifdef FEAT_AUTOCMD
1536 /* Paranoia: did autocms wipe out the buffer with changes? */
1537 if (!buf_valid(buf))
1538 return TRUE;
1539 # endif
1540 break;
1542 #endif
1544 /* Open the changed buffer in the current window. */
1545 if (buf != curbuf)
1546 set_curbuf(buf, DOBUF_GOTO);
1548 return TRUE;
1552 * return FAIL if there is no file name, OK if there is one
1553 * give error message for FAIL
1556 check_fname()
1558 if (curbuf->b_ffname == NULL)
1560 EMSG(_(e_noname));
1561 return FAIL;
1563 return OK;
1567 * flush the contents of a buffer, unless it has no file name
1569 * return FAIL for failure, OK otherwise
1572 buf_write_all(buf, forceit)
1573 buf_T *buf;
1574 int forceit;
1576 int retval;
1577 #ifdef FEAT_AUTOCMD
1578 buf_T *old_curbuf = curbuf;
1579 #endif
1581 retval = (buf_write(buf, buf->b_ffname, buf->b_fname,
1582 (linenr_T)1, buf->b_ml.ml_line_count, NULL,
1583 FALSE, forceit, TRUE, FALSE));
1584 #ifdef FEAT_AUTOCMD
1585 if (curbuf != old_curbuf)
1587 msg_source(hl_attr(HLF_W));
1588 MSG(_("Warning: Entered other buffer unexpectedly (check autocommands)"));
1590 #endif
1591 return retval;
1595 * Code to handle the argument list.
1598 static char_u *do_one_arg __ARGS((char_u *str));
1599 static int do_arglist __ARGS((char_u *str, int what, int after));
1600 static void alist_check_arg_idx __ARGS((void));
1601 static int editing_arg_idx __ARGS((win_T *win));
1602 #ifdef FEAT_LISTCMDS
1603 static int alist_add_list __ARGS((int count, char_u **files, int after));
1604 #endif
1605 #define AL_SET 1
1606 #define AL_ADD 2
1607 #define AL_DEL 3
1610 * Isolate one argument, taking backticks.
1611 * Changes the argument in-place, puts a NUL after it. Backticks remain.
1612 * Return a pointer to the start of the next argument.
1614 static char_u *
1615 do_one_arg(str)
1616 char_u *str;
1618 char_u *p;
1619 int inbacktick;
1621 inbacktick = FALSE;
1622 for (p = str; *str; ++str)
1624 /* When the backslash is used for escaping the special meaning of a
1625 * character we need to keep it until wildcard expansion. */
1626 if (rem_backslash(str))
1628 *p++ = *str++;
1629 *p++ = *str;
1631 else
1633 /* An item ends at a space not in backticks */
1634 if (!inbacktick && vim_isspace(*str))
1635 break;
1636 if (*str == '`')
1637 inbacktick ^= TRUE;
1638 *p++ = *str;
1641 str = skipwhite(str);
1642 *p = NUL;
1644 return str;
1648 * Separate the arguments in "str" and return a list of pointers in the
1649 * growarray "gap".
1652 get_arglist(gap, str)
1653 garray_T *gap;
1654 char_u *str;
1656 ga_init2(gap, (int)sizeof(char_u *), 20);
1657 while (*str != NUL)
1659 if (ga_grow(gap, 1) == FAIL)
1661 ga_clear(gap);
1662 return FAIL;
1664 ((char_u **)gap->ga_data)[gap->ga_len++] = str;
1666 /* Isolate one argument, change it in-place, put a NUL after it. */
1667 str = do_one_arg(str);
1669 return OK;
1672 #if defined(FEAT_QUICKFIX) || defined(FEAT_SYN_HL) || defined(PROTO)
1674 * Parse a list of arguments (file names), expand them and return in
1675 * "fnames[fcountp]".
1676 * Return FAIL or OK.
1679 get_arglist_exp(str, fcountp, fnamesp)
1680 char_u *str;
1681 int *fcountp;
1682 char_u ***fnamesp;
1684 garray_T ga;
1685 int i;
1687 if (get_arglist(&ga, str) == FAIL)
1688 return FAIL;
1689 i = gen_expand_wildcards(ga.ga_len, (char_u **)ga.ga_data,
1690 fcountp, fnamesp, EW_FILE|EW_NOTFOUND);
1691 ga_clear(&ga);
1692 return i;
1694 #endif
1696 #if defined(FEAT_GUI) || defined(FEAT_CLIENTSERVER) || defined(PROTO)
1698 * Redefine the argument list.
1700 void
1701 set_arglist(str)
1702 char_u *str;
1704 do_arglist(str, AL_SET, 0);
1706 #endif
1709 * "what" == AL_SET: Redefine the argument list to 'str'.
1710 * "what" == AL_ADD: add files in 'str' to the argument list after "after".
1711 * "what" == AL_DEL: remove files in 'str' from the argument list.
1713 * Return FAIL for failure, OK otherwise.
1715 /*ARGSUSED*/
1716 static int
1717 do_arglist(str, what, after)
1718 char_u *str;
1719 int what;
1720 int after; /* 0 means before first one */
1722 garray_T new_ga;
1723 int exp_count;
1724 char_u **exp_files;
1725 int i;
1726 #ifdef FEAT_LISTCMDS
1727 char_u *p;
1728 int match;
1729 #endif
1732 * Collect all file name arguments in "new_ga".
1734 if (get_arglist(&new_ga, str) == FAIL)
1735 return FAIL;
1737 #ifdef FEAT_LISTCMDS
1738 if (what == AL_DEL)
1740 regmatch_T regmatch;
1741 int didone;
1744 * Delete the items: use each item as a regexp and find a match in the
1745 * argument list.
1747 #ifdef CASE_INSENSITIVE_FILENAME
1748 regmatch.rm_ic = TRUE; /* Always ignore case */
1749 #else
1750 regmatch.rm_ic = FALSE; /* Never ignore case */
1751 #endif
1752 for (i = 0; i < new_ga.ga_len && !got_int; ++i)
1754 p = ((char_u **)new_ga.ga_data)[i];
1755 p = file_pat_to_reg_pat(p, NULL, NULL, FALSE);
1756 if (p == NULL)
1757 break;
1758 regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0);
1759 if (regmatch.regprog == NULL)
1761 vim_free(p);
1762 break;
1765 didone = FALSE;
1766 for (match = 0; match < ARGCOUNT; ++match)
1767 if (vim_regexec(&regmatch, alist_name(&ARGLIST[match]),
1768 (colnr_T)0))
1770 didone = TRUE;
1771 vim_free(ARGLIST[match].ae_fname);
1772 mch_memmove(ARGLIST + match, ARGLIST + match + 1,
1773 (ARGCOUNT - match - 1) * sizeof(aentry_T));
1774 --ALIST(curwin)->al_ga.ga_len;
1775 if (curwin->w_arg_idx > match)
1776 --curwin->w_arg_idx;
1777 --match;
1780 vim_free(regmatch.regprog);
1781 vim_free(p);
1782 if (!didone)
1783 EMSG2(_(e_nomatch2), ((char_u **)new_ga.ga_data)[i]);
1785 ga_clear(&new_ga);
1787 else
1788 #endif
1790 i = expand_wildcards(new_ga.ga_len, (char_u **)new_ga.ga_data,
1791 &exp_count, &exp_files, EW_DIR|EW_FILE|EW_ADDSLASH|EW_NOTFOUND);
1792 ga_clear(&new_ga);
1793 if (i == FAIL)
1794 return FAIL;
1795 if (exp_count == 0)
1797 EMSG(_(e_nomatch));
1798 return FAIL;
1801 #ifdef FEAT_LISTCMDS
1802 if (what == AL_ADD)
1804 (void)alist_add_list(exp_count, exp_files, after);
1805 vim_free(exp_files);
1807 else /* what == AL_SET */
1808 #endif
1809 alist_set(ALIST(curwin), exp_count, exp_files, FALSE, NULL, 0);
1812 alist_check_arg_idx();
1814 return OK;
1818 * Check the validity of the arg_idx for each other window.
1820 static void
1821 alist_check_arg_idx()
1823 #ifdef FEAT_WINDOWS
1824 win_T *win;
1825 tabpage_T *tp;
1827 FOR_ALL_TAB_WINDOWS(tp, win)
1828 if (win->w_alist == curwin->w_alist)
1829 check_arg_idx(win);
1830 #else
1831 check_arg_idx(curwin);
1832 #endif
1836 * Return TRUE if window "win" is editing then file at the current argument
1837 * index.
1839 static int
1840 editing_arg_idx(win)
1841 win_T *win;
1843 return !(win->w_arg_idx >= WARGCOUNT(win)
1844 || (win->w_buffer->b_fnum
1845 != WARGLIST(win)[win->w_arg_idx].ae_fnum
1846 && (win->w_buffer->b_ffname == NULL
1847 || !(fullpathcmp(
1848 alist_name(&WARGLIST(win)[win->w_arg_idx]),
1849 win->w_buffer->b_ffname, TRUE) & FPC_SAME))));
1853 * Check if window "win" is editing the w_arg_idx file in its argument list.
1855 void
1856 check_arg_idx(win)
1857 win_T *win;
1859 if (WARGCOUNT(win) > 1 && !editing_arg_idx(win))
1861 /* We are not editing the current entry in the argument list.
1862 * Set "arg_had_last" if we are editing the last one. */
1863 win->w_arg_idx_invalid = TRUE;
1864 if (win->w_arg_idx != WARGCOUNT(win) - 1
1865 && arg_had_last == FALSE
1866 #ifdef FEAT_WINDOWS
1867 && ALIST(win) == &global_alist
1868 #endif
1869 && GARGCOUNT > 0
1870 && win->w_arg_idx < GARGCOUNT
1871 && (win->w_buffer->b_fnum == GARGLIST[GARGCOUNT - 1].ae_fnum
1872 || (win->w_buffer->b_ffname != NULL
1873 && (fullpathcmp(alist_name(&GARGLIST[GARGCOUNT - 1]),
1874 win->w_buffer->b_ffname, TRUE) & FPC_SAME))))
1875 arg_had_last = TRUE;
1877 else
1879 /* We are editing the current entry in the argument list.
1880 * Set "arg_had_last" if it's also the last one */
1881 win->w_arg_idx_invalid = FALSE;
1882 if (win->w_arg_idx == WARGCOUNT(win) - 1
1883 #ifdef FEAT_WINDOWS
1884 && win->w_alist == &global_alist
1885 #endif
1887 arg_had_last = TRUE;
1892 * ":args", ":argslocal" and ":argsglobal".
1894 void
1895 ex_args(eap)
1896 exarg_T *eap;
1898 int i;
1900 if (eap->cmdidx != CMD_args)
1902 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
1903 alist_unlink(ALIST(curwin));
1904 if (eap->cmdidx == CMD_argglobal)
1905 ALIST(curwin) = &global_alist;
1906 else /* eap->cmdidx == CMD_arglocal */
1907 alist_new();
1908 #else
1909 ex_ni(eap);
1910 return;
1911 #endif
1914 if (!ends_excmd(*eap->arg))
1917 * ":args file ..": define new argument list, handle like ":next"
1918 * Also for ":argslocal file .." and ":argsglobal file ..".
1920 ex_next(eap);
1922 else
1923 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
1924 if (eap->cmdidx == CMD_args)
1925 #endif
1928 * ":args": list arguments.
1930 if (ARGCOUNT > 0)
1932 /* Overwrite the command, for a short list there is no scrolling
1933 * required and no wait_return(). */
1934 gotocmdline(TRUE);
1935 for (i = 0; i < ARGCOUNT; ++i)
1937 if (i == curwin->w_arg_idx)
1938 msg_putchar('[');
1939 msg_outtrans(alist_name(&ARGLIST[i]));
1940 if (i == curwin->w_arg_idx)
1941 msg_putchar(']');
1942 msg_putchar(' ');
1946 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
1947 else if (eap->cmdidx == CMD_arglocal)
1949 garray_T *gap = &curwin->w_alist->al_ga;
1952 * ":argslocal": make a local copy of the global argument list.
1954 if (ga_grow(gap, GARGCOUNT) == OK)
1955 for (i = 0; i < GARGCOUNT; ++i)
1956 if (GARGLIST[i].ae_fname != NULL)
1958 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fname =
1959 vim_strsave(GARGLIST[i].ae_fname);
1960 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fnum =
1961 GARGLIST[i].ae_fnum;
1962 ++gap->ga_len;
1965 #endif
1969 * ":previous", ":sprevious", ":Next" and ":sNext".
1971 void
1972 ex_previous(eap)
1973 exarg_T *eap;
1975 /* If past the last one already, go to the last one. */
1976 if (curwin->w_arg_idx - (int)eap->line2 >= ARGCOUNT)
1977 do_argfile(eap, ARGCOUNT - 1);
1978 else
1979 do_argfile(eap, curwin->w_arg_idx - (int)eap->line2);
1983 * ":rewind", ":first", ":sfirst" and ":srewind".
1985 void
1986 ex_rewind(eap)
1987 exarg_T *eap;
1989 do_argfile(eap, 0);
1993 * ":last" and ":slast".
1995 void
1996 ex_last(eap)
1997 exarg_T *eap;
1999 do_argfile(eap, ARGCOUNT - 1);
2003 * ":argument" and ":sargument".
2005 void
2006 ex_argument(eap)
2007 exarg_T *eap;
2009 int i;
2011 if (eap->addr_count > 0)
2012 i = eap->line2 - 1;
2013 else
2014 i = curwin->w_arg_idx;
2015 do_argfile(eap, i);
2019 * Edit file "argn" of the argument lists.
2021 void
2022 do_argfile(eap, argn)
2023 exarg_T *eap;
2024 int argn;
2026 int other;
2027 char_u *p;
2028 int old_arg_idx = curwin->w_arg_idx;
2030 if (argn < 0 || argn >= ARGCOUNT)
2032 if (ARGCOUNT <= 1)
2033 EMSG(_("E163: There is only one file to edit"));
2034 else if (argn < 0)
2035 EMSG(_("E164: Cannot go before first file"));
2036 else
2037 EMSG(_("E165: Cannot go beyond last file"));
2039 else
2041 setpcmark();
2042 #ifdef FEAT_GUI
2043 need_mouse_correct = TRUE;
2044 #endif
2046 #ifdef FEAT_WINDOWS
2047 /* split window or create new tab page first */
2048 if (*eap->cmd == 's' || cmdmod.tab != 0)
2050 if (win_split(0, 0) == FAIL)
2051 return;
2052 # ifdef FEAT_SCROLLBIND
2053 curwin->w_p_scb = FALSE;
2054 # endif
2056 else
2057 #endif
2060 * if 'hidden' set, only check for changed file when re-editing
2061 * the same buffer
2063 other = TRUE;
2064 if (P_HID(curbuf))
2066 p = fix_fname(alist_name(&ARGLIST[argn]));
2067 other = otherfile(p);
2068 vim_free(p);
2070 if ((!P_HID(curbuf) || !other)
2071 && check_changed(curbuf, TRUE, !other, eap->forceit, FALSE))
2072 return;
2075 curwin->w_arg_idx = argn;
2076 if (argn == ARGCOUNT - 1
2077 #ifdef FEAT_WINDOWS
2078 && curwin->w_alist == &global_alist
2079 #endif
2081 arg_had_last = TRUE;
2083 /* Edit the file; always use the last known line number.
2084 * When it fails (e.g. Abort for already edited file) restore the
2085 * argument index. */
2086 if (do_ecmd(0, alist_name(&ARGLIST[curwin->w_arg_idx]), NULL,
2087 eap, ECMD_LAST,
2088 (P_HID(curwin->w_buffer) ? ECMD_HIDE : 0) +
2089 (eap->forceit ? ECMD_FORCEIT : 0)) == FAIL)
2090 curwin->w_arg_idx = old_arg_idx;
2091 /* like Vi: set the mark where the cursor is in the file. */
2092 else if (eap->cmdidx != CMD_argdo)
2093 setmark('\'');
2098 * ":next", and commands that behave like it.
2100 void
2101 ex_next(eap)
2102 exarg_T *eap;
2104 int i;
2107 * check for changed buffer now, if this fails the argument list is not
2108 * redefined.
2110 if ( P_HID(curbuf)
2111 || eap->cmdidx == CMD_snext
2112 || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
2114 if (*eap->arg != NUL) /* redefine file list */
2116 if (do_arglist(eap->arg, AL_SET, 0) == FAIL)
2117 return;
2118 i = 0;
2120 else
2121 i = curwin->w_arg_idx + (int)eap->line2;
2122 do_argfile(eap, i);
2126 #ifdef FEAT_LISTCMDS
2128 * ":argedit"
2130 void
2131 ex_argedit(eap)
2132 exarg_T *eap;
2134 int fnum;
2135 int i;
2136 char_u *s;
2138 /* Add the argument to the buffer list and get the buffer number. */
2139 fnum = buflist_add(eap->arg, BLN_LISTED);
2141 /* Check if this argument is already in the argument list. */
2142 for (i = 0; i < ARGCOUNT; ++i)
2143 if (ARGLIST[i].ae_fnum == fnum)
2144 break;
2145 if (i == ARGCOUNT)
2147 /* Can't find it, add it to the argument list. */
2148 s = vim_strsave(eap->arg);
2149 if (s == NULL)
2150 return;
2151 i = alist_add_list(1, &s,
2152 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
2153 if (i < 0)
2154 return;
2155 curwin->w_arg_idx = i;
2158 alist_check_arg_idx();
2160 /* Edit the argument. */
2161 do_argfile(eap, i);
2165 * ":argadd"
2167 void
2168 ex_argadd(eap)
2169 exarg_T *eap;
2171 do_arglist(eap->arg, AL_ADD,
2172 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
2173 #ifdef FEAT_TITLE
2174 maketitle();
2175 #endif
2179 * ":argdelete"
2181 void
2182 ex_argdelete(eap)
2183 exarg_T *eap;
2185 int i;
2186 int n;
2188 if (eap->addr_count > 0)
2190 /* ":1,4argdel": Delete all arguments in the range. */
2191 if (eap->line2 > ARGCOUNT)
2192 eap->line2 = ARGCOUNT;
2193 n = eap->line2 - eap->line1 + 1;
2194 if (*eap->arg != NUL || n <= 0)
2195 EMSG(_(e_invarg));
2196 else
2198 for (i = eap->line1; i <= eap->line2; ++i)
2199 vim_free(ARGLIST[i - 1].ae_fname);
2200 mch_memmove(ARGLIST + eap->line1 - 1, ARGLIST + eap->line2,
2201 (size_t)((ARGCOUNT - eap->line2) * sizeof(aentry_T)));
2202 ALIST(curwin)->al_ga.ga_len -= n;
2203 if (curwin->w_arg_idx >= eap->line2)
2204 curwin->w_arg_idx -= n;
2205 else if (curwin->w_arg_idx > eap->line1)
2206 curwin->w_arg_idx = eap->line1;
2209 else if (*eap->arg == NUL)
2210 EMSG(_(e_argreq));
2211 else
2212 do_arglist(eap->arg, AL_DEL, 0);
2213 #ifdef FEAT_TITLE
2214 maketitle();
2215 #endif
2219 * ":argdo", ":windo", ":bufdo", ":tabdo"
2221 void
2222 ex_listdo(eap)
2223 exarg_T *eap;
2225 int i;
2226 #ifdef FEAT_WINDOWS
2227 win_T *wp;
2228 tabpage_T *tp;
2229 #endif
2230 buf_T *buf;
2231 int next_fnum = 0;
2232 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2233 char_u *save_ei = NULL;
2234 #endif
2235 char_u *p_shm_save;
2237 #ifndef FEAT_WINDOWS
2238 if (eap->cmdidx == CMD_windo)
2240 ex_ni(eap);
2241 return;
2243 #endif
2245 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2246 if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo)
2247 /* Don't do syntax HL autocommands. Skipping the syntax file is a
2248 * great speed improvement. */
2249 save_ei = au_event_disable(",Syntax");
2250 #endif
2252 if (eap->cmdidx == CMD_windo
2253 || eap->cmdidx == CMD_tabdo
2254 || P_HID(curbuf)
2255 || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
2257 /* start at the first argument/window/buffer */
2258 i = 0;
2259 #ifdef FEAT_WINDOWS
2260 wp = firstwin;
2261 tp = first_tabpage;
2262 #endif
2263 /* set pcmark now */
2264 if (eap->cmdidx == CMD_bufdo)
2265 goto_buffer(eap, DOBUF_FIRST, FORWARD, 0);
2266 else
2267 setpcmark();
2268 listcmd_busy = TRUE; /* avoids setting pcmark below */
2270 while (!got_int)
2272 if (eap->cmdidx == CMD_argdo)
2274 /* go to argument "i" */
2275 if (i == ARGCOUNT)
2276 break;
2277 /* Don't call do_argfile() when already there, it will try
2278 * reloading the file. */
2279 if (curwin->w_arg_idx != i || !editing_arg_idx(curwin))
2281 /* Clear 'shm' to avoid that the file message overwrites
2282 * any output from the command. */
2283 p_shm_save = vim_strsave(p_shm);
2284 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
2285 do_argfile(eap, i);
2286 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
2287 vim_free(p_shm_save);
2289 if (curwin->w_arg_idx != i)
2290 break;
2291 ++i;
2293 #ifdef FEAT_WINDOWS
2294 else if (eap->cmdidx == CMD_windo)
2296 /* go to window "wp" */
2297 if (!win_valid(wp))
2298 break;
2299 win_goto(wp);
2300 if (curwin != wp)
2301 break; /* something must be wrong */
2302 wp = curwin->w_next;
2304 else if (eap->cmdidx == CMD_tabdo)
2306 /* go to window "tp" */
2307 if (!valid_tabpage(tp))
2308 break;
2309 goto_tabpage_tp(tp);
2310 tp = tp->tp_next;
2312 #endif
2313 else if (eap->cmdidx == CMD_bufdo)
2315 /* Remember the number of the next listed buffer, in case
2316 * ":bwipe" is used or autocommands do something strange. */
2317 next_fnum = -1;
2318 for (buf = curbuf->b_next; buf != NULL; buf = buf->b_next)
2319 if (buf->b_p_bl)
2321 next_fnum = buf->b_fnum;
2322 break;
2326 /* execute the command */
2327 do_cmdline(eap->arg, eap->getline, eap->cookie,
2328 DOCMD_VERBOSE + DOCMD_NOWAIT);
2330 if (eap->cmdidx == CMD_bufdo)
2332 /* Done? */
2333 if (next_fnum < 0)
2334 break;
2335 /* Check if the buffer still exists. */
2336 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
2337 if (buf->b_fnum == next_fnum)
2338 break;
2339 if (buf == NULL)
2340 break;
2342 /* Go to the next buffer. Clear 'shm' to avoid that the file
2343 * message overwrites any output from the command. */
2344 p_shm_save = vim_strsave(p_shm);
2345 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
2346 goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
2347 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
2348 vim_free(p_shm_save);
2350 /* If autocommands took us elsewhere, quit here */
2351 if (curbuf->b_fnum != next_fnum)
2352 break;
2355 if (eap->cmdidx == CMD_windo)
2357 validate_cursor(); /* cursor may have moved */
2358 #ifdef FEAT_SCROLLBIND
2359 /* required when 'scrollbind' has been set */
2360 if (curwin->w_p_scb)
2361 do_check_scrollbind(TRUE);
2362 #endif
2365 listcmd_busy = FALSE;
2368 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2369 if (save_ei != NULL)
2371 au_event_restore(save_ei);
2372 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
2373 curbuf->b_fname, TRUE, curbuf);
2375 #endif
2379 * Add files[count] to the arglist of the current window after arg "after".
2380 * The file names in files[count] must have been allocated and are taken over.
2381 * Files[] itself is not taken over.
2382 * Returns index of first added argument. Returns -1 when failed (out of mem).
2384 static int
2385 alist_add_list(count, files, after)
2386 int count;
2387 char_u **files;
2388 int after; /* where to add: 0 = before first one */
2390 int i;
2392 if (ga_grow(&ALIST(curwin)->al_ga, count) == OK)
2394 if (after < 0)
2395 after = 0;
2396 if (after > ARGCOUNT)
2397 after = ARGCOUNT;
2398 if (after < ARGCOUNT)
2399 mch_memmove(&(ARGLIST[after + count]), &(ARGLIST[after]),
2400 (ARGCOUNT - after) * sizeof(aentry_T));
2401 for (i = 0; i < count; ++i)
2403 ARGLIST[after + i].ae_fname = files[i];
2404 ARGLIST[after + i].ae_fnum = buflist_add(files[i], BLN_LISTED);
2406 ALIST(curwin)->al_ga.ga_len += count;
2407 if (curwin->w_arg_idx >= after)
2408 ++curwin->w_arg_idx;
2409 return after;
2412 for (i = 0; i < count; ++i)
2413 vim_free(files[i]);
2414 return -1;
2417 #endif /* FEAT_LISTCMDS */
2419 #ifdef FEAT_EVAL
2421 * ":compiler[!] {name}"
2423 void
2424 ex_compiler(eap)
2425 exarg_T *eap;
2427 char_u *buf;
2428 char_u *old_cur_comp = NULL;
2429 char_u *p;
2431 if (*eap->arg == NUL)
2433 /* List all compiler scripts. */
2434 do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')");
2435 /* ) keep the indenter happy... */
2437 else
2439 buf = alloc((unsigned)(STRLEN(eap->arg) + 14));
2440 if (buf != NULL)
2442 if (eap->forceit)
2444 /* ":compiler! {name}" sets global options */
2445 do_cmdline_cmd((char_u *)
2446 "command -nargs=* CompilerSet set <args>");
2448 else
2450 /* ":compiler! {name}" sets local options.
2451 * To remain backwards compatible "current_compiler" is always
2452 * used. A user's compiler plugin may set it, the distributed
2453 * plugin will then skip the settings. Afterwards set
2454 * "b:current_compiler" and restore "current_compiler". */
2455 old_cur_comp = get_var_value((char_u *)"current_compiler");
2456 if (old_cur_comp != NULL)
2457 old_cur_comp = vim_strsave(old_cur_comp);
2458 do_cmdline_cmd((char_u *)
2459 "command -nargs=* CompilerSet setlocal <args>");
2461 do_unlet((char_u *)"current_compiler", TRUE);
2462 do_unlet((char_u *)"b:current_compiler", TRUE);
2464 sprintf((char *)buf, "compiler/%s.vim", eap->arg);
2465 if (source_runtime(buf, TRUE) == FAIL)
2466 EMSG2(_("E666: compiler not supported: %s"), eap->arg);
2467 vim_free(buf);
2469 do_cmdline_cmd((char_u *)":delcommand CompilerSet");
2471 /* Set "b:current_compiler" from "current_compiler". */
2472 p = get_var_value((char_u *)"current_compiler");
2473 if (p != NULL)
2474 set_internal_string_var((char_u *)"b:current_compiler", p);
2476 /* Restore "current_compiler" for ":compiler {name}". */
2477 if (!eap->forceit)
2479 if (old_cur_comp != NULL)
2481 set_internal_string_var((char_u *)"current_compiler",
2482 old_cur_comp);
2483 vim_free(old_cur_comp);
2485 else
2486 do_unlet((char_u *)"current_compiler", TRUE);
2491 #endif
2494 * ":runtime {name}"
2496 void
2497 ex_runtime(eap)
2498 exarg_T *eap;
2500 source_runtime(eap->arg, eap->forceit);
2503 static void source_callback __ARGS((char_u *fname, void *cookie));
2505 /*ARGSUSED*/
2506 static void
2507 source_callback(fname, cookie)
2508 char_u *fname;
2509 void *cookie;
2511 (void)do_source(fname, FALSE, DOSO_NONE);
2515 * Source the file "name" from all directories in 'runtimepath'.
2516 * "name" can contain wildcards.
2517 * When "all" is TRUE, source all files, otherwise only the first one.
2518 * return FAIL when no file could be sourced, OK otherwise.
2521 source_runtime(name, all)
2522 char_u *name;
2523 int all;
2525 return do_in_runtimepath(name, all, source_callback, NULL);
2529 * Find "name" in 'runtimepath'. When found, invoke the callback function for
2530 * it: callback(fname, "cookie")
2531 * When "all" is TRUE repeat for all matches, otherwise only the first one is
2532 * used.
2533 * Returns OK when at least one match found, FAIL otherwise.
2536 do_in_runtimepath(name, all, callback, cookie)
2537 char_u *name;
2538 int all;
2539 void (*callback)__ARGS((char_u *fname, void *ck));
2540 void *cookie;
2542 char_u *rtp;
2543 char_u *np;
2544 char_u *buf;
2545 char_u *rtp_copy;
2546 char_u *tail;
2547 int num_files;
2548 char_u **files;
2549 int i;
2550 int did_one = FALSE;
2551 #ifdef AMIGA
2552 struct Process *proc = (struct Process *)FindTask(0L);
2553 APTR save_winptr = proc->pr_WindowPtr;
2555 /* Avoid a requester here for a volume that doesn't exist. */
2556 proc->pr_WindowPtr = (APTR)-1L;
2557 #endif
2559 /* Make a copy of 'runtimepath'. Invoking the callback may change the
2560 * value. */
2561 rtp_copy = vim_strsave(p_rtp);
2562 buf = alloc(MAXPATHL);
2563 if (buf != NULL && rtp_copy != NULL)
2565 if (p_verbose > 1)
2567 verbose_enter();
2568 smsg((char_u *)_("Searching for \"%s\" in \"%s\""),
2569 (char *)name, (char *)p_rtp);
2570 verbose_leave();
2573 /* Loop over all entries in 'runtimepath'. */
2574 rtp = rtp_copy;
2575 while (*rtp != NUL && (all || !did_one))
2577 /* Copy the path from 'runtimepath' to buf[]. */
2578 copy_option_part(&rtp, buf, MAXPATHL, ",");
2579 if (STRLEN(buf) + STRLEN(name) + 2 < MAXPATHL)
2581 add_pathsep(buf);
2582 tail = buf + STRLEN(buf);
2584 /* Loop over all patterns in "name" */
2585 np = name;
2586 while (*np != NUL && (all || !did_one))
2588 /* Append the pattern from "name" to buf[]. */
2589 copy_option_part(&np, tail, (int)(MAXPATHL - (tail - buf)),
2590 "\t ");
2592 if (p_verbose > 2)
2594 verbose_enter();
2595 smsg((char_u *)_("Searching for \"%s\""), buf);
2596 verbose_leave();
2599 /* Expand wildcards, invoke the callback for each match. */
2600 if (gen_expand_wildcards(1, &buf, &num_files, &files,
2601 EW_FILE) == OK)
2603 for (i = 0; i < num_files; ++i)
2605 (*callback)(files[i], cookie);
2606 did_one = TRUE;
2607 if (!all)
2608 break;
2610 FreeWild(num_files, files);
2616 vim_free(buf);
2617 vim_free(rtp_copy);
2618 if (p_verbose > 0 && !did_one)
2620 verbose_enter();
2621 smsg((char_u *)_("not found in 'runtimepath': \"%s\""), name);
2622 verbose_leave();
2625 #ifdef AMIGA
2626 proc->pr_WindowPtr = save_winptr;
2627 #endif
2629 return did_one ? OK : FAIL;
2632 #if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD)
2634 * ":options"
2636 /*ARGSUSED*/
2637 void
2638 ex_options(eap)
2639 exarg_T *eap;
2641 cmd_source((char_u *)SYS_OPTWIN_FILE, NULL);
2643 #endif
2646 * ":source {fname}"
2648 void
2649 ex_source(eap)
2650 exarg_T *eap;
2652 #ifdef FEAT_BROWSE
2653 if (cmdmod.browse)
2655 char_u *fname = NULL;
2657 fname = do_browse(0, (char_u *)_("Source Vim script"), eap->arg,
2658 NULL, NULL, BROWSE_FILTER_MACROS, NULL);
2659 if (fname != NULL)
2661 cmd_source(fname, eap);
2662 vim_free(fname);
2665 else
2666 #endif
2667 cmd_source(eap->arg, eap);
2670 static void
2671 cmd_source(fname, eap)
2672 char_u *fname;
2673 exarg_T *eap;
2675 if (*fname == NUL)
2676 EMSG(_(e_argreq));
2678 else if (eap != NULL && eap->forceit)
2679 /* ":source!": read Normal mdoe commands
2680 * Need to execute the commands directly. This is required at least
2681 * for:
2682 * - ":g" command busy
2683 * - after ":argdo", ":windo" or ":bufdo"
2684 * - another command follows
2685 * - inside a loop
2687 openscript(fname, global_busy || listcmd_busy || eap->nextcmd != NULL
2688 #ifdef FEAT_EVAL
2689 || eap->cstack->cs_idx >= 0
2690 #endif
2693 /* ":source" read ex commands */
2694 else if (do_source(fname, FALSE, DOSO_NONE) == FAIL)
2695 EMSG2(_(e_notopen), fname);
2699 * ":source" and associated commands.
2702 * Structure used to store info for each sourced file.
2703 * It is shared between do_source() and getsourceline().
2704 * This is required, because it needs to be handed to do_cmdline() and
2705 * sourcing can be done recursively.
2707 struct source_cookie
2709 FILE *fp; /* opened file for sourcing */
2710 char_u *nextline; /* if not NULL: line that was read ahead */
2711 int finished; /* ":finish" used */
2712 #if defined (USE_CRNL) || defined (USE_CR)
2713 int fileformat; /* EOL_UNKNOWN, EOL_UNIX or EOL_DOS */
2714 int error; /* TRUE if LF found after CR-LF */
2715 #endif
2716 #ifdef FEAT_EVAL
2717 linenr_T breakpoint; /* next line with breakpoint or zero */
2718 char_u *fname; /* name of sourced file */
2719 int dbg_tick; /* debug_tick when breakpoint was set */
2720 int level; /* top nesting level of sourced file */
2721 #endif
2722 #ifdef FEAT_MBYTE
2723 vimconv_T conv; /* type of conversion */
2724 #endif
2727 #ifdef FEAT_EVAL
2729 * Return the address holding the next breakpoint line for a source cookie.
2731 linenr_T *
2732 source_breakpoint(cookie)
2733 void *cookie;
2735 return &((struct source_cookie *)cookie)->breakpoint;
2739 * Return the address holding the debug tick for a source cookie.
2741 int *
2742 source_dbg_tick(cookie)
2743 void *cookie;
2745 return &((struct source_cookie *)cookie)->dbg_tick;
2749 * Return the nesting level for a source cookie.
2752 source_level(cookie)
2753 void *cookie;
2755 return ((struct source_cookie *)cookie)->level;
2757 #endif
2759 static char_u *get_one_sourceline __ARGS((struct source_cookie *sp));
2761 #if defined(WIN32) && defined(FEAT_CSCOPE)
2762 static FILE *fopen_noinh_readbin __ARGS((char *filename));
2765 * Special function to open a file without handle inheritance.
2767 static FILE *
2768 fopen_noinh_readbin(filename)
2769 char *filename;
2771 int fd_tmp = mch_open(filename, O_RDONLY | O_BINARY | O_NOINHERIT, 0);
2773 if (fd_tmp == -1)
2774 return NULL;
2775 return fdopen(fd_tmp, READBIN);
2777 #endif
2781 * do_source: Read the file "fname" and execute its lines as EX commands.
2783 * This function may be called recursively!
2785 * return FAIL if file could not be opened, OK otherwise
2788 do_source(fname, check_other, is_vimrc)
2789 char_u *fname;
2790 int check_other; /* check for .vimrc and _vimrc */
2791 int is_vimrc; /* DOSO_ value */
2793 struct source_cookie cookie;
2794 char_u *save_sourcing_name;
2795 linenr_T save_sourcing_lnum;
2796 char_u *p;
2797 char_u *fname_exp;
2798 int retval = FAIL;
2799 #ifdef FEAT_EVAL
2800 scid_T save_current_SID;
2801 static scid_T last_current_SID = 0;
2802 void *save_funccalp;
2803 int save_debug_break_level = debug_break_level;
2804 scriptitem_T *si = NULL;
2805 # ifdef UNIX
2806 struct stat st;
2807 int stat_ok;
2808 # endif
2809 #endif
2810 #ifdef STARTUPTIME
2811 struct timeval tv_rel;
2812 struct timeval tv_start;
2813 #endif
2814 #ifdef FEAT_PROFILE
2815 proftime_T wait_start;
2816 #endif
2818 #ifdef RISCOS
2819 p = mch_munge_fname(fname);
2820 #else
2821 p = expand_env_save(fname);
2822 #endif
2823 if (p == NULL)
2824 return retval;
2825 fname_exp = fix_fname(p);
2826 vim_free(p);
2827 if (fname_exp == NULL)
2828 return retval;
2829 if (mch_isdir(fname_exp))
2831 smsg((char_u *)_("Cannot source a directory: \"%s\""), fname);
2832 goto theend;
2835 #ifdef FEAT_AUTOCMD
2836 /* Apply SourceCmd autocommands, they should get the file and source it. */
2837 if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL)
2838 && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp,
2839 FALSE, curbuf))
2840 # ifdef FEAT_EVAL
2841 return aborting() ? FAIL : OK;
2842 # else
2843 return OK;
2844 # endif
2846 /* Apply SourcePre autocommands, they may get the file. */
2847 apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, FALSE, curbuf);
2848 #endif
2850 #if defined(WIN32) && defined(FEAT_CSCOPE)
2851 cookie.fp = fopen_noinh_readbin((char *)fname_exp);
2852 #else
2853 cookie.fp = mch_fopen((char *)fname_exp, READBIN);
2854 #endif
2855 if (cookie.fp == NULL && check_other)
2858 * Try again, replacing file name ".vimrc" by "_vimrc" or vice versa,
2859 * and ".exrc" by "_exrc" or vice versa.
2861 p = gettail(fname_exp);
2862 if ((*p == '.' || *p == '_')
2863 && (STRICMP(p + 1, "vimrc") == 0
2864 || STRICMP(p + 1, "gvimrc") == 0
2865 || STRICMP(p + 1, "exrc") == 0))
2867 if (*p == '_')
2868 *p = '.';
2869 else
2870 *p = '_';
2871 #if defined(WIN32) && defined(FEAT_CSCOPE)
2872 cookie.fp = fopen_noinh_readbin((char *)fname_exp);
2873 #else
2874 cookie.fp = mch_fopen((char *)fname_exp, READBIN);
2875 #endif
2879 if (cookie.fp == NULL)
2881 if (p_verbose > 0)
2883 verbose_enter();
2884 if (sourcing_name == NULL)
2885 smsg((char_u *)_("could not source \"%s\""), fname);
2886 else
2887 smsg((char_u *)_("line %ld: could not source \"%s\""),
2888 sourcing_lnum, fname);
2889 verbose_leave();
2891 goto theend;
2895 * The file exists.
2896 * - In verbose mode, give a message.
2897 * - For a vimrc file, may want to set 'compatible', call vimrc_found().
2899 if (p_verbose > 1)
2901 verbose_enter();
2902 if (sourcing_name == NULL)
2903 smsg((char_u *)_("sourcing \"%s\""), fname);
2904 else
2905 smsg((char_u *)_("line %ld: sourcing \"%s\""),
2906 sourcing_lnum, fname);
2907 verbose_leave();
2909 if (is_vimrc == DOSO_VIMRC)
2910 vimrc_found(fname_exp, (char_u *)"MYVIMRC");
2911 else if (is_vimrc == DOSO_GVIMRC)
2912 vimrc_found(fname_exp, (char_u *)"MYGVIMRC");
2914 #ifdef USE_CRNL
2915 /* If no automatic file format: Set default to CR-NL. */
2916 if (*p_ffs == NUL)
2917 cookie.fileformat = EOL_DOS;
2918 else
2919 cookie.fileformat = EOL_UNKNOWN;
2920 cookie.error = FALSE;
2921 #endif
2923 #ifdef USE_CR
2924 /* If no automatic file format: Set default to CR. */
2925 if (*p_ffs == NUL)
2926 cookie.fileformat = EOL_MAC;
2927 else
2928 cookie.fileformat = EOL_UNKNOWN;
2929 cookie.error = FALSE;
2930 #endif
2932 cookie.nextline = NULL;
2933 cookie.finished = FALSE;
2935 #ifdef FEAT_EVAL
2937 * Check if this script has a breakpoint.
2939 cookie.breakpoint = dbg_find_breakpoint(TRUE, fname_exp, (linenr_T)0);
2940 cookie.fname = fname_exp;
2941 cookie.dbg_tick = debug_tick;
2943 cookie.level = ex_nesting_level;
2944 #endif
2945 #ifdef FEAT_MBYTE
2946 cookie.conv.vc_type = CONV_NONE; /* no conversion */
2948 /* Try reading the first few bytes to check for a UTF-8 BOM. */
2950 char_u buf[3];
2952 if (fread((char *)buf, sizeof(char_u), (size_t)3, cookie.fp)
2953 == (size_t)3
2954 && buf[0] == 0xef && buf[1] == 0xbb && buf[2] == 0xbf)
2955 /* Found BOM, setup conversion and skip over it. */
2956 convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc);
2957 else
2958 /* No BOM found, rewind. */
2959 fseek(cookie.fp, 0L, SEEK_SET);
2961 #endif
2964 * Keep the sourcing name/lnum, for recursive calls.
2966 save_sourcing_name = sourcing_name;
2967 sourcing_name = fname_exp;
2968 save_sourcing_lnum = sourcing_lnum;
2969 sourcing_lnum = 0;
2971 #ifdef STARTUPTIME
2972 time_push(&tv_rel, &tv_start);
2973 #endif
2975 #ifdef FEAT_EVAL
2976 # ifdef FEAT_PROFILE
2977 if (do_profiling == PROF_YES)
2978 prof_child_enter(&wait_start); /* entering a child now */
2979 # endif
2981 /* Don't use local function variables, if called from a function.
2982 * Also starts profiling timer for nested script. */
2983 save_funccalp = save_funccal();
2986 * Check if this script was sourced before to finds its SID.
2987 * If it's new, generate a new SID.
2989 save_current_SID = current_SID;
2990 # ifdef UNIX
2991 stat_ok = (mch_stat((char *)fname_exp, &st) >= 0);
2992 # endif
2993 for (current_SID = script_items.ga_len; current_SID > 0; --current_SID)
2995 si = &SCRIPT_ITEM(current_SID);
2996 if (si->sn_name != NULL
2997 && (
2998 # ifdef UNIX
2999 /* Compare dev/ino when possible, it catches symbolic
3000 * links. Also compare file names, the inode may change
3001 * when the file was edited. */
3002 ((stat_ok && si->sn_dev != -1)
3003 && (si->sn_dev == st.st_dev
3004 && si->sn_ino == st.st_ino)) ||
3005 # endif
3006 fnamecmp(si->sn_name, fname_exp) == 0))
3007 break;
3009 if (current_SID == 0)
3011 current_SID = ++last_current_SID;
3012 if (ga_grow(&script_items, (int)(current_SID - script_items.ga_len))
3013 == FAIL)
3014 goto almosttheend;
3015 while (script_items.ga_len < current_SID)
3017 ++script_items.ga_len;
3018 SCRIPT_ITEM(script_items.ga_len).sn_name = NULL;
3019 # ifdef FEAT_PROFILE
3020 SCRIPT_ITEM(script_items.ga_len).sn_prof_on = FALSE;
3021 # endif
3023 si = &SCRIPT_ITEM(current_SID);
3024 si->sn_name = fname_exp;
3025 fname_exp = NULL;
3026 # ifdef UNIX
3027 if (stat_ok)
3029 si->sn_dev = st.st_dev;
3030 si->sn_ino = st.st_ino;
3032 else
3033 si->sn_dev = -1;
3034 # endif
3036 /* Allocate the local script variables to use for this script. */
3037 new_script_vars(current_SID);
3040 # ifdef FEAT_PROFILE
3041 if (do_profiling == PROF_YES)
3043 int forceit;
3045 /* Check if we do profiling for this script. */
3046 if (!si->sn_prof_on && has_profiling(TRUE, si->sn_name, &forceit))
3048 script_do_profile(si);
3049 si->sn_pr_force = forceit;
3051 if (si->sn_prof_on)
3053 ++si->sn_pr_count;
3054 profile_start(&si->sn_pr_start);
3055 profile_zero(&si->sn_pr_children);
3058 # endif
3059 #endif
3062 * Call do_cmdline, which will call getsourceline() to get the lines.
3064 do_cmdline(NULL, getsourceline, (void *)&cookie,
3065 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT);
3067 retval = OK;
3069 #ifdef FEAT_PROFILE
3070 if (do_profiling == PROF_YES)
3072 /* Get "si" again, "script_items" may have been reallocated. */
3073 si = &SCRIPT_ITEM(current_SID);
3074 if (si->sn_prof_on)
3076 profile_end(&si->sn_pr_start);
3077 profile_sub_wait(&wait_start, &si->sn_pr_start);
3078 profile_add(&si->sn_pr_total, &si->sn_pr_start);
3079 profile_self(&si->sn_pr_self, &si->sn_pr_start,
3080 &si->sn_pr_children);
3083 #endif
3085 if (got_int)
3086 EMSG(_(e_interr));
3087 sourcing_name = save_sourcing_name;
3088 sourcing_lnum = save_sourcing_lnum;
3089 if (p_verbose > 1)
3091 verbose_enter();
3092 smsg((char_u *)_("finished sourcing %s"), fname);
3093 if (sourcing_name != NULL)
3094 smsg((char_u *)_("continuing in %s"), sourcing_name);
3095 verbose_leave();
3097 #ifdef STARTUPTIME
3098 vim_snprintf(IObuff, IOSIZE, "sourcing %s", fname);
3099 time_msg(IObuff, &tv_start);
3100 time_pop(&tv_rel);
3101 #endif
3103 #ifdef FEAT_EVAL
3105 * After a "finish" in debug mode, need to break at first command of next
3106 * sourced file.
3108 if (save_debug_break_level > ex_nesting_level
3109 && debug_break_level == ex_nesting_level)
3110 ++debug_break_level;
3111 #endif
3113 #ifdef FEAT_EVAL
3114 almosttheend:
3115 current_SID = save_current_SID;
3116 restore_funccal(save_funccalp);
3117 # ifdef FEAT_PROFILE
3118 if (do_profiling == PROF_YES)
3119 prof_child_exit(&wait_start); /* leaving a child now */
3120 # endif
3121 #endif
3122 fclose(cookie.fp);
3123 vim_free(cookie.nextline);
3124 #ifdef FEAT_MBYTE
3125 convert_setup(&cookie.conv, NULL, NULL);
3126 #endif
3128 theend:
3129 vim_free(fname_exp);
3130 return retval;
3133 #if defined(FEAT_EVAL) || defined(PROTO)
3136 * ":scriptnames"
3138 /*ARGSUSED*/
3139 void
3140 ex_scriptnames(eap)
3141 exarg_T *eap;
3143 int i;
3145 for (i = 1; i <= script_items.ga_len && !got_int; ++i)
3146 if (SCRIPT_ITEM(i).sn_name != NULL)
3147 smsg((char_u *)"%3d: %s", i, SCRIPT_ITEM(i).sn_name);
3150 # if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
3152 * Fix slashes in the list of script names for 'shellslash'.
3154 void
3155 scriptnames_slash_adjust()
3157 int i;
3159 for (i = 1; i <= script_items.ga_len; ++i)
3160 if (SCRIPT_ITEM(i).sn_name != NULL)
3161 slash_adjust(SCRIPT_ITEM(i).sn_name);
3163 # endif
3166 * Get a pointer to a script name. Used for ":verbose set".
3168 char_u *
3169 get_scriptname(id)
3170 scid_T id;
3172 if (id == SID_MODELINE)
3173 return (char_u *)_("modeline");
3174 if (id == SID_CMDARG)
3175 return (char_u *)_("--cmd argument");
3176 if (id == SID_CARG)
3177 return (char_u *)_("-c argument");
3178 if (id == SID_ENV)
3179 return (char_u *)_("environment variable");
3180 if (id == SID_ERROR)
3181 return (char_u *)_("error handler");
3182 return SCRIPT_ITEM(id).sn_name;
3185 # if defined(EXITFREE) || defined(PROTO)
3186 void
3187 free_scriptnames()
3189 int i;
3191 for (i = script_items.ga_len; i > 0; --i)
3192 vim_free(SCRIPT_ITEM(i).sn_name);
3193 ga_clear(&script_items);
3195 # endif
3197 #endif
3199 #if defined(USE_CR) || defined(PROTO)
3201 # if defined(__MSL__) && (__MSL__ >= 22)
3203 * Newer version of the Metrowerks library handle DOS and UNIX files
3204 * without help.
3205 * Test with earlier versions, MSL 2.2 is the library supplied with
3206 * Codewarrior Pro 2.
3208 char *
3209 fgets_cr(s, n, stream)
3210 char *s;
3211 int n;
3212 FILE *stream;
3214 return fgets(s, n, stream);
3216 # else
3218 * Version of fgets() which also works for lines ending in a <CR> only
3219 * (Macintosh format).
3220 * For older versions of the Metrowerks library.
3221 * At least CodeWarrior 9 needed this code.
3223 char *
3224 fgets_cr(s, n, stream)
3225 char *s;
3226 int n;
3227 FILE *stream;
3229 int c = 0;
3230 int char_read = 0;
3232 while (!feof(stream) && c != '\r' && c != '\n' && char_read < n - 1)
3234 c = fgetc(stream);
3235 s[char_read++] = c;
3236 /* If the file is in DOS format, we need to skip a NL after a CR. I
3237 * thought it was the other way around, but this appears to work... */
3238 if (c == '\n')
3240 c = fgetc(stream);
3241 if (c != '\r')
3242 ungetc(c, stream);
3246 s[char_read] = 0;
3247 if (char_read == 0)
3248 return NULL;
3250 if (feof(stream) && char_read == 1)
3251 return NULL;
3253 return s;
3255 # endif
3256 #endif
3259 * Get one full line from a sourced file.
3260 * Called by do_cmdline() when it's called from do_source().
3262 * Return a pointer to the line in allocated memory.
3263 * Return NULL for end-of-file or some error.
3265 /* ARGSUSED */
3266 char_u *
3267 getsourceline(c, cookie, indent)
3268 int c; /* not used */
3269 void *cookie;
3270 int indent; /* not used */
3272 struct source_cookie *sp = (struct source_cookie *)cookie;
3273 char_u *line;
3274 char_u *p, *s;
3276 #ifdef FEAT_EVAL
3277 /* If breakpoints have been added/deleted need to check for it. */
3278 if (sp->dbg_tick < debug_tick)
3280 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
3281 sp->dbg_tick = debug_tick;
3283 # ifdef FEAT_PROFILE
3284 if (do_profiling == PROF_YES)
3285 script_line_end();
3286 # endif
3287 #endif
3289 * Get current line. If there is a read-ahead line, use it, otherwise get
3290 * one now.
3292 if (sp->finished)
3293 line = NULL;
3294 else if (sp->nextline == NULL)
3295 line = get_one_sourceline(sp);
3296 else
3298 line = sp->nextline;
3299 sp->nextline = NULL;
3300 ++sourcing_lnum;
3302 #ifdef FEAT_PROFILE
3303 if (line != NULL && do_profiling == PROF_YES)
3304 script_line_start();
3305 #endif
3307 /* Only concatenate lines starting with a \ when 'cpoptions' doesn't
3308 * contain the 'C' flag. */
3309 if (line != NULL && (vim_strchr(p_cpo, CPO_CONCAT) == NULL))
3311 /* compensate for the one line read-ahead */
3312 --sourcing_lnum;
3313 for (;;)
3315 sp->nextline = get_one_sourceline(sp);
3316 if (sp->nextline == NULL)
3317 break;
3318 p = skipwhite(sp->nextline);
3319 if (*p != '\\')
3320 break;
3321 s = alloc((int)(STRLEN(line) + STRLEN(p)));
3322 if (s == NULL) /* out of memory */
3323 break;
3324 STRCPY(s, line);
3325 STRCAT(s, p + 1);
3326 vim_free(line);
3327 line = s;
3328 vim_free(sp->nextline);
3332 #ifdef FEAT_MBYTE
3333 if (line != NULL && sp->conv.vc_type != CONV_NONE)
3335 /* Convert the encoding of the script line. */
3336 s = string_convert(&sp->conv, line, NULL);
3337 if (s != NULL)
3339 vim_free(line);
3340 line = s;
3343 #endif
3345 #ifdef FEAT_EVAL
3346 /* Did we encounter a breakpoint? */
3347 if (sp->breakpoint != 0 && sp->breakpoint <= sourcing_lnum)
3349 dbg_breakpoint(sp->fname, sourcing_lnum);
3350 /* Find next breakpoint. */
3351 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
3352 sp->dbg_tick = debug_tick;
3354 #endif
3356 return line;
3359 static char_u *
3360 get_one_sourceline(sp)
3361 struct source_cookie *sp;
3363 garray_T ga;
3364 int len;
3365 int c;
3366 char_u *buf;
3367 #ifdef USE_CRNL
3368 int has_cr; /* CR-LF found */
3369 #endif
3370 #ifdef USE_CR
3371 char_u *scan;
3372 #endif
3373 int have_read = FALSE;
3375 /* use a growarray to store the sourced line */
3376 ga_init2(&ga, 1, 250);
3379 * Loop until there is a finished line (or end-of-file).
3381 sourcing_lnum++;
3382 for (;;)
3384 /* make room to read at least 120 (more) characters */
3385 if (ga_grow(&ga, 120) == FAIL)
3386 break;
3387 buf = (char_u *)ga.ga_data;
3389 #ifdef USE_CR
3390 if (sp->fileformat == EOL_MAC)
3392 if (fgets_cr((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
3393 sp->fp) == NULL)
3394 break;
3396 else
3397 #endif
3398 if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
3399 sp->fp) == NULL)
3400 break;
3401 len = ga.ga_len + (int)STRLEN(buf + ga.ga_len);
3402 #ifdef USE_CRNL
3403 /* Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the
3404 * CTRL-Z by its own, or after a NL. */
3405 if ( (len == 1 || (len >= 2 && buf[len - 2] == '\n'))
3406 && sp->fileformat == EOL_DOS
3407 && buf[len - 1] == Ctrl_Z)
3409 buf[len - 1] = NUL;
3410 break;
3412 #endif
3414 #ifdef USE_CR
3415 /* If the read doesn't stop on a new line, and there's
3416 * some CR then we assume a Mac format */
3417 if (sp->fileformat == EOL_UNKNOWN)
3419 if (buf[len - 1] != '\n' && vim_strchr(buf, '\r') != NULL)
3420 sp->fileformat = EOL_MAC;
3421 else
3422 sp->fileformat = EOL_UNIX;
3425 if (sp->fileformat == EOL_MAC)
3427 scan = vim_strchr(buf, '\r');
3429 if (scan != NULL)
3431 *scan = '\n';
3432 if (*(scan + 1) != 0)
3434 *(scan + 1) = 0;
3435 fseek(sp->fp, (long)(scan - buf - len + 1), SEEK_CUR);
3438 len = STRLEN(buf);
3440 #endif
3442 have_read = TRUE;
3443 ga.ga_len = len;
3445 /* If the line was longer than the buffer, read more. */
3446 if (ga.ga_maxlen - ga.ga_len == 1 && buf[len - 1] != '\n')
3447 continue;
3449 if (len >= 1 && buf[len - 1] == '\n') /* remove trailing NL */
3451 #ifdef USE_CRNL
3452 has_cr = (len >= 2 && buf[len - 2] == '\r');
3453 if (sp->fileformat == EOL_UNKNOWN)
3455 if (has_cr)
3456 sp->fileformat = EOL_DOS;
3457 else
3458 sp->fileformat = EOL_UNIX;
3461 if (sp->fileformat == EOL_DOS)
3463 if (has_cr) /* replace trailing CR */
3465 buf[len - 2] = '\n';
3466 --len;
3467 --ga.ga_len;
3469 else /* lines like ":map xx yy^M" will have failed */
3471 if (!sp->error)
3473 msg_source(hl_attr(HLF_W));
3474 EMSG(_("W15: Warning: Wrong line separator, ^M may be missing"));
3476 sp->error = TRUE;
3477 sp->fileformat = EOL_UNIX;
3480 #endif
3481 /* The '\n' is escaped if there is an odd number of ^V's just
3482 * before it, first set "c" just before the 'V's and then check
3483 * len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo */
3484 for (c = len - 2; c >= 0 && buf[c] == Ctrl_V; c--)
3486 if ((len & 1) != (c & 1)) /* escaped NL, read more */
3488 sourcing_lnum++;
3489 continue;
3492 buf[len - 1] = NUL; /* remove the NL */
3496 * Check for ^C here now and then, so recursive :so can be broken.
3498 line_breakcheck();
3499 break;
3502 if (have_read)
3503 return (char_u *)ga.ga_data;
3505 vim_free(ga.ga_data);
3506 return NULL;
3509 #if defined(FEAT_PROFILE) || defined(PROTO)
3511 * Called when starting to read a script line.
3512 * "sourcing_lnum" must be correct!
3513 * When skipping lines it may not actually be executed, but we won't find out
3514 * until later and we need to store the time now.
3516 void
3517 script_line_start()
3519 scriptitem_T *si;
3520 sn_prl_T *pp;
3522 if (current_SID <= 0 || current_SID > script_items.ga_len)
3523 return;
3524 si = &SCRIPT_ITEM(current_SID);
3525 if (si->sn_prof_on && sourcing_lnum >= 1)
3527 /* Grow the array before starting the timer, so that the time spend
3528 * here isn't counted. */
3529 ga_grow(&si->sn_prl_ga, (int)(sourcing_lnum - si->sn_prl_ga.ga_len));
3530 si->sn_prl_idx = sourcing_lnum - 1;
3531 while (si->sn_prl_ga.ga_len <= si->sn_prl_idx
3532 && si->sn_prl_ga.ga_len < si->sn_prl_ga.ga_maxlen)
3534 /* Zero counters for a line that was not used before. */
3535 pp = &PRL_ITEM(si, si->sn_prl_ga.ga_len);
3536 pp->snp_count = 0;
3537 profile_zero(&pp->sn_prl_total);
3538 profile_zero(&pp->sn_prl_self);
3539 ++si->sn_prl_ga.ga_len;
3541 si->sn_prl_execed = FALSE;
3542 profile_start(&si->sn_prl_start);
3543 profile_zero(&si->sn_prl_children);
3544 profile_get_wait(&si->sn_prl_wait);
3549 * Called when actually executing a function line.
3551 void
3552 script_line_exec()
3554 scriptitem_T *si;
3556 if (current_SID <= 0 || current_SID > script_items.ga_len)
3557 return;
3558 si = &SCRIPT_ITEM(current_SID);
3559 if (si->sn_prof_on && si->sn_prl_idx >= 0)
3560 si->sn_prl_execed = TRUE;
3564 * Called when done with a function line.
3566 void
3567 script_line_end()
3569 scriptitem_T *si;
3570 sn_prl_T *pp;
3572 if (current_SID <= 0 || current_SID > script_items.ga_len)
3573 return;
3574 si = &SCRIPT_ITEM(current_SID);
3575 if (si->sn_prof_on && si->sn_prl_idx >= 0
3576 && si->sn_prl_idx < si->sn_prl_ga.ga_len)
3578 if (si->sn_prl_execed)
3580 pp = &PRL_ITEM(si, si->sn_prl_idx);
3581 ++pp->snp_count;
3582 profile_end(&si->sn_prl_start);
3583 profile_sub_wait(&si->sn_prl_wait, &si->sn_prl_start);
3584 profile_add(&pp->sn_prl_total, &si->sn_prl_start);
3585 profile_self(&pp->sn_prl_self, &si->sn_prl_start,
3586 &si->sn_prl_children);
3588 si->sn_prl_idx = -1;
3591 #endif
3594 * ":scriptencoding": Set encoding conversion for a sourced script.
3595 * Without the multi-byte feature it's simply ignored.
3597 /*ARGSUSED*/
3598 void
3599 ex_scriptencoding(eap)
3600 exarg_T *eap;
3602 #ifdef FEAT_MBYTE
3603 struct source_cookie *sp;
3604 char_u *name;
3606 if (!getline_equal(eap->getline, eap->cookie, getsourceline))
3608 EMSG(_("E167: :scriptencoding used outside of a sourced file"));
3609 return;
3612 if (*eap->arg != NUL)
3614 name = enc_canonize(eap->arg);
3615 if (name == NULL) /* out of memory */
3616 return;
3618 else
3619 name = eap->arg;
3621 /* Setup for conversion from the specified encoding to 'encoding'. */
3622 sp = (struct source_cookie *)getline_cookie(eap->getline, eap->cookie);
3623 convert_setup(&sp->conv, name, p_enc);
3625 if (name != eap->arg)
3626 vim_free(name);
3627 #endif
3630 #if defined(FEAT_EVAL) || defined(PROTO)
3632 * ":finish": Mark a sourced file as finished.
3634 void
3635 ex_finish(eap)
3636 exarg_T *eap;
3638 if (getline_equal(eap->getline, eap->cookie, getsourceline))
3639 do_finish(eap, FALSE);
3640 else
3641 EMSG(_("E168: :finish used outside of a sourced file"));
3645 * Mark a sourced file as finished. Possibly makes the ":finish" pending.
3646 * Also called for a pending finish at the ":endtry" or after returning from
3647 * an extra do_cmdline(). "reanimate" is used in the latter case.
3649 void
3650 do_finish(eap, reanimate)
3651 exarg_T *eap;
3652 int reanimate;
3654 int idx;
3656 if (reanimate)
3657 ((struct source_cookie *)getline_cookie(eap->getline,
3658 eap->cookie))->finished = FALSE;
3661 * Cleanup (and inactivate) conditionals, but stop when a try conditional
3662 * not in its finally clause (which then is to be executed next) is found.
3663 * In this case, make the ":finish" pending for execution at the ":endtry".
3664 * Otherwise, finish normally.
3666 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
3667 if (idx >= 0)
3669 eap->cstack->cs_pending[idx] = CSTP_FINISH;
3670 report_make_pending(CSTP_FINISH, NULL);
3672 else
3673 ((struct source_cookie *)getline_cookie(eap->getline,
3674 eap->cookie))->finished = TRUE;
3679 * Return TRUE when a sourced file had the ":finish" command: Don't give error
3680 * message for missing ":endif".
3681 * Return FALSE when not sourcing a file.
3684 source_finished(fgetline, cookie)
3685 char_u *(*fgetline) __ARGS((int, void *, int));
3686 void *cookie;
3688 return (getline_equal(fgetline, cookie, getsourceline)
3689 && ((struct source_cookie *)getline_cookie(
3690 fgetline, cookie))->finished);
3692 #endif
3694 #if defined(FEAT_LISTCMDS) || defined(PROTO)
3696 * ":checktime [buffer]"
3698 void
3699 ex_checktime(eap)
3700 exarg_T *eap;
3702 buf_T *buf;
3703 int save_no_check_timestamps = no_check_timestamps;
3705 no_check_timestamps = 0;
3706 if (eap->addr_count == 0) /* default is all buffers */
3707 check_timestamps(FALSE);
3708 else
3710 buf = buflist_findnr((int)eap->line2);
3711 if (buf != NULL) /* cannot happen? */
3712 (void)buf_check_timestamp(buf, FALSE);
3714 no_check_timestamps = save_no_check_timestamps;
3716 #endif
3718 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3719 && (defined(FEAT_EVAL) || defined(FEAT_MULTI_LANG))
3720 static char *get_locale_val __ARGS((int what));
3722 static char *
3723 get_locale_val(what)
3724 int what;
3726 char *loc;
3728 /* Obtain the locale value from the libraries. For DJGPP this is
3729 * redefined and it doesn't use the arguments. */
3730 loc = setlocale(what, NULL);
3732 # ifdef WIN32
3733 if (loc != NULL)
3735 char_u *p;
3737 /* setocale() returns something like "LC_COLLATE=<name>;LC_..." when
3738 * one of the values (e.g., LC_CTYPE) differs. */
3739 p = vim_strchr(loc, '=');
3740 if (p != NULL)
3742 loc = ++p;
3743 while (*p != NUL) /* remove trailing newline */
3745 if (*p < ' ' || *p == ';')
3747 *p = NUL;
3748 break;
3750 ++p;
3754 # endif
3756 return loc;
3758 #endif
3761 #ifdef WIN32
3763 * On MS-Windows locale names are strings like "German_Germany.1252", but
3764 * gettext expects "de". Try to translate one into another here for a few
3765 * supported languages.
3767 static char_u *
3768 gettext_lang(char_u *name)
3770 int i;
3771 static char *(mtable[]) = {
3772 "afrikaans", "af",
3773 "czech", "cs",
3774 "dutch", "nl",
3775 "german", "de",
3776 "english_united kingdom", "en_GB",
3777 "spanish", "es",
3778 "french", "fr",
3779 "italian", "it",
3780 "japanese", "ja",
3781 "korean", "ko",
3782 "norwegian", "no",
3783 "polish", "pl",
3784 "russian", "ru",
3785 "slovak", "sk",
3786 "swedish", "sv",
3787 "ukrainian", "uk",
3788 "chinese_china", "zh_CN",
3789 "chinese_taiwan", "zh_TW",
3790 NULL};
3792 for (i = 0; mtable[i] != NULL; i += 2)
3793 if (STRNICMP(mtable[i], name, STRLEN(mtable[i])) == 0)
3794 return mtable[i + 1];
3795 return name;
3797 #endif
3799 #if defined(FEAT_MULTI_LANG) || defined(PROTO)
3801 * Obtain the current messages language. Used to set the default for
3802 * 'helplang'. May return NULL or an empty string.
3804 char_u *
3805 get_mess_lang()
3807 char_u *p;
3809 # if (defined(HAVE_LOCALE_H) || defined(X_LOCALE))
3810 # if defined(LC_MESSAGES)
3811 p = (char_u *)get_locale_val(LC_MESSAGES);
3812 # else
3813 /* This is necessary for Win32, where LC_MESSAGES is not defined and $LANG
3814 * may be set to the LCID number. LC_COLLATE is the best guess, LC_TIME
3815 * and LC_MONETARY may be set differently for a Japanese working in the
3816 * US. */
3817 p = (char_u *)get_locale_val(LC_COLLATE);
3818 # endif
3819 # else
3820 p = mch_getenv((char_u *)"LC_ALL");
3821 if (p == NULL || *p == NUL)
3823 p = mch_getenv((char_u *)"LC_MESSAGES");
3824 if (p == NULL || *p == NUL)
3825 p = mch_getenv((char_u *)"LANG");
3827 # endif
3828 # ifdef WIN32
3829 p = gettext_lang(p);
3830 # endif
3831 return p;
3833 #endif
3835 /* Complicated #if; matches with where get_mess_env() is used below. */
3836 #if (defined(FEAT_EVAL) && !((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3837 && defined(LC_MESSAGES))) \
3838 || ((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3839 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)) \
3840 && !defined(LC_MESSAGES))
3841 static char_u *get_mess_env __ARGS((void));
3844 * Get the language used for messages from the environment.
3846 static char_u *
3847 get_mess_env()
3849 char_u *p;
3851 p = mch_getenv((char_u *)"LC_ALL");
3852 if (p == NULL || *p == NUL)
3854 p = mch_getenv((char_u *)"LC_MESSAGES");
3855 if (p == NULL || *p == NUL)
3857 p = mch_getenv((char_u *)"LANG");
3858 if (p != NULL && VIM_ISDIGIT(*p))
3859 p = NULL; /* ignore something like "1043" */
3860 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
3861 if (p == NULL || *p == NUL)
3862 p = (char_u *)get_locale_val(LC_CTYPE);
3863 # endif
3866 return p;
3868 #endif
3870 #if defined(FEAT_EVAL) || defined(PROTO)
3873 * Set the "v:lang" variable according to the current locale setting.
3874 * Also do "v:lc_time"and "v:ctype".
3876 void
3877 set_lang_var()
3879 char_u *loc;
3881 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
3882 loc = (char_u *)get_locale_val(LC_CTYPE);
3883 # else
3884 /* setlocale() not supported: use the default value */
3885 loc = (char_u *)"C";
3886 # endif
3887 set_vim_var_string(VV_CTYPE, loc, -1);
3889 /* When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall
3890 * back to LC_CTYPE if it's empty. */
3891 # if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) && defined(LC_MESSAGES)
3892 loc = (char_u *)get_locale_val(LC_MESSAGES);
3893 # else
3894 loc = get_mess_env();
3895 # endif
3896 set_vim_var_string(VV_LANG, loc, -1);
3898 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
3899 loc = (char_u *)get_locale_val(LC_TIME);
3900 # endif
3901 set_vim_var_string(VV_LC_TIME, loc, -1);
3903 #endif
3905 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3906 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE))
3908 * ":language": Set the language (locale).
3910 void
3911 ex_language(eap)
3912 exarg_T *eap;
3914 char *loc;
3915 char_u *p;
3916 char_u *name;
3917 int what = LC_ALL;
3918 char *whatstr = "";
3919 #ifdef LC_MESSAGES
3920 # define VIM_LC_MESSAGES LC_MESSAGES
3921 #else
3922 # define VIM_LC_MESSAGES 6789
3923 #endif
3925 name = eap->arg;
3927 /* Check for "messages {name}", "ctype {name}" or "time {name}" argument.
3928 * Allow abbreviation, but require at least 3 characters to avoid
3929 * confusion with a two letter language name "me" or "ct". */
3930 p = skiptowhite(eap->arg);
3931 if ((*p == NUL || vim_iswhite(*p)) && p - eap->arg >= 3)
3933 if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0)
3935 what = VIM_LC_MESSAGES;
3936 name = skipwhite(p);
3937 whatstr = "messages ";
3939 else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0)
3941 what = LC_CTYPE;
3942 name = skipwhite(p);
3943 whatstr = "ctype ";
3945 else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0)
3947 what = LC_TIME;
3948 name = skipwhite(p);
3949 whatstr = "time ";
3953 if (*name == NUL)
3955 #ifndef LC_MESSAGES
3956 if (what == VIM_LC_MESSAGES)
3957 p = get_mess_env();
3958 else
3959 #endif
3960 p = (char_u *)setlocale(what, NULL);
3961 if (p == NULL || *p == NUL)
3962 p = (char_u *)"Unknown";
3963 smsg((char_u *)_("Current %slanguage: \"%s\""), whatstr, p);
3965 else
3967 #ifndef LC_MESSAGES
3968 if (what == VIM_LC_MESSAGES)
3969 loc = "";
3970 else
3971 #endif
3972 loc = setlocale(what, (char *)name);
3973 if (loc == NULL)
3974 EMSG2(_("E197: Cannot set language to \"%s\""), name);
3975 else
3977 #ifdef HAVE_NL_MSG_CAT_CNTR
3978 /* Need to do this for GNU gettext, otherwise cached translations
3979 * will be used again. */
3980 extern int _nl_msg_cat_cntr;
3982 ++_nl_msg_cat_cntr;
3983 #endif
3984 /* Reset $LC_ALL, otherwise it would overrule everything. */
3985 vim_setenv((char_u *)"LC_ALL", (char_u *)"");
3987 if (what != LC_TIME)
3989 /* Tell gettext() what to translate to. It apparently doesn't
3990 * use the currently effective locale. Also do this when
3991 * FEAT_GETTEXT isn't defined, so that shell commands use this
3992 * value. */
3993 if (what == LC_ALL)
3995 vim_setenv((char_u *)"LANG", name);
3996 # ifdef WIN32
3997 /* Apparently MS-Windows printf() may cause a crash when
3998 * we give it 8-bit text while it's expecting text in the
3999 * current locale. This call avoids that. */
4000 setlocale(LC_CTYPE, "C");
4001 # endif
4003 if (what != LC_CTYPE)
4005 char_u *mname;
4006 #ifdef WIN32
4007 mname = gettext_lang(name);
4008 #else
4009 mname = name;
4010 #endif
4011 vim_setenv((char_u *)"LC_MESSAGES", mname);
4012 #ifdef FEAT_MULTI_LANG
4013 set_helplang_default(mname);
4014 #endif
4017 /* Set $LC_CTYPE, because it overrules $LANG, and
4018 * gtk_set_locale() calls setlocale() again. gnome_init()
4019 * sets $LC_CTYPE to "en_US" (that's a bug!). */
4020 if (what != VIM_LC_MESSAGES)
4021 vim_setenv((char_u *)"LC_CTYPE", name);
4022 # ifdef FEAT_GUI_GTK
4023 /* Let GTK know what locale we're using. Not sure this is
4024 * really needed... */
4025 if (gui.in_use)
4026 (void)gtk_set_locale();
4027 # endif
4030 # ifdef FEAT_EVAL
4031 /* Set v:lang, v:lc_time and v:ctype to the final result. */
4032 set_lang_var();
4033 # endif
4038 # if defined(FEAT_CMDL_COMPL) || defined(PROTO)
4040 * Function given to ExpandGeneric() to obtain the possible arguments of the
4041 * ":language" command.
4043 /*ARGSUSED*/
4044 char_u *
4045 get_lang_arg(xp, idx)
4046 expand_T *xp;
4047 int idx;
4049 if (idx == 0)
4050 return (char_u *)"messages";
4051 if (idx == 1)
4052 return (char_u *)"ctype";
4053 if (idx == 2)
4054 return (char_u *)"time";
4055 return NULL;
4057 # endif
4059 #endif