Merge pull request #5621 from jamessan/vim-7.4.1975

vim-patch:7.4.1975,7.4.1976,7.4.1977,7.4.1978,7.4.1979,7.4.1986,7.4.2029,7.4.2224,8.0.0219,8.0.0614
This commit is contained in:
James McCoy 2017-06-07 14:05:46 +00:00 committed by GitHub
commit d3d0c9a7b1
32 changed files with 564 additions and 245 deletions

View File

@ -22,6 +22,8 @@ done, the features in this document are not available. See |+eval| and
There are six types of variables:
Number A 32 or 64 bit signed number. |expr-number| *Number*
64-bit Number is available only when compiled with the
|+num64| feature.
Examples: -123 0x10 0177 0b1011
Float A floating point number. |floating-point-format| *Float*
@ -887,6 +889,11 @@ When dividing a Number by zero the result depends on the value:
<0 / 0 = -0x7fffffff (like negative infinity)
(before Vim 7.2 it was always 0x7fffffff)
When 64-bit Number support is enabled:
0 / 0 = -0x8000000000000000 (like NaN for Float)
>0 / 0 = 0x7fffffffffffffff (like positive infinity)
<0 / 0 = -0x7fffffffffffffff (like negative infinity)
When the righthand side of '%' is zero, the result is 0.
None of these work for |Funcref|s.
@ -3546,17 +3553,19 @@ float2nr({expr}) *float2nr()*
decimal point.
{expr} must evaluate to a |Float| or a Number.
When the value of {expr} is out of range for a |Number| the
result is truncated to 0x7fffffff or -0x7fffffff. NaN results
in -0x80000000.
result is truncated to 0x7fffffff or -0x7fffffff (or when
64-bit Number support is enabled, 0x7fffffffffffffff or
-0x7fffffffffffffff. NaN results in -0x80000000 (or when
64-bit Number support is enabled, -0x8000000000000000).
Examples: >
echo float2nr(3.95)
< 3 >
echo float2nr(-23.45)
< -23 >
echo float2nr(1.0e100)
< 2147483647 >
< 2147483647 (or 9223372036854775807) >
echo float2nr(-1.0e150)
< -2147483647 >
< -2147483647 (or -9223372036854775807) >
echo float2nr(1.0e-100)
< 0
@ -7996,7 +8005,10 @@ winwidth({nr}) *winwidth()*
:if winwidth(0) <= 50
: exe "normal 50\<C-W>|"
:endif
<
< For getting the terminal or screen size, see the 'columns'
option.
wordcount() *wordcount()*
The result is a dictionary of byte/chars/word statistics for
the current buffer. This is the same info as provided by
@ -8150,6 +8162,7 @@ mouseshape Compiled with support for 'mouseshape'.
multi_byte Compiled with support for 'encoding'
multi_byte_encoding 'encoding' is set to a multi-byte encoding.
multi_lang Compiled with support for multiple languages.
num64 Compiled with 64-bit |Number| support.
nvim This is Nvim. |has-patch|
path_extra Compiled with up/downwards search in 'path' and 'tags'
persistent_undo Compiled with support for persistent undo history.

View File

@ -352,6 +352,7 @@ N *+mouseshape* |'mouseshape'|
N *+multi_byte* 16 and 32 bit characters |multibyte|
*+multi_byte_ime* Win32 input method for multibyte chars |multibyte-ime|
N *+multi_lang* non-English language support |multi-lang|
*+num64* 64-bit Number support |Number|
N *+path_extra* Up/downwards search in 'path' and 'tags'
N *+persistent_undo* Persistent undo |undo-persistence|
*+postscript* |:hardcopy| writes a PostScript file

View File

@ -83,14 +83,16 @@ static inline void restore_win_for_buf(win_T *save_curwin,
}
}
static inline void buf_set_changedtick(buf_T *const buf, const int changedtick)
static inline void buf_set_changedtick(buf_T *const buf,
const varnumber_T changedtick)
REAL_FATTR_NONNULL_ALL REAL_FATTR_ALWAYS_INLINE;
/// Set b_changedtick and corresponding variable
///
/// @param[out] buf Buffer to set changedtick in.
/// @param[in] changedtick New value.
static inline void buf_set_changedtick(buf_T *const buf, const int changedtick)
static inline void buf_set_changedtick(buf_T *const buf,
const varnumber_T changedtick)
{
#ifndef NDEBUG
dictitem_T *const changedtick_di = tv_dict_find(

View File

@ -1621,13 +1621,13 @@ bool vim_isblankline(char_u *lbuf)
/// @param unptr Returns the unsigned result.
/// @param maxlen Max length of string to check.
void vim_str2nr(const char_u *const start, int *const prep, int *const len,
const int what, long *const nptr, unsigned long *const unptr,
const int maxlen)
const int what, varnumber_T *const nptr,
uvarnumber_T *const unptr, const int maxlen)
{
const char_u *ptr = start;
int pre = 0; // default is decimal
bool negative = false;
unsigned long un = 0;
uvarnumber_T un = 0;
if (ptr[0] == '-') {
negative = true;
@ -1683,7 +1683,12 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len,
n += 2; // skip over "0b"
}
while ('0' <= *ptr && *ptr <= '1') {
un = 2 * un + (unsigned long)(*ptr - '0');
// avoid ubsan error for overflow
if (un < UVARNUMBER_MAX / 2) {
un = 2 * un + (uvarnumber_T)(*ptr - '0');
} else {
un = UVARNUMBER_MAX;
}
ptr++;
if (n++ == maxlen) {
break;
@ -1692,7 +1697,12 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len,
} else if ((pre == '0') || what == STR2NR_OCT + STR2NR_FORCE) {
// octal
while ('0' <= *ptr && *ptr <= '7') {
un = 8 * un + (unsigned long)(*ptr - '0');
// avoid ubsan error for overflow
if (un < UVARNUMBER_MAX / 8) {
un = 8 * un + (uvarnumber_T)(*ptr - '0');
} else {
un = UVARNUMBER_MAX;
}
ptr++;
if (n++ == maxlen) {
break;
@ -1705,7 +1715,12 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len,
n += 2; // skip over "0x"
}
while (ascii_isxdigit(*ptr)) {
un = 16 * un + (unsigned long)hex2nr(*ptr);
// avoid ubsan error for overflow
if (un < UVARNUMBER_MAX / 16) {
un = 16 * un + (uvarnumber_T)hex2nr(*ptr);
} else {
un = UVARNUMBER_MAX;
}
ptr++;
if (n++ == maxlen) {
break;
@ -1714,7 +1729,12 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len,
} else {
// decimal
while (ascii_isdigit(*ptr)) {
un = 10 * un + (unsigned long)(*ptr - '0');
// avoid ubsan error for overflow
if (un < UVARNUMBER_MAX / 10) {
un = 10 * un + (uvarnumber_T)(*ptr - '0');
} else {
un = UVARNUMBER_MAX;
}
ptr++;
if (n++ == maxlen) {
break;
@ -1731,11 +1751,18 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len,
}
if (nptr != NULL) {
if (negative) {
// account for leading '-' for decimal numbers
*nptr = -(long)un;
if (negative) { // account for leading '-' for decimal numbers
// avoid ubsan error for overflow
if (un > VARNUMBER_MAX) {
*nptr = VARNUMBER_MIN;
} else {
*nptr = -(varnumber_T)un;
}
} else {
*nptr = (long)un;
if (un > VARNUMBER_MAX) {
un = VARNUMBER_MAX;
}
*nptr = (varnumber_T)un;
}
}

View File

@ -6,6 +6,7 @@
*/
#include <assert.h>
#include <float.h>
#include <inttypes.h>
#include <stdarg.h>
#include <string.h>
@ -446,7 +447,7 @@ typedef struct {
bool rpc;
int refcount;
Callback on_stdout, on_stderr, on_exit;
int *status_ptr;
varnumber_T *status_ptr;
uint64_t id;
MultiQueue *events;
} TerminalJobData;
@ -1081,10 +1082,10 @@ char_u *eval_to_string_safe(char_u *arg, char_u **nextcmd, int use_sandbox)
* Evaluates "expr" silently.
* Returns -1 for an error.
*/
int eval_to_number(char_u *expr)
varnumber_T eval_to_number(char_u *expr)
{
typval_T rettv;
int retval;
varnumber_T retval;
char_u *p = skipwhite(expr);
++emsg_off;
@ -1203,7 +1204,7 @@ int call_vim_function(
typval_T *rettv
)
{
long n;
varnumber_T n;
int len;
int doesrange;
void *save_funccalp = NULL;
@ -1264,11 +1265,11 @@ int call_vim_function(
/// @param[in] safe Use with sandbox.
///
/// @return -1 when calling function fails, result of function otherwise.
long call_func_retnr(char_u *func, int argc, const char_u *const *const argv,
int safe)
varnumber_T call_func_retnr(char_u *func, int argc,
const char_u *const *const argv, int safe)
{
typval_T rettv;
long retval;
varnumber_T retval;
/* All arguments are passed as strings, no conversion to number. */
if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL)
@ -1396,7 +1397,7 @@ void prof_child_exit(proftime_T *tm /* where waittime was stored */
int eval_foldexpr(char_u *arg, int *cp)
{
typval_T tv;
int retval;
varnumber_T retval;
char_u *s;
int use_sandbox = was_set_insecurely((char_u *)"foldexpr",
OPT_LOCAL);
@ -1429,7 +1430,7 @@ int eval_foldexpr(char_u *arg, int *cp)
--sandbox;
--textlock;
return retval;
return (int)retval;
}
/*
@ -2283,7 +2284,7 @@ static char_u *get_lval(char_u *const name, typval_T *const rettv,
if (empty1) {
lp->ll_n1 = 0;
} else {
lp->ll_n1 = tv_get_number(&var1); // Is number or string.
lp->ll_n1 = (long)tv_get_number(&var1); // Is number or string.
tv_clear(&var1);
}
lp->ll_dict = NULL;
@ -2312,7 +2313,7 @@ static char_u *get_lval(char_u *const name, typval_T *const rettv,
* Otherwise "lp->ll_n2" is set to the second index.
*/
if (lp->ll_range && !lp->ll_empty2) {
lp->ll_n2 = tv_get_number(&var2); // Is number or string.
lp->ll_n2 = (long)tv_get_number(&var2); // Is number or string.
tv_clear(&var2);
if (lp->ll_n2 < 0) {
ni = tv_list_find(lp->ll_list, lp->ll_n2);
@ -3522,7 +3523,7 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate)
exptype_T type = TYPE_UNKNOWN;
int type_is = FALSE; /* TRUE for "is" and "isnot" */
int len = 2;
long n1, n2;
varnumber_T n1, n2;
int ic;
/*
@ -3784,7 +3785,7 @@ static int eval5(char_u **arg, typval_T *rettv, int evaluate)
typval_T var2;
typval_T var3;
int op;
long n1, n2;
varnumber_T n1, n2;
float_T f1 = 0, f2 = 0;
char_u *p;
@ -3914,29 +3915,26 @@ static int eval5(char_u **arg, typval_T *rettv, int evaluate)
// TODO(ZyX-I): move to eval/expressions
/*
* Handle fifth level expression:
* * number multiplication
* / number division
* % number modulo
*
* "arg" must point to the first non-white of the expression.
* "arg" is advanced to the next non-white after the recognized expression.
*
* Return OK or FAIL.
*/
static int
eval6 (
char_u **arg,
typval_T *rettv,
int evaluate,
int want_string /* after "." operator */
)
/// Handle fifth level expression:
/// - * number multiplication
/// - / number division
/// - % number modulo
///
/// @param[in,out] arg Points to the first non-whitespace character of the
/// expression. Is advanced to the next non-whitespace
/// character after the recognized expression.
/// @param[out] rettv Location where result is saved.
/// @param[in] evaluate If not true, rettv is not populated.
/// @param[in] want_string True if "." is string_concatenation, otherwise
/// float
/// @return OK or FAIL.
static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string)
FUNC_ATTR_NO_SANITIZE_UNDEFINED
{
typval_T var2;
int op;
long n1, n2;
int use_float = FALSE;
varnumber_T n1, n2;
bool use_float = false;
float_T f1 = 0, f2;
bool error = false;
@ -3957,7 +3955,7 @@ eval6 (
if (evaluate) {
if (rettv->v_type == VAR_FLOAT) {
f1 = rettv->vval.v_float;
use_float = TRUE;
use_float = true;
n1 = 0;
} else {
n1 = tv_get_number_chk(rettv, &error);
@ -3981,7 +3979,7 @@ eval6 (
if (var2.v_type == VAR_FLOAT) {
if (!use_float) {
f1 = n1;
use_float = TRUE;
use_float = true;
}
f2 = var2.vval.v_float;
n2 = 0;
@ -4024,18 +4022,20 @@ eval6 (
rettv->v_type = VAR_FLOAT;
rettv->vval.v_float = f1;
} else {
if (op == '*')
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
} else if (op == '/') {
if (n2 == 0) { // give an error message?
if (n1 == 0) {
n1 = VARNUMBER_MIN; // similar to NaN
} else if (n1 < 0) {
n1 = -VARNUMBER_MAX;
} else {
n1 = VARNUMBER_MAX;
}
} else {
n1 = n1 / n2;
}
} else {
if (n2 == 0) /* give an error message? */
n1 = 0;
@ -4084,7 +4084,7 @@ static int eval7(
int want_string // after "." operator
)
{
long n;
varnumber_T n;
int len;
char_u *s;
char_u *start_leader, *end_leader;
@ -4282,7 +4282,7 @@ static int eval7(
// Apply logical NOT and unary '-', from right to left, ignore '+'.
if (ret == OK && evaluate && end_leader > start_leader) {
bool error = false;
int val = 0;
varnumber_T val = 0;
float_T f = 0.0;
if (rettv->v_type == VAR_FLOAT) {
@ -6688,7 +6688,7 @@ static void f_argv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
int idx;
if (argvars[0].v_type != VAR_UNKNOWN) {
idx = tv_get_number_chk(&argvars[0], NULL);
idx = (int)tv_get_number_chk(&argvars[0], NULL);
if (idx >= 0 && idx < ARGCOUNT) {
rettv->vval.v_string = (char_u *)xstrdup(
(const char *)alist_name(&ARGLIST[idx]));
@ -7424,7 +7424,7 @@ static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return;
}
const int startcol = tv_get_number_chk(&argvars[0], NULL);
const colnr_T startcol = tv_get_number_chk(&argvars[0], NULL);
if (startcol <= 0) {
return;
}
@ -7635,9 +7635,9 @@ static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
} else {
line = tv_get_lnum(argvars);
col = tv_get_number_chk(&argvars[1], NULL);
col = (long)tv_get_number_chk(&argvars[1], NULL);
if (argvars[2].v_type != VAR_UNKNOWN) {
coladd = tv_get_number_chk(&argvars[2], NULL);
coladd = (long)tv_get_number_chk(&argvars[2], NULL);
}
}
if (line < 0 || col < 0
@ -8191,7 +8191,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
} else if (!tv_check_lock(l1->lv_lock, arg_errmsg, TV_TRANSLATE)) {
listitem_T *item;
if (argvars[2].v_type != VAR_UNKNOWN) {
before = tv_get_number_chk(&argvars[2], &error);
before = (long)tv_get_number_chk(&argvars[2], &error);
if (error) {
return; // Type error; errmsg already given.
}
@ -8560,9 +8560,9 @@ static void f_float2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
float_T f;
if (tv_get_float_chk(argvars, &f)) {
if (f < VARNUMBER_MIN) {
rettv->vval.v_number = VARNUMBER_MIN;
} else if (f > VARNUMBER_MAX) {
if (f <= -VARNUMBER_MAX + DBL_EPSILON) {
rettv->vval.v_number = -VARNUMBER_MAX;
} else if (f >= VARNUMBER_MAX - DBL_EPSILON) {
rettv->vval.v_number = VARNUMBER_MAX;
} else {
rettv->vval.v_number = (varnumber_T)f;
@ -10537,6 +10537,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr)
"mouse",
"multi_byte",
"multi_lang",
"num64",
"packages",
"path_extra",
"persistent_undo",
@ -12966,7 +12967,7 @@ static void f_range(typval_T *argvars, typval_T *rettv, FunPtr fptr)
varnumber_T start;
varnumber_T end;
varnumber_T stride = 1;
long i;
varnumber_T i;
bool error = false;
start = tv_get_number_chk(&argvars[0], &error);
@ -13184,7 +13185,7 @@ static int list2proftime(typval_T *arg, proftime_T *tm) FUNC_ATTR_NONNULL_ALL
// in f_reltime() we split up the 64-bit proftime_T into two 32-bit
// values, now we combine them again.
union {
struct { varnumber_T low, high; } split;
struct { int32_t low, high; } split;
proftime_T prof;
} u = { .split.high = n1, .split.low = n2 };
@ -13225,7 +13226,7 @@ static void f_reltime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// (varnumber_T is defined as int). For all our supported platforms, int's
// are at least 32-bits wide. So we'll use two 32-bit values to store it.
union {
struct { varnumber_T low, high; } split;
struct { int32_t low, high; } split;
proftime_T prof;
} u = { .prof = res };
@ -15173,8 +15174,8 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero)
int res;
if (sortinfo->item_compare_numbers) {
const long v1 = tv_get_number(tv1);
const long v2 = tv_get_number(tv2);
const varnumber_T v1 = tv_get_number(tv1);
const varnumber_T v2 = tv_get_number(tv2);
res = v1 == v2 ? 0 : v1 > v2 ? 1 : -1;
goto item_compare_end;
@ -15722,7 +15723,7 @@ static void f_str2float(typval_T *argvars, typval_T *rettv, FunPtr fptr)
static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int base = 10;
long n;
varnumber_T n;
int what;
if (argvars[1].v_type != VAR_UNKNOWN) {
@ -18138,7 +18139,7 @@ static int eval_isnamec1(int c)
/*
* Get number v: variable value.
*/
long get_vim_var_nr(int idx) FUNC_ATTR_PURE
varnumber_T get_vim_var_nr(int idx) FUNC_ATTR_PURE
{
return vimvars[idx].vv_nr;
}

View File

@ -435,8 +435,8 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len,
case 'u': {
const char ubuf[] = { t[1], t[2], t[3], t[4] };
t += 4;
unsigned long ch;
vim_str2nr((char_u *) ubuf, NULL, NULL,
uvarnumber_T ch;
vim_str2nr((char_u *)ubuf, NULL, NULL,
STR2NR_HEX | STR2NR_FORCE, NULL, &ch, 4);
if (ch == 0) {
hasnul = true;
@ -609,7 +609,7 @@ parse_json_number_check:
tv.v_type = VAR_FLOAT;
} else {
// Convert integer
long nr;
varnumber_T nr;
int num_len;
vim_str2nr((char_u *) s, NULL, &num_len, 0, &nr, NULL, (int) (p - s));
if ((int) exp_num_len != num_len) {
@ -617,7 +617,7 @@ parse_json_number_check:
"to integer vim_str2nr consumed %i bytes in place of %zu"),
(int) exp_num_len, s, num_len, exp_num_len);
}
tv.vval.v_number = (varnumber_T) nr;
tv.vval.v_number = nr;
}
if (json_decoder_pop(OBJ(tv, false, *didcomma, *didcolon),
stack, container_stack,

View File

@ -25,7 +25,7 @@ char *e_listidx = N_("E684: list index out of range: %" PRId64);
/// @return OK or FAIL.
int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2,
const char *const op)
FUNC_ATTR_NONNULL_ALL
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NO_SANITIZE_UNDEFINED
{
// Can't do anything with a Funcref, a Dict or special value on the right.
if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT) {
@ -55,7 +55,7 @@ int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2,
// nr += nr or nr -= nr
varnumber_T n = tv_get_number(tv1);
if (tv2->v_type == VAR_FLOAT) {
float_T f = n;
float_T f = (float_T)n;
if (*op == '+') {
f += tv2->vval.v_float;
@ -99,7 +99,7 @@ int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2,
}
const float_T f = (tv2->v_type == VAR_FLOAT
? tv2->vval.v_float
: tv_get_number(tv2));
: (float_T)tv_get_number(tv2));
if (*op == '+') {
tv1->vval.v_float += f;
} else {

View File

@ -2405,9 +2405,7 @@ varnumber_T tv_get_number_chk(const typval_T *const tv, bool *const ret_error)
case VAR_STRING: {
varnumber_T n = 0;
if (tv->vval.v_string != NULL) {
long nr;
vim_str2nr(tv->vval.v_string, NULL, NULL, STR2NR_ALL, &nr, NULL, 0);
n = (varnumber_T)nr;
vim_str2nr(tv->vval.v_string, NULL, NULL, STR2NR_ALL, &n, NULL, 0);
}
return n;
}
@ -2444,7 +2442,7 @@ varnumber_T tv_get_number_chk(const typval_T *const tv, bool *const ret_error)
linenr_T tv_get_lnum(const typval_T *const tv)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
linenr_T lnum = tv_get_number_chk(tv, NULL);
linenr_T lnum = (linenr_T)tv_get_number_chk(tv, NULL);
if (lnum == 0) { // No valid number, try using same function as line() does.
int fnum;
pos_T *const fp = var2fpos(tv, true, &fnum);

View File

@ -1,7 +1,7 @@
#ifndef NVIM_EVAL_TYPVAL_H
#define NVIM_EVAL_TYPVAL_H
#include <limits.h>
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
@ -20,20 +20,21 @@
#include "nvim/macros.h"
/// Type used for VimL VAR_NUMBER values
typedef int varnumber_T;
typedef int64_t varnumber_T;
typedef uint64_t uvarnumber_T;
/// Type used for VimL VAR_FLOAT values
typedef double float_T;
/// Maximal possible value of varnumber_T variable
#define VARNUMBER_MAX INT_MAX
#define VARNUMBER_MAX INT64_MAX
#define UVARNUMBER_MAX UINT64_MAX
/// Mimimal possible value of varnumber_T variable
#define VARNUMBER_MIN INT_MIN
#define PRIdVARNUMBER "d"
#define VARNUMBER_MIN INT64_MIN
/// %d printf format specifier for varnumber_T
#define PRIdVARNUMBER "d"
#define PRIdVARNUMBER PRId64
typedef struct listvar_S list_T;
typedef struct dictvar_S dict_T;

View File

@ -318,14 +318,12 @@ static int sort_abort; ///< flag to indicate if sorting has been interrupted
/// Struct to store info to be sorted.
typedef struct {
linenr_T lnum; ///< line number
long start_col_nr; ///< starting column number or number
long end_col_nr; ///< ending column number
union {
struct {
long start_col_nr; ///< starting column number
long end_col_nr; ///< ending column number
varnumber_T start_col_nr; ///< starting column number
varnumber_T end_col_nr; ///< ending column number
} line;
long value; ///< value if sorting by integer
varnumber_T value; ///< value if sorting by integer
float_T value_flt; ///< value if sorting by float
} st_u;
} sorti_T;

View File

@ -5002,7 +5002,7 @@ int get_list_range(char_u **str, int *num1, int *num2)
{
int len;
int first = false;
long num;
varnumber_T num;
*str = skipwhite(*str);
if (**str == '-' || ascii_isdigit(**str)) { // parse "from" part of range

View File

@ -281,8 +281,8 @@ readfile (
colnr_T len;
long size = 0;
char_u *p = NULL;
off_t filesize = 0;
int skip_read = FALSE;
off_T filesize = 0;
int skip_read = false;
context_sha256_T sha_ctx;
int read_undo_file = FALSE;
int split = 0; /* number of split lines */
@ -777,9 +777,9 @@ retry:
if (read_buffer) {
read_buf_lnum = 1;
read_buf_col = 0;
} else if (read_stdin || lseek(fd, (off_t)0L, SEEK_SET) != 0) {
/* Can't rewind the file, give up. */
error = TRUE;
} else if (read_stdin || vim_lseek(fd, (off_T)0L, SEEK_SET) != 0) {
// Can't rewind the file, give up.
error = true;
goto failed;
}
/* Delete the previously read lines. */
@ -1614,19 +1614,16 @@ rewind_retry:
if (fileformat == EOL_DOS) {
if (ptr[-1] == CAR) { /* remove CR */
ptr[-1] = NUL;
--len;
}
/*
* Reading in Dos format, but no CR-LF found!
* When 'fileformats' includes "unix", delete all
* the lines read so far and start all over again.
* Otherwise give an error message later.
*/
else if (ff_error != EOL_DOS) {
if ( try_unix
&& !read_stdin
&& (read_buffer
|| lseek(fd, (off_t)0L, SEEK_SET) == 0)) {
len--;
} else if (ff_error != EOL_DOS) {
// Reading in Dos format, but no CR-LF found!
// When 'fileformats' includes "unix", delete all
// the lines read so far and start all over again.
// Otherwise give an error message later.
if (try_unix
&& !read_stdin
&& (read_buffer
|| vim_lseek(fd, (off_T)0L, SEEK_SET) == 0)) {
fileformat = EOL_UNIX;
if (set_options)
set_fileformat(EOL_UNIX, OPT_LOCAL);
@ -3833,7 +3830,7 @@ static bool msg_add_fileformat(int eol_type)
/*
* Append line and character count to IObuff.
*/
void msg_add_lines(int insert_space, long lnum, off_t nchars)
void msg_add_lines(int insert_space, long lnum, off_T nchars)
{
char_u *p;
@ -6870,8 +6867,8 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io,
patcmd.next = active_apc_list;
active_apc_list = &patcmd;
/* set v:cmdarg (only when there is a matching pattern) */
save_cmdbang = get_vim_var_nr(VV_CMDBANG);
// set v:cmdarg (only when there is a matching pattern)
save_cmdbang = (long)get_vim_var_nr(VV_CMDBANG);
if (eap != NULL) {
save_cmdarg = set_cmdarg(eap, NULL);
set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);

View File

@ -2894,7 +2894,7 @@ static void foldlevelExpr(fline_T *flp)
/* KeyTyped may be reset to 0 when calling a function which invokes
* do_cmdline(). To make 'foldopen' work correctly restore KeyTyped. */
save_keytyped = KeyTyped;
n = eval_foldexpr(flp->wp->w_p_fde, &c);
n = (int)eval_foldexpr(flp->wp->w_p_fde, &c);
KeyTyped = save_keytyped;
switch (c) {

View File

@ -95,6 +95,10 @@
# undef FUNC_ATTR_NORETURN
#endif
#ifdef FUNC_ATTR_NO_SANITIZE_UNDEFINED
# undef FUNC_ATTR_NO_SANITIZE_UNDEFINED
#endif
#ifndef DID_REAL_ATTR
# define DID_REAL_ATTR
# ifdef __GNUC__
@ -122,6 +126,14 @@
# define REAL_FATTR_ALLOC_SIZE(x) __attribute__((alloc_size(x)))
# define REAL_FATTR_ALLOC_SIZE_PROD(x, y) __attribute__((alloc_size(x, y)))
# endif
# if NVIM_HAS_ATTRIBUTE(no_sanitize_undefined)
# define REAL_FATTR_NO_SANITIZE_UNDEFINED \
__attribute__((no_sanitize_undefined))
# elif NVIM_HAS_ATTRIBUTE(no_sanitize)
# define REAL_FATTR_NO_SANITIZE_UNDEFINED \
__attribute__((no_sanitize("undefined")))
# endif
# endif
// Define attributes that are not defined for this compiler.
@ -177,6 +189,10 @@
# ifndef REAL_FATTR_NORETURN
# define REAL_FATTR_NORETURN
# endif
# ifndef REAL_FATTR_NO_SANITIZE_UNDEFINED
# define REAL_FATTR_NO_SANITIZE_UNDEFINED
# endif
#endif
#ifdef DEFINE_FUNC_ATTRIBUTES
@ -198,6 +214,7 @@
# define FUNC_ATTR_NONNULL_ARG(...) REAL_FATTR_NONNULL_ARG(__VA_ARGS__)
# define FUNC_ATTR_NONNULL_RET REAL_FATTR_NONNULL_RET
# define FUNC_ATTR_NORETURN REAL_FATTR_NORETURN
# define FUNC_ATTR_NO_SANITIZE_UNDEFINED REAL_FATTR_NO_SANITIZE_UNDEFINED
#elif !defined(DO_NOT_DEFINE_EMPTY_ATTRIBUTES)
# define FUNC_ATTR_MALLOC
# define FUNC_ATTR_ALLOC_SIZE(x)
@ -212,4 +229,5 @@
# define FUNC_ATTR_NONNULL_ARG(...)
# define FUNC_ATTR_NONNULL_RET
# define FUNC_ATTR_NORETURN
# define FUNC_ATTR_NO_SANITIZE_UNDEFINED
#endif

View File

@ -97,6 +97,34 @@ typedef enum {
EXTERN long Rows INIT(= DFLT_ROWS); // nr of rows in the screen
EXTERN long Columns INIT(= DFLT_COLS); // nr of columns in the screen
// We use 64-bit file functions here, if available. E.g. ftello() returns
// off_t instead of long, which helps if long is 32 bit and off_t is 64 bit.
// We assume that when fseeko() is available then ftello() is too.
// Note that Windows has different function names.
#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__MINGW32__)
typedef __int64 off_T;
# ifdef __MINGW32__
# define vim_lseek lseek64
# define vim_fseek fseeko64
# define vim_ftell ftello64
# else
# define vim_lseek _lseeki64
# define vim_fseek _fseeki64
# define vim_ftell _ftelli64
# endif
#else
typedef off_t off_T;
# ifdef HAVE_FSEEKO
# define vim_lseek lseek
# define vim_ftell ftello
# define vim_fseek fseeko
# else
# define vim_lseek lseek
# define vim_ftell ftell
# define vim_fseek(a, b, c) fseek(a, (long)b, c)
# endif
#endif
/*
* The characters and attributes cached for the screen.
*/
@ -987,7 +1015,7 @@ EXTERN int did_cursorhold INIT(= false); // set when CursorHold t'gerd
// for CursorMoved event
EXTERN pos_T last_cursormoved INIT(= INIT_POS_T(0, 0, 0));
EXTERN int last_changedtick INIT(= 0); // for TextChanged event
EXTERN varnumber_T last_changedtick INIT(= 0); // for TextChanged event
EXTERN buf_T *last_changedtick_buf INIT(= NULL);
EXTERN int postponed_split INIT(= 0); /* for CTRL-W CTRL-] command */

View File

@ -471,7 +471,7 @@ int get_breakindent_win(win_T *wp, char_u *line) {
|| prev_tick != wp->w_buffer->b_changedtick) {
prev_line = line;
prev_ts = wp->w_buffer->b_p_ts;
prev_tick = wp->w_buffer->b_changedtick;
prev_tick = (int)wp->w_buffer->b_changedtick;
prev_indent = get_indent_str(line,
(int)wp->w_buffer->b_p_ts, wp->w_p_list);
}
@ -538,7 +538,7 @@ int get_expr_indent(void)
sandbox++;
}
textlock++;
indent = eval_to_number(curbuf->b_p_inde);
indent = (int)eval_to_number(curbuf->b_p_inde);
if (use_sandbox) {
sandbox--;

View File

@ -557,7 +557,7 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp,
int modifiers;
int bit;
int key;
unsigned long n;
uvarnumber_T n;
int l;
if (src_len == 0) {

View File

@ -115,18 +115,18 @@ memfile_T *mf_open(char_u *fname, int flags)
}
}
off_t size;
off_T size;
// When recovering, the actual block size will be retrieved from block 0
// in ml_recover(). The size used here may be wrong, therefore mf_blocknr_max
// must be rounded up.
if (mfp->mf_fd < 0
|| (flags & (O_TRUNC|O_EXCL))
|| (size = lseek(mfp->mf_fd, (off_t)0L, SEEK_END)) <= 0) {
|| (size = vim_lseek(mfp->mf_fd, 0L, SEEK_END)) <= 0) {
// no file or empty file
mfp->mf_blocknr_max = 0;
} else {
assert(sizeof(off_t) <= sizeof(blocknr_T)
assert(sizeof(off_T) <= sizeof(blocknr_T)
&& mfp->mf_page_size > 0
&& mfp->mf_page_size - 1 <= INT64_MAX - size);
mfp->mf_blocknr_max = (((blocknr_T)size + mfp->mf_page_size - 1)
@ -689,9 +689,9 @@ static int mf_read(memfile_T *mfp, bhdr_T *hp)
return FAIL;
unsigned page_size = mfp->mf_page_size;
// TODO(elmart): Check (page_size * hp->bh_bnum) within off_t bounds.
off_t offset = (off_t)(page_size * hp->bh_bnum);
if (lseek(mfp->mf_fd, offset, SEEK_SET) != offset) {
// TODO(elmart): Check (page_size * hp->bh_bnum) within off_T bounds.
off_T offset = (off_T)(page_size * hp->bh_bnum);
if (vim_lseek(mfp->mf_fd, offset, SEEK_SET) != offset) {
PERROR(_("E294: Seek error in swap file read"));
return FAIL;
}
@ -716,7 +716,7 @@ static int mf_read(memfile_T *mfp, bhdr_T *hp)
/// - Write error in swap file.
static int mf_write(memfile_T *mfp, bhdr_T *hp)
{
off_t offset; // offset in the file
off_T offset; // offset in the file
blocknr_T nr; // block nr which is being written
bhdr_T *hp2;
unsigned page_size; // number of bytes in a page
@ -745,9 +745,9 @@ static int mf_write(memfile_T *mfp, bhdr_T *hp)
hp2 = hp;
}
// TODO(elmart): Check (page_size * nr) within off_t bounds.
offset = (off_t)(page_size * nr);
if (lseek(mfp->mf_fd, offset, SEEK_SET) != offset) {
// TODO(elmart): Check (page_size * nr) within off_T bounds.
offset = (off_T)(page_size * nr);
if (vim_lseek(mfp->mf_fd, offset, SEEK_SET) != offset) {
PERROR(_("E296: Seek error in swap file write"));
return FAIL;
}

View File

@ -763,7 +763,7 @@ void ml_recover(void)
int idx;
int top;
int txt_start;
off_t size;
off_T size;
int called_from_main;
int serious_error = TRUE;
long mtime;
@ -914,10 +914,11 @@ void ml_recover(void)
msg_end();
goto theend;
}
if ((size = lseek(mfp->mf_fd, (off_t)0L, SEEK_END)) <= 0)
mfp->mf_blocknr_max = 0; /* no file or empty file */
else
if ((size = vim_lseek(mfp->mf_fd, (off_T)0L, SEEK_END)) <= 0) {
mfp->mf_blocknr_max = 0; // no file or empty file
} else {
mfp->mf_blocknr_max = size / mfp->mf_page_size;
}
mfp->mf_infile_count = mfp->mf_blocknr_max;
/* need to reallocate the memory used to store the data */

View File

@ -938,13 +938,11 @@ static int stuff_yank(int regname, char_u *p)
static int execreg_lastc = NUL;
/*
* execute a yank register: copy it into the stuff buffer
*
* return FAIL for failure, OK otherwise
*/
int
do_execreg (
/// Execute a yank register: copy it into the stuff buffer
///
/// Return FAIL for failure, OK otherwise
int
do_execreg(
int regname,
int colon, /* insert ':' before each line */
int addcr, /* always add '\n' to end of line */
@ -4439,8 +4437,8 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
char_u buf2[NUMBUFLEN];
int pre; // 'X' or 'x': hex; '0': octal; 'B' or 'b': bin
static bool hexupper = false; // 0xABC
unsigned long n;
unsigned long oldn;
uvarnumber_T n;
uvarnumber_T oldn;
char_u *ptr;
int c;
int todel;
@ -4635,20 +4633,20 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
oldn = n;
n = subtract ? n - (unsigned long) Prenum1
: n + (unsigned long) Prenum1;
n = subtract ? n - (uvarnumber_T)Prenum1
: n + (uvarnumber_T)Prenum1;
// handle wraparound for decimal numbers
if (!pre) {
if (subtract) {
if (n > oldn) {
n = 1 + (n ^ (unsigned long)-1);
n = 1 + (n ^ (uvarnumber_T)-1);
negative ^= true;
}
} else {
// add
if (n < oldn) {
n = (n ^ (unsigned long)-1);
n = (n ^ (uvarnumber_T)-1);
negative ^= true;
}
}
@ -5238,11 +5236,13 @@ void clear_oparg(oparg_T *oap)
* case, eol_size will be added to the character count to account for
* the size of the EOL character.
*/
static long line_count_info(char_u *line, long *wc, long *cc, long limit, int eol_size)
static varnumber_T line_count_info(char_u *line, varnumber_T *wc,
varnumber_T *cc, varnumber_T limit,
int eol_size)
{
long i;
long words = 0;
long chars = 0;
varnumber_T i;
varnumber_T words = 0;
varnumber_T chars = 0;
int is_word = 0;
for (i = 0; i < limit && line[i] != NUL; ) {
@ -5280,15 +5280,15 @@ void cursor_pos_info(dict_T *dict)
char_u buf1[50];
char_u buf2[40];
linenr_T lnum;
long byte_count = 0;
long bom_count = 0;
long byte_count_cursor = 0;
long char_count = 0;
long char_count_cursor = 0;
long word_count = 0;
long word_count_cursor = 0;
varnumber_T byte_count = 0;
varnumber_T bom_count = 0;
varnumber_T byte_count_cursor = 0;
varnumber_T char_count = 0;
varnumber_T char_count_cursor = 0;
varnumber_T word_count = 0;
varnumber_T word_count_cursor = 0;
int eol_size;
long last_check = 100000L;
varnumber_T last_check = 100000L;
long line_count_selected = 0;
pos_T min_pos, max_pos;
oparg_T oparg;
@ -5395,15 +5395,16 @@ void cursor_pos_info(dict_T *dict)
if (lnum == curwin->w_cursor.lnum) {
word_count_cursor += word_count;
char_count_cursor += char_count;
byte_count_cursor = byte_count +
line_count_info(ml_get(lnum),
&word_count_cursor, &char_count_cursor,
(long)(curwin->w_cursor.col + 1), eol_size);
byte_count_cursor = byte_count
+ line_count_info(ml_get(lnum), &word_count_cursor,
&char_count_cursor,
(varnumber_T)(curwin->w_cursor.col + 1),
eol_size);
}
}
/* Add to the running totals */
byte_count += line_count_info(ml_get(lnum), &word_count,
&char_count, (long)MAXCOL, eol_size);
// Add to the running totals
byte_count += line_count_info(ml_get(lnum), &word_count, &char_count,
(varnumber_T)MAXCOL, eol_size);
}
// Correction for when last line doesn't have an EOL.

View File

@ -1144,7 +1144,7 @@ do_set (
int afterchar; /* character just after option name */
int len;
int i;
long value;
varnumber_T value;
int key;
uint32_t flags; /* flags for current option */
char_u *varp = NULL; /* pointer to variable for current option */
@ -1477,7 +1477,7 @@ do_set (
if (removing) {
value = *(long *)varp - value;
}
errmsg = (char_u *)set_num_option(opt_idx, varp, value,
errmsg = (char_u *)set_num_option(opt_idx, varp, (long)value,
errbuf, sizeof(errbuf),
opt_flags);
} else if (opt_idx >= 0) { // String.
@ -4630,7 +4630,7 @@ get_option_value (
if ((int *)varp == &curbuf->b_changed) {
*numval = curbufIsChanged();
} else {
*numval = *(int *)varp;
*numval = (long) *(int *)varp; // NOLINT(whitespace/cast)
}
}
return 1;

View File

@ -4027,7 +4027,7 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
if ((di = tv_dict_find(what, S_LEN("nr"))) != NULL) {
// Use the specified quickfix/location list
if (di->di_tv.v_type == VAR_NUMBER) {
qf_idx = di->di_tv.vval.v_number - 1;
qf_idx = (int)di->di_tv.vval.v_number - 1;
if (qf_idx < 0 || qf_idx >= qi->qf_listcount) {
return FAIL;
}
@ -4101,7 +4101,7 @@ static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title,
char *const filename = tv_dict_get_string(d, "filename", true);
int bufnum = (int)tv_dict_get_number(d, "bufnr");
long lnum = tv_dict_get_number(d, "lnum");
long lnum = (long)tv_dict_get_number(d, "lnum");
int col = (int)tv_dict_get_number(d, "col");
char_u vcol = (char_u)tv_dict_get_number(d, "vcol");
int nr = (int)tv_dict_get_number(d, "nr");
@ -4183,7 +4183,7 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action)
if ((di = tv_dict_find(what, S_LEN("nr"))) != NULL) {
// Use the specified quickfix/location list
if (di->di_tv.v_type == VAR_NUMBER) {
qf_idx = di->di_tv.vval.v_number - 1;
qf_idx = (int)di->di_tv.vval.v_number - 1;
if (qf_idx < 0 || qf_idx >= qi->qf_listcount) {
return FAIL;
}

View File

@ -653,7 +653,7 @@ static float_T tv_float(typval_T *const tvs, int *const idxp)
if (tvs[idx].v_type == VAR_FLOAT) {
f = tvs[idx].vval.v_float;
} else if (tvs[idx].v_type == VAR_NUMBER) {
f = tvs[idx].vval.v_number;
f = (float_T)tvs[idx].vval.v_number;
} else {
EMSG(_("E807: Expected Float argument for printf()"));
}
@ -910,6 +910,13 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap,
default: break;
}
switch (fmt_spec) {
case 'd': case 'u': case 'o': case 'x': case 'X':
if (tvs && length_modifier == '\0') {
length_modifier = '2';
}
}
// get parameter value, do initial processing
switch (fmt_spec) {
// '%' and 'c' behave similar to 's' regarding flags and field widths

View File

@ -105,15 +105,6 @@ static char_u *topmsg = (char_u *)N_("E556: at top of tag stack");
static char_u *tagmatchname = NULL; /* name of last used tag */
/*
* We use ftello() here, if available. It returns off_t instead of long,
* which helps if long is 32 bit and off_t is 64 bit.
* We assume that when fseeko() is available then ftello() is too.
*/
#ifdef HAVE_FSEEKO
# define ftell ftello
#endif
/*
* Tag for preview window is remembered separately, to avoid messing up the
* normal tagstack.
@ -1088,22 +1079,21 @@ find_tags (
char_u *p;
char_u *s;
int i;
int tag_file_sorted = NUL; /* !_TAG_FILE_SORTED value */
struct tag_search_info /* Binary search file offsets */
{
off_t low_offset; /* offset for first char of first line that
could match */
off_t high_offset; /* offset of char after last line that could
match */
off_t curr_offset; /* Current file offset in search range */
off_t curr_offset_used; /* curr_offset used when skipping back */
off_t match_offset; /* Where the binary search found a tag */
int low_char; /* first char at low_offset */
int high_char; /* first char at high_offset */
int tag_file_sorted = NUL; // !_TAG_FILE_SORTED value
struct tag_search_info { // Binary search file offsets
off_T low_offset; // offset for first char of first line that
// could match
off_T high_offset; // offset of char after last line that could
// match
off_T curr_offset; // Current file offset in search range
off_T curr_offset_used; // curr_offset used when skipping back
off_T match_offset; // Where the binary search found a tag
int low_char; // first char at low_offset
int high_char; // first char at high_offset
} search_info;
off_t filesize;
off_T filesize;
int tagcmp;
off_t offset;
off_T offset;
int round;
enum {
TS_START, /* at start of file */
@ -1378,36 +1368,28 @@ find_tags (
if (state == TS_BINARY || state == TS_SKIP_BACK) {
/* Adjust the search file offset to the correct position */
search_info.curr_offset_used = search_info.curr_offset;
#ifdef HAVE_FSEEKO
fseeko(fp, search_info.curr_offset, SEEK_SET);
#else
fseek(fp, (long)search_info.curr_offset, SEEK_SET);
#endif
vim_fseek(fp, search_info.curr_offset, SEEK_SET);
eof = vim_fgets(lbuf, LSIZE, fp);
if (!eof && search_info.curr_offset != 0) {
/* The explicit cast is to work around a bug in gcc 3.4.2
* (repeated below). */
search_info.curr_offset = ftell(fp);
search_info.curr_offset = vim_ftell(fp);
if (search_info.curr_offset == search_info.high_offset) {
/* oops, gone a bit too far; try from low offset */
#ifdef HAVE_FSEEKO
fseeko(fp, search_info.low_offset, SEEK_SET);
#else
fseek(fp, (long)search_info.low_offset, SEEK_SET);
#endif
// oops, gone a bit too far; try from low offset
vim_fseek(fp, search_info.low_offset, SEEK_SET);
search_info.curr_offset = search_info.low_offset;
}
eof = vim_fgets(lbuf, LSIZE, fp);
}
/* skip empty and blank lines */
while (!eof && vim_isblankline(lbuf)) {
search_info.curr_offset = ftell(fp);
search_info.curr_offset = vim_ftell(fp);
eof = vim_fgets(lbuf, LSIZE, fp);
}
if (eof) {
/* Hit end of file. Skip backwards. */
state = TS_SKIP_BACK;
search_info.match_offset = ftell(fp);
search_info.match_offset = vim_ftell(fp);
search_info.curr_offset = search_info.curr_offset_used;
continue;
}
@ -1523,10 +1505,10 @@ line_read_in:
*/
if (state == TS_BINARY) {
// Get the tag file size.
if ((filesize = lseek(fileno(fp), (off_t)0L, SEEK_END)) <= 0) {
if ((filesize = vim_lseek(fileno(fp), (off_T)0L, SEEK_END)) <= 0) {
state = TS_LINEAR;
} else {
lseek(fileno(fp), (off_t)0L, SEEK_SET);
vim_lseek(fileno(fp), (off_T)0L, SEEK_SET);
/* Calculate the first read offset in the file. Start
* the search in the middle of the file. */
@ -1564,11 +1546,7 @@ parse_line:
/* Avoid getting stuck. */
linear = TRUE;
state = TS_LINEAR;
# ifdef HAVE_FSEEKO
fseeko(fp, search_info.low_offset, SEEK_SET);
# else
fseek(fp, (long)search_info.low_offset, SEEK_SET);
# endif
vim_fseek(fp, search_info.low_offset, SEEK_SET);
}
continue;
}
@ -1647,7 +1625,7 @@ parse_line:
continue;
}
if (tagcmp < 0) {
search_info.curr_offset = ftell(fp);
search_info.curr_offset = vim_ftell(fp);
if (search_info.curr_offset < search_info.high_offset) {
search_info.low_offset = search_info.curr_offset;
if (sortic)
@ -1683,10 +1661,11 @@ parse_line:
} else if (state == TS_STEP_FORWARD) {
assert(cmplen >= 0);
if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0) {
if ((off_t)ftell(fp) > search_info.match_offset)
break; /* past last match */
else
continue; /* before first match */
if ((off_T)vim_ftell(fp) > search_info.match_offset) {
break; // past last match
} else {
continue; // before first match
}
}
} else
/* skip this match if it can't match */
@ -1907,10 +1886,11 @@ parse_line:
if (line_error) {
EMSG2(_("E431: Format error in tags file \"%s\""), tag_fname);
if (!use_cscope)
EMSGN(_("Before byte %" PRId64), ftell(fp));
stop_searching = TRUE;
line_error = FALSE;
if (!use_cscope) {
EMSGN(_("Before byte %" PRId64), vim_ftell(fp));
}
stop_searching = true;
line_error = false;
}
if (!use_cscope)

View File

@ -60,6 +60,7 @@ NEW_TESTS ?= \
test_quickfix.res \
test_signs.res \
test_smartindent.res \
test_stat.res \
test_substitute.res \
test_syntax.res \
test_tabpage.res \

View File

@ -98,6 +98,35 @@ func Test_special_char()
call assert_fails('echo "\<C-">')
endfunc
func Test_option_value()
" boolean
set bri
call assert_equal(1, &bri)
set nobri
call assert_equal(0, &bri)
" number
set ts=1
call assert_equal(1, &ts)
set ts=8
call assert_equal(8, &ts)
" string
exe "set cedit=\<Esc>"
call assert_equal("\<Esc>", &cedit)
set cpo=
call assert_equal("", &cpo)
set cpo=abcdefi
call assert_equal("abcdefi", &cpo)
set cpo&vim
endfunc
function Test_printf_64bit()
if has('num64')
call assert_equal("123456789012345", printf('%d', 123456789012345))
endif
endfunc
func Test_setmatches()
hi def link 1 Comment
hi def link 2 PreProc

View File

@ -224,6 +224,20 @@ func Test_str2float()
call assert_fails("call str2float(function('string'))", 'E729:')
endfunc
func Test_float2nr()
call assert_equal(1, float2nr(1.234))
call assert_equal(123, float2nr(1.234e2))
call assert_equal(12, float2nr(123.4e-1))
let max_number = 1/0
let min_number = -max_number
call assert_equal(max_number/2+1, float2nr(pow(2, 62)))
call assert_equal(max_number, float2nr(pow(2, 63)))
call assert_equal(max_number, float2nr(pow(2, 64)))
call assert_equal(min_number/2-1, float2nr(-pow(2, 62)))
call assert_equal(min_number, float2nr(-pow(2, 63)))
call assert_equal(min_number, float2nr(-pow(2, 64)))
endfunc
func Test_floor()
call assert_equal('2.0', string(floor(2.0)))
call assert_equal('2.0', string(floor(2.11)))
@ -283,3 +297,36 @@ func Test_isnan()
call assert_equal(0, isnan([]))
call assert_equal(0, isnan({}))
endfunc
" This was converted from test65
func Test_float_misc()
call assert_equal('123.456000', printf('%f', 123.456))
call assert_equal('1.234560e+02', printf('%e', 123.456))
call assert_equal('123.456', printf('%g', 123.456))
" +=
let v = 1.234
let v += 6.543
call assert_equal('7.777', printf('%g', v))
let v = 1.234
let v += 5
call assert_equal('6.234', printf('%g', v))
let v = 5
let v += 3.333
call assert_equal('8.333', string(v))
" ==
let v = 1.234
call assert_true(v == 1.234)
call assert_false(v == 1.2341)
" add-subtract
call assert_equal('5.234', printf('%g', 4 + 1.234))
call assert_equal('-6.766', printf('%g', 1.234 - 8))
" mult-div
call assert_equal('4.936', printf('%g', 4 * 1.234))
call assert_equal('0.003241', printf('%g', 4.0 / 1234))
" dict
call assert_equal("{'x': 1.234, 'y': -2.0e20}", string({'x': 1.234, 'y': -2.0e20}))
" list
call assert_equal('[-123.4, 2.0e-20]', string([-123.4, 2.0e-20]))
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -0,0 +1,34 @@
" Tests for large files
" This is only executed manually: "make test_largefile".
" This is not run as part of "make test".
func Test_largefile()
let fname = 'Xlarge.txt'
call delete(fname)
exe "e" fname
" Make sure that a line break is 1 byte (LF).
set ff=unix
set undolevels=-1
" Input 99 'A's. The line becomes 100 bytes including a line break.
exe "normal 99iA\<Esc>"
yank
" Put 39,999,999 times. The file becomes 4,000,000,000 bytes.
normal 39999999p
" Moving around in the file randomly.
normal G
normal 10%
normal 90%
normal 50%
normal gg
w
" Check if the file size is 4,000,000,000 bytes.
let fsize=getfsize(fname)
if has('num64')
call assert_true(fsize == 4000000000)
else
" getfsize() returns -2 if a Number is 32 bits.
call assert_true(fsize == -2)
endif
call delete(fname)
endfunc

View File

@ -0,0 +1,64 @@
" Tests for stat functions and checktime
func Test_existent_file()
let fname='Xtest.tmp'
let ts=localtime()
sleep 1
let fl=['Hello World!']
call writefile(fl, fname)
let tf=getftime(fname)
sleep 1
let te=localtime()
call assert_true(ts <= tf && tf <= te)
call assert_equal(strlen(fl[0] . "\n"), getfsize(fname))
call assert_equal('file', getftype(fname))
call assert_equal('rw-', getfperm(fname)[0:2])
endfunc
func Test_existent_directory()
let dname='.'
call assert_equal(0, getfsize(dname))
call assert_equal('dir', getftype(dname))
call assert_equal('rwx', getfperm(dname)[0:2])
endfunc
func Test_checktime()
let fname='Xtest.tmp'
let fl=['Hello World!']
call writefile(fl, fname)
set autoread
exec 'e' fname
sleep 2
let fl=readfile(fname)
let fl[0] .= ' - checktime'
call writefile(fl, fname)
checktime
call assert_equal(fl[0], getline(1))
endfunc
func Test_nonexistent_file()
let fname='Xtest.tmp'
call delete(fname)
call assert_equal(-1, getftime(fname))
call assert_equal(-1, getfsize(fname))
call assert_equal('', getftype(fname))
call assert_equal('', getfperm(fname))
endfunc
func Test_win32_symlink_dir()
" On Windows, non-admin users cannot create symlinks.
" So we use an existing symlink for this test.
if has('win32')
" Check if 'C:\Users\All Users' is a symlink to a directory.
let res=system('dir C:\Users /a')
if match(res, '\C<SYMLINKD> *All Users') >= 0
" Get the filetype of the symlink.
call assert_equal('dir', getftype('C:\Users\All Users'))
endif
endif
endfunc

View File

@ -1062,6 +1062,32 @@ func Test_echo_and_string()
call assert_equal(["{'a': [], 'b': []}",
\ "{'a': [], 'b': []}"], l)
"-------------------------------------------------------------------------------
" Test 94: 64-bit Numbers {{{1
"-------------------------------------------------------------------------------
func Test_num64()
if !has('num64')
return
endif
call assert_notequal( 4294967296, 0)
call assert_notequal(-4294967296, 0)
call assert_equal( 4294967296, 0xFFFFffff + 1)
call assert_equal(-4294967296, -0xFFFFffff - 1)
call assert_equal( 9223372036854775807, 1 / 0)
call assert_equal(-9223372036854775807, -1 / 0)
call assert_equal(-9223372036854775807 - 1, 0 / 0)
call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150))
call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150))
let rng = range(0xFFFFffff, 0x100000001)
call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng)
call assert_equal(0x100000001, max(rng))
call assert_equal(0xFFFFffff, min(rng))
call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N'))
endfunc
"-------------------------------------------------------------------------------
@ -1146,6 +1172,49 @@ func Test_script_emty_line_continuation()
\
endfunc
"-------------------------------------------------------------------------------
" Test 97: bitwise functions {{{1
"-------------------------------------------------------------------------------
func Test_bitwise_functions()
" and
call assert_equal(127, and(127, 127))
call assert_equal(16, and(127, 16))
call assert_equal(0, and(127, 128))
call assert_fails("call and(1.0, 1)", 'E805:')
call assert_fails("call and([], 1)", 'E745:')
call assert_fails("call and({}, 1)", 'E728:')
call assert_fails("call and(1, 1.0)", 'E805:')
call assert_fails("call and(1, [])", 'E745:')
call assert_fails("call and(1, {})", 'E728:')
" or
call assert_equal(23, or(16, 7))
call assert_equal(15, or(8, 7))
call assert_equal(123, or(0, 123))
call assert_fails("call or(1.0, 1)", 'E805:')
call assert_fails("call or([], 1)", 'E745:')
call assert_fails("call or({}, 1)", 'E728:')
call assert_fails("call or(1, 1.0)", 'E805:')
call assert_fails("call or(1, [])", 'E745:')
call assert_fails("call or(1, {})", 'E728:')
" xor
call assert_equal(0, xor(127, 127))
call assert_equal(111, xor(127, 16))
call assert_equal(255, xor(127, 128))
call assert_fails("call xor(1.0, 1)", 'E805:')
call assert_fails("call xor([], 1)", 'E745:')
call assert_fails("call xor({}, 1)", 'E728:')
call assert_fails("call xor(1, 1.0)", 'E805:')
call assert_fails("call xor(1, [])", 'E745:')
call assert_fails("call xor(1, {})", 'E728:')
" invert
call assert_equal(65408, and(invert(127), 65535))
call assert_equal(65519, and(invert(16), 65535))
call assert_equal(65407, and(invert(128), 65535))
call assert_fails("call invert(1.0)", 'E805:')
call assert_fails("call invert([])", 'E745:')
call assert_fails("call invert({})", 'E728:')
endfunc
"-------------------------------------------------------------------------------
" Modelines {{{1
" vim: ts=8 sw=4 tw=80 fdm=marker

View File

@ -220,7 +220,7 @@ static const int included_patches[] = {
2227,
2226,
2225,
// 2224,
2224,
2223,
2222,
2221,
@ -415,7 +415,7 @@ static const int included_patches[] = {
// 2032 NA
2031,
// 2030 NA
// 2029,
2029,
2028,
// 2027 NA
// 2026 NA
@ -458,18 +458,18 @@ static const int included_patches[] = {
1989,
// 1988 NA
// 1987 NA
// 1986,
1986,
// 1985 NA
1984,
// 1983 NA
// 1982 NA
1981,
1980,
// 1979,
// 1978,
// 1977,
// 1976,
// 1975,
1979,
1978,
1977,
1976,
1975,
// 1974 NA
1973,
// 1972 NA

View File

@ -337,7 +337,8 @@ describe('msgpack*() functions', function()
eq(1, eval('type(parsed[0]) == type(0) ' ..
'|| parsed[0]._TYPE is v:msgpack_types.integer'))
if eval('type(parsed[0]) == type(0)') == 1 then
eq(1, eval('0xFFFFFFFFFFFFFFFF == parsed[0]'))
command('call assert_equal(0xFFFFFFFFFFFFFFFF, parsed[0])')
eq({}, eval('v:errors'))
else
eq({_TYPE={}, _VAL={1, 3, 0x7FFFFFFF, 0x7FFFFFFF}}, eval('parsed[0]'))
end
@ -351,7 +352,8 @@ describe('msgpack*() functions', function()
eq(1, eval('type(parsed[0]) == type(0) ' ..
'|| parsed[0]._TYPE is v:msgpack_types.integer'))
if eval('type(parsed[0]) == type(0)') == 1 then
eq(1, eval('-0x8000000000000000 == parsed[0]'))
command('call assert_equal(-0x7fffffffffffffff - 1, parsed[0])')
eq({}, eval('v:errors'))
else
eq({_TYPE={}, _VAL={-1, 2, 0, 0}}, eval('parsed[0]'))
end