diff options
author | Bram Moolenaar <Bram@vim.org> | 2019-06-15 15:45:06 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2019-06-15 15:45:06 +0200 |
commit | 9937a055437ef67b57a1bdec8f0799b669c9dbf0 (patch) | |
tree | 64fee6ad078086b7714995b03cb7891641d13533 /src/eval.c | |
parent | dfa97f2aed3d8ca195d09e2ce91cef227f933961 (diff) | |
download | vim-git-9937a055437ef67b57a1bdec8f0799b669c9dbf0.tar.gz |
patch 8.1.1539: not easy to define a variable and lock itv8.1.1539
Problem: Not easy to define a variable and lock it.
Solution: Add ":const".
Diffstat (limited to 'src/eval.c')
-rw-r--r-- | src/eval.c | 139 |
1 files changed, 112 insertions, 27 deletions
diff --git a/src/eval.c b/src/eval.c index e2d3d48bd..cdaf103a2 100644 --- a/src/eval.c +++ b/src/eval.c @@ -28,6 +28,7 @@ static char *e_missbrac = N_("E111: Missing ']'"); static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary"); static char *e_letwrong = N_("E734: Wrong variable type for %s="); static char *e_illvar = N_("E461: Illegal variable name: %s"); +static char *e_cannot_mod = N_("E995: Cannot modify existing variable"); #ifdef FEAT_FLOAT static char *e_float_as_string = N_("E806: using Float as a String"); #endif @@ -212,7 +213,8 @@ static struct vimvar static dictitem_T vimvars_var; /* variable used for v: */ #define vimvarht vimvardict.dv_hashtab -static int ex_let_vars(char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, char_u *nextchars); +static void ex_let_const(exarg_T *eap, int is_const); +static int ex_let_vars(char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, int is_const, char_u *nextchars); static char_u *skip_var_list(char_u *arg, int *var_count, int *semicolon); static char_u *skip_var_one(char_u *arg); static void list_glob_vars(int *first); @@ -222,8 +224,8 @@ static void list_tab_vars(int *first); static void list_vim_vars(int *first); static void list_script_vars(int *first); static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first); -static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, char_u *endchars, char_u *op); -static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op); +static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, int is_const, char_u *endchars, char_u *op); +static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, int is_const, char_u *op); static int tv_op(typval_T *tv1, typval_T *tv2, char_u *op); static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep); static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit); @@ -248,6 +250,7 @@ static typval_T *alloc_string_tv(char_u *string); static void delete_var(hashtab_T *ht, hashitem_T *hi); static void list_one_var(dictitem_T *v, char *prefix, int *first); static void list_one_var_a(char *prefix, char_u *name, int type, char_u *string, int *first); +static void set_var_const(char_u *name, typval_T *tv, int copy, int is_const); static int tv_check_lock(typval_T *tv, char_u *name, int use_gettext); static char_u *find_option_end(char_u **arg, int *opt_flags); @@ -526,9 +529,9 @@ var_redir_start(char_u *name, int append) tv.v_type = VAR_STRING; tv.vval.v_string = (char_u *)""; if (append) - set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"."); + set_var_lval(redir_lval, redir_endp, &tv, TRUE, FALSE, (char_u *)"."); else - set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"="); + set_var_lval(redir_lval, redir_endp, &tv, TRUE, FALSE, (char_u *)"="); clear_lval(redir_lval); err = did_emsg; did_emsg |= save_emsg; @@ -601,7 +604,8 @@ var_redir_stop(void) 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, (char_u *)"."); + set_var_lval(redir_lval, redir_endp, &tv, FALSE, FALSE, + (char_u *)"."); clear_lval(redir_lval); } @@ -1338,6 +1342,24 @@ heredoc_get(exarg_T *eap, char_u *cmd) void ex_let(exarg_T *eap) { + ex_let_const(eap, FALSE); +} + +/* + * ":const" list all variable values + * ":const var1 var2" list variable values + * ":const var = expr" assignment command. + * ":const [var1, var2] = expr" unpack list. + */ + void +ex_const(exarg_T *eap) +{ + ex_let_const(eap, TRUE); +} + + static void +ex_let_const(exarg_T *eap, int is_const) +{ char_u *arg = eap->arg; char_u *expr = NULL; typval_T rettv; @@ -1396,7 +1418,7 @@ ex_let(exarg_T *eap) op[0] = '='; op[1] = NUL; (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count, - op); + is_const, op); clear_tv(&rettv); } } @@ -1429,7 +1451,7 @@ ex_let(exarg_T *eap) else if (i != FAIL) { (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count, - op); + is_const, op); clear_tv(&rettv); } } @@ -1447,9 +1469,10 @@ ex_let(exarg_T *eap) ex_let_vars( char_u *arg_start, typval_T *tv, - int copy, /* copy values from "tv", don't move */ - int semicolon, /* from skip_var_list() */ - int var_count, /* from skip_var_list() */ + int copy, // copy values from "tv", don't move + int semicolon, // from skip_var_list() + int var_count, // from skip_var_list() + int is_const, // lock variables for const char_u *nextchars) { char_u *arg = arg_start; @@ -1463,7 +1486,7 @@ ex_let_vars( /* * ":let var = expr" or ":for var in list" */ - if (ex_let_one(arg, tv, copy, nextchars, nextchars) == NULL) + if (ex_let_one(arg, tv, copy, is_const, nextchars, nextchars) == NULL) return FAIL; return OK; } @@ -1493,7 +1516,8 @@ ex_let_vars( while (*arg != ']') { arg = skipwhite(arg + 1); - arg = ex_let_one(arg, &item->li_tv, TRUE, (char_u *)",;]", nextchars); + arg = ex_let_one(arg, &item->li_tv, TRUE, is_const, + (char_u *)",;]", nextchars); item = item->li_next; if (arg == NULL) return FAIL; @@ -1517,8 +1541,8 @@ ex_let_vars( ltv.vval.v_list = l; l->lv_refcount = 1; - arg = ex_let_one(skipwhite(arg + 1), <v, FALSE, - (char_u *)"]", nextchars); + arg = ex_let_one(skipwhite(arg + 1), <v, FALSE, is_const, + (char_u *)"]", nextchars); clear_tv(<v); if (arg == NULL) return FAIL; @@ -1805,11 +1829,12 @@ list_arg_vars(exarg_T *eap, char_u *arg, int *first) */ static char_u * ex_let_one( - char_u *arg, /* points to variable name */ - typval_T *tv, /* value to assign to variable */ - int copy, /* copy value from "tv" */ - char_u *endchars, /* valid chars after variable name or NULL */ - char_u *op) /* "+", "-", "." or NULL*/ + char_u *arg, // points to variable name + typval_T *tv, // value to assign to variable + int copy, // copy value from "tv" + int is_const, // lock variable for const + char_u *endchars, // valid chars after variable name or NULL + char_u *op) // "+", "-", "." or NULL { int c1; char_u *name; @@ -1824,6 +1849,11 @@ ex_let_one( */ if (*arg == '$') { + if (is_const) + { + emsg(_("E996: Cannot lock an environment variable")); + return NULL; + } /* Find the end of the name. */ ++arg; name = arg; @@ -1879,6 +1909,11 @@ ex_let_one( */ else if (*arg == '&') { + if (is_const) + { + emsg(_("E996: Cannot lock an option")); + return NULL; + } /* Find the end of the name. */ p = find_option_end(&arg, &opt_flags); if (p == NULL || (endchars != NULL @@ -1943,6 +1978,11 @@ ex_let_one( */ else if (*arg == '@') { + if (is_const) + { + emsg(_("E996: Cannot lock a register")); + return NULL; + } ++arg; if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL) semsg(_(e_letwrong), op); @@ -1988,7 +2028,7 @@ ex_let_one( emsg(_(e_letunexp)); else { - set_var_lval(&lv, p, tv, copy, op); + set_var_lval(&lv, p, tv, copy, is_const, op); arg_end = p; } } @@ -2430,6 +2470,7 @@ set_var_lval( char_u *endp, typval_T *rettv, int copy, + int is_const, // Disallow to modify existing variable for :const char_u *op) { int cc; @@ -2495,6 +2536,13 @@ set_var_lval( { typval_T tv; + if (is_const) + { + emsg(_(e_cannot_mod)); + *endp = cc; + return; + } + // handle +=, -=, *=, /=, %= and .= di = NULL; if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name), @@ -2509,7 +2557,7 @@ set_var_lval( } } else - set_var(lp->ll_name, rettv, copy); + set_var_const(lp->ll_name, rettv, copy, is_const); *endp = cc; } else if (var_check_lock(lp->ll_newkey == NULL @@ -2521,6 +2569,12 @@ set_var_lval( listitem_T *ll_li = lp->ll_li; int ll_n1 = lp->ll_n1; + if (is_const) + { + emsg(_("E996: Cannot lock a range")); + return; + } + /* * Check whether any of the list items is locked */ @@ -2574,6 +2628,11 @@ set_var_lval( /* * Assign to a List or Dictionary item. */ + if (is_const) + { + emsg(_("E996: Cannot lock a list or dict")); + return; + } if (lp->ll_newkey != NULL) { if (op != NULL && *op != '=') @@ -2860,8 +2919,8 @@ next_for_item(void *fi_void, char_u *arg) tv.v_lock = VAR_FIXED; tv.vval.v_number = blob_get(fi->fi_blob, fi->fi_bi); ++fi->fi_bi; - return ex_let_vars(arg, &tv, TRUE, - fi->fi_semicolon, fi->fi_varcount, NULL) == OK; + return ex_let_vars(arg, &tv, TRUE, fi->fi_semicolon, + fi->fi_varcount, FALSE, NULL) == OK; } item = fi->fi_lw.lw_item; @@ -2870,8 +2929,8 @@ next_for_item(void *fi_void, char_u *arg) else { fi->fi_lw.lw_item = item->li_next; - result = (ex_let_vars(arg, &item->li_tv, TRUE, - fi->fi_semicolon, fi->fi_varcount, NULL) == OK); + result = (ex_let_vars(arg, &item->li_tv, TRUE, fi->fi_semicolon, + fi->fi_varcount, FALSE, NULL) == OK); } return result; } @@ -8051,7 +8110,22 @@ list_one_var_a( set_var( char_u *name, typval_T *tv, - int copy) /* make copy of value in "tv" */ + int copy) // make copy of value in "tv" +{ + set_var_const(name, tv, copy, FALSE); +} + +/* + * Set variable "name" to value in "tv". + * If the variable already exists and "is_const" is FALSE the value is updated. + * Otherwise the variable is created. + */ + static void +set_var_const( + char_u *name, + typval_T *tv, + int copy, // make copy of value in "tv" + int is_const) // disallow to modify existing variable { dictitem_T *v; char_u *varname; @@ -8075,6 +8149,12 @@ set_var( if (v != NULL) { + if (is_const) + { + emsg(_(e_cannot_mod)); + return; + } + /* existing variable, need to clear the value */ if (var_check_ro(v->di_flags, name, FALSE) || var_check_lock(v->di_tv.v_lock, name, FALSE)) @@ -8152,6 +8232,8 @@ set_var( return; } v->di_flags = DI_FLAGS_ALLOC; + if (is_const) + v->di_flags |= DI_FLAGS_LOCK; } if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT) @@ -8162,6 +8244,9 @@ set_var( v->di_tv.v_lock = 0; init_tv(tv); } + + if (is_const) + v->di_tv.v_lock |= VAR_LOCKED; } /* |