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 * vim9script.c: :vim9script, :import, :export and friends 12 */ 13 14 #include "vim.h" 15 16 #if defined(FEAT_EVAL) 17 # include "vim9.h" 18 #endif 19 20 /* 21 * Return TRUE when currently using Vim9 script syntax. 22 * Does not go up the stack, a ":function" inside vim9script uses legacy 23 * syntax. 24 */ 25 int 26 in_vim9script(void) 27 { 28 // "sc_version" is also set when compiling a ":def" function in legacy 29 // script. 30 return (current_sctx.sc_version == SCRIPT_VERSION_VIM9 31 || (cmdmod.cmod_flags & CMOD_VIM9CMD)) 32 && !(cmdmod.cmod_flags & CMOD_LEGACY); 33 } 34 35 #if defined(FEAT_EVAL) || defined(PROTO) 36 /* 37 * Return TRUE if the current script is Vim9 script. 38 * This also returns TRUE in a legacy function in a Vim9 script. 39 */ 40 int 41 current_script_is_vim9(void) 42 { 43 return SCRIPT_ID_VALID(current_sctx.sc_sid) 44 && SCRIPT_ITEM(current_sctx.sc_sid)->sn_version 45 == SCRIPT_VERSION_VIM9; 46 } 47 #endif 48 49 /* 50 * ":vim9script". 51 */ 52 void 53 ex_vim9script(exarg_T *eap UNUSED) 54 { 55 #ifdef FEAT_EVAL 56 int sid = current_sctx.sc_sid; 57 scriptitem_T *si; 58 59 if (!getline_equal(eap->getline, eap->cookie, getsourceline)) 60 { 61 emsg(_(e_vim9script_can_only_be_used_in_script)); 62 return; 63 } 64 65 si = SCRIPT_ITEM(sid); 66 if (si->sn_state == SN_STATE_HAD_COMMAND) 67 { 68 emsg(_(e_vim9script_must_be_first_command_in_script)); 69 return; 70 } 71 if (!IS_WHITE_OR_NUL(*eap->arg) && STRCMP(eap->arg, "noclear") != 0) 72 { 73 semsg(_(e_invarg2), eap->arg); 74 return; 75 } 76 if (si->sn_state == SN_STATE_RELOAD && IS_WHITE_OR_NUL(*eap->arg)) 77 { 78 hashtab_T *ht = &SCRIPT_VARS(sid); 79 80 // Reloading a script without the "noclear" argument: clear 81 // script-local variables and functions. 82 hashtab_free_contents(ht); 83 hash_init(ht); 84 delete_script_functions(sid); 85 86 // old imports and script variables are no longer valid 87 free_imports_and_script_vars(sid); 88 } 89 si->sn_state = SN_STATE_HAD_COMMAND; 90 91 current_sctx.sc_version = SCRIPT_VERSION_VIM9; 92 si->sn_version = SCRIPT_VERSION_VIM9; 93 94 if (STRCMP(p_cpo, CPO_VIM) != 0) 95 { 96 si->sn_save_cpo = vim_strsave(p_cpo); 97 set_option_value((char_u *)"cpo", 0L, (char_u *)CPO_VIM, OPT_NO_REDRAW); 98 } 99 #else 100 // No check for this being the first command, it doesn't matter. 101 current_sctx.sc_version = SCRIPT_VERSION_VIM9; 102 #endif 103 } 104 105 /* 106 * When in Vim9 script give an error and return FAIL. 107 */ 108 int 109 not_in_vim9(exarg_T *eap) 110 { 111 if (in_vim9script()) 112 switch (eap->cmdidx) 113 { 114 case CMD_k: 115 if (eap->addr_count > 0) 116 { 117 emsg(_(e_norange)); 118 return FAIL; 119 } 120 // FALLTHROUGH 121 case CMD_append: 122 case CMD_change: 123 case CMD_insert: 124 case CMD_open: 125 case CMD_t: 126 case CMD_xit: 127 semsg(_(e_command_not_supported_in_vim9_script_missing_var_str), eap->cmd); 128 return FAIL; 129 default: break; 130 } 131 return OK; 132 } 133 134 /* 135 * Give an error message if "p" points at "#{" and return TRUE. 136 * This avoids that using a legacy style #{} dictionary leads to difficult to 137 * understand errors. 138 */ 139 int 140 vim9_bad_comment(char_u *p) 141 { 142 if (p[0] == '#' && p[1] == '{' && p[2] != '{') 143 { 144 emsg(_(e_cannot_use_hash_curly_to_start_comment)); 145 return TRUE; 146 } 147 return FALSE; 148 } 149 150 /* 151 * Return TRUE if "p" points at a "#" not followed by one '{'. 152 * Does not check for white space. 153 */ 154 int 155 vim9_comment_start(char_u *p) 156 { 157 return p[0] == '#' && (p[1] != '{' || p[2] == '{'); 158 } 159 160 #if defined(FEAT_EVAL) || defined(PROTO) 161 162 /* 163 * "++nr" and "--nr" commands. 164 */ 165 void 166 ex_incdec(exarg_T *eap) 167 { 168 char_u *cmd = eap->cmd; 169 size_t len = STRLEN(eap->cmd) + 6; 170 171 // This works like "nr += 1" or "nr -= 1". 172 eap->cmd = alloc(len); 173 if (eap->cmd == NULL) 174 return; 175 vim_snprintf((char *)eap->cmd, len, "%s %c= 1", cmd + 2, 176 eap->cmdidx == CMD_increment ? '+' : '-'); 177 eap->arg = eap->cmd; 178 eap->cmdidx = CMD_var; 179 ex_let(eap); 180 vim_free(eap->cmd); 181 eap->cmd = cmd; 182 } 183 184 /* 185 * ":export let Name: type" 186 * ":export const Name: type" 187 * ":export def Name(..." 188 * ":export class Name ..." 189 */ 190 void 191 ex_export(exarg_T *eap) 192 { 193 if (!in_vim9script()) 194 { 195 emsg(_(e_export_can_only_be_used_in_vim9script)); 196 return; 197 } 198 199 eap->cmd = eap->arg; 200 (void)find_ex_command(eap, NULL, lookup_scriptitem, NULL); 201 switch (eap->cmdidx) 202 { 203 case CMD_let: 204 case CMD_var: 205 case CMD_final: 206 case CMD_const: 207 case CMD_def: 208 // case CMD_class: 209 is_export = TRUE; 210 do_cmdline(eap->cmd, eap->getline, eap->cookie, 211 DOCMD_VERBOSE + DOCMD_NOWAIT); 212 213 // The command will reset "is_export" when exporting an item. 214 if (is_export) 215 { 216 emsg(_(e_export_with_invalid_argument)); 217 is_export = FALSE; 218 } 219 break; 220 default: 221 emsg(_(e_invalid_command_after_export)); 222 break; 223 } 224 } 225 226 /* 227 * Add a new imported item entry to the current script. 228 */ 229 static imported_T * 230 new_imported(garray_T *gap) 231 { 232 if (ga_grow(gap, 1) == OK) 233 return ((imported_T *)gap->ga_data + gap->ga_len++); 234 return NULL; 235 } 236 237 /* 238 * Free all imported items in script "sid". 239 */ 240 void 241 free_imports_and_script_vars(int sid) 242 { 243 scriptitem_T *si = SCRIPT_ITEM(sid); 244 int idx; 245 246 for (idx = 0; idx < si->sn_imports.ga_len; ++idx) 247 { 248 imported_T *imp = ((imported_T *)si->sn_imports.ga_data) + idx; 249 250 vim_free(imp->imp_name); 251 } 252 ga_clear(&si->sn_imports); 253 254 free_all_script_vars(si); 255 256 clear_type_list(&si->sn_type_list); 257 } 258 259 /* 260 * Mark all imports as possible to redefine. Used when a script is loaded 261 * again but not cleared. 262 */ 263 void 264 mark_imports_for_reload(int sid) 265 { 266 scriptitem_T *si = SCRIPT_ITEM(sid); 267 int idx; 268 269 for (idx = 0; idx < si->sn_imports.ga_len; ++idx) 270 { 271 imported_T *imp = ((imported_T *)si->sn_imports.ga_data) + idx; 272 273 imp->imp_flags |= IMP_FLAGS_RELOAD; 274 } 275 } 276 277 /* 278 * ":import Item from 'filename'" 279 * ":import Item as Alias from 'filename'" 280 * ":import {Item} from 'filename'". 281 * ":import {Item as Alias} from 'filename'" 282 * ":import {Item, Item} from 'filename'" 283 * ":import {Item, Item as Alias} from 'filename'" 284 * 285 * ":import * as Name from 'filename'" 286 */ 287 void 288 ex_import(exarg_T *eap) 289 { 290 char_u *cmd_end; 291 evalarg_T evalarg; 292 293 if (!getline_equal(eap->getline, eap->cookie, getsourceline)) 294 { 295 emsg(_(e_import_can_only_be_used_in_script)); 296 return; 297 } 298 fill_evalarg_from_eap(&evalarg, eap, eap->skip); 299 300 cmd_end = handle_import(eap->arg, NULL, current_sctx.sc_sid, 301 &evalarg, NULL); 302 if (cmd_end != NULL) 303 eap->nextcmd = check_nextcmd(cmd_end); 304 clear_evalarg(&evalarg, eap); 305 } 306 307 /* 308 * Find an exported item in "sid" matching the name at "*argp". 309 * When it is a variable return the index. 310 * When it is a user function return "*ufunc". 311 * When not found returns -1 and "*ufunc" is NULL. 312 */ 313 int 314 find_exported( 315 int sid, 316 char_u *name, 317 ufunc_T **ufunc, 318 type_T **type, 319 cctx_T *cctx, 320 int verbose) 321 { 322 int idx = -1; 323 svar_T *sv; 324 scriptitem_T *script = SCRIPT_ITEM(sid); 325 326 // Find name in "script". 327 idx = get_script_item_idx(sid, name, 0, cctx); 328 if (idx >= 0) 329 { 330 sv = ((svar_T *)script->sn_var_vals.ga_data) + idx; 331 if (!sv->sv_export) 332 { 333 if (verbose) 334 semsg(_(e_item_not_exported_in_script_str), name); 335 return -1; 336 } 337 *type = sv->sv_type; 338 *ufunc = NULL; 339 } 340 else 341 { 342 char_u buffer[200]; 343 char_u *funcname; 344 345 // it could be a user function. 346 if (STRLEN(name) < sizeof(buffer) - 15) 347 funcname = buffer; 348 else 349 { 350 funcname = alloc(STRLEN(name) + 15); 351 if (funcname == NULL) 352 return -1; 353 } 354 funcname[0] = K_SPECIAL; 355 funcname[1] = KS_EXTRA; 356 funcname[2] = (int)KE_SNR; 357 sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name); 358 *ufunc = find_func(funcname, FALSE, NULL); 359 if (funcname != buffer) 360 vim_free(funcname); 361 362 if (*ufunc == NULL) 363 { 364 if (verbose) 365 semsg(_(e_item_not_found_in_script_str), name); 366 return -1; 367 } 368 else if (((*ufunc)->uf_flags & FC_EXPORT) == 0) 369 { 370 if (verbose) 371 semsg(_(e_item_not_exported_in_script_str), name); 372 *ufunc = NULL; 373 return -1; 374 } 375 } 376 377 return idx; 378 } 379 380 /* 381 * Handle an ":import" command and add the resulting imported_T to "gap", when 382 * not NULL, or script "import_sid" sn_imports. 383 * "cctx" is NULL at the script level. 384 * Returns a pointer to after the command or NULL in case of failure 385 */ 386 char_u * 387 handle_import( 388 char_u *arg_start, 389 garray_T *gap, 390 int import_sid, 391 evalarg_T *evalarg, 392 void *cctx) 393 { 394 char_u *arg = arg_start; 395 char_u *cmd_end = NULL; 396 int ret = FAIL; 397 typval_T tv; 398 int sid = -1; 399 int res; 400 int mult = FALSE; 401 garray_T names; 402 garray_T as_names; 403 404 ga_init2(&names, sizeof(char_u *), 10); 405 ga_init2(&as_names, sizeof(char_u *), 10); 406 if (*arg == '{') 407 { 408 // "import {item, item} from ..." 409 mult = TRUE; 410 arg = skipwhite_and_linebreak(arg + 1, evalarg); 411 } 412 413 for (;;) 414 { 415 char_u *p = arg; 416 int had_comma = FALSE; 417 char_u *as_name = NULL; 418 419 // accept "*" or "Name" 420 if (!mult && arg[0] == '*' && IS_WHITE_OR_NUL(arg[1])) 421 ++arg; 422 else 423 while (eval_isnamec(*arg)) 424 ++arg; 425 if (p == arg) 426 break; 427 if (ga_grow(&names, 1) == FAIL || ga_grow(&as_names, 1) == FAIL) 428 goto erret; 429 ((char_u **)names.ga_data)[names.ga_len] = vim_strnsave(p, arg - p); 430 ++names.ga_len; 431 432 arg = skipwhite_and_linebreak(arg, evalarg); 433 if (STRNCMP("as", arg, 2) == 0 && IS_WHITE_OR_NUL(arg[2])) 434 { 435 // skip over "as Name "; no line break allowed after "as" 436 arg = skipwhite(arg + 2); 437 p = arg; 438 if (eval_isnamec1(*arg)) 439 while (eval_isnamec(*arg)) 440 ++arg; 441 if (check_defined(p, arg - p, cctx, FALSE) == FAIL) 442 goto erret; 443 as_name = vim_strnsave(p, arg - p); 444 arg = skipwhite_and_linebreak(arg, evalarg); 445 } 446 else if (*arg_start == '*') 447 { 448 emsg(_(e_missing_as_after_star)); 449 goto erret; 450 } 451 // without "as Name" the as_names entry is NULL 452 ((char_u **)as_names.ga_data)[as_names.ga_len] = as_name; 453 ++as_names.ga_len; 454 455 if (!mult) 456 break; 457 if (*arg == ',') 458 { 459 had_comma = TRUE; 460 ++arg; 461 } 462 arg = skipwhite_and_linebreak(arg, evalarg); 463 if (*arg == '}') 464 { 465 ++arg; 466 break; 467 } 468 if (!had_comma) 469 { 470 emsg(_(e_missing_comma_in_import)); 471 goto erret; 472 } 473 } 474 arg = skipwhite_and_linebreak(arg, evalarg); 475 476 if (names.ga_len == 0) 477 { 478 emsg(_(e_syntax_error_in_import)); 479 goto erret; 480 } 481 482 if (STRNCMP("from", arg, 4) != 0 || !IS_WHITE_OR_NUL(arg[4])) 483 { 484 emsg(_(e_missing_from)); 485 goto erret; 486 } 487 488 arg = skipwhite_and_linebreak(arg + 4, evalarg); 489 tv.v_type = VAR_UNKNOWN; 490 // TODO: should we accept any expression? 491 if (*arg == '\'') 492 ret = eval_lit_string(&arg, &tv, TRUE); 493 else if (*arg == '"') 494 ret = eval_string(&arg, &tv, TRUE); 495 if (ret == FAIL || tv.vval.v_string == NULL || *tv.vval.v_string == NUL) 496 { 497 emsg(_(e_invalid_string_after_from)); 498 goto erret; 499 } 500 cmd_end = arg; 501 502 /* 503 * find script file 504 */ 505 if (*tv.vval.v_string == '.') 506 { 507 size_t len; 508 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); 509 char_u *tail = gettail(si->sn_name); 510 char_u *from_name; 511 512 // Relative to current script: "./name.vim", "../../name.vim". 513 len = STRLEN(si->sn_name) - STRLEN(tail) + STRLEN(tv.vval.v_string) + 2; 514 from_name = alloc((int)len); 515 if (from_name == NULL) 516 { 517 clear_tv(&tv); 518 goto erret; 519 } 520 vim_strncpy(from_name, si->sn_name, tail - si->sn_name); 521 add_pathsep(from_name); 522 STRCAT(from_name, tv.vval.v_string); 523 simplify_filename(from_name); 524 525 res = do_source(from_name, FALSE, DOSO_NONE, &sid); 526 vim_free(from_name); 527 } 528 else if (mch_isFullName(tv.vval.v_string)) 529 { 530 // Absolute path: "/tmp/name.vim" 531 res = do_source(tv.vval.v_string, FALSE, DOSO_NONE, &sid); 532 } 533 else 534 { 535 size_t len = 7 + STRLEN(tv.vval.v_string) + 1; 536 char_u *from_name; 537 538 // Find file in "import" subdirs in 'runtimepath'. 539 from_name = alloc((int)len); 540 if (from_name == NULL) 541 { 542 clear_tv(&tv); 543 goto erret; 544 } 545 vim_snprintf((char *)from_name, len, "import/%s", tv.vval.v_string); 546 res = source_in_path(p_rtp, from_name, DIP_NOAFTER, &sid); 547 vim_free(from_name); 548 } 549 550 if (res == FAIL || sid <= 0) 551 { 552 semsg(_(e_could_not_import_str), tv.vval.v_string); 553 clear_tv(&tv); 554 goto erret; 555 } 556 clear_tv(&tv); 557 558 if (*arg_start == '*') 559 { 560 imported_T *imported; 561 char_u *as_name = ((char_u **)as_names.ga_data)[0]; 562 563 // "import * as That" 564 imported = find_imported(as_name, STRLEN(as_name), cctx); 565 if (imported != NULL && imported->imp_sid == sid) 566 { 567 if (imported->imp_flags & IMP_FLAGS_RELOAD) 568 // import already defined on a previous script load 569 imported->imp_flags &= ~IMP_FLAGS_RELOAD; 570 else 571 { 572 semsg(_(e_name_already_defined_str), as_name); 573 goto erret; 574 } 575 } 576 577 imported = new_imported(gap != NULL ? gap 578 : &SCRIPT_ITEM(import_sid)->sn_imports); 579 if (imported == NULL) 580 goto erret; 581 imported->imp_name = as_name; 582 ((char_u **)as_names.ga_data)[0] = NULL; 583 imported->imp_sid = sid; 584 imported->imp_flags = IMP_FLAGS_STAR; 585 } 586 else 587 { 588 int i; 589 590 arg = arg_start; 591 if (*arg == '{') 592 arg = skipwhite(arg + 1); 593 for (i = 0; i < names.ga_len; ++i) 594 { 595 char_u *name = ((char_u **)names.ga_data)[i]; 596 char_u *as_name = ((char_u **)as_names.ga_data)[i]; 597 size_t len = STRLEN(name); 598 int idx; 599 imported_T *imported; 600 ufunc_T *ufunc = NULL; 601 type_T *type; 602 603 idx = find_exported(sid, name, &ufunc, &type, cctx, TRUE); 604 605 if (idx < 0 && ufunc == NULL) 606 goto erret; 607 608 // If already imported with the same propertis and the 609 // IMP_FLAGS_RELOAD set then we keep that entry. Otherwise create 610 // a new one (and give an error for an existing import). 611 imported = find_imported(name, len, cctx); 612 if (imported != NULL 613 && (imported->imp_flags & IMP_FLAGS_RELOAD) 614 && imported->imp_sid == sid 615 && (idx >= 0 616 ? (equal_type(imported->imp_type, type) 617 && imported->imp_var_vals_idx == idx) 618 : (equal_type(imported->imp_type, ufunc->uf_func_type) 619 && STRCMP(imported->imp_funcname, 620 ufunc->uf_name) == 0))) 621 { 622 imported->imp_flags &= ~IMP_FLAGS_RELOAD; 623 } 624 else 625 { 626 if (as_name == NULL 627 && check_defined(name, len, cctx, FALSE) == FAIL) 628 goto erret; 629 630 imported = new_imported(gap != NULL ? gap 631 : &SCRIPT_ITEM(import_sid)->sn_imports); 632 if (imported == NULL) 633 goto erret; 634 635 if (as_name == NULL) 636 { 637 imported->imp_name = name; 638 ((char_u **)names.ga_data)[i] = NULL; 639 } 640 else 641 { 642 // "import This as That ..." 643 imported->imp_name = as_name; 644 ((char_u **)as_names.ga_data)[i] = NULL; 645 } 646 imported->imp_sid = sid; 647 if (idx >= 0) 648 { 649 imported->imp_type = type; 650 imported->imp_var_vals_idx = idx; 651 } 652 else 653 { 654 imported->imp_type = ufunc->uf_func_type; 655 imported->imp_funcname = ufunc->uf_name; 656 } 657 } 658 } 659 } 660 erret: 661 ga_clear_strings(&names); 662 ga_clear_strings(&as_names); 663 return cmd_end; 664 } 665 666 /* 667 * Declare a script-local variable without init: "let var: type". 668 * "const" is an error since the value is missing. 669 * Returns a pointer to after the type. 670 */ 671 char_u * 672 vim9_declare_scriptvar(exarg_T *eap, char_u *arg) 673 { 674 char_u *p; 675 char_u *name; 676 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); 677 type_T *type; 678 typval_T init_tv; 679 680 if (eap->cmdidx == CMD_final || eap->cmdidx == CMD_const) 681 { 682 if (eap->cmdidx == CMD_final) 683 emsg(_(e_final_requires_a_value)); 684 else 685 emsg(_(e_const_requires_a_value)); 686 return arg + STRLEN(arg); 687 } 688 689 // Check for valid starting character. 690 if (!eval_isnamec1(*arg)) 691 { 692 semsg(_(e_invarg2), arg); 693 return arg + STRLEN(arg); 694 } 695 696 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p)) 697 if (*p == ':' && (VIM_ISWHITE(p[1]) || p != arg + 1)) 698 break; 699 700 if (*p != ':') 701 { 702 emsg(_(e_type_or_initialization_required)); 703 return arg + STRLEN(arg); 704 } 705 if (!VIM_ISWHITE(p[1])) 706 { 707 semsg(_(e_white_space_required_after_str_str), ":", p); 708 return arg + STRLEN(arg); 709 } 710 name = vim_strnsave(arg, p - arg); 711 712 // parse type, check for reserved name 713 p = skipwhite(p + 1); 714 type = parse_type(&p, &si->sn_type_list, TRUE); 715 if (type == NULL || check_reserved_name(name) == FAIL) 716 { 717 vim_free(name); 718 return p; 719 } 720 721 // Create the variable with 0/NULL value. 722 CLEAR_FIELD(init_tv); 723 if (type->tt_type == VAR_ANY) 724 // A variable of type "any" is not possible, just use zero instead 725 init_tv.v_type = VAR_NUMBER; 726 else 727 init_tv.v_type = type->tt_type; 728 set_var_const(name, type, &init_tv, FALSE, 0, 0); 729 730 vim_free(name); 731 return p; 732 } 733 734 /* 735 * Vim9 part of adding a script variable: add it to sn_all_vars (lookup by name 736 * with a hashtable) and sn_var_vals (lookup by index). 737 * When "create" is TRUE this is a new variable, otherwise find and update an 738 * existing variable. 739 * "flags" can have ASSIGN_FINAL or ASSIGN_CONST. 740 * When "*type" is NULL use "tv" for the type and update "*type". If 741 * "do_member" is TRUE also use the member type, otherwise use "any". 742 */ 743 void 744 update_vim9_script_var( 745 int create, 746 dictitem_T *di, 747 int flags, 748 typval_T *tv, 749 type_T **type, 750 int do_member) 751 { 752 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); 753 hashitem_T *hi; 754 svar_T *sv; 755 756 if (create) 757 { 758 sallvar_T *newsav; 759 760 // Store a pointer to the typval_T, so that it can be found by index 761 // instead of using a hastab lookup. 762 if (ga_grow(&si->sn_var_vals, 1) == FAIL) 763 return; 764 765 sv = ((svar_T *)si->sn_var_vals.ga_data) + si->sn_var_vals.ga_len; 766 newsav = (sallvar_T *)alloc_clear( 767 sizeof(sallvar_T) + STRLEN(di->di_key)); 768 if (newsav == NULL) 769 return; 770 771 sv->sv_tv = &di->di_tv; 772 sv->sv_const = (flags & ASSIGN_FINAL) ? ASSIGN_FINAL 773 : (flags & ASSIGN_CONST) ? ASSIGN_CONST : 0; 774 sv->sv_export = is_export; 775 newsav->sav_var_vals_idx = si->sn_var_vals.ga_len; 776 ++si->sn_var_vals.ga_len; 777 STRCPY(&newsav->sav_key, di->di_key); 778 sv->sv_name = newsav->sav_key; 779 newsav->sav_di = di; 780 newsav->sav_block_id = si->sn_current_block_id; 781 782 hi = hash_find(&si->sn_all_vars.dv_hashtab, newsav->sav_key); 783 if (!HASHITEM_EMPTY(hi)) 784 { 785 sallvar_T *sav = HI2SAV(hi); 786 787 // variable with this name exists in another block 788 while (sav->sav_next != NULL) 789 sav = sav->sav_next; 790 sav->sav_next = newsav; 791 } 792 else 793 // new variable name 794 hash_add(&si->sn_all_vars.dv_hashtab, newsav->sav_key); 795 } 796 else 797 { 798 sv = find_typval_in_script(&di->di_tv); 799 } 800 if (sv != NULL) 801 { 802 if (*type == NULL) 803 *type = typval2type(tv, get_copyID(), &si->sn_type_list, 804 do_member); 805 sv->sv_type = *type; 806 } 807 808 // let ex_export() know the export worked. 809 is_export = FALSE; 810 } 811 812 /* 813 * Hide a script variable when leaving a block. 814 * "idx" is de index in sn_var_vals. 815 * When "func_defined" is non-zero then a function was defined in this block, 816 * the variable may be accessed by it. Otherwise the variable can be cleared. 817 */ 818 void 819 hide_script_var(scriptitem_T *si, int idx, int func_defined) 820 { 821 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx; 822 hashtab_T *script_ht = get_script_local_ht(); 823 hashtab_T *all_ht = &si->sn_all_vars.dv_hashtab; 824 hashitem_T *script_hi; 825 hashitem_T *all_hi; 826 827 // Remove a variable declared inside the block, if it still exists. 828 // If it was added in a nested block it will already have been removed. 829 // The typval is moved into the sallvar_T. 830 script_hi = hash_find(script_ht, sv->sv_name); 831 all_hi = hash_find(all_ht, sv->sv_name); 832 if (!HASHITEM_EMPTY(script_hi) && !HASHITEM_EMPTY(all_hi)) 833 { 834 dictitem_T *di = HI2DI(script_hi); 835 sallvar_T *sav = HI2SAV(all_hi); 836 sallvar_T *sav_prev = NULL; 837 838 // There can be multiple entries with the same name in different 839 // blocks, find the right one. 840 while (sav != NULL && sav->sav_var_vals_idx != idx) 841 { 842 sav_prev = sav; 843 sav = sav->sav_next; 844 } 845 if (sav != NULL) 846 { 847 if (func_defined) 848 { 849 // move the typval from the dictitem to the sallvar 850 sav->sav_tv = di->di_tv; 851 di->di_tv.v_type = VAR_UNKNOWN; 852 sav->sav_flags = di->di_flags; 853 sav->sav_di = NULL; 854 sv->sv_tv = &sav->sav_tv; 855 } 856 else 857 { 858 if (sav_prev == NULL) 859 hash_remove(all_ht, all_hi); 860 else 861 sav_prev->sav_next = sav->sav_next; 862 sv->sv_name = NULL; 863 vim_free(sav); 864 } 865 delete_var(script_ht, script_hi); 866 } 867 } 868 } 869 870 /* 871 * Free the script variables from "sn_all_vars". 872 */ 873 void 874 free_all_script_vars(scriptitem_T *si) 875 { 876 int todo; 877 hashtab_T *ht = &si->sn_all_vars.dv_hashtab; 878 hashitem_T *hi; 879 sallvar_T *sav; 880 sallvar_T *sav_next; 881 882 hash_lock(ht); 883 todo = (int)ht->ht_used; 884 for (hi = ht->ht_array; todo > 0; ++hi) 885 { 886 if (!HASHITEM_EMPTY(hi)) 887 { 888 --todo; 889 890 // Free the variable. Don't remove it from the hashtab, ht_array 891 // might change then. hash_clear() takes care of it later. 892 sav = HI2SAV(hi); 893 while (sav != NULL) 894 { 895 sav_next = sav->sav_next; 896 if (sav->sav_di == NULL) 897 clear_tv(&sav->sav_tv); 898 vim_free(sav); 899 sav = sav_next; 900 } 901 } 902 } 903 hash_clear(ht); 904 hash_init(ht); 905 906 ga_clear(&si->sn_var_vals); 907 908 // existing commands using script variable indexes are no longer valid 909 si->sn_script_seq = current_sctx.sc_seq; 910 } 911 912 /* 913 * Find the script-local variable that links to "dest". 914 * Returns NULL if not found. 915 */ 916 svar_T * 917 find_typval_in_script(typval_T *dest) 918 { 919 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); 920 int idx; 921 922 if (si->sn_version != SCRIPT_VERSION_VIM9) 923 // legacy script doesn't store variable types 924 return NULL; 925 926 // Find the svar_T in sn_var_vals. 927 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx) 928 { 929 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx; 930 931 // If "sv_name" is NULL the variable was hidden when leaving a block, 932 // don't check "sv_tv" then, it might be used for another variable now. 933 if (sv->sv_name != NULL && sv->sv_tv == dest) 934 return sv; 935 } 936 iemsg("find_typval_in_script(): not found"); 937 return NULL; 938 } 939 940 /* 941 * Check if the type of script variable "dest" allows assigning "value". 942 * If needed convert "value" to a bool. 943 */ 944 int 945 check_script_var_type( 946 typval_T *dest, 947 typval_T *value, 948 char_u *name, 949 where_T where) 950 { 951 svar_T *sv = find_typval_in_script(dest); 952 int ret; 953 954 if (sv != NULL) 955 { 956 if (sv->sv_const != 0) 957 { 958 semsg(_(e_readonlyvar), name); 959 return FAIL; 960 } 961 ret = check_typval_type(sv->sv_type, value, where); 962 if (ret == OK && need_convert_to_bool(sv->sv_type, value)) 963 { 964 int val = tv2bool(value); 965 966 clear_tv(value); 967 value->v_type = VAR_BOOL; 968 value->v_lock = 0; 969 value->vval.v_number = val ? VVAL_TRUE : VVAL_FALSE; 970 } 971 return ret; 972 } 973 974 return OK; // not really 975 } 976 977 // words that cannot be used as a variable 978 static char *reserved[] = { 979 "true", 980 "false", 981 "null", 982 "this", 983 NULL 984 }; 985 986 int 987 check_reserved_name(char_u *name) 988 { 989 int idx; 990 991 for (idx = 0; reserved[idx] != NULL; ++idx) 992 if (STRCMP(reserved[idx], name) == 0) 993 { 994 semsg(_(e_cannot_use_reserved_name), name); 995 return FAIL; 996 } 997 return OK; 998 } 999 1000 #endif // FEAT_EVAL 1001