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