patch 9.1.0870: too many strlen() calls in eval.c

Problem:  too many strlen() calls in eval.c
Solution: Refactor eval.c to remove calls to STRLEN()
          (John Marriott)

closes: #16066

Signed-off-by: John Marriott <basilisk@internode.on.net>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/eval.c b/src/eval.c
index cc289b4..fabe964 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -375,14 +375,12 @@
 {
     if (expr->v_type == VAR_PARTIAL)
 	return eval_expr_partial(expr, argv, argc, fc_arg, rettv);
-    else if (expr->v_type == VAR_INSTR)
+    if (expr->v_type == VAR_INSTR)
 	return exe_typval_instr(expr, rettv);
-    else if (expr->v_type == VAR_FUNC || want_func)
+    if (expr->v_type == VAR_FUNC || want_func)
 	return eval_expr_func(expr, argv, argc, rettv);
-    else
-	return eval_expr_string(expr, rettv);
 
-    return OK;
+    return eval_expr_string(expr, rettv);
 }
 
 /*
@@ -2248,7 +2246,7 @@
 
 	    // handle +=, -=, *=, /=, %= and .=
 	    di = NULL;
-	    if (eval_variable(lp->ll_name, (int)STRLEN(lp->ll_name),
+	    if (eval_variable(lp->ll_name, (int)(lp->ll_name_end - lp->ll_name),
 				 lp->ll_sid, &tv, &di, EVAL_VAR_VERBOSE) == OK)
 	    {
 		if (di != NULL && check_typval_is_value(&di->di_tv) == FAIL)
@@ -6153,18 +6151,33 @@
 class_tv2string(typval_T *tv, char_u **tofree)
 {
     char_u	*r = NULL;
+    size_t	rsize;
     class_T	*cl = tv->vval.v_class;
+    char_u	*class_name = (char_u *)"[unknown]";
+    size_t	class_namelen = 9;
     char	*s = "class";
+    size_t	slen = 5;
 
-    if (cl != NULL && IS_INTERFACE(cl))
-	s = "interface";
-    else if (cl != NULL && IS_ENUM(cl))
-	s = "enum";
-    size_t len = STRLEN(s) + 1 +
-				(cl == NULL ? 9 : STRLEN(cl->class_name)) + 1;
-    r = *tofree = alloc(len);
-    vim_snprintf((char *)r, len, "%s %s", s,
-			cl == NULL ? "[unknown]" : (char *)cl->class_name);
+    if (cl != NULL)
+    {
+	class_name = cl->class_name;
+	class_namelen = STRLEN(cl->class_name);
+	if (IS_INTERFACE(cl))
+	{
+	    s = "interface";
+	    slen = 9;
+	}
+	else if (IS_ENUM(cl))
+	{
+	    s = "enum";
+	    slen = 4;
+	}
+    }
+
+    rsize = slen + 1 + class_namelen + 1;
+    r = *tofree = alloc(rsize);
+    if (r != NULL)
+	vim_snprintf((char *)r, rsize, "%s %s", s, (char *)class_name);
 
     return r;
 }
@@ -6197,7 +6210,7 @@
     else if (copyID != 0 && obj->obj_copyID == copyID
 	    && obj->obj_class->class_obj_member_count != 0)
     {
-	size_t n = 25 + strlen((char *)obj->obj_class->class_name);
+	size_t n = 25 + STRLEN((char *)obj->obj_class->class_name);
 	r = alloc(n);
 	if (r != NULL)
 	    (void)vim_snprintf((char *)r, n, "object of %s {...}",
@@ -6911,14 +6924,14 @@
     temp_result = eval_to_string(expr_start + 1, FALSE, FALSE);
     if (temp_result != NULL)
     {
-	retval = alloc(STRLEN(temp_result) + (expr_start - in_start)
-						   + (in_end - expr_end) + 1);
+	size_t	retvalsize = (size_t)(expr_start - in_start)
+				+ STRLEN(temp_result)
+				+ (size_t)(in_end - expr_end) + 1;
+
+	retval = alloc(retvalsize);
 	if (retval != NULL)
-	{
-	    STRCPY(retval, in_start);
-	    STRCAT(retval, temp_result);
-	    STRCAT(retval, expr_end + 1);
-	}
+	    vim_snprintf((char *)retval, retvalsize, "%s%s%s",
+				in_start, temp_result, expr_end + 1);
     }
     vim_free(temp_result);
 
@@ -7610,21 +7623,17 @@
     char_u *
 do_string_sub(
     char_u	*str,
+    size_t	len,
     char_u	*pat,
     char_u	*sub,
     typval_T	*expr,
-    char_u	*flags)
+    char_u	*flags,
+    size_t	*ret_len)		// length of returned buffer
 {
-    int		sublen;
     regmatch_T	regmatch;
-    int		i;
-    int		do_all;
-    char_u	*tail;
-    char_u	*end;
     garray_T	ga;
     char_u	*ret;
     char_u	*save_cpo;
-    char_u	*zero_width = NULL;
 
     // Make 'cpoptions' empty, so that the 'l' flag doesn't work here
     save_cpo = p_cpo;
@@ -7632,14 +7641,17 @@
 
     ga_init2(&ga, 1, 200);
 
-    do_all = (flags[0] == 'g');
-
     regmatch.rm_ic = p_ic;
     regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
     if (regmatch.regprog != NULL)
     {
-	tail = str;
-	end = str + STRLEN(str);
+	char_u	*tail = str;
+	char_u	*end = str + len;
+	int	do_all = (flags[0] == 'g');
+	int	sublen;
+	int	i;
+	char_u	*zero_width = NULL;
+
 	while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
 	{
 	    // Skip empty match except for first match.
@@ -7694,12 +7706,20 @@
 	}
 
 	if (ga.ga_data != NULL)
+	{
 	    STRCPY((char *)ga.ga_data + ga.ga_len, tail);
+	    ga.ga_len += (int)(end - tail);
+	}
 
 	vim_regfree(regmatch.regprog);
     }
 
-    ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
+    if (ga.ga_data != NULL)
+    {
+	str = (char_u *)ga.ga_data;
+	len = (size_t)ga.ga_len;
+    }
+    ret = vim_strnsave(str, len);
     ga_clear(&ga);
     if (p_cpo == empty_option)
 	p_cpo = save_cpo;
@@ -7713,5 +7733,8 @@
 	free_string_option(save_cpo);
     }
 
+    if (ret_len != NULL)
+	*ret_len = len;
+
     return ret;
 }