1 /* vi:set ts=8 sts=4 sw=4 noet: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 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 */ 9 10 /* 11 * ex_cmds2.c: some more functions for command line commands 12 */ 13 14 #include "vim.h" 15 #include "version.h" 16 17 static void cmd_source(char_u *fname, exarg_T *eap); 18 19 #ifdef FEAT_EVAL 20 /* Growarray to store info about already sourced scripts. 21 * For Unix also store the dev/ino, so that we don't have to stat() each 22 * script when going through the list. */ 23 typedef struct scriptitem_S 24 { 25 char_u *sn_name; 26 # ifdef UNIX 27 int sn_dev_valid; 28 dev_t sn_dev; 29 ino_t sn_ino; 30 # endif 31 # ifdef FEAT_PROFILE 32 int sn_prof_on; /* TRUE when script is/was profiled */ 33 int sn_pr_force; /* forceit: profile functions in this script */ 34 proftime_T sn_pr_child; /* time set when going into first child */ 35 int sn_pr_nest; /* nesting for sn_pr_child */ 36 /* profiling the script as a whole */ 37 int sn_pr_count; /* nr of times sourced */ 38 proftime_T sn_pr_total; /* time spent in script + children */ 39 proftime_T sn_pr_self; /* time spent in script itself */ 40 proftime_T sn_pr_start; /* time at script start */ 41 proftime_T sn_pr_children; /* time in children after script start */ 42 /* profiling the script per line */ 43 garray_T sn_prl_ga; /* things stored for every line */ 44 proftime_T sn_prl_start; /* start time for current line */ 45 proftime_T sn_prl_children; /* time spent in children for this line */ 46 proftime_T sn_prl_wait; /* wait start time for current line */ 47 int sn_prl_idx; /* index of line being timed; -1 if none */ 48 int sn_prl_execed; /* line being timed was executed */ 49 # endif 50 } scriptitem_T; 51 52 static garray_T script_items = {0, 0, sizeof(scriptitem_T), 4, NULL}; 53 #define SCRIPT_ITEM(id) (((scriptitem_T *)script_items.ga_data)[(id) - 1]) 54 55 # ifdef FEAT_PROFILE 56 /* Struct used in sn_prl_ga for every line of a script. */ 57 typedef struct sn_prl_S 58 { 59 int snp_count; /* nr of times line was executed */ 60 proftime_T sn_prl_total; /* time spent in a line + children */ 61 proftime_T sn_prl_self; /* time spent in a line itself */ 62 } sn_prl_T; 63 64 # define PRL_ITEM(si, idx) (((sn_prl_T *)(si)->sn_prl_ga.ga_data)[(idx)]) 65 # endif 66 #endif 67 68 #if defined(FEAT_EVAL) || defined(PROTO) 69 static int debug_greedy = FALSE; /* batch mode debugging: don't save 70 and restore typeahead. */ 71 static int get_maxbacktrace_level(void); 72 static void do_setdebugtracelevel(char_u *arg); 73 static void do_checkbacktracelevel(void); 74 static void do_showbacktrace(char_u *cmd); 75 76 /* 77 * do_debug(): Debug mode. 78 * Repeatedly get Ex commands, until told to continue normal execution. 79 */ 80 void 81 do_debug(char_u *cmd) 82 { 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 int save_ex_normal_busy; 94 int n; 95 char_u *cmdline = NULL; 96 char_u *p; 97 char *tail = NULL; 98 static int last_cmd = 0; 99 #define CMD_CONT 1 100 #define CMD_NEXT 2 101 #define CMD_STEP 3 102 #define CMD_FINISH 4 103 #define CMD_QUIT 5 104 #define CMD_INTERRUPT 6 105 #define CMD_BACKTRACE 7 106 #define CMD_FRAME 8 107 #define CMD_UP 9 108 #define CMD_DOWN 10 109 110 #ifdef ALWAYS_USE_GUI 111 /* Can't do this when there is no terminal for input/output. */ 112 if (!gui.in_use) 113 { 114 /* Break as soon as possible. */ 115 debug_break_level = 9999; 116 return; 117 } 118 #endif 119 120 /* Make sure we are in raw mode and start termcap mode. Might have side 121 * effects... */ 122 settmode(TMODE_RAW); 123 starttermcap(); 124 125 ++RedrawingDisabled; /* don't redisplay the window */ 126 ++no_wait_return; /* don't wait for return */ 127 did_emsg = FALSE; /* don't use error from debugged stuff */ 128 cmd_silent = FALSE; /* display commands */ 129 msg_silent = FALSE; /* display messages */ 130 emsg_silent = FALSE; /* display error messages */ 131 redir_off = TRUE; /* don't redirect debug commands */ 132 133 State = NORMAL; 134 135 if (!debug_did_msg) 136 MSG(_("Entering Debug mode. Type \"cont\" to continue.")); 137 if (sourcing_name != NULL) 138 msg(sourcing_name); 139 if (sourcing_lnum != 0) 140 smsg((char_u *)_("line %ld: %s"), (long)sourcing_lnum, cmd); 141 else 142 smsg((char_u *)_("cmd: %s"), cmd); 143 144 /* 145 * Repeat getting a command and executing it. 146 */ 147 for (;;) 148 { 149 msg_scroll = TRUE; 150 need_wait_return = FALSE; 151 152 /* Save the current typeahead buffer and replace it with an empty one. 153 * This makes sure we get input from the user here and don't interfere 154 * with the commands being executed. Reset "ex_normal_busy" to avoid 155 * the side effects of using ":normal". Save the stuff buffer and make 156 * it empty. Set ignore_script to avoid reading from script input. */ 157 save_ex_normal_busy = ex_normal_busy; 158 ex_normal_busy = 0; 159 if (!debug_greedy) 160 { 161 save_typeahead(&typeaheadbuf); 162 typeahead_saved = TRUE; 163 save_ignore_script = ignore_script; 164 ignore_script = TRUE; 165 } 166 167 vim_free(cmdline); 168 cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL); 169 170 if (typeahead_saved) 171 { 172 restore_typeahead(&typeaheadbuf); 173 ignore_script = save_ignore_script; 174 } 175 ex_normal_busy = save_ex_normal_busy; 176 177 cmdline_row = msg_row; 178 msg_starthere(); 179 if (cmdline != NULL) 180 { 181 /* If this is a debug command, set "last_cmd". 182 * If not, reset "last_cmd". 183 * For a blank line use previous command. */ 184 p = skipwhite(cmdline); 185 if (*p != NUL) 186 { 187 switch (*p) 188 { 189 case 'c': last_cmd = CMD_CONT; 190 tail = "ont"; 191 break; 192 case 'n': last_cmd = CMD_NEXT; 193 tail = "ext"; 194 break; 195 case 's': last_cmd = CMD_STEP; 196 tail = "tep"; 197 break; 198 case 'f': 199 last_cmd = 0; 200 if (p[1] == 'r') 201 { 202 last_cmd = CMD_FRAME; 203 tail = "rame"; 204 } 205 else 206 { 207 last_cmd = CMD_FINISH; 208 tail = "inish"; 209 } 210 break; 211 case 'q': last_cmd = CMD_QUIT; 212 tail = "uit"; 213 break; 214 case 'i': last_cmd = CMD_INTERRUPT; 215 tail = "nterrupt"; 216 break; 217 case 'b': last_cmd = CMD_BACKTRACE; 218 if (p[1] == 't') 219 tail = "t"; 220 else 221 tail = "acktrace"; 222 break; 223 case 'w': last_cmd = CMD_BACKTRACE; 224 tail = "here"; 225 break; 226 case 'u': last_cmd = CMD_UP; 227 tail = "p"; 228 break; 229 case 'd': last_cmd = CMD_DOWN; 230 tail = "own"; 231 break; 232 default: last_cmd = 0; 233 } 234 if (last_cmd != 0) 235 { 236 /* Check that the tail matches. */ 237 ++p; 238 while (*p != NUL && *p == *tail) 239 { 240 ++p; 241 ++tail; 242 } 243 if (ASCII_ISALPHA(*p) && last_cmd != CMD_FRAME) 244 last_cmd = 0; 245 } 246 } 247 248 if (last_cmd != 0) 249 { 250 /* Execute debug command: decided where to break next and 251 * return. */ 252 switch (last_cmd) 253 { 254 case CMD_CONT: 255 debug_break_level = -1; 256 break; 257 case CMD_NEXT: 258 debug_break_level = ex_nesting_level; 259 break; 260 case CMD_STEP: 261 debug_break_level = 9999; 262 break; 263 case CMD_FINISH: 264 debug_break_level = ex_nesting_level - 1; 265 break; 266 case CMD_QUIT: 267 got_int = TRUE; 268 debug_break_level = -1; 269 break; 270 case CMD_INTERRUPT: 271 got_int = TRUE; 272 debug_break_level = 9999; 273 /* Do not repeat ">interrupt" cmd, continue stepping. */ 274 last_cmd = CMD_STEP; 275 break; 276 case CMD_BACKTRACE: 277 do_showbacktrace(cmd); 278 continue; 279 case CMD_FRAME: 280 if (*p == NUL) 281 { 282 do_showbacktrace(cmd); 283 } 284 else 285 { 286 p = skipwhite(p); 287 do_setdebugtracelevel(p); 288 } 289 continue; 290 case CMD_UP: 291 debug_backtrace_level++; 292 do_checkbacktracelevel(); 293 continue; 294 case CMD_DOWN: 295 debug_backtrace_level--; 296 do_checkbacktracelevel(); 297 continue; 298 } 299 /* Going out reset backtrace_level */ 300 debug_backtrace_level = 0; 301 break; 302 } 303 304 /* don't debug this command */ 305 n = debug_break_level; 306 debug_break_level = -1; 307 (void)do_cmdline(cmdline, getexline, NULL, 308 DOCMD_VERBOSE|DOCMD_EXCRESET); 309 debug_break_level = n; 310 } 311 lines_left = Rows - 1; 312 } 313 vim_free(cmdline); 314 315 --RedrawingDisabled; 316 --no_wait_return; 317 redraw_all_later(NOT_VALID); 318 need_wait_return = FALSE; 319 msg_scroll = save_msg_scroll; 320 lines_left = Rows - 1; 321 State = save_State; 322 did_emsg = save_did_emsg; 323 cmd_silent = save_cmd_silent; 324 msg_silent = save_msg_silent; 325 emsg_silent = save_emsg_silent; 326 redir_off = save_redir_off; 327 328 /* Only print the message again when typing a command before coming back 329 * here. */ 330 debug_did_msg = TRUE; 331 } 332 333 static int 334 get_maxbacktrace_level(void) 335 { 336 char *p, *q; 337 int maxbacktrace = 0; 338 339 if (sourcing_name != NULL) 340 { 341 p = (char *)sourcing_name; 342 while ((q = strstr(p, "..")) != NULL) 343 { 344 p = q + 2; 345 maxbacktrace++; 346 } 347 } 348 return maxbacktrace; 349 } 350 351 static void 352 do_setdebugtracelevel(char_u *arg) 353 { 354 int level; 355 356 level = atoi((char *)arg); 357 if (*arg == '+' || level < 0) 358 debug_backtrace_level += level; 359 else 360 debug_backtrace_level = level; 361 362 do_checkbacktracelevel(); 363 } 364 365 static void 366 do_checkbacktracelevel(void) 367 { 368 if (debug_backtrace_level < 0) 369 { 370 debug_backtrace_level = 0; 371 MSG(_("frame is zero")); 372 } 373 else 374 { 375 int max = get_maxbacktrace_level(); 376 377 if (debug_backtrace_level > max) 378 { 379 debug_backtrace_level = max; 380 smsg((char_u *)_("frame at highest level: %d"), max); 381 } 382 } 383 } 384 385 static void 386 do_showbacktrace(char_u *cmd) 387 { 388 char *cur; 389 char *next; 390 int i = 0; 391 int max = get_maxbacktrace_level(); 392 393 if (sourcing_name != NULL) 394 { 395 cur = (char *)sourcing_name; 396 while (!got_int) 397 { 398 next = strstr(cur, ".."); 399 if (next != NULL) 400 *next = NUL; 401 if (i == max - debug_backtrace_level) 402 smsg((char_u *)"->%d %s", max - i, cur); 403 else 404 smsg((char_u *)" %d %s", max - i, cur); 405 ++i; 406 if (next == NULL) 407 break; 408 *next = '.'; 409 cur = next + 2; 410 } 411 } 412 if (sourcing_lnum != 0) 413 smsg((char_u *)_("line %ld: %s"), (long)sourcing_lnum, cmd); 414 else 415 smsg((char_u *)_("cmd: %s"), cmd); 416 } 417 418 /* 419 * ":debug". 420 */ 421 void 422 ex_debug(exarg_T *eap) 423 { 424 int debug_break_level_save = debug_break_level; 425 426 debug_break_level = 9999; 427 do_cmdline_cmd(eap->arg); 428 debug_break_level = debug_break_level_save; 429 } 430 431 static char_u *debug_breakpoint_name = NULL; 432 static linenr_T debug_breakpoint_lnum; 433 434 /* 435 * When debugging or a breakpoint is set on a skipped command, no debug prompt 436 * is shown by do_one_cmd(). This situation is indicated by debug_skipped, and 437 * debug_skipped_name is then set to the source name in the breakpoint case. If 438 * a skipped command decides itself that a debug prompt should be displayed, it 439 * can do so by calling dbg_check_skipped(). 440 */ 441 static int debug_skipped; 442 static char_u *debug_skipped_name; 443 444 /* 445 * Go to debug mode when a breakpoint was encountered or "ex_nesting_level" is 446 * at or below the break level. But only when the line is actually 447 * executed. Return TRUE and set breakpoint_name for skipped commands that 448 * decide to execute something themselves. 449 * Called from do_one_cmd() before executing a command. 450 */ 451 void 452 dbg_check_breakpoint(exarg_T *eap) 453 { 454 char_u *p; 455 456 debug_skipped = FALSE; 457 if (debug_breakpoint_name != NULL) 458 { 459 if (!eap->skip) 460 { 461 /* replace K_SNR with "<SNR>" */ 462 if (debug_breakpoint_name[0] == K_SPECIAL 463 && debug_breakpoint_name[1] == KS_EXTRA 464 && debug_breakpoint_name[2] == (int)KE_SNR) 465 p = (char_u *)"<SNR>"; 466 else 467 p = (char_u *)""; 468 smsg((char_u *)_("Breakpoint in \"%s%s\" line %ld"), 469 p, 470 debug_breakpoint_name + (*p == NUL ? 0 : 3), 471 (long)debug_breakpoint_lnum); 472 debug_breakpoint_name = NULL; 473 do_debug(eap->cmd); 474 } 475 else 476 { 477 debug_skipped = TRUE; 478 debug_skipped_name = debug_breakpoint_name; 479 debug_breakpoint_name = NULL; 480 } 481 } 482 else if (ex_nesting_level <= debug_break_level) 483 { 484 if (!eap->skip) 485 do_debug(eap->cmd); 486 else 487 { 488 debug_skipped = TRUE; 489 debug_skipped_name = NULL; 490 } 491 } 492 } 493 494 /* 495 * Go to debug mode if skipped by dbg_check_breakpoint() because eap->skip was 496 * set. Return TRUE when the debug mode is entered this time. 497 */ 498 int 499 dbg_check_skipped(exarg_T *eap) 500 { 501 int prev_got_int; 502 503 if (debug_skipped) 504 { 505 /* 506 * Save the value of got_int and reset it. We don't want a previous 507 * interruption cause flushing the input buffer. 508 */ 509 prev_got_int = got_int; 510 got_int = FALSE; 511 debug_breakpoint_name = debug_skipped_name; 512 /* eap->skip is TRUE */ 513 eap->skip = FALSE; 514 (void)dbg_check_breakpoint(eap); 515 eap->skip = TRUE; 516 got_int |= prev_got_int; 517 return TRUE; 518 } 519 return FALSE; 520 } 521 522 /* 523 * The list of breakpoints: dbg_breakp. 524 * This is a grow-array of structs. 525 */ 526 struct debuggy 527 { 528 int dbg_nr; /* breakpoint number */ 529 int dbg_type; /* DBG_FUNC or DBG_FILE */ 530 char_u *dbg_name; /* function or file name */ 531 regprog_T *dbg_prog; /* regexp program */ 532 linenr_T dbg_lnum; /* line number in function or file */ 533 int dbg_forceit; /* ! used */ 534 }; 535 536 static garray_T dbg_breakp = {0, 0, sizeof(struct debuggy), 4, NULL}; 537 #define BREAKP(idx) (((struct debuggy *)dbg_breakp.ga_data)[idx]) 538 #define DEBUGGY(gap, idx) (((struct debuggy *)gap->ga_data)[idx]) 539 static int last_breakp = 0; /* nr of last defined breakpoint */ 540 541 #ifdef FEAT_PROFILE 542 /* Profiling uses file and func names similar to breakpoints. */ 543 static garray_T prof_ga = {0, 0, sizeof(struct debuggy), 4, NULL}; 544 #endif 545 #define DBG_FUNC 1 546 #define DBG_FILE 2 547 548 static int dbg_parsearg(char_u *arg, garray_T *gap); 549 static linenr_T debuggy_find(int file,char_u *fname, linenr_T after, garray_T *gap, int *fp); 550 551 /* 552 * Parse the arguments of ":profile", ":breakadd" or ":breakdel" and put them 553 * in the entry just after the last one in dbg_breakp. Note that "dbg_name" 554 * is allocated. 555 * Returns FAIL for failure. 556 */ 557 static int 558 dbg_parsearg( 559 char_u *arg, 560 garray_T *gap) /* either &dbg_breakp or &prof_ga */ 561 { 562 char_u *p = arg; 563 char_u *q; 564 struct debuggy *bp; 565 int here = FALSE; 566 567 if (ga_grow(gap, 1) == FAIL) 568 return FAIL; 569 bp = &DEBUGGY(gap, gap->ga_len); 570 571 /* Find "func" or "file". */ 572 if (STRNCMP(p, "func", 4) == 0) 573 bp->dbg_type = DBG_FUNC; 574 else if (STRNCMP(p, "file", 4) == 0) 575 bp->dbg_type = DBG_FILE; 576 else if ( 577 #ifdef FEAT_PROFILE 578 gap != &prof_ga && 579 #endif 580 STRNCMP(p, "here", 4) == 0) 581 { 582 if (curbuf->b_ffname == NULL) 583 { 584 EMSG(_(e_noname)); 585 return FAIL; 586 } 587 bp->dbg_type = DBG_FILE; 588 here = TRUE; 589 } 590 else 591 { 592 EMSG2(_(e_invarg2), p); 593 return FAIL; 594 } 595 p = skipwhite(p + 4); 596 597 /* Find optional line number. */ 598 if (here) 599 bp->dbg_lnum = curwin->w_cursor.lnum; 600 else if ( 601 #ifdef FEAT_PROFILE 602 gap != &prof_ga && 603 #endif 604 VIM_ISDIGIT(*p)) 605 { 606 bp->dbg_lnum = getdigits(&p); 607 p = skipwhite(p); 608 } 609 else 610 bp->dbg_lnum = 0; 611 612 /* Find the function or file name. Don't accept a function name with (). */ 613 if ((!here && *p == NUL) 614 || (here && *p != NUL) 615 || (bp->dbg_type == DBG_FUNC && strstr((char *)p, "()") != NULL)) 616 { 617 EMSG2(_(e_invarg2), arg); 618 return FAIL; 619 } 620 621 if (bp->dbg_type == DBG_FUNC) 622 bp->dbg_name = vim_strsave(p); 623 else if (here) 624 bp->dbg_name = vim_strsave(curbuf->b_ffname); 625 else 626 { 627 /* Expand the file name in the same way as do_source(). This means 628 * doing it twice, so that $DIR/file gets expanded when $DIR is 629 * "~/dir". */ 630 q = expand_env_save(p); 631 if (q == NULL) 632 return FAIL; 633 p = expand_env_save(q); 634 vim_free(q); 635 if (p == NULL) 636 return FAIL; 637 if (*p != '*') 638 { 639 bp->dbg_name = fix_fname(p); 640 vim_free(p); 641 } 642 else 643 bp->dbg_name = p; 644 } 645 646 if (bp->dbg_name == NULL) 647 return FAIL; 648 return OK; 649 } 650 651 /* 652 * ":breakadd". 653 */ 654 void 655 ex_breakadd(exarg_T *eap) 656 { 657 struct debuggy *bp; 658 char_u *pat; 659 garray_T *gap; 660 661 gap = &dbg_breakp; 662 #ifdef FEAT_PROFILE 663 if (eap->cmdidx == CMD_profile) 664 gap = &prof_ga; 665 #endif 666 667 if (dbg_parsearg(eap->arg, gap) == OK) 668 { 669 bp = &DEBUGGY(gap, gap->ga_len); 670 bp->dbg_forceit = eap->forceit; 671 672 pat = file_pat_to_reg_pat(bp->dbg_name, NULL, NULL, FALSE); 673 if (pat != NULL) 674 { 675 bp->dbg_prog = vim_regcomp(pat, RE_MAGIC + RE_STRING); 676 vim_free(pat); 677 } 678 if (pat == NULL || bp->dbg_prog == NULL) 679 vim_free(bp->dbg_name); 680 else 681 { 682 if (bp->dbg_lnum == 0) /* default line number is 1 */ 683 bp->dbg_lnum = 1; 684 #ifdef FEAT_PROFILE 685 if (eap->cmdidx != CMD_profile) 686 #endif 687 { 688 DEBUGGY(gap, gap->ga_len).dbg_nr = ++last_breakp; 689 ++debug_tick; 690 } 691 ++gap->ga_len; 692 } 693 } 694 } 695 696 /* 697 * ":debuggreedy". 698 */ 699 void 700 ex_debuggreedy(exarg_T *eap) 701 { 702 if (eap->addr_count == 0 || eap->line2 != 0) 703 debug_greedy = TRUE; 704 else 705 debug_greedy = FALSE; 706 } 707 708 /* 709 * ":breakdel" and ":profdel". 710 */ 711 void 712 ex_breakdel(exarg_T *eap) 713 { 714 struct debuggy *bp, *bpi; 715 int nr; 716 int todel = -1; 717 int del_all = FALSE; 718 int i; 719 linenr_T best_lnum = 0; 720 garray_T *gap; 721 722 gap = &dbg_breakp; 723 if (eap->cmdidx == CMD_profdel) 724 { 725 #ifdef FEAT_PROFILE 726 gap = &prof_ga; 727 #else 728 ex_ni(eap); 729 return; 730 #endif 731 } 732 733 if (vim_isdigit(*eap->arg)) 734 { 735 /* ":breakdel {nr}" */ 736 nr = atol((char *)eap->arg); 737 for (i = 0; i < gap->ga_len; ++i) 738 if (DEBUGGY(gap, i).dbg_nr == nr) 739 { 740 todel = i; 741 break; 742 } 743 } 744 else if (*eap->arg == '*') 745 { 746 todel = 0; 747 del_all = TRUE; 748 } 749 else 750 { 751 /* ":breakdel {func|file} [lnum] {name}" */ 752 if (dbg_parsearg(eap->arg, gap) == FAIL) 753 return; 754 bp = &DEBUGGY(gap, gap->ga_len); 755 for (i = 0; i < gap->ga_len; ++i) 756 { 757 bpi = &DEBUGGY(gap, i); 758 if (bp->dbg_type == bpi->dbg_type 759 && STRCMP(bp->dbg_name, bpi->dbg_name) == 0 760 && (bp->dbg_lnum == bpi->dbg_lnum 761 || (bp->dbg_lnum == 0 762 && (best_lnum == 0 763 || bpi->dbg_lnum < best_lnum)))) 764 { 765 todel = i; 766 best_lnum = bpi->dbg_lnum; 767 } 768 } 769 vim_free(bp->dbg_name); 770 } 771 772 if (todel < 0) 773 EMSG2(_("E161: Breakpoint not found: %s"), eap->arg); 774 else 775 { 776 while (gap->ga_len > 0) 777 { 778 vim_free(DEBUGGY(gap, todel).dbg_name); 779 vim_regfree(DEBUGGY(gap, todel).dbg_prog); 780 --gap->ga_len; 781 if (todel < gap->ga_len) 782 mch_memmove(&DEBUGGY(gap, todel), &DEBUGGY(gap, todel + 1), 783 (gap->ga_len - todel) * sizeof(struct debuggy)); 784 #ifdef FEAT_PROFILE 785 if (eap->cmdidx == CMD_breakdel) 786 #endif 787 ++debug_tick; 788 if (!del_all) 789 break; 790 } 791 792 /* If all breakpoints were removed clear the array. */ 793 if (gap->ga_len == 0) 794 ga_clear(gap); 795 } 796 } 797 798 /* 799 * ":breaklist". 800 */ 801 void 802 ex_breaklist(exarg_T *eap UNUSED) 803 { 804 struct debuggy *bp; 805 int i; 806 807 if (dbg_breakp.ga_len == 0) 808 MSG(_("No breakpoints defined")); 809 else 810 for (i = 0; i < dbg_breakp.ga_len; ++i) 811 { 812 bp = &BREAKP(i); 813 if (bp->dbg_type == DBG_FILE) 814 home_replace(NULL, bp->dbg_name, NameBuff, MAXPATHL, TRUE); 815 smsg((char_u *)_("%3d %s %s line %ld"), 816 bp->dbg_nr, 817 bp->dbg_type == DBG_FUNC ? "func" : "file", 818 bp->dbg_type == DBG_FUNC ? bp->dbg_name : NameBuff, 819 (long)bp->dbg_lnum); 820 } 821 } 822 823 /* 824 * Find a breakpoint for a function or sourced file. 825 * Returns line number at which to break; zero when no matching breakpoint. 826 */ 827 linenr_T 828 dbg_find_breakpoint( 829 int file, /* TRUE for a file, FALSE for a function */ 830 char_u *fname, /* file or function name */ 831 linenr_T after) /* after this line number */ 832 { 833 return debuggy_find(file, fname, after, &dbg_breakp, NULL); 834 } 835 836 #if defined(FEAT_PROFILE) || defined(PROTO) 837 /* 838 * Return TRUE if profiling is on for a function or sourced file. 839 */ 840 int 841 has_profiling( 842 int file, /* TRUE for a file, FALSE for a function */ 843 char_u *fname, /* file or function name */ 844 int *fp) /* return: forceit */ 845 { 846 return (debuggy_find(file, fname, (linenr_T)0, &prof_ga, fp) 847 != (linenr_T)0); 848 } 849 #endif 850 851 /* 852 * Common code for dbg_find_breakpoint() and has_profiling(). 853 */ 854 static linenr_T 855 debuggy_find( 856 int file, /* TRUE for a file, FALSE for a function */ 857 char_u *fname, /* file or function name */ 858 linenr_T after, /* after this line number */ 859 garray_T *gap, /* either &dbg_breakp or &prof_ga */ 860 int *fp) /* if not NULL: return forceit */ 861 { 862 struct debuggy *bp; 863 int i; 864 linenr_T lnum = 0; 865 char_u *name = fname; 866 int prev_got_int; 867 868 /* Return quickly when there are no breakpoints. */ 869 if (gap->ga_len == 0) 870 return (linenr_T)0; 871 872 /* Replace K_SNR in function name with "<SNR>". */ 873 if (!file && fname[0] == K_SPECIAL) 874 { 875 name = alloc((unsigned)STRLEN(fname) + 3); 876 if (name == NULL) 877 name = fname; 878 else 879 { 880 STRCPY(name, "<SNR>"); 881 STRCPY(name + 5, fname + 3); 882 } 883 } 884 885 for (i = 0; i < gap->ga_len; ++i) 886 { 887 /* Skip entries that are not useful or are for a line that is beyond 888 * an already found breakpoint. */ 889 bp = &DEBUGGY(gap, i); 890 if (((bp->dbg_type == DBG_FILE) == file && ( 891 #ifdef FEAT_PROFILE 892 gap == &prof_ga || 893 #endif 894 (bp->dbg_lnum > after && (lnum == 0 || bp->dbg_lnum < lnum))))) 895 { 896 /* 897 * Save the value of got_int and reset it. We don't want a 898 * previous interruption cancel matching, only hitting CTRL-C 899 * while matching should abort it. 900 */ 901 prev_got_int = got_int; 902 got_int = FALSE; 903 if (vim_regexec_prog(&bp->dbg_prog, FALSE, name, (colnr_T)0)) 904 { 905 lnum = bp->dbg_lnum; 906 if (fp != NULL) 907 *fp = bp->dbg_forceit; 908 } 909 got_int |= prev_got_int; 910 } 911 } 912 if (name != fname) 913 vim_free(name); 914 915 return lnum; 916 } 917 918 /* 919 * Called when a breakpoint was encountered. 920 */ 921 void 922 dbg_breakpoint(char_u *name, linenr_T lnum) 923 { 924 /* We need to check if this line is actually executed in do_one_cmd() */ 925 debug_breakpoint_name = name; 926 debug_breakpoint_lnum = lnum; 927 } 928 929 930 # if defined(FEAT_PROFILE) || defined(FEAT_RELTIME) || defined(PROTO) 931 /* 932 * Store the current time in "tm". 933 */ 934 void 935 profile_start(proftime_T *tm) 936 { 937 # ifdef WIN3264 938 QueryPerformanceCounter(tm); 939 # else 940 gettimeofday(tm, NULL); 941 # endif 942 } 943 944 /* 945 * Compute the elapsed time from "tm" till now and store in "tm". 946 */ 947 void 948 profile_end(proftime_T *tm) 949 { 950 proftime_T now; 951 952 # ifdef WIN3264 953 QueryPerformanceCounter(&now); 954 tm->QuadPart = now.QuadPart - tm->QuadPart; 955 # else 956 gettimeofday(&now, NULL); 957 tm->tv_usec = now.tv_usec - tm->tv_usec; 958 tm->tv_sec = now.tv_sec - tm->tv_sec; 959 if (tm->tv_usec < 0) 960 { 961 tm->tv_usec += 1000000; 962 --tm->tv_sec; 963 } 964 # endif 965 } 966 967 /* 968 * Subtract the time "tm2" from "tm". 969 */ 970 void 971 profile_sub(proftime_T *tm, proftime_T *tm2) 972 { 973 # ifdef WIN3264 974 tm->QuadPart -= tm2->QuadPart; 975 # else 976 tm->tv_usec -= tm2->tv_usec; 977 tm->tv_sec -= tm2->tv_sec; 978 if (tm->tv_usec < 0) 979 { 980 tm->tv_usec += 1000000; 981 --tm->tv_sec; 982 } 983 # endif 984 } 985 986 /* 987 * Return a string that represents the time in "tm". 988 * Uses a static buffer! 989 */ 990 char * 991 profile_msg(proftime_T *tm) 992 { 993 static char buf[50]; 994 995 # ifdef WIN3264 996 LARGE_INTEGER fr; 997 998 QueryPerformanceFrequency(&fr); 999 sprintf(buf, "%10.6lf", (double)tm->QuadPart / (double)fr.QuadPart); 1000 # else 1001 sprintf(buf, "%3ld.%06ld", (long)tm->tv_sec, (long)tm->tv_usec); 1002 # endif 1003 return buf; 1004 } 1005 1006 # if defined(FEAT_FLOAT) || defined(PROTO) 1007 /* 1008 * Return a float that represents the time in "tm". 1009 */ 1010 float_T 1011 profile_float(proftime_T *tm) 1012 { 1013 # ifdef WIN3264 1014 LARGE_INTEGER fr; 1015 1016 QueryPerformanceFrequency(&fr); 1017 return (float_T)tm->QuadPart / (float_T)fr.QuadPart; 1018 # else 1019 return (float_T)tm->tv_sec + (float_T)tm->tv_usec / 1000000.0; 1020 # endif 1021 } 1022 # endif 1023 1024 /* 1025 * Put the time "msec" past now in "tm". 1026 */ 1027 void 1028 profile_setlimit(long msec, proftime_T *tm) 1029 { 1030 if (msec <= 0) /* no limit */ 1031 profile_zero(tm); 1032 else 1033 { 1034 # ifdef WIN3264 1035 LARGE_INTEGER fr; 1036 1037 QueryPerformanceCounter(tm); 1038 QueryPerformanceFrequency(&fr); 1039 tm->QuadPart += (LONGLONG)((double)msec / 1000.0 * (double)fr.QuadPart); 1040 # else 1041 long usec; 1042 1043 gettimeofday(tm, NULL); 1044 usec = (long)tm->tv_usec + (long)msec * 1000; 1045 tm->tv_usec = usec % 1000000L; 1046 tm->tv_sec += usec / 1000000L; 1047 # endif 1048 } 1049 } 1050 1051 /* 1052 * Return TRUE if the current time is past "tm". 1053 */ 1054 int 1055 profile_passed_limit(proftime_T *tm) 1056 { 1057 proftime_T now; 1058 1059 # ifdef WIN3264 1060 if (tm->QuadPart == 0) /* timer was not set */ 1061 return FALSE; 1062 QueryPerformanceCounter(&now); 1063 return (now.QuadPart > tm->QuadPart); 1064 # else 1065 if (tm->tv_sec == 0) /* timer was not set */ 1066 return FALSE; 1067 gettimeofday(&now, NULL); 1068 return (now.tv_sec > tm->tv_sec 1069 || (now.tv_sec == tm->tv_sec && now.tv_usec > tm->tv_usec)); 1070 # endif 1071 } 1072 1073 /* 1074 * Set the time in "tm" to zero. 1075 */ 1076 void 1077 profile_zero(proftime_T *tm) 1078 { 1079 # ifdef WIN3264 1080 tm->QuadPart = 0; 1081 # else 1082 tm->tv_usec = 0; 1083 tm->tv_sec = 0; 1084 # endif 1085 } 1086 1087 # endif /* FEAT_PROFILE || FEAT_RELTIME */ 1088 1089 # if defined(FEAT_TIMERS) || defined(PROTO) 1090 static timer_T *first_timer = NULL; 1091 static long last_timer_id = 0; 1092 1093 # ifdef WIN3264 1094 # define GET_TIMEDIFF(timer, now) \ 1095 (long)(((double)(timer->tr_due.QuadPart - now.QuadPart) \ 1096 / (double)fr.QuadPart) * 1000); 1097 # else 1098 # define GET_TIMEDIFF(timer, now) \ 1099 (timer->tr_due.tv_sec - now.tv_sec) * 1000 \ 1100 + (timer->tr_due.tv_usec - now.tv_usec) / 1000; 1101 # endif 1102 1103 /* 1104 * Insert a timer in the list of timers. 1105 */ 1106 static void 1107 insert_timer(timer_T *timer) 1108 { 1109 timer->tr_next = first_timer; 1110 timer->tr_prev = NULL; 1111 if (first_timer != NULL) 1112 first_timer->tr_prev = timer; 1113 first_timer = timer; 1114 did_add_timer = TRUE; 1115 } 1116 1117 /* 1118 * Take a timer out of the list of timers. 1119 */ 1120 static void 1121 remove_timer(timer_T *timer) 1122 { 1123 if (timer->tr_prev == NULL) 1124 first_timer = timer->tr_next; 1125 else 1126 timer->tr_prev->tr_next = timer->tr_next; 1127 if (timer->tr_next != NULL) 1128 timer->tr_next->tr_prev = timer->tr_prev; 1129 } 1130 1131 static void 1132 free_timer(timer_T *timer) 1133 { 1134 free_callback(timer->tr_callback, timer->tr_partial); 1135 vim_free(timer); 1136 } 1137 1138 /* 1139 * Create a timer and return it. NULL if out of memory. 1140 * Caller should set the callback. 1141 */ 1142 timer_T * 1143 create_timer(long msec, int repeat) 1144 { 1145 timer_T *timer = (timer_T *)alloc_clear(sizeof(timer_T)); 1146 long prev_id = last_timer_id; 1147 1148 if (timer == NULL) 1149 return NULL; 1150 if (++last_timer_id <= prev_id) 1151 /* Overflow! Might cause duplicates... */ 1152 last_timer_id = 0; 1153 timer->tr_id = last_timer_id; 1154 insert_timer(timer); 1155 if (repeat != 0) 1156 timer->tr_repeat = repeat - 1; 1157 timer->tr_interval = msec; 1158 1159 profile_setlimit(msec, &timer->tr_due); 1160 return timer; 1161 } 1162 1163 /* 1164 * Invoke the callback of "timer". 1165 */ 1166 static void 1167 timer_callback(timer_T *timer) 1168 { 1169 typval_T rettv; 1170 int dummy; 1171 typval_T argv[2]; 1172 1173 argv[0].v_type = VAR_NUMBER; 1174 argv[0].vval.v_number = (varnumber_T)timer->tr_id; 1175 argv[1].v_type = VAR_UNKNOWN; 1176 1177 call_func(timer->tr_callback, (int)STRLEN(timer->tr_callback), 1178 &rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE, 1179 timer->tr_partial, NULL); 1180 clear_tv(&rettv); 1181 } 1182 1183 /* 1184 * Call timers that are due. 1185 * Return the time in msec until the next timer is due. 1186 */ 1187 long 1188 check_due_timer(void) 1189 { 1190 timer_T *timer; 1191 timer_T *timer_next; 1192 long this_due; 1193 long next_due = -1; 1194 proftime_T now; 1195 int did_one = FALSE; 1196 long current_id = last_timer_id; 1197 # ifdef WIN3264 1198 LARGE_INTEGER fr; 1199 1200 QueryPerformanceFrequency(&fr); 1201 # endif 1202 profile_start(&now); 1203 for (timer = first_timer; timer != NULL && !got_int; timer = timer_next) 1204 { 1205 timer_next = timer->tr_next; 1206 1207 if (timer->tr_id == -1 || timer->tr_firing || timer->tr_paused) 1208 continue; 1209 this_due = GET_TIMEDIFF(timer, now); 1210 if (this_due <= 1) 1211 { 1212 timer->tr_firing = TRUE; 1213 timer_callback(timer); 1214 timer->tr_firing = FALSE; 1215 timer_next = timer->tr_next; 1216 did_one = TRUE; 1217 1218 /* Only fire the timer again if it repeats and stop_timer() wasn't 1219 * called while inside the callback (tr_id == -1). */ 1220 if (timer->tr_repeat != 0 && timer->tr_id != -1) 1221 { 1222 profile_setlimit(timer->tr_interval, &timer->tr_due); 1223 this_due = GET_TIMEDIFF(timer, now); 1224 if (this_due < 1) 1225 this_due = 1; 1226 if (timer->tr_repeat > 0) 1227 --timer->tr_repeat; 1228 } 1229 else 1230 { 1231 this_due = -1; 1232 remove_timer(timer); 1233 free_timer(timer); 1234 } 1235 } 1236 if (this_due > 0 && (next_due == -1 || next_due > this_due)) 1237 next_due = this_due; 1238 } 1239 1240 if (did_one) 1241 redraw_after_callback(); 1242 1243 return current_id != last_timer_id ? 1 : next_due; 1244 } 1245 1246 /* 1247 * Find a timer by ID. Returns NULL if not found; 1248 */ 1249 timer_T * 1250 find_timer(long id) 1251 { 1252 timer_T *timer; 1253 1254 if (id >= 0) 1255 { 1256 for (timer = first_timer; timer != NULL; timer = timer->tr_next) 1257 if (timer->tr_id == id) 1258 return timer; 1259 } 1260 return NULL; 1261 } 1262 1263 1264 /* 1265 * Stop a timer and delete it. 1266 */ 1267 void 1268 stop_timer(timer_T *timer) 1269 { 1270 if (timer->tr_firing) 1271 /* Free the timer after the callback returns. */ 1272 timer->tr_id = -1; 1273 else 1274 { 1275 remove_timer(timer); 1276 free_timer(timer); 1277 } 1278 } 1279 1280 void 1281 stop_all_timers(void) 1282 { 1283 timer_T *timer; 1284 timer_T *timer_next; 1285 1286 for (timer = first_timer; timer != NULL; timer = timer_next) 1287 { 1288 timer_next = timer->tr_next; 1289 stop_timer(timer); 1290 } 1291 } 1292 1293 void 1294 add_timer_info(typval_T *rettv, timer_T *timer) 1295 { 1296 list_T *list = rettv->vval.v_list; 1297 dict_T *dict = dict_alloc(); 1298 dictitem_T *di; 1299 long remaining; 1300 proftime_T now; 1301 # ifdef WIN3264 1302 LARGE_INTEGER fr; 1303 #endif 1304 1305 if (dict == NULL) 1306 return; 1307 list_append_dict(list, dict); 1308 1309 dict_add_nr_str(dict, "id", timer->tr_id, NULL); 1310 dict_add_nr_str(dict, "time", (long)timer->tr_interval, NULL); 1311 1312 profile_start(&now); 1313 # ifdef WIN3264 1314 QueryPerformanceFrequency(&fr); 1315 # endif 1316 remaining = GET_TIMEDIFF(timer, now); 1317 dict_add_nr_str(dict, "remaining", (long)remaining, NULL); 1318 1319 dict_add_nr_str(dict, "repeat", 1320 (long)(timer->tr_repeat < 0 ? -1 : timer->tr_repeat + 1), NULL); 1321 dict_add_nr_str(dict, "paused", (long)(timer->tr_paused), NULL); 1322 1323 di = dictitem_alloc((char_u *)"callback"); 1324 if (di != NULL) 1325 { 1326 if (dict_add(dict, di) == FAIL) 1327 vim_free(di); 1328 else if (timer->tr_partial != NULL) 1329 { 1330 di->di_tv.v_type = VAR_PARTIAL; 1331 di->di_tv.vval.v_partial = timer->tr_partial; 1332 ++timer->tr_partial->pt_refcount; 1333 } 1334 else 1335 { 1336 di->di_tv.v_type = VAR_FUNC; 1337 di->di_tv.vval.v_string = vim_strsave(timer->tr_callback); 1338 } 1339 di->di_tv.v_lock = 0; 1340 } 1341 } 1342 1343 void 1344 add_timer_info_all(typval_T *rettv) 1345 { 1346 timer_T *timer; 1347 1348 for (timer = first_timer; timer != NULL; timer = timer->tr_next) 1349 if (timer->tr_id != -1) 1350 add_timer_info(rettv, timer); 1351 } 1352 1353 /* 1354 * Mark references in partials of timers. 1355 */ 1356 int 1357 set_ref_in_timer(int copyID) 1358 { 1359 int abort = FALSE; 1360 timer_T *timer; 1361 typval_T tv; 1362 1363 for (timer = first_timer; timer != NULL; timer = timer->tr_next) 1364 { 1365 if (timer->tr_partial != NULL) 1366 { 1367 tv.v_type = VAR_PARTIAL; 1368 tv.vval.v_partial = timer->tr_partial; 1369 } 1370 else 1371 { 1372 tv.v_type = VAR_FUNC; 1373 tv.vval.v_string = timer->tr_callback; 1374 } 1375 abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL); 1376 } 1377 return abort; 1378 } 1379 1380 # if defined(EXITFREE) || defined(PROTO) 1381 void 1382 timer_free_all() 1383 { 1384 timer_T *timer; 1385 1386 while (first_timer != NULL) 1387 { 1388 timer = first_timer; 1389 remove_timer(timer); 1390 free_timer(timer); 1391 } 1392 } 1393 # endif 1394 # endif 1395 1396 #if defined(FEAT_SYN_HL) && defined(FEAT_RELTIME) && defined(FEAT_FLOAT) 1397 # if defined(HAVE_MATH_H) 1398 # include <math.h> 1399 # endif 1400 1401 /* 1402 * Divide the time "tm" by "count" and store in "tm2". 1403 */ 1404 void 1405 profile_divide(proftime_T *tm, int count, proftime_T *tm2) 1406 { 1407 if (count == 0) 1408 profile_zero(tm2); 1409 else 1410 { 1411 # ifdef WIN3264 1412 tm2->QuadPart = tm->QuadPart / count; 1413 # else 1414 double usec = (tm->tv_sec * 1000000.0 + tm->tv_usec) / count; 1415 1416 tm2->tv_sec = floor(usec / 1000000.0); 1417 tm2->tv_usec = vim_round(usec - (tm2->tv_sec * 1000000.0)); 1418 # endif 1419 } 1420 } 1421 #endif 1422 1423 # if defined(FEAT_PROFILE) || defined(PROTO) 1424 /* 1425 * Functions for profiling. 1426 */ 1427 static void script_do_profile(scriptitem_T *si); 1428 static void script_dump_profile(FILE *fd); 1429 static proftime_T prof_wait_time; 1430 1431 /* 1432 * Add the time "tm2" to "tm". 1433 */ 1434 void 1435 profile_add(proftime_T *tm, proftime_T *tm2) 1436 { 1437 # ifdef WIN3264 1438 tm->QuadPart += tm2->QuadPart; 1439 # else 1440 tm->tv_usec += tm2->tv_usec; 1441 tm->tv_sec += tm2->tv_sec; 1442 if (tm->tv_usec >= 1000000) 1443 { 1444 tm->tv_usec -= 1000000; 1445 ++tm->tv_sec; 1446 } 1447 # endif 1448 } 1449 1450 /* 1451 * Add the "self" time from the total time and the children's time. 1452 */ 1453 void 1454 profile_self(proftime_T *self, proftime_T *total, proftime_T *children) 1455 { 1456 /* Check that the result won't be negative. Can happen with recursive 1457 * calls. */ 1458 #ifdef WIN3264 1459 if (total->QuadPart <= children->QuadPart) 1460 return; 1461 #else 1462 if (total->tv_sec < children->tv_sec 1463 || (total->tv_sec == children->tv_sec 1464 && total->tv_usec <= children->tv_usec)) 1465 return; 1466 #endif 1467 profile_add(self, total); 1468 profile_sub(self, children); 1469 } 1470 1471 /* 1472 * Get the current waittime. 1473 */ 1474 void 1475 profile_get_wait(proftime_T *tm) 1476 { 1477 *tm = prof_wait_time; 1478 } 1479 1480 /* 1481 * Subtract the passed waittime since "tm" from "tma". 1482 */ 1483 void 1484 profile_sub_wait(proftime_T *tm, proftime_T *tma) 1485 { 1486 proftime_T tm3 = prof_wait_time; 1487 1488 profile_sub(&tm3, tm); 1489 profile_sub(tma, &tm3); 1490 } 1491 1492 /* 1493 * Return TRUE if "tm1" and "tm2" are equal. 1494 */ 1495 int 1496 profile_equal(proftime_T *tm1, proftime_T *tm2) 1497 { 1498 # ifdef WIN3264 1499 return (tm1->QuadPart == tm2->QuadPart); 1500 # else 1501 return (tm1->tv_usec == tm2->tv_usec && tm1->tv_sec == tm2->tv_sec); 1502 # endif 1503 } 1504 1505 /* 1506 * Return <0, 0 or >0 if "tm1" < "tm2", "tm1" == "tm2" or "tm1" > "tm2" 1507 */ 1508 int 1509 profile_cmp(const proftime_T *tm1, const proftime_T *tm2) 1510 { 1511 # ifdef WIN3264 1512 return (int)(tm2->QuadPart - tm1->QuadPart); 1513 # else 1514 if (tm1->tv_sec == tm2->tv_sec) 1515 return tm2->tv_usec - tm1->tv_usec; 1516 return tm2->tv_sec - tm1->tv_sec; 1517 # endif 1518 } 1519 1520 static char_u *profile_fname = NULL; 1521 static proftime_T pause_time; 1522 1523 /* 1524 * ":profile cmd args" 1525 */ 1526 void 1527 ex_profile(exarg_T *eap) 1528 { 1529 char_u *e; 1530 int len; 1531 1532 e = skiptowhite(eap->arg); 1533 len = (int)(e - eap->arg); 1534 e = skipwhite(e); 1535 1536 if (len == 5 && STRNCMP(eap->arg, "start", 5) == 0 && *e != NUL) 1537 { 1538 vim_free(profile_fname); 1539 profile_fname = expand_env_save_opt(e, TRUE); 1540 do_profiling = PROF_YES; 1541 profile_zero(&prof_wait_time); 1542 set_vim_var_nr(VV_PROFILING, 1L); 1543 } 1544 else if (do_profiling == PROF_NONE) 1545 EMSG(_("E750: First use \":profile start {fname}\"")); 1546 else if (STRCMP(eap->arg, "pause") == 0) 1547 { 1548 if (do_profiling == PROF_YES) 1549 profile_start(&pause_time); 1550 do_profiling = PROF_PAUSED; 1551 } 1552 else if (STRCMP(eap->arg, "continue") == 0) 1553 { 1554 if (do_profiling == PROF_PAUSED) 1555 { 1556 profile_end(&pause_time); 1557 profile_add(&prof_wait_time, &pause_time); 1558 } 1559 do_profiling = PROF_YES; 1560 } 1561 else 1562 { 1563 /* The rest is similar to ":breakadd". */ 1564 ex_breakadd(eap); 1565 } 1566 } 1567 1568 /* Command line expansion for :profile. */ 1569 static enum 1570 { 1571 PEXP_SUBCMD, /* expand :profile sub-commands */ 1572 PEXP_FUNC /* expand :profile func {funcname} */ 1573 } pexpand_what; 1574 1575 static char *pexpand_cmds[] = { 1576 "start", 1577 #define PROFCMD_START 0 1578 "pause", 1579 #define PROFCMD_PAUSE 1 1580 "continue", 1581 #define PROFCMD_CONTINUE 2 1582 "func", 1583 #define PROFCMD_FUNC 3 1584 "file", 1585 #define PROFCMD_FILE 4 1586 NULL 1587 #define PROFCMD_LAST 5 1588 }; 1589 1590 /* 1591 * Function given to ExpandGeneric() to obtain the profile command 1592 * specific expansion. 1593 */ 1594 char_u * 1595 get_profile_name(expand_T *xp UNUSED, int idx) 1596 { 1597 switch (pexpand_what) 1598 { 1599 case PEXP_SUBCMD: 1600 return (char_u *)pexpand_cmds[idx]; 1601 /* case PEXP_FUNC: TODO */ 1602 default: 1603 return NULL; 1604 } 1605 } 1606 1607 /* 1608 * Handle command line completion for :profile command. 1609 */ 1610 void 1611 set_context_in_profile_cmd(expand_T *xp, char_u *arg) 1612 { 1613 char_u *end_subcmd; 1614 1615 /* Default: expand subcommands. */ 1616 xp->xp_context = EXPAND_PROFILE; 1617 pexpand_what = PEXP_SUBCMD; 1618 xp->xp_pattern = arg; 1619 1620 end_subcmd = skiptowhite(arg); 1621 if (*end_subcmd == NUL) 1622 return; 1623 1624 if (end_subcmd - arg == 5 && STRNCMP(arg, "start", 5) == 0) 1625 { 1626 xp->xp_context = EXPAND_FILES; 1627 xp->xp_pattern = skipwhite(end_subcmd); 1628 return; 1629 } 1630 1631 /* TODO: expand function names after "func" */ 1632 xp->xp_context = EXPAND_NOTHING; 1633 } 1634 1635 /* 1636 * Dump the profiling info. 1637 */ 1638 void 1639 profile_dump(void) 1640 { 1641 FILE *fd; 1642 1643 if (profile_fname != NULL) 1644 { 1645 fd = mch_fopen((char *)profile_fname, "w"); 1646 if (fd == NULL) 1647 EMSG2(_(e_notopen), profile_fname); 1648 else 1649 { 1650 script_dump_profile(fd); 1651 func_dump_profile(fd); 1652 fclose(fd); 1653 } 1654 } 1655 } 1656 1657 /* 1658 * Start profiling script "fp". 1659 */ 1660 static void 1661 script_do_profile(scriptitem_T *si) 1662 { 1663 si->sn_pr_count = 0; 1664 profile_zero(&si->sn_pr_total); 1665 profile_zero(&si->sn_pr_self); 1666 1667 ga_init2(&si->sn_prl_ga, sizeof(sn_prl_T), 100); 1668 si->sn_prl_idx = -1; 1669 si->sn_prof_on = TRUE; 1670 si->sn_pr_nest = 0; 1671 } 1672 1673 /* 1674 * save time when starting to invoke another script or function. 1675 */ 1676 void 1677 script_prof_save( 1678 proftime_T *tm) /* place to store wait time */ 1679 { 1680 scriptitem_T *si; 1681 1682 if (current_SID > 0 && current_SID <= script_items.ga_len) 1683 { 1684 si = &SCRIPT_ITEM(current_SID); 1685 if (si->sn_prof_on && si->sn_pr_nest++ == 0) 1686 profile_start(&si->sn_pr_child); 1687 } 1688 profile_get_wait(tm); 1689 } 1690 1691 /* 1692 * Count time spent in children after invoking another script or function. 1693 */ 1694 void 1695 script_prof_restore(proftime_T *tm) 1696 { 1697 scriptitem_T *si; 1698 1699 if (current_SID > 0 && current_SID <= script_items.ga_len) 1700 { 1701 si = &SCRIPT_ITEM(current_SID); 1702 if (si->sn_prof_on && --si->sn_pr_nest == 0) 1703 { 1704 profile_end(&si->sn_pr_child); 1705 profile_sub_wait(tm, &si->sn_pr_child); /* don't count wait time */ 1706 profile_add(&si->sn_pr_children, &si->sn_pr_child); 1707 profile_add(&si->sn_prl_children, &si->sn_pr_child); 1708 } 1709 } 1710 } 1711 1712 static proftime_T inchar_time; 1713 1714 /* 1715 * Called when starting to wait for the user to type a character. 1716 */ 1717 void 1718 prof_inchar_enter(void) 1719 { 1720 profile_start(&inchar_time); 1721 } 1722 1723 /* 1724 * Called when finished waiting for the user to type a character. 1725 */ 1726 void 1727 prof_inchar_exit(void) 1728 { 1729 profile_end(&inchar_time); 1730 profile_add(&prof_wait_time, &inchar_time); 1731 } 1732 1733 /* 1734 * Dump the profiling results for all scripts in file "fd". 1735 */ 1736 static void 1737 script_dump_profile(FILE *fd) 1738 { 1739 int id; 1740 scriptitem_T *si; 1741 int i; 1742 FILE *sfd; 1743 sn_prl_T *pp; 1744 1745 for (id = 1; id <= script_items.ga_len; ++id) 1746 { 1747 si = &SCRIPT_ITEM(id); 1748 if (si->sn_prof_on) 1749 { 1750 fprintf(fd, "SCRIPT %s\n", si->sn_name); 1751 if (si->sn_pr_count == 1) 1752 fprintf(fd, "Sourced 1 time\n"); 1753 else 1754 fprintf(fd, "Sourced %d times\n", si->sn_pr_count); 1755 fprintf(fd, "Total time: %s\n", profile_msg(&si->sn_pr_total)); 1756 fprintf(fd, " Self time: %s\n", profile_msg(&si->sn_pr_self)); 1757 fprintf(fd, "\n"); 1758 fprintf(fd, "count total (s) self (s)\n"); 1759 1760 sfd = mch_fopen((char *)si->sn_name, "r"); 1761 if (sfd == NULL) 1762 fprintf(fd, "Cannot open file!\n"); 1763 else 1764 { 1765 for (i = 0; i < si->sn_prl_ga.ga_len; ++i) 1766 { 1767 if (vim_fgets(IObuff, IOSIZE, sfd)) 1768 break; 1769 pp = &PRL_ITEM(si, i); 1770 if (pp->snp_count > 0) 1771 { 1772 fprintf(fd, "%5d ", pp->snp_count); 1773 if (profile_equal(&pp->sn_prl_total, &pp->sn_prl_self)) 1774 fprintf(fd, " "); 1775 else 1776 fprintf(fd, "%s ", profile_msg(&pp->sn_prl_total)); 1777 fprintf(fd, "%s ", profile_msg(&pp->sn_prl_self)); 1778 } 1779 else 1780 fprintf(fd, " "); 1781 fprintf(fd, "%s", IObuff); 1782 } 1783 fclose(sfd); 1784 } 1785 fprintf(fd, "\n"); 1786 } 1787 } 1788 } 1789 1790 /* 1791 * Return TRUE when a function defined in the current script should be 1792 * profiled. 1793 */ 1794 int 1795 prof_def_func(void) 1796 { 1797 if (current_SID > 0) 1798 return SCRIPT_ITEM(current_SID).sn_pr_force; 1799 return FALSE; 1800 } 1801 1802 # endif 1803 #endif 1804 1805 /* 1806 * If 'autowrite' option set, try to write the file. 1807 * Careful: autocommands may make "buf" invalid! 1808 * 1809 * return FAIL for failure, OK otherwise 1810 */ 1811 int 1812 autowrite(buf_T *buf, int forceit) 1813 { 1814 int r; 1815 bufref_T bufref; 1816 1817 if (!(p_aw || p_awa) || !p_write 1818 #ifdef FEAT_QUICKFIX 1819 /* never autowrite a "nofile" or "nowrite" buffer */ 1820 || bt_dontwrite(buf) 1821 #endif 1822 || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL) 1823 return FAIL; 1824 set_bufref(&bufref, buf); 1825 r = buf_write_all(buf, forceit); 1826 1827 /* Writing may succeed but the buffer still changed, e.g., when there is a 1828 * conversion error. We do want to return FAIL then. */ 1829 if (bufref_valid(&bufref) && bufIsChanged(buf)) 1830 r = FAIL; 1831 return r; 1832 } 1833 1834 /* 1835 * flush all buffers, except the ones that are readonly 1836 */ 1837 void 1838 autowrite_all(void) 1839 { 1840 buf_T *buf; 1841 1842 if (!(p_aw || p_awa) || !p_write) 1843 return; 1844 FOR_ALL_BUFFERS(buf) 1845 if (bufIsChanged(buf) && !buf->b_p_ro) 1846 { 1847 #ifdef FEAT_AUTOCMD 1848 bufref_T bufref; 1849 1850 set_bufref(&bufref, buf); 1851 #endif 1852 (void)buf_write_all(buf, FALSE); 1853 #ifdef FEAT_AUTOCMD 1854 /* an autocommand may have deleted the buffer */ 1855 if (!bufref_valid(&bufref)) 1856 buf = firstbuf; 1857 #endif 1858 } 1859 } 1860 1861 /* 1862 * Return TRUE if buffer was changed and cannot be abandoned. 1863 * For flags use the CCGD_ values. 1864 */ 1865 int 1866 check_changed(buf_T *buf, int flags) 1867 { 1868 int forceit = (flags & CCGD_FORCEIT); 1869 #ifdef FEAT_AUTOCMD 1870 bufref_T bufref; 1871 1872 set_bufref(&bufref, buf); 1873 #endif 1874 1875 if ( !forceit 1876 && bufIsChanged(buf) 1877 && ((flags & CCGD_MULTWIN) || buf->b_nwindows <= 1) 1878 && (!(flags & CCGD_AW) || autowrite(buf, forceit) == FAIL)) 1879 { 1880 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 1881 if ((p_confirm || cmdmod.confirm) && p_write) 1882 { 1883 buf_T *buf2; 1884 int count = 0; 1885 1886 if (flags & CCGD_ALLBUF) 1887 FOR_ALL_BUFFERS(buf2) 1888 if (bufIsChanged(buf2) 1889 && (buf2->b_ffname != NULL 1890 # ifdef FEAT_BROWSE 1891 || cmdmod.browse 1892 # endif 1893 )) 1894 ++count; 1895 # ifdef FEAT_AUTOCMD 1896 if (!bufref_valid(&bufref)) 1897 /* Autocommand deleted buffer, oops! It's not changed now. */ 1898 return FALSE; 1899 # endif 1900 dialog_changed(buf, count > 1); 1901 # ifdef FEAT_AUTOCMD 1902 if (!bufref_valid(&bufref)) 1903 /* Autocommand deleted buffer, oops! It's not changed now. */ 1904 return FALSE; 1905 # endif 1906 return bufIsChanged(buf); 1907 } 1908 #endif 1909 if (flags & CCGD_EXCMD) 1910 EMSG(_(e_nowrtmsg)); 1911 else 1912 EMSG(_(e_nowrtmsg_nobang)); 1913 return TRUE; 1914 } 1915 return FALSE; 1916 } 1917 1918 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO) 1919 1920 #if defined(FEAT_BROWSE) || defined(PROTO) 1921 /* 1922 * When wanting to write a file without a file name, ask the user for a name. 1923 */ 1924 void 1925 browse_save_fname(buf_T *buf) 1926 { 1927 if (buf->b_fname == NULL) 1928 { 1929 char_u *fname; 1930 1931 fname = do_browse(BROWSE_SAVE, (char_u *)_("Save As"), 1932 NULL, NULL, NULL, NULL, buf); 1933 if (fname != NULL) 1934 { 1935 if (setfname(buf, fname, NULL, TRUE) == OK) 1936 buf->b_flags |= BF_NOTEDITED; 1937 vim_free(fname); 1938 } 1939 } 1940 } 1941 #endif 1942 1943 /* 1944 * Ask the user what to do when abandoning a changed buffer. 1945 * Must check 'write' option first! 1946 */ 1947 void 1948 dialog_changed( 1949 buf_T *buf, 1950 int checkall) /* may abandon all changed buffers */ 1951 { 1952 char_u buff[DIALOG_MSG_SIZE]; 1953 int ret; 1954 buf_T *buf2; 1955 exarg_T ea; 1956 1957 dialog_msg(buff, _("Save changes to \"%s\"?"), 1958 (buf->b_fname != NULL) ? 1959 buf->b_fname : (char_u *)_("Untitled")); 1960 if (checkall) 1961 ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1); 1962 else 1963 ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1); 1964 1965 /* Init ea pseudo-structure, this is needed for the check_overwrite() 1966 * function. */ 1967 ea.append = ea.forceit = FALSE; 1968 1969 if (ret == VIM_YES) 1970 { 1971 #ifdef FEAT_BROWSE 1972 /* May get file name, when there is none */ 1973 browse_save_fname(buf); 1974 #endif 1975 if (buf->b_fname != NULL && check_overwrite(&ea, buf, 1976 buf->b_fname, buf->b_ffname, FALSE) == OK) 1977 /* didn't hit Cancel */ 1978 (void)buf_write_all(buf, FALSE); 1979 } 1980 else if (ret == VIM_NO) 1981 { 1982 unchanged(buf, TRUE); 1983 } 1984 else if (ret == VIM_ALL) 1985 { 1986 /* 1987 * Write all modified files that can be written. 1988 * Skip readonly buffers, these need to be confirmed 1989 * individually. 1990 */ 1991 FOR_ALL_BUFFERS(buf2) 1992 { 1993 if (bufIsChanged(buf2) 1994 && (buf2->b_ffname != NULL 1995 #ifdef FEAT_BROWSE 1996 || cmdmod.browse 1997 #endif 1998 ) 1999 && !buf2->b_p_ro) 2000 { 2001 #ifdef FEAT_AUTOCMD 2002 bufref_T bufref; 2003 2004 set_bufref(&bufref, buf2); 2005 #endif 2006 #ifdef FEAT_BROWSE 2007 /* May get file name, when there is none */ 2008 browse_save_fname(buf2); 2009 #endif 2010 if (buf2->b_fname != NULL && check_overwrite(&ea, buf2, 2011 buf2->b_fname, buf2->b_ffname, FALSE) == OK) 2012 /* didn't hit Cancel */ 2013 (void)buf_write_all(buf2, FALSE); 2014 #ifdef FEAT_AUTOCMD 2015 /* an autocommand may have deleted the buffer */ 2016 if (!bufref_valid(&bufref)) 2017 buf2 = firstbuf; 2018 #endif 2019 } 2020 } 2021 } 2022 else if (ret == VIM_DISCARDALL) 2023 { 2024 /* 2025 * mark all buffers as unchanged 2026 */ 2027 FOR_ALL_BUFFERS(buf2) 2028 unchanged(buf2, TRUE); 2029 } 2030 } 2031 #endif 2032 2033 /* 2034 * Return TRUE if the buffer "buf" can be abandoned, either by making it 2035 * hidden, autowriting it or unloading it. 2036 */ 2037 int 2038 can_abandon(buf_T *buf, int forceit) 2039 { 2040 return ( P_HID(buf) 2041 || !bufIsChanged(buf) 2042 || buf->b_nwindows > 1 2043 || autowrite(buf, forceit) == OK 2044 || forceit); 2045 } 2046 2047 static void add_bufnum(int *bufnrs, int *bufnump, int nr); 2048 2049 /* 2050 * Add a buffer number to "bufnrs", unless it's already there. 2051 */ 2052 static void 2053 add_bufnum(int *bufnrs, int *bufnump, int nr) 2054 { 2055 int i; 2056 2057 for (i = 0; i < *bufnump; ++i) 2058 if (bufnrs[i] == nr) 2059 return; 2060 bufnrs[*bufnump] = nr; 2061 *bufnump = *bufnump + 1; 2062 } 2063 2064 /* 2065 * Return TRUE if any buffer was changed and cannot be abandoned. 2066 * That changed buffer becomes the current buffer. 2067 * When "unload" is true the current buffer is unloaded instead of making it 2068 * hidden. This is used for ":q!". 2069 */ 2070 int 2071 check_changed_any( 2072 int hidden, /* Only check hidden buffers */ 2073 int unload) 2074 { 2075 int ret = FALSE; 2076 buf_T *buf; 2077 int save; 2078 int i; 2079 int bufnum = 0; 2080 int bufcount = 0; 2081 int *bufnrs; 2082 #ifdef FEAT_WINDOWS 2083 tabpage_T *tp; 2084 win_T *wp; 2085 #endif 2086 2087 FOR_ALL_BUFFERS(buf) 2088 ++bufcount; 2089 2090 if (bufcount == 0) 2091 return FALSE; 2092 2093 bufnrs = (int *)alloc(sizeof(int) * bufcount); 2094 if (bufnrs == NULL) 2095 return FALSE; 2096 2097 /* curbuf */ 2098 bufnrs[bufnum++] = curbuf->b_fnum; 2099 #ifdef FEAT_WINDOWS 2100 /* buf in curtab */ 2101 FOR_ALL_WINDOWS(wp) 2102 if (wp->w_buffer != curbuf) 2103 add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum); 2104 2105 /* buf in other tab */ 2106 FOR_ALL_TABPAGES(tp) 2107 if (tp != curtab) 2108 for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next) 2109 add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum); 2110 #endif 2111 /* any other buf */ 2112 FOR_ALL_BUFFERS(buf) 2113 add_bufnum(bufnrs, &bufnum, buf->b_fnum); 2114 2115 for (i = 0; i < bufnum; ++i) 2116 { 2117 buf = buflist_findnr(bufnrs[i]); 2118 if (buf == NULL) 2119 continue; 2120 if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf)) 2121 { 2122 bufref_T bufref; 2123 2124 set_bufref(&bufref, buf); 2125 /* Try auto-writing the buffer. If this fails but the buffer no 2126 * longer exists it's not changed, that's OK. */ 2127 if (check_changed(buf, (p_awa ? CCGD_AW : 0) 2128 | CCGD_MULTWIN 2129 | CCGD_ALLBUF) && bufref_valid(&bufref)) 2130 break; /* didn't save - still changes */ 2131 } 2132 } 2133 2134 if (i >= bufnum) 2135 goto theend; 2136 2137 ret = TRUE; 2138 exiting = FALSE; 2139 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 2140 /* 2141 * When ":confirm" used, don't give an error message. 2142 */ 2143 if (!(p_confirm || cmdmod.confirm)) 2144 #endif 2145 { 2146 /* There must be a wait_return for this message, do_buffer() 2147 * may cause a redraw. But wait_return() is a no-op when vgetc() 2148 * is busy (Quit used from window menu), then make sure we don't 2149 * cause a scroll up. */ 2150 if (vgetc_busy > 0) 2151 { 2152 msg_row = cmdline_row; 2153 msg_col = 0; 2154 msg_didout = FALSE; 2155 } 2156 if (EMSG2(_("E162: No write since last change for buffer \"%s\""), 2157 buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname)) 2158 { 2159 save = no_wait_return; 2160 no_wait_return = FALSE; 2161 wait_return(FALSE); 2162 no_wait_return = save; 2163 } 2164 } 2165 2166 #ifdef FEAT_WINDOWS 2167 /* Try to find a window that contains the buffer. */ 2168 if (buf != curbuf) 2169 FOR_ALL_TAB_WINDOWS(tp, wp) 2170 if (wp->w_buffer == buf) 2171 { 2172 # ifdef FEAT_AUTOCMD 2173 bufref_T bufref; 2174 2175 set_bufref(&bufref, buf); 2176 # endif 2177 goto_tabpage_win(tp, wp); 2178 # ifdef FEAT_AUTOCMD 2179 /* Paranoia: did autocms wipe out the buffer with changes? */ 2180 if (!bufref_valid(&bufref)) 2181 { 2182 goto theend; 2183 } 2184 # endif 2185 goto buf_found; 2186 } 2187 buf_found: 2188 #endif 2189 2190 /* Open the changed buffer in the current window. */ 2191 if (buf != curbuf) 2192 set_curbuf(buf, unload ? DOBUF_UNLOAD : DOBUF_GOTO); 2193 2194 theend: 2195 vim_free(bufnrs); 2196 return ret; 2197 } 2198 2199 /* 2200 * return FAIL if there is no file name, OK if there is one 2201 * give error message for FAIL 2202 */ 2203 int 2204 check_fname(void) 2205 { 2206 if (curbuf->b_ffname == NULL) 2207 { 2208 EMSG(_(e_noname)); 2209 return FAIL; 2210 } 2211 return OK; 2212 } 2213 2214 /* 2215 * flush the contents of a buffer, unless it has no file name 2216 * 2217 * return FAIL for failure, OK otherwise 2218 */ 2219 int 2220 buf_write_all(buf_T *buf, int forceit) 2221 { 2222 int retval; 2223 #ifdef FEAT_AUTOCMD 2224 buf_T *old_curbuf = curbuf; 2225 #endif 2226 2227 retval = (buf_write(buf, buf->b_ffname, buf->b_fname, 2228 (linenr_T)1, buf->b_ml.ml_line_count, NULL, 2229 FALSE, forceit, TRUE, FALSE)); 2230 #ifdef FEAT_AUTOCMD 2231 if (curbuf != old_curbuf) 2232 { 2233 msg_source(hl_attr(HLF_W)); 2234 MSG(_("Warning: Entered other buffer unexpectedly (check autocommands)")); 2235 } 2236 #endif 2237 return retval; 2238 } 2239 2240 /* 2241 * Code to handle the argument list. 2242 */ 2243 2244 static char_u *do_one_arg(char_u *str); 2245 static int do_arglist(char_u *str, int what, int after); 2246 static void alist_check_arg_idx(void); 2247 static int editing_arg_idx(win_T *win); 2248 #ifdef FEAT_LISTCMDS 2249 static int alist_add_list(int count, char_u **files, int after); 2250 #endif 2251 #define AL_SET 1 2252 #define AL_ADD 2 2253 #define AL_DEL 3 2254 2255 /* 2256 * Isolate one argument, taking backticks. 2257 * Changes the argument in-place, puts a NUL after it. Backticks remain. 2258 * Return a pointer to the start of the next argument. 2259 */ 2260 static char_u * 2261 do_one_arg(char_u *str) 2262 { 2263 char_u *p; 2264 int inbacktick; 2265 2266 inbacktick = FALSE; 2267 for (p = str; *str; ++str) 2268 { 2269 /* When the backslash is used for escaping the special meaning of a 2270 * character we need to keep it until wildcard expansion. */ 2271 if (rem_backslash(str)) 2272 { 2273 *p++ = *str++; 2274 *p++ = *str; 2275 } 2276 else 2277 { 2278 /* An item ends at a space not in backticks */ 2279 if (!inbacktick && vim_isspace(*str)) 2280 break; 2281 if (*str == '`') 2282 inbacktick ^= TRUE; 2283 *p++ = *str; 2284 } 2285 } 2286 str = skipwhite(str); 2287 *p = NUL; 2288 2289 return str; 2290 } 2291 2292 /* 2293 * Separate the arguments in "str" and return a list of pointers in the 2294 * growarray "gap". 2295 */ 2296 int 2297 get_arglist(garray_T *gap, char_u *str) 2298 { 2299 ga_init2(gap, (int)sizeof(char_u *), 20); 2300 while (*str != NUL) 2301 { 2302 if (ga_grow(gap, 1) == FAIL) 2303 { 2304 ga_clear(gap); 2305 return FAIL; 2306 } 2307 ((char_u **)gap->ga_data)[gap->ga_len++] = str; 2308 2309 /* Isolate one argument, change it in-place, put a NUL after it. */ 2310 str = do_one_arg(str); 2311 } 2312 return OK; 2313 } 2314 2315 #if defined(FEAT_QUICKFIX) || defined(FEAT_SYN_HL) || defined(PROTO) 2316 /* 2317 * Parse a list of arguments (file names), expand them and return in 2318 * "fnames[fcountp]". When "wig" is TRUE, removes files matching 'wildignore'. 2319 * Return FAIL or OK. 2320 */ 2321 int 2322 get_arglist_exp( 2323 char_u *str, 2324 int *fcountp, 2325 char_u ***fnamesp, 2326 int wig) 2327 { 2328 garray_T ga; 2329 int i; 2330 2331 if (get_arglist(&ga, str) == FAIL) 2332 return FAIL; 2333 if (wig == TRUE) 2334 i = expand_wildcards(ga.ga_len, (char_u **)ga.ga_data, 2335 fcountp, fnamesp, EW_FILE|EW_NOTFOUND); 2336 else 2337 i = gen_expand_wildcards(ga.ga_len, (char_u **)ga.ga_data, 2338 fcountp, fnamesp, EW_FILE|EW_NOTFOUND); 2339 2340 ga_clear(&ga); 2341 return i; 2342 } 2343 #endif 2344 2345 #if defined(FEAT_GUI) || defined(FEAT_CLIENTSERVER) || defined(PROTO) 2346 /* 2347 * Redefine the argument list. 2348 */ 2349 void 2350 set_arglist(char_u *str) 2351 { 2352 do_arglist(str, AL_SET, 0); 2353 } 2354 #endif 2355 2356 /* 2357 * "what" == AL_SET: Redefine the argument list to 'str'. 2358 * "what" == AL_ADD: add files in 'str' to the argument list after "after". 2359 * "what" == AL_DEL: remove files in 'str' from the argument list. 2360 * 2361 * Return FAIL for failure, OK otherwise. 2362 */ 2363 static int 2364 do_arglist( 2365 char_u *str, 2366 int what, 2367 int after UNUSED) /* 0 means before first one */ 2368 { 2369 garray_T new_ga; 2370 int exp_count; 2371 char_u **exp_files; 2372 int i; 2373 #ifdef FEAT_LISTCMDS 2374 char_u *p; 2375 int match; 2376 #endif 2377 2378 /* 2379 * Set default argument for ":argadd" command. 2380 */ 2381 if (what == AL_ADD && *str == NUL) 2382 { 2383 if (curbuf->b_ffname == NULL) 2384 return FAIL; 2385 str = curbuf->b_fname; 2386 } 2387 2388 /* 2389 * Collect all file name arguments in "new_ga". 2390 */ 2391 if (get_arglist(&new_ga, str) == FAIL) 2392 return FAIL; 2393 2394 #ifdef FEAT_LISTCMDS 2395 if (what == AL_DEL) 2396 { 2397 regmatch_T regmatch; 2398 int didone; 2399 2400 /* 2401 * Delete the items: use each item as a regexp and find a match in the 2402 * argument list. 2403 */ 2404 regmatch.rm_ic = p_fic; /* ignore case when 'fileignorecase' is set */ 2405 for (i = 0; i < new_ga.ga_len && !got_int; ++i) 2406 { 2407 p = ((char_u **)new_ga.ga_data)[i]; 2408 p = file_pat_to_reg_pat(p, NULL, NULL, FALSE); 2409 if (p == NULL) 2410 break; 2411 regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0); 2412 if (regmatch.regprog == NULL) 2413 { 2414 vim_free(p); 2415 break; 2416 } 2417 2418 didone = FALSE; 2419 for (match = 0; match < ARGCOUNT; ++match) 2420 if (vim_regexec(®match, alist_name(&ARGLIST[match]), 2421 (colnr_T)0)) 2422 { 2423 didone = TRUE; 2424 vim_free(ARGLIST[match].ae_fname); 2425 mch_memmove(ARGLIST + match, ARGLIST + match + 1, 2426 (ARGCOUNT - match - 1) * sizeof(aentry_T)); 2427 --ALIST(curwin)->al_ga.ga_len; 2428 if (curwin->w_arg_idx > match) 2429 --curwin->w_arg_idx; 2430 --match; 2431 } 2432 2433 vim_regfree(regmatch.regprog); 2434 vim_free(p); 2435 if (!didone) 2436 EMSG2(_(e_nomatch2), ((char_u **)new_ga.ga_data)[i]); 2437 } 2438 ga_clear(&new_ga); 2439 } 2440 else 2441 #endif 2442 { 2443 i = expand_wildcards(new_ga.ga_len, (char_u **)new_ga.ga_data, 2444 &exp_count, &exp_files, EW_DIR|EW_FILE|EW_ADDSLASH|EW_NOTFOUND); 2445 ga_clear(&new_ga); 2446 if (i == FAIL || exp_count == 0) 2447 { 2448 EMSG(_(e_nomatch)); 2449 return FAIL; 2450 } 2451 2452 #ifdef FEAT_LISTCMDS 2453 if (what == AL_ADD) 2454 { 2455 (void)alist_add_list(exp_count, exp_files, after); 2456 vim_free(exp_files); 2457 } 2458 else /* what == AL_SET */ 2459 #endif 2460 alist_set(ALIST(curwin), exp_count, exp_files, FALSE, NULL, 0); 2461 } 2462 2463 alist_check_arg_idx(); 2464 2465 return OK; 2466 } 2467 2468 /* 2469 * Check the validity of the arg_idx for each other window. 2470 */ 2471 static void 2472 alist_check_arg_idx(void) 2473 { 2474 #ifdef FEAT_WINDOWS 2475 win_T *win; 2476 tabpage_T *tp; 2477 2478 FOR_ALL_TAB_WINDOWS(tp, win) 2479 if (win->w_alist == curwin->w_alist) 2480 check_arg_idx(win); 2481 #else 2482 check_arg_idx(curwin); 2483 #endif 2484 } 2485 2486 /* 2487 * Return TRUE if window "win" is editing the file at the current argument 2488 * index. 2489 */ 2490 static int 2491 editing_arg_idx(win_T *win) 2492 { 2493 return !(win->w_arg_idx >= WARGCOUNT(win) 2494 || (win->w_buffer->b_fnum 2495 != WARGLIST(win)[win->w_arg_idx].ae_fnum 2496 && (win->w_buffer->b_ffname == NULL 2497 || !(fullpathcmp( 2498 alist_name(&WARGLIST(win)[win->w_arg_idx]), 2499 win->w_buffer->b_ffname, TRUE) & FPC_SAME)))); 2500 } 2501 2502 /* 2503 * Check if window "win" is editing the w_arg_idx file in its argument list. 2504 */ 2505 void 2506 check_arg_idx(win_T *win) 2507 { 2508 if (WARGCOUNT(win) > 1 && !editing_arg_idx(win)) 2509 { 2510 /* We are not editing the current entry in the argument list. 2511 * Set "arg_had_last" if we are editing the last one. */ 2512 win->w_arg_idx_invalid = TRUE; 2513 if (win->w_arg_idx != WARGCOUNT(win) - 1 2514 && arg_had_last == FALSE 2515 #ifdef FEAT_WINDOWS 2516 && ALIST(win) == &global_alist 2517 #endif 2518 && GARGCOUNT > 0 2519 && win->w_arg_idx < GARGCOUNT 2520 && (win->w_buffer->b_fnum == GARGLIST[GARGCOUNT - 1].ae_fnum 2521 || (win->w_buffer->b_ffname != NULL 2522 && (fullpathcmp(alist_name(&GARGLIST[GARGCOUNT - 1]), 2523 win->w_buffer->b_ffname, TRUE) & FPC_SAME)))) 2524 arg_had_last = TRUE; 2525 } 2526 else 2527 { 2528 /* We are editing the current entry in the argument list. 2529 * Set "arg_had_last" if it's also the last one */ 2530 win->w_arg_idx_invalid = FALSE; 2531 if (win->w_arg_idx == WARGCOUNT(win) - 1 2532 #ifdef FEAT_WINDOWS 2533 && win->w_alist == &global_alist 2534 #endif 2535 ) 2536 arg_had_last = TRUE; 2537 } 2538 } 2539 2540 /* 2541 * ":args", ":argslocal" and ":argsglobal". 2542 */ 2543 void 2544 ex_args(exarg_T *eap) 2545 { 2546 int i; 2547 2548 if (eap->cmdidx != CMD_args) 2549 { 2550 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS) 2551 alist_unlink(ALIST(curwin)); 2552 if (eap->cmdidx == CMD_argglobal) 2553 ALIST(curwin) = &global_alist; 2554 else /* eap->cmdidx == CMD_arglocal */ 2555 alist_new(); 2556 #else 2557 ex_ni(eap); 2558 return; 2559 #endif 2560 } 2561 2562 if (!ends_excmd(*eap->arg)) 2563 { 2564 /* 2565 * ":args file ..": define new argument list, handle like ":next" 2566 * Also for ":argslocal file .." and ":argsglobal file ..". 2567 */ 2568 ex_next(eap); 2569 } 2570 else 2571 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS) 2572 if (eap->cmdidx == CMD_args) 2573 #endif 2574 { 2575 /* 2576 * ":args": list arguments. 2577 */ 2578 if (ARGCOUNT > 0) 2579 { 2580 /* Overwrite the command, for a short list there is no scrolling 2581 * required and no wait_return(). */ 2582 gotocmdline(TRUE); 2583 for (i = 0; i < ARGCOUNT; ++i) 2584 { 2585 if (i == curwin->w_arg_idx) 2586 msg_putchar('['); 2587 msg_outtrans(alist_name(&ARGLIST[i])); 2588 if (i == curwin->w_arg_idx) 2589 msg_putchar(']'); 2590 msg_putchar(' '); 2591 } 2592 } 2593 } 2594 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS) 2595 else if (eap->cmdidx == CMD_arglocal) 2596 { 2597 garray_T *gap = &curwin->w_alist->al_ga; 2598 2599 /* 2600 * ":argslocal": make a local copy of the global argument list. 2601 */ 2602 if (ga_grow(gap, GARGCOUNT) == OK) 2603 for (i = 0; i < GARGCOUNT; ++i) 2604 if (GARGLIST[i].ae_fname != NULL) 2605 { 2606 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fname = 2607 vim_strsave(GARGLIST[i].ae_fname); 2608 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fnum = 2609 GARGLIST[i].ae_fnum; 2610 ++gap->ga_len; 2611 } 2612 } 2613 #endif 2614 } 2615 2616 /* 2617 * ":previous", ":sprevious", ":Next" and ":sNext". 2618 */ 2619 void 2620 ex_previous(exarg_T *eap) 2621 { 2622 /* If past the last one already, go to the last one. */ 2623 if (curwin->w_arg_idx - (int)eap->line2 >= ARGCOUNT) 2624 do_argfile(eap, ARGCOUNT - 1); 2625 else 2626 do_argfile(eap, curwin->w_arg_idx - (int)eap->line2); 2627 } 2628 2629 /* 2630 * ":rewind", ":first", ":sfirst" and ":srewind". 2631 */ 2632 void 2633 ex_rewind(exarg_T *eap) 2634 { 2635 do_argfile(eap, 0); 2636 } 2637 2638 /* 2639 * ":last" and ":slast". 2640 */ 2641 void 2642 ex_last(exarg_T *eap) 2643 { 2644 do_argfile(eap, ARGCOUNT - 1); 2645 } 2646 2647 /* 2648 * ":argument" and ":sargument". 2649 */ 2650 void 2651 ex_argument(exarg_T *eap) 2652 { 2653 int i; 2654 2655 if (eap->addr_count > 0) 2656 i = eap->line2 - 1; 2657 else 2658 i = curwin->w_arg_idx; 2659 do_argfile(eap, i); 2660 } 2661 2662 /* 2663 * Edit file "argn" of the argument lists. 2664 */ 2665 void 2666 do_argfile(exarg_T *eap, int argn) 2667 { 2668 int other; 2669 char_u *p; 2670 int old_arg_idx = curwin->w_arg_idx; 2671 2672 if (argn < 0 || argn >= ARGCOUNT) 2673 { 2674 if (ARGCOUNT <= 1) 2675 EMSG(_("E163: There is only one file to edit")); 2676 else if (argn < 0) 2677 EMSG(_("E164: Cannot go before first file")); 2678 else 2679 EMSG(_("E165: Cannot go beyond last file")); 2680 } 2681 else 2682 { 2683 setpcmark(); 2684 #ifdef FEAT_GUI 2685 need_mouse_correct = TRUE; 2686 #endif 2687 2688 #ifdef FEAT_WINDOWS 2689 /* split window or create new tab page first */ 2690 if (*eap->cmd == 's' || cmdmod.tab != 0) 2691 { 2692 if (win_split(0, 0) == FAIL) 2693 return; 2694 RESET_BINDING(curwin); 2695 } 2696 else 2697 #endif 2698 { 2699 /* 2700 * if 'hidden' set, only check for changed file when re-editing 2701 * the same buffer 2702 */ 2703 other = TRUE; 2704 if (P_HID(curbuf)) 2705 { 2706 p = fix_fname(alist_name(&ARGLIST[argn])); 2707 other = otherfile(p); 2708 vim_free(p); 2709 } 2710 if ((!P_HID(curbuf) || !other) 2711 && check_changed(curbuf, CCGD_AW 2712 | (other ? 0 : CCGD_MULTWIN) 2713 | (eap->forceit ? CCGD_FORCEIT : 0) 2714 | CCGD_EXCMD)) 2715 return; 2716 } 2717 2718 curwin->w_arg_idx = argn; 2719 if (argn == ARGCOUNT - 1 2720 #ifdef FEAT_WINDOWS 2721 && curwin->w_alist == &global_alist 2722 #endif 2723 ) 2724 arg_had_last = TRUE; 2725 2726 /* Edit the file; always use the last known line number. 2727 * When it fails (e.g. Abort for already edited file) restore the 2728 * argument index. */ 2729 if (do_ecmd(0, alist_name(&ARGLIST[curwin->w_arg_idx]), NULL, 2730 eap, ECMD_LAST, 2731 (P_HID(curwin->w_buffer) ? ECMD_HIDE : 0) 2732 + (eap->forceit ? ECMD_FORCEIT : 0), curwin) == FAIL) 2733 curwin->w_arg_idx = old_arg_idx; 2734 /* like Vi: set the mark where the cursor is in the file. */ 2735 else if (eap->cmdidx != CMD_argdo) 2736 setmark('\''); 2737 } 2738 } 2739 2740 /* 2741 * ":next", and commands that behave like it. 2742 */ 2743 void 2744 ex_next(exarg_T *eap) 2745 { 2746 int i; 2747 2748 /* 2749 * check for changed buffer now, if this fails the argument list is not 2750 * redefined. 2751 */ 2752 if ( P_HID(curbuf) 2753 || eap->cmdidx == CMD_snext 2754 || !check_changed(curbuf, CCGD_AW 2755 | (eap->forceit ? CCGD_FORCEIT : 0) 2756 | CCGD_EXCMD)) 2757 { 2758 if (*eap->arg != NUL) /* redefine file list */ 2759 { 2760 if (do_arglist(eap->arg, AL_SET, 0) == FAIL) 2761 return; 2762 i = 0; 2763 } 2764 else 2765 i = curwin->w_arg_idx + (int)eap->line2; 2766 do_argfile(eap, i); 2767 } 2768 } 2769 2770 #if defined(FEAT_LISTCMDS) || defined(PROTO) 2771 /* 2772 * ":argedit" 2773 */ 2774 void 2775 ex_argedit(exarg_T *eap) 2776 { 2777 int fnum; 2778 int i; 2779 char_u *s; 2780 2781 /* Add the argument to the buffer list and get the buffer number. */ 2782 fnum = buflist_add(eap->arg, BLN_LISTED); 2783 2784 /* Check if this argument is already in the argument list. */ 2785 for (i = 0; i < ARGCOUNT; ++i) 2786 if (ARGLIST[i].ae_fnum == fnum) 2787 break; 2788 if (i == ARGCOUNT) 2789 { 2790 /* Can't find it, add it to the argument list. */ 2791 s = vim_strsave(eap->arg); 2792 if (s == NULL) 2793 return; 2794 i = alist_add_list(1, &s, 2795 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1); 2796 if (i < 0) 2797 return; 2798 curwin->w_arg_idx = i; 2799 } 2800 2801 alist_check_arg_idx(); 2802 2803 /* Edit the argument. */ 2804 do_argfile(eap, i); 2805 } 2806 2807 /* 2808 * ":argadd" 2809 */ 2810 void 2811 ex_argadd(exarg_T *eap) 2812 { 2813 do_arglist(eap->arg, AL_ADD, 2814 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1); 2815 #ifdef FEAT_TITLE 2816 maketitle(); 2817 #endif 2818 } 2819 2820 /* 2821 * ":argdelete" 2822 */ 2823 void 2824 ex_argdelete(exarg_T *eap) 2825 { 2826 int i; 2827 int n; 2828 2829 if (eap->addr_count > 0) 2830 { 2831 /* ":1,4argdel": Delete all arguments in the range. */ 2832 if (eap->line2 > ARGCOUNT) 2833 eap->line2 = ARGCOUNT; 2834 n = eap->line2 - eap->line1 + 1; 2835 if (*eap->arg != NUL || n <= 0) 2836 EMSG(_(e_invarg)); 2837 else 2838 { 2839 for (i = eap->line1; i <= eap->line2; ++i) 2840 vim_free(ARGLIST[i - 1].ae_fname); 2841 mch_memmove(ARGLIST + eap->line1 - 1, ARGLIST + eap->line2, 2842 (size_t)((ARGCOUNT - eap->line2) * sizeof(aentry_T))); 2843 ALIST(curwin)->al_ga.ga_len -= n; 2844 if (curwin->w_arg_idx >= eap->line2) 2845 curwin->w_arg_idx -= n; 2846 else if (curwin->w_arg_idx > eap->line1) 2847 curwin->w_arg_idx = eap->line1; 2848 if (ARGCOUNT == 0) 2849 curwin->w_arg_idx = 0; 2850 else if (curwin->w_arg_idx >= ARGCOUNT) 2851 curwin->w_arg_idx = ARGCOUNT - 1; 2852 } 2853 } 2854 else if (*eap->arg == NUL) 2855 EMSG(_(e_argreq)); 2856 else 2857 do_arglist(eap->arg, AL_DEL, 0); 2858 #ifdef FEAT_TITLE 2859 maketitle(); 2860 #endif 2861 } 2862 2863 /* 2864 * ":argdo", ":windo", ":bufdo", ":tabdo", ":cdo", ":ldo", ":cfdo" and ":lfdo" 2865 */ 2866 void 2867 ex_listdo(exarg_T *eap) 2868 { 2869 int i; 2870 #ifdef FEAT_WINDOWS 2871 win_T *wp; 2872 tabpage_T *tp; 2873 #endif 2874 buf_T *buf = curbuf; 2875 int next_fnum = 0; 2876 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL) 2877 char_u *save_ei = NULL; 2878 #endif 2879 char_u *p_shm_save; 2880 #ifdef FEAT_QUICKFIX 2881 int qf_size = 0; 2882 int qf_idx; 2883 #endif 2884 2885 #ifndef FEAT_WINDOWS 2886 if (eap->cmdidx == CMD_windo) 2887 { 2888 ex_ni(eap); 2889 return; 2890 } 2891 #endif 2892 2893 #ifndef FEAT_QUICKFIX 2894 if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo || 2895 eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) 2896 { 2897 ex_ni(eap); 2898 return; 2899 } 2900 #endif 2901 2902 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL) 2903 if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo) 2904 /* Don't do syntax HL autocommands. Skipping the syntax file is a 2905 * great speed improvement. */ 2906 save_ei = au_event_disable(",Syntax"); 2907 #endif 2908 #ifdef FEAT_CLIPBOARD 2909 start_global_changes(); 2910 #endif 2911 2912 if (eap->cmdidx == CMD_windo 2913 || eap->cmdidx == CMD_tabdo 2914 || P_HID(curbuf) 2915 || !check_changed(curbuf, CCGD_AW 2916 | (eap->forceit ? CCGD_FORCEIT : 0) 2917 | CCGD_EXCMD)) 2918 { 2919 i = 0; 2920 /* start at the eap->line1 argument/window/buffer */ 2921 #ifdef FEAT_WINDOWS 2922 wp = firstwin; 2923 tp = first_tabpage; 2924 #endif 2925 switch (eap->cmdidx) 2926 { 2927 #ifdef FEAT_WINDOWS 2928 case CMD_windo: 2929 for ( ; wp != NULL && i + 1 < eap->line1; wp = wp->w_next) 2930 i++; 2931 break; 2932 case CMD_tabdo: 2933 for( ; tp != NULL && i + 1 < eap->line1; tp = tp->tp_next) 2934 i++; 2935 break; 2936 #endif 2937 case CMD_argdo: 2938 i = eap->line1 - 1; 2939 break; 2940 default: 2941 break; 2942 } 2943 /* set pcmark now */ 2944 if (eap->cmdidx == CMD_bufdo) 2945 { 2946 /* Advance to the first listed buffer after "eap->line1". */ 2947 for (buf = firstbuf; buf != NULL && (buf->b_fnum < eap->line1 2948 || !buf->b_p_bl); buf = buf->b_next) 2949 if (buf->b_fnum > eap->line2) 2950 { 2951 buf = NULL; 2952 break; 2953 } 2954 if (buf != NULL) 2955 goto_buffer(eap, DOBUF_FIRST, FORWARD, buf->b_fnum); 2956 } 2957 #ifdef FEAT_QUICKFIX 2958 else if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo 2959 || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) 2960 { 2961 qf_size = qf_get_size(eap); 2962 if (qf_size <= 0 || eap->line1 > qf_size) 2963 buf = NULL; 2964 else 2965 { 2966 ex_cc(eap); 2967 2968 buf = curbuf; 2969 i = eap->line1 - 1; 2970 if (eap->addr_count <= 0) 2971 /* default is all the quickfix/location list entries */ 2972 eap->line2 = qf_size; 2973 } 2974 } 2975 #endif 2976 else 2977 setpcmark(); 2978 listcmd_busy = TRUE; /* avoids setting pcmark below */ 2979 2980 while (!got_int && buf != NULL) 2981 { 2982 if (eap->cmdidx == CMD_argdo) 2983 { 2984 /* go to argument "i" */ 2985 if (i == ARGCOUNT) 2986 break; 2987 /* Don't call do_argfile() when already there, it will try 2988 * reloading the file. */ 2989 if (curwin->w_arg_idx != i || !editing_arg_idx(curwin)) 2990 { 2991 /* Clear 'shm' to avoid that the file message overwrites 2992 * any output from the command. */ 2993 p_shm_save = vim_strsave(p_shm); 2994 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0); 2995 do_argfile(eap, i); 2996 set_option_value((char_u *)"shm", 0L, p_shm_save, 0); 2997 vim_free(p_shm_save); 2998 } 2999 if (curwin->w_arg_idx != i) 3000 break; 3001 } 3002 #ifdef FEAT_WINDOWS 3003 else if (eap->cmdidx == CMD_windo) 3004 { 3005 /* go to window "wp" */ 3006 if (!win_valid(wp)) 3007 break; 3008 win_goto(wp); 3009 if (curwin != wp) 3010 break; /* something must be wrong */ 3011 wp = curwin->w_next; 3012 } 3013 else if (eap->cmdidx == CMD_tabdo) 3014 { 3015 /* go to window "tp" */ 3016 if (!valid_tabpage(tp)) 3017 break; 3018 goto_tabpage_tp(tp, TRUE, TRUE); 3019 tp = tp->tp_next; 3020 } 3021 #endif 3022 else if (eap->cmdidx == CMD_bufdo) 3023 { 3024 /* Remember the number of the next listed buffer, in case 3025 * ":bwipe" is used or autocommands do something strange. */ 3026 next_fnum = -1; 3027 for (buf = curbuf->b_next; buf != NULL; buf = buf->b_next) 3028 if (buf->b_p_bl) 3029 { 3030 next_fnum = buf->b_fnum; 3031 break; 3032 } 3033 } 3034 3035 ++i; 3036 3037 /* execute the command */ 3038 do_cmdline(eap->arg, eap->getline, eap->cookie, 3039 DOCMD_VERBOSE + DOCMD_NOWAIT); 3040 3041 if (eap->cmdidx == CMD_bufdo) 3042 { 3043 /* Done? */ 3044 if (next_fnum < 0 || next_fnum > eap->line2) 3045 break; 3046 /* Check if the buffer still exists. */ 3047 FOR_ALL_BUFFERS(buf) 3048 if (buf->b_fnum == next_fnum) 3049 break; 3050 if (buf == NULL) 3051 break; 3052 3053 /* Go to the next buffer. Clear 'shm' to avoid that the file 3054 * message overwrites any output from the command. */ 3055 p_shm_save = vim_strsave(p_shm); 3056 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0); 3057 goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum); 3058 set_option_value((char_u *)"shm", 0L, p_shm_save, 0); 3059 vim_free(p_shm_save); 3060 3061 /* If autocommands took us elsewhere, quit here. */ 3062 if (curbuf->b_fnum != next_fnum) 3063 break; 3064 } 3065 3066 #ifdef FEAT_QUICKFIX 3067 if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo 3068 || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) 3069 { 3070 if (i >= qf_size || i >= eap->line2) 3071 break; 3072 3073 qf_idx = qf_get_cur_idx(eap); 3074 3075 ex_cnext(eap); 3076 3077 /* If jumping to the next quickfix entry fails, quit here */ 3078 if (qf_get_cur_idx(eap) == qf_idx) 3079 break; 3080 } 3081 #endif 3082 3083 if (eap->cmdidx == CMD_windo) 3084 { 3085 validate_cursor(); /* cursor may have moved */ 3086 #ifdef FEAT_SCROLLBIND 3087 /* required when 'scrollbind' has been set */ 3088 if (curwin->w_p_scb) 3089 do_check_scrollbind(TRUE); 3090 #endif 3091 } 3092 3093 #ifdef FEAT_WINDOWS 3094 if (eap->cmdidx == CMD_windo || eap->cmdidx == CMD_tabdo) 3095 if (i+1 > eap->line2) 3096 break; 3097 #endif 3098 if (eap->cmdidx == CMD_argdo && i >= eap->line2) 3099 break; 3100 } 3101 listcmd_busy = FALSE; 3102 } 3103 3104 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL) 3105 if (save_ei != NULL) 3106 { 3107 au_event_restore(save_ei); 3108 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, 3109 curbuf->b_fname, TRUE, curbuf); 3110 } 3111 #endif 3112 #ifdef FEAT_CLIPBOARD 3113 end_global_changes(); 3114 #endif 3115 } 3116 3117 /* 3118 * Add files[count] to the arglist of the current window after arg "after". 3119 * The file names in files[count] must have been allocated and are taken over. 3120 * Files[] itself is not taken over. 3121 * Returns index of first added argument. Returns -1 when failed (out of mem). 3122 */ 3123 static int 3124 alist_add_list( 3125 int count, 3126 char_u **files, 3127 int after) /* where to add: 0 = before first one */ 3128 { 3129 int i; 3130 int old_argcount = ARGCOUNT; 3131 3132 if (ga_grow(&ALIST(curwin)->al_ga, count) == OK) 3133 { 3134 if (after < 0) 3135 after = 0; 3136 if (after > ARGCOUNT) 3137 after = ARGCOUNT; 3138 if (after < ARGCOUNT) 3139 mch_memmove(&(ARGLIST[after + count]), &(ARGLIST[after]), 3140 (ARGCOUNT - after) * sizeof(aentry_T)); 3141 for (i = 0; i < count; ++i) 3142 { 3143 ARGLIST[after + i].ae_fname = files[i]; 3144 ARGLIST[after + i].ae_fnum = buflist_add(files[i], BLN_LISTED); 3145 } 3146 ALIST(curwin)->al_ga.ga_len += count; 3147 if (old_argcount > 0 && curwin->w_arg_idx >= after) 3148 curwin->w_arg_idx += count; 3149 return after; 3150 } 3151 3152 for (i = 0; i < count; ++i) 3153 vim_free(files[i]); 3154 return -1; 3155 } 3156 3157 #endif /* FEAT_LISTCMDS */ 3158 3159 #ifdef FEAT_EVAL 3160 /* 3161 * ":compiler[!] {name}" 3162 */ 3163 void 3164 ex_compiler(exarg_T *eap) 3165 { 3166 char_u *buf; 3167 char_u *old_cur_comp = NULL; 3168 char_u *p; 3169 3170 if (*eap->arg == NUL) 3171 { 3172 /* List all compiler scripts. */ 3173 do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')"); 3174 /* ) keep the indenter happy... */ 3175 } 3176 else 3177 { 3178 buf = alloc((unsigned)(STRLEN(eap->arg) + 14)); 3179 if (buf != NULL) 3180 { 3181 if (eap->forceit) 3182 { 3183 /* ":compiler! {name}" sets global options */ 3184 do_cmdline_cmd((char_u *) 3185 "command -nargs=* CompilerSet set <args>"); 3186 } 3187 else 3188 { 3189 /* ":compiler! {name}" sets local options. 3190 * To remain backwards compatible "current_compiler" is always 3191 * used. A user's compiler plugin may set it, the distributed 3192 * plugin will then skip the settings. Afterwards set 3193 * "b:current_compiler" and restore "current_compiler". 3194 * Explicitly prepend "g:" to make it work in a function. */ 3195 old_cur_comp = get_var_value((char_u *)"g:current_compiler"); 3196 if (old_cur_comp != NULL) 3197 old_cur_comp = vim_strsave(old_cur_comp); 3198 do_cmdline_cmd((char_u *) 3199 "command -nargs=* CompilerSet setlocal <args>"); 3200 } 3201 do_unlet((char_u *)"g:current_compiler", TRUE); 3202 do_unlet((char_u *)"b:current_compiler", TRUE); 3203 3204 sprintf((char *)buf, "compiler/%s.vim", eap->arg); 3205 if (source_runtime(buf, DIP_ALL) == FAIL) 3206 EMSG2(_("E666: compiler not supported: %s"), eap->arg); 3207 vim_free(buf); 3208 3209 do_cmdline_cmd((char_u *)":delcommand CompilerSet"); 3210 3211 /* Set "b:current_compiler" from "current_compiler". */ 3212 p = get_var_value((char_u *)"g:current_compiler"); 3213 if (p != NULL) 3214 set_internal_string_var((char_u *)"b:current_compiler", p); 3215 3216 /* Restore "current_compiler" for ":compiler {name}". */ 3217 if (!eap->forceit) 3218 { 3219 if (old_cur_comp != NULL) 3220 { 3221 set_internal_string_var((char_u *)"g:current_compiler", 3222 old_cur_comp); 3223 vim_free(old_cur_comp); 3224 } 3225 else 3226 do_unlet((char_u *)"g:current_compiler", TRUE); 3227 } 3228 } 3229 } 3230 } 3231 #endif 3232 3233 /* 3234 * ":runtime [what] {name}" 3235 */ 3236 void 3237 ex_runtime(exarg_T *eap) 3238 { 3239 char_u *arg = eap->arg; 3240 char_u *p = skiptowhite(arg); 3241 int len = (int)(p - arg); 3242 int flags = eap->forceit ? DIP_ALL : 0; 3243 3244 if (STRNCMP(arg, "START", len) == 0) 3245 { 3246 flags += DIP_START + DIP_NORTP; 3247 arg = skipwhite(arg + len); 3248 } 3249 else if (STRNCMP(arg, "OPT", len) == 0) 3250 { 3251 flags += DIP_OPT + DIP_NORTP; 3252 arg = skipwhite(arg + len); 3253 } 3254 else if (STRNCMP(arg, "PACK", len) == 0) 3255 { 3256 flags += DIP_START + DIP_OPT + DIP_NORTP; 3257 arg = skipwhite(arg + len); 3258 } 3259 else if (STRNCMP(arg, "ALL", len) == 0) 3260 { 3261 flags += DIP_START + DIP_OPT; 3262 arg = skipwhite(arg + len); 3263 } 3264 3265 source_runtime(arg, flags); 3266 } 3267 3268 static void 3269 source_callback(char_u *fname, void *cookie UNUSED) 3270 { 3271 (void)do_source(fname, FALSE, DOSO_NONE); 3272 } 3273 3274 /* 3275 * Source the file "name" from all directories in 'runtimepath'. 3276 * "name" can contain wildcards. 3277 * When "flags" has DIP_ALL: source all files, otherwise only the first one. 3278 * 3279 * return FAIL when no file could be sourced, OK otherwise. 3280 */ 3281 int 3282 source_runtime(char_u *name, int flags) 3283 { 3284 return do_in_runtimepath(name, flags, source_callback, NULL); 3285 } 3286 3287 /* 3288 * Find the file "name" in all directories in "path" and invoke 3289 * "callback(fname, cookie)". 3290 * "name" can contain wildcards. 3291 * When "flags" has DIP_ALL: source all files, otherwise only the first one. 3292 * When "flags" has DIP_DIR: find directories instead of files. 3293 * When "flags" has DIP_ERR: give an error message if there is no match. 3294 * 3295 * return FAIL when no file could be sourced, OK otherwise. 3296 */ 3297 int 3298 do_in_path( 3299 char_u *path, 3300 char_u *name, 3301 int flags, 3302 void (*callback)(char_u *fname, void *ck), 3303 void *cookie) 3304 { 3305 char_u *rtp; 3306 char_u *np; 3307 char_u *buf; 3308 char_u *rtp_copy; 3309 char_u *tail; 3310 int num_files; 3311 char_u **files; 3312 int i; 3313 int did_one = FALSE; 3314 #ifdef AMIGA 3315 struct Process *proc = (struct Process *)FindTask(0L); 3316 APTR save_winptr = proc->pr_WindowPtr; 3317 3318 /* Avoid a requester here for a volume that doesn't exist. */ 3319 proc->pr_WindowPtr = (APTR)-1L; 3320 #endif 3321 3322 /* Make a copy of 'runtimepath'. Invoking the callback may change the 3323 * value. */ 3324 rtp_copy = vim_strsave(path); 3325 buf = alloc(MAXPATHL); 3326 if (buf != NULL && rtp_copy != NULL) 3327 { 3328 if (p_verbose > 1 && name != NULL) 3329 { 3330 verbose_enter(); 3331 smsg((char_u *)_("Searching for \"%s\" in \"%s\""), 3332 (char *)name, (char *)path); 3333 verbose_leave(); 3334 } 3335 3336 /* Loop over all entries in 'runtimepath'. */ 3337 rtp = rtp_copy; 3338 while (*rtp != NUL && ((flags & DIP_ALL) || !did_one)) 3339 { 3340 size_t buflen; 3341 3342 /* Copy the path from 'runtimepath' to buf[]. */ 3343 copy_option_part(&rtp, buf, MAXPATHL, ","); 3344 buflen = STRLEN(buf); 3345 3346 /* Skip after or non-after directories. */ 3347 if (flags & (DIP_NOAFTER | DIP_AFTER)) 3348 { 3349 int is_after = buflen >= 5 3350 && STRCMP(buf + buflen - 5, "after") == 0; 3351 3352 if ((is_after && (flags & DIP_NOAFTER)) 3353 || (!is_after && (flags & DIP_AFTER))) 3354 continue; 3355 } 3356 3357 if (name == NULL) 3358 { 3359 (*callback)(buf, (void *) &cookie); 3360 if (!did_one) 3361 did_one = (cookie == NULL); 3362 } 3363 else if (buflen + STRLEN(name) + 2 < MAXPATHL) 3364 { 3365 add_pathsep(buf); 3366 tail = buf + STRLEN(buf); 3367 3368 /* Loop over all patterns in "name" */ 3369 np = name; 3370 while (*np != NUL && ((flags & DIP_ALL) || !did_one)) 3371 { 3372 /* Append the pattern from "name" to buf[]. */ 3373 copy_option_part(&np, tail, (int)(MAXPATHL - (tail - buf)), 3374 "\t "); 3375 3376 if (p_verbose > 2) 3377 { 3378 verbose_enter(); 3379 smsg((char_u *)_("Searching for \"%s\""), buf); 3380 verbose_leave(); 3381 } 3382 3383 /* Expand wildcards, invoke the callback for each match. */ 3384 if (gen_expand_wildcards(1, &buf, &num_files, &files, 3385 (flags & DIP_DIR) ? EW_DIR : EW_FILE) == OK) 3386 { 3387 for (i = 0; i < num_files; ++i) 3388 { 3389 (*callback)(files[i], cookie); 3390 did_one = TRUE; 3391 if (!(flags & DIP_ALL)) 3392 break; 3393 } 3394 FreeWild(num_files, files); 3395 } 3396 } 3397 } 3398 } 3399 } 3400 vim_free(buf); 3401 vim_free(rtp_copy); 3402 if (!did_one && name != NULL) 3403 { 3404 char *basepath = path == p_rtp ? "runtimepath" : "packpath"; 3405 3406 if (flags & DIP_ERR) 3407 EMSG3(_(e_dirnotf), basepath, name); 3408 else if (p_verbose > 0) 3409 { 3410 verbose_enter(); 3411 smsg((char_u *)_("not found in '%s': \"%s\""), basepath, name); 3412 verbose_leave(); 3413 } 3414 } 3415 3416 #ifdef AMIGA 3417 proc->pr_WindowPtr = save_winptr; 3418 #endif 3419 3420 return did_one ? OK : FAIL; 3421 } 3422 3423 /* 3424 * Find "name" in 'runtimepath'. When found, invoke the callback function for 3425 * it: callback(fname, "cookie") 3426 * When "flags" has DIP_ALL repeat for all matches, otherwise only the first 3427 * one is used. 3428 * Returns OK when at least one match found, FAIL otherwise. 3429 * 3430 * If "name" is NULL calls callback for each entry in runtimepath. Cookie is 3431 * passed by reference in this case, setting it to NULL indicates that callback 3432 * has done its job. 3433 */ 3434 int 3435 do_in_runtimepath( 3436 char_u *name, 3437 int flags, 3438 void (*callback)(char_u *fname, void *ck), 3439 void *cookie) 3440 { 3441 int done = FAIL; 3442 char_u *s; 3443 int len; 3444 char *start_dir = "pack/*/start/*/%s"; 3445 char *opt_dir = "pack/*/opt/*/%s"; 3446 3447 if ((flags & DIP_NORTP) == 0) 3448 done = do_in_path(p_rtp, name, flags, callback, cookie); 3449 3450 if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_START)) 3451 { 3452 len = (int)(STRLEN(start_dir) + STRLEN(name)); 3453 s = alloc(len); 3454 if (s == NULL) 3455 return FAIL; 3456 vim_snprintf((char *)s, len, start_dir, name); 3457 done = do_in_path(p_pp, s, flags, callback, cookie); 3458 vim_free(s); 3459 } 3460 3461 if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_OPT)) 3462 { 3463 len = (int)(STRLEN(opt_dir) + STRLEN(name)); 3464 s = alloc(len); 3465 if (s == NULL) 3466 return FAIL; 3467 vim_snprintf((char *)s, len, opt_dir, name); 3468 done = do_in_path(p_pp, s, flags, callback, cookie); 3469 vim_free(s); 3470 } 3471 3472 return done; 3473 } 3474 3475 /* 3476 * Expand wildcards in "pat" and invoke do_source() for each match. 3477 */ 3478 static void 3479 source_all_matches(char_u *pat) 3480 { 3481 int num_files; 3482 char_u **files; 3483 int i; 3484 3485 if (gen_expand_wildcards(1, &pat, &num_files, &files, EW_FILE) == OK) 3486 { 3487 for (i = 0; i < num_files; ++i) 3488 (void)do_source(files[i], FALSE, DOSO_NONE); 3489 FreeWild(num_files, files); 3490 } 3491 } 3492 3493 /* used for "cookie" of add_pack_plugin() */ 3494 static int APP_ADD_DIR; 3495 static int APP_LOAD; 3496 static int APP_BOTH; 3497 3498 static void 3499 add_pack_plugin(char_u *fname, void *cookie) 3500 { 3501 char_u *p4, *p3, *p2, *p1, *p; 3502 char_u *insp; 3503 int c; 3504 char_u *new_rtp; 3505 int keep; 3506 size_t oldlen; 3507 size_t addlen; 3508 char_u *afterdir; 3509 size_t afterlen = 0; 3510 char_u *ffname = fix_fname(fname); 3511 size_t fname_len; 3512 3513 if (ffname == NULL) 3514 return; 3515 if (cookie != &APP_LOAD && strstr((char *)p_rtp, (char *)ffname) == NULL) 3516 { 3517 /* directory is not yet in 'runtimepath', add it */ 3518 p4 = p3 = p2 = p1 = get_past_head(ffname); 3519 for (p = p1; *p; mb_ptr_adv(p)) 3520 if (vim_ispathsep_nocolon(*p)) 3521 { 3522 p4 = p3; p3 = p2; p2 = p1; p1 = p; 3523 } 3524 3525 /* now we have: 3526 * rtp/pack/name/start/name 3527 * p4 p3 p2 p1 3528 * 3529 * find the part up to "pack" in 'runtimepath' */ 3530 c = *p4; 3531 *p4 = NUL; 3532 3533 /* Find "ffname" in "p_rtp", ignoring '/' vs '\' differences. */ 3534 fname_len = STRLEN(ffname); 3535 insp = p_rtp; 3536 for (;;) 3537 { 3538 if (vim_fnamencmp(insp, ffname, fname_len) == 0) 3539 break; 3540 insp = vim_strchr(insp, ','); 3541 if (insp == NULL) 3542 break; 3543 ++insp; 3544 } 3545 3546 if (insp == NULL) 3547 /* not found, append at the end */ 3548 insp = p_rtp + STRLEN(p_rtp); 3549 else 3550 { 3551 /* append after the matching directory. */ 3552 insp += STRLEN(ffname); 3553 while (*insp != NUL && *insp != ',') 3554 ++insp; 3555 } 3556 *p4 = c; 3557 3558 /* check if rtp/pack/name/start/name/after exists */ 3559 afterdir = concat_fnames(ffname, (char_u *)"after", TRUE); 3560 if (afterdir != NULL && mch_isdir(afterdir)) 3561 afterlen = STRLEN(afterdir) + 1; /* add one for comma */ 3562 3563 oldlen = STRLEN(p_rtp); 3564 addlen = STRLEN(ffname) + 1; /* add one for comma */ 3565 new_rtp = alloc((int)(oldlen + addlen + afterlen + 1)); /* add one for NUL */ 3566 if (new_rtp == NULL) 3567 goto theend; 3568 keep = (int)(insp - p_rtp); 3569 mch_memmove(new_rtp, p_rtp, keep); 3570 new_rtp[keep] = ','; 3571 mch_memmove(new_rtp + keep + 1, ffname, addlen); 3572 if (p_rtp[keep] != NUL) 3573 mch_memmove(new_rtp + keep + addlen, p_rtp + keep, 3574 oldlen - keep + 1); 3575 if (afterlen > 0) 3576 { 3577 STRCAT(new_rtp, ","); 3578 STRCAT(new_rtp, afterdir); 3579 } 3580 set_option_value((char_u *)"rtp", 0L, new_rtp, 0); 3581 vim_free(new_rtp); 3582 vim_free(afterdir); 3583 } 3584 3585 if (cookie != &APP_ADD_DIR) 3586 { 3587 static char *plugpat = "%s/plugin/**/*.vim"; 3588 static char *ftpat = "%s/ftdetect/*.vim"; 3589 int len; 3590 char_u *pat; 3591 3592 len = (int)STRLEN(ffname) + (int)STRLEN(ftpat); 3593 pat = alloc(len); 3594 if (pat == NULL) 3595 goto theend; 3596 vim_snprintf((char *)pat, len, plugpat, ffname); 3597 source_all_matches(pat); 3598 3599 #ifdef FEAT_AUTOCMD 3600 { 3601 char_u *cmd = vim_strsave((char_u *)"g:did_load_filetypes"); 3602 3603 /* If runtime/filetype.vim wasn't loaded yet, the scripts will be 3604 * found when it loads. */ 3605 if (cmd != NULL && eval_to_number(cmd) > 0) 3606 { 3607 do_cmdline_cmd((char_u *)"augroup filetypedetect"); 3608 vim_snprintf((char *)pat, len, ftpat, ffname); 3609 source_all_matches(pat); 3610 do_cmdline_cmd((char_u *)"augroup END"); 3611 } 3612 vim_free(cmd); 3613 } 3614 #endif 3615 vim_free(pat); 3616 } 3617 3618 theend: 3619 vim_free(ffname); 3620 } 3621 3622 static int did_source_packages = FALSE; 3623 3624 /* 3625 * ":packloadall" 3626 * Find plugins in the package directories and source them. 3627 * "eap" is NULL when invoked during startup. 3628 */ 3629 void 3630 ex_packloadall(exarg_T *eap) 3631 { 3632 if (!did_source_packages || (eap != NULL && eap->forceit)) 3633 { 3634 did_source_packages = TRUE; 3635 3636 /* First do a round to add all directories to 'runtimepath', then load 3637 * the plugins. This allows for plugins to use an autoload directory 3638 * of another plugin. */ 3639 do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, 3640 add_pack_plugin, &APP_ADD_DIR); 3641 do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, 3642 add_pack_plugin, &APP_LOAD); 3643 } 3644 } 3645 3646 /* 3647 * ":packadd[!] {name}" 3648 */ 3649 void 3650 ex_packadd(exarg_T *eap) 3651 { 3652 static char *plugpat = "pack/*/opt/%s"; 3653 int len; 3654 char *pat; 3655 3656 len = (int)STRLEN(plugpat) + (int)STRLEN(eap->arg); 3657 pat = (char *)alloc(len); 3658 if (pat == NULL) 3659 return; 3660 vim_snprintf(pat, len, plugpat, eap->arg); 3661 do_in_path(p_pp, (char_u *)pat, DIP_ALL + DIP_DIR + DIP_ERR, 3662 add_pack_plugin, eap->forceit ? &APP_ADD_DIR : &APP_BOTH); 3663 vim_free(pat); 3664 } 3665 3666 #if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD) 3667 /* 3668 * ":options" 3669 */ 3670 void 3671 ex_options( 3672 exarg_T *eap UNUSED) 3673 { 3674 cmd_source((char_u *)SYS_OPTWIN_FILE, NULL); 3675 } 3676 #endif 3677 3678 /* 3679 * ":source {fname}" 3680 */ 3681 void 3682 ex_source(exarg_T *eap) 3683 { 3684 #ifdef FEAT_BROWSE 3685 if (cmdmod.browse) 3686 { 3687 char_u *fname = NULL; 3688 3689 fname = do_browse(0, (char_u *)_("Source Vim script"), eap->arg, 3690 NULL, NULL, BROWSE_FILTER_MACROS, NULL); 3691 if (fname != NULL) 3692 { 3693 cmd_source(fname, eap); 3694 vim_free(fname); 3695 } 3696 } 3697 else 3698 #endif 3699 cmd_source(eap->arg, eap); 3700 } 3701 3702 static void 3703 cmd_source(char_u *fname, exarg_T *eap) 3704 { 3705 if (*fname == NUL) 3706 EMSG(_(e_argreq)); 3707 3708 else if (eap != NULL && eap->forceit) 3709 /* ":source!": read Normal mode commands 3710 * Need to execute the commands directly. This is required at least 3711 * for: 3712 * - ":g" command busy 3713 * - after ":argdo", ":windo" or ":bufdo" 3714 * - another command follows 3715 * - inside a loop 3716 */ 3717 openscript(fname, global_busy || listcmd_busy || eap->nextcmd != NULL 3718 #ifdef FEAT_EVAL 3719 || eap->cstack->cs_idx >= 0 3720 #endif 3721 ); 3722 3723 /* ":source" read ex commands */ 3724 else if (do_source(fname, FALSE, DOSO_NONE) == FAIL) 3725 EMSG2(_(e_notopen), fname); 3726 } 3727 3728 /* 3729 * ":source" and associated commands. 3730 */ 3731 /* 3732 * Structure used to store info for each sourced file. 3733 * It is shared between do_source() and getsourceline(). 3734 * This is required, because it needs to be handed to do_cmdline() and 3735 * sourcing can be done recursively. 3736 */ 3737 struct source_cookie 3738 { 3739 FILE *fp; /* opened file for sourcing */ 3740 char_u *nextline; /* if not NULL: line that was read ahead */ 3741 int finished; /* ":finish" used */ 3742 #if defined(USE_CRNL) || defined(USE_CR) 3743 int fileformat; /* EOL_UNKNOWN, EOL_UNIX or EOL_DOS */ 3744 int error; /* TRUE if LF found after CR-LF */ 3745 #endif 3746 #ifdef FEAT_EVAL 3747 linenr_T breakpoint; /* next line with breakpoint or zero */ 3748 char_u *fname; /* name of sourced file */ 3749 int dbg_tick; /* debug_tick when breakpoint was set */ 3750 int level; /* top nesting level of sourced file */ 3751 #endif 3752 #ifdef FEAT_MBYTE 3753 vimconv_T conv; /* type of conversion */ 3754 #endif 3755 }; 3756 3757 #ifdef FEAT_EVAL 3758 /* 3759 * Return the address holding the next breakpoint line for a source cookie. 3760 */ 3761 linenr_T * 3762 source_breakpoint(void *cookie) 3763 { 3764 return &((struct source_cookie *)cookie)->breakpoint; 3765 } 3766 3767 /* 3768 * Return the address holding the debug tick for a source cookie. 3769 */ 3770 int * 3771 source_dbg_tick(void *cookie) 3772 { 3773 return &((struct source_cookie *)cookie)->dbg_tick; 3774 } 3775 3776 /* 3777 * Return the nesting level for a source cookie. 3778 */ 3779 int 3780 source_level(void *cookie) 3781 { 3782 return ((struct source_cookie *)cookie)->level; 3783 } 3784 #endif 3785 3786 static char_u *get_one_sourceline(struct source_cookie *sp); 3787 3788 #if (defined(WIN32) && defined(FEAT_CSCOPE)) || defined(HAVE_FD_CLOEXEC) 3789 # define USE_FOPEN_NOINH 3790 static FILE *fopen_noinh_readbin(char *filename); 3791 3792 /* 3793 * Special function to open a file without handle inheritance. 3794 * When possible the handle is closed on exec(). 3795 */ 3796 static FILE * 3797 fopen_noinh_readbin(char *filename) 3798 { 3799 # ifdef WIN32 3800 int fd_tmp = mch_open(filename, O_RDONLY | O_BINARY | O_NOINHERIT, 0); 3801 # else 3802 int fd_tmp = mch_open(filename, O_RDONLY, 0); 3803 # endif 3804 3805 if (fd_tmp == -1) 3806 return NULL; 3807 3808 # ifdef HAVE_FD_CLOEXEC 3809 { 3810 int fdflags = fcntl(fd_tmp, F_GETFD); 3811 if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) 3812 (void)fcntl(fd_tmp, F_SETFD, fdflags | FD_CLOEXEC); 3813 } 3814 # endif 3815 3816 return fdopen(fd_tmp, READBIN); 3817 } 3818 #endif 3819 3820 3821 /* 3822 * do_source: Read the file "fname" and execute its lines as EX commands. 3823 * 3824 * This function may be called recursively! 3825 * 3826 * return FAIL if file could not be opened, OK otherwise 3827 */ 3828 int 3829 do_source( 3830 char_u *fname, 3831 int check_other, /* check for .vimrc and _vimrc */ 3832 int is_vimrc) /* DOSO_ value */ 3833 { 3834 struct source_cookie cookie; 3835 char_u *save_sourcing_name; 3836 linenr_T save_sourcing_lnum; 3837 char_u *p; 3838 char_u *fname_exp; 3839 char_u *firstline = NULL; 3840 int retval = FAIL; 3841 #ifdef FEAT_EVAL 3842 scid_T save_current_SID; 3843 static scid_T last_current_SID = 0; 3844 void *save_funccalp; 3845 int save_debug_break_level = debug_break_level; 3846 scriptitem_T *si = NULL; 3847 # ifdef UNIX 3848 stat_T st; 3849 int stat_ok; 3850 # endif 3851 #endif 3852 #ifdef STARTUPTIME 3853 struct timeval tv_rel; 3854 struct timeval tv_start; 3855 #endif 3856 #ifdef FEAT_PROFILE 3857 proftime_T wait_start; 3858 #endif 3859 3860 p = expand_env_save(fname); 3861 if (p == NULL) 3862 return retval; 3863 fname_exp = fix_fname(p); 3864 vim_free(p); 3865 if (fname_exp == NULL) 3866 return retval; 3867 if (mch_isdir(fname_exp)) 3868 { 3869 smsg((char_u *)_("Cannot source a directory: \"%s\""), fname); 3870 goto theend; 3871 } 3872 3873 #ifdef FEAT_AUTOCMD 3874 /* Apply SourceCmd autocommands, they should get the file and source it. */ 3875 if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL) 3876 && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp, 3877 FALSE, curbuf)) 3878 { 3879 # ifdef FEAT_EVAL 3880 retval = aborting() ? FAIL : OK; 3881 # else 3882 retval = OK; 3883 # endif 3884 goto theend; 3885 } 3886 3887 /* Apply SourcePre autocommands, they may get the file. */ 3888 apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, FALSE, curbuf); 3889 #endif 3890 3891 #ifdef USE_FOPEN_NOINH 3892 cookie.fp = fopen_noinh_readbin((char *)fname_exp); 3893 #else 3894 cookie.fp = mch_fopen((char *)fname_exp, READBIN); 3895 #endif 3896 if (cookie.fp == NULL && check_other) 3897 { 3898 /* 3899 * Try again, replacing file name ".vimrc" by "_vimrc" or vice versa, 3900 * and ".exrc" by "_exrc" or vice versa. 3901 */ 3902 p = gettail(fname_exp); 3903 if ((*p == '.' || *p == '_') 3904 && (STRICMP(p + 1, "vimrc") == 0 3905 || STRICMP(p + 1, "gvimrc") == 0 3906 || STRICMP(p + 1, "exrc") == 0)) 3907 { 3908 if (*p == '_') 3909 *p = '.'; 3910 else 3911 *p = '_'; 3912 #ifdef USE_FOPEN_NOINH 3913 cookie.fp = fopen_noinh_readbin((char *)fname_exp); 3914 #else 3915 cookie.fp = mch_fopen((char *)fname_exp, READBIN); 3916 #endif 3917 } 3918 } 3919 3920 if (cookie.fp == NULL) 3921 { 3922 if (p_verbose > 0) 3923 { 3924 verbose_enter(); 3925 if (sourcing_name == NULL) 3926 smsg((char_u *)_("could not source \"%s\""), fname); 3927 else 3928 smsg((char_u *)_("line %ld: could not source \"%s\""), 3929 sourcing_lnum, fname); 3930 verbose_leave(); 3931 } 3932 goto theend; 3933 } 3934 3935 /* 3936 * The file exists. 3937 * - In verbose mode, give a message. 3938 * - For a vimrc file, may want to set 'compatible', call vimrc_found(). 3939 */ 3940 if (p_verbose > 1) 3941 { 3942 verbose_enter(); 3943 if (sourcing_name == NULL) 3944 smsg((char_u *)_("sourcing \"%s\""), fname); 3945 else 3946 smsg((char_u *)_("line %ld: sourcing \"%s\""), 3947 sourcing_lnum, fname); 3948 verbose_leave(); 3949 } 3950 if (is_vimrc == DOSO_VIMRC) 3951 vimrc_found(fname_exp, (char_u *)"MYVIMRC"); 3952 else if (is_vimrc == DOSO_GVIMRC) 3953 vimrc_found(fname_exp, (char_u *)"MYGVIMRC"); 3954 3955 #ifdef USE_CRNL 3956 /* If no automatic file format: Set default to CR-NL. */ 3957 if (*p_ffs == NUL) 3958 cookie.fileformat = EOL_DOS; 3959 else 3960 cookie.fileformat = EOL_UNKNOWN; 3961 cookie.error = FALSE; 3962 #endif 3963 3964 #ifdef USE_CR 3965 /* If no automatic file format: Set default to CR. */ 3966 if (*p_ffs == NUL) 3967 cookie.fileformat = EOL_MAC; 3968 else 3969 cookie.fileformat = EOL_UNKNOWN; 3970 cookie.error = FALSE; 3971 #endif 3972 3973 cookie.nextline = NULL; 3974 cookie.finished = FALSE; 3975 3976 #ifdef FEAT_EVAL 3977 /* 3978 * Check if this script has a breakpoint. 3979 */ 3980 cookie.breakpoint = dbg_find_breakpoint(TRUE, fname_exp, (linenr_T)0); 3981 cookie.fname = fname_exp; 3982 cookie.dbg_tick = debug_tick; 3983 3984 cookie.level = ex_nesting_level; 3985 #endif 3986 3987 /* 3988 * Keep the sourcing name/lnum, for recursive calls. 3989 */ 3990 save_sourcing_name = sourcing_name; 3991 sourcing_name = fname_exp; 3992 save_sourcing_lnum = sourcing_lnum; 3993 sourcing_lnum = 0; 3994 3995 #ifdef FEAT_MBYTE 3996 cookie.conv.vc_type = CONV_NONE; /* no conversion */ 3997 3998 /* Read the first line so we can check for a UTF-8 BOM. */ 3999 firstline = getsourceline(0, (void *)&cookie, 0); 4000 if (firstline != NULL && STRLEN(firstline) >= 3 && firstline[0] == 0xef 4001 && firstline[1] == 0xbb && firstline[2] == 0xbf) 4002 { 4003 /* Found BOM; setup conversion, skip over BOM and recode the line. */ 4004 convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc); 4005 p = string_convert(&cookie.conv, firstline + 3, NULL); 4006 if (p == NULL) 4007 p = vim_strsave(firstline + 3); 4008 if (p != NULL) 4009 { 4010 vim_free(firstline); 4011 firstline = p; 4012 } 4013 } 4014 #endif 4015 4016 #ifdef STARTUPTIME 4017 if (time_fd != NULL) 4018 time_push(&tv_rel, &tv_start); 4019 #endif 4020 4021 #ifdef FEAT_EVAL 4022 # ifdef FEAT_PROFILE 4023 if (do_profiling == PROF_YES) 4024 prof_child_enter(&wait_start); /* entering a child now */ 4025 # endif 4026 4027 /* Don't use local function variables, if called from a function. 4028 * Also starts profiling timer for nested script. */ 4029 save_funccalp = save_funccal(); 4030 4031 /* 4032 * Check if this script was sourced before to finds its SID. 4033 * If it's new, generate a new SID. 4034 */ 4035 save_current_SID = current_SID; 4036 # ifdef UNIX 4037 stat_ok = (mch_stat((char *)fname_exp, &st) >= 0); 4038 # endif 4039 for (current_SID = script_items.ga_len; current_SID > 0; --current_SID) 4040 { 4041 si = &SCRIPT_ITEM(current_SID); 4042 if (si->sn_name != NULL 4043 && ( 4044 # ifdef UNIX 4045 /* Compare dev/ino when possible, it catches symbolic 4046 * links. Also compare file names, the inode may change 4047 * when the file was edited. */ 4048 ((stat_ok && si->sn_dev_valid) 4049 && (si->sn_dev == st.st_dev 4050 && si->sn_ino == st.st_ino)) || 4051 # endif 4052 fnamecmp(si->sn_name, fname_exp) == 0)) 4053 break; 4054 } 4055 if (current_SID == 0) 4056 { 4057 current_SID = ++last_current_SID; 4058 if (ga_grow(&script_items, (int)(current_SID - script_items.ga_len)) 4059 == FAIL) 4060 goto almosttheend; 4061 while (script_items.ga_len < current_SID) 4062 { 4063 ++script_items.ga_len; 4064 SCRIPT_ITEM(script_items.ga_len).sn_name = NULL; 4065 # ifdef FEAT_PROFILE 4066 SCRIPT_ITEM(script_items.ga_len).sn_prof_on = FALSE; 4067 # endif 4068 } 4069 si = &SCRIPT_ITEM(current_SID); 4070 si->sn_name = fname_exp; 4071 fname_exp = NULL; 4072 # ifdef UNIX 4073 if (stat_ok) 4074 { 4075 si->sn_dev_valid = TRUE; 4076 si->sn_dev = st.st_dev; 4077 si->sn_ino = st.st_ino; 4078 } 4079 else 4080 si->sn_dev_valid = FALSE; 4081 # endif 4082 4083 /* Allocate the local script variables to use for this script. */ 4084 new_script_vars(current_SID); 4085 } 4086 4087 # ifdef FEAT_PROFILE 4088 if (do_profiling == PROF_YES) 4089 { 4090 int forceit; 4091 4092 /* Check if we do profiling for this script. */ 4093 if (!si->sn_prof_on && has_profiling(TRUE, si->sn_name, &forceit)) 4094 { 4095 script_do_profile(si); 4096 si->sn_pr_force = forceit; 4097 } 4098 if (si->sn_prof_on) 4099 { 4100 ++si->sn_pr_count; 4101 profile_start(&si->sn_pr_start); 4102 profile_zero(&si->sn_pr_children); 4103 } 4104 } 4105 # endif 4106 #endif 4107 4108 /* 4109 * Call do_cmdline, which will call getsourceline() to get the lines. 4110 */ 4111 do_cmdline(firstline, getsourceline, (void *)&cookie, 4112 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT); 4113 retval = OK; 4114 4115 #ifdef FEAT_PROFILE 4116 if (do_profiling == PROF_YES) 4117 { 4118 /* Get "si" again, "script_items" may have been reallocated. */ 4119 si = &SCRIPT_ITEM(current_SID); 4120 if (si->sn_prof_on) 4121 { 4122 profile_end(&si->sn_pr_start); 4123 profile_sub_wait(&wait_start, &si->sn_pr_start); 4124 profile_add(&si->sn_pr_total, &si->sn_pr_start); 4125 profile_self(&si->sn_pr_self, &si->sn_pr_start, 4126 &si->sn_pr_children); 4127 } 4128 } 4129 #endif 4130 4131 if (got_int) 4132 EMSG(_(e_interr)); 4133 sourcing_name = save_sourcing_name; 4134 sourcing_lnum = save_sourcing_lnum; 4135 if (p_verbose > 1) 4136 { 4137 verbose_enter(); 4138 smsg((char_u *)_("finished sourcing %s"), fname); 4139 if (sourcing_name != NULL) 4140 smsg((char_u *)_("continuing in %s"), sourcing_name); 4141 verbose_leave(); 4142 } 4143 #ifdef STARTUPTIME 4144 if (time_fd != NULL) 4145 { 4146 vim_snprintf((char *)IObuff, IOSIZE, "sourcing %s", fname); 4147 time_msg((char *)IObuff, &tv_start); 4148 time_pop(&tv_rel); 4149 } 4150 #endif 4151 4152 #ifdef FEAT_EVAL 4153 /* 4154 * After a "finish" in debug mode, need to break at first command of next 4155 * sourced file. 4156 */ 4157 if (save_debug_break_level > ex_nesting_level 4158 && debug_break_level == ex_nesting_level) 4159 ++debug_break_level; 4160 #endif 4161 4162 #ifdef FEAT_EVAL 4163 almosttheend: 4164 current_SID = save_current_SID; 4165 restore_funccal(save_funccalp); 4166 # ifdef FEAT_PROFILE 4167 if (do_profiling == PROF_YES) 4168 prof_child_exit(&wait_start); /* leaving a child now */ 4169 # endif 4170 #endif 4171 fclose(cookie.fp); 4172 vim_free(cookie.nextline); 4173 vim_free(firstline); 4174 #ifdef FEAT_MBYTE 4175 convert_setup(&cookie.conv, NULL, NULL); 4176 #endif 4177 4178 theend: 4179 vim_free(fname_exp); 4180 return retval; 4181 } 4182 4183 #if defined(FEAT_EVAL) || defined(PROTO) 4184 4185 /* 4186 * ":scriptnames" 4187 */ 4188 void 4189 ex_scriptnames(exarg_T *eap UNUSED) 4190 { 4191 int i; 4192 4193 for (i = 1; i <= script_items.ga_len && !got_int; ++i) 4194 if (SCRIPT_ITEM(i).sn_name != NULL) 4195 { 4196 home_replace(NULL, SCRIPT_ITEM(i).sn_name, 4197 NameBuff, MAXPATHL, TRUE); 4198 smsg((char_u *)"%3d: %s", i, NameBuff); 4199 } 4200 } 4201 4202 # if defined(BACKSLASH_IN_FILENAME) || defined(PROTO) 4203 /* 4204 * Fix slashes in the list of script names for 'shellslash'. 4205 */ 4206 void 4207 scriptnames_slash_adjust(void) 4208 { 4209 int i; 4210 4211 for (i = 1; i <= script_items.ga_len; ++i) 4212 if (SCRIPT_ITEM(i).sn_name != NULL) 4213 slash_adjust(SCRIPT_ITEM(i).sn_name); 4214 } 4215 # endif 4216 4217 /* 4218 * Get a pointer to a script name. Used for ":verbose set". 4219 */ 4220 char_u * 4221 get_scriptname(scid_T id) 4222 { 4223 if (id == SID_MODELINE) 4224 return (char_u *)_("modeline"); 4225 if (id == SID_CMDARG) 4226 return (char_u *)_("--cmd argument"); 4227 if (id == SID_CARG) 4228 return (char_u *)_("-c argument"); 4229 if (id == SID_ENV) 4230 return (char_u *)_("environment variable"); 4231 if (id == SID_ERROR) 4232 return (char_u *)_("error handler"); 4233 return SCRIPT_ITEM(id).sn_name; 4234 } 4235 4236 # if defined(EXITFREE) || defined(PROTO) 4237 void 4238 free_scriptnames(void) 4239 { 4240 int i; 4241 4242 for (i = script_items.ga_len; i > 0; --i) 4243 vim_free(SCRIPT_ITEM(i).sn_name); 4244 ga_clear(&script_items); 4245 } 4246 # endif 4247 4248 #endif 4249 4250 #if defined(USE_CR) || defined(PROTO) 4251 4252 # if defined(__MSL__) && (__MSL__ >= 22) 4253 /* 4254 * Newer version of the Metrowerks library handle DOS and UNIX files 4255 * without help. 4256 * Test with earlier versions, MSL 2.2 is the library supplied with 4257 * Codewarrior Pro 2. 4258 */ 4259 char * 4260 fgets_cr(char *s, int n, FILE *stream) 4261 { 4262 return fgets(s, n, stream); 4263 } 4264 # else 4265 /* 4266 * Version of fgets() which also works for lines ending in a <CR> only 4267 * (Macintosh format). 4268 * For older versions of the Metrowerks library. 4269 * At least CodeWarrior 9 needed this code. 4270 */ 4271 char * 4272 fgets_cr(char *s, int n, FILE *stream) 4273 { 4274 int c = 0; 4275 int char_read = 0; 4276 4277 while (!feof(stream) && c != '\r' && c != '\n' && char_read < n - 1) 4278 { 4279 c = fgetc(stream); 4280 s[char_read++] = c; 4281 /* If the file is in DOS format, we need to skip a NL after a CR. I 4282 * thought it was the other way around, but this appears to work... */ 4283 if (c == '\n') 4284 { 4285 c = fgetc(stream); 4286 if (c != '\r') 4287 ungetc(c, stream); 4288 } 4289 } 4290 4291 s[char_read] = 0; 4292 if (char_read == 0) 4293 return NULL; 4294 4295 if (feof(stream) && char_read == 1) 4296 return NULL; 4297 4298 return s; 4299 } 4300 # endif 4301 #endif 4302 4303 /* 4304 * Get one full line from a sourced file. 4305 * Called by do_cmdline() when it's called from do_source(). 4306 * 4307 * Return a pointer to the line in allocated memory. 4308 * Return NULL for end-of-file or some error. 4309 */ 4310 char_u * 4311 getsourceline(int c UNUSED, void *cookie, int indent UNUSED) 4312 { 4313 struct source_cookie *sp = (struct source_cookie *)cookie; 4314 char_u *line; 4315 char_u *p; 4316 4317 #ifdef FEAT_EVAL 4318 /* If breakpoints have been added/deleted need to check for it. */ 4319 if (sp->dbg_tick < debug_tick) 4320 { 4321 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum); 4322 sp->dbg_tick = debug_tick; 4323 } 4324 # ifdef FEAT_PROFILE 4325 if (do_profiling == PROF_YES) 4326 script_line_end(); 4327 # endif 4328 #endif 4329 /* 4330 * Get current line. If there is a read-ahead line, use it, otherwise get 4331 * one now. 4332 */ 4333 if (sp->finished) 4334 line = NULL; 4335 else if (sp->nextline == NULL) 4336 line = get_one_sourceline(sp); 4337 else 4338 { 4339 line = sp->nextline; 4340 sp->nextline = NULL; 4341 ++sourcing_lnum; 4342 } 4343 #ifdef FEAT_PROFILE 4344 if (line != NULL && do_profiling == PROF_YES) 4345 script_line_start(); 4346 #endif 4347 4348 /* Only concatenate lines starting with a \ when 'cpoptions' doesn't 4349 * contain the 'C' flag. */ 4350 if (line != NULL && (vim_strchr(p_cpo, CPO_CONCAT) == NULL)) 4351 { 4352 /* compensate for the one line read-ahead */ 4353 --sourcing_lnum; 4354 4355 /* Get the next line and concatenate it when it starts with a 4356 * backslash. We always need to read the next line, keep it in 4357 * sp->nextline. */ 4358 sp->nextline = get_one_sourceline(sp); 4359 if (sp->nextline != NULL && *(p = skipwhite(sp->nextline)) == '\\') 4360 { 4361 garray_T ga; 4362 4363 ga_init2(&ga, (int)sizeof(char_u), 400); 4364 ga_concat(&ga, line); 4365 ga_concat(&ga, p + 1); 4366 for (;;) 4367 { 4368 vim_free(sp->nextline); 4369 sp->nextline = get_one_sourceline(sp); 4370 if (sp->nextline == NULL) 4371 break; 4372 p = skipwhite(sp->nextline); 4373 if (*p != '\\') 4374 break; 4375 /* Adjust the growsize to the current length to speed up 4376 * concatenating many lines. */ 4377 if (ga.ga_len > 400) 4378 { 4379 if (ga.ga_len > 8000) 4380 ga.ga_growsize = 8000; 4381 else 4382 ga.ga_growsize = ga.ga_len; 4383 } 4384 ga_concat(&ga, p + 1); 4385 } 4386 ga_append(&ga, NUL); 4387 vim_free(line); 4388 line = ga.ga_data; 4389 } 4390 } 4391 4392 #ifdef FEAT_MBYTE 4393 if (line != NULL && sp->conv.vc_type != CONV_NONE) 4394 { 4395 char_u *s; 4396 4397 /* Convert the encoding of the script line. */ 4398 s = string_convert(&sp->conv, line, NULL); 4399 if (s != NULL) 4400 { 4401 vim_free(line); 4402 line = s; 4403 } 4404 } 4405 #endif 4406 4407 #ifdef FEAT_EVAL 4408 /* Did we encounter a breakpoint? */ 4409 if (sp->breakpoint != 0 && sp->breakpoint <= sourcing_lnum) 4410 { 4411 dbg_breakpoint(sp->fname, sourcing_lnum); 4412 /* Find next breakpoint. */ 4413 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum); 4414 sp->dbg_tick = debug_tick; 4415 } 4416 #endif 4417 4418 return line; 4419 } 4420 4421 static char_u * 4422 get_one_sourceline(struct source_cookie *sp) 4423 { 4424 garray_T ga; 4425 int len; 4426 int c; 4427 char_u *buf; 4428 #ifdef USE_CRNL 4429 int has_cr; /* CR-LF found */ 4430 #endif 4431 #ifdef USE_CR 4432 char_u *scan; 4433 #endif 4434 int have_read = FALSE; 4435 4436 /* use a growarray to store the sourced line */ 4437 ga_init2(&ga, 1, 250); 4438 4439 /* 4440 * Loop until there is a finished line (or end-of-file). 4441 */ 4442 sourcing_lnum++; 4443 for (;;) 4444 { 4445 /* make room to read at least 120 (more) characters */ 4446 if (ga_grow(&ga, 120) == FAIL) 4447 break; 4448 buf = (char_u *)ga.ga_data; 4449 4450 #ifdef USE_CR 4451 if (sp->fileformat == EOL_MAC) 4452 { 4453 if (fgets_cr((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len, 4454 sp->fp) == NULL) 4455 break; 4456 } 4457 else 4458 #endif 4459 if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len, 4460 sp->fp) == NULL) 4461 break; 4462 len = ga.ga_len + (int)STRLEN(buf + ga.ga_len); 4463 #ifdef USE_CRNL 4464 /* Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the 4465 * CTRL-Z by its own, or after a NL. */ 4466 if ( (len == 1 || (len >= 2 && buf[len - 2] == '\n')) 4467 && sp->fileformat == EOL_DOS 4468 && buf[len - 1] == Ctrl_Z) 4469 { 4470 buf[len - 1] = NUL; 4471 break; 4472 } 4473 #endif 4474 4475 #ifdef USE_CR 4476 /* If the read doesn't stop on a new line, and there's 4477 * some CR then we assume a Mac format */ 4478 if (sp->fileformat == EOL_UNKNOWN) 4479 { 4480 if (buf[len - 1] != '\n' && vim_strchr(buf, '\r') != NULL) 4481 sp->fileformat = EOL_MAC; 4482 else 4483 sp->fileformat = EOL_UNIX; 4484 } 4485 4486 if (sp->fileformat == EOL_MAC) 4487 { 4488 scan = vim_strchr(buf, '\r'); 4489 4490 if (scan != NULL) 4491 { 4492 *scan = '\n'; 4493 if (*(scan + 1) != 0) 4494 { 4495 *(scan + 1) = 0; 4496 fseek(sp->fp, (long)(scan - buf - len + 1), SEEK_CUR); 4497 } 4498 } 4499 len = STRLEN(buf); 4500 } 4501 #endif 4502 4503 have_read = TRUE; 4504 ga.ga_len = len; 4505 4506 /* If the line was longer than the buffer, read more. */ 4507 if (ga.ga_maxlen - ga.ga_len == 1 && buf[len - 1] != '\n') 4508 continue; 4509 4510 if (len >= 1 && buf[len - 1] == '\n') /* remove trailing NL */ 4511 { 4512 #ifdef USE_CRNL 4513 has_cr = (len >= 2 && buf[len - 2] == '\r'); 4514 if (sp->fileformat == EOL_UNKNOWN) 4515 { 4516 if (has_cr) 4517 sp->fileformat = EOL_DOS; 4518 else 4519 sp->fileformat = EOL_UNIX; 4520 } 4521 4522 if (sp->fileformat == EOL_DOS) 4523 { 4524 if (has_cr) /* replace trailing CR */ 4525 { 4526 buf[len - 2] = '\n'; 4527 --len; 4528 --ga.ga_len; 4529 } 4530 else /* lines like ":map xx yy^M" will have failed */ 4531 { 4532 if (!sp->error) 4533 { 4534 msg_source(hl_attr(HLF_W)); 4535 EMSG(_("W15: Warning: Wrong line separator, ^M may be missing")); 4536 } 4537 sp->error = TRUE; 4538 sp->fileformat = EOL_UNIX; 4539 } 4540 } 4541 #endif 4542 /* The '\n' is escaped if there is an odd number of ^V's just 4543 * before it, first set "c" just before the 'V's and then check 4544 * len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo */ 4545 for (c = len - 2; c >= 0 && buf[c] == Ctrl_V; c--) 4546 ; 4547 if ((len & 1) != (c & 1)) /* escaped NL, read more */ 4548 { 4549 sourcing_lnum++; 4550 continue; 4551 } 4552 4553 buf[len - 1] = NUL; /* remove the NL */ 4554 } 4555 4556 /* 4557 * Check for ^C here now and then, so recursive :so can be broken. 4558 */ 4559 line_breakcheck(); 4560 break; 4561 } 4562 4563 if (have_read) 4564 return (char_u *)ga.ga_data; 4565 4566 vim_free(ga.ga_data); 4567 return NULL; 4568 } 4569 4570 #if defined(FEAT_PROFILE) || defined(PROTO) 4571 /* 4572 * Called when starting to read a script line. 4573 * "sourcing_lnum" must be correct! 4574 * When skipping lines it may not actually be executed, but we won't find out 4575 * until later and we need to store the time now. 4576 */ 4577 void 4578 script_line_start(void) 4579 { 4580 scriptitem_T *si; 4581 sn_prl_T *pp; 4582 4583 if (current_SID <= 0 || current_SID > script_items.ga_len) 4584 return; 4585 si = &SCRIPT_ITEM(current_SID); 4586 if (si->sn_prof_on && sourcing_lnum >= 1) 4587 { 4588 /* Grow the array before starting the timer, so that the time spent 4589 * here isn't counted. */ 4590 (void)ga_grow(&si->sn_prl_ga, (int)(sourcing_lnum - si->sn_prl_ga.ga_len)); 4591 si->sn_prl_idx = sourcing_lnum - 1; 4592 while (si->sn_prl_ga.ga_len <= si->sn_prl_idx 4593 && si->sn_prl_ga.ga_len < si->sn_prl_ga.ga_maxlen) 4594 { 4595 /* Zero counters for a line that was not used before. */ 4596 pp = &PRL_ITEM(si, si->sn_prl_ga.ga_len); 4597 pp->snp_count = 0; 4598 profile_zero(&pp->sn_prl_total); 4599 profile_zero(&pp->sn_prl_self); 4600 ++si->sn_prl_ga.ga_len; 4601 } 4602 si->sn_prl_execed = FALSE; 4603 profile_start(&si->sn_prl_start); 4604 profile_zero(&si->sn_prl_children); 4605 profile_get_wait(&si->sn_prl_wait); 4606 } 4607 } 4608 4609 /* 4610 * Called when actually executing a function line. 4611 */ 4612 void 4613 script_line_exec(void) 4614 { 4615 scriptitem_T *si; 4616 4617 if (current_SID <= 0 || current_SID > script_items.ga_len) 4618 return; 4619 si = &SCRIPT_ITEM(current_SID); 4620 if (si->sn_prof_on && si->sn_prl_idx >= 0) 4621 si->sn_prl_execed = TRUE; 4622 } 4623 4624 /* 4625 * Called when done with a function line. 4626 */ 4627 void 4628 script_line_end(void) 4629 { 4630 scriptitem_T *si; 4631 sn_prl_T *pp; 4632 4633 if (current_SID <= 0 || current_SID > script_items.ga_len) 4634 return; 4635 si = &SCRIPT_ITEM(current_SID); 4636 if (si->sn_prof_on && si->sn_prl_idx >= 0 4637 && si->sn_prl_idx < si->sn_prl_ga.ga_len) 4638 { 4639 if (si->sn_prl_execed) 4640 { 4641 pp = &PRL_ITEM(si, si->sn_prl_idx); 4642 ++pp->snp_count; 4643 profile_end(&si->sn_prl_start); 4644 profile_sub_wait(&si->sn_prl_wait, &si->sn_prl_start); 4645 profile_add(&pp->sn_prl_total, &si->sn_prl_start); 4646 profile_self(&pp->sn_prl_self, &si->sn_prl_start, 4647 &si->sn_prl_children); 4648 } 4649 si->sn_prl_idx = -1; 4650 } 4651 } 4652 #endif 4653 4654 /* 4655 * ":scriptencoding": Set encoding conversion for a sourced script. 4656 * Without the multi-byte feature it's simply ignored. 4657 */ 4658 void 4659 ex_scriptencoding(exarg_T *eap UNUSED) 4660 { 4661 #ifdef FEAT_MBYTE 4662 struct source_cookie *sp; 4663 char_u *name; 4664 4665 if (!getline_equal(eap->getline, eap->cookie, getsourceline)) 4666 { 4667 EMSG(_("E167: :scriptencoding used outside of a sourced file")); 4668 return; 4669 } 4670 4671 if (*eap->arg != NUL) 4672 { 4673 name = enc_canonize(eap->arg); 4674 if (name == NULL) /* out of memory */ 4675 return; 4676 } 4677 else 4678 name = eap->arg; 4679 4680 /* Setup for conversion from the specified encoding to 'encoding'. */ 4681 sp = (struct source_cookie *)getline_cookie(eap->getline, eap->cookie); 4682 convert_setup(&sp->conv, name, p_enc); 4683 4684 if (name != eap->arg) 4685 vim_free(name); 4686 #endif 4687 } 4688 4689 #if defined(FEAT_EVAL) || defined(PROTO) 4690 /* 4691 * ":finish": Mark a sourced file as finished. 4692 */ 4693 void 4694 ex_finish(exarg_T *eap) 4695 { 4696 if (getline_equal(eap->getline, eap->cookie, getsourceline)) 4697 do_finish(eap, FALSE); 4698 else 4699 EMSG(_("E168: :finish used outside of a sourced file")); 4700 } 4701 4702 /* 4703 * Mark a sourced file as finished. Possibly makes the ":finish" pending. 4704 * Also called for a pending finish at the ":endtry" or after returning from 4705 * an extra do_cmdline(). "reanimate" is used in the latter case. 4706 */ 4707 void 4708 do_finish(exarg_T *eap, int reanimate) 4709 { 4710 int idx; 4711 4712 if (reanimate) 4713 ((struct source_cookie *)getline_cookie(eap->getline, 4714 eap->cookie))->finished = FALSE; 4715 4716 /* 4717 * Cleanup (and inactivate) conditionals, but stop when a try conditional 4718 * not in its finally clause (which then is to be executed next) is found. 4719 * In this case, make the ":finish" pending for execution at the ":endtry". 4720 * Otherwise, finish normally. 4721 */ 4722 idx = cleanup_conditionals(eap->cstack, 0, TRUE); 4723 if (idx >= 0) 4724 { 4725 eap->cstack->cs_pending[idx] = CSTP_FINISH; 4726 report_make_pending(CSTP_FINISH, NULL); 4727 } 4728 else 4729 ((struct source_cookie *)getline_cookie(eap->getline, 4730 eap->cookie))->finished = TRUE; 4731 } 4732 4733 4734 /* 4735 * Return TRUE when a sourced file had the ":finish" command: Don't give error 4736 * message for missing ":endif". 4737 * Return FALSE when not sourcing a file. 4738 */ 4739 int 4740 source_finished( 4741 char_u *(*fgetline)(int, void *, int), 4742 void *cookie) 4743 { 4744 return (getline_equal(fgetline, cookie, getsourceline) 4745 && ((struct source_cookie *)getline_cookie( 4746 fgetline, cookie))->finished); 4747 } 4748 #endif 4749 4750 #if defined(FEAT_LISTCMDS) || defined(PROTO) 4751 /* 4752 * ":checktime [buffer]" 4753 */ 4754 void 4755 ex_checktime(exarg_T *eap) 4756 { 4757 buf_T *buf; 4758 int save_no_check_timestamps = no_check_timestamps; 4759 4760 no_check_timestamps = 0; 4761 if (eap->addr_count == 0) /* default is all buffers */ 4762 check_timestamps(FALSE); 4763 else 4764 { 4765 buf = buflist_findnr((int)eap->line2); 4766 if (buf != NULL) /* cannot happen? */ 4767 (void)buf_check_timestamp(buf, FALSE); 4768 } 4769 no_check_timestamps = save_no_check_timestamps; 4770 } 4771 #endif 4772 4773 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \ 4774 && (defined(FEAT_EVAL) || defined(FEAT_MULTI_LANG)) 4775 # define HAVE_GET_LOCALE_VAL 4776 static char_u *get_locale_val(int what); 4777 4778 static char_u * 4779 get_locale_val(int what) 4780 { 4781 char_u *loc; 4782 4783 /* Obtain the locale value from the libraries. */ 4784 loc = (char_u *)setlocale(what, NULL); 4785 4786 # ifdef WIN32 4787 if (loc != NULL) 4788 { 4789 char_u *p; 4790 4791 /* setocale() returns something like "LC_COLLATE=<name>;LC_..." when 4792 * one of the values (e.g., LC_CTYPE) differs. */ 4793 p = vim_strchr(loc, '='); 4794 if (p != NULL) 4795 { 4796 loc = ++p; 4797 while (*p != NUL) /* remove trailing newline */ 4798 { 4799 if (*p < ' ' || *p == ';') 4800 { 4801 *p = NUL; 4802 break; 4803 } 4804 ++p; 4805 } 4806 } 4807 } 4808 # endif 4809 4810 return loc; 4811 } 4812 #endif 4813 4814 4815 #ifdef WIN32 4816 /* 4817 * On MS-Windows locale names are strings like "German_Germany.1252", but 4818 * gettext expects "de". Try to translate one into another here for a few 4819 * supported languages. 4820 */ 4821 static char_u * 4822 gettext_lang(char_u *name) 4823 { 4824 int i; 4825 static char *(mtable[]) = { 4826 "afrikaans", "af", 4827 "czech", "cs", 4828 "dutch", "nl", 4829 "german", "de", 4830 "english_united kingdom", "en_GB", 4831 "spanish", "es", 4832 "french", "fr", 4833 "italian", "it", 4834 "japanese", "ja", 4835 "korean", "ko", 4836 "norwegian", "no", 4837 "polish", "pl", 4838 "russian", "ru", 4839 "slovak", "sk", 4840 "swedish", "sv", 4841 "ukrainian", "uk", 4842 "chinese_china", "zh_CN", 4843 "chinese_taiwan", "zh_TW", 4844 NULL}; 4845 4846 for (i = 0; mtable[i] != NULL; i += 2) 4847 if (STRNICMP(mtable[i], name, STRLEN(mtable[i])) == 0) 4848 return (char_u *)mtable[i + 1]; 4849 return name; 4850 } 4851 #endif 4852 4853 #if defined(FEAT_MULTI_LANG) || defined(PROTO) 4854 /* 4855 * Obtain the current messages language. Used to set the default for 4856 * 'helplang'. May return NULL or an empty string. 4857 */ 4858 char_u * 4859 get_mess_lang(void) 4860 { 4861 char_u *p; 4862 4863 # ifdef HAVE_GET_LOCALE_VAL 4864 # if defined(LC_MESSAGES) 4865 p = get_locale_val(LC_MESSAGES); 4866 # else 4867 /* This is necessary for Win32, where LC_MESSAGES is not defined and $LANG 4868 * may be set to the LCID number. LC_COLLATE is the best guess, LC_TIME 4869 * and LC_MONETARY may be set differently for a Japanese working in the 4870 * US. */ 4871 p = get_locale_val(LC_COLLATE); 4872 # endif 4873 # else 4874 p = mch_getenv((char_u *)"LC_ALL"); 4875 if (p == NULL || *p == NUL) 4876 { 4877 p = mch_getenv((char_u *)"LC_MESSAGES"); 4878 if (p == NULL || *p == NUL) 4879 p = mch_getenv((char_u *)"LANG"); 4880 } 4881 # endif 4882 # ifdef WIN32 4883 p = gettext_lang(p); 4884 # endif 4885 return p; 4886 } 4887 #endif 4888 4889 /* Complicated #if; matches with where get_mess_env() is used below. */ 4890 #if (defined(FEAT_EVAL) && !((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \ 4891 && defined(LC_MESSAGES))) \ 4892 || ((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \ 4893 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)) \ 4894 && !defined(LC_MESSAGES)) 4895 static char_u *get_mess_env(void); 4896 4897 /* 4898 * Get the language used for messages from the environment. 4899 */ 4900 static char_u * 4901 get_mess_env(void) 4902 { 4903 char_u *p; 4904 4905 p = mch_getenv((char_u *)"LC_ALL"); 4906 if (p == NULL || *p == NUL) 4907 { 4908 p = mch_getenv((char_u *)"LC_MESSAGES"); 4909 if (p == NULL || *p == NUL) 4910 { 4911 p = mch_getenv((char_u *)"LANG"); 4912 if (p != NULL && VIM_ISDIGIT(*p)) 4913 p = NULL; /* ignore something like "1043" */ 4914 # ifdef HAVE_GET_LOCALE_VAL 4915 if (p == NULL || *p == NUL) 4916 p = get_locale_val(LC_CTYPE); 4917 # endif 4918 } 4919 } 4920 return p; 4921 } 4922 #endif 4923 4924 #if defined(FEAT_EVAL) || defined(PROTO) 4925 4926 /* 4927 * Set the "v:lang" variable according to the current locale setting. 4928 * Also do "v:lc_time"and "v:ctype". 4929 */ 4930 void 4931 set_lang_var(void) 4932 { 4933 char_u *loc; 4934 4935 # ifdef HAVE_GET_LOCALE_VAL 4936 loc = get_locale_val(LC_CTYPE); 4937 # else 4938 /* setlocale() not supported: use the default value */ 4939 loc = (char_u *)"C"; 4940 # endif 4941 set_vim_var_string(VV_CTYPE, loc, -1); 4942 4943 /* When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall 4944 * back to LC_CTYPE if it's empty. */ 4945 # if defined(HAVE_GET_LOCALE_VAL) && defined(LC_MESSAGES) 4946 loc = get_locale_val(LC_MESSAGES); 4947 # else 4948 loc = get_mess_env(); 4949 # endif 4950 set_vim_var_string(VV_LANG, loc, -1); 4951 4952 # ifdef HAVE_GET_LOCALE_VAL 4953 loc = get_locale_val(LC_TIME); 4954 # endif 4955 set_vim_var_string(VV_LC_TIME, loc, -1); 4956 } 4957 #endif 4958 4959 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \ 4960 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)) 4961 /* 4962 * ":language": Set the language (locale). 4963 */ 4964 void 4965 ex_language(exarg_T *eap) 4966 { 4967 char *loc; 4968 char_u *p; 4969 char_u *name; 4970 int what = LC_ALL; 4971 char *whatstr = ""; 4972 #ifdef LC_MESSAGES 4973 # define VIM_LC_MESSAGES LC_MESSAGES 4974 #else 4975 # define VIM_LC_MESSAGES 6789 4976 #endif 4977 4978 name = eap->arg; 4979 4980 /* Check for "messages {name}", "ctype {name}" or "time {name}" argument. 4981 * Allow abbreviation, but require at least 3 characters to avoid 4982 * confusion with a two letter language name "me" or "ct". */ 4983 p = skiptowhite(eap->arg); 4984 if ((*p == NUL || vim_iswhite(*p)) && p - eap->arg >= 3) 4985 { 4986 if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0) 4987 { 4988 what = VIM_LC_MESSAGES; 4989 name = skipwhite(p); 4990 whatstr = "messages "; 4991 } 4992 else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0) 4993 { 4994 what = LC_CTYPE; 4995 name = skipwhite(p); 4996 whatstr = "ctype "; 4997 } 4998 else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0) 4999 { 5000 what = LC_TIME; 5001 name = skipwhite(p); 5002 whatstr = "time "; 5003 } 5004 } 5005 5006 if (*name == NUL) 5007 { 5008 #ifndef LC_MESSAGES 5009 if (what == VIM_LC_MESSAGES) 5010 p = get_mess_env(); 5011 else 5012 #endif 5013 p = (char_u *)setlocale(what, NULL); 5014 if (p == NULL || *p == NUL) 5015 p = (char_u *)"Unknown"; 5016 smsg((char_u *)_("Current %slanguage: \"%s\""), whatstr, p); 5017 } 5018 else 5019 { 5020 #ifndef LC_MESSAGES 5021 if (what == VIM_LC_MESSAGES) 5022 loc = ""; 5023 else 5024 #endif 5025 { 5026 loc = setlocale(what, (char *)name); 5027 #if defined(FEAT_FLOAT) && defined(LC_NUMERIC) 5028 /* Make sure strtod() uses a decimal point, not a comma. */ 5029 setlocale(LC_NUMERIC, "C"); 5030 #endif 5031 } 5032 if (loc == NULL) 5033 EMSG2(_("E197: Cannot set language to \"%s\""), name); 5034 else 5035 { 5036 #ifdef HAVE_NL_MSG_CAT_CNTR 5037 /* Need to do this for GNU gettext, otherwise cached translations 5038 * will be used again. */ 5039 extern int _nl_msg_cat_cntr; 5040 5041 ++_nl_msg_cat_cntr; 5042 #endif 5043 /* Reset $LC_ALL, otherwise it would overrule everything. */ 5044 vim_setenv((char_u *)"LC_ALL", (char_u *)""); 5045 5046 if (what != LC_TIME) 5047 { 5048 /* Tell gettext() what to translate to. It apparently doesn't 5049 * use the currently effective locale. Also do this when 5050 * FEAT_GETTEXT isn't defined, so that shell commands use this 5051 * value. */ 5052 if (what == LC_ALL) 5053 { 5054 vim_setenv((char_u *)"LANG", name); 5055 5056 /* Clear $LANGUAGE because GNU gettext uses it. */ 5057 vim_setenv((char_u *)"LANGUAGE", (char_u *)""); 5058 # ifdef WIN32 5059 /* Apparently MS-Windows printf() may cause a crash when 5060 * we give it 8-bit text while it's expecting text in the 5061 * current locale. This call avoids that. */ 5062 setlocale(LC_CTYPE, "C"); 5063 # endif 5064 } 5065 if (what != LC_CTYPE) 5066 { 5067 char_u *mname; 5068 #ifdef WIN32 5069 mname = gettext_lang(name); 5070 #else 5071 mname = name; 5072 #endif 5073 vim_setenv((char_u *)"LC_MESSAGES", mname); 5074 #ifdef FEAT_MULTI_LANG 5075 set_helplang_default(mname); 5076 #endif 5077 } 5078 } 5079 5080 # ifdef FEAT_EVAL 5081 /* Set v:lang, v:lc_time and v:ctype to the final result. */ 5082 set_lang_var(); 5083 # endif 5084 # ifdef FEAT_TITLE 5085 maketitle(); 5086 # endif 5087 } 5088 } 5089 } 5090 5091 # if defined(FEAT_CMDL_COMPL) || defined(PROTO) 5092 5093 static char_u **locales = NULL; /* Array of all available locales */ 5094 static int did_init_locales = FALSE; 5095 5096 static void init_locales(void); 5097 static char_u **find_locales(void); 5098 5099 /* 5100 * Lazy initialization of all available locales. 5101 */ 5102 static void 5103 init_locales(void) 5104 { 5105 if (!did_init_locales) 5106 { 5107 did_init_locales = TRUE; 5108 locales = find_locales(); 5109 } 5110 } 5111 5112 /* Return an array of strings for all available locales + NULL for the 5113 * last element. Return NULL in case of error. */ 5114 static char_u ** 5115 find_locales(void) 5116 { 5117 garray_T locales_ga; 5118 char_u *loc; 5119 5120 /* Find all available locales by running command "locale -a". If this 5121 * doesn't work we won't have completion. */ 5122 char_u *locale_a = get_cmd_output((char_u *)"locale -a", 5123 NULL, SHELL_SILENT, NULL); 5124 if (locale_a == NULL) 5125 return NULL; 5126 ga_init2(&locales_ga, sizeof(char_u *), 20); 5127 5128 /* Transform locale_a string where each locale is separated by "\n" 5129 * into an array of locale strings. */ 5130 loc = (char_u *)strtok((char *)locale_a, "\n"); 5131 5132 while (loc != NULL) 5133 { 5134 if (ga_grow(&locales_ga, 1) == FAIL) 5135 break; 5136 loc = vim_strsave(loc); 5137 if (loc == NULL) 5138 break; 5139 5140 ((char_u **)locales_ga.ga_data)[locales_ga.ga_len++] = loc; 5141 loc = (char_u *)strtok(NULL, "\n"); 5142 } 5143 vim_free(locale_a); 5144 if (ga_grow(&locales_ga, 1) == FAIL) 5145 { 5146 ga_clear(&locales_ga); 5147 return NULL; 5148 } 5149 ((char_u **)locales_ga.ga_data)[locales_ga.ga_len] = NULL; 5150 return (char_u **)locales_ga.ga_data; 5151 } 5152 5153 # if defined(EXITFREE) || defined(PROTO) 5154 void 5155 free_locales(void) 5156 { 5157 int i; 5158 if (locales != NULL) 5159 { 5160 for (i = 0; locales[i] != NULL; i++) 5161 vim_free(locales[i]); 5162 vim_free(locales); 5163 locales = NULL; 5164 } 5165 } 5166 # endif 5167 5168 /* 5169 * Function given to ExpandGeneric() to obtain the possible arguments of the 5170 * ":language" command. 5171 */ 5172 char_u * 5173 get_lang_arg(expand_T *xp UNUSED, int idx) 5174 { 5175 if (idx == 0) 5176 return (char_u *)"messages"; 5177 if (idx == 1) 5178 return (char_u *)"ctype"; 5179 if (idx == 2) 5180 return (char_u *)"time"; 5181 5182 init_locales(); 5183 if (locales == NULL) 5184 return NULL; 5185 return locales[idx - 3]; 5186 } 5187 5188 /* 5189 * Function given to ExpandGeneric() to obtain the available locales. 5190 */ 5191 char_u * 5192 get_locales(expand_T *xp UNUSED, int idx) 5193 { 5194 init_locales(); 5195 if (locales == NULL) 5196 return NULL; 5197 return locales[idx]; 5198 } 5199 # endif 5200 5201 #endif 5202