Allow empty elements in directory-append
* doc/lispref/files.texi (Directory Names): Document it. * src/fileio.c (Fdirectory_append): Allow empty elements.
This commit is contained in:
parent
03f844249c
commit
aa9cba6587
3 changed files with 42 additions and 17 deletions
|
@ -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,
|
||||
|
|
46
src/fileio.c
46
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue