summaryrefslogtreecommitdiff
path: root/src/fileio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fileio.c')
-rw-r--r--src/fileio.c146
1 files changed, 131 insertions, 15 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 741e297d29c..13c99bee109 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -749,6 +749,114 @@ For that reason, you should normally use `make-temp-file' instead. */)
empty_unibyte_string, Qnil);
}
+DEFUN ("file-name-concat", Ffile_name_concat, Sfile_name_concat, 1, MANY, 0,
+ doc: /* Append COMPONENTS to DIRECTORY and return the resulting string.
+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, eargs = 0;
+ Lisp_Object *elements = args;
+ Lisp_Object result;
+ ptrdiff_t i;
+
+ /* First go through the list to check the types and see whether
+ they're all of the same multibytedness. */
+ 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)
+ continue;
+ eargs++;
+ /* Multibyte and non-ASCII. */
+ if (STRING_MULTIBYTE (arg) && SCHARS (arg) != SBYTES (arg))
+ multibytes++;
+ /* We're not adding a slash to the final part. */
+ if (i == nargs - 1
+ || IS_DIRECTORY_SEP (*(SSDATA (arg) + SBYTES (arg) - 1)))
+ {
+ bytes += SBYTES (arg);
+ chars += SCHARS (arg);
+ }
+ else
+ {
+ bytes += SBYTES (arg) + 1;
+ chars += SCHARS (arg) + 1;
+ }
+ }
+
+ /* Convert if needed. */
+ if ((multibytes != 0 && multibytes != nargs)
+ || eargs != nargs)
+ {
+ 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] = Fstring_to_multibyte (arg);
+ arg = elements[i];
+ /* We have to recompute the number of bytes. */
+ if (i == eargs - 1
+ || IS_DIRECTORY_SEP (*(SSDATA (arg) + SBYTES (arg) - 1)))
+ {
+ bytes += SBYTES (arg);
+ chars += SCHARS (arg);
+ }
+ else
+ {
+ bytes += SBYTES (arg) + 1;
+ chars += SCHARS (arg) + 1;
+ }
+ }
+ }
+
+ /* Allocate an empty string. */
+ if (multibytes == 0)
+ result = make_uninit_string (chars);
+ else
+ result = make_uninit_multibyte_string (chars, bytes);
+ /* Null-terminate the string. */
+ *(SSDATA (result) + SBYTES (result)) = 0;
+
+ /* Copy over the data. */
+ char *p = SSDATA (result);
+ 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 < eargs - 1 && !IS_DIRECTORY_SEP (*(p - 1)))
+ *p++ = DIRECTORY_SEP;
+ }
+
+ if (elements != args)
+ xfree (elements);
+
+ return result;
+}
+
/* NAME must be a string. */
static bool
file_name_absolute_no_tilde_p (Lisp_Object name)
@@ -1830,6 +1938,9 @@ the value of that variable. The variable name should be terminated
with a character not a letter, digit or underscore; otherwise, enclose
the entire variable name in braces.
+If FOO is not defined in the environment, `$FOO' is left unchanged in
+the value of this function.
+
If `/~' appears, all of FILENAME through that `/' is discarded.
If `//' appears, everything up to and including the first of
those `/' is discarded. */)
@@ -2987,12 +3098,16 @@ file_directory_p (Lisp_Object file)
DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p,
Sfile_accessible_directory_p, 1, 1, 0,
doc: /* Return t if FILENAME names a directory you can open.
-For the value to be t, FILENAME must specify the name of a directory
-as a file, and the directory must allow you to open files in it. In
-order to use a directory as a buffer's current directory, this
-predicate must return true. A directory name spec may be given
-instead; then the value is t if the directory so specified exists and
-really is a readable and searchable directory. */)
+This means that FILENAME must specify the name of a directory, and the
+directory must allow you to open files in it. If this isn't the case,
+return nil.
+
+FILENAME can either be a directory name (eg. \"/tmp/foo/\") or the
+file name of a file which is a directory (eg. \"/tmp/foo\", without
+the final slash).
+
+In order to use a directory as a buffer's current directory, this
+predicate must return true. */)
(Lisp_Object filename)
{
Lisp_Object absname;
@@ -4537,7 +4652,7 @@ by calling `format-decode', which see. */)
if (inserted == 0)
{
if (we_locked_file)
- unlock_file (BVAR (current_buffer, file_truename));
+ Funlock_file (BVAR (current_buffer, file_truename));
Vdeactivate_mark = old_Vdeactivate_mark;
}
else
@@ -4699,8 +4814,8 @@ by calling `format-decode', which see. */)
if (NILP (handler))
{
if (!NILP (BVAR (current_buffer, file_truename)))
- unlock_file (BVAR (current_buffer, file_truename));
- unlock_file (filename);
+ Funlock_file (BVAR (current_buffer, file_truename));
+ Funlock_file (filename);
}
if (not_regular)
xsignal2 (Qfile_error,
@@ -5161,7 +5276,7 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename,
if (open_and_close_file && !auto_saving)
{
- lock_file (lockname);
+ Flock_file (lockname);
file_locked = 1;
}
@@ -5186,7 +5301,7 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename,
{
int open_errno = errno;
if (file_locked)
- unlock_file (lockname);
+ Funlock_file (lockname);
report_file_errno ("Opening output file", filename, open_errno);
}
@@ -5201,7 +5316,7 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename,
{
int lseek_errno = errno;
if (file_locked)
- unlock_file (lockname);
+ Funlock_file (lockname);
report_file_errno ("Lseek error", filename, lseek_errno);
}
}
@@ -5338,7 +5453,7 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename,
unbind_to (count, Qnil);
if (file_locked)
- unlock_file (lockname);
+ Funlock_file (lockname);
/* Do this before reporting IO error
to avoid a "file has changed on disk" warning on
@@ -5363,14 +5478,14 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename,
bset_filename (current_buffer, visit_file);
update_mode_lines = 14;
if (auto_saving_into_visited_file)
- unlock_file (lockname);
+ Funlock_file (lockname);
}
else if (quietly)
{
if (auto_saving_into_visited_file)
{
SAVE_MODIFF = MODIFF;
- unlock_file (lockname);
+ Funlock_file (lockname);
}
return Qnil;
@@ -6481,6 +6596,7 @@ This includes interactive calls to `delete-file' and
defsubr (&Sdirectory_file_name);
defsubr (&Smake_temp_file_internal);
defsubr (&Smake_temp_name);
+ defsubr (&Sfile_name_concat);
defsubr (&Sexpand_file_name);
defsubr (&Ssubstitute_in_file_name);
defsubr (&Scopy_file);