Commit 50e9e580 authored by Dmitry Antipov's avatar Dmitry Antipov
Browse files

Avoid extra calls to strlen in filesystem I/O routines.

* fileio.c (Fexpand_file_name): Avoid calls to strlen if
the length of 'newdir' is known or may be precalculated.
(file_accessible_directory_p): Prefer to pass Lisp_Object,
not 'char *', and so use precalculated length.
(Ffile_accessible_directory_p):
* callproc.c (encode_current_directory, init_callproc):
* charset.c (init_charset):
* lread.c (load_path_check, load_path_default): Adjust users.
* lisp.h (file_accessible_directory_p): Tweak prototype.
parent 203fb363
2014-09-01 Dmitry Antipov <dmantipov@yandex.ru>
Avoid extra calls to strlen in filesystem I/O routines.
* fileio.c (Fexpand_file_name): Avoid calls to strlen if
the length of 'newdir' is known or may be precalculated.
(file_accessible_directory_p): Prefer to pass Lisp_Object,
not 'char *', and so use precalculated length.
(Ffile_accessible_directory_p):
* callproc.c (encode_current_directory, init_callproc):
* charset.c (init_charset):
* lread.c (load_path_check, load_path_default): Adjust users.
* lisp.h (file_accessible_directory_p): Tweak prototype.
2014-09-01 Eli Zaretskii <eliz@gnu.org>
 
