diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/config.mk.in | 3 | ||||
-rw-r--r-- | src/digraph.c | 7 | ||||
-rw-r--r-- | src/eval.c | 1005 | ||||
-rw-r--r-- | src/ex_cmds.c | 13 | ||||
-rw-r--r-- | src/ex_cmds.h | 12 | ||||
-rw-r--r-- | src/ex_cmds2.c | 23 | ||||
-rw-r--r-- | src/farsi.c | 4 | ||||
-rw-r--r-- | src/fold.c | 2 | ||||
-rw-r--r-- | src/gui_gtk_x11.c | 5 | ||||
-rw-r--r-- | src/main.c | 10 | ||||
-rw-r--r-- | src/memfile.c | 4 | ||||
-rw-r--r-- | src/memline.c | 8 | ||||
-rw-r--r-- | src/menu.c | 8 | ||||
-rw-r--r-- | src/misc1.c | 8 | ||||
-rw-r--r-- | src/nbdebug.h | 2 | ||||
-rw-r--r-- | src/os_amiga.c | 4 | ||||
-rw-r--r-- | src/os_win16.c | 1 | ||||
-rw-r--r-- | src/os_win16.h | 1 | ||||
-rw-r--r-- | src/po/ca.po | 2362 | ||||
-rw-r--r-- | src/po/fi.po | 6216 | ||||
-rw-r--r-- | src/po/ga.po | 1756 | ||||
-rw-r--r-- | src/po/it.po | 212 | ||||
-rw-r--r-- | src/po/ru.cp1251.po | 16 | ||||
-rw-r--r-- | src/po/ru.po | 16 | ||||
-rw-r--r-- | src/po/sv.po | 8 | ||||
-rw-r--r-- | src/po/uk.po | 5018 | ||||
-rw-r--r-- | src/proto/misc2.pro | 8 | ||||
-rw-r--r-- | src/proto/search.pro | 1 | ||||
-rw-r--r-- | src/pty.c | 4 | ||||
-rw-r--r-- | src/search.c | 61 | ||||
-rw-r--r-- | src/syntax.c | 70 | ||||
-rw-r--r-- | src/testdir/Make_vms.mms | 4 | ||||
-rw-r--r-- | src/testdir/Makefile | 2 | ||||
-rw-r--r-- | src/testdir/test11.in | 12 | ||||
-rw-r--r-- | src/testdir/test3.in | 2 | ||||
-rw-r--r-- | src/testdir/test65.in | 78 |
36 files changed, 13808 insertions, 3158 deletions
diff --git a/src/config.mk.in b/src/config.mk.in index 759559a4e8..9590d445a1 100644 --- a/src/config.mk.in +++ b/src/config.mk.in @@ -109,6 +109,9 @@ exec_prefix = @exec_prefix@ ### Prefix for location of data files BINDIR = @bindir@ +### For autoconf 2.60 and later (avoid a warning) +datarootdir = @datarootdir@ + ### Prefix for location of data files DATADIR = @datadir@ diff --git a/src/digraph.c b/src/digraph.c index 9d04af6197..b867598a62 100644 --- a/src/digraph.c +++ b/src/digraph.c @@ -2538,6 +2538,7 @@ keymap_unload() char_u buf[KMAP_MAXLEN + 10]; int i; char_u *save_cpo = p_cpo; + kmap_T *kp; if (!(curbuf->b_kmap_state & KEYMAP_LOADED)) return; @@ -2546,11 +2547,13 @@ keymap_unload() p_cpo = (char_u *)"C"; /* clear the ":lmap"s */ + kp = (kmap_T *)curbuf->b_kmap_ga.ga_data; for (i = 0; i < curbuf->b_kmap_ga.ga_len; ++i) { - vim_snprintf((char *)buf, sizeof(buf), "<buffer> %s", - ((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].from); + vim_snprintf((char *)buf, sizeof(buf), "<buffer> %s", kp[i].from); (void)do_map(1, buf, LANGMAP, FALSE); + vim_free(kp[i].from); + vim_free(kp[i].to); } p_cpo = save_cpo; diff --git a/src/eval.c b/src/eval.c index 54ca054ca1..fada51d646 100644 --- a/src/eval.c +++ b/src/eval.c @@ -16,6 +16,8 @@ #include "vim.h" +#if defined(FEAT_EVAL) || defined(PROTO) + #ifdef AMIGA # include <time.h> /* for strftime() */ #endif @@ -24,12 +26,10 @@ # include <time.h> /* for time_t */ #endif -#ifdef HAVE_FCNTL_H -# include <fcntl.h> +#if defined(FEAT_FLOAT) && defined(HAVE_MATH_H) +# include <math.h> #endif -#if defined(FEAT_EVAL) || defined(PROTO) - #define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */ /* @@ -108,6 +108,7 @@ 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_nofunc = N_("E130: Unknown function: %s"); static char *e_illvar = N_("E461: Illegal variable name: %s"); + /* * All user-defined global variables are stored in dictionary "globvardict". * "globvars_var" is the variable that is used for "g:". @@ -164,13 +165,13 @@ struct ufunc int uf_profiling; /* TRUE when func is being profiled */ /* profiling the function as a whole */ int uf_tm_count; /* nr of calls */ - proftime_T uf_tm_total; /* time spend in function + children */ - proftime_T uf_tm_self; /* time spend in function itself */ + proftime_T uf_tm_total; /* time spent in function + children */ + proftime_T uf_tm_self; /* time spent in function itself */ proftime_T uf_tm_children; /* time spent in children this call */ /* profiling the function per line */ int *uf_tml_count; /* nr of times line was executed */ - proftime_T *uf_tml_total; /* time spend in a line + children */ - proftime_T *uf_tml_self; /* time spend in a line itself */ + proftime_T *uf_tml_total; /* time spent in a line + children */ + proftime_T *uf_tml_self; /* time spent in a line itself */ proftime_T uf_tml_start; /* start time for current line */ proftime_T uf_tml_children; /* time spent in children for this line */ proftime_T uf_tml_wait; /* start wait time for current line */ @@ -346,13 +347,15 @@ static struct vimvar {VV_NAME("mouse_lnum", VAR_NUMBER), 0}, {VV_NAME("mouse_col", VAR_NUMBER), 0}, {VV_NAME("operator", VAR_STRING), VV_RO}, + {VV_NAME("searchforward", VAR_NUMBER), 0}, }; /* shorthand */ -#define vv_type vv_di.di_tv.v_type -#define vv_nr vv_di.di_tv.vval.v_number -#define vv_str vv_di.di_tv.vval.v_string -#define vv_tv vv_di.di_tv +#define vv_type vv_di.di_tv.v_type +#define vv_nr vv_di.di_tv.vval.v_number +#define vv_float vv_di.di_tv.vval.v_float +#define vv_str vv_di.di_tv.vval.v_string +#define vv_tv vv_di.di_tv /* * The v: variables are stored in dictionary "vimvardict". @@ -450,6 +453,9 @@ static int get_dict_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static char_u *echo_string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID)); static char_u *tv2string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID)); static char_u *string_quote __ARGS((char_u *str, int function)); +#ifdef FEAT_FLOAT +static int string2float __ARGS((char_u *text, float_T *value)); +#endif static int get_env_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static int find_internal_func __ARGS((char_u *name)); static char_u *deref_func_name __ARGS((char_u *name, int *lenp)); @@ -457,11 +463,17 @@ static int get_func_tv __ARGS((char_u *name, int len, typval_T *rettv, char_u ** static int call_func __ARGS((char_u *name, int len, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict)); static void emsg_funcname __ARGS((char *ermsg, char_u *name)); +#ifdef FEAT_FLOAT +static void f_abs __ARGS((typval_T *argvars, typval_T *rettv)); +#endif static void f_add __ARGS((typval_T *argvars, typval_T *rettv)); static void f_append __ARGS((typval_T *argvars, typval_T *rettv)); static void f_argc __ARGS((typval_T *argvars, typval_T *rettv)); static void f_argidx __ARGS((typval_T *argvars, typval_T *rettv)); static void f_argv __ARGS((typval_T *argvars, typval_T *rettv)); +#ifdef FEAT_FLOAT +static void f_atan __ARGS((typval_T *argvars, typval_T *rettv)); +#endif static void f_browse __ARGS((typval_T *argvars, typval_T *rettv)); static void f_browsedir __ARGS((typval_T *argvars, typval_T *rettv)); static void f_bufexists __ARGS((typval_T *argvars, typval_T *rettv)); @@ -473,6 +485,9 @@ static void f_bufwinnr __ARGS((typval_T *argvars, typval_T *rettv)); static void f_byte2line __ARGS((typval_T *argvars, typval_T *rettv)); static void f_byteidx __ARGS((typval_T *argvars, typval_T *rettv)); static void f_call __ARGS((typval_T *argvars, typval_T *rettv)); +#ifdef FEAT_FLOAT +static void f_ceil __ARGS((typval_T *argvars, typval_T *rettv)); +#endif static void f_changenr __ARGS((typval_T *argvars, typval_T *rettv)); static void f_char2nr __ARGS((typval_T *argvars, typval_T *rettv)); static void f_cindent __ARGS((typval_T *argvars, typval_T *rettv)); @@ -485,6 +500,9 @@ static void f_complete_check __ARGS((typval_T *argvars, typval_T *rettv)); #endif static void f_confirm __ARGS((typval_T *argvars, typval_T *rettv)); static void f_copy __ARGS((typval_T *argvars, typval_T *rettv)); +#ifdef FEAT_FLOAT +static void f_cos __ARGS((typval_T *argvars, typval_T *rettv)); +#endif static void f_count __ARGS((typval_T *argvars, typval_T *rettv)); static void f_cscope_connection __ARGS((typval_T *argvars, typval_T *rettv)); static void f_cursor __ARGS((typval_T *argsvars, typval_T *rettv)); @@ -507,6 +525,10 @@ static void f_filewritable __ARGS((typval_T *argvars, typval_T *rettv)); static void f_filter __ARGS((typval_T *argvars, typval_T *rettv)); static void f_finddir __ARGS((typval_T *argvars, typval_T *rettv)); static void f_findfile __ARGS((typval_T *argvars, typval_T *rettv)); +#ifdef FEAT_FLOAT +static void f_float2nr __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_floor __ARGS((typval_T *argvars, typval_T *rettv)); +#endif static void f_fnameescape __ARGS((typval_T *argvars, typval_T *rettv)); static void f_fnamemodify __ARGS((typval_T *argvars, typval_T *rettv)); static void f_foldclosed __ARGS((typval_T *argvars, typval_T *rettv)); @@ -578,6 +600,9 @@ static void f_line __ARGS((typval_T *argvars, typval_T *rettv)); static void f_line2byte __ARGS((typval_T *argvars, typval_T *rettv)); static void f_lispindent __ARGS((typval_T *argvars, typval_T *rettv)); static void f_localtime __ARGS((typval_T *argvars, typval_T *rettv)); +#ifdef FEAT_FLOAT +static void f_log10 __ARGS((typval_T *argvars, typval_T *rettv)); +#endif static void f_map __ARGS((typval_T *argvars, typval_T *rettv)); static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv)); static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv)); @@ -597,6 +622,9 @@ static void f_mode __ARGS((typval_T *argvars, typval_T *rettv)); static void f_nextnonblank __ARGS((typval_T *argvars, typval_T *rettv)); static void f_nr2char __ARGS((typval_T *argvars, typval_T *rettv)); static void f_pathshorten __ARGS((typval_T *argvars, typval_T *rettv)); +#ifdef FEAT_FLOAT +static void f_pow __ARGS((typval_T *argvars, typval_T *rettv)); +#endif static void f_prevnonblank __ARGS((typval_T *argvars, typval_T *rettv)); static void f_printf __ARGS((typval_T *argvars, typval_T *rettv)); static void f_pumvisible __ARGS((typval_T *argvars, typval_T *rettv)); @@ -614,6 +642,9 @@ static void f_rename __ARGS((typval_T *argvars, typval_T *rettv)); static void f_repeat __ARGS((typval_T *argvars, typval_T *rettv)); static void f_resolve __ARGS((typval_T *argvars, typval_T *rettv)); static void f_reverse __ARGS((typval_T *argvars, typval_T *rettv)); +#ifdef FEAT_FLOAT +static void f_round __ARGS((typval_T *argvars, typval_T *rettv)); +#endif static void f_search __ARGS((typval_T *argvars, typval_T *rettv)); static void f_searchdecl __ARGS((typval_T *argvars, typval_T *rettv)); static void f_searchpair __ARGS((typval_T *argvars, typval_T *rettv)); @@ -633,11 +664,18 @@ static void f_settabwinvar __ARGS((typval_T *argvars, typval_T *rettv)); static void f_setwinvar __ARGS((typval_T *argvars, typval_T *rettv)); static void f_shellescape __ARGS((typval_T *argvars, typval_T *rettv)); static void f_simplify __ARGS((typval_T *argvars, typval_T *rettv)); +#ifdef FEAT_FLOAT +static void f_sin __ARGS((typval_T *argvars, typval_T *rettv)); +#endif static void f_sort __ARGS((typval_T *argvars, typval_T *rettv)); static void f_soundfold __ARGS((typval_T *argvars, typval_T *rettv)); static void f_spellbadword __ARGS((typval_T *argvars, typval_T *rettv)); static void f_spellsuggest __ARGS((typval_T *argvars, typval_T *rettv)); static void f_split __ARGS((typval_T *argvars, typval_T *rettv)); +#ifdef FEAT_FLOAT +static void f_sqrt __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_str2float __ARGS((typval_T *argvars, typval_T *rettv)); +#endif static void f_str2nr __ARGS((typval_T *argvars, typval_T *rettv)); #ifdef HAVE_STRFTIME static void f_strftime __ARGS((typval_T *argvars, typval_T *rettv)); @@ -665,6 +703,9 @@ static void f_test __ARGS((typval_T *argvars, typval_T *rettv)); static void f_tolower __ARGS((typval_T *argvars, typval_T *rettv)); static void f_toupper __ARGS((typval_T *argvars, typval_T *rettv)); static void f_tr __ARGS((typval_T *argvars, typval_T *rettv)); +#ifdef FEAT_FLOAT +static void f_trunc __ARGS((typval_T *argvars, typval_T *rettv)); +#endif static void f_type __ARGS((typval_T *argvars, typval_T *rettv)); static void f_values __ARGS((typval_T *argvars, typval_T *rettv)); static void f_virtcol __ARGS((typval_T *argvars, typval_T *rettv)); @@ -788,6 +829,7 @@ eval_init() /* add to compat scope dict */ hash_add(&compat_hashtab, p->vv_di.di_key); } + set_vim_var_nr(VV_SEARCHFORWARD, 1L); } #if defined(EXITFREE) || defined(PROTO) @@ -818,15 +860,15 @@ eval_clear() /* global variables */ vars_clear(&globvarht); - /* functions */ - free_all_functions(); - hash_clear(&func_hashtab); - /* autoloaded script names */ ga_clear_strings(&ga_loaded); /* unreferenced lists and dicts */ (void)garbage_collect(); + + /* functions */ + free_all_functions(); + hash_clear(&func_hashtab); } #endif @@ -1422,7 +1464,8 @@ eval_expr(arg, nextcmd) || defined(FEAT_COMPL_FUNC) || defined(PROTO) /* * Call some vimL function and return the result in "*rettv". - * Uses argv[argc] for the function arguments. + * Uses argv[argc] for the function arguments. Only Number and String + * arguments are currently supported. * Returns OK or FAIL. */ static int @@ -2849,16 +2892,36 @@ tv_op(tv1, tv2, op) { /* nr += nr or nr -= nr*/ n = get_tv_number(tv1); - if (*op == '+') - n += get_tv_number(tv2); +#ifdef FEAT_FLOAT + if (tv2->v_type == VAR_FLOAT) + { + float_T f = n; + + if (*op == '+') + f += tv2->vval.v_float; + else + f -= tv2->vval.v_float; + clear_tv(tv1); + tv1->v_type = VAR_FLOAT; + tv1->vval.v_float = f; + } else - n -= get_tv_number(tv2); - clear_tv(tv1); - tv1->v_type = VAR_NUMBER; - tv1->vval.v_number = n; +#endif + { + if (*op == '+') + n += get_tv_number(tv2); + else + n -= get_tv_number(tv2); + clear_tv(tv1); + tv1->v_type = VAR_NUMBER; + tv1->vval.v_number = n; + } } else { + if (tv2->v_type == VAR_FLOAT) + break; + /* str .= str */ s = get_tv_string(tv1); s = concat_str(s, get_tv_string_buf(tv2, numbuf)); @@ -2867,6 +2930,27 @@ tv_op(tv1, tv2, op) tv1->vval.v_string = s; } return OK; + +#ifdef FEAT_FLOAT + case VAR_FLOAT: + { + float_T f; + + if (*op == '.' || (tv2->v_type != VAR_FLOAT + && tv2->v_type != VAR_NUMBER + && tv2->v_type != VAR_STRING)) + break; + if (tv2->v_type == VAR_FLOAT) + f = tv2->vval.v_float; + else + f = get_tv_number(tv2); + if (*op == '+') + tv1->vval.v_float += f; + else + tv1->vval.v_float -= f; + } + return OK; +#endif } } @@ -4115,7 +4199,7 @@ eval4(arg, rettv, evaluate) } /* - * If there is a comparitive operator, use it. + * If there is a comparative operator, use it. */ if (type != TYPE_UNKNOWN) { @@ -4131,7 +4215,7 @@ eval4(arg, rettv, evaluate) ic = FALSE; ++len; } - /* nothing appened: use 'ignorecase' */ + /* nothing appended: use 'ignorecase' */ else ic = p_ic; @@ -4238,6 +4322,40 @@ eval4(arg, rettv, evaluate) } } +#ifdef FEAT_FLOAT + /* + * If one of the two variables is a float, compare as a float. + * When using "=~" or "!~", always compare as string. + */ + else if ((rettv->v_type == VAR_FLOAT || var2.v_type == VAR_FLOAT) + && type != TYPE_MATCH && type != TYPE_NOMATCH) + { + float_T f1, f2; + + if (rettv->v_type == VAR_FLOAT) + f1 = rettv->vval.v_float; + else + f1 = get_tv_number(rettv); + if (var2.v_type == VAR_FLOAT) + f2 = var2.vval.v_float; + else + f2 = get_tv_number(&var2); + n1 = FALSE; + switch (type) + { + case TYPE_EQUAL: n1 = (f1 == f2); break; + case TYPE_NEQUAL: n1 = (f1 != f2); break; + case TYPE_GREATER: n1 = (f1 > f2); break; + case TYPE_GEQUAL: n1 = (f1 >= f2); break; + case TYPE_SMALLER: n1 = (f1 < f2); break; + case TYPE_SEQUAL: n1 = (f1 <= f2); break; + case TYPE_UNKNOWN: + case TYPE_MATCH: + case TYPE_NOMATCH: break; /* avoid gcc warning */ + } + } +#endif + /* * If one of the two variables is a number, compare as a number. * When using "=~" or "!~", always compare as string. @@ -4330,6 +4448,9 @@ eval5(arg, rettv, evaluate) typval_T var3; int op; long n1, n2; +#ifdef FEAT_FLOAT + float_T f1 = 0, f2 = 0; +#endif char_u *s1, *s2; char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; char_u *p; @@ -4349,7 +4470,11 @@ eval5(arg, rettv, evaluate) if (op != '+' && op != '-' && op != '.') break; - if (op != '+' || rettv->v_type != VAR_LIST) + if ((op != '+' || rettv->v_type != VAR_LIST) +#ifdef FEAT_FLOAT + && (op == '.' || rettv->v_type != VAR_FLOAT) +#endif + ) { /* For "list + ...", an illegal use of the first operand as * a number cannot be determined before evaluating the 2nd @@ -4413,29 +4538,73 @@ eval5(arg, rettv, evaluate) { int error = FALSE; - n1 = get_tv_number_chk(rettv, &error); - if (error) +#ifdef FEAT_FLOAT + if (rettv->v_type == VAR_FLOAT) { - /* 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; + f1 = rettv->vval.v_float; + n1 = 0; } - n2 = get_tv_number_chk(&var2, &error); - if (error) + else +#endif { - clear_tv(rettv); - clear_tv(&var2); - return FAIL; + 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; + } +#ifdef FEAT_FLOAT + if (var2.v_type == VAR_FLOAT) + f1 = n1; +#endif + } +#ifdef FEAT_FLOAT + if (var2.v_type == VAR_FLOAT) + { + f2 = var2.vval.v_float; + n2 = 0; + } + else +#endif + { + n2 = get_tv_number_chk(&var2, &error); + if (error) + { + clear_tv(rettv); + clear_tv(&var2); + return FAIL; + } +#ifdef FEAT_FLOAT + if (rettv->v_type == VAR_FLOAT) + f2 = n2; +#endif } clear_tv(rettv); - if (op == '+') - n1 = n1 + n2; + +#ifdef FEAT_FLOAT + /* If there is a float on either side the result is a float. */ + if (rettv->v_type == VAR_FLOAT || var2.v_type == VAR_FLOAT) + { + if (op == '+') + f1 = f1 + f2; + else + f1 = f1 - f2; + rettv->v_type = VAR_FLOAT; + rettv->vval.v_float = f1; + } else - n1 = n1 - n2; - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = n1; +#endif + { + if (op == '+') + n1 = n1 + n2; + else + n1 = n1 - n2; + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = n1; + } } clear_tv(&var2); } @@ -4463,6 +4632,10 @@ eval6(arg, rettv, evaluate) typval_T var2; int op; long n1, n2; +#ifdef FEAT_FLOAT + int use_float = FALSE; + float_T f1 = 0, f2; +#endif int error = FALSE; /* @@ -4482,7 +4655,16 @@ eval6(arg, rettv, evaluate) if (evaluate) { - n1 = get_tv_number_chk(rettv, &error); +#ifdef FEAT_FLOAT + if (rettv->v_type == VAR_FLOAT) + { + f1 = rettv->vval.v_float; + use_float = TRUE; + n1 = 0; + } + else +#endif + n1 = get_tv_number_chk(rettv, &error); clear_tv(rettv); if (error) return FAIL; @@ -4499,32 +4681,82 @@ eval6(arg, rettv, evaluate) if (evaluate) { - n2 = get_tv_number_chk(&var2, &error); - clear_tv(&var2); - if (error) - return FAIL; +#ifdef FEAT_FLOAT + if (var2.v_type == VAR_FLOAT) + { + if (!use_float) + { + f1 = n1; + use_float = TRUE; + } + f2 = var2.vval.v_float; + n2 = 0; + } + else +#endif + { + n2 = get_tv_number_chk(&var2, &error); + clear_tv(&var2); + if (error) + return FAIL; +#ifdef FEAT_FLOAT + if (use_float) + f2 = n2; +#endif + } /* * Compute the result. + * When either side is a float the result is a float. */ - if (op == '*') - n1 = n1 * n2; - else if (op == '/') +#ifdef FEAT_FLOAT + if (use_float) { - if (n2 == 0) /* give an error message? */ - n1 = 0x7fffffffL; + if (op == '*') + f1 = f1 * f2; + else if (op == '/') + { + /* We rely on the floating point library to handle divide + * by zero to result in "inf" and not a crash. */ + f1 = f1 / f2; + } else - n1 = n1 / n2; + { + EMSG(_("E804: Cannot use % with float")); + return FAIL; + } + rettv->v_type = VAR_FLOAT; + rettv->vval.v_float = f1; } else +#endif { - if (n2 == 0) /* give an error message? */ - n1 = 0; + if (op == '*') + n1 = n1 * n2; + else if (op == '/') + { + if (n2 == 0) /* give an error message? */ + { + if (n1 == 0) + n1 = -0x7fffffffL - 1L; /* similar to NaN */ + else if (n1 < 0) + n1 = -0x7fffffffL; + else + n1 = 0x7fffffffL; + } + else + n1 = n1 / n2; + } else - n1 = n1 % n2; + { + if (n2 == 0) /* give an error message? */ + n1 = 0; + else + n1 = n1 % n2; + } + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = n1; } - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = n1; } } @@ -4566,7 +4798,6 @@ eval7(arg, rettv, evaluate) long n; int len; char_u *s; - int val; char_u *start_leader, *end_leader; int ret = OK; char_u *alias; @@ -4600,14 +4831,55 @@ eval7(arg, rettv, evaluate) case '7': case '8': case '9': - vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL); - *arg += len; - if (evaluate) + { +#ifdef FEAT_FLOAT + char_u *p = skipdigits(*arg + 1); + int get_float = FALSE; + + /* We accept a float when the format matches + * "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very + * strict to avoid backwards compatibility problems. */ + if (p[0] == '.' && vim_isdigit(p[1])) { - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = n; + get_float = TRUE; + p = skipdigits(p + 2); + if (*p == 'e' || *p == 'E') + { + ++p; + if (*p == '-' || *p == '+') + ++p; + if (!vim_isdigit(*p)) + get_float = FALSE; + else + p = skipdigits(p + 1); + } + if (ASCII_ISALPHA(*p) || *p == '.') + get_float = FALSE; + } + if (get_float) + { + float_T f; + + *arg += string2float(*arg, &f); + if (evaluate) + { + rettv->v_type = VAR_FLOAT; + rettv->vval.v_float = f; + } + } + else +#endif + { + vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL); + *arg += len; + if (evaluate) + { + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = n; + } } break; + } /* * String constant: "string". @@ -4735,8 +5007,15 @@ eval7(arg, rettv, evaluate) if (ret == OK && evaluate && end_leader > start_leader) { int error = FALSE; + int val = 0; +#ifdef FEAT_FLOAT + float_T f = 0.0; - val = get_tv_number_chk(rettv, &error); + if (rettv->v_type == VAR_FLOAT) + f = rettv->vval.v_float; + else +#endif + val = get_tv_number_chk(rettv, &error); if (error) { clear_tv(rettv); @@ -4748,13 +5027,37 @@ eval7(arg, rettv, evaluate) { --end_leader; if (*end_leader == '!') - val = !val; + { +#ifdef FEAT_FLOAT + if (rettv->v_type == VAR_FLOAT) + f = !f; + else +#endif + val = !val; + } else if (*end_leader == '-') - val = -val; + { +#ifdef FEAT_FLOAT + if (rettv->v_type == VAR_FLOAT) + f = -f; + else +#endif + val = -val; + } + } +#ifdef FEAT_FLOAT + if (rettv->v_type == VAR_FLOAT) + { + clear_tv(rettv); + rettv->vval.v_float = f; + } + else +#endif + { + 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; } } @@ -4781,7 +5084,11 @@ eval_index(arg, rettv, evaluate, verbose) char_u *s; char_u *key = NULL; - if (rettv->v_type == VAR_FUNC) + if (rettv->v_type == VAR_FUNC +#ifdef FEAT_FLOAT + || rettv->v_type == VAR_FLOAT +#endif + ) { if (verbose) EMSG(_("E695: Cannot index a Funcref")); @@ -5567,7 +5874,7 @@ dict_equal(d1, d2, ic) /* * Return TRUE if "tv1" and "tv2" have the same value. * Compares the items just like "==" would compare them, but strings and - * numbers are different. + * numbers are different. Floats and numbers are also different. */ static int tv_equal(tv1, tv2, ic) @@ -5609,6 +5916,11 @@ tv_equal(tv1, tv2, ic) case VAR_NUMBER: return tv1->vval.v_number == tv2->vval.v_number; +#ifdef FEAT_FLOAT + case VAR_FLOAT: + return tv1->vval.v_float == tv2->vval.v_float; +#endif + case VAR_STRING: s1 = get_tv_string_buf(tv1, buf1); s2 = get_tv_string_buf(tv2, buf2); @@ -6898,6 +7210,14 @@ echo_string(tv, tofree, numbuf, copyID) r = get_tv_string_buf(tv, numbuf); break; +#ifdef FEAT_FLOAT + case VAR_FLOAT: + *tofree = NULL; + vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv->vval.v_float); + r = numbuf; + break; +#endif + default: EMSG2(_(e_intern2), "echo_string()"); *tofree = NULL; @@ -6929,6 +7249,12 @@ tv2string(tv, tofree, numbuf, copyID) case VAR_STRING: *tofree = string_quote(tv->vval.v_string, FALSE); return *tofree; +#ifdef FEAT_FLOAT + case VAR_FLOAT: + *tofree = NULL; + vim_snprintf((char *)numbuf, NUMBUFLEN - 1, "%g", tv->vval.v_float); + return numbuf; +#endif case VAR_NUMBER: case VAR_LIST: case VAR_DICT: @@ -6985,6 +7311,27 @@ string_quote(str, function) return s; } +#ifdef FEAT_FLOAT +/* + * Convert the string "text" to a floating point number. + * This uses st |