Skip to content

Commit f9706e9

Browse files
committed
patch 8.2.0296: mixing up "long long" and __int64 may cause problems
Problem: Mixing up "long long" and __int64 may cause problems. (John Marriott) Solution: Pass varnumber_T to vim_snprintf(). Add v:numbersize.
1 parent c036e87 commit f9706e9

12 files changed

Lines changed: 108 additions & 96 deletions

File tree

runtime/doc/eval.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ There are ten types of variables:
4848

4949
*Number* *Integer*
5050
Number A 32 or 64 bit signed number. |expr-number|
51-
64-bit Numbers are available only when compiled with the
52-
|+num64| feature.
51+
The number of bits is available in |v:numbersize|.
5352
Examples: -123 0x10 0177 0b1011
5453

5554
Float A floating point number. |floating-point-format| *Float*
@@ -1991,6 +1990,10 @@ v:null An empty String. Used to put "null" in JSON. See
19911990
That is so that eval() can parse the string back to the same
19921991
value. Read-only.
19931992

1993+
*v:numbersize* *numbersize-variable*
1994+
v:numbersize Number of bits in a Number. This is normally 64, but on some
1995+
systems it my be 32.
1996+
19941997
*v:oldfiles* *oldfiles-variable*
19951998
v:oldfiles List of file names that is loaded from the |viminfo| file on
19961999
startup. These are the files that Vim remembers marks for.

runtime/doc/various.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*various.txt* For Vim version 8.2. Last change: 2019 Dec 07
1+
*various.txt* For Vim version 8.2. Last change: 2020 Feb 22
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -407,7 +407,9 @@ N *+multi_lang* non-English language support |multi-lang|
407407
m *+mzscheme* Mzscheme interface |mzscheme|
408408
m *+mzscheme/dyn* Mzscheme interface |mzscheme-dynamic| |/dyn|
409409
m *+netbeans_intg* |netbeans|
410-
*+num64* 64-bit Number support |Number|
410+
*+num64* 64-bit Number support |Number|
411+
Always enabled since 8.2.0271, use v:numbersize to
412+
check the actual size of a Number.
411413
m *+ole* Win32 GUI only: |ole-interface|
412414
N *+packages* Loading |packages|
413415
N *+path_extra* Up/downwards search in 'path' and 'tags'

src/eval.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5665,7 +5665,7 @@ tv_get_string_buf_chk(typval_T *varp, char_u *buf)
56655665
{
56665666
case VAR_NUMBER:
56675667
vim_snprintf((char *)buf, NUMBUFLEN, "%lld",
5668-
(long_long_T)varp->vval.v_number);
5668+
(varnumber_T)varp->vval.v_number);
56695669
return buf;
56705670
case VAR_FUNC:
56715671
case VAR_PARTIAL:

src/evalvars.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,9 @@ static struct vimvar
120120
{VV_NAME("errors", VAR_LIST), 0},
121121
{VV_NAME("false", VAR_BOOL), VV_RO},
122122
{VV_NAME("true", VAR_BOOL), VV_RO},
123-
{VV_NAME("null", VAR_SPECIAL), VV_RO},
124123
{VV_NAME("none", VAR_SPECIAL), VV_RO},
124+
{VV_NAME("null", VAR_SPECIAL), VV_RO},
125+
{VV_NAME("numbersize", VAR_NUMBER), VV_RO},
125126
{VV_NAME("vim_did_enter", VAR_NUMBER), VV_RO},
126127
{VV_NAME("testing", VAR_NUMBER), 0},
127128
{VV_NAME("t_number", VAR_NUMBER), VV_RO},
@@ -229,6 +230,7 @@ evalvars_init(void)
229230
set_vim_var_nr(VV_TRUE, VVAL_TRUE);
230231
set_vim_var_nr(VV_NONE, VVAL_NONE);
231232
set_vim_var_nr(VV_NULL, VVAL_NULL);
233+
set_vim_var_nr(VV_NUMBERSIZE, sizeof(varnumber_T) * 8);
232234

