aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDmitry Antipov2014-09-02 09:44:38 +0400
committerDmitry Antipov2014-09-02 09:44:38 +0400
commita4a30aa0ecf0a9f032f2744548abf96b6d3d117e (patch)
treef6aeb5703de388d2bba373c8b5f441188a4cf85a /src
parent068c8b7d6aa777b44032c71a869d799107644574 (diff)
downloademacs-a4a30aa0ecf0a9f032f2744548abf96b6d3d117e.tar.gz
emacs-a4a30aa0ecf0a9f032f2744548abf96b6d3d117e.zip
* fileio.c (CHECK_LENGTH): New macro.
(Fexpand_file_name): Use it and get rid of a few more calls to strlen and strcat.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog6
-rw-r--r--src/fileio.c46
2 files changed, 37 insertions, 15 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index a5ec9c35efa..2de909ef800 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,9 @@
12014-09-02 Dmitry Antipov <dmantipov@yandex.ru>
2
3 * fileio.c (CHECK_LENGTH): New macro.
4 (Fexpand_file_name): Use it and get rid of a few more calls
5 to strlen and strcat.
6
12014-09-01 Dmitry Antipov <dmantipov@yandex.ru> 72014-09-01 Dmitry Antipov <dmantipov@yandex.ru>
2 8
3 Avoid extra calls to strlen in filesystem I/O routines. 9 Avoid extra calls to strlen in filesystem I/O routines.
diff --git a/src/fileio.c b/src/fileio.c
index 2842839f2b3..bd1e650c427 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -847,8 +847,15 @@ probably use `make-temp-file' instead, except in three circumstances:
847 return make_temp_name (prefix, 0); 847 return make_temp_name (prefix, 0);
848} 848}
849 849
850/* The following function does a lot of work with \0-terminated strings.
851 To avoid extra calls to strlen and strcat, we maintain an important
852 lengths explicitly. This macro is used to check whether we're in sync. */
853#ifdef ENABLE_CHECKING
854#define CHECK_LENGTH(str, len) (eassert (strlen (str) == len), len)
855#else
856#define CHECK_LENGTH(str, len) (len)
857#endif /* ENABLE_CHECKING */
850 858
851
852DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0, 859DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
853 doc: /* Convert filename NAME to absolute, and canonicalize it. 860 doc: /* Convert filename NAME to absolute, and canonicalize it.
854Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative 861Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative
@@ -889,7 +896,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
889 bool collapse_newdir = 1; 896 bool collapse_newdir = 1;
890 bool is_escaped = 0; 897 bool is_escaped = 0;
891#endif /* DOS_NT */ 898#endif /* DOS_NT */
892 ptrdiff_t length, newdirlen; 899 ptrdiff_t length, newdirlen, nmlen, nbytes;
893 Lisp_Object handler, result, handled_name; 900 Lisp_Object handler, result, handled_name;
894 bool multibyte; 901 bool multibyte;
895 Lisp_Object hdir; 902 Lisp_Object hdir;
@@ -1018,14 +1025,16 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1018 default_directory = Fdowncase (default_directory); 1025 default_directory = Fdowncase (default_directory);
1019#endif 1026#endif
1020 1027
1021 /* Make a local copy of nm[] to protect it from GC in DECODE_FILE below. */ 1028 /* Make a local copy of NAME to protect it from GC in DECODE_FILE below. */
1022 nm = xlispstrdupa (name); 1029 nm = xlispstrdupa (name);
1030 nmlen = SBYTES (name);
1023 1031
1024#ifdef DOS_NT 1032#ifdef DOS_NT
1025 /* Note if special escape prefix is present, but remove for now. */ 1033 /* Note if special escape prefix is present, but remove for now. */
1026 if (nm[0] == '/' && nm[1] == ':') 1034 if (nm[0] == '/' && nm[1] == ':')
1027 { 1035 {
1028 is_escaped = 1; 1036 is_escaped = 1;
1037 nmlen -= 2;
1029 nm += 2; 1038 nm += 2;
1030 } 1039 }
1031 1040
@@ -1035,6 +1044,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1035 if (IS_DRIVE (nm[0]) && IS_DEVICE_SEP (nm[1])) 1044 if (IS_DRIVE (nm[0]) && IS_DEVICE_SEP (nm[1]))
1036 { 1045 {
1037 drive = (unsigned char) nm[0]; 1046 drive = (unsigned char) nm[0];
1047 nmlen -= 2;
1038 nm += 2; 1048 nm += 2;
1039 } 1049 }
1040 1050
@@ -1043,7 +1053,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1043 colon when stripping the drive letter. Otherwise, this expands to 1053 colon when stripping the drive letter. Otherwise, this expands to
1044 "//somedir". */ 1054 "//somedir". */
1045 if (drive && IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])) 1055 if (drive && IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
1046 nm++; 1056 nmlen--, nm++;
1047 1057
1048 /* Discard any previous drive specifier if nm is now in UNC format. */ 1058 /* Discard any previous drive specifier if nm is now in UNC format. */
1049 if (IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]) 1059 if (IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])
@@ -1104,7 +1114,8 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1104 if (IS_DIRECTORY_SEP (nm[1])) 1114 if (IS_DIRECTORY_SEP (nm[1]))
1105 { 1115 {
1106 if (strcmp (nm, SSDATA (name)) != 0) 1116 if (strcmp (nm, SSDATA (name)) != 0)
1107 name = make_specified_string (nm, -1, strlen (nm), multibyte); 1117 name = make_specified_string
1118 (nm, -1, CHECK_LENGTH (nm, nmlen), multibyte);
1108 } 1119 }
1109 else 1120 else
1110#endif 1121#endif
@@ -1125,7 +1136,8 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1125#else /* not DOS_NT */ 1136#else /* not DOS_NT */
1126 if (strcmp (nm, SSDATA (name)) == 0) 1137 if (strcmp (nm, SSDATA (name)) == 0)
1127 return name; 1138 return name;
1128 return make_specified_string (nm, -1, strlen (nm), multibyte); 1139 return make_specified_string
1140 (nm, -1, CHECK_LENGTH (nm, nmlen), multibyte);
1129#endif /* not DOS_NT */ 1141#endif /* not DOS_NT */
1130 } 1142 }
1131 } 1143 }
@@ -1158,7 +1170,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1158 1170
1159 if (!(newdir = egetenv ("HOME"))) 1171 if (!(newdir = egetenv ("HOME")))
1160 newdir = ""; 1172 newdir = "";
1161 nm++; 1173 nmlen--, nm++;
1162 /* `egetenv' may return a unibyte string, which will bite us since 1174 /* `egetenv' may return a unibyte string, which will bite us since
1163 we expect the directory to be multibyte. */ 1175 we expect the directory to be multibyte. */
1164#ifdef WINDOWSNT 1176#ifdef WINDOWSNT
@@ -1211,6 +1223,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1211 newdir = SSDATA (hdir); 1223 newdir = SSDATA (hdir);
1212 newdirlen = SBYTES (hdir); 1224 newdirlen = SBYTES (hdir);
1213 } 1225 }
1226 nmlen -= (p - nm);
1214 nm = p; 1227 nm = p;
1215#ifdef DOS_NT 1228#ifdef DOS_NT
1216 collapse_newdir = 0; 1229 collapse_newdir = 0;
@@ -1320,9 +1333,11 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1320 if (!IS_DIRECTORY_SEP (nm[0])) 1333 if (!IS_DIRECTORY_SEP (nm[0]))
1321 { 1334 {
1322 char *tmp = alloca (newdirlen + file_name_as_directory_slop 1335 char *tmp = alloca (newdirlen + file_name_as_directory_slop
1323 + strlen (nm) + 1); 1336 + CHECK_LENGTH (nm, nmlen) + 1);
1324 file_name_as_directory (tmp, newdir, newdirlen, multibyte); 1337 nbytes = file_name_as_directory (tmp, newdir, newdirlen,
1325 strcat (tmp, nm); 1338 multibyte);
1339 memcpy (tmp + nbytes, nm, nmlen + 1);
1340 nmlen += nbytes;
1326 nm = tmp; 1341 nm = tmp;
1327 } 1342 }
1328 adir = alloca (adir_size); 1343 adir = alloca (adir_size);
@@ -1382,8 +1397,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1382 { 1397 {
1383 /* Ignore any slash at the end of newdir, unless newdir is 1398 /* Ignore any slash at the end of newdir, unless newdir is
1384 just "/" or "//". */ 1399 just "/" or "//". */
1385 length = newdirlen; 1400 length = CHECK_LENGTH (newdir, newdirlen);
1386 eassert (length == strlen (newdir));
1387 while (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1]) 1401 while (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1])
1388 && ! (length == 2 && IS_DIRECTORY_SEP (newdir[0]))) 1402 && ! (length == 2 && IS_DIRECTORY_SEP (newdir[0])))
1389 length--; 1403 length--;
@@ -1392,7 +1406,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1392 length = 0; 1406 length = 0;
1393 1407
1394 /* Now concatenate the directory and name to new space in the stack frame. */ 1408 /* Now concatenate the directory and name to new space in the stack frame. */
1395 tlen = length + file_name_as_directory_slop + strlen (nm) + 1; 1409 tlen = length + file_name_as_directory_slop + CHECK_LENGTH (nm, nmlen) + 1;
1396#ifdef DOS_NT 1410#ifdef DOS_NT
1397 /* Reserve space for drive specifier and escape prefix, since either 1411 /* Reserve space for drive specifier and escape prefix, since either
1398 or both may need to be inserted. (The Microsoft x86 compiler 1412 or both may need to be inserted. (The Microsoft x86 compiler
@@ -1403,6 +1417,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1403 target = SAFE_ALLOCA (tlen); 1417 target = SAFE_ALLOCA (tlen);
1404#endif /* not DOS_NT */ 1418#endif /* not DOS_NT */
1405 *target = 0; 1419 *target = 0;
1420 nbytes = 0;
1406 1421
1407 if (newdir) 1422 if (newdir)
1408 { 1423 {
@@ -1420,13 +1435,14 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1420 { 1435 {
1421 memcpy (target, newdir, length); 1436 memcpy (target, newdir, length);
1422 target[length] = 0; 1437 target[length] = 0;
1438 nbytes = length;
1423 } 1439 }
1424 } 1440 }
1425 else 1441 else
1426 file_name_as_directory (target, newdir, length, multibyte); 1442 nbytes = file_name_as_directory (target, newdir, length, multibyte);
1427 } 1443 }
1428 1444
1429 strcat (target, nm); 1445 memcpy (target + nbytes, nm, nmlen + 1);
1430 1446
1431 /* Now canonicalize by removing `//', `/.' and `/foo/..' if they 1447 /* Now canonicalize by removing `//', `/.' and `/foo/..' if they
1432 appear. */ 1448 appear. */