changeset 36366:c57c92a46534 draft v9.1.0803

patch 9.1.0803: tests: no error check when setting global 'isk' Commit: https://github.com/vim/vim/commit/5e7a6a4a106923e45c67dae6810e4c9753f88025 Author: Milly <milly.ca@gmail.com> Date: Tue Oct 22 22:27:19 2024 +0200 patch 9.1.0803: tests: no error check when setting global 'isk' Problem: tests: no error check when setting global 'isk' Solution: also parse and check global 'isk' value (Milly) closes: #15915 Signed-off-by: Milly <milly.ca@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
author Christian Brabandt <cb@256bit.org>
date Tue, 22 Oct 2024 22:30:03 +0200
parents fc26d11e435f
children 5bc2cab29bfd
files src/charset.c src/optiondefs.h src/optionstr.c src/proto/charset.pro src/proto/optionstr.pro src/testdir/gen_opt_test.vim src/version.c
diffstat 7 files changed, 153 insertions(+), 97 deletions(-) [+]
line wrap: on
line diff
--- a/src/charset.c
+++ b/src/charset.c
@@ -13,6 +13,7 @@
 # include <wchar.h>	    // for towupper() and towlower()
 #endif
 
+static int parse_isopt(char_u *var, buf_T *buf, int only_check);
 static int win_nolbr_chartabsize(chartabsize_T *cts, int *headp);
 static unsigned nr2hex(unsigned c);
 
