patch 8.1.2035: recognizing octal numbers is confusing

Problem:    Recognizing octal numbers is confusing.
Solution:   Introduce scriptversion 4: do not use octal and allow for single
            quote inside numbers.
diff --git a/src/eval.c b/src/eval.c
index acdfac3..680ca1a 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -2617,7 +2617,9 @@
 		else
 		{
 		    // decimal, hex or octal number
-		    vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0, TRUE);
+		    vim_str2nr(*arg, NULL, &len, current_sctx.sc_version >= 4
+				  ? STR2NR_NO_OCT + STR2NR_QUOTE
+				  : STR2NR_ALL, &n, NULL, 0, TRUE);
 		    if (len == 0)
 		    {
 			semsg(_(e_invexpr2), *arg);
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 438aac8..6772692 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -728,7 +728,7 @@
     {"str2float",	1, 1, FEARG_1,	  f_str2float},
 #endif
     {"str2list",	1, 2, FEARG_1,	  f_str2list},
-    {"str2nr",		1, 2, FEARG_1,	  f_str2nr},
+    {"str2nr",		1, 3, FEARG_1,	  f_str2nr},
     {"strcharpart",	2, 3, FEARG_1,	  f_strcharpart},
     {"strchars",	1, 2, FEARG_1,	  f_strchars},
     {"strdisplaywidth",	1, 2, FEARG_1,	  f_strdisplaywidth},
@@ -7323,7 +7323,7 @@
     int		base = 10;
     char_u	*p;
     varnumber_T	n;
-    int		what;
+    int		what = 0;
     int		isneg;
 
     if (argvars[1].v_type != VAR_UNKNOWN)
@@ -7334,6 +7334,8 @@
 	    emsg(_(e_invarg));
 	    return;
 	}
+	if (argvars[2].v_type != VAR_UNKNOWN && tv_get_number(&argvars[2]))
+	    what |= STR2NR_QUOTE;
     }
 
     p = skipwhite(tv_get_string(&argvars[0]));
@@ -7342,10 +7344,9 @@
 	p = skipwhite(p + 1);
     switch (base)
     {
-	case 2: what = STR2NR_BIN + STR2NR_FORCE; break;
-	case 8: what = STR2NR_OCT + STR2NR_FORCE; break;
-	case 16: what = STR2NR_HEX + STR2NR_FORCE; break;
-	default: what = 0;
+	case 2: what |= STR2NR_BIN + STR2NR_FORCE; break;
+	case 8: what |= STR2NR_OCT + STR2NR_FORCE; break;
+	case 16: what |= STR2NR_HEX + STR2NR_FORCE; break;
     }
     vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, FALSE);
     // Text after the number is silently ignored.
diff --git a/src/scriptfile.c b/src/scriptfile.c
index d46b1e0..92db59c 100644
--- a/src/scriptfile.c
+++ b/src/scriptfile.c
@@ -1659,7 +1659,7 @@
     nr = getdigits(&eap->arg);
     if (nr == 0 || *eap->arg != NUL)
 	emsg(_(e_invarg));
-    else if (nr > 3)
+    else if (nr > 4)
 	semsg(_("E999: scriptversion not supported: %d"), nr);
     else
 	current_sctx.sc_version = nr;
diff --git a/src/testdir/test_eval_stuff.vim b/src/testdir/test_eval_stuff.vim
index b518f5a..720f309 100644
--- a/src/testdir/test_eval_stuff.vim
+++ b/src/testdir/test_eval_stuff.vim
@@ -74,7 +74,7 @@
   new
   call setline(1, ['one', 'two', 'three'])
   setlocal ff=dos
-  write XReadfile
+  silent write XReadfile
   let lines = 'XReadfile'->readfile()
   call assert_equal(['one', 'two', 'three'], lines)
   let lines = readfile('XReadfile', '', 2)
@@ -124,6 +124,15 @@
   call assert_equal('ab', a)
 endfunc
 
+" Test fix for issue #4507
+func Test_skip_after_throw()
+  try
+    throw 'something'
+    let x = wincol() || &ts
+  catch /something/
+  endtry
+endfunc
+
 scriptversion 2
 func Test_string_concat_scriptversion2()
   call assert_true(has('vimscript-2'))
@@ -183,17 +192,23 @@
   call assert_true(1 && l:x.foo)
 endfunc
 
-func Test_scriptversion()
+scriptversion 4
+func Test_vvar_scriptversion4()
+  call assert_equal(17, 017)
+  call assert_equal(18, 018)
+  call assert_equal(64, 0b1'00'00'00)
+  call assert_equal(1048576, 0x10'00'00)
+  call assert_equal(1000000, 1'000'000)
+endfunc
+
+scriptversion 1
+func Test_vvar_scriptversion1()
+  call assert_equal(15, 017)
+  call assert_equal(18, 018)
+endfunc
+
+func Test_scriptversion_fail()
   call writefile(['scriptversion 9'], 'Xversionscript')
   call assert_fails('source Xversionscript', 'E999:')
   call delete('Xversionscript')
 endfunc
-
-" Test fix for issue #4507
-func Test_skip_after_throw()
-  try
-    throw 'something'
-    let x = wincol() || &ts
-  catch /something/
-  endtry
-endfunc
diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim
index 2e051bb..e782061 100644
--- a/src/testdir/test_functions.vim
+++ b/src/testdir/test_functions.vim
@@ -157,6 +157,12 @@
   call assert_equal(11259375, str2nr('0XABCDEF', 16))
   call assert_equal(-11259375, str2nr('-0xABCDEF', 16))
 
+  call assert_equal(1, str2nr("1'000'000", 10, 0))
+  call assert_equal(256, str2nr("1'0000'0000", 2, 1))
+  call assert_equal(262144, str2nr("1'000'000", 8, 1))
+  call assert_equal(1000000, str2nr("1'000'000", 10, 1))
+  call assert_equal(65536, str2nr("1'00'00", 16, 1))
+
   call assert_equal(0, str2nr('0x10'))
   call assert_equal(0, str2nr('0b10'))
   call assert_equal(1, str2nr('12', 2))
diff --git a/src/version.c b/src/version.c
index 69c77d8..09baa53 100644
--- a/src/version.c
+++ b/src/version.c
@@ -758,6 +758,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2035,
+/**/
     2034,
 /**/
     2033,
diff --git a/src/vim.h b/src/vim.h
index 46ca693..8afa933 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -307,11 +307,15 @@
 #define NUMBUFLEN 65
 
 // flags for vim_str2nr()
-#define STR2NR_BIN 1
-#define STR2NR_OCT 2
-#define STR2NR_HEX 4
+#define STR2NR_BIN 0x01
+#define STR2NR_OCT 0x02
+#define STR2NR_HEX 0x04
 #define STR2NR_ALL (STR2NR_BIN + STR2NR_OCT + STR2NR_HEX)
-#define STR2NR_FORCE 8 // only when ONE of the above is used
+#define STR2NR_NO_OCT (STR2NR_BIN + STR2NR_HEX)
+
+#define STR2NR_FORCE 0x80   // only when ONE of the above is used
+
+#define STR2NR_QUOTE 0x10   // ignore embedded single quotes
 
 /*
  * Shorthand for unsigned variables. Many systems, but not all, have u_char