summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Ingebrigtsen <larsi@gnus.org>2021-07-25 08:00:50 +0200
committerLars Ingebrigtsen <larsi@gnus.org>2021-07-25 08:00:50 +0200
commitaa9cba658768aba4da1b74ffb33d9962ffff5756 (patch)
tree39d07450a850e5b46687f18c367e64e723cbb7a3
parent03f844249cb15a8380d09041a537803c933a2769 (diff)
downloademacs-aa9cba658768aba4da1b74ffb33d9962ffff5756.tar.gz
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.texi4
-rw-r--r--src/fileio.c46
-rw-r--r--test/src/fileio-tests.el9
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.
@end group
@end example
-A zero-length directory or component is not allowed.
+A @var{directory} or components that are @code{nil} or the empty
+string are ignored---they are filtered out first and do not affect the
+results in any way.
This is almost the same as using @code{concat}, but @var{dirname} (and
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. */)
DEFUN ("directory-append", Fdirectory_append, Sdirectory_append, 1, MANY, 0,
doc: /* Append COMPONENTS to DIRECTORY and return the resulting string.
-COMPONENTS must be strings.
+Elements in COMPONENTS must be a string or nil.
DIRECTORY or the non-final elements in COMPONENTS may or may not end
with a slash -- if they don't end with a slash, a slash will be
inserted before contatenating.
usage: (record DIRECTORY &rest COMPONENTS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
- ptrdiff_t chars = 0, bytes = 0, multibytes = 0;
+ ptrdiff_t chars = 0, bytes = 0, multibytes = 0, eargs = 0;
Lisp_Object *elements = args;
Lisp_Object result;
ptrdiff_t i;
@@ -768,9 +768,13 @@ usage: (record DIRECTORY &rest COMPONENTS) */)
for (i = 0; i < nargs; i++)
{
Lisp_Object arg = args[i];
+ /* Skip empty and nil elements. */
+ if (NILP (arg))
+ continue;
CHECK_STRING (arg);
if (SCHARS (arg) == 0)
- xsignal1 (Qfile_error, build_string ("Empty file name"));
+ continue;
+ eargs++;
/* Multibyte and non-ASCII. */
if (STRING_MULTIBYTE (arg) && SCHARS (arg) != SBYTES (arg))
multibytes++;
@@ -789,25 +793,41 @@ usage: (record DIRECTORY &rest COMPONENTS) */)
}
/* Convert if needed. */
- if (multibytes != 0 && multibytes != nargs)
+ if ((multibytes != 0 && multibytes != nargs)
+ || eargs != nargs)
{
- elements = xmalloc (nargs * sizeof *elements);
+ int j = 0;
+ elements = xmalloc (eargs * sizeof *elements);
bytes = 0;
+ chars = 0;
+
+ /* Filter out nil/"". */
for (i = 0; i < nargs; i++)
{
Lisp_Object arg = args[i];
+ if (!NILP (arg) && SCHARS (arg) != 0)
+ elements[j++] = arg;
+ }
+
+ for (i = 0; i < eargs; i++)
+ {
+ Lisp_Object arg = elements[i];
/* Use multibyte or all-ASCII strings as is. */
- if (STRING_MULTIBYTE (arg) || string_ascii_p (arg))
- elements[i] = arg;
- else
+ if (!STRING_MULTIBYTE (arg) && !string_ascii_p (arg))
elements[i] = Fstring_to_multibyte (arg);
arg = elements[i];
/* We have to recompute the number of bytes. */
- if (i == nargs - 1
+ if (i == eargs - 1
|| IS_DIRECTORY_SEP (*(SSDATA (arg) + SBYTES (arg) - 1)))
- bytes += SBYTES (arg);
+ {
+ bytes += SBYTES (arg);
+ chars += SCHARS (arg);
+ }
else
- bytes += SBYTES (arg) + 1;
+ {
+ bytes += SBYTES (arg) + 1;
+ chars += SCHARS (arg) + 1;
+ }
}
}
@@ -821,13 +841,13 @@ usage: (record DIRECTORY &rest COMPONENTS) */)
/* Copy over the data. */
char *p = SSDATA (result);
- for (i = 0; i < nargs; i++)
+ for (i = 0; i < eargs; i++)
{
Lisp_Object arg = elements[i];
memcpy (p, SSDATA (arg), SBYTES (arg));
p += SBYTES (arg);
/* The last element shouldn't have a slash added at the end. */
- if (i < nargs - 1 && !IS_DIRECTORY_SEP (*(p - 1)))
+ if (i < eargs - 1 && !IS_DIRECTORY_SEP (*(p - 1)))
*p++ = DIRECTORY_SEP;
}
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."
(aset string 2 255)
(should (not (multibyte-string-p string)))
(should (equal (directory-append "fóo" string) "fóo/aa\377aa")))
- (should-error (directory-append "foo" ""))
- (should-error (directory-append "" "bar"))
- (should-error (directory-append "" "")))
+ (should (equal (directory-append "foo") "foo"))
+ (should (equal (directory-append "foo/") "foo/"))
+ (should (equal (directory-append "foo" "") "foo"))
+ (should (equal (directory-append "foo" "" "" "" nil) "foo"))
+ (should (equal (directory-append "" "bar") "bar"))
+ (should (equal (directory-append "" "") "")))
;;; fileio-tests.el ends here