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