diff options
author | Lars Ingebrigtsen <larsi@gnus.org> | 2021-07-25 08:00:50 +0200 |
---|---|---|
committer | Lars Ingebrigtsen <larsi@gnus.org> | 2021-07-25 08:00:50 +0200 |
commit | aa9cba658768aba4da1b74ffb33d9962ffff5756 (patch) | |
tree | 39d07450a850e5b46687f18c367e64e723cbb7a3 /src | |
parent | 03f844249cb15a8380d09041a537803c933a2769 (diff) | |
download | emacs-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.
Diffstat (limited to 'src')
-rw-r--r-- | src/fileio.c | 46 |
1 files changed, 33 insertions, 13 deletions
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; } |