diff options
author | Bram Moolenaar <Bram@vim.org> | 2005-06-13 22:28:56 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2005-06-13 22:28:56 +0000 |
commit | 9ba0eb850c0f4c94df3b7f7461610bf0b073f712 (patch) | |
tree | 11638af8ad8ecdfd337a6db15914b2e2cdff3aea /src | |
parent | bac97eb8ae6b067466cab0481cac2f25b335ffe7 (diff) |
updated for version 7.0084v7.0084
Diffstat (limited to 'src')
-rw-r--r-- | src/Make_mvc.mak | 15 | ||||
-rw-r--r-- | src/eval.c | 1108 | ||||
-rw-r--r-- | src/ex_cmds.c | 4 | ||||
-rw-r--r-- | src/ex_docmd.c | 1 | ||||
-rw-r--r-- | src/ex_getln.c | 8 | ||||
-rw-r--r-- | src/gui_w32.c | 13 | ||||
-rw-r--r-- | src/gui_w48.c | 23 | ||||
-rw-r--r-- | src/if_cscope.c | 2 | ||||
-rw-r--r-- | src/if_python.c | 38 | ||||
-rw-r--r-- | src/misc1.c | 21 | ||||
-rw-r--r-- | src/misc2.c | 102 | ||||
-rw-r--r-- | src/normal.c | 7 | ||||
-rw-r--r-- | src/option.c | 30 | ||||
-rw-r--r-- | src/os_mswin.c | 18 | ||||
-rw-r--r-- | src/os_w32exe.c | 1 | ||||
-rw-r--r-- | src/os_win32.c | 14 | ||||
-rw-r--r-- | src/proto/misc1.pro | 1 | ||||
-rw-r--r-- | src/proto/misc2.pro | 1 | ||||
-rw-r--r-- | src/proto/spell.pro | 3 | ||||
-rw-r--r-- | src/spell.c | 2291 | ||||
-rw-r--r-- | src/tag.c | 11 | ||||
-rw-r--r-- | src/ui.c | 1 | ||||
-rw-r--r-- | src/version.h | 4 |
23 files changed, 3156 insertions, 561 deletions
diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index 4d4ea225e3..eb5aa7e9e7 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -110,7 +110,8 @@ TARGETOS = BOTH -# Select one of eight object code directories, depends on GUI, OLE and DEBUG. +# Select one of eight object code directories, depends on GUI, OLE, DEBUG and +# interfaces. # If you change something else, do "make clean" first! !if "$(GUI)" == "yes" OBJDIR = .\ObjG @@ -120,6 +121,18 @@ OBJDIR = .\ObjC !if "$(OLE)" == "yes" OBJDIR = $(OBJDIR)O !endif +!ifdef PERL +OBJDIR = $(OBJDIR)L +!endif +!ifdef PYTHON +OBJDIR = $(OBJDIR)Y +!endif +!ifdef TCL +OBJDIR = $(OBJDIR)T +!endif +!ifdef RUBY +OBJDIR = $(OBJDIR)R +!endif !ifdef MZSCHEME OBJDIR = $(OBJDIR)Z !endif diff --git a/src/eval.c b/src/eval.c index aa3935034a..913f8ed0f2 100644 --- a/src/eval.c +++ b/src/eval.c @@ -264,12 +264,11 @@ typedef struct #define VV_RO 2 /* read-only */ #define VV_RO_SBX 4 /* read-only in the sandbox */ -#define VV_NAME(s, t) s, sizeof(s) - 1, {{t}}, {0} +#define VV_NAME(s, t) s, {{t}}, {0} static struct vimvar { char *vv_name; /* name of variable, without v: */ - int vv_len; /* length of name */ dictitem_T vv_di; /* value and name for key */ char vv_filler[16]; /* space for LONGEST name below!!! */ char vv_flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */ @@ -594,9 +593,12 @@ static void free_tv __ARGS((typval_T *varp)); static void clear_tv __ARGS((typval_T *varp)); static void init_tv __ARGS((typval_T *varp)); static long get_tv_number __ARGS((typval_T *varp)); +static long get_tv_number_chk __ARGS((typval_T *varp, int *denote)); static linenr_T get_tv_lnum __ARGS((typval_T *argvars)); static char_u *get_tv_string __ARGS((typval_T *varp)); +static char_u *get_tv_string_chk __ARGS((typval_T *varp)); static char_u *get_tv_string_buf __ARGS((typval_T *varp, char_u *buf)); +static char_u *get_tv_string_buf_chk __ARGS((typval_T *varp, char_u *buf)); static dictitem_T *find_var __ARGS((char_u *name, hashtab_T **htp)); static dictitem_T *find_var_in_ht __ARGS((hashtab_T *ht, char_u *varname, int writing)); static hashtab_T *find_var_ht __ARGS((char_u *name, char_u **varname)); @@ -1023,7 +1025,7 @@ eval_to_bool(arg, error, nextcmd, skip) *error = FALSE; if (!skip) { - retval = (get_tv_number(&tv) != 0); + retval = (get_tv_number_chk(&tv, error) != 0); clear_tv(&tv); } } @@ -1137,7 +1139,7 @@ eval_to_number(expr) retval = -1; else { - retval = get_tv_number(&rettv); + retval = get_tv_number_chk(&rettv, NULL); clear_tv(&rettv); } --emsg_off; @@ -1775,8 +1777,8 @@ ex_let_one(arg, tv, copy, endchars, op) { c1 = name[len]; name[len] = NUL; - p = get_tv_string(tv); - if (op != NULL && *op == '.') + p = get_tv_string_chk(tv); + if (p != NULL && op != NULL && *op == '.') { int mustfree = FALSE; char_u *s = vim_getenv(name, &mustfree); @@ -1789,15 +1791,18 @@ ex_let_one(arg, tv, copy, endchars, op) } } if (p != NULL) + { vim_setenv(name, p); - if (STRICMP(name, "HOME") == 0) - init_homedir(); - else if (didset_vim && STRICMP(name, "VIM") == 0) - didset_vim = FALSE; - else if (didset_vimruntime && STRICMP(name, "VIMRUNTIME") == 0) - didset_vimruntime = FALSE; + if (STRICMP(name, "HOME") == 0) + init_homedir(); + else if (didset_vim && STRICMP(name, "VIM") == 0) + didset_vim = FALSE; + else if (didset_vimruntime + && STRICMP(name, "VIMRUNTIME") == 0) + didset_vimruntime = FALSE; + arg_end = arg; + } name[len] = c1; - arg_end = arg; vim_free(tofree); } } @@ -1827,8 +1832,8 @@ ex_let_one(arg, tv, copy, endchars, op) *p = NUL; n = get_tv_number(tv); - s = get_tv_string(tv); - if (op != NULL && *op != '=') + s = get_tv_string_chk(tv); /* != NULL if number or string */ + if (s != NULL && op != NULL && *op != '=') { opt_type = get_option_value(arg, &numval, &stringval, opt_flags); @@ -1852,9 +1857,12 @@ ex_let_one(arg, tv, copy, endchars, op) } } } - set_option_value(arg, n, s, opt_flags); + if (s != NULL) + { + set_option_value(arg, n, s, opt_flags); + arg_end = p; + } *p = c1; - arg_end = p; vim_free(stringval); } } @@ -1875,8 +1883,8 @@ ex_let_one(arg, tv, copy, endchars, op) char_u *tofree = NULL; char_u *s; - p = get_tv_string(tv); - if (op != NULL && *op == '.') + p = get_tv_string_chk(tv); + if (p != NULL && op != NULL && *op == '.') { s = get_reg_contents(*arg == '@' ? '"' : *arg, FALSE, FALSE); if (s != NULL) @@ -1886,8 +1894,10 @@ ex_let_one(arg, tv, copy, endchars, op) } } if (p != NULL) + { write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE); - arg_end = arg + 1; + arg_end = arg + 1; + } vim_free(tofree); } } @@ -2070,6 +2080,12 @@ get_lval(name, rettv, lp, unlet, skip, quiet, fne_flags) empty1 = FALSE; if (eval1(&p, &var1, TRUE) == FAIL) /* recursive! */ return NULL; + if (get_tv_string_chk(&var1) == NULL) + { + /* not a number or string */ + clear_tv(&var1); + return NULL; + } } /* Optionally get the second index [ :expr]. */ @@ -2104,6 +2120,14 @@ get_lval(name, rettv, lp, unlet, skip, quiet, fne_flags) clear_tv(&var1); return NULL; } + if (get_tv_string_chk(&var2) == NULL) + { + /* not a number or string */ + if (!empty1) + clear_tv(&var1); + clear_tv(&var2); + return NULL; + } } lp->ll_range = TRUE; } @@ -2130,7 +2154,7 @@ get_lval(name, rettv, lp, unlet, skip, quiet, fne_flags) if (len == -1) { /* "[key]": get key from "var1" */ - key = get_tv_string(&var1); + key = get_tv_string(&var1); /* is number or string */ if (*key == NUL) { if (!quiet) @@ -2176,7 +2200,7 @@ get_lval(name, rettv, lp, unlet, skip, quiet, fne_flags) lp->ll_n1 = 0; else { - lp->ll_n1 = get_tv_number(&var1); + lp->ll_n1 = get_tv_number(&var1); /* is number or string */ clear_tv(&var1); } lp->ll_dict = NULL; @@ -2199,7 +2223,7 @@ get_lval(name, rettv, lp, unlet, skip, quiet, fne_flags) */ if (lp->ll_range && !lp->ll_empty2) { - lp->ll_n2 = get_tv_number(&var2); + lp->ll_n2 = get_tv_number(&var2); /* is number or string */ clear_tv(&var2); if (lp->ll_n2 < 0) { @@ -3340,9 +3364,13 @@ eval1(arg, rettv, evaluate) result = FALSE; if (evaluate) { - if (get_tv_number(rettv) != 0) + int error = FALSE; + + if (get_tv_number_chk(rettv, &error) != 0) result = TRUE; clear_tv(rettv); + if (error) + return FAIL; } /* @@ -3398,6 +3426,7 @@ eval2(arg, rettv, evaluate) typval_T var2; long result; int first; + int error = FALSE; /* * Get the first variable. @@ -3414,9 +3443,11 @@ eval2(arg, rettv, evaluate) { if (evaluate && first) { - if (get_tv_number(rettv) != 0) + if (get_tv_number_chk(rettv, &error) != 0) result = TRUE; clear_tv(rettv); + if (error) + return FAIL; first = FALSE; } @@ -3432,9 +3463,11 @@ eval2(arg, rettv, evaluate) */ if (evaluate && !result) { - if (get_tv_number(&var2) != 0) + if (get_tv_number_chk(&var2, &error) != 0) result = TRUE; clear_tv(&var2); + if (error) + return FAIL; } if (evaluate) { @@ -3464,6 +3497,7 @@ eval3(arg, rettv, evaluate) typval_T var2; long result; int first; + int error = FALSE; /* * Get the first variable. @@ -3480,9 +3514,11 @@ eval3(arg, rettv, evaluate) { if (evaluate && first) { - if (get_tv_number(rettv) == 0) + if (get_tv_number_chk(rettv, &error) == 0) result = FALSE; clear_tv(rettv); + if (error) + return FAIL; first = FALSE; } @@ -3498,9 +3534,11 @@ eval3(arg, rettv, evaluate) */ if (evaluate && result) { - if (get_tv_number(&var2) == 0) + if (get_tv_number_chk(&var2, &error) == 0) result = FALSE; clear_tv(&var2); + if (error) + return FAIL; } if (evaluate) { @@ -3832,6 +3870,22 @@ eval5(arg, rettv, evaluate) if (op != '+' && op != '-' && op != '.') break; + if (op != '+' || rettv->v_type != VAR_LIST) + { + /* For "list + ...", an illegal use of the first operand as + * a number cannot be determined before evaluating the 2nd + * operand: if this is also a list, all is ok. + * For "something . ...", "something - ..." or "non-list + ...", + * we know that the first operand needs to be a string or number + * without evaluating the 2nd operand. So check before to avoid + * side effects after an error. */ + if (evaluate && get_tv_string_chk(rettv) == NULL) + { + clear_tv(rettv); + return FAIL; + } + } + /* * Get the second variable. */ @@ -3849,8 +3903,14 @@ eval5(arg, rettv, evaluate) */ if (op == '.') { - s1 = get_tv_string_buf(rettv, buf1); - s2 = get_tv_string_buf(&var2, buf2); + s1 = get_tv_string_buf(rettv, buf1); /* already checked */ + s2 = get_tv_string_buf_chk(&var2, buf2); + if (s2 == NULL) /* type error ? */ + { + clear_tv(rettv); + clear_tv(&var2); + return FAIL; + } p = concat_str(s1, s2); clear_tv(rettv); rettv->v_type = VAR_STRING; @@ -3872,8 +3932,24 @@ eval5(arg, rettv, evaluate) } else { - n1 = get_tv_number(rettv); - n2 = get_tv_number(&var2); + int error = FALSE; + + n1 = get_tv_number_chk(rettv, &error); + if (error) + { + /* This can only happen for "list + non-list". + * For "non-list + ..." or "something - ...", we returned + * before evaluating the 2nd operand. */ + clear_tv(rettv); + return FAIL; + } + n2 = get_tv_number_chk(&var2, &error); + if (error) + { + clear_tv(rettv); + clear_tv(&var2); + return FAIL; + } clear_tv(rettv); if (op == '+') n1 = n1 + n2; @@ -3908,6 +3984,7 @@ eval6(arg, rettv, evaluate) typval_T var2; int op; long n1, n2; + int error = FALSE; /* * Get the first variable. @@ -3926,8 +4003,10 @@ eval6(arg, rettv, evaluate) if (evaluate) { - n1 = get_tv_number(rettv); + n1 = get_tv_number_chk(rettv, &error); clear_tv(rettv); + if (error) + return FAIL; } else n1 = 0; @@ -3941,8 +4020,10 @@ eval6(arg, rettv, evaluate) if (evaluate) { - n2 = get_tv_number(&var2); + n2 = get_tv_number_chk(&var2, &error); clear_tv(&var2); + if (error) + return FAIL; /* * Compute the result. @@ -4175,18 +4256,28 @@ eval7(arg, rettv, evaluate) */ if (ret == OK && evaluate && end_leader > start_leader) { - val = get_tv_number(rettv); - while (end_leader > start_leader) + int error = FALSE; + + val = get_tv_number_chk(rettv, &error); + if (error) { - --end_leader; - if (*end_leader == '!') - val = !val; - else if (*end_leader == '-') - val = -val; + clear_tv(rettv); + ret = FAIL; + } + else + { + while (end_leader > start_leader) + { + --end_leader; + if (*end_leader == '!') + val = !val; + else if (*end_leader == '-') + val = -val; + } + clear_tv(rettv); + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = val; } - clear_tv(rettv); - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = val; } return ret; @@ -4243,6 +4334,12 @@ eval_index(arg, rettv, evaluate, verbose) empty1 = TRUE; else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */ return FAIL; + else if (evaluate && get_tv_string_chk(&var1) == NULL) + { + /* not a number or string */ + clear_tv(&var1); + return FAIL; + } /* * Get the second variable from inside the [:]. @@ -4255,7 +4352,16 @@ eval_index(arg, rettv, evaluate, verbose) empty2 = TRUE; else if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */ { - clear_tv(&var1); + if (!empty1) + clear_tv(&var1); + return FAIL; + } + else if (evaluate && get_tv_string_chk(&var2) == NULL) + { + /* not a number or string */ + if (!empty1) + clear_tv(&var1); + clear_tv(&var2); return FAIL; } } @@ -4928,6 +5034,7 @@ tv_equal(tv1, tv2, ic) int ic; /* ignore case */ { char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; + char_u *s1, *s2; if (tv1->v_type == VAR_LIST || tv2->v_type == VAR_LIST) { @@ -4963,12 +5070,13 @@ tv_equal(tv1, tv2, ic) if (get_tv_number(tv1) != get_tv_number(tv2)) return FALSE; } - else if (!ic && STRCMP(get_tv_string_buf(tv1, buf1), - get_tv_string_buf(tv2, buf2)) != 0) - return FALSE; - else if (ic && STRICMP(get_tv_string_buf(tv1, buf1), - get_tv_string_buf(tv2, buf2)) != 0) - return FALSE; + else + { + s1 = get_tv_string_buf(tv1, buf1); + s2 = get_tv_string_buf(tv2, buf2); + if ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) != 0) + return FALSE; + } return TRUE; } @@ -5828,10 +5936,12 @@ get_dict_tv(arg, rettv, evaluate) clear_tv(&tvkey); goto failret; } - key = get_tv_string_buf(&tvkey, buf); - if (*key == NUL) + key = get_tv_string_buf_chk(&tvkey, buf); + if (key == NULL || *key == NUL) { - EMSG(_(e_emptykey)); + /* "key" is NULL when get_tv_string_buf_chk() gave an errmsg */ + if (key != NULL) + EMSG(_(e_emptykey)); clear_tv(&tvkey); goto failret; } @@ -6731,12 +6841,12 @@ f_append(argvars, rettv) typval_T *rettv; { long lnum; + char_u *line; list_T *l = NULL; listitem_T *li = NULL; typval_T *tv; long added = 0; - rettv->vval.v_number = 1; /* Default: Failed */ lnum = get_tv_lnum(argvars); if (lnum >= 0 && lnum <= curbuf->b_ml.ml_line_count @@ -6749,6 +6859,7 @@ f_append(argvars, rettv) return; li = l->lv_first; } + rettv->vval.v_number = 0; /* Default: Success */ for (;;) { if (l == NULL) @@ -6757,7 +6868,13 @@ f_append(argvars, rettv) break; /* end of list */ else tv = &li->li_tv; /* append item from list */ - ml_append(lnum + added, get_tv_string(tv), (colnr_T)0, FALSE); + line = get_tv_string_chk(tv); + if (line == NULL) /* type error */ + { + rettv->vval.v_number = 1; /* Failed */ + break; + } + ml_append(lnum + added, line, (colnr_T)0, FALSE); ++added; if (l == NULL) break; @@ -6767,8 +6884,9 @@ f_append(argvars, rettv) appended_lines_mark(lnum, added); if (curwin->w_cursor.lnum > lnum) curwin->w_cursor.lnum += added; - rettv->vval.v_number = 0; /* Success */ } + else + rettv->vval.v_number = 1; /* Failed */ } /* @@ -6805,7 +6923,7 @@ f_argv(argvars, rettv) { int idx; - idx = get_tv_number(&argvars[0]); + idx = get_tv_number_chk(&argvars[0], NULL); if (idx >= 0 && idx < ARGCOUNT) rettv->vval.v_string = vim_strsave(alist_name(&ARGLIST[idx])); else @@ -6829,13 +6947,17 @@ f_browse(argvars, rettv) char_u *defname; char_u buf[NUMBUFLEN]; char_u buf2[NUMBUFLEN]; + int error = FALSE; - save = get_tv_number(&argvars[0]); - title = get_tv_string(&argvars[1]); - initdir = get_tv_string_buf(&argvars[2], buf); - defname = get_tv_string_buf(&argvars[3], buf2); + save = get_tv_number_chk(&argvars[0], &error); + title = get_tv_string_chk(&argvars[1]); + initdir = get_tv_string_buf_chk(&argvars[2], buf); + defname = get_tv_string_buf_chk(&argvars[3], buf2); - rettv->vval.v_string = + if (error || title == NULL || initdir == NULL || defname == NULL) + rettv->vval.v_string = NULL; + else + rettv->vval.v_string = do_browse(save ? BROWSE_SAVE : 0, title, defname, NULL, initdir, NULL, curbuf); #else @@ -6858,10 +6980,13 @@ f_browsedir(argvars, rettv) char_u *initdir; char_u buf[NUMBUFLEN]; - title = get_tv_string(&argvars[0]); - initdir = get_tv_string_buf(&argvars[1], buf); + title = get_tv_string_chk(&argvars[0]); + initdir = get_tv_string_buf_chk(&argvars[1], buf); - rettv->vval.v_string = do_browse(BROWSE_DIR, + if (title == NULL || initdir == NULL) + rettv->vval.v_string = NULL; + else + rettv->vval.v_string = do_browse(BROWSE_DIR, title, NULL, NULL, initdir, NULL, curbuf); #else rettv->vval.v_string = NULL; @@ -6994,6 +7119,7 @@ f_bufname(argvars, rettv) { buf_T *buf; + (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ ++emsg_off; buf = get_buf_tv(&argvars[0]); rettv->v_type = VAR_STRING; @@ -7014,6 +7140,7 @@ f_bufnr(argvars, rettv) { buf_T *buf; + (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ ++emsg_off; buf = get_buf_tv(&argvars[0]); if (buf != NULL) @@ -7037,6 +7164,7 @@ f_bufwinnr(argvars, rettv) #endif buf_T *buf; + (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ ++emsg_off; buf = get_buf_tv(&argvars[0]); #ifdef FEAT_WINDOWS @@ -7067,7 +7195,7 @@ f_byte2line(argvars, rettv) #else long boff = 0; - boff = get_tv_number(&argvars[0]) - 1; + boff = get_tv_number(&argvars[0]) - 1; /* boff gets -1 on type error */ if (boff < 0) rettv->vval.v_number = -1; else @@ -7091,10 +7219,10 @@ f_byteidx(argvars, rettv) char_u *str; long idx; - str = get_tv_string(&argvars[0]); - idx = get_tv_number(&argvars[1]); + str = get_tv_string_chk(&argvars[0]); + idx = get_tv_number_chk(&argvars[1], NULL); rettv->vval.v_number = -1; - if (idx < 0) + if (str == NULL || idx < 0) return; #ifdef FEAT_MBYTE @@ -7140,6 +7268,8 @@ f_call(argvars, rettv) func = argvars[0].vval.v_string; else func = get_tv_string(&argvars[0]); + if (*func == NUL) + return; /* type error or empty name */ if (argvars[2].v_type != VAR_UNKNOWN) { @@ -7185,8 +7315,7 @@ f_char2nr(argvars, rettv) { #ifdef FEAT_MBYTE if (has_mbyte) - rettv->vval.v_number = - (*mb_ptr2char)(get_tv_string(&argvars[0])); + rettv->vval.v_number = (*mb_ptr2char)(get_tv_string(&argvars[0])); else #endif rettv->vval.v_number = get_tv_string(&argvars[0])[0]; @@ -7285,26 +7414,35 @@ f_confirm(argvars, rettv) char_u buf2[NUMBUFLEN]; int def = 1; int type = VIM_GENERIC; - int c; + char_u *typestr; + int error = FALSE; - message = get_tv_string(&argvars[0]); + message = get_tv_string_chk(&argvars[0]); + if (message == NULL) + error = TRUE; if (argvars[1].v_type != VAR_UNKNOWN) { - buttons = get_tv_string_buf(&argvars[1], buf); + buttons = get_tv_string_buf_chk(&argvars[1], buf); + if (buttons == NULL) + error = TRUE; if (argvars[2].v_type != VAR_UNKNOWN) { - def = get_tv_number(&argvars[2]); + def = get_tv_number_chk(&argvars[2], &error); if (argvars[3].v_type != VAR_UNKNOWN) { - /* avoid that TOUPPER_ASC calls get_tv_string_buf() twice */ - c = *get_tv_string_buf(&argvars[3], buf2); - switch (TOUPPER_ASC(c)) + typestr = get_tv_string_buf_chk(&argvars[3], buf2); + if (typestr == NULL) + error = TRUE; + else { - case 'E': type = VIM_ERROR; break; - case 'Q': type = VIM_QUESTION; break; - case 'I': type = VIM_INFO; break; - case 'W': type = VIM_WARNING; break; - case 'G': type = VIM_GENERIC; break; + switch (TOUPPER_ASC(*typestr)) + { + case 'E': type = VIM_ERROR; break; + case 'Q': type = VIM_QUESTION; break; + case 'I': type = VIM_INFO; break; + case 'W': type = VIM_WARNING; break; + case 'G': type = VIM_GENERIC; break; + } } } } @@ -7313,7 +7451,10 @@ f_confirm(argvars, rettv) if (buttons == NULL || *buttons == NUL) buttons = (char_u *)_("&Ok"); - rettv->vval.v_number = do_dialog(type, NULL, message, buttons, + if (error) + rettv->vval.v_number = 0; + else + rettv->vval.v_number = do_dialog(type, NULL, message, buttons, def, NULL); #else rettv->vval.v_number = 0; @@ -7353,14 +7494,21 @@ f_count(argvars, rettv) li = l->lv_first; if (argvars[2].v_type != VAR_UNKNOWN) { - ic = get_tv_number(&argvars[2]); + int error = FALSE; + + ic = get_tv_number_chk(&argvars[2], &error); if (argvars[3].v_type != VAR_UNKNOWN) { - idx = get_tv_number(&argvars[3]); - li = list_find(l, idx); - if (li == NULL) - EMSGN(_(e_listidx), idx); + idx = get_tv_number_chk(&argvars[3], &error); + if (!error) + { + li = list_find(l, idx); + if (li == NULL) + EMSGN(_(e_listidx), idx); + } } + if (error) + li = NULL; } for ( ; li != NULL; li = li->li_next) @@ -7376,14 +7524,16 @@ f_count(argvars, rettv) if ((d = argvars[0].vval.v_dict) != NULL) { + int error = FALSE; + if (argvars[2].v_type != VAR_UNKNOWN) { - ic = get_tv_number(&argvars[2]); + ic = get_tv_number_chk(&argvars[2], &error); if (argvars[3].v_type != VAR_UNKNOWN) EMSG(_(e_invarg)); } - todo = d->dv_hashtab.ht_used; + todo = error ? 0 : d->dv_hashtab.ht_used; for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) { if (!HASHITEM_EMPTY(hi)) @@ -7446,9 +7596,11 @@ f_cursor(argvars, rettv) long line, col; line = get_tv_lnum(argvars); + col = get_tv_number_chk(&argvars[1], NULL); + if (line < 0 || col < 0) + return; /* type error; errmsg already given */ if (line > 0) curwin->w_cursor.lnum = line; - col = get_tv_number(&argvars[1]); if (col > 0) curwin->w_cursor.col = col - 1; #ifdef FEAT_VIRTUALEDIT @@ -7478,7 +7630,7 @@ f_deepcopy(argvars, rettv) int noref = 0; if (argvars[1].v_type != VAR_UNKNOWN) - noref = get_tv_number(&argvars[1]); + noref = get_tv_number_chk(&argvars[1], NULL); if (noref < 0 || noref > 1) EMSG(_(e_invarg)); else @@ -7549,6 +7701,8 @@ f_diff_hlID(argvars, rettv) int filler_lines; int col; + if (lnum < 0) /* ignore type error in {lnum} arg */ + lnum = 0; if (lnum != prev_lnum || changedtick != curbuf->b_changedtick || fnum != curbuf->b_fnum) @@ -7578,7 +7732,7 @@ f_diff_hlID(argvars, rettv) if (hlID == HLF_CHD || hlID == HLF_TXD) { - col = get_tv_number(&argvars[1]) - 1; + col = get_tv_number(&argvars[1]) - 1; /* ignore type error in {col} */ if (col >= change_start && col <= change_end) hlID = HLF_TXD; /* changed text */ else @@ -7650,11 +7804,15 @@ f_eval(argvars, rettv) { char_u *s; - s = get_tv_string(&argvars[0]); - s = skipwhite(s); + s = get_tv_string_chk(&argvars[0]); + if (s != NULL) + s = skipwhite(s); - if (eval1(&s, rettv, TRUE) == FAIL) + if (s == NULL || eval1(&s, rettv, TRUE) == FAIL) + { + rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; + } else if (*s != NUL) EMSG(_(e_trailing)); } @@ -7772,6 +7930,7 @@ f_expand(argvars, rettv) char_u *errormsg; int flags = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND; expand_T xpc; + int error = FALSE; rettv->v_type = VAR_STRING; s = get_tv_string(&argvars[0]); @@ -7785,12 +7944,18 @@ f_expand(argvars, rettv) { /* When the optional second argument is non-zero, don't remove matches * for 'suffixes' and 'wildignore' */ - if (argvars[1].v_type != VAR_UNKNOWN && get_tv_number(&argvars[1])) + if (argvars[1].v_type != VAR_UNKNOWN + && get_tv_number_chk(&argvars[1], &error)) flags |= WILD_KEEP_ALL; - ExpandInit(&xpc); - xpc.xp_context = EXPAND_FILES; - rettv->vval.v_string = ExpandOne(&xpc, s, NULL, flags, WILD_ALL); - ExpandCleanup(&xpc); + if (!error) + { + ExpandInit(&xpc); + xpc.xp_context = EXPAND_FILES; + rettv->vval.v_string = ExpandOne(&xpc, s, NULL, flags, WILD_ALL); + ExpandCleanup(&xpc); + } + else + rettv->vval.v_string = NULL; } } @@ -7809,6 +7974,7 @@ f_extend(argvars, rettv) list_T *l1, *l2; listitem_T *item; long before; + int error = FALSE; l1 = argvars[0].vval.v_list; l2 = argvars[1].vval.v_list; @@ -7817,7 +7983,10 @@ f_extend(argvars, rettv) { if (argvars[2].v_type != VAR_UNKNOWN) { - before = get_tv_number(&argvars[2]); + before = get_tv_number_chk(&argvars[2], &error); + if (error) + return; /* type error; errmsg already given */ + if (before == l1->lv_len) item = NULL; else @@ -7857,7 +8026,9 @@ f_extend(argvars, rettv) { static char *(av[]) = {"keep", "force", "error"}; - action = get_tv_string(&argvars[2]); + action = get_tv_string_chk(&argvars[2]); + if (action == NULL) + return; /* type error; errmsg already given */ for (i = 0; i < 3; ++i) if (STRCMP(action, av[i]) == 0) break; @@ -7963,22 +8134,30 @@ findfilendir(argvars, rettv, dir) if (argvars[1].v_type != VAR_UNKNOWN) { - p = get_tv_string_buf(&argvars[1], pathbuf); - if (*p != NUL) - path = p; + p = get_tv_string_buf_chk(&argvars[1], pathbuf); + if (p == NULL) + count = -1; /* error */ + else + { + if (*p != NUL) + path = p; - if (argvars[2].v_type != VAR_UNKNOWN) - count = get_tv_number(&argvars[2]); + if (argvars[2].v_type != VAR_UNKNOWN) + count = get_tv_number_chk(&argvars[2], NULL); /* -1: error */ + } } - do + if (*fname != NUL && count >= 0) { - vim_free(fresult); - fresult = find_file_in_path_option(first ? fname : NULL, - first ? (int)STRLEN(fname) : 0, - 0, first, path, dir, NULL); - first = FALSE; - } while (--count > 0 && fresult != NULL); + do + { + vim_free(fresult); + fresult = find_file_in_path_option(first ? fname : NULL, + first ? (int)STRLEN(fname) : 0, + 0, first, path, dir, NULL); + first = FALSE; + } while (--count > 0 && fresult != NULL); + } rettv->vval.v_string = fresult; #else @@ -8073,53 +8252,60 @@ filter_map(argvars, rettv, map) return; } - prepare_vimvar(VV_VAL, &save_val); - expr = skipwhite(get_tv_string_buf(&argvars[1], buf)); - - if (argvars[0].v_type == VAR_DICT) + expr = get_tv_string_buf_chk(&argvars[1], buf); + /* On type errors, the preceding call has already displayed an error + * message. Avoid a misleading error message for an empty string that + * was not passed as argument. */ + if (expr != NULL) { - prepare_vimvar(VV_KEY, &save_key); - vimvars[VV_KEY].vv_type = VAR_STRING; + prepare_vimvar(VV_VAL, &save_val); + expr = skipwhite(expr); - ht = &d->dv_hashtab; - hash_lock(ht); - todo = ht->ht_used; - for (hi = ht->ht_array; todo > 0; ++hi) + if (argvars[0].v_type == VAR_DICT) { - if (!HASHITEM_EMPTY(hi)) + prepare_vimvar(VV_KEY, &save_key); + vimvars[VV_KEY].vv_type = VAR_STRING; + + ht = &d->dv_hashtab; + hash_lock(ht); + todo = ht->ht_used; + for (hi = ht->ht_array; todo > 0; ++hi) { - --todo; - di = HI2DI(hi); - if (tv_check_lock(di->di_tv.v_lock, msg)) + if (!HA |