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