* w32proc.c (w32_compare_strings): Support "C" and "POSIX"
......
......@@ -129,7 +129,7 @@ encode_current_directory (void)
if (STRING_MULTIBYTE (dir))
dir = ENCODE_FILE (dir);
if (! file_accessible_directory_p (SSDATA (dir)))
if (! file_accessible_directory_p (dir))
report_file_error ("Setting current directory",
BVAR (current_buffer, directory));
......@@ -1625,12 +1625,12 @@ init_callproc (void)
#endif
{
tempdir = Fdirectory_file_name (Vexec_directory);
if (! file_accessible_directory_p (SSDATA (tempdir)))
if (! file_accessible_directory_p (tempdir))
dir_warning ("arch-dependent data dir", Vexec_directory);
}
tempdir = Fdirectory_file_name (Vdata_directory);
if (! file_accessible_directory_p (SSDATA (tempdir)))
if (! file_accessible_directory_p (tempdir))
dir_warning ("arch-independent data dir", Vdata_directory);
sh = getenv ("SHELL");
......
......@@ -2298,7 +2298,7 @@ init_charset (void)
{
Lisp_Object tempdir;
tempdir = Fexpand_file_name (build_string ("charsets"), Vdata_directory);
if (! file_accessible_directory_p (SSDATA (tempdir)))
if (! file_accessible_directory_p (tempdir))
{
/* This used to be non-fatal (dir_warning), but it should not
happen, and if it does sooner or later it will cause some
......
......@@ -889,7 +889,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
bool collapse_newdir = 1;
bool is_escaped = 0;
#endif /* DOS_NT */
ptrdiff_t length;
ptrdiff_t length, newdirlen;
Lisp_Object handler, result, handled_name;
bool multibyte;
Lisp_Object hdir;
......@@ -1147,6 +1147,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
append it to the current working directory. */
newdir = 0;
newdirlen = -1;
if (nm[0] == '~') /* prefix ~ */
{
......@@ -1171,10 +1172,12 @@ filesystem tree, not (expand-file-name ".." dirname). */)
else
#endif
tem = build_string (newdir);
newdirlen = SBYTES (tem);
if (multibyte && !STRING_MULTIBYTE (tem))
{
hdir = DECODE_FILE (tem);
newdir = SSDATA (hdir);
newdirlen = SBYTES (hdir);
}
#ifdef DOS_NT
collapse_newdir = 0;
......@@ -1201,10 +1204,12 @@ filesystem tree, not (expand-file-name ".." dirname). */)
bite us since we expect the directory to be
multibyte. */
tem = build_string (newdir);
newdirlen = SBYTES (tem);
if (multibyte && !STRING_MULTIBYTE (tem))
{
hdir = DECODE_FILE (tem);
newdir = SSDATA (hdir);
newdirlen = SBYTES (hdir);
}
nm = p;
#ifdef DOS_NT
......@@ -1234,7 +1239,8 @@ filesystem tree, not (expand-file-name ".." dirname). */)
Lisp_Object tem = build_string (adir);
tem = DECODE_FILE (tem);
memcpy (adir, SSDATA (tem), SBYTES (tem) + 1);
newdirlen = SBYTES (tem);
memcpy (adir, SSDATA (tem), newdirlen + 1);
}
}
if (!adir)
......@@ -1245,6 +1251,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
adir[1] = ':';
adir[2] = '/';
adir[3] = 0;
newdirlen = 3;
}
newdir = adir;
}
......@@ -1265,11 +1272,13 @@ filesystem tree, not (expand-file-name ".." dirname). */)
&& !newdir)
{
newdir = SSDATA (default_directory);
newdirlen = SBYTES (default_directory);
#ifdef DOS_NT
/* Note if special escape prefix is present, but remove for now. */
if (newdir[0] == '/' && newdir[1] == ':')
{
is_escaped = 1;
newdirlen -= 2;
newdir += 2;
}
#endif
......@@ -1305,14 +1314,14 @@ filesystem tree, not (expand-file-name ".." dirname). */)
if (IS_DRIVE (newdir[0]) && IS_DEVICE_SEP (newdir[1]))
{
drive = (unsigned char) newdir[0];
newdirlen -= 2;
newdir += 2;
}
if (!IS_DIRECTORY_SEP (nm[0]))
{
ptrdiff_t newlen = strlen (newdir);
char *tmp = alloca (newlen + file_name_as_directory_slop
char *tmp = alloca (newdirlen + file_name_as_directory_slop
+ strlen (nm) + 1);
file_name_as_directory (tmp, newdir, newlen, multibyte);
file_name_as_directory (tmp, newdir, newdirlen, multibyte);
strcat (tmp, nm);
nm = tmp;
}
......@@ -1329,8 +1338,11 @@ filesystem tree, not (expand-file-name ".." dirname). */)
Lisp_Object tem = build_string (adir);
tem = DECODE_FILE (tem);
memcpy (adir, SSDATA (tem), SBYTES (tem) + 1);
newdirlen = SBYTES (tem);
memcpy (adir, SSDATA (tem), newdirlen + 1);
}
else
newdirlen = strlen (aidr);
newdir = adir;
}
......@@ -1338,6 +1350,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
if (IS_DRIVE (newdir[0]) && IS_DEVICE_SEP (newdir[1]))
{
drive = newdir[0];
newdirlen -= 2;
newdir += 2;
}
......@@ -1349,17 +1362,18 @@ filesystem tree, not (expand-file-name ".." dirname). */)
if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1])
&& !IS_DIRECTORY_SEP (newdir[2]))
{
char *adir = strcpy (alloca (strlen (newdir) + 1), newdir);
char *adir = strcpy (alloca (newdirlen + 1), newdir);
char *p = adir + 2;
while (*p && !IS_DIRECTORY_SEP (*p)) p++;
p++;
while (*p && !IS_DIRECTORY_SEP (*p)) p++;
*p = 0;
newdir = adir;
newdirlen = strlen (adir);
}
else
#endif
newdir = "";
newdirlen = 0, newdir = "";
}
}
#endif /* DOS_NT */
......@@ -1368,7 +1382,8 @@ filesystem tree, not (expand-file-name ".." dirname). */)
{
/* Ignore any slash at the end of newdir, unless newdir is
just "/" or "//". */
length = strlen (newdir);
length = newdirlen;
eassert (length == strlen (newdir));
while (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1])
&& ! (length == 2 && IS_DIRECTORY_SEP (newdir[0])))
length--;
......@@ -2765,23 +2780,24 @@ searchable directory. */)
}
absname = ENCODE_FILE (absname);
return file_accessible_directory_p (SSDATA (absname)) ? Qt : Qnil;
return file_accessible_directory_p (absname) ? Qt : Qnil;
}
/* If FILE is a searchable directory or a symlink to a
searchable directory, return true. Otherwise return
false and set errno to an error number. */
bool
file_accessible_directory_p (char const *file)
file_accessible_directory_p (Lisp_Object file)
{
#ifdef DOS_NT
/* There's no need to test whether FILE is searchable, as the
searchable/executable bit is invented on DOS_NT platforms. */
return file_directory_p (file);
return file_directory_p (SSDATA (file));
#else
/* On POSIXish platforms, use just one system call; this avoids a
race and is typically faster. */
ptrdiff_t len = strlen (file);
const char *data = SSDATA (file);
ptrdiff_t len = SBYTES (file);
char const *dir;
bool ok;
int saved_errno;
......@@ -2793,15 +2809,15 @@ file_accessible_directory_p (char const *file)
"/" and "//" are distinct on some platforms, whereas "/", "///",
"////", etc. are all equivalent. */
if (! len)
dir = file;
dir = data;
else
{
/* Just check for trailing '/' when deciding whether to append '/'.
That's simpler than testing the two special cases "/" and "//",
and it's a safe optimization here. */
char *buf = SAFE_ALLOCA (len + 3);
memcpy (buf, file, len);
strcpy (buf + len, &"/."[file[len - 1] == '/']);
memcpy (buf, data, len);
strcpy (buf + len, &"/."[data[len - 1] == '/']);
dir = buf;
}
......
......@@ -4029,7 +4029,7 @@ extern _Noreturn void report_file_error (const char *, Lisp_Object);
extern bool internal_delete_file (Lisp_Object);
extern Lisp_Object emacs_readlinkat (int, const char *);
extern bool file_directory_p (const char *);
extern bool file_accessible_directory_p (const char *);
extern bool file_accessible_directory_p (Lisp_Object);
extern void init_fileio (void);
extern void syms_of_fileio (void);
extern Lisp_Object make_temp_name (Lisp_Object, bool);
......
......@@ -4213,7 +4213,7 @@ load_path_check (Lisp_Object lpath)
if (STRINGP (dirfile))
{
dirfile = Fdirectory_file_name (dirfile);
if (! file_accessible_directory_p (SSDATA (dirfile)))
if (! file_accessible_directory_p (dirfile))
dir_warning ("Lisp directory", XCAR (path_tail));
}
}
......
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