patch 9.0.1400: find_file_in_path() is not reentrant

Problem:    find_file_in_path() is not reentrant.
Solution:   Instead of global variables pass pointers to the functions.
            (closes #12093)
diff --git a/src/findfile.c b/src/findfile.c
index e0d9d66..7287b10 100644
--- a/src/findfile.c
+++ b/src/findfile.c
@@ -1571,23 +1571,21 @@
     int		len,		// length of file name
     int		options,
     int		first,		// use count'th matching file name
-    char_u	*rel_fname)	// file name searching relative to
+    char_u	*rel_fname,	// file name searching relative to
+    char_u	**file_to_find,	// in/out: modified copy of file name
+    char	**search_ctx)	// in/out: state of the search
 {
     return find_file_in_path_option(ptr, len, options, first,
 	    *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path,
-	    FINDFILE_BOTH, rel_fname, curbuf->b_p_sua);
+	    FINDFILE_BOTH, rel_fname, curbuf->b_p_sua,
+	    file_to_find, search_ctx);
 }
 
-static char_u	*ff_file_to_find = NULL;
-static void	*fdip_search_ctx = NULL;
-
 # if defined(EXITFREE) || defined(PROTO)
     void
 free_findfile(void)
 {
-    vim_free(ff_file_to_find);
-    vim_findfile_cleanup(fdip_search_ctx);
-    vim_free(ff_expand_buffer);
+    VIM_CLEAR(ff_expand_buffer);
 }
 # endif
 
@@ -1607,10 +1605,13 @@
     char_u	*ptr,		// file name
     int		len,		// length of file name
     int		options,
-    char_u	*rel_fname)	// file name searching relative to
+    char_u	*rel_fname,	// file name searching relative to
+    char_u	**file_to_find,	// in/out: modified copy of file name
+    char	**search_ctx)	// in/out: state of the search
 {
     return find_file_in_path_option(ptr, len, options, TRUE, p_cdpath,
-				       FINDFILE_DIR, rel_fname, (char_u *)"");
+				       FINDFILE_DIR, rel_fname, (char_u *)"",
+				       file_to_find, search_ctx);
 }
 
     char_u *
@@ -1622,8 +1623,11 @@
     char_u	*path_option,	// p_path or p_cdpath
     int		find_what,	// FINDFILE_FILE, _DIR or _BOTH
     char_u	*rel_fname,	// file name we are looking relative to.
