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