diff options
| author | Dmitry Antipov | 2014-09-02 09:44:38 +0400 |
|---|---|---|
| committer | Dmitry Antipov | 2014-09-02 09:44:38 +0400 |
| commit | a4a30aa0ecf0a9f032f2744548abf96b6d3d117e (patch) | |
| tree | f6aeb5703de388d2bba373c8b5f441188a4cf85a | |
| parent | 068c8b7d6aa777b44032c71a869d799107644574 (diff) | |
| download | emacs-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.
| -rw-r--r-- | src/ChangeLog | 6 | ||||
| -rw-r--r-- | src/fileio.c | 46 |
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 @@ | |||
| 1 | 2014-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 | |||
| 1 | 2014-09-01 Dmitry Antipov <dmantipov@yandex.ru> | 7 | 2014-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 | |||
| 852 | DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0, | 859 | DEFUN ("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. |
| 854 | Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative | 861 | Second 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. */ |