-    char_u	*suffixes)	// list of suffixes, 'suffixesadd' option
+    char_u	*suffixes,	// list of suffixes, 'suffixesadd' option
+    char_u	**file_to_find,	// in/out: modified copy of file name
+    char	**search_ctx_arg) // in/out: state of the search
 {
+    ff_search_ctx_T	**search_ctx = (ff_search_ctx_T **)search_ctx_arg;
     static char_u	*dir;
     static int		did_findfile_init = FALSE;
     char_u		save_char;
@@ -1649,9 +1653,9 @@
 	expand_env_esc(ptr, NameBuff, MAXPATHL, FALSE, TRUE, NULL);
 	ptr[len] = save_char;
 
-	vim_free(ff_file_to_find);
-	ff_file_to_find = vim_strsave(NameBuff);
-	if (ff_file_to_find == NULL)	// out of memory
+	vim_free(*file_to_find);
+	*file_to_find = vim_strsave(NameBuff);
+	if (*file_to_find == NULL)	// out of memory
 	{
 	    file_name = NULL;
 	    goto theend;
@@ -1659,30 +1663,30 @@
 	if (options & FNAME_UNESC)
 	{
 	    // Change all "\ " to " ".
-	    for (ptr = ff_file_to_find; *ptr != NUL; ++ptr)
+	    for (ptr = *file_to_find; *ptr != NUL; ++ptr)
 		if (ptr[0] == '\\' && ptr[1] == ' ')
 		    mch_memmove(ptr, ptr + 1, STRLEN(ptr));
 	}
     }
 
-    rel_to_curdir = (ff_file_to_find[0] == '.'
-		    && (ff_file_to_find[1] == NUL
-			|| vim_ispathsep(ff_file_to_find[1])
-			|| (ff_file_to_find[1] == '.'
-			    && (ff_file_to_find[2] == NUL
-				|| vim_ispathsep(ff_file_to_find[2])))));
-    if (vim_isAbsName(ff_file_to_find)
+    rel_to_curdir = ((*file_to_find)[0] == '.'
+		    && ((*file_to_find)[1] == NUL
+			|| vim_ispathsep((*file_to_find)[1])
+			|| ((*file_to_find)[1] == '.'
+			    && ((*file_to_find)[2] == NUL
+				|| vim_ispathsep((*file_to_find)[2])))));
+    if (vim_isAbsName(*file_to_find)
 	    // "..", "../path", "." and "./path": don't use the path_option
 	    || rel_to_curdir
 # if defined(MSWIN)
 	    // handle "\tmp" as absolute path
-	    || vim_ispathsep(ff_file_to_find[0])
+	    || vim_ispathsep((*file_to_find)[0])
 	    // handle "c:name" as absolute path
-	    || (ff_file_to_find[0] != NUL && ff_file_to_find[1] == ':')
+	    || ((*file_to_find)[0] != NUL && (*file_to_find)[1] == ':')
 # endif
 # ifdef AMIGA
 	    // handle ":tmp" as absolute path
-	    || ff_file_to_find[0] == ':'
+	    || (*file_to_find)[0] == ':'
 # endif
        )
     {
@@ -1696,9 +1700,9 @@
 	    int		l;
 	    int		run;
 
-	    if (path_with_url(ff_file_to_find))
+	    if (path_with_url(*file_to_find))
 	    {
-		file_name = vim_strsave(ff_file_to_find);
+		file_name = vim_strsave(*file_to_find);
 		goto theend;
 	    }
 
@@ -1706,7 +1710,7 @@
 	    // Otherwise or when this fails use the current directory.
 	    for (run = 1; run <= 2; ++run)
 	    {
-		l = (int)STRLEN(ff_file_to_find);
+		l = (int)STRLEN(*file_to_find);
 		if (run == 1
 			&& rel_to_curdir
 			&& (options & FNAME_REL)
@@ -1714,12 +1718,12 @@
 			&& STRLEN(rel_fname) + l < MAXPATHL)
 		{
 		    STRCPY(NameBuff, rel_fname);
-		    STRCPY(gettail(NameBuff), ff_file_to_find);
+		    STRCPY(gettail(NameBuff), *file_to_find);
 		    l = (int)STRLEN(NameBuff);
 		}
 		else
 		{
-		    STRCPY(NameBuff, ff_file_to_find);
+		    STRCPY(NameBuff, *file_to_find);
 		    run = 2;
 		}
 
@@ -1753,7 +1757,7 @@
 	if (first == TRUE)
 	{
 	    // vim_findfile_free_visited can handle a possible NULL pointer
-	    vim_findfile_free_visited(fdip_search_ctx);
+	    vim_findfile_free_visited(*search_ctx);
 	    dir = path_option;
 	    did_findfile_init = FALSE;
 	}
@@ -1762,7 +1766,7 @@
 	{
 	    if (did_findfile_init)
 	    {
-		file_name = vim_findfile(fdip_search_ctx);
+		file_name = vim_findfile(*search_ctx);
 		if (file_name != NULL)
 		    break;
 
@@ -1776,8 +1780,8 @@
 		{
 		    // We searched all paths of the option, now we can
 		    // free the search context.
-		    vim_findfile_cleanup(fdip_search_ctx);
-		    fdip_search_ctx = NULL;
+		    vim_findfile_cleanup(*search_ctx);
+		    *search_ctx = NULL;
 		    break;
 		}
 
@@ -1790,10 +1794,10 @@
 
 		// get the stopdir string
 		r_ptr = vim_findfile_stopdir(buf);
-		fdip_search_ctx = vim_findfile_init(buf, ff_file_to_find,
+		*search_ctx = vim_findfile_init(buf, *file_to_find,
 					    r_ptr, 100, FALSE, find_what,
-					   fdip_search_ctx, FALSE, rel_fname);
-		if (fdip_search_ctx != NULL)
+					   *search_ctx, FALSE, rel_fname);
+		if (*search_ctx != NULL)
 		    did_findfile_init = TRUE;
 		vim_free(buf);
 	    }
@@ -1804,20 +1808,17 @@
 	if (first == TRUE)
 	{
 	    if (find_what == FINDFILE_DIR)
-		semsg(_(e_cant_find_directory_str_in_cdpath),
-			ff_file_to_find);
+		semsg(_(e_cant_find_directory_str_in_cdpath), *file_to_find);
 	    else
-		semsg(_(e_cant_find_file_str_in_path),
-			ff_file_to_find);
+		semsg(_(e_cant_find_file_str_in_path), *file_to_find);
 	}
 	else
 	{
 	    if (find_what == FINDFILE_DIR)
 		semsg(_(e_no_more_directory_str_found_in_cdpath),
-			ff_file_to_find);
+								*file_to_find);
 	    else
-		semsg(_(e_no_more_file_str_found_in_path),
-			ff_file_to_find);
+		semsg(_(e_no_more_file_str_found_in_path), *file_to_find);
 	}
     }
 
@@ -2046,8 +2047,11 @@
 
     if (options & FNAME_EXP)
     {
+	char_u	*file_to_find = NULL;
+	char	*search_ctx = NULL;
+
 	file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
-							     TRUE, rel_fname);
+				  TRUE, rel_fname, &file_to_find, &search_ctx);
 
 # if defined(FEAT_FIND_ID) && defined(FEAT_EVAL)
 	/*
@@ -2063,7 +2067,7 @@
 		ptr = tofree;
 		len = (int)STRLEN(ptr);
 		file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
-							     TRUE, rel_fname);
+				  TRUE, rel_fname, &file_to_find, &search_ctx);
 	    }
 	}
 # endif
@@ -2080,8 +2084,12 @@
 	while (file_name != NULL && --count > 0)
 	{
 	    vim_free(file_name);
-	    file_name = find_file_in_path(ptr, len, options, FALSE, rel_fname);
+	    file_name = find_file_in_path(ptr, len, options, FALSE, rel_fname,
+						   &file_to_find, &search_ctx);
 	}
+
+	vim_free(file_to_find);
+	vim_findfile_cleanup(search_ctx);
     }
     else
 	file_name = vim_strnsave(ptr, len);