diff options
author | Bram Moolenaar <Bram@vim.org> | 2019-09-01 16:01:30 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2019-09-01 16:01:30 +0200 |
commit | da6c03342117fb7f4a8110bd9e8627b612a05a64 (patch) | |
tree | 978562abf59627127149d50d9f2650a69e78c078 /src/eval.c | |
parent | 0fdddeeb66bbe326860ddfc573eba42f6487bbda (diff) |
patch 8.1.1957: more code can be moved to evalvars.cv8.1.1957
Problem: More code can be moved to evalvars.c.
Solution: Move code to where it fits better. (Yegappan Lakshmanan,
closes #4883)
Diffstat (limited to 'src/eval.c')
-rw-r--r-- | src/eval.c | 532 |
1 files changed, 15 insertions, 517 deletions
diff --git a/src/eval.c b/src/eval.c index f32092c821..e75624345a 100644 --- a/src/eval.c +++ b/src/eval.c @@ -38,9 +38,6 @@ static int current_copyID = 0; static int echo_attr = 0; /* attributes used for ":echo" */ -/* The names of packages that once were loaded are remembered. */ -static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL}; - /* * Info used by a ":for" loop. */ @@ -156,8 +153,8 @@ eval_clear(void) free_scriptnames(); free_locales(); - /* autoloaded script names */ - ga_clear_strings(&ga_loaded); + // autoloaded script names + free_autoload_scriptnames(); // unreferenced lists and dicts (void)garbage_collect(FALSE); @@ -167,240 +164,6 @@ eval_clear(void) } #endif -static lval_T *redir_lval = NULL; -#define EVALCMD_BUSY (redir_lval == (lval_T *)&redir_lval) -static garray_T redir_ga; /* only valid when redir_lval is not NULL */ -static char_u *redir_endp = NULL; -static char_u *redir_varname = NULL; - -/* - * Start recording command output to a variable - * When "append" is TRUE append to an existing variable. - * Returns OK if successfully completed the setup. FAIL otherwise. - */ - int -var_redir_start(char_u *name, int append) -{ - int save_emsg; - int err; - typval_T tv; - - /* Catch a bad name early. */ - if (!eval_isnamec1(*name)) - { - emsg(_(e_invarg)); - return FAIL; - } - - /* Make a copy of the name, it is used in redir_lval until redir ends. */ - redir_varname = vim_strsave(name); - if (redir_varname == NULL) - return FAIL; - - redir_lval = ALLOC_CLEAR_ONE(lval_T); - if (redir_lval == NULL) - { - var_redir_stop(); - return FAIL; - } - - /* The output is stored in growarray "redir_ga" until redirection ends. */ - ga_init2(&redir_ga, (int)sizeof(char), 500); - - /* Parse the variable name (can be a dict or list entry). */ - redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, 0, - FNE_CHECK_START); - if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL) - { - clear_lval(redir_lval); - if (redir_endp != NULL && *redir_endp != NUL) - /* Trailing characters are present after the variable name */ - emsg(_(e_trailing)); - else - emsg(_(e_invarg)); - redir_endp = NULL; /* don't store a value, only cleanup */ - var_redir_stop(); - return FAIL; - } - - /* check if we can write to the variable: set it to or append an empty - * string */ - save_emsg = did_emsg; - did_emsg = FALSE; - tv.v_type = VAR_STRING; - tv.vval.v_string = (char_u *)""; - if (append) - set_var_lval(redir_lval, redir_endp, &tv, TRUE, FALSE, (char_u *)"."); - else - set_var_lval(redir_lval, redir_endp, &tv, TRUE, FALSE, (char_u *)"="); - clear_lval(redir_lval); - err = did_emsg; - did_emsg |= save_emsg; - if (err) - { - redir_endp = NULL; /* don't store a value, only cleanup */ - var_redir_stop(); - return FAIL; - } - - return OK; -} - -/* - * Append "value[value_len]" to the variable set by var_redir_start(). - * The actual appending is postponed until redirection ends, because the value - * appended may in fact be the string we write to, changing it may cause freed - * memory to be used: - * :redir => foo - * :let foo - * :redir END - */ - void -var_redir_str(char_u *value, int value_len) -{ - int len; - - if (redir_lval == NULL) - return; - - if (value_len == -1) - len = (int)STRLEN(value); /* Append the entire string */ - else - len = value_len; /* Append only "value_len" characters */ - - if (ga_grow(&redir_ga, len) == OK) - { - mch_memmove((char *)redir_ga.ga_data + redir_ga.ga_len, value, len); - redir_ga.ga_len += len; - } - else - var_redir_stop(); -} - -/* - * Stop redirecting command output to a variable. - * Frees the allocated memory. - */ - void -var_redir_stop(void) -{ - typval_T tv; - - if (EVALCMD_BUSY) - { - redir_lval = NULL; - return; - } - - if (redir_lval != NULL) - { - /* If there was no error: assign the text to the variable. */ - if (redir_endp != NULL) - { - ga_append(&redir_ga, NUL); /* Append the trailing NUL. */ - tv.v_type = VAR_STRING; - tv.vval.v_string = redir_ga.ga_data; - /* Call get_lval() again, if it's inside a Dict or List it may - * have changed. */ - redir_endp = get_lval(redir_varname, NULL, redir_lval, - FALSE, FALSE, 0, FNE_CHECK_START); - if (redir_endp != NULL && redir_lval->ll_name != NULL) - set_var_lval(redir_lval, redir_endp, &tv, FALSE, FALSE, - (char_u *)"."); - clear_lval(redir_lval); - } - - /* free the collected output */ - VIM_CLEAR(redir_ga.ga_data); - - VIM_CLEAR(redir_lval); - } - VIM_CLEAR(redir_varname); -} - - int -eval_charconvert( - char_u *enc_from, - char_u *enc_to, - char_u *fname_from, - char_u *fname_to) -{ - int err = FALSE; - - set_vim_var_string(VV_CC_FROM, enc_from, -1); - set_vim_var_string(VV_CC_TO, enc_to, -1); - set_vim_var_string(VV_FNAME_IN, fname_from, -1); - set_vim_var_string(VV_FNAME_OUT, fname_to, -1); - if (eval_to_bool(p_ccv, &err, NULL, FALSE)) - err = TRUE; - set_vim_var_string(VV_CC_FROM, NULL, -1); - set_vim_var_string(VV_CC_TO, NULL, -1); - set_vim_var_string(VV_FNAME_IN, NULL, -1); - set_vim_var_string(VV_FNAME_OUT, NULL, -1); - - if (err) - return FAIL; - return OK; -} - -# if defined(FEAT_POSTSCRIPT) || defined(PROTO) - int -eval_printexpr(char_u *fname, char_u *args) -{ - int err = FALSE; - - set_vim_var_string(VV_FNAME_IN, fname, -1); - set_vim_var_string(VV_CMDARG, args, -1); - if (eval_to_bool(p_pexpr, &err, NULL, FALSE)) - err = TRUE; - set_vim_var_string(VV_FNAME_IN, NULL, -1); - set_vim_var_string(VV_CMDARG, NULL, -1); - - if (err) - { - mch_remove(fname); - return FAIL; - } - return OK; -} -# endif - -# if defined(FEAT_DIFF) || defined(PROTO) - void -eval_diff( - char_u *origfile, - char_u *newfile, - char_u *outfile) -{ - int err = FALSE; - - set_vim_var_string(VV_FNAME_IN, origfile, -1); - set_vim_var_string(VV_FNAME_NEW, newfile, -1); - set_vim_var_string(VV_FNAME_OUT, outfile, -1); - (void)eval_to_bool(p_dex, &err, NULL, FALSE); - set_vim_var_string(VV_FNAME_IN, NULL, -1); - set_vim_var_string(VV_FNAME_NEW, NULL, -1); - set_vim_var_string(VV_FNAME_OUT, NULL, -1); -} - - void -eval_patch( - char_u *origfile, - char_u *difffile, - char_u *outfile) -{ - int err; - - set_vim_var_string(VV_FNAME_IN, origfile, -1); - set_vim_var_string(VV_FNAME_DIFF, difffile, -1); - set_vim_var_string(VV_FNAME_OUT, outfile, -1); - (void)eval_to_bool(p_pex, &err, NULL, FALSE); - set_vim_var_string(VV_FNAME_IN, NULL, -1); - set_vim_var_string(VV_FNAME_DIFF, NULL, -1); - set_vim_var_string(VV_FNAME_OUT, NULL, -1); -} -# endif - /* * Top level evaluation function, returning a boolean. * Sets "error" to TRUE if there was an error. @@ -671,65 +434,6 @@ eval_to_number(char_u *expr) return retval; } -#if defined(FEAT_SPELL) || defined(PROTO) -/* - * Evaluate an expression to a list with suggestions. - * For the "expr:" part of 'spellsuggest'. - * Returns NULL when there is an error. - */ - list_T * -eval_spell_expr(char_u *badword, char_u *expr) -{ - typval_T save_val; - typval_T rettv; - list_T *list = NULL; - char_u *p = skipwhite(expr); - - /* Set "v:val" to the bad word. */ - prepare_vimvar(VV_VAL, &save_val); - set_vim_var_string(VV_VAL, badword, -1); - if (p_verbose == 0) - ++emsg_off; - - if (eval1(&p, &rettv, TRUE) == OK) - { - if (rettv.v_type != VAR_LIST) - clear_tv(&rettv); - else - list = rettv.vval.v_list; - } - - if (p_verbose == 0) - --emsg_off; - clear_tv(get_vim_var_tv(VV_VAL)); - restore_vimvar(VV_VAL, &save_val); - - return list; -} - -/* - * "list" is supposed to contain two items: a word and a number. Return the - * word in "pp" and the number as the return value. - * Return -1 if anything isn't right. - * Used to get the good word and score from the eval_spell_expr() result. - */ - int -get_spellword(list_T *list, char_u **pp) -{ - listitem_T *li; - - li = list->lv_first; - if (li == NULL) - return -1; - *pp = tv_get_string(&li->li_tv); - - li = li->li_next; - if (li == NULL) - return -1; - return (int)tv_get_number(&li->li_tv); -} -#endif - /* * Top level evaluation function. * Returns an allocated typval_T with the result. @@ -1153,7 +857,7 @@ get_lval( if (lp->ll_di == NULL) { // Can't add "v:" or "a:" variable. - if (lp->ll_dict == &vimvardict + if (lp->ll_dict == get_vimvar_dict() || &lp->ll_dict->dv_hashtab == get_funccal_args_ht()) { semsg(_(e_illvar), name); @@ -1921,31 +1625,6 @@ set_context_for_expression( xp->xp_pattern = arg; } -#if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO) -/* - * Delete all "menutrans_" variables. - */ - void -del_menutrans_vars(void) -{ - hashitem_T *hi; - int todo; - - hash_lock(&globvarht); - todo = (int)globvarht.ht_used; - for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi) - { - if (!HASHITEM_EMPTY(hi)) - { - --todo; - if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0) - delete_var(&globvarht, hi); - } - } - hash_unlock(&globvarht); -} -#endif - /* * Return TRUE if "pat" matches "text". * Does not use 'cpo' and always uses 'magic'. @@ -4215,7 +3894,7 @@ garbage_collect(int testing) abort = abort || set_ref_in_item(&tp->tp_winvar.di_tv, copyID, NULL, NULL); /* global variables */ - abort = abort || set_ref_in_ht(&globvarht, copyID, NULL); + abort = abort || garbage_collect_globvars(copyID); /* function-local variables */ abort = abort || set_ref_in_call_stack(copyID); @@ -4630,20 +4309,6 @@ set_ref_in_item( return abort; } - static char * -get_var_special_name(int nr) -{ - switch (nr) - { - case VVAL_FALSE: return "v:false"; - case VVAL_TRUE: return "v:true"; - case VVAL_NONE: return "v:none"; - case VVAL_NULL: return "v:null"; - } - internal_error("get_var_special_name()"); - return "42"; -} - /* * Return a string with the string representation of a variable. * If the memory is allocated "tofree" is set to it, otherwise NULL. @@ -6204,112 +5869,6 @@ item_copy( } /* - * This function is used by f_input() and f_inputdialog() functions. The third - * argument to f_input() specifies the type of completion to use at the - * prompt. The third argument to f_inputdialog() specifies the value to return - * when the user cancels the prompt. - */ - void -get_user_input( - typval_T *argvars, - typval_T *rettv, - int inputdialog, - int secret) -{ - char_u *prompt = tv_get_string_chk(&argvars[0]); - char_u *p = NULL; - int c; - char_u buf[NUMBUFLEN]; - int cmd_silent_save = cmd_silent; - char_u *defstr = (char_u *)""; - int xp_type = EXPAND_NOTHING; - char_u *xp_arg = NULL; - - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; - -#ifdef NO_CONSOLE_INPUT - /* While starting up, there is no place to enter text. When running tests - * with --not-a-term we assume feedkeys() will be used. */ - if (no_console_input() && !is_not_a_term()) - return; -#endif - - cmd_silent = FALSE; /* Want to see the prompt. */ - if (prompt != NULL) - { - /* Only the part of the message after the last NL is considered as - * prompt for the command line */ - p = vim_strrchr(prompt, '\n'); - if (p == NULL) - p = prompt; - else - { - ++p; - c = *p; - *p = NUL; - msg_start(); - msg_clr_eos(); - msg_puts_attr((char *)prompt, echo_attr); - msg_didout = FALSE; - msg_starthere(); - *p = c; - } - cmdline_row = msg_row; - - if (argvars[1].v_type != VAR_UNKNOWN) - { - defstr = tv_get_string_buf_chk(&argvars[1], buf); - if (defstr != NULL) - stuffReadbuffSpec(defstr); - - if (!inputdialog && argvars[2].v_type != VAR_UNKNOWN) - { - char_u *xp_name; - int xp_namelen; - long argt; - - /* input() with a third argument: completion */ - rettv->vval.v_string = NULL; - - xp_name = tv_get_string_buf_chk(&argvars[2], buf); - if (xp_name == NULL) - return; - - xp_namelen = (int)STRLEN(xp_name); - - if (parse_compl_arg(xp_name, xp_namelen, &xp_type, &argt, - &xp_arg) == FAIL) - return; - } - } - - if (defstr != NULL) - { - int save_ex_normal_busy = ex_normal_busy; - - ex_normal_busy = 0; - rettv->vval.v_string = - getcmdline_prompt(secret ? NUL : '@', p, echo_attr, - xp_type, xp_arg); - ex_normal_busy = save_ex_normal_busy; - } - if (inputdialog && rettv->vval.v_string == NULL - && argvars[1].v_type != VAR_UNKNOWN - && argvars[2].v_type != VAR_UNKNOWN) - rettv->vval.v_string = vim_strsave(tv_get_string_buf( - &argvars[2], buf)); - - vim_free(xp_arg); - - /* since the user typed this, no need to wait for return */ - need_wait_return = FALSE; - msg_didout = FALSE; - } - cmd_silent = cmd_silent_save; -} - -/* * ":echo expr1 ..." print each argument separated with a space, add a * newline at the end. * ":echon expr1 ..." print each argument plain. @@ -6425,6 +5984,15 @@ ex_echohl(exarg_T *eap) } /* + * Returns the :echo attribute + */ + int +get_echo_attr(void) +{ + return echo_attr; +} + +/* * ":execute expr1 ..." execute the result of an expression. * ":echomsg expr1 ..." Print a message * ":echoerr expr1 ..." Print an error @@ -6551,78 +6119,6 @@ find_option_end(char_u **arg, int *opt_flags) } /* - * Return the autoload script name for a function or variable name. - * Returns NULL when out of memory. - * Caller must make sure that "name" contains AUTOLOAD_CHAR. - */ - char_u * -autoload_name(char_u *name) -{ - char_u *p, *q = NULL; - char_u *scriptname; - - // Get the script file name: replace '#' with '/', append ".vim". - scriptname = alloc(STRLEN(name) + 14); - if (scriptname == NULL) - return NULL; - STRCPY(scriptname, "autoload/"); - STRCAT(scriptname, name); - for (p = scriptname + 9; (p = vim_strchr(p, AUTOLOAD_CHAR)) != NULL; - q = p, ++p) - *p = '/'; - STRCPY(q, ".vim"); - return scriptname; -} - -/* - * If "name" has a package name try autoloading the script for it. - * Return TRUE if a package was loaded. - */ - int -script_autoload( - char_u *name, - int reload) /* load script again when already loaded */ -{ - char_u *p; - char_u *scriptname, *tofree; - int ret = FALSE; - int i; - - /* If there is no '#' after name[0] there is no package name. */ - p = vim_strchr(name, AUTOLOAD_CHAR); - if (p == NULL || p == name) - return FALSE; - - tofree = scriptname = autoload_name(name); - if (scriptname == NULL) - return FALSE; - - /* Find the name in the list of previously loaded package names. Skip - * "autoload/", it's always the same. */ - for (i = 0; i < ga_loaded.ga_len; ++i) - if (STRCMP(((char_u **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0) - break; - if (!reload && i < ga_loaded.ga_len) - ret = FALSE; /* was loaded already */ - else - { - /* Remember the name if it wasn't loaded already. */ - if (i == ga_loaded.ga_len && ga_grow(&ga_loaded, 1) == OK) - { - ((char_u **)ga_loaded.ga_data)[ga_loaded.ga_len++] = scriptname; - tofree = NULL; - } - - /* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */ - if (source_runtime(scriptname, 0) == OK) - ret = TRUE; - } - - vim_free(tofree); - return ret; -} - -/* * Display script name where an item was last set. * Should only be invoked when 'verbose' is non-zero. */ @@ -7739,6 +7235,8 @@ filter_map(typval_T *argvars, typval_T *rettv, int map) prepare_vimvar(VV_KEY, &save_key); if (argvars[0].v_type == VAR_DICT) { + set_vim_var_type(VV_KEY, VAR_STRING); + ht = &d->dv_hashtab; hash_lock(ht); todo = (int)ht->ht_used; |