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