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