@@ -75,11 +76,8 @@ buf_init_chartab(
     int		global)		// FALSE: only set buf->b_chartab[]
 {
     int		c;
-    int		c2;
     char_u	*p;
     int		i;
-    int		tilde;
-    int		do_isalpha;
 
     if (global)
     {
@@ -135,9 +133,7 @@ buf_init_chartab(
     if (buf->b_p_lisp)
 	SET_CHARTAB(buf, '-');
 
-    // Walk through the 'isident', 'iskeyword', 'isfname' and 'isprint'
-    // options Each option is a list of characters, character numbers or
-    // ranges, separated by commas, e.g.: "200-210,x,#-178,-"
+    // Walk through the 'isident', 'iskeyword', 'isfname' and 'isprint' options.
     for (i = global ? 0 : 3; i <= 3; ++i)
     {
 	if (i == 0)
@@ -149,114 +145,152 @@ buf_init_chartab(
 	else	// i == 3
 	    p = buf->b_p_isk;	// fourth round: 'iskeyword'
 
-	while (*p)
+	if (parse_isopt(p, buf, FALSE) == FAIL)
+	    return FAIL;
+    }
+
+    chartab_initialized = TRUE;
+    return OK;
+}
+
+/**
+ * Checks the format for the option settings 'iskeyword', 'isident', 'isfname'
+ * or 'isprint'.
+ * Returns FAIL if has an error, OK otherwise.
+ */
+	int
+check_isopt(char_u *var)
+{
+    return parse_isopt(var, NULL, TRUE);
+}
+
+    static int
+parse_isopt(
+	char_u	*var,
+	buf_T	*buf,
+	int	only_check)	// FALSE: refill g_chartab[]
+{
+    char_u	*p = var;
+    int		c;
+    int		c2;
+    int		tilde;
+    int		do_isalpha;
+    int		trail_comma;
+
+    // Parses the 'isident', 'iskeyword', 'isfname' and 'isprint' options.
+    // Each option is a list of characters, character numbers or ranges,
+    // separated by commas, e.g.: "200-210,x,#-178,-"
+    while (*p)
+    {
+	tilde = FALSE;
+	do_isalpha = FALSE;
+	if (*p == '^' && p[1] != NUL)
 	{
-	    tilde = FALSE;
-	    do_isalpha = FALSE;
-	    if (*p == '^' && p[1] != NUL)
-	    {
-		tilde = TRUE;
-		++p;
-	    }
+	    tilde = TRUE;
+	    ++p;
+	}
+	if (VIM_ISDIGIT(*p))
+	    c = getdigits(&p);
+	else if (has_mbyte)
+	    c = mb_ptr2char_adv(&p);
+	else
+	    c = *p++;
+	c2 = -1;
+	if (*p == '-' && p[1] != NUL)
+	{
+	    ++p;
 	    if (VIM_ISDIGIT(*p))
-		c = getdigits(&p);
+		c2 = getdigits(&p);
 	    else if (has_mbyte)
-		c = mb_ptr2char_adv(&p);
+		c2 = mb_ptr2char_adv(&p);
 	    else
-		c = *p++;
-	    c2 = -1;
-	    if (*p == '-' && p[1] != NUL)
+		c2 = *p++;
+	}
+	if (c <= 0 || c >= 256 || (c2 < c && c2 != -1) || c2 >= 256
+						  || !(*p == NUL || *p == ','))
+	    return FAIL;
+
+	trail_comma = *p == ',';
+	p = skip_to_option_part(p);
+	if (trail_comma && *p == NUL)
+	    // Trailing comma is not allowed.
+	    return FAIL;
+
+	if (only_check)
+	    continue;
+
+	if (c2 == -1)	// not a range
+	{
+	    /*
+	     * A single '@' (not "@-@"):
+	     * Decide on letters being ID/printable/keyword chars with
+	     * standard function isalpha(). This takes care of locale for
+	     * single-byte characters).
+	     */
+	    if (c == '@')
 	    {
-		++p;
-		if (VIM_ISDIGIT(*p))
-		    c2 = getdigits(&p);
-		else if (has_mbyte)
-		    c2 = mb_ptr2char_adv(&p);
-		else
-		    c2 = *p++;
+		do_isalpha = TRUE;
+		c = 1;
+		c2 = 255;
 	    }
-	    if (c <= 0 || c >= 256 || (c2 < c && c2 != -1) || c2 >= 256
-						 || !(*p == NUL || *p == ','))
-		return FAIL;
+	    else
+		c2 = c;
+	}
 
-	    if (c2 == -1)	// not a range
+	while (c <= c2)
+	{
+	    // Use the MB_ functions here, because isalpha() doesn't
+	    // work properly when 'encoding' is "latin1" and the locale is
+	    // "C".
+	    if (!do_isalpha || MB_ISLOWER(c) || MB_ISUPPER(c))
 	    {
-		/*
-		 * A single '@' (not "@-@"):
-		 * Decide on letters being ID/printable/keyword chars with
-		 * standard function isalpha(). This takes care of locale for
-		 * single-byte characters).
-		 */
-		if (c == '@')
+		if (var == p_isi)			// (re)set ID flag
 		{
-		    do_isalpha = TRUE;
-		    c = 1;
-		    c2 = 255;
+		    if (tilde)
+			g_chartab[c] &= ~CT_ID_CHAR;
+		    else
+			g_chartab[c] |= CT_ID_CHAR;
 		}
-		else
-		    c2 = c;
-	    }
-	    while (c <= c2)
-	    {
-		// Use the MB_ functions here, because isalpha() doesn't
-		// work properly when 'encoding' is "latin1" and the locale is
-		// "C".
-		if (!do_isalpha || MB_ISLOWER(c) || MB_ISUPPER(c))
+		else if (var == p_isp)			// (re)set printable
 		{
-		    if (i == 0)			// (re)set ID flag
+		    if ((c < ' ' || c > '~'
+			    // For double-byte we keep the cell width, so
+			    // that we can detect it from the first byte.
+			) && !(enc_dbcs && MB_BYTE2LEN(c) == 2))
 		    {
 			if (tilde)
-			    g_chartab[c] &= ~CT_ID_CHAR;
-			else
-			    g_chartab[c] |= CT_ID_CHAR;
-		    }
-		    else if (i == 1)		// (re)set printable
-		    {
-			if ((c < ' ' || c > '~'
-				// For double-byte we keep the cell width, so
-				// that we can detect it from the first byte.
-			    ) && !(enc_dbcs && MB_BYTE2LEN(c) == 2))
 			{
-			    if (tilde)
-			    {
-				g_chartab[c] = (g_chartab[c] & ~CT_CELL_MASK)
-					     + ((dy_flags & DY_UHEX) ? 4 : 2);
-				g_chartab[c] &= ~CT_PRINT_CHAR;
-			    }
-			    else
-			    {
-				g_chartab[c] = (g_chartab[c] & ~CT_CELL_MASK)
-									   + 1;
-				g_chartab[c] |= CT_PRINT_CHAR;
-			    }
+			    g_chartab[c] = (g_chartab[c] & ~CT_CELL_MASK)
+					 + ((dy_flags & DY_UHEX) ? 4 : 2);
+			    g_chartab[c] &= ~CT_PRINT_CHAR;
+			}
+			else
+			{
+			    g_chartab[c] = (g_chartab[c] & ~CT_CELL_MASK) + 1;
+			    g_chartab[c] |= CT_PRINT_CHAR;
 			}
 		    }
-		    else if (i == 2)		// (re)set fname flag
-		    {
-			if (tilde)
-			    g_chartab[c] &= ~CT_FNAME_CHAR;
-			else
-			    g_chartab[c] |= CT_FNAME_CHAR;
-		    }
-		    else // i == 3		 (re)set keyword flag
-		    {
-			if (tilde)
-			    RESET_CHARTAB(buf, c);
-			else
-			    SET_CHARTAB(buf, c);
-		    }
+		}
+		else if (var == p_isf)			// (re)set fname flag
+		{
+		    if (tilde)
+			g_chartab[c] &= ~CT_FNAME_CHAR;
+		    else
+			g_chartab[c] |= CT_FNAME_CHAR;
 		}
-		++c;
+		else // var == p_isk || var == buf->b_p_isk
+							// (re)set keyword flag
+		{
+		    if (tilde)
+			RESET_CHARTAB(buf, c);
+		    else
+			SET_CHARTAB(buf, c);
+		}
 	    }
-
-	    c = *p;
-	    p = skip_to_option_part(p);
-	    if (c == ',' && *p == NUL)
-		// Trailing comma is not allowed.
-		return FAIL;
+	    ++c;
 	}
     }
-    chartab_initialized = TRUE;
+
     return OK;
 }
 
--- a/src/optiondefs.h
+++ b/src/optiondefs.h
@@ -1456,7 +1456,7 @@ static struct vimoption options[] =
 #endif
 				(char_u *)0L} SCTX_INIT},
     {"iskeyword",   "isk",  P_STRING|P_ALLOCED|P_VIM|P_COMMA|P_NODUP,
-			    (char_u *)&p_isk, PV_ISK, did_set_isopt, NULL,
+			    (char_u *)&p_isk, PV_ISK, did_set_iskeyword, NULL,
 			    {
 				(char_u *)"@,48-57,_",
 #if defined(MSWIN)
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -2775,13 +2775,32 @@ did_set_imactivatekey(optset_T *args UNU
 #endif
 
 /*
+ * The 'iskeyword' option is changed.
+ */
+    char *
+did_set_iskeyword(optset_T *args)
+{
+    char_u	**varp = (char_u **)args->os_varp;
+
+    if (varp == &p_isk)		// only check for global-value
+    {
+	if (check_isopt(*varp) == FAIL)
+	    return e_invalid_argument;
+    }
+    else			// fallthrough for local-value
+	return did_set_isopt(args);
+
+    return NULL;
+}
+
+/*
  * The 'isident' or the 'iskeyword' or the 'isprint' or the 'isfname' option is
  * changed.
  */
     char *
 did_set_isopt(optset_T *args)
 {
-    // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[]
+    // 'isident', 'iskeyword', 'isprint' or 'isfname' option: refill g_chartab[]
     // If the new option is invalid, use old value.
     // 'lisp' option: refill g_chartab[] for '-' char.
     if (init_chartab() == FAIL)
--- a/src/proto/charset.pro
+++ b/src/proto/charset.pro
@@ -1,6 +1,7 @@
 /* charset.c */
 int init_chartab(void);
 int buf_init_chartab(buf_T *buf, int global);
+int check_isopt(char_u *isopt);
 void trans_characters(char_u *buf, int bufsize);
 char_u *transstr(char_u *s);
 char_u *str_foldcase(char_u *str, int orglen, char_u *buf, int buflen);
--- a/src/proto/optionstr.pro
+++ b/src/proto/optionstr.pro
@@ -99,6 +99,7 @@ char *did_set_highlight(optset_T *args);
 int expand_set_highlight(optexpand_T *args, int *numMatches, char_u ***matches);
 char *did_set_iconstring(optset_T *args);
 char *did_set_imactivatekey(optset_T *args);
+char *did_set_iskeyword(optset_T *args);
 char *did_set_isopt(optset_T *args);
 char *did_set_jumpoptions(optset_T *args);
 int expand_set_jumpoptions(optexpand_T *args, int *numMatches, char_u ***matches);
--- a/src/testdir/gen_opt_test.vim
+++ b/src/testdir/gen_opt_test.vim
@@ -49,7 +49,6 @@ let skip_setglobal_reasons = #{
       \ colorcolumn:	'TODO: fix missing error handling for setglobal',
       \ conceallevel:	'TODO: fix missing error handling for setglobal',
       \ foldcolumn:	'TODO: fix missing error handling for setglobal',
-      \ iskeyword:	'TODO: fix missing error handling for setglobal',
       \ numberwidth:	'TODO: fix missing error handling for setglobal',
       \ scrolloff:	'TODO: fix missing error handling for setglobal',
       \ shiftwidth:	'TODO: fix missing error handling for setglobal',
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    803,
+/**/
     802,
 /**/
     801,