[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] trunk r117803: * fileio.c (CHECK_LENGTH): New macro.
From: |
Dmitry Antipov |
Subject: |
[Emacs-diffs] trunk r117803: * fileio.c (CHECK_LENGTH): New macro. |
Date: |
Tue, 02 Sep 2014 05:44:50 +0000 |
User-agent: |
Bazaar (2.6b2) |
------------------------------------------------------------
revno: 117803
revision-id: address@hidden
parent: address@hidden
committer: Dmitry Antipov <address@hidden>
branch nick: trunk
timestamp: Tue 2014-09-02 09:44:38 +0400
message:
* fileio.c (CHECK_LENGTH): New macro.
(Fexpand_file_name): Use it and get rid of a few more calls
to strlen and strcat.
modified:
src/ChangeLog changelog-20091113204419-o5vbwnq5f7feedwu-1438
src/fileio.c fileio.c-20091113204419-o5vbwnq5f7feedwu-210
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog 2014-09-01 16:05:43 +0000
+++ b/src/ChangeLog 2014-09-02 05:44:38 +0000
@@ -1,3 +1,9 @@
+2014-09-02 Dmitry Antipov <address@hidden>
+
+ * fileio.c (CHECK_LENGTH): New macro.
+ (Fexpand_file_name): Use it and get rid of a few more calls
+ to strlen and strcat.
+
2014-09-01 Dmitry Antipov <address@hidden>
Avoid extra calls to strlen in filesystem I/O routines.
=== modified file 'src/fileio.c'
--- a/src/fileio.c 2014-09-02 03:47:54 +0000
+++ b/src/fileio.c 2014-09-02 05:44:38 +0000
@@ -847,8 +847,15 @@
return make_temp_name (prefix, 0);
}
+/* The following function does a lot of work with \0-terminated strings.
+ To avoid extra calls to strlen and strcat, we maintain an important
+ lengths explicitly. This macro is used to check whether we're in sync. */
+#ifdef ENABLE_CHECKING
+#define CHECK_LENGTH(str, len) (eassert (strlen (str) == len), len)
+#else
+#define CHECK_LENGTH(str, len) (len)
+#endif /* ENABLE_CHECKING */
-
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
@@ -889,7 +896,7 @@
bool collapse_newdir = 1;
bool is_escaped = 0;
#endif /* DOS_NT */
- ptrdiff_t length, newdirlen;
+ ptrdiff_t length, newdirlen, nmlen, nbytes;
Lisp_Object handler, result, handled_name;
bool multibyte;
Lisp_Object hdir;
@@ -1018,14 +1025,16 @@
default_directory = Fdowncase (default_directory);
#endif
- /* Make a local copy of nm[] to protect it from GC in DECODE_FILE below. */
+ /* Make a local copy of NAME to protect it from GC in DECODE_FILE below. */
nm = xlispstrdupa (name);
+ nmlen = SBYTES (name);
#ifdef DOS_NT
/* Note if special escape prefix is present, but remove for now. */
if (nm[0] == '/' && nm[1] == ':')
{
is_escaped = 1;
+ nmlen -= 2;
nm += 2;
}
@@ -1035,6 +1044,7 @@
if (IS_DRIVE (nm[0]) && IS_DEVICE_SEP (nm[1]))
{
drive = (unsigned char) nm[0];
+ nmlen -= 2;
nm += 2;
}
@@ -1043,7 +1053,7 @@
colon when stripping the drive letter. Otherwise, this expands to
"//somedir". */
if (drive && IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
- nm++;
+ nmlen--, nm++;
/* Discard any previous drive specifier if nm is now in UNC format. */
if (IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])
@@ -1104,7 +1114,8 @@
if (IS_DIRECTORY_SEP (nm[1]))
{
if (strcmp (nm, SSDATA (name)) != 0)
- name = make_specified_string (nm, -1, strlen (nm), multibyte);
+ name = make_specified_string
+ (nm, -1, CHECK_LENGTH (nm, nmlen), multibyte);
}
else
#endif
@@ -1125,7 +1136,8 @@
#else /* not DOS_NT */
if (strcmp (nm, SSDATA (name)) == 0)
return name;
- return make_specified_string (nm, -1, strlen (nm), multibyte);
+ return make_specified_string
+ (nm, -1, CHECK_LENGTH (nm, nmlen), multibyte);
#endif /* not DOS_NT */
}
}
@@ -1158,7 +1170,7 @@
if (!(newdir = egetenv ("HOME")))
newdir = "";
- nm++;
+ nmlen--, nm++;
/* `egetenv' may return a unibyte string, which will bite us since
we expect the directory to be multibyte. */
#ifdef WINDOWSNT
@@ -1211,6 +1223,7 @@
newdir = SSDATA (hdir);
newdirlen = SBYTES (hdir);
}
+ nmlen -= (p - nm);
nm = p;
#ifdef DOS_NT
collapse_newdir = 0;
@@ -1320,9 +1333,11 @@
if (!IS_DIRECTORY_SEP (nm[0]))
{
char *tmp = alloca (newdirlen + file_name_as_directory_slop
- + strlen (nm) + 1);
- file_name_as_directory (tmp, newdir, newdirlen, multibyte);
- strcat (tmp, nm);
+ + CHECK_LENGTH (nm, nmlen) + 1);
+ nbytes = file_name_as_directory (tmp, newdir, newdirlen,
+ multibyte);
+ memcpy (tmp + nbytes, nm, nmlen + 1);
+ nmlen += nbytes;
nm = tmp;
}
adir = alloca (adir_size);
@@ -1382,8 +1397,7 @@
{
/* Ignore any slash at the end of newdir, unless newdir is
just "/" or "//". */
- length = newdirlen;
- eassert (length == strlen (newdir));
+ length = CHECK_LENGTH (newdir, newdirlen);
while (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1])
&& ! (length == 2 && IS_DIRECTORY_SEP (newdir[0])))
length--;
@@ -1392,7 +1406,7 @@
length = 0;
/* Now concatenate the directory and name to new space in the stack frame.
*/
- tlen = length + file_name_as_directory_slop + strlen (nm) + 1;
+ tlen = length + file_name_as_directory_slop + CHECK_LENGTH (nm, nmlen) + 1;
#ifdef DOS_NT
/* Reserve space for drive specifier and escape prefix, since either
or both may need to be inserted. (The Microsoft x86 compiler
@@ -1403,6 +1417,7 @@
target = SAFE_ALLOCA (tlen);
#endif /* not DOS_NT */
*target = 0;
+ nbytes = 0;
if (newdir)
{
@@ -1420,13 +1435,14 @@
{
memcpy (target, newdir, length);
target[length] = 0;
+ nbytes = length;
}
}
else
- file_name_as_directory (target, newdir, length, multibyte);
+ nbytes = file_name_as_directory (target, newdir, length, multibyte);
}
- strcat (target, nm);
+ memcpy (target + nbytes, nm, nmlen + 1);
/* Now canonicalize by removing `//', `/.' and `/foo/..' if they
appear. */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] trunk r117803: * fileio.c (CHECK_LENGTH): New macro.,
Dmitry Antipov <=