diff options
| author | Lars Ingebrigtsen | 2021-07-25 08:00:50 +0200 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2021-07-25 08:00:50 +0200 |
| commit | aa9cba658768aba4da1b74ffb33d9962ffff5756 (patch) | |
| tree | 39d07450a850e5b46687f18c367e64e723cbb7a3 | |
| parent | 03f844249cb15a8380d09041a537803c933a2769 (diff) | |
| download | emacs-aa9cba658768aba4da1b74ffb33d9962ffff5756.tar.gz emacs-aa9cba658768aba4da1b74ffb33d9962ffff5756.zip | |
Allow empty elements in directory-append
* doc/lispref/files.texi (Directory Names): Document it.
* src/fileio.c (Fdirectory_append): Allow empty elements.
| -rw-r--r-- | doc/lispref/files.texi | 4 | ||||
| -rw-r--r-- | src/fileio.c | 46 | ||||
| -rw-r--r-- | test/src/fileio-tests.el | 9 |
3 files changed, 42 insertions, 17 deletions
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 804cef292ee..e7a0ad2d06c 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi | |||
| @@ -2355,7 +2355,9 @@ didn't end with a slash. | |||
| 2355 | @end group | 2355 | @end group |
| 2356 | @end example | 2356 | @end example |
| 2357 | 2357 | ||
| 2358 | A zero-length directory or component is not allowed. | 2358 | A @var{directory} or components that are @code{nil} or the empty |
| 2359 | string are ignored---they are filtered out first and do not affect the | ||
| 2360 | results in any way. | ||
| 2359 | 2361 | ||
| 2360 | This is almost the same as using @code{concat}, but @var{dirname} (and | 2362 | This is almost the same as using @code{concat}, but @var{dirname} (and |
| 2361 | the non-final components) may or may not end with slash characters, | 2363 | the non-final components) may or may not end with slash characters, |
diff --git a/src/fileio.c b/src/fileio.c index d6b3e7bca40..3d8b082a59c 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -751,14 +751,14 @@ For that reason, you should normally use `make-temp-file' instead. */) | |||
| 751 | 751 | ||
| 752 | DEFUN ("directory-append", Fdirectory_append, Sdirectory_append, 1, MANY, 0, | 752 | DEFUN ("directory-append", Fdirectory_append, Sdirectory_append, 1, MANY, 0, |
| 753 | doc: /* Append COMPONENTS to DIRECTORY and return the resulting string. | 753 | doc: /* Append COMPONENTS to DIRECTORY and return the resulting string. |
| 754 | COMPONENTS must be strings. | 754 | Elements in COMPONENTS must be a string or nil. |
| 755 | DIRECTORY or the non-final elements in COMPONENTS may or may not end | 755 | DIRECTORY or the non-final elements in COMPONENTS may or may not end |
| 756 | with a slash -- if they don't end with a slash, a slash will be | 756 | with a slash -- if they don't end with a slash, a slash will be |
| 757 | inserted before contatenating. | 757 | inserted before contatenating. |
| 758 | usage: (record DIRECTORY &rest COMPONENTS) */) | 758 | usage: (record DIRECTORY &rest COMPONENTS) */) |
| 759 | (ptrdiff_t nargs, Lisp_Object *args) | 759 | (ptrdiff_t nargs, Lisp_Object *args) |
| 760 | { | 760 | { |
| 761 | ptrdiff_t chars = 0, bytes = 0, multibytes = 0; | 761 | ptrdiff_t chars = 0, bytes = 0, multibytes = 0, eargs = 0; |
| 762 | Lisp_Object *elements = args; | 762 | Lisp_Object *elements = args; |
| 763 | Lisp_Object result; | 763 | Lisp_Object result; |
| 764 | ptrdiff_t i; | 764 | ptrdiff_t i; |
| @@ -768,9 +768,13 @@ usage: (record DIRECTORY &rest COMPONENTS) */) | |||
| 768 | for (i = 0; i < nargs; i++) | 768 | for (i = 0; i < nargs; i++) |
| 769 | { | 769 | { |
| 770 | Lisp_Object arg = args[i]; | 770 | Lisp_Object arg = args[i]; |
| 771 | /* Skip empty and nil elements. */ | ||
| 772 | if (NILP (arg)) | ||
| 773 | continue; | ||
| 771 | CHECK_STRING (arg); | 774 | CHECK_STRING (arg); |
| 772 | if (SCHARS (arg) == 0) | 775 | if (SCHARS (arg) == 0) |
| 773 | xsignal1 (Qfile_error, build_string ("Empty file name")); | 776 | continue; |
| 777 | eargs++; | ||
| 774 | /* Multibyte and non-ASCII. */ | 778 | /* Multibyte and non-ASCII. */ |
| 775 | if (STRING_MULTIBYTE (arg) && SCHARS (arg) != SBYTES (arg)) | 779 | if (STRING_MULTIBYTE (arg) && SCHARS (arg) != SBYTES (arg)) |
| 776 | multibytes++; | 780 | multibytes++; |
| @@ -789,25 +793,41 @@ usage: (record DIRECTORY &rest COMPONENTS) */) | |||
| 789 | } | 793 | } |
| 790 | 794 | ||
| 791 | /* Convert if needed. */ | 795 | /* Convert if needed. */ |
| 792 | if (multibytes != 0 && multibytes != nargs) | 796 | if ((multibytes != 0 && multibytes != nargs) |
| 797 | || eargs != nargs) | ||
| 793 | { | 798 | { |
| 794 | elements = xmalloc (nargs * sizeof *elements); | 799 | int j = 0; |
| 800 | elements = xmalloc (eargs * sizeof *elements); | ||
| 795 | bytes = 0; | 801 | bytes = 0; |
| 802 | chars = 0; | ||
| 803 | |||
| 804 | /* Filter out nil/"". */ | ||
| 796 | for (i = 0; i < nargs; i++) | 805 | for (i = 0; i < nargs; i++) |
| 797 | { | 806 | { |
| 798 | Lisp_Object arg = args[i]; | 807 | Lisp_Object arg = args[i]; |
| 808 | if (!NILP (arg) && SCHARS (arg) != 0) | ||
| 809 | elements[j++] = arg; | ||
| 810 | } | ||
| 811 | |||
| 812 | for (i = 0; i < eargs; i++) | ||
| 813 | { | ||
| 814 | Lisp_Object arg = elements[i]; | ||
| 799 | /* Use multibyte or all-ASCII strings as is. */ | 815 | /* Use multibyte or all-ASCII strings as is. */ |
| 800 | if (STRING_MULTIBYTE (arg) || string_ascii_p (arg)) | 816 | if (!STRING_MULTIBYTE (arg) && !string_ascii_p (arg)) |
| 801 | elements[i] = arg; | ||
| 802 | else | ||
| 803 | elements[i] = Fstring_to_multibyte (arg); | 817 | elements[i] = Fstring_to_multibyte (arg); |
| 804 | arg = elements[i]; | 818 | arg = elements[i]; |
| 805 | /* We have to recompute the number of bytes. */ | 819 | /* We have to recompute the number of bytes. */ |
| 806 | if (i == nargs - 1 | 820 | if (i == eargs - 1 |
| 807 | || IS_DIRECTORY_SEP (*(SSDATA (arg) + SBYTES (arg) - 1))) | 821 | || IS_DIRECTORY_SEP (*(SSDATA (arg) + SBYTES (arg) - 1))) |
| 808 | bytes += SBYTES (arg); | 822 | { |
| 823 | bytes += SBYTES (arg); | ||
| 824 | chars += SCHARS (arg); | ||
| 825 | } | ||
| 809 | else | 826 | else |
| 810 | bytes += SBYTES (arg) + 1; | 827 | { |
| 828 | bytes += SBYTES (arg) + 1; | ||
| 829 | chars += SCHARS (arg) + 1; | ||
| 830 | } | ||
| 811 | } | 831 | } |
| 812 | } | 832 | } |
| 813 | 833 | ||
| @@ -821,13 +841,13 @@ usage: (record DIRECTORY &rest COMPONENTS) */) | |||
| 821 | 841 | ||
| 822 | /* Copy over the data. */ | 842 | /* Copy over the data. */ |
| 823 | char *p = SSDATA (result); | 843 | char *p = SSDATA (result); |
| 824 | for (i = 0; i < nargs; i++) | 844 | for (i = 0; i < eargs; i++) |
| 825 | { | 845 | { |
| 826 | Lisp_Object arg = elements[i]; | 846 | Lisp_Object arg = elements[i]; |
| 827 | memcpy (p, SSDATA (arg), SBYTES (arg)); | 847 | memcpy (p, SSDATA (arg), SBYTES (arg)); |
| 828 | p += SBYTES (arg); | 848 | p += SBYTES (arg); |
| 829 | /* The last element shouldn't have a slash added at the end. */ | 849 | /* The last element shouldn't have a slash added at the end. */ |
| 830 | if (i < nargs - 1 && !IS_DIRECTORY_SEP (*(p - 1))) | 850 | if (i < eargs - 1 && !IS_DIRECTORY_SEP (*(p - 1))) |
| 831 | *p++ = DIRECTORY_SEP; | 851 | *p++ = DIRECTORY_SEP; |
| 832 | } | 852 | } |
| 833 | 853 | ||
diff --git a/test/src/fileio-tests.el b/test/src/fileio-tests.el index 73a7775279a..b1288f943e3 100644 --- a/test/src/fileio-tests.el +++ b/test/src/fileio-tests.el | |||
| @@ -175,8 +175,11 @@ Also check that an encoding error can appear in a symlink." | |||
| 175 | (aset string 2 255) | 175 | (aset string 2 255) |
| 176 | (should (not (multibyte-string-p string))) | 176 | (should (not (multibyte-string-p string))) |
| 177 | (should (equal (directory-append "fóo" string) "fóo/aa\377aa"))) | 177 | (should (equal (directory-append "fóo" string) "fóo/aa\377aa"))) |
| 178 | (should-error (directory-append "foo" "")) | 178 | (should (equal (directory-append "foo") "foo")) |
| 179 | (should-error (directory-append "" "bar")) | 179 | (should (equal (directory-append "foo/") "foo/")) |
| 180 | (should-error (directory-append "" ""))) | 180 | (should (equal (directory-append "foo" "") "foo")) |
| 181 | (should (equal (directory-append "foo" "" "" "" nil) "foo")) | ||
| 182 | (should (equal (directory-append "" "bar") "bar")) | ||
| 183 | (should (equal (directory-append "" "") ""))) | ||
| 181 | 184 | ||
| 182 | ;;; fileio-tests.el ends here | 185 | ;;; fileio-tests.el ends here |