Merged from the latest developing branch.
[MacVim.git] / src / ex_cmds2.c
blob2c0f80dfe747c69f7e3b5c00f2917f8bc4e5a50c
1 /* vi:set ts=8 sts=4 sw=4:
3 * VIM - Vi IMproved by Bram Moolenaar
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
11 * ex_cmds2.c: some more functions for command line commands
14 #if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64)
15 # include "vimio.h" /* for mch_open(), must be before vim.h */
16 #endif
18 #include "vim.h"
19 #include "version.h"
21 static void cmd_source __ARGS((char_u *fname, exarg_T *eap));
23 #ifdef FEAT_EVAL
24 /* Growarray to store info about already sourced scripts.
25 * For Unix also store the dev/ino, so that we don't have to stat() each
26 * script when going through the list. */
27 typedef struct scriptitem_S
29 char_u *sn_name;
30 # ifdef UNIX
31 int sn_dev;
32 ino_t sn_ino;
33 # endif
34 # ifdef FEAT_PROFILE
35 int sn_prof_on; /* TRUE when script is/was profiled */
36 int sn_pr_force; /* forceit: profile functions in this script */
37 proftime_T sn_pr_child; /* time set when going into first child */
38 int sn_pr_nest; /* nesting for sn_pr_child */
39 /* profiling the script as a whole */
40 int sn_pr_count; /* nr of times sourced */
41 proftime_T sn_pr_total; /* time spent in script + children */
42 proftime_T sn_pr_self; /* time spent in script itself */
43 proftime_T sn_pr_start; /* time at script start */
44 proftime_T sn_pr_children; /* time in children after script start */
45 /* profiling the script per line */
46 garray_T sn_prl_ga; /* things stored for every line */
47 proftime_T sn_prl_start; /* start time for current line */
48 proftime_T sn_prl_children; /* time spent in children for this line */
49 proftime_T sn_prl_wait; /* wait start time for current line */
50 int sn_prl_idx; /* index of line being timed; -1 if none */
51 int sn_prl_execed; /* line being timed was executed */
52 # endif
53 } scriptitem_T;
55 static garray_T script_items = {0, 0, sizeof(scriptitem_T), 4, NULL};
56 #define SCRIPT_ITEM(id) (((scriptitem_T *)script_items.ga_data)[(id) - 1])
58 # ifdef FEAT_PROFILE
59 /* Struct used in sn_prl_ga for every line of a script. */
60 typedef struct sn_prl_S
62 int snp_count; /* nr of times line was executed */
63 proftime_T sn_prl_total; /* time spent in a line + children */
64 proftime_T sn_prl_self; /* time spent in a line itself */
65 } sn_prl_T;
67 # define PRL_ITEM(si, idx) (((sn_prl_T *)(si)->sn_prl_ga.ga_data)[(idx)])
68 # endif
69 #endif
71 #if defined(FEAT_EVAL) || defined(PROTO)
72 static int debug_greedy = FALSE; /* batch mode debugging: don't save
73 and restore typeahead. */
76 * do_debug(): Debug mode.
77 * Repeatedly get Ex commands, until told to continue normal execution.
79 void
80 do_debug(cmd)
81 char_u *cmd;
83 int save_msg_scroll = msg_scroll;
84 int save_State = State;
85 int save_did_emsg = did_emsg;
86 int save_cmd_silent = cmd_silent;
87 int save_msg_silent = msg_silent;
88 int save_emsg_silent = emsg_silent;
89 int save_redir_off = redir_off;
90 tasave_T typeaheadbuf;
91 int typeahead_saved = FALSE;
92 int save_ignore_script = 0;
93 # ifdef FEAT_EX_EXTRA
94 int save_ex_normal_busy;
95 # endif
96 int n;
97 char_u *cmdline = NULL;
98 char_u *p;
99 char *tail = NULL;
100 static int last_cmd = 0;
101 #define CMD_CONT 1
102 #define CMD_NEXT 2
103 #define CMD_STEP 3
104 #define CMD_FINISH 4
105 #define CMD_QUIT 5
106 #define CMD_INTERRUPT 6
108 #ifdef ALWAYS_USE_GUI
109 /* Can't do this when there is no terminal for input/output. */
110 if (!gui.in_use)
112 /* Break as soon as possible. */
113 debug_break_level = 9999;
114 return;
116 #endif
118 /* Make sure we are in raw mode and start termcap mode. Might have side
119 * effects... */
120 settmode(TMODE_RAW);
121 starttermcap();
123 ++RedrawingDisabled; /* don't redisplay the window */
124 ++no_wait_return; /* don't wait for return */
125 did_emsg = FALSE; /* don't use error from debugged stuff */
126 cmd_silent = FALSE; /* display commands */
127 msg_silent = FALSE; /* display messages */
128 emsg_silent = FALSE; /* display error messages */
129 redir_off = TRUE; /* don't redirect debug commands */
131 State = NORMAL;
132 #ifdef FEAT_SNIFF
133 want_sniff_request = 0; /* No K_SNIFF wanted */
134 #endif
136 if (!debug_did_msg)
137 MSG(_("Entering Debug mode. Type \"cont\" to continue."));
138 if (sourcing_name != NULL)
139 msg(sourcing_name);
140 if (sourcing_lnum != 0)
141 smsg((char_u *)_("line %ld: %s"), (long)sourcing_lnum, cmd);
142 else
143 smsg((char_u *)_("cmd: %s"), cmd);
146 * Repeat getting a command and executing it.
148 for (;;)
150 msg_scroll = TRUE;
151 need_wait_return = FALSE;
152 #ifdef FEAT_SNIFF
153 ProcessSniffRequests();
154 #endif
155 /* Save the current typeahead buffer and replace it with an empty one.
156 * This makes sure we get input from the user here and don't interfere
157 * with the commands being executed. Reset "ex_normal_busy" to avoid
158 * the side effects of using ":normal". Save the stuff buffer and make
159 * it empty. Set ignore_script to avoid reading from script input. */
160 # ifdef FEAT_EX_EXTRA
161 save_ex_normal_busy = ex_normal_busy;
162 ex_normal_busy = 0;
163 # endif
164 if (!debug_greedy)
166 save_typeahead(&typeaheadbuf);
167 typeahead_saved = TRUE;
168 save_ignore_script = ignore_script;
169 ignore_script = TRUE;
172 cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL);
174 if (typeahead_saved)
176 restore_typeahead(&typeaheadbuf);
177 ignore_script = save_ignore_script;
179 # ifdef FEAT_EX_EXTRA
180 ex_normal_busy = save_ex_normal_busy;
181 # endif
183 cmdline_row = msg_row;
184 if (cmdline != NULL)
186 /* If this is a debug command, set "last_cmd".
187 * If not, reset "last_cmd".
188 * For a blank line use previous command. */
189 p = skipwhite(cmdline);
190 if (*p != NUL)
192 switch (*p)
194 case 'c': last_cmd = CMD_CONT;
195 tail = "ont";
196 break;
197 case 'n': last_cmd = CMD_NEXT;
198 tail = "ext";
199 break;
200 case 's': last_cmd = CMD_STEP;
201 tail = "tep";
202 break;
203 case 'f': last_cmd = CMD_FINISH;
204 tail = "inish";
205 break;
206 case 'q': last_cmd = CMD_QUIT;
207 tail = "uit";
208 break;
209 case 'i': last_cmd = CMD_INTERRUPT;
210 tail = "nterrupt";
211 break;
212 default: last_cmd = 0;
214 if (last_cmd != 0)
216 /* Check that the tail matches. */
217 ++p;
218 while (*p != NUL && *p == *tail)
220 ++p;
221 ++tail;
223 if (ASCII_ISALPHA(*p))
224 last_cmd = 0;
228 if (last_cmd != 0)
230 /* Execute debug command: decided where to break next and
231 * return. */
232 switch (last_cmd)
234 case CMD_CONT:
235 debug_break_level = -1;
236 break;
237 case CMD_NEXT:
238 debug_break_level = ex_nesting_level;
239 break;
240 case CMD_STEP:
241 debug_break_level = 9999;
242 break;
243 case CMD_FINISH:
244 debug_break_level = ex_nesting_level - 1;
245 break;
246 case CMD_QUIT:
247 got_int = TRUE;
248 debug_break_level = -1;
249 break;
250 case CMD_INTERRUPT:
251 got_int = TRUE;
252 debug_break_level = 9999;
253 /* Do not repeat ">interrupt" cmd, continue stepping. */
254 last_cmd = CMD_STEP;
255 break;
257 break;
260 /* don't debug this command */
261 n = debug_break_level;
262 debug_break_level = -1;
263 (void)do_cmdline(cmdline, getexline, NULL,
264 DOCMD_VERBOSE|DOCMD_EXCRESET);
265 debug_break_level = n;
267 vim_free(cmdline);
269 lines_left = Rows - 1;
271 vim_free(cmdline);
273 --RedrawingDisabled;
274 --no_wait_return;
275 redraw_all_later(NOT_VALID);
276 need_wait_return = FALSE;
277 msg_scroll = save_msg_scroll;
278 lines_left = Rows - 1;
279 State = save_State;
280 did_emsg = save_did_emsg;
281 cmd_silent = save_cmd_silent;
282 msg_silent = save_msg_silent;
283 emsg_silent = save_emsg_silent;
284 redir_off = save_redir_off;
286 /* Only print the message again when typing a command before coming back
287 * here. */
288 debug_did_msg = TRUE;
292 * ":debug".
294 void
295 ex_debug(eap)
296 exarg_T *eap;
298 int debug_break_level_save = debug_break_level;
300 debug_break_level = 9999;
301 do_cmdline_cmd(eap->arg);
302 debug_break_level = debug_break_level_save;
305 static char_u *debug_breakpoint_name = NULL;
306 static linenr_T debug_breakpoint_lnum;
309 * When debugging or a breakpoint is set on a skipped command, no debug prompt
310 * is shown by do_one_cmd(). This situation is indicated by debug_skipped, and
311 * debug_skipped_name is then set to the source name in the breakpoint case. If
312 * a skipped command decides itself that a debug prompt should be displayed, it
313 * can do so by calling dbg_check_skipped().
315 static int debug_skipped;
316 static char_u *debug_skipped_name;
319 * Go to debug mode when a breakpoint was encountered or "ex_nesting_level" is
320 * at or below the break level. But only when the line is actually
321 * executed. Return TRUE and set breakpoint_name for skipped commands that
322 * decide to execute something themselves.
323 * Called from do_one_cmd() before executing a command.
325 void
326 dbg_check_breakpoint(eap)
327 exarg_T *eap;
329 char_u *p;
331 debug_skipped = FALSE;
332 if (debug_breakpoint_name != NULL)
334 if (!eap->skip)
336 /* replace K_SNR with "<SNR>" */
337 if (debug_breakpoint_name[0] == K_SPECIAL
338 && debug_breakpoint_name[1] == KS_EXTRA
339 && debug_breakpoint_name[2] == (int)KE_SNR)
340 p = (char_u *)"<SNR>";
341 else
342 p = (char_u *)"";
343 smsg((char_u *)_("Breakpoint in \"%s%s\" line %ld"),
345 debug_breakpoint_name + (*p == NUL ? 0 : 3),
346 (long)debug_breakpoint_lnum);
347 debug_breakpoint_name = NULL;
348 do_debug(eap->cmd);
350 else
352 debug_skipped = TRUE;
353 debug_skipped_name = debug_breakpoint_name;
354 debug_breakpoint_name = NULL;
357 else if (ex_nesting_level <= debug_break_level)
359 if (!eap->skip)
360 do_debug(eap->cmd);
361 else
363 debug_skipped = TRUE;
364 debug_skipped_name = NULL;
370 * Go to debug mode if skipped by dbg_check_breakpoint() because eap->skip was
371 * set. Return TRUE when the debug mode is entered this time.
374 dbg_check_skipped(eap)
375 exarg_T *eap;
377 int prev_got_int;
379 if (debug_skipped)
382 * Save the value of got_int and reset it. We don't want a previous
383 * interruption cause flushing the input buffer.
385 prev_got_int = got_int;
386 got_int = FALSE;
387 debug_breakpoint_name = debug_skipped_name;
388 /* eap->skip is TRUE */
389 eap->skip = FALSE;
390 (void)dbg_check_breakpoint(eap);
391 eap->skip = TRUE;
392 got_int |= prev_got_int;
393 return TRUE;
395 return FALSE;
399 * The list of breakpoints: dbg_breakp.
400 * This is a grow-array of structs.
402 struct debuggy
404 int dbg_nr; /* breakpoint number */
405 int dbg_type; /* DBG_FUNC or DBG_FILE */
406 char_u *dbg_name; /* function or file name */
407 regprog_T *dbg_prog; /* regexp program */
408 linenr_T dbg_lnum; /* line number in function or file */
409 int dbg_forceit; /* ! used */
412 static garray_T dbg_breakp = {0, 0, sizeof(struct debuggy), 4, NULL};
413 #define BREAKP(idx) (((struct debuggy *)dbg_breakp.ga_data)[idx])
414 #define DEBUGGY(gap, idx) (((struct debuggy *)gap->ga_data)[idx])
415 static int last_breakp = 0; /* nr of last defined breakpoint */
417 #ifdef FEAT_PROFILE
418 /* Profiling uses file and func names similar to breakpoints. */
419 static garray_T prof_ga = {0, 0, sizeof(struct debuggy), 4, NULL};
420 #endif
421 #define DBG_FUNC 1
422 #define DBG_FILE 2
424 static int dbg_parsearg __ARGS((char_u *arg, garray_T *gap));
425 static linenr_T debuggy_find __ARGS((int file,char_u *fname, linenr_T after, garray_T *gap, int *fp));
428 * Parse the arguments of ":profile", ":breakadd" or ":breakdel" and put them
429 * in the entry just after the last one in dbg_breakp. Note that "dbg_name"
430 * is allocated.
431 * Returns FAIL for failure.
433 static int
434 dbg_parsearg(arg, gap)
435 char_u *arg;
436 garray_T *gap; /* either &dbg_breakp or &prof_ga */
438 char_u *p = arg;
439 char_u *q;
440 struct debuggy *bp;
441 int here = FALSE;
443 if (ga_grow(gap, 1) == FAIL)
444 return FAIL;
445 bp = &DEBUGGY(gap, gap->ga_len);
447 /* Find "func" or "file". */
448 if (STRNCMP(p, "func", 4) == 0)
449 bp->dbg_type = DBG_FUNC;
450 else if (STRNCMP(p, "file", 4) == 0)
451 bp->dbg_type = DBG_FILE;
452 else if (
453 #ifdef FEAT_PROFILE
454 gap != &prof_ga &&
455 #endif
456 STRNCMP(p, "here", 4) == 0)
458 if (curbuf->b_ffname == NULL)
460 EMSG(_(e_noname));
461 return FAIL;
463 bp->dbg_type = DBG_FILE;
464 here = TRUE;
466 else
468 EMSG2(_(e_invarg2), p);
469 return FAIL;
471 p = skipwhite(p + 4);
473 /* Find optional line number. */
474 if (here)
475 bp->dbg_lnum = curwin->w_cursor.lnum;
476 else if (
477 #ifdef FEAT_PROFILE
478 gap != &prof_ga &&
479 #endif
480 VIM_ISDIGIT(*p))
482 bp->dbg_lnum = getdigits(&p);
483 p = skipwhite(p);
485 else
486 bp->dbg_lnum = 0;
488 /* Find the function or file name. Don't accept a function name with (). */
489 if ((!here && *p == NUL)
490 || (here && *p != NUL)
491 || (bp->dbg_type == DBG_FUNC && strstr((char *)p, "()") != NULL))
493 EMSG2(_(e_invarg2), arg);
494 return FAIL;
497 if (bp->dbg_type == DBG_FUNC)
498 bp->dbg_name = vim_strsave(p);
499 else if (here)
500 bp->dbg_name = vim_strsave(curbuf->b_ffname);
501 else
503 /* Expand the file name in the same way as do_source(). This means
504 * doing it twice, so that $DIR/file gets expanded when $DIR is
505 * "~/dir". */
506 #ifdef RISCOS
507 q = mch_munge_fname(p);
508 #else
509 q = expand_env_save(p);
510 #endif
511 if (q == NULL)
512 return FAIL;
513 #ifdef RISCOS
514 p = mch_munge_fname(q);
515 #else
516 p = expand_env_save(q);
517 #endif
518 vim_free(q);
519 if (p == NULL)
520 return FAIL;
521 if (*p != '*')
523 bp->dbg_name = fix_fname(p);
524 vim_free(p);
526 else
527 bp->dbg_name = p;
530 if (bp->dbg_name == NULL)
531 return FAIL;
532 return OK;
536 * ":breakadd".
538 void
539 ex_breakadd(eap)
540 exarg_T *eap;
542 struct debuggy *bp;
543 char_u *pat;
544 garray_T *gap;
546 gap = &dbg_breakp;
547 #ifdef FEAT_PROFILE
548 if (eap->cmdidx == CMD_profile)
549 gap = &prof_ga;
550 #endif
552 if (dbg_parsearg(eap->arg, gap) == OK)
554 bp = &DEBUGGY(gap, gap->ga_len);
555 bp->dbg_forceit = eap->forceit;
557 pat = file_pat_to_reg_pat(bp->dbg_name, NULL, NULL, FALSE);
558 if (pat != NULL)
560 bp->dbg_prog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
561 vim_free(pat);
563 if (pat == NULL || bp->dbg_prog == NULL)
564 vim_free(bp->dbg_name);
565 else
567 if (bp->dbg_lnum == 0) /* default line number is 1 */
568 bp->dbg_lnum = 1;
569 #ifdef FEAT_PROFILE
570 if (eap->cmdidx != CMD_profile)
571 #endif
573 DEBUGGY(gap, gap->ga_len).dbg_nr = ++last_breakp;
574 ++debug_tick;
576 ++gap->ga_len;
582 * ":debuggreedy".
584 void
585 ex_debuggreedy(eap)
586 exarg_T *eap;
588 if (eap->addr_count == 0 || eap->line2 != 0)
589 debug_greedy = TRUE;
590 else
591 debug_greedy = FALSE;
595 * ":breakdel" and ":profdel".
597 void
598 ex_breakdel(eap)
599 exarg_T *eap;
601 struct debuggy *bp, *bpi;
602 int nr;
603 int todel = -1;
604 int del_all = FALSE;
605 int i;
606 linenr_T best_lnum = 0;
607 garray_T *gap;
609 gap = &dbg_breakp;
610 #ifdef FEAT_PROFILE
611 if (eap->cmdidx == CMD_profdel)
612 gap = &prof_ga;
613 #endif
615 if (vim_isdigit(*eap->arg))
617 /* ":breakdel {nr}" */
618 nr = atol((char *)eap->arg);
619 for (i = 0; i < gap->ga_len; ++i)
620 if (DEBUGGY(gap, i).dbg_nr == nr)
622 todel = i;
623 break;
626 else if (*eap->arg == '*')
628 todel = 0;
629 del_all = TRUE;
631 else
633 /* ":breakdel {func|file} [lnum] {name}" */
634 if (dbg_parsearg(eap->arg, gap) == FAIL)
635 return;
636 bp = &DEBUGGY(gap, gap->ga_len);
637 for (i = 0; i < gap->ga_len; ++i)
639 bpi = &DEBUGGY(gap, i);
640 if (bp->dbg_type == bpi->dbg_type
641 && STRCMP(bp->dbg_name, bpi->dbg_name) == 0
642 && (bp->dbg_lnum == bpi->dbg_lnum
643 || (bp->dbg_lnum == 0
644 && (best_lnum == 0
645 || bpi->dbg_lnum < best_lnum))))
647 todel = i;
648 best_lnum = bpi->dbg_lnum;
651 vim_free(bp->dbg_name);
654 if (todel < 0)
655 EMSG2(_("E161: Breakpoint not found: %s"), eap->arg);
656 else
658 while (gap->ga_len > 0)
660 vim_free(DEBUGGY(gap, todel).dbg_name);
661 vim_free(DEBUGGY(gap, todel).dbg_prog);
662 --gap->ga_len;
663 if (todel < gap->ga_len)
664 mch_memmove(&DEBUGGY(gap, todel), &DEBUGGY(gap, todel + 1),
665 (gap->ga_len - todel) * sizeof(struct debuggy));
666 #ifdef FEAT_PROFILE
667 if (eap->cmdidx == CMD_breakdel)
668 #endif
669 ++debug_tick;
670 if (!del_all)
671 break;
674 /* If all breakpoints were removed clear the array. */
675 if (gap->ga_len == 0)
676 ga_clear(gap);
681 * ":breaklist".
683 /*ARGSUSED*/
684 void
685 ex_breaklist(eap)
686 exarg_T *eap;
688 struct debuggy *bp;
689 int i;
691 if (dbg_breakp.ga_len == 0)
692 MSG(_("No breakpoints defined"));
693 else
694 for (i = 0; i < dbg_breakp.ga_len; ++i)
696 bp = &BREAKP(i);
697 smsg((char_u *)_("%3d %s %s line %ld"),
698 bp->dbg_nr,
699 bp->dbg_type == DBG_FUNC ? "func" : "file",
700 bp->dbg_name,
701 (long)bp->dbg_lnum);
706 * Find a breakpoint for a function or sourced file.
707 * Returns line number at which to break; zero when no matching breakpoint.
709 linenr_T
710 dbg_find_breakpoint(file, fname, after)
711 int file; /* TRUE for a file, FALSE for a function */
712 char_u *fname; /* file or function name */
713 linenr_T after; /* after this line number */
715 return debuggy_find(file, fname, after, &dbg_breakp, NULL);
718 #if defined(FEAT_PROFILE) || defined(PROTO)
720 * Return TRUE if profiling is on for a function or sourced file.
723 has_profiling(file, fname, fp)
724 int file; /* TRUE for a file, FALSE for a function */
725 char_u *fname; /* file or function name */
726 int *fp; /* return: forceit */
728 return (debuggy_find(file, fname, (linenr_T)0, &prof_ga, fp)
729 != (linenr_T)0);
731 #endif
734 * Common code for dbg_find_breakpoint() and has_profiling().
736 static linenr_T
737 debuggy_find(file, fname, after, gap, fp)
738 int file; /* TRUE for a file, FALSE for a function */
739 char_u *fname; /* file or function name */
740 linenr_T after; /* after this line number */
741 garray_T *gap; /* either &dbg_breakp or &prof_ga */
742 int *fp; /* if not NULL: return forceit */
744 struct debuggy *bp;
745 int i;
746 linenr_T lnum = 0;
747 regmatch_T regmatch;
748 char_u *name = fname;
749 int prev_got_int;
751 /* Return quickly when there are no breakpoints. */
752 if (gap->ga_len == 0)
753 return (linenr_T)0;
755 /* Replace K_SNR in function name with "<SNR>". */
756 if (!file && fname[0] == K_SPECIAL)
758 name = alloc((unsigned)STRLEN(fname) + 3);
759 if (name == NULL)
760 name = fname;
761 else
763 STRCPY(name, "<SNR>");
764 STRCPY(name + 5, fname + 3);
768 for (i = 0; i < gap->ga_len; ++i)
770 /* Skip entries that are not useful or are for a line that is beyond
771 * an already found breakpoint. */
772 bp = &DEBUGGY(gap, i);
773 if (((bp->dbg_type == DBG_FILE) == file && (
774 #ifdef FEAT_PROFILE
775 gap == &prof_ga ||
776 #endif
777 (bp->dbg_lnum > after && (lnum == 0 || bp->dbg_lnum < lnum)))))
779 regmatch.regprog = bp->dbg_prog;
780 regmatch.rm_ic = FALSE;
782 * Save the value of got_int and reset it. We don't want a
783 * previous interruption cancel matching, only hitting CTRL-C
784 * while matching should abort it.
786 prev_got_int = got_int;
787 got_int = FALSE;
788 if (vim_regexec(&regmatch, name, (colnr_T)0))
790 lnum = bp->dbg_lnum;
791 if (fp != NULL)
792 *fp = bp->dbg_forceit;
794 got_int |= prev_got_int;
797 if (name != fname)
798 vim_free(name);
800 return lnum;
804 * Called when a breakpoint was encountered.
806 void
807 dbg_breakpoint(name, lnum)
808 char_u *name;
809 linenr_T lnum;
811 /* We need to check if this line is actually executed in do_one_cmd() */
812 debug_breakpoint_name = name;
813 debug_breakpoint_lnum = lnum;
817 # if defined(FEAT_PROFILE) || defined(FEAT_RELTIME) || defined(PROTO)
819 * Store the current time in "tm".
821 void
822 profile_start(tm)
823 proftime_T *tm;
825 # ifdef WIN3264
826 QueryPerformanceCounter(tm);
827 # else
828 gettimeofday(tm, NULL);
829 # endif
833 * Compute the elapsed time from "tm" till now and store in "tm".
835 void
836 profile_end(tm)
837 proftime_T *tm;
839 proftime_T now;
841 # ifdef WIN3264
842 QueryPerformanceCounter(&now);
843 tm->QuadPart = now.QuadPart - tm->QuadPart;
844 # else
845 gettimeofday(&now, NULL);
846 tm->tv_usec = now.tv_usec - tm->tv_usec;
847 tm->tv_sec = now.tv_sec - tm->tv_sec;
848 if (tm->tv_usec < 0)
850 tm->tv_usec += 1000000;
851 --tm->tv_sec;
853 # endif
857 * Subtract the time "tm2" from "tm".
859 void
860 profile_sub(tm, tm2)
861 proftime_T *tm, *tm2;
863 # ifdef WIN3264
864 tm->QuadPart -= tm2->QuadPart;
865 # else
866 tm->tv_usec -= tm2->tv_usec;
867 tm->tv_sec -= tm2->tv_sec;
868 if (tm->tv_usec < 0)
870 tm->tv_usec += 1000000;
871 --tm->tv_sec;
873 # endif
877 * Return a string that represents the time in "tm".
878 * Uses a static buffer!
880 char *
881 profile_msg(tm)
882 proftime_T *tm;
884 static char buf[50];
886 # ifdef WIN3264
887 LARGE_INTEGER fr;
889 QueryPerformanceFrequency(&fr);
890 sprintf(buf, "%10.6lf", (double)tm->QuadPart / (double)fr.QuadPart);
891 # else
892 sprintf(buf, "%3ld.%06ld", (long)tm->tv_sec, (long)tm->tv_usec);
893 # endif
894 return buf;
898 * Put the time "msec" past now in "tm".
900 void
901 profile_setlimit(msec, tm)
902 long msec;
903 proftime_T *tm;
905 if (msec <= 0) /* no limit */
906 profile_zero(tm);
907 else
909 # ifdef WIN3264
910 LARGE_INTEGER fr;
912 QueryPerformanceCounter(tm);
913 QueryPerformanceFrequency(&fr);
914 tm->QuadPart += (LONGLONG)((double)msec / 1000.0 * (double)fr.QuadPart);
915 # else
916 long usec;
918 gettimeofday(tm, NULL);
919 usec = (long)tm->tv_usec + (long)msec * 1000;
920 tm->tv_usec = usec % 1000000L;
921 tm->tv_sec += usec / 1000000L;
922 # endif
927 * Return TRUE if the current time is past "tm".
930 profile_passed_limit(tm)
931 proftime_T *tm;
933 proftime_T now;
935 # ifdef WIN3264
936 if (tm->QuadPart == 0) /* timer was not set */
937 return FALSE;
938 QueryPerformanceCounter(&now);
939 return (now.QuadPart > tm->QuadPart);
940 # else
941 if (tm->tv_sec == 0) /* timer was not set */
942 return FALSE;
943 gettimeofday(&now, NULL);
944 return (now.tv_sec > tm->tv_sec
945 || (now.tv_sec == tm->tv_sec && now.tv_usec > tm->tv_usec));
946 # endif
950 * Set the time in "tm" to zero.
952 void
953 profile_zero(tm)
954 proftime_T *tm;
956 # ifdef WIN3264
957 tm->QuadPart = 0;
958 # else
959 tm->tv_usec = 0;
960 tm->tv_sec = 0;
961 # endif
964 # endif /* FEAT_PROFILE || FEAT_RELTIME */
966 # if defined(FEAT_PROFILE) || defined(PROTO)
968 * Functions for profiling.
970 static void script_do_profile __ARGS((scriptitem_T *si));
971 static void script_dump_profile __ARGS((FILE *fd));
972 static proftime_T prof_wait_time;
975 * Add the time "tm2" to "tm".
977 void
978 profile_add(tm, tm2)
979 proftime_T *tm, *tm2;
981 # ifdef WIN3264
982 tm->QuadPart += tm2->QuadPart;
983 # else
984 tm->tv_usec += tm2->tv_usec;
985 tm->tv_sec += tm2->tv_sec;
986 if (tm->tv_usec >= 1000000)
988 tm->tv_usec -= 1000000;
989 ++tm->tv_sec;
991 # endif
995 * Add the "self" time from the total time and the children's time.
997 void
998 profile_self(self, total, children)
999 proftime_T *self, *total, *children;
1001 /* Check that the result won't be negative. Can happen with recursive
1002 * calls. */
1003 #ifdef WIN3264
1004 if (total->QuadPart <= children->QuadPart)
1005 return;
1006 #else
1007 if (total->tv_sec < children->tv_sec
1008 || (total->tv_sec == children->tv_sec
1009 && total->tv_usec <= children->tv_usec))
1010 return;
1011 #endif
1012 profile_add(self, total);
1013 profile_sub(self, children);
1017 * Get the current waittime.
1019 void
1020 profile_get_wait(tm)
1021 proftime_T *tm;
1023 *tm = prof_wait_time;
1027 * Subtract the passed waittime since "tm" from "tma".
1029 void
1030 profile_sub_wait(tm, tma)
1031 proftime_T *tm, *tma;
1033 proftime_T tm3 = prof_wait_time;
1035 profile_sub(&tm3, tm);
1036 profile_sub(tma, &tm3);
1040 * Return TRUE if "tm1" and "tm2" are equal.
1043 profile_equal(tm1, tm2)
1044 proftime_T *tm1, *tm2;
1046 # ifdef WIN3264
1047 return (tm1->QuadPart == tm2->QuadPart);
1048 # else
1049 return (tm1->tv_usec == tm2->tv_usec && tm1->tv_sec == tm2->tv_sec);
1050 # endif
1054 * Return <0, 0 or >0 if "tm1" < "tm2", "tm1" == "tm2" or "tm1" > "tm2"
1057 profile_cmp(tm1, tm2)
1058 proftime_T *tm1, *tm2;
1060 # ifdef WIN3264
1061 return (int)(tm2->QuadPart - tm1->QuadPart);
1062 # else
1063 if (tm1->tv_sec == tm2->tv_sec)
1064 return tm2->tv_usec - tm1->tv_usec;
1065 return tm2->tv_sec - tm1->tv_sec;
1066 # endif
1069 static char_u *profile_fname = NULL;
1070 static proftime_T pause_time;
1073 * ":profile cmd args"
1075 void
1076 ex_profile(eap)
1077 exarg_T *eap;
1079 char_u *e;
1080 int len;
1082 e = skiptowhite(eap->arg);
1083 len = (int)(e - eap->arg);
1084 e = skipwhite(e);
1086 if (len == 5 && STRNCMP(eap->arg, "start", 5) == 0 && *e != NUL)
1088 vim_free(profile_fname);
1089 profile_fname = vim_strsave(e);
1090 do_profiling = PROF_YES;
1091 profile_zero(&prof_wait_time);
1092 set_vim_var_nr(VV_PROFILING, 1L);
1094 else if (do_profiling == PROF_NONE)
1095 EMSG(_("E750: First use :profile start <fname>"));
1096 else if (STRCMP(eap->arg, "pause") == 0)
1098 if (do_profiling == PROF_YES)
1099 profile_start(&pause_time);
1100 do_profiling = PROF_PAUSED;
1102 else if (STRCMP(eap->arg, "continue") == 0)
1104 if (do_profiling == PROF_PAUSED)
1106 profile_end(&pause_time);
1107 profile_add(&prof_wait_time, &pause_time);
1109 do_profiling = PROF_YES;
1111 else
1113 /* The rest is similar to ":breakadd". */
1114 ex_breakadd(eap);
1119 * Dump the profiling info.
1121 void
1122 profile_dump()
1124 FILE *fd;
1126 if (profile_fname != NULL)
1128 fd = mch_fopen((char *)profile_fname, "w");
1129 if (fd == NULL)
1130 EMSG2(_(e_notopen), profile_fname);
1131 else
1133 script_dump_profile(fd);
1134 func_dump_profile(fd);
1135 fclose(fd);
1141 * Start profiling script "fp".
1143 static void
1144 script_do_profile(si)
1145 scriptitem_T *si;
1147 si->sn_pr_count = 0;
1148 profile_zero(&si->sn_pr_total);
1149 profile_zero(&si->sn_pr_self);
1151 ga_init2(&si->sn_prl_ga, sizeof(sn_prl_T), 100);
1152 si->sn_prl_idx = -1;
1153 si->sn_prof_on = TRUE;
1154 si->sn_pr_nest = 0;
1158 * save time when starting to invoke another script or function.
1160 void
1161 script_prof_save(tm)
1162 proftime_T *tm; /* place to store wait time */
1164 scriptitem_T *si;
1166 if (current_SID > 0 && current_SID <= script_items.ga_len)
1168 si = &SCRIPT_ITEM(current_SID);
1169 if (si->sn_prof_on && si->sn_pr_nest++ == 0)
1170 profile_start(&si->sn_pr_child);
1172 profile_get_wait(tm);
1176 * Count time spent in children after invoking another script or function.
1178 void
1179 script_prof_restore(tm)
1180 proftime_T *tm;
1182 scriptitem_T *si;
1184 if (current_SID > 0 && current_SID <= script_items.ga_len)
1186 si = &SCRIPT_ITEM(current_SID);
1187 if (si->sn_prof_on && --si->sn_pr_nest == 0)
1189 profile_end(&si->sn_pr_child);
1190 profile_sub_wait(tm, &si->sn_pr_child); /* don't count wait time */
1191 profile_add(&si->sn_pr_children, &si->sn_pr_child);
1192 profile_add(&si->sn_prl_children, &si->sn_pr_child);
1197 static proftime_T inchar_time;
1200 * Called when starting to wait for the user to type a character.
1202 void
1203 prof_inchar_enter()
1205 profile_start(&inchar_time);
1209 * Called when finished waiting for the user to type a character.
1211 void
1212 prof_inchar_exit()
1214 profile_end(&inchar_time);
1215 profile_add(&prof_wait_time, &inchar_time);
1219 * Dump the profiling results for all scripts in file "fd".
1221 static void
1222 script_dump_profile(fd)
1223 FILE *fd;
1225 int id;
1226 scriptitem_T *si;
1227 int i;
1228 FILE *sfd;
1229 sn_prl_T *pp;
1231 for (id = 1; id <= script_items.ga_len; ++id)
1233 si = &SCRIPT_ITEM(id);
1234 if (si->sn_prof_on)
1236 fprintf(fd, "SCRIPT %s\n", si->sn_name);
1237 if (si->sn_pr_count == 1)
1238 fprintf(fd, "Sourced 1 time\n");
1239 else
1240 fprintf(fd, "Sourced %d times\n", si->sn_pr_count);
1241 fprintf(fd, "Total time: %s\n", profile_msg(&si->sn_pr_total));
1242 fprintf(fd, " Self time: %s\n", profile_msg(&si->sn_pr_self));
1243 fprintf(fd, "\n");
1244 fprintf(fd, "count total (s) self (s)\n");
1246 sfd = mch_fopen((char *)si->sn_name, "r");
1247 if (sfd == NULL)
1248 fprintf(fd, "Cannot open file!\n");
1249 else
1251 for (i = 0; i < si->sn_prl_ga.ga_len; ++i)
1253 if (vim_fgets(IObuff, IOSIZE, sfd))
1254 break;
1255 pp = &PRL_ITEM(si, i);
1256 if (pp->snp_count > 0)
1258 fprintf(fd, "%5d ", pp->snp_count);
1259 if (profile_equal(&pp->sn_prl_total, &pp->sn_prl_self))
1260 fprintf(fd, " ");
1261 else
1262 fprintf(fd, "%s ", profile_msg(&pp->sn_prl_total));
1263 fprintf(fd, "%s ", profile_msg(&pp->sn_prl_self));
1265 else
1266 fprintf(fd, " ");
1267 fprintf(fd, "%s", IObuff);
1269 fclose(sfd);
1271 fprintf(fd, "\n");
1277 * Return TRUE when a function defined in the current script should be
1278 * profiled.
1281 prof_def_func()
1283 if (current_SID > 0)
1284 return SCRIPT_ITEM(current_SID).sn_pr_force;
1285 return FALSE;
1288 # endif
1289 #endif
1292 * If 'autowrite' option set, try to write the file.
1293 * Careful: autocommands may make "buf" invalid!
1295 * return FAIL for failure, OK otherwise
1298 autowrite(buf, forceit)
1299 buf_T *buf;
1300 int forceit;
1302 int r;
1304 if (!(p_aw || p_awa) || !p_write
1305 #ifdef FEAT_QUICKFIX
1306 /* never autowrite a "nofile" or "nowrite" buffer */
1307 || bt_dontwrite(buf)
1308 #endif
1309 || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL)
1310 return FAIL;
1311 r = buf_write_all(buf, forceit);
1313 /* Writing may succeed but the buffer still changed, e.g., when there is a
1314 * conversion error. We do want to return FAIL then. */
1315 if (buf_valid(buf) && bufIsChanged(buf))
1316 r = FAIL;
1317 return r;
1321 * flush all buffers, except the ones that are readonly
1323 void
1324 autowrite_all()
1326 buf_T *buf;
1328 if (!(p_aw || p_awa) || !p_write)
1329 return;
1330 for (buf = firstbuf; buf; buf = buf->b_next)
1331 if (bufIsChanged(buf) && !buf->b_p_ro)
1333 (void)buf_write_all(buf, FALSE);
1334 #ifdef FEAT_AUTOCMD
1335 /* an autocommand may have deleted the buffer */
1336 if (!buf_valid(buf))
1337 buf = firstbuf;
1338 #endif
1343 * return TRUE if buffer was changed and cannot be abandoned.
1345 /*ARGSUSED*/
1347 check_changed(buf, checkaw, mult_win, forceit, allbuf)
1348 buf_T *buf;
1349 int checkaw; /* do autowrite if buffer was changed */
1350 int mult_win; /* check also when several wins for the buf */
1351 int forceit;
1352 int allbuf; /* may write all buffers */
1354 if ( !forceit
1355 && bufIsChanged(buf)
1356 && (mult_win || buf->b_nwindows <= 1)
1357 && (!checkaw || autowrite(buf, forceit) == FAIL))
1359 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1360 if ((p_confirm || cmdmod.confirm) && p_write)
1362 buf_T *buf2;
1363 int count = 0;
1365 if (allbuf)
1366 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1367 if (bufIsChanged(buf2)
1368 && (buf2->b_ffname != NULL
1369 # ifdef FEAT_BROWSE
1370 || cmdmod.browse
1371 # endif
1373 ++count;
1374 # ifdef FEAT_AUTOCMD
1375 if (!buf_valid(buf))
1376 /* Autocommand deleted buffer, oops! It's not changed now. */
1377 return FALSE;
1378 # endif
1379 dialog_changed(buf, count > 1);
1380 # ifdef FEAT_AUTOCMD
1381 if (!buf_valid(buf))
1382 /* Autocommand deleted buffer, oops! It's not changed now. */
1383 return FALSE;
1384 # endif
1385 return bufIsChanged(buf);
1387 #endif
1388 EMSG(_(e_nowrtmsg));
1389 return TRUE;
1391 return FALSE;
1394 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO)
1396 #if defined(FEAT_BROWSE) || defined(PROTO)
1398 * When wanting to write a file without a file name, ask the user for a name.
1400 void
1401 browse_save_fname(buf)
1402 buf_T *buf;
1404 if (buf->b_fname == NULL)
1406 char_u *fname;
1408 fname = do_browse(BROWSE_SAVE, (char_u *)_("Save As"),
1409 NULL, NULL, NULL, NULL, buf);
1410 if (fname != NULL)
1412 if (setfname(buf, fname, NULL, TRUE) == OK)
1413 buf->b_flags |= BF_NOTEDITED;
1414 vim_free(fname);
1418 #endif
1421 * Ask the user what to do when abondoning a changed buffer.
1422 * Must check 'write' option first!
1424 void
1425 dialog_changed(buf, checkall)
1426 buf_T *buf;
1427 int checkall; /* may abandon all changed buffers */
1429 char_u buff[IOSIZE];
1430 int ret;
1431 buf_T *buf2;
1433 dialog_msg(buff, _("Save changes to \"%s\"?"),
1434 (buf->b_fname != NULL) ?
1435 buf->b_fname : (char_u *)_("Untitled"));
1436 if (checkall)
1437 ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1);
1438 else
1439 ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
1441 if (ret == VIM_YES)
1443 #ifdef FEAT_BROWSE
1444 /* May get file name, when there is none */
1445 browse_save_fname(buf);
1446 #endif
1447 if (buf->b_fname != NULL) /* didn't hit Cancel */
1448 (void)buf_write_all(buf, FALSE);
1450 else if (ret == VIM_NO)
1452 unchanged(buf, TRUE);
1454 else if (ret == VIM_ALL)
1457 * Write all modified files that can be written.
1458 * Skip readonly buffers, these need to be confirmed
1459 * individually.
1461 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1463 if (bufIsChanged(buf2)
1464 && (buf2->b_ffname != NULL
1465 #ifdef FEAT_BROWSE
1466 || cmdmod.browse
1467 #endif
1469 && !buf2->b_p_ro)
1471 #ifdef FEAT_BROWSE
1472 /* May get file name, when there is none */
1473 browse_save_fname(buf2);
1474 #endif
1475 if (buf2->b_fname != NULL) /* didn't hit Cancel */
1476 (void)buf_write_all(buf2, FALSE);
1477 #ifdef FEAT_AUTOCMD
1478 /* an autocommand may have deleted the buffer */
1479 if (!buf_valid(buf2))
1480 buf2 = firstbuf;
1481 #endif
1485 else if (ret == VIM_DISCARDALL)
1488 * mark all buffers as unchanged
1490 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1491 unchanged(buf2, TRUE);
1494 #endif
1497 * Return TRUE if the buffer "buf" can be abandoned, either by making it
1498 * hidden, autowriting it or unloading it.
1501 can_abandon(buf, forceit)
1502 buf_T *buf;
1503 int forceit;
1505 return ( P_HID(buf)
1506 || !bufIsChanged(buf)
1507 || buf->b_nwindows > 1
1508 || autowrite(buf, forceit) == OK
1509 || forceit);
1513 * Return TRUE if any buffer was changed and cannot be abandoned.
1514 * That changed buffer becomes the current buffer.
1517 check_changed_any(hidden)
1518 int hidden; /* Only check hidden buffers */
1520 buf_T *buf;
1521 int save;
1522 #ifdef FEAT_WINDOWS
1523 win_T *wp;
1524 #endif
1526 for (;;)
1528 /* check curbuf first: if it was changed we can't abandon it */
1529 if (!hidden && curbufIsChanged())
1530 buf = curbuf;
1531 else
1533 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
1534 if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf))
1535 break;
1537 if (buf == NULL) /* No buffers changed */
1538 return FALSE;
1540 /* Try auto-writing the buffer. If this fails but the buffer no
1541 * longer exists it's not changed, that's OK. */
1542 if (check_changed(buf, p_awa, TRUE, FALSE, TRUE) && buf_valid(buf))
1543 break; /* didn't save - still changes */
1546 exiting = FALSE;
1547 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1549 * When ":confirm" used, don't give an error message.
1551 if (!(p_confirm || cmdmod.confirm))
1552 #endif
1554 /* There must be a wait_return for this message, do_buffer()
1555 * may cause a redraw. But wait_return() is a no-op when vgetc()
1556 * is busy (Quit used from window menu), then make sure we don't
1557 * cause a scroll up. */
1558 if (vgetc_busy > 0)
1560 msg_row = cmdline_row;
1561 msg_col = 0;
1562 msg_didout = FALSE;
1564 if (EMSG2(_("E162: No write since last change for buffer \"%s\""),
1565 buf_spname(buf) != NULL ? (char_u *)buf_spname(buf) :
1566 buf->b_fname))
1568 save = no_wait_return;
1569 no_wait_return = FALSE;
1570 wait_return(FALSE);
1571 no_wait_return = save;
1575 #ifdef FEAT_WINDOWS
1576 /* Try to find a window that contains the buffer. */
1577 if (buf != curbuf)
1578 for (wp = firstwin; wp != NULL; wp = wp->w_next)
1579 if (wp->w_buffer == buf)
1581 win_goto(wp);
1582 # ifdef FEAT_AUTOCMD
1583 /* Paranoia: did autocms wipe out the buffer with changes? */
1584 if (!buf_valid(buf))
1585 return TRUE;
1586 # endif
1587 break;
1589 #endif
1591 /* Open the changed buffer in the current window. */
1592 if (buf != curbuf)
1593 set_curbuf(buf, DOBUF_GOTO);
1595 return TRUE;
1599 * return FAIL if there is no file name, OK if there is one
1600 * give error message for FAIL
1603 check_fname()
1605 if (curbuf->b_ffname == NULL)
1607 EMSG(_(e_noname));
1608 return FAIL;
1610 return OK;
1614 * flush the contents of a buffer, unless it has no file name
1616 * return FAIL for failure, OK otherwise
1619 buf_write_all(buf, forceit)
1620 buf_T *buf;
1621 int forceit;
1623 int retval;
1624 #ifdef FEAT_AUTOCMD
1625 buf_T *old_curbuf = curbuf;
1626 #endif
1628 retval = (buf_write(buf, buf->b_ffname, buf->b_fname,
1629 (linenr_T)1, buf->b_ml.ml_line_count, NULL,
1630 FALSE, forceit, TRUE, FALSE));
1631 #ifdef FEAT_AUTOCMD
1632 if (curbuf != old_curbuf)
1634 msg_source(hl_attr(HLF_W));
1635 MSG(_("Warning: Entered other buffer unexpectedly (check autocommands)"));
1637 #endif
1638 return retval;
1642 * Code to handle the argument list.
1645 static char_u *do_one_arg __ARGS((char_u *str));
1646 static int do_arglist __ARGS((char_u *str, int what, int after));
1647 static void alist_check_arg_idx __ARGS((void));
1648 static int editing_arg_idx __ARGS((win_T *win));
1649 #ifdef FEAT_LISTCMDS
1650 static int alist_add_list __ARGS((int count, char_u **files, int after));
1651 #endif
1652 #define AL_SET 1
1653 #define AL_ADD 2
1654 #define AL_DEL 3
1657 * Isolate one argument, taking backticks.
1658 * Changes the argument in-place, puts a NUL after it. Backticks remain.
1659 * Return a pointer to the start of the next argument.
1661 static char_u *
1662 do_one_arg(str)
1663 char_u *str;
1665 char_u *p;
1666 int inbacktick;
1668 inbacktick = FALSE;
1669 for (p = str; *str; ++str)
1671 /* When the backslash is used for escaping the special meaning of a
1672 * character we need to keep it until wildcard expansion. */
1673 if (rem_backslash(str))
1675 *p++ = *str++;
1676 *p++ = *str;
1678 else
1680 /* An item ends at a space not in backticks */
1681 if (!inbacktick && vim_isspace(*str))
1682 break;
1683 if (*str == '`')
1684 inbacktick ^= TRUE;
1685 *p++ = *str;
1688 str = skipwhite(str);
1689 *p = NUL;
1691 return str;
1695 * Separate the arguments in "str" and return a list of pointers in the
1696 * growarray "gap".
1699 get_arglist(gap, str)
1700 garray_T *gap;
1701 char_u *str;
1703 ga_init2(gap, (int)sizeof(char_u *), 20);
1704 while (*str != NUL)
1706 if (ga_grow(gap, 1) == FAIL)
1708 ga_clear(gap);
1709 return FAIL;
1711 ((char_u **)gap->ga_data)[gap->ga_len++] = str;
1713 /* Isolate one argument, change it in-place, put a NUL after it. */
1714 str = do_one_arg(str);
1716 return OK;
1719 #if defined(FEAT_QUICKFIX) || defined(FEAT_SYN_HL) || defined(PROTO)
1721 * Parse a list of arguments (file names), expand them and return in
1722 * "fnames[fcountp]".
1723 * Return FAIL or OK.
1726 get_arglist_exp(str, fcountp, fnamesp)
1727 char_u *str;
1728 int *fcountp;
1729 char_u ***fnamesp;
1731 garray_T ga;
1732 int i;
1734 if (get_arglist(&ga, str) == FAIL)
1735 return FAIL;
1736 i = gen_expand_wildcards(ga.ga_len, (char_u **)ga.ga_data,
1737 fcountp, fnamesp, EW_FILE|EW_NOTFOUND);
1738 ga_clear(&ga);
1739 return i;
1741 #endif
1743 #if defined(FEAT_GUI) || defined(FEAT_CLIENTSERVER) || defined(PROTO)
1745 * Redefine the argument list.
1747 void
1748 set_arglist(str)
1749 char_u *str;
1751 do_arglist(str, AL_SET, 0);
1753 #endif
1756 * "what" == AL_SET: Redefine the argument list to 'str'.
1757 * "what" == AL_ADD: add files in 'str' to the argument list after "after".
1758 * "what" == AL_DEL: remove files in 'str' from the argument list.
1760 * Return FAIL for failure, OK otherwise.
1762 /*ARGSUSED*/
1763 static int
1764 do_arglist(str, what, after)
1765 char_u *str;
1766 int what;
1767 int after; /* 0 means before first one */
1769 garray_T new_ga;
1770 int exp_count;
1771 char_u **exp_files;
1772 int i;
1773 #ifdef FEAT_LISTCMDS
1774 char_u *p;
1775 int match;
1776 #endif
1779 * Collect all file name arguments in "new_ga".
1781 if (get_arglist(&new_ga, str) == FAIL)
1782 return FAIL;
1784 #ifdef FEAT_LISTCMDS
1785 if (what == AL_DEL)
1787 regmatch_T regmatch;
1788 int didone;
1791 * Delete the items: use each item as a regexp and find a match in the
1792 * argument list.
1794 #ifdef CASE_INSENSITIVE_FILENAME
1795 regmatch.rm_ic = TRUE; /* Always ignore case */
1796 #else
1797 regmatch.rm_ic = FALSE; /* Never ignore case */
1798 #endif
1799 for (i = 0; i < new_ga.ga_len && !got_int; ++i)
1801 p = ((char_u **)new_ga.ga_data)[i];
1802 p = file_pat_to_reg_pat(p, NULL, NULL, FALSE);
1803 if (p == NULL)
1804 break;
1805 regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0);
1806 if (regmatch.regprog == NULL)
1808 vim_free(p);
1809 break;
1812 didone = FALSE;
1813 for (match = 0; match < ARGCOUNT; ++match)
1814 if (vim_regexec(&regmatch, alist_name(&ARGLIST[match]),
1815 (colnr_T)0))
1817 didone = TRUE;
1818 vim_free(ARGLIST[match].ae_fname);
1819 mch_memmove(ARGLIST + match, ARGLIST + match + 1,
1820 (ARGCOUNT - match - 1) * sizeof(aentry_T));
1821 --ALIST(curwin)->al_ga.ga_len;
1822 if (curwin->w_arg_idx > match)
1823 --curwin->w_arg_idx;
1824 --match;
1827 vim_free(regmatch.regprog);
1828 vim_free(p);
1829 if (!didone)
1830 EMSG2(_(e_nomatch2), ((char_u **)new_ga.ga_data)[i]);
1832 ga_clear(&new_ga);
1834 else
1835 #endif
1837 i = expand_wildcards(new_ga.ga_len, (char_u **)new_ga.ga_data,
1838 &exp_count, &exp_files, EW_DIR|EW_FILE|EW_ADDSLASH|EW_NOTFOUND);
1839 ga_clear(&new_ga);
1840 if (i == FAIL)
1841 return FAIL;
1842 if (exp_count == 0)
1844 EMSG(_(e_nomatch));
1845 return FAIL;
1848 #ifdef FEAT_LISTCMDS
1849 if (what == AL_ADD)
1851 (void)alist_add_list(exp_count, exp_files, after);
1852 vim_free(exp_files);
1854 else /* what == AL_SET */
1855 #endif
1856 alist_set(ALIST(curwin), exp_count, exp_files, FALSE, NULL, 0);
1859 alist_check_arg_idx();
1861 return OK;
1865 * Check the validity of the arg_idx for each other window.
1867 static void
1868 alist_check_arg_idx()
1870 #ifdef FEAT_WINDOWS
1871 win_T *win;
1872 tabpage_T *tp;
1874 FOR_ALL_TAB_WINDOWS(tp, win)
1875 if (win->w_alist == curwin->w_alist)
1876 check_arg_idx(win);
1877 #else
1878 check_arg_idx(curwin);
1879 #endif
1883 * Return TRUE if window "win" is editing then file at the current argument
1884 * index.
1886 static int
1887 editing_arg_idx(win)
1888 win_T *win;
1890 return !(win->w_arg_idx >= WARGCOUNT(win)
1891 || (win->w_buffer->b_fnum
1892 != WARGLIST(win)[win->w_arg_idx].ae_fnum
1893 && (win->w_buffer->b_ffname == NULL
1894 || !(fullpathcmp(
1895 alist_name(&WARGLIST(win)[win->w_arg_idx]),
1896 win->w_buffer->b_ffname, TRUE) & FPC_SAME))));
1900 * Check if window "win" is editing the w_arg_idx file in its argument list.
1902 void
1903 check_arg_idx(win)
1904 win_T *win;
1906 if (WARGCOUNT(win) > 1 && !editing_arg_idx(win))
1908 /* We are not editing the current entry in the argument list.
1909 * Set "arg_had_last" if we are editing the last one. */
1910 win->w_arg_idx_invalid = TRUE;
1911 if (win->w_arg_idx != WARGCOUNT(win) - 1
1912 && arg_had_last == FALSE
1913 #ifdef FEAT_WINDOWS
1914 && ALIST(win) == &global_alist
1915 #endif
1916 && GARGCOUNT > 0
1917 && win->w_arg_idx < GARGCOUNT
1918 && (win->w_buffer->b_fnum == GARGLIST[GARGCOUNT - 1].ae_fnum
1919 || (win->w_buffer->b_ffname != NULL
1920 && (fullpathcmp(alist_name(&GARGLIST[GARGCOUNT - 1]),
1921 win->w_buffer->b_ffname, TRUE) & FPC_SAME))))
1922 arg_had_last = TRUE;
1924 else
1926 /* We are editing the current entry in the argument list.
1927 * Set "arg_had_last" if it's also the last one */
1928 win->w_arg_idx_invalid = FALSE;
1929 if (win->w_arg_idx == WARGCOUNT(win) - 1
1930 #ifdef FEAT_WINDOWS
1931 && win->w_alist == &global_alist
1932 #endif
1934 arg_had_last = TRUE;
1939 * ":args", ":argslocal" and ":argsglobal".
1941 void
1942 ex_args(eap)
1943 exarg_T *eap;
1945 int i;
1947 if (eap->cmdidx != CMD_args)
1949 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
1950 alist_unlink(ALIST(curwin));
1951 if (eap->cmdidx == CMD_argglobal)
1952 ALIST(curwin) = &global_alist;
1953 else /* eap->cmdidx == CMD_arglocal */
1954 alist_new();
1955 #else
1956 ex_ni(eap);
1957 return;
1958 #endif
1961 if (!ends_excmd(*eap->arg))
1964 * ":args file ..": define new argument list, handle like ":next"
1965 * Also for ":argslocal file .." and ":argsglobal file ..".
1967 ex_next(eap);
1969 else
1970 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
1971 if (eap->cmdidx == CMD_args)
1972 #endif
1975 * ":args": list arguments.
1977 if (ARGCOUNT > 0)
1979 /* Overwrite the command, for a short list there is no scrolling
1980 * required and no wait_return(). */
1981 gotocmdline(TRUE);
1982 for (i = 0; i < ARGCOUNT; ++i)
1984 if (i == curwin->w_arg_idx)
1985 msg_putchar('[');
1986 msg_outtrans(alist_name(&ARGLIST[i]));
1987 if (i == curwin->w_arg_idx)
1988 msg_putchar(']');
1989 msg_putchar(' ');
1993 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
1994 else if (eap->cmdidx == CMD_arglocal)
1996 garray_T *gap = &curwin->w_alist->al_ga;
1999 * ":argslocal": make a local copy of the global argument list.
2001 if (ga_grow(gap, GARGCOUNT) == OK)
2002 for (i = 0; i < GARGCOUNT; ++i)
2003 if (GARGLIST[i].ae_fname != NULL)
2005 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fname =
2006 vim_strsave(GARGLIST[i].ae_fname);
2007 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fnum =
2008 GARGLIST[i].ae_fnum;
2009 ++gap->ga_len;
2012 #endif
2016 * ":previous", ":sprevious", ":Next" and ":sNext".
2018 void
2019 ex_previous(eap)
2020 exarg_T *eap;
2022 /* If past the last one already, go to the last one. */
2023 if (curwin->w_arg_idx - (int)eap->line2 >= ARGCOUNT)
2024 do_argfile(eap, ARGCOUNT - 1);
2025 else
2026 do_argfile(eap, curwin->w_arg_idx - (int)eap->line2);
2030 * ":rewind", ":first", ":sfirst" and ":srewind".
2032 void
2033 ex_rewind(eap)
2034 exarg_T *eap;
2036 do_argfile(eap, 0);
2040 * ":last" and ":slast".
2042 void
2043 ex_last(eap)
2044 exarg_T *eap;
2046 do_argfile(eap, ARGCOUNT - 1);
2050 * ":argument" and ":sargument".
2052 void
2053 ex_argument(eap)
2054 exarg_T *eap;
2056 int i;
2058 if (eap->addr_count > 0)
2059 i = eap->line2 - 1;
2060 else
2061 i = curwin->w_arg_idx;
2062 do_argfile(eap, i);
2066 * Edit file "argn" of the argument lists.
2068 void
2069 do_argfile(eap, argn)
2070 exarg_T *eap;
2071 int argn;
2073 int other;
2074 char_u *p;
2075 int old_arg_idx = curwin->w_arg_idx;
2077 if (argn < 0 || argn >= ARGCOUNT)
2079 if (ARGCOUNT <= 1)
2080 EMSG(_("E163: There is only one file to edit"));
2081 else if (argn < 0)
2082 EMSG(_("E164: Cannot go before first file"));
2083 else
2084 EMSG(_("E165: Cannot go beyond last file"));
2086 else
2088 setpcmark();
2089 #ifdef FEAT_GUI
2090 need_mouse_correct = TRUE;
2091 #endif
2093 #ifdef FEAT_WINDOWS
2094 /* split window or create new tab page first */
2095 if (*eap->cmd == 's' || cmdmod.tab != 0)
2097 if (win_split(0, 0) == FAIL)
2098 return;
2099 # ifdef FEAT_SCROLLBIND
2100 curwin->w_p_scb = FALSE;
2101 # endif
2103 else
2104 #endif
2107 * if 'hidden' set, only check for changed file when re-editing
2108 * the same buffer
2110 other = TRUE;
2111 if (P_HID(curbuf))
2113 p = fix_fname(alist_name(&ARGLIST[argn]));
2114 other = otherfile(p);
2115 vim_free(p);
2117 if ((!P_HID(curbuf) || !other)
2118 && check_changed(curbuf, TRUE, !other, eap->forceit, FALSE))
2119 return;
2122 curwin->w_arg_idx = argn;
2123 if (argn == ARGCOUNT - 1
2124 #ifdef FEAT_WINDOWS
2125 && curwin->w_alist == &global_alist
2126 #endif
2128 arg_had_last = TRUE;
2130 /* Edit the file; always use the last known line number.
2131 * When it fails (e.g. Abort for already edited file) restore the
2132 * argument index. */
2133 if (do_ecmd(0, alist_name(&ARGLIST[curwin->w_arg_idx]), NULL,
2134 eap, ECMD_LAST,
2135 (P_HID(curwin->w_buffer) ? ECMD_HIDE : 0)
2136 + (eap->forceit ? ECMD_FORCEIT : 0), curwin) == FAIL)
2137 curwin->w_arg_idx = old_arg_idx;
2138 /* like Vi: set the mark where the cursor is in the file. */
2139 else if (eap->cmdidx != CMD_argdo)
2140 setmark('\'');
2145 * ":next", and commands that behave like it.
2147 void
2148 ex_next(eap)
2149 exarg_T *eap;
2151 int i;
2154 * check for changed buffer now, if this fails the argument list is not
2155 * redefined.
2157 if ( P_HID(curbuf)
2158 || eap->cmdidx == CMD_snext
2159 || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
2161 if (*eap->arg != NUL) /* redefine file list */
2163 if (do_arglist(eap->arg, AL_SET, 0) == FAIL)
2164 return;
2165 i = 0;
2167 else
2168 i = curwin->w_arg_idx + (int)eap->line2;
2169 do_argfile(eap, i);
2173 #ifdef FEAT_LISTCMDS
2175 * ":argedit"
2177 void
2178 ex_argedit(eap)
2179 exarg_T *eap;
2181 int fnum;
2182 int i;
2183 char_u *s;
2185 /* Add the argument to the buffer list and get the buffer number. */
2186 fnum = buflist_add(eap->arg, BLN_LISTED);
2188 /* Check if this argument is already in the argument list. */
2189 for (i = 0; i < ARGCOUNT; ++i)
2190 if (ARGLIST[i].ae_fnum == fnum)
2191 break;
2192 if (i == ARGCOUNT)
2194 /* Can't find it, add it to the argument list. */
2195 s = vim_strsave(eap->arg);
2196 if (s == NULL)
2197 return;
2198 i = alist_add_list(1, &s,
2199 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
2200 if (i < 0)
2201 return;
2202 curwin->w_arg_idx = i;
2205 alist_check_arg_idx();
2207 /* Edit the argument. */
2208 do_argfile(eap, i);
2212 * ":argadd"
2214 void
2215 ex_argadd(eap)
2216 exarg_T *eap;
2218 do_arglist(eap->arg, AL_ADD,
2219 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
2220 #ifdef FEAT_TITLE
2221 maketitle();
2222 #endif
2226 * ":argdelete"
2228 void
2229 ex_argdelete(eap)
2230 exarg_T *eap;
2232 int i;
2233 int n;
2235 if (eap->addr_count > 0)
2237 /* ":1,4argdel": Delete all arguments in the range. */
2238 if (eap->line2 > ARGCOUNT)
2239 eap->line2 = ARGCOUNT;
2240 n = eap->line2 - eap->line1 + 1;
2241 if (*eap->arg != NUL || n <= 0)
2242 EMSG(_(e_invarg));
2243 else
2245 for (i = eap->line1; i <= eap->line2; ++i)
2246 vim_free(ARGLIST[i - 1].ae_fname);
2247 mch_memmove(ARGLIST + eap->line1 - 1, ARGLIST + eap->line2,
2248 (size_t)((ARGCOUNT - eap->line2) * sizeof(aentry_T)));
2249 ALIST(curwin)->al_ga.ga_len -= n;
2250 if (curwin->w_arg_idx >= eap->line2)
2251 curwin->w_arg_idx -= n;
2252 else if (curwin->w_arg_idx > eap->line1)
2253 curwin->w_arg_idx = eap->line1;
2256 else if (*eap->arg == NUL)
2257 EMSG(_(e_argreq));
2258 else
2259 do_arglist(eap->arg, AL_DEL, 0);
2260 #ifdef FEAT_TITLE
2261 maketitle();
2262 #endif
2266 * ":argdo", ":windo", ":bufdo", ":tabdo"
2268 void
2269 ex_listdo(eap)
2270 exarg_T *eap;
2272 int i;
2273 #ifdef FEAT_WINDOWS
2274 win_T *wp;
2275 tabpage_T *tp;
2276 #endif
2277 buf_T *buf;
2278 int next_fnum = 0;
2279 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2280 char_u *save_ei = NULL;
2281 #endif
2282 char_u *p_shm_save;
2284 #ifndef FEAT_WINDOWS
2285 if (eap->cmdidx == CMD_windo)
2287 ex_ni(eap);
2288 return;
2290 #endif
2292 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2293 if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo)
2294 /* Don't do syntax HL autocommands. Skipping the syntax file is a
2295 * great speed improvement. */
2296 save_ei = au_event_disable(",Syntax");
2297 #endif
2299 if (eap->cmdidx == CMD_windo
2300 || eap->cmdidx == CMD_tabdo
2301 || P_HID(curbuf)
2302 || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
2304 /* start at the first argument/window/buffer */
2305 i = 0;
2306 #ifdef FEAT_WINDOWS
2307 wp = firstwin;
2308 tp = first_tabpage;
2309 #endif
2310 /* set pcmark now */
2311 if (eap->cmdidx == CMD_bufdo)
2312 goto_buffer(eap, DOBUF_FIRST, FORWARD, 0);
2313 else
2314 setpcmark();
2315 listcmd_busy = TRUE; /* avoids setting pcmark below */
2317 while (!got_int)
2319 if (eap->cmdidx == CMD_argdo)
2321 /* go to argument "i" */
2322 if (i == ARGCOUNT)
2323 break;
2324 /* Don't call do_argfile() when already there, it will try
2325 * reloading the file. */
2326 if (curwin->w_arg_idx != i || !editing_arg_idx(curwin))
2328 /* Clear 'shm' to avoid that the file message overwrites
2329 * any output from the command. */
2330 p_shm_save = vim_strsave(p_shm);
2331 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
2332 do_argfile(eap, i);
2333 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
2334 vim_free(p_shm_save);
2336 if (curwin->w_arg_idx != i)
2337 break;
2338 ++i;
2340 #ifdef FEAT_WINDOWS
2341 else if (eap->cmdidx == CMD_windo)
2343 /* go to window "wp" */
2344 if (!win_valid(wp))
2345 break;
2346 win_goto(wp);
2347 if (curwin != wp)
2348 break; /* something must be wrong */
2349 wp = curwin->w_next;
2351 else if (eap->cmdidx == CMD_tabdo)
2353 /* go to window "tp" */
2354 if (!valid_tabpage(tp))
2355 break;
2356 goto_tabpage_tp(tp);
2357 tp = tp->tp_next;
2359 #endif
2360 else if (eap->cmdidx == CMD_bufdo)
2362 /* Remember the number of the next listed buffer, in case
2363 * ":bwipe" is used or autocommands do something strange. */
2364 next_fnum = -1;
2365 for (buf = curbuf->b_next; buf != NULL; buf = buf->b_next)
2366 if (buf->b_p_bl)
2368 next_fnum = buf->b_fnum;
2369 break;
2373 /* execute the command */
2374 do_cmdline(eap->arg, eap->getline, eap->cookie,
2375 DOCMD_VERBOSE + DOCMD_NOWAIT);
2377 if (eap->cmdidx == CMD_bufdo)
2379 /* Done? */
2380 if (next_fnum < 0)
2381 break;
2382 /* Check if the buffer still exists. */
2383 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
2384 if (buf->b_fnum == next_fnum)
2385 break;
2386 if (buf == NULL)
2387 break;
2389 /* Go to the next buffer. Clear 'shm' to avoid that the file
2390 * message overwrites any output from the command. */
2391 p_shm_save = vim_strsave(p_shm);
2392 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
2393 goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
2394 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
2395 vim_free(p_shm_save);
2397 /* If autocommands took us elsewhere, quit here */
2398 if (curbuf->b_fnum != next_fnum)
2399 break;
2402 if (eap->cmdidx == CMD_windo)
2404 validate_cursor(); /* cursor may have moved */
2405 #ifdef FEAT_SCROLLBIND
2406 /* required when 'scrollbind' has been set */
2407 if (curwin->w_p_scb)
2408 do_check_scrollbind(TRUE);
2409 #endif
2412 listcmd_busy = FALSE;
2415 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2416 if (save_ei != NULL)
2418 au_event_restore(save_ei);
2419 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
2420 curbuf->b_fname, TRUE, curbuf);
2422 #endif
2426 * Add files[count] to the arglist of the current window after arg "after".
2427 * The file names in files[count] must have been allocated and are taken over.
2428 * Files[] itself is not taken over.
2429 * Returns index of first added argument. Returns -1 when failed (out of mem).
2431 static int
2432 alist_add_list(count, files, after)
2433 int count;
2434 char_u **files;
2435 int after; /* where to add: 0 = before first one */
2437 int i;
2439 if (ga_grow(&ALIST(curwin)->al_ga, count) == OK)
2441 if (after < 0)
2442 after = 0;
2443 if (after > ARGCOUNT)
2444 after = ARGCOUNT;
2445 if (after < ARGCOUNT)
2446 mch_memmove(&(ARGLIST[after + count]), &(ARGLIST[after]),
2447 (ARGCOUNT - after) * sizeof(aentry_T));
2448 for (i = 0; i < count; ++i)
2450 ARGLIST[after + i].ae_fname = files[i];
2451 ARGLIST[after + i].ae_fnum = buflist_add(files[i], BLN_LISTED);
2453 ALIST(curwin)->al_ga.ga_len += count;
2454 if (curwin->w_arg_idx >= after)
2455 ++curwin->w_arg_idx;
2456 return after;
2459 for (i = 0; i < count; ++i)
2460 vim_free(files[i]);
2461 return -1;
2464 #endif /* FEAT_LISTCMDS */
2466 #ifdef FEAT_EVAL
2468 * ":compiler[!] {name}"
2470 void
2471 ex_compiler(eap)
2472 exarg_T *eap;
2474 char_u *buf;
2475 char_u *old_cur_comp = NULL;
2476 char_u *p;
2478 if (*eap->arg == NUL)
2480 /* List all compiler scripts. */
2481 do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')");
2482 /* ) keep the indenter happy... */
2484 else
2486 buf = alloc((unsigned)(STRLEN(eap->arg) + 14));
2487 if (buf != NULL)
2489 if (eap->forceit)
2491 /* ":compiler! {name}" sets global options */
2492 do_cmdline_cmd((char_u *)
2493 "command -nargs=* CompilerSet set <args>");
2495 else
2497 /* ":compiler! {name}" sets local options.
2498 * To remain backwards compatible "current_compiler" is always
2499 * used. A user's compiler plugin may set it, the distributed
2500 * plugin will then skip the settings. Afterwards set
2501 * "b:current_compiler" and restore "current_compiler". */
2502 old_cur_comp = get_var_value((char_u *)"current_compiler");
2503 if (old_cur_comp != NULL)
2504 old_cur_comp = vim_strsave(old_cur_comp);
2505 do_cmdline_cmd((char_u *)
2506 "command -nargs=* CompilerSet setlocal <args>");
2508 do_unlet((char_u *)"current_compiler", TRUE);
2509 do_unlet((char_u *)"b:current_compiler", TRUE);
2511 sprintf((char *)buf, "compiler/%s.vim", eap->arg);
2512 if (source_runtime(buf, TRUE) == FAIL)
2513 EMSG2(_("E666: compiler not supported: %s"), eap->arg);
2514 vim_free(buf);
2516 do_cmdline_cmd((char_u *)":delcommand CompilerSet");
2518 /* Set "b:current_compiler" from "current_compiler". */
2519 p = get_var_value((char_u *)"current_compiler");
2520 if (p != NULL)
2521 set_internal_string_var((char_u *)"b:current_compiler", p);
2523 /* Restore "current_compiler" for ":compiler {name}". */
2524 if (!eap->forceit)
2526 if (old_cur_comp != NULL)
2528 set_internal_string_var((char_u *)"current_compiler",
2529 old_cur_comp);
2530 vim_free(old_cur_comp);
2532 else
2533 do_unlet((char_u *)"current_compiler", TRUE);
2538 #endif
2541 * ":runtime {name}"
2543 void
2544 ex_runtime(eap)
2545 exarg_T *eap;
2547 source_runtime(eap->arg, eap->forceit);
2550 static void source_callback __ARGS((char_u *fname, void *cookie));
2552 /*ARGSUSED*/
2553 static void
2554 source_callback(fname, cookie)
2555 char_u *fname;
2556 void *cookie;
2558 (void)do_source(fname, FALSE, DOSO_NONE);
2562 * Source the file "name" from all directories in 'runtimepath'.
2563 * "name" can contain wildcards.
2564 * When "all" is TRUE, source all files, otherwise only the first one.
2565 * return FAIL when no file could be sourced, OK otherwise.
2568 source_runtime(name, all)
2569 char_u *name;
2570 int all;
2572 return do_in_runtimepath(name, all, source_callback, NULL);
2576 * Find "name" in 'runtimepath'. When found, invoke the callback function for
2577 * it: callback(fname, "cookie")
2578 * When "all" is TRUE repeat for all matches, otherwise only the first one is
2579 * used.
2580 * Returns OK when at least one match found, FAIL otherwise.
2583 do_in_runtimepath(name, all, callback, cookie)
2584 char_u *name;
2585 int all;
2586 void (*callback)__ARGS((char_u *fname, void *ck));
2587 void *cookie;
2589 char_u *rtp;
2590 char_u *np;
2591 char_u *buf;
2592 char_u *rtp_copy;
2593 char_u *tail;
2594 int num_files;
2595 char_u **files;
2596 int i;
2597 int did_one = FALSE;
2598 #ifdef AMIGA
2599 struct Process *proc = (struct Process *)FindTask(0L);
2600 APTR save_winptr = proc->pr_WindowPtr;
2602 /* Avoid a requester here for a volume that doesn't exist. */
2603 proc->pr_WindowPtr = (APTR)-1L;
2604 #endif
2606 /* Make a copy of 'runtimepath'. Invoking the callback may change the
2607 * value. */
2608 rtp_copy = vim_strsave(p_rtp);
2609 buf = alloc(MAXPATHL);
2610 if (buf != NULL && rtp_copy != NULL)
2612 if (p_verbose > 1)
2614 verbose_enter();
2615 smsg((char_u *)_("Searching for \"%s\" in \"%s\""),
2616 (char *)name, (char *)p_rtp);
2617 verbose_leave();
2620 /* Loop over all entries in 'runtimepath'. */
2621 rtp = rtp_copy;
2622 while (*rtp != NUL && (all || !did_one))
2624 /* Copy the path from 'runtimepath' to buf[]. */
2625 copy_option_part(&rtp, buf, MAXPATHL, ",");
2626 if (STRLEN(buf) + STRLEN(name) + 2 < MAXPATHL)
2628 add_pathsep(buf);
2629 tail = buf + STRLEN(buf);
2631 /* Loop over all patterns in "name" */
2632 np = name;
2633 while (*np != NUL && (all || !did_one))
2635 /* Append the pattern from "name" to buf[]. */
2636 copy_option_part(&np, tail, (int)(MAXPATHL - (tail - buf)),
2637 "\t ");
2639 if (p_verbose > 2)
2641 verbose_enter();
2642 smsg((char_u *)_("Searching for \"%s\""), buf);
2643 verbose_leave();
2646 /* Expand wildcards, invoke the callback for each match. */
2647 if (gen_expand_wildcards(1, &buf, &num_files, &files,
2648 EW_FILE) == OK)
2650 for (i = 0; i < num_files; ++i)
2652 (*callback)(files[i], cookie);
2653 did_one = TRUE;
2654 if (!all)
2655 break;
2657 FreeWild(num_files, files);
2663 vim_free(buf);
2664 vim_free(rtp_copy);
2665 if (p_verbose > 0 && !did_one)
2667 verbose_enter();
2668 smsg((char_u *)_("not found in 'runtimepath': \"%s\""), name);
2669 verbose_leave();
2672 #ifdef AMIGA
2673 proc->pr_WindowPtr = save_winptr;
2674 #endif
2676 return did_one ? OK : FAIL;
2679 #if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD)
2681 * ":options"
2683 /*ARGSUSED*/
2684 void
2685 ex_options(eap)
2686 exarg_T *eap;
2688 cmd_source((char_u *)SYS_OPTWIN_FILE, NULL);
2690 #endif
2693 * ":source {fname}"
2695 void
2696 ex_source(eap)
2697 exarg_T *eap;
2699 #ifdef FEAT_BROWSE
2700 if (cmdmod.browse)
2702 char_u *fname = NULL;
2704 fname = do_browse(0, (char_u *)_("Source Vim script"), eap->arg,
2705 NULL, NULL, BROWSE_FILTER_MACROS, NULL);
2706 if (fname != NULL)
2708 cmd_source(fname, eap);
2709 vim_free(fname);
2712 else
2713 #endif
2714 cmd_source(eap->arg, eap);
2717 static void
2718 cmd_source(fname, eap)
2719 char_u *fname;
2720 exarg_T *eap;
2722 if (*fname == NUL)
2723 EMSG(_(e_argreq));
2725 else if (eap != NULL && eap->forceit)
2726 /* ":source!": read Normal mdoe commands
2727 * Need to execute the commands directly. This is required at least
2728 * for:
2729 * - ":g" command busy
2730 * - after ":argdo", ":windo" or ":bufdo"
2731 * - another command follows
2732 * - inside a loop
2734 openscript(fname, global_busy || listcmd_busy || eap->nextcmd != NULL
2735 #ifdef FEAT_EVAL
2736 || eap->cstack->cs_idx >= 0
2737 #endif
2740 /* ":source" read ex commands */
2741 else if (do_source(fname, FALSE, DOSO_NONE) == FAIL)
2742 EMSG2(_(e_notopen), fname);
2746 * ":source" and associated commands.
2749 * Structure used to store info for each sourced file.
2750 * It is shared between do_source() and getsourceline().
2751 * This is required, because it needs to be handed to do_cmdline() and
2752 * sourcing can be done recursively.
2754 struct source_cookie
2756 FILE *fp; /* opened file for sourcing */
2757 char_u *nextline; /* if not NULL: line that was read ahead */
2758 int finished; /* ":finish" used */
2759 #if defined (USE_CRNL) || defined (USE_CR)
2760 int fileformat; /* EOL_UNKNOWN, EOL_UNIX or EOL_DOS */
2761 int error; /* TRUE if LF found after CR-LF */
2762 #endif
2763 #ifdef FEAT_EVAL
2764 linenr_T breakpoint; /* next line with breakpoint or zero */
2765 char_u *fname; /* name of sourced file */
2766 int dbg_tick; /* debug_tick when breakpoint was set */
2767 int level; /* top nesting level of sourced file */
2768 #endif
2769 #ifdef FEAT_MBYTE
2770 vimconv_T conv; /* type of conversion */
2771 #endif
2774 #ifdef FEAT_EVAL
2776 * Return the address holding the next breakpoint line for a source cookie.
2778 linenr_T *
2779 source_breakpoint(cookie)
2780 void *cookie;
2782 return &((struct source_cookie *)cookie)->breakpoint;
2786 * Return the address holding the debug tick for a source cookie.
2788 int *
2789 source_dbg_tick(cookie)
2790 void *cookie;
2792 return &((struct source_cookie *)cookie)->dbg_tick;
2796 * Return the nesting level for a source cookie.
2799 source_level(cookie)
2800 void *cookie;
2802 return ((struct source_cookie *)cookie)->level;
2804 #endif
2806 static char_u *get_one_sourceline __ARGS((struct source_cookie *sp));
2808 #if defined(WIN32) && defined(FEAT_CSCOPE)
2809 static FILE *fopen_noinh_readbin __ARGS((char *filename));
2812 * Special function to open a file without handle inheritance.
2814 static FILE *
2815 fopen_noinh_readbin(filename)
2816 char *filename;
2818 int fd_tmp = mch_open(filename, O_RDONLY | O_BINARY | O_NOINHERIT, 0);
2820 if (fd_tmp == -1)
2821 return NULL;
2822 return fdopen(fd_tmp, READBIN);
2824 #endif
2828 * do_source: Read the file "fname" and execute its lines as EX commands.
2830 * This function may be called recursively!
2832 * return FAIL if file could not be opened, OK otherwise
2835 do_source(fname, check_other, is_vimrc)
2836 char_u *fname;
2837 int check_other; /* check for .vimrc and _vimrc */
2838 int is_vimrc; /* DOSO_ value */
2840 struct source_cookie cookie;
2841 char_u *save_sourcing_name;
2842 linenr_T save_sourcing_lnum;
2843 char_u *p;
2844 char_u *fname_exp;
2845 int retval = FAIL;
2846 #ifdef FEAT_EVAL
2847 scid_T save_current_SID;
2848 static scid_T last_current_SID = 0;
2849 void *save_funccalp;
2850 int save_debug_break_level = debug_break_level;
2851 scriptitem_T *si = NULL;
2852 # ifdef UNIX
2853 struct stat st;
2854 int stat_ok;
2855 # endif
2856 #endif
2857 #ifdef STARTUPTIME
2858 struct timeval tv_rel;
2859 struct timeval tv_start;
2860 #endif
2861 #ifdef FEAT_PROFILE
2862 proftime_T wait_start;
2863 #endif
2865 #ifdef RISCOS
2866 p = mch_munge_fname(fname);
2867 #else
2868 p = expand_env_save(fname);
2869 #endif
2870 if (p == NULL)
2871 return retval;
2872 fname_exp = fix_fname(p);
2873 vim_free(p);
2874 if (fname_exp == NULL)
2875 return retval;
2876 if (mch_isdir(fname_exp))
2878 smsg((char_u *)_("Cannot source a directory: \"%s\""), fname);
2879 goto theend;
2882 #ifdef FEAT_AUTOCMD
2883 /* Apply SourceCmd autocommands, they should get the file and source it. */
2884 if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL)
2885 && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp,
2886 FALSE, curbuf))
2888 # ifdef FEAT_EVAL
2889 retval = aborting() ? FAIL : OK;
2890 # else
2891 retval = OK;
2892 # endif
2893 goto theend;
2896 /* Apply SourcePre autocommands, they may get the file. */
2897 apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, FALSE, curbuf);
2898 #endif
2900 #if defined(WIN32) && defined(FEAT_CSCOPE)
2901 cookie.fp = fopen_noinh_readbin((char *)fname_exp);
2902 #else
2903 cookie.fp = mch_fopen((char *)fname_exp, READBIN);
2904 #endif
2905 if (cookie.fp == NULL && check_other)
2908 * Try again, replacing file name ".vimrc" by "_vimrc" or vice versa,
2909 * and ".exrc" by "_exrc" or vice versa.
2911 p = gettail(fname_exp);
2912 if ((*p == '.' || *p == '_')
2913 && (STRICMP(p + 1, "vimrc") == 0
2914 || STRICMP(p + 1, "gvimrc") == 0
2915 || STRICMP(p + 1, "exrc") == 0))
2917 if (*p == '_')
2918 *p = '.';
2919 else
2920 *p = '_';
2921 #if defined(WIN32) && defined(FEAT_CSCOPE)
2922 cookie.fp = fopen_noinh_readbin((char *)fname_exp);
2923 #else
2924 cookie.fp = mch_fopen((char *)fname_exp, READBIN);
2925 #endif
2929 if (cookie.fp == NULL)
2931 if (p_verbose > 0)
2933 verbose_enter();
2934 if (sourcing_name == NULL)
2935 smsg((char_u *)_("could not source \"%s\""), fname);
2936 else
2937 smsg((char_u *)_("line %ld: could not source \"%s\""),
2938 sourcing_lnum, fname);
2939 verbose_leave();
2941 goto theend;
2945 * The file exists.
2946 * - In verbose mode, give a message.
2947 * - For a vimrc file, may want to set 'compatible', call vimrc_found().
2949 if (p_verbose > 1)
2951 verbose_enter();
2952 if (sourcing_name == NULL)
2953 smsg((char_u *)_("sourcing \"%s\""), fname);
2954 else
2955 smsg((char_u *)_("line %ld: sourcing \"%s\""),
2956 sourcing_lnum, fname);
2957 verbose_leave();
2959 if (is_vimrc == DOSO_VIMRC)
2960 vimrc_found(fname_exp, (char_u *)"MYVIMRC");
2961 else if (is_vimrc == DOSO_GVIMRC)
2962 vimrc_found(fname_exp, (char_u *)"MYGVIMRC");
2964 #ifdef USE_CRNL
2965 /* If no automatic file format: Set default to CR-NL. */
2966 if (*p_ffs == NUL)
2967 cookie.fileformat = EOL_DOS;
2968 else
2969 cookie.fileformat = EOL_UNKNOWN;
2970 cookie.error = FALSE;
2971 #endif
2973 #ifdef USE_CR
2974 /* If no automatic file format: Set default to CR. */
2975 if (*p_ffs == NUL)
2976 cookie.fileformat = EOL_MAC;
2977 else
2978 cookie.fileformat = EOL_UNKNOWN;
2979 cookie.error = FALSE;
2980 #endif
2982 cookie.nextline = NULL;
2983 cookie.finished = FALSE;
2985 #ifdef FEAT_EVAL
2987 * Check if this script has a breakpoint.
2989 cookie.breakpoint = dbg_find_breakpoint(TRUE, fname_exp, (linenr_T)0);
2990 cookie.fname = fname_exp;
2991 cookie.dbg_tick = debug_tick;
2993 cookie.level = ex_nesting_level;
2994 #endif
2995 #ifdef FEAT_MBYTE
2996 cookie.conv.vc_type = CONV_NONE; /* no conversion */
2998 /* Try reading the first few bytes to check for a UTF-8 BOM. */
3000 char_u buf[3];
3002 if (fread((char *)buf, sizeof(char_u), (size_t)3, cookie.fp)
3003 == (size_t)3
3004 && buf[0] == 0xef && buf[1] == 0xbb && buf[2] == 0xbf)
3005 /* Found BOM, setup conversion and skip over it. */
3006 convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc);
3007 else
3008 /* No BOM found, rewind. */
3009 fseek(cookie.fp, 0L, SEEK_SET);
3011 #endif
3014 * Keep the sourcing name/lnum, for recursive calls.
3016 save_sourcing_name = sourcing_name;
3017 sourcing_name = fname_exp;
3018 save_sourcing_lnum = sourcing_lnum;
3019 sourcing_lnum = 0;
3021 #ifdef STARTUPTIME
3022 time_push(&tv_rel, &tv_start);
3023 #endif
3025 #ifdef FEAT_EVAL
3026 # ifdef FEAT_PROFILE
3027 if (do_profiling == PROF_YES)
3028 prof_child_enter(&wait_start); /* entering a child now */
3029 # endif
3031 /* Don't use local function variables, if called from a function.
3032 * Also starts profiling timer for nested script. */
3033 save_funccalp = save_funccal();
3036 * Check if this script was sourced before to finds its SID.
3037 * If it's new, generate a new SID.
3039 save_current_SID = current_SID;
3040 # ifdef UNIX
3041 stat_ok = (mch_stat((char *)fname_exp, &st) >= 0);
3042 # endif
3043 for (current_SID = script_items.ga_len; current_SID > 0; --current_SID)
3045 si = &SCRIPT_ITEM(current_SID);
3046 if (si->sn_name != NULL
3047 && (
3048 # ifdef UNIX
3049 /* Compare dev/ino when possible, it catches symbolic
3050 * links. Also compare file names, the inode may change
3051 * when the file was edited. */
3052 ((stat_ok && si->sn_dev != -1)
3053 && (si->sn_dev == st.st_dev
3054 && si->sn_ino == st.st_ino)) ||
3055 # endif
3056 fnamecmp(si->sn_name, fname_exp) == 0))
3057 break;
3059 if (current_SID == 0)
3061 current_SID = ++last_current_SID;
3062 if (ga_grow(&script_items, (int)(current_SID - script_items.ga_len))
3063 == FAIL)
3064 goto almosttheend;
3065 while (script_items.ga_len < current_SID)
3067 ++script_items.ga_len;
3068 SCRIPT_ITEM(script_items.ga_len).sn_name = NULL;
3069 # ifdef FEAT_PROFILE
3070 SCRIPT_ITEM(script_items.ga_len).sn_prof_on = FALSE;
3071 # endif
3073 si = &SCRIPT_ITEM(current_SID);
3074 si->sn_name = fname_exp;
3075 fname_exp = NULL;
3076 # ifdef UNIX
3077 if (stat_ok)
3079 si->sn_dev = st.st_dev;
3080 si->sn_ino = st.st_ino;
3082 else
3083 si->sn_dev = -1;
3084 # endif
3086 /* Allocate the local script variables to use for this script. */
3087 new_script_vars(current_SID);
3090 # ifdef FEAT_PROFILE
3091 if (do_profiling == PROF_YES)
3093 int forceit;
3095 /* Check if we do profiling for this script. */
3096 if (!si->sn_prof_on && has_profiling(TRUE, si->sn_name, &forceit))
3098 script_do_profile(si);
3099 si->sn_pr_force = forceit;
3101 if (si->sn_prof_on)
3103 ++si->sn_pr_count;
3104 profile_start(&si->sn_pr_start);
3105 profile_zero(&si->sn_pr_children);
3108 # endif
3109 #endif
3112 * Call do_cmdline, which will call getsourceline() to get the lines.
3114 do_cmdline(NULL, getsourceline, (void *)&cookie,
3115 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT);
3117 retval = OK;
3119 #ifdef FEAT_PROFILE
3120 if (do_profiling == PROF_YES)
3122 /* Get "si" again, "script_items" may have been reallocated. */
3123 si = &SCRIPT_ITEM(current_SID);
3124 if (si->sn_prof_on)
3126 profile_end(&si->sn_pr_start);
3127 profile_sub_wait(&wait_start, &si->sn_pr_start);
3128 profile_add(&si->sn_pr_total, &si->sn_pr_start);
3129 profile_self(&si->sn_pr_self, &si->sn_pr_start,
3130 &si->sn_pr_children);
3133 #endif
3135 if (got_int)
3136 EMSG(_(e_interr));
3137 sourcing_name = save_sourcing_name;
3138 sourcing_lnum = save_sourcing_lnum;
3139 if (p_verbose > 1)
3141 verbose_enter();
3142 smsg((char_u *)_("finished sourcing %s"), fname);
3143 if (sourcing_name != NULL)
3144 smsg((char_u *)_("continuing in %s"), sourcing_name);
3145 verbose_leave();
3147 #ifdef STARTUPTIME
3148 vim_snprintf((char *)IObuff, IOSIZE, "sourcing %s", fname);
3149 time_msg((char *)IObuff, &tv_start);
3150 time_pop(&tv_rel);
3151 #endif
3153 #ifdef FEAT_EVAL
3155 * After a "finish" in debug mode, need to break at first command of next
3156 * sourced file.
3158 if (save_debug_break_level > ex_nesting_level
3159 && debug_break_level == ex_nesting_level)
3160 ++debug_break_level;
3161 #endif
3163 #ifdef FEAT_EVAL
3164 almosttheend:
3165 current_SID = save_current_SID;
3166 restore_funccal(save_funccalp);
3167 # ifdef FEAT_PROFILE
3168 if (do_profiling == PROF_YES)
3169 prof_child_exit(&wait_start); /* leaving a child now */
3170 # endif
3171 #endif
3172 fclose(cookie.fp);
3173 vim_free(cookie.nextline);
3174 #ifdef FEAT_MBYTE
3175 convert_setup(&cookie.conv, NULL, NULL);
3176 #endif
3178 theend:
3179 vim_free(fname_exp);
3180 return retval;
3183 #if defined(FEAT_EVAL) || defined(PROTO)
3186 * ":scriptnames"
3188 /*ARGSUSED*/
3189 void
3190 ex_scriptnames(eap)
3191 exarg_T *eap;
3193 int i;
3195 for (i = 1; i <= script_items.ga_len && !got_int; ++i)
3196 if (SCRIPT_ITEM(i).sn_name != NULL)
3197 smsg((char_u *)"%3d: %s", i, SCRIPT_ITEM(i).sn_name);
3200 # if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
3202 * Fix slashes in the list of script names for 'shellslash'.
3204 void
3205 scriptnames_slash_adjust()
3207 int i;
3209 for (i = 1; i <= script_items.ga_len; ++i)
3210 if (SCRIPT_ITEM(i).sn_name != NULL)
3211 slash_adjust(SCRIPT_ITEM(i).sn_name);
3213 # endif
3216 * Get a pointer to a script name. Used for ":verbose set".
3218 char_u *
3219 get_scriptname(id)
3220 scid_T id;
3222 if (id == SID_MODELINE)
3223 return (char_u *)_("modeline");
3224 if (id == SID_CMDARG)
3225 return (char_u *)_("--cmd argument");
3226 if (id == SID_CARG)
3227 return (char_u *)_("-c argument");
3228 if (id == SID_ENV)
3229 return (char_u *)_("environment variable");
3230 if (id == SID_ERROR)
3231 return (char_u *)_("error handler");
3232 return SCRIPT_ITEM(id).sn_name;
3235 # if defined(EXITFREE) || defined(PROTO)
3236 void
3237 free_scriptnames()
3239 int i;
3241 for (i = script_items.ga_len; i > 0; --i)
3242 vim_free(SCRIPT_ITEM(i).sn_name);
3243 ga_clear(&script_items);
3245 # endif
3247 #endif
3249 #if defined(USE_CR) || defined(PROTO)
3251 # if defined(__MSL__) && (__MSL__ >= 22)
3253 * Newer version of the Metrowerks library handle DOS and UNIX files
3254 * without help.
3255 * Test with earlier versions, MSL 2.2 is the library supplied with
3256 * Codewarrior Pro 2.
3258 char *
3259 fgets_cr(s, n, stream)
3260 char *s;
3261 int n;
3262 FILE *stream;
3264 return fgets(s, n, stream);
3266 # else
3268 * Version of fgets() which also works for lines ending in a <CR> only
3269 * (Macintosh format).
3270 * For older versions of the Metrowerks library.
3271 * At least CodeWarrior 9 needed this code.
3273 char *
3274 fgets_cr(s, n, stream)
3275 char *s;
3276 int n;
3277 FILE *stream;
3279 int c = 0;
3280 int char_read = 0;
3282 while (!feof(stream) && c != '\r' && c != '\n' && char_read < n - 1)
3284 c = fgetc(stream);
3285 s[char_read++] = c;
3286 /* If the file is in DOS format, we need to skip a NL after a CR. I
3287 * thought it was the other way around, but this appears to work... */
3288 if (c == '\n')
3290 c = fgetc(stream);
3291 if (c != '\r')
3292 ungetc(c, stream);
3296 s[char_read] = 0;
3297 if (char_read == 0)
3298 return NULL;
3300 if (feof(stream) && char_read == 1)
3301 return NULL;
3303 return s;
3305 # endif
3306 #endif
3309 * Get one full line from a sourced file.
3310 * Called by do_cmdline() when it's called from do_source().
3312 * Return a pointer to the line in allocated memory.
3313 * Return NULL for end-of-file or some error.
3315 /* ARGSUSED */
3316 char_u *
3317 getsourceline(c, cookie, indent)
3318 int c; /* not used */
3319 void *cookie;
3320 int indent; /* not used */
3322 struct source_cookie *sp = (struct source_cookie *)cookie;
3323 char_u *line;
3324 char_u *p, *s;
3326 #ifdef FEAT_EVAL
3327 /* If breakpoints have been added/deleted need to check for it. */
3328 if (sp->dbg_tick < debug_tick)
3330 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
3331 sp->dbg_tick = debug_tick;
3333 # ifdef FEAT_PROFILE
3334 if (do_profiling == PROF_YES)
3335 script_line_end();
3336 # endif
3337 #endif
3339 * Get current line. If there is a read-ahead line, use it, otherwise get
3340 * one now.
3342 if (sp->finished)
3343 line = NULL;
3344 else if (sp->nextline == NULL)
3345 line = get_one_sourceline(sp);
3346 else
3348 line = sp->nextline;
3349 sp->nextline = NULL;
3350 ++sourcing_lnum;
3352 #ifdef FEAT_PROFILE
3353 if (line != NULL && do_profiling == PROF_YES)
3354 script_line_start();
3355 #endif
3357 /* Only concatenate lines starting with a \ when 'cpoptions' doesn't
3358 * contain the 'C' flag. */
3359 if (line != NULL && (vim_strchr(p_cpo, CPO_CONCAT) == NULL))
3361 /* compensate for the one line read-ahead */
3362 --sourcing_lnum;
3363 for (;;)
3365 sp->nextline = get_one_sourceline(sp);
3366 if (sp->nextline == NULL)
3367 break;
3368 p = skipwhite(sp->nextline);
3369 if (*p != '\\')
3370 break;
3371 s = alloc((int)(STRLEN(line) + STRLEN(p)));
3372 if (s == NULL) /* out of memory */
3373 break;
3374 STRCPY(s, line);
3375 STRCAT(s, p + 1);
3376 vim_free(line);
3377 line = s;
3378 vim_free(sp->nextline);
3382 #ifdef FEAT_MBYTE
3383 if (line != NULL && sp->conv.vc_type != CONV_NONE)
3385 /* Convert the encoding of the script line. */
3386 s = string_convert(&sp->conv, line, NULL);
3387 if (s != NULL)
3389 vim_free(line);
3390 line = s;
3393 #endif
3395 #ifdef FEAT_EVAL
3396 /* Did we encounter a breakpoint? */
3397 if (sp->breakpoint != 0 && sp->breakpoint <= sourcing_lnum)
3399 dbg_breakpoint(sp->fname, sourcing_lnum);
3400 /* Find next breakpoint. */
3401 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
3402 sp->dbg_tick = debug_tick;
3404 #endif
3406 return line;
3409 static char_u *
3410 get_one_sourceline(sp)
3411 struct source_cookie *sp;
3413 garray_T ga;
3414 int len;
3415 int c;
3416 char_u *buf;
3417 #ifdef USE_CRNL
3418 int has_cr; /* CR-LF found */
3419 #endif
3420 #ifdef USE_CR
3421 char_u *scan;
3422 #endif
3423 int have_read = FALSE;
3425 /* use a growarray to store the sourced line */
3426 ga_init2(&ga, 1, 250);
3429 * Loop until there is a finished line (or end-of-file).
3431 sourcing_lnum++;
3432 for (;;)
3434 /* make room to read at least 120 (more) characters */
3435 if (ga_grow(&ga, 120) == FAIL)
3436 break;
3437 buf = (char_u *)ga.ga_data;
3439 #ifdef USE_CR
3440 if (sp->fileformat == EOL_MAC)
3442 if (fgets_cr((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
3443 sp->fp) == NULL)
3444 break;
3446 else
3447 #endif
3448 if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
3449 sp->fp) == NULL)
3450 break;
3451 len = ga.ga_len + (int)STRLEN(buf + ga.ga_len);
3452 #ifdef USE_CRNL
3453 /* Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the
3454 * CTRL-Z by its own, or after a NL. */
3455 if ( (len == 1 || (len >= 2 && buf[len - 2] == '\n'))
3456 && sp->fileformat == EOL_DOS
3457 && buf[len - 1] == Ctrl_Z)
3459 buf[len - 1] = NUL;
3460 break;
3462 #endif
3464 #ifdef USE_CR
3465 /* If the read doesn't stop on a new line, and there's
3466 * some CR then we assume a Mac format */
3467 if (sp->fileformat == EOL_UNKNOWN)
3469 if (buf[len - 1] != '\n' && vim_strchr(buf, '\r') != NULL)
3470 sp->fileformat = EOL_MAC;
3471 else
3472 sp->fileformat = EOL_UNIX;
3475 if (sp->fileformat == EOL_MAC)
3477 scan = vim_strchr(buf, '\r');
3479 if (scan != NULL)
3481 *scan = '\n';
3482 if (*(scan + 1) != 0)
3484 *(scan + 1) = 0;
3485 fseek(sp->fp, (long)(scan - buf - len + 1), SEEK_CUR);
3488 len = STRLEN(buf);
3490 #endif
3492 have_read = TRUE;
3493 ga.ga_len = len;
3495 /* If the line was longer than the buffer, read more. */
3496 if (ga.ga_maxlen - ga.ga_len == 1 && buf[len - 1] != '\n')
3497 continue;
3499 if (len >= 1 && buf[len - 1] == '\n') /* remove trailing NL */
3501 #ifdef USE_CRNL
3502 has_cr = (len >= 2 && buf[len - 2] == '\r');
3503 if (sp->fileformat == EOL_UNKNOWN)
3505 if (has_cr)
3506 sp->fileformat = EOL_DOS;
3507 else
3508 sp->fileformat = EOL_UNIX;
3511 if (sp->fileformat == EOL_DOS)
3513 if (has_cr) /* replace trailing CR */
3515 buf[len - 2] = '\n';
3516 --len;
3517 --ga.ga_len;
3519 else /* lines like ":map xx yy^M" will have failed */
3521 if (!sp->error)
3523 msg_source(hl_attr(HLF_W));
3524 EMSG(_("W15: Warning: Wrong line separator, ^M may be missing"));
3526 sp->error = TRUE;
3527 sp->fileformat = EOL_UNIX;
3530 #endif
3531 /* The '\n' is escaped if there is an odd number of ^V's just
3532 * before it, first set "c" just before the 'V's and then check
3533 * len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo */
3534 for (c = len - 2; c >= 0 && buf[c] == Ctrl_V; c--)
3536 if ((len & 1) != (c & 1)) /* escaped NL, read more */
3538 sourcing_lnum++;
3539 continue;
3542 buf[len - 1] = NUL; /* remove the NL */
3546 * Check for ^C here now and then, so recursive :so can be broken.
3548 line_breakcheck();
3549 break;
3552 if (have_read)
3553 return (char_u *)ga.ga_data;
3555 vim_free(ga.ga_data);
3556 return NULL;
3559 #if defined(FEAT_PROFILE) || defined(PROTO)
3561 * Called when starting to read a script line.
3562 * "sourcing_lnum" must be correct!
3563 * When skipping lines it may not actually be executed, but we won't find out
3564 * until later and we need to store the time now.
3566 void
3567 script_line_start()
3569 scriptitem_T *si;
3570 sn_prl_T *pp;
3572 if (current_SID <= 0 || current_SID > script_items.ga_len)
3573 return;
3574 si = &SCRIPT_ITEM(current_SID);
3575 if (si->sn_prof_on && sourcing_lnum >= 1)
3577 /* Grow the array before starting the timer, so that the time spent
3578 * here isn't counted. */
3579 ga_grow(&si->sn_prl_ga, (int)(sourcing_lnum - si->sn_prl_ga.ga_len));
3580 si->sn_prl_idx = sourcing_lnum - 1;
3581 while (si->sn_prl_ga.ga_len <= si->sn_prl_idx
3582 && si->sn_prl_ga.ga_len < si->sn_prl_ga.ga_maxlen)
3584 /* Zero counters for a line that was not used before. */
3585 pp = &PRL_ITEM(si, si->sn_prl_ga.ga_len);
3586 pp->snp_count = 0;
3587 profile_zero(&pp->sn_prl_total);
3588 profile_zero(&pp->sn_prl_self);
3589 ++si->sn_prl_ga.ga_len;
3591 si->sn_prl_execed = FALSE;
3592 profile_start(&si->sn_prl_start);
3593 profile_zero(&si->sn_prl_children);
3594 profile_get_wait(&si->sn_prl_wait);
3599 * Called when actually executing a function line.
3601 void
3602 script_line_exec()
3604 scriptitem_T *si;
3606 if (current_SID <= 0 || current_SID > script_items.ga_len)
3607 return;
3608 si = &SCRIPT_ITEM(current_SID);
3609 if (si->sn_prof_on && si->sn_prl_idx >= 0)
3610 si->sn_prl_execed = TRUE;
3614 * Called when done with a function line.
3616 void
3617 script_line_end()
3619 scriptitem_T *si;
3620 sn_prl_T *pp;
3622 if (current_SID <= 0 || current_SID > script_items.ga_len)
3623 return;
3624 si = &SCRIPT_ITEM(current_SID);
3625 if (si->sn_prof_on && si->sn_prl_idx >= 0
3626 && si->sn_prl_idx < si->sn_prl_ga.ga_len)
3628 if (si->sn_prl_execed)
3630 pp = &PRL_ITEM(si, si->sn_prl_idx);
3631 ++pp->snp_count;
3632 profile_end(&si->sn_prl_start);
3633 profile_sub_wait(&si->sn_prl_wait, &si->sn_prl_start);
3634 profile_add(&pp->sn_prl_total, &si->sn_prl_start);
3635 profile_self(&pp->sn_prl_self, &si->sn_prl_start,
3636 &si->sn_prl_children);
3638 si->sn_prl_idx = -1;
3641 #endif
3644 * ":scriptencoding": Set encoding conversion for a sourced script.
3645 * Without the multi-byte feature it's simply ignored.
3647 /*ARGSUSED*/
3648 void
3649 ex_scriptencoding(eap)
3650 exarg_T *eap;
3652 #ifdef FEAT_MBYTE
3653 struct source_cookie *sp;
3654 char_u *name;
3656 if (!getline_equal(eap->getline, eap->cookie, getsourceline))
3658 EMSG(_("E167: :scriptencoding used outside of a sourced file"));
3659 return;
3662 if (*eap->arg != NUL)
3664 name = enc_canonize(eap->arg);
3665 if (name == NULL) /* out of memory */
3666 return;
3668 else
3669 name = eap->arg;
3671 /* Setup for conversion from the specified encoding to 'encoding'. */
3672 sp = (struct source_cookie *)getline_cookie(eap->getline, eap->cookie);
3673 convert_setup(&sp->conv, name, p_enc);
3675 if (name != eap->arg)
3676 vim_free(name);
3677 #endif
3680 #if defined(FEAT_EVAL) || defined(PROTO)
3682 * ":finish": Mark a sourced file as finished.
3684 void
3685 ex_finish(eap)
3686 exarg_T *eap;
3688 if (getline_equal(eap->getline, eap->cookie, getsourceline))
3689 do_finish(eap, FALSE);
3690 else
3691 EMSG(_("E168: :finish used outside of a sourced file"));
3695 * Mark a sourced file as finished. Possibly makes the ":finish" pending.
3696 * Also called for a pending finish at the ":endtry" or after returning from
3697 * an extra do_cmdline(). "reanimate" is used in the latter case.
3699 void
3700 do_finish(eap, reanimate)
3701 exarg_T *eap;
3702 int reanimate;
3704 int idx;
3706 if (reanimate)
3707 ((struct source_cookie *)getline_cookie(eap->getline,
3708 eap->cookie))->finished = FALSE;
3711 * Cleanup (and inactivate) conditionals, but stop when a try conditional
3712 * not in its finally clause (which then is to be executed next) is found.
3713 * In this case, make the ":finish" pending for execution at the ":endtry".
3714 * Otherwise, finish normally.
3716 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
3717 if (idx >= 0)
3719 eap->cstack->cs_pending[idx] = CSTP_FINISH;
3720 report_make_pending(CSTP_FINISH, NULL);
3722 else
3723 ((struct source_cookie *)getline_cookie(eap->getline,
3724 eap->cookie))->finished = TRUE;
3729 * Return TRUE when a sourced file had the ":finish" command: Don't give error
3730 * message for missing ":endif".
3731 * Return FALSE when not sourcing a file.
3734 source_finished(fgetline, cookie)
3735 char_u *(*fgetline) __ARGS((int, void *, int));
3736 void *cookie;
3738 return (getline_equal(fgetline, cookie, getsourceline)
3739 && ((struct source_cookie *)getline_cookie(
3740 fgetline, cookie))->finished);
3742 #endif
3744 #if defined(FEAT_LISTCMDS) || defined(PROTO)
3746 * ":checktime [buffer]"
3748 void
3749 ex_checktime(eap)
3750 exarg_T *eap;
3752 buf_T *buf;
3753 int save_no_check_timestamps = no_check_timestamps;
3755 no_check_timestamps = 0;
3756 if (eap->addr_count == 0) /* default is all buffers */
3757 check_timestamps(FALSE);
3758 else
3760 buf = buflist_findnr((int)eap->line2);
3761 if (buf != NULL) /* cannot happen? */
3762 (void)buf_check_timestamp(buf, FALSE);
3764 no_check_timestamps = save_no_check_timestamps;
3766 #endif
3768 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3769 && (defined(FEAT_EVAL) || defined(FEAT_MULTI_LANG))
3770 static char *get_locale_val __ARGS((int what));
3772 static char *
3773 get_locale_val(what)
3774 int what;
3776 char *loc;
3778 /* Obtain the locale value from the libraries. For DJGPP this is
3779 * redefined and it doesn't use the arguments. */
3780 loc = setlocale(what, NULL);
3782 # ifdef WIN32
3783 if (loc != NULL)
3785 char_u *p;
3787 /* setocale() returns something like "LC_COLLATE=<name>;LC_..." when
3788 * one of the values (e.g., LC_CTYPE) differs. */
3789 p = vim_strchr(loc, '=');
3790 if (p != NULL)
3792 loc = ++p;
3793 while (*p != NUL) /* remove trailing newline */
3795 if (*p < ' ' || *p == ';')
3797 *p = NUL;
3798 break;
3800 ++p;
3804 # endif
3806 return loc;
3808 #endif
3811 #ifdef WIN32
3813 * On MS-Windows locale names are strings like "German_Germany.1252", but
3814 * gettext expects "de". Try to translate one into another here for a few
3815 * supported languages.
3817 static char_u *
3818 gettext_lang(char_u *name)
3820 int i;
3821 static char *(mtable[]) = {
3822 "afrikaans", "af",
3823 "czech", "cs",
3824 "dutch", "nl",
3825 "german", "de",
3826 "english_united kingdom", "en_GB",
3827 "spanish", "es",
3828 "french", "fr",
3829 "italian", "it",
3830 "japanese", "ja",
3831 "korean", "ko",
3832 "norwegian", "no",
3833 "polish", "pl",
3834 "russian", "ru",
3835 "slovak", "sk",
3836 "swedish", "sv",
3837 "ukrainian", "uk",
3838 "chinese_china", "zh_CN",
3839 "chinese_taiwan", "zh_TW",
3840 NULL};
3842 for (i = 0; mtable[i] != NULL; i += 2)
3843 if (STRNICMP(mtable[i], name, STRLEN(mtable[i])) == 0)
3844 return mtable[i + 1];
3845 return name;
3847 #endif
3849 #if defined(FEAT_MULTI_LANG) || defined(PROTO)
3851 * Obtain the current messages language. Used to set the default for
3852 * 'helplang'. May return NULL or an empty string.
3854 char_u *
3855 get_mess_lang()
3857 char_u *p;
3859 # if (defined(HAVE_LOCALE_H) || defined(X_LOCALE))
3860 # if defined(LC_MESSAGES)
3861 p = (char_u *)get_locale_val(LC_MESSAGES);
3862 # else
3863 /* This is necessary for Win32, where LC_MESSAGES is not defined and $LANG
3864 * may be set to the LCID number. LC_COLLATE is the best guess, LC_TIME
3865 * and LC_MONETARY may be set differently for a Japanese working in the
3866 * US. */
3867 p = (char_u *)get_locale_val(LC_COLLATE);
3868 # endif
3869 # else
3870 p = mch_getenv((char_u *)"LC_ALL");
3871 if (p == NULL || *p == NUL)
3873 p = mch_getenv((char_u *)"LC_MESSAGES");
3874 if (p == NULL || *p == NUL)
3875 p = mch_getenv((char_u *)"LANG");
3877 # endif
3878 # ifdef WIN32
3879 p = gettext_lang(p);
3880 # endif
3881 return p;
3883 #endif
3885 /* Complicated #if; matches with where get_mess_env() is used below. */
3886 #if (defined(FEAT_EVAL) && !((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3887 && defined(LC_MESSAGES))) \
3888 || ((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3889 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)) \
3890 && !defined(LC_MESSAGES))
3891 static char_u *get_mess_env __ARGS((void));
3894 * Get the language used for messages from the environment.
3896 static char_u *
3897 get_mess_env()
3899 char_u *p;
3901 p = mch_getenv((char_u *)"LC_ALL");
3902 if (p == NULL || *p == NUL)
3904 p = mch_getenv((char_u *)"LC_MESSAGES");
3905 if (p == NULL || *p == NUL)
3907 p = mch_getenv((char_u *)"LANG");
3908 if (p != NULL && VIM_ISDIGIT(*p))
3909 p = NULL; /* ignore something like "1043" */
3910 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
3911 if (p == NULL || *p == NUL)
3912 p = (char_u *)get_locale_val(LC_CTYPE);
3913 # endif
3916 return p;
3918 #endif
3920 #if defined(FEAT_EVAL) || defined(PROTO)
3923 * Set the "v:lang" variable according to the current locale setting.
3924 * Also do "v:lc_time"and "v:ctype".
3926 void
3927 set_lang_var()
3929 char_u *loc;
3931 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
3932 loc = (char_u *)get_locale_val(LC_CTYPE);
3933 # else
3934 /* setlocale() not supported: use the default value */
3935 loc = (char_u *)"C";
3936 # endif
3937 set_vim_var_string(VV_CTYPE, loc, -1);
3939 /* When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall
3940 * back to LC_CTYPE if it's empty. */
3941 # if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) && defined(LC_MESSAGES)
3942 loc = (char_u *)get_locale_val(LC_MESSAGES);
3943 # else
3944 loc = get_mess_env();
3945 # endif
3946 set_vim_var_string(VV_LANG, loc, -1);
3948 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
3949 loc = (char_u *)get_locale_val(LC_TIME);
3950 # endif
3951 set_vim_var_string(VV_LC_TIME, loc, -1);
3953 #endif
3955 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3956 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE))
3958 * ":language": Set the language (locale).
3960 void
3961 ex_language(eap)
3962 exarg_T *eap;
3964 char *loc;
3965 char_u *p;
3966 char_u *name;
3967 int what = LC_ALL;
3968 char *whatstr = "";
3969 #ifdef LC_MESSAGES
3970 # define VIM_LC_MESSAGES LC_MESSAGES
3971 #else
3972 # define VIM_LC_MESSAGES 6789
3973 #endif
3975 name = eap->arg;
3977 /* Check for "messages {name}", "ctype {name}" or "time {name}" argument.
3978 * Allow abbreviation, but require at least 3 characters to avoid
3979 * confusion with a two letter language name "me" or "ct". */
3980 p = skiptowhite(eap->arg);
3981 if ((*p == NUL || vim_iswhite(*p)) && p - eap->arg >= 3)
3983 if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0)
3985 what = VIM_LC_MESSAGES;
3986 name = skipwhite(p);
3987 whatstr = "messages ";
3989 else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0)
3991 what = LC_CTYPE;
3992 name = skipwhite(p);
3993 whatstr = "ctype ";
3995 else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0)
3997 what = LC_TIME;
3998 name = skipwhite(p);
3999 whatstr = "time ";
4003 if (*name == NUL)
4005 #ifndef LC_MESSAGES
4006 if (what == VIM_LC_MESSAGES)
4007 p = get_mess_env();
4008 else
4009 #endif
4010 p = (char_u *)setlocale(what, NULL);
4011 if (p == NULL || *p == NUL)
4012 p = (char_u *)"Unknown";
4013 smsg((char_u *)_("Current %slanguage: \"%s\""), whatstr, p);
4015 else
4017 #ifndef LC_MESSAGES
4018 if (what == VIM_LC_MESSAGES)
4019 loc = "";
4020 else
4021 #endif
4023 loc = setlocale(what, (char *)name);
4024 #if defined(FEAT_FLOAT) && defined(LC_NUMERIC)
4025 /* Make sure strtod() uses a decimal point, not a comma. */
4026 setlocale(LC_NUMERIC, "C");
4027 #endif
4029 if (loc == NULL)
4030 EMSG2(_("E197: Cannot set language to \"%s\""), name);
4031 else
4033 #ifdef HAVE_NL_MSG_CAT_CNTR
4034 /* Need to do this for GNU gettext, otherwise cached translations
4035 * will be used again. */
4036 extern int _nl_msg_cat_cntr;
4038 ++_nl_msg_cat_cntr;
4039 #endif
4040 /* Reset $LC_ALL, otherwise it would overrule everything. */
4041 vim_setenv((char_u *)"LC_ALL", (char_u *)"");
4043 if (what != LC_TIME)
4045 /* Tell gettext() what to translate to. It apparently doesn't
4046 * use the currently effective locale. Also do this when
4047 * FEAT_GETTEXT isn't defined, so that shell commands use this
4048 * value. */
4049 if (what == LC_ALL)
4051 vim_setenv((char_u *)"LANG", name);
4052 # ifdef WIN32
4053 /* Apparently MS-Windows printf() may cause a crash when
4054 * we give it 8-bit text while it's expecting text in the
4055 * current locale. This call avoids that. */
4056 setlocale(LC_CTYPE, "C");
4057 # endif
4059 if (what != LC_CTYPE)
4061 char_u *mname;
4062 #ifdef WIN32
4063 mname = gettext_lang(name);
4064 #else
4065 mname = name;
4066 #endif
4067 vim_setenv((char_u *)"LC_MESSAGES", mname);
4068 #ifdef FEAT_MULTI_LANG
4069 set_helplang_default(mname);
4070 #endif
4073 /* Set $LC_CTYPE, because it overrules $LANG, and
4074 * gtk_set_locale() calls setlocale() again. gnome_init()
4075 * sets $LC_CTYPE to "en_US" (that's a bug!). */
4076 if (what != VIM_LC_MESSAGES)
4077 vim_setenv((char_u *)"LC_CTYPE", name);
4078 # ifdef FEAT_GUI_GTK
4079 /* Let GTK know what locale we're using. Not sure this is
4080 * really needed... */
4081 if (gui.in_use)
4082 (void)gtk_set_locale();
4083 # endif
4086 # ifdef FEAT_EVAL
4087 /* Set v:lang, v:lc_time and v:ctype to the final result. */
4088 set_lang_var();
4089 # endif
4094 # if defined(FEAT_CMDL_COMPL) || defined(PROTO)
4096 * Function given to ExpandGeneric() to obtain the possible arguments of the
4097 * ":language" command.
4099 /*ARGSUSED*/
4100 char_u *
4101 get_lang_arg(xp, idx)
4102 expand_T *xp;
4103 int idx;
4105 if (idx == 0)
4106 return (char_u *)"messages";
4107 if (idx == 1)
4108 return (char_u *)"ctype";
4109 if (idx == 2)
4110 return (char_u *)"time";
4111 return NULL;
4113 # endif
4115 #endif