Update credits
[MacVim.git] / src / ex_cmds2.c
blob7071794c9602880895dd56441380ef3027bb2a56
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 = 0;
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;
903 * Put the time "msec" past now in "tm".
905 void
906 profile_setlimit(msec, tm)
907 long msec;
908 proftime_T *tm;
910 if (msec <= 0) /* no limit */
911 profile_zero(tm);
912 else
914 # ifdef WIN3264
915 LARGE_INTEGER fr;
917 QueryPerformanceCounter(tm);
918 QueryPerformanceFrequency(&fr);
919 tm->QuadPart += (LONGLONG)((double)msec / 1000.0 * (double)fr.QuadPart);
920 # else
921 long usec;
923 gettimeofday(tm, NULL);
924 usec = (long)tm->tv_usec + (long)msec * 1000;
925 tm->tv_usec = usec % 1000000L;
926 tm->tv_sec += usec / 1000000L;
927 # endif
932 * Return TRUE if the current time is past "tm".
935 profile_passed_limit(tm)
936 proftime_T *tm;
938 proftime_T now;
940 # ifdef WIN3264
941 if (tm->QuadPart == 0) /* timer was not set */
942 return FALSE;
943 QueryPerformanceCounter(&now);
944 return (now.QuadPart > tm->QuadPart);
945 # else
946 if (tm->tv_sec == 0) /* timer was not set */
947 return FALSE;
948 gettimeofday(&now, NULL);
949 return (now.tv_sec > tm->tv_sec
950 || (now.tv_sec == tm->tv_sec && now.tv_usec > tm->tv_usec));
951 # endif
955 * Set the time in "tm" to zero.
957 void
958 profile_zero(tm)
959 proftime_T *tm;
961 # ifdef WIN3264
962 tm->QuadPart = 0;
963 # else
964 tm->tv_usec = 0;
965 tm->tv_sec = 0;
966 # endif
969 # endif /* FEAT_PROFILE || FEAT_RELTIME */
971 # if defined(FEAT_PROFILE) || defined(PROTO)
973 * Functions for profiling.
975 static void script_do_profile __ARGS((scriptitem_T *si));
976 static void script_dump_profile __ARGS((FILE *fd));
977 static proftime_T prof_wait_time;
980 * Add the time "tm2" to "tm".
982 void
983 profile_add(tm, tm2)
984 proftime_T *tm, *tm2;
986 # ifdef WIN3264
987 tm->QuadPart += tm2->QuadPart;
988 # else
989 tm->tv_usec += tm2->tv_usec;
990 tm->tv_sec += tm2->tv_sec;
991 if (tm->tv_usec >= 1000000)
993 tm->tv_usec -= 1000000;
994 ++tm->tv_sec;
996 # endif
1000 * Add the "self" time from the total time and the children's time.
1002 void
1003 profile_self(self, total, children)
1004 proftime_T *self, *total, *children;
1006 /* Check that the result won't be negative. Can happen with recursive
1007 * calls. */
1008 #ifdef WIN3264
1009 if (total->QuadPart <= children->QuadPart)
1010 return;
1011 #else
1012 if (total->tv_sec < children->tv_sec
1013 || (total->tv_sec == children->tv_sec
1014 && total->tv_usec <= children->tv_usec))
1015 return;
1016 #endif
1017 profile_add(self, total);
1018 profile_sub(self, children);
1022 * Get the current waittime.
1024 void
1025 profile_get_wait(tm)
1026 proftime_T *tm;
1028 *tm = prof_wait_time;
1032 * Subtract the passed waittime since "tm" from "tma".
1034 void
1035 profile_sub_wait(tm, tma)
1036 proftime_T *tm, *tma;
1038 proftime_T tm3 = prof_wait_time;
1040 profile_sub(&tm3, tm);
1041 profile_sub(tma, &tm3);
1045 * Return TRUE if "tm1" and "tm2" are equal.
1048 profile_equal(tm1, tm2)
1049 proftime_T *tm1, *tm2;
1051 # ifdef WIN3264
1052 return (tm1->QuadPart == tm2->QuadPart);
1053 # else
1054 return (tm1->tv_usec == tm2->tv_usec && tm1->tv_sec == tm2->tv_sec);
1055 # endif
1059 * Return <0, 0 or >0 if "tm1" < "tm2", "tm1" == "tm2" or "tm1" > "tm2"
1062 profile_cmp(tm1, tm2)
1063 proftime_T *tm1, *tm2;
1065 # ifdef WIN3264
1066 return (int)(tm2->QuadPart - tm1->QuadPart);
1067 # else
1068 if (tm1->tv_sec == tm2->tv_sec)
1069 return tm2->tv_usec - tm1->tv_usec;
1070 return tm2->tv_sec - tm1->tv_sec;
1071 # endif
1074 static char_u *profile_fname = NULL;
1075 static proftime_T pause_time;
1078 * ":profile cmd args"
1080 void
1081 ex_profile(eap)
1082 exarg_T *eap;
1084 char_u *e;
1085 int len;
1087 e = skiptowhite(eap->arg);
1088 len = (int)(e - eap->arg);
1089 e = skipwhite(e);
1091 if (len == 5 && STRNCMP(eap->arg, "start", 5) == 0 && *e != NUL)
1093 vim_free(profile_fname);
1094 profile_fname = vim_strsave(e);
1095 do_profiling = PROF_YES;
1096 profile_zero(&prof_wait_time);
1097 set_vim_var_nr(VV_PROFILING, 1L);
1099 else if (do_profiling == PROF_NONE)
1100 EMSG(_("E750: First use :profile start <fname>"));
1101 else if (STRCMP(eap->arg, "pause") == 0)
1103 if (do_profiling == PROF_YES)
1104 profile_start(&pause_time);
1105 do_profiling = PROF_PAUSED;
1107 else if (STRCMP(eap->arg, "continue") == 0)
1109 if (do_profiling == PROF_PAUSED)
1111 profile_end(&pause_time);
1112 profile_add(&prof_wait_time, &pause_time);
1114 do_profiling = PROF_YES;
1116 else
1118 /* The rest is similar to ":breakadd". */
1119 ex_breakadd(eap);
1124 * Dump the profiling info.
1126 void
1127 profile_dump()
1129 FILE *fd;
1131 if (profile_fname != NULL)
1133 fd = mch_fopen((char *)profile_fname, "w");
1134 if (fd == NULL)
1135 EMSG2(_(e_notopen), profile_fname);
1136 else
1138 script_dump_profile(fd);
1139 func_dump_profile(fd);
1140 fclose(fd);
1146 * Start profiling script "fp".
1148 static void
1149 script_do_profile(si)
1150 scriptitem_T *si;
1152 si->sn_pr_count = 0;
1153 profile_zero(&si->sn_pr_total);
1154 profile_zero(&si->sn_pr_self);
1156 ga_init2(&si->sn_prl_ga, sizeof(sn_prl_T), 100);
1157 si->sn_prl_idx = -1;
1158 si->sn_prof_on = TRUE;
1159 si->sn_pr_nest = 0;
1163 * save time when starting to invoke another script or function.
1165 void
1166 script_prof_save(tm)
1167 proftime_T *tm; /* place to store wait time */
1169 scriptitem_T *si;
1171 if (current_SID > 0 && current_SID <= script_items.ga_len)
1173 si = &SCRIPT_ITEM(current_SID);
1174 if (si->sn_prof_on && si->sn_pr_nest++ == 0)
1175 profile_start(&si->sn_pr_child);
1177 profile_get_wait(tm);
1181 * Count time spent in children after invoking another script or function.
1183 void
1184 script_prof_restore(tm)
1185 proftime_T *tm;
1187 scriptitem_T *si;
1189 if (current_SID > 0 && current_SID <= script_items.ga_len)
1191 si = &SCRIPT_ITEM(current_SID);
1192 if (si->sn_prof_on && --si->sn_pr_nest == 0)
1194 profile_end(&si->sn_pr_child);
1195 profile_sub_wait(tm, &si->sn_pr_child); /* don't count wait time */
1196 profile_add(&si->sn_pr_children, &si->sn_pr_child);
1197 profile_add(&si->sn_prl_children, &si->sn_pr_child);
1202 static proftime_T inchar_time;
1205 * Called when starting to wait for the user to type a character.
1207 void
1208 prof_inchar_enter()
1210 profile_start(&inchar_time);
1214 * Called when finished waiting for the user to type a character.
1216 void
1217 prof_inchar_exit()
1219 profile_end(&inchar_time);
1220 profile_add(&prof_wait_time, &inchar_time);
1224 * Dump the profiling results for all scripts in file "fd".
1226 static void
1227 script_dump_profile(fd)
1228 FILE *fd;
1230 int id;
1231 scriptitem_T *si;
1232 int i;
1233 FILE *sfd;
1234 sn_prl_T *pp;
1236 for (id = 1; id <= script_items.ga_len; ++id)
1238 si = &SCRIPT_ITEM(id);
1239 if (si->sn_prof_on)
1241 fprintf(fd, "SCRIPT %s\n", si->sn_name);
1242 if (si->sn_pr_count == 1)
1243 fprintf(fd, "Sourced 1 time\n");
1244 else
1245 fprintf(fd, "Sourced %d times\n", si->sn_pr_count);
1246 fprintf(fd, "Total time: %s\n", profile_msg(&si->sn_pr_total));
1247 fprintf(fd, " Self time: %s\n", profile_msg(&si->sn_pr_self));
1248 fprintf(fd, "\n");
1249 fprintf(fd, "count total (s) self (s)\n");
1251 sfd = mch_fopen((char *)si->sn_name, "r");
1252 if (sfd == NULL)
1253 fprintf(fd, "Cannot open file!\n");
1254 else
1256 for (i = 0; i < si->sn_prl_ga.ga_len; ++i)
1258 if (vim_fgets(IObuff, IOSIZE, sfd))
1259 break;
1260 pp = &PRL_ITEM(si, i);
1261 if (pp->snp_count > 0)
1263 fprintf(fd, "%5d ", pp->snp_count);
1264 if (profile_equal(&pp->sn_prl_total, &pp->sn_prl_self))
1265 fprintf(fd, " ");
1266 else
1267 fprintf(fd, "%s ", profile_msg(&pp->sn_prl_total));
1268 fprintf(fd, "%s ", profile_msg(&pp->sn_prl_self));
1270 else
1271 fprintf(fd, " ");
1272 fprintf(fd, "%s", IObuff);
1274 fclose(sfd);
1276 fprintf(fd, "\n");
1282 * Return TRUE when a function defined in the current script should be
1283 * profiled.
1286 prof_def_func()
1288 if (current_SID > 0)
1289 return SCRIPT_ITEM(current_SID).sn_pr_force;
1290 return FALSE;
1293 # endif
1294 #endif
1297 * If 'autowrite' option set, try to write the file.
1298 * Careful: autocommands may make "buf" invalid!
1300 * return FAIL for failure, OK otherwise
1303 autowrite(buf, forceit)
1304 buf_T *buf;
1305 int forceit;
1307 int r;
1309 if (!(p_aw || p_awa) || !p_write
1310 #ifdef FEAT_QUICKFIX
1311 /* never autowrite a "nofile" or "nowrite" buffer */
1312 || bt_dontwrite(buf)
1313 #endif
1314 || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL)
1315 return FAIL;
1316 r = buf_write_all(buf, forceit);
1318 /* Writing may succeed but the buffer still changed, e.g., when there is a
1319 * conversion error. We do want to return FAIL then. */
1320 if (buf_valid(buf) && bufIsChanged(buf))
1321 r = FAIL;
1322 return r;
1326 * flush all buffers, except the ones that are readonly
1328 void
1329 autowrite_all()
1331 buf_T *buf;
1333 if (!(p_aw || p_awa) || !p_write)
1334 return;
1335 for (buf = firstbuf; buf; buf = buf->b_next)
1336 if (bufIsChanged(buf) && !buf->b_p_ro)
1338 (void)buf_write_all(buf, FALSE);
1339 #ifdef FEAT_AUTOCMD
1340 /* an autocommand may have deleted the buffer */
1341 if (!buf_valid(buf))
1342 buf = firstbuf;
1343 #endif
1348 * return TRUE if buffer was changed and cannot be abandoned.
1350 /*ARGSUSED*/
1352 check_changed(buf, checkaw, mult_win, forceit, allbuf)
1353 buf_T *buf;
1354 int checkaw; /* do autowrite if buffer was changed */
1355 int mult_win; /* check also when several wins for the buf */
1356 int forceit;
1357 int allbuf; /* may write all buffers */
1359 if ( !forceit
1360 && bufIsChanged(buf)
1361 && (mult_win || buf->b_nwindows <= 1)
1362 && (!checkaw || autowrite(buf, forceit) == FAIL))
1364 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1365 if ((p_confirm || cmdmod.confirm) && p_write)
1367 buf_T *buf2;
1368 int count = 0;
1370 if (allbuf)
1371 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1372 if (bufIsChanged(buf2)
1373 && (buf2->b_ffname != NULL
1374 # ifdef FEAT_BROWSE
1375 || cmdmod.browse
1376 # endif
1378 ++count;
1379 # ifdef FEAT_AUTOCMD
1380 if (!buf_valid(buf))
1381 /* Autocommand deleted buffer, oops! It's not changed now. */
1382 return FALSE;
1383 # endif
1384 dialog_changed(buf, count > 1);
1385 # ifdef FEAT_AUTOCMD
1386 if (!buf_valid(buf))
1387 /* Autocommand deleted buffer, oops! It's not changed now. */
1388 return FALSE;
1389 # endif
1390 return bufIsChanged(buf);
1392 #endif
1393 EMSG(_(e_nowrtmsg));
1394 return TRUE;
1396 return FALSE;
1399 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO)
1401 #if defined(FEAT_BROWSE) || defined(PROTO)
1403 * When wanting to write a file without a file name, ask the user for a name.
1405 void
1406 browse_save_fname(buf)
1407 buf_T *buf;
1409 if (buf->b_fname == NULL)
1411 char_u *fname;
1413 fname = do_browse(BROWSE_SAVE, (char_u *)_("Save As"),
1414 NULL, NULL, NULL, NULL, buf);
1415 if (fname != NULL)
1417 if (setfname(buf, fname, NULL, TRUE) == OK)
1418 buf->b_flags |= BF_NOTEDITED;
1419 vim_free(fname);
1423 #endif
1426 * Ask the user what to do when abondoning a changed buffer.
1427 * Must check 'write' option first!
1429 void
1430 dialog_changed(buf, checkall)
1431 buf_T *buf;
1432 int checkall; /* may abandon all changed buffers */
1434 char_u buff[IOSIZE];
1435 int ret;
1436 buf_T *buf2;
1438 dialog_msg(buff, _("Save changes to \"%s\"?"),
1439 (buf->b_fname != NULL) ?
1440 buf->b_fname : (char_u *)_("Untitled"));
1441 if (checkall)
1442 ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1);
1443 else
1444 ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
1446 if (ret == VIM_YES)
1448 #ifdef FEAT_BROWSE
1449 /* May get file name, when there is none */
1450 browse_save_fname(buf);
1451 #endif
1452 if (buf->b_fname != NULL) /* didn't hit Cancel */
1453 (void)buf_write_all(buf, FALSE);
1455 else if (ret == VIM_NO)
1457 unchanged(buf, TRUE);
1459 else if (ret == VIM_ALL)
1462 * Write all modified files that can be written.
1463 * Skip readonly buffers, these need to be confirmed
1464 * individually.
1466 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1468 if (bufIsChanged(buf2)
1469 && (buf2->b_ffname != NULL
1470 #ifdef FEAT_BROWSE
1471 || cmdmod.browse
1472 #endif
1474 && !buf2->b_p_ro)
1476 #ifdef FEAT_BROWSE
1477 /* May get file name, when there is none */
1478 browse_save_fname(buf2);
1479 #endif
1480 if (buf2->b_fname != NULL) /* didn't hit Cancel */
1481 (void)buf_write_all(buf2, FALSE);
1482 #ifdef FEAT_AUTOCMD
1483 /* an autocommand may have deleted the buffer */
1484 if (!buf_valid(buf2))
1485 buf2 = firstbuf;
1486 #endif
1490 else if (ret == VIM_DISCARDALL)
1493 * mark all buffers as unchanged
1495 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1496 unchanged(buf2, TRUE);
1499 #endif
1502 * Return TRUE if the buffer "buf" can be abandoned, either by making it
1503 * hidden, autowriting it or unloading it.
1506 can_abandon(buf, forceit)
1507 buf_T *buf;
1508 int forceit;
1510 return ( P_HID(buf)
1511 || !bufIsChanged(buf)
1512 || buf->b_nwindows > 1
1513 || autowrite(buf, forceit) == OK
1514 || forceit);
1518 * Return TRUE if any buffer was changed and cannot be abandoned.
1519 * That changed buffer becomes the current buffer.
1522 check_changed_any(hidden)
1523 int hidden; /* Only check hidden buffers */
1525 buf_T *buf;
1526 int save;
1527 #ifdef FEAT_WINDOWS
1528 win_T *wp;
1529 #endif
1531 for (;;)
1533 /* check curbuf first: if it was changed we can't abandon it */
1534 if (!hidden && curbufIsChanged())
1535 buf = curbuf;
1536 else
1538 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
1539 if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf))
1540 break;
1542 if (buf == NULL) /* No buffers changed */
1543 return FALSE;
1545 /* Try auto-writing the buffer. If this fails but the buffer no
1546 * longer exists it's not changed, that's OK. */
1547 if (check_changed(buf, p_awa, TRUE, FALSE, TRUE) && buf_valid(buf))
1548 break; /* didn't save - still changes */
1551 exiting = FALSE;
1552 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1554 * When ":confirm" used, don't give an error message.
1556 if (!(p_confirm || cmdmod.confirm))
1557 #endif
1559 /* There must be a wait_return for this message, do_buffer()
1560 * may cause a redraw. But wait_return() is a no-op when vgetc()
1561 * is busy (Quit used from window menu), then make sure we don't
1562 * cause a scroll up. */
1563 if (vgetc_busy > 0)
1565 msg_row = cmdline_row;
1566 msg_col = 0;
1567 msg_didout = FALSE;
1569 if (EMSG2(_("E162: No write since last change for buffer \"%s\""),
1570 buf_spname(buf) != NULL ? (char_u *)buf_spname(buf) :
1571 buf->b_fname))
1573 save = no_wait_return;
1574 no_wait_return = FALSE;
1575 wait_return(FALSE);
1576 no_wait_return = save;
1580 #ifdef FEAT_WINDOWS
1581 /* Try to find a window that contains the buffer. */
1582 if (buf != curbuf)
1583 for (wp = firstwin; wp != NULL; wp = wp->w_next)
1584 if (wp->w_buffer == buf)
1586 win_goto(wp);
1587 # ifdef FEAT_AUTOCMD
1588 /* Paranoia: did autocms wipe out the buffer with changes? */
1589 if (!buf_valid(buf))
1590 return TRUE;
1591 # endif
1592 break;
1594 #endif
1596 /* Open the changed buffer in the current window. */
1597 if (buf != curbuf)
1598 set_curbuf(buf, DOBUF_GOTO);
1600 return TRUE;
1604 * return FAIL if there is no file name, OK if there is one
1605 * give error message for FAIL
1608 check_fname()
1610 if (curbuf->b_ffname == NULL)
1612 EMSG(_(e_noname));
1613 return FAIL;
1615 return OK;
1619 * flush the contents of a buffer, unless it has no file name
1621 * return FAIL for failure, OK otherwise
1624 buf_write_all(buf, forceit)
1625 buf_T *buf;
1626 int forceit;
1628 int retval;
1629 #ifdef FEAT_AUTOCMD
1630 buf_T *old_curbuf = curbuf;
1631 #endif
1633 retval = (buf_write(buf, buf->b_ffname, buf->b_fname,
1634 (linenr_T)1, buf->b_ml.ml_line_count, NULL,
1635 FALSE, forceit, TRUE, FALSE));
1636 #ifdef FEAT_AUTOCMD
1637 if (curbuf != old_curbuf)
1639 msg_source(hl_attr(HLF_W));
1640 MSG(_("Warning: Entered other buffer unexpectedly (check autocommands)"));
1642 #endif
1643 return retval;
1647 * Code to handle the argument list.
1650 static char_u *do_one_arg __ARGS((char_u *str));
1651 static int do_arglist __ARGS((char_u *str, int what, int after));
1652 static void alist_check_arg_idx __ARGS((void));
1653 static int editing_arg_idx __ARGS((win_T *win));
1654 #ifdef FEAT_LISTCMDS
1655 static int alist_add_list __ARGS((int count, char_u **files, int after));
1656 #endif
1657 #define AL_SET 1
1658 #define AL_ADD 2
1659 #define AL_DEL 3
1662 * Isolate one argument, taking backticks.
1663 * Changes the argument in-place, puts a NUL after it. Backticks remain.
1664 * Return a pointer to the start of the next argument.
1666 static char_u *
1667 do_one_arg(str)
1668 char_u *str;
1670 char_u *p;
1671 int inbacktick;
1673 inbacktick = FALSE;
1674 for (p = str; *str; ++str)
1676 /* When the backslash is used for escaping the special meaning of a
1677 * character we need to keep it until wildcard expansion. */
1678 if (rem_backslash(str))
1680 *p++ = *str++;
1681 *p++ = *str;
1683 else
1685 /* An item ends at a space not in backticks */
1686 if (!inbacktick && vim_isspace(*str))
1687 break;
1688 if (*str == '`')
1689 inbacktick ^= TRUE;
1690 *p++ = *str;
1693 str = skipwhite(str);
1694 *p = NUL;
1696 return str;
1700 * Separate the arguments in "str" and return a list of pointers in the
1701 * growarray "gap".
1704 get_arglist(gap, str)
1705 garray_T *gap;
1706 char_u *str;
1708 ga_init2(gap, (int)sizeof(char_u *), 20);
1709 while (*str != NUL)
1711 if (ga_grow(gap, 1) == FAIL)
1713 ga_clear(gap);
1714 return FAIL;
1716 ((char_u **)gap->ga_data)[gap->ga_len++] = str;
1718 /* Isolate one argument, change it in-place, put a NUL after it. */
1719 str = do_one_arg(str);
1721 return OK;
1724 #if defined(FEAT_QUICKFIX) || defined(FEAT_SYN_HL) || defined(PROTO)
1726 * Parse a list of arguments (file names), expand them and return in
1727 * "fnames[fcountp]".
1728 * Return FAIL or OK.
1731 get_arglist_exp(str, fcountp, fnamesp)
1732 char_u *str;
1733 int *fcountp;
1734 char_u ***fnamesp;
1736 garray_T ga;
1737 int i;
1739 if (get_arglist(&ga, str) == FAIL)
1740 return FAIL;
1741 i = gen_expand_wildcards(ga.ga_len, (char_u **)ga.ga_data,
1742 fcountp, fnamesp, EW_FILE|EW_NOTFOUND);
1743 ga_clear(&ga);
1744 return i;
1746 #endif
1748 #if defined(FEAT_GUI) || defined(FEAT_CLIENTSERVER) || defined(PROTO)
1750 * Redefine the argument list.
1752 void
1753 set_arglist(str)
1754 char_u *str;
1756 do_arglist(str, AL_SET, 0);
1758 #endif
1761 * "what" == AL_SET: Redefine the argument list to 'str'.
1762 * "what" == AL_ADD: add files in 'str' to the argument list after "after".
1763 * "what" == AL_DEL: remove files in 'str' from the argument list.
1765 * Return FAIL for failure, OK otherwise.
1767 /*ARGSUSED*/
1768 static int
1769 do_arglist(str, what, after)
1770 char_u *str;
1771 int what;
1772 int after; /* 0 means before first one */
1774 garray_T new_ga;
1775 int exp_count;
1776 char_u **exp_files;
1777 int i;
1778 #ifdef FEAT_LISTCMDS
1779 char_u *p;
1780 int match;
1781 #endif
1784 * Collect all file name arguments in "new_ga".
1786 if (get_arglist(&new_ga, str) == FAIL)
1787 return FAIL;
1789 #ifdef FEAT_LISTCMDS
1790 if (what == AL_DEL)
1792 regmatch_T regmatch;
1793 int didone;
1796 * Delete the items: use each item as a regexp and find a match in the
1797 * argument list.
1799 #ifdef CASE_INSENSITIVE_FILENAME
1800 regmatch.rm_ic = TRUE; /* Always ignore case */
1801 #else
1802 regmatch.rm_ic = FALSE; /* Never ignore case */
1803 #endif
1804 for (i = 0; i < new_ga.ga_len && !got_int; ++i)
1806 p = ((char_u **)new_ga.ga_data)[i];
1807 p = file_pat_to_reg_pat(p, NULL, NULL, FALSE);
1808 if (p == NULL)
1809 break;
1810 regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0);
1811 if (regmatch.regprog == NULL)
1813 vim_free(p);
1814 break;
1817 didone = FALSE;
1818 for (match = 0; match < ARGCOUNT; ++match)
1819 if (vim_regexec(&regmatch, alist_name(&ARGLIST[match]),
1820 (colnr_T)0))
1822 didone = TRUE;
1823 vim_free(ARGLIST[match].ae_fname);
1824 mch_memmove(ARGLIST + match, ARGLIST + match + 1,
1825 (ARGCOUNT - match - 1) * sizeof(aentry_T));
1826 --ALIST(curwin)->al_ga.ga_len;
1827 if (curwin->w_arg_idx > match)
1828 --curwin->w_arg_idx;
1829 --match;
1832 vim_free(regmatch.regprog);
1833 vim_free(p);
1834 if (!didone)
1835 EMSG2(_(e_nomatch2), ((char_u **)new_ga.ga_data)[i]);
1837 ga_clear(&new_ga);
1839 else
1840 #endif
1842 i = expand_wildcards(new_ga.ga_len, (char_u **)new_ga.ga_data,
1843 &exp_count, &exp_files, EW_DIR|EW_FILE|EW_ADDSLASH|EW_NOTFOUND);
1844 ga_clear(&new_ga);
1845 if (i == FAIL)
1846 return FAIL;
1847 if (exp_count == 0)
1849 EMSG(_(e_nomatch));
1850 return FAIL;
1853 #ifdef FEAT_LISTCMDS
1854 if (what == AL_ADD)
1856 (void)alist_add_list(exp_count, exp_files, after);
1857 vim_free(exp_files);
1859 else /* what == AL_SET */
1860 #endif
1861 alist_set(ALIST(curwin), exp_count, exp_files, FALSE, NULL, 0);
1864 alist_check_arg_idx();
1866 return OK;
1870 * Check the validity of the arg_idx for each other window.
1872 static void
1873 alist_check_arg_idx()
1875 #ifdef FEAT_WINDOWS
1876 win_T *win;
1877 tabpage_T *tp;
1879 FOR_ALL_TAB_WINDOWS(tp, win)
1880 if (win->w_alist == curwin->w_alist)
1881 check_arg_idx(win);
1882 #else
1883 check_arg_idx(curwin);
1884 #endif
1888 * Return TRUE if window "win" is editing then file at the current argument
1889 * index.
1891 static int
1892 editing_arg_idx(win)
1893 win_T *win;
1895 return !(win->w_arg_idx >= WARGCOUNT(win)
1896 || (win->w_buffer->b_fnum
1897 != WARGLIST(win)[win->w_arg_idx].ae_fnum
1898 && (win->w_buffer->b_ffname == NULL
1899 || !(fullpathcmp(
1900 alist_name(&WARGLIST(win)[win->w_arg_idx]),
1901 win->w_buffer->b_ffname, TRUE) & FPC_SAME))));
1905 * Check if window "win" is editing the w_arg_idx file in its argument list.
1907 void
1908 check_arg_idx(win)
1909 win_T *win;
1911 if (WARGCOUNT(win) > 1 && !editing_arg_idx(win))
1913 /* We are not editing the current entry in the argument list.
1914 * Set "arg_had_last" if we are editing the last one. */
1915 win->w_arg_idx_invalid = TRUE;
1916 if (win->w_arg_idx != WARGCOUNT(win) - 1
1917 && arg_had_last == FALSE
1918 #ifdef FEAT_WINDOWS
1919 && ALIST(win) == &global_alist
1920 #endif
1921 && GARGCOUNT > 0
1922 && win->w_arg_idx < GARGCOUNT
1923 && (win->w_buffer->b_fnum == GARGLIST[GARGCOUNT - 1].ae_fnum
1924 || (win->w_buffer->b_ffname != NULL
1925 && (fullpathcmp(alist_name(&GARGLIST[GARGCOUNT - 1]),
1926 win->w_buffer->b_ffname, TRUE) & FPC_SAME))))
1927 arg_had_last = TRUE;
1929 else
1931 /* We are editing the current entry in the argument list.
1932 * Set "arg_had_last" if it's also the last one */
1933 win->w_arg_idx_invalid = FALSE;
1934 if (win->w_arg_idx == WARGCOUNT(win) - 1
1935 #ifdef FEAT_WINDOWS
1936 && win->w_alist == &global_alist
1937 #endif
1939 arg_had_last = TRUE;
1944 * ":args", ":argslocal" and ":argsglobal".
1946 void
1947 ex_args(eap)
1948 exarg_T *eap;
1950 int i;
1952 if (eap->cmdidx != CMD_args)
1954 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
1955 alist_unlink(ALIST(curwin));
1956 if (eap->cmdidx == CMD_argglobal)
1957 ALIST(curwin) = &global_alist;
1958 else /* eap->cmdidx == CMD_arglocal */
1959 alist_new();
1960 #else
1961 ex_ni(eap);
1962 return;
1963 #endif
1966 if (!ends_excmd(*eap->arg))
1969 * ":args file ..": define new argument list, handle like ":next"
1970 * Also for ":argslocal file .." and ":argsglobal file ..".
1972 ex_next(eap);
1974 else
1975 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
1976 if (eap->cmdidx == CMD_args)
1977 #endif
1980 * ":args": list arguments.
1982 if (ARGCOUNT > 0)
1984 /* Overwrite the command, for a short list there is no scrolling
1985 * required and no wait_return(). */
1986 gotocmdline(TRUE);
1987 for (i = 0; i < ARGCOUNT; ++i)
1989 if (i == curwin->w_arg_idx)
1990 msg_putchar('[');
1991 msg_outtrans(alist_name(&ARGLIST[i]));
1992 if (i == curwin->w_arg_idx)
1993 msg_putchar(']');
1994 msg_putchar(' ');
1998 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
1999 else if (eap->cmdidx == CMD_arglocal)
2001 garray_T *gap = &curwin->w_alist->al_ga;
2004 * ":argslocal": make a local copy of the global argument list.
2006 if (ga_grow(gap, GARGCOUNT) == OK)
2007 for (i = 0; i < GARGCOUNT; ++i)
2008 if (GARGLIST[i].ae_fname != NULL)
2010 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fname =
2011 vim_strsave(GARGLIST[i].ae_fname);
2012 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fnum =
2013 GARGLIST[i].ae_fnum;
2014 ++gap->ga_len;
2017 #endif
2021 * ":previous", ":sprevious", ":Next" and ":sNext".
2023 void
2024 ex_previous(eap)
2025 exarg_T *eap;
2027 /* If past the last one already, go to the last one. */
2028 if (curwin->w_arg_idx - (int)eap->line2 >= ARGCOUNT)
2029 do_argfile(eap, ARGCOUNT - 1);
2030 else
2031 do_argfile(eap, curwin->w_arg_idx - (int)eap->line2);
2035 * ":rewind", ":first", ":sfirst" and ":srewind".
2037 void
2038 ex_rewind(eap)
2039 exarg_T *eap;
2041 do_argfile(eap, 0);
2045 * ":last" and ":slast".
2047 void
2048 ex_last(eap)
2049 exarg_T *eap;
2051 do_argfile(eap, ARGCOUNT - 1);
2055 * ":argument" and ":sargument".
2057 void
2058 ex_argument(eap)
2059 exarg_T *eap;
2061 int i;
2063 if (eap->addr_count > 0)
2064 i = eap->line2 - 1;
2065 else
2066 i = curwin->w_arg_idx;
2067 do_argfile(eap, i);
2071 * Edit file "argn" of the argument lists.
2073 void
2074 do_argfile(eap, argn)
2075 exarg_T *eap;
2076 int argn;
2078 int other;
2079 char_u *p;
2080 int old_arg_idx = curwin->w_arg_idx;
2082 if (argn < 0 || argn >= ARGCOUNT)
2084 if (ARGCOUNT <= 1)
2085 EMSG(_("E163: There is only one file to edit"));
2086 else if (argn < 0)
2087 EMSG(_("E164: Cannot go before first file"));
2088 else
2089 EMSG(_("E165: Cannot go beyond last file"));
2091 else
2093 setpcmark();
2094 #ifdef FEAT_GUI
2095 need_mouse_correct = TRUE;
2096 #endif
2098 #ifdef FEAT_WINDOWS
2099 /* split window or create new tab page first */
2100 if (*eap->cmd == 's' || cmdmod.tab != 0)
2102 if (win_split(0, 0) == FAIL)
2103 return;
2104 # ifdef FEAT_SCROLLBIND
2105 curwin->w_p_scb = FALSE;
2106 # endif
2108 else
2109 #endif
2112 * if 'hidden' set, only check for changed file when re-editing
2113 * the same buffer
2115 other = TRUE;
2116 if (P_HID(curbuf))
2118 p = fix_fname(alist_name(&ARGLIST[argn]));
2119 other = otherfile(p);
2120 vim_free(p);
2122 if ((!P_HID(curbuf) || !other)
2123 && check_changed(curbuf, TRUE, !other, eap->forceit, FALSE))
2124 return;
2127 curwin->w_arg_idx = argn;
2128 if (argn == ARGCOUNT - 1
2129 #ifdef FEAT_WINDOWS
2130 && curwin->w_alist == &global_alist
2131 #endif
2133 arg_had_last = TRUE;
2135 /* Edit the file; always use the last known line number.
2136 * When it fails (e.g. Abort for already edited file) restore the
2137 * argument index. */
2138 if (do_ecmd(0, alist_name(&ARGLIST[curwin->w_arg_idx]), NULL,
2139 eap, ECMD_LAST,
2140 (P_HID(curwin->w_buffer) ? ECMD_HIDE : 0) +
2141 (eap->forceit ? ECMD_FORCEIT : 0)) == FAIL)
2142 curwin->w_arg_idx = old_arg_idx;
2143 /* like Vi: set the mark where the cursor is in the file. */
2144 else if (eap->cmdidx != CMD_argdo)
2145 setmark('\'');
2150 * ":next", and commands that behave like it.
2152 void
2153 ex_next(eap)
2154 exarg_T *eap;
2156 int i;
2159 * check for changed buffer now, if this fails the argument list is not
2160 * redefined.
2162 if ( P_HID(curbuf)
2163 || eap->cmdidx == CMD_snext
2164 || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
2166 if (*eap->arg != NUL) /* redefine file list */
2168 if (do_arglist(eap->arg, AL_SET, 0) == FAIL)
2169 return;
2170 i = 0;
2172 else
2173 i = curwin->w_arg_idx + (int)eap->line2;
2174 do_argfile(eap, i);
2178 #ifdef FEAT_LISTCMDS
2180 * ":argedit"
2182 void
2183 ex_argedit(eap)
2184 exarg_T *eap;
2186 int fnum;
2187 int i;
2188 char_u *s;
2190 /* Add the argument to the buffer list and get the buffer number. */
2191 fnum = buflist_add(eap->arg, BLN_LISTED);
2193 /* Check if this argument is already in the argument list. */
2194 for (i = 0; i < ARGCOUNT; ++i)
2195 if (ARGLIST[i].ae_fnum == fnum)
2196 break;
2197 if (i == ARGCOUNT)
2199 /* Can't find it, add it to the argument list. */
2200 s = vim_strsave(eap->arg);
2201 if (s == NULL)
2202 return;
2203 i = alist_add_list(1, &s,
2204 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
2205 if (i < 0)
2206 return;
2207 curwin->w_arg_idx = i;
2210 alist_check_arg_idx();
2212 /* Edit the argument. */
2213 do_argfile(eap, i);
2217 * ":argadd"
2219 void
2220 ex_argadd(eap)
2221 exarg_T *eap;
2223 do_arglist(eap->arg, AL_ADD,
2224 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
2225 #ifdef FEAT_TITLE
2226 maketitle();
2227 #endif
2231 * ":argdelete"
2233 void
2234 ex_argdelete(eap)
2235 exarg_T *eap;
2237 int i;
2238 int n;
2240 if (eap->addr_count > 0)
2242 /* ":1,4argdel": Delete all arguments in the range. */
2243 if (eap->line2 > ARGCOUNT)
2244 eap->line2 = ARGCOUNT;
2245 n = eap->line2 - eap->line1 + 1;
2246 if (*eap->arg != NUL || n <= 0)
2247 EMSG(_(e_invarg));
2248 else
2250 for (i = eap->line1; i <= eap->line2; ++i)
2251 vim_free(ARGLIST[i - 1].ae_fname);
2252 mch_memmove(ARGLIST + eap->line1 - 1, ARGLIST + eap->line2,
2253 (size_t)((ARGCOUNT - eap->line2) * sizeof(aentry_T)));
2254 ALIST(curwin)->al_ga.ga_len -= n;
2255 if (curwin->w_arg_idx >= eap->line2)
2256 curwin->w_arg_idx -= n;
2257 else if (curwin->w_arg_idx > eap->line1)
2258 curwin->w_arg_idx = eap->line1;
2261 else if (*eap->arg == NUL)
2262 EMSG(_(e_argreq));
2263 else
2264 do_arglist(eap->arg, AL_DEL, 0);
2265 #ifdef FEAT_TITLE
2266 maketitle();
2267 #endif
2271 * ":argdo", ":windo", ":bufdo", ":tabdo"
2273 void
2274 ex_listdo(eap)
2275 exarg_T *eap;
2277 int i;
2278 #ifdef FEAT_WINDOWS
2279 win_T *wp;
2280 tabpage_T *tp;
2281 #endif
2282 buf_T *buf;
2283 int next_fnum = 0;
2284 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2285 char_u *save_ei = NULL;
2286 #endif
2287 char_u *p_shm_save;
2289 #ifndef FEAT_WINDOWS
2290 if (eap->cmdidx == CMD_windo)
2292 ex_ni(eap);
2293 return;
2295 #endif
2297 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2298 if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo)
2299 /* Don't do syntax HL autocommands. Skipping the syntax file is a
2300 * great speed improvement. */
2301 save_ei = au_event_disable(",Syntax");
2302 #endif
2304 if (eap->cmdidx == CMD_windo
2305 || eap->cmdidx == CMD_tabdo
2306 || P_HID(curbuf)
2307 || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
2309 /* start at the first argument/window/buffer */
2310 i = 0;
2311 #ifdef FEAT_WINDOWS
2312 wp = firstwin;
2313 tp = first_tabpage;
2314 #endif
2315 /* set pcmark now */
2316 if (eap->cmdidx == CMD_bufdo)
2317 goto_buffer(eap, DOBUF_FIRST, FORWARD, 0);
2318 else
2319 setpcmark();
2320 listcmd_busy = TRUE; /* avoids setting pcmark below */
2322 while (!got_int)
2324 if (eap->cmdidx == CMD_argdo)
2326 /* go to argument "i" */
2327 if (i == ARGCOUNT)
2328 break;
2329 /* Don't call do_argfile() when already there, it will try
2330 * reloading the file. */
2331 if (curwin->w_arg_idx != i || !editing_arg_idx(curwin))
2333 /* Clear 'shm' to avoid that the file message overwrites
2334 * any output from the command. */
2335 p_shm_save = vim_strsave(p_shm);
2336 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
2337 do_argfile(eap, i);
2338 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
2339 vim_free(p_shm_save);
2341 if (curwin->w_arg_idx != i)
2342 break;
2343 ++i;
2345 #ifdef FEAT_WINDOWS
2346 else if (eap->cmdidx == CMD_windo)
2348 /* go to window "wp" */
2349 if (!win_valid(wp))
2350 break;
2351 win_goto(wp);
2352 if (curwin != wp)
2353 break; /* something must be wrong */
2354 wp = curwin->w_next;
2356 else if (eap->cmdidx == CMD_tabdo)
2358 /* go to window "tp" */
2359 if (!valid_tabpage(tp))
2360 break;
2361 goto_tabpage_tp(tp);
2362 tp = tp->tp_next;
2364 #endif
2365 else if (eap->cmdidx == CMD_bufdo)
2367 /* Remember the number of the next listed buffer, in case
2368 * ":bwipe" is used or autocommands do something strange. */
2369 next_fnum = -1;
2370 for (buf = curbuf->b_next; buf != NULL; buf = buf->b_next)
2371 if (buf->b_p_bl)
2373 next_fnum = buf->b_fnum;
2374 break;
2378 /* execute the command */
2379 do_cmdline(eap->arg, eap->getline, eap->cookie,
2380 DOCMD_VERBOSE + DOCMD_NOWAIT);
2382 if (eap->cmdidx == CMD_bufdo)
2384 /* Done? */
2385 if (next_fnum < 0)
2386 break;
2387 /* Check if the buffer still exists. */
2388 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
2389 if (buf->b_fnum == next_fnum)
2390 break;
2391 if (buf == NULL)
2392 break;
2394 /* Go to the next buffer. Clear 'shm' to avoid that the file
2395 * message overwrites any output from the command. */
2396 p_shm_save = vim_strsave(p_shm);
2397 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
2398 goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
2399 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
2400 vim_free(p_shm_save);
2402 /* If autocommands took us elsewhere, quit here */
2403 if (curbuf->b_fnum != next_fnum)
2404 break;
2407 if (eap->cmdidx == CMD_windo)
2409 validate_cursor(); /* cursor may have moved */
2410 #ifdef FEAT_SCROLLBIND
2411 /* required when 'scrollbind' has been set */
2412 if (curwin->w_p_scb)
2413 do_check_scrollbind(TRUE);
2414 #endif
2417 listcmd_busy = FALSE;
2420 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2421 if (save_ei != NULL)
2423 au_event_restore(save_ei);
2424 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
2425 curbuf->b_fname, TRUE, curbuf);
2427 #endif
2431 * Add files[count] to the arglist of the current window after arg "after".
2432 * The file names in files[count] must have been allocated and are taken over.
2433 * Files[] itself is not taken over.
2434 * Returns index of first added argument. Returns -1 when failed (out of mem).
2436 static int
2437 alist_add_list(count, files, after)
2438 int count;
2439 char_u **files;
2440 int after; /* where to add: 0 = before first one */
2442 int i;
2444 if (ga_grow(&ALIST(curwin)->al_ga, count) == OK)
2446 if (after < 0)
2447 after = 0;
2448 if (after > ARGCOUNT)
2449 after = ARGCOUNT;
2450 if (after < ARGCOUNT)
2451 mch_memmove(&(ARGLIST[after + count]), &(ARGLIST[after]),
2452 (ARGCOUNT - after) * sizeof(aentry_T));
2453 for (i = 0; i < count; ++i)
2455 ARGLIST[after + i].ae_fname = files[i];
2456 ARGLIST[after + i].ae_fnum = buflist_add(files[i], BLN_LISTED);
2458 ALIST(curwin)->al_ga.ga_len += count;
2459 if (curwin->w_arg_idx >= after)
2460 ++curwin->w_arg_idx;
2461 return after;
2464 for (i = 0; i < count; ++i)
2465 vim_free(files[i]);
2466 return -1;
2469 #endif /* FEAT_LISTCMDS */
2471 #ifdef FEAT_EVAL
2473 * ":compiler[!] {name}"
2475 void
2476 ex_compiler(eap)
2477 exarg_T *eap;
2479 char_u *buf;
2480 char_u *old_cur_comp = NULL;
2481 char_u *p;
2483 if (*eap->arg == NUL)
2485 /* List all compiler scripts. */
2486 do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')");
2487 /* ) keep the indenter happy... */
2489 else
2491 buf = alloc((unsigned)(STRLEN(eap->arg) + 14));
2492 if (buf != NULL)
2494 if (eap->forceit)
2496 /* ":compiler! {name}" sets global options */
2497 do_cmdline_cmd((char_u *)
2498 "command -nargs=* CompilerSet set <args>");
2500 else
2502 /* ":compiler! {name}" sets local options.
2503 * To remain backwards compatible "current_compiler" is always
2504 * used. A user's compiler plugin may set it, the distributed
2505 * plugin will then skip the settings. Afterwards set
2506 * "b:current_compiler" and restore "current_compiler". */
2507 old_cur_comp = get_var_value((char_u *)"current_compiler");
2508 if (old_cur_comp != NULL)
2509 old_cur_comp = vim_strsave(old_cur_comp);
2510 do_cmdline_cmd((char_u *)
2511 "command -nargs=* CompilerSet setlocal <args>");
2513 do_unlet((char_u *)"current_compiler", TRUE);
2514 do_unlet((char_u *)"b:current_compiler", TRUE);
2516 sprintf((char *)buf, "compiler/%s.vim", eap->arg);
2517 if (source_runtime(buf, TRUE) == FAIL)
2518 EMSG2(_("E666: compiler not supported: %s"), eap->arg);
2519 vim_free(buf);
2521 do_cmdline_cmd((char_u *)":delcommand CompilerSet");
2523 /* Set "b:current_compiler" from "current_compiler". */
2524 p = get_var_value((char_u *)"current_compiler");
2525 if (p != NULL)
2526 set_internal_string_var((char_u *)"b:current_compiler", p);
2528 /* Restore "current_compiler" for ":compiler {name}". */
2529 if (!eap->forceit)
2531 if (old_cur_comp != NULL)
2533 set_internal_string_var((char_u *)"current_compiler",
2534 old_cur_comp);
2535 vim_free(old_cur_comp);
2537 else
2538 do_unlet((char_u *)"current_compiler", TRUE);
2543 #endif
2546 * ":runtime {name}"
2548 void
2549 ex_runtime(eap)
2550 exarg_T *eap;
2552 source_runtime(eap->arg, eap->forceit);
2555 static void source_callback __ARGS((char_u *fname, void *cookie));
2557 /*ARGSUSED*/
2558 static void
2559 source_callback(fname, cookie)
2560 char_u *fname;
2561 void *cookie;
2563 (void)do_source(fname, FALSE, DOSO_NONE);
2567 * Source the file "name" from all directories in 'runtimepath'.
2568 * "name" can contain wildcards.
2569 * When "all" is TRUE, source all files, otherwise only the first one.
2570 * return FAIL when no file could be sourced, OK otherwise.
2573 source_runtime(name, all)
2574 char_u *name;
2575 int all;
2577 return do_in_runtimepath(name, all, source_callback, NULL);
2581 * Find "name" in 'runtimepath'. When found, invoke the callback function for
2582 * it: callback(fname, "cookie")
2583 * When "all" is TRUE repeat for all matches, otherwise only the first one is
2584 * used.
2585 * Returns OK when at least one match found, FAIL otherwise.
2588 do_in_runtimepath(name, all, callback, cookie)
2589 char_u *name;
2590 int all;
2591 void (*callback)__ARGS((char_u *fname, void *ck));
2592 void *cookie;
2594 char_u *rtp;
2595 char_u *np;
2596 char_u *buf;
2597 char_u *rtp_copy;
2598 char_u *tail;
2599 int num_files;
2600 char_u **files;
2601 int i;
2602 int did_one = FALSE;
2603 #ifdef AMIGA
2604 struct Process *proc = (struct Process *)FindTask(0L);
2605 APTR save_winptr = proc->pr_WindowPtr;
2607 /* Avoid a requester here for a volume that doesn't exist. */
2608 proc->pr_WindowPtr = (APTR)-1L;
2609 #endif
2611 /* Make a copy of 'runtimepath'. Invoking the callback may change the
2612 * value. */
2613 rtp_copy = vim_strsave(p_rtp);
2614 buf = alloc(MAXPATHL);
2615 if (buf != NULL && rtp_copy != NULL)
2617 if (p_verbose > 1)
2619 verbose_enter();
2620 smsg((char_u *)_("Searching for \"%s\" in \"%s\""),
2621 (char *)name, (char *)p_rtp);
2622 verbose_leave();
2625 /* Loop over all entries in 'runtimepath'. */
2626 rtp = rtp_copy;
2627 while (*rtp != NUL && (all || !did_one))
2629 /* Copy the path from 'runtimepath' to buf[]. */
2630 copy_option_part(&rtp, buf, MAXPATHL, ",");
2631 if (STRLEN(buf) + STRLEN(name) + 2 < MAXPATHL)
2633 add_pathsep(buf);
2634 tail = buf + STRLEN(buf);
2636 /* Loop over all patterns in "name" */
2637 np = name;
2638 while (*np != NUL && (all || !did_one))
2640 /* Append the pattern from "name" to buf[]. */
2641 copy_option_part(&np, tail, (int)(MAXPATHL - (tail - buf)),
2642 "\t ");
2644 if (p_verbose > 2)
2646 verbose_enter();
2647 smsg((char_u *)_("Searching for \"%s\""), buf);
2648 verbose_leave();
2651 /* Expand wildcards, invoke the callback for each match. */
2652 if (gen_expand_wildcards(1, &buf, &num_files, &files,
2653 EW_FILE) == OK)
2655 for (i = 0; i < num_files; ++i)
2657 (*callback)(files[i], cookie);
2658 did_one = TRUE;
2659 if (!all)
2660 break;
2662 FreeWild(num_files, files);
2668 vim_free(buf);
2669 vim_free(rtp_copy);
2670 if (p_verbose > 0 && !did_one)
2672 verbose_enter();
2673 smsg((char_u *)_("not found in 'runtimepath': \"%s\""), name);
2674 verbose_leave();
2677 #ifdef AMIGA
2678 proc->pr_WindowPtr = save_winptr;
2679 #endif
2681 return did_one ? OK : FAIL;
2684 #if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD)
2686 * ":options"
2688 /*ARGSUSED*/
2689 void
2690 ex_options(eap)
2691 exarg_T *eap;
2693 cmd_source((char_u *)SYS_OPTWIN_FILE, NULL);
2695 #endif
2698 * ":source {fname}"
2700 void
2701 ex_source(eap)
2702 exarg_T *eap;
2704 #ifdef FEAT_BROWSE
2705 if (cmdmod.browse)
2707 char_u *fname = NULL;
2709 fname = do_browse(0, (char_u *)_("Source Vim script"), eap->arg,
2710 NULL, NULL, BROWSE_FILTER_MACROS, NULL);
2711 if (fname != NULL)
2713 cmd_source(fname, eap);
2714 vim_free(fname);
2717 else
2718 #endif
2719 cmd_source(eap->arg, eap);
2722 static void
2723 cmd_source(fname, eap)
2724 char_u *fname;
2725 exarg_T *eap;
2727 if (*fname == NUL)
2728 EMSG(_(e_argreq));
2730 else if (eap != NULL && eap->forceit)
2731 /* ":source!": read Normal mdoe commands
2732 * Need to execute the commands directly. This is required at least
2733 * for:
2734 * - ":g" command busy
2735 * - after ":argdo", ":windo" or ":bufdo"
2736 * - another command follows
2737 * - inside a loop
2739 openscript(fname, global_busy || listcmd_busy || eap->nextcmd != NULL
2740 #ifdef FEAT_EVAL
2741 || eap->cstack->cs_idx >= 0
2742 #endif
2745 /* ":source" read ex commands */
2746 else if (do_source(fname, FALSE, DOSO_NONE) == FAIL)
2747 EMSG2(_(e_notopen), fname);
2751 * ":source" and associated commands.
2754 * Structure used to store info for each sourced file.
2755 * It is shared between do_source() and getsourceline().
2756 * This is required, because it needs to be handed to do_cmdline() and
2757 * sourcing can be done recursively.
2759 struct source_cookie
2761 FILE *fp; /* opened file for sourcing */
2762 char_u *nextline; /* if not NULL: line that was read ahead */
2763 int finished; /* ":finish" used */
2764 #if defined (USE_CRNL) || defined (USE_CR)
2765 int fileformat; /* EOL_UNKNOWN, EOL_UNIX or EOL_DOS */
2766 int error; /* TRUE if LF found after CR-LF */
2767 #endif
2768 #ifdef FEAT_EVAL
2769 linenr_T breakpoint; /* next line with breakpoint or zero */
2770 char_u *fname; /* name of sourced file */
2771 int dbg_tick; /* debug_tick when breakpoint was set */
2772 int level; /* top nesting level of sourced file */
2773 #endif
2774 #ifdef FEAT_MBYTE
2775 vimconv_T conv; /* type of conversion */
2776 #endif
2779 #ifdef FEAT_EVAL
2781 * Return the address holding the next breakpoint line for a source cookie.
2783 linenr_T *
2784 source_breakpoint(cookie)
2785 void *cookie;
2787 return &((struct source_cookie *)cookie)->breakpoint;
2791 * Return the address holding the debug tick for a source cookie.
2793 int *
2794 source_dbg_tick(cookie)
2795 void *cookie;
2797 return &((struct source_cookie *)cookie)->dbg_tick;
2801 * Return the nesting level for a source cookie.
2804 source_level(cookie)
2805 void *cookie;
2807 return ((struct source_cookie *)cookie)->level;
2809 #endif
2811 static char_u *get_one_sourceline __ARGS((struct source_cookie *sp));
2813 #if defined(WIN32) && defined(FEAT_CSCOPE)
2814 static FILE *fopen_noinh_readbin __ARGS((char *filename));
2817 * Special function to open a file without handle inheritance.
2819 static FILE *
2820 fopen_noinh_readbin(filename)
2821 char *filename;
2823 int fd_tmp = mch_open(filename, O_RDONLY | O_BINARY | O_NOINHERIT, 0);
2825 if (fd_tmp == -1)
2826 return NULL;
2827 return fdopen(fd_tmp, READBIN);
2829 #endif
2833 * do_source: Read the file "fname" and execute its lines as EX commands.
2835 * This function may be called recursively!
2837 * return FAIL if file could not be opened, OK otherwise
2840 do_source(fname, check_other, is_vimrc)
2841 char_u *fname;
2842 int check_other; /* check for .vimrc and _vimrc */
2843 int is_vimrc; /* DOSO_ value */
2845 struct source_cookie cookie;
2846 char_u *save_sourcing_name;
2847 linenr_T save_sourcing_lnum;
2848 char_u *p;
2849 char_u *fname_exp;
2850 int retval = FAIL;
2851 #ifdef FEAT_EVAL
2852 scid_T save_current_SID;
2853 static scid_T last_current_SID = 0;
2854 void *save_funccalp;
2855 int save_debug_break_level = debug_break_level;
2856 scriptitem_T *si = NULL;
2857 # ifdef UNIX
2858 struct stat st;
2859 int stat_ok;
2860 # endif
2861 #endif
2862 #ifdef STARTUPTIME
2863 struct timeval tv_rel;
2864 struct timeval tv_start;
2865 #endif
2866 #ifdef FEAT_PROFILE
2867 proftime_T wait_start;
2868 #endif
2870 #ifdef RISCOS
2871 p = mch_munge_fname(fname);
2872 #else
2873 p = expand_env_save(fname);
2874 #endif
2875 if (p == NULL)
2876 return retval;
2877 fname_exp = fix_fname(p);
2878 vim_free(p);
2879 if (fname_exp == NULL)
2880 return retval;
2881 if (mch_isdir(fname_exp))
2883 smsg((char_u *)_("Cannot source a directory: \"%s\""), fname);
2884 goto theend;
2887 #ifdef FEAT_AUTOCMD
2888 /* Apply SourceCmd autocommands, they should get the file and source it. */
2889 if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL)
2890 && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp,
2891 FALSE, curbuf))
2893 # ifdef FEAT_EVAL
2894 retval = aborting() ? FAIL : OK;
2895 # else
2896 retval = OK;
2897 # endif
2898 goto theend;
2901 /* Apply SourcePre autocommands, they may get the file. */
2902 apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, FALSE, curbuf);
2903 #endif
2905 #if defined(WIN32) && defined(FEAT_CSCOPE)
2906 cookie.fp = fopen_noinh_readbin((char *)fname_exp);
2907 #else
2908 cookie.fp = mch_fopen((char *)fname_exp, READBIN);
2909 #endif
2910 if (cookie.fp == NULL && check_other)
2913 * Try again, replacing file name ".vimrc" by "_vimrc" or vice versa,
2914 * and ".exrc" by "_exrc" or vice versa.
2916 p = gettail(fname_exp);
2917 if ((*p == '.' || *p == '_')
2918 && (STRICMP(p + 1, "vimrc") == 0
2919 || STRICMP(p + 1, "gvimrc") == 0
2920 || STRICMP(p + 1, "exrc") == 0))
2922 if (*p == '_')
2923 *p = '.';
2924 else
2925 *p = '_';
2926 #if defined(WIN32) && defined(FEAT_CSCOPE)
2927 cookie.fp = fopen_noinh_readbin((char *)fname_exp);
2928 #else
2929 cookie.fp = mch_fopen((char *)fname_exp, READBIN);
2930 #endif
2934 if (cookie.fp == NULL)
2936 if (p_verbose > 0)
2938 verbose_enter();
2939 if (sourcing_name == NULL)
2940 smsg((char_u *)_("could not source \"%s\""), fname);
2941 else
2942 smsg((char_u *)_("line %ld: could not source \"%s\""),
2943 sourcing_lnum, fname);
2944 verbose_leave();
2946 goto theend;
2950 * The file exists.
2951 * - In verbose mode, give a message.
2952 * - For a vimrc file, may want to set 'compatible', call vimrc_found().
2954 if (p_verbose > 1)
2956 verbose_enter();
2957 if (sourcing_name == NULL)
2958 smsg((char_u *)_("sourcing \"%s\""), fname);
2959 else
2960 smsg((char_u *)_("line %ld: sourcing \"%s\""),
2961 sourcing_lnum, fname);
2962 verbose_leave();
2964 if (is_vimrc == DOSO_VIMRC)
2965 vimrc_found(fname_exp, (char_u *)"MYVIMRC");
2966 else if (is_vimrc == DOSO_GVIMRC)
2967 vimrc_found(fname_exp, (char_u *)"MYGVIMRC");
2969 #ifdef USE_CRNL
2970 /* If no automatic file format: Set default to CR-NL. */
2971 if (*p_ffs == NUL)
2972 cookie.fileformat = EOL_DOS;
2973 else
2974 cookie.fileformat = EOL_UNKNOWN;
2975 cookie.error = FALSE;
2976 #endif
2978 #ifdef USE_CR
2979 /* If no automatic file format: Set default to CR. */
2980 if (*p_ffs == NUL)
2981 cookie.fileformat = EOL_MAC;
2982 else
2983 cookie.fileformat = EOL_UNKNOWN;
2984 cookie.error = FALSE;
2985 #endif
2987 cookie.nextline = NULL;
2988 cookie.finished = FALSE;
2990 #ifdef FEAT_EVAL
2992 * Check if this script has a breakpoint.
2994 cookie.breakpoint = dbg_find_breakpoint(TRUE, fname_exp, (linenr_T)0);
2995 cookie.fname = fname_exp;
2996 cookie.dbg_tick = debug_tick;
2998 cookie.level = ex_nesting_level;
2999 #endif
3000 #ifdef FEAT_MBYTE
3001 cookie.conv.vc_type = CONV_NONE; /* no conversion */
3003 /* Try reading the first few bytes to check for a UTF-8 BOM. */
3005 char_u buf[3];
3007 if (fread((char *)buf, sizeof(char_u), (size_t)3, cookie.fp)
3008 == (size_t)3
3009 && buf[0] == 0xef && buf[1] == 0xbb && buf[2] == 0xbf)
3010 /* Found BOM, setup conversion and skip over it. */
3011 convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc);
3012 else
3013 /* No BOM found, rewind. */
3014 fseek(cookie.fp, 0L, SEEK_SET);
3016 #endif
3019 * Keep the sourcing name/lnum, for recursive calls.
3021 save_sourcing_name = sourcing_name;
3022 sourcing_name = fname_exp;
3023 save_sourcing_lnum = sourcing_lnum;
3024 sourcing_lnum = 0;
3026 #ifdef STARTUPTIME
3027 time_push(&tv_rel, &tv_start);
3028 #endif
3030 #ifdef FEAT_EVAL
3031 # ifdef FEAT_PROFILE
3032 if (do_profiling == PROF_YES)
3033 prof_child_enter(&wait_start); /* entering a child now */
3034 # endif
3036 /* Don't use local function variables, if called from a function.
3037 * Also starts profiling timer for nested script. */
3038 save_funccalp = save_funccal();
3041 * Check if this script was sourced before to finds its SID.
3042 * If it's new, generate a new SID.
3044 save_current_SID = current_SID;
3045 # ifdef UNIX
3046 stat_ok = (mch_stat((char *)fname_exp, &st) >= 0);
3047 # endif
3048 for (current_SID = script_items.ga_len; current_SID > 0; --current_SID)
3050 si = &SCRIPT_ITEM(current_SID);
3051 if (si->sn_name != NULL
3052 && (
3053 # ifdef UNIX
3054 /* Compare dev/ino when possible, it catches symbolic
3055 * links. Also compare file names, the inode may change
3056 * when the file was edited. */
3057 ((stat_ok && si->sn_dev != -1)
3058 && (si->sn_dev == st.st_dev
3059 && si->sn_ino == st.st_ino)) ||
3060 # endif
3061 fnamecmp(si->sn_name, fname_exp) == 0))
3062 break;
3064 if (current_SID == 0)
3066 current_SID = ++last_current_SID;
3067 if (ga_grow(&script_items, (int)(current_SID - script_items.ga_len))
3068 == FAIL)
3069 goto almosttheend;
3070 while (script_items.ga_len < current_SID)
3072 ++script_items.ga_len;
3073 SCRIPT_ITEM(script_items.ga_len).sn_name = NULL;
3074 # ifdef FEAT_PROFILE
3075 SCRIPT_ITEM(script_items.ga_len).sn_prof_on = FALSE;
3076 # endif
3078 si = &SCRIPT_ITEM(current_SID);
3079 si->sn_name = fname_exp;
3080 fname_exp = NULL;
3081 # ifdef UNIX
3082 if (stat_ok)
3084 si->sn_dev = st.st_dev;
3085 si->sn_ino = st.st_ino;
3087 else
3088 si->sn_dev = -1;
3089 # endif
3091 /* Allocate the local script variables to use for this script. */
3092 new_script_vars(current_SID);
3095 # ifdef FEAT_PROFILE
3096 if (do_profiling == PROF_YES)
3098 int forceit;
3100 /* Check if we do profiling for this script. */
3101 if (!si->sn_prof_on && has_profiling(TRUE, si->sn_name, &forceit))
3103 script_do_profile(si);
3104 si->sn_pr_force = forceit;
3106 if (si->sn_prof_on)
3108 ++si->sn_pr_count;
3109 profile_start(&si->sn_pr_start);
3110 profile_zero(&si->sn_pr_children);
3113 # endif
3114 #endif
3117 * Call do_cmdline, which will call getsourceline() to get the lines.
3119 do_cmdline(NULL, getsourceline, (void *)&cookie,
3120 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT);
3122 retval = OK;
3124 #ifdef FEAT_PROFILE
3125 if (do_profiling == PROF_YES)
3127 /* Get "si" again, "script_items" may have been reallocated. */
3128 si = &SCRIPT_ITEM(current_SID);
3129 if (si->sn_prof_on)
3131 profile_end(&si->sn_pr_start);
3132 profile_sub_wait(&wait_start, &si->sn_pr_start);
3133 profile_add(&si->sn_pr_total, &si->sn_pr_start);
3134 profile_self(&si->sn_pr_self, &si->sn_pr_start,
3135 &si->sn_pr_children);
3138 #endif
3140 if (got_int)
3141 EMSG(_(e_interr));
3142 sourcing_name = save_sourcing_name;
3143 sourcing_lnum = save_sourcing_lnum;
3144 if (p_verbose > 1)
3146 verbose_enter();
3147 smsg((char_u *)_("finished sourcing %s"), fname);
3148 if (sourcing_name != NULL)
3149 smsg((char_u *)_("continuing in %s"), sourcing_name);
3150 verbose_leave();
3152 #ifdef STARTUPTIME
3153 vim_snprintf(IObuff, IOSIZE, "sourcing %s", fname);
3154 time_msg(IObuff, &tv_start);
3155 time_pop(&tv_rel);
3156 #endif
3158 #ifdef FEAT_EVAL
3160 * After a "finish" in debug mode, need to break at first command of next
3161 * sourced file.
3163 if (save_debug_break_level > ex_nesting_level
3164 && debug_break_level == ex_nesting_level)
3165 ++debug_break_level;
3166 #endif
3168 #ifdef FEAT_EVAL
3169 almosttheend:
3170 current_SID = save_current_SID;
3171 restore_funccal(save_funccalp);
3172 # ifdef FEAT_PROFILE
3173 if (do_profiling == PROF_YES)
3174 prof_child_exit(&wait_start); /* leaving a child now */
3175 # endif
3176 #endif
3177 fclose(cookie.fp);
3178 vim_free(cookie.nextline);
3179 #ifdef FEAT_MBYTE
3180 convert_setup(&cookie.conv, NULL, NULL);
3181 #endif
3183 theend:
3184 vim_free(fname_exp);
3185 return retval;
3188 #if defined(FEAT_EVAL) || defined(PROTO)
3191 * ":scriptnames"
3193 /*ARGSUSED*/
3194 void
3195 ex_scriptnames(eap)
3196 exarg_T *eap;
3198 int i;
3200 for (i = 1; i <= script_items.ga_len && !got_int; ++i)
3201 if (SCRIPT_ITEM(i).sn_name != NULL)
3202 smsg((char_u *)"%3d: %s", i, SCRIPT_ITEM(i).sn_name);
3205 # if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
3207 * Fix slashes in the list of script names for 'shellslash'.
3209 void
3210 scriptnames_slash_adjust()
3212 int i;
3214 for (i = 1; i <= script_items.ga_len; ++i)
3215 if (SCRIPT_ITEM(i).sn_name != NULL)
3216 slash_adjust(SCRIPT_ITEM(i).sn_name);
3218 # endif
3221 * Get a pointer to a script name. Used for ":verbose set".
3223 char_u *
3224 get_scriptname(id)
3225 scid_T id;
3227 if (id == SID_MODELINE)
3228 return (char_u *)_("modeline");
3229 if (id == SID_CMDARG)
3230 return (char_u *)_("--cmd argument");
3231 if (id == SID_CARG)
3232 return (char_u *)_("-c argument");
3233 if (id == SID_ENV)
3234 return (char_u *)_("environment variable");
3235 if (id == SID_ERROR)
3236 return (char_u *)_("error handler");
3237 return SCRIPT_ITEM(id).sn_name;
3240 # if defined(EXITFREE) || defined(PROTO)
3241 void
3242 free_scriptnames()
3244 int i;
3246 for (i = script_items.ga_len; i > 0; --i)
3247 vim_free(SCRIPT_ITEM(i).sn_name);
3248 ga_clear(&script_items);
3250 # endif
3252 #endif
3254 #if defined(USE_CR) || defined(PROTO)
3256 # if defined(__MSL__) && (__MSL__ >= 22)
3258 * Newer version of the Metrowerks library handle DOS and UNIX files
3259 * without help.
3260 * Test with earlier versions, MSL 2.2 is the library supplied with
3261 * Codewarrior Pro 2.
3263 char *
3264 fgets_cr(s, n, stream)
3265 char *s;
3266 int n;
3267 FILE *stream;
3269 return fgets(s, n, stream);
3271 # else
3273 * Version of fgets() which also works for lines ending in a <CR> only
3274 * (Macintosh format).
3275 * For older versions of the Metrowerks library.
3276 * At least CodeWarrior 9 needed this code.
3278 char *
3279 fgets_cr(s, n, stream)
3280 char *s;
3281 int n;
3282 FILE *stream;
3284 int c = 0;
3285 int char_read = 0;
3287 while (!feof(stream) && c != '\r' && c != '\n' && char_read < n - 1)
3289 c = fgetc(stream);
3290 s[char_read++] = c;
3291 /* If the file is in DOS format, we need to skip a NL after a CR. I
3292 * thought it was the other way around, but this appears to work... */
3293 if (c == '\n')
3295 c = fgetc(stream);
3296 if (c != '\r')
3297 ungetc(c, stream);
3301 s[char_read] = 0;
3302 if (char_read == 0)
3303 return NULL;
3305 if (feof(stream) && char_read == 1)
3306 return NULL;
3308 return s;
3310 # endif
3311 #endif
3314 * Get one full line from a sourced file.
3315 * Called by do_cmdline() when it's called from do_source().
3317 * Return a pointer to the line in allocated memory.
3318 * Return NULL for end-of-file or some error.
3320 /* ARGSUSED */
3321 char_u *
3322 getsourceline(c, cookie, indent)
3323 int c; /* not used */
3324 void *cookie;
3325 int indent; /* not used */
3327 struct source_cookie *sp = (struct source_cookie *)cookie;
3328 char_u *line;
3329 char_u *p, *s;
3331 #ifdef FEAT_EVAL
3332 /* If breakpoints have been added/deleted need to check for it. */
3333 if (sp->dbg_tick < debug_tick)
3335 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
3336 sp->dbg_tick = debug_tick;
3338 # ifdef FEAT_PROFILE
3339 if (do_profiling == PROF_YES)
3340 script_line_end();
3341 # endif
3342 #endif
3344 * Get current line. If there is a read-ahead line, use it, otherwise get
3345 * one now.
3347 if (sp->finished)
3348 line = NULL;
3349 else if (sp->nextline == NULL)
3350 line = get_one_sourceline(sp);
3351 else
3353 line = sp->nextline;
3354 sp->nextline = NULL;
3355 ++sourcing_lnum;
3357 #ifdef FEAT_PROFILE
3358 if (line != NULL && do_profiling == PROF_YES)
3359 script_line_start();
3360 #endif
3362 /* Only concatenate lines starting with a \ when 'cpoptions' doesn't
3363 * contain the 'C' flag. */
3364 if (line != NULL && (vim_strchr(p_cpo, CPO_CONCAT) == NULL))
3366 /* compensate for the one line read-ahead */
3367 --sourcing_lnum;
3368 for (;;)
3370 sp->nextline = get_one_sourceline(sp);
3371 if (sp->nextline == NULL)
3372 break;
3373 p = skipwhite(sp->nextline);
3374 if (*p != '\\')
3375 break;
3376 s = alloc((int)(STRLEN(line) + STRLEN(p)));
3377 if (s == NULL) /* out of memory */
3378 break;
3379 STRCPY(s, line);
3380 STRCAT(s, p + 1);
3381 vim_free(line);
3382 line = s;
3383 vim_free(sp->nextline);
3387 #ifdef FEAT_MBYTE
3388 if (line != NULL && sp->conv.vc_type != CONV_NONE)
3390 /* Convert the encoding of the script line. */
3391 s = string_convert(&sp->conv, line, NULL);
3392 if (s != NULL)
3394 vim_free(line);
3395 line = s;
3398 #endif
3400 #ifdef FEAT_EVAL
3401 /* Did we encounter a breakpoint? */
3402 if (sp->breakpoint != 0 && sp->breakpoint <= sourcing_lnum)
3404 dbg_breakpoint(sp->fname, sourcing_lnum);
3405 /* Find next breakpoint. */
3406 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
3407 sp->dbg_tick = debug_tick;
3409 #endif
3411 return line;
3414 static char_u *
3415 get_one_sourceline(sp)
3416 struct source_cookie *sp;
3418 garray_T ga;
3419 int len;
3420 int c;
3421 char_u *buf;
3422 #ifdef USE_CRNL
3423 int has_cr; /* CR-LF found */
3424 #endif
3425 #ifdef USE_CR
3426 char_u *scan;
3427 #endif
3428 int have_read = FALSE;
3430 /* use a growarray to store the sourced line */
3431 ga_init2(&ga, 1, 250);
3434 * Loop until there is a finished line (or end-of-file).
3436 sourcing_lnum++;
3437 for (;;)
3439 /* make room to read at least 120 (more) characters */
3440 if (ga_grow(&ga, 120) == FAIL)
3441 break;
3442 buf = (char_u *)ga.ga_data;
3444 #ifdef USE_CR
3445 if (sp->fileformat == EOL_MAC)
3447 if (fgets_cr((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
3448 sp->fp) == NULL)
3449 break;
3451 else
3452 #endif
3453 if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
3454 sp->fp) == NULL)
3455 break;
3456 len = ga.ga_len + (int)STRLEN(buf + ga.ga_len);
3457 #ifdef USE_CRNL
3458 /* Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the
3459 * CTRL-Z by its own, or after a NL. */
3460 if ( (len == 1 || (len >= 2 && buf[len - 2] == '\n'))
3461 && sp->fileformat == EOL_DOS
3462 && buf[len - 1] == Ctrl_Z)
3464 buf[len - 1] = NUL;
3465 break;
3467 #endif
3469 #ifdef USE_CR
3470 /* If the read doesn't stop on a new line, and there's
3471 * some CR then we assume a Mac format */
3472 if (sp->fileformat == EOL_UNKNOWN)
3474 if (buf[len - 1] != '\n' && vim_strchr(buf, '\r') != NULL)
3475 sp->fileformat = EOL_MAC;
3476 else
3477 sp->fileformat = EOL_UNIX;
3480 if (sp->fileformat == EOL_MAC)
3482 scan = vim_strchr(buf, '\r');
3484 if (scan != NULL)
3486 *scan = '\n';
3487 if (*(scan + 1) != 0)
3489 *(scan + 1) = 0;
3490 fseek(sp->fp, (long)(scan - buf - len + 1), SEEK_CUR);
3493 len = STRLEN(buf);
3495 #endif
3497 have_read = TRUE;
3498 ga.ga_len = len;
3500 /* If the line was longer than the buffer, read more. */
3501 if (ga.ga_maxlen - ga.ga_len == 1 && buf[len - 1] != '\n')
3502 continue;
3504 if (len >= 1 && buf[len - 1] == '\n') /* remove trailing NL */
3506 #ifdef USE_CRNL
3507 has_cr = (len >= 2 && buf[len - 2] == '\r');
3508 if (sp->fileformat == EOL_UNKNOWN)
3510 if (has_cr)
3511 sp->fileformat = EOL_DOS;
3512 else
3513 sp->fileformat = EOL_UNIX;
3516 if (sp->fileformat == EOL_DOS)
3518 if (has_cr) /* replace trailing CR */
3520 buf[len - 2] = '\n';
3521 --len;
3522 --ga.ga_len;
3524 else /* lines like ":map xx yy^M" will have failed */
3526 if (!sp->error)
3528 msg_source(hl_attr(HLF_W));
3529 EMSG(_("W15: Warning: Wrong line separator, ^M may be missing"));
3531 sp->error = TRUE;
3532 sp->fileformat = EOL_UNIX;
3535 #endif
3536 /* The '\n' is escaped if there is an odd number of ^V's just
3537 * before it, first set "c" just before the 'V's and then check
3538 * len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo */
3539 for (c = len - 2; c >= 0 && buf[c] == Ctrl_V; c--)
3541 if ((len & 1) != (c & 1)) /* escaped NL, read more */
3543 sourcing_lnum++;
3544 continue;
3547 buf[len - 1] = NUL; /* remove the NL */
3551 * Check for ^C here now and then, so recursive :so can be broken.
3553 line_breakcheck();
3554 break;
3557 if (have_read)
3558 return (char_u *)ga.ga_data;
3560 vim_free(ga.ga_data);
3561 return NULL;
3564 #if defined(FEAT_PROFILE) || defined(PROTO)
3566 * Called when starting to read a script line.
3567 * "sourcing_lnum" must be correct!
3568 * When skipping lines it may not actually be executed, but we won't find out
3569 * until later and we need to store the time now.
3571 void
3572 script_line_start()
3574 scriptitem_T *si;
3575 sn_prl_T *pp;
3577 if (current_SID <= 0 || current_SID > script_items.ga_len)
3578 return;
3579 si = &SCRIPT_ITEM(current_SID);
3580 if (si->sn_prof_on && sourcing_lnum >= 1)
3582 /* Grow the array before starting the timer, so that the time spend
3583 * here isn't counted. */
3584 ga_grow(&si->sn_prl_ga, (int)(sourcing_lnum - si->sn_prl_ga.ga_len));
3585 si->sn_prl_idx = sourcing_lnum - 1;
3586 while (si->sn_prl_ga.ga_len <= si->sn_prl_idx
3587 && si->sn_prl_ga.ga_len < si->sn_prl_ga.ga_maxlen)
3589 /* Zero counters for a line that was not used before. */
3590 pp = &PRL_ITEM(si, si->sn_prl_ga.ga_len);
3591 pp->snp_count = 0;
3592 profile_zero(&pp->sn_prl_total);
3593 profile_zero(&pp->sn_prl_self);
3594 ++si->sn_prl_ga.ga_len;
3596 si->sn_prl_execed = FALSE;
3597 profile_start(&si->sn_prl_start);
3598 profile_zero(&si->sn_prl_children);
3599 profile_get_wait(&si->sn_prl_wait);
3604 * Called when actually executing a function line.
3606 void
3607 script_line_exec()
3609 scriptitem_T *si;
3611 if (current_SID <= 0 || current_SID > script_items.ga_len)
3612 return;
3613 si = &SCRIPT_ITEM(current_SID);
3614 if (si->sn_prof_on && si->sn_prl_idx >= 0)
3615 si->sn_prl_execed = TRUE;
3619 * Called when done with a function line.
3621 void
3622 script_line_end()
3624 scriptitem_T *si;
3625 sn_prl_T *pp;
3627 if (current_SID <= 0 || current_SID > script_items.ga_len)
3628 return;
3629 si = &SCRIPT_ITEM(current_SID);
3630 if (si->sn_prof_on && si->sn_prl_idx >= 0
3631 && si->sn_prl_idx < si->sn_prl_ga.ga_len)
3633 if (si->sn_prl_execed)
3635 pp = &PRL_ITEM(si, si->sn_prl_idx);
3636 ++pp->snp_count;
3637 profile_end(&si->sn_prl_start);
3638 profile_sub_wait(&si->sn_prl_wait, &si->sn_prl_start);
3639 profile_add(&pp->sn_prl_total, &si->sn_prl_start);
3640 profile_self(&pp->sn_prl_self, &si->sn_prl_start,
3641 &si->sn_prl_children);
3643 si->sn_prl_idx = -1;
3646 #endif
3649 * ":scriptencoding": Set encoding conversion for a sourced script.
3650 * Without the multi-byte feature it's simply ignored.
3652 /*ARGSUSED*/
3653 void
3654 ex_scriptencoding(eap)
3655 exarg_T *eap;
3657 #ifdef FEAT_MBYTE
3658 struct source_cookie *sp;
3659 char_u *name;
3661 if (!getline_equal(eap->getline, eap->cookie, getsourceline))
3663 EMSG(_("E167: :scriptencoding used outside of a sourced file"));
3664 return;
3667 if (*eap->arg != NUL)
3669 name = enc_canonize(eap->arg);
3670 if (name == NULL) /* out of memory */
3671 return;
3673 else
3674 name = eap->arg;
3676 /* Setup for conversion from the specified encoding to 'encoding'. */
3677 sp = (struct source_cookie *)getline_cookie(eap->getline, eap->cookie);
3678 convert_setup(&sp->conv, name, p_enc);
3680 if (name != eap->arg)
3681 vim_free(name);
3682 #endif
3685 #if defined(FEAT_EVAL) || defined(PROTO)
3687 * ":finish": Mark a sourced file as finished.
3689 void
3690 ex_finish(eap)
3691 exarg_T *eap;
3693 if (getline_equal(eap->getline, eap->cookie, getsourceline))
3694 do_finish(eap, FALSE);
3695 else
3696 EMSG(_("E168: :finish used outside of a sourced file"));
3700 * Mark a sourced file as finished. Possibly makes the ":finish" pending.
3701 * Also called for a pending finish at the ":endtry" or after returning from
3702 * an extra do_cmdline(). "reanimate" is used in the latter case.
3704 void
3705 do_finish(eap, reanimate)
3706 exarg_T *eap;
3707 int reanimate;
3709 int idx;
3711 if (reanimate)
3712 ((struct source_cookie *)getline_cookie(eap->getline,
3713 eap->cookie))->finished = FALSE;
3716 * Cleanup (and inactivate) conditionals, but stop when a try conditional
3717 * not in its finally clause (which then is to be executed next) is found.
3718 * In this case, make the ":finish" pending for execution at the ":endtry".
3719 * Otherwise, finish normally.
3721 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
3722 if (idx >= 0)
3724 eap->cstack->cs_pending[idx] = CSTP_FINISH;
3725 report_make_pending(CSTP_FINISH, NULL);
3727 else
3728 ((struct source_cookie *)getline_cookie(eap->getline,
3729 eap->cookie))->finished = TRUE;
3734 * Return TRUE when a sourced file had the ":finish" command: Don't give error
3735 * message for missing ":endif".
3736 * Return FALSE when not sourcing a file.
3739 source_finished(fgetline, cookie)
3740 char_u *(*fgetline) __ARGS((int, void *, int));
3741 void *cookie;
3743 return (getline_equal(fgetline, cookie, getsourceline)
3744 && ((struct source_cookie *)getline_cookie(
3745 fgetline, cookie))->finished);
3747 #endif
3749 #if defined(FEAT_LISTCMDS) || defined(PROTO)
3751 * ":checktime [buffer]"
3753 void
3754 ex_checktime(eap)
3755 exarg_T *eap;
3757 buf_T *buf;
3758 int save_no_check_timestamps = no_check_timestamps;
3760 no_check_timestamps = 0;
3761 if (eap->addr_count == 0) /* default is all buffers */
3762 check_timestamps(FALSE);
3763 else
3765 buf = buflist_findnr((int)eap->line2);
3766 if (buf != NULL) /* cannot happen? */
3767 (void)buf_check_timestamp(buf, FALSE);
3769 no_check_timestamps = save_no_check_timestamps;
3771 #endif
3773 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3774 && (defined(FEAT_EVAL) || defined(FEAT_MULTI_LANG))
3775 static char *get_locale_val __ARGS((int what));
3777 static char *
3778 get_locale_val(what)
3779 int what;
3781 char *loc;
3783 /* Obtain the locale value from the libraries. For DJGPP this is
3784 * redefined and it doesn't use the arguments. */
3785 loc = setlocale(what, NULL);
3787 # ifdef WIN32
3788 if (loc != NULL)
3790 char_u *p;
3792 /* setocale() returns something like "LC_COLLATE=<name>;LC_..." when
3793 * one of the values (e.g., LC_CTYPE) differs. */
3794 p = vim_strchr(loc, '=');
3795 if (p != NULL)
3797 loc = ++p;
3798 while (*p != NUL) /* remove trailing newline */
3800 if (*p < ' ' || *p == ';')
3802 *p = NUL;
3803 break;
3805 ++p;
3809 # endif
3811 return loc;
3813 #endif
3816 #ifdef WIN32
3818 * On MS-Windows locale names are strings like "German_Germany.1252", but
3819 * gettext expects "de". Try to translate one into another here for a few
3820 * supported languages.
3822 static char_u *
3823 gettext_lang(char_u *name)
3825 int i;
3826 static char *(mtable[]) = {
3827 "afrikaans", "af",
3828 "czech", "cs",
3829 "dutch", "nl",
3830 "german", "de",
3831 "english_united kingdom", "en_GB",
3832 "spanish", "es",
3833 "french", "fr",
3834 "italian", "it",
3835 "japanese", "ja",
3836 "korean", "ko",
3837 "norwegian", "no",
3838 "polish", "pl",
3839 "russian", "ru",
3840 "slovak", "sk",
3841 "swedish", "sv",
3842 "ukrainian", "uk",
3843 "chinese_china", "zh_CN",
3844 "chinese_taiwan", "zh_TW",
3845 NULL};
3847 for (i = 0; mtable[i] != NULL; i += 2)
3848 if (STRNICMP(mtable[i], name, STRLEN(mtable[i])) == 0)
3849 return mtable[i + 1];
3850 return name;
3852 #endif
3854 #if defined(FEAT_MULTI_LANG) || defined(PROTO)
3856 * Obtain the current messages language. Used to set the default for
3857 * 'helplang'. May return NULL or an empty string.
3859 char_u *
3860 get_mess_lang()
3862 char_u *p;
3864 # if (defined(HAVE_LOCALE_H) || defined(X_LOCALE))
3865 # if defined(LC_MESSAGES)
3866 p = (char_u *)get_locale_val(LC_MESSAGES);
3867 # else
3868 /* This is necessary for Win32, where LC_MESSAGES is not defined and $LANG
3869 * may be set to the LCID number. LC_COLLATE is the best guess, LC_TIME
3870 * and LC_MONETARY may be set differently for a Japanese working in the
3871 * US. */
3872 p = (char_u *)get_locale_val(LC_COLLATE);
3873 # endif
3874 # else
3875 p = mch_getenv((char_u *)"LC_ALL");
3876 if (p == NULL || *p == NUL)
3878 p = mch_getenv((char_u *)"LC_MESSAGES");
3879 if (p == NULL || *p == NUL)
3880 p = mch_getenv((char_u *)"LANG");
3882 # endif
3883 # ifdef WIN32
3884 p = gettext_lang(p);
3885 # endif
3886 return p;
3888 #endif
3890 /* Complicated #if; matches with where get_mess_env() is used below. */
3891 #if (defined(FEAT_EVAL) && !((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3892 && defined(LC_MESSAGES))) \
3893 || ((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3894 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)) \
3895 && !defined(LC_MESSAGES))
3896 static char_u *get_mess_env __ARGS((void));
3899 * Get the language used for messages from the environment.
3901 static char_u *
3902 get_mess_env()
3904 char_u *p;
3906 p = mch_getenv((char_u *)"LC_ALL");
3907 if (p == NULL || *p == NUL)
3909 p = mch_getenv((char_u *)"LC_MESSAGES");
3910 if (p == NULL || *p == NUL)
3912 p = mch_getenv((char_u *)"LANG");
3913 if (p != NULL && VIM_ISDIGIT(*p))
3914 p = NULL; /* ignore something like "1043" */
3915 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
3916 if (p == NULL || *p == NUL)
3917 p = (char_u *)get_locale_val(LC_CTYPE);
3918 # endif
3921 return p;
3923 #endif
3925 #if defined(FEAT_EVAL) || defined(PROTO)
3928 * Set the "v:lang" variable according to the current locale setting.
3929 * Also do "v:lc_time"and "v:ctype".
3931 void
3932 set_lang_var()
3934 char_u *loc;
3936 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
3937 loc = (char_u *)get_locale_val(LC_CTYPE);
3938 # else
3939 /* setlocale() not supported: use the default value */
3940 loc = (char_u *)"C";
3941 # endif
3942 set_vim_var_string(VV_CTYPE, loc, -1);
3944 /* When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall
3945 * back to LC_CTYPE if it's empty. */
3946 # if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) && defined(LC_MESSAGES)
3947 loc = (char_u *)get_locale_val(LC_MESSAGES);
3948 # else
3949 loc = get_mess_env();
3950 # endif
3951 set_vim_var_string(VV_LANG, loc, -1);
3953 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
3954 loc = (char_u *)get_locale_val(LC_TIME);
3955 # endif
3956 set_vim_var_string(VV_LC_TIME, loc, -1);
3958 #endif
3960 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3961 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE))
3963 * ":language": Set the language (locale).
3965 void
3966 ex_language(eap)
3967 exarg_T *eap;
3969 char *loc;
3970 char_u *p;
3971 char_u *name;
3972 int what = LC_ALL;
3973 char *whatstr = "";
3974 #ifdef LC_MESSAGES
3975 # define VIM_LC_MESSAGES LC_MESSAGES
3976 #else
3977 # define VIM_LC_MESSAGES 6789
3978 #endif
3980 name = eap->arg;
3982 /* Check for "messages {name}", "ctype {name}" or "time {name}" argument.
3983 * Allow abbreviation, but require at least 3 characters to avoid
3984 * confusion with a two letter language name "me" or "ct". */
3985 p = skiptowhite(eap->arg);
3986 if ((*p == NUL || vim_iswhite(*p)) && p - eap->arg >= 3)
3988 if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0)
3990 what = VIM_LC_MESSAGES;
3991 name = skipwhite(p);
3992 whatstr = "messages ";
3994 else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0)
3996 what = LC_CTYPE;
3997 name = skipwhite(p);
3998 whatstr = "ctype ";
4000 else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0)
4002 what = LC_TIME;
4003 name = skipwhite(p);
4004 whatstr = "time ";
4008 if (*name == NUL)
4010 #ifndef LC_MESSAGES
4011 if (what == VIM_LC_MESSAGES)
4012 p = get_mess_env();
4013 else
4014 #endif
4015 p = (char_u *)setlocale(what, NULL);
4016 if (p == NULL || *p == NUL)
4017 p = (char_u *)"Unknown";
4018 smsg((char_u *)_("Current %slanguage: \"%s\""), whatstr, p);
4020 else
4022 #ifndef LC_MESSAGES
4023 if (what == VIM_LC_MESSAGES)
4024 loc = "";
4025 else
4026 #endif
4027 loc = setlocale(what, (char *)name);
4028 if (loc == NULL)
4029 EMSG2(_("E197: Cannot set language to \"%s\""), name);
4030 else
4032 #ifdef HAVE_NL_MSG_CAT_CNTR
4033 /* Need to do this for GNU gettext, otherwise cached translations
4034 * will be used again. */
4035 extern int _nl_msg_cat_cntr;
4037 ++_nl_msg_cat_cntr;
4038 #endif
4039 /* Reset $LC_ALL, otherwise it would overrule everything. */
4040 vim_setenv((char_u *)"LC_ALL", (char_u *)"");
4042 if (what != LC_TIME)
4044 /* Tell gettext() what to translate to. It apparently doesn't
4045 * use the currently effective locale. Also do this when
4046 * FEAT_GETTEXT isn't defined, so that shell commands use this
4047 * value. */
4048 if (what == LC_ALL)
4050 vim_setenv((char_u *)"LANG", name);
4051 # ifdef WIN32
4052 /* Apparently MS-Windows printf() may cause a crash when
4053 * we give it 8-bit text while it's expecting text in the
4054 * current locale. This call avoids that. */
4055 setlocale(LC_CTYPE, "C");
4056 # endif
4058 if (what != LC_CTYPE)
4060 char_u *mname;
4061 #ifdef WIN32
4062 mname = gettext_lang(name);
4063 #else
4064 mname = name;
4065 #endif
4066 vim_setenv((char_u *)"LC_MESSAGES", mname);
4067 #ifdef FEAT_MULTI_LANG
4068 set_helplang_default(mname);
4069 #endif
4072 /* Set $LC_CTYPE, because it overrules $LANG, and
4073 * gtk_set_locale() calls setlocale() again. gnome_init()
4074 * sets $LC_CTYPE to "en_US" (that's a bug!). */
4075 if (what != VIM_LC_MESSAGES)
4076 vim_setenv((char_u *)"LC_CTYPE", name);
4077 # ifdef FEAT_GUI_GTK
4078 /* Let GTK know what locale we're using. Not sure this is
4079 * really needed... */
4080 if (gui.in_use)
4081 (void)gtk_set_locale();
4082 # endif
4085 # ifdef FEAT_EVAL
4086 /* Set v:lang, v:lc_time and v:ctype to the final result. */
4087 set_lang_var();
4088 # endif
4093 # if defined(FEAT_CMDL_COMPL) || defined(PROTO)
4095 * Function given to ExpandGeneric() to obtain the possible arguments of the
4096 * ":language" command.
4098 /*ARGSUSED*/
4099 char_u *
4100 get_lang_arg(xp, idx)
4101 expand_T *xp;
4102 int idx;
4104 if (idx == 0)
4105 return (char_u *)"messages";
4106 if (idx == 1)
4107 return (char_u *)"ctype";
4108 if (idx == 2)
4109 return (char_u *)"time";
4110 return NULL;
4112 # endif
4114 #endif