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 * scriptfile.c: functions for dealing with the runtime directories/files 12 */ 13 14 #include "vim.h" 15 16 /* 17 * ":runtime [what] {name}" 18 */ 19 void 20 ex_runtime(exarg_T *eap) 21 { 22 char_u *arg = eap->arg; 23 char_u *p = skiptowhite(arg); 24 int len = (int)(p - arg); 25 int flags = eap->forceit ? DIP_ALL : 0; 26 27 if (STRNCMP(arg, "START", len) == 0) 28 { 29 flags += DIP_START + DIP_NORTP; 30 arg = skipwhite(arg + len); 31 } 32 else if (STRNCMP(arg, "OPT", len) == 0) 33 { 34 flags += DIP_OPT + DIP_NORTP; 35 arg = skipwhite(arg + len); 36 } 37 else if (STRNCMP(arg, "PACK", len) == 0) 38 { 39 flags += DIP_START + DIP_OPT + DIP_NORTP; 40 arg = skipwhite(arg + len); 41 } 42 else if (STRNCMP(arg, "ALL", len) == 0) 43 { 44 flags += DIP_START + DIP_OPT; 45 arg = skipwhite(arg + len); 46 } 47 48 source_runtime(arg, flags); 49 } 50 51 static void 52 source_callback(char_u *fname, void *cookie UNUSED) 53 { 54 (void)do_source(fname, FALSE, DOSO_NONE); 55 } 56 57 /* 58 * Find the file "name" in all directories in "path" and invoke 59 * "callback(fname, cookie)". 60 * "name" can contain wildcards. 61 * When "flags" has DIP_ALL: source all files, otherwise only the first one. 62 * When "flags" has DIP_DIR: find directories instead of files. 63 * When "flags" has DIP_ERR: give an error message if there is no match. 64 * 65 * return FAIL when no file could be sourced, OK otherwise. 66 */ 67 int 68 do_in_path( 69 char_u *path, 70 char_u *name, 71 int flags, 72 void (*callback)(char_u *fname, void *ck), 73 void *cookie) 74 { 75 char_u *rtp; 76 char_u *np; 77 char_u *buf; 78 char_u *rtp_copy; 79 char_u *tail; 80 int num_files; 81 char_u **files; 82 int i; 83 int did_one = FALSE; 84 #ifdef AMIGA 85 struct Process *proc = (struct Process *)FindTask(0L); 86 APTR save_winptr = proc->pr_WindowPtr; 87 88 // Avoid a requester here for a volume that doesn't exist. 89 proc->pr_WindowPtr = (APTR)-1L; 90 #endif 91 92 // Make a copy of 'runtimepath'. Invoking the callback may change the 93 // value. 94 rtp_copy = vim_strsave(path); 95 buf = alloc(MAXPATHL); 96 if (buf != NULL && rtp_copy != NULL) 97 { 98 if (p_verbose > 1 && name != NULL) 99 { 100 verbose_enter(); 101 smsg(_("Searching for \"%s\" in \"%s\""), 102 (char *)name, (char *)path); 103 verbose_leave(); 104 } 105 106 // Loop over all entries in 'runtimepath'. 107 rtp = rtp_copy; 108 while (*rtp != NUL && ((flags & DIP_ALL) || !did_one)) 109 { 110 size_t buflen; 111 112 // Copy the path from 'runtimepath' to buf[]. 113 copy_option_part(&rtp, buf, MAXPATHL, ","); 114 buflen = STRLEN(buf); 115 116 // Skip after or non-after directories. 117 if (flags & (DIP_NOAFTER | DIP_AFTER)) 118 { 119 int is_after = buflen >= 5 120 && STRCMP(buf + buflen - 5, "after") == 0; 121 122 if ((is_after && (flags & DIP_NOAFTER)) 123 || (!is_after && (flags & DIP_AFTER))) 124 continue; 125 } 126 127 if (name == NULL) 128 { 129 (*callback)(buf, (void *) &cookie); 130 if (!did_one) 131 did_one = (cookie == NULL); 132 } 133 else if (buflen + STRLEN(name) + 2 < MAXPATHL) 134 { 135 add_pathsep(buf); 136 tail = buf + STRLEN(buf); 137 138 // Loop over all patterns in "name" 139 np = name; 140 while (*np != NUL && ((flags & DIP_ALL) || !did_one)) 141 { 142 // Append the pattern from "name" to buf[]. 143 copy_option_part(&np, tail, (int)(MAXPATHL - (tail - buf)), 144 "\t "); 145 146 if (p_verbose > 2) 147 { 148 verbose_enter(); 149 smsg(_("Searching for \"%s\""), buf); 150 verbose_leave(); 151 } 152 153 // Expand wildcards, invoke the callback for each match. 154 if (gen_expand_wildcards(1, &buf, &num_files, &files, 155 (flags & DIP_DIR) ? EW_DIR : EW_FILE) == OK) 156 { 157 for (i = 0; i < num_files; ++i) 158 { 159 (*callback)(files[i], cookie); 160 did_one = TRUE; 161 if (!(flags & DIP_ALL)) 162 break; 163 } 164 FreeWild(num_files, files); 165 } 166 } 167 } 168 } 169 } 170 vim_free(buf); 171 vim_free(rtp_copy); 172 if (!did_one && name != NULL) 173 { 174 char *basepath = path == p_rtp ? "runtimepath" : "packpath"; 175 176 if (flags & DIP_ERR) 177 semsg(_(e_dirnotf), basepath, name); 178 else if (p_verbose > 0) 179 { 180 verbose_enter(); 181 smsg(_("not found in '%s': \"%s\""), basepath, name); 182 verbose_leave(); 183 } 184 } 185 186 #ifdef AMIGA 187 proc->pr_WindowPtr = save_winptr; 188 #endif 189 190 return did_one ? OK : FAIL; 191 } 192 193 /* 194 * Find "name" in "path". When found, invoke the callback function for 195 * it: callback(fname, "cookie") 196 * When "flags" has DIP_ALL repeat for all matches, otherwise only the first 197 * one is used. 198 * Returns OK when at least one match found, FAIL otherwise. 199 * 200 * If "name" is NULL calls callback for each entry in "path". Cookie is 201 * passed by reference in this case, setting it to NULL indicates that callback 202 * has done its job. 203 */ 204 static int 205 do_in_path_and_pp( 206 char_u *path, 207 char_u *name, 208 int flags, 209 void (*callback)(char_u *fname, void *ck), 210 void *cookie) 211 { 212 int done = FAIL; 213 char_u *s; 214 int len; 215 char *start_dir = "pack/*/start/*/%s"; 216 char *opt_dir = "pack/*/opt/*/%s"; 217 218 if ((flags & DIP_NORTP) == 0) 219 done = do_in_path(path, name, flags, callback, cookie); 220 221 if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_START)) 222 { 223 len = (int)(STRLEN(start_dir) + STRLEN(name)); 224 s = alloc(len); 225 if (s == NULL) 226 return FAIL; 227 vim_snprintf((char *)s, len, start_dir, name); 228 done = do_in_path(p_pp, s, flags, callback, cookie); 229 vim_free(s); 230 } 231 232 if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_OPT)) 233 { 234 len = (int)(STRLEN(opt_dir) + STRLEN(name)); 235 s = alloc(len); 236 if (s == NULL) 237 return FAIL; 238 vim_snprintf((char *)s, len, opt_dir, name); 239 done = do_in_path(p_pp, s, flags, callback, cookie); 240 vim_free(s); 241 } 242 243 return done; 244 } 245 246 /* 247 * Just like do_in_path_and_pp(), using 'runtimepath' for "path". 248 */ 249 int 250 do_in_runtimepath( 251 char_u *name, 252 int flags, 253 void (*callback)(char_u *fname, void *ck), 254 void *cookie) 255 { 256 return do_in_path_and_pp(p_rtp, name, flags, callback, cookie); 257 } 258 259 /* 260 * Source the file "name" from all directories in 'runtimepath'. 261 * "name" can contain wildcards. 262 * When "flags" has DIP_ALL: source all files, otherwise only the first one. 263 * 264 * return FAIL when no file could be sourced, OK otherwise. 265 */ 266 int 267 source_runtime(char_u *name, int flags) 268 { 269 return source_in_path(p_rtp, name, flags); 270 } 271 272 /* 273 * Just like source_runtime(), but use "path" instead of 'runtimepath'. 274 */ 275 int 276 source_in_path(char_u *path, char_u *name, int flags) 277 { 278 return do_in_path_and_pp(path, name, flags, source_callback, NULL); 279 } 280 281 282 #if defined(FEAT_EVAL) || defined(PROTO) 283 284 /* 285 * Expand wildcards in "pat" and invoke do_source() for each match. 286 */ 287 static void 288 source_all_matches(char_u *pat) 289 { 290 int num_files; 291 char_u **files; 292 int i; 293 294 if (gen_expand_wildcards(1, &pat, &num_files, &files, EW_FILE) == OK) 295 { 296 for (i = 0; i < num_files; ++i) 297 (void)do_source(files[i], FALSE, DOSO_NONE); 298 FreeWild(num_files, files); 299 } 300 } 301 302 /* 303 * Add the package directory to 'runtimepath'. 304 */ 305 static int 306 add_pack_dir_to_rtp(char_u *fname) 307 { 308 char_u *p4, *p3, *p2, *p1, *p; 309 char_u *entry; 310 char_u *insp = NULL; 311 int c; 312 char_u *new_rtp; 313 int keep; 314 size_t oldlen; 315 size_t addlen; 316 size_t new_rtp_len; 317 char_u *afterdir = NULL; 318 size_t afterlen = 0; 319 char_u *after_insp = NULL; 320 char_u *ffname = NULL; 321 size_t fname_len; 322 char_u *buf = NULL; 323 char_u *rtp_ffname; 324 int match; 325 int retval = FAIL; 326 327 p4 = p3 = p2 = p1 = get_past_head(fname); 328 for (p = p1; *p; MB_PTR_ADV(p)) 329 if (vim_ispathsep_nocolon(*p)) 330 { 331 p4 = p3; p3 = p2; p2 = p1; p1 = p; 332 } 333 334 // now we have: 335 // rtp/pack/name/start/name 336 // p4 p3 p2 p1 337 // 338 // find the part up to "pack" in 'runtimepath' 339 c = *++p4; // append pathsep in order to expand symlink 340 *p4 = NUL; 341 ffname = fix_fname(fname); 342 *p4 = c; 343 if (ffname == NULL) 344 return FAIL; 345 346 // Find "ffname" in "p_rtp", ignoring '/' vs '\' differences. 347 // Also stop at the first "after" directory. 348 fname_len = STRLEN(ffname); 349 buf = alloc(MAXPATHL); 350 if (buf == NULL) 351 goto theend; 352 for (entry = p_rtp; *entry != NUL; ) 353 { 354 char_u *cur_entry = entry; 355 356 copy_option_part(&entry, buf, MAXPATHL, ","); 357 if (insp == NULL) 358 { 359 add_pathsep(buf); 360 rtp_ffname = fix_fname(buf); 361 if (rtp_ffname == NULL) 362 goto theend; 363 match = vim_fnamencmp(rtp_ffname, ffname, fname_len) == 0; 364 vim_free(rtp_ffname); 365 if (match) 366 // Insert "ffname" after this entry (and comma). 367 insp = entry; 368 } 369 370 if ((p = (char_u *)strstr((char *)buf, "after")) != NULL 371 && p > buf 372 && vim_ispathsep(p[-1]) 373 && (vim_ispathsep(p[5]) || p[5] == NUL || p[5] == ',')) 374 { 375 if (insp == NULL) 376 // Did not find "ffname" before the first "after" directory, 377 // insert it before this entry. 378 insp = cur_entry; 379 after_insp = cur_entry; 380 break; 381 } 382 } 383 384 if (insp == NULL) 385 // Both "fname" and "after" not found, append at the end. 386 insp = p_rtp + STRLEN(p_rtp); 387 388 // check if rtp/pack/name/start/name/after exists 389 afterdir = concat_fnames(fname, (char_u *)"after", TRUE); 390 if (afterdir != NULL && mch_isdir(afterdir)) 391 afterlen = STRLEN(afterdir) + 1; // add one for comma 392 393 oldlen = STRLEN(p_rtp); 394 addlen = STRLEN(fname) + 1; // add one for comma 395 new_rtp = alloc(oldlen + addlen + afterlen + 1); // add one for NUL 396 if (new_rtp == NULL) 397 goto theend; 398 399 // We now have 'rtp' parts: {keep}{keep_after}{rest}. 400 // Create new_rtp, first: {keep},{fname} 401 keep = (int)(insp - p_rtp); 402 mch_memmove(new_rtp, p_rtp, keep); 403 new_rtp_len = keep; 404 if (*insp == NUL) 405 new_rtp[new_rtp_len++] = ','; // add comma before 406 mch_memmove(new_rtp + new_rtp_len, fname, addlen - 1); 407 new_rtp_len += addlen - 1; 408 if (*insp != NUL) 409 new_rtp[new_rtp_len++] = ','; // add comma after 410 411 if (afterlen > 0 && after_insp != NULL) 412 { 413 int keep_after = (int)(after_insp - p_rtp); 414 415 // Add to new_rtp: {keep},{fname}{keep_after},{afterdir} 416 mch_memmove(new_rtp + new_rtp_len, p_rtp + keep, 417 keep_after - keep); 418 new_rtp_len += keep_after - keep; 419 mch_memmove(new_rtp + new_rtp_len, afterdir, afterlen - 1); 420 new_rtp_len += afterlen - 1; 421 new_rtp[new_rtp_len++] = ','; 422 keep = keep_after; 423 } 424 425 if (p_rtp[keep] != NUL) 426 // Append rest: {keep},{fname}{keep_after},{afterdir}{rest} 427 mch_memmove(new_rtp + new_rtp_len, p_rtp + keep, oldlen - keep + 1); 428 else 429 new_rtp[new_rtp_len] = NUL; 430 431 if (afterlen > 0 && after_insp == NULL) 432 { 433 // Append afterdir when "after" was not found: 434 // {keep},{fname}{rest},{afterdir} 435 STRCAT(new_rtp, ","); 436 STRCAT(new_rtp, afterdir); 437 } 438 439 set_option_value((char_u *)"rtp", 0L, new_rtp, 0); 440 vim_free(new_rtp); 441 retval = OK; 442 443 theend: 444 vim_free(buf); 445 vim_free(ffname); 446 vim_free(afterdir); 447 return retval; 448 } 449 450 /* 451 * Load scripts in "plugin" and "ftdetect" directories of the package. 452 */ 453 static int 454 load_pack_plugin(char_u *fname) 455 { 456 static char *plugpat = "%s/plugin/**/*.vim"; 457 static char *ftpat = "%s/ftdetect/*.vim"; 458 int len; 459 char_u *ffname = fix_fname(fname); 460 char_u *pat = NULL; 461 int retval = FAIL; 462 463 if (ffname == NULL) 464 return FAIL; 465 len = (int)STRLEN(ffname) + (int)STRLEN(ftpat); 466 pat = alloc(len); 467 if (pat == NULL) 468 goto theend; 469 vim_snprintf((char *)pat, len, plugpat, ffname); 470 source_all_matches(pat); 471 472 { 473 char_u *cmd = vim_strsave((char_u *)"g:did_load_filetypes"); 474 475 // If runtime/filetype.vim wasn't loaded yet, the scripts will be 476 // found when it loads. 477 if (cmd != NULL && eval_to_number(cmd) > 0) 478 { 479 do_cmdline_cmd((char_u *)"augroup filetypedetect"); 480 vim_snprintf((char *)pat, len, ftpat, ffname); 481 source_all_matches(pat); 482 do_cmdline_cmd((char_u *)"augroup END"); 483 } 484 vim_free(cmd); 485 } 486 vim_free(pat); 487 retval = OK; 488 489 theend: 490 vim_free(ffname); 491 return retval; 492 } 493 494 // used for "cookie" of add_pack_plugin() 495 static int APP_ADD_DIR; 496 static int APP_LOAD; 497 static int APP_BOTH; 498 499 static void 500 add_pack_plugin(char_u *fname, void *cookie) 501 { 502 if (cookie != &APP_LOAD) 503 { 504 char_u *buf = alloc(MAXPATHL); 505 char_u *p; 506 int found = FALSE; 507 508 if (buf == NULL) 509 return; 510 p = p_rtp; 511 while (*p != NUL) 512 { 513 copy_option_part(&p, buf, MAXPATHL, ","); 514 if (pathcmp((char *)buf, (char *)fname, -1) == 0) 515 { 516 found = TRUE; 517 break; 518 } 519 } 520 vim_free(buf); 521 if (!found) 522 // directory is not yet in 'runtimepath', add it 523 if (add_pack_dir_to_rtp(fname) == FAIL) 524 return; 525 } 526 527 if (cookie != &APP_ADD_DIR) 528 load_pack_plugin(fname); 529 } 530 531 /* 532 * Add all packages in the "start" directory to 'runtimepath'. 533 */ 534 void 535 add_pack_start_dirs(void) 536 { 537 do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, 538 add_pack_plugin, &APP_ADD_DIR); 539 } 540 541 /* 542 * Load plugins from all packages in the "start" directory. 543 */ 544 void 545 load_start_packages(void) 546 { 547 did_source_packages = TRUE; 548 do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, 549 add_pack_plugin, &APP_LOAD); 550 } 551 552 /* 553 * ":packloadall" 554 * Find plugins in the package directories and source them. 555 */ 556 void 557 ex_packloadall(exarg_T *eap) 558 { 559 if (!did_source_packages || eap->forceit) 560 { 561 // First do a round to add all directories to 'runtimepath', then load 562 // the plugins. This allows for plugins to use an autoload directory 563 // of another plugin. 564 add_pack_start_dirs(); 565 load_start_packages(); 566 } 567 } 568 569 /* 570 * ":packadd[!] {name}" 571 */ 572 void 573 ex_packadd(exarg_T *eap) 574 { 575 static char *plugpat = "pack/*/%s/%s"; 576 int len; 577 char *pat; 578 int round; 579 int res = OK; 580 581 // Round 1: use "start", round 2: use "opt". 582 for (round = 1; round <= 2; ++round) 583 { 584 // Only look under "start" when loading packages wasn't done yet. 585 if (round == 1 && did_source_packages) 586 continue; 587 588 len = (int)STRLEN(plugpat) + (int)STRLEN(eap->arg) + 5; 589 pat = alloc(len); 590 if (pat == NULL) 591 return; 592 vim_snprintf(pat, len, plugpat, round == 1 ? "start" : "opt", eap->arg); 593 // The first round don't give a "not found" error, in the second round 594 // only when nothing was found in the first round. 595 res = do_in_path(p_pp, (char_u *)pat, 596 DIP_ALL + DIP_DIR + (round == 2 && res == FAIL ? DIP_ERR : 0), 597 add_pack_plugin, eap->forceit ? &APP_ADD_DIR : &APP_BOTH); 598 vim_free(pat); 599 } 600 } 601 #endif 602 603 /* 604 * Expand color scheme, compiler or filetype names. 605 * Search from 'runtimepath': 606 * 'runtimepath'/{dirnames}/{pat}.vim 607 * When "flags" has DIP_START: search also from 'start' of 'packpath': 608 * 'packpath'/pack/ * /start/ * /{dirnames}/{pat}.vim 609 * When "flags" has DIP_OPT: search also from 'opt' of 'packpath': 610 * 'packpath'/pack/ * /opt/ * /{dirnames}/{pat}.vim 611 * "dirnames" is an array with one or more directory names. 612 */ 613 int 614 ExpandRTDir( 615 char_u *pat, 616 int flags, 617 int *num_file, 618 char_u ***file, 619 char *dirnames[]) 620 { 621 char_u *s; 622 char_u *e; 623 char_u *match; 624 garray_T ga; 625 int i; 626 int pat_len; 627 628 *num_file = 0; 629 *file = NULL; 630 pat_len = (int)STRLEN(pat); 631 ga_init2(&ga, (int)sizeof(char *), 10); 632 633 for (i = 0; dirnames[i] != NULL; ++i) 634 { 635 s = alloc(STRLEN(dirnames[i]) + pat_len + 7); 636 if (s == NULL) 637 { 638 ga_clear_strings(&ga); 639 return FAIL; 640 } 641 sprintf((char *)s, "%s/%s*.vim", dirnames[i], pat); 642 globpath(p_rtp, s, &ga, 0); 643 vim_free(s); 644 } 645 646 if (flags & DIP_START) { 647 for (i = 0; dirnames[i] != NULL; ++i) 648 { 649 s = alloc(STRLEN(dirnames[i]) + pat_len + 22); 650 if (s == NULL) 651 { 652 ga_clear_strings(&ga); 653 return FAIL; 654 } 655 sprintf((char *)s, "pack/*/start/*/%s/%s*.vim", dirnames[i], pat); 656 globpath(p_pp, s, &ga, 0); 657 vim_free(s); 658 } 659 } 660 661 if (flags & DIP_OPT) { 662 for (i = 0; dirnames[i] != NULL; ++i) 663 { 664 s = alloc(STRLEN(dirnames[i]) + pat_len + 20); 665 if (s == NULL) 666 { 667 ga_clear_strings(&ga); 668 return FAIL; 669 } 670 sprintf((char *)s, "pack/*/opt/*/%s/%s*.vim", dirnames[i], pat); 671 globpath(p_pp, s, &ga, 0); 672 vim_free(s); 673 } 674 } 675 676 for (i = 0; i < ga.ga_len; ++i) 677 { 678 match = ((char_u **)ga.ga_data)[i]; 679 s = match; 680 e = s + STRLEN(s); 681 if (e - 4 > s && STRNICMP(e - 4, ".vim", 4) == 0) 682 { 683 e -= 4; 684 for (s = e; s > match; MB_PTR_BACK(match, s)) 685 if (s < match || vim_ispathsep(*s)) 686 break; 687 ++s; 688 *e = NUL; 689 mch_memmove(match, s, e - s + 1); 690 } 691 } 692 693 if (ga.ga_len == 0) 694 return FAIL; 695 696 // Sort and remove duplicates which can happen when specifying multiple 697 // directories in dirnames. 698 remove_duplicates(&ga); 699 700 *file = ga.ga_data; 701 *num_file = ga.ga_len; 702 return OK; 703 } 704 705 /* 706 * Expand loadplugin names: 707 * 'packpath'/pack/ * /opt/{pat} 708 */ 709 int 710 ExpandPackAddDir( 711 char_u *pat, 712 int *num_file, 713 char_u ***file) 714 { 715 char_u *s; 716 char_u *e; 717 char_u *match; 718 garray_T ga; 719 int i; 720 int pat_len; 721 722 *num_file = 0; 723 *file = NULL; 724 pat_len = (int)STRLEN(pat); 725 ga_init2(&ga, (int)sizeof(char *), 10); 726 727 s = alloc(pat_len + 26); 728 if (s == NULL) 729 { 730 ga_clear_strings(&ga); 731 return FAIL; 732 } 733 sprintf((char *)s, "pack/*/opt/%s*", pat); 734 globpath(p_pp, s, &ga, 0); 735 vim_free(s); 736 737 for (i = 0; i < ga.ga_len; ++i) 738 { 739 match = ((char_u **)ga.ga_data)[i]; 740 s = gettail(match); 741 e = s + STRLEN(s); 742 mch_memmove(match, s, e - s + 1); 743 } 744 745 if (ga.ga_len == 0) 746 return FAIL; 747 748 // Sort and remove duplicates which can happen when specifying multiple 749 // directories in dirnames. 750 remove_duplicates(&ga); 751 752 *file = ga.ga_data; 753 *num_file = ga.ga_len; 754 return OK; 755 } 756 757 static void 758 cmd_source(char_u *fname, exarg_T *eap) 759 { 760 if (*fname == NUL) 761 emsg(_(e_argreq)); 762 763 else if (eap != NULL && eap->forceit) 764 // ":source!": read Normal mode commands 765 // Need to execute the commands directly. This is required at least 766 // for: 767 // - ":g" command busy 768 // - after ":argdo", ":windo" or ":bufdo" 769 // - another command follows 770 // - inside a loop 771 openscript(fname, global_busy || listcmd_busy || eap->nextcmd != NULL 772 #ifdef FEAT_EVAL 773 || eap->cstack->cs_idx >= 0 774 #endif 775 ); 776 777 // ":source" read ex commands 778 else if (do_source(fname, FALSE, DOSO_NONE) == FAIL) 779 semsg(_(e_notopen), fname); 780 } 781 782 /* 783 * ":source {fname}" 784 */ 785 void 786 ex_source(exarg_T *eap) 787 { 788 #ifdef FEAT_BROWSE 789 if (cmdmod.browse) 790 { 791 char_u *fname = NULL; 792 793 fname = do_browse(0, (char_u *)_("Source Vim script"), eap->arg, 794 NULL, NULL, 795 (char_u *)_(BROWSE_FILTER_MACROS), NULL); 796 if (fname != NULL) 797 { 798 cmd_source(fname, eap); 799 vim_free(fname); 800 } 801 } 802 else 803 #endif 804 cmd_source(eap->arg, eap); 805 } 806 807 #if defined(FEAT_EVAL) || defined(PROTO) 808 /* 809 * ":options" 810 */ 811 void 812 ex_options( 813 exarg_T *eap UNUSED) 814 { 815 vim_setenv((char_u *)"OPTWIN_CMD", 816 (char_u *)(cmdmod.tab ? "tab" 817 : (cmdmod.split & WSP_VERT) ? "vert" : "")); 818 cmd_source((char_u *)SYS_OPTWIN_FILE, NULL); 819 } 820 #endif 821 822 /* 823 * ":source" and associated commands. 824 */ 825 /* 826 * Structure used to store info for each sourced file. 827 * It is shared between do_source() and getsourceline(). 828 * This is required, because it needs to be handed to do_cmdline() and 829 * sourcing can be done recursively. 830 */ 831 struct source_cookie 832 { 833 FILE *fp; // opened file for sourcing 834 char_u *nextline; // if not NULL: line that was read ahead 835 linenr_T sourcing_lnum; // line number of the source file 836 int finished; // ":finish" used 837 #ifdef USE_CRNL 838 int fileformat; // EOL_UNKNOWN, EOL_UNIX or EOL_DOS 839 int error; // TRUE if LF found after CR-LF 840 #endif 841 #ifdef FEAT_EVAL 842 linenr_T breakpoint; // next line with breakpoint or zero 843 char_u *fname; // name of sourced file 844 int dbg_tick; // debug_tick when breakpoint was set 845 int level; // top nesting level of sourced file 846 #endif 847 vimconv_T conv; // type of conversion 848 }; 849 850 #ifdef FEAT_EVAL 851 /* 852 * Return the address holding the next breakpoint line for a source cookie. 853 */ 854 linenr_T * 855 source_breakpoint(void *cookie) 856 { 857 return &((struct source_cookie *)cookie)->breakpoint; 858 } 859 860 /* 861 * Return the address holding the debug tick for a source cookie. 862 */ 863 int * 864 source_dbg_tick(void *cookie) 865 { 866 return &((struct source_cookie *)cookie)->dbg_tick; 867 } 868 869 /* 870 * Return the nesting level for a source cookie. 871 */ 872 int 873 source_level(void *cookie) 874 { 875 return ((struct source_cookie *)cookie)->level; 876 } 877 #endif 878 879 #if (defined(MSWIN) && defined(FEAT_CSCOPE)) || defined(HAVE_FD_CLOEXEC) 880 # define USE_FOPEN_NOINH 881 /* 882 * Special function to open a file without handle inheritance. 883 * When possible the handle is closed on exec(). 884 */ 885 static FILE * 886 fopen_noinh_readbin(char *filename) 887 { 888 # ifdef MSWIN 889 int fd_tmp = mch_open(filename, O_RDONLY | O_BINARY | O_NOINHERIT, 0); 890 # else 891 int fd_tmp = mch_open(filename, O_RDONLY, 0); 892 # endif 893 894 if (fd_tmp == -1) 895 return NULL; 896 897 # ifdef HAVE_FD_CLOEXEC 898 { 899 int fdflags = fcntl(fd_tmp, F_GETFD); 900 if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) 901 (void)fcntl(fd_tmp, F_SETFD, fdflags | FD_CLOEXEC); 902 } 903 # endif 904 905 return fdopen(fd_tmp, READBIN); 906 } 907 #endif 908 909 /* 910 * do_source: Read the file "fname" and execute its lines as EX commands. 911 * 912 * This function may be called recursively! 913 * 914 * return FAIL if file could not be opened, OK otherwise 915 */ 916 int 917 do_source( 918 char_u *fname, 919 int check_other, // check for .vimrc and _vimrc 920 int is_vimrc) // DOSO_ value 921 { 922 struct source_cookie cookie; 923 char_u *save_sourcing_name; 924 linenr_T save_sourcing_lnum; 925 char_u *p; 926 char_u *fname_exp; 927 char_u *firstline = NULL; 928 int retval = FAIL; 929 #ifdef FEAT_EVAL 930 sctx_T save_current_sctx; 931 static scid_T last_current_SID = 0; 932 static int last_current_SID_seq = 0; 933 funccal_entry_T funccalp_entry; 934 int save_debug_break_level = debug_break_level; 935 scriptitem_T *si = NULL; 936 # ifdef UNIX 937 stat_T st; 938 int stat_ok; 939 # endif 940 #endif 941 #ifdef STARTUPTIME 942 struct timeval tv_rel; 943 struct timeval tv_start; 944 #endif 945 #ifdef FEAT_PROFILE 946 proftime_T wait_start; 947 #endif 948 int trigger_source_post = FALSE; 949 950 p = expand_env_save(fname); 951 if (p == NULL) 952 return retval; 953 fname_exp = fix_fname(p); 954 vim_free(p); 955 if (fname_exp == NULL) 956 return retval; 957 if (mch_isdir(fname_exp)) 958 { 959 smsg(_("Cannot source a directory: \"%s\""), fname); 960 goto theend; 961 } 962 963 // Apply SourceCmd autocommands, they should get the file and source it. 964 if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL) 965 && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp, 966 FALSE, curbuf)) 967 { 968 #ifdef FEAT_EVAL 969 retval = aborting() ? FAIL : OK; 970 #else 971 retval = OK; 972 #endif 973 if (retval == OK) 974 // Apply SourcePost autocommands. 975 apply_autocmds(EVENT_SOURCEPOST, fname_exp, fname_exp, 976 FALSE, curbuf); 977 goto theend; 978 } 979 980 // Apply SourcePre autocommands, they may get the file. 981 apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, FALSE, curbuf); 982 983 #ifdef USE_FOPEN_NOINH 984 cookie.fp = fopen_noinh_readbin((char *)fname_exp); 985 #else 986 cookie.fp = mch_fopen((char *)fname_exp, READBIN); 987 #endif 988 if (cookie.fp == NULL && check_other) 989 { 990 // Try again, replacing file name ".vimrc" by "_vimrc" or vice versa, 991 // and ".exrc" by "_exrc" or vice versa. 992 p = gettail(fname_exp); 993 if ((*p == '.' || *p == '_') 994 && (STRICMP(p + 1, "vimrc") == 0 995 || STRICMP(p + 1, "gvimrc") == 0 996 || STRICMP(p + 1, "exrc") == 0)) 997 { 998 if (*p == '_') 999 *p = '.'; 1000 else 1001 *p = '_'; 1002 #ifdef USE_FOPEN_NOINH 1003 cookie.fp = fopen_noinh_readbin((char *)fname_exp); 1004 #else 1005 cookie.fp = mch_fopen((char *)fname_exp, READBIN); 1006 #endif 1007 } 1008 } 1009 1010 if (cookie.fp == NULL) 1011 { 1012 if (p_verbose > 0) 1013 { 1014 verbose_enter(); 1015 if (sourcing_name == NULL) 1016 smsg(_("could not source \"%s\""), fname); 1017 else 1018 smsg(_("line %ld: could not source \"%s\""), 1019 sourcing_lnum, fname); 1020 verbose_leave(); 1021 } 1022 goto theend; 1023 } 1024 1025 // The file exists. 1026 // - In verbose mode, give a message. 1027 // - For a vimrc file, may want to set 'compatible', call vimrc_found(). 1028 if (p_verbose > 1) 1029 { 1030 verbose_enter(); 1031 if (sourcing_name == NULL) 1032 smsg(_("sourcing \"%s\""), fname); 1033 else 1034 smsg(_("line %ld: sourcing \"%s\""), 1035 sourcing_lnum, fname); 1036 verbose_leave(); 1037 } 1038 if (is_vimrc == DOSO_VIMRC) 1039 vimrc_found(fname_exp, (char_u *)"MYVIMRC"); 1040 else if (is_vimrc == DOSO_GVIMRC) 1041 vimrc_found(fname_exp, (char_u *)"MYGVIMRC"); 1042 1043 #ifdef USE_CRNL 1044 // If no automatic file format: Set default to CR-NL. 1045 if (*p_ffs == NUL) 1046 cookie.fileformat = EOL_DOS; 1047 else 1048 cookie.fileformat = EOL_UNKNOWN; 1049 cookie.error = FALSE; 1050 #endif 1051 1052 cookie.nextline = NULL; 1053 cookie.sourcing_lnum = 0; 1054 cookie.finished = FALSE; 1055 1056 #ifdef FEAT_EVAL 1057 // Check if this script has a breakpoint. 1058 cookie.breakpoint = dbg_find_breakpoint(TRUE, fname_exp, (linenr_T)0); 1059 cookie.fname = fname_exp; 1060 cookie.dbg_tick = debug_tick; 1061 1062 cookie.level = ex_nesting_level; 1063 #endif 1064 1065 // Keep the sourcing name/lnum, for recursive calls. 1066 save_sourcing_name = sourcing_name; 1067 sourcing_name = fname_exp; 1068 save_sourcing_lnum = sourcing_lnum; 1069 sourcing_lnum = 0; 1070 1071 #ifdef STARTUPTIME 1072 if (time_fd != NULL) 1073 time_push(&tv_rel, &tv_start); 1074 #endif 1075 1076 #ifdef FEAT_EVAL 1077 # ifdef FEAT_PROFILE 1078 if (do_profiling == PROF_YES) 1079 prof_child_enter(&wait_start); // entering a child now 1080 # endif 1081 1082 // Don't use local function variables, if called from a function. 1083 // Also starts profiling timer for nested script. 1084 save_funccal(&funccalp_entry); 1085 1086 save_current_sctx = current_sctx; 1087 current_sctx.sc_lnum = 0; 1088 current_sctx.sc_version = 1; 1089 1090 // Check if this script was sourced before to finds its SID. 1091 // If it's new, generate a new SID. 1092 // Always use a new sequence number. 1093 current_sctx.sc_seq = ++last_current_SID_seq; 1094 # ifdef UNIX 1095 stat_ok = (mch_stat((char *)fname_exp, &st) >= 0); 1096 # endif 1097 for (current_sctx.sc_sid = script_items.ga_len; current_sctx.sc_sid > 0; 1098 --current_sctx.sc_sid) 1099 { 1100 si = &SCRIPT_ITEM(current_sctx.sc_sid); 1101 if (si->sn_name != NULL 1102 && ( 1103 # ifdef UNIX 1104 // Compare dev/ino when possible, it catches symbolic 1105 // links. Also compare file names, the inode may change 1106 // when the file was edited. 1107 ((stat_ok && si->sn_dev_valid) 1108 && (si->sn_dev == st.st_dev 1109 && si->sn_ino == st.st_ino)) || 1110 # endif 1111 fnamecmp(si->sn_name, fname_exp) == 0)) 1112 break; 1113 } 1114 if (current_sctx.sc_sid == 0) 1115 { 1116 current_sctx.sc_sid = ++last_current_SID; 1117 if (ga_grow(&script_items, 1118 (int)(current_sctx.sc_sid - script_items.ga_len)) == FAIL) 1119 goto almosttheend; 1120 while (script_items.ga_len < current_sctx.sc_sid) 1121 { 1122 ++script_items.ga_len; 1123 SCRIPT_ITEM(script_items.ga_len).sn_name = NULL; 1124 # ifdef FEAT_PROFILE 1125 SCRIPT_ITEM(script_items.ga_len).sn_prof_on = FALSE; 1126 # endif 1127 } 1128 si = &SCRIPT_ITEM(current_sctx.sc_sid); 1129 si->sn_name = fname_exp; 1130 fname_exp = vim_strsave(si->sn_name); // used for autocmd 1131 # ifdef UNIX 1132 if (stat_ok) 1133 { 1134 si->sn_dev_valid = TRUE; 1135 si->sn_dev = st.st_dev; 1136 si->sn_ino = st.st_ino; 1137 } 1138 else 1139 si->sn_dev_valid = FALSE; 1140 # endif 1141 1142 // Allocate the local script variables to use for this script. 1143 new_script_vars(current_sctx.sc_sid); 1144 } 1145 1146 # ifdef FEAT_PROFILE 1147 if (do_profiling == PROF_YES) 1148 { 1149 int forceit; 1150 1151 // Check if we do profiling for this script. 1152 if (!si->sn_prof_on && has_profiling(TRUE, si->sn_name, &forceit)) 1153 { 1154 script_do_profile(si); 1155 si->sn_pr_force = forceit; 1156 } 1157 if (si->sn_prof_on) 1158 { 1159 ++si->sn_pr_count; 1160 profile_start(&si->sn_pr_start); 1161 profile_zero(&si->sn_pr_children); 1162 } 1163 } 1164 # endif 1165 #endif 1166 1167 cookie.conv.vc_type = CONV_NONE; // no conversion 1168 1169 // Read the first line so we can check for a UTF-8 BOM. 1170 firstline = getsourceline(0, (void *)&cookie, 0, TRUE); 1171 if (firstline != NULL && STRLEN(firstline) >= 3 && firstline[0] == 0xef 1172 && firstline[1] == 0xbb && firstline[2] == 0xbf) 1173 { 1174 // Found BOM; setup conversion, skip over BOM and recode the line. 1175 convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc); 1176 p = string_convert(&cookie.conv, firstline + 3, NULL); 1177 if (p == NULL) 1178 p = vim_strsave(firstline + 3); 1179 if (p != NULL) 1180 { 1181 vim_free(firstline); 1182 firstline = p; 1183 } 1184 } 1185 1186 // Call do_cmdline, which will call getsourceline() to get the lines. 1187 do_cmdline(firstline, getsourceline, (void *)&cookie, 1188 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT); 1189 retval = OK; 1190 1191 #ifdef FEAT_PROFILE 1192 if (do_profiling == PROF_YES) 1193 { 1194 // Get "si" again, "script_items" may have been reallocated. 1195 si = &SCRIPT_ITEM(current_sctx.sc_sid); 1196 if (si->sn_prof_on) 1197 { 1198 profile_end(&si->sn_pr_start); 1199 profile_sub_wait(&wait_start, &si->sn_pr_start); 1200 profile_add(&si->sn_pr_total, &si->sn_pr_start); 1201 profile_self(&si->sn_pr_self, &si->sn_pr_start, 1202 &si->sn_pr_children); 1203 } 1204 } 1205 #endif 1206 1207 if (got_int) 1208 emsg(_(e_interr)); 1209 sourcing_name = save_sourcing_name; 1210 sourcing_lnum = save_sourcing_lnum; 1211 if (p_verbose > 1) 1212 { 1213 verbose_enter(); 1214 smsg(_("finished sourcing %s"), fname); 1215 if (sourcing_name != NULL) 1216 smsg(_("continuing in %s"), sourcing_name); 1217 verbose_leave(); 1218 } 1219 #ifdef STARTUPTIME 1220 if (time_fd != NULL) 1221 { 1222 vim_snprintf((char *)IObuff, IOSIZE, "sourcing %s", fname); 1223 time_msg((char *)IObuff, &tv_start); 1224 time_pop(&tv_rel); 1225 } 1226 #endif 1227 1228 if (!got_int) 1229 trigger_source_post = TRUE; 1230 1231 #ifdef FEAT_EVAL 1232 // After a "finish" in debug mode, need to break at first command of next 1233 // sourced file. 1234 if (save_debug_break_level > ex_nesting_level 1235 && debug_break_level == ex_nesting_level) 1236 ++debug_break_level; 1237 #endif 1238 1239 #ifdef FEAT_EVAL 1240 almosttheend: 1241 current_sctx = save_current_sctx; 1242 restore_funccal(); 1243 # ifdef FEAT_PROFILE 1244 if (do_profiling == PROF_YES) 1245 prof_child_exit(&wait_start); // leaving a child now 1246 # endif 1247 #endif 1248 fclose(cookie.fp); 1249 vim_free(cookie.nextline); 1250 vim_free(firstline); 1251 convert_setup(&cookie.conv, NULL, NULL); 1252 1253 if (trigger_source_post) 1254 apply_autocmds(EVENT_SOURCEPOST, fname_exp, fname_exp, FALSE, curbuf); 1255 1256 theend: 1257 vim_free(fname_exp); 1258 return retval; 1259 } 1260 1261 #if defined(FEAT_EVAL) || defined(PROTO) 1262 1263 /* 1264 * ":scriptnames" 1265 */ 1266 void 1267 ex_scriptnames(exarg_T *eap) 1268 { 1269 int i; 1270 1271 if (eap->addr_count > 0) 1272 { 1273 // :script {scriptId}: edit the script 1274 if (eap->line2 < 1 || eap->line2 > script_items.ga_len) 1275 emsg(_(e_invarg)); 1276 else 1277 { 1278 eap->arg = SCRIPT_ITEM(eap->line2).sn_name; 1279 do_exedit(eap, NULL); 1280 } 1281 return; 1282 } 1283 1284 for (i = 1; i <= script_items.ga_len && !got_int; ++i) 1285 if (SCRIPT_ITEM(i).sn_name != NULL) 1286 { 1287 home_replace(NULL, SCRIPT_ITEM(i).sn_name, 1288 NameBuff, MAXPATHL, TRUE); 1289 smsg("%3d: %s", i, NameBuff); 1290 } 1291 } 1292 1293 # if defined(BACKSLASH_IN_FILENAME) || defined(PROTO) 1294 /* 1295 * Fix slashes in the list of script names for 'shellslash'. 1296 */ 1297 void 1298 scriptnames_slash_adjust(void) 1299 { 1300 int i; 1301 1302 for (i = 1; i <= script_items.ga_len; ++i) 1303 if (SCRIPT_ITEM(i).sn_name != NULL) 1304 slash_adjust(SCRIPT_ITEM(i).sn_name); 1305 } 1306 # endif 1307 1308 /* 1309 * Get a pointer to a script name. Used for ":verbose set". 1310 */ 1311 char_u * 1312 get_scriptname(scid_T id) 1313 { 1314 if (id == SID_MODELINE) 1315 return (char_u *)_("modeline"); 1316 if (id == SID_CMDARG) 1317 return (char_u *)_("--cmd argument"); 1318 if (id == SID_CARG) 1319 return (char_u *)_("-c argument"); 1320 if (id == SID_ENV) 1321 return (char_u *)_("environment variable"); 1322 if (id == SID_ERROR) 1323 return (char_u *)_("error handler"); 1324 return SCRIPT_ITEM(id).sn_name; 1325 } 1326 1327 # if defined(EXITFREE) || defined(PROTO) 1328 void 1329 free_scriptnames(void) 1330 { 1331 int i; 1332 1333 for (i = script_items.ga_len; i > 0; --i) 1334 vim_free(SCRIPT_ITEM(i).sn_name); 1335 ga_clear(&script_items); 1336 } 1337 # endif 1338 1339 #endif 1340 1341 linenr_T 1342 get_sourced_lnum(char_u *(*fgetline)(int, void *, int, int), void *cookie) 1343 { 1344 return fgetline == getsourceline 1345 ? ((struct source_cookie *)cookie)->sourcing_lnum 1346 : sourcing_lnum; 1347 } 1348 1349 static char_u * 1350 get_one_sourceline(struct source_cookie *sp) 1351 { 1352 garray_T ga; 1353 int len; 1354 int c; 1355 char_u *buf; 1356 #ifdef USE_CRNL 1357 int has_cr; // CR-LF found 1358 #endif 1359 int have_read = FALSE; 1360 1361 // use a growarray to store the sourced line 1362 ga_init2(&ga, 1, 250); 1363 1364 // Loop until there is a finished line (or end-of-file). 1365 ++sp->sourcing_lnum; 1366 for (;;) 1367 { 1368 // make room to read at least 120 (more) characters 1369 if (ga_grow(&ga, 120) == FAIL) 1370 break; 1371 buf = (char_u *)ga.ga_data; 1372 1373 if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len, 1374 sp->fp) == NULL) 1375 break; 1376 len = ga.ga_len + (int)STRLEN(buf + ga.ga_len); 1377 #ifdef USE_CRNL 1378 // Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the 1379 // CTRL-Z by its own, or after a NL. 1380 if ( (len == 1 || (len >= 2 && buf[len - 2] == '\n')) 1381 && sp->fileformat == EOL_DOS 1382 && buf[len - 1] == Ctrl_Z) 1383 { 1384 buf[len - 1] = NUL; 1385 break; 1386 } 1387 #endif 1388 1389 have_read = TRUE; 1390 ga.ga_len = len; 1391 1392 // If the line was longer than the buffer, read more. 1393 if (ga.ga_maxlen - ga.ga_len == 1 && buf[len - 1] != '\n') 1394 continue; 1395 1396 if (len >= 1 && buf[len - 1] == '\n') // remove trailing NL 1397 { 1398 #ifdef USE_CRNL 1399 has_cr = (len >= 2 && buf[len - 2] == '\r'); 1400 if (sp->fileformat == EOL_UNKNOWN) 1401 { 1402 if (has_cr) 1403 sp->fileformat = EOL_DOS; 1404 else 1405 sp->fileformat = EOL_UNIX; 1406 } 1407 1408 if (sp->fileformat == EOL_DOS) 1409 { 1410 if (has_cr) // replace trailing CR 1411 { 1412 buf[len - 2] = '\n'; 1413 --len; 1414 --ga.ga_len; 1415 } 1416 else // lines like ":map xx yy^M" will have failed 1417 { 1418 if (!sp->error) 1419 { 1420 msg_source(HL_ATTR(HLF_W)); 1421 emsg(_("W15: Warning: Wrong line separator, ^M may be missing")); 1422 } 1423 sp->error = TRUE; 1424 sp->fileformat = EOL_UNIX; 1425 } 1426 } 1427 #endif 1428 // The '\n' is escaped if there is an odd number of ^V's just 1429 // before it, first set "c" just before the 'V's and then check 1430 // len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo 1431 for (c = len - 2; c >= 0 && buf[c] == Ctrl_V; c--) 1432 ; 1433 if ((len & 1) != (c & 1)) // escaped NL, read more 1434 { 1435 ++sp->sourcing_lnum; 1436 continue; 1437 } 1438 1439 buf[len - 1] = NUL; // remove the NL 1440 } 1441 1442 // Check for ^C here now and then, so recursive :so can be broken. 1443 line_breakcheck(); 1444 break; 1445 } 1446 1447 if (have_read) 1448 return (char_u *)ga.ga_data; 1449 1450 vim_free(ga.ga_data); 1451 return NULL; 1452 } 1453 1454 /* 1455 * Get one full line from a sourced file. 1456 * Called by do_cmdline() when it's called from do_source(). 1457 * 1458 * Return a pointer to the line in allocated memory. 1459 * Return NULL for end-of-file or some error. 1460 */ 1461 char_u * 1462 getsourceline(int c UNUSED, void *cookie, int indent UNUSED, int do_concat) 1463 { 1464 struct source_cookie *sp = (struct source_cookie *)cookie; 1465 char_u *line; 1466 char_u *p; 1467 1468 #ifdef FEAT_EVAL 1469 // If breakpoints have been added/deleted need to check for it. 1470 if (sp->dbg_tick < debug_tick) 1471 { 1472 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum); 1473 sp->dbg_tick = debug_tick; 1474 } 1475 # ifdef FEAT_PROFILE 1476 if (do_profiling == PROF_YES) 1477 script_line_end(); 1478 # endif 1479 #endif 1480 1481 // Set the current sourcing line number. 1482 sourcing_lnum = sp->sourcing_lnum + 1; 1483 1484 // Get current line. If there is a read-ahead line, use it, otherwise get 1485 // one now. 1486 if (sp->finished) 1487 line = NULL; 1488 else if (sp->nextline == NULL) 1489 line = get_one_sourceline(sp); 1490 else 1491 { 1492 line = sp->nextline; 1493 sp->nextline = NULL; 1494 ++sp->sourcing_lnum; 1495 } 1496 #ifdef FEAT_PROFILE 1497 if (line != NULL && do_profiling == PROF_YES) 1498 script_line_start(); 1499 #endif 1500 1501 // Only concatenate lines starting with a \ when 'cpoptions' doesn't 1502 // contain the 'C' flag. 1503 if (line != NULL && do_concat && vim_strchr(p_cpo, CPO_CONCAT) == NULL) 1504 { 1505 // compensate for the one line read-ahead 1506 --sp->sourcing_lnum; 1507 1508 // Get the next line and concatenate it when it starts with a 1509 // backslash. We always need to read the next line, keep it in 1510 // sp->nextline. 1511 /* Also check for a comment in between continuation lines: "\ */ 1512 sp->nextline = get_one_sourceline(sp); 1513 if (sp->nextline != NULL 1514 && (*(p = skipwhite(sp->nextline)) == '\\' 1515 || (p[0] == '"' && p[1] == '\\' && p[2] == ' '))) 1516 { 1517 garray_T ga; 1518 1519 ga_init2(&ga, (int)sizeof(char_u), 400); 1520 ga_concat(&ga, line); 1521 if (*p == '\\') 1522 ga_concat(&ga, p + 1); 1523 for (;;) 1524 { 1525 vim_free(sp->nextline); 1526 sp->nextline = get_one_sourceline(sp); 1527 if (sp->nextline == NULL) 1528 break; 1529 p = skipwhite(sp->nextline); 1530 if (*p == '\\') 1531 { 1532 // Adjust the growsize to the current length to speed up 1533 // concatenating many lines. 1534 if (ga.ga_len > 400) 1535 { 1536 if (ga.ga_len > 8000) 1537 ga.ga_growsize = 8000; 1538 else 1539 ga.ga_growsize = ga.ga_len; 1540 } 1541 ga_concat(&ga, p + 1); 1542 } 1543 else if (p[0] != '"' || p[1] != '\\' || p[2] != ' ') 1544 break; 1545 } 1546 ga_append(&ga, NUL); 1547 vim_free(line); 1548 line = ga.ga_data; 1549 } 1550 } 1551 1552 if (line != NULL && sp->conv.vc_type != CONV_NONE) 1553 { 1554 char_u *s; 1555 1556 // Convert the encoding of the script line. 1557 s = string_convert(&sp->conv, line, NULL); 1558 if (s != NULL) 1559 { 1560 vim_free(line); 1561 line = s; 1562 } 1563 } 1564 1565 #ifdef FEAT_EVAL 1566 // Did we encounter a breakpoint? 1567 if (sp->breakpoint != 0 && sp->breakpoint <= sourcing_lnum) 1568 { 1569 dbg_breakpoint(sp->fname, sourcing_lnum); 1570 // Find next breakpoint. 1571 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum); 1572 sp->dbg_tick = debug_tick; 1573 } 1574 #endif 1575 1576 return line; 1577 } 1578 1579 /* 1580 * ":scriptencoding": Set encoding conversion for a sourced script. 1581 */ 1582 void 1583 ex_scriptencoding(exarg_T *eap) 1584 { 1585 struct source_cookie *sp; 1586 char_u *name; 1587 1588 if (!getline_equal(eap->getline, eap->cookie, getsourceline)) 1589 { 1590 emsg(_("E167: :scriptencoding used outside of a sourced file")); 1591 return; 1592 } 1593 1594 if (*eap->arg != NUL) 1595 { 1596 name = enc_canonize(eap->arg); 1597 if (name == NULL) // out of memory 1598 return; 1599 } 1600 else 1601 name = eap->arg; 1602 1603 // Setup for conversion from the specified encoding to 'encoding'. 1604 sp = (struct source_cookie *)getline_cookie(eap->getline, eap->cookie); 1605 convert_setup(&sp->conv, name, p_enc); 1606 1607 if (name != eap->arg) 1608 vim_free(name); 1609 } 1610 1611 /* 1612 * ":scriptversion": Set Vim script version for a sourced script. 1613 */ 1614 void 1615 ex_scriptversion(exarg_T *eap UNUSED) 1616 { 1617 #ifdef FEAT_EVAL 1618 int nr; 1619 1620 if (!getline_equal(eap->getline, eap->cookie, getsourceline)) 1621 { 1622 emsg(_("E984: :scriptversion used outside of a sourced file")); 1623 return; 1624 } 1625 1626 nr = getdigits(&eap->arg); 1627 if (nr == 0 || *eap->arg != NUL) 1628 emsg(_(e_invarg)); 1629 else if (nr > 3) 1630 semsg(_("E999: scriptversion not supported: %d"), nr); 1631 else 1632 current_sctx.sc_version = nr; 1633 #endif 1634 } 1635 1636 #if defined(FEAT_EVAL) || defined(PROTO) 1637 /* 1638 * ":finish": Mark a sourced file as finished. 1639 */ 1640 void 1641 ex_finish(exarg_T *eap) 1642 { 1643 if (getline_equal(eap->getline, eap->cookie, getsourceline)) 1644 do_finish(eap, FALSE); 1645 else 1646 emsg(_("E168: :finish used outside of a sourced file")); 1647 } 1648 1649 /* 1650 * Mark a sourced file as finished. Possibly makes the ":finish" pending. 1651 * Also called for a pending finish at the ":endtry" or after returning from 1652 * an extra do_cmdline(). "reanimate" is used in the latter case. 1653 */ 1654 void 1655 do_finish(exarg_T *eap, int reanimate) 1656 { 1657 int idx; 1658 1659 if (reanimate) 1660 ((struct source_cookie *)getline_cookie(eap->getline, 1661 eap->cookie))->finished = FALSE; 1662 1663 // Cleanup (and inactivate) conditionals, but stop when a try conditional 1664 // not in its finally clause (which then is to be executed next) is found. 1665 // In this case, make the ":finish" pending for execution at the ":endtry". 1666 // Otherwise, finish normally. 1667 idx = cleanup_conditionals(eap->cstack, 0, TRUE); 1668 if (idx >= 0) 1669 { 1670 eap->cstack->cs_pending[idx] = CSTP_FINISH; 1671 report_make_pending(CSTP_FINISH, NULL); 1672 } 1673 else 1674 ((struct source_cookie *)getline_cookie(eap->getline, 1675 eap->cookie))->finished = TRUE; 1676 } 1677 1678 1679 /* 1680 * Return TRUE when a sourced file had the ":finish" command: Don't give error 1681 * message for missing ":endif". 1682 * Return FALSE when not sourcing a file. 1683 */ 1684 int 1685 source_finished( 1686 char_u *(*fgetline)(int, void *, int, int), 1687 void *cookie) 1688 { 1689 return (getline_equal(fgetline, cookie, getsourceline) 1690 && ((struct source_cookie *)getline_cookie( 1691 fgetline, cookie))->finished); 1692 } 1693 #endif 1694