[7.2.173] Without lint there is no check for unused function arguments.
[vim_extended.git] / src / ex_cmds2.c
blobbfa322d870d19719e10b499c893400fb51ed88e5
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 void
684 ex_breaklist(eap)
685 exarg_T *eap UNUSED;
687 struct debuggy *bp;
688 int i;
690 if (dbg_breakp.ga_len == 0)
691 MSG(_("No breakpoints defined"));
692 else
693 for (i = 0; i < dbg_breakp.ga_len; ++i)
695 bp = &BREAKP(i);
696 smsg((char_u *)_("%3d %s %s line %ld"),
697 bp->dbg_nr,
698 bp->dbg_type == DBG_FUNC ? "func" : "file",
699 bp->dbg_name,
700 (long)bp->dbg_lnum);
705 * Find a breakpoint for a function or sourced file.
706 * Returns line number at which to break; zero when no matching breakpoint.
708 linenr_T
709 dbg_find_breakpoint(file, fname, after)
710 int file; /* TRUE for a file, FALSE for a function */
711 char_u *fname; /* file or function name */
712 linenr_T after; /* after this line number */
714 return debuggy_find(file, fname, after, &dbg_breakp, NULL);
717 #if defined(FEAT_PROFILE) || defined(PROTO)
719 * Return TRUE if profiling is on for a function or sourced file.
722 has_profiling(file, fname, fp)
723 int file; /* TRUE for a file, FALSE for a function */
724 char_u *fname; /* file or function name */
725 int *fp; /* return: forceit */
727 return (debuggy_find(file, fname, (linenr_T)0, &prof_ga, fp)
728 != (linenr_T)0);
730 #endif
733 * Common code for dbg_find_breakpoint() and has_profiling().
735 static linenr_T
736 debuggy_find(file, fname, after, gap, fp)
737 int file; /* TRUE for a file, FALSE for a function */
738 char_u *fname; /* file or function name */
739 linenr_T after; /* after this line number */
740 garray_T *gap; /* either &dbg_breakp or &prof_ga */
741 int *fp; /* if not NULL: return forceit */
743 struct debuggy *bp;
744 int i;
745 linenr_T lnum = 0;
746 regmatch_T regmatch;
747 char_u *name = fname;
748 int prev_got_int;
750 /* Return quickly when there are no breakpoints. */
751 if (gap->ga_len == 0)
752 return (linenr_T)0;
754 /* Replace K_SNR in function name with "<SNR>". */
755 if (!file && fname[0] == K_SPECIAL)
757 name = alloc((unsigned)STRLEN(fname) + 3);
758 if (name == NULL)
759 name = fname;
760 else
762 STRCPY(name, "<SNR>");
763 STRCPY(name + 5, fname + 3);
767 for (i = 0; i < gap->ga_len; ++i)
769 /* Skip entries that are not useful or are for a line that is beyond
770 * an already found breakpoint. */
771 bp = &DEBUGGY(gap, i);
772 if (((bp->dbg_type == DBG_FILE) == file && (
773 #ifdef FEAT_PROFILE
774 gap == &prof_ga ||
775 #endif
776 (bp->dbg_lnum > after && (lnum == 0 || bp->dbg_lnum < lnum)))))
778 regmatch.regprog = bp->dbg_prog;
779 regmatch.rm_ic = FALSE;
781 * Save the value of got_int and reset it. We don't want a
782 * previous interruption cancel matching, only hitting CTRL-C
783 * while matching should abort it.
785 prev_got_int = got_int;
786 got_int = FALSE;
787 if (vim_regexec(&regmatch, name, (colnr_T)0))
789 lnum = bp->dbg_lnum;
790 if (fp != NULL)
791 *fp = bp->dbg_forceit;
793 got_int |= prev_got_int;
796 if (name != fname)
797 vim_free(name);
799 return lnum;
803 * Called when a breakpoint was encountered.
805 void
806 dbg_breakpoint(name, lnum)
807 char_u *name;
808 linenr_T lnum;
810 /* We need to check if this line is actually executed in do_one_cmd() */
811 debug_breakpoint_name = name;
812 debug_breakpoint_lnum = lnum;
816 # if defined(FEAT_PROFILE) || defined(FEAT_RELTIME) || defined(PROTO)
818 * Store the current time in "tm".
820 void
821 profile_start(tm)
822 proftime_T *tm;
824 # ifdef WIN3264
825 QueryPerformanceCounter(tm);
826 # else
827 gettimeofday(tm, NULL);
828 # endif
832 * Compute the elapsed time from "tm" till now and store in "tm".
834 void
835 profile_end(tm)
836 proftime_T *tm;
838 proftime_T now;
840 # ifdef WIN3264
841 QueryPerformanceCounter(&now);
842 tm->QuadPart = now.QuadPart - tm->QuadPart;
843 # else
844 gettimeofday(&now, NULL);
845 tm->tv_usec = now.tv_usec - tm->tv_usec;
846 tm->tv_sec = now.tv_sec - tm->tv_sec;
847 if (tm->tv_usec < 0)
849 tm->tv_usec += 1000000;
850 --tm->tv_sec;
852 # endif
856 * Subtract the time "tm2" from "tm".
858 void
859 profile_sub(tm, tm2)
860 proftime_T *tm, *tm2;
862 # ifdef WIN3264
863 tm->QuadPart -= tm2->QuadPart;
864 # else
865 tm->tv_usec -= tm2->tv_usec;
866 tm->tv_sec -= tm2->tv_sec;
867 if (tm->tv_usec < 0)
869 tm->tv_usec += 1000000;
870 --tm->tv_sec;
872 # endif
876 * Return a string that represents the time in "tm".
877 * Uses a static buffer!
879 char *
880 profile_msg(tm)
881 proftime_T *tm;
883 static char buf[50];
885 # ifdef WIN3264
886 LARGE_INTEGER fr;
888 QueryPerformanceFrequency(&fr);
889 sprintf(buf, "%10.6lf", (double)tm->QuadPart / (double)fr.QuadPart);
890 # else
891 sprintf(buf, "%3ld.%06ld", (long)tm->tv_sec, (long)tm->tv_usec);
892 # endif
893 return buf;
897 * Put the time "msec" past now in "tm".
899 void
900 profile_setlimit(msec, tm)
901 long msec;
902 proftime_T *tm;
904 if (msec <= 0) /* no limit */
905 profile_zero(tm);
906 else
908 # ifdef WIN3264
909 LARGE_INTEGER fr;
911 QueryPerformanceCounter(tm);
912 QueryPerformanceFrequency(&fr);
913 tm->QuadPart += (LONGLONG)((double)msec / 1000.0 * (double)fr.QuadPart);
914 # else
915 long usec;
917 gettimeofday(tm, NULL);
918 usec = (long)tm->tv_usec + (long)msec * 1000;
919 tm->tv_usec = usec % 1000000L;
920 tm->tv_sec += usec / 1000000L;
921 # endif
926 * Return TRUE if the current time is past "tm".
929 profile_passed_limit(tm)
930 proftime_T *tm;
932 proftime_T now;
934 # ifdef WIN3264
935 if (tm->QuadPart == 0) /* timer was not set */
936 return FALSE;
937 QueryPerformanceCounter(&now);
938 return (now.QuadPart > tm->QuadPart);
939 # else
940 if (tm->tv_sec == 0) /* timer was not set */
941 return FALSE;
942 gettimeofday(&now, NULL);
943 return (now.tv_sec > tm->tv_sec
944 || (now.tv_sec == tm->tv_sec && now.tv_usec > tm->tv_usec));
945 # endif
949 * Set the time in "tm" to zero.
951 void
952 profile_zero(tm)
953 proftime_T *tm;
955 # ifdef WIN3264
956 tm->QuadPart = 0;
957 # else
958 tm->tv_usec = 0;
959 tm->tv_sec = 0;
960 # endif
963 # endif /* FEAT_PROFILE || FEAT_RELTIME */
965 # if defined(FEAT_PROFILE) || defined(PROTO)
967 * Functions for profiling.
969 static void script_do_profile __ARGS((scriptitem_T *si));
970 static void script_dump_profile __ARGS((FILE *fd));
971 static proftime_T prof_wait_time;
974 * Add the time "tm2" to "tm".
976 void
977 profile_add(tm, tm2)
978 proftime_T *tm, *tm2;
980 # ifdef WIN3264
981 tm->QuadPart += tm2->QuadPart;
982 # else
983 tm->tv_usec += tm2->tv_usec;
984 tm->tv_sec += tm2->tv_sec;
985 if (tm->tv_usec >= 1000000)
987 tm->tv_usec -= 1000000;
988 ++tm->tv_sec;
990 # endif
994 * Add the "self" time from the total time and the children's time.
996 void
997 profile_self(self, total, children)
998 proftime_T *self, *total, *children;
1000 /* Check that the result won't be negative. Can happen with recursive
1001 * calls. */
1002 #ifdef WIN3264
1003 if (total->QuadPart <= children->QuadPart)
1004 return;
1005 #else
1006 if (total->tv_sec < children->tv_sec
1007 || (total->tv_sec == children->tv_sec
1008 && total->tv_usec <= children->tv_usec))
1009 return;
1010 #endif
1011 profile_add(self, total);
1012 profile_sub(self, children);
1016 * Get the current waittime.
1018 void
1019 profile_get_wait(tm)
1020 proftime_T *tm;
1022 *tm = prof_wait_time;
1026 * Subtract the passed waittime since "tm" from "tma".
1028 void
1029 profile_sub_wait(tm, tma)
1030 proftime_T *tm, *tma;
1032 proftime_T tm3 = prof_wait_time;
1034 profile_sub(&tm3, tm);
1035 profile_sub(tma, &tm3);
1039 * Return TRUE if "tm1" and "tm2" are equal.
1042 profile_equal(tm1, tm2)
1043 proftime_T *tm1, *tm2;
1045 # ifdef WIN3264
1046 return (tm1->QuadPart == tm2->QuadPart);
1047 # else
1048 return (tm1->tv_usec == tm2->tv_usec && tm1->tv_sec == tm2->tv_sec);
1049 # endif
1053 * Return <0, 0 or >0 if "tm1" < "tm2", "tm1" == "tm2" or "tm1" > "tm2"
1056 profile_cmp(tm1, tm2)
1057 proftime_T *tm1, *tm2;
1059 # ifdef WIN3264
1060 return (int)(tm2->QuadPart - tm1->QuadPart);
1061 # else
1062 if (tm1->tv_sec == tm2->tv_sec)
1063 return tm2->tv_usec - tm1->tv_usec;
1064 return tm2->tv_sec - tm1->tv_sec;
1065 # endif
1068 static char_u *profile_fname = NULL;
1069 static proftime_T pause_time;
1072 * ":profile cmd args"
1074 void
1075 ex_profile(eap)
1076 exarg_T *eap;
1078 char_u *e;
1079 int len;
1081 e = skiptowhite(eap->arg);
1082 len = (int)(e - eap->arg);
1083 e = skipwhite(e);
1085 if (len == 5 && STRNCMP(eap->arg, "start", 5) == 0 && *e != NUL)
1087 vim_free(profile_fname);
1088 profile_fname = vim_strsave(e);
1089 do_profiling = PROF_YES;
1090 profile_zero(&prof_wait_time);
1091 set_vim_var_nr(VV_PROFILING, 1L);
1093 else if (do_profiling == PROF_NONE)
1094 EMSG(_("E750: First use :profile start <fname>"));
1095 else if (STRCMP(eap->arg, "pause") == 0)
1097 if (do_profiling == PROF_YES)
1098 profile_start(&pause_time);
1099 do_profiling = PROF_PAUSED;
1101 else if (STRCMP(eap->arg, "continue") == 0)
1103 if (do_profiling == PROF_PAUSED)
1105 profile_end(&pause_time);
1106 profile_add(&prof_wait_time, &pause_time);
1108 do_profiling = PROF_YES;
1110 else
1112 /* The rest is similar to ":breakadd". */
1113 ex_breakadd(eap);
1118 * Dump the profiling info.
1120 void
1121 profile_dump()
1123 FILE *fd;
1125 if (profile_fname != NULL)
1127 fd = mch_fopen((char *)profile_fname, "w");
1128 if (fd == NULL)
1129 EMSG2(_(e_notopen), profile_fname);
1130 else
1132 script_dump_profile(fd);
1133 func_dump_profile(fd);
1134 fclose(fd);
1140 * Start profiling script "fp".
1142 static void
1143 script_do_profile(si)
1144 scriptitem_T *si;
1146 si->sn_pr_count = 0;
1147 profile_zero(&si->sn_pr_total);
1148 profile_zero(&si->sn_pr_self);
1150 ga_init2(&si->sn_prl_ga, sizeof(sn_prl_T), 100);
1151 si->sn_prl_idx = -1;
1152 si->sn_prof_on = TRUE;
1153 si->sn_pr_nest = 0;
1157 * save time when starting to invoke another script or function.
1159 void
1160 script_prof_save(tm)
1161 proftime_T *tm; /* place to store wait time */
1163 scriptitem_T *si;
1165 if (current_SID > 0 && current_SID <= script_items.ga_len)
1167 si = &SCRIPT_ITEM(current_SID);
1168 if (si->sn_prof_on && si->sn_pr_nest++ == 0)
1169 profile_start(&si->sn_pr_child);
1171 profile_get_wait(tm);
1175 * Count time spent in children after invoking another script or function.
1177 void
1178 script_prof_restore(tm)
1179 proftime_T *tm;
1181 scriptitem_T *si;
1183 if (current_SID > 0 && current_SID <= script_items.ga_len)
1185 si = &SCRIPT_ITEM(current_SID);
1186 if (si->sn_prof_on && --si->sn_pr_nest == 0)
1188 profile_end(&si->sn_pr_child);
1189 profile_sub_wait(tm, &si->sn_pr_child); /* don't count wait time */
1190 profile_add(&si->sn_pr_children, &si->sn_pr_child);
1191 profile_add(&si->sn_prl_children, &si->sn_pr_child);
1196 static proftime_T inchar_time;
1199 * Called when starting to wait for the user to type a character.
1201 void
1202 prof_inchar_enter()
1204 profile_start(&inchar_time);
1208 * Called when finished waiting for the user to type a character.
1210 void
1211 prof_inchar_exit()
1213 profile_end(&inchar_time);
1214 profile_add(&prof_wait_time, &inchar_time);
1218 * Dump the profiling results for all scripts in file "fd".
1220 static void
1221 script_dump_profile(fd)
1222 FILE *fd;
1224 int id;
1225 scriptitem_T *si;
1226 int i;
1227 FILE *sfd;
1228 sn_prl_T *pp;
1230 for (id = 1; id <= script_items.ga_len; ++id)
1232 si = &SCRIPT_ITEM(id);
1233 if (si->sn_prof_on)
1235 fprintf(fd, "SCRIPT %s\n", si->sn_name);
1236 if (si->sn_pr_count == 1)
1237 fprintf(fd, "Sourced 1 time\n");
1238 else
1239 fprintf(fd, "Sourced %d times\n", si->sn_pr_count);
1240 fprintf(fd, "Total time: %s\n", profile_msg(&si->sn_pr_total));
1241 fprintf(fd, " Self time: %s\n", profile_msg(&si->sn_pr_self));
1242 fprintf(fd, "\n");
1243 fprintf(fd, "count total (s) self (s)\n");
1245 sfd = mch_fopen((char *)si->sn_name, "r");
1246 if (sfd == NULL)
1247 fprintf(fd, "Cannot open file!\n");
1248 else
1250 for (i = 0; i < si->sn_prl_ga.ga_len; ++i)
1252 if (vim_fgets(IObuff, IOSIZE, sfd))
1253 break;
1254 pp = &PRL_ITEM(si, i);
1255 if (pp->snp_count > 0)
1257 fprintf(fd, "%5d ", pp->snp_count);
1258 if (profile_equal(&pp->sn_prl_total, &pp->sn_prl_self))
1259 fprintf(fd, " ");
1260 else
1261 fprintf(fd, "%s ", profile_msg(&pp->sn_prl_total));
1262 fprintf(fd, "%s ", profile_msg(&pp->sn_prl_self));
1264 else
1265 fprintf(fd, " ");
1266 fprintf(fd, "%s", IObuff);
1268 fclose(sfd);
1270 fprintf(fd, "\n");
1276 * Return TRUE when a function defined in the current script should be
1277 * profiled.
1280 prof_def_func()
1282 if (current_SID > 0)
1283 return SCRIPT_ITEM(current_SID).sn_pr_force;
1284 return FALSE;
1287 # endif
1288 #endif
1291 * If 'autowrite' option set, try to write the file.
1292 * Careful: autocommands may make "buf" invalid!
1294 * return FAIL for failure, OK otherwise
1297 autowrite(buf, forceit)
1298 buf_T *buf;
1299 int forceit;
1301 int r;
1303 if (!(p_aw || p_awa) || !p_write
1304 #ifdef FEAT_QUICKFIX
1305 /* never autowrite a "nofile" or "nowrite" buffer */
1306 || bt_dontwrite(buf)
1307 #endif
1308 || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL)
1309 return FAIL;
1310 r = buf_write_all(buf, forceit);
1312 /* Writing may succeed but the buffer still changed, e.g., when there is a
1313 * conversion error. We do want to return FAIL then. */
1314 if (buf_valid(buf) && bufIsChanged(buf))
1315 r = FAIL;
1316 return r;
1320 * flush all buffers, except the ones that are readonly
1322 void
1323 autowrite_all()
1325 buf_T *buf;
1327 if (!(p_aw || p_awa) || !p_write)
1328 return;
1329 for (buf = firstbuf; buf; buf = buf->b_next)
1330 if (bufIsChanged(buf) && !buf->b_p_ro)
1332 (void)buf_write_all(buf, FALSE);
1333 #ifdef FEAT_AUTOCMD
1334 /* an autocommand may have deleted the buffer */
1335 if (!buf_valid(buf))
1336 buf = firstbuf;
1337 #endif
1342 * return TRUE if buffer was changed and cannot be abandoned.
1345 check_changed(buf, checkaw, mult_win, forceit, allbuf)
1346 buf_T *buf;
1347 int checkaw; /* do autowrite if buffer was changed */
1348 int mult_win; /* check also when several wins for the buf */
1349 int forceit;
1350 int allbuf UNUSED; /* may write all buffers */
1352 if ( !forceit
1353 && bufIsChanged(buf)
1354 && (mult_win || buf->b_nwindows <= 1)
1355 && (!checkaw || autowrite(buf, forceit) == FAIL))
1357 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1358 if ((p_confirm || cmdmod.confirm) && p_write)
1360 buf_T *buf2;
1361 int count = 0;
1363 if (allbuf)
1364 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1365 if (bufIsChanged(buf2)
1366 && (buf2->b_ffname != NULL
1367 # ifdef FEAT_BROWSE
1368 || cmdmod.browse
1369 # endif
1371 ++count;
1372 # ifdef FEAT_AUTOCMD
1373 if (!buf_valid(buf))
1374 /* Autocommand deleted buffer, oops! It's not changed now. */
1375 return FALSE;
1376 # endif
1377 dialog_changed(buf, count > 1);
1378 # ifdef FEAT_AUTOCMD
1379 if (!buf_valid(buf))
1380 /* Autocommand deleted buffer, oops! It's not changed now. */
1381 return FALSE;
1382 # endif
1383 return bufIsChanged(buf);
1385 #endif
1386 EMSG(_(e_nowrtmsg));
1387 return TRUE;
1389 return FALSE;
1392 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO)
1394 #if defined(FEAT_BROWSE) || defined(PROTO)
1396 * When wanting to write a file without a file name, ask the user for a name.
1398 void
1399 browse_save_fname(buf)
1400 buf_T *buf;
1402 if (buf->b_fname == NULL)
1404 char_u *fname;
1406 fname = do_browse(BROWSE_SAVE, (char_u *)_("Save As"),
1407 NULL, NULL, NULL, NULL, buf);
1408 if (fname != NULL)
1410 if (setfname(buf, fname, NULL, TRUE) == OK)
1411 buf->b_flags |= BF_NOTEDITED;
1412 vim_free(fname);
1416 #endif
1419 * Ask the user what to do when abondoning a changed buffer.
1420 * Must check 'write' option first!
1422 void
1423 dialog_changed(buf, checkall)
1424 buf_T *buf;
1425 int checkall; /* may abandon all changed buffers */
1427 char_u buff[IOSIZE];
1428 int ret;
1429 buf_T *buf2;
1431 dialog_msg(buff, _("Save changes to \"%s\"?"),
1432 (buf->b_fname != NULL) ?
1433 buf->b_fname : (char_u *)_("Untitled"));
1434 if (checkall)
1435 ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1);
1436 else
1437 ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
1439 if (ret == VIM_YES)
1441 #ifdef FEAT_BROWSE
1442 /* May get file name, when there is none */
1443 browse_save_fname(buf);
1444 #endif
1445 if (buf->b_fname != NULL) /* didn't hit Cancel */
1446 (void)buf_write_all(buf, FALSE);
1448 else if (ret == VIM_NO)
1450 unchanged(buf, TRUE);
1452 else if (ret == VIM_ALL)
1455 * Write all modified files that can be written.
1456 * Skip readonly buffers, these need to be confirmed
1457 * individually.
1459 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1461 if (bufIsChanged(buf2)
1462 && (buf2->b_ffname != NULL
1463 #ifdef FEAT_BROWSE
1464 || cmdmod.browse
1465 #endif
1467 && !buf2->b_p_ro)
1469 #ifdef FEAT_BROWSE
1470 /* May get file name, when there is none */
1471 browse_save_fname(buf2);
1472 #endif
1473 if (buf2->b_fname != NULL) /* didn't hit Cancel */
1474 (void)buf_write_all(buf2, FALSE);
1475 #ifdef FEAT_AUTOCMD
1476 /* an autocommand may have deleted the buffer */
1477 if (!buf_valid(buf2))
1478 buf2 = firstbuf;
1479 #endif
1483 else if (ret == VIM_DISCARDALL)
1486 * mark all buffers as unchanged
1488 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1489 unchanged(buf2, TRUE);
1492 #endif
1495 * Return TRUE if the buffer "buf" can be abandoned, either by making it
1496 * hidden, autowriting it or unloading it.
1499 can_abandon(buf, forceit)
1500 buf_T *buf;
1501 int forceit;
1503 return ( P_HID(buf)
1504 || !bufIsChanged(buf)
1505 || buf->b_nwindows > 1
1506 || autowrite(buf, forceit) == OK
1507 || forceit);
1511 * Return TRUE if any buffer was changed and cannot be abandoned.
1512 * That changed buffer becomes the current buffer.
1515 check_changed_any(hidden)
1516 int hidden; /* Only check hidden buffers */
1518 buf_T *buf;
1519 int save;
1520 #ifdef FEAT_WINDOWS
1521 win_T *wp;
1522 #endif
1524 for (;;)
1526 /* check curbuf first: if it was changed we can't abandon it */
1527 if (!hidden && curbufIsChanged())
1528 buf = curbuf;
1529 else
1531 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
1532 if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf))
1533 break;
1535 if (buf == NULL) /* No buffers changed */
1536 return FALSE;
1538 /* Try auto-writing the buffer. If this fails but the buffer no
1539 * longer exists it's not changed, that's OK. */
1540 if (check_changed(buf, p_awa, TRUE, FALSE, TRUE) && buf_valid(buf))
1541 break; /* didn't save - still changes */
1544 exiting = FALSE;
1545 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1547 * When ":confirm" used, don't give an error message.
1549 if (!(p_confirm || cmdmod.confirm))
1550 #endif
1552 /* There must be a wait_return for this message, do_buffer()
1553 * may cause a redraw. But wait_return() is a no-op when vgetc()
1554 * is busy (Quit used from window menu), then make sure we don't
1555 * cause a scroll up. */
1556 if (vgetc_busy > 0)
1558 msg_row = cmdline_row;
1559 msg_col = 0;
1560 msg_didout = FALSE;
1562 if (EMSG2(_("E162: No write since last change for buffer \"%s\""),
1563 buf_spname(buf) != NULL ? (char_u *)buf_spname(buf) :
1564 buf->b_fname))
1566 save = no_wait_return;
1567 no_wait_return = FALSE;
1568 wait_return(FALSE);
1569 no_wait_return = save;
1573 #ifdef FEAT_WINDOWS
1574 /* Try to find a window that contains the buffer. */
1575 if (buf != curbuf)
1576 for (wp = firstwin; wp != NULL; wp = wp->w_next)
1577 if (wp->w_buffer == buf)
1579 win_goto(wp);
1580 # ifdef FEAT_AUTOCMD
1581 /* Paranoia: did autocms wipe out the buffer with changes? */
1582 if (!buf_valid(buf))
1583 return TRUE;
1584 # endif
1585 break;
1587 #endif
1589 /* Open the changed buffer in the current window. */
1590 if (buf != curbuf)
1591 set_curbuf(buf, DOBUF_GOTO);
1593 return TRUE;
1597 * return FAIL if there is no file name, OK if there is one
1598 * give error message for FAIL
1601 check_fname()
1603 if (curbuf->b_ffname == NULL)
1605 EMSG(_(e_noname));
1606 return FAIL;
1608 return OK;
1612 * flush the contents of a buffer, unless it has no file name
1614 * return FAIL for failure, OK otherwise
1617 buf_write_all(buf, forceit)
1618 buf_T *buf;
1619 int forceit;
1621 int retval;
1622 #ifdef FEAT_AUTOCMD
1623 buf_T *old_curbuf = curbuf;
1624 #endif
1626 retval = (buf_write(buf, buf->b_ffname, buf->b_fname,
1627 (linenr_T)1, buf->b_ml.ml_line_count, NULL,
1628 FALSE, forceit, TRUE, FALSE));
1629 #ifdef FEAT_AUTOCMD
1630 if (curbuf != old_curbuf)
1632 msg_source(hl_attr(HLF_W));
1633 MSG(_("Warning: Entered other buffer unexpectedly (check autocommands)"));
1635 #endif
1636 return retval;
1640 * Code to handle the argument list.
1643 static char_u *do_one_arg __ARGS((char_u *str));
1644 static int do_arglist __ARGS((char_u *str, int what, int after));
1645 static void alist_check_arg_idx __ARGS((void));
1646 static int editing_arg_idx __ARGS((win_T *win));
1647 #ifdef FEAT_LISTCMDS
1648 static int alist_add_list __ARGS((int count, char_u **files, int after));
1649 #endif
1650 #define AL_SET 1
1651 #define AL_ADD 2
1652 #define AL_DEL 3
1655 * Isolate one argument, taking backticks.
1656 * Changes the argument in-place, puts a NUL after it. Backticks remain.
1657 * Return a pointer to the start of the next argument.
1659 static char_u *
1660 do_one_arg(str)
1661 char_u *str;
1663 char_u *p;
1664 int inbacktick;
1666 inbacktick = FALSE;
1667 for (p = str; *str; ++str)
1669 /* When the backslash is used for escaping the special meaning of a
1670 * character we need to keep it until wildcard expansion. */
1671 if (rem_backslash(str))
1673 *p++ = *str++;
1674 *p++ = *str;
1676 else
1678 /* An item ends at a space not in backticks */
1679 if (!inbacktick && vim_isspace(*str))
1680 break;
1681 if (*str == '`')
1682 inbacktick ^= TRUE;
1683 *p++ = *str;
1686 str = skipwhite(str);
1687 *p = NUL;
1689 return str;
1693 * Separate the arguments in "str" and return a list of pointers in the
1694 * growarray "gap".
1697 get_arglist(gap, str)
1698 garray_T *gap;
1699 char_u *str;
1701 ga_init2(gap, (int)sizeof(char_u *), 20);
1702 while (*str != NUL)
1704 if (ga_grow(gap, 1) == FAIL)
1706 ga_clear(gap);
1707 return FAIL;
1709 ((char_u **)gap->ga_data)[gap->ga_len++] = str;
1711 /* Isolate one argument, change it in-place, put a NUL after it. */
1712 str = do_one_arg(str);
1714 return OK;
1717 #if defined(FEAT_QUICKFIX) || defined(FEAT_SYN_HL) || defined(PROTO)
1719 * Parse a list of arguments (file names), expand them and return in
1720 * "fnames[fcountp]".
1721 * Return FAIL or OK.
1724 get_arglist_exp(str, fcountp, fnamesp)
1725 char_u *str;
1726 int *fcountp;
1727 char_u ***fnamesp;
1729 garray_T ga;
1730 int i;
1732 if (get_arglist(&ga, str) == FAIL)
1733 return FAIL;
1734 i = gen_expand_wildcards(ga.ga_len, (char_u **)ga.ga_data,
1735 fcountp, fnamesp, EW_FILE|EW_NOTFOUND);
1736 ga_clear(&ga);
1737 return i;
1739 #endif
1741 #if defined(FEAT_GUI) || defined(FEAT_CLIENTSERVER) || defined(PROTO)
1743 * Redefine the argument list.
1745 void
1746 set_arglist(str)
1747 char_u *str;
1749 do_arglist(str, AL_SET, 0);
1751 #endif
1754 * "what" == AL_SET: Redefine the argument list to 'str'.
1755 * "what" == AL_ADD: add files in 'str' to the argument list after "after".
1756 * "what" == AL_DEL: remove files in 'str' from the argument list.
1758 * Return FAIL for failure, OK otherwise.
1760 static int
1761 do_arglist(str, what, after)
1762 char_u *str;
1763 int what UNUSED;
1764 int after UNUSED; /* 0 means before first one */
1766 garray_T new_ga;
1767 int exp_count;
1768 char_u **exp_files;
1769 int i;
1770 #ifdef FEAT_LISTCMDS
1771 char_u *p;
1772 int match;
1773 #endif
1776 * Collect all file name arguments in "new_ga".
1778 if (get_arglist(&new_ga, str) == FAIL)
1779 return FAIL;
1781 #ifdef FEAT_LISTCMDS
1782 if (what == AL_DEL)
1784 regmatch_T regmatch;
1785 int didone;
1788 * Delete the items: use each item as a regexp and find a match in the
1789 * argument list.
1791 #ifdef CASE_INSENSITIVE_FILENAME
1792 regmatch.rm_ic = TRUE; /* Always ignore case */
1793 #else
1794 regmatch.rm_ic = FALSE; /* Never ignore case */
1795 #endif
1796 for (i = 0; i < new_ga.ga_len && !got_int; ++i)
1798 p = ((char_u **)new_ga.ga_data)[i];
1799 p = file_pat_to_reg_pat(p, NULL, NULL, FALSE);
1800 if (p == NULL)
1801 break;
1802 regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0);
1803 if (regmatch.regprog == NULL)
1805 vim_free(p);
1806 break;
1809 didone = FALSE;
1810 for (match = 0; match < ARGCOUNT; ++match)
1811 if (vim_regexec(&regmatch, alist_name(&ARGLIST[match]),
1812 (colnr_T)0))
1814 didone = TRUE;
1815 vim_free(ARGLIST[match].ae_fname);
1816 mch_memmove(ARGLIST + match, ARGLIST + match + 1,
1817 (ARGCOUNT - match - 1) * sizeof(aentry_T));
1818 --ALIST(curwin)->al_ga.ga_len;
1819 if (curwin->w_arg_idx > match)
1820 --curwin->w_arg_idx;
1821 --match;
1824 vim_free(regmatch.regprog);
1825 vim_free(p);
1826 if (!didone)
1827 EMSG2(_(e_nomatch2), ((char_u **)new_ga.ga_data)[i]);
1829 ga_clear(&new_ga);
1831 else
1832 #endif
1834 i = expand_wildcards(new_ga.ga_len, (char_u **)new_ga.ga_data,
1835 &exp_count, &exp_files, EW_DIR|EW_FILE|EW_ADDSLASH|EW_NOTFOUND);
1836 ga_clear(&new_ga);
1837 if (i == FAIL)
1838 return FAIL;
1839 if (exp_count == 0)
1841 EMSG(_(e_nomatch));
1842 return FAIL;
1845 #ifdef FEAT_LISTCMDS
1846 if (what == AL_ADD)
1848 (void)alist_add_list(exp_count, exp_files, after);
1849 vim_free(exp_files);
1851 else /* what == AL_SET */
1852 #endif
1853 alist_set(ALIST(curwin), exp_count, exp_files, FALSE, NULL, 0);
1856 alist_check_arg_idx();
1858 return OK;
1862 * Check the validity of the arg_idx for each other window.
1864 static void
1865 alist_check_arg_idx()
1867 #ifdef FEAT_WINDOWS
1868 win_T *win;
1869 tabpage_T *tp;
1871 FOR_ALL_TAB_WINDOWS(tp, win)
1872 if (win->w_alist == curwin->w_alist)
1873 check_arg_idx(win);
1874 #else
1875 check_arg_idx(curwin);
1876 #endif
1880 * Return TRUE if window "win" is editing then file at the current argument
1881 * index.
1883 static int
1884 editing_arg_idx(win)
1885 win_T *win;
1887 return !(win->w_arg_idx >= WARGCOUNT(win)
1888 || (win->w_buffer->b_fnum
1889 != WARGLIST(win)[win->w_arg_idx].ae_fnum
1890 && (win->w_buffer->b_ffname == NULL
1891 || !(fullpathcmp(
1892 alist_name(&WARGLIST(win)[win->w_arg_idx]),
1893 win->w_buffer->b_ffname, TRUE) & FPC_SAME))));
1897 * Check if window "win" is editing the w_arg_idx file in its argument list.
1899 void
1900 check_arg_idx(win)
1901 win_T *win;
1903 if (WARGCOUNT(win) > 1 && !editing_arg_idx(win))
1905 /* We are not editing the current entry in the argument list.
1906 * Set "arg_had_last" if we are editing the last one. */
1907 win->w_arg_idx_invalid = TRUE;
1908 if (win->w_arg_idx != WARGCOUNT(win) - 1
1909 && arg_had_last == FALSE
1910 #ifdef FEAT_WINDOWS
1911 && ALIST(win) == &global_alist
1912 #endif
1913 && GARGCOUNT > 0
1914 && win->w_arg_idx < GARGCOUNT
1915 && (win->w_buffer->b_fnum == GARGLIST[GARGCOUNT - 1].ae_fnum
1916 || (win->w_buffer->b_ffname != NULL
1917 && (fullpathcmp(alist_name(&GARGLIST[GARGCOUNT - 1]),
1918 win->w_buffer->b_ffname, TRUE) & FPC_SAME))))
1919 arg_had_last = TRUE;
1921 else
1923 /* We are editing the current entry in the argument list.
1924 * Set "arg_had_last" if it's also the last one */
1925 win->w_arg_idx_invalid = FALSE;
1926 if (win->w_arg_idx == WARGCOUNT(win) - 1
1927 #ifdef FEAT_WINDOWS
1928 && win->w_alist == &global_alist
1929 #endif
1931 arg_had_last = TRUE;
1936 * ":args", ":argslocal" and ":argsglobal".
1938 void
1939 ex_args(eap)
1940 exarg_T *eap;
1942 int i;
1944 if (eap->cmdidx != CMD_args)
1946 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
1947 alist_unlink(ALIST(curwin));
1948 if (eap->cmdidx == CMD_argglobal)
1949 ALIST(curwin) = &global_alist;
1950 else /* eap->cmdidx == CMD_arglocal */
1951 alist_new();
1952 #else
1953 ex_ni(eap);
1954 return;
1955 #endif
1958 if (!ends_excmd(*eap->arg))
1961 * ":args file ..": define new argument list, handle like ":next"
1962 * Also for ":argslocal file .." and ":argsglobal file ..".
1964 ex_next(eap);
1966 else
1967 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
1968 if (eap->cmdidx == CMD_args)
1969 #endif
1972 * ":args": list arguments.
1974 if (ARGCOUNT > 0)
1976 /* Overwrite the command, for a short list there is no scrolling
1977 * required and no wait_return(). */
1978 gotocmdline(TRUE);
1979 for (i = 0; i < ARGCOUNT; ++i)
1981 if (i == curwin->w_arg_idx)
1982 msg_putchar('[');
1983 msg_outtrans(alist_name(&ARGLIST[i]));
1984 if (i == curwin->w_arg_idx)
1985 msg_putchar(']');
1986 msg_putchar(' ');
1990 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
1991 else if (eap->cmdidx == CMD_arglocal)
1993 garray_T *gap = &curwin->w_alist->al_ga;
1996 * ":argslocal": make a local copy of the global argument list.
1998 if (ga_grow(gap, GARGCOUNT) == OK)
1999 for (i = 0; i < GARGCOUNT; ++i)
2000 if (GARGLIST[i].ae_fname != NULL)
2002 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fname =
2003 vim_strsave(GARGLIST[i].ae_fname);
2004 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fnum =
2005 GARGLIST[i].ae_fnum;
2006 ++gap->ga_len;
2009 #endif
2013 * ":previous", ":sprevious", ":Next" and ":sNext".
2015 void
2016 ex_previous(eap)
2017 exarg_T *eap;
2019 /* If past the last one already, go to the last one. */
2020 if (curwin->w_arg_idx - (int)eap->line2 >= ARGCOUNT)
2021 do_argfile(eap, ARGCOUNT - 1);
2022 else
2023 do_argfile(eap, curwin->w_arg_idx - (int)eap->line2);
2027 * ":rewind", ":first", ":sfirst" and ":srewind".
2029 void
2030 ex_rewind(eap)
2031 exarg_T *eap;
2033 do_argfile(eap, 0);
2037 * ":last" and ":slast".
2039 void
2040 ex_last(eap)
2041 exarg_T *eap;
2043 do_argfile(eap, ARGCOUNT - 1);
2047 * ":argument" and ":sargument".
2049 void
2050 ex_argument(eap)
2051 exarg_T *eap;
2053 int i;
2055 if (eap->addr_count > 0)
2056 i = eap->line2 - 1;
2057 else
2058 i = curwin->w_arg_idx;
2059 do_argfile(eap, i);
2063 * Edit file "argn" of the argument lists.
2065 void
2066 do_argfile(eap, argn)
2067 exarg_T *eap;
2068 int argn;
2070 int other;
2071 char_u *p;
2072 int old_arg_idx = curwin->w_arg_idx;
2074 if (argn < 0 || argn >= ARGCOUNT)
2076 if (ARGCOUNT <= 1)
2077 EMSG(_("E163: There is only one file to edit"));
2078 else if (argn < 0)
2079 EMSG(_("E164: Cannot go before first file"));
2080 else
2081 EMSG(_("E165: Cannot go beyond last file"));
2083 else
2085 setpcmark();
2086 #ifdef FEAT_GUI
2087 need_mouse_correct = TRUE;
2088 #endif
2090 #ifdef FEAT_WINDOWS
2091 /* split window or create new tab page first */
2092 if (*eap->cmd == 's' || cmdmod.tab != 0)
2094 if (win_split(0, 0) == FAIL)
2095 return;
2096 # ifdef FEAT_SCROLLBIND
2097 curwin->w_p_scb = FALSE;
2098 # endif
2100 else
2101 #endif
2104 * if 'hidden' set, only check for changed file when re-editing
2105 * the same buffer
2107 other = TRUE;
2108 if (P_HID(curbuf))
2110 p = fix_fname(alist_name(&ARGLIST[argn]));
2111 other = otherfile(p);
2112 vim_free(p);
2114 if ((!P_HID(curbuf) || !other)
2115 && check_changed(curbuf, TRUE, !other, eap->forceit, FALSE))
2116 return;
2119 curwin->w_arg_idx = argn;
2120 if (argn == ARGCOUNT - 1
2121 #ifdef FEAT_WINDOWS
2122 && curwin->w_alist == &global_alist
2123 #endif
2125 arg_had_last = TRUE;
2127 /* Edit the file; always use the last known line number.
2128 * When it fails (e.g. Abort for already edited file) restore the
2129 * argument index. */
2130 if (do_ecmd(0, alist_name(&ARGLIST[curwin->w_arg_idx]), NULL,
2131 eap, ECMD_LAST,
2132 (P_HID(curwin->w_buffer) ? ECMD_HIDE : 0)
2133 + (eap->forceit ? ECMD_FORCEIT : 0), curwin) == FAIL)
2134 curwin->w_arg_idx = old_arg_idx;
2135 /* like Vi: set the mark where the cursor is in the file. */
2136 else if (eap->cmdidx != CMD_argdo)
2137 setmark('\'');
2142 * ":next", and commands that behave like it.
2144 void
2145 ex_next(eap)
2146 exarg_T *eap;
2148 int i;
2151 * check for changed buffer now, if this fails the argument list is not
2152 * redefined.
2154 if ( P_HID(curbuf)
2155 || eap->cmdidx == CMD_snext
2156 || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
2158 if (*eap->arg != NUL) /* redefine file list */
2160 if (do_arglist(eap->arg, AL_SET, 0) == FAIL)
2161 return;
2162 i = 0;
2164 else
2165 i = curwin->w_arg_idx + (int)eap->line2;
2166 do_argfile(eap, i);
2170 #ifdef FEAT_LISTCMDS
2172 * ":argedit"
2174 void
2175 ex_argedit(eap)
2176 exarg_T *eap;
2178 int fnum;
2179 int i;
2180 char_u *s;
2182 /* Add the argument to the buffer list and get the buffer number. */
2183 fnum = buflist_add(eap->arg, BLN_LISTED);
2185 /* Check if this argument is already in the argument list. */
2186 for (i = 0; i < ARGCOUNT; ++i)
2187 if (ARGLIST[i].ae_fnum == fnum)
2188 break;
2189 if (i == ARGCOUNT)
2191 /* Can't find it, add it to the argument list. */
2192 s = vim_strsave(eap->arg);
2193 if (s == NULL)
2194 return;
2195 i = alist_add_list(1, &s,
2196 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
2197 if (i < 0)
2198 return;
2199 curwin->w_arg_idx = i;
2202 alist_check_arg_idx();
2204 /* Edit the argument. */
2205 do_argfile(eap, i);
2209 * ":argadd"
2211 void
2212 ex_argadd(eap)
2213 exarg_T *eap;
2215 do_arglist(eap->arg, AL_ADD,
2216 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
2217 #ifdef FEAT_TITLE
2218 maketitle();
2219 #endif
2223 * ":argdelete"
2225 void
2226 ex_argdelete(eap)
2227 exarg_T *eap;
2229 int i;
2230 int n;
2232 if (eap->addr_count > 0)
2234 /* ":1,4argdel": Delete all arguments in the range. */
2235 if (eap->line2 > ARGCOUNT)
2236 eap->line2 = ARGCOUNT;
2237 n = eap->line2 - eap->line1 + 1;
2238 if (*eap->arg != NUL || n <= 0)
2239 EMSG(_(e_invarg));
2240 else
2242 for (i = eap->line1; i <= eap->line2; ++i)
2243 vim_free(ARGLIST[i - 1].ae_fname);
2244 mch_memmove(ARGLIST + eap->line1 - 1, ARGLIST + eap->line2,
2245 (size_t)((ARGCOUNT - eap->line2) * sizeof(aentry_T)));
2246 ALIST(curwin)->al_ga.ga_len -= n;
2247 if (curwin->w_arg_idx >= eap->line2)
2248 curwin->w_arg_idx -= n;
2249 else if (curwin->w_arg_idx > eap->line1)
2250 curwin->w_arg_idx = eap->line1;
2253 else if (*eap->arg == NUL)
2254 EMSG(_(e_argreq));
2255 else
2256 do_arglist(eap->arg, AL_DEL, 0);
2257 #ifdef FEAT_TITLE
2258 maketitle();
2259 #endif
2263 * ":argdo", ":windo", ":bufdo", ":tabdo"
2265 void
2266 ex_listdo(eap)
2267 exarg_T *eap;
2269 int i;
2270 #ifdef FEAT_WINDOWS
2271 win_T *wp;
2272 tabpage_T *tp;
2273 #endif
2274 buf_T *buf;
2275 int next_fnum = 0;
2276 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2277 char_u *save_ei = NULL;
2278 #endif
2279 char_u *p_shm_save;
2281 #ifndef FEAT_WINDOWS
2282 if (eap->cmdidx == CMD_windo)
2284 ex_ni(eap);
2285 return;
2287 #endif
2289 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2290 if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo)
2291 /* Don't do syntax HL autocommands. Skipping the syntax file is a
2292 * great speed improvement. */
2293 save_ei = au_event_disable(",Syntax");
2294 #endif
2296 if (eap->cmdidx == CMD_windo
2297 || eap->cmdidx == CMD_tabdo
2298 || P_HID(curbuf)
2299 || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
2301 /* start at the first argument/window/buffer */
2302 i = 0;
2303 #ifdef FEAT_WINDOWS
2304 wp = firstwin;
2305 tp = first_tabpage;
2306 #endif
2307 /* set pcmark now */
2308 if (eap->cmdidx == CMD_bufdo)
2309 goto_buffer(eap, DOBUF_FIRST, FORWARD, 0);
2310 else
2311 setpcmark();
2312 listcmd_busy = TRUE; /* avoids setting pcmark below */
2314 while (!got_int)
2316 if (eap->cmdidx == CMD_argdo)
2318 /* go to argument "i" */
2319 if (i == ARGCOUNT)
2320 break;
2321 /* Don't call do_argfile() when already there, it will try
2322 * reloading the file. */
2323 if (curwin->w_arg_idx != i || !editing_arg_idx(curwin))
2325 /* Clear 'shm' to avoid that the file message overwrites
2326 * any output from the command. */
2327 p_shm_save = vim_strsave(p_shm);
2328 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
2329 do_argfile(eap, i);
2330 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
2331 vim_free(p_shm_save);
2333 if (curwin->w_arg_idx != i)
2334 break;
2335 ++i;
2337 #ifdef FEAT_WINDOWS
2338 else if (eap->cmdidx == CMD_windo)
2340 /* go to window "wp" */
2341 if (!win_valid(wp))
2342 break;
2343 win_goto(wp);
2344 if (curwin != wp)
2345 break; /* something must be wrong */
2346 wp = curwin->w_next;
2348 else if (eap->cmdidx == CMD_tabdo)
2350 /* go to window "tp" */
2351 if (!valid_tabpage(tp))
2352 break;
2353 goto_tabpage_tp(tp);
2354 tp = tp->tp_next;
2356 #endif
2357 else if (eap->cmdidx == CMD_bufdo)
2359 /* Remember the number of the next listed buffer, in case
2360 * ":bwipe" is used or autocommands do something strange. */
2361 next_fnum = -1;
2362 for (buf = curbuf->b_next; buf != NULL; buf = buf->b_next)
2363 if (buf->b_p_bl)
2365 next_fnum = buf->b_fnum;
2366 break;
2370 /* execute the command */
2371 do_cmdline(eap->arg, eap->getline, eap->cookie,
2372 DOCMD_VERBOSE + DOCMD_NOWAIT);
2374 if (eap->cmdidx == CMD_bufdo)
2376 /* Done? */
2377 if (next_fnum < 0)
2378 break;
2379 /* Check if the buffer still exists. */
2380 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
2381 if (buf->b_fnum == next_fnum)
2382 break;
2383 if (buf == NULL)
2384 break;
2386 /* Go to the next buffer. Clear 'shm' to avoid that the file
2387 * message overwrites any output from the command. */
2388 p_shm_save = vim_strsave(p_shm);
2389 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
2390 goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
2391 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
2392 vim_free(p_shm_save);
2394 /* If autocommands took us elsewhere, quit here */
2395 if (curbuf->b_fnum != next_fnum)
2396 break;
2399 if (eap->cmdidx == CMD_windo)
2401 validate_cursor(); /* cursor may have moved */
2402 #ifdef FEAT_SCROLLBIND
2403 /* required when 'scrollbind' has been set */
2404 if (curwin->w_p_scb)
2405 do_check_scrollbind(TRUE);
2406 #endif
2409 listcmd_busy = FALSE;
2412 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2413 if (save_ei != NULL)
2415 au_event_restore(save_ei);
2416 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
2417 curbuf->b_fname, TRUE, curbuf);
2419 #endif
2423 * Add files[count] to the arglist of the current window after arg "after".
2424 * The file names in files[count] must have been allocated and are taken over.
2425 * Files[] itself is not taken over.
2426 * Returns index of first added argument. Returns -1 when failed (out of mem).
2428 static int
2429 alist_add_list(count, files, after)
2430 int count;
2431 char_u **files;
2432 int after; /* where to add: 0 = before first one */
2434 int i;
2436 if (ga_grow(&ALIST(curwin)->al_ga, count) == OK)
2438 if (after < 0)
2439 after = 0;
2440 if (after > ARGCOUNT)
2441 after = ARGCOUNT;
2442 if (after < ARGCOUNT)
2443 mch_memmove(&(ARGLIST[after + count]), &(ARGLIST[after]),
2444 (ARGCOUNT - after) * sizeof(aentry_T));
2445 for (i = 0; i < count; ++i)
2447 ARGLIST[after + i].ae_fname = files[i];
2448 ARGLIST[after + i].ae_fnum = buflist_add(files[i], BLN_LISTED);
2450 ALIST(curwin)->al_ga.ga_len += count;
2451 if (curwin->w_arg_idx >= after)
2452 ++curwin->w_arg_idx;
2453 return after;
2456 for (i = 0; i < count; ++i)
2457 vim_free(files[i]);
2458 return -1;
2461 #endif /* FEAT_LISTCMDS */
2463 #ifdef FEAT_EVAL
2465 * ":compiler[!] {name}"
2467 void
2468 ex_compiler(eap)
2469 exarg_T *eap;
2471 char_u *buf;
2472 char_u *old_cur_comp = NULL;
2473 char_u *p;
2475 if (*eap->arg == NUL)
2477 /* List all compiler scripts. */
2478 do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')");
2479 /* ) keep the indenter happy... */
2481 else
2483 buf = alloc((unsigned)(STRLEN(eap->arg) + 14));
2484 if (buf != NULL)
2486 if (eap->forceit)
2488 /* ":compiler! {name}" sets global options */
2489 do_cmdline_cmd((char_u *)
2490 "command -nargs=* CompilerSet set <args>");
2492 else
2494 /* ":compiler! {name}" sets local options.
2495 * To remain backwards compatible "current_compiler" is always
2496 * used. A user's compiler plugin may set it, the distributed
2497 * plugin will then skip the settings. Afterwards set
2498 * "b:current_compiler" and restore "current_compiler". */
2499 old_cur_comp = get_var_value((char_u *)"current_compiler");
2500 if (old_cur_comp != NULL)
2501 old_cur_comp = vim_strsave(old_cur_comp);
2502 do_cmdline_cmd((char_u *)
2503 "command -nargs=* CompilerSet setlocal <args>");
2505 do_unlet((char_u *)"current_compiler", TRUE);
2506 do_unlet((char_u *)"b:current_compiler", TRUE);
2508 sprintf((char *)buf, "compiler/%s.vim", eap->arg);
2509 if (source_runtime(buf, TRUE) == FAIL)
2510 EMSG2(_("E666: compiler not supported: %s"), eap->arg);
2511 vim_free(buf);
2513 do_cmdline_cmd((char_u *)":delcommand CompilerSet");
2515 /* Set "b:current_compiler" from "current_compiler". */
2516 p = get_var_value((char_u *)"current_compiler");
2517 if (p != NULL)
2518 set_internal_string_var((char_u *)"b:current_compiler", p);
2520 /* Restore "current_compiler" for ":compiler {name}". */
2521 if (!eap->forceit)
2523 if (old_cur_comp != NULL)
2525 set_internal_string_var((char_u *)"current_compiler",
2526 old_cur_comp);
2527 vim_free(old_cur_comp);
2529 else
2530 do_unlet((char_u *)"current_compiler", TRUE);
2535 #endif
2538 * ":runtime {name}"
2540 void
2541 ex_runtime(eap)
2542 exarg_T *eap;
2544 source_runtime(eap->arg, eap->forceit);
2547 static void source_callback __ARGS((char_u *fname, void *cookie));
2549 static void
2550 source_callback(fname, cookie)
2551 char_u *fname;
2552 void *cookie UNUSED;
2554 (void)do_source(fname, FALSE, DOSO_NONE);
2558 * Source the file "name" from all directories in 'runtimepath'.
2559 * "name" can contain wildcards.
2560 * When "all" is TRUE, source all files, otherwise only the first one.
2561 * return FAIL when no file could be sourced, OK otherwise.
2564 source_runtime(name, all)
2565 char_u *name;
2566 int all;
2568 return do_in_runtimepath(name, all, source_callback, NULL);
2572 * Find "name" in 'runtimepath'. When found, invoke the callback function for
2573 * it: callback(fname, "cookie")
2574 * When "all" is TRUE repeat for all matches, otherwise only the first one is
2575 * used.
2576 * Returns OK when at least one match found, FAIL otherwise.
2579 do_in_runtimepath(name, all, callback, cookie)
2580 char_u *name;
2581 int all;
2582 void (*callback)__ARGS((char_u *fname, void *ck));
2583 void *cookie;
2585 char_u *rtp;
2586 char_u *np;
2587 char_u *buf;
2588 char_u *rtp_copy;
2589 char_u *tail;
2590 int num_files;
2591 char_u **files;
2592 int i;
2593 int did_one = FALSE;
2594 #ifdef AMIGA
2595 struct Process *proc = (struct Process *)FindTask(0L);
2596 APTR save_winptr = proc->pr_WindowPtr;
2598 /* Avoid a requester here for a volume that doesn't exist. */
2599 proc->pr_WindowPtr = (APTR)-1L;
2600 #endif
2602 /* Make a copy of 'runtimepath'. Invoking the callback may change the
2603 * value. */
2604 rtp_copy = vim_strsave(p_rtp);
2605 buf = alloc(MAXPATHL);
2606 if (buf != NULL && rtp_copy != NULL)
2608 if (p_verbose > 1)
2610 verbose_enter();
2611 smsg((char_u *)_("Searching for \"%s\" in \"%s\""),
2612 (char *)name, (char *)p_rtp);
2613 verbose_leave();
2616 /* Loop over all entries in 'runtimepath'. */
2617 rtp = rtp_copy;
2618 while (*rtp != NUL && (all || !did_one))
2620 /* Copy the path from 'runtimepath' to buf[]. */
2621 copy_option_part(&rtp, buf, MAXPATHL, ",");
2622 if (STRLEN(buf) + STRLEN(name) + 2 < MAXPATHL)
2624 add_pathsep(buf);
2625 tail = buf + STRLEN(buf);
2627 /* Loop over all patterns in "name" */
2628 np = name;
2629 while (*np != NUL && (all || !did_one))
2631 /* Append the pattern from "name" to buf[]. */
2632 copy_option_part(&np, tail, (int)(MAXPATHL - (tail - buf)),
2633 "\t ");
2635 if (p_verbose > 2)
2637 verbose_enter();
2638 smsg((char_u *)_("Searching for \"%s\""), buf);
2639 verbose_leave();
2642 /* Expand wildcards, invoke the callback for each match. */
2643 if (gen_expand_wildcards(1, &buf, &num_files, &files,
2644 EW_FILE) == OK)
2646 for (i = 0; i < num_files; ++i)
2648 (*callback)(files[i], cookie);
2649 did_one = TRUE;
2650 if (!all)
2651 break;
2653 FreeWild(num_files, files);
2659 vim_free(buf);
2660 vim_free(rtp_copy);
2661 if (p_verbose > 0 && !did_one)
2663 verbose_enter();
2664 smsg((char_u *)_("not found in 'runtimepath': \"%s\""), name);
2665 verbose_leave();
2668 #ifdef AMIGA
2669 proc->pr_WindowPtr = save_winptr;
2670 #endif
2672 return did_one ? OK : FAIL;
2675 #if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD)
2677 * ":options"
2679 void
2680 ex_options(eap)
2681 exarg_T *eap UNUSED;
2683 cmd_source((char_u *)SYS_OPTWIN_FILE, NULL);
2685 #endif
2688 * ":source {fname}"
2690 void
2691 ex_source(eap)
2692 exarg_T *eap;
2694 #ifdef FEAT_BROWSE
2695 if (cmdmod.browse)
2697 char_u *fname = NULL;
2699 fname = do_browse(0, (char_u *)_("Source Vim script"), eap->arg,
2700 NULL, NULL, BROWSE_FILTER_MACROS, NULL);
2701 if (fname != NULL)
2703 cmd_source(fname, eap);
2704 vim_free(fname);
2707 else
2708 #endif
2709 cmd_source(eap->arg, eap);
2712 static void
2713 cmd_source(fname, eap)
2714 char_u *fname;
2715 exarg_T *eap;
2717 if (*fname == NUL)
2718 EMSG(_(e_argreq));
2720 else if (eap != NULL && eap->forceit)
2721 /* ":source!": read Normal mdoe commands
2722 * Need to execute the commands directly. This is required at least
2723 * for:
2724 * - ":g" command busy
2725 * - after ":argdo", ":windo" or ":bufdo"
2726 * - another command follows
2727 * - inside a loop
2729 openscript(fname, global_busy || listcmd_busy || eap->nextcmd != NULL
2730 #ifdef FEAT_EVAL
2731 || eap->cstack->cs_idx >= 0
2732 #endif
2735 /* ":source" read ex commands */
2736 else if (do_source(fname, FALSE, DOSO_NONE) == FAIL)
2737 EMSG2(_(e_notopen), fname);
2741 * ":source" and associated commands.
2744 * Structure used to store info for each sourced file.
2745 * It is shared between do_source() and getsourceline().
2746 * This is required, because it needs to be handed to do_cmdline() and
2747 * sourcing can be done recursively.
2749 struct source_cookie
2751 FILE *fp; /* opened file for sourcing */
2752 char_u *nextline; /* if not NULL: line that was read ahead */
2753 int finished; /* ":finish" used */
2754 #if defined (USE_CRNL) || defined (USE_CR)
2755 int fileformat; /* EOL_UNKNOWN, EOL_UNIX or EOL_DOS */
2756 int error; /* TRUE if LF found after CR-LF */
2757 #endif
2758 #ifdef FEAT_EVAL
2759 linenr_T breakpoint; /* next line with breakpoint or zero */
2760 char_u *fname; /* name of sourced file */
2761 int dbg_tick; /* debug_tick when breakpoint was set */
2762 int level; /* top nesting level of sourced file */
2763 #endif
2764 #ifdef FEAT_MBYTE
2765 vimconv_T conv; /* type of conversion */
2766 #endif
2769 #ifdef FEAT_EVAL
2771 * Return the address holding the next breakpoint line for a source cookie.
2773 linenr_T *
2774 source_breakpoint(cookie)
2775 void *cookie;
2777 return &((struct source_cookie *)cookie)->breakpoint;
2781 * Return the address holding the debug tick for a source cookie.
2783 int *
2784 source_dbg_tick(cookie)
2785 void *cookie;
2787 return &((struct source_cookie *)cookie)->dbg_tick;
2791 * Return the nesting level for a source cookie.
2794 source_level(cookie)
2795 void *cookie;
2797 return ((struct source_cookie *)cookie)->level;
2799 #endif
2801 static char_u *get_one_sourceline __ARGS((struct source_cookie *sp));
2803 #if defined(WIN32) && defined(FEAT_CSCOPE)
2804 static FILE *fopen_noinh_readbin __ARGS((char *filename));
2807 * Special function to open a file without handle inheritance.
2809 static FILE *
2810 fopen_noinh_readbin(filename)
2811 char *filename;
2813 int fd_tmp = mch_open(filename, O_RDONLY | O_BINARY | O_NOINHERIT, 0);
2815 if (fd_tmp == -1)
2816 return NULL;
2817 return fdopen(fd_tmp, READBIN);
2819 #endif
2823 * do_source: Read the file "fname" and execute its lines as EX commands.
2825 * This function may be called recursively!
2827 * return FAIL if file could not be opened, OK otherwise
2830 do_source(fname, check_other, is_vimrc)
2831 char_u *fname;
2832 int check_other; /* check for .vimrc and _vimrc */
2833 int is_vimrc; /* DOSO_ value */
2835 struct source_cookie cookie;
2836 char_u *save_sourcing_name;
2837 linenr_T save_sourcing_lnum;
2838 char_u *p;
2839 char_u *fname_exp;
2840 char_u *firstline = NULL;
2841 int retval = FAIL;
2842 #ifdef FEAT_EVAL
2843 scid_T save_current_SID;
2844 static scid_T last_current_SID = 0;
2845 void *save_funccalp;
2846 int save_debug_break_level = debug_break_level;
2847 scriptitem_T *si = NULL;
2848 # ifdef UNIX
2849 struct stat st;
2850 int stat_ok;
2851 # endif
2852 #endif
2853 #ifdef STARTUPTIME
2854 struct timeval tv_rel;
2855 struct timeval tv_start;
2856 #endif
2857 #ifdef FEAT_PROFILE
2858 proftime_T wait_start;
2859 #endif
2861 #ifdef RISCOS
2862 p = mch_munge_fname(fname);
2863 #else
2864 p = expand_env_save(fname);
2865 #endif
2866 if (p == NULL)
2867 return retval;
2868 fname_exp = fix_fname(p);
2869 vim_free(p);
2870 if (fname_exp == NULL)
2871 return retval;
2872 if (mch_isdir(fname_exp))
2874 smsg((char_u *)_("Cannot source a directory: \"%s\""), fname);
2875 goto theend;
2878 #ifdef FEAT_AUTOCMD
2879 /* Apply SourceCmd autocommands, they should get the file and source it. */
2880 if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL)
2881 && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp,
2882 FALSE, curbuf))
2884 # ifdef FEAT_EVAL
2885 retval = aborting() ? FAIL : OK;
2886 # else
2887 retval = OK;
2888 # endif
2889 goto theend;
2892 /* Apply SourcePre autocommands, they may get the file. */
2893 apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, FALSE, curbuf);
2894 #endif
2896 #if defined(WIN32) && defined(FEAT_CSCOPE)
2897 cookie.fp = fopen_noinh_readbin((char *)fname_exp);
2898 #else
2899 cookie.fp = mch_fopen((char *)fname_exp, READBIN);
2900 #endif
2901 if (cookie.fp == NULL && check_other)
2904 * Try again, replacing file name ".vimrc" by "_vimrc" or vice versa,
2905 * and ".exrc" by "_exrc" or vice versa.
2907 p = gettail(fname_exp);
2908 if ((*p == '.' || *p == '_')
2909 && (STRICMP(p + 1, "vimrc") == 0
2910 || STRICMP(p + 1, "gvimrc") == 0
2911 || STRICMP(p + 1, "exrc") == 0))
2913 if (*p == '_')
2914 *p = '.';
2915 else
2916 *p = '_';
2917 #if defined(WIN32) && defined(FEAT_CSCOPE)
2918 cookie.fp = fopen_noinh_readbin((char *)fname_exp);
2919 #else
2920 cookie.fp = mch_fopen((char *)fname_exp, READBIN);
2921 #endif
2925 if (cookie.fp == NULL)
2927 if (p_verbose > 0)
2929 verbose_enter();
2930 if (sourcing_name == NULL)
2931 smsg((char_u *)_("could not source \"%s\""), fname);
2932 else
2933 smsg((char_u *)_("line %ld: could not source \"%s\""),
2934 sourcing_lnum, fname);
2935 verbose_leave();
2937 goto theend;
2941 * The file exists.
2942 * - In verbose mode, give a message.
2943 * - For a vimrc file, may want to set 'compatible', call vimrc_found().
2945 if (p_verbose > 1)
2947 verbose_enter();
2948 if (sourcing_name == NULL)
2949 smsg((char_u *)_("sourcing \"%s\""), fname);
2950 else
2951 smsg((char_u *)_("line %ld: sourcing \"%s\""),
2952 sourcing_lnum, fname);
2953 verbose_leave();
2955 if (is_vimrc == DOSO_VIMRC)
2956 vimrc_found(fname_exp, (char_u *)"MYVIMRC");
2957 else if (is_vimrc == DOSO_GVIMRC)
2958 vimrc_found(fname_exp, (char_u *)"MYGVIMRC");
2960 #ifdef USE_CRNL
2961 /* If no automatic file format: Set default to CR-NL. */
2962 if (*p_ffs == NUL)
2963 cookie.fileformat = EOL_DOS;
2964 else
2965 cookie.fileformat = EOL_UNKNOWN;
2966 cookie.error = FALSE;
2967 #endif
2969 #ifdef USE_CR
2970 /* If no automatic file format: Set default to CR. */
2971 if (*p_ffs == NUL)
2972 cookie.fileformat = EOL_MAC;
2973 else
2974 cookie.fileformat = EOL_UNKNOWN;
2975 cookie.error = FALSE;
2976 #endif
2978 cookie.nextline = NULL;
2979 cookie.finished = FALSE;
2981 #ifdef FEAT_EVAL
2983 * Check if this script has a breakpoint.
2985 cookie.breakpoint = dbg_find_breakpoint(TRUE, fname_exp, (linenr_T)0);
2986 cookie.fname = fname_exp;
2987 cookie.dbg_tick = debug_tick;
2989 cookie.level = ex_nesting_level;
2990 #endif
2993 * Keep the sourcing name/lnum, for recursive calls.
2995 save_sourcing_name = sourcing_name;
2996 sourcing_name = fname_exp;
2997 save_sourcing_lnum = sourcing_lnum;
2998 sourcing_lnum = 0;
3000 #ifdef FEAT_MBYTE
3001 cookie.conv.vc_type = CONV_NONE; /* no conversion */
3003 /* Read the first line so we can check for a UTF-8 BOM. */
3004 firstline = getsourceline(0, (void *)&cookie, 0);
3005 if (firstline != NULL && STRLEN(firstline) >= 3 && firstline[0] == 0xef
3006 && firstline[1] == 0xbb && firstline[2] == 0xbf)
3008 /* Found BOM; setup conversion, skip over BOM and recode the line. */
3009 convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc);
3010 p = string_convert(&cookie.conv, firstline + 3, NULL);
3011 if (p == NULL)
3012 p = vim_strsave(firstline + 3);
3013 if (p != NULL)
3015 vim_free(firstline);
3016 firstline = p;
3019 #endif
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(firstline, getsourceline, (void *)&cookie,
3115 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT);
3116 retval = OK;
3118 #ifdef FEAT_PROFILE
3119 if (do_profiling == PROF_YES)
3121 /* Get "si" again, "script_items" may have been reallocated. */
3122 si = &SCRIPT_ITEM(current_SID);
3123 if (si->sn_prof_on)
3125 profile_end(&si->sn_pr_start);
3126 profile_sub_wait(&wait_start, &si->sn_pr_start);
3127 profile_add(&si->sn_pr_total, &si->sn_pr_start);
3128 profile_self(&si->sn_pr_self, &si->sn_pr_start,
3129 &si->sn_pr_children);
3132 #endif
3134 if (got_int)
3135 EMSG(_(e_interr));
3136 sourcing_name = save_sourcing_name;
3137 sourcing_lnum = save_sourcing_lnum;
3138 if (p_verbose > 1)
3140 verbose_enter();
3141 smsg((char_u *)_("finished sourcing %s"), fname);
3142 if (sourcing_name != NULL)
3143 smsg((char_u *)_("continuing in %s"), sourcing_name);
3144 verbose_leave();
3146 #ifdef STARTUPTIME
3147 vim_snprintf((char *)IObuff, IOSIZE, "sourcing %s", fname);
3148 time_msg((char *)IObuff, &tv_start);
3149 time_pop(&tv_rel);
3150 #endif
3152 #ifdef FEAT_EVAL
3154 * After a "finish" in debug mode, need to break at first command of next
3155 * sourced file.
3157 if (save_debug_break_level > ex_nesting_level
3158 && debug_break_level == ex_nesting_level)
3159 ++debug_break_level;
3160 #endif
3162 #ifdef FEAT_EVAL
3163 almosttheend:
3164 current_SID = save_current_SID;
3165 restore_funccal(save_funccalp);
3166 # ifdef FEAT_PROFILE
3167 if (do_profiling == PROF_YES)
3168 prof_child_exit(&wait_start); /* leaving a child now */
3169 # endif
3170 #endif
3171 fclose(cookie.fp);
3172 vim_free(cookie.nextline);
3173 vim_free(firstline);
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 void
3189 ex_scriptnames(eap)
3190 exarg_T *eap UNUSED;
3192 int i;
3194 for (i = 1; i <= script_items.ga_len && !got_int; ++i)
3195 if (SCRIPT_ITEM(i).sn_name != NULL)
3196 smsg((char_u *)"%3d: %s", i, SCRIPT_ITEM(i).sn_name);
3199 # if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
3201 * Fix slashes in the list of script names for 'shellslash'.
3203 void
3204 scriptnames_slash_adjust()
3206 int i;
3208 for (i = 1; i <= script_items.ga_len; ++i)
3209 if (SCRIPT_ITEM(i).sn_name != NULL)
3210 slash_adjust(SCRIPT_ITEM(i).sn_name);
3212 # endif
3215 * Get a pointer to a script name. Used for ":verbose set".
3217 char_u *
3218 get_scriptname(id)
3219 scid_T id;
3221 if (id == SID_MODELINE)
3222 return (char_u *)_("modeline");
3223 if (id == SID_CMDARG)
3224 return (char_u *)_("--cmd argument");
3225 if (id == SID_CARG)
3226 return (char_u *)_("-c argument");
3227 if (id == SID_ENV)
3228 return (char_u *)_("environment variable");
3229 if (id == SID_ERROR)
3230 return (char_u *)_("error handler");
3231 return SCRIPT_ITEM(id).sn_name;
3234 # if defined(EXITFREE) || defined(PROTO)
3235 void
3236 free_scriptnames()
3238 int i;
3240 for (i = script_items.ga_len; i > 0; --i)
3241 vim_free(SCRIPT_ITEM(i).sn_name);
3242 ga_clear(&script_items);
3244 # endif
3246 #endif
3248 #if defined(USE_CR) || defined(PROTO)
3250 # if defined(__MSL__) && (__MSL__ >= 22)
3252 * Newer version of the Metrowerks library handle DOS and UNIX files
3253 * without help.
3254 * Test with earlier versions, MSL 2.2 is the library supplied with
3255 * Codewarrior Pro 2.
3257 char *
3258 fgets_cr(s, n, stream)
3259 char *s;
3260 int n;
3261 FILE *stream;
3263 return fgets(s, n, stream);
3265 # else
3267 * Version of fgets() which also works for lines ending in a <CR> only
3268 * (Macintosh format).
3269 * For older versions of the Metrowerks library.
3270 * At least CodeWarrior 9 needed this code.
3272 char *
3273 fgets_cr(s, n, stream)
3274 char *s;
3275 int n;
3276 FILE *stream;
3278 int c = 0;
3279 int char_read = 0;
3281 while (!feof(stream) && c != '\r' && c != '\n' && char_read < n - 1)
3283 c = fgetc(stream);
3284 s[char_read++] = c;
3285 /* If the file is in DOS format, we need to skip a NL after a CR. I
3286 * thought it was the other way around, but this appears to work... */
3287 if (c == '\n')
3289 c = fgetc(stream);
3290 if (c != '\r')
3291 ungetc(c, stream);
3295 s[char_read] = 0;
3296 if (char_read == 0)
3297 return NULL;
3299 if (feof(stream) && char_read == 1)
3300 return NULL;
3302 return s;
3304 # endif
3305 #endif
3308 * Get one full line from a sourced file.
3309 * Called by do_cmdline() when it's called from do_source().
3311 * Return a pointer to the line in allocated memory.
3312 * Return NULL for end-of-file or some error.
3314 char_u *
3315 getsourceline(c, cookie, indent)
3316 int c UNUSED;
3317 void *cookie;
3318 int indent UNUSED;
3320 struct source_cookie *sp = (struct source_cookie *)cookie;
3321 char_u *line;
3322 char_u *p, *s;
3324 #ifdef FEAT_EVAL
3325 /* If breakpoints have been added/deleted need to check for it. */
3326 if (sp->dbg_tick < debug_tick)
3328 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
3329 sp->dbg_tick = debug_tick;
3331 # ifdef FEAT_PROFILE
3332 if (do_profiling == PROF_YES)
3333 script_line_end();
3334 # endif
3335 #endif
3337 * Get current line. If there is a read-ahead line, use it, otherwise get
3338 * one now.
3340 if (sp->finished)
3341 line = NULL;
3342 else if (sp->nextline == NULL)
3343 line = get_one_sourceline(sp);
3344 else
3346 line = sp->nextline;
3347 sp->nextline = NULL;
3348 ++sourcing_lnum;
3350 #ifdef FEAT_PROFILE
3351 if (line != NULL && do_profiling == PROF_YES)
3352 script_line_start();
3353 #endif
3355 /* Only concatenate lines starting with a \ when 'cpoptions' doesn't
3356 * contain the 'C' flag. */
3357 if (line != NULL && (vim_strchr(p_cpo, CPO_CONCAT) == NULL))
3359 /* compensate for the one line read-ahead */
3360 --sourcing_lnum;
3361 for (;;)
3363 sp->nextline = get_one_sourceline(sp);
3364 if (sp->nextline == NULL)
3365 break;
3366 p = skipwhite(sp->nextline);
3367 if (*p != '\\')
3368 break;
3369 s = alloc((unsigned)(STRLEN(line) + STRLEN(p)));
3370 if (s == NULL) /* out of memory */
3371 break;
3372 STRCPY(s, line);
3373 STRCAT(s, p + 1);
3374 vim_free(line);
3375 line = s;
3376 vim_free(sp->nextline);
3380 #ifdef FEAT_MBYTE
3381 if (line != NULL && sp->conv.vc_type != CONV_NONE)
3383 /* Convert the encoding of the script line. */
3384 s = string_convert(&sp->conv, line, NULL);
3385 if (s != NULL)
3387 vim_free(line);
3388 line = s;
3391 #endif
3393 #ifdef FEAT_EVAL
3394 /* Did we encounter a breakpoint? */
3395 if (sp->breakpoint != 0 && sp->breakpoint <= sourcing_lnum)
3397 dbg_breakpoint(sp->fname, sourcing_lnum);
3398 /* Find next breakpoint. */
3399 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
3400 sp->dbg_tick = debug_tick;
3402 #endif
3404 return line;
3407 static char_u *
3408 get_one_sourceline(sp)
3409 struct source_cookie *sp;
3411 garray_T ga;
3412 int len;
3413 int c;
3414 char_u *buf;
3415 #ifdef USE_CRNL
3416 int has_cr; /* CR-LF found */
3417 #endif
3418 #ifdef USE_CR
3419 char_u *scan;
3420 #endif
3421 int have_read = FALSE;
3423 /* use a growarray to store the sourced line */
3424 ga_init2(&ga, 1, 250);
3427 * Loop until there is a finished line (or end-of-file).
3429 sourcing_lnum++;
3430 for (;;)
3432 /* make room to read at least 120 (more) characters */
3433 if (ga_grow(&ga, 120) == FAIL)
3434 break;
3435 buf = (char_u *)ga.ga_data;
3437 #ifdef USE_CR
3438 if (sp->fileformat == EOL_MAC)
3440 if (fgets_cr((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
3441 sp->fp) == NULL)
3442 break;
3444 else
3445 #endif
3446 if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
3447 sp->fp) == NULL)
3448 break;
3449 len = ga.ga_len + (int)STRLEN(buf + ga.ga_len);
3450 #ifdef USE_CRNL
3451 /* Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the
3452 * CTRL-Z by its own, or after a NL. */
3453 if ( (len == 1 || (len >= 2 && buf[len - 2] == '\n'))
3454 && sp->fileformat == EOL_DOS
3455 && buf[len - 1] == Ctrl_Z)
3457 buf[len - 1] = NUL;
3458 break;
3460 #endif
3462 #ifdef USE_CR
3463 /* If the read doesn't stop on a new line, and there's
3464 * some CR then we assume a Mac format */
3465 if (sp->fileformat == EOL_UNKNOWN)
3467 if (buf[len - 1] != '\n' && vim_strchr(buf, '\r') != NULL)
3468 sp->fileformat = EOL_MAC;
3469 else
3470 sp->fileformat = EOL_UNIX;
3473 if (sp->fileformat == EOL_MAC)
3475 scan = vim_strchr(buf, '\r');
3477 if (scan != NULL)
3479 *scan = '\n';
3480 if (*(scan + 1) != 0)
3482 *(scan + 1) = 0;
3483 fseek(sp->fp, (long)(scan - buf - len + 1), SEEK_CUR);
3486 len = STRLEN(buf);
3488 #endif
3490 have_read = TRUE;
3491 ga.ga_len = len;
3493 /* If the line was longer than the buffer, read more. */
3494 if (ga.ga_maxlen - ga.ga_len == 1 && buf[len - 1] != '\n')
3495 continue;
3497 if (len >= 1 && buf[len - 1] == '\n') /* remove trailing NL */
3499 #ifdef USE_CRNL
3500 has_cr = (len >= 2 && buf[len - 2] == '\r');
3501 if (sp->fileformat == EOL_UNKNOWN)
3503 if (has_cr)
3504 sp->fileformat = EOL_DOS;
3505 else
3506 sp->fileformat = EOL_UNIX;
3509 if (sp->fileformat == EOL_DOS)
3511 if (has_cr) /* replace trailing CR */
3513 buf[len - 2] = '\n';
3514 --len;
3515 --ga.ga_len;
3517 else /* lines like ":map xx yy^M" will have failed */
3519 if (!sp->error)
3521 msg_source(hl_attr(HLF_W));
3522 EMSG(_("W15: Warning: Wrong line separator, ^M may be missing"));
3524 sp->error = TRUE;
3525 sp->fileformat = EOL_UNIX;
3528 #endif
3529 /* The '\n' is escaped if there is an odd number of ^V's just
3530 * before it, first set "c" just before the 'V's and then check
3531 * len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo */
3532 for (c = len - 2; c >= 0 && buf[c] == Ctrl_V; c--)
3534 if ((len & 1) != (c & 1)) /* escaped NL, read more */
3536 sourcing_lnum++;
3537 continue;
3540 buf[len - 1] = NUL; /* remove the NL */
3544 * Check for ^C here now and then, so recursive :so can be broken.
3546 line_breakcheck();
3547 break;
3550 if (have_read)
3551 return (char_u *)ga.ga_data;
3553 vim_free(ga.ga_data);
3554 return NULL;
3557 #if defined(FEAT_PROFILE) || defined(PROTO)
3559 * Called when starting to read a script line.
3560 * "sourcing_lnum" must be correct!
3561 * When skipping lines it may not actually be executed, but we won't find out
3562 * until later and we need to store the time now.
3564 void
3565 script_line_start()
3567 scriptitem_T *si;
3568 sn_prl_T *pp;
3570 if (current_SID <= 0 || current_SID > script_items.ga_len)
3571 return;
3572 si = &SCRIPT_ITEM(current_SID);
3573 if (si->sn_prof_on && sourcing_lnum >= 1)
3575 /* Grow the array before starting the timer, so that the time spent
3576 * here isn't counted. */
3577 ga_grow(&si->sn_prl_ga, (int)(sourcing_lnum - si->sn_prl_ga.ga_len));
3578 si->sn_prl_idx = sourcing_lnum - 1;
3579 while (si->sn_prl_ga.ga_len <= si->sn_prl_idx
3580 && si->sn_prl_ga.ga_len < si->sn_prl_ga.ga_maxlen)
3582 /* Zero counters for a line that was not used before. */
3583 pp = &PRL_ITEM(si, si->sn_prl_ga.ga_len);
3584 pp->snp_count = 0;
3585 profile_zero(&pp->sn_prl_total);
3586 profile_zero(&pp->sn_prl_self);
3587 ++si->sn_prl_ga.ga_len;
3589 si->sn_prl_execed = FALSE;
3590 profile_start(&si->sn_prl_start);
3591 profile_zero(&si->sn_prl_children);
3592 profile_get_wait(&si->sn_prl_wait);
3597 * Called when actually executing a function line.
3599 void
3600 script_line_exec()
3602 scriptitem_T *si;
3604 if (current_SID <= 0 || current_SID > script_items.ga_len)
3605 return;
3606 si = &SCRIPT_ITEM(current_SID);
3607 if (si->sn_prof_on && si->sn_prl_idx >= 0)
3608 si->sn_prl_execed = TRUE;
3612 * Called when done with a function line.
3614 void
3615 script_line_end()
3617 scriptitem_T *si;
3618 sn_prl_T *pp;
3620 if (current_SID <= 0 || current_SID > script_items.ga_len)
3621 return;
3622 si = &SCRIPT_ITEM(current_SID);
3623 if (si->sn_prof_on && si->sn_prl_idx >= 0
3624 && si->sn_prl_idx < si->sn_prl_ga.ga_len)
3626 if (si->sn_prl_execed)
3628 pp = &PRL_ITEM(si, si->sn_prl_idx);
3629 ++pp->snp_count;
3630 profile_end(&si->sn_prl_start);
3631 profile_sub_wait(&si->sn_prl_wait, &si->sn_prl_start);
3632 profile_add(&pp->sn_prl_total, &si->sn_prl_start);
3633 profile_self(&pp->sn_prl_self, &si->sn_prl_start,
3634 &si->sn_prl_children);
3636 si->sn_prl_idx = -1;
3639 #endif
3642 * ":scriptencoding": Set encoding conversion for a sourced script.
3643 * Without the multi-byte feature it's simply ignored.
3645 void
3646 ex_scriptencoding(eap)
3647 exarg_T *eap UNUSED;
3649 #ifdef FEAT_MBYTE
3650 struct source_cookie *sp;
3651 char_u *name;
3653 if (!getline_equal(eap->getline, eap->cookie, getsourceline))
3655 EMSG(_("E167: :scriptencoding used outside of a sourced file"));
3656 return;
3659 if (*eap->arg != NUL)
3661 name = enc_canonize(eap->arg);
3662 if (name == NULL) /* out of memory */
3663 return;
3665 else
3666 name = eap->arg;
3668 /* Setup for conversion from the specified encoding to 'encoding'. */
3669 sp = (struct source_cookie *)getline_cookie(eap->getline, eap->cookie);
3670 convert_setup(&sp->conv, name, p_enc);
3672 if (name != eap->arg)
3673 vim_free(name);
3674 #endif
3677 #if defined(FEAT_EVAL) || defined(PROTO)
3679 * ":finish": Mark a sourced file as finished.
3681 void
3682 ex_finish(eap)
3683 exarg_T *eap;
3685 if (getline_equal(eap->getline, eap->cookie, getsourceline))
3686 do_finish(eap, FALSE);
3687 else
3688 EMSG(_("E168: :finish used outside of a sourced file"));
3692 * Mark a sourced file as finished. Possibly makes the ":finish" pending.
3693 * Also called for a pending finish at the ":endtry" or after returning from
3694 * an extra do_cmdline(). "reanimate" is used in the latter case.
3696 void
3697 do_finish(eap, reanimate)
3698 exarg_T *eap;
3699 int reanimate;
3701 int idx;
3703 if (reanimate)
3704 ((struct source_cookie *)getline_cookie(eap->getline,
3705 eap->cookie))->finished = FALSE;
3708 * Cleanup (and inactivate) conditionals, but stop when a try conditional
3709 * not in its finally clause (which then is to be executed next) is found.
3710 * In this case, make the ":finish" pending for execution at the ":endtry".
3711 * Otherwise, finish normally.
3713 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
3714 if (idx >= 0)
3716 eap->cstack->cs_pending[idx] = CSTP_FINISH;
3717 report_make_pending(CSTP_FINISH, NULL);
3719 else
3720 ((struct source_cookie *)getline_cookie(eap->getline,
3721 eap->cookie))->finished = TRUE;
3726 * Return TRUE when a sourced file had the ":finish" command: Don't give error
3727 * message for missing ":endif".
3728 * Return FALSE when not sourcing a file.
3731 source_finished(fgetline, cookie)
3732 char_u *(*fgetline) __ARGS((int, void *, int));
3733 void *cookie;
3735 return (getline_equal(fgetline, cookie, getsourceline)
3736 && ((struct source_cookie *)getline_cookie(
3737 fgetline, cookie))->finished);
3739 #endif
3741 #if defined(FEAT_LISTCMDS) || defined(PROTO)
3743 * ":checktime [buffer]"
3745 void
3746 ex_checktime(eap)
3747 exarg_T *eap;
3749 buf_T *buf;
3750 int save_no_check_timestamps = no_check_timestamps;
3752 no_check_timestamps = 0;
3753 if (eap->addr_count == 0) /* default is all buffers */
3754 check_timestamps(FALSE);
3755 else
3757 buf = buflist_findnr((int)eap->line2);
3758 if (buf != NULL) /* cannot happen? */
3759 (void)buf_check_timestamp(buf, FALSE);
3761 no_check_timestamps = save_no_check_timestamps;
3763 #endif
3765 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3766 && (defined(FEAT_EVAL) || defined(FEAT_MULTI_LANG))
3767 static char *get_locale_val __ARGS((int what));
3769 static char *
3770 get_locale_val(what)
3771 int what;
3773 char *loc;
3775 /* Obtain the locale value from the libraries. For DJGPP this is
3776 * redefined and it doesn't use the arguments. */
3777 loc = setlocale(what, NULL);
3779 # ifdef WIN32
3780 if (loc != NULL)
3782 char_u *p;
3784 /* setocale() returns something like "LC_COLLATE=<name>;LC_..." when
3785 * one of the values (e.g., LC_CTYPE) differs. */
3786 p = vim_strchr(loc, '=');
3787 if (p != NULL)
3789 loc = ++p;
3790 while (*p != NUL) /* remove trailing newline */
3792 if (*p < ' ' || *p == ';')
3794 *p = NUL;
3795 break;
3797 ++p;
3801 # endif
3803 return loc;
3805 #endif
3808 #ifdef WIN32
3810 * On MS-Windows locale names are strings like "German_Germany.1252", but
3811 * gettext expects "de". Try to translate one into another here for a few
3812 * supported languages.
3814 static char_u *
3815 gettext_lang(char_u *name)
3817 int i;
3818 static char *(mtable[]) = {
3819 "afrikaans", "af",
3820 "czech", "cs",
3821 "dutch", "nl",
3822 "german", "de",
3823 "english_united kingdom", "en_GB",
3824 "spanish", "es",
3825 "french", "fr",
3826 "italian", "it",
3827 "japanese", "ja",
3828 "korean", "ko",
3829 "norwegian", "no",
3830 "polish", "pl",
3831 "russian", "ru",
3832 "slovak", "sk",
3833 "swedish", "sv",
3834 "ukrainian", "uk",
3835 "chinese_china", "zh_CN",
3836 "chinese_taiwan", "zh_TW",
3837 NULL};
3839 for (i = 0; mtable[i] != NULL; i += 2)
3840 if (STRNICMP(mtable[i], name, STRLEN(mtable[i])) == 0)
3841 return mtable[i + 1];
3842 return name;
3844 #endif
3846 #if defined(FEAT_MULTI_LANG) || defined(PROTO)
3848 * Obtain the current messages language. Used to set the default for
3849 * 'helplang'. May return NULL or an empty string.
3851 char_u *
3852 get_mess_lang()
3854 char_u *p;
3856 # if (defined(HAVE_LOCALE_H) || defined(X_LOCALE))
3857 # if defined(LC_MESSAGES)
3858 p = (char_u *)get_locale_val(LC_MESSAGES);
3859 # else
3860 /* This is necessary for Win32, where LC_MESSAGES is not defined and $LANG
3861 * may be set to the LCID number. LC_COLLATE is the best guess, LC_TIME
3862 * and LC_MONETARY may be set differently for a Japanese working in the
3863 * US. */
3864 p = (char_u *)get_locale_val(LC_COLLATE);
3865 # endif
3866 # else
3867 p = mch_getenv((char_u *)"LC_ALL");
3868 if (p == NULL || *p == NUL)
3870 p = mch_getenv((char_u *)"LC_MESSAGES");
3871 if (p == NULL || *p == NUL)
3872 p = mch_getenv((char_u *)"LANG");
3874 # endif
3875 # ifdef WIN32
3876 p = gettext_lang(p);
3877 # endif
3878 return p;
3880 #endif
3882 /* Complicated #if; matches with where get_mess_env() is used below. */
3883 #if (defined(FEAT_EVAL) && !((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3884 && defined(LC_MESSAGES))) \
3885 || ((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3886 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)) \
3887 && !defined(LC_MESSAGES))
3888 static char_u *get_mess_env __ARGS((void));
3891 * Get the language used for messages from the environment.
3893 static char_u *
3894 get_mess_env()
3896 char_u *p;
3898 p = mch_getenv((char_u *)"LC_ALL");
3899 if (p == NULL || *p == NUL)
3901 p = mch_getenv((char_u *)"LC_MESSAGES");
3902 if (p == NULL || *p == NUL)
3904 p = mch_getenv((char_u *)"LANG");
3905 if (p != NULL && VIM_ISDIGIT(*p))
3906 p = NULL; /* ignore something like "1043" */
3907 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
3908 if (p == NULL || *p == NUL)
3909 p = (char_u *)get_locale_val(LC_CTYPE);
3910 # endif
3913 return p;
3915 #endif
3917 #if defined(FEAT_EVAL) || defined(PROTO)
3920 * Set the "v:lang" variable according to the current locale setting.
3921 * Also do "v:lc_time"and "v:ctype".
3923 void
3924 set_lang_var()
3926 char_u *loc;
3928 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
3929 loc = (char_u *)get_locale_val(LC_CTYPE);
3930 # else
3931 /* setlocale() not supported: use the default value */
3932 loc = (char_u *)"C";
3933 # endif
3934 set_vim_var_string(VV_CTYPE, loc, -1);
3936 /* When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall
3937 * back to LC_CTYPE if it's empty. */
3938 # if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) && defined(LC_MESSAGES)
3939 loc = (char_u *)get_locale_val(LC_MESSAGES);
3940 # else
3941 loc = get_mess_env();
3942 # endif
3943 set_vim_var_string(VV_LANG, loc, -1);
3945 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
3946 loc = (char_u *)get_locale_val(LC_TIME);
3947 # endif
3948 set_vim_var_string(VV_LC_TIME, loc, -1);
3950 #endif
3952 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3953 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE))
3955 * ":language": Set the language (locale).
3957 void
3958 ex_language(eap)
3959 exarg_T *eap;
3961 char *loc;
3962 char_u *p;
3963 char_u *name;
3964 int what = LC_ALL;
3965 char *whatstr = "";
3966 #ifdef LC_MESSAGES
3967 # define VIM_LC_MESSAGES LC_MESSAGES
3968 #else
3969 # define VIM_LC_MESSAGES 6789
3970 #endif
3972 name = eap->arg;
3974 /* Check for "messages {name}", "ctype {name}" or "time {name}" argument.
3975 * Allow abbreviation, but require at least 3 characters to avoid
3976 * confusion with a two letter language name "me" or "ct". */
3977 p = skiptowhite(eap->arg);
3978 if ((*p == NUL || vim_iswhite(*p)) && p - eap->arg >= 3)
3980 if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0)
3982 what = VIM_LC_MESSAGES;
3983 name = skipwhite(p);
3984 whatstr = "messages ";
3986 else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0)
3988 what = LC_CTYPE;
3989 name = skipwhite(p);
3990 whatstr = "ctype ";
3992 else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0)
3994 what = LC_TIME;
3995 name = skipwhite(p);
3996 whatstr = "time ";
4000 if (*name == NUL)
4002 #ifndef LC_MESSAGES
4003 if (what == VIM_LC_MESSAGES)
4004 p = get_mess_env();
4005 else
4006 #endif
4007 p = (char_u *)setlocale(what, NULL);
4008 if (p == NULL || *p == NUL)
4009 p = (char_u *)"Unknown";
4010 smsg((char_u *)_("Current %slanguage: \"%s\""), whatstr, p);
4012 else
4014 #ifndef LC_MESSAGES
4015 if (what == VIM_LC_MESSAGES)
4016 loc = "";
4017 else
4018 #endif
4020 loc = setlocale(what, (char *)name);
4021 #if defined(FEAT_FLOAT) && defined(LC_NUMERIC)
4022 /* Make sure strtod() uses a decimal point, not a comma. */
4023 setlocale(LC_NUMERIC, "C");
4024 #endif
4026 if (loc == NULL)
4027 EMSG2(_("E197: Cannot set language to \"%s\""), name);
4028 else
4030 #ifdef HAVE_NL_MSG_CAT_CNTR
4031 /* Need to do this for GNU gettext, otherwise cached translations
4032 * will be used again. */
4033 extern int _nl_msg_cat_cntr;
4035 ++_nl_msg_cat_cntr;
4036 #endif
4037 /* Reset $LC_ALL, otherwise it would overrule everything. */
4038 vim_setenv((char_u *)"LC_ALL", (char_u *)"");
4040 if (what != LC_TIME)
4042 /* Tell gettext() what to translate to. It apparently doesn't
4043 * use the currently effective locale. Also do this when
4044 * FEAT_GETTEXT isn't defined, so that shell commands use this
4045 * value. */
4046 if (what == LC_ALL)
4048 vim_setenv((char_u *)"LANG", name);
4049 # ifdef WIN32
4050 /* Apparently MS-Windows printf() may cause a crash when
4051 * we give it 8-bit text while it's expecting text in the
4052 * current locale. This call avoids that. */
4053 setlocale(LC_CTYPE, "C");
4054 # endif
4056 if (what != LC_CTYPE)
4058 char_u *mname;
4059 #ifdef WIN32
4060 mname = gettext_lang(name);
4061 #else
4062 mname = name;
4063 #endif
4064 vim_setenv((char_u *)"LC_MESSAGES", mname);
4065 #ifdef FEAT_MULTI_LANG
4066 set_helplang_default(mname);
4067 #endif
4070 /* Set $LC_CTYPE, because it overrules $LANG, and
4071 * gtk_set_locale() calls setlocale() again. gnome_init()
4072 * sets $LC_CTYPE to "en_US" (that's a bug!). */
4073 if (what != VIM_LC_MESSAGES)
4074 vim_setenv((char_u *)"LC_CTYPE", name);
4075 # ifdef FEAT_GUI_GTK
4076 /* Let GTK know what locale we're using. Not sure this is
4077 * really needed... */
4078 if (gui.in_use)
4079 (void)gtk_set_locale();
4080 # endif
4083 # ifdef FEAT_EVAL
4084 /* Set v:lang, v:lc_time and v:ctype to the final result. */
4085 set_lang_var();
4086 # endif
4091 # if defined(FEAT_CMDL_COMPL) || defined(PROTO)
4093 * Function given to ExpandGeneric() to obtain the possible arguments of the
4094 * ":language" command.
4096 char_u *
4097 get_lang_arg(xp, idx)
4098 expand_T *xp UNUSED;
4099 int idx;
4101 if (idx == 0)
4102 return (char_u *)"messages";
4103 if (idx == 1)
4104 return (char_u *)"ctype";
4105 if (idx == 2)
4106 return (char_u *)"time";
4107 return NULL;
4109 # endif
4111 #endif