1 /* vi:set ts=8 sts=4 sw=4: 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 #if defined(WIN32) && defined(FEAT_CSCOPE) 15 # include "vimio.h" 16 #endif 17 18 #include "vim.h" 19 20 #if defined(WIN32) && defined(FEAT_CSCOPE) 21 # include <fcntl.h> 22 #endif 23 24 #include "version.h" 25 26 static void cmd_source __ARGS((char_u *fname, exarg_T *eap)); 27 28 #ifdef FEAT_EVAL 29 /* Growarray to store info about already sourced scripts. 30 * For Unix also store the dev/ino, so that we don't have to stat() each 31 * script when going through the list. */ 32 typedef struct scriptitem_S 33 { 34 char_u *sn_name; 35 # ifdef UNIX 36 int sn_dev; 37 ino_t sn_ino; 38 # endif 39 # ifdef FEAT_PROFILE 40 int sn_prof_on; /* TRUE when script is/was profiled */ 41 int sn_pr_force; /* forceit: profile functions in this script */ 42 proftime_T sn_pr_child; /* time set when going into first child */ 43 int sn_pr_nest; /* nesting for sn_pr_child */ 44 /* profiling the script as a whole */ 45 int sn_pr_count; /* nr of times sourced */ 46 proftime_T sn_pr_total; /* time spend in script + children */ 47 proftime_T sn_pr_self; /* time spend in script itself */ 48 proftime_T sn_pr_start; /* time at script start */ 49 proftime_T sn_pr_children; /* time in children after script start */ 50 /* profiling the script per line */ 51 garray_T sn_prl_ga; /* things stored for every line */ 52 proftime_T sn_prl_start; /* start time for current line */ 53 proftime_T sn_prl_children; /* time spent in children for this line */ 54 proftime_T sn_prl_wait; /* wait start time for current line */ 55 int sn_prl_idx; /* index of line being timed; -1 if none */ 56 int sn_prl_execed; /* line being timed was executed */ 57 # endif 58 } scriptitem_T; 59 60 static garray_T script_items = {0, 0, sizeof(scriptitem_T), 4, NULL}; 61 #define SCRIPT_ITEM(id) (((scriptitem_T *)script_items.ga_data)[(id) - 1]) 62 63 # ifdef FEAT_PROFILE 64 /* Struct used in sn_prl_ga for every line of a script. */ 65 typedef struct sn_prl_S 66 { 67 int snp_count; /* nr of times line was executed */ 68 proftime_T sn_prl_total; /* time spend in a line + children */ 69 proftime_T sn_prl_self; /* time spend in a line itself */ 70 } sn_prl_T; 71 72 # define PRL_ITEM(si, idx) (((sn_prl_T *)(si)->sn_prl_ga.ga_data)[(idx)]) 73 # endif 74 #endif 75 76 #if defined(FEAT_EVAL) || defined(PROTO) 77 static int debug_greedy = FALSE; /* batch mode debugging: don't save 78 and restore typeahead. */ 79 80 /* 81 * do_debug(): Debug mode. 82 * Repeatedly get Ex commands, until told to continue normal execution. 83 */ 84 void 85 do_debug(cmd) 86 char_u *cmd; 87 { 88 int save_msg_scroll = msg_scroll; 89 int save_State = State; 90 int save_did_emsg = did_emsg; 91 int save_cmd_silent = cmd_silent; 92 int save_msg_silent = msg_silent; 93 int save_emsg_silent = emsg_silent; 94 int save_redir_off = redir_off; 95 tasave_T typeaheadbuf; 96 # ifdef FEAT_EX_EXTRA 97 int save_ex_normal_busy; 98 # endif 99 int n; 100 char_u *cmdline = NULL; 101 char_u *p; 102 char *tail = NULL; 103 static int last_cmd = 0; 104 #define CMD_CONT 1 105 #define CMD_NEXT 2 106 #define CMD_STEP 3 107 #define CMD_FINISH 4 108 #define CMD_QUIT 5 109 #define CMD_INTERRUPT 6 110 111 #ifdef ALWAYS_USE_GUI 112 /* Can't do this when there is no terminal for input/output. */ 113 if (!gui.in_use) 114 { 115 /* Break as soon as possible. */ 116 debug_break_level = 9999; 117 return; 118 } 119 #endif 120 121 /* Make sure we are in raw mode and start termcap mode. Might have side 122 * effects... */ 123 settmode(TMODE_RAW); 124 starttermcap(); 125 126 ++RedrawingDisabled; /* don't redisplay the window */ 127 ++no_wait_return; /* don't wait for return */ 128 did_emsg = FALSE; /* don't use error from debugged stuff */ 129 cmd_silent = FALSE; /* display commands */ 130 msg_silent = FALSE; /* display messages */ 131 emsg_silent = FALSE; /* display error messages */ 132 redir_off = TRUE; /* don't redirect debug commands */ 133 134 State = NORMAL; 135 #ifdef FEAT_SNIFF 136 want_sniff_request = 0; /* No K_SNIFF wanted */ 137 #endif 138 139 if (!debug_did_msg) 140 MSG(_("Entering Debug mode. Type \"cont\" to continue.")); 141 if (sourcing_name != NULL) 142 msg(sourcing_name); 143 if (sourcing_lnum != 0) 144 smsg((char_u *)_("line %ld: %s"), (long)sourcing_lnum, cmd); 145 else 146 smsg((char_u *)_("cmd: %s"), cmd); 147 148 /* 149 * Repeat getting a command and executing it. 150 */ 151 for (;;) 152 { 153 msg_scroll = TRUE; 154 need_wait_return = FALSE; 155 #ifdef FEAT_SNIFF 156 ProcessSniffRequests(); 157 #endif 158 /* Save the current typeahead buffer and replace it with an empty one. 159 * This makes sure we get input from the user here and don't interfere 160 * with the commands being executed. Reset "ex_normal_busy" to avoid 161 * the side effects of using ":normal". Save the stuff buffer and make 162 * it empty. */ 163 # ifdef FEAT_EX_EXTRA 164 save_ex_normal_busy = ex_normal_busy; 165 ex_normal_busy = 0; 166 # endif 167 if (!debug_greedy) 168 save_typeahead(&typeaheadbuf); 169 170 cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL); 171 172 if (!debug_greedy) 173 restore_typeahead(&typeaheadbuf); 174 # ifdef FEAT_EX_EXTRA 175 ex_normal_busy = save_ex_normal_busy; 176 # endif 177 178 cmdline_row = msg_row; 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': last_cmd = CMD_FINISH; 199 tail = "inish"; 200 break; 201 case 'q': last_cmd = CMD_QUIT; 202 tail = "uit"; 203 break; 204 case 'i': last_cmd = CMD_INTERRUPT; 205 tail = "nterrupt"; 206 break; 207 default: last_cmd = 0; 208 } 209 if (last_cmd != 0) 210 { 211 /* Check that the tail matches. */ 212 ++p; 213 while (*p != NUL && *p == *tail) 214 { 215 ++p; 216 ++tail; 217 } 218 if (ASCII_ISALPHA(*p)) 219 last_cmd = 0; 220 } 221 } 222 223 if (last_cmd != 0) 224 { 225 /* Execute debug command: decided where to break next and 226 * return. */ 227 switch (last_cmd) 228 { 229 case CMD_CONT: 230 debug_break_level = -1; 231 break; 232 case CMD_NEXT: 233 debug_break_level = ex_nesting_level; 234 break; 235 case CMD_STEP: 236 debug_break_level = 9999; 237 break; 238 case CMD_FINISH: 239 debug_break_level = ex_nesting_level - 1; 240 break; 241 case CMD_QUIT: 242 got_int = TRUE; 243 debug_break_level = -1; 244 break; 245 case CMD_INTERRUPT: 246 got_int = TRUE; 247 debug_break_level = 9999; 248 /* Do not repeat ">interrupt" cmd, continue stepping. */ 249 last_cmd = CMD_STEP; 250 break; 251 } 252 break; 253 } 254 255 /* don't debug this command */ 256 n = debug_break_level; 257 debug_break_level = -1; 258 (void)do_cmdline(cmdline, getexline, NULL, 259 DOCMD_VERBOSE|DOCMD_EXCRESET); 260 debug_break_level = n; 261 262 vim_free(cmdline); 263 } 264 lines_left = Rows - 1; 265 } 266 vim_free(cmdline); 267 268 --RedrawingDisabled; 269 --no_wait_return; 270 redraw_all_later(NOT_VALID); 271 need_wait_return = FALSE; 272 msg_scroll = save_msg_scroll; 273 lines_left = Rows - 1; 274 State = save_State; 275 did_emsg = save_did_emsg; 276 cmd_silent = save_cmd_silent; 277 msg_silent = save_msg_silent; 278 emsg_silent = save_emsg_silent; 279 redir_off = save_redir_off; 280 281 /* Only print the message again when typing a command before coming back 282 * here. */ 283 debug_did_msg = TRUE; 284 } 285 286 /* 287 * ":debug". 288 */ 289 void 290 ex_debug(eap) 291 exarg_T *eap; 292 { 293 int debug_break_level_save = debug_break_level; 294 295 debug_break_level = 9999; 296 do_cmdline_cmd(eap->arg); 297 debug_break_level = debug_break_level_save; 298 } 299 300 static char_u *debug_breakpoint_name = NULL; 301 static linenr_T debug_breakpoint_lnum; 302 303 /* 304 * When debugging or a breakpoint is set on a skipped command, no debug prompt 305 * is shown by do_one_cmd(). This situation is indicated by debug_skipped, and 306 * debug_skipped_name is then set to the source name in the breakpoint case. If 307 * a skipped command decides itself that a debug prompt should be displayed, it 308 * can do so by calling dbg_check_skipped(). 309 */ 310 static int debug_skipped; 311 static char_u *debug_skipped_name; 312 313 /* 314 * Go to debug mode when a breakpoint was encountered or "ex_nesting_level" is 315 * at or below the break level. But only when the line is actually 316 * executed. Return TRUE and set breakpoint_name for skipped commands that 317 * decide to execute something themselves. 318 * Called from do_one_cmd() before executing a command. 319 */ 320 void 321 dbg_check_breakpoint(eap) 322 exarg_T *eap; 323 { 324 char_u *p; 325 326 debug_skipped = FALSE; 327 if (debug_breakpoint_name != NULL) 328 { 329 if (!eap->skip) 330 { 331 /* replace K_SNR with "<SNR>" */ 332 if (debug_breakpoint_name[0] == K_SPECIAL 333 && debug_breakpoint_name[1] == KS_EXTRA 334 && debug_breakpoint_name[2] == (int)KE_SNR) 335 p = (char_u *)"<SNR>"; 336 else 337 p = (char_u *)""; 338 smsg((char_u *)_("Breakpoint in \"%s%s\" line %ld"), 339 p, 340 debug_breakpoint_name + (*p == NUL ? 0 : 3), 341 (long)debug_breakpoint_lnum); 342 debug_breakpoint_name = NULL; 343 do_debug(eap->cmd); 344 } 345 else 346 { 347 debug_skipped = TRUE; 348 debug_skipped_name = debug_breakpoint_name; 349 debug_breakpoint_name = NULL; 350 } 351 } 352 else if (ex_nesting_level <= debug_break_level) 353 { 354 if (!eap->skip) 355 do_debug(eap->cmd); 356 else 357 { 358 debug_skipped = TRUE; 359 debug_skipped_name = NULL; 360 } 361 } 362 } 363 364 /* 365 * Go to debug mode if skipped by dbg_check_breakpoint() because eap->skip was 366 * set. Return TRUE when the debug mode is entered this time. 367 */ 368 int 369 dbg_check_skipped(eap) 370 exarg_T *eap; 371 { 372 int prev_got_int; 373 374 if (debug_skipped) 375 { 376 /* 377 * Save the value of got_int and reset it. We don't want a previous 378 * interruption cause flushing the input buffer. 379 */ 380 prev_got_int = got_int; 381 got_int = FALSE; 382 debug_breakpoint_name = debug_skipped_name; 383 /* eap->skip is TRUE */ 384 eap->skip = FALSE; 385 (void)dbg_check_breakpoint(eap); 386 eap->skip = TRUE; 387 got_int |= prev_got_int; 388 return TRUE; 389 } 390 return FALSE; 391 } 392 393 /* 394 * The list of breakpoints: dbg_breakp. 395 * This is a grow-array of structs. 396 */ 397 struct debuggy 398 { 399 int dbg_nr; /* breakpoint number */ 400 int dbg_type; /* DBG_FUNC or DBG_FILE */ 401 char_u *dbg_name; /* function or file name */ 402 regprog_T *dbg_prog; /* regexp program */ 403 linenr_T dbg_lnum; /* line number in function or file */ 404 int dbg_forceit; /* ! used */ 405 }; 406 407 static garray_T dbg_breakp = {0, 0, sizeof(struct debuggy), 4, NULL}; 408 #define BREAKP(idx) (((struct debuggy *)dbg_breakp.ga_data)[idx]) 409 #define DEBUGGY(gap, idx) (((struct debuggy *)gap->ga_data)[idx]) 410 static int last_breakp = 0; /* nr of last defined breakpoint */ 411 412 #ifdef FEAT_PROFILE 413 /* Profiling uses file and func names similar to breakpoints. */ 414 static garray_T prof_ga = {0, 0, sizeof(struct debuggy), 4, NULL}; 415 #endif 416 #define DBG_FUNC 1 417 #define DBG_FILE 2 418 419 static int dbg_parsearg __ARGS((char_u *arg, garray_T *gap)); 420 static linenr_T debuggy_find __ARGS((int file,char_u *fname, linenr_T after, garray_T *gap, int *fp)); 421 422 /* 423 * Parse the arguments of ":profile", ":breakadd" or ":breakdel" and put them 424 * in the entry just after the last one in dbg_breakp. Note that "dbg_name" 425 * is allocated. 426 * Returns FAIL for failure. 427 */ 428 static int 429 dbg_parsearg(arg, gap) 430 char_u *arg; 431 garray_T *gap; /* either &dbg_breakp or &prof_ga */ 432 { 433 char_u *p = arg; 434 char_u *q; 435 struct debuggy *bp; 436 int here = FALSE; 437 438 if (ga_grow(gap, 1) == FAIL) 439 return FAIL; 440 bp = &DEBUGGY(gap, gap->ga_len); 441 442 /* Find "func" or "file". */ 443 if (STRNCMP(p, "func", 4) == 0) 444 bp->dbg_type = DBG_FUNC; 445 else if (STRNCMP(p, "file", 4) == 0) 446 bp->dbg_type = DBG_FILE; 447 else if ( 448 #ifdef FEAT_PROFILE 449 gap != &prof_ga && 450 #endif 451 STRNCMP(p, "here", 4) == 0) 452 { 453 if (curbuf->b_ffname == NULL) 454 { 455 EMSG(_(e_noname)); 456 return FAIL; 457 } 458 bp->dbg_type = DBG_FILE; 459 here = TRUE; 460 } 461 else 462 { 463 EMSG2(_(e_invarg2), p); 464 return FAIL; 465 } 466 p = skipwhite(p + 4); 467 468 /* Find optional line number. */ 469 if (here) 470 bp->dbg_lnum = curwin->w_cursor.lnum; 471 else if ( 472 #ifdef FEAT_PROFILE 473 gap != &prof_ga && 474 #endif 475 VIM_ISDIGIT(*p)) 476 { 477 bp->dbg_lnum = getdigits(&p); 478 p = skipwhite(p); 479 } 480 else 481 bp->dbg_lnum = 0; 482 483 /* Find the function or file name. Don't accept a function name with (). */ 484 if ((!here && *p == NUL) 485 || (here && *p != NUL) 486 || (bp->dbg_type == DBG_FUNC && strstr((char *)p, "()") != NULL)) 487 { 488 EMSG2(_(e_invarg2), arg); 489 return FAIL; 490 } 491 492 if (bp->dbg_type == DBG_FUNC) 493 bp->dbg_name = vim_strsave(p); 494 else if (here) 495 bp->dbg_name = vim_strsave(curbuf->b_ffname); 496 else 497 { 498 /* Expand the file name in the same way as do_source(). This means 499 * doing it twice, so that $DIR/file gets expanded when $DIR is 500 * "~/dir". */ 501 #ifdef RISCOS 502 q = mch_munge_fname(p); 503 #else 504 q = expand_env_save(p); 505 #endif 506 if (q == NULL) 507 return FAIL; 508 #ifdef RISCOS 509 p = mch_munge_fname(q); 510 #else 511 p = expand_env_save(q); 512 #endif 513 vim_free(q); 514 if (p == NULL) 515 return FAIL; 516 if (*p != '*') 517 { 518 bp->dbg_name = fix_fname(p); 519 vim_free(p); 520 } 521 else 522 bp->dbg_name = p; 523 } 524 525 if (bp->dbg_name == NULL) 526 return FAIL; 527 return OK; 528 } 529 530 /* 531 * ":breakadd". 532 */ 533 void 534 ex_breakadd(eap) 535 exarg_T *eap; 536 { 537 struct debuggy *bp; 538 char_u *pat; 539 garray_T *gap; 540 541 gap = &dbg_breakp; 542 #ifdef FEAT_PROFILE 543 if (eap->cmdidx == CMD_profile) 544 gap = &prof_ga; 545 #endif 546 547 if (dbg_parsearg(eap->arg, gap) == OK) 548 { 549 bp = &DEBUGGY(gap, gap->ga_len); 550 bp->dbg_forceit = eap->forceit; 551 552 pat = file_pat_to_reg_pat(bp->dbg_name, NULL, NULL, FALSE); 553 if (pat != NULL) 554 { 555 bp->dbg_prog = vim_regcomp(pat, RE_MAGIC + RE_STRING); 556 vim_free(pat); 557 } 558 if (pat == NULL || bp->dbg_prog == NULL) 559 vim_free(bp->dbg_name); 560 else 561 { 562 if (bp->dbg_lnum == 0) /* default line number is 1 */ 563 bp->dbg_lnum = 1; 564 #ifdef FEAT_PROFILE 565 if (eap->cmdidx != CMD_profile) 566 #endif 567 { 568 DEBUGGY(gap, gap->ga_len).dbg_nr = ++last_breakp; 569 ++debug_tick; 570 } 571 ++gap->ga_len; 572 } 573 } 574 } 575 576 /* 577 * ":debuggreedy". 578 */ 579 void 580 ex_debuggreedy(eap) 581 exarg_T *eap; 582 { 583 if (eap->addr_count == 0 || eap->line2 != 0) 584 debug_greedy = TRUE; 585 else 586 debug_greedy = FALSE; 587 } 588 589 /* 590 * ":breakdel" and ":profdel". 591 */ 592 void 593 ex_breakdel(eap) 594 exarg_T *eap; 595 { 596 struct debuggy *bp, *bpi; 597 int nr; 598 int todel = -1; 599 int del_all = FALSE; 600 int i; 601 linenr_T best_lnum = 0; 602 garray_T *gap; 603 604 gap = &dbg_breakp; 605 #ifdef FEAT_PROFILE 606 if (eap->cmdidx == CMD_profdel) 607 gap = &prof_ga; 608 #endif 609 610 if (vim_isdigit(*eap->arg)) 611 { 612 /* ":breakdel {nr}" */ 613 nr = atol((char *)eap->arg); 614 for (i = 0; i < gap->ga_len; ++i) 615 if (DEBUGGY(gap, i).dbg_nr == nr) 616 { 617 todel = i; 618 break; 619 } 620 } 621 else if (*eap->arg == '*') 622 { 623 todel = 0; 624 del_all = TRUE; 625 } 626 else 627 { 628 /* ":breakdel {func|file} [lnum] {name}" */ 629 if (dbg_parsearg(eap->arg, gap) == FAIL) 630 return; 631 bp = &DEBUGGY(gap, gap->ga_len); 632 for (i = 0; i < gap->ga_len; ++i) 633 { 634 bpi = &DEBUGGY(gap, i); 635 if (bp->dbg_type == bpi->dbg_type 636 && STRCMP(bp->dbg_name, bpi->dbg_name) == 0 637 && (bp->dbg_lnum == bpi->dbg_lnum 638 || (bp->dbg_lnum == 0 639 && (best_lnum == 0 640 || bpi->dbg_lnum < best_lnum)))) 641 { 642 todel = i; 643 best_lnum = bpi->dbg_lnum; 644 } 645 } 646 vim_free(bp->dbg_name); 647 } 648 649 if (todel < 0) 650 EMSG2(_("E161: Breakpoint not found: %s"), eap->arg); 651 else 652 { 653 while (gap->ga_len > 0) 654 { 655 vim_free(DEBUGGY(gap, todel).dbg_name); 656 vim_free(DEBUGGY(gap, todel).dbg_prog); 657 --gap->ga_len; 658 if (todel < gap->ga_len) 659 mch_memmove(&DEBUGGY(gap, todel), &DEBUGGY(gap, todel + 1), 660 (gap->ga_len - todel) * sizeof(struct debuggy)); 661 #ifdef FEAT_PROFILE 662 if (eap->cmdidx == CMD_breakdel) 663 #endif 664 ++debug_tick; 665 if (!del_all) 666 break; 667 } 668 669 /* If all breakpoints were removed clear the array. */ 670 if (gap->ga_len == 0) 671 ga_clear(gap); 672 } 673 } 674 675 /* 676 * ":breaklist". 677 */ 678 /*ARGSUSED*/ 679 void 680 ex_breaklist(eap) 681 exarg_T *eap; 682 { 683 struct debuggy *bp; 684 int i; 685 686 if (dbg_breakp.ga_len == 0) 687 MSG(_("No breakpoints defined")); 688 else 689 for (i = 0; i < dbg_breakp.ga_len; ++i) 690 { 691 bp = &BREAKP(i); 692 smsg((char_u *)_("%3d %s %s line %ld"), 693 bp->dbg_nr, 694 bp->dbg_type == DBG_FUNC ? "func" : "file", 695 bp->dbg_name, 696 (long)bp->dbg_lnum); 697 } 698 } 699 700 /* 701 * Find a breakpoint for a function or sourced file. 702 * Returns line number at which to break; zero when no matching breakpoint. 703 */ 704 linenr_T 705 dbg_find_breakpoint(file, fname, after) 706 int file; /* TRUE for a file, FALSE for a function */ 707 char_u *fname; /* file or function name */ 708 linenr_T after; /* after this line number */ 709 { 710 return debuggy_find(file, fname, after, &dbg_breakp, NULL); 711 } 712 713 #if defined(FEAT_PROFILE) || defined(PROTO) 714 /* 715 * Return TRUE if profiling is on for a function or sourced file. 716 */ 717 int 718 has_profiling(file, fname, fp) 719 int file; /* TRUE for a file, FALSE for a function */ 720 char_u *fname; /* file or function name */ 721 int *fp; /* return: forceit */ 722 { 723 return (debuggy_find(file, fname, (linenr_T)0, &prof_ga, fp) 724 != (linenr_T)0); 725 } 726 #endif 727 728 /* 729 * Common code for dbg_find_breakpoint() and has_profiling(). 730 */ 731 static linenr_T 732 debuggy_find(file, fname, after, gap, fp) 733 int file; /* TRUE for a file, FALSE for a function */ 734 char_u *fname; /* file or function name */ 735 linenr_T after; /* after this line number */ 736 garray_T *gap; /* either &dbg_breakp or &prof_ga */ 737 int *fp; /* if not NULL: return forceit */ 738 { 739 struct debuggy *bp; 740 int i; 741 linenr_T lnum = 0; 742 regmatch_T regmatch; 743 char_u *name = fname; 744 int prev_got_int; 745 746 /* Return quickly when there are no breakpoints. */ 747 if (gap->ga_len == 0) 748 return (linenr_T)0; 749 750 /* Replace K_SNR in function name with "<SNR>". */ 751 if (!file && fname[0] == K_SPECIAL) 752 { 753 name = alloc((unsigned)STRLEN(fname) + 3); 754 if (name == NULL) 755 name = fname; 756 else 757 { 758 STRCPY(name, "<SNR>"); 759 STRCPY(name + 5, fname + 3); 760 } 761 } 762 763 for (i = 0; i < gap->ga_len; ++i) 764 { 765 /* Skip entries that are not useful or are for a line that is beyond 766 * an already found breakpoint. */ 767 bp = &DEBUGGY(gap, i); 768 if (((bp->dbg_type == DBG_FILE) == file && ( 769 #ifdef FEAT_PROFILE 770 gap == &prof_ga || 771 #endif 772 (bp->dbg_lnum > after && (lnum == 0 || bp->dbg_lnum < lnum))))) 773 { 774 regmatch.regprog = bp->dbg_prog; 775 regmatch.rm_ic = FALSE; 776 /* 777 * Save the value of got_int and reset it. We don't want a 778 * previous interruption cancel matching, only hitting CTRL-C 779 * while matching should abort it. 780 */ 781 prev_got_int = got_int; 782 got_int = FALSE; 783 if (vim_regexec(®match, name, (colnr_T)0)) 784 { 785 lnum = bp->dbg_lnum; 786 if (fp != NULL) 787 *fp = bp->dbg_forceit; 788 } 789 got_int |= prev_got_int; 790 } 791 } 792 if (name != fname) 793 vim_free(name); 794 795 return lnum; 796 } 797 798 /* 799 * Called when a breakpoint was encountered. 800 */ 801 void 802 dbg_breakpoint(name, lnum) 803 char_u *name; 804 linenr_T lnum; 805 { 806 /* We need to check if this line is actually executed in do_one_cmd() */ 807 debug_breakpoint_name = name; 808 debug_breakpoint_lnum = lnum; 809 } 810 811 812 # if defined(FEAT_PROFILE) || defined(FEAT_RELTIME) || defined(PROTO) 813 /* 814 * Store the current time in "tm". 815 */ 816 void 817 profile_start(tm) 818 proftime_T *tm; 819 { 820 # ifdef WIN3264 821 QueryPerformanceCounter(tm); 822 # else 823 gettimeofday(tm, NULL); 824 # endif 825 } 826 827 /* 828 * Compute the elapsed time from "tm" till now and store in "tm". 829 */ 830 void 831 profile_end(tm) 832 proftime_T *tm; 833 { 834 proftime_T now; 835 836 # ifdef WIN3264 837 QueryPerformanceCounter(&now); 838 tm->QuadPart = now.QuadPart - tm->QuadPart; 839 # else 840 gettimeofday(&now, NULL); 841 tm->tv_usec = now.tv_usec - tm->tv_usec; 842 tm->tv_sec = now.tv_sec - tm->tv_sec; 843 if (tm->tv_usec < 0) 844 { 845 tm->tv_usec += 1000000; 846 --tm->tv_sec; 847 } 848 # endif 849 } 850 851 /* 852 * Subtract the time "tm2" from "tm". 853 */ 854 void 855 profile_sub(tm, tm2) 856 proftime_T *tm, *tm2; 857 { 858 # ifdef WIN3264 859 tm->QuadPart -= tm2->QuadPart; 860 # else 861 tm->tv_usec -= tm2->tv_usec; 862 tm->tv_sec -= tm2->tv_sec; 863 if (tm->tv_usec < 0) 864 { 865 tm->tv_usec += 1000000; 866 --tm->tv_sec; 867 } 868 # endif 869 } 870 871 /* 872 * Return a string that represents the time in "tm". 873 * Uses a static buffer! 874 */ 875 char * 876 profile_msg(tm) 877 proftime_T *tm; 878 { 879 static char buf[50]; 880 881 # ifdef WIN3264 882 LARGE_INTEGER fr; 883 884 QueryPerformanceFrequency(&fr); 885 sprintf(buf, "%10.6lf", (double)tm->QuadPart / (double)fr.QuadPart); 886 # else 887 sprintf(buf, "%3ld.%06ld", (long)tm->tv_sec, (long)tm->tv_usec); 888 #endif 889 return buf; 890 } 891 892 # endif /* FEAT_PROFILE || FEAT_RELTIME */ 893 894 # if defined(FEAT_PROFILE) || defined(PROTO) 895 /* 896 * Functions for profiling. 897 */ 898 static void script_do_profile __ARGS((scriptitem_T *si)); 899 static void script_dump_profile __ARGS((FILE *fd)); 900 static proftime_T prof_wait_time; 901 902 /* 903 * Set the time in "tm" to zero. 904 */ 905 void 906 profile_zero(tm) 907 proftime_T *tm; 908 { 909 # ifdef WIN3264 910 tm->QuadPart = 0; 911 # else 912 tm->tv_usec = 0; 913 tm->tv_sec = 0; 914 # endif 915 } 916 917 /* 918 * Add the time "tm2" to "tm". 919 */ 920 void 921 profile_add(tm, tm2) 922 proftime_T *tm, *tm2; 923 { 924 # ifdef WIN3264 925 tm->QuadPart += tm2->QuadPart; 926 # else 927 tm->tv_usec += tm2->tv_usec; 928 tm->tv_sec += tm2->tv_sec; 929 if (tm->tv_usec >= 1000000) 930 { 931 tm->tv_usec -= 1000000; 932 ++tm->tv_sec; 933 } 934 # endif 935 } 936 937 /* 938 * Add the "self" time from the total time and the children's time. 939 */ 940 void 941 profile_self(self, total, children) 942 proftime_T *self, *total, *children; 943 { 944 /* Check that the result won't be negative. Can happen with recursive 945 * calls. */ 946 #ifdef WIN3264 947 if (total->QuadPart <= children->QuadPart) 948 return; 949 #else 950 if (total->tv_sec < children->tv_sec 951 || (total->tv_sec == children->tv_sec 952 && total->tv_usec <= children->tv_usec)) 953 return; 954 #endif 955 profile_add(self, total); 956 profile_sub(self, children); 957 } 958 959 /* 960 * Get the current waittime. 961 */ 962 void 963 profile_get_wait(tm) 964 proftime_T *tm; 965 { 966 *tm = prof_wait_time; 967 } 968 969 /* 970 * Subtract the passed waittime since "tm" from "tma". 971 */ 972 void 973 profile_sub_wait(tm, tma) 974 proftime_T *tm, *tma; 975 { 976 proftime_T tm3 = prof_wait_time; 977 978 profile_sub(&tm3, tm); 979 profile_sub(tma, &tm3); 980 } 981 982 /* 983 * Return TRUE if "tm1" and "tm2" are equal. 984 */ 985 int 986 profile_equal(tm1, tm2) 987 proftime_T *tm1, *tm2; 988 { 989 # ifdef WIN3264 990 return (tm1->QuadPart == tm2->QuadPart); 991 # else 992 return (tm1->tv_usec == tm2->tv_usec && tm1->tv_sec == tm2->tv_sec); 993 # endif 994 } 995 996 /* 997 * Return <0, 0 or >0 if "tm1" < "tm2", "tm1" == "tm2" or "tm1" > "tm2" 998 */ 999 int 1000 profile_cmp(tm1, tm2) 1001 proftime_T *tm1, *tm2; 1002 { 1003 # ifdef WIN3264 1004 return (int)(tm2->QuadPart - tm1->QuadPart); 1005 # else 1006 if (tm1->tv_sec == tm2->tv_sec) 1007 return tm2->tv_usec - tm1->tv_usec; 1008 return tm2->tv_sec - tm1->tv_sec; 1009 # endif 1010 } 1011 1012 static char_u *profile_fname = NULL; 1013 static proftime_T pause_time; 1014 1015 /* 1016 * ":profile cmd args" 1017 */ 1018 void 1019 ex_profile(eap) 1020 exarg_T *eap; 1021 { 1022 char_u *e; 1023 int len; 1024 1025 e = skiptowhite(eap->arg); 1026 len = e - eap->arg; 1027 e = skipwhite(e); 1028 1029 if (len == 5 && STRNCMP(eap->arg, "start", 5) == 0 && *e != NUL) 1030 { 1031 vim_free(profile_fname); 1032 profile_fname = vim_strsave(e); 1033 do_profiling = PROF_YES; 1034 profile_zero(&prof_wait_time); 1035 set_vim_var_nr(VV_PROFILING, 1L); 1036 } 1037 else if (do_profiling == PROF_NONE) 1038 EMSG(_("E750: First use :profile start <fname>")); 1039 else if (STRCMP(eap->arg, "pause") == 0) 1040 { 1041 if (do_profiling == PROF_YES) 1042 profile_start(&pause_time); 1043 do_profiling = PROF_PAUSED; 1044 } 1045 else if (STRCMP(eap->arg, "continue") == 0) 1046 { 1047 if (do_profiling == PROF_PAUSED) 1048 { 1049 profile_end(&pause_time); 1050 profile_add(&prof_wait_time, &pause_time); 1051 } 1052 do_profiling = PROF_YES; 1053 } 1054 else 1055 { 1056 /* The rest is similar to ":breakadd". */ 1057 ex_breakadd(eap); 1058 } 1059 } 1060 1061 /* 1062 * Dump the profiling info. 1063 */ 1064 void 1065 profile_dump() 1066 { 1067 FILE *fd; 1068 1069 if (profile_fname != NULL) 1070 { 1071 fd = mch_fopen((char *)profile_fname, "w"); 1072 if (fd == NULL) 1073 EMSG2(_(e_notopen), profile_fname); 1074 else 1075 { 1076 script_dump_profile(fd); 1077 func_dump_profile(fd); 1078 fclose(fd); 1079 } 1080 } 1081 } 1082 1083 /* 1084 * Start profiling script "fp". 1085 */ 1086 static void 1087 script_do_profile(si) 1088 scriptitem_T *si; 1089 { 1090 si->sn_pr_count = 0; 1091 profile_zero(&si->sn_pr_total); 1092 profile_zero(&si->sn_pr_self); 1093 1094 ga_init2(&si->sn_prl_ga, sizeof(sn_prl_T), 100); 1095 si->sn_prl_idx = -1; 1096 si->sn_prof_on = TRUE; 1097 si->sn_pr_nest = 0; 1098 } 1099 1100 /* 1101 * save time when starting to invoke another script or function. 1102 */ 1103 void 1104 script_prof_save(tm) 1105 proftime_T *tm; /* place to store wait time */ 1106 { 1107 scriptitem_T *si; 1108 1109 if (current_SID > 0 && current_SID <= script_items.ga_len) 1110 { 1111 si = &SCRIPT_ITEM(current_SID); 1112 if (si->sn_prof_on && si->sn_pr_nest++ == 0) 1113 profile_start(&si->sn_pr_child); 1114 } 1115 profile_get_wait(tm); 1116 } 1117 1118 /* 1119 * Count time spent in children after invoking another script or function. 1120 */ 1121 void 1122 script_prof_restore(tm) 1123 proftime_T *tm; 1124 { 1125 scriptitem_T *si; 1126 1127 if (current_SID > 0 && current_SID <= script_items.ga_len) 1128 { 1129 si = &SCRIPT_ITEM(current_SID); 1130 if (si->sn_prof_on && --si->sn_pr_nest == 0) 1131 { 1132 profile_end(&si->sn_pr_child); 1133 profile_sub_wait(tm, &si->sn_pr_child); /* don't count wait time */ 1134 profile_add(&si->sn_pr_children, &si->sn_pr_child); 1135 profile_add(&si->sn_prl_children, &si->sn_pr_child); 1136 } 1137 } 1138 } 1139 1140 static proftime_T inchar_time; 1141 1142 /* 1143 * Called when starting to wait for the user to type a character. 1144 */ 1145 void 1146 prof_inchar_enter() 1147 { 1148 profile_start(&inchar_time); 1149 } 1150 1151 /* 1152 * Called when finished waiting for the user to type a character. 1153 */ 1154 void 1155 prof_inchar_exit() 1156 { 1157 profile_end(&inchar_time); 1158 profile_add(&prof_wait_time, &inchar_time); 1159 } 1160 1161 /* 1162 * Dump the profiling results for all scripts in file "fd". 1163 */ 1164 static void 1165 script_dump_profile(fd) 1166 FILE *fd; 1167 { 1168 int id; 1169 scriptitem_T *si; 1170 int i; 1171 FILE *sfd; 1172 sn_prl_T *pp; 1173 1174 for (id = 1; id <= script_items.ga_len; ++id) 1175 { 1176 si = &SCRIPT_ITEM(id); 1177 if (si->sn_prof_on) 1178 { 1179 fprintf(fd, "SCRIPT %s\n", si->sn_name); 1180 if (si->sn_pr_count == 1) 1181 fprintf(fd, "Sourced 1 time\n"); 1182 else 1183 fprintf(fd, "Sourced %d times\n", si->sn_pr_count); 1184 fprintf(fd, "Total time: %s\n", profile_msg(&si->sn_pr_total)); 1185 fprintf(fd, " Self time: %s\n", profile_msg(&si->sn_pr_self)); 1186 fprintf(fd, "\n"); 1187 fprintf(fd, "count total (s) self (s)\n"); 1188 1189 sfd = mch_fopen((char *)si->sn_name, "r"); 1190 if (sfd == NULL) 1191 fprintf(fd, "Cannot open file!\n"); 1192 else 1193 { 1194 for (i = 0; i < si->sn_prl_ga.ga_len; ++i) 1195 { 1196 if (vim_fgets(IObuff, IOSIZE, sfd)) 1197 break; 1198 pp = &PRL_ITEM(si, i); 1199 if (pp->snp_count > 0) 1200 { 1201 fprintf(fd, "%5d ", pp->snp_count); 1202 if (profile_equal(&pp->sn_prl_total, &pp->sn_prl_self)) 1203 fprintf(fd, " "); 1204 else 1205 fprintf(fd, "%s ", profile_msg(&pp->sn_prl_total)); 1206 fprintf(fd, "%s ", profile_msg(&pp->sn_prl_self)); 1207 } 1208 else 1209 fprintf(fd, " "); 1210 fprintf(fd, "%s", IObuff); 1211 } 1212 fclose(sfd); 1213 } 1214 fprintf(fd, "\n"); 1215 } 1216 } 1217 } 1218 1219 /* 1220 * Return TRUE when a function defined in the current script should be 1221 * profiled. 1222 */ 1223 int 1224 prof_def_func() 1225 { 1226 if (current_SID > 0) 1227 return SCRIPT_ITEM(current_SID).sn_pr_force; 1228 return FALSE; 1229 } 1230 1231 # endif 1232 #endif 1233 1234 /* 1235 * If 'autowrite' option set, try to write the file. 1236 * Careful: autocommands may make "buf" invalid! 1237 * 1238 * return FAIL for failure, OK otherwise 1239 */ 1240 int 1241 autowrite(buf, forceit) 1242 buf_T *buf; 1243 int forceit; 1244 { 1245 if (!(p_aw || p_awa) || !p_write 1246 #ifdef FEAT_QUICKFIX 1247 /* never autowrite a "nofile" or "nowrite" buffer */ 1248 || bt_dontwrite(buf) 1249 #endif 1250 || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL) 1251 return FAIL; 1252 return buf_write_all(buf, forceit); 1253 } 1254 1255 /* 1256 * flush all buffers, except the ones that are readonly 1257 */ 1258 void 1259 autowrite_all() 1260 { 1261 buf_T *buf; 1262 1263 if (!(p_aw || p_awa) || !p_write) 1264 return; 1265 for (buf = firstbuf; buf; buf = buf->b_next) 1266 if (bufIsChanged(buf) && !buf->b_p_ro) 1267 { 1268 (void)buf_write_all(buf, FALSE); 1269 #ifdef FEAT_AUTOCMD 1270 /* an autocommand may have deleted the buffer */ 1271 if (!buf_valid(buf)) 1272 buf = firstbuf; 1273 #endif 1274 } 1275 } 1276 1277 /* 1278 * return TRUE if buffer was changed and cannot be abandoned. 1279 */ 1280 /*ARGSUSED*/ 1281 int 1282 check_changed(buf, checkaw, mult_win, forceit, allbuf) 1283 buf_T *buf; 1284 int checkaw; /* do autowrite if buffer was changed */ 1285 int mult_win; /* check also when several wins for the buf */ 1286 int forceit; 1287 int allbuf; /* may write all buffers */ 1288 { 1289 if ( !forceit 1290 && bufIsChanged(buf) 1291 && (mult_win || buf->b_nwindows <= 1) 1292 && (!checkaw || autowrite(buf, forceit) == FAIL)) 1293 { 1294 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 1295 if ((p_confirm || cmdmod.confirm) && p_write) 1296 { 1297 buf_T *buf2; 1298 int count = 0; 1299 1300 if (allbuf) 1301 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next) 1302 if (bufIsChanged(buf2) 1303 && (buf2->b_ffname != NULL 1304 # ifdef FEAT_BROWSE 1305 || cmdmod.browse 1306 # endif 1307 )) 1308 ++count; 1309 # ifdef FEAT_AUTOCMD 1310 if (!buf_valid(buf)) 1311 /* Autocommand deleted buffer, oops! It's not changed now. */ 1312 return FALSE; 1313 # endif 1314 dialog_changed(buf, count > 1); 1315 # ifdef FEAT_AUTOCMD 1316 if (!buf_valid(buf)) 1317 /* Autocommand deleted buffer, oops! It's not changed now. */ 1318 return FALSE; 1319 # endif 1320 return bufIsChanged(buf); 1321 } 1322 #endif 1323 EMSG(_(e_nowrtmsg)); 1324 return TRUE; 1325 } 1326 return FALSE; 1327 } 1328 1329 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO) 1330 1331 #if defined(FEAT_BROWSE) || defined(PROTO) 1332 /* 1333 * When wanting to write a file without a file name, ask the user for a name. 1334 */ 1335 void 1336 browse_save_fname(buf) 1337 buf_T *buf; 1338 { 1339 if (buf->b_fname == NULL) 1340 { 1341 char_u *fname; 1342 1343 fname = do_browse(BROWSE_SAVE, (char_u *)_("Save As"), 1344 NULL, NULL, NULL, NULL, buf); 1345 if (fname != NULL) 1346 { 1347 if (setfname(buf, fname, NULL, TRUE) == OK) 1348 buf->b_flags |= BF_NOTEDITED; 1349 vim_free(fname); 1350 } 1351 } 1352 } 1353 #endif 1354 1355 /* 1356 * Ask the user what to do when abondoning a changed buffer. 1357 * Must check 'write' option first! 1358 */ 1359 void 1360 dialog_changed(buf, checkall) 1361 buf_T *buf; 1362 int checkall; /* may abandon all changed buffers */ 1363 { 1364 char_u buff[IOSIZE]; 1365 int ret; 1366 buf_T *buf2; 1367 1368 dialog_msg(buff, _("Save changes to \"%s\"?"), 1369 (buf->b_fname != NULL) ? 1370 buf->b_fname : (char_u *)_("Untitled")); 1371 if (checkall) 1372 ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1); 1373 else 1374 ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1); 1375 1376 if (ret == VIM_YES) 1377 { 1378 #ifdef FEAT_BROWSE 1379 /* May get file name, when there is none */ 1380 browse_save_fname(buf); 1381 #endif 1382 if (buf->b_fname != NULL) /* didn't hit Cancel */ 1383 (void)buf_write_all(buf, FALSE); 1384 } 1385 else if (ret == VIM_NO) 1386 { 1387 unchanged(buf, TRUE); 1388 } 1389 else if (ret == VIM_ALL) 1390 { 1391 /* 1392 * Write all modified files that can be written. 1393 * Skip readonly buffers, these need to be confirmed 1394 * individually. 1395 */ 1396 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next) 1397 { 1398 if (bufIsChanged(buf2) 1399 && (buf2->b_ffname != NULL 1400 #ifdef FEAT_BROWSE 1401 || cmdmod.browse 1402 #endif 1403 ) 1404 && !buf2->b_p_ro) 1405 { 1406 #ifdef FEAT_BROWSE 1407 /* May get file name, when there is none */ 1408 browse_save_fname(buf2); 1409 #endif 1410 if (buf2->b_fname != NULL) /* didn't hit Cancel */ 1411 (void)buf_write_all(buf2, FALSE); 1412 #ifdef FEAT_AUTOCMD 1413 /* an autocommand may have deleted the buffer */ 1414 if (!buf_valid(buf2)) 1415 buf2 = firstbuf; 1416 #endif 1417 } 1418 } 1419 } 1420 else if (ret == VIM_DISCARDALL) 1421 { 1422 /* 1423 * mark all buffers as unchanged 1424 */ 1425 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next) 1426 unchanged(buf2, TRUE); 1427 } 1428 } 1429 #endif 1430 1431 /* 1432 * Return TRUE if the buffer "buf" can be abandoned, either by making it 1433 * hidden, autowriting it or unloading it. 1434 */ 1435 int 1436 can_abandon(buf, forceit) 1437 buf_T *buf; 1438 int forceit; 1439 { 1440 return ( P_HID(buf) 1441 || !bufIsChanged(buf) 1442 || buf->b_nwindows > 1 1443 || autowrite(buf, forceit) == OK 1444 || forceit); 1445 } 1446 1447 /* 1448 * Return TRUE if any buffer was changed and cannot be abandoned. 1449 * That changed buffer becomes the current buffer. 1450 */ 1451 int 1452 check_changed_any(hidden) 1453 int hidden; /* Only check hidden buffers */ 1454 { 1455 buf_T *buf; 1456 int save; 1457 #ifdef FEAT_WINDOWS 1458 win_T *wp; 1459 #endif 1460 1461 for (;;) 1462 { 1463 /* check curbuf first: if it was changed we can't abandon it */ 1464 if (!hidden && curbufIsChanged()) 1465 buf = curbuf; 1466 else 1467 { 1468 for (buf = firstbuf; buf != NULL; buf = buf->b_next) 1469 if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf)) 1470 break; 1471 } 1472 if (buf == NULL) /* No buffers changed */ 1473 return FALSE; 1474 1475 if (check_changed(buf, p_awa, TRUE, FALSE, TRUE) && buf_valid(buf)) 1476 break; /* didn't save - still changes */ 1477 } 1478 1479 exiting = FALSE; 1480 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 1481 /* 1482 * When ":confirm" used, don't give an error message. 1483 */ 1484 if (!(p_confirm || cmdmod.confirm)) 1485 #endif 1486 { 1487 /* There must be a wait_return for this message, do_buffer() 1488 * may cause a redraw. But wait_return() is a no-op when vgetc() 1489 * is busy (Quit used from window menu), then make sure we don't 1490 * cause a scroll up. */ 1491 if (vgetc_busy) 1492 { 1493 msg_row = cmdline_row; 1494 msg_col = 0; 1495 msg_didout = FALSE; 1496 } 1497 if (EMSG2(_("E162: No write since last change for buffer \"%s\""), 1498 buf_spname(buf) != NULL ? (char_u *)buf_spname(buf) : 1499 buf->b_fname)) 1500 { 1501 save = no_wait_return; 1502 no_wait_return = FALSE; 1503 wait_return(FALSE); 1504 no_wait_return = save; 1505 } 1506 } 1507 1508 #ifdef FEAT_WINDOWS 1509 /* Try to find a window that contains the buffer. */ 1510 if (buf != curbuf) 1511 for (wp = firstwin; wp != NULL; wp = wp->w_next) 1512 if (wp->w_buffer == buf) 1513 { 1514 win_goto(wp); 1515 # ifdef FEAT_AUTOCMD 1516 /* Paranoia: did autocms wipe out the buffer with changes? */ 1517 if (!buf_valid(buf)) 1518 return TRUE; 1519 # endif 1520 break; 1521 } 1522 #endif 1523 1524 /* Open the changed buffer in the current window. */ 1525 if (buf != curbuf) 1526 set_curbuf(buf, DOBUF_GOTO); 1527 1528 return TRUE; 1529 } 1530 1531 /* 1532 * return FAIL if there is no file name, OK if there is one 1533 * give error message for FAIL 1534 */ 1535 int 1536 check_fname() 1537 { 1538 if (curbuf->b_ffname == NULL) 1539 { 1540 EMSG(_(e_noname)); 1541 return FAIL; 1542 } 1543 return OK; 1544 } 1545 1546 /* 1547 * flush the contents of a buffer, unless it has no file name 1548 * 1549 * return FAIL for failure, OK otherwise 1550 */ 1551 int 1552 buf_write_all(buf, forceit) 1553 buf_T *buf; 1554 int forceit; 1555 { 1556 int retval; 1557 #ifdef FEAT_AUTOCMD 1558 buf_T *old_curbuf = curbuf; 1559 #endif 1560 1561 retval = (buf_write(buf, buf->b_ffname, buf->b_fname, 1562 (linenr_T)1, buf->b_ml.ml_line_count, NULL, 1563 FALSE, forceit, TRUE, FALSE)); 1564 #ifdef FEAT_AUTOCMD 1565 if (curbuf != old_curbuf) 1566 { 1567 msg_source(hl_attr(HLF_W)); 1568 MSG(_("Warning: Entered other buffer unexpectedly (check autocommands)")); 1569 } 1570 #endif 1571 return retval; 1572 } 1573 1574 /* 1575 * Code to handle the argument list. 1576 */ 1577 1578 static char_u *do_one_arg __ARGS((char_u *str)); 1579 static int do_arglist __ARGS((char_u *str, int what, int after)); 1580 static void alist_check_arg_idx __ARGS((void)); 1581 static int editing_arg_idx __ARGS((win_T *win)); 1582 #ifdef FEAT_LISTCMDS 1583 static int alist_add_list __ARGS((int count, char_u **files, int after)); 1584 #endif 1585 #define AL_SET 1 1586 #define AL_ADD 2 1587 #define AL_DEL 3 1588 1589 /* 1590 * Isolate one argument, taking backticks. 1591 * Changes the argument in-place, puts a NUL after it. Backticks remain. 1592 * Return a pointer to the start of the next argument. 1593 */ 1594 static char_u * 1595 do_one_arg(str) 1596 char_u *str; 1597 { 1598 char_u *p; 1599 int inbacktick; 1600 1601 inbacktick = FALSE; 1602 for (p = str; *str; ++str) 1603 { 1604 /* When the backslash is used for escaping the special meaning of a 1605 * character we need to keep it until wildcard expansion. */ 1606 if (rem_backslash(str)) 1607 { 1608 *p++ = *str++; 1609 *p++ = *str; 1610 } 1611 else 1612 { 1613 /* An item ends at a space not in backticks */ 1614 if (!inbacktick && vim_isspace(*str)) 1615 break; 1616 if (*str == '`') 1617 inbacktick ^= TRUE; 1618 *p++ = *str; 1619 } 1620 } 1621 str = skipwhite(str); 1622 *p = NUL; 1623 1624 return str; 1625 } 1626 1627 /* 1628 * Separate the arguments in "str" and return a list of pointers in the 1629 * growarray "gap". 1630 */ 1631 int 1632 get_arglist(gap, str) 1633 garray_T *gap; 1634 char_u *str; 1635 { 1636 ga_init2(gap, (int)sizeof(char_u *), 20); 1637 while (*str != NUL) 1638 { 1639 if (ga_grow(gap, 1) == FAIL) 1640 { 1641 ga_clear(gap); 1642 return FAIL; 1643 } 1644 ((char_u **)gap->ga_data)[gap->ga_len++] = str; 1645 1646 /* Isolate one argument, change it in-place, put a NUL after it. */ 1647 str = do_one_arg(str); 1648 } 1649 return OK; 1650 } 1651 1652 #if defined(FEAT_QUICKFIX) || defined(FEAT_SYN_HL) || defined(PROTO) 1653 /* 1654 * Parse a list of arguments (file names), expand them and return in 1655 * "fnames[fcountp]". 1656 * Return FAIL or OK. 1657 */ 1658 int 1659 get_arglist_exp(str, fcountp, fnamesp) 1660 char_u *str; 1661 int *fcountp; 1662 char_u ***fnamesp; 1663 { 1664 garray_T ga; 1665 int i; 1666 1667 if (get_arglist(&ga, str) == FAIL) 1668 return FAIL; 1669 i = gen_expand_wildcards(ga.ga_len, (char_u **)ga.ga_data, 1670 fcountp, fnamesp, EW_FILE|EW_NOTFOUND); 1671 ga_clear(&ga); 1672 return i; 1673 } 1674 #endif 1675 1676 #if defined(FEAT_GUI) || defined(FEAT_CLIENTSERVER) || defined(PROTO) 1677 /* 1678 * Redefine the argument list. 1679 */ 1680 void 1681 set_arglist(str) 1682 char_u *str; 1683 { 1684 do_arglist(str, AL_SET, 0); 1685 } 1686 #endif 1687 1688 /* 1689 * "what" == AL_SET: Redefine the argument list to 'str'. 1690 * "what" == AL_ADD: add files in 'str' to the argument list after "after". 1691 * "what" == AL_DEL: remove files in 'str' from the argument list. 1692 * 1693 * Return FAIL for failure, OK otherwise. 1694 */ 1695 /*ARGSUSED*/ 1696 static int 1697 do_arglist(str, what, after) 1698 char_u *str; 1699 int what; 1700 int after; /* 0 means before first one */ 1701 { 1702 garray_T new_ga; 1703 int exp_count; 1704 char_u **exp_files; 1705 int i; 1706 #ifdef FEAT_LISTCMDS 1707 char_u *p; 1708 int match; 1709 #endif 1710 1711 /* 1712 * Collect all file name arguments in "new_ga". 1713 */ 1714 if (get_arglist(&new_ga, str) == FAIL) 1715 return FAIL; 1716 1717 #ifdef FEAT_LISTCMDS 1718 if (what == AL_DEL) 1719 { 1720 regmatch_T regmatch; 1721 int didone; 1722 1723 /* 1724 * Delete the items: use each item as a regexp and find a match in the 1725 * argument list. 1726 */ 1727 #ifdef CASE_INSENSITIVE_FILENAME 1728 regmatch.rm_ic = TRUE; /* Always ignore case */ 1729 #else 1730 regmatch.rm_ic = FALSE; /* Never ignore case */ 1731 #endif 1732 for (i = 0; i < new_ga.ga_len && !got_int; ++i) 1733 { 1734 p = ((char_u **)new_ga.ga_data)[i]; 1735 p = file_pat_to_reg_pat(p, NULL, NULL, FALSE); 1736 if (p == NULL) 1737 break; 1738 regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0); 1739 if (regmatch.regprog == NULL) 1740 { 1741 vim_free(p); 1742 break; 1743 } 1744 1745 didone = FALSE; 1746 for (match = 0; match < ARGCOUNT; ++match) 1747 if (vim_regexec(®match, alist_name(&ARGLIST[match]), 1748 (colnr_T)0)) 1749 { 1750 didone = TRUE; 1751 vim_free(ARGLIST[match].ae_fname); 1752 mch_memmove(ARGLIST + match, ARGLIST + match + 1, 1753 (ARGCOUNT - match - 1) * sizeof(aentry_T)); 1754 --ALIST(curwin)->al_ga.ga_len; 1755 if (curwin->w_arg_idx > match) 1756 --curwin->w_arg_idx; 1757 --match; 1758 } 1759 1760 vim_free(regmatch.regprog); 1761 vim_free(p); 1762 if (!didone) 1763 EMSG2(_(e_nomatch2), ((char_u **)new_ga.ga_data)[i]); 1764 } 1765 ga_clear(&new_ga); 1766 } 1767 else 1768 #endif 1769 { 1770 i = expand_wildcards(new_ga.ga_len, (char_u **)new_ga.ga_data, 1771 &exp_count, &exp_files, EW_DIR|EW_FILE|EW_ADDSLASH|EW_NOTFOUND); 1772 ga_clear(&new_ga); 1773 if (i == FAIL) 1774 return FAIL; 1775 if (exp_count == 0) 1776 { 1777 EMSG(_(e_nomatch)); 1778 return FAIL; 1779 } 1780 1781 #ifdef FEAT_LISTCMDS 1782 if (what == AL_ADD) 1783 { 1784 (void)alist_add_list(exp_count, exp_files, after); 1785 vim_free(exp_files); 1786 } 1787 else /* what == AL_SET */ 1788 #endif 1789 alist_set(ALIST(curwin), exp_count, exp_files, FALSE, NULL, 0); 1790 } 1791 1792 alist_check_arg_idx(); 1793 1794 return OK; 1795 } 1796 1797 /* 1798 * Check the validity of the arg_idx for each other window. 1799 */ 1800 static void 1801 alist_check_arg_idx() 1802 { 1803 #ifdef FEAT_WINDOWS 1804 win_T *win; 1805 tabpage_T *tp; 1806 1807 FOR_ALL_TAB_WINDOWS(tp, win) 1808 if (win->w_alist == curwin->w_alist) 1809 check_arg_idx(win); 1810 #else 1811 check_arg_idx(curwin); 1812 #endif 1813 } 1814 1815 /* 1816 * Return TRUE if window "win" is editing then file at the current argument 1817 * index. 1818 */ 1819 static int 1820 editing_arg_idx(win) 1821 win_T *win; 1822 { 1823 return !(win->w_arg_idx >= WARGCOUNT(win) 1824 || (win->w_buffer->b_fnum 1825 != WARGLIST(win)[win->w_arg_idx].ae_fnum 1826 && (win->w_buffer->b_ffname == NULL 1827 || !(fullpathcmp( 1828 alist_name(&WARGLIST(win)[win->w_arg_idx]), 1829 win->w_buffer->b_ffname, TRUE) & FPC_SAME)))); 1830 } 1831 1832 /* 1833 * Check if window "win" is editing the w_arg_idx file in its argument list. 1834 */ 1835 void 1836 check_arg_idx(win) 1837 win_T *win; 1838 { 1839 if (WARGCOUNT(win) > 1 && !editing_arg_idx(win)) 1840 { 1841 /* We are not editing the current entry in the argument list. 1842 * Set "arg_had_last" if we are editing the last one. */ 1843 win->w_arg_idx_invalid = TRUE; 1844 if (win->w_arg_idx != WARGCOUNT(win) - 1 1845 && arg_had_last == FALSE 1846 #ifdef FEAT_WINDOWS 1847 && ALIST(win) == &global_alist 1848 #endif 1849 && GARGCOUNT > 0 1850 && win->w_arg_idx < GARGCOUNT 1851 && (win->w_buffer->b_fnum == GARGLIST[GARGCOUNT - 1].ae_fnum 1852 || (win->w_buffer->b_ffname != NULL 1853 && (fullpathcmp(alist_name(&GARGLIST[GARGCOUNT - 1]), 1854 win->w_buffer->b_ffname, TRUE) & FPC_SAME)))) 1855 arg_had_last = TRUE; 1856 } 1857 else 1858 { 1859 /* We are editing the current entry in the argument list. 1860 * Set "arg_had_last" if it's also the last one */ 1861 win->w_arg_idx_invalid = FALSE; 1862 if (win->w_arg_idx == WARGCOUNT(win) - 1 1863 #ifdef FEAT_WINDOWS 1864 && win->w_alist == &global_alist 1865 #endif 1866 ) 1867 arg_had_last = TRUE; 1868 } 1869 } 1870 1871 /* 1872 * ":args", ":argslocal" and ":argsglobal". 1873 */ 1874 void 1875 ex_args(eap) 1876 exarg_T *eap; 1877 { 1878 int i; 1879 1880 if (eap->cmdidx != CMD_args) 1881 { 1882 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS) 1883 alist_unlink(ALIST(curwin)); 1884 if (eap->cmdidx == CMD_argglobal) 1885 ALIST(curwin) = &global_alist; 1886 else /* eap->cmdidx == CMD_arglocal */ 1887 alist_new(); 1888 #else 1889 ex_ni(eap); 1890 return; 1891 #endif 1892 } 1893 1894 if (!ends_excmd(*eap->arg)) 1895 { 1896 /* 1897 * ":args file ..": define new argument list, handle like ":next" 1898 * Also for ":argslocal file .." and ":argsglobal file ..". 1899 */ 1900 ex_next(eap); 1901 } 1902 else 1903 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS) 1904 if (eap->cmdidx == CMD_args) 1905 #endif 1906 { 1907 /* 1908 * ":args": list arguments. 1909 */ 1910 if (ARGCOUNT > 0) 1911 { 1912 /* Overwrite the command, for a short list there is no scrolling 1913 * required and no wait_return(). */ 1914 gotocmdline(TRUE); 1915 for (i = 0; i < ARGCOUNT; ++i) 1916 { 1917 if (i == curwin->w_arg_idx) 1918 msg_putchar('['); 1919 msg_outtrans(alist_name(&ARGLIST[i])); 1920 if (i == curwin->w_arg_idx) 1921 msg_putchar(']'); 1922 msg_putchar(' '); 1923 } 1924 } 1925 } 1926 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS) 1927 else if (eap->cmdidx == CMD_arglocal) 1928 { 1929 garray_T *gap = &curwin->w_alist->al_ga; 1930 1931 /* 1932 * ":argslocal": make a local copy of the global argument list. 1933 */ 1934 if (ga_grow(gap, GARGCOUNT) == OK) 1935 for (i = 0; i < GARGCOUNT; ++i) 1936 if (GARGLIST[i].ae_fname != NULL) 1937 { 1938 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fname = 1939 vim_strsave(GARGLIST[i].ae_fname); 1940 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fnum = 1941 GARGLIST[i].ae_fnum; 1942 ++gap->ga_len; 1943 } 1944 } 1945 #endif 1946 } 1947 1948 /* 1949 * ":previous", ":sprevious", ":Next" and ":sNext". 1950 */ 1951 void 1952 ex_previous(eap) 1953 exarg_T *eap; 1954 { 1955 /* If past the last one already, go to the last one. */ 1956 if (curwin->w_arg_idx - (int)eap->line2 >= ARGCOUNT) 1957 do_argfile(eap, ARGCOUNT - 1); 1958 else 1959 do_argfile(eap, curwin->w_arg_idx - (int)eap->line2); 1960 } 1961 1962 /* 1963 * ":rewind", ":first", ":sfirst" and ":srewind". 1964 */ 1965 void 1966 ex_rewind(eap) 1967 exarg_T *eap; 1968 { 1969 do_argfile(eap, 0); 1970 } 1971 1972 /* 1973 * ":last" and ":slast". 1974 */ 1975 void 1976 ex_last(eap) 1977 exarg_T *eap; 1978 { 1979 do_argfile(eap, ARGCOUNT - 1); 1980 } 1981 1982 /* 1983 * ":argument" and ":sargument". 1984 */ 1985 void 1986 ex_argument(eap) 1987 exarg_T *eap; 1988 { 1989 int i; 1990 1991 if (eap->addr_count > 0) 1992 i = eap->line2 - 1; 1993 else 1994 i = curwin->w_arg_idx; 1995 do_argfile(eap, i); 1996 } 1997 1998 /* 1999 * Edit file "argn" of the argument lists. 2000 */ 2001 void 2002 do_argfile(eap, argn) 2003 exarg_T *eap; 2004 int argn; 2005 { 2006 int other; 2007 char_u *p; 2008 int old_arg_idx = curwin->w_arg_idx; 2009 2010 if (argn < 0 || argn >= ARGCOUNT) 2011 { 2012 if (ARGCOUNT <= 1) 2013 EMSG(_("E163: There is only one file to edit")); 2014 else if (argn < 0) 2015 EMSG(_("E164: Cannot go before first file")); 2016 else 2017 EMSG(_("E165: Cannot go beyond last file")); 2018 } 2019 else 2020 { 2021 setpcmark(); 2022 #ifdef FEAT_GUI 2023 need_mouse_correct = TRUE; 2024 #endif 2025 2026 #ifdef FEAT_WINDOWS 2027 /* split window or create new tab page first */ 2028 if (*eap->cmd == 's' || cmdmod.tab != 0) 2029 { 2030 if (win_split(0, 0) == FAIL) 2031 return; 2032 # ifdef FEAT_SCROLLBIND 2033 curwin->w_p_scb = FALSE; 2034 # endif 2035 } 2036 else 2037 #endif 2038 { 2039 /* 2040 * if 'hidden' set, only check for changed file when re-editing 2041 * the same buffer 2042 */ 2043 other = TRUE; 2044 if (P_HID(curbuf)) 2045 { 2046 p = fix_fname(alist_name(&ARGLIST[argn])); 2047 other = otherfile(p); 2048 vim_free(p); 2049 } 2050 if ((!P_HID(curbuf) || !other) 2051 && check_changed(curbuf, TRUE, !other, eap->forceit, FALSE)) 2052 return; 2053 } 2054 2055 curwin->w_arg_idx = argn; 2056 if (argn == ARGCOUNT - 1 2057 #ifdef FEAT_WINDOWS 2058 && curwin->w_alist == &global_alist 2059 #endif 2060 ) 2061 arg_had_last = TRUE; 2062 2063 /* Edit the file; always use the last known line number. 2064 * When it fails (e.g. Abort for already edited file) restore the 2065 * argument index. */ 2066 if (do_ecmd(0, alist_name(&ARGLIST[curwin->w_arg_idx]), NULL, 2067 eap, ECMD_LAST, 2068 (P_HID(curwin->w_buffer) ? ECMD_HIDE : 0) + 2069 (eap->forceit ? ECMD_FORCEIT : 0)) == FAIL) 2070 curwin->w_arg_idx = old_arg_idx; 2071 /* like Vi: set the mark where the cursor is in the file. */ 2072 else if (eap->cmdidx != CMD_argdo) 2073 setmark('\''); 2074 } 2075 } 2076 2077 /* 2078 * ":next", and commands that behave like it. 2079 */ 2080 void 2081 ex_next(eap) 2082 exarg_T *eap; 2083 { 2084 int i; 2085 2086 /* 2087 * check for changed buffer now, if this fails the argument list is not 2088 * redefined. 2089 */ 2090 if ( P_HID(curbuf) 2091 || eap->cmdidx == CMD_snext 2092 || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE)) 2093 { 2094 if (*eap->arg != NUL) /* redefine file list */ 2095 { 2096 if (do_arglist(eap->arg, AL_SET, 0) == FAIL) 2097 return; 2098 i = 0; 2099 } 2100 else 2101 i = curwin->w_arg_idx + (int)eap->line2; 2102 do_argfile(eap, i); 2103 } 2104 } 2105 2106 #ifdef FEAT_LISTCMDS 2107 /* 2108 * ":argedit" 2109 */ 2110 void 2111 ex_argedit(eap) 2112 exarg_T *eap; 2113 { 2114 int fnum; 2115 int i; 2116 char_u *s; 2117 2118 /* Add the argument to the buffer list and get the buffer number. */ 2119 fnum = buflist_add(eap->arg, BLN_LISTED); 2120 2121 /* Check if this argument is already in the argument list. */ 2122 for (i = 0; i < ARGCOUNT; ++i) 2123 if (ARGLIST[i].ae_fnum == fnum) 2124 break; 2125 if (i == ARGCOUNT) 2126 { 2127 /* Can't find it, add it to the argument list. */ 2128 s = vim_strsave(eap->arg); 2129 if (s == NULL) 2130 return; 2131 i = alist_add_list(1, &s, 2132 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1); 2133 if (i < 0) 2134 return; 2135 curwin->w_arg_idx = i; 2136 } 2137 2138 alist_check_arg_idx(); 2139 2140 /* Edit the argument. */ 2141 do_argfile(eap, i); 2142 } 2143 2144 /* 2145 * ":argadd" 2146 */ 2147 void 2148 ex_argadd(eap) 2149 exarg_T *eap; 2150 { 2151 do_arglist(eap->arg, AL_ADD, 2152 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1); 2153 #ifdef FEAT_TITLE 2154 maketitle(); 2155 #endif 2156 } 2157 2158 /* 2159 * ":argdelete" 2160 */ 2161 void 2162 ex_argdelete(eap) 2163 exarg_T *eap; 2164 { 2165 int i; 2166 int n; 2167 2168 if (eap->addr_count > 0) 2169 { 2170 /* ":1,4argdel": Delete all arguments in the range. */ 2171 if (eap->line2 > ARGCOUNT) 2172 eap->line2 = ARGCOUNT; 2173 n = eap->line2 - eap->line1 + 1; 2174 if (*eap->arg != NUL || n <= 0) 2175 EMSG(_(e_invarg)); 2176 else 2177 { 2178 for (i = eap->line1; i <= eap->line2; ++i) 2179 vim_free(ARGLIST[i - 1].ae_fname); 2180 mch_memmove(ARGLIST + eap->line1 - 1, ARGLIST + eap->line2, 2181 (size_t)((ARGCOUNT - eap->line2) * sizeof(aentry_T))); 2182 ALIST(curwin)->al_ga.ga_len -= n; 2183 if (curwin->w_arg_idx >= eap->line2) 2184 curwin->w_arg_idx -= n; 2185 else if (curwin->w_arg_idx > eap->line1) 2186 curwin->w_arg_idx = eap->line1; 2187 } 2188 } 2189 else if (*eap->arg == NUL) 2190 EMSG(_(e_argreq)); 2191 else 2192 do_arglist(eap->arg, AL_DEL, 0); 2193 #ifdef FEAT_TITLE 2194 maketitle(); 2195 #endif 2196 } 2197 2198 /* 2199 * ":argdo", ":windo", ":bufdo", ":tabdo" 2200 */ 2201 void 2202 ex_listdo(eap) 2203 exarg_T *eap; 2204 { 2205 int i; 2206 #ifdef FEAT_WINDOWS 2207 win_T *wp; 2208 tabpage_T *tp; 2209 #endif 2210 buf_T *buf; 2211 int next_fnum = 0; 2212 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL) 2213 char_u *save_ei = NULL; 2214 #endif 2215 char_u *p_shm_save; 2216 2217 #ifndef FEAT_WINDOWS 2218 if (eap->cmdidx == CMD_windo) 2219 { 2220 ex_ni(eap); 2221 return; 2222 } 2223 #endif 2224 2225 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL) 2226 if (eap->cmdidx != CMD_windo) 2227 /* Don't do syntax HL autocommands. Skipping the syntax file is a 2228 * great speed improvement. */ 2229 save_ei = au_event_disable(",Syntax"); 2230 #endif 2231 2232 if (eap->cmdidx == CMD_windo 2233 || eap->cmdidx == CMD_tabdo 2234 || P_HID(curbuf) 2235 || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE)) 2236 { 2237 /* start at the first argument/window/buffer */ 2238 i = 0; 2239 #ifdef FEAT_WINDOWS 2240 wp = firstwin; 2241 tp = first_tabpage; 2242 #endif 2243 /* set pcmark now */ 2244 if (eap->cmdidx == CMD_bufdo) 2245 goto_buffer(eap, DOBUF_FIRST, FORWARD, 0); 2246 else 2247 setpcmark(); 2248 listcmd_busy = TRUE; /* avoids setting pcmark below */ 2249 2250 while (!got_int) 2251 { 2252 if (eap->cmdidx == CMD_argdo) 2253 { 2254 /* go to argument "i" */ 2255 if (i == ARGCOUNT) 2256 break; 2257 /* Don't call do_argfile() when already there, it will try 2258 * reloading the file. */ 2259 if (curwin->w_arg_idx != i || !editing_arg_idx(curwin)) 2260 { 2261 /* Clear 'shm' to avoid that the file message overwrites 2262 * any output from the command. */ 2263 p_shm_save = vim_strsave(p_shm); 2264 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0); 2265 do_argfile(eap, i); 2266 set_option_value((char_u *)"shm", 0L, p_shm_save, 0); 2267 vim_free(p_shm_save); 2268 } 2269 if (curwin->w_arg_idx != i) 2270 break; 2271 ++i; 2272 } 2273 #ifdef FEAT_WINDOWS 2274 else if (eap->cmdidx == CMD_windo) 2275 { 2276 /* go to window "wp" */ 2277 if (!win_valid(wp)) 2278 break; 2279 win_goto(wp); 2280 wp = curwin->w_next; 2281 } 2282 else if (eap->cmdidx == CMD_tabdo) 2283 { 2284 /* go to window "tp" */ 2285 if (!valid_tabpage(tp)) 2286 break; 2287 goto_tabpage_tp(tp); 2288 tp = tp->tp_next; 2289 } 2290 #endif 2291 else if (eap->cmdidx == CMD_bufdo) 2292 { 2293 /* Remember the number of the next listed buffer, in case 2294 * ":bwipe" is used or autocommands do something strange. */ 2295 next_fnum = -1; 2296 for (buf = curbuf->b_next; buf != NULL; buf = buf->b_next) 2297 if (buf->b_p_bl) 2298 { 2299 next_fnum = buf->b_fnum; 2300 break; 2301 } 2302 } 2303 2304 /* execute the command */ 2305 do_cmdline(eap->arg, eap->getline, eap->cookie, 2306 DOCMD_VERBOSE + DOCMD_NOWAIT); 2307 2308 if (eap->cmdidx == CMD_bufdo) 2309 { 2310 /* Done? */ 2311 if (next_fnum < 0) 2312 break; 2313 /* Check if the buffer still exists. */ 2314 for (buf = firstbuf; buf != NULL; buf = buf->b_next) 2315 if (buf->b_fnum == next_fnum) 2316 break; 2317 if (buf == NULL) 2318 break; 2319 2320 /* Go to the next buffer. Clear 'shm' to avoid that the file 2321 * message overwrites any output from the command. */ 2322 p_shm_save = vim_strsave(p_shm); 2323 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0); 2324 goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum); 2325 set_option_value((char_u *)"shm", 0L, p_shm_save, 0); 2326 vim_free(p_shm_save); 2327 2328 /* If autocommands took us elsewhere, quit here */ 2329 if (curbuf->b_fnum != next_fnum) 2330 break; 2331 } 2332 2333 if (eap->cmdidx == CMD_windo) 2334 { 2335 validate_cursor(); /* cursor may have moved */ 2336 #ifdef FEAT_SCROLLBIND 2337 /* required when 'scrollbind' has been set */ 2338 if (curwin->w_p_scb) 2339 do_check_scrollbind(TRUE); 2340 #endif 2341 } 2342 } 2343 listcmd_busy = FALSE; 2344 } 2345 2346 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL) 2347 if (save_ei != NULL) 2348 { 2349 au_event_restore(save_ei); 2350 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, 2351 curbuf->b_fname, TRUE, curbuf); 2352 } 2353 #endif 2354 } 2355 2356 /* 2357 * Add files[count] to the arglist of the current window after arg "after". 2358 * The file names in files[count] must have been allocated and are taken over. 2359 * Files[] itself is not taken over. 2360 * Returns index of first added argument. Returns -1 when failed (out of mem). 2361 */ 2362 static int 2363 alist_add_list(count, files, after) 2364 int count; 2365 char_u **files; 2366 int after; /* where to add: 0 = before first one */ 2367 { 2368 int i; 2369 2370 if (ga_grow(&ALIST(curwin)->al_ga, count) == OK) 2371 { 2372 if (after < 0) 2373 after = 0; 2374 if (after > ARGCOUNT) 2375 after = ARGCOUNT; 2376 if (after < ARGCOUNT) 2377 mch_memmove(&(ARGLIST[after + count]), &(ARGLIST[after]), 2378 (ARGCOUNT - after) * sizeof(aentry_T)); 2379 for (i = 0; i < count; ++i) 2380 { 2381 ARGLIST[after + i].ae_fname = files[i]; 2382 ARGLIST[after + i].ae_fnum = buflist_add(files[i], BLN_LISTED); 2383 } 2384 ALIST(curwin)->al_ga.ga_len += count; 2385 if (curwin->w_arg_idx >= after) 2386 ++curwin->w_arg_idx; 2387 return after; 2388 } 2389 2390 for (i = 0; i < count; ++i) 2391 vim_free(files[i]); 2392 return -1; 2393 } 2394 2395 #endif /* FEAT_LISTCMDS */ 2396 2397 #ifdef FEAT_EVAL 2398 /* 2399 * ":compiler[!] {name}" 2400 */ 2401 void 2402 ex_compiler(eap) 2403 exarg_T *eap; 2404 { 2405 char_u *buf; 2406 char_u *old_cur_comp = NULL; 2407 char_u *p; 2408 2409 if (*eap->arg == NUL) 2410 { 2411 /* List all compiler scripts. */ 2412 do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')"); 2413 /* ) keep the indenter happy... */ 2414 } 2415 else 2416 { 2417 buf = alloc((unsigned)(STRLEN(eap->arg) + 14)); 2418 if (buf != NULL) 2419 { 2420 if (eap->forceit) 2421 { 2422 /* ":compiler! {name}" sets global options */ 2423 do_cmdline_cmd((char_u *) 2424 "command -nargs=* CompilerSet set <args>"); 2425 } 2426 else 2427 { 2428 /* ":compiler! {name}" sets local options. 2429 * To remain backwards compatible "current_compiler" is always 2430 * used. A user's compiler plugin may set it, the distributed 2431 * plugin will then skip the settings. Afterwards set 2432 * "b:current_compiler" and restore "current_compiler". */ 2433 old_cur_comp = get_var_value((char_u *)"current_compiler"); 2434 if (old_cur_comp != NULL) 2435 old_cur_comp = vim_strsave(old_cur_comp); 2436 do_cmdline_cmd((char_u *) 2437 "command -nargs=* CompilerSet setlocal <args>"); 2438 } 2439 do_unlet((char_u *)"current_compiler", TRUE); 2440 do_unlet((char_u *)"b:current_compiler", TRUE); 2441 2442 sprintf((char *)buf, "compiler/%s.vim", eap->arg); 2443 if (source_runtime(buf, TRUE) == FAIL) 2444 EMSG2(_("E666: compiler not supported: %s"), eap->arg); 2445 vim_free(buf); 2446 2447 do_cmdline_cmd((char_u *)":delcommand CompilerSet"); 2448 2449 /* Set "b:current_compiler" from "current_compiler". */ 2450 p = get_var_value((char_u *)"current_compiler"); 2451 if (p != NULL) 2452 set_internal_string_var((char_u *)"b:current_compiler", p); 2453 2454 /* Restore "current_compiler" for ":compiler {name}". */ 2455 if (!eap->forceit) 2456 { 2457 if (old_cur_comp != NULL) 2458 { 2459 set_internal_string_var((char_u *)"current_compiler", 2460 old_cur_comp); 2461 vim_free(old_cur_comp); 2462 } 2463 else 2464 do_unlet((char_u *)"current_compiler", TRUE); 2465 } 2466 } 2467 } 2468 } 2469 #endif 2470 2471 /* 2472 * ":runtime {name}" 2473 */ 2474 void 2475 ex_runtime(eap) 2476 exarg_T *eap; 2477 { 2478 source_runtime(eap->arg, eap->forceit); 2479 } 2480 2481 static void source_callback __ARGS((char_u *fname, void *cookie)); 2482 2483 /*ARGSUSED*/ 2484 static void 2485 source_callback(fname, cookie) 2486 char_u *fname; 2487 void *cookie; 2488 { 2489 (void)do_source(fname, FALSE, FALSE); 2490 } 2491 2492 /* 2493 * Source the file "name" from all directories in 'runtimepath'. 2494 * "name" can contain wildcards. 2495 * When "all" is TRUE, source all files, otherwise only the first one. 2496 * return FAIL when no file could be sourced, OK otherwise. 2497 */ 2498 int 2499 source_runtime(name, all) 2500 char_u *name; 2501 int all; 2502 { 2503 return do_in_runtimepath(name, all, source_callback, NULL); 2504 } 2505 2506 /* 2507 * Find "name" in 'runtimepath'. When found, invoke the callback function for 2508 * it: callback(fname, "cookie") 2509 * When "all" is TRUE repeat for all matches, otherwise only the first one is 2510 * used. 2511 * Returns OK when at least one match found, FAIL otherwise. 2512 */ 2513 int 2514 do_in_runtimepath(name, all, callback, cookie) 2515 char_u *name; 2516 int all; 2517 void (*callback)__ARGS((char_u *fname, void *ck)); 2518 void *cookie; 2519 { 2520 char_u *rtp; 2521 char_u *np; 2522 char_u *buf; 2523 char_u *rtp_copy; 2524 char_u *tail; 2525 int num_files; 2526 char_u **files; 2527 int i; 2528 int did_one = FALSE; 2529 #ifdef AMIGA 2530 struct Process *proc = (struct Process *)FindTask(0L); 2531 APTR save_winptr = proc->pr_WindowPtr; 2532 2533 /* Avoid a requester here for a volume that doesn't exist. */ 2534 proc->pr_WindowPtr = (APTR)-1L; 2535 #endif 2536 2537 /* Make a copy of 'runtimepath'. Invoking the callback may change the 2538 * value. */ 2539 rtp_copy = vim_strsave(p_rtp); 2540 buf = alloc(MAXPATHL); 2541 if (buf != NULL && rtp_copy != NULL) 2542 { 2543 if (p_verbose > 1) 2544 { 2545 verbose_enter(); 2546 smsg((char_u *)_("Searching for \"%s\" in \"%s\""), 2547 (char *)name, (char *)p_rtp); 2548 verbose_leave(); 2549 } 2550 2551 /* Loop over all entries in 'runtimepath'. */ 2552 rtp = rtp_copy; 2553 while (*rtp != NUL && (all || !did_one)) 2554 { 2555 /* Copy the path from 'runtimepath' to buf[]. */ 2556 copy_option_part(&rtp, buf, MAXPATHL, ","); 2557 if (STRLEN(buf) + STRLEN(name) + 2 < MAXPATHL) 2558 { 2559 add_pathsep(buf); 2560 tail = buf + STRLEN(buf); 2561 2562 /* Loop over all patterns in "name" */ 2563 np = name; 2564 while (*np != NUL && (all || !did_one)) 2565 { 2566 /* Append the pattern from "name" to buf[]. */ 2567 copy_option_part(&np, tail, (int)(MAXPATHL - (tail - buf)), 2568 "\t "); 2569 2570 if (p_verbose > 2) 2571 { 2572 verbose_enter(); 2573 smsg((char_u *)_("Searching for \"%s\""), buf); 2574 verbose_leave(); 2575 } 2576 2577 /* Expand wildcards, invoke the callback for each match. */ 2578 if (gen_expand_wildcards(1, &buf, &num_files, &files, 2579 EW_FILE) == OK) 2580 { 2581 for (i = 0; i < num_files; ++i) 2582 { 2583 (*callback)(files[i], cookie); 2584 did_one = TRUE; 2585 if (!all) 2586 break; 2587 } 2588 FreeWild(num_files, files); 2589 } 2590 } 2591 } 2592 } 2593 } 2594 vim_free(buf); 2595 vim_free(rtp_copy); 2596 if (p_verbose > 0 && !did_one) 2597 { 2598 verbose_enter(); 2599 smsg((char_u *)_("not found in 'runtimepath': \"%s\""), name); 2600 verbose_leave(); 2601 } 2602 2603 #ifdef AMIGA 2604 proc->pr_WindowPtr = save_winptr; 2605 #endif 2606 2607 return did_one ? OK : FAIL; 2608 } 2609 2610 #if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD) 2611 /* 2612 * ":options" 2613 */ 2614 /*ARGSUSED*/ 2615 void 2616 ex_options(eap) 2617 exarg_T *eap; 2618 { 2619 cmd_source((char_u *)SYS_OPTWIN_FILE, NULL); 2620 } 2621 #endif 2622 2623 /* 2624 * ":source {fname}" 2625 */ 2626 void 2627 ex_source(eap) 2628 exarg_T *eap; 2629 { 2630 #ifdef FEAT_BROWSE 2631 if (cmdmod.browse) 2632 { 2633 char_u *fname = NULL; 2634 2635 fname = do_browse(0, (char_u *)_("Source Vim script"), eap->arg, 2636 NULL, NULL, BROWSE_FILTER_MACROS, NULL); 2637 if (fname != NULL) 2638 { 2639 cmd_source(fname, eap); 2640 vim_free(fname); 2641 } 2642 } 2643 else 2644 #endif 2645 cmd_source(eap->arg, eap); 2646 } 2647 2648 static void 2649 cmd_source(fname, eap) 2650 char_u *fname; 2651 exarg_T *eap; 2652 { 2653 if (*fname == NUL) 2654 EMSG(_(e_argreq)); 2655 2656 else if (eap != NULL && eap->forceit) 2657 /* ":source!": read Normal mdoe commands 2658 * Need to execute the commands directly. This is required at least 2659 * for: 2660 * - ":g" command busy 2661 * - after ":argdo", ":windo" or ":bufdo" 2662 * - another command follows 2663 * - inside a loop 2664 */ 2665 openscript(fname, global_busy || listcmd_busy || eap->nextcmd != NULL 2666 #ifdef FEAT_EVAL 2667 || eap->cstack->cs_idx >= 0 2668 #endif 2669 ); 2670 2671 /* ":source" read ex commands */ 2672 else if (do_source(fname, FALSE, FALSE) == FAIL) 2673 EMSG2(_(e_notopen), fname); 2674 } 2675 2676 /* 2677 * ":source" and associated commands. 2678 */ 2679 /* 2680 * Structure used to store info for each sourced file. 2681 * It is shared between do_source() and getsourceline(). 2682 * This is required, because it needs to be handed to do_cmdline() and 2683 * sourcing can be done recursively. 2684 */ 2685 struct source_cookie 2686 { 2687 FILE *fp; /* opened file for sourcing */ 2688 char_u *nextline; /* if not NULL: line that was read ahead */ 2689 int finished; /* ":finish" used */ 2690 #if defined (USE_CRNL) || defined (USE_CR) 2691 int fileformat; /* EOL_UNKNOWN, EOL_UNIX or EOL_DOS */ 2692 int error; /* TRUE if LF found after CR-LF */ 2693 #endif 2694 #ifdef FEAT_EVAL 2695 linenr_T breakpoint; /* next line with breakpoint or zero */ 2696 char_u *fname; /* name of sourced file */ 2697 int dbg_tick; /* debug_tick when breakpoint was set */ 2698 int level; /* top nesting level of sourced file */ 2699 #endif 2700 #ifdef FEAT_MBYTE 2701 vimconv_T conv; /* type of conversion */ 2702 #endif 2703 }; 2704 2705 #ifdef FEAT_EVAL 2706 /* 2707 * Return the address holding the next breakpoint line for a source cookie. 2708 */ 2709 linenr_T * 2710 source_breakpoint(cookie) 2711 void *cookie; 2712 { 2713 return &((struct source_cookie *)cookie)->breakpoint; 2714 } 2715 2716 /* 2717 * Return the address holding the debug tick for a source cookie. 2718 */ 2719 int * 2720 source_dbg_tick(cookie) 2721 void *cookie; 2722 { 2723 return &((struct source_cookie *)cookie)->dbg_tick; 2724 } 2725 2726 /* 2727 * Return the nesting level for a source cookie. 2728 */ 2729 int 2730 source_level(cookie) 2731 void *cookie; 2732 { 2733 return ((struct source_cookie *)cookie)->level; 2734 } 2735 #endif 2736 2737 static char_u *get_one_sourceline __ARGS((struct source_cookie *sp)); 2738 2739 #if defined(WIN32) && defined(FEAT_CSCOPE) 2740 static FILE *fopen_noinh_readbin __ARGS((char *filename)); 2741 2742 /* 2743 * Special function to open a file without handle inheritance. 2744 */ 2745 static FILE * 2746 fopen_noinh_readbin(filename) 2747 char *filename; 2748 { 2749 int fd_tmp = mch_open(filename, O_RDONLY | O_BINARY | O_NOINHERIT, 0); 2750 2751 if (fd_tmp == -1) 2752 return NULL; 2753 return fdopen(fd_tmp, READBIN); 2754 } 2755 #endif 2756 2757 2758 /* 2759 * do_source: Read the file "fname" and execute its lines as EX commands. 2760 * 2761 * This function may be called recursively! 2762 * 2763 * return FAIL if file could not be opened, OK otherwise 2764 */ 2765 int 2766 do_source(fname, check_other, is_vimrc) 2767 char_u *fname; 2768 int check_other; /* check for .vimrc and _vimrc */ 2769 int is_vimrc; /* call vimrc_found() when file exists */ 2770 { 2771 struct source_cookie cookie; 2772 char_u *save_sourcing_name; 2773 linenr_T save_sourcing_lnum; 2774 char_u *p; 2775 char_u *fname_exp; 2776 int retval = FAIL; 2777 #ifdef FEAT_EVAL 2778 scid_T save_current_SID; 2779 static scid_T last_current_SID = 0; 2780 void *save_funccalp; 2781 int save_debug_break_level = debug_break_level; 2782 scriptitem_T *si = NULL; 2783 # ifdef UNIX 2784 struct stat st; 2785 int stat_ok; 2786 # endif 2787 #endif 2788 #ifdef STARTUPTIME 2789 struct timeval tv_rel; 2790 struct timeval tv_start; 2791 #endif 2792 #ifdef FEAT_PROFILE 2793 proftime_T wait_start; 2794 #endif 2795 2796 #ifdef RISCOS 2797 p = mch_munge_fname(fname); 2798 #else 2799 p = expand_env_save(fname); 2800 #endif 2801 if (p == NULL) 2802 return retval; 2803 fname_exp = fix_fname(p); 2804 vim_free(p); 2805 if (fname_exp == NULL) 2806 return retval; 2807 if (mch_isdir(fname_exp)) 2808 { 2809 smsg((char_u *)_("Cannot source a directory: \"%s\""), fname); 2810 goto theend; 2811 } 2812 2813 #ifdef FEAT_AUTOCMD 2814 apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, FALSE, curbuf); 2815 #endif 2816 2817 #if defined(WIN32) && defined(FEAT_CSCOPE) 2818 cookie.fp = fopen_noinh_readbin((char *)fname_exp); 2819 #else 2820 cookie.fp = mch_fopen((char *)fname_exp, READBIN); 2821 #endif 2822 if (cookie.fp == NULL && check_other) 2823 { 2824 /* 2825 * Try again, replacing file name ".vimrc" by "_vimrc" or vice versa, 2826 * and ".exrc" by "_exrc" or vice versa. 2827 */ 2828 p = gettail(fname_exp); 2829 if ((*p == '.' || *p == '_') 2830 && (STRICMP(p + 1, "vimrc") == 0 2831 || STRICMP(p + 1, "gvimrc") == 0 2832 || STRICMP(p + 1, "exrc") == 0)) 2833 { 2834 if (*p == '_') 2835 *p = '.'; 2836 else 2837 *p = '_'; 2838 #if defined(WIN32) && defined(FEAT_CSCOPE) 2839 cookie.fp = fopen_noinh_readbin((char *)fname_exp); 2840 #else 2841 cookie.fp = mch_fopen((char *)fname_exp, READBIN); 2842 #endif 2843 } 2844 } 2845 2846 if (cookie.fp == NULL) 2847 { 2848 if (p_verbose > 0) 2849 { 2850 verbose_enter(); 2851 if (sourcing_name == NULL) 2852 smsg((char_u *)_("could not source \"%s\""), fname); 2853 else 2854 smsg((char_u *)_("line %ld: could not source \"%s\""), 2855 sourcing_lnum, fname); 2856 verbose_leave(); 2857 } 2858 goto theend; 2859 } 2860 2861 /* 2862 * The file exists. 2863 * - In verbose mode, give a message. 2864 * - For a vimrc file, may want to set 'compatible', call vimrc_found(). 2865 */ 2866 if (p_verbose > 1) 2867 { 2868 verbose_enter(); 2869 if (sourcing_name == NULL) 2870 smsg((char_u *)_("sourcing \"%s\""), fname); 2871 else 2872 smsg((char_u *)_("line %ld: sourcing \"%s\""), 2873 sourcing_lnum, fname); 2874 verbose_leave(); 2875 } 2876 if (is_vimrc) 2877 vimrc_found(); 2878 2879 #ifdef USE_CRNL 2880 /* If no automatic file format: Set default to CR-NL. */ 2881 if (*p_ffs == NUL) 2882 cookie.fileformat = EOL_DOS; 2883 else 2884 cookie.fileformat = EOL_UNKNOWN; 2885 cookie.error = FALSE; 2886 #endif 2887 2888 #ifdef USE_CR 2889 /* If no automatic file format: Set default to CR. */ 2890 if (*p_ffs == NUL) 2891 cookie.fileformat = EOL_MAC; 2892 else 2893 cookie.fileformat = EOL_UNKNOWN; 2894 cookie.error = FALSE; 2895 #endif 2896 2897 cookie.nextline = NULL; 2898 cookie.finished = FALSE; 2899 2900 #ifdef FEAT_EVAL 2901 /* 2902 * Check if this script has a breakpoint. 2903 */ 2904 cookie.breakpoint = dbg_find_breakpoint(TRUE, fname_exp, (linenr_T)0); 2905 cookie.fname = fname_exp; 2906 cookie.dbg_tick = debug_tick; 2907 2908 cookie.level = ex_nesting_level; 2909 #endif 2910 #ifdef FEAT_MBYTE 2911 cookie.conv.vc_type = CONV_NONE; /* no conversion */ 2912 2913 /* Try reading the first few bytes to check for a UTF-8 BOM. */ 2914 { 2915 char_u buf[3]; 2916 2917 if (fread((char *)buf, sizeof(char_u), (size_t)3, cookie.fp) 2918 == (size_t)3 2919 && buf[0] == 0xef && buf[1] == 0xbb && buf[2] == 0xbf) 2920 /* Found BOM, setup conversion and skip over it. */ 2921 convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc); 2922 else 2923 /* No BOM found, rewind. */ 2924 fseek(cookie.fp, 0L, SEEK_SET); 2925 } 2926 #endif 2927 2928 /* 2929 * Keep the sourcing name/lnum, for recursive calls. 2930 */ 2931 save_sourcing_name = sourcing_name; 2932 sourcing_name = fname_exp; 2933 save_sourcing_lnum = sourcing_lnum; 2934 sourcing_lnum = 0; 2935 2936 #ifdef STARTUPTIME 2937 time_push(&tv_rel, &tv_start); 2938 #endif 2939 2940 #ifdef FEAT_EVAL 2941 # ifdef FEAT_PROFILE 2942 if (do_profiling == PROF_YES) 2943 prof_child_enter(&wait_start); /* entering a child now */ 2944 # endif 2945 2946 /* Don't use local function variables, if called from a function. 2947 * Also starts profiling timer for nested script. */ 2948 save_funccalp = save_funccal(); 2949 2950 /* 2951 * Check if this script was sourced before to finds its SID. 2952 * If it's new, generate a new SID. 2953 */ 2954 save_current_SID = current_SID; 2955 # ifdef UNIX 2956 stat_ok = (mch_stat((char *)fname_exp, &st) >= 0); 2957 # endif 2958 for (current_SID = script_items.ga_len; current_SID > 0; --current_SID) 2959 { 2960 si = &SCRIPT_ITEM(current_SID); 2961 if (si->sn_name != NULL 2962 && ( 2963 # ifdef UNIX 2964 /* Compare dev/ino when possible, it catches symbolic 2965 * links. Also compare file names, the inode may change 2966 * when the file was edited. */ 2967 ((stat_ok && si->sn_dev != -1) 2968 && (si->sn_dev == st.st_dev 2969 && si->sn_ino == st.st_ino)) || 2970 # endif 2971 fnamecmp(si->sn_name, fname_exp) == 0)) 2972 break; 2973 } 2974 if (current_SID == 0) 2975 { 2976 current_SID = ++last_current_SID; 2977 if (ga_grow(&script_items, (int)(current_SID - script_items.ga_len)) 2978 == FAIL) 2979 goto almosttheend; 2980 while (script_items.ga_len < current_SID) 2981 { 2982 ++script_items.ga_len; 2983 SCRIPT_ITEM(script_items.ga_len).sn_name = NULL; 2984 # ifdef FEAT_PROFILE 2985 SCRIPT_ITEM(script_items.ga_len).sn_prof_on = FALSE; 2986 # endif 2987 } 2988 si = &SCRIPT_ITEM(current_SID); 2989 si->sn_name = fname_exp; 2990 fname_exp = NULL; 2991 # ifdef UNIX 2992 if (stat_ok) 2993 { 2994 si->sn_dev = st.st_dev; 2995 si->sn_ino = st.st_ino; 2996 } 2997 else 2998 si->sn_dev = -1; 2999 # endif 3000 3001 /* Allocate the local script variables to use for this script. */ 3002 new_script_vars(current_SID); 3003 } 3004 3005 # ifdef FEAT_PROFILE 3006 if (do_profiling == PROF_YES) 3007 { 3008 int forceit; 3009 3010 /* Check if we do profiling for this script. */ 3011 if (!si->sn_prof_on && has_profiling(TRUE, si->sn_name, &forceit)) 3012 { 3013 script_do_profile(si); 3014 si->sn_pr_force = forceit; 3015 } 3016 if (si->sn_prof_on) 3017 { 3018 ++si->sn_pr_count; 3019 profile_start(&si->sn_pr_start); 3020 profile_zero(&si->sn_pr_children); 3021 } 3022 } 3023 # endif 3024 #endif 3025 3026 /* 3027 * Call do_cmdline, which will call getsourceline() to get the lines. 3028 */ 3029 do_cmdline(NULL, getsourceline, (void *)&cookie, 3030 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT); 3031 3032 retval = OK; 3033 3034 #ifdef FEAT_PROFILE 3035 if (do_profiling == PROF_YES) 3036 { 3037 /* Get "si" again, "script_items" may have been reallocated. */ 3038 si = &SCRIPT_ITEM(current_SID); 3039 if (si->sn_prof_on) 3040 { 3041 profile_end(&si->sn_pr_start); 3042 profile_sub_wait(&wait_start, &si->sn_pr_start); 3043 profile_add(&si->sn_pr_total, &si->sn_pr_start); 3044 profile_self(&si->sn_pr_self, &si->sn_pr_start, 3045 &si->sn_pr_children); 3046 } 3047 } 3048 #endif 3049 3050 if (got_int) 3051 EMSG(_(e_interr)); 3052 sourcing_name = save_sourcing_name; 3053 sourcing_lnum = save_sourcing_lnum; 3054 if (p_verbose > 1) 3055 { 3056 verbose_enter(); 3057 smsg((char_u *)_("finished sourcing %s"), fname); 3058 if (sourcing_name != NULL) 3059 smsg((char_u *)_("continuing in %s"), sourcing_name); 3060 verbose_leave(); 3061 } 3062 #ifdef STARTUPTIME 3063 vim_snprintf(IObuff, IOSIZE, "sourcing %s", fname); 3064 time_msg(IObuff, &tv_start); 3065 time_pop(&tv_rel); 3066 #endif 3067 3068 #ifdef FEAT_EVAL 3069 /* 3070 * After a "finish" in debug mode, need to break at first command of next 3071 * sourced file. 3072 */ 3073 if (save_debug_break_level > ex_nesting_level 3074 && debug_break_level == ex_nesting_level) 3075 ++debug_break_level; 3076 #endif 3077 3078 #ifdef FEAT_EVAL 3079 almosttheend: 3080 current_SID = save_current_SID; 3081 restore_funccal(save_funccalp); 3082 # ifdef FEAT_PROFILE 3083 if (do_profiling == PROF_YES) 3084 prof_child_exit(&wait_start); /* leaving a child now */ 3085 # endif 3086 #endif 3087 fclose(cookie.fp); 3088 vim_free(cookie.nextline); 3089 #ifdef FEAT_MBYTE 3090 convert_setup(&cookie.conv, NULL, NULL); 3091 #endif 3092 3093 theend: 3094 vim_free(fname_exp); 3095 return retval; 3096 } 3097 3098 #if defined(FEAT_EVAL) || defined(PROTO) 3099 3100 /* 3101 * ":scriptnames" 3102 */ 3103 /*ARGSUSED*/ 3104 void 3105 ex_scriptnames(eap) 3106 exarg_T *eap; 3107 { 3108 int i; 3109 3110 for (i = 1; i <= script_items.ga_len && !got_int; ++i) 3111 if (SCRIPT_ITEM(i).sn_name != NULL) 3112 smsg((char_u *)"%3d: %s", i, SCRIPT_ITEM(i).sn_name); 3113 } 3114 3115 # if defined(BACKSLASH_IN_FILENAME) || defined(PROTO) 3116 /* 3117 * Fix slashes in the list of script names for 'shellslash'. 3118 */ 3119 void 3120 scriptnames_slash_adjust() 3121 { 3122 int i; 3123 3124 for (i = 1; i <= script_items.ga_len; ++i) 3125 if (SCRIPT_ITEM(i).sn_name != NULL) 3126 slash_adjust(SCRIPT_ITEM(i).sn_name); 3127 } 3128 # endif 3129 3130 /* 3131 * Get a pointer to a script name. Used for ":verbose set". 3132 */ 3133 char_u * 3134 get_scriptname(id) 3135 scid_T id; 3136 { 3137 if (id == SID_MODELINE) 3138 return (char_u *)_("modeline"); 3139 if (id == SID_CMDARG) 3140 return (char_u *)_("--cmd argument"); 3141 if (id == SID_CARG) 3142 return (char_u *)_("-c argument"); 3143 if (id == SID_ENV) 3144 return (char_u *)_("environment variable"); 3145 if (id == SID_ERROR) 3146 return (char_u *)_("error handler"); 3147 return SCRIPT_ITEM(id).sn_name; 3148 } 3149 3150 # if defined(EXITFREE) || defined(PROTO) 3151 void 3152 free_scriptnames() 3153 { 3154 int i; 3155 3156 for (i = script_items.ga_len; i > 0; --i) 3157 vim_free(SCRIPT_ITEM(i).sn_name); 3158 ga_clear(&script_items); 3159 } 3160 # endif 3161 3162 #endif 3163 3164 #if defined(USE_CR) || defined(PROTO) 3165 3166 # if defined(__MSL__) && (__MSL__ >= 22) 3167 /* 3168 * Newer version of the Metrowerks library handle DOS and UNIX files 3169 * without help. 3170 * Test with earlier versions, MSL 2.2 is the library supplied with 3171 * Codewarrior Pro 2. 3172 */ 3173 char * 3174 fgets_cr(s, n, stream) 3175 char *s; 3176 int n; 3177 FILE *stream; 3178 { 3179 return fgets(s, n, stream); 3180 } 3181 # else 3182 /* 3183 * Version of fgets() which also works for lines ending in a <CR> only 3184 * (Macintosh format). 3185 * For older versions of the Metrowerks library. 3186 * At least CodeWarrior 9 needed this code. 3187 */ 3188 char * 3189 fgets_cr(s, n, stream) 3190 char *s; 3191 int n; 3192 FILE *stream; 3193 { 3194 int c = 0; 3195 int char_read = 0; 3196 3197 while (!feof(stream) && c != '\r' && c != '\n' && char_read < n - 1) 3198 { 3199 c = fgetc(stream); 3200 s[char_read++] = c; 3201 /* If the file is in DOS format, we need to skip a NL after a CR. I 3202 * thought it was the other way around, but this appears to work... */ 3203 if (c == '\n') 3204 { 3205 c = fgetc(stream); 3206 if (c != '\r') 3207 ungetc(c, stream); 3208 } 3209 } 3210 3211 s[char_read] = 0; 3212 if (char_read == 0) 3213 return NULL; 3214 3215 if (feof(stream) && char_read == 1) 3216 return NULL; 3217 3218 return s; 3219 } 3220 # endif 3221 #endif 3222 3223 /* 3224 * Get one full line from a sourced file. 3225 * Called by do_cmdline() when it's called from do_source(). 3226 * 3227 * Return a pointer to the line in allocated memory. 3228 * Return NULL for end-of-file or some error. 3229 */ 3230 /* ARGSUSED */ 3231 char_u * 3232 getsourceline(c, cookie, indent) 3233 int c; /* not used */ 3234 void *cookie; 3235 int indent; /* not used */ 3236 { 3237 struct source_cookie *sp = (struct source_cookie *)cookie; 3238 char_u *line; 3239 char_u *p, *s; 3240 3241 #ifdef FEAT_EVAL 3242 /* If breakpoints have been added/deleted need to check for it. */ 3243 if (sp->dbg_tick < debug_tick) 3244 { 3245 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum); 3246 sp->dbg_tick = debug_tick; 3247 } 3248 # ifdef FEAT_PROFILE 3249 if (do_profiling == PROF_YES) 3250 script_line_end(); 3251 # endif 3252 #endif 3253 /* 3254 * Get current line. If there is a read-ahead line, use it, otherwise get 3255 * one now. 3256 */ 3257 if (sp->finished) 3258 line = NULL; 3259 else if (sp->nextline == NULL) 3260 line = get_one_sourceline(sp); 3261 else 3262 { 3263 line = sp->nextline; 3264 sp->nextline = NULL; 3265 ++sourcing_lnum; 3266 } 3267 #ifdef FEAT_PROFILE 3268 if (line != NULL && do_profiling == PROF_YES) 3269 script_line_start(); 3270 #endif 3271 3272 /* Only concatenate lines starting with a \ when 'cpoptions' doesn't 3273 * contain the 'C' flag. */ 3274 if (line != NULL && (vim_strchr(p_cpo, CPO_CONCAT) == NULL)) 3275 { 3276 /* compensate for the one line read-ahead */ 3277 --sourcing_lnum; 3278 for (;;) 3279 { 3280 sp->nextline = get_one_sourceline(sp); 3281 if (sp->nextline == NULL) 3282 break; 3283 p = skipwhite(sp->nextline); 3284 if (*p != '\\') 3285 break; 3286 s = alloc((int)(STRLEN(line) + STRLEN(p))); 3287 if (s == NULL) /* out of memory */ 3288 break; 3289 STRCPY(s, line); 3290 STRCAT(s, p + 1); 3291 vim_free(line); 3292 line = s; 3293 vim_free(sp->nextline); 3294 } 3295 } 3296 3297 #ifdef FEAT_MBYTE 3298 if (line != NULL && sp->conv.vc_type != CONV_NONE) 3299 { 3300 /* Convert the encoding of the script line. */ 3301 s = string_convert(&sp->conv, line, NULL); 3302 if (s != NULL) 3303 { 3304 vim_free(line); 3305 line = s; 3306 } 3307 } 3308 #endif 3309 3310 #ifdef FEAT_EVAL 3311 /* Did we encounter a breakpoint? */ 3312 if (sp->breakpoint != 0 && sp->breakpoint <= sourcing_lnum) 3313 { 3314 dbg_breakpoint(sp->fname, sourcing_lnum); 3315 /* Find next breakpoint. */ 3316 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum); 3317 sp->dbg_tick = debug_tick; 3318 } 3319 #endif 3320 3321 return line; 3322 } 3323 3324 static char_u * 3325 get_one_sourceline(sp) 3326 struct source_cookie *sp; 3327 { 3328 garray_T ga; 3329 int len; 3330 int c; 3331 char_u *buf; 3332 #ifdef USE_CRNL 3333 int has_cr; /* CR-LF found */ 3334 #endif 3335 #ifdef USE_CR 3336 char_u *scan; 3337 #endif 3338 int have_read = FALSE; 3339 3340 /* use a growarray to store the sourced line */ 3341 ga_init2(&ga, 1, 250); 3342 3343 /* 3344 * Loop until there is a finished line (or end-of-file). 3345 */ 3346 sourcing_lnum++; 3347 for (;;) 3348 { 3349 /* make room to read at least 120 (more) characters */ 3350 if (ga_grow(&ga, 120) == FAIL) 3351 break; 3352 buf = (char_u *)ga.ga_data; 3353 3354 #ifdef USE_CR 3355 if (sp->fileformat == EOL_MAC) 3356 { 3357 if (fgets_cr((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len, 3358 sp->fp) == NULL) 3359 break; 3360 } 3361 else 3362 #endif 3363 if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len, 3364 sp->fp) == NULL) 3365 break; 3366 len = ga.ga_len + (int)STRLEN(buf + ga.ga_len); 3367 #ifdef USE_CRNL 3368 /* Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the 3369 * CTRL-Z by its own, or after a NL. */ 3370 if ( (len == 1 || (len >= 2 && buf[len - 2] == '\n')) 3371 && sp->fileformat == EOL_DOS 3372 && buf[len - 1] == Ctrl_Z) 3373 { 3374 buf[len - 1] = NUL; 3375 break; 3376 } 3377 #endif 3378 3379 #ifdef USE_CR 3380 /* If the read doesn't stop on a new line, and there's 3381 * some CR then we assume a Mac format */ 3382 if (sp->fileformat == EOL_UNKNOWN) 3383 { 3384 if (buf[len - 1] != '\n' && vim_strchr(buf, '\r') != NULL) 3385 sp->fileformat = EOL_MAC; 3386 else 3387 sp->fileformat = EOL_UNIX; 3388 } 3389 3390 if (sp->fileformat == EOL_MAC) 3391 { 3392 scan = vim_strchr(buf, '\r'); 3393 3394 if (scan != NULL) 3395 { 3396 *scan = '\n'; 3397 if (*(scan + 1) != 0) 3398 { 3399 *(scan + 1) = 0; 3400 fseek(sp->fp, (long)(scan - buf - len + 1), SEEK_CUR); 3401 } 3402 } 3403 len = STRLEN(buf); 3404 } 3405 #endif 3406 3407 have_read = TRUE; 3408 ga.ga_len = len; 3409 3410 /* If the line was longer than the buffer, read more. */ 3411 if (ga.ga_maxlen - ga.ga_len == 1 && buf[len - 1] != '\n') 3412 continue; 3413 3414 if (len >= 1 && buf[len - 1] == '\n') /* remove trailing NL */ 3415 { 3416 #ifdef USE_CRNL 3417 has_cr = (len >= 2 && buf[len - 2] == '\r'); 3418 if (sp->fileformat == EOL_UNKNOWN) 3419 { 3420 if (has_cr) 3421 sp->fileformat = EOL_DOS; 3422 else 3423 sp->fileformat = EOL_UNIX; 3424 } 3425 3426 if (sp->fileformat == EOL_DOS) 3427 { 3428 if (has_cr) /* replace trailing CR */ 3429 { 3430 buf[len - 2] = '\n'; 3431 --len; 3432 --ga.ga_len; 3433 } 3434 else /* lines like ":map xx yy^M" will have failed */ 3435 { 3436 if (!sp->error) 3437 { 3438 msg_source(hl_attr(HLF_W)); 3439 EMSG(_("W15: Warning: Wrong line separator, ^M may be missing")); 3440 } 3441 sp->error = TRUE; 3442 sp->fileformat = EOL_UNIX; 3443 } 3444 } 3445 #endif 3446 /* The '\n' is escaped if there is an odd number of ^V's just 3447 * before it, first set "c" just before the 'V's and then check 3448 * len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo */ 3449 for (c = len - 2; c >= 0 && buf[c] == Ctrl_V; c--) 3450 ; 3451 if ((len & 1) != (c & 1)) /* escaped NL, read more */ 3452 { 3453 sourcing_lnum++; 3454 continue; 3455 } 3456 3457 buf[len - 1] = NUL; /* remove the NL */ 3458 } 3459 3460 /* 3461 * Check for ^C here now and then, so recursive :so can be broken. 3462 */ 3463 line_breakcheck(); 3464 break; 3465 } 3466 3467 if (have_read) 3468 return (char_u *)ga.ga_data; 3469 3470 vim_free(ga.ga_data); 3471 return NULL; 3472 } 3473 3474 #if defined(FEAT_PROFILE) || defined(PROTO) 3475 /* 3476 * Called when starting to read a script line. 3477 * "sourcing_lnum" must be correct! 3478 * When skipping lines it may not actually be executed, but we won't find out 3479 * until later and we need to store the time now. 3480 */ 3481 void 3482 script_line_start() 3483 { 3484 scriptitem_T *si; 3485 sn_prl_T *pp; 3486 3487 if (current_SID <= 0 || current_SID > script_items.ga_len) 3488 return; 3489 si = &SCRIPT_ITEM(current_SID); 3490 if (si->sn_prof_on && sourcing_lnum >= 1) 3491 { 3492 /* Grow the array before starting the timer, so that the time spend 3493 * here isn't counted. */ 3494 ga_grow(&si->sn_prl_ga, (int)(sourcing_lnum - si->sn_prl_ga.ga_len)); 3495 si->sn_prl_idx = sourcing_lnum - 1; 3496 while (si->sn_prl_ga.ga_len <= si->sn_prl_idx 3497 && si->sn_prl_ga.ga_len < si->sn_prl_ga.ga_maxlen) 3498 { 3499 /* Zero counters for a line that was not used before. */ 3500 pp = &PRL_ITEM(si, si->sn_prl_ga.ga_len); 3501 pp->snp_count = 0; 3502 profile_zero(&pp->sn_prl_total); 3503 profile_zero(&pp->sn_prl_self); 3504 ++si->sn_prl_ga.ga_len; 3505 } 3506 si->sn_prl_execed = FALSE; 3507 profile_start(&si->sn_prl_start); 3508 profile_zero(&si->sn_prl_children); 3509 profile_get_wait(&si->sn_prl_wait); 3510 } 3511 } 3512 3513 /* 3514 * Called when actually executing a function line. 3515 */ 3516 void 3517 script_line_exec() 3518 { 3519 scriptitem_T *si; 3520 3521 if (current_SID <= 0 || current_SID > script_items.ga_len) 3522 return; 3523 si = &SCRIPT_ITEM(current_SID); 3524 if (si->sn_prof_on && si->sn_prl_idx >= 0) 3525 si->sn_prl_execed = TRUE; 3526 } 3527 3528 /* 3529 * Called when done with a function line. 3530 */ 3531 void 3532 script_line_end() 3533 { 3534 scriptitem_T *si; 3535 sn_prl_T *pp; 3536 3537 if (current_SID <= 0 || current_SID > script_items.ga_len) 3538 return; 3539 si = &SCRIPT_ITEM(current_SID); 3540 if (si->sn_prof_on && si->sn_prl_idx >= 0 3541 && si->sn_prl_idx < si->sn_prl_ga.ga_len) 3542 { 3543 if (si->sn_prl_execed) 3544 { 3545 pp = &PRL_ITEM(si, si->sn_prl_idx); 3546 ++pp->snp_count; 3547 profile_end(&si->sn_prl_start); 3548 profile_sub_wait(&si->sn_prl_wait, &si->sn_prl_start); 3549 profile_add(&pp->sn_prl_total, &si->sn_prl_start); 3550 profile_self(&pp->sn_prl_self, &si->sn_prl_start, 3551 &si->sn_prl_children); 3552 } 3553 si->sn_prl_idx = -1; 3554 } 3555 } 3556 #endif 3557 3558 /* 3559 * ":scriptencoding": Set encoding conversion for a sourced script. 3560 * Without the multi-byte feature it's simply ignored. 3561 */ 3562 /*ARGSUSED*/ 3563 void 3564 ex_scriptencoding(eap) 3565 exarg_T *eap; 3566 { 3567 #ifdef FEAT_MBYTE 3568 struct source_cookie *sp; 3569 char_u *name; 3570 3571 if (!getline_equal(eap->getline, eap->cookie, getsourceline)) 3572 { 3573 EMSG(_("E167: :scriptencoding used outside of a sourced file")); 3574 return; 3575 } 3576 3577 if (*eap->arg != NUL) 3578 { 3579 name = enc_canonize(eap->arg); 3580 if (name == NULL) /* out of memory */ 3581 return; 3582 } 3583 else 3584 name = eap->arg; 3585 3586 /* Setup for conversion from the specified encoding to 'encoding'. */ 3587 sp = (struct source_cookie *)getline_cookie(eap->getline, eap->cookie); 3588 convert_setup(&sp->conv, name, p_enc); 3589 3590 if (name != eap->arg) 3591 vim_free(name); 3592 #endif 3593 } 3594 3595 #if defined(FEAT_EVAL) || defined(PROTO) 3596 /* 3597 * ":finish": Mark a sourced file as finished. 3598 */ 3599 void 3600 ex_finish(eap) 3601 exarg_T *eap; 3602 { 3603 if (getline_equal(eap->getline, eap->cookie, getsourceline)) 3604 do_finish(eap, FALSE); 3605 else 3606 EMSG(_("E168: :finish used outside of a sourced file")); 3607 } 3608 3609 /* 3610 * Mark a sourced file as finished. Possibly makes the ":finish" pending. 3611 * Also called for a pending finish at the ":endtry" or after returning from 3612 * an extra do_cmdline(). "reanimate" is used in the latter case. 3613 */ 3614 void 3615 do_finish(eap, reanimate) 3616 exarg_T *eap; 3617 int reanimate; 3618 { 3619 int idx; 3620 3621 if (reanimate) 3622 ((struct source_cookie *)getline_cookie(eap->getline, 3623 eap->cookie))->finished = FALSE; 3624 3625 /* 3626 * Cleanup (and inactivate) conditionals, but stop when a try conditional 3627 * not in its finally clause (which then is to be executed next) is found. 3628 * In this case, make the ":finish" pending for execution at the ":endtry". 3629 * Otherwise, finish normally. 3630 */ 3631 idx = cleanup_conditionals(eap->cstack, 0, TRUE); 3632 if (idx >= 0) 3633 { 3634 eap->cstack->cs_pending[idx] = CSTP_FINISH; 3635 report_make_pending(CSTP_FINISH, NULL); 3636 } 3637 else 3638 ((struct source_cookie *)getline_cookie(eap->getline, 3639 eap->cookie))->finished = TRUE; 3640 } 3641 3642 3643 /* 3644 * Return TRUE when a sourced file had the ":finish" command: Don't give error 3645 * message for missing ":endif". 3646 * Return FALSE when not sourcing a file. 3647 */ 3648 int 3649 source_finished(getline, cookie) 3650 char_u *(*getline) __ARGS((int, void *, int)); 3651 void *cookie; 3652 { 3653 return (getline_equal(getline, cookie, getsourceline) 3654 && ((struct source_cookie *)getline_cookie( 3655 getline, cookie))->finished); 3656 } 3657 #endif 3658 3659 #if defined(FEAT_LISTCMDS) || defined(PROTO) 3660 /* 3661 * ":checktime [buffer]" 3662 */ 3663 void 3664 ex_checktime(eap) 3665 exarg_T *eap; 3666 { 3667 buf_T *buf; 3668 int save_no_check_timestamps = no_check_timestamps; 3669 3670 no_check_timestamps = 0; 3671 if (eap->addr_count == 0) /* default is all buffers */ 3672 check_timestamps(FALSE); 3673 else 3674 { 3675 buf = buflist_findnr((int)eap->line2); 3676 if (buf != NULL) /* cannot happen? */ 3677 (void)buf_check_timestamp(buf, FALSE); 3678 } 3679 no_check_timestamps = save_no_check_timestamps; 3680 } 3681 #endif 3682 3683 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \ 3684 && (defined(FEAT_EVAL) || defined(FEAT_MULTI_LANG)) 3685 static char *get_locale_val __ARGS((int what)); 3686 3687 static char * 3688 get_locale_val(what) 3689 int what; 3690 { 3691 char *loc; 3692 3693 /* Obtain the locale value from the libraries. For DJGPP this is 3694 * redefined and it doesn't use the arguments. */ 3695 loc = setlocale(what, NULL); 3696 3697 # if defined(__BORLANDC__) 3698 if (loc != NULL) 3699 { 3700 char_u *p; 3701 3702 /* Borland returns something like "LC_CTYPE=<name>\n" 3703 * Let's try to fix that bug here... */ 3704 p = vim_strchr(loc, '='); 3705 if (p != NULL) 3706 { 3707 loc = ++p; 3708 while (*p != NUL) /* remove trailing newline */ 3709 { 3710 if (*p < ' ') 3711 { 3712 *p = NUL; 3713 break; 3714 } 3715 ++p; 3716 } 3717 } 3718 } 3719 # endif 3720 3721 return loc; 3722 } 3723 #endif 3724 3725 3726 #ifdef WIN32 3727 /* 3728 * On MS-Windows locale names are strings like "German_Germany.1252", but 3729 * gettext expects "de". Try to translate one into another here for a few 3730 * supported languages. 3731 */ 3732 static char_u * 3733 gettext_lang(char_u *name) 3734 { 3735 int i; 3736 static char *(mtable[]) = { 3737 "afrikaans", "af", 3738 "czech", "cs", 3739 "dutch", "nl", 3740 "german", "de", 3741 "english_united kingdom", "en_GB", 3742 "spanish", "es", 3743 "french", "fr", 3744 "italian", "it", 3745 "japanese", "ja", 3746 "korean", "ko", 3747 "norwegian", "no", 3748 "polish", "pl", 3749 "russian", "ru", 3750 "slovak", "sk", 3751 "swedish", "sv", 3752 "ukrainian", "uk", 3753 "chinese_china", "zh_CN", 3754 "chinese_taiwan", "zh_TW", 3755 NULL}; 3756 3757 for (i = 0; mtable[i] != NULL; i += 2) 3758 if (STRNICMP(mtable[i], name, STRLEN(mtable[i])) == 0) 3759 return mtable[i + 1]; 3760 return name; 3761 } 3762 #endif 3763 3764 #if defined(FEAT_MULTI_LANG) || defined(PROTO) 3765 /* 3766 * Obtain the current messages language. Used to set the default for 3767 * 'helplang'. May return NULL or an empty string. 3768 */ 3769 char_u * 3770 get_mess_lang() 3771 { 3772 char_u *p; 3773 3774 # if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) 3775 # if defined(LC_MESSAGES) 3776 p = (char_u *)get_locale_val(LC_MESSAGES); 3777 # else 3778 /* This is necessary for Win32, where LC_MESSAGES is not defined and $LANG 3779 * may be set to the LCID number. */ 3780 p = (char_u *)get_locale_val(LC_ALL); 3781 # endif 3782 # else 3783 p = mch_getenv((char_u *)"LC_ALL"); 3784 if (p == NULL || *p == NUL) 3785 { 3786 p = mch_getenv((char_u *)"LC_MESSAGES"); 3787 if (p == NULL || *p == NUL) 3788 p = mch_getenv((char_u *)"LANG"); 3789 } 3790 # endif 3791 # ifdef WIN32 3792 p = gettext_lang(p); 3793 # endif 3794 return p; 3795 } 3796 #endif 3797 3798 /* Complicated #if; matches with where get_mess_env() is used below. */ 3799 #if (defined(FEAT_EVAL) && !((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \ 3800 && defined(LC_MESSAGES))) \ 3801 || ((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \ 3802 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)) \ 3803 && !defined(LC_MESSAGES)) 3804 static char_u *get_mess_env __ARGS((void)); 3805 3806 /* 3807 * Get the language used for messages from the environment. 3808 */ 3809 static char_u * 3810 get_mess_env() 3811 { 3812 char_u *p; 3813 3814 p = mch_getenv((char_u *)"LC_ALL"); 3815 if (p == NULL || *p == NUL) 3816 { 3817 p = mch_getenv((char_u *)"LC_MESSAGES"); 3818 if (p == NULL || *p == NUL) 3819 { 3820 p = mch_getenv((char_u *)"LANG"); 3821 if (p != NULL && VIM_ISDIGIT(*p)) 3822 p = NULL; /* ignore something like "1043" */ 3823 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 3824 if (p == NULL || *p == NUL) 3825 p = (char_u *)get_locale_val(LC_CTYPE); 3826 # endif 3827 } 3828 } 3829 return p; 3830 } 3831 #endif 3832 3833 #if defined(FEAT_EVAL) || defined(PROTO) 3834 3835 /* 3836 * Set the "v:lang" variable according to the current locale setting. 3837 * Also do "v:lc_time"and "v:ctype". 3838 */ 3839 void 3840 set_lang_var() 3841 { 3842 char_u *loc; 3843 3844 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 3845 loc = (char_u *)get_locale_val(LC_CTYPE); 3846 # else 3847 /* setlocale() not supported: use the default value */ 3848 loc = (char_u *)"C"; 3849 # endif 3850 set_vim_var_string(VV_CTYPE, loc, -1); 3851 3852 /* When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall 3853 * back to LC_CTYPE if it's empty. */ 3854 # if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) && defined(LC_MESSAGES) 3855 loc = (char_u *)get_locale_val(LC_MESSAGES); 3856 # else 3857 loc = get_mess_env(); 3858 # endif 3859 set_vim_var_string(VV_LANG, loc, -1); 3860 3861 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 3862 loc = (char_u *)get_locale_val(LC_TIME); 3863 # endif 3864 set_vim_var_string(VV_LC_TIME, loc, -1); 3865 } 3866 #endif 3867 3868 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \ 3869 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)) 3870 /* 3871 * ":language": Set the language (locale). 3872 */ 3873 void 3874 ex_language(eap) 3875 exarg_T *eap; 3876 { 3877 char *loc; 3878 char_u *p; 3879 char_u *name; 3880 int what = LC_ALL; 3881 char *whatstr = ""; 3882 #ifdef LC_MESSAGES 3883 # define VIM_LC_MESSAGES LC_MESSAGES 3884 #else 3885 # define VIM_LC_MESSAGES 6789 3886 #endif 3887 3888 name = eap->arg; 3889 3890 /* Check for "messages {name}", "ctype {name}" or "time {name}" argument. 3891 * Allow abbreviation, but require at least 3 characters to avoid 3892 * confusion with a two letter language name "me" or "ct". */ 3893 p = skiptowhite(eap->arg); 3894 if ((*p == NUL || vim_iswhite(*p)) && p - eap->arg >= 3) 3895 { 3896 if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0) 3897 { 3898 what = VIM_LC_MESSAGES; 3899 name = skipwhite(p); 3900 whatstr = "messages "; 3901 } 3902 else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0) 3903 { 3904 what = LC_CTYPE; 3905 name = skipwhite(p); 3906 whatstr = "ctype "; 3907 } 3908 else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0) 3909 { 3910 what = LC_TIME; 3911 name = skipwhite(p); 3912 whatstr = "time "; 3913 } 3914 } 3915 3916 if (*name == NUL) 3917 { 3918 #ifndef LC_MESSAGES 3919 if (what == VIM_LC_MESSAGES) 3920 p = get_mess_env(); 3921 else 3922 #endif 3923 p = (char_u *)setlocale(what, NULL); 3924 if (p == NULL || *p == NUL) 3925 p = (char_u *)"Unknown"; 3926 smsg((char_u *)_("Current %slanguage: \"%s\""), whatstr, p); 3927 } 3928 else 3929 { 3930 #ifndef LC_MESSAGES 3931 if (what == VIM_LC_MESSAGES) 3932 loc = ""; 3933 else 3934 #endif 3935 loc = setlocale(what, (char *)name); 3936 if (loc == NULL) 3937 EMSG2(_("E197: Cannot set language to \"%s\""), name); 3938 else 3939 { 3940 #ifdef HAVE_NL_MSG_CAT_CNTR 3941 /* Need to do this for GNU gettext, otherwise cached translations 3942 * will be used again. */ 3943 extern int _nl_msg_cat_cntr; 3944 3945 ++_nl_msg_cat_cntr; 3946 #endif 3947 /* Reset $LC_ALL, otherwise it would overrule everyting. */ 3948 vim_setenv((char_u *)"LC_ALL", (char_u *)""); 3949 3950 if (what != LC_TIME) 3951 { 3952 /* Tell gettext() what to translate to. It apparently doesn't 3953 * use the currently effective locale. Also do this when 3954 * FEAT_GETTEXT isn't defined, so that shell commands use this 3955 * value. */ 3956 if (what == LC_ALL) 3957 { 3958 vim_setenv((char_u *)"LANG", name); 3959 # ifdef WIN32 3960 /* Apparently MS-Windows printf() may cause a crash when 3961 * we give it 8-bit text while it's expecting text in the 3962 * current locale. This call avoids that. */ 3963 setlocale(LC_CTYPE, "C"); 3964 # endif 3965 } 3966 if (what != LC_CTYPE) 3967 { 3968 char_u *mname; 3969 #ifdef WIN32 3970 mname = gettext_lang(name); 3971 #else 3972 mname = name; 3973 #endif 3974 vim_setenv((char_u *)"LC_MESSAGES", mname); 3975 #ifdef FEAT_MULTI_LANG 3976 set_helplang_default(mname); 3977 #endif 3978 } 3979 3980 /* Set $LC_CTYPE, because it overrules $LANG, and 3981 * gtk_set_locale() calls setlocale() again. gnome_init() 3982 * sets $LC_CTYPE to "en_US" (that's a bug!). */ 3983 if (what != VIM_LC_MESSAGES) 3984 vim_setenv((char_u *)"LC_CTYPE", name); 3985 # ifdef FEAT_GUI_GTK 3986 /* Let GTK know what locale we're using. Not sure this is 3987 * really needed... */ 3988 if (gui.in_use) 3989 (void)gtk_set_locale(); 3990 # endif 3991 } 3992 3993 # ifdef FEAT_EVAL 3994 /* Set v:lang, v:lc_time and v:ctype to the final result. */ 3995 set_lang_var(); 3996 # endif 3997 } 3998 } 3999 } 4000 4001 # if defined(FEAT_CMDL_COMPL) || defined(PROTO) 4002 /* 4003 * Function given to ExpandGeneric() to obtain the possible arguments of the 4004 * ":language" command. 4005 */ 4006 /*ARGSUSED*/ 4007 char_u * 4008 get_lang_arg(xp, idx) 4009 expand_T *xp; 4010 int idx; 4011 { 4012 if (idx == 0) 4013 return (char_u *)"messages"; 4014 if (idx == 1) 4015 return (char_u *)"ctype"; 4016 if (idx == 2) 4017 return (char_u *)"time"; 4018 return NULL; 4019 } 4020 # endif 4021 4022 #endif 4023