Commit c70a4df6 authored by Stefan Monnier's avatar Stefan Monnier
Browse files

(Fexpand_file_name): Use IS_DEVICE_SEP.

(file_name_absolute_p): New fun, extracted from Ffile_name_absolute_p.
(Ffile_name_absolute_p): Use it.
(search_embedded_absfilename): New fun, extracted from Fsubstitute_in_file_name.
Use file_name_absolute_p.  Free the pw data after use.
(Fsubstitute_in_file_name): Use it.
After cutting a prefix, re-check file-name-handler.
parent f60a6f87
2005-03-28 Stefan Monnier <monnier@iro.umontreal.ca>
* fileio.c (Fexpand_file_name): Use IS_DEVICE_SEP.
(file_name_absolute_p): New fun, extracted from Ffile_name_absolute_p.
(Ffile_name_absolute_p): Use it.
(search_embedded_absfilename): New fun, extracted from
Fsubstitute_in_file_name. Use file_name_absolute_p.
Free the pw data after use.
(Fsubstitute_in_file_name): Use it.
After cutting a prefix, re-check file-name-handler.
2005-03-26 Lennart Borgman <lennart.borgman.073@student.lu.se>
* w32term.h (x_output): add focus_state.
......
......@@ -1014,7 +1014,7 @@ probably use `make-temp-file' instead, except in three circumstances:
DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
doc: /* Convert filename NAME to absolute, and canonicalize it.
Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative
(does not start with slash); if DEFAULT-DIRECTORY is nil or missing,
\(does not start with slash); if DEFAULT-DIRECTORY is nil or missing,
the current buffer's value of default-directory is used.
File name components that are `.' are removed, and
so are file name components followed by `..', along with the `..' itself;
......@@ -1464,7 +1464,7 @@ See also the function `substitute-in-file-name'. */)
indirectly by prepending newdir to nm if necessary, and using
cwd (or the wd of newdir's drive) as the new newdir. */
if (IS_DRIVE (newdir[0]) && newdir[1] == ':')
if (IS_DRIVE (newdir[0]) && IS_DEVICE_SEP (newdir[1]))
{
drive = newdir[0];
newdir += 2;
......@@ -1487,7 +1487,7 @@ See also the function `substitute-in-file-name'. */)
}
/* Strip off drive name from prefix, if present. */
if (IS_DRIVE (newdir[0]) && newdir[1] == ':')
if (IS_DRIVE (newdir[0]) && IS_DEVICE_SEP (newdir[1]))
{
drive = newdir[0];
newdir += 2;
......@@ -1721,7 +1721,7 @@ See also the function `substitute-in-file-name'. */)
DEAFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
"Convert FILENAME to absolute, and canonicalize it.\n\
Second arg DEFAULT is directory to start with if FILENAME is relative\n\
(does not start with slash); if DEFAULT is nil or missing,\n\
\(does not start with slash); if DEFAULT is nil or missing,\n\
the current buffer's value of default-directory is used.\n\
Filenames containing `.' or `..' as components are simplified;\n\
initial `~/' expands to your home directory.\n\
......@@ -2040,6 +2040,75 @@ See also the function `substitute-in-file-name'.")
}
#endif
/* If /~ or // appears, discard everything through first slash. */
static int
file_name_absolute_p (filename)
const unsigned char *filename;
{
return
(IS_DIRECTORY_SEP (*filename) || *filename == '~'
#ifdef VMS
/* ??? This criterion is probably wrong for '<'. */
|| index (filename, ':') || index (filename, '<')
|| (*filename == '[' && (filename[1] != '-'
|| (filename[2] != '.' && filename[2] != ']'))
&& filename[1] != '.')
#endif /* VMS */
#ifdef DOS_NT
|| (IS_DRIVE (*filename) && IS_DEVICE_SEP (filename[1])
&& IS_DIRECTORY_SEP (filename[2]))
#endif
);
}
static unsigned char *
search_embedded_absfilename (nm, endp)
unsigned char *nm, *endp;
{
unsigned char *p, *s;
for (p = nm + 1; p < endp; p++)
{
if ((0
#ifdef VMS
|| p[-1] == ':' || p[-1] == ']' || p[-1] == '>'
#endif /* VMS */
|| IS_DIRECTORY_SEP (p[-1]))
&& file_name_absolute_p (p)
#if defined (APOLLO) || defined (WINDOWSNT) || defined(CYGWIN)
/* // at start of file name is meaningful in Apollo,
WindowsNT and Cygwin systems. */
&& !(IS_DIRECTORY_SEP (p[0]) && p - 1 != nm)
#endif /* not (APOLLO || WINDOWSNT || CYGWIN) */
)
{
for (s = p; *s && (!IS_DIRECTORY_SEP (*s)
#ifdef VMS
&& *s != ':'
#endif /* VMS */
); s++);
if (p[0] == '~' && s > p + 1) /* we've got "/~something/" */
{
unsigned char *o = alloca (s - p + 1);
struct passwd *pw;
bcopy (p, o, s - p);
o [s - p] = 0;
/* If we have ~user and `user' exists, discard
everything up to ~. But if `user' does not exist, leave
~user alone, it might be a literal file name. */
if ((pw = getpwnam (o + 1)))
return p;
else
xfree (pw);
}
else
return p;
}
}
return NULL;
}
DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name,
Ssubstitute_in_file_name, 1, 1, 0,
doc: /* Substitute environment variables referred to in FILENAME.
......@@ -2061,7 +2130,6 @@ duplicates what `expand-file-name' does. */)
int total = 0;
int substituted = 0;
unsigned char *xnm;
struct passwd *pw;
Lisp_Object handler;
CHECK_STRING (filename);
......@@ -2081,61 +2149,17 @@ duplicates what `expand-file-name' does. */)
endp = nm + SBYTES (filename);
/* If /~ or // appears, discard everything through first slash. */
for (p = nm; p != endp; p++)
{
if ((p[0] == '~'
#if defined (APOLLO) || defined (WINDOWSNT) || defined(CYGWIN)
/* // at start of file name is meaningful in Apollo,
WindowsNT and Cygwin systems. */
|| (IS_DIRECTORY_SEP (p[0]) && p - 1 != nm)
#else /* not (APOLLO || WINDOWSNT || CYGWIN) */
|| IS_DIRECTORY_SEP (p[0])
#endif /* not (APOLLO || WINDOWSNT || CYGWIN) */
)
&& p != nm
&& (0
#ifdef VMS
|| p[-1] == ':' || p[-1] == ']' || p[-1] == '>'
#endif /* VMS */
|| IS_DIRECTORY_SEP (p[-1])))
{
for (s = p; *s && (!IS_DIRECTORY_SEP (*s)
#ifdef VMS
&& *s != ':'
#endif /* VMS */
); s++);
if (p[0] == '~' && s > p + 1) /* we've got "/~something/" */
{
o = (unsigned char *) alloca (s - p + 1);
bcopy ((char *) p, o, s - p);
o [s - p] = 0;
pw = (struct passwd *) getpwnam (o + 1);
}
/* If we have ~/ or ~user and `user' exists, discard
everything up to ~. But if `user' does not exist, leave
~user alone, it might be a literal file name. */
if (IS_DIRECTORY_SEP (p[0]) || s == p + 1 || pw)
{
nm = p;
substituted = 1;
}
}
#ifdef DOS_NT
/* see comment in expand-file-name about drive specifiers */
else if (IS_DRIVE (p[0]) && p[1] == ':'
&& p > nm && IS_DIRECTORY_SEP (p[-1]))
{
nm = p;
substituted = 1;
}
#endif /* DOS_NT */
}
p = search_embedded_absfilename (nm, endp);
if (p)
/* Start over with the new string, so we check the file-name-handler
again. Important with filenames like "/home/foo//:/hello///there"
which whould substitute to "/:/hello///there" rather than "/there". */
return Fsubstitute_in_file_name
(make_specified_string (p, -1, endp - p,
STRING_MULTIBYTE (filename)));
#ifdef VMS
return make_specified_string (nm, -1, strlen (nm),
STRING_MULTIBYTE (filename));
return filename;
#else
/* See if any variables are substituted into the string
......@@ -2261,22 +2285,11 @@ duplicates what `expand-file-name' does. */)
*x = 0;
/* If /~ or // appears, discard everything through first slash. */
for (p = xnm; p != x; p++)
if ((p[0] == '~'
#if defined (APOLLO) || defined (WINDOWSNT) || defined(CYGWIN)
|| (IS_DIRECTORY_SEP (p[0]) && p - 1 != xnm)
#else /* not (APOLLO || WINDOWSNT || CYGWIN) */
|| IS_DIRECTORY_SEP (p[0])
#endif /* not (APOLLO || WINDOWSNT || CYGWIN) */
)
&& p != xnm && IS_DIRECTORY_SEP (p[-1]))
xnm = p;
#ifdef DOS_NT
else if (IS_DRIVE (p[0]) && p[1] == ':'
&& p > xnm && IS_DIRECTORY_SEP (p[-1]))
xnm = p;
#endif
while ((p = search_embedded_absfilename (xnm, x)))
/* This time we do not start over because we've already expanded envvars
and replaced $$ with $. Maybe we should start over as well, but we'd
need to quote some $ to $$ first. */
xnm = p;
return make_specified_string (xnm, -1, x - xnm, STRING_MULTIBYTE (filename));
......@@ -2959,24 +2972,8 @@ On Unix, this is a name starting with a `/' or a `~'. */)
(filename)
Lisp_Object filename;
{
const unsigned char *ptr;
CHECK_STRING (filename);
ptr = SDATA (filename);
if (IS_DIRECTORY_SEP (*ptr) || *ptr == '~'
#ifdef VMS
/* ??? This criterion is probably wrong for '<'. */
|| index (ptr, ':') || index (ptr, '<')
|| (*ptr == '[' && (ptr[1] != '-' || (ptr[2] != '.' && ptr[2] != ']'))
&& ptr[1] != '.')
#endif /* VMS */
#ifdef DOS_NT
|| (IS_DRIVE (*ptr) && ptr[1] == ':' && IS_DIRECTORY_SEP (ptr[2]))
#endif
)
return Qt;
else
return Qnil;
return file_name_absolute_p (SDATA (filename)) ? Qt : Qnil;
}
/* Return nonzero if file FILENAME exists and can be executed. */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment