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