xref: /vim-8.2.3635/src/filepath.c (revision 2e693a88)
1 /* vi:set ts=8 sts=4 sw=4 noet:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 
10 /*
11  * filepath.c: dealing with file names ant paths.
12  */
13 
14 #include "vim.h"
15 
16 #ifdef MSWIN
17 /*
18  * Functions for ":8" filename modifier: get 8.3 version of a filename.
19  */
20 
21 /*
22  * Get the short path (8.3) for the filename in "fnamep".
23  * Only works for a valid file name.
24  * When the path gets longer "fnamep" is changed and the allocated buffer
25  * is put in "bufp".
26  * *fnamelen is the length of "fnamep" and set to 0 for a nonexistent path.
27  * Returns OK on success, FAIL on failure.
28  */
29     static int
30 get_short_pathname(char_u **fnamep, char_u **bufp, int *fnamelen)
31 {
32     int		l, len;
33     char_u	*newbuf;
34 
35     len = *fnamelen;
36     l = GetShortPathName((LPSTR)*fnamep, (LPSTR)*fnamep, len);
37     if (l > len - 1)
38     {
39 	// If that doesn't work (not enough space), then save the string
40 	// and try again with a new buffer big enough.
41 	newbuf = vim_strnsave(*fnamep, l);
42 	if (newbuf == NULL)
43 	    return FAIL;
44 
45 	vim_free(*bufp);
46 	*fnamep = *bufp = newbuf;
47 
48 	// Really should always succeed, as the buffer is big enough.
49 	l = GetShortPathName((LPSTR)*fnamep, (LPSTR)*fnamep, l+1);
50     }
51 
52     *fnamelen = l;
53     return OK;
54 }
55 
56 /*
57  * Get the short path (8.3) for the filename in "fname". The converted
58  * path is returned in "bufp".
59  *
60  * Some of the directories specified in "fname" may not exist. This function
61  * will shorten the existing directories at the beginning of the path and then
62  * append the remaining non-existing path.
63  *
64  * fname - Pointer to the filename to shorten.  On return, contains the
65  *	   pointer to the shortened pathname
66  * bufp -  Pointer to an allocated buffer for the filename.
67  * fnamelen - Length of the filename pointed to by fname
68  *
69  * Returns OK on success (or nothing done) and FAIL on failure (out of memory).
70  */
71     static int
72 shortpath_for_invalid_fname(
73     char_u	**fname,
74     char_u	**bufp,
75     int		*fnamelen)
76 {
77     char_u	*short_fname, *save_fname, *pbuf_unused;
78     char_u	*endp, *save_endp;
79     char_u	ch;
80     int		old_len, len;
81     int		new_len, sfx_len;
82     int		retval = OK;
83 
84     // Make a copy
85     old_len = *fnamelen;
86     save_fname = vim_strnsave(*fname, old_len);
87     pbuf_unused = NULL;
88     short_fname = NULL;
89 
90     endp = save_fname + old_len - 1; // Find the end of the copy
91     save_endp = endp;
92 
93     /*
94      * Try shortening the supplied path till it succeeds by removing one
95      * directory at a time from the tail of the path.
96      */
97     len = 0;
98     for (;;)
99     {
100 	// go back one path-separator
101 	while (endp > save_fname && !after_pathsep(save_fname, endp + 1))
102 	    --endp;
103 	if (endp <= save_fname)
104 	    break;		// processed the complete path
105 
106 	/*
107 	 * Replace the path separator with a NUL and try to shorten the
108 	 * resulting path.
109 	 */
110 	ch = *endp;
111 	*endp = 0;
112 	short_fname = save_fname;
113 	len = (int)STRLEN(short_fname) + 1;
114 	if (get_short_pathname(&short_fname, &pbuf_unused, &len) == FAIL)
115 	{
116 	    retval = FAIL;
117 	    goto theend;
118 	}
119 	*endp = ch;	// preserve the string
120 
121 	if (len > 0)
122 	    break;	// successfully shortened the path
123 
124 	// failed to shorten the path. Skip the path separator
125 	--endp;
126     }
127 
128     if (len > 0)
129     {
130 	/*
131 	 * Succeeded in shortening the path. Now concatenate the shortened
132 	 * path with the remaining path at the tail.
133 	 */
134 
135 	/* Compute the length of the new path. */
136 	sfx_len = (int)(save_endp - endp) + 1;
137 	new_len = len + sfx_len;
138 
139 	*fnamelen = new_len;
140 	vim_free(*bufp);
141 	if (new_len > old_len)
142 	{
143 	    // There is not enough space in the currently allocated string,
144 	    // copy it to a buffer big enough.
145 	    *fname = *bufp = vim_strnsave(short_fname, new_len);
146 	    if (*fname == NULL)
147 	    {
148 		retval = FAIL;
149 		goto theend;
150 	    }
151 	}
152 	else
153 	{
154 	    // Transfer short_fname to the main buffer (it's big enough),
155 	    // unless get_short_pathname() did its work in-place.
156 	    *fname = *bufp = save_fname;
157 	    if (short_fname != save_fname)
158 		vim_strncpy(save_fname, short_fname, len);
159 	    save_fname = NULL;
160 	}
161 
162 	// concat the not-shortened part of the path
163 	vim_strncpy(*fname + len, endp, sfx_len);
164 	(*fname)[new_len] = NUL;
165     }
166 
167 theend:
168     vim_free(pbuf_unused);
169     vim_free(save_fname);
170 
171     return retval;
172 }
173 
174 /*
175  * Get a pathname for a partial path.
176  * Returns OK for success, FAIL for failure.
177  */
178     static int
179 shortpath_for_partial(
180     char_u	**fnamep,
181     char_u	**bufp,
182     int		*fnamelen)
183 {
184     int		sepcount, len, tflen;
185     char_u	*p;
186     char_u	*pbuf, *tfname;
187     int		hasTilde;
188 
189     // Count up the path separators from the RHS.. so we know which part
190     // of the path to return.
191     sepcount = 0;
192     for (p = *fnamep; p < *fnamep + *fnamelen; MB_PTR_ADV(p))
193 	if (vim_ispathsep(*p))
194 	    ++sepcount;
195 
196     // Need full path first (use expand_env() to remove a "~/")
197     hasTilde = (**fnamep == '~');
198     if (hasTilde)
199 	pbuf = tfname = expand_env_save(*fnamep);
200     else
201 	pbuf = tfname = FullName_save(*fnamep, FALSE);
202 
203     len = tflen = (int)STRLEN(tfname);
204 
205     if (get_short_pathname(&tfname, &pbuf, &len) == FAIL)
206 	return FAIL;
207 
208     if (len == 0)
209     {
210 	// Don't have a valid filename, so shorten the rest of the
211 	// path if we can. This CAN give us invalid 8.3 filenames, but
212 	// there's not a lot of point in guessing what it might be.
213 	len = tflen;
214 	if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == FAIL)
215 	    return FAIL;
216     }
217 
218     // Count the paths backward to find the beginning of the desired string.
219     for (p = tfname + len - 1; p >= tfname; --p)
220     {
221 	if (has_mbyte)
222 	    p -= mb_head_off(tfname, p);
223 	if (vim_ispathsep(*p))
224 	{
225 	    if (sepcount == 0 || (hasTilde && sepcount == 1))
226 		break;
227 	    else
228 		sepcount --;
229 	}
230     }
231     if (hasTilde)
232     {
233 	--p;
234 	if (p >= tfname)
235 	    *p = '~';
236 	else
237 	    return FAIL;
238     }
239     else
240 	++p;
241 
242     // Copy in the string - p indexes into tfname - allocated at pbuf
243     vim_free(*bufp);
244     *fnamelen = (int)STRLEN(p);
245     *bufp = pbuf;
246     *fnamep = p;
247 
248     return OK;
249 }
250 #endif // MSWIN
251 
252 /*
253  * Adjust a filename, according to a string of modifiers.
254  * *fnamep must be NUL terminated when called.  When returning, the length is
255  * determined by *fnamelen.
256  * Returns VALID_ flags or -1 for failure.
257  * When there is an error, *fnamep is set to NULL.
258  */
259     int
260 modify_fname(
261     char_u	*src,		// string with modifiers
262     int		tilde_file,	// "~" is a file name, not $HOME
263     int		*usedlen,	// characters after src that are used
264     char_u	**fnamep,	// file name so far
265     char_u	**bufp,		// buffer for allocated file name or NULL
266     int		*fnamelen)	// length of fnamep
267 {
268     int		valid = 0;
269     char_u	*tail;
270     char_u	*s, *p, *pbuf;
271     char_u	dirname[MAXPATHL];
272     int		c;
273     int		has_fullname = 0;
274 #ifdef MSWIN
275     char_u	*fname_start = *fnamep;
276     int		has_shortname = 0;
277 #endif
278 
279 repeat:
280     // ":p" - full path/file_name
281     if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
282     {
283 	has_fullname = 1;
284 
285 	valid |= VALID_PATH;
286 	*usedlen += 2;
287 
288 	// Expand "~/path" for all systems and "~user/path" for Unix and VMS
289 	if ((*fnamep)[0] == '~'
290 #if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME))
291 		&& ((*fnamep)[1] == '/'
292 # ifdef BACKSLASH_IN_FILENAME
293 		    || (*fnamep)[1] == '\\'
294 # endif
295 		    || (*fnamep)[1] == NUL)
296 #endif
297 		&& !(tilde_file && (*fnamep)[1] == NUL)
298 	   )
299 	{
300 	    *fnamep = expand_env_save(*fnamep);
301 	    vim_free(*bufp);	// free any allocated file name
302 	    *bufp = *fnamep;
303 	    if (*fnamep == NULL)
304 		return -1;
305 	}
306 
307 	// When "/." or "/.." is used: force expansion to get rid of it.
308 	for (p = *fnamep; *p != NUL; MB_PTR_ADV(p))
309 	{
310 	    if (vim_ispathsep(*p)
311 		    && p[1] == '.'
312 		    && (p[2] == NUL
313 			|| vim_ispathsep(p[2])
314 			|| (p[2] == '.'
315 			    && (p[3] == NUL || vim_ispathsep(p[3])))))
316 		break;
317 	}
318 
319 	// FullName_save() is slow, don't use it when not needed.
320 	if (*p != NUL || !vim_isAbsName(*fnamep))
321 	{
322 	    *fnamep = FullName_save(*fnamep, *p != NUL);
323 	    vim_free(*bufp);	// free any allocated file name
324 	    *bufp = *fnamep;
325 	    if (*fnamep == NULL)
326 		return -1;
327 	}
328 
329 #ifdef MSWIN
330 # if _WIN32_WINNT >= 0x0500
331 	if (vim_strchr(*fnamep, '~') != NULL)
332 	{
333 	    // Expand 8.3 filename to full path.  Needed to make sure the same
334 	    // file does not have two different names.
335 	    // Note: problem does not occur if _WIN32_WINNT < 0x0500.
336 	    WCHAR *wfname = enc_to_utf16(*fnamep, NULL);
337 	    WCHAR buf[_MAX_PATH];
338 
339 	    if (wfname != NULL)
340 	    {
341 		if (GetLongPathNameW(wfname, buf, _MAX_PATH))
342 		{
343 		    char_u *p = utf16_to_enc(buf, NULL);
344 
345 		    if (p != NULL)
346 		    {
347 			vim_free(*bufp);    // free any allocated file name
348 			*bufp = *fnamep = p;
349 		    }
350 		}
351 		vim_free(wfname);
352 	    }
353 	}
354 # endif
355 #endif
356 	// Append a path separator to a directory.
357 	if (mch_isdir(*fnamep))
358 	{
359 	    // Make room for one or two extra characters.
360 	    *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2);
361 	    vim_free(*bufp);	// free any allocated file name
362 	    *bufp = *fnamep;
363 	    if (*fnamep == NULL)
364 		return -1;
365 	    add_pathsep(*fnamep);
366 	}
367     }
368 
369     // ":." - path relative to the current directory
370     // ":~" - path relative to the home directory
371     // ":8" - shortname path - postponed till after
372     while (src[*usedlen] == ':'
373 		  && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8'))
374     {
375 	*usedlen += 2;
376 	if (c == '8')
377 	{
378 #ifdef MSWIN
379 	    has_shortname = 1; // Postpone this.
380 #endif
381 	    continue;
382 	}
383 	pbuf = NULL;
384 	// Need full path first (use expand_env() to remove a "~/")
385 	if (!has_fullname)
386 	{
387 	    if (c == '.' && **fnamep == '~')
388 		p = pbuf = expand_env_save(*fnamep);
389 	    else
390 		p = pbuf = FullName_save(*fnamep, FALSE);
391 	}
392 	else
393 	    p = *fnamep;
394 
395 	has_fullname = 0;
396 
397 	if (p != NULL)
398 	{
399 	    if (c == '.')
400 	    {
401 		mch_dirname(dirname, MAXPATHL);
402 		s = shorten_fname(p, dirname);
403 		if (s != NULL)
404 		{
405 		    *fnamep = s;
406 		    if (pbuf != NULL)
407 		    {
408 			vim_free(*bufp);   // free any allocated file name
409 			*bufp = pbuf;
410 			pbuf = NULL;
411 		    }
412 		}
413 	    }
414 	    else
415 	    {
416 		home_replace(NULL, p, dirname, MAXPATHL, TRUE);
417 		// Only replace it when it starts with '~'
418 		if (*dirname == '~')
419 		{
420 		    s = vim_strsave(dirname);
421 		    if (s != NULL)
422 		    {
423 			*fnamep = s;
424 			vim_free(*bufp);
425 			*bufp = s;
426 		    }
427 		}
428 	    }
429 	    vim_free(pbuf);
430 	}
431     }
432 
433     tail = gettail(*fnamep);
434     *fnamelen = (int)STRLEN(*fnamep);
435 
436     // ":h" - head, remove "/file_name", can be repeated
437     // Don't remove the first "/" or "c:\"
438     while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
439     {
440 	valid |= VALID_HEAD;
441 	*usedlen += 2;
442 	s = get_past_head(*fnamep);
443 	while (tail > s && after_pathsep(s, tail))
444 	    MB_PTR_BACK(*fnamep, tail);
445 	*fnamelen = (int)(tail - *fnamep);
446 #ifdef VMS
447 	if (*fnamelen > 0)
448 	    *fnamelen += 1; // the path separator is part of the path
449 #endif
450 	if (*fnamelen == 0)
451 	{
452 	    // Result is empty.  Turn it into "." to make ":cd %:h" work.
453 	    p = vim_strsave((char_u *)".");
454 	    if (p == NULL)
455 		return -1;
456 	    vim_free(*bufp);
457 	    *bufp = *fnamep = tail = p;
458 	    *fnamelen = 1;
459 	}
460 	else
461 	{
462 	    while (tail > s && !after_pathsep(s, tail))
463 		MB_PTR_BACK(*fnamep, tail);
464 	}
465     }
466 
467     // ":8" - shortname
468     if (src[*usedlen] == ':' && src[*usedlen + 1] == '8')
469     {
470 	*usedlen += 2;
471 #ifdef MSWIN
472 	has_shortname = 1;
473 #endif
474     }
475 
476 #ifdef MSWIN
477     /*
478      * Handle ":8" after we have done 'heads' and before we do 'tails'.
479      */
480     if (has_shortname)
481     {
482 	// Copy the string if it is shortened by :h and when it wasn't copied
483 	// yet, because we are going to change it in place.  Avoids changing
484 	// the buffer name for "%:8".
485 	if (*fnamelen < (int)STRLEN(*fnamep) || *fnamep == fname_start)
486 	{
487 	    p = vim_strnsave(*fnamep, *fnamelen);
488 	    if (p == NULL)
489 		return -1;
490 	    vim_free(*bufp);
491 	    *bufp = *fnamep = p;
492 	}
493 
494 	// Split into two implementations - makes it easier.  First is where
495 	// there isn't a full name already, second is where there is.
496 	if (!has_fullname && !vim_isAbsName(*fnamep))
497 	{
498 	    if (shortpath_for_partial(fnamep, bufp, fnamelen) == FAIL)
499 		return -1;
500 	}
501 	else
502 	{
503 	    int		l = *fnamelen;
504 
505 	    // Simple case, already have the full-name.
506 	    // Nearly always shorter, so try first time.
507 	    if (get_short_pathname(fnamep, bufp, &l) == FAIL)
508 		return -1;
509 
510 	    if (l == 0)
511 	    {
512 		// Couldn't find the filename, search the paths.
513 		l = *fnamelen;
514 		if (shortpath_for_invalid_fname(fnamep, bufp, &l) == FAIL)
515 		    return -1;
516 	    }
517 	    *fnamelen = l;
518 	}
519     }
520 #endif // MSWIN
521 
522     // ":t" - tail, just the basename
523     if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
524     {
525 	*usedlen += 2;
526 	*fnamelen -= (int)(tail - *fnamep);
527 	*fnamep = tail;
528     }
529 
530     // ":e" - extension, can be repeated
531     // ":r" - root, without extension, can be repeated
532     while (src[*usedlen] == ':'
533 	    && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
534     {
535 	// find a '.' in the tail:
536 	// - for second :e: before the current fname
537 	// - otherwise: The last '.'
538 	if (src[*usedlen + 1] == 'e' && *fnamep > tail)
539 	    s = *fnamep - 2;
540 	else
541 	    s = *fnamep + *fnamelen - 1;
542 	for ( ; s > tail; --s)
543 	    if (s[0] == '.')
544 		break;
545 	if (src[*usedlen + 1] == 'e')		// :e
546 	{
547 	    if (s > tail)
548 	    {
549 		*fnamelen += (int)(*fnamep - (s + 1));
550 		*fnamep = s + 1;
551 #ifdef VMS
552 		// cut version from the extension
553 		s = *fnamep + *fnamelen - 1;
554 		for ( ; s > *fnamep; --s)
555 		    if (s[0] == ';')
556 			break;
557 		if (s > *fnamep)
558 		    *fnamelen = s - *fnamep;
559 #endif
560 	    }
561 	    else if (*fnamep <= tail)
562 		*fnamelen = 0;
563 	}
564 	else				// :r
565 	{
566 	    char_u *limit = *fnamep;
567 
568 	    if (limit < tail)
569 		limit = tail;
570 	    if (s > limit)	// remove one extension
571 		*fnamelen = (int)(s - *fnamep);
572 	}
573 	*usedlen += 2;
574     }
575 
576     // ":s?pat?foo?" - substitute
577     // ":gs?pat?foo?" - global substitute
578     if (src[*usedlen] == ':'
579 	    && (src[*usedlen + 1] == 's'
580 		|| (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's')))
581     {
582 	char_u	    *str;
583 	char_u	    *pat;
584 	char_u	    *sub;
585 	int	    sep;
586 	char_u	    *flags;
587 	int	    didit = FALSE;
588 
589 	flags = (char_u *)"";
590 	s = src + *usedlen + 2;
591 	if (src[*usedlen + 1] == 'g')
592 	{
593 	    flags = (char_u *)"g";
594 	    ++s;
595 	}
596 
597 	sep = *s++;
598 	if (sep)
599 	{
600 	    // find end of pattern
601 	    p = vim_strchr(s, sep);
602 	    if (p != NULL)
603 	    {
604 		pat = vim_strnsave(s, (int)(p - s));
605 		if (pat != NULL)
606 		{
607 		    s = p + 1;
608 		    // find end of substitution
609 		    p = vim_strchr(s, sep);
610 		    if (p != NULL)
611 		    {
612 			sub = vim_strnsave(s, (int)(p - s));
613 			str = vim_strnsave(*fnamep, *fnamelen);
614 			if (sub != NULL && str != NULL)
615 			{
616 			    *usedlen = (int)(p + 1 - src);
617 			    s = do_string_sub(str, pat, sub, NULL, flags);
618 			    if (s != NULL)
619 			    {
620 				*fnamep = s;
621 				*fnamelen = (int)STRLEN(s);
622 				vim_free(*bufp);
623 				*bufp = s;
624 				didit = TRUE;
625 			    }
626 			}
627 			vim_free(sub);
628 			vim_free(str);
629 		    }
630 		    vim_free(pat);
631 		}
632 	    }
633 	    // after using ":s", repeat all the modifiers
634 	    if (didit)
635 		goto repeat;
636 	}
637     }
638 
639     if (src[*usedlen] == ':' && src[*usedlen + 1] == 'S')
640     {
641 	// vim_strsave_shellescape() needs a NUL terminated string.
642 	c = (*fnamep)[*fnamelen];
643 	if (c != NUL)
644 	    (*fnamep)[*fnamelen] = NUL;
645 	p = vim_strsave_shellescape(*fnamep, FALSE, FALSE);
646 	if (c != NUL)
647 	    (*fnamep)[*fnamelen] = c;
648 	if (p == NULL)
649 	    return -1;
650 	vim_free(*bufp);
651 	*bufp = *fnamep = p;
652 	*fnamelen = (int)STRLEN(p);
653 	*usedlen += 2;
654     }
655 
656     return valid;
657 }
658 
659 #if defined(FEAT_EVAL) || defined(PROTO)
660 
661 /*
662  * "chdir(dir)" function
663  */
664     void
665 f_chdir(typval_T *argvars, typval_T *rettv)
666 {
667     char_u	*cwd;
668     cdscope_T	scope = CDSCOPE_GLOBAL;
669 
670     rettv->v_type = VAR_STRING;
671     rettv->vval.v_string = NULL;
672 
673     if (argvars[0].v_type != VAR_STRING)
674 	return;
675 
676     // Return the current directory
677     cwd = alloc(MAXPATHL);
678     if (cwd != NULL)
679     {
680 	if (mch_dirname(cwd, MAXPATHL) != FAIL)
681 	{
682 #ifdef BACKSLASH_IN_FILENAME
683 	    slash_adjust(cwd);
684 #endif
685 	    rettv->vval.v_string = vim_strsave(cwd);
686 	}
687 	vim_free(cwd);
688     }
689 
690     if (curwin->w_localdir != NULL)
691 	scope = CDSCOPE_WINDOW;
692     else if (curtab->tp_localdir != NULL)
693 	scope = CDSCOPE_TABPAGE;
694 
695     if (!changedir_func(argvars[0].vval.v_string, TRUE, scope))
696 	// Directory change failed
697 	VIM_CLEAR(rettv->vval.v_string);
698 }
699 
700 /*
701  * "delete()" function
702  */
703     void
704 f_delete(typval_T *argvars, typval_T *rettv)
705 {
706     char_u	nbuf[NUMBUFLEN];
707     char_u	*name;
708     char_u	*flags;
709 
710     rettv->vval.v_number = -1;
711     if (check_restricted() || check_secure())
712 	return;
713 
714     name = tv_get_string(&argvars[0]);
715     if (name == NULL || *name == NUL)
716     {
717 	emsg(_(e_invarg));
718 	return;
719     }
720 
721     if (argvars[1].v_type != VAR_UNKNOWN)
722 	flags = tv_get_string_buf(&argvars[1], nbuf);
723     else
724 	flags = (char_u *)"";
725 
726     if (*flags == NUL)
727 	// delete a file
728 	rettv->vval.v_number = mch_remove(name) == 0 ? 0 : -1;
729     else if (STRCMP(flags, "d") == 0)
730 	// delete an empty directory
731 	rettv->vval.v_number = mch_rmdir(name) == 0 ? 0 : -1;
732     else if (STRCMP(flags, "rf") == 0)
733 	// delete a directory recursively
734 	rettv->vval.v_number = delete_recursive(name);
735     else
736 	semsg(_(e_invexpr2), flags);
737 }
738 
739 /*
740  * "executable()" function
741  */
742     void
743 f_executable(typval_T *argvars, typval_T *rettv)
744 {
745     char_u *name = tv_get_string(&argvars[0]);
746 
747     // Check in $PATH and also check directly if there is a directory name.
748     rettv->vval.v_number = mch_can_exe(name, NULL, TRUE);
749 }
750 
751 /*
752  * "exepath()" function
753  */
754     void
755 f_exepath(typval_T *argvars, typval_T *rettv)
756 {
757     char_u *p = NULL;
758 
759     (void)mch_can_exe(tv_get_string(&argvars[0]), &p, TRUE);
760     rettv->v_type = VAR_STRING;
761     rettv->vval.v_string = p;
762 }
763 
764 /*
765  * "filereadable()" function
766  */
767     void
768 f_filereadable(typval_T *argvars, typval_T *rettv)
769 {
770     int		fd;
771     char_u	*p;
772     int		n;
773 
774 #ifndef O_NONBLOCK
775 # define O_NONBLOCK 0
776 #endif
777     p = tv_get_string(&argvars[0]);
778     if (*p && !mch_isdir(p) && (fd = mch_open((char *)p,
779 					      O_RDONLY | O_NONBLOCK, 0)) >= 0)
780     {
781 	n = TRUE;
782 	close(fd);
783     }
784     else
785 	n = FALSE;
786 
787     rettv->vval.v_number = n;
788 }
789 
790 /*
791  * Return 0 for not writable, 1 for writable file, 2 for a dir which we have
792  * rights to write into.
793  */
794     void
795 f_filewritable(typval_T *argvars, typval_T *rettv)
796 {
797     rettv->vval.v_number = filewritable(tv_get_string(&argvars[0]));
798 }
799 
800     static void
801 findfilendir(
802     typval_T	*argvars UNUSED,
803     typval_T	*rettv,
804     int		find_what UNUSED)
805 {
806 #ifdef FEAT_SEARCHPATH
807     char_u	*fname;
808     char_u	*fresult = NULL;
809     char_u	*path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
810     char_u	*p;
811     char_u	pathbuf[NUMBUFLEN];
812     int		count = 1;
813     int		first = TRUE;
814     int		error = FALSE;
815 #endif
816 
817     rettv->vval.v_string = NULL;
818     rettv->v_type = VAR_STRING;
819 
820 #ifdef FEAT_SEARCHPATH
821     fname = tv_get_string(&argvars[0]);
822 
823     if (argvars[1].v_type != VAR_UNKNOWN)
824     {
825 	p = tv_get_string_buf_chk(&argvars[1], pathbuf);
826 	if (p == NULL)
827 	    error = TRUE;
828 	else
829 	{
830 	    if (*p != NUL)
831 		path = p;
832 
833 	    if (argvars[2].v_type != VAR_UNKNOWN)
834 		count = (int)tv_get_number_chk(&argvars[2], &error);
835 	}
836     }
837 
838     if (count < 0 && rettv_list_alloc(rettv) == FAIL)
839 	error = TRUE;
840 
841     if (*fname != NUL && !error)
842     {
843 	do
844 	{
845 	    if (rettv->v_type == VAR_STRING || rettv->v_type == VAR_LIST)
846 		vim_free(fresult);
847 	    fresult = find_file_in_path_option(first ? fname : NULL,
848 					       first ? (int)STRLEN(fname) : 0,
849 					0, first, path,
850 					find_what,
851 					curbuf->b_ffname,
852 					find_what == FINDFILE_DIR
853 					    ? (char_u *)"" : curbuf->b_p_sua);
854 	    first = FALSE;
855 
856 	    if (fresult != NULL && rettv->v_type == VAR_LIST)
857 		list_append_string(rettv->vval.v_list, fresult, -1);
858 
859 	} while ((rettv->v_type == VAR_LIST || --count > 0) && fresult != NULL);
860     }
861 
862     if (rettv->v_type == VAR_STRING)
863 	rettv->vval.v_string = fresult;
864 #endif
865 }
866 
867 /*
868  * "finddir({fname}[, {path}[, {count}]])" function
869  */
870     void
871 f_finddir(typval_T *argvars, typval_T *rettv)
872 {
873     findfilendir(argvars, rettv, FINDFILE_DIR);
874 }
875 
876 /*
877  * "findfile({fname}[, {path}[, {count}]])" function
878  */
879     void
880 f_findfile(typval_T *argvars, typval_T *rettv)
881 {
882     findfilendir(argvars, rettv, FINDFILE_FILE);
883 }
884 
885 /*
886  * "fnamemodify({fname}, {mods})" function
887  */
888     void
889 f_fnamemodify(typval_T *argvars, typval_T *rettv)
890 {
891     char_u	*fname;
892     char_u	*mods;
893     int		usedlen = 0;
894     int		len;
895     char_u	*fbuf = NULL;
896     char_u	buf[NUMBUFLEN];
897 
898     fname = tv_get_string_chk(&argvars[0]);
899     mods = tv_get_string_buf_chk(&argvars[1], buf);
900     if (fname == NULL || mods == NULL)
901 	fname = NULL;
902     else
903     {
904 	len = (int)STRLEN(fname);
905 	(void)modify_fname(mods, FALSE, &usedlen, &fname, &fbuf, &len);
906     }
907 
908     rettv->v_type = VAR_STRING;
909     if (fname == NULL)
910 	rettv->vval.v_string = NULL;
911     else
912 	rettv->vval.v_string = vim_strnsave(fname, len);
913     vim_free(fbuf);
914 }
915 
916 /*
917  * "getcwd()" function
918  *
919  * Return the current working directory of a window in a tab page.
920  * First optional argument 'winnr' is the window number or -1 and the second
921  * optional argument 'tabnr' is the tab page number.
922  *
923  * If no arguments are supplied, then return the directory of the current
924  * window.
925  * If only 'winnr' is specified and is not -1 or 0 then return the directory of
926  * the specified window.
927  * If 'winnr' is 0 then return the directory of the current window.
928  * If both 'winnr and 'tabnr' are specified and 'winnr' is -1 then return the
929  * directory of the specified tab page.  Otherwise return the directory of the
930  * specified window in the specified tab page.
931  * If the window or the tab page doesn't exist then return NULL.
932  */
933     void
934 f_getcwd(typval_T *argvars, typval_T *rettv)
935 {
936     win_T	*wp = NULL;
937     tabpage_T	*tp = NULL;
938     char_u	*cwd;
939     int		global = FALSE;
940 
941     rettv->v_type = VAR_STRING;
942     rettv->vval.v_string = NULL;
943 
944     if (argvars[0].v_type == VAR_NUMBER
945 	    && argvars[0].vval.v_number == -1
946 	    && argvars[1].v_type == VAR_UNKNOWN)
947 	global = TRUE;
948     else
949 	wp = find_tabwin(&argvars[0], &argvars[1], &tp);
950 
951     if (wp != NULL && wp->w_localdir != NULL)
952 	rettv->vval.v_string = vim_strsave(wp->w_localdir);
953     else if (tp != NULL && tp->tp_localdir != NULL)
954 	rettv->vval.v_string = vim_strsave(tp->tp_localdir);
955     else if (wp != NULL || tp != NULL || global)
956     {
957 	if (globaldir != NULL)
958 	    rettv->vval.v_string = vim_strsave(globaldir);
959 	else
960 	{
961 	    cwd = alloc(MAXPATHL);
962 	    if (cwd != NULL)
963 	    {
964 		if (mch_dirname(cwd, MAXPATHL) != FAIL)
965 		    rettv->vval.v_string = vim_strsave(cwd);
966 		vim_free(cwd);
967 	    }
968 	}
969     }
970 #ifdef BACKSLASH_IN_FILENAME
971     if (rettv->vval.v_string != NULL)
972 	slash_adjust(rettv->vval.v_string);
973 #endif
974 }
975 
976 /*
977  * "getfperm({fname})" function
978  */
979     void
980 f_getfperm(typval_T *argvars, typval_T *rettv)
981 {
982     char_u	*fname;
983     stat_T	st;
984     char_u	*perm = NULL;
985     char_u	flags[] = "rwx";
986     int		i;
987 
988     fname = tv_get_string(&argvars[0]);
989 
990     rettv->v_type = VAR_STRING;
991     if (mch_stat((char *)fname, &st) >= 0)
992     {
993 	perm = vim_strsave((char_u *)"---------");
994 	if (perm != NULL)
995 	{
996 	    for (i = 0; i < 9; i++)
997 	    {
998 		if (st.st_mode & (1 << (8 - i)))
999 		    perm[i] = flags[i % 3];
1000 	    }
1001 	}
1002     }
1003     rettv->vval.v_string = perm;
1004 }
1005 
1006 /*
1007  * "getfsize({fname})" function
1008  */
1009     void
1010 f_getfsize(typval_T *argvars, typval_T *rettv)
1011 {
1012     char_u	*fname;
1013     stat_T	st;
1014 
1015     fname = tv_get_string(&argvars[0]);
1016 
1017     rettv->v_type = VAR_NUMBER;
1018 
1019     if (mch_stat((char *)fname, &st) >= 0)
1020     {
1021 	if (mch_isdir(fname))
1022 	    rettv->vval.v_number = 0;
1023 	else
1024 	{
1025 	    rettv->vval.v_number = (varnumber_T)st.st_size;
1026 
1027 	    // non-perfect check for overflow
1028 	    if ((off_T)rettv->vval.v_number != (off_T)st.st_size)
1029 		rettv->vval.v_number = -2;
1030 	}
1031     }
1032     else
1033 	  rettv->vval.v_number = -1;
1034 }
1035 
1036 /*
1037  * "getftime({fname})" function
1038  */
1039     void
1040 f_getftime(typval_T *argvars, typval_T *rettv)
1041 {
1042     char_u	*fname;
1043     stat_T	st;
1044 
1045     fname = tv_get_string(&argvars[0]);
1046 
1047     if (mch_stat((char *)fname, &st) >= 0)
1048 	rettv->vval.v_number = (varnumber_T)st.st_mtime;
1049     else
1050 	rettv->vval.v_number = -1;
1051 }
1052 
1053 /*
1054  * "getftype({fname})" function
1055  */
1056     void
1057 f_getftype(typval_T *argvars, typval_T *rettv)
1058 {
1059     char_u	*fname;
1060     stat_T	st;
1061     char_u	*type = NULL;
1062     char	*t;
1063 
1064     fname = tv_get_string(&argvars[0]);
1065 
1066     rettv->v_type = VAR_STRING;
1067     if (mch_lstat((char *)fname, &st) >= 0)
1068     {
1069 	if (S_ISREG(st.st_mode))
1070 	    t = "file";
1071 	else if (S_ISDIR(st.st_mode))
1072 	    t = "dir";
1073 	else if (S_ISLNK(st.st_mode))
1074 	    t = "link";
1075 	else if (S_ISBLK(st.st_mode))
1076 	    t = "bdev";
1077 	else if (S_ISCHR(st.st_mode))
1078 	    t = "cdev";
1079 	else if (S_ISFIFO(st.st_mode))
1080 	    t = "fifo";
1081 	else if (S_ISSOCK(st.st_mode))
1082 	    t = "socket";
1083 	else
1084 	    t = "other";
1085 	type = vim_strsave((char_u *)t);
1086     }
1087     rettv->vval.v_string = type;
1088 }
1089 
1090 /*
1091  * "glob()" function
1092  */
1093     void
1094 f_glob(typval_T *argvars, typval_T *rettv)
1095 {
1096     int		options = WILD_SILENT|WILD_USE_NL;
1097     expand_T	xpc;
1098     int		error = FALSE;
1099 
1100     // When the optional second argument is non-zero, don't remove matches
1101     // for 'wildignore' and don't put matches for 'suffixes' at the end.
1102     rettv->v_type = VAR_STRING;
1103     if (argvars[1].v_type != VAR_UNKNOWN)
1104     {
1105 	if (tv_get_number_chk(&argvars[1], &error))
1106 	    options |= WILD_KEEP_ALL;
1107 	if (argvars[2].v_type != VAR_UNKNOWN)
1108 	{
1109 	    if (tv_get_number_chk(&argvars[2], &error))
1110 		rettv_list_set(rettv, NULL);
1111 	    if (argvars[3].v_type != VAR_UNKNOWN
1112 				    && tv_get_number_chk(&argvars[3], &error))
1113 		options |= WILD_ALLLINKS;
1114 	}
1115     }
1116     if (!error)
1117     {
1118 	ExpandInit(&xpc);
1119 	xpc.xp_context = EXPAND_FILES;
1120 	if (p_wic)
1121 	    options += WILD_ICASE;
1122 	if (rettv->v_type == VAR_STRING)
1123 	    rettv->vval.v_string = ExpandOne(&xpc, tv_get_string(&argvars[0]),
1124 						     NULL, options, WILD_ALL);
1125 	else if (rettv_list_alloc(rettv) != FAIL)
1126 	{
1127 	  int i;
1128 
1129 	  ExpandOne(&xpc, tv_get_string(&argvars[0]),
1130 						NULL, options, WILD_ALL_KEEP);
1131 	  for (i = 0; i < xpc.xp_numfiles; i++)
1132 	      list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1);
1133 
1134 	  ExpandCleanup(&xpc);
1135 	}
1136     }
1137     else
1138 	rettv->vval.v_string = NULL;
1139 }
1140 
1141 /*
1142  * "glob2regpat()" function
1143  */
1144     void
1145 f_glob2regpat(typval_T *argvars, typval_T *rettv)
1146 {
1147     char_u	*pat = tv_get_string_chk(&argvars[0]);
1148 
1149     rettv->v_type = VAR_STRING;
1150     rettv->vval.v_string = (pat == NULL)
1151 			 ? NULL : file_pat_to_reg_pat(pat, NULL, NULL, FALSE);
1152 }
1153 
1154 /*
1155  * "globpath()" function
1156  */
1157     void
1158 f_globpath(typval_T *argvars, typval_T *rettv)
1159 {
1160     int		flags = WILD_IGNORE_COMPLETESLASH;
1161     char_u	buf1[NUMBUFLEN];
1162     char_u	*file = tv_get_string_buf_chk(&argvars[1], buf1);
1163     int		error = FALSE;
1164     garray_T	ga;
1165     int		i;
1166 
1167     // When the optional second argument is non-zero, don't remove matches
1168     // for 'wildignore' and don't put matches for 'suffixes' at the end.
1169     rettv->v_type = VAR_STRING;
1170     if (argvars[2].v_type != VAR_UNKNOWN)
1171     {
1172 	if (tv_get_number_chk(&argvars[2], &error))
1173 	    flags |= WILD_KEEP_ALL;
1174 	if (argvars[3].v_type != VAR_UNKNOWN)
1175 	{
1176 	    if (tv_get_number_chk(&argvars[3], &error))
1177 		rettv_list_set(rettv, NULL);
1178 	    if (argvars[4].v_type != VAR_UNKNOWN
1179 				    && tv_get_number_chk(&argvars[4], &error))
1180 		flags |= WILD_ALLLINKS;
1181 	}
1182     }
1183     if (file != NULL && !error)
1184     {
1185 	ga_init2(&ga, (int)sizeof(char_u *), 10);
1186 	globpath(tv_get_string(&argvars[0]), file, &ga, flags);
1187 	if (rettv->v_type == VAR_STRING)
1188 	    rettv->vval.v_string = ga_concat_strings(&ga, "\n");
1189 	else if (rettv_list_alloc(rettv) != FAIL)
1190 	    for (i = 0; i < ga.ga_len; ++i)
1191 		list_append_string(rettv->vval.v_list,
1192 					    ((char_u **)(ga.ga_data))[i], -1);
1193 	ga_clear_strings(&ga);
1194     }
1195     else
1196 	rettv->vval.v_string = NULL;
1197 }
1198 
1199 /*
1200  * "isdirectory()" function
1201  */
1202     void
1203 f_isdirectory(typval_T *argvars, typval_T *rettv)
1204 {
1205     rettv->vval.v_number = mch_isdir(tv_get_string(&argvars[0]));
1206 }
1207 
1208 /*
1209  * Evaluate "expr" (= "context") for readdir().
1210  */
1211     static int
1212 readdir_checkitem(void *context, char_u *name)
1213 {
1214     typval_T	*expr = (typval_T *)context;
1215     typval_T	save_val;
1216     typval_T	rettv;
1217     typval_T	argv[2];
1218     int		retval = 0;
1219     int		error = FALSE;
1220 
1221     if (expr->v_type == VAR_UNKNOWN)
1222 	return 1;
1223 
1224     prepare_vimvar(VV_VAL, &save_val);
1225     set_vim_var_string(VV_VAL, name, -1);
1226     argv[0].v_type = VAR_STRING;
1227     argv[0].vval.v_string = name;
1228 
1229     if (eval_expr_typval(expr, argv, 1, &rettv) == FAIL)
1230 	goto theend;
1231 
1232     retval = tv_get_number_chk(&rettv, &error);
1233     if (error)
1234 	retval = -1;
1235     clear_tv(&rettv);
1236 
1237 theend:
1238     set_vim_var_string(VV_VAL, NULL, 0);
1239     restore_vimvar(VV_VAL, &save_val);
1240     return retval;
1241 }
1242 
1243 /*
1244  * Create the directory in which "dir" is located, and higher levels when
1245  * needed.
1246  * Return OK or FAIL.
1247  */
1248     static int
1249 mkdir_recurse(char_u *dir, int prot)
1250 {
1251     char_u	*p;
1252     char_u	*updir;
1253     int		r = FAIL;
1254 
1255     // Get end of directory name in "dir".
1256     // We're done when it's "/" or "c:/".
1257     p = gettail_sep(dir);
1258     if (p <= get_past_head(dir))
1259 	return OK;
1260 
1261     // If the directory exists we're done.  Otherwise: create it.
1262     updir = vim_strnsave(dir, (int)(p - dir));
1263     if (updir == NULL)
1264 	return FAIL;
1265     if (mch_isdir(updir))
1266 	r = OK;
1267     else if (mkdir_recurse(updir, prot) == OK)
1268 	r = vim_mkdir_emsg(updir, prot);
1269     vim_free(updir);
1270     return r;
1271 }
1272 
1273 /*
1274  * "mkdir()" function
1275  */
1276     void
1277 f_mkdir(typval_T *argvars, typval_T *rettv)
1278 {
1279     char_u	*dir;
1280     char_u	buf[NUMBUFLEN];
1281     int		prot = 0755;
1282 
1283     rettv->vval.v_number = FAIL;
1284     if (check_restricted() || check_secure())
1285 	return;
1286 
1287     dir = tv_get_string_buf(&argvars[0], buf);
1288     if (*dir == NUL)
1289 	return;
1290 
1291     if (*gettail(dir) == NUL)
1292 	// remove trailing slashes
1293 	*gettail_sep(dir) = NUL;
1294 
1295     if (argvars[1].v_type != VAR_UNKNOWN)
1296     {
1297 	if (argvars[2].v_type != VAR_UNKNOWN)
1298 	{
1299 	    prot = (int)tv_get_number_chk(&argvars[2], NULL);
1300 	    if (prot == -1)
1301 		return;
1302 	}
1303 	if (STRCMP(tv_get_string(&argvars[1]), "p") == 0)
1304 	{
1305 	    if (mch_isdir(dir))
1306 	    {
1307 		// With the "p" flag it's OK if the dir already exists.
1308 		rettv->vval.v_number = OK;
1309 		return;
1310 	    }
1311 	    mkdir_recurse(dir, prot);
1312 	}
1313     }
1314     rettv->vval.v_number = vim_mkdir_emsg(dir, prot);
1315 }
1316 
1317 /*
1318  * "pathshorten()" function
1319  */
1320     void
1321 f_pathshorten(typval_T *argvars, typval_T *rettv)
1322 {
1323     char_u	*p;
1324 
1325     rettv->v_type = VAR_STRING;
1326     p = tv_get_string_chk(&argvars[0]);
1327     if (p == NULL)
1328 	rettv->vval.v_string = NULL;
1329     else
1330     {
1331 	p = vim_strsave(p);
1332 	rettv->vval.v_string = p;
1333 	if (p != NULL)
1334 	    shorten_dir(p);
1335     }
1336 }
1337 
1338 /*
1339  * "readdir()" function
1340  */
1341     void
1342 f_readdir(typval_T *argvars, typval_T *rettv)
1343 {
1344     typval_T	*expr;
1345     int		ret;
1346     char_u	*path;
1347     char_u	*p;
1348     garray_T	ga;
1349     int		i;
1350 
1351     if (rettv_list_alloc(rettv) == FAIL)
1352 	return;
1353     path = tv_get_string(&argvars[0]);
1354     expr = &argvars[1];
1355 
1356     ret = readdir_core(&ga, path, (void *)expr, readdir_checkitem);
1357     if (ret == OK && rettv->vval.v_list != NULL && ga.ga_len > 0)
1358     {
1359 	for (i = 0; i < ga.ga_len; i++)
1360 	{
1361 	    p = ((char_u **)ga.ga_data)[i];
1362 	    list_append_string(rettv->vval.v_list, p, -1);
1363 	}
1364     }
1365     ga_clear_strings(&ga);
1366 }
1367 
1368 /*
1369  * "readfile()" function
1370  */
1371     void
1372 f_readfile(typval_T *argvars, typval_T *rettv)
1373 {
1374     int		binary = FALSE;
1375     int		blob = FALSE;
1376     int		failed = FALSE;
1377     char_u	*fname;
1378     FILE	*fd;
1379     char_u	buf[(IOSIZE/256)*256];	// rounded to avoid odd + 1
1380     int		io_size = sizeof(buf);
1381     int		readlen;		// size of last fread()
1382     char_u	*prev	 = NULL;	// previously read bytes, if any
1383     long	prevlen  = 0;		// length of data in prev
1384     long	prevsize = 0;		// size of prev buffer
1385     long	maxline  = MAXLNUM;
1386     long	cnt	 = 0;
1387     char_u	*p;			// position in buf
1388     char_u	*start;			// start of current line
1389 
1390     if (argvars[1].v_type != VAR_UNKNOWN)
1391     {
1392 	if (STRCMP(tv_get_string(&argvars[1]), "b") == 0)
1393 	    binary = TRUE;
1394 	if (STRCMP(tv_get_string(&argvars[1]), "B") == 0)
1395 	    blob = TRUE;
1396 
1397 	if (argvars[2].v_type != VAR_UNKNOWN)
1398 	    maxline = (long)tv_get_number(&argvars[2]);
1399     }
1400 
1401     if (blob)
1402     {
1403 	if (rettv_blob_alloc(rettv) == FAIL)
1404 	    return;
1405     }
1406     else
1407     {
1408 	if (rettv_list_alloc(rettv) == FAIL)
1409 	    return;
1410     }
1411 
1412     // Always open the file in binary mode, library functions have a mind of
1413     // their own about CR-LF conversion.
1414     fname = tv_get_string(&argvars[0]);
1415     if (*fname == NUL || (fd = mch_fopen((char *)fname, READBIN)) == NULL)
1416     {
1417 	semsg(_(e_notopen), *fname == NUL ? (char_u *)_("<empty>") : fname);
1418 	return;
1419     }
1420 
1421     if (blob)
1422     {
1423 	if (read_blob(fd, rettv->vval.v_blob) == FAIL)
1424 	{
1425 	    emsg("cannot read file");
1426 	    blob_free(rettv->vval.v_blob);
1427 	}
1428 	fclose(fd);
1429 	return;
1430     }
1431 
1432     while (cnt < maxline || maxline < 0)
1433     {
1434 	readlen = (int)fread(buf, 1, io_size, fd);
1435 
1436 	// This for loop processes what was read, but is also entered at end
1437 	// of file so that either:
1438 	// - an incomplete line gets written
1439 	// - a "binary" file gets an empty line at the end if it ends in a
1440 	//   newline.
1441 	for (p = buf, start = buf;
1442 		p < buf + readlen || (readlen <= 0 && (prevlen > 0 || binary));
1443 		++p)
1444 	{
1445 	    if (*p == '\n' || readlen <= 0)
1446 	    {
1447 		listitem_T  *li;
1448 		char_u	    *s	= NULL;
1449 		long_u	    len = p - start;
1450 
1451 		// Finished a line.  Remove CRs before NL.
1452 		if (readlen > 0 && !binary)
1453 		{
1454 		    while (len > 0 && start[len - 1] == '\r')
1455 			--len;
1456 		    // removal may cross back to the "prev" string
1457 		    if (len == 0)
1458 			while (prevlen > 0 && prev[prevlen - 1] == '\r')
1459 			    --prevlen;
1460 		}
1461 		if (prevlen == 0)
1462 		    s = vim_strnsave(start, (int)len);
1463 		else
1464 		{
1465 		    // Change "prev" buffer to be the right size.  This way
1466 		    // the bytes are only copied once, and very long lines are
1467 		    // allocated only once.
1468 		    if ((s = vim_realloc(prev, prevlen + len + 1)) != NULL)
1469 		    {
1470 			mch_memmove(s + prevlen, start, len);
1471 			s[prevlen + len] = NUL;
1472 			prev = NULL; // the list will own the string
1473 			prevlen = prevsize = 0;
1474 		    }
1475 		}
1476 		if (s == NULL)
1477 		{
1478 		    do_outofmem_msg((long_u) prevlen + len + 1);
1479 		    failed = TRUE;
1480 		    break;
1481 		}
1482 
1483 		if ((li = listitem_alloc()) == NULL)
1484 		{
1485 		    vim_free(s);
1486 		    failed = TRUE;
1487 		    break;
1488 		}
1489 		li->li_tv.v_type = VAR_STRING;
1490 		li->li_tv.v_lock = 0;
1491 		li->li_tv.vval.v_string = s;
1492 		list_append(rettv->vval.v_list, li);
1493 
1494 		start = p + 1; // step over newline
1495 		if ((++cnt >= maxline && maxline >= 0) || readlen <= 0)
1496 		    break;
1497 	    }
1498 	    else if (*p == NUL)
1499 		*p = '\n';
1500 	    // Check for utf8 "bom"; U+FEFF is encoded as EF BB BF.  Do this
1501 	    // when finding the BF and check the previous two bytes.
1502 	    else if (*p == 0xbf && enc_utf8 && !binary)
1503 	    {
1504 		// Find the two bytes before the 0xbf.	If p is at buf, or buf
1505 		// + 1, these may be in the "prev" string.
1506 		char_u back1 = p >= buf + 1 ? p[-1]
1507 				     : prevlen >= 1 ? prev[prevlen - 1] : NUL;
1508 		char_u back2 = p >= buf + 2 ? p[-2]
1509 			  : p == buf + 1 && prevlen >= 1 ? prev[prevlen - 1]
1510 			  : prevlen >= 2 ? prev[prevlen - 2] : NUL;
1511 
1512 		if (back2 == 0xef && back1 == 0xbb)
1513 		{
1514 		    char_u *dest = p - 2;
1515 
1516 		    // Usually a BOM is at the beginning of a file, and so at
1517 		    // the beginning of a line; then we can just step over it.
1518 		    if (start == dest)
1519 			start = p + 1;
1520 		    else
1521 		    {
1522 			// have to shuffle buf to close gap
1523 			int adjust_prevlen = 0;
1524 
1525 			if (dest < buf)
1526 			{
1527 			    adjust_prevlen = (int)(buf - dest); // must be 1 or 2
1528 			    dest = buf;
1529 			}
1530 			if (readlen > p - buf + 1)
1531 			    mch_memmove(dest, p + 1, readlen - (p - buf) - 1);
1532 			readlen -= 3 - adjust_prevlen;
1533 			prevlen -= adjust_prevlen;
1534 			p = dest - 1;
1535 		    }
1536 		}
1537 	    }
1538 	} // for
1539 
1540 	if (failed || (cnt >= maxline && maxline >= 0) || readlen <= 0)
1541 	    break;
1542 	if (start < p)
1543 	{
1544 	    // There's part of a line in buf, store it in "prev".
1545 	    if (p - start + prevlen >= prevsize)
1546 	    {
1547 		// need bigger "prev" buffer
1548 		char_u *newprev;
1549 
1550 		// A common use case is ordinary text files and "prev" gets a
1551 		// fragment of a line, so the first allocation is made
1552 		// small, to avoid repeatedly 'allocing' large and
1553 		// 'reallocing' small.
1554 		if (prevsize == 0)
1555 		    prevsize = (long)(p - start);
1556 		else
1557 		{
1558 		    long grow50pc = (prevsize * 3) / 2;
1559 		    long growmin  = (long)((p - start) * 2 + prevlen);
1560 		    prevsize = grow50pc > growmin ? grow50pc : growmin;
1561 		}
1562 		newprev = vim_realloc(prev, prevsize);
1563 		if (newprev == NULL)
1564 		{
1565 		    do_outofmem_msg((long_u)prevsize);
1566 		    failed = TRUE;
1567 		    break;
1568 		}
1569 		prev = newprev;
1570 	    }
1571 	    // Add the line part to end of "prev".
1572 	    mch_memmove(prev + prevlen, start, p - start);
1573 	    prevlen += (long)(p - start);
1574 	}
1575     } // while
1576 
1577     // For a negative line count use only the lines at the end of the file,
1578     // free the rest.
1579     if (!failed && maxline < 0)
1580 	while (cnt > -maxline)
1581 	{
1582 	    listitem_remove(rettv->vval.v_list, rettv->vval.v_list->lv_first);
1583 	    --cnt;
1584 	}
1585 
1586     if (failed)
1587     {
1588 	// an empty list is returned on error
1589 	list_free(rettv->vval.v_list);
1590 	rettv_list_alloc(rettv);
1591     }
1592 
1593     vim_free(prev);
1594     fclose(fd);
1595 }
1596 
1597 /*
1598  * "resolve()" function
1599  */
1600     void
1601 f_resolve(typval_T *argvars, typval_T *rettv)
1602 {
1603     char_u	*p;
1604 #ifdef HAVE_READLINK
1605     char_u	*buf = NULL;
1606 #endif
1607 
1608     p = tv_get_string(&argvars[0]);
1609 #ifdef FEAT_SHORTCUT
1610     {
1611 	char_u	*v = NULL;
1612 
1613 	v = mch_resolve_path(p, TRUE);
1614 	if (v != NULL)
1615 	    rettv->vval.v_string = v;
1616 	else
1617 	    rettv->vval.v_string = vim_strsave(p);
1618     }
1619 #else
1620 # ifdef HAVE_READLINK
1621     {
1622 	char_u	*cpy;
1623 	int	len;
1624 	char_u	*remain = NULL;
1625 	char_u	*q;
1626 	int	is_relative_to_current = FALSE;
1627 	int	has_trailing_pathsep = FALSE;
1628 	int	limit = 100;
1629 
1630 	p = vim_strsave(p);
1631 
1632 	if (p[0] == '.' && (vim_ispathsep(p[1])
1633 				   || (p[1] == '.' && (vim_ispathsep(p[2])))))
1634 	    is_relative_to_current = TRUE;
1635 
1636 	len = STRLEN(p);
1637 	if (len > 0 && after_pathsep(p, p + len))
1638 	{
1639 	    has_trailing_pathsep = TRUE;
1640 	    p[len - 1] = NUL; // the trailing slash breaks readlink()
1641 	}
1642 
1643 	q = getnextcomp(p);
1644 	if (*q != NUL)
1645 	{
1646 	    // Separate the first path component in "p", and keep the
1647 	    // remainder (beginning with the path separator).
1648 	    remain = vim_strsave(q - 1);
1649 	    q[-1] = NUL;
1650 	}
1651 
1652 	buf = alloc(MAXPATHL + 1);
1653 	if (buf == NULL)
1654 	    goto fail;
1655 
1656 	for (;;)
1657 	{
1658 	    for (;;)
1659 	    {
1660 		len = readlink((char *)p, (char *)buf, MAXPATHL);
1661 		if (len <= 0)
1662 		    break;
1663 		buf[len] = NUL;
1664 
1665 		if (limit-- == 0)
1666 		{
1667 		    vim_free(p);
1668 		    vim_free(remain);
1669 		    emsg(_("E655: Too many symbolic links (cycle?)"));
1670 		    rettv->vval.v_string = NULL;
1671 		    goto fail;
1672 		}
1673 
1674 		// Ensure that the result will have a trailing path separator
1675 		// if the argument has one.
1676 		if (remain == NULL && has_trailing_pathsep)
1677 		    add_pathsep(buf);
1678 
1679 		// Separate the first path component in the link value and
1680 		// concatenate the remainders.
1681 		q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf);
1682 		if (*q != NUL)
1683 		{
1684 		    if (remain == NULL)
1685 			remain = vim_strsave(q - 1);
1686 		    else
1687 		    {
1688 			cpy = concat_str(q - 1, remain);
1689 			if (cpy != NULL)
1690 			{
1691 			    vim_free(remain);
1692 			    remain = cpy;
1693 			}
1694 		    }
1695 		    q[-1] = NUL;
1696 		}
1697 
1698 		q = gettail(p);
1699 		if (q > p && *q == NUL)
1700 		{
1701 		    // Ignore trailing path separator.
1702 		    q[-1] = NUL;
1703 		    q = gettail(p);
1704 		}
1705 		if (q > p && !mch_isFullName(buf))
1706 		{
1707 		    // symlink is relative to directory of argument
1708 		    cpy = alloc(STRLEN(p) + STRLEN(buf) + 1);
1709 		    if (cpy != NULL)
1710 		    {
1711 			STRCPY(cpy, p);
1712 			STRCPY(gettail(cpy), buf);
1713 			vim_free(p);
1714 			p = cpy;
1715 		    }
1716 		}
1717 		else
1718 		{
1719 		    vim_free(p);
1720 		    p = vim_strsave(buf);
1721 		}
1722 	    }
1723 
1724 	    if (remain == NULL)
1725 		break;
1726 
1727 	    // Append the first path component of "remain" to "p".
1728 	    q = getnextcomp(remain + 1);
1729 	    len = q - remain - (*q != NUL);
1730 	    cpy = vim_strnsave(p, STRLEN(p) + len);
1731 	    if (cpy != NULL)
1732 	    {
1733 		STRNCAT(cpy, remain, len);
1734 		vim_free(p);
1735 		p = cpy;
1736 	    }
1737 	    // Shorten "remain".
1738 	    if (*q != NUL)
1739 		STRMOVE(remain, q - 1);
1740 	    else
1741 		VIM_CLEAR(remain);
1742 	}
1743 
1744 	// If the result is a relative path name, make it explicitly relative to
1745 	// the current directory if and only if the argument had this form.
1746 	if (!vim_ispathsep(*p))
1747 	{
1748 	    if (is_relative_to_current
1749 		    && *p != NUL
1750 		    && !(p[0] == '.'
1751 			&& (p[1] == NUL
1752 			    || vim_ispathsep(p[1])
1753 			    || (p[1] == '.'
1754 				&& (p[2] == NUL
1755 				    || vim_ispathsep(p[2]))))))
1756 	    {
1757 		// Prepend "./".
1758 		cpy = concat_str((char_u *)"./", p);
1759 		if (cpy != NULL)
1760 		{
1761 		    vim_free(p);
1762 		    p = cpy;
1763 		}
1764 	    }
1765 	    else if (!is_relative_to_current)
1766 	    {
1767 		// Strip leading "./".
1768 		q = p;
1769 		while (q[0] == '.' && vim_ispathsep(q[1]))
1770 		    q += 2;
1771 		if (q > p)
1772 		    STRMOVE(p, p + 2);
1773 	    }
1774 	}
1775 
1776 	// Ensure that the result will have no trailing path separator
1777 	// if the argument had none.  But keep "/" or "//".
1778 	if (!has_trailing_pathsep)
1779 	{
1780 	    q = p + STRLEN(p);
1781 	    if (after_pathsep(p, q))
1782 		*gettail_sep(p) = NUL;
1783 	}
1784 
1785 	rettv->vval.v_string = p;
1786     }
1787 # else
1788     rettv->vval.v_string = vim_strsave(p);
1789 # endif
1790 #endif
1791 
1792     simplify_filename(rettv->vval.v_string);
1793 
1794 #ifdef HAVE_READLINK
1795 fail:
1796     vim_free(buf);
1797 #endif
1798     rettv->v_type = VAR_STRING;
1799 }
1800 
1801 /*
1802  * "tempname()" function
1803  */
1804     void
1805 f_tempname(typval_T *argvars UNUSED, typval_T *rettv)
1806 {
1807     static int	x = 'A';
1808 
1809     rettv->v_type = VAR_STRING;
1810     rettv->vval.v_string = vim_tempname(x, FALSE);
1811 
1812     // Advance 'x' to use A-Z and 0-9, so that there are at least 34 different
1813     // names.  Skip 'I' and 'O', they are used for shell redirection.
1814     do
1815     {
1816 	if (x == 'Z')
1817 	    x = '0';
1818 	else if (x == '9')
1819 	    x = 'A';
1820 	else
1821 	{
1822 #ifdef EBCDIC
1823 	    if (x == 'I')
1824 		x = 'J';
1825 	    else if (x == 'R')
1826 		x = 'S';
1827 	    else
1828 #endif
1829 		++x;
1830 	}
1831     } while (x == 'I' || x == 'O');
1832 }
1833 
1834 /*
1835  * "writefile()" function
1836  */
1837     void
1838 f_writefile(typval_T *argvars, typval_T *rettv)
1839 {
1840     int		binary = FALSE;
1841     int		append = FALSE;
1842 #ifdef HAVE_FSYNC
1843     int		do_fsync = p_fs;
1844 #endif
1845     char_u	*fname;
1846     FILE	*fd;
1847     int		ret = 0;
1848     listitem_T	*li;
1849     list_T	*list = NULL;
1850     blob_T	*blob = NULL;
1851 
1852     rettv->vval.v_number = -1;
1853     if (check_secure())
1854 	return;
1855 
1856     if (argvars[0].v_type == VAR_LIST)
1857     {
1858 	list = argvars[0].vval.v_list;
1859 	if (list == NULL)
1860 	    return;
1861 	for (li = list->lv_first; li != NULL; li = li->li_next)
1862 	    if (tv_get_string_chk(&li->li_tv) == NULL)
1863 		return;
1864     }
1865     else if (argvars[0].v_type == VAR_BLOB)
1866     {
1867 	blob = argvars[0].vval.v_blob;
1868 	if (blob == NULL)
1869 	    return;
1870     }
1871     else
1872     {
1873 	semsg(_(e_invarg2), "writefile()");
1874 	return;
1875     }
1876 
1877     if (argvars[2].v_type != VAR_UNKNOWN)
1878     {
1879 	char_u *arg2 = tv_get_string_chk(&argvars[2]);
1880 
1881 	if (arg2 == NULL)
1882 	    return;
1883 	if (vim_strchr(arg2, 'b') != NULL)
1884 	    binary = TRUE;
1885 	if (vim_strchr(arg2, 'a') != NULL)
1886 	    append = TRUE;
1887 #ifdef HAVE_FSYNC
1888 	if (vim_strchr(arg2, 's') != NULL)
1889 	    do_fsync = TRUE;
1890 	else if (vim_strchr(arg2, 'S') != NULL)
1891 	    do_fsync = FALSE;
1892 #endif
1893     }
1894 
1895     fname = tv_get_string_chk(&argvars[1]);
1896     if (fname == NULL)
1897 	return;
1898 
1899     // Always open the file in binary mode, library functions have a mind of
1900     // their own about CR-LF conversion.
1901     if (*fname == NUL || (fd = mch_fopen((char *)fname,
1902 				      append ? APPENDBIN : WRITEBIN)) == NULL)
1903     {
1904 	semsg(_(e_notcreate), *fname == NUL ? (char_u *)_("<empty>") : fname);
1905 	ret = -1;
1906     }
1907     else if (blob)
1908     {
1909 	if (write_blob(fd, blob) == FAIL)
1910 	    ret = -1;
1911 #ifdef HAVE_FSYNC
1912 	else if (do_fsync)
1913 	    // Ignore the error, the user wouldn't know what to do about it.
1914 	    // May happen for a device.
1915 	    vim_ignored = vim_fsync(fileno(fd));
1916 #endif
1917 	fclose(fd);
1918     }
1919     else
1920     {
1921 	if (write_list(fd, list, binary) == FAIL)
1922 	    ret = -1;
1923 #ifdef HAVE_FSYNC
1924 	else if (do_fsync)
1925 	    // Ignore the error, the user wouldn't know what to do about it.
1926 	    // May happen for a device.
1927 	    vim_ignored = vim_fsync(fileno(fd));
1928 #endif
1929 	fclose(fd);
1930     }
1931 
1932     rettv->vval.v_number = ret;
1933 }
1934 
1935 #endif // FEAT_EVAL
1936 
1937 #if defined(FEAT_BROWSE) || defined(PROTO)
1938 /*
1939  * Generic browse function.  Calls gui_mch_browse() when possible.
1940  * Later this may pop-up a non-GUI file selector (external command?).
1941  */
1942     char_u *
1943 do_browse(
1944     int		flags,		// BROWSE_SAVE and BROWSE_DIR
1945     char_u	*title,		// title for the window
1946     char_u	*dflt,		// default file name (may include directory)
1947     char_u	*ext,		// extension added
1948     char_u	*initdir,	// initial directory, NULL for current dir or
1949 				// when using path from "dflt"
1950     char_u	*filter,	// file name filter
1951     buf_T	*buf)		// buffer to read/write for
1952 {
1953     char_u		*fname;
1954     static char_u	*last_dir = NULL;    // last used directory
1955     char_u		*tofree = NULL;
1956     int			save_browse = cmdmod.browse;
1957 
1958     // Must turn off browse to avoid that autocommands will get the
1959     // flag too!
1960     cmdmod.browse = FALSE;
1961 
1962     if (title == NULL || *title == NUL)
1963     {
1964 	if (flags & BROWSE_DIR)
1965 	    title = (char_u *)_("Select Directory dialog");
1966 	else if (flags & BROWSE_SAVE)
1967 	    title = (char_u *)_("Save File dialog");
1968 	else
1969 	    title = (char_u *)_("Open File dialog");
1970     }
1971 
1972     // When no directory specified, use default file name, default dir, buffer
1973     // dir, last dir or current dir
1974     if ((initdir == NULL || *initdir == NUL) && dflt != NULL && *dflt != NUL)
1975     {
1976 	if (mch_isdir(dflt))		// default file name is a directory
1977 	{
1978 	    initdir = dflt;
1979 	    dflt = NULL;
1980 	}
1981 	else if (gettail(dflt) != dflt)	// default file name includes a path
1982 	{
1983 	    tofree = vim_strsave(dflt);
1984 	    if (tofree != NULL)
1985 	    {
1986 		initdir = tofree;
1987 		*gettail(initdir) = NUL;
1988 		dflt = gettail(dflt);
1989 	    }
1990 	}
1991     }
1992 
1993     if (initdir == NULL || *initdir == NUL)
1994     {
1995 	// When 'browsedir' is a directory, use it
1996 	if (STRCMP(p_bsdir, "last") != 0
1997 		&& STRCMP(p_bsdir, "buffer") != 0
1998 		&& STRCMP(p_bsdir, "current") != 0
1999 		&& mch_isdir(p_bsdir))
2000 	    initdir = p_bsdir;
2001 	// When saving or 'browsedir' is "buffer", use buffer fname
2002 	else if (((flags & BROWSE_SAVE) || *p_bsdir == 'b')
2003 		&& buf != NULL && buf->b_ffname != NULL)
2004 	{
2005 	    if (dflt == NULL || *dflt == NUL)
2006 		dflt = gettail(curbuf->b_ffname);
2007 	    tofree = vim_strsave(curbuf->b_ffname);
2008 	    if (tofree != NULL)
2009 	    {
2010 		initdir = tofree;
2011 		*gettail(initdir) = NUL;
2012 	    }
2013 	}
2014 	// When 'browsedir' is "last", use dir from last browse
2015 	else if (*p_bsdir == 'l')
2016 	    initdir = last_dir;
2017 	// When 'browsedir is "current", use current directory.  This is the
2018 	// default already, leave initdir empty.
2019     }
2020 
2021 # ifdef FEAT_GUI
2022     if (gui.in_use)		// when this changes, also adjust f_has()!
2023     {
2024 	if (filter == NULL
2025 #  ifdef FEAT_EVAL
2026 		&& (filter = get_var_value((char_u *)"b:browsefilter")) == NULL
2027 		&& (filter = get_var_value((char_u *)"g:browsefilter")) == NULL
2028 #  endif
2029 	)
2030 	    filter = BROWSE_FILTER_DEFAULT;
2031 	if (flags & BROWSE_DIR)
2032 	{
2033 #  if defined(FEAT_GUI_GTK) || defined(MSWIN)
2034 	    // For systems that have a directory dialog.
2035 	    fname = gui_mch_browsedir(title, initdir);
2036 #  else
2037 	    // Generic solution for selecting a directory: select a file and
2038 	    // remove the file name.
2039 	    fname = gui_mch_browse(0, title, dflt, ext, initdir, (char_u *)"");
2040 #  endif
2041 #  if !defined(FEAT_GUI_GTK)
2042 	    // Win32 adds a dummy file name, others return an arbitrary file
2043 	    // name.  GTK+ 2 returns only the directory,
2044 	    if (fname != NULL && *fname != NUL && !mch_isdir(fname))
2045 	    {
2046 		// Remove the file name.
2047 		char_u	    *tail = gettail_sep(fname);
2048 
2049 		if (tail == fname)
2050 		    *tail++ = '.';	// use current dir
2051 		*tail = NUL;
2052 	    }
2053 #  endif
2054 	}
2055 	else
2056 	    fname = gui_mch_browse(flags & BROWSE_SAVE,
2057 			       title, dflt, ext, initdir, (char_u *)_(filter));
2058 
2059 	// We hang around in the dialog for a while, the user might do some
2060 	// things to our files.  The Win32 dialog allows deleting or renaming
2061 	// a file, check timestamps.
2062 	need_check_timestamps = TRUE;
2063 	did_check_timestamps = FALSE;
2064     }
2065     else
2066 # endif
2067     {
2068 	// TODO: non-GUI file selector here
2069 	emsg(_("E338: Sorry, no file browser in console mode"));
2070 	fname = NULL;
2071     }
2072 
2073     // keep the directory for next time
2074     if (fname != NULL)
2075     {
2076 	vim_free(last_dir);
2077 	last_dir = vim_strsave(fname);
2078 	if (last_dir != NULL && !(flags & BROWSE_DIR))
2079 	{
2080 	    *gettail(last_dir) = NUL;
2081 	    if (*last_dir == NUL)
2082 	    {
2083 		// filename only returned, must be in current dir
2084 		vim_free(last_dir);
2085 		last_dir = alloc(MAXPATHL);
2086 		if (last_dir != NULL)
2087 		    mch_dirname(last_dir, MAXPATHL);
2088 	    }
2089 	}
2090     }
2091 
2092     vim_free(tofree);
2093     cmdmod.browse = save_browse;
2094 
2095     return fname;
2096 }
2097 #endif
2098 
2099 #if defined(FEAT_EVAL) || defined(PROTO)
2100 
2101 /*
2102  * "browse(save, title, initdir, default)" function
2103  */
2104     void
2105 f_browse(typval_T *argvars UNUSED, typval_T *rettv)
2106 {
2107 # ifdef FEAT_BROWSE
2108     int		save;
2109     char_u	*title;
2110     char_u	*initdir;
2111     char_u	*defname;
2112     char_u	buf[NUMBUFLEN];
2113     char_u	buf2[NUMBUFLEN];
2114     int		error = FALSE;
2115 
2116     save = (int)tv_get_number_chk(&argvars[0], &error);
2117     title = tv_get_string_chk(&argvars[1]);
2118     initdir = tv_get_string_buf_chk(&argvars[2], buf);
2119     defname = tv_get_string_buf_chk(&argvars[3], buf2);
2120 
2121     if (error || title == NULL || initdir == NULL || defname == NULL)
2122 	rettv->vval.v_string = NULL;
2123     else
2124 	rettv->vval.v_string =
2125 		 do_browse(save ? BROWSE_SAVE : 0,
2126 				 title, defname, NULL, initdir, NULL, curbuf);
2127 # else
2128     rettv->vval.v_string = NULL;
2129 # endif
2130     rettv->v_type = VAR_STRING;
2131 }
2132 
2133 /*
2134  * "browsedir(title, initdir)" function
2135  */
2136     void
2137 f_browsedir(typval_T *argvars UNUSED, typval_T *rettv)
2138 {
2139 # ifdef FEAT_BROWSE
2140     char_u	*title;
2141     char_u	*initdir;
2142     char_u	buf[NUMBUFLEN];
2143 
2144     title = tv_get_string_chk(&argvars[0]);
2145     initdir = tv_get_string_buf_chk(&argvars[1], buf);
2146 
2147     if (title == NULL || initdir == NULL)
2148 	rettv->vval.v_string = NULL;
2149     else
2150 	rettv->vval.v_string = do_browse(BROWSE_DIR,
2151 				    title, NULL, NULL, initdir, NULL, curbuf);
2152 # else
2153     rettv->vval.v_string = NULL;
2154 # endif
2155     rettv->v_type = VAR_STRING;
2156 }
2157 
2158 #endif // FEAT_EVAL
2159 
2160 /*
2161  * Replace home directory by "~" in each space or comma separated file name in
2162  * 'src'.
2163  * If anything fails (except when out of space) dst equals src.
2164  */
2165     void
2166 home_replace(
2167     buf_T	*buf,	// when not NULL, check for help files
2168     char_u	*src,	// input file name
2169     char_u	*dst,	// where to put the result
2170     int		dstlen,	// maximum length of the result
2171     int		one)	// if TRUE, only replace one file name, include
2172 			// spaces and commas in the file name.
2173 {
2174     size_t	dirlen = 0, envlen = 0;
2175     size_t	len;
2176     char_u	*homedir_env, *homedir_env_orig;
2177     char_u	*p;
2178 
2179     if (src == NULL)
2180     {
2181 	*dst = NUL;
2182 	return;
2183     }
2184 
2185     /*
2186      * If the file is a help file, remove the path completely.
2187      */
2188     if (buf != NULL && buf->b_help)
2189     {
2190 	vim_snprintf((char *)dst, dstlen, "%s", gettail(src));
2191 	return;
2192     }
2193 
2194     /*
2195      * We check both the value of the $HOME environment variable and the
2196      * "real" home directory.
2197      */
2198     if (homedir != NULL)
2199 	dirlen = STRLEN(homedir);
2200 
2201 #ifdef VMS
2202     homedir_env_orig = homedir_env = mch_getenv((char_u *)"SYS$LOGIN");
2203 #else
2204     homedir_env_orig = homedir_env = mch_getenv((char_u *)"HOME");
2205 #endif
2206 #ifdef MSWIN
2207     if (homedir_env == NULL)
2208 	homedir_env_orig = homedir_env = mch_getenv((char_u *)"USERPROFILE");
2209 #endif
2210     // Empty is the same as not set.
2211     if (homedir_env != NULL && *homedir_env == NUL)
2212 	homedir_env = NULL;
2213 
2214     if (homedir_env != NULL && *homedir_env == '~')
2215     {
2216 	int	usedlen = 0;
2217 	int	flen;
2218 	char_u	*fbuf = NULL;
2219 
2220 	flen = (int)STRLEN(homedir_env);
2221 	(void)modify_fname((char_u *)":p", FALSE, &usedlen,
2222 						  &homedir_env, &fbuf, &flen);
2223 	flen = (int)STRLEN(homedir_env);
2224 	if (flen > 0 && vim_ispathsep(homedir_env[flen - 1]))
2225 	    // Remove the trailing / that is added to a directory.
2226 	    homedir_env[flen - 1] = NUL;
2227     }
2228 
2229     if (homedir_env != NULL)
2230 	envlen = STRLEN(homedir_env);
2231 
2232     if (!one)
2233 	src = skipwhite(src);
2234     while (*src && dstlen > 0)
2235     {
2236 	/*
2237 	 * Here we are at the beginning of a file name.
2238 	 * First, check to see if the beginning of the file name matches
2239 	 * $HOME or the "real" home directory. Check that there is a '/'
2240 	 * after the match (so that if e.g. the file is "/home/pieter/bla",
2241 	 * and the home directory is "/home/piet", the file does not end up
2242 	 * as "~er/bla" (which would seem to indicate the file "bla" in user
2243 	 * er's home directory)).
2244 	 */
2245 	p = homedir;
2246 	len = dirlen;
2247 	for (;;)
2248 	{
2249 	    if (   len
2250 		&& fnamencmp(src, p, len) == 0
2251 		&& (vim_ispathsep(src[len])
2252 		    || (!one && (src[len] == ',' || src[len] == ' '))
2253 		    || src[len] == NUL))
2254 	    {
2255 		src += len;
2256 		if (--dstlen > 0)
2257 		    *dst++ = '~';
2258 
2259 		/*
2260 		 * If it's just the home directory, add  "/".
2261 		 */
2262 		if (!vim_ispathsep(src[0]) && --dstlen > 0)
2263 		    *dst++ = '/';
2264 		break;
2265 	    }
2266 	    if (p == homedir_env)
2267 		break;
2268 	    p = homedir_env;
2269 	    len = envlen;
2270 	}
2271 
2272 	// if (!one) skip to separator: space or comma
2273 	while (*src && (one || (*src != ',' && *src != ' ')) && --dstlen > 0)
2274 	    *dst++ = *src++;
2275 	// skip separator
2276 	while ((*src == ' ' || *src == ',') && --dstlen > 0)
2277 	    *dst++ = *src++;
2278     }
2279     // if (dstlen == 0) out of space, what to do???
2280 
2281     *dst = NUL;
2282 
2283     if (homedir_env != homedir_env_orig)
2284 	vim_free(homedir_env);
2285 }
2286 
2287 /*
2288  * Like home_replace, store the replaced string in allocated memory.
2289  * When something fails, NULL is returned.
2290  */
2291     char_u  *
2292 home_replace_save(
2293     buf_T	*buf,	// when not NULL, check for help files
2294     char_u	*src)	// input file name
2295 {
2296     char_u	*dst;
2297     unsigned	len;
2298 
2299     len = 3;			// space for "~/" and trailing NUL
2300     if (src != NULL)		// just in case
2301 	len += (unsigned)STRLEN(src);
2302     dst = alloc(len);
2303     if (dst != NULL)
2304 	home_replace(buf, src, dst, len, TRUE);
2305     return dst;
2306 }
2307 
2308 /*
2309  * Compare two file names and return:
2310  * FPC_SAME   if they both exist and are the same file.
2311  * FPC_SAMEX  if they both don't exist and have the same file name.
2312  * FPC_DIFF   if they both exist and are different files.
2313  * FPC_NOTX   if they both don't exist.
2314  * FPC_DIFFX  if one of them doesn't exist.
2315  * For the first name environment variables are expanded if "expandenv" is
2316  * TRUE.
2317  */
2318     int
2319 fullpathcmp(
2320     char_u *s1,
2321     char_u *s2,
2322     int	    checkname,		// when both don't exist, check file names
2323     int	    expandenv)
2324 {
2325 #ifdef UNIX
2326     char_u	    exp1[MAXPATHL];
2327     char_u	    full1[MAXPATHL];
2328     char_u	    full2[MAXPATHL];
2329     stat_T	    st1, st2;
2330     int		    r1, r2;
2331 
2332     if (expandenv)
2333 	expand_env(s1, exp1, MAXPATHL);
2334     else
2335 	vim_strncpy(exp1, s1, MAXPATHL - 1);
2336     r1 = mch_stat((char *)exp1, &st1);
2337     r2 = mch_stat((char *)s2, &st2);
2338     if (r1 != 0 && r2 != 0)
2339     {
2340 	/* if mch_stat() doesn't work, may compare the names */
2341 	if (checkname)
2342 	{
2343 	    if (fnamecmp(exp1, s2) == 0)
2344 		return FPC_SAMEX;
2345 	    r1 = vim_FullName(exp1, full1, MAXPATHL, FALSE);
2346 	    r2 = vim_FullName(s2, full2, MAXPATHL, FALSE);
2347 	    if (r1 == OK && r2 == OK && fnamecmp(full1, full2) == 0)
2348 		return FPC_SAMEX;
2349 	}
2350 	return FPC_NOTX;
2351     }
2352     if (r1 != 0 || r2 != 0)
2353 	return FPC_DIFFX;
2354     if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino)
2355 	return FPC_SAME;
2356     return FPC_DIFF;
2357 #else
2358     char_u  *exp1;		// expanded s1
2359     char_u  *full1;		// full path of s1
2360     char_u  *full2;		// full path of s2
2361     int	    retval = FPC_DIFF;
2362     int	    r1, r2;
2363 
2364     // allocate one buffer to store three paths (alloc()/free() is slow!)
2365     if ((exp1 = alloc(MAXPATHL * 3)) != NULL)
2366     {
2367 	full1 = exp1 + MAXPATHL;
2368 	full2 = full1 + MAXPATHL;
2369 
2370 	if (expandenv)
2371 	    expand_env(s1, exp1, MAXPATHL);
2372 	else
2373 	    vim_strncpy(exp1, s1, MAXPATHL - 1);
2374 	r1 = vim_FullName(exp1, full1, MAXPATHL, FALSE);
2375 	r2 = vim_FullName(s2, full2, MAXPATHL, FALSE);
2376 
2377 	// If vim_FullName() fails, the file probably doesn't exist.
2378 	if (r1 != OK && r2 != OK)
2379 	{
2380 	    if (checkname && fnamecmp(exp1, s2) == 0)
2381 		retval = FPC_SAMEX;
2382 	    else
2383 		retval = FPC_NOTX;
2384 	}
2385 	else if (r1 != OK || r2 != OK)
2386 	    retval = FPC_DIFFX;
2387 	else if (fnamecmp(full1, full2))
2388 	    retval = FPC_DIFF;
2389 	else
2390 	    retval = FPC_SAME;
2391 	vim_free(exp1);
2392     }
2393     return retval;
2394 #endif
2395 }
2396 
2397 /*
2398  * Get the tail of a path: the file name.
2399  * When the path ends in a path separator the tail is the NUL after it.
2400  * Fail safe: never returns NULL.
2401  */
2402     char_u *
2403 gettail(char_u *fname)
2404 {
2405     char_u  *p1, *p2;
2406 
2407     if (fname == NULL)
2408 	return (char_u *)"";
2409     for (p1 = p2 = get_past_head(fname); *p2; )	// find last part of path
2410     {
2411 	if (vim_ispathsep_nocolon(*p2))
2412 	    p1 = p2 + 1;
2413 	MB_PTR_ADV(p2);
2414     }
2415     return p1;
2416 }
2417 
2418 /*
2419  * Get pointer to tail of "fname", including path separators.  Putting a NUL
2420  * here leaves the directory name.  Takes care of "c:/" and "//".
2421  * Always returns a valid pointer.
2422  */
2423     char_u *
2424 gettail_sep(char_u *fname)
2425 {
2426     char_u	*p;
2427     char_u	*t;
2428 
2429     p = get_past_head(fname);	// don't remove the '/' from "c:/file"
2430     t = gettail(fname);
2431     while (t > p && after_pathsep(fname, t))
2432 	--t;
2433 #ifdef VMS
2434     // path separator is part of the path
2435     ++t;
2436 #endif
2437     return t;
2438 }
2439 
2440 /*
2441  * get the next path component (just after the next path separator).
2442  */
2443     char_u *
2444 getnextcomp(char_u *fname)
2445 {
2446     while (*fname && !vim_ispathsep(*fname))
2447 	MB_PTR_ADV(fname);
2448     if (*fname)
2449 	++fname;
2450     return fname;
2451 }
2452 
2453 /*
2454  * Get a pointer to one character past the head of a path name.
2455  * Unix: after "/"; DOS: after "c:\"; Amiga: after "disk:/"; Mac: no head.
2456  * If there is no head, path is returned.
2457  */
2458     char_u *
2459 get_past_head(char_u *path)
2460 {
2461     char_u  *retval;
2462 
2463 #if defined(MSWIN)
2464     // may skip "c:"
2465     if (isalpha(path[0]) && path[1] == ':')
2466 	retval = path + 2;
2467     else
2468 	retval = path;
2469 #else
2470 # if defined(AMIGA)
2471     // may skip "label:"
2472     retval = vim_strchr(path, ':');
2473     if (retval == NULL)
2474 	retval = path;
2475 # else	// Unix
2476     retval = path;
2477 # endif
2478 #endif
2479 
2480     while (vim_ispathsep(*retval))
2481 	++retval;
2482 
2483     return retval;
2484 }
2485 
2486 /*
2487  * Return TRUE if 'c' is a path separator.
2488  * Note that for MS-Windows this includes the colon.
2489  */
2490     int
2491 vim_ispathsep(int c)
2492 {
2493 #ifdef UNIX
2494     return (c == '/');	    // UNIX has ':' inside file names
2495 #else
2496 # ifdef BACKSLASH_IN_FILENAME
2497     return (c == ':' || c == '/' || c == '\\');
2498 # else
2499 #  ifdef VMS
2500     // server"user passwd"::device:[full.path.name]fname.extension;version"
2501     return (c == ':' || c == '[' || c == ']' || c == '/'
2502 	    || c == '<' || c == '>' || c == '"' );
2503 #  else
2504     return (c == ':' || c == '/');
2505 #  endif // VMS
2506 # endif
2507 #endif
2508 }
2509 
2510 /*
2511  * Like vim_ispathsep(c), but exclude the colon for MS-Windows.
2512  */
2513     int
2514 vim_ispathsep_nocolon(int c)
2515 {
2516     return vim_ispathsep(c)
2517 #ifdef BACKSLASH_IN_FILENAME
2518 	&& c != ':'
2519 #endif
2520 	;
2521 }
2522 
2523 /*
2524  * Shorten the path of a file from "~/foo/../.bar/fname" to "~/f/../.b/fname"
2525  * It's done in-place.
2526  */
2527     void
2528 shorten_dir(char_u *str)
2529 {
2530     char_u	*tail, *s, *d;
2531     int		skip = FALSE;
2532 
2533     tail = gettail(str);
2534     d = str;
2535     for (s = str; ; ++s)
2536     {
2537 	if (s >= tail)		    // copy the whole tail
2538 	{
2539 	    *d++ = *s;
2540 	    if (*s == NUL)
2541 		break;
2542 	}
2543 	else if (vim_ispathsep(*s))	    // copy '/' and next char
2544 	{
2545 	    *d++ = *s;
2546 	    skip = FALSE;
2547 	}
2548 	else if (!skip)
2549 	{
2550 	    *d++ = *s;		    // copy next char
2551 	    if (*s != '~' && *s != '.') // and leading "~" and "."
2552 		skip = TRUE;
2553 	    if (has_mbyte)
2554 	    {
2555 		int l = mb_ptr2len(s);
2556 
2557 		while (--l > 0)
2558 		    *d++ = *++s;
2559 	    }
2560 	}
2561     }
2562 }
2563 
2564 /*
2565  * Return TRUE if the directory of "fname" exists, FALSE otherwise.
2566  * Also returns TRUE if there is no directory name.
2567  * "fname" must be writable!.
2568  */
2569     int
2570 dir_of_file_exists(char_u *fname)
2571 {
2572     char_u	*p;
2573     int		c;
2574     int		retval;
2575 
2576     p = gettail_sep(fname);
2577     if (p == fname)
2578 	return TRUE;
2579     c = *p;
2580     *p = NUL;
2581     retval = mch_isdir(fname);
2582     *p = c;
2583     return retval;
2584 }
2585 
2586 /*
2587  * Versions of fnamecmp() and fnamencmp() that handle '/' and '\' equally
2588  * and deal with 'fileignorecase'.
2589  */
2590     int
2591 vim_fnamecmp(char_u *x, char_u *y)
2592 {
2593 #ifdef BACKSLASH_IN_FILENAME
2594     return vim_fnamencmp(x, y, MAXPATHL);
2595 #else
2596     if (p_fic)
2597 	return MB_STRICMP(x, y);
2598     return STRCMP(x, y);
2599 #endif
2600 }
2601 
2602     int
2603 vim_fnamencmp(char_u *x, char_u *y, size_t len)
2604 {
2605 #ifdef BACKSLASH_IN_FILENAME
2606     char_u	*px = x;
2607     char_u	*py = y;
2608     int		cx = NUL;
2609     int		cy = NUL;
2610 
2611     while (len > 0)
2612     {
2613 	cx = PTR2CHAR(px);
2614 	cy = PTR2CHAR(py);
2615 	if (cx == NUL || cy == NUL
2616 	    || ((p_fic ? MB_TOLOWER(cx) != MB_TOLOWER(cy) : cx != cy)
2617 		&& !(cx == '/' && cy == '\\')
2618 		&& !(cx == '\\' && cy == '/')))
2619 	    break;
2620 	len -= mb_ptr2len(px);
2621 	px += mb_ptr2len(px);
2622 	py += mb_ptr2len(py);
2623     }
2624     if (len == 0)
2625 	return 0;
2626     return (cx - cy);
2627 #else
2628     if (p_fic)
2629 	return MB_STRNICMP(x, y, len);
2630     return STRNCMP(x, y, len);
2631 #endif
2632 }
2633 
2634 /*
2635  * Concatenate file names fname1 and fname2 into allocated memory.
2636  * Only add a '/' or '\\' when 'sep' is TRUE and it is necessary.
2637  */
2638     char_u  *
2639 concat_fnames(char_u *fname1, char_u *fname2, int sep)
2640 {
2641     char_u  *dest;
2642 
2643     dest = alloc(STRLEN(fname1) + STRLEN(fname2) + 3);
2644     if (dest != NULL)
2645     {
2646 	STRCPY(dest, fname1);
2647 	if (sep)
2648 	    add_pathsep(dest);
2649 	STRCAT(dest, fname2);
2650     }
2651     return dest;
2652 }
2653 
2654 /*
2655  * Add a path separator to a file name, unless it already ends in a path
2656  * separator.
2657  */
2658     void
2659 add_pathsep(char_u *p)
2660 {
2661     if (*p != NUL && !after_pathsep(p, p + STRLEN(p)))
2662 	STRCAT(p, PATHSEPSTR);
2663 }
2664 
2665 /*
2666  * FullName_save - Make an allocated copy of a full file name.
2667  * Returns NULL when out of memory.
2668  */
2669     char_u  *
2670 FullName_save(
2671     char_u	*fname,
2672     int		force)		// force expansion, even when it already looks
2673 				// like a full path name
2674 {
2675     char_u	*buf;
2676     char_u	*new_fname = NULL;
2677 
2678     if (fname == NULL)
2679 	return NULL;
2680 
2681     buf = alloc(MAXPATHL);
2682     if (buf != NULL)
2683     {
2684 	if (vim_FullName(fname, buf, MAXPATHL, force) != FAIL)
2685 	    new_fname = vim_strsave(buf);
2686 	else
2687 	    new_fname = vim_strsave(fname);
2688 	vim_free(buf);
2689     }
2690     return new_fname;
2691 }
2692 
2693 /*
2694  * return TRUE if "fname" exists.
2695  */
2696     int
2697 vim_fexists(char_u *fname)
2698 {
2699     stat_T st;
2700 
2701     if (mch_stat((char *)fname, &st))
2702 	return FALSE;
2703     return TRUE;
2704 }
2705 
2706 /*
2707  * Invoke expand_wildcards() for one pattern.
2708  * Expand items like "%:h" before the expansion.
2709  * Returns OK or FAIL.
2710  */
2711     int
2712 expand_wildcards_eval(
2713     char_u	 **pat,		// pointer to input pattern
2714     int		  *num_file,	// resulting number of files
2715     char_u	***file,	// array of resulting files
2716     int		   flags)	// EW_DIR, etc.
2717 {
2718     int		ret = FAIL;
2719     char_u	*eval_pat = NULL;
2720     char_u	*exp_pat = *pat;
2721     char      *ignored_msg;
2722     int		usedlen;
2723 
2724     if (*exp_pat == '%' || *exp_pat == '#' || *exp_pat == '<')
2725     {
2726 	++emsg_off;
2727 	eval_pat = eval_vars(exp_pat, exp_pat, &usedlen,
2728 						    NULL, &ignored_msg, NULL);
2729 	--emsg_off;
2730 	if (eval_pat != NULL)
2731 	    exp_pat = concat_str(eval_pat, exp_pat + usedlen);
2732     }
2733 
2734     if (exp_pat != NULL)
2735 	ret = expand_wildcards(1, &exp_pat, num_file, file, flags);
2736 
2737     if (eval_pat != NULL)
2738     {
2739 	vim_free(exp_pat);
2740 	vim_free(eval_pat);
2741     }
2742 
2743     return ret;
2744 }
2745 
2746 /*
2747  * Expand wildcards.  Calls gen_expand_wildcards() and removes files matching
2748  * 'wildignore'.
2749  * Returns OK or FAIL.  When FAIL then "num_files" won't be set.
2750  */
2751     int
2752 expand_wildcards(
2753     int		   num_pat,	// number of input patterns
2754     char_u	 **pat,		// array of input patterns
2755     int		  *num_files,	// resulting number of files
2756     char_u	***files,	// array of resulting files
2757     int		   flags)	// EW_DIR, etc.
2758 {
2759     int		retval;
2760     int		i, j;
2761     char_u	*p;
2762     int		non_suf_match;	// number without matching suffix
2763 
2764     retval = gen_expand_wildcards(num_pat, pat, num_files, files, flags);
2765 
2766     // When keeping all matches, return here
2767     if ((flags & EW_KEEPALL) || retval == FAIL)
2768 	return retval;
2769 
2770 #ifdef FEAT_WILDIGN
2771     /*
2772      * Remove names that match 'wildignore'.
2773      */
2774     if (*p_wig)
2775     {
2776 	char_u	*ffname;
2777 
2778 	// check all files in (*files)[]
2779 	for (i = 0; i < *num_files; ++i)
2780 	{
2781 	    ffname = FullName_save((*files)[i], FALSE);
2782 	    if (ffname == NULL)		// out of memory
2783 		break;
2784 # ifdef VMS
2785 	    vms_remove_version(ffname);
2786 # endif
2787 	    if (match_file_list(p_wig, (*files)[i], ffname))
2788 	    {
2789 		// remove this matching file from the list
2790 		vim_free((*files)[i]);
2791 		for (j = i; j + 1 < *num_files; ++j)
2792 		    (*files)[j] = (*files)[j + 1];
2793 		--*num_files;
2794 		--i;
2795 	    }
2796 	    vim_free(ffname);
2797 	}
2798 
2799 	// If the number of matches is now zero, we fail.
2800 	if (*num_files == 0)
2801 	{
2802 	    VIM_CLEAR(*files);
2803 	    return FAIL;
2804 	}
2805     }
2806 #endif
2807 
2808     /*
2809      * Move the names where 'suffixes' match to the end.
2810      */
2811     if (*num_files > 1)
2812     {
2813 	non_suf_match = 0;
2814 	for (i = 0; i < *num_files; ++i)
2815 	{
2816 	    if (!match_suffix((*files)[i]))
2817 	    {
2818 		/*
2819 		 * Move the name without matching suffix to the front
2820 		 * of the list.
2821 		 */
2822 		p = (*files)[i];
2823 		for (j = i; j > non_suf_match; --j)
2824 		    (*files)[j] = (*files)[j - 1];
2825 		(*files)[non_suf_match++] = p;
2826 	    }
2827 	}
2828     }
2829 
2830     return retval;
2831 }
2832 
2833 /*
2834  * Return TRUE if "fname" matches with an entry in 'suffixes'.
2835  */
2836     int
2837 match_suffix(char_u *fname)
2838 {
2839     int		fnamelen, setsuflen;
2840     char_u	*setsuf;
2841 #define MAXSUFLEN 30	    // maximum length of a file suffix
2842     char_u	suf_buf[MAXSUFLEN];
2843 
2844     fnamelen = (int)STRLEN(fname);
2845     setsuflen = 0;
2846     for (setsuf = p_su; *setsuf; )
2847     {
2848 	setsuflen = copy_option_part(&setsuf, suf_buf, MAXSUFLEN, ".,");
2849 	if (setsuflen == 0)
2850 	{
2851 	    char_u *tail = gettail(fname);
2852 
2853 	    // empty entry: match name without a '.'
2854 	    if (vim_strchr(tail, '.') == NULL)
2855 	    {
2856 		setsuflen = 1;
2857 		break;
2858 	    }
2859 	}
2860 	else
2861 	{
2862 	    if (fnamelen >= setsuflen
2863 		    && fnamencmp(suf_buf, fname + fnamelen - setsuflen,
2864 						  (size_t)setsuflen) == 0)
2865 		break;
2866 	    setsuflen = 0;
2867 	}
2868     }
2869     return (setsuflen != 0);
2870 }
2871 
2872 #ifdef VIM_BACKTICK
2873 
2874 /*
2875  * Return TRUE if we can expand this backtick thing here.
2876  */
2877     static int
2878 vim_backtick(char_u *p)
2879 {
2880     return (*p == '`' && *(p + 1) != NUL && *(p + STRLEN(p) - 1) == '`');
2881 }
2882 
2883 /*
2884  * Expand an item in `backticks` by executing it as a command.
2885  * Currently only works when pat[] starts and ends with a `.
2886  * Returns number of file names found, -1 if an error is encountered.
2887  */
2888     static int
2889 expand_backtick(
2890     garray_T	*gap,
2891     char_u	*pat,
2892     int		flags)	// EW_* flags
2893 {
2894     char_u	*p;
2895     char_u	*cmd;
2896     char_u	*buffer;
2897     int		cnt = 0;
2898     int		i;
2899 
2900     // Create the command: lop off the backticks.
2901     cmd = vim_strnsave(pat + 1, (int)STRLEN(pat) - 2);
2902     if (cmd == NULL)
2903 	return -1;
2904 
2905 #ifdef FEAT_EVAL
2906     if (*cmd == '=')	    // `={expr}`: Expand expression
2907 	buffer = eval_to_string(cmd + 1, &p, TRUE);
2908     else
2909 #endif
2910 	buffer = get_cmd_output(cmd, NULL,
2911 				(flags & EW_SILENT) ? SHELL_SILENT : 0, NULL);
2912     vim_free(cmd);
2913     if (buffer == NULL)
2914 	return -1;
2915 
2916     cmd = buffer;
2917     while (*cmd != NUL)
2918     {
2919 	cmd = skipwhite(cmd);		// skip over white space
2920 	p = cmd;
2921 	while (*p != NUL && *p != '\r' && *p != '\n') // skip over entry
2922 	    ++p;
2923 	// add an entry if it is not empty
2924 	if (p > cmd)
2925 	{
2926 	    i = *p;
2927 	    *p = NUL;
2928 	    addfile(gap, cmd, flags);
2929 	    *p = i;
2930 	    ++cnt;
2931 	}
2932 	cmd = p;
2933 	while (*cmd != NUL && (*cmd == '\r' || *cmd == '\n'))
2934 	    ++cmd;
2935     }
2936 
2937     vim_free(buffer);
2938     return cnt;
2939 }
2940 #endif // VIM_BACKTICK
2941 
2942 #if defined(MSWIN)
2943 /*
2944  * File name expansion code for MS-DOS, Win16 and Win32.  It's here because
2945  * it's shared between these systems.
2946  */
2947 
2948 /*
2949  * comparison function for qsort in dos_expandpath()
2950  */
2951     static int
2952 pstrcmp(const void *a, const void *b)
2953 {
2954     return (pathcmp(*(char **)a, *(char **)b, -1));
2955 }
2956 
2957 /*
2958  * Recursively expand one path component into all matching files and/or
2959  * directories.  Adds matches to "gap".  Handles "*", "?", "[a-z]", "**", etc.
2960  * Return the number of matches found.
2961  * "path" has backslashes before chars that are not to be expanded, starting
2962  * at "path[wildoff]".
2963  * Return the number of matches found.
2964  * NOTE: much of this is identical to unix_expandpath(), keep in sync!
2965  */
2966     static int
2967 dos_expandpath(
2968     garray_T	*gap,
2969     char_u	*path,
2970     int		wildoff,
2971     int		flags,		// EW_* flags
2972     int		didstar)	// expanded "**" once already
2973 {
2974     char_u	*buf;
2975     char_u	*path_end;
2976     char_u	*p, *s, *e;
2977     int		start_len = gap->ga_len;
2978     char_u	*pat;
2979     regmatch_T	regmatch;
2980     int		starts_with_dot;
2981     int		matches;
2982     int		len;
2983     int		starstar = FALSE;
2984     static int	stardepth = 0;	    // depth for "**" expansion
2985     HANDLE		hFind = INVALID_HANDLE_VALUE;
2986     WIN32_FIND_DATAW    wfb;
2987     WCHAR		*wn = NULL;	// UCS-2 name, NULL when not used.
2988     char_u		*matchname;
2989     int			ok;
2990 
2991     // Expanding "**" may take a long time, check for CTRL-C.
2992     if (stardepth > 0)
2993     {
2994 	ui_breakcheck();
2995 	if (got_int)
2996 	    return 0;
2997     }
2998 
2999     // Make room for file name.  When doing encoding conversion the actual
3000     // length may be quite a bit longer, thus use the maximum possible length.
3001     buf = alloc(MAXPATHL);
3002     if (buf == NULL)
3003 	return 0;
3004 
3005     /*
3006      * Find the first part in the path name that contains a wildcard or a ~1.
3007      * Copy it into buf, including the preceding characters.
3008      */
3009     p = buf;
3010     s = buf;
3011     e = NULL;
3012     path_end = path;
3013     while (*path_end != NUL)
3014     {
3015 	// May ignore a wildcard that has a backslash before it; it will
3016 	// be removed by rem_backslash() or file_pat_to_reg_pat() below.
3017 	if (path_end >= path + wildoff && rem_backslash(path_end))
3018 	    *p++ = *path_end++;
3019 	else if (*path_end == '\\' || *path_end == ':' || *path_end == '/')
3020 	{
3021 	    if (e != NULL)
3022 		break;
3023 	    s = p + 1;
3024 	}
3025 	else if (path_end >= path + wildoff
3026 			 && vim_strchr((char_u *)"*?[~", *path_end) != NULL)
3027 	    e = p;
3028 	if (has_mbyte)
3029 	{
3030 	    len = (*mb_ptr2len)(path_end);
3031 	    STRNCPY(p, path_end, len);
3032 	    p += len;
3033 	    path_end += len;
3034 	}
3035 	else
3036 	    *p++ = *path_end++;
3037     }
3038     e = p;
3039     *e = NUL;
3040 
3041     // now we have one wildcard component between s and e
3042     // Remove backslashes between "wildoff" and the start of the wildcard
3043     // component.
3044     for (p = buf + wildoff; p < s; ++p)
3045 	if (rem_backslash(p))
3046 	{
3047 	    STRMOVE(p, p + 1);
3048 	    --e;
3049 	    --s;
3050 	}
3051 
3052     // Check for "**" between "s" and "e".
3053     for (p = s; p < e; ++p)
3054 	if (p[0] == '*' && p[1] == '*')
3055 	    starstar = TRUE;
3056 
3057     starts_with_dot = *s == '.';
3058     pat = file_pat_to_reg_pat(s, e, NULL, FALSE);
3059     if (pat == NULL)
3060     {
3061 	vim_free(buf);
3062 	return 0;
3063     }
3064 
3065     // compile the regexp into a program
3066     if (flags & (EW_NOERROR | EW_NOTWILD))
3067 	++emsg_silent;
3068     regmatch.rm_ic = TRUE;		// Always ignore case
3069     regmatch.regprog = vim_regcomp(pat, RE_MAGIC);
3070     if (flags & (EW_NOERROR | EW_NOTWILD))
3071 	--emsg_silent;
3072     vim_free(pat);
3073 
3074     if (regmatch.regprog == NULL && (flags & EW_NOTWILD) == 0)
3075     {
3076 	vim_free(buf);
3077 	return 0;
3078     }
3079 
3080     // remember the pattern or file name being looked for
3081     matchname = vim_strsave(s);
3082 
3083     // If "**" is by itself, this is the first time we encounter it and more
3084     // is following then find matches without any directory.
3085     if (!didstar && stardepth < 100 && starstar && e - s == 2
3086 							  && *path_end == '/')
3087     {
3088 	STRCPY(s, path_end + 1);
3089 	++stardepth;
3090 	(void)dos_expandpath(gap, buf, (int)(s - buf), flags, TRUE);
3091 	--stardepth;
3092     }
3093 
3094     // Scan all files in the directory with "dir/ *.*"
3095     STRCPY(s, "*.*");
3096     wn = enc_to_utf16(buf, NULL);
3097     if (wn != NULL)
3098 	hFind = FindFirstFileW(wn, &wfb);
3099     ok = (hFind != INVALID_HANDLE_VALUE);
3100 
3101     while (ok)
3102     {
3103 	p = utf16_to_enc(wfb.cFileName, NULL);   // p is allocated here
3104 	if (p == NULL)
3105 	    break;  // out of memory
3106 
3107 	// Ignore entries starting with a dot, unless when asked for.  Accept
3108 	// all entries found with "matchname".
3109 	if ((p[0] != '.' || starts_with_dot
3110 			 || ((flags & EW_DODOT)
3111 			     && p[1] != NUL && (p[1] != '.' || p[2] != NUL)))
3112 		&& (matchname == NULL
3113 		  || (regmatch.regprog != NULL
3114 				     && vim_regexec(&regmatch, p, (colnr_T)0))
3115 		  || ((flags & EW_NOTWILD)
3116 		     && fnamencmp(path + (s - buf), p, e - s) == 0)))
3117 	{
3118 	    STRCPY(s, p);
3119 	    len = (int)STRLEN(buf);
3120 
3121 	    if (starstar && stardepth < 100)
3122 	    {
3123 		// For "**" in the pattern first go deeper in the tree to
3124 		// find matches.
3125 		STRCPY(buf + len, "/**");
3126 		STRCPY(buf + len + 3, path_end);
3127 		++stardepth;
3128 		(void)dos_expandpath(gap, buf, len + 1, flags, TRUE);
3129 		--stardepth;
3130 	    }
3131 
3132 	    STRCPY(buf + len, path_end);
3133 	    if (mch_has_exp_wildcard(path_end))
3134 	    {
3135 		// need to expand another component of the path
3136 		// remove backslashes for the remaining components only
3137 		(void)dos_expandpath(gap, buf, len + 1, flags, FALSE);
3138 	    }
3139 	    else
3140 	    {
3141 		// no more wildcards, check if there is a match
3142 		// remove backslashes for the remaining components only
3143 		if (*path_end != 0)
3144 		    backslash_halve(buf + len + 1);
3145 		if (mch_getperm(buf) >= 0)	// add existing file
3146 		    addfile(gap, buf, flags);
3147 	    }
3148 	}
3149 
3150 	vim_free(p);
3151 	ok = FindNextFileW(hFind, &wfb);
3152 
3153 	// If no more matches and no match was used, try expanding the name
3154 	// itself.  Finds the long name of a short filename.
3155 	if (!ok && matchname != NULL && gap->ga_len == start_len)
3156 	{
3157 	    STRCPY(s, matchname);
3158 	    FindClose(hFind);
3159 	    vim_free(wn);
3160 	    wn = enc_to_utf16(buf, NULL);
3161 	    if (wn != NULL)
3162 		hFind = FindFirstFileW(wn, &wfb);
3163 	    else
3164 		hFind =	INVALID_HANDLE_VALUE;
3165 	    ok = (hFind != INVALID_HANDLE_VALUE);
3166 	    VIM_CLEAR(matchname);
3167 	}
3168     }
3169 
3170     FindClose(hFind);
3171     vim_free(wn);
3172     vim_free(buf);
3173     vim_regfree(regmatch.regprog);
3174     vim_free(matchname);
3175 
3176     matches = gap->ga_len - start_len;
3177     if (matches > 0)
3178 	qsort(((char_u **)gap->ga_data) + start_len, (size_t)matches,
3179 						   sizeof(char_u *), pstrcmp);
3180     return matches;
3181 }
3182 
3183     int
3184 mch_expandpath(
3185     garray_T	*gap,
3186     char_u	*path,
3187     int		flags)		// EW_* flags
3188 {
3189     return dos_expandpath(gap, path, 0, flags, FALSE);
3190 }
3191 #endif // MSWIN
3192 
3193 #if (defined(UNIX) && !defined(VMS)) || defined(USE_UNIXFILENAME) \
3194 	|| defined(PROTO)
3195 /*
3196  * Unix style wildcard expansion code.
3197  * It's here because it's used both for Unix and Mac.
3198  */
3199     static int
3200 pstrcmp(const void *a, const void *b)
3201 {
3202     return (pathcmp(*(char **)a, *(char **)b, -1));
3203 }
3204 
3205 /*
3206  * Recursively expand one path component into all matching files and/or
3207  * directories.  Adds matches to "gap".  Handles "*", "?", "[a-z]", "**", etc.
3208  * "path" has backslashes before chars that are not to be expanded, starting
3209  * at "path + wildoff".
3210  * Return the number of matches found.
3211  * NOTE: much of this is identical to dos_expandpath(), keep in sync!
3212  */
3213     int
3214 unix_expandpath(
3215     garray_T	*gap,
3216     char_u	*path,
3217     int		wildoff,
3218     int		flags,		// EW_* flags
3219     int		didstar)	// expanded "**" once already
3220 {
3221     char_u	*buf;
3222     char_u	*path_end;
3223     char_u	*p, *s, *e;
3224     int		start_len = gap->ga_len;
3225     char_u	*pat;
3226     regmatch_T	regmatch;
3227     int		starts_with_dot;
3228     int		matches;
3229     int		len;
3230     int		starstar = FALSE;
3231     static int	stardepth = 0;	    // depth for "**" expansion
3232 
3233     DIR		*dirp;
3234     struct dirent *dp;
3235 
3236     // Expanding "**" may take a long time, check for CTRL-C.
3237     if (stardepth > 0)
3238     {
3239 	ui_breakcheck();
3240 	if (got_int)
3241 	    return 0;
3242     }
3243 
3244     // make room for file name
3245     buf = alloc(STRLEN(path) + BASENAMELEN + 5);
3246     if (buf == NULL)
3247 	return 0;
3248 
3249     /*
3250      * Find the first part in the path name that contains a wildcard.
3251      * When EW_ICASE is set every letter is considered to be a wildcard.
3252      * Copy it into "buf", including the preceding characters.
3253      */
3254     p = buf;
3255     s = buf;
3256     e = NULL;
3257     path_end = path;
3258     while (*path_end != NUL)
3259     {
3260 	// May ignore a wildcard that has a backslash before it; it will
3261 	// be removed by rem_backslash() or file_pat_to_reg_pat() below.
3262 	if (path_end >= path + wildoff && rem_backslash(path_end))
3263 	    *p++ = *path_end++;
3264 	else if (*path_end == '/')
3265 	{
3266 	    if (e != NULL)
3267 		break;
3268 	    s = p + 1;
3269 	}
3270 	else if (path_end >= path + wildoff
3271 			 && (vim_strchr((char_u *)"*?[{~$", *path_end) != NULL
3272 			     || (!p_fic && (flags & EW_ICASE)
3273 					     && isalpha(PTR2CHAR(path_end)))))
3274 	    e = p;
3275 	if (has_mbyte)
3276 	{
3277 	    len = (*mb_ptr2len)(path_end);
3278 	    STRNCPY(p, path_end, len);
3279 	    p += len;
3280 	    path_end += len;
3281 	}
3282 	else
3283 	    *p++ = *path_end++;
3284     }
3285     e = p;
3286     *e = NUL;
3287 
3288     // Now we have one wildcard component between "s" and "e".
3289     // Remove backslashes between "wildoff" and the start of the wildcard
3290     // component.
3291     for (p = buf + wildoff; p < s; ++p)
3292 	if (rem_backslash(p))
3293 	{
3294 	    STRMOVE(p, p + 1);
3295 	    --e;
3296 	    --s;
3297 	}
3298 
3299     // Check for "**" between "s" and "e".
3300     for (p = s; p < e; ++p)
3301 	if (p[0] == '*' && p[1] == '*')
3302 	    starstar = TRUE;
3303 
3304     // convert the file pattern to a regexp pattern
3305     starts_with_dot = *s == '.';
3306     pat = file_pat_to_reg_pat(s, e, NULL, FALSE);
3307     if (pat == NULL)
3308     {
3309 	vim_free(buf);
3310 	return 0;
3311     }
3312 
3313     // compile the regexp into a program
3314     if (flags & EW_ICASE)
3315 	regmatch.rm_ic = TRUE;		// 'wildignorecase' set
3316     else
3317 	regmatch.rm_ic = p_fic;	// ignore case when 'fileignorecase' is set
3318     if (flags & (EW_NOERROR | EW_NOTWILD))
3319 	++emsg_silent;
3320     regmatch.regprog = vim_regcomp(pat, RE_MAGIC);
3321     if (flags & (EW_NOERROR | EW_NOTWILD))
3322 	--emsg_silent;
3323     vim_free(pat);
3324 
3325     if (regmatch.regprog == NULL && (flags & EW_NOTWILD) == 0)
3326     {
3327 	vim_free(buf);
3328 	return 0;
3329     }
3330 
3331     // If "**" is by itself, this is the first time we encounter it and more
3332     // is following then find matches without any directory.
3333     if (!didstar && stardepth < 100 && starstar && e - s == 2
3334 							  && *path_end == '/')
3335     {
3336 	STRCPY(s, path_end + 1);
3337 	++stardepth;
3338 	(void)unix_expandpath(gap, buf, (int)(s - buf), flags, TRUE);
3339 	--stardepth;
3340     }
3341 
3342     // open the directory for scanning
3343     *s = NUL;
3344     dirp = opendir(*buf == NUL ? "." : (char *)buf);
3345 
3346     // Find all matching entries
3347     if (dirp != NULL)
3348     {
3349 	for (;;)
3350 	{
3351 	    dp = readdir(dirp);
3352 	    if (dp == NULL)
3353 		break;
3354 	    if ((dp->d_name[0] != '.' || starts_with_dot
3355 			|| ((flags & EW_DODOT)
3356 			    && dp->d_name[1] != NUL
3357 			    && (dp->d_name[1] != '.' || dp->d_name[2] != NUL)))
3358 		 && ((regmatch.regprog != NULL && vim_regexec(&regmatch,
3359 					     (char_u *)dp->d_name, (colnr_T)0))
3360 		   || ((flags & EW_NOTWILD)
3361 		     && fnamencmp(path + (s - buf), dp->d_name, e - s) == 0)))
3362 	    {
3363 		STRCPY(s, dp->d_name);
3364 		len = STRLEN(buf);
3365 
3366 		if (starstar && stardepth < 100)
3367 		{
3368 		    // For "**" in the pattern first go deeper in the tree to
3369 		    // find matches.
3370 		    STRCPY(buf + len, "/**");
3371 		    STRCPY(buf + len + 3, path_end);
3372 		    ++stardepth;
3373 		    (void)unix_expandpath(gap, buf, len + 1, flags, TRUE);
3374 		    --stardepth;
3375 		}
3376 
3377 		STRCPY(buf + len, path_end);
3378 		if (mch_has_exp_wildcard(path_end)) // handle more wildcards
3379 		{
3380 		    // need to expand another component of the path
3381 		    // remove backslashes for the remaining components only
3382 		    (void)unix_expandpath(gap, buf, len + 1, flags, FALSE);
3383 		}
3384 		else
3385 		{
3386 		    stat_T  sb;
3387 
3388 		    // no more wildcards, check if there is a match
3389 		    // remove backslashes for the remaining components only
3390 		    if (*path_end != NUL)
3391 			backslash_halve(buf + len + 1);
3392 		    // add existing file or symbolic link
3393 		    if ((flags & EW_ALLLINKS) ? mch_lstat((char *)buf, &sb) >= 0
3394 						      : mch_getperm(buf) >= 0)
3395 		    {
3396 #ifdef MACOS_CONVERT
3397 			size_t precomp_len = STRLEN(buf)+1;
3398 			char_u *precomp_buf =
3399 			    mac_precompose_path(buf, precomp_len, &precomp_len);
3400 
3401 			if (precomp_buf)
3402 			{
3403 			    mch_memmove(buf, precomp_buf, precomp_len);
3404 			    vim_free(precomp_buf);
3405 			}
3406 #endif
3407 			addfile(gap, buf, flags);
3408 		    }
3409 		}
3410 	    }
3411 	}
3412 
3413 	closedir(dirp);
3414     }
3415 
3416     vim_free(buf);
3417     vim_regfree(regmatch.regprog);
3418 
3419     matches = gap->ga_len - start_len;
3420     if (matches > 0)
3421 	qsort(((char_u **)gap->ga_data) + start_len, matches,
3422 						   sizeof(char_u *), pstrcmp);
3423     return matches;
3424 }
3425 #endif
3426 
3427 /*
3428  * Return TRUE if "p" contains what looks like an environment variable.
3429  * Allowing for escaping.
3430  */
3431     static int
3432 has_env_var(char_u *p)
3433 {
3434     for ( ; *p; MB_PTR_ADV(p))
3435     {
3436 	if (*p == '\\' && p[1] != NUL)
3437 	    ++p;
3438 	else if (vim_strchr((char_u *)
3439 #if defined(MSWIN)
3440 				    "$%"
3441 #else
3442 				    "$"
3443 #endif
3444 					, *p) != NULL)
3445 	    return TRUE;
3446     }
3447     return FALSE;
3448 }
3449 
3450 #ifdef SPECIAL_WILDCHAR
3451 /*
3452  * Return TRUE if "p" contains a special wildcard character, one that Vim
3453  * cannot expand, requires using a shell.
3454  */
3455     static int
3456 has_special_wildchar(char_u *p)
3457 {
3458     for ( ; *p; MB_PTR_ADV(p))
3459     {
3460 	// Disallow line break characters.
3461 	if (*p == '\r' || *p == '\n')
3462 	    break;
3463 	// Allow for escaping.
3464 	if (*p == '\\' && p[1] != NUL && p[1] != '\r' && p[1] != '\n')
3465 	    ++p;
3466 	else if (vim_strchr((char_u *)SPECIAL_WILDCHAR, *p) != NULL)
3467 	{
3468 	    // A { must be followed by a matching }.
3469 	    if (*p == '{' && vim_strchr(p, '}') == NULL)
3470 		continue;
3471 	    // A quote and backtick must be followed by another one.
3472 	    if ((*p == '`' || *p == '\'') && vim_strchr(p, *p) == NULL)
3473 		continue;
3474 	    return TRUE;
3475 	}
3476     }
3477     return FALSE;
3478 }
3479 #endif
3480 
3481 /*
3482  * Generic wildcard expansion code.
3483  *
3484  * Characters in "pat" that should not be expanded must be preceded with a
3485  * backslash. E.g., "/path\ with\ spaces/my\*star*"
3486  *
3487  * Return FAIL when no single file was found.  In this case "num_file" is not
3488  * set, and "file" may contain an error message.
3489  * Return OK when some files found.  "num_file" is set to the number of
3490  * matches, "file" to the array of matches.  Call FreeWild() later.
3491  */
3492     int
3493 gen_expand_wildcards(
3494     int		num_pat,	// number of input patterns
3495     char_u	**pat,		// array of input patterns
3496     int		*num_file,	// resulting number of files
3497     char_u	***file,	// array of resulting files
3498     int		flags)		// EW_* flags
3499 {
3500     int			i;
3501     garray_T		ga;
3502     char_u		*p;
3503     static int		recursive = FALSE;
3504     int			add_pat;
3505     int			retval = OK;
3506 #if defined(FEAT_SEARCHPATH)
3507     int			did_expand_in_path = FALSE;
3508 #endif
3509 
3510     /*
3511      * expand_env() is called to expand things like "~user".  If this fails,
3512      * it calls ExpandOne(), which brings us back here.  In this case, always
3513      * call the machine specific expansion function, if possible.  Otherwise,
3514      * return FAIL.
3515      */
3516     if (recursive)
3517 #ifdef SPECIAL_WILDCHAR
3518 	return mch_expand_wildcards(num_pat, pat, num_file, file, flags);
3519 #else
3520 	return FAIL;
3521 #endif
3522 
3523 #ifdef SPECIAL_WILDCHAR
3524     /*
3525      * If there are any special wildcard characters which we cannot handle
3526      * here, call machine specific function for all the expansion.  This
3527      * avoids starting the shell for each argument separately.
3528      * For `=expr` do use the internal function.
3529      */
3530     for (i = 0; i < num_pat; i++)
3531     {
3532 	if (has_special_wildchar(pat[i])
3533 # ifdef VIM_BACKTICK
3534 		&& !(vim_backtick(pat[i]) && pat[i][1] == '=')
3535 # endif
3536 	   )
3537 	    return mch_expand_wildcards(num_pat, pat, num_file, file, flags);
3538     }
3539 #endif
3540 
3541     recursive = TRUE;
3542 
3543     /*
3544      * The matching file names are stored in a growarray.  Init it empty.
3545      */
3546     ga_init2(&ga, (int)sizeof(char_u *), 30);
3547 
3548     for (i = 0; i < num_pat; ++i)
3549     {
3550 	add_pat = -1;
3551 	p = pat[i];
3552 
3553 #ifdef VIM_BACKTICK
3554 	if (vim_backtick(p))
3555 	{
3556 	    add_pat = expand_backtick(&ga, p, flags);
3557 	    if (add_pat == -1)
3558 		retval = FAIL;
3559 	}
3560 	else
3561 #endif
3562 	{
3563 	    /*
3564 	     * First expand environment variables, "~/" and "~user/".
3565 	     */
3566 	    if ((has_env_var(p) && !(flags & EW_NOTENV)) || *p == '~')
3567 	    {
3568 		p = expand_env_save_opt(p, TRUE);
3569 		if (p == NULL)
3570 		    p = pat[i];
3571 #ifdef UNIX
3572 		/*
3573 		 * On Unix, if expand_env() can't expand an environment
3574 		 * variable, use the shell to do that.  Discard previously
3575 		 * found file names and start all over again.
3576 		 */
3577 		else if (has_env_var(p) || *p == '~')
3578 		{
3579 		    vim_free(p);
3580 		    ga_clear_strings(&ga);
3581 		    i = mch_expand_wildcards(num_pat, pat, num_file, file,
3582 							 flags|EW_KEEPDOLLAR);
3583 		    recursive = FALSE;
3584 		    return i;
3585 		}
3586 #endif
3587 	    }
3588 
3589 	    /*
3590 	     * If there are wildcards: Expand file names and add each match to
3591 	     * the list.  If there is no match, and EW_NOTFOUND is given, add
3592 	     * the pattern.
3593 	     * If there are no wildcards: Add the file name if it exists or
3594 	     * when EW_NOTFOUND is given.
3595 	     */
3596 	    if (mch_has_exp_wildcard(p))
3597 	    {
3598 #if defined(FEAT_SEARCHPATH)
3599 		if ((flags & EW_PATH)
3600 			&& !mch_isFullName(p)
3601 			&& !(p[0] == '.'
3602 			    && (vim_ispathsep(p[1])
3603 				|| (p[1] == '.' && vim_ispathsep(p[2]))))
3604 		   )
3605 		{
3606 		    // :find completion where 'path' is used.
3607 		    // Recursiveness is OK here.
3608 		    recursive = FALSE;
3609 		    add_pat = expand_in_path(&ga, p, flags);
3610 		    recursive = TRUE;
3611 		    did_expand_in_path = TRUE;
3612 		}
3613 		else
3614 #endif
3615 		    add_pat = mch_expandpath(&ga, p, flags);
3616 	    }
3617 	}
3618 
3619 	if (add_pat == -1 || (add_pat == 0 && (flags & EW_NOTFOUND)))
3620 	{
3621 	    char_u	*t = backslash_halve_save(p);
3622 
3623 	    // When EW_NOTFOUND is used, always add files and dirs.  Makes
3624 	    // "vim c:/" work.
3625 	    if (flags & EW_NOTFOUND)
3626 		addfile(&ga, t, flags | EW_DIR | EW_FILE);
3627 	    else
3628 		addfile(&ga, t, flags);
3629 
3630 	    if (t != p)
3631 		vim_free(t);
3632 	}
3633 
3634 #if defined(FEAT_SEARCHPATH)
3635 	if (did_expand_in_path && ga.ga_len > 0 && (flags & EW_PATH))
3636 	    uniquefy_paths(&ga, p);
3637 #endif
3638 	if (p != pat[i])
3639 	    vim_free(p);
3640     }
3641 
3642     *num_file = ga.ga_len;
3643     *file = (ga.ga_data != NULL) ? (char_u **)ga.ga_data : (char_u **)"";
3644 
3645     recursive = FALSE;
3646 
3647     return ((flags & EW_EMPTYOK) || ga.ga_data != NULL) ? retval : FAIL;
3648 }
3649 
3650 /*
3651  * Add a file to a file list.  Accepted flags:
3652  * EW_DIR	add directories
3653  * EW_FILE	add files
3654  * EW_EXEC	add executable files
3655  * EW_NOTFOUND	add even when it doesn't exist
3656  * EW_ADDSLASH	add slash after directory name
3657  * EW_ALLLINKS	add symlink also when the referred file does not exist
3658  */
3659     void
3660 addfile(
3661     garray_T	*gap,
3662     char_u	*f,	/* filename */
3663     int		flags)
3664 {
3665     char_u	*p;
3666     int		isdir;
3667     stat_T	sb;
3668 
3669     // if the file/dir/link doesn't exist, may not add it
3670     if (!(flags & EW_NOTFOUND) && ((flags & EW_ALLLINKS)
3671 			? mch_lstat((char *)f, &sb) < 0 : mch_getperm(f) < 0))
3672 	return;
3673 
3674 #ifdef FNAME_ILLEGAL
3675     // if the file/dir contains illegal characters, don't add it
3676     if (vim_strpbrk(f, (char_u *)FNAME_ILLEGAL) != NULL)
3677 	return;
3678 #endif
3679 
3680     isdir = mch_isdir(f);
3681     if ((isdir && !(flags & EW_DIR)) || (!isdir && !(flags & EW_FILE)))
3682 	return;
3683 
3684     // If the file isn't executable, may not add it.  Do accept directories.
3685     // When invoked from expand_shellcmd() do not use $PATH.
3686     if (!isdir && (flags & EW_EXEC)
3687 			     && !mch_can_exe(f, NULL, !(flags & EW_SHELLCMD)))
3688 	return;
3689 
3690     // Make room for another item in the file list.
3691     if (ga_grow(gap, 1) == FAIL)
3692 	return;
3693 
3694     p = alloc(STRLEN(f) + 1 + isdir);
3695     if (p == NULL)
3696 	return;
3697 
3698     STRCPY(p, f);
3699 #ifdef BACKSLASH_IN_FILENAME
3700     slash_adjust(p);
3701 #endif
3702     /*
3703      * Append a slash or backslash after directory names if none is present.
3704      */
3705 #ifndef DONT_ADD_PATHSEP_TO_DIR
3706     if (isdir && (flags & EW_ADDSLASH))
3707 	add_pathsep(p);
3708 #endif
3709     ((char_u **)gap->ga_data)[gap->ga_len++] = p;
3710 }
3711 
3712 /*
3713  * Free the list of files returned by expand_wildcards() or other expansion
3714  * functions.
3715  */
3716     void
3717 FreeWild(int count, char_u **files)
3718 {
3719     if (count <= 0 || files == NULL)
3720 	return;
3721     while (count--)
3722 	vim_free(files[count]);
3723     vim_free(files);
3724 }
3725 
3726 /*
3727  * Compare path "p[]" to "q[]".
3728  * If "maxlen" >= 0 compare "p[maxlen]" to "q[maxlen]"
3729  * Return value like strcmp(p, q), but consider path separators.
3730  */
3731     int
3732 pathcmp(const char *p, const char *q, int maxlen)
3733 {
3734     int		i, j;
3735     int		c1, c2;
3736     const char	*s = NULL;
3737 
3738     for (i = 0, j = 0; maxlen < 0 || (i < maxlen && j < maxlen);)
3739     {
3740 	c1 = PTR2CHAR((char_u *)p + i);
3741 	c2 = PTR2CHAR((char_u *)q + j);
3742 
3743 	// End of "p": check if "q" also ends or just has a slash.
3744 	if (c1 == NUL)
3745 	{
3746 	    if (c2 == NUL)  // full match
3747 		return 0;
3748 	    s = q;
3749 	    i = j;
3750 	    break;
3751 	}
3752 
3753 	// End of "q": check if "p" just has a slash.
3754 	if (c2 == NUL)
3755 	{
3756 	    s = p;
3757 	    break;
3758 	}
3759 
3760 	if ((p_fic ? MB_TOUPPER(c1) != MB_TOUPPER(c2) : c1 != c2)
3761 #ifdef BACKSLASH_IN_FILENAME
3762 		// consider '/' and '\\' to be equal
3763 		&& !((c1 == '/' && c2 == '\\')
3764 		    || (c1 == '\\' && c2 == '/'))
3765 #endif
3766 		)
3767 	{
3768 	    if (vim_ispathsep(c1))
3769 		return -1;
3770 	    if (vim_ispathsep(c2))
3771 		return 1;
3772 	    return p_fic ? MB_TOUPPER(c1) - MB_TOUPPER(c2)
3773 		    : c1 - c2;  // no match
3774 	}
3775 
3776 	i += mb_ptr2len((char_u *)p + i);
3777 	j += mb_ptr2len((char_u *)q + j);
3778     }
3779     if (s == NULL)	// "i" or "j" ran into "maxlen"
3780 	return 0;
3781 
3782     c1 = PTR2CHAR((char_u *)s + i);
3783     c2 = PTR2CHAR((char_u *)s + i + mb_ptr2len((char_u *)s + i));
3784     // ignore a trailing slash, but not "//" or ":/"
3785     if (c2 == NUL
3786 	    && i > 0
3787 	    && !after_pathsep((char_u *)s, (char_u *)s + i)
3788 #ifdef BACKSLASH_IN_FILENAME
3789 	    && (c1 == '/' || c1 == '\\')
3790 #else
3791 	    && c1 == '/'
3792 #endif
3793        )
3794 	return 0;   // match with trailing slash
3795     if (s == q)
3796 	return -1;	    // no match
3797     return 1;
3798 }
3799 
3800 /*
3801  * Return TRUE if "name" is a full (absolute) path name or URL.
3802  */
3803     int
3804 vim_isAbsName(char_u *name)
3805 {
3806     return (path_with_url(name) != 0 || mch_isFullName(name));
3807 }
3808 
3809 /*
3810  * Get absolute file name into buffer "buf[len]".
3811  *
3812  * return FAIL for failure, OK otherwise
3813  */
3814     int
3815 vim_FullName(
3816     char_u	*fname,
3817     char_u	*buf,
3818     int		len,
3819     int		force)	    // force expansion even when already absolute
3820 {
3821     int		retval = OK;
3822     int		url;
3823 
3824     *buf = NUL;
3825     if (fname == NULL)
3826 	return FAIL;
3827 
3828     url = path_with_url(fname);
3829     if (!url)
3830 	retval = mch_FullName(fname, buf, len, force);
3831     if (url || retval == FAIL)
3832     {
3833 	// something failed; use the file name (truncate when too long)
3834 	vim_strncpy(buf, fname, len - 1);
3835     }
3836 #if defined(MSWIN)
3837     slash_adjust(buf);
3838 #endif
3839     return retval;
3840 }
3841