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