233235
set_vim_var_nr(VV_TYPE_NUMBER, VAR_TYPE_NUMBER);
234236
set_vim_var_nr(VV_TYPE_STRING, VAR_TYPE_STRING);

src/fileio.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3016,14 +3016,14 @@ msg_add_lines(
30163016
*p++ = ' ';
30173017
if (shortmess(SHM_LINES))
30183018
vim_snprintf((char *)p, IOSIZE - (p - IObuff),
3019-
"%ldL, %lldC", lnum, (long_long_T)nchars);
3019+
"%ldL, %lldC", lnum, (varnumber_T)nchars);
30203020
else
30213021
{
30223022
sprintf((char *)p, NGETTEXT("%ld line, ", "%ld lines, ", lnum), lnum);
30233023
p += STRLEN(p);
30243024
vim_snprintf((char *)p, IOSIZE - (p - IObuff),
30253025
NGETTEXT("%lld character", "%lld characters", nchars),
3026-
(long_long_T)nchars);
3026+
(varnumber_T)nchars);
30273027
}
30283028
}
30293029

src/json.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
215215

216216
case VAR_NUMBER:
217217
vim_snprintf((char *)numbuf, NUMBUFLEN, "%lld",
218-
(long_long_T)val->vval.v_number);
218+
(varnumber_T)val->vval.v_number);
219219
ga_concat(gap, numbuf);
220220
break;
221221

