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