changeset 19477:2bb0e80fcd32 v8.2.0296

patch 8.2.0296: mixing up "long long" and __int64 may cause problems Commit: https://github.com/vim/vim/commit/f9706e9df0e37d214fb08eda30ba29627e97a607 Author: Bram Moolenaar <Bram@vim.org> 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.
author Bram Moolenaar <Bram@vim.org>
date Sat, 22 Feb 2020 14:30:04 +0100
parents 381e5000c519
children 98e759662690
files runtime/doc/eval.txt runtime/doc/various.txt src/eval.c src/evalvars.c src/fileio.c src/json.c src/message.c src/ops.c src/structs.h src/testdir/test_eval_stuff.vim src/version.c src/vim.h
diffstat 12 files changed, 108 insertions(+), 96 deletions(-) [+]
line wrap: on
line diff
--- 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.
--- 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'
--- 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:
--- 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);
--- 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);
     }
 }
 
--- 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;
 
--- 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
--- 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)
 	{
--- 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;
--- 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
--- 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,
--- 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