src/message.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4129,7 +4129,7 @@ infinity_str(int positive,
41294129
* Limited support for floating point was added: 'f', 'F', 'e', 'E', 'g', 'G'.
41304130
*
41314131
* Length modifiers 'h' (short int) and 'l' (long int) and 'll' (long long int)
4132-
* are supported.
4132+
* are supported. NOTE: for 'll' the argument is varnumber_T or uvarnumber_T.
41334133
*
41344134
* The locale is not used, the string is used as a byte string. This is only
41354135
* relevant for double-byte encodings where the second byte may be '%'.
@@ -4371,7 +4371,7 @@ vim_vsnprintf_typval(
43714371
p++;
43724372
if (length_modifier == 'l' && *p == 'l')
43734373
{
4374-
// double l = long long
4374+
// double l = __int64 / varnumber_T
43754375
length_modifier = 'L';
43764376
p++;
43774377
}
@@ -4501,20 +4501,20 @@ vim_vsnprintf_typval(
45014501
// argument is never negative)
45024502
int arg_sign = 0;
45034503

4504-
// only defined for length modifier h, or for no
4505-
// length modifiers
4504+
// only set for length modifier h, or for no length
4505+
// modifiers
45064506
int int_arg = 0;
45074507
unsigned int uint_arg = 0;
45084508

4509-
// only defined for length modifier l
4509+
// only set for length modifier l
45104510
long int long_arg = 0;
45114511
unsigned long int ulong_arg = 0;
45124512

4513-
// only defined for length modifier ll
4513+
// only set for length modifier ll
45144514
varnumber_T llong_arg = 0;
45154515
uvarnumber_T ullong_arg = 0;
45164516

4517-
// only defined for b conversion
4517+
// only set for b conversion
45184518
uvarnumber_T bin_arg = 0;
45194519

45204520
// pointer argument value -only defined for p

src/ops.c

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3364,17 +3364,13 @@ do_addsub(
33643364
buf2[i] = '\0';
33653365
}
33663366
else if (pre == 0)
3367-
vim_snprintf((char *)buf2, NUMBUFLEN, "%llu",
3368-
(long_long_u_T)n);
3367+
vim_snprintf((char *)buf2, NUMBUFLEN, "%llu", (uvarnumber_T)n);
33693368
else if (pre == '0')
3370-
vim_snprintf((char *)buf2, NUMBUFLEN, "%llo",
3371-
(long_long_u_T)n);
3369+
vim_snprintf((char *)buf2, NUMBUFLEN, "%llo", (uvarnumber_T)n);
33723370
else if (pre && hexupper)
3373-
vim_snprintf((char *)buf2, NUMBUFLEN, "%llX",
3374-
(long_long_u_T)n);
3371+
vim_snprintf((char *)buf2, NUMBUFLEN, "%llX", (uvarnumber_T)n);
33753372
else
3376-
vim_snprintf((char *)buf2, NUMBUFLEN, "%llx",
3377-
(long_long_u_T)n);
3373+
vim_snprintf((char *)buf2, NUMBUFLEN, "%llx", (uvarnumber_T)n);
33783374
length -= (int)STRLEN(buf2);
33793375

33803376
/*
@@ -3773,21 +3769,21 @@ cursor_pos_info(dict_T *dict)
37733769
_("Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Bytes"),
37743770
buf1, line_count_selected,
37753771
(long)curbuf->b_ml.ml_line_count,
3776-
(long_long_T)word_count_cursor,
3777-
(long_long_T)word_count,
3778-
(long_long_T)byte_count_cursor,
3779-
(long_long_T)byte_count);
3772+
(varnumber_T)word_count_cursor,
3773+
(varnumber_T)word_count,
3774+
(varnumber_T)byte_count_cursor,
3775+
(varnumber_T)byte_count);
37803776
else
37813777
vim_snprintf((char *)IObuff, IOSIZE,
37823778
_("Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Chars; %lld of %lld Bytes"),
37833779
buf1, line_count_selected,
37843780
(long)curbuf->b_ml.ml_line_count,
3785-
(long_long_T)word_count_cursor,
3786-
(long_long_T)word_count,
3787-
(long_long_T)char_count_cursor,
3788-
(long_long_T)char_count,
3789-
(long_long_T)byte_count_cursor,
3790-
(long_long_T)byte_count);
3781+
(varnumber_T)word_count_cursor,
3782+
(varnumber_T)word_count,
3783+
(varnumber_T)char_count_cursor,
3784+
(varnumber_T)char_count,
3785+
(varnumber_T)byte_count_cursor,
3786+
(varnumber_T)byte_count);
37913787
}
37923788
else
37933789
{
@@ -3805,17 +3801,17 @@ cursor_pos_info(dict_T *dict)
38053801
(char *)buf1, (char *)buf2,
38063802
(long)curwin->w_cursor.lnum,
38073803
(long)curbuf->b_ml.ml_line_count,
3808-
(long_long_T)word_count_cursor, (long_long_T)word_count,
3809-
(long_long_T)byte_count_cursor, (long_long_T)byte_count);
3804+
(varnumber_T)word_count_cursor, (varnumber_T)word_count,
3805+
(varnumber_T)byte_count_cursor, (varnumber_T)byte_count);
38103806
else
38113807
vim_snprintf((char *)IObuff, IOSIZE,
38123808
_("Col %s of %s; Line %ld of %ld; Word %lld of %lld; Char %lld of %lld; Byte %lld of %lld"),
38133809
(char *)buf1, (char *)buf2,
38143810
(long)curwin->w_cursor.lnum,
38153811
(long)curbuf->b_ml.ml_line_count,
3816-
(long_long_T)word_count_cursor, (long_long_T)word_count,
3817-
(long_long_T)char_count_cursor, (long_long_T)char_count,
3818-
(long_long_T)byte_count_cursor, (long_long_T)byte_count);
3812+
(varnumber_T)word_count_cursor, (varnumber_T)word_count,
3813+
(varnumber_T)char_count_cursor, (varnumber_T)char_count,
3814+
(varnumber_T)byte_count_cursor, (varnumber_T)byte_count);
38193815
}
38203816
}
38213817

@@ -3825,7 +3821,7 @@ cursor_pos_info(dict_T *dict)
38253821
size_t len = STRLEN(IObuff);
38263822

38273823
vim_snprintf((char *)IObuff + len, IOSIZE - len,
3828-
_("(+%lld for BOM)"), (long_long_T)bom_count);
3824+
_("(+%lld for BOM)"), (varnumber_T)bom_count);
38293825
}
38303826
if (dict == NULL)
38313827
{

src/structs.h

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,30 +1248,40 @@ typedef long_u hash_T; // Type for hi_hash
12481248
// Use 64-bit Number.
12491249
#ifdef MSWIN
12501250
# ifdef PROTO
1251-
typedef long varnumber_T;
1252-
typedef unsigned long uvarnumber_T;
1253-
# define VARNUM_MIN LONG_MIN
1254-
# define VARNUM_MAX LONG_MAX
1255-
# define UVARNUM_MAX ULONG_MAX
1251+
// workaround for cproto that doesn't recognize __int64
1252+
typedef long varnumber_T;
1253+
typedef unsigned long uvarnumber_T;
1254+
# define VARNUM_MIN LONG_MIN
1255+
# define VARNUM_MAX LONG_MAX
1256+
# define UVARNUM_MAX ULONG_MAX
12561257
# else
1257-
typedef __int64 varnumber_T;
1258-
typedef unsigned __int64 uvarnumber_T;
1259-
# define VARNUM_MIN _I64_MIN
1260-
# define VARNUM_MAX _I64_MAX
1261-
# define UVARNUM_MAX _UI64_MAX
1258+
typedef __int64 varnumber_T;
1259+
typedef unsigned __int64 uvarnumber_T;
1260+
# define VARNUM_MIN _I64_MIN
1261+
# define VARNUM_MAX _I64_MAX
1262+
# define UVARNUM_MAX _UI64_MAX
1263+
# endif
1264+
#elif defined(HAVE_NO_LONG_LONG)
1265+
# if defined(HAVE_STDINT_H)
1266+
typedef int64_t varnumber_T;
1267+
typedef uint64_t uvarnumber_T;
1268+
# define VARNUM_MIN INT64_MIN
1269+
# define VARNUM_MAX INT64_MAX
1270+
# define UVARNUM_MAX UINT64_MAX
1271+
# else
1272+
// this may cause trouble for code that depends on 64 bit ints
1273+
typedef long varnumber_T;
1274+
typedef unsigned long uvarnumber_T;
1275+
# define VARNUM_MIN LONG_MIN
1276+
# define VARNUM_MAX LONG_MAX
1277+
# define UVARNUM_MAX ULONG_MAX
12621278
# endif
1263-
#elif defined(HAVE_STDINT_H)
1264-
typedef int64_t varnumber_T;
1265-
typedef uint64_t uvarnumber_T;
1266-
# define VARNUM_MIN INT64_MIN
1267-
# define VARNUM_MAX INT64_MAX
1268-
# define UVARNUM_MAX UINT64_MAX
12691279
#else
1270-
typedef long varnumber_T;
1271-
typedef unsigned long uvarnumber_T;
1272-
# define VARNUM_MIN LONG_MIN
1273-
# define VARNUM_MAX LONG_MAX
1274-
# define UVARNUM_MAX ULONG_MAX
1280+
typedef long long varnumber_T;
1281+
typedef unsigned long long uvarnumber_T;
1282+
# define VARNUM_MIN LLONG_MIN
1283+
# define VARNUM_MAX LLONG_MAX
1284+
# define UVARNUM_MAX ULLONG_MAX
12751285
#endif
12761286

12771287
typedef double float_T;

src/testdir/test_eval_stuff.vim

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,3 +228,9 @@ func Test_excute_null()
228228
call assert_fails('execute test_null_channel()', 'E908:')
229229
endif
230230
endfunc
231+
232+
func Test_numbersize()
233+
" This will fail on systems without 64 bit int support or when not configured
234+
" correctly.
235+
call assert_equal(64, v:numbersize)
236+
endfunc

0 commit comments

Comments
 (0)