# HG changeset patch # User Bram Moolenaar # Date 1582378204 -3600 # Node ID 2bb0e80fcd32433b9d113489c0c2f8b3cb225c6d # Parent 381e5000c51947513f700bb9add78873fda552b8 patch 8.2.0296: mixing up "long long" and __int64 may cause problems Commit: https://github.com/vim/vim/commit/f9706e9df0e37d214fb08eda30ba29627e97a607 Author: Bram Moolenaar Date: Sat Feb 22 14:27:04 2020 +0100 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. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -48,8 +48,7 @@ There are ten types of variables: *Number* *Integer* Number A 32 or 64 bit signed number. |expr-number| - 64-bit Numbers are available only when compiled with the - |+num64| feature. + The number of bits is available in |v:numbersize|. Examples: -123 0x10 0177 0b1011 Float A floating point number. |floating-point-format| *Float* @@ -1991,6 +1990,10 @@ v:null An empty String. Used to put "nu That is so that eval() can parse the string back to the same value. Read-only. + *v:numbersize* *numbersize-variable* +v:numbersize Number of bits in a Number. This is normally 64, but on some + systems it my be 32. + *v:oldfiles* *oldfiles-variable* v:oldfiles List of file names that is loaded from the |viminfo| file on startup. These are the files that Vim remembers marks for. diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -1,4 +1,4 @@ -*various.txt* For Vim version 8.2. Last change: 2019 Dec 07 +*various.txt* For Vim version 8.2. Last change: 2020 Feb 22 VIM REFERENCE MANUAL by Bram Moolenaar @@ -407,7 +407,9 @@ N *+multi_lang* non-English language su m *+mzscheme* Mzscheme interface |mzscheme| m *+mzscheme/dyn* Mzscheme interface |mzscheme-dynamic| |/dyn| m *+netbeans_intg* |netbeans| - *+num64* 64-bit Number support |Number| + *+num64* 64-bit Number support |Number| + Always enabled since 8.2.0271, use v:numbersize to + check the actual size of a Number. m *+ole* Win32 GUI only: |ole-interface| N *+packages* Loading |packages| N *+path_extra* Up/downwards search in 'path' and 'tags' diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -5665,7 +5665,7 @@ tv_get_string_buf_chk(typval_T *varp, ch { case VAR_NUMBER: vim_snprintf((char *)buf, NUMBUFLEN, "%lld", - (long_long_T)varp->vval.v_number); + (varnumber_T)varp->vval.v_number); return buf; case VAR_FUNC: case VAR_PARTIAL: diff --git a/src/evalvars.c b/src/evalvars.c --- a/src/evalvars.c +++ b/src/evalvars.c @@ -120,8 +120,9 @@ static struct vimvar {VV_NAME("errors", VAR_LIST), 0}, {VV_NAME("false", VAR_BOOL), VV_RO}, {VV_NAME("true", VAR_BOOL), VV_RO}, + {VV_NAME("none", VAR_SPECIAL), VV_RO}, {VV_NAME("null", VAR_SPECIAL), VV_RO}, - {VV_NAME("none", VAR_SPECIAL), VV_RO}, + {VV_NAME("numbersize", VAR_NUMBER), VV_RO}, {VV_NAME("vim_did_enter", VAR_NUMBER), VV_RO}, {VV_NAME("testing", VAR_NUMBER), 0}, {VV_NAME("t_number", VAR_NUMBER), VV_RO}, @@ -229,6 +230,7 @@ evalvars_init(void) set_vim_var_nr(VV_TRUE, VVAL_TRUE); set_vim_var_nr(VV_NONE, VVAL_NONE); set_vim_var_nr(VV_NULL, VVAL_NULL); + set_vim_var_nr(VV_NUMBERSIZE, sizeof(varnumber_T) * 8); set_vim_var_nr(VV_TYPE_NUMBER, VAR_TYPE_NUMBER); set_vim_var_nr(VV_TYPE_STRING, VAR_TYPE_STRING); diff --git a/src/fileio.c b/src/fileio.c --- a/src/fileio.c +++ b/src/fileio.c @@ -3016,14 +3016,14 @@ msg_add_lines( *p++ = ' '; if (shortmess(SHM_LINES)) vim_snprintf((char *)p, IOSIZE - (p - IObuff), - "%ldL, %lldC", lnum, (long_long_T)nchars); + "%ldL, %lldC", lnum, (varnumber_T)nchars); else { sprintf((char *)p, NGETTEXT("%ld line, ", "%ld lines, ", lnum), lnum); p += STRLEN(p); vim_snprintf((char *)p, IOSIZE - (p - IObuff), NGETTEXT("%lld character", "%lld characters", nchars), - (long_long_T)nchars); + (varnumber_T)nchars); } } diff --git a/src/json.c b/src/json.c --- a/src/json.c +++ b/src/json.c @@ -215,7 +215,7 @@ json_encode_item(garray_T *gap, typval_T case VAR_NUMBER: vim_snprintf((char *)numbuf, NUMBUFLEN, "%lld", - (long_long_T)val->vval.v_number); + (varnumber_T)val->vval.v_number); ga_concat(gap, numbuf); break; diff --git a/src/message.c b/src/message.c --- a/src/message.c +++ b/src/message.c @@ -4129,7 +4129,7 @@ infinity_str(int positive, * Limited support for floating point was added: 'f', 'F', 'e', 'E', 'g', 'G'. * * Length modifiers 'h' (short int) and 'l' (long int) and 'll' (long long int) - * are supported. + * are supported. NOTE: for 'll' the argument is varnumber_T or uvarnumber_T. * * The locale is not used, the string is used as a byte string. This is only * relevant for double-byte encodings where the second byte may be '%'. @@ -4371,7 +4371,7 @@ vim_vsnprintf_typval( p++; if (length_modifier == 'l' && *p == 'l') { - // double l = long long + // double l = __int64 / varnumber_T length_modifier = 'L'; p++; } @@ -4501,20 +4501,20 @@ vim_vsnprintf_typval( // argument is never negative) int arg_sign = 0; - // only defined for length modifier h, or for no - // length modifiers + // only set for length modifier h, or for no length + // modifiers int int_arg = 0; unsigned int uint_arg = 0; - // only defined for length modifier l + // only set for length modifier l long int long_arg = 0; unsigned long int ulong_arg = 0; - // only defined for length modifier ll + // only set for length modifier ll varnumber_T llong_arg = 0; uvarnumber_T ullong_arg = 0; - // only defined for b conversion + // only set for b conversion uvarnumber_T bin_arg = 0; // pointer argument value -only defined for p diff --git a/src/ops.c b/src/ops.c --- a/src/ops.c +++ b/src/ops.c @@ -3364,17 +3364,13 @@ do_addsub( buf2[i] = '\0'; } else if (pre == 0) - vim_snprintf((char *)buf2, NUMBUFLEN, "%llu", - (long_long_u_T)n); + vim_snprintf((char *)buf2, NUMBUFLEN, "%llu", (uvarnumber_T)n); else if (pre == '0') - vim_snprintf((char *)buf2, NUMBUFLEN, "%llo", - (long_long_u_T)n); + vim_snprintf((char *)buf2, NUMBUFLEN, "%llo", (uvarnumber_T)n); else if (pre && hexupper) - vim_snprintf((char *)buf2, NUMBUFLEN, "%llX", - (long_long_u_T)n); + vim_snprintf((char *)buf2, NUMBUFLEN, "%llX", (uvarnumber_T)n); else - vim_snprintf((char *)buf2, NUMBUFLEN, "%llx", - (long_long_u_T)n); + vim_snprintf((char *)buf2, NUMBUFLEN, "%llx", (uvarnumber_T)n); length -= (int)STRLEN(buf2); /* @@ -3773,21 +3769,21 @@ cursor_pos_info(dict_T *dict) _("Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Bytes"), buf1, line_count_selected, (long)curbuf->b_ml.ml_line_count, - (long_long_T)word_count_cursor, - (long_long_T)word_count, - (long_long_T)byte_count_cursor, - (long_long_T)byte_count); + (varnumber_T)word_count_cursor, + (varnumber_T)word_count, + (varnumber_T)byte_count_cursor, + (varnumber_T)byte_count); else vim_snprintf((char *)IObuff, IOSIZE, _("Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Chars; %lld of %lld Bytes"), buf1, line_count_selected, (long)curbuf->b_ml.ml_line_count, - (long_long_T)word_count_cursor, - (long_long_T)word_count, - (long_long_T)char_count_cursor, - (long_long_T)char_count, - (long_long_T)byte_count_cursor, - (long_long_T)byte_count); + (varnumber_T)word_count_cursor, + (varnumber_T)word_count, + (varnumber_T)char_count_cursor, + (varnumber_T)char_count, + (varnumber_T)byte_count_cursor, + (varnumber_T)byte_count); } else { @@ -3805,17 +3801,17 @@ cursor_pos_info(dict_T *dict) (char *)buf1, (char *)buf2, (long)curwin->w_cursor.lnum, (long)curbuf->b_ml.ml_line_count, - (long_long_T)word_count_cursor, (long_long_T)word_count, - (long_long_T)byte_count_cursor, (long_long_T)byte_count); + (varnumber_T)word_count_cursor, (varnumber_T)word_count, + (varnumber_T)byte_count_cursor, (varnumber_T)byte_count); else vim_snprintf((char *)IObuff, IOSIZE, _("Col %s of %s; Line %ld of %ld; Word %lld of %lld; Char %lld of %lld; Byte %lld of %lld"), (char *)buf1, (char *)buf2, (long)curwin->w_cursor.lnum, (long)curbuf->b_ml.ml_line_count, - (long_long_T)word_count_cursor, (long_long_T)word_count, - (long_long_T)char_count_cursor, (long_long_T)char_count, - (long_long_T)byte_count_cursor, (long_long_T)byte_count); + (varnumber_T)word_count_cursor, (varnumber_T)word_count, + (varnumber_T)char_count_cursor, (varnumber_T)char_count, + (varnumber_T)byte_count_cursor, (varnumber_T)byte_count); } } @@ -3825,7 +3821,7 @@ cursor_pos_info(dict_T *dict) size_t len = STRLEN(IObuff); vim_snprintf((char *)IObuff + len, IOSIZE - len, - _("(+%lld for BOM)"), (long_long_T)bom_count); + _("(+%lld for BOM)"), (varnumber_T)bom_count); } if (dict == NULL) { diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -1248,30 +1248,40 @@ typedef long_u hash_T; // Type for hi_h // Use 64-bit Number. #ifdef MSWIN # ifdef PROTO -typedef long varnumber_T; -typedef unsigned long uvarnumber_T; -# define VARNUM_MIN LONG_MIN -# define VARNUM_MAX LONG_MAX -# define UVARNUM_MAX ULONG_MAX + // workaround for cproto that doesn't recognize __int64 + typedef long varnumber_T; + typedef unsigned long uvarnumber_T; +# define VARNUM_MIN LONG_MIN +# define VARNUM_MAX LONG_MAX +# define UVARNUM_MAX ULONG_MAX # else -typedef __int64 varnumber_T; -typedef unsigned __int64 uvarnumber_T; -# define VARNUM_MIN _I64_MIN -# define VARNUM_MAX _I64_MAX -# define UVARNUM_MAX _UI64_MAX + typedef __int64 varnumber_T; + typedef unsigned __int64 uvarnumber_T; +# define VARNUM_MIN _I64_MIN +# define VARNUM_MAX _I64_MAX +# define UVARNUM_MAX _UI64_MAX # endif -#elif defined(HAVE_STDINT_H) -typedef int64_t varnumber_T; -typedef uint64_t uvarnumber_T; -# define VARNUM_MIN INT64_MIN -# define VARNUM_MAX INT64_MAX -# define UVARNUM_MAX UINT64_MAX +#elif defined(HAVE_NO_LONG_LONG) +# if defined(HAVE_STDINT_H) + typedef int64_t varnumber_T; + typedef uint64_t uvarnumber_T; +# define VARNUM_MIN INT64_MIN +# define VARNUM_MAX INT64_MAX +# define UVARNUM_MAX UINT64_MAX +# else + // this may cause trouble for code that depends on 64 bit ints + typedef long varnumber_T; + typedef unsigned long uvarnumber_T; +# define VARNUM_MIN LONG_MIN +# define VARNUM_MAX LONG_MAX +# define UVARNUM_MAX ULONG_MAX +# endif #else -typedef long varnumber_T; -typedef unsigned long uvarnumber_T; -# define VARNUM_MIN LONG_MIN -# define VARNUM_MAX LONG_MAX -# define UVARNUM_MAX ULONG_MAX + typedef long long varnumber_T; + typedef unsigned long long uvarnumber_T; +# define VARNUM_MIN LLONG_MIN +# define VARNUM_MAX LLONG_MAX +# define UVARNUM_MAX ULLONG_MAX #endif typedef double float_T; diff --git a/src/testdir/test_eval_stuff.vim b/src/testdir/test_eval_stuff.vim --- a/src/testdir/test_eval_stuff.vim +++ b/src/testdir/test_eval_stuff.vim @@ -228,3 +228,9 @@ func Test_excute_null() call assert_fails('execute test_null_channel()', 'E908:') endif endfunc + +func Test_numbersize() + " This will fail on systems without 64 bit int support or when not configured + " correctly. + call assert_equal(64, v:numbersize) +endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -739,6 +739,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 296, +/**/ 295, /**/ 294, diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -328,16 +328,6 @@ typedef unsigned char char_u; typedef unsigned short short_u; typedef unsigned int int_u; -// Older systems do not have support for long long -// use a typedef instead of hard-coded long long -#ifdef HAVE_NO_LONG_LONG - typedef long long_long_T; - typedef long unsigned long_long_u_T; -#else - typedef long long long_long_T; - typedef long long unsigned long_long_u_T; -#endif - // Make sure long_u is big enough to hold a pointer. // On Win64, longs are 32 bits and pointers are 64 bits. // For printf() and scanf(), we need to take care of long_u specifically. @@ -1975,31 +1965,32 @@ typedef int sock_T; #define VV_ERRORS 67 #define VV_FALSE 68 #define VV_TRUE 69 -#define VV_NULL 70 -#define VV_NONE 71 -#define VV_VIM_DID_ENTER 72 -#define VV_TESTING 73 -#define VV_TYPE_NUMBER 74 -#define VV_TYPE_STRING 75 -#define VV_TYPE_FUNC 76 -#define VV_TYPE_LIST 77 -#define VV_TYPE_DICT 78 -#define VV_TYPE_FLOAT 79 -#define VV_TYPE_BOOL 80 -#define VV_TYPE_NONE 81 -#define VV_TYPE_JOB 82 -#define VV_TYPE_CHANNEL 83 -#define VV_TYPE_BLOB 84 -#define VV_TERMRFGRESP 85 -#define VV_TERMRBGRESP 86 -#define VV_TERMU7RESP 87 -#define VV_TERMSTYLERESP 88 -#define VV_TERMBLINKRESP 89 -#define VV_EVENT 90 -#define VV_VERSIONLONG 91 -#define VV_ECHOSPACE 92 -#define VV_ARGV 93 -#define VV_LEN 94 // number of v: vars +#define VV_NONE 70 +#define VV_NULL 71 +#define VV_NUMBERSIZE 72 +#define VV_VIM_DID_ENTER 73 +#define VV_TESTING 74 +#define VV_TYPE_NUMBER 75 +#define VV_TYPE_STRING 76 +#define VV_TYPE_FUNC 77 +#define VV_TYPE_LIST 78 +#define VV_TYPE_DICT 79 +#define VV_TYPE_FLOAT 80 +#define VV_TYPE_BOOL 81 +#define VV_TYPE_NONE 82 +#define VV_TYPE_JOB 83 +#define VV_TYPE_CHANNEL 84 +#define VV_TYPE_BLOB 85 +#define VV_TERMRFGRESP 86 +#define VV_TERMRBGRESP 87 +#define VV_TERMU7RESP 88 +#define VV_TERMSTYLERESP 89 +#define VV_TERMBLINKRESP 90 +#define VV_EVENT 91 +#define VV_VERSIONLONG 92 +#define VV_ECHOSPACE 93 +#define VV_ARGV 94 +#define VV_LEN 95 // number of v: vars // used for v_number in VAR_BOOL and VAR_SPECIAL #define VVAL_FALSE 0L // VAR_BOOL