/* File IO for GNU Emacs.
- Copyright (C) 1985,86,87,88,93,94,95,96,97,1998 Free Software Foundation, Inc.
+ Copyright (C) 1985,86,87,88,93,94,95,96,97,98,99,2000, 2001
+ Free Software Foundation, Inc.
This file is part of GNU Emacs.
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#define _GNU_SOURCE /* for euidaccess */
+
#include <config.h>
-#if defined (USG5) || defined (BSD_SYSTEM) || defined (LINUX)
+#if defined (USG5) || defined (BSD_SYSTEM) || defined (GNU_LINUX)
#include <fcntl.h>
#endif
#include <unistd.h>
#endif
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#endif
-
#if !defined (S_ISLNK) && defined (S_IFLNK)
# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#endif
#include <errno.h>
#ifndef vax11c
+#ifndef USE_CRT_DLL
extern int errno;
#endif
-
-extern char *strerror ();
+#endif
#ifdef APOLLO
#include <sys/time.h>
# define lstat stat
#endif
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#define max(a, b) ((a) > (b) ? (a) : (b))
-
/* Nonzero during writing of auto-save files */
int auto_saving;
Lisp_Object Qcar_less_than_car;
-static int a_write P_ ((int, char *, int, int,
+static int a_write P_ ((int, Lisp_Object, int, int,
Lisp_Object *, struct coding_system *));
-static int e_write P_ ((int, char *, int, struct coding_system *));
+static int e_write P_ ((int, Lisp_Object, int, int, struct coding_system *));
+
\f
void
report_file_error (string, data)
Lisp_Object errstring;
int errorno = errno;
- errstring = build_string (strerror (errno));
+ synchronize_system_messages_locale ();
+ errstring = code_convert_string_norecord (build_string (strerror (errorno)),
+ Vlocale_coding_system, 0);
+
while (1)
switch (errorno)
{
close_file_unwind (fd)
Lisp_Object fd;
{
- close (XFASTINT (fd));
+ emacs_close (XFASTINT (fd));
return Qnil;
}
Lisp_Object Qfile_name_as_directory;
Lisp_Object Qcopy_file;
Lisp_Object Qmake_directory_internal;
+Lisp_Object Qmake_directory;
Lisp_Object Qdelete_directory;
Lisp_Object Qdelete_file;
Lisp_Object Qrename_file;
Lisp_Object Qset_visited_file_modtime;
DEFUN ("find-file-name-handler", Ffind_file_name_handler, Sfind_file_name_handler, 2, 2, 0,
- "Return FILENAME's handler function for OPERATION, if it has one.\n\
-Otherwise, return nil.\n\
-A file name is handled if one of the regular expressions in\n\
-`file-name-handler-alist' matches it.\n\n\
-If OPERATION equals `inhibit-file-name-operation', then we ignore\n\
-any handlers that are members of `inhibit-file-name-handlers',\n\
-but we still do run any other handlers. This lets handlers\n\
-use the standard functions without calling themselves recursively.")
- (filename, operation)
- Lisp_Object filename, operation;
+ doc: /* Return FILENAME's handler function for OPERATION, if it has one.
+Otherwise, return nil.
+A file name is handled if one of the regular expressions in
+`file-name-handler-alist' matches it.
+
+If OPERATION equals `inhibit-file-name-operation', then we ignore
+any handlers that are members of `inhibit-file-name-handlers',
+but we still do run any other handlers. This lets handlers
+use the standard functions without calling themselves recursively. */)
+ (filename, operation)
+ Lisp_Object filename, operation;
{
/* This function must not munge the match data. */
- Lisp_Object chain, inhibited_handlers;
+ Lisp_Object chain, inhibited_handlers, result;
+ int pos = -1;
- CHECK_STRING (filename, 0);
+ result = Qnil;
+ CHECK_STRING (filename);
if (EQ (operation, Vinhibit_file_name_operation))
inhibited_handlers = Vinhibit_file_name_handlers;
inhibited_handlers = Qnil;
for (chain = Vfile_name_handler_alist; CONSP (chain);
- chain = XCONS (chain)->cdr)
+ chain = XCDR (chain))
{
Lisp_Object elt;
- elt = XCONS (chain)->car;
+ elt = XCAR (chain);
if (CONSP (elt))
{
Lisp_Object string;
- string = XCONS (elt)->car;
- if (STRINGP (string) && fast_string_match (string, filename) >= 0)
+ int match_pos;
+ string = XCAR (elt);
+ if (STRINGP (string)
+ && (match_pos = fast_string_match (string, filename)) > pos)
{
Lisp_Object handler, tem;
- handler = XCONS (elt)->cdr;
+ handler = XCDR (elt);
tem = Fmemq (handler, inhibited_handlers);
if (NILP (tem))
- return handler;
+ {
+ result = handler;
+ pos = match_pos;
+ }
}
}
QUIT;
}
- return Qnil;
+ return result;
}
\f
DEFUN ("file-name-directory", Ffile_name_directory, Sfile_name_directory,
- 1, 1, 0,
- "Return the directory component in file name FILENAME.\n\
-Return nil if FILENAME does not include a directory.\n\
-Otherwise return a directory spec.\n\
-Given a Unix syntax file name, returns a string ending in slash;\n\
-on VMS, perhaps instead a string ending in `:', `]' or `>'.")
- (filename)
+ 1, 1, 0,
+ doc: /* Return the directory component in file name FILENAME.
+Return nil if FILENAME does not include a directory.
+Otherwise return a directory spec.
+Given a Unix syntax file name, returns a string ending in slash;
+on VMS, perhaps instead a string ending in `:', `]' or `>'. */)
+ (filename)
Lisp_Object filename;
{
register unsigned char *beg;
register unsigned char *p;
Lisp_Object handler;
- CHECK_STRING (filename, 0);
+ CHECK_STRING (filename);
/* If the file name has special constructs in it,
call the corresponding file handler. */
DEFUN ("file-name-nondirectory", Ffile_name_nondirectory,
Sfile_name_nondirectory, 1, 1, 0,
- "Return file name FILENAME sans its directory.\n\
-For example, in a Unix-syntax file name,\n\
-this is everything after the last slash,\n\
-or the entire name if it contains no slash.")
- (filename)
+ doc: /* Return file name FILENAME sans its directory.
+For example, in a Unix-syntax file name,
+this is everything after the last slash,
+or the entire name if it contains no slash. */)
+ (filename)
Lisp_Object filename;
{
register unsigned char *beg, *p, *end;
Lisp_Object handler;
- CHECK_STRING (filename, 0);
+ CHECK_STRING (filename);
/* If the file name has special constructs in it,
call the corresponding file handler. */
DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory,
Sunhandled_file_name_directory, 1, 1, 0,
- "Return a directly usable directory name somehow associated with FILENAME.\n\
-A `directly usable' directory name is one that may be used without the\n\
-intervention of any file handler.\n\
-If FILENAME is a directly usable file itself, return\n\
-\(file-name-directory FILENAME).\n\
-The `call-process' and `start-process' functions use this function to\n\
-get a current directory to run processes in.")
- (filename)
- Lisp_Object filename;
+ doc: /* Return a directly usable directory name somehow associated with FILENAME.
+A `directly usable' directory name is one that may be used without the
+intervention of any file handler.
+If FILENAME is a directly usable file itself, return
+\(file-name-directory FILENAME).
+The `call-process' and `start-process' functions use this function to
+get a current directory to run processes in. */)
+ (filename)
+ Lisp_Object filename;
{
Lisp_Object handler;
DEFUN ("file-name-as-directory", Ffile_name_as_directory,
Sfile_name_as_directory, 1, 1, 0,
- "Return a string representing file FILENAME interpreted as a directory.\n\
-This operation exists because a directory is also a file, but its name as\n\
-a directory is different from its name as a file.\n\
-The result can be used as the value of `default-directory'\n\
-or passed as second argument to `expand-file-name'.\n\
-For a Unix-syntax file name, just appends a slash.\n\
-On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc.")
- (file)
+ doc: /* Return a string representing file FILENAME interpreted as a directory.
+This operation exists because a directory is also a file, but its name as
+a directory is different from its name as a file.
+The result can be used as the value of `default-directory'
+or passed as second argument to `expand-file-name'.
+For a Unix-syntax file name, just appends a slash.
+On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc. */)
+ (file)
Lisp_Object file;
{
char *buf;
Lisp_Object handler;
- CHECK_STRING (file, 0);
+ CHECK_STRING (file);
if (NILP (file))
return Qnil;
}
DEFUN ("directory-file-name", Fdirectory_file_name, Sdirectory_file_name,
- 1, 1, 0,
- "Returns the file name of the directory named DIRECTORY.\n\
-This is the name of the file that holds the data for the directory DIRECTORY.\n\
-This operation exists because a directory is also a file, but its name as\n\
-a directory is different from its name as a file.\n\
-In Unix-syntax, this function just removes the final slash.\n\
-On VMS, given a VMS-syntax directory name such as \"[X.Y]\",\n\
-it returns a file name such as \"[X]Y.DIR.1\".")
- (directory)
+ 1, 1, 0,
+ doc: /* Returns the file name of the directory named DIRECTORY.
+This is the name of the file that holds the data for the directory DIRECTORY.
+This operation exists because a directory is also a file, but its name as
+a directory is different from its name as a file.
+In Unix-syntax, this function just removes the final slash.
+On VMS, given a VMS-syntax directory name such as \"[X.Y]\",
+it returns a file name such as \"[X]Y.DIR.1\". */)
+ (directory)
Lisp_Object directory;
{
char *buf;
Lisp_Object handler;
- CHECK_STRING (directory, 0);
+ CHECK_STRING (directory);
if (NILP (directory))
return Qnil;
'w','x','y','z','0','1','2','3',
'4','5','6','7','8','9','-','_'
};
+
static unsigned make_temp_name_count, make_temp_name_count_initialized_p;
-DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0,
- "Generate temporary file name (string) starting with PREFIX (a string).\n\
-The Emacs process number forms part of the result,\n\
-so there is no danger of generating a name being used by another process.\n\
-\n\
-In addition, this function makes an attempt to choose a name\n\
-which has no existing file. To make this work,\n\
-PREFIX should be an absolute file name.")
- (prefix)
+/* Value is a temporary file name starting with PREFIX, a string.
+
+ The Emacs process number forms part of the result, so there is
+ no danger of generating a name being used by another process.
+ In addition, this function makes an attempt to choose a name
+ which has no existing file. To make this work, PREFIX should be
+ an absolute file name.
+
+ BASE64_P non-zero means add the pid as 3 characters in base64
+ encoding. In this case, 6 characters will be added to PREFIX to
+ form the file name. Otherwise, if Emacs is running on a system
+ with long file names, add the pid as a decimal number.
+
+ This function signals an error if no unique file name could be
+ generated. */
+
+Lisp_Object
+make_temp_name (prefix, base64_p)
Lisp_Object prefix;
+ int base64_p;
{
Lisp_Object val;
int len;
unsigned char *p, *data;
char pidbuf[20];
int pidlen;
-
- CHECK_STRING (prefix, 0);
+
+ CHECK_STRING (prefix);
/* VAL is created by adding 6 characters to PREFIX. The first
three are the PID of this process, in base 64, and the second
pid = (int) getpid ();
+ if (base64_p)
+ {
+ pidbuf[0] = make_temp_name_tbl[pid & 63], pid >>= 6;
+ pidbuf[1] = make_temp_name_tbl[pid & 63], pid >>= 6;
+ pidbuf[2] = make_temp_name_tbl[pid & 63], pid >>= 6;
+ pidlen = 3;
+ }
+ else
+ {
#ifdef HAVE_LONG_FILE_NAMES
- sprintf (pidbuf, "%d", pid);
- pidlen = strlen (pidbuf);
+ sprintf (pidbuf, "%d", pid);
+ pidlen = strlen (pidbuf);
#else
- pidbuf[0] = make_temp_name_tbl[pid & 63], pid >>= 6;
- pidbuf[1] = make_temp_name_tbl[pid & 63], pid >>= 6;
- pidbuf[2] = make_temp_name_tbl[pid & 63], pid >>= 6;
- pidlen = 3;
+ pidbuf[0] = make_temp_name_tbl[pid & 63], pid >>= 6;
+ pidbuf[1] = make_temp_name_tbl[pid & 63], pid >>= 6;
+ pidbuf[2] = make_temp_name_tbl[pid & 63], pid >>= 6;
+ pidlen = 3;
#endif
-
+ }
+
len = XSTRING (prefix)->size;
val = make_uninit_string (len + 3 + pidlen);
data = XSTRING (val)->data;
in looping through 225307 stat's, which is not only
dog-slow, but also useless since it will fallback to
the errow below, anyway. */
- report_file_error ("Cannot create temporary name for prefix `%s'",
+ report_file_error ("Cannot create temporary name for prefix",
Fcons (prefix, Qnil));
/* not reached */
}
return Qnil;
}
+
+DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0,
+ doc: /* Generate temporary file name (string) starting with PREFIX (a string).
+The Emacs process number forms part of the result,
+so there is no danger of generating a name being used by another process.
+
+In addition, this function makes an attempt to choose a name
+which has no existing file. To make this work,
+PREFIX should be an absolute file name.
+
+There is a race condition between calling `make-temp-name' and creating the
+file which opens all kinds of security holes. For that reason, you should
+probably use `make-temp-file' instead, except in three circumstances:
+
+* If you are creating the file in the user's home directory.
+* If you are creating a directory rather than an ordinary file.
+* If you are taking special precautions as `make-temp-file' does. */)
+ (prefix)
+ Lisp_Object prefix;
+{
+ return make_temp_name (prefix, 0);
+}
+
+
\f
DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
- "Convert filename NAME to absolute, and canonicalize it.\n\
-Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative\n\
- (does not start with slash); if DEFAULT-DIRECTORY is nil or missing,\n\
-the current buffer's value of default-directory is used.\n\
-File name components that are `.' are removed, and \n\
-so are file name components followed by `..', along with the `..' itself;\n\
-note that these simplifications are done without checking the resulting\n\
-file names in the file system.\n\
-An initial `~/' expands to your home directory.\n\
-An initial `~USER/' expands to USER's home directory.\n\
-See also the function `substitute-in-file-name'.")
- (name, default_directory)
+ doc: /* Convert filename NAME to absolute, and canonicalize it.
+Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative
+ (does not start with slash); if DEFAULT-DIRECTORY is nil or missing,
+the current buffer's value of default-directory is used.
+File name components that are `.' are removed, and
+so are file name components followed by `..', along with the `..' itself;
+note that these simplifications are done without checking the resulting
+file names in the file system.
+An initial `~/' expands to your home directory.
+An initial `~USER/' expands to USER's home directory.
+See also the function `substitute-in-file-name'. */)
+ (name, default_directory)
Lisp_Object name, default_directory;
{
unsigned char *nm;
int length;
Lisp_Object handler;
- CHECK_STRING (name, 0);
+ CHECK_STRING (name);
/* If the file name has special constructs in it,
call the corresponding file handler. */
if (NILP (default_directory))
default_directory = current_buffer->directory;
if (! STRINGP (default_directory))
- default_directory = build_string ("/");
+ {
+#ifdef DOS_NT
+ /* "/" is not considered a root directory on DOS_NT, so using "/"
+ here causes an infinite recursion in, e.g., the following:
+
+ (let (default-directory)
+ (expand-file-name "a"))
+
+ To avoid this, we set default_directory to the root of the
+ current drive. */
+ extern char *emacs_root_dir (void);
+
+ default_directory = build_string (emacs_root_dir ());
+#else
+ default_directory = build_string ("/");
+#endif
+ }
if (!NILP (default_directory))
{
}
#endif
- /* If nm is absolute, look for /./ or /../ sequences; if none are
- found, we can probably return right away. We will avoid allocating
- a new string if name is already fully expanded. */
+ /* If nm is absolute, look for `/./' or `/../' or `//''sequences; if
+ none are found, we can probably return right away. We will avoid
+ allocating a new string if name is already fully expanded. */
if (
IS_DIRECTORY_SEP (nm[0])
#ifdef MSDOS
|| (p[2] == '.' && (IS_DIRECTORY_SEP (p[3])
|| p[3] == 0))))
lose = 1;
+ /* We want to replace multiple `/' in a row with a single
+ slash. */
+ else if (p > nm
+ && IS_DIRECTORY_SEP (p[0])
+ && IS_DIRECTORY_SEP (p[1]))
+ lose = 1;
+
#ifdef VMS
if (p[0] == '\\')
lose = 1;
/* ASSERT (IS_DIRECTORY_SEP (target[0])) if not VMS */
- /* Now canonicalize by removing /. and /foo/.. if they appear. */
+ /* Now canonicalize by removing `//', `/.' and `/foo/..' if they
+ appear. */
p = target;
o = target;
++o;
p += 3;
}
+ else if (p > target
+ && IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1]))
+ {
+ /* Collapse multiple `/' in a row. */
+ *o++ = *p++;
+ while (IS_DIRECTORY_SEP (*p))
+ ++p;
+ }
else
{
*o++ = *p++;
}
#if 0
+/* PLEASE DO NOT DELETE THIS COMMENTED-OUT VERSION!
+ This is the old version of expand-file-name, before it was thoroughly
+ rewritten for Emacs 10.31. We leave this version here commented-out,
+ because the code is very complex and likely to have subtle bugs. If
+ bugs _are_ found, it might be of interest to look at the old code and
+ see what did it do in the relevant situation.
+
+ Don't remove this code: it's true that it will be accessible via CVS,
+ but a few years from deletion, people will forget it is there. */
+
/* Changed this DEFUN to a DEAFUN, so as not to confuse `make-docfile'. */
DEAFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
"Convert FILENAME to absolute, and canonicalize it.\n\
int dots = 0;
#endif /* VMS */
- CHECK_STRING (name, 0);
+ CHECK_STRING (name);
#ifdef VMS
/* Filenames on VMS are always upper case. */
{
if (NILP (defalt))
defalt = current_buffer->directory;
- CHECK_STRING (defalt, 1);
+ CHECK_STRING (defalt);
newdir = XSTRING (defalt)->data;
}
#endif
\f
DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name,
- Ssubstitute_in_file_name, 1, 1, 0,
- "Substitute environment variables referred to in FILENAME.\n\
-`$FOO' where FOO is an environment variable name means to substitute\n\
-the value of that variable. The variable name should be terminated\n\
-with a character not a letter, digit or underscore; otherwise, enclose\n\
-the entire variable name in braces.\n\
-If `/~' appears, all of FILENAME through that `/' is discarded.\n\n\
-On VMS, `$' substitution is not done; this function does little and only\n\
-duplicates what `expand-file-name' does.")
- (filename)
+ Ssubstitute_in_file_name, 1, 1, 0,
+ doc: /* Substitute environment variables referred to in FILENAME.
+`$FOO' where FOO is an environment variable name means to substitute
+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 `/~' appears, all of FILENAME through that `/' is discarded.
+
+On VMS, `$' substitution is not done; this function does little and only
+duplicates what `expand-file-name' does. */)
+ (filename)
Lisp_Object filename;
{
unsigned char *nm;
register unsigned char *s, *p, *o, *x, *endp;
- unsigned char *target;
+ unsigned char *target = NULL;
int total = 0;
int substituted = 0;
unsigned char *xnm;
+ struct passwd *pw;
Lisp_Object handler;
- CHECK_STRING (filename, 0);
+ CHECK_STRING (filename);
/* If the file name has special constructs in it,
call the corresponding file handler. */
#endif /* VMS */
|| IS_DIRECTORY_SEP (p[-1])))
{
- nm = p;
- substituted = 1;
+ for (s = p; *s && (!IS_DIRECTORY_SEP (*s)
+#ifdef VMS
+ && *s != ':'
+#endif /* VMS */
+ ); s++);
+ if (p[0] == '~' && s > p + 1) /* we've got "/~something/" */
+ {
+ o = (unsigned char *) alloca (s - p + 1);
+ bcopy ((char *) p, o, s - p);
+ o [s - p] = 0;
+
+ pw = (struct passwd *) getpwnam (o + 1);
+ }
+ /* If we have ~/ or ~user and `user' exists, discard
+ everything up to ~. But if `user' does not exist, leave
+ ~user alone, it might be a literal file name. */
+ if (IS_DIRECTORY_SEP (p[0]) || s == p + 1 || pw)
+ {
+ nm = p;
+ substituted = 1;
+ }
}
#ifdef DOS_NT
/* see comment in expand-file-name about drive specifiers */
/* Get variable value */
o = (unsigned char *) egetenv (target);
- if (!o) goto badvar;
- total += strlen (o);
- substituted = 1;
+ if (o)
+ {
+ total += strlen (o);
+ substituted = 1;
+ }
+ else if (*p == '}')
+ goto badvar;
}
if (!substituted)
/* Get variable value */
o = (unsigned char *) egetenv (target);
if (!o)
- goto badvar;
-
- if (STRING_MULTIBYTE (filename))
+ {
+ *x++ = '$';
+ strcpy (x, target); x+= strlen (target);
+ }
+ else if (STRING_MULTIBYTE (filename))
{
/* If the original string is multibyte,
convert what we substitute into multibyte. */
- unsigned char workbuf[4], *str;
- int len;
-
while (*o)
{
- int c = *o++;
- c = unibyte_char_to_multibyte (c);
- if (! SINGLE_BYTE_CHAR_P (c))
- {
- len = CHAR_STRING (c, workbuf, str);
- bcopy (str, x, len);
- x += len;
- }
- else
- *x++ = c;
+ int c = unibyte_char_to_multibyte (*o++);
+ x += CHAR_STRING (c, x);
}
}
else
/* NOTREACHED */
#endif /* not VMS */
+ return Qnil;
}
\f
/* A slightly faster and more convenient way to get
}
DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 4,
- "fCopy file: \nFCopy %s to file: \np\nP",
- "Copy FILE to NEWNAME. Both args must be strings.\n\
-Signals a `file-already-exists' error if file NEWNAME already exists,\n\
-unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.\n\
-A number as third arg means request confirmation if NEWNAME already exists.\n\
-This is what happens in interactive use with M-x.\n\
-Fourth arg KEEP-TIME non-nil means give the new file the same\n\
-last-modified time as the old one. (This works on only some systems.)\n\
-A prefix arg makes KEEP-TIME non-nil.")
- (file, newname, ok_if_already_exists, keep_date)
- Lisp_Object file, newname, ok_if_already_exists, keep_date;
+ "fCopy file: \nFCopy %s to file: \np\nP",
+ doc: /* Copy FILE to NEWNAME. Both args must be strings.
+If NEWNAME names a directory, copy FILE there.
+Signals a `file-already-exists' error if file NEWNAME already exists,
+unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.
+A number as third arg means request confirmation if NEWNAME already exists.
+This is what happens in interactive use with M-x.
+Fourth arg KEEP-TIME non-nil means give the new file the same
+last-modified time as the old one. (This works on only some systems.)
+A prefix arg makes KEEP-TIME non-nil. */)
+ (file, newname, ok_if_already_exists, keep_time)
+ Lisp_Object file, newname, ok_if_already_exists, keep_time;
{
int ifd, ofd, n;
char buf[16 * 1024];
encoded_file = encoded_newname = Qnil;
GCPRO4 (file, newname, encoded_file, encoded_newname);
- CHECK_STRING (file, 0);
- CHECK_STRING (newname, 1);
+ CHECK_STRING (file);
+ CHECK_STRING (newname);
+
+ if (!NILP (Ffile_directory_p (newname)))
+ newname = Fexpand_file_name (file, newname);
+ else
+ newname = Fexpand_file_name (newname, Qnil);
file = Fexpand_file_name (file, Qnil);
- newname = Fexpand_file_name (newname, Qnil);
/* If the input file name has special constructs in it,
call the corresponding file handler. */
handler = Ffind_file_name_handler (newname, Qcopy_file);
if (!NILP (handler))
RETURN_UNGCPRO (call5 (handler, Qcopy_file, file, newname,
- ok_if_already_exists, keep_date));
+ ok_if_already_exists, keep_time));
encoded_file = ENCODE_FILE (file);
encoded_newname = ENCODE_FILE (newname);
else if (stat (XSTRING (encoded_newname)->data, &out_st) < 0)
out_st.st_mode = 0;
- ifd = open (XSTRING (encoded_file)->data, O_RDONLY);
+#ifdef WINDOWSNT
+ if (!CopyFile (XSTRING (encoded_file)->data,
+ XSTRING (encoded_newname)->data,
+ FALSE))
+ report_file_error ("Copying file", Fcons (file, Fcons (newname, Qnil)));
+ else if (NILP (keep_time))
+ {
+ EMACS_TIME now;
+ DWORD attributes;
+ char * filename;
+
+ EMACS_GET_TIME (now);
+ filename = XSTRING (encoded_newname)->data;
+
+ /* Ensure file is writable while its modified time is set. */
+ attributes = GetFileAttributes (filename);
+ SetFileAttributes (filename, attributes & ~FILE_ATTRIBUTE_READONLY);
+ if (set_file_times (filename, now, now))
+ {
+ /* Restore original attributes. */
+ SetFileAttributes (filename, attributes);
+ Fsignal (Qfile_date_error,
+ Fcons (build_string ("Cannot set file date"),
+ Fcons (newname, Qnil)));
+ }
+ /* Restore original attributes. */
+ SetFileAttributes (filename, attributes);
+ }
+#else /* not WINDOWSNT */
+ ifd = emacs_open (XSTRING (encoded_file)->data, O_RDONLY, 0);
if (ifd < 0)
report_file_error ("Opening input file", Fcons (file, Qnil));
immediate_quit = 1;
QUIT;
- while ((n = read (ifd, buf, sizeof buf)) > 0)
- if (write (ofd, buf, n) != n)
+ while ((n = emacs_read (ifd, buf, sizeof buf)) > 0)
+ if (emacs_write (ofd, buf, n) != n)
report_file_error ("I/O error", Fcons (newname, Qnil));
immediate_quit = 0;
/* Closing the output clobbers the file times on some systems. */
- if (close (ofd) < 0)
+ if (emacs_close (ofd) < 0)
report_file_error ("I/O error", Fcons (newname, Qnil));
if (input_file_statable_p)
{
- if (!NILP (keep_date))
+ if (!NILP (keep_time))
{
EMACS_TIME atime, mtime;
EMACS_SET_SECS_USECS (atime, st.st_atime, 0);
#endif /* MSDOS */
}
- close (ifd);
+ emacs_close (ifd);
+#endif /* WINDOWSNT */
/* Discard the unwind protects. */
specpdl_ptr = specpdl + count;
\f
DEFUN ("make-directory-internal", Fmake_directory_internal,
Smake_directory_internal, 1, 1, 0,
- "Create a new directory named DIRECTORY.")
- (directory)
+ doc: /* Create a new directory named DIRECTORY. */)
+ (directory)
Lisp_Object directory;
{
unsigned char *dir;
Lisp_Object handler;
Lisp_Object encoded_dir;
- CHECK_STRING (directory, 0);
+ CHECK_STRING (directory);
directory = Fexpand_file_name (directory, Qnil);
handler = Ffind_file_name_handler (directory, Qmake_directory_internal);
}
DEFUN ("delete-directory", Fdelete_directory, Sdelete_directory, 1, 1, "FDelete directory: ",
- "Delete the directory named DIRECTORY.")
- (directory)
+ doc: /* Delete the directory named DIRECTORY. */)
+ (directory)
Lisp_Object directory;
{
unsigned char *dir;
Lisp_Object handler;
Lisp_Object encoded_dir;
- CHECK_STRING (directory, 0);
+ CHECK_STRING (directory);
directory = Fdirectory_file_name (Fexpand_file_name (directory, Qnil));
handler = Ffind_file_name_handler (directory, Qdelete_directory);
}
DEFUN ("delete-file", Fdelete_file, Sdelete_file, 1, 1, "fDelete file: ",
- "Delete file named FILENAME.\n\
-If file has multiple names, it continues to exist with the other names.")
- (filename)
+ doc: /* Delete file named FILENAME.
+If file has multiple names, it continues to exist with the other names. */)
+ (filename)
Lisp_Object filename;
{
Lisp_Object handler;
Lisp_Object encoded_file;
- CHECK_STRING (filename, 0);
+ CHECK_STRING (filename);
filename = Fexpand_file_name (filename, Qnil);
handler = Ffind_file_name_handler (filename, Qdelete_file);
}
\f
DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
- "fRename file: \nFRename %s to file: \np",
- "Rename FILE as NEWNAME. Both args strings.\n\
-If file has names other than FILE, it continues to have those names.\n\
-Signals a `file-already-exists' error if a file NEWNAME already exists\n\
-unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
-A number as third arg means request confirmation if NEWNAME already exists.\n\
-This is what happens in interactive use with M-x.")
- (file, newname, ok_if_already_exists)
+ "fRename file: \nFRename %s to file: \np",
+ doc: /* Rename FILE as NEWNAME. Both args strings.
+If file has names other than FILE, it continues to have those names.
+Signals a `file-already-exists' error if a file NEWNAME already exists
+unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.
+A number as third arg means request confirmation if NEWNAME already exists.
+This is what happens in interactive use with M-x. */)
+ (file, newname, ok_if_already_exists)
Lisp_Object file, newname, ok_if_already_exists;
{
#ifdef NO_ARG_ARRAY
encoded_file = encoded_newname = Qnil;
GCPRO4 (file, newname, encoded_file, encoded_newname);
- CHECK_STRING (file, 0);
- CHECK_STRING (newname, 1);
+ CHECK_STRING (file);
+ CHECK_STRING (newname);
file = Fexpand_file_name (file, Qnil);
newname = Fexpand_file_name (newname, Qnil);
encoded_file = ENCODE_FILE (file);
encoded_newname = ENCODE_FILE (newname);
+#ifdef DOS_NT
+ /* If the file names are identical but for the case, don't ask for
+ confirmation: they simply want to change the letter-case of the
+ file name. */
+ if (NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname))))
+#endif
if (NILP (ok_if_already_exists)
|| INTEGERP (ok_if_already_exists))
barf_or_query_if_file_exists (encoded_newname, "rename to it",
}
DEFUN ("add-name-to-file", Fadd_name_to_file, Sadd_name_to_file, 2, 3,
- "fAdd name to file: \nFName to add to %s: \np",
- "Give FILE additional name NEWNAME. Both args strings.\n\
-Signals a `file-already-exists' error if a file NEWNAME already exists\n\
-unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
-A number as third arg means request confirmation if NEWNAME already exists.\n\
-This is what happens in interactive use with M-x.")
- (file, newname, ok_if_already_exists)
+ "fAdd name to file: \nFName to add to %s: \np",
+ doc: /* Give FILE additional name NEWNAME. Both args strings.
+Signals a `file-already-exists' error if a file NEWNAME already exists
+unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.
+A number as third arg means request confirmation if NEWNAME already exists.
+This is what happens in interactive use with M-x. */)
+ (file, newname, ok_if_already_exists)
Lisp_Object file, newname, ok_if_already_exists;
{
#ifdef NO_ARG_ARRAY
GCPRO4 (file, newname, encoded_file, encoded_newname);
encoded_file = encoded_newname = Qnil;
- CHECK_STRING (file, 0);
- CHECK_STRING (newname, 1);
+ CHECK_STRING (file);
+ CHECK_STRING (newname);
file = Fexpand_file_name (file, Qnil);
newname = Fexpand_file_name (newname, Qnil);
#ifdef S_IFLNK
DEFUN ("make-symbolic-link", Fmake_symbolic_link, Smake_symbolic_link, 2, 3,
- "FMake symbolic link to file: \nFMake symbolic link to file %s: \np",
- "Make a symbolic link to FILENAME, named LINKNAME. Both args strings.\n\
-Signals a `file-already-exists' error if a file LINKNAME already exists\n\
-unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
-A number as third arg means request confirmation if LINKNAME already exists.\n\
-This happens for interactive use with M-x.")
- (filename, linkname, ok_if_already_exists)
+ "FMake symbolic link to file: \nFMake symbolic link to file %s: \np",
+ doc: /* Make a symbolic link to FILENAME, named LINKNAME. Both args strings.
+Signals a `file-already-exists' error if a file LINKNAME already exists
+unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.
+A number as third arg means request confirmation if LINKNAME already exists.
+This happens for interactive use with M-x. */)
+ (filename, linkname, ok_if_already_exists)
Lisp_Object filename, linkname, ok_if_already_exists;
{
#ifdef NO_ARG_ARRAY
GCPRO4 (filename, linkname, encoded_filename, encoded_linkname);
encoded_filename = encoded_linkname = Qnil;
- CHECK_STRING (filename, 0);
- CHECK_STRING (linkname, 1);
+ CHECK_STRING (filename);
+ CHECK_STRING (linkname);
/* If the link target has a ~, we must expand it to get
a truly valid file name. Otherwise, do not expand;
we want to permit links to relative file names. */
DEFUN ("define-logical-name", Fdefine_logical_name, Sdefine_logical_name,
2, 2, "sDefine logical name: \nsDefine logical name %s as: ",
- "Define the job-wide logical name NAME to have the value STRING.\n\
-If STRING is nil or a null string, the logical name NAME is deleted.")
- (name, string)
+ doc: /* Define the job-wide logical name NAME to have the value STRING.
+If STRING is nil or a null string, the logical name NAME is deleted. */)
+ (name, string)
Lisp_Object name;
Lisp_Object string;
{
- CHECK_STRING (name, 0);
+ CHECK_STRING (name);
if (NILP (string))
delete_logical_name (XSTRING (name)->data);
else
{
- CHECK_STRING (string, 1);
+ CHECK_STRING (string);
if (XSTRING (string)->size == 0)
delete_logical_name (XSTRING (name)->data);
#ifdef HPUX_NET
DEFUN ("sysnetunam", Fsysnetunam, Ssysnetunam, 2, 2, 0,
- "Open a network connection to PATH using LOGIN as the login string.")
+ doc: /* Open a network connection to PATH using LOGIN as the login string. */)
(path, login)
Lisp_Object path, login;
{
int netresult;
- CHECK_STRING (path, 0);
- CHECK_STRING (login, 0);
+ CHECK_STRING (path);
+ CHECK_STRING (login);
netresult = netunam (XSTRING (path)->data, XSTRING (login)->data);
\f
DEFUN ("file-name-absolute-p", Ffile_name_absolute_p, Sfile_name_absolute_p,
1, 1, 0,
- "Return t if file FILENAME specifies an absolute file name.\n\
-On Unix, this is a name starting with a `/' or a `~'.")
+ doc: /* Return t if file FILENAME specifies an absolute file name.
+On Unix, this is a name starting with a `/' or a `~'. */)
(filename)
Lisp_Object filename;
{
unsigned char *ptr;
- CHECK_STRING (filename, 0);
+ CHECK_STRING (filename);
ptr = XSTRING (filename)->data;
if (IS_DIRECTORY_SEP (*ptr) || *ptr == '~'
#ifdef VMS
}
DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0,
- "Return t if file FILENAME exists. (This does not mean you can read it.)\n\
-See also `file-readable-p' and `file-attributes'.")
- (filename)
+ doc: /* Return t if file FILENAME exists. (This does not mean you can read it.)
+See also `file-readable-p' and `file-attributes'. */)
+ (filename)
Lisp_Object filename;
{
Lisp_Object absname;
Lisp_Object handler;
struct stat statbuf;
- CHECK_STRING (filename, 0);
+ CHECK_STRING (filename);
absname = Fexpand_file_name (filename, Qnil);
/* If the file name has special constructs in it,
}
DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
- "Return t if FILENAME can be executed by you.\n\
-For a directory, this means you can access files in that directory.")
- (filename)
- Lisp_Object filename;
-
+ doc: /* Return t if FILENAME can be executed by you.
+For a directory, this means you can access files in that directory. */)
+ (filename)
+ Lisp_Object filename;
{
Lisp_Object absname;
Lisp_Object handler;
- CHECK_STRING (filename, 0);
+ CHECK_STRING (filename);
absname = Fexpand_file_name (filename, Qnil);
/* If the file name has special constructs in it,
}
DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0,
- "Return t if file FILENAME exists and you can read it.\n\
-See also `file-exists-p' and `file-attributes'.")
- (filename)
+ doc: /* Return t if file FILENAME exists and you can read it.
+See also `file-exists-p' and `file-attributes'. */)
+ (filename)
Lisp_Object filename;
{
Lisp_Object absname;
int flags;
struct stat statbuf;
- CHECK_STRING (filename, 0);
+ CHECK_STRING (filename);
absname = Fexpand_file_name (filename, Qnil);
/* If the file name has special constructs in it,
absname = ENCODE_FILE (absname);
-#ifdef DOS_NT
- /* Under MS-DOS and Windows, open does not work for directories. */
+#if defined(DOS_NT) || defined(macintosh)
+ /* Under MS-DOS, Windows, and Macintosh, open does not work for
+ directories. */
if (access (XSTRING (absname)->data, 0) == 0)
return Qt;
return Qnil;
-#else /* not DOS_NT */
+#else /* not DOS_NT and not macintosh */
flags = O_RDONLY;
#if defined (S_ISFIFO) && defined (O_NONBLOCK)
/* Opening a fifo without O_NONBLOCK can wait.
if (S_ISFIFO (statbuf.st_mode))
flags |= O_NONBLOCK;
#endif
- desc = open (XSTRING (absname)->data, flags);
+ desc = emacs_open (XSTRING (absname)->data, flags, 0);
if (desc < 0)
return Qnil;
- close (desc);
+ emacs_close (desc);
return Qt;
-#endif /* not DOS_NT */
+#endif /* not DOS_NT and not macintosh */
}
/* Having this before file-symlink-p mysteriously caused it to be forgotten
on the RT/PC. */
DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
- "Return t if file FILENAME can be written or created by you.")
- (filename)
+ doc: /* Return t if file FILENAME can be written or created by you. */)
+ (filename)
Lisp_Object filename;
{
Lisp_Object absname, dir, encoded;
Lisp_Object handler;
struct stat statbuf;
- CHECK_STRING (filename, 0);
+ CHECK_STRING (filename);
absname = Fexpand_file_name (filename, Qnil);
/* If the file name has special constructs in it,
#endif /* MSDOS */
dir = ENCODE_FILE (dir);
+#ifdef WINDOWSNT
+ /* The read-only attribute of the parent directory doesn't affect
+ whether a file or directory can be created within it. Some day we
+ should check ACLs though, which do affect this. */
+ if (stat (XSTRING (dir)->data, &statbuf) < 0)
+ return Qnil;
+ return (statbuf.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil;
+#else
return (check_writable (!NILP (dir) ? (char *) XSTRING (dir)->data : "")
? Qt : Qnil);
+#endif
}
\f
DEFUN ("access-file", Faccess_file, Saccess_file, 2, 2, 0,
- "Access file FILENAME, and get an error if that does not work.\n\
-The second argument STRING is used in the error message.\n\
-If there is no error, we return nil.")
- (filename, string)
+ doc: /* Access file FILENAME, and get an error if that does not work.
+The second argument STRING is used in the error message.
+If there is no error, we return nil. */)
+ (filename, string)
Lisp_Object filename, string;
{
- Lisp_Object handler, encoded_filename;
+ Lisp_Object handler, encoded_filename, absname;
int fd;
- CHECK_STRING (filename, 0);
- CHECK_STRING (string, 1);
+ CHECK_STRING (filename);
+ absname = Fexpand_file_name (filename, Qnil);
+
+ CHECK_STRING (string);
/* If the file name has special constructs in it,
call the corresponding file handler. */
- handler = Ffind_file_name_handler (filename, Qaccess_file);
+ handler = Ffind_file_name_handler (absname, Qaccess_file);
if (!NILP (handler))
- return call3 (handler, Qaccess_file, filename, string);
+ return call3 (handler, Qaccess_file, absname, string);
- encoded_filename = ENCODE_FILE (filename);
+ encoded_filename = ENCODE_FILE (absname);
- fd = open (XSTRING (encoded_filename)->data, O_RDONLY);
+ fd = emacs_open (XSTRING (encoded_filename)->data, O_RDONLY, 0);
if (fd < 0)
report_file_error (XSTRING (string)->data, Fcons (filename, Qnil));
- close (fd);
+ emacs_close (fd);
return Qnil;
}
\f
DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0,
- "Return non-nil if file FILENAME is the name of a symbolic link.\n\
-The value is the name of the file to which it is linked.\n\
-Otherwise returns nil.")
- (filename)
+ doc: /* Return non-nil if file FILENAME is the name of a symbolic link.
+The value is the name of the file to which it is linked.
+Otherwise returns nil. */)
+ (filename)
Lisp_Object filename;
{
#ifdef S_IFLNK
Lisp_Object val;
Lisp_Object handler;
- CHECK_STRING (filename, 0);
+ CHECK_STRING (filename);
filename = Fexpand_file_name (filename, Qnil);
/* If the file name has special constructs in it,
filename = ENCODE_FILE (filename);
- bufsize = 100;
- while (1)
+ bufsize = 50;
+ buf = NULL;
+ do
{
- buf = (char *) xmalloc (bufsize);
+ bufsize *= 2;
+ buf = (char *) xrealloc (buf, bufsize);
bzero (buf, bufsize);
+
+ errno = 0;
valsize = readlink (XSTRING (filename)->data, buf, bufsize);
- if (valsize < bufsize) break;
- /* Buffer was not long enough */
- xfree (buf);
- bufsize *= 2;
- }
- if (valsize == -1)
- {
- xfree (buf);
- return Qnil;
+ if (valsize == -1)
+ {
+#ifdef ERANGE
+ /* HP-UX reports ERANGE if buffer is too small. */
+ if (errno == ERANGE)
+ valsize = bufsize;
+ else
+#endif
+ {
+ xfree (buf);
+ return Qnil;
+ }
+ }
}
+ while (valsize >= bufsize);
+
val = make_string (buf, valsize);
+ if (buf[0] == '/' && index (buf, ':'))
+ val = concat2 (build_string ("/:"), val);
xfree (buf);
val = DECODE_FILE (val);
return val;
}
DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0,
- "Return t if FILENAME names an existing directory.\n\
-Symbolic links to directories count as directories.\n\
-See `file-symlink-p' to distinguish symlinks.")
- (filename)
+ doc: /* Return t if FILENAME names an existing directory.
+Symbolic links to directories count as directories.
+See `file-symlink-p' to distinguish symlinks. */)
+ (filename)
Lisp_Object filename;
{
register Lisp_Object absname;
}
DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p, Sfile_accessible_directory_p, 1, 1, 0,
- "Return t if file FILENAME is the name of a directory as a file,\n\
-and files in that directory can be opened by you. In order to use a\n\
-directory as a buffer's current directory, this predicate must return true.\n\
-A directory name spec may be given instead; then the value is t\n\
-if the directory so specified exists and really is a readable and\n\
-searchable directory.")
- (filename)
+ doc: /* Return t if file 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. */)
+ (filename)
Lisp_Object filename;
{
Lisp_Object handler;
}
DEFUN ("file-regular-p", Ffile_regular_p, Sfile_regular_p, 1, 1, 0,
- "Return t if file FILENAME is the name of a regular file.\n\
-This is the sort of file that holds an ordinary stream of data bytes.")
- (filename)
+ doc: /* Return t if file FILENAME is the name of a regular file.
+This is the sort of file that holds an ordinary stream of data bytes. */)
+ (filename)
Lisp_Object filename;
{
register Lisp_Object absname;
}
\f
DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
- "Return mode bits of file named FILENAME, as an integer.")
- (filename)
+ doc: /* Return mode bits of file named FILENAME, as an integer. */)
+ (filename)
Lisp_Object filename;
{
Lisp_Object absname;
}
DEFUN ("set-file-modes", Fset_file_modes, Sset_file_modes, 2, 2, 0,
- "Set mode bits of file named FILENAME to MODE (an integer).\n\
-Only the 12 low bits of MODE are used.")
+ doc: /* Set mode bits of file named FILENAME to MODE (an integer).
+Only the 12 low bits of MODE are used. */)
(filename, mode)
Lisp_Object filename, mode;
{
Lisp_Object handler;
absname = Fexpand_file_name (filename, current_buffer->directory);
- CHECK_NUMBER (mode, 1);
+ CHECK_NUMBER (mode);
/* If the file name has special constructs in it,
call the corresponding file handler. */
}
DEFUN ("set-default-file-modes", Fset_default_file_modes, Sset_default_file_modes, 1, 1, 0,
- "Set the file permission bits for newly created files.\n\
-The argument MODE should be an integer; only the low 9 bits are used.\n\
-This setting is inherited by subprocesses.")
- (mode)
+ doc: /* Set the file permission bits for newly created files.
+The argument MODE should be an integer; only the low 9 bits are used.
+This setting is inherited by subprocesses. */)
+ (mode)
Lisp_Object mode;
{
- CHECK_NUMBER (mode, 0);
+ CHECK_NUMBER (mode);
umask ((~ XINT (mode)) & 0777);
}
DEFUN ("default-file-modes", Fdefault_file_modes, Sdefault_file_modes, 0, 0, 0,
- "Return the default file protection for created files.\n\
-The value is an integer.")
- ()
+ doc: /* Return the default file protection for created files.
+The value is an integer. */)
+ ()
{
int realmask;
Lisp_Object value;
XSETINT (value, (~ realmask) & 0777);
return value;
}
+
\f
-#ifdef unix
+#ifdef __NetBSD__
+#define unix 42
+#endif
+#ifdef unix
DEFUN ("unix-sync", Funix_sync, Sunix_sync, 0, 0, "",
- "Tell Unix to finish all pending disk updates.")
- ()
+ doc: /* Tell Unix to finish all pending disk updates. */)
+ ()
{
sync ();
return Qnil;
#endif /* unix */
DEFUN ("file-newer-than-file-p", Ffile_newer_than_file_p, Sfile_newer_than_file_p, 2, 2, 0,
- "Return t if file FILE1 is newer than file FILE2.\n\
-If FILE1 does not exist, the answer is nil;\n\
-otherwise, if FILE2 does not exist, the answer is t.")
- (file1, file2)
+ doc: /* Return t if file FILE1 is newer than file FILE2.
+If FILE1 does not exist, the answer is nil;
+otherwise, if FILE2 does not exist, the answer is t. */)
+ (file1, file2)
Lisp_Object file1, file2;
{
Lisp_Object absname1, absname2;
Lisp_Object handler;
struct gcpro gcpro1, gcpro2;
- CHECK_STRING (file1, 0);
- CHECK_STRING (file2, 0);
+ CHECK_STRING (file1);
+ CHECK_STRING (file2);
absname1 = Qnil;
GCPRO2 (absname1, file2);
#define READ_BUF_SIZE (64 << 10)
#endif
-/* This function is called when a function bound to
- Vset_auto_coding_function causes some error. At that time, a text
- of a file has already been inserted in the current buffer, but,
- markers has not yet been adjusted. Thus we must adjust markers
- here. We are sure that the buffer was empty before the text of the
- file was inserted. */
+extern void adjust_markers_for_delete P_ ((int, int, int, int));
+
+/* This function is called after Lisp functions to decide a coding
+ system are called, or when they cause an error. Before they are
+ called, the current buffer is set unibyte and it contains only a
+ newly inserted text (thus the buffer was empty before the
+ insertion).
+
+ The functions may set markers, overlays, text properties, or even
+ alter the buffer contents, change the current buffer.
+
+ Here, we reset all those changes by:
+ o set back the current buffer.
+ o move all markers and overlays to BEG.
+ o remove all text properties.
+ o set back the buffer multibyteness. */
static Lisp_Object
-set_auto_coding_unwind (multibyte)
- Lisp_Object multibyte;
+decide_coding_unwind (unwind_data)
+ Lisp_Object unwind_data;
{
- int inserted = Z_BYTE - BEG_BYTE;
+ Lisp_Object multibyte, undo_list, buffer;
+
+ multibyte = XCAR (unwind_data);
+ unwind_data = XCDR (unwind_data);
+ undo_list = XCAR (unwind_data);
+ buffer = XCDR (unwind_data);
+
+ if (current_buffer != XBUFFER (buffer))
+ set_buffer_internal (XBUFFER (buffer));
+ adjust_markers_for_delete (BEG, BEG_BYTE, Z, Z_BYTE);
+ adjust_overlays_for_delete (BEG, Z - BEG);
+ BUF_INTERVALS (current_buffer) = 0;
+ TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
- if (!NILP (multibyte))
- inserted = multibyte_chars_in_text (GPT_ADDR - inserted, inserted);
- adjust_after_insert (PT, PT_BYTE, Z, Z_BYTE, inserted);
+ /* Now we are safe to change the buffer's multibyteness directly. */
+ current_buffer->enable_multibyte_characters = multibyte;
+ current_buffer->undo_list = undo_list;
return Qnil;
}
+
+/* Used to pass values from insert-file-contents to read_non_regular. */
+
+static int non_regular_fd;
+static int non_regular_inserted;
+static int non_regular_nbytes;
+
+
+/* Read from a non-regular file.
+ Read non_regular_trytry bytes max from non_regular_fd.
+ Non_regular_inserted specifies where to put the read bytes.
+ Value is the number of bytes read. */
+
+static Lisp_Object
+read_non_regular ()
+{
+ int nbytes;
+
+ immediate_quit = 1;
+ QUIT;
+ nbytes = emacs_read (non_regular_fd,
+ BEG_ADDR + PT_BYTE - 1 + non_regular_inserted,
+ non_regular_nbytes);
+ immediate_quit = 0;
+ return make_number (nbytes);
+}
+
+
+/* Condition-case handler used when reading from non-regular files
+ in insert-file-contents. */
+
+static Lisp_Object
+read_non_regular_quit ()
+{
+ return Qnil;
+}
+
+
DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
- 1, 5, 0,
- "Insert contents of file FILENAME after point.\n\
-Returns list of absolute file name and number of bytes inserted.\n\
-If second argument VISIT is non-nil, the buffer's visited filename\n\
-and last save file modtime are set, and it is marked unmodified.\n\
-If visiting and the file does not exist, visiting is completed\n\
-before the error is signaled.\n\
-The optional third and fourth arguments BEG and END\n\
-specify what portion of the file to insert.\n\
-These arguments count bytes in the file, not characters in the buffer.\n\
-If VISIT is non-nil, BEG and END must be nil.\n\
-\n\
-If optional fifth argument REPLACE is non-nil,\n\
-it means replace the current buffer contents (in the accessible portion)\n\
-with the file contents. This is better than simply deleting and inserting\n\
-the whole thing because (1) it preserves some marker positions\n\
-and (2) it puts less data in the undo list.\n\
-When REPLACE is non-nil, the value is the number of characters actually read,\n\
-which is often less than the number of characters to be read.\n\
-\n\
-This does code conversion according to the value of\n\
-`coding-system-for-read' or `file-coding-system-alist',\n\
-and sets the variable `last-coding-system-used' to the coding system\n\
-actually used.")
- (filename, visit, beg, end, replace)
+ 1, 5, 0,
+ doc: /* Insert contents of file FILENAME after point.
+Returns list of absolute file name and number of bytes inserted.
+If second argument VISIT is non-nil, the buffer's visited filename
+and last save file modtime are set, and it is marked unmodified.
+If visiting and the file does not exist, visiting is completed
+before the error is signaled.
+The optional third and fourth arguments BEG and END
+specify what portion of the file to insert.
+These arguments count bytes in the file, not characters in the buffer.
+If VISIT is non-nil, BEG and END must be nil.
+
+If optional fifth argument REPLACE is non-nil,
+it means replace the current buffer contents (in the accessible portion)
+with the file contents. This is better than simply deleting and inserting
+the whole thing because (1) it preserves some marker positions
+and (2) it puts less data in the undo list.
+When REPLACE is non-nil, the value is the number of characters actually read,
+which is often less than the number of characters to be read.
+
+This does code conversion according to the value of
+`coding-system-for-read' or `file-coding-system-alist',
+and sets the variable `last-coding-system-used' to the coding system
+actually used. */)
+ (filename, visit, beg, end, replace)
Lisp_Object filename, visit, beg, end, replace;
{
struct stat st;
int inserted = 0;
register int how_much;
register int unprocessed;
- int count = specpdl_ptr - specpdl;
+ int count = BINDING_STACK_SIZE ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
Lisp_Object handler, val, insval, orig_filename;
Lisp_Object p;
- int total;
+ int total = 0;
int not_regular = 0;
unsigned char read_buf[READ_BUF_SIZE];
struct coding_system coding;
int replace_handled = 0;
int set_coding_system = 0;
int coding_system_decided = 0;
+ int read_quit = 0;
if (current_buffer->base_buffer && ! NILP (visit))
error ("Cannot do file visiting in an indirect buffer");
GCPRO4 (filename, val, p, orig_filename);
- CHECK_STRING (filename, 0);
+ CHECK_STRING (filename);
filename = Fexpand_file_name (filename, Qnil);
/* If the file name has special constructs in it,
{
val = call6 (handler, Qinsert_file_contents, filename,
visit, beg, end, replace);
- if (CONSP (val) && CONSP (XCONS (val)->cdr))
- inserted = XINT (XCONS (XCONS (val)->cdr)->car);
+ if (CONSP (val) && CONSP (XCDR (val)))
+ inserted = XINT (XCAR (XCDR (val)));
goto handled;
}
#ifndef APOLLO
if (stat (XSTRING (filename)->data, &st) < 0)
#else
- if ((fd = open (XSTRING (filename)->data, O_RDONLY)) < 0
+ if ((fd = emacs_open (XSTRING (filename)->data, O_RDONLY, 0)) < 0
|| fstat (fd, &st) < 0)
#endif /* not APOLLO */
#endif /* WINDOWSNT */
{
- if (fd >= 0) close (fd);
+ if (fd >= 0) emacs_close (fd);
badopen:
if (NILP (visit))
report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
st.st_mtime = -1;
how_much = 0;
if (!NILP (Vcoding_system_for_read))
- current_buffer->buffer_file_coding_system = Vcoding_system_for_read;
+ Fset (Qbuffer_file_coding_system, Vcoding_system_for_read);
goto notfound;
}
#endif
if (fd < 0)
- if ((fd = open (XSTRING (filename)->data, O_RDONLY)) < 0)
+ if ((fd = emacs_open (XSTRING (filename)->data, O_RDONLY, 0)) < 0)
goto badopen;
/* Replacement should preserve point as it preserves markers. */
/* Prevent redisplay optimizations. */
current_buffer->clip_changed = 1;
- if (!NILP (beg) || !NILP (end))
- if (!NILP (visit))
- error ("Attempt to visit less than an entire file");
+ if (!NILP (visit))
+ {
+ if (!NILP (beg) || !NILP (end))
+ error ("Attempt to visit less than an entire file");
+ if (BEG < Z && NILP (replace))
+ error ("Cannot do file visiting in a non-empty buffer");
+ }
if (!NILP (beg))
- CHECK_NUMBER (beg, 0);
+ CHECK_NUMBER (beg);
else
XSETFASTINT (beg, 0);
if (!NILP (end))
- CHECK_NUMBER (end, 0);
+ CHECK_NUMBER (end);
else
{
if (! not_regular)
{
XSETINT (end, st.st_size);
- if (XINT (end) != st.st_size)
+
+ /* Arithmetic overflow can occur if an Emacs integer cannot
+ represent the file size, or if the calculations below
+ overflow. The calculations below double the file size
+ twice, so check that it can be multiplied by 4 safely. */
+ if (XINT (end) != st.st_size
+ || ((int) st.st_size * 4) / 4 != st.st_size)
error ("Maximum buffer size exceeded");
+
+ /* The file size returned from stat may be zero, but data
+ may be readable nonetheless, for example when this is a
+ file in the /proc filesystem. */
+ if (st.st_size == 0)
+ XSETINT (end, READ_BUF_SIZE);
}
}
We assume that the 1K-byte and 3K-byte for heading
and tailing respectively are sufficient for this
purpose. */
- int how_many, nread;
+ int nread;
if (st.st_size <= (1024 * 4))
- nread = read (fd, read_buf, 1024 * 4);
+ nread = emacs_read (fd, read_buf, 1024 * 4);
else
{
- nread = read (fd, read_buf, 1024);
+ nread = emacs_read (fd, read_buf, 1024);
if (nread >= 0)
{
if (lseek (fd, st.st_size - (1024 * 3), 0) < 0)
report_file_error ("Setting file position",
Fcons (orig_filename, Qnil));
- nread += read (fd, read_buf + nread, 1024 * 3);
+ nread += emacs_read (fd, read_buf + nread, 1024 * 3);
}
}
if (nread < 0)
error ("IO error reading %s: %s",
- XSTRING (orig_filename)->data, strerror (errno));
+ XSTRING (orig_filename)->data, emacs_strerror (errno));
else if (nread > 0)
{
- int count = specpdl_ptr - specpdl;
struct buffer *prev = current_buffer;
+ Lisp_Object buffer;
+ struct buffer *buf;
record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
- temp_output_buffer_setup (" *code-converting-work*");
- set_buffer_internal (XBUFFER (Vstandard_output));
- current_buffer->enable_multibyte_characters = Qnil;
+
+ buffer = Fget_buffer_create (build_string (" *code-converting-work*"));
+ buf = XBUFFER (buffer);
+
+ buf->directory = current_buffer->directory;
+ buf->read_only = Qnil;
+ buf->filename = Qnil;
+ buf->undo_list = Qt;
+ buf->overlays_before = Qnil;
+ buf->overlays_after = Qnil;
+
+ set_buffer_internal (buf);
+ Ferase_buffer ();
+ buf->enable_multibyte_characters = Qnil;
+
insert_1_both (read_buf, nread, nread, 0, 0, 0);
TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
val = call2 (Vset_auto_coding_function,
filename, make_number (nread));
set_buffer_internal (prev);
+
/* Discard the unwind protect for recovering the
current buffer. */
specpdl_ptr--;
args[2] = visit, args[3] = beg, args[4] = end, args[5] = replace;
coding_systems = Ffind_operation_coding_system (6, args);
if (CONSP (coding_systems))
- val = XCONS (coding_systems)->car;
+ val = XCAR (coding_systems);
}
}
setup_coding_system (Fcheck_coding_system (val), &coding);
+ /* Ensure we set Vlast_coding_system_used. */
+ set_coding_system = 1;
if (NILP (current_buffer->enable_multibyte_characters)
&& ! NILP (val))
end-of-line conversion. */
setup_raw_text_coding_system (&coding);
+ coding.src_multibyte = 0;
+ coding.dst_multibyte
+ = !NILP (current_buffer->enable_multibyte_characters);
coding_system_decided = 1;
}
- /* Ensure we always set Vlast_coding_system_used. */
- set_coding_system = 1;
-
/* If requested, replace the accessible part of the buffer
with the file contents. Avoid replacing text at the
beginning or end of the buffer that matches the file contents;
and let the following if-statement handle the replace job. */
if (!NILP (replace)
&& BEGV < ZV
- && ! CODING_REQUIRE_DECODING (&coding)
- && (coding.eol_type == CODING_EOL_UNDECIDED
- || coding.eol_type == CODING_EOL_LF))
+ && !(coding.common_flags & CODING_REQUIRE_DECODING_MASK))
{
/* same_at_start and same_at_end count bytes,
because file access counts bytes
{
int nread, bufpos;
- nread = read (fd, buffer, sizeof buffer);
+ nread = emacs_read (fd, buffer, sizeof buffer);
if (nread < 0)
error ("IO error reading %s: %s",
- XSTRING (orig_filename)->data, strerror (errno));
+ XSTRING (orig_filename)->data, emacs_strerror (errno));
else if (nread == 0)
break;
if (coding.type == coding_type_undecided)
detect_coding (&coding, buffer, nread);
- if (CODING_REQUIRE_DECODING (&coding))
+ if (coding.common_flags & CODING_REQUIRE_DECODING_MASK)
/* We found that the file should be decoded somehow.
Let's give up here. */
{
there's no need to replace anything. */
if (same_at_start - BEGV_BYTE == XINT (end))
{
- close (fd);
+ emacs_close (fd);
specpdl_ptr--;
/* Truncate the buffer to the size of the file. */
- del_range_1 (same_at_start, same_at_end, 0);
+ del_range_1 (same_at_start, same_at_end, 0, 0);
goto handled;
}
immediate_quit = 1;
report_file_error ("Setting file position",
Fcons (orig_filename, Qnil));
- total_read = 0;
+ total_read = nread = 0;
while (total_read < trial)
{
- nread = read (fd, buffer + total_read, trial - total_read);
- if (nread <= 0)
+ nread = emacs_read (fd, buffer + total_read, trial - total_read);
+ if (nread < 0)
error ("IO error reading %s: %s",
- XSTRING (orig_filename)->data, strerror (errno));
+ XSTRING (orig_filename)->data, emacs_strerror (errno));
+ else if (nread == 0)
+ break;
total_read += nread;
}
+
/* Scan this bufferful from the end, comparing with
the Emacs buffer. */
bufpos = total_read;
+
/* Compare with same_at_start to avoid counting some buffer text
as matching both at the file's beginning and at the end. */
while (bufpos > 0 && same_at_end > same_at_start
giveup_match_end = 1;
break;
}
+
+ if (nread == 0)
+ break;
}
immediate_quit = 0;
/* Allow quitting out of the actual I/O. */
immediate_quit = 1;
QUIT;
- this = read (fd, destination, trytry);
+ this = emacs_read (fd, destination, trytry);
immediate_quit = 0;
if (this < 0 || this + unprocessed == 0)
/* Convert this batch with results in CONVERSION_BUFFER. */
if (how_much >= total) /* This is the last block. */
coding.mode |= CODING_MODE_LAST_BLOCK;
+ if (coding.composing != COMPOSITION_DISABLED)
+ coding_allocate_composition_data (&coding, BEGV);
result = decode_coding (&coding, read_buf,
conversion_buffer + inserted,
this, bufsize - inserted);
/* Save for next iteration whatever we didn't convert. */
unprocessed = this - coding.consumed;
bcopy (read_buf + coding.consumed, read_buf, unprocessed);
- this = coding.produced;
+ if (!NILP (current_buffer->enable_multibyte_characters))
+ this = coding.produced;
+ else
+ this = str_as_unibyte (conversion_buffer + inserted,
+ coding.produced);
}
inserted += this;
if (how_much == -1)
error ("IO error reading %s: %s",
- XSTRING (orig_filename)->data, strerror (errno));
+ XSTRING (orig_filename)->data, emacs_strerror (errno));
else if (how_much == -2)
error ("maximum buffer size exceeded");
}
if (bufpos == inserted)
{
xfree (conversion_buffer);
- close (fd);
+ emacs_close (fd);
specpdl_ptr--;
/* Truncate the buffer to the size of the file. */
del_range_byte (same_at_start, same_at_end, 0);
SET_PT_BOTH (temp, same_at_start);
insert_1 (conversion_buffer + same_at_start - BEG_BYTE, inserted,
0, 0, 0);
+ if (coding.cmp_data && coding.cmp_data->used)
+ coding_restore_composition (&coding, Fcurrent_buffer ());
+ coding_free_composition_data (&coding);
+
/* Set `inserted' to the number of inserted characters. */
inserted = PT - temp;
- free (conversion_buffer);
- close (fd);
+ xfree (conversion_buffer);
+ emacs_close (fd);
specpdl_ptr--;
goto handled;
before exiting the loop, it is set to a negative value if I/O
error occurs. */
how_much = 0;
+
/* Total bytes inserted. */
inserted = 0;
+
/* Here, we don't do code conversion in the loop. It is done by
code_convert_region after all data are read into the buffer. */
- while (how_much < total)
- {
+ {
+ int gap_size = GAP_SIZE;
+
+ while (how_much < total)
+ {
/* try is reserved in some compilers (Microsoft C) */
- int trytry = min (total - how_much, READ_BUF_SIZE);
- int this;
+ int trytry = min (total - how_much, READ_BUF_SIZE);
+ int this;
- /* For a special file, GAP_SIZE should be checked every time. */
- if (not_regular && GAP_SIZE < trytry)
- make_gap (total - GAP_SIZE);
+ if (not_regular)
+ {
+ Lisp_Object val;
- /* Allow quitting out of the actual I/O. */
- immediate_quit = 1;
- QUIT;
- this = read (fd, BYTE_POS_ADDR (PT_BYTE + inserted - 1) + 1, trytry);
- immediate_quit = 0;
+ /* Maybe make more room. */
+ if (gap_size < trytry)
+ {
+ make_gap (total - gap_size);
+ gap_size = GAP_SIZE;
+ }
- if (this <= 0)
- {
- how_much = this;
- break;
- }
+ /* Read from the file, capturing `quit'. When an
+ error occurs, end the loop, and arrange for a quit
+ to be signaled after decoding the text we read. */
+ non_regular_fd = fd;
+ non_regular_inserted = inserted;
+ non_regular_nbytes = trytry;
+ val = internal_condition_case_1 (read_non_regular, Qnil, Qerror,
+ read_non_regular_quit);
+ if (NILP (val))
+ {
+ read_quit = 1;
+ break;
+ }
- GAP_SIZE -= this;
- GPT_BYTE += this;
- ZV_BYTE += this;
- Z_BYTE += this;
- GPT += this;
- ZV += this;
- Z += this;
-
- /* For a regular file, where TOTAL is the real size,
- count HOW_MUCH to compare with it.
- For a special file, where TOTAL is just a buffer size,
- so don't bother counting in HOW_MUCH.
- (INSERTED is where we count the number of characters inserted.) */
- if (! not_regular)
- how_much += this;
- inserted += this;
- }
+ this = XINT (val);
+ }
+ else
+ {
+ /* Allow quitting out of the actual I/O. We don't make text
+ part of the buffer until all the reading is done, so a C-g
+ here doesn't do any harm. */
+ immediate_quit = 1;
+ QUIT;
+ this = emacs_read (fd, BEG_ADDR + PT_BYTE - 1 + inserted, trytry);
+ immediate_quit = 0;
+ }
+
+ if (this <= 0)
+ {
+ how_much = this;
+ break;
+ }
+
+ gap_size -= this;
+
+ /* For a regular file, where TOTAL is the real size,
+ count HOW_MUCH to compare with it.
+ For a special file, where TOTAL is just a buffer size,
+ so don't bother counting in HOW_MUCH.
+ (INSERTED is where we count the number of characters inserted.) */
+ if (! not_regular)
+ how_much += this;
+ inserted += this;
+ }
+ }
+
+ /* Make the text read part of the buffer. */
+ GAP_SIZE -= inserted;
+ GPT += inserted;
+ GPT_BYTE += inserted;
+ ZV += inserted;
+ ZV_BYTE += inserted;
+ Z += inserted;
+ Z_BYTE += inserted;
if (GAP_SIZE > 0)
/* Put an anchor to ensure multi-byte form ends at gap. */
*GPT_ADDR = 0;
- close (fd);
+ emacs_close (fd);
/* Discard the unwind protect for closing the file. */
specpdl_ptr--;
if (how_much < 0)
error ("IO error reading %s: %s",
- XSTRING (orig_filename)->data, strerror (errno));
+ XSTRING (orig_filename)->data, emacs_strerror (errno));
+
+ notfound:
if (! coding_system_decided)
{
/* The coding system is not yet decided. Decide it by an
- optimized method for handling `coding:' tag. */
+ optimized method for handling `coding:' tag.
+
+ Note that we can get here only if the buffer was empty
+ before the insertion. */
Lisp_Object val;
val = Qnil;
val = Vcoding_system_for_read;
else
{
- if (inserted > 0 && ! NILP (Vset_auto_coding_function))
- {
- /* Since we are sure that the current buffer was
- empty before the insertion, we can toggle
- enable-multibyte-characters directly here without
- taking care of marker adjustment and byte
- combining problem. */
- Lisp_Object prev_multibyte;
+ /* Since we are sure that the current buffer was empty
+ before the insertion, we can toggle
+ enable-multibyte-characters directly here without taking
+ care of marker adjustment and byte combining problem. By
+ this way, we can run Lisp program safely before decoding
+ the inserted text. */
+ Lisp_Object unwind_data;
int count = specpdl_ptr - specpdl;
- prev_multibyte = current_buffer->enable_multibyte_characters;
+ unwind_data = Fcons (current_buffer->enable_multibyte_characters,
+ Fcons (current_buffer->undo_list,
+ Fcurrent_buffer ()));
current_buffer->enable_multibyte_characters = Qnil;
- record_unwind_protect (set_auto_coding_unwind,
- prev_multibyte);
+ current_buffer->undo_list = Qt;
+ record_unwind_protect (decide_coding_unwind, unwind_data);
+
+ if (inserted > 0 && ! NILP (Vset_auto_coding_function))
+ {
val = call2 (Vset_auto_coding_function,
filename, make_number (inserted));
- /* Discard the unwind protect for recovering the
- error of Vset_auto_coding_function. */
- specpdl_ptr--;
- current_buffer->enable_multibyte_characters = prev_multibyte;
- TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
}
if (NILP (val))
args[2] = visit, args[3] = beg, args[4] = end, args[5] = Qnil;
coding_systems = Ffind_operation_coding_system (6, args);
if (CONSP (coding_systems))
- val = XCONS (coding_systems)->car;
+ val = XCAR (coding_systems);
}
+
+ unbind_to (count, Qnil);
+ inserted = Z_BYTE - BEG_BYTE;
}
/* The following kludgy code is to avoid some compiler bug.
setup_coding_system (val, &temp_coding);
bcopy (&temp_coding, &coding, sizeof coding);
}
+ /* Ensure we set Vlast_coding_system_used. */
+ set_coding_system = 1;
if (NILP (current_buffer->enable_multibyte_characters)
&& ! NILP (val))
/* We must suppress all character code conversion except for
end-of-line conversion. */
setup_raw_text_coding_system (&coding);
+ coding.src_multibyte = 0;
+ coding.dst_multibyte
+ = !NILP (current_buffer->enable_multibyte_characters);
+ }
+
+ if (!NILP (visit)
+ /* Can't do this if part of the buffer might be preserved. */
+ && NILP (replace)
+ && (coding.type == coding_type_no_conversion
+ || coding.type == coding_type_raw_text))
+ {
+ /* Visiting a file with these coding system makes the buffer
+ unibyte. */
+ current_buffer->enable_multibyte_characters = Qnil;
+ coding.dst_multibyte = 0;
}
if (inserted > 0 || coding.type == coding_type_ccl)
{
if (CODING_MAY_REQUIRE_DECODING (&coding))
{
- /* Here, we don't have to consider byte combining (see the
- comment below) because code_convert_region takes care of
- it. */
code_convert_region (PT, PT_BYTE, PT + inserted, PT_BYTE + inserted,
&coding, 0, 0);
- inserted = (NILP (current_buffer->enable_multibyte_characters)
- ? coding.produced : coding.produced_char);
- }
- else if (!NILP (current_buffer->enable_multibyte_characters))
- {
- int inserted_byte = inserted;
-
- /* There's a possibility that we must combine bytes at the
- head (resp. the tail) of the just inserted text with the
- bytes before (resp. after) the gap to form a single
- character. */
- inserted = multibyte_chars_in_text (GPT_ADDR - inserted, inserted);
- adjust_after_insert (PT, PT_BYTE,
- PT + inserted_byte, PT_BYTE + inserted_byte,
- inserted);
+ inserted = coding.produced_char;
}
else
adjust_after_insert (PT, PT_BYTE, PT + inserted, PT_BYTE + inserted,
- inserted);
+ inserted);
}
#ifdef DOS_NT
current_buffer->buffer_file_type = Qnil;
#endif
- notfound:
handled:
if (!NILP (visit))
Fsignal (Qfile_error,
Fcons (build_string ("not a regular file"),
Fcons (orig_filename, Qnil)));
-
- /* If visiting nonexistent file, return nil. */
- if (current_buffer->modtime == -1)
- report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
}
/* Decode file format */
if (inserted > 0)
{
+ int empty_undo_list_p = 0;
+
+ /* If we're anyway going to discard undo information, don't
+ record it in the first place. The buffer's undo list at this
+ point is either nil or t when visiting a file. */
+ if (!NILP (visit))
+ {
+ empty_undo_list_p = NILP (current_buffer->undo_list);
+ current_buffer->undo_list = Qt;
+ }
+
insval = call3 (Qformat_decode,
Qnil, make_number (inserted), visit);
- CHECK_NUMBER (insval, 0);
+ CHECK_NUMBER (insval);
inserted = XFASTINT (insval);
+
+ if (!NILP (visit))
+ current_buffer->undo_list = empty_undo_list_p ? Qnil : Qt;
}
+ if (set_coding_system)
+ Vlast_coding_system_used = coding.symbol;
+
/* Call after-change hooks for the inserted text, aside from the case
of normal visiting (not with REPLACE), which is done in a new buffer
"before" the buffer is changed. */
if (inserted > 0 && total > 0
&& (NILP (visit) || !NILP (replace)))
- signal_after_change (PT, 0, inserted);
-
- if (set_coding_system)
- Vlast_coding_system_used = coding.symbol;
+ {
+ signal_after_change (PT, 0, inserted);
+ update_compositions (PT, PT, CHECK_BORDER);
+ }
- if (inserted > 0)
+ p = Vafter_insert_file_functions;
+ while (!NILP (p))
{
- p = Vafter_insert_file_functions;
- while (!NILP (p))
+ insval = call1 (Fcar (p), make_number (inserted));
+ if (!NILP (insval))
{
- insval = call1 (Fcar (p), make_number (inserted));
- if (!NILP (insval))
- {
- CHECK_NUMBER (insval, 0);
- inserted = XFASTINT (insval);
- }
- QUIT;
- p = Fcdr (p);
+ CHECK_NUMBER (insval);
+ inserted = XFASTINT (insval);
}
+ QUIT;
+ p = Fcdr (p);
+ }
+
+ if (!NILP (visit)
+ && current_buffer->modtime == -1)
+ {
+ /* If visiting nonexistent file, return nil. */
+ report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
}
+ if (read_quit)
+ Fsignal (Qquit, Qnil);
+
/* ??? Retval needs to be dealt with in all cases consistently. */
if (NILP (val))
val = Fcons (orig_filename,
RETURN_UNGCPRO (unbind_to (count, val));
}
\f
-static Lisp_Object build_annotations P_ ((Lisp_Object, Lisp_Object,
- Lisp_Object));
+static Lisp_Object build_annotations P_ ((Lisp_Object, Lisp_Object));
+static Lisp_Object build_annotations_2 P_ ((Lisp_Object, Lisp_Object,
+ Lisp_Object, Lisp_Object));
/* If build_annotations switched buffers, switch back to BUF.
Kill the temporary buffer that was selected in the meantime.
return Qnil;
}
+/* Decide the coding-system to encode the data with. */
+
+void
+choose_write_coding_system (start, end, filename,
+ append, visit, lockname, coding)
+ Lisp_Object start, end, filename, append, visit, lockname;
+ struct coding_system *coding;
+{
+ Lisp_Object val;
+
+ if (auto_saving)
+ val = Qnil;
+ else if (!NILP (Vcoding_system_for_write))
+ val = Vcoding_system_for_write;
+ else
+ {
+ /* If the variable `buffer-file-coding-system' is set locally,
+ it means that the file was read with some kind of code
+ conversion or the variable is explicitly set by users. We
+ had better write it out with the same coding system even if
+ `enable-multibyte-characters' is nil.
+
+ If it is not set locally, we anyway have to convert EOL
+ format if the default value of `buffer-file-coding-system'
+ tells that it is not Unix-like (LF only) format. */
+ int using_default_coding = 0;
+ int force_raw_text = 0;
+
+ val = current_buffer->buffer_file_coding_system;
+ if (NILP (val)
+ || NILP (Flocal_variable_p (Qbuffer_file_coding_system, Qnil)))
+ {
+ val = Qnil;
+ if (NILP (current_buffer->enable_multibyte_characters))
+ force_raw_text = 1;
+ }
+
+ if (NILP (val))
+ {
+ /* Check file-coding-system-alist. */
+ Lisp_Object args[7], coding_systems;
+
+ args[0] = Qwrite_region; args[1] = start; args[2] = end;
+ args[3] = filename; args[4] = append; args[5] = visit;
+ args[6] = lockname;
+ coding_systems = Ffind_operation_coding_system (7, args);
+ if (CONSP (coding_systems) && !NILP (XCDR (coding_systems)))
+ val = XCDR (coding_systems);
+ }
+
+ if (NILP (val)
+ && !NILP (current_buffer->buffer_file_coding_system))
+ {
+ /* If we still have not decided a coding system, use the
+ default value of buffer-file-coding-system. */
+ val = current_buffer->buffer_file_coding_system;
+ using_default_coding = 1;
+ }
+
+ if (!force_raw_text
+ && !NILP (Ffboundp (Vselect_safe_coding_system_function)))
+ /* Confirm that VAL can surely encode the current region. */
+ val = call3 (Vselect_safe_coding_system_function, start, end, val);
+
+ setup_coding_system (Fcheck_coding_system (val), coding);
+ if (coding->eol_type == CODING_EOL_UNDECIDED
+ && !using_default_coding)
+ {
+ if (! EQ (default_buffer_file_coding.symbol,
+ buffer_defaults.buffer_file_coding_system))
+ setup_coding_system (buffer_defaults.buffer_file_coding_system,
+ &default_buffer_file_coding);
+ if (default_buffer_file_coding.eol_type != CODING_EOL_UNDECIDED)
+ {
+ Lisp_Object subsidiaries;
+
+ coding->eol_type = default_buffer_file_coding.eol_type;
+ subsidiaries = Fget (coding->symbol, Qeol_type);
+ if (VECTORP (subsidiaries)
+ && XVECTOR (subsidiaries)->size == 3)
+ coding->symbol
+ = XVECTOR (subsidiaries)->contents[coding->eol_type];
+ }
+ }
+
+ if (force_raw_text)
+ setup_raw_text_coding_system (coding);
+ goto done_setup_coding;
+ }
+
+ setup_coding_system (Fcheck_coding_system (val), coding);
+
+ done_setup_coding:
+ if (!STRINGP (start) && !NILP (current_buffer->selective_display))
+ coding->mode |= CODING_MODE_SELECTIVE_DISPLAY;
+}
+
DEFUN ("write-region", Fwrite_region, Swrite_region, 3, 7,
- "r\nFWrite region to file: \ni\ni\ni\np",
- "Write current region into specified file.\n\
-When called from a program, takes three arguments:\n\
-START, END and FILENAME. START and END are buffer positions.\n\
-Optional fourth argument APPEND if non-nil means\n\
- append to existing file contents (if any).\n\
-Optional fifth argument VISIT if t means\n\
- set the last-save-file-modtime of buffer to this file's modtime\n\
- and mark buffer not modified.\n\
-If VISIT is a string, it is a second file name;\n\
- the output goes to FILENAME, but the buffer is marked as visiting VISIT.\n\
- VISIT is also the file name to lock and unlock for clash detection.\n\
-If VISIT is neither t nor nil nor a string,\n\
- that means do not print the \"Wrote file\" message.\n\
-The optional sixth arg LOCKNAME, if non-nil, specifies the name to\n\
- use for locking and unlocking, overriding FILENAME and VISIT.\n\
-The optional seventh arg MUSTBENEW, if non-nil, insists on a check\n\
- for an existing file with the same name. If MUSTBENEW is `excl',\n\
- that means to get an error if the file already exists; never overwrite.\n\
- If MUSTBENEW is neither nil nor `excl', that means ask for\n\
- confirmation before overwriting, but do go ahead and overwrite the file\n\
- if the user confirms.\n\
-Kludgy feature: if START is a string, then that string is written\n\
-to the file, instead of any buffer contents, and END is ignored.\n\
-\n\
-This does code conversion according to the value of\n\
-`coding-system-for-write', `buffer-file-coding-system', or\n\
-`file-coding-system-alist', and sets the variable\n\
-`last-coding-system-used' to the coding system actually used.")
-
- (start, end, filename, append, visit, lockname, mustbenew)
+ "r\nFWrite region to file: \ni\ni\ni\np",
+ doc: /* Write current region into specified file.
+When called from a program, requires three arguments:
+START, END and FILENAME. START and END are normally buffer positions
+specifying the part of the buffer to write.
+If START is nil, that means to use the entire buffer contents.
+If START is a string, then output that string to the file
+instead of any buffer contents; END is ignored.
+
+Optional fourth argument APPEND if non-nil means
+ append to existing file contents (if any). If it is an integer,
+ seek to that offset in the file before writing.
+Optional fifth argument VISIT if t means
+ set the last-save-file-modtime of buffer to this file's modtime
+ and mark buffer not modified.
+If VISIT is a string, it is a second file name;
+ the output goes to FILENAME, but the buffer is marked as visiting VISIT.
+ VISIT is also the file name to lock and unlock for clash detection.
+If VISIT is neither t nor nil nor a string,
+ that means do not print the \"Wrote file\" message.
+The optional sixth arg LOCKNAME, if non-nil, specifies the name to
+ use for locking and unlocking, overriding FILENAME and VISIT.
+The optional seventh arg MUSTBENEW, if non-nil, insists on a check
+ for an existing file with the same name. If MUSTBENEW is `excl',
+ that means to get an error if the file already exists; never overwrite.
+ If MUSTBENEW is neither nil nor `excl', that means ask for
+ confirmation before overwriting, but do go ahead and overwrite the file
+ if the user confirms.
+
+This does code conversion according to the value of
+`coding-system-for-write', `buffer-file-coding-system', or
+`file-coding-system-alist', and sets the variable
+`last-coding-system-used' to the coding system actually used. */)
+ (start, end, filename, append, visit, lockname, mustbenew)
Lisp_Object start, end, filename, append, visit, lockname, mustbenew;
{
register int desc;
int failure;
- int save_errno;
+ int save_errno = 0;
unsigned char *fn;
struct stat st;
int tem;
Lisp_Object visit_file;
Lisp_Object annotations;
Lisp_Object encoded_filename;
- int visiting, quietly;
+ int visiting = (EQ (visit, Qt) || STRINGP (visit));
+ int quietly = !NILP (visit);
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
struct buffer *given_buffer;
#ifdef DOS_NT
#endif /* DOS_NT */
struct coding_system coding;
- if (current_buffer->base_buffer && ! NILP (visit))
+ if (current_buffer->base_buffer && visiting)
error ("Cannot do file visiting in an indirect buffer");
if (!NILP (start) && !STRINGP (start))
validate_region (&start, &end);
- GCPRO4 (start, filename, visit, lockname);
-
- /* Decide the coding-system to encode the data with. */
- {
- Lisp_Object val;
-
- if (auto_saving)
- val = Qnil;
- else if (!NILP (Vcoding_system_for_write))
- val = Vcoding_system_for_write;
- else
- {
- /* If the variable `buffer-file-coding-system' is set locally,
- it means that the file was read with some kind of code
- conversion or the varialbe is explicitely set by users. We
- had better write it out with the same coding system even if
- `enable-multibyte-characters' is nil.
-
- If it is not set locally, we anyway have to convert EOL
- format if the default value of `buffer-file-coding-system'
- tells that it is not Unix-like (LF only) format. */
- int using_default_coding = 0;
- int force_raw_text = 0;
-
- val = current_buffer->buffer_file_coding_system;
- if (NILP (val)
- || NILP (Flocal_variable_p (Qbuffer_file_coding_system, Qnil)))
- {
- val = Qnil;
- if (NILP (current_buffer->enable_multibyte_characters))
- force_raw_text = 1;
- }
-
- if (NILP (val))
- {
- /* Check file-coding-system-alist. */
- Lisp_Object args[7], coding_systems;
-
- args[0] = Qwrite_region; args[1] = start; args[2] = end;
- args[3] = filename; args[4] = append; args[5] = visit;
- args[6] = lockname;
- coding_systems = Ffind_operation_coding_system (7, args);
- if (CONSP (coding_systems) && !NILP (XCONS (coding_systems)->cdr))
- val = XCONS (coding_systems)->cdr;
- }
-
- if (NILP (val)
- && !NILP (current_buffer->buffer_file_coding_system))
- {
- /* If we still have not decided a coding system, use the
- default value of buffer-file-coding-system. */
- val = current_buffer->buffer_file_coding_system;
- using_default_coding = 1;
- }
-
- if (!force_raw_text
- && !NILP (Ffboundp (Vselect_safe_coding_system_function)))
- /* Confirm that VAL can surely encode the current region. */
- val = call3 (Vselect_safe_coding_system_function, start, end, val);
-
- setup_coding_system (Fcheck_coding_system (val), &coding);
- if (coding.eol_type == CODING_EOL_UNDECIDED
- && !using_default_coding)
- {
- if (! EQ (default_buffer_file_coding.symbol,
- buffer_defaults.buffer_file_coding_system))
- setup_coding_system (buffer_defaults.buffer_file_coding_system,
- &default_buffer_file_coding);
- if (default_buffer_file_coding.eol_type != CODING_EOL_UNDECIDED)
- {
- Lisp_Object subsidiaries;
-
- coding.eol_type = default_buffer_file_coding.eol_type;
- subsidiaries = Fget (coding.symbol, Qeol_type);
- if (VECTORP (subsidiaries)
- && XVECTOR (subsidiaries)->size == 3)
- coding.symbol
- = XVECTOR (subsidiaries)->contents[coding.eol_type];
- }
- }
-
- if (force_raw_text)
- setup_raw_text_coding_system (&coding);
- goto done_setup_coding;
- }
-
- setup_coding_system (Fcheck_coding_system (val), &coding);
-
- done_setup_coding:
- if (!STRINGP (start) && !NILP (current_buffer->selective_display))
- coding.mode |= CODING_MODE_SELECTIVE_DISPLAY;
- }
-
- Vlast_coding_system_used = coding.symbol;
+ GCPRO5 (start, filename, visit, visit_file, lockname);
filename = Fexpand_file_name (filename, Qnil);
- if (! NILP (confirm) && confirm != Qexcl)
+ if (!NILP (mustbenew) && !EQ (mustbenew, Qexcl))
barf_or_query_if_file_exists (filename, "overwrite", 1, 0, 1);
if (STRINGP (visit))
visit_file = Fexpand_file_name (visit, Qnil);
else
visit_file = filename;
- UNGCPRO;
-
- visiting = (EQ (visit, Qt) || STRINGP (visit));
- quietly = !NILP (visit);
-
- annotations = Qnil;
if (NILP (lockname))
lockname = visit_file;
- GCPRO5 (start, filename, annotations, visit_file, lockname);
+ annotations = Qnil;
/* If the file name has special constructs in it,
call the corresponding file handler. */
count1 = specpdl_ptr - specpdl;
given_buffer = current_buffer;
- annotations = build_annotations (start, end, coding.pre_write_conversion);
+ annotations = build_annotations (start, end);
+ if (current_buffer != given_buffer)
+ {
+ XSETFASTINT (start, BEGV);
+ XSETFASTINT (end, ZV);
+ }
+
+ UNGCPRO;
+
+ GCPRO5 (start, filename, annotations, visit_file, lockname);
+
+ /* Decide the coding-system to encode the data with.
+ We used to make this choice before calling build_annotations, but that
+ leads to problems when a write-annotate-function takes care of
+ unsavable chars (as was the case with X-Symbol). */
+ choose_write_coding_system (start, end, filename,
+ append, visit, lockname, &coding);
+ Vlast_coding_system_used = coding.symbol;
+
+ given_buffer = current_buffer;
+ annotations = build_annotations_2 (start, end,
+ coding.pre_write_conversion, annotations);
if (current_buffer != given_buffer)
{
XSETFASTINT (start, BEGV);
desc = -1;
if (!NILP (append))
#ifdef DOS_NT
- desc = open (fn, O_WRONLY | buffer_file_type);
+ desc = emacs_open (fn, O_WRONLY | buffer_file_type, 0);
#else /* not DOS_NT */
- desc = open (fn, O_WRONLY);
+ desc = emacs_open (fn, O_WRONLY, 0);
#endif /* not DOS_NT */
if (desc < 0 && (NILP (append) || errno == ENOENT))
if (auto_saving) /* Overwrite any previous version of autosave file */
{
vms_truncate (fn); /* if fn exists, truncate to zero length */
- desc = open (fn, O_RDWR);
+ desc = emacs_open (fn, O_RDWR, 0);
if (desc < 0)
desc = creat_copy_attrs (STRINGP (current_buffer->filename)
? XSTRING (current_buffer->filename)->data : 0,
/* We can't make a new version;
try to truncate and rewrite existing version if any. */
vms_truncate (fn);
- desc = open (fn, O_RDWR);
+ desc = emacs_open (fn, O_RDWR, 0);
}
#endif
}
}
#else /* not VMS */
#ifdef DOS_NT
- desc = open (fn,
- O_WRONLY | O_TRUNC | O_CREAT | buffer_file_type,
- S_IREAD | S_IWRITE);
+ desc = emacs_open (fn,
+ O_WRONLY | O_CREAT | buffer_file_type
+ | (EQ (mustbenew, Qexcl) ? O_EXCL : O_TRUNC),
+ S_IREAD | S_IWRITE);
#else /* not DOS_NT */
- desc = open (fn, O_WRONLY | O_TRUNC | O_CREAT
- | (confirm == Qexcl ? O_EXCL : 0),
- auto_saving ? auto_save_mode_bits : 0666);
+ desc = emacs_open (fn, O_WRONLY | O_TRUNC | O_CREAT
+ | (EQ (mustbenew, Qexcl) ? O_EXCL : 0),
+ auto_saving ? auto_save_mode_bits : 0666);
#endif /* not DOS_NT */
#endif /* not VMS */
- UNGCPRO;
-
if (desc < 0)
{
#ifdef CLASH_DETECTION
if (!auto_saving) unlock_file (lockname);
errno = save_errno;
#endif /* CLASH_DETECTION */
+ UNGCPRO;
report_file_error ("Opening output file", Fcons (filename, Qnil));
}
record_unwind_protect (close_file_unwind, make_number (desc));
if (!NILP (append) && !NILP (Ffile_regular_p (filename)))
- if (lseek (desc, 0, 2) < 0)
- {
+ {
+ long ret;
+
+ if (NUMBERP (append))
+ ret = lseek (desc, XINT (append), 1);
+ else
+ ret = lseek (desc, 0, 2);
+ if (ret < 0)
+ {
#ifdef CLASH_DETECTION
- if (!auto_saving) unlock_file (lockname);
+ if (!auto_saving) unlock_file (lockname);
#endif /* CLASH_DETECTION */
- report_file_error ("Lseek error", Fcons (filename, Qnil));
- }
+ UNGCPRO;
+ report_file_error ("Lseek error", Fcons (filename, Qnil));
+ }
+ }
+
+ UNGCPRO;
#ifdef VMS
/*
if (STRINGP (start))
{
- failure = 0 > a_write (desc, XSTRING (start)->data,
- STRING_BYTES (XSTRING (start)), 0, &annotations,
- &coding);
+ failure = 0 > a_write (desc, start, 0, XSTRING (start)->size,
+ &annotations, &coding);
save_errno = errno;
}
else if (XINT (start) != XINT (end))
{
- register int end1 = CHAR_TO_BYTE (XINT (end));
-
tem = CHAR_TO_BYTE (XINT (start));
if (XINT (start) < GPT)
{
- failure = 0 > a_write (desc, BYTE_POS_ADDR (tem),
- min (GPT_BYTE, end1) - tem, tem, &annotations,
- &coding);
+ failure = 0 > a_write (desc, Qnil, XINT (start),
+ min (GPT, XINT (end)) - XINT (start),
+ &annotations, &coding);
save_errno = errno;
}
if (XINT (end) > GPT && !failure)
{
- tem = max (tem, GPT_BYTE);
- failure = 0 > a_write (desc, BYTE_POS_ADDR (tem), end1 - tem,
- tem, &annotations, &coding);
+ tem = max (XINT (start), GPT);
+ failure = 0 > a_write (desc, Qnil, tem , XINT (end) - tem,
+ &annotations, &coding);
save_errno = errno;
}
}
{
/* If file was empty, still need to write the annotations */
coding.mode |= CODING_MODE_LAST_BLOCK;
- failure = 0 > a_write (desc, "", 0, XINT (start), &annotations, &coding);
+ failure = 0 > a_write (desc, Qnil, XINT (end), 0, &annotations, &coding);
save_errno = errno;
}
{
/* We have to flush out a data. */
coding.mode |= CODING_MODE_LAST_BLOCK;
- failure = 0 > e_write (desc, "", 0, &coding);
+ failure = 0 > e_write (desc, Qnil, 0, 0, &coding);
save_errno = errno;
}
#endif
/* NFS can report a write failure now. */
- if (close (desc) < 0)
+ if (emacs_close (desc) < 0)
failure = 1, save_errno = errno;
#ifdef VMS
if (failure)
error ("IO error writing %s: %s", XSTRING (filename)->data,
- strerror (save_errno));
+ emacs_strerror (save_errno));
if (visiting)
{
Lisp_Object merge ();
DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0,
- "Return t if (car A) is numerically less than (car B).")
- (a, b)
+ doc: /* Return t if (car A) is numerically less than (car B). */)
+ (a, b)
Lisp_Object a, b;
{
return Flss (Fcar (a), Fcar (b));
as save-excursion would do. */
static Lisp_Object
-build_annotations (start, end, pre_write_conversion)
- Lisp_Object start, end, pre_write_conversion;
+build_annotations (start, end)
+ Lisp_Object start, end;
{
Lisp_Object annotations;
Lisp_Object p, res;
struct gcpro gcpro1, gcpro2;
Lisp_Object original_buffer;
+ int i;
XSETBUFFER (original_buffer, current_buffer);
p = Vauto_save_file_format;
else
p = current_buffer->file_format;
- while (!NILP (p))
+ for (i = 0; !NILP (p); p = Fcdr (p), ++i)
{
struct buffer *given_buffer = current_buffer;
+
Vwrite_region_annotations_so_far = annotations;
- res = call4 (Qformat_annotate_function, Fcar (p), start, end,
- original_buffer);
+
+ /* Value is either a list of annotations or nil if the function
+ has written annotations to a temporary buffer, which is now
+ current. */
+ res = call5 (Qformat_annotate_function, Fcar (p), start, end,
+ original_buffer, make_number (i));
if (current_buffer != given_buffer)
{
XSETFASTINT (start, BEGV);
XSETFASTINT (end, ZV);
annotations = Qnil;
}
- Flength (res);
- annotations = merge (annotations, res, Qcar_less_than_car);
- p = Fcdr (p);
+
+ if (CONSP (res))
+ annotations = merge (annotations, res, Qcar_less_than_car);
}
+ UNGCPRO;
+ return annotations;
+}
+
+static Lisp_Object
+build_annotations_2 (start, end, pre_write_conversion, annotations)
+ Lisp_Object start, end, pre_write_conversion, annotations;
+{
+ struct gcpro gcpro1;
+ Lisp_Object res;
+
+ GCPRO1 (annotations);
/* At last, do the same for the function PRE_WRITE_CONVERSION
implied by the current coding-system. */
if (!NILP (pre_write_conversion))
return annotations;
}
\f
-/* Write to descriptor DESC the NBYTES bytes starting at ADDR,
- assuming they start at byte position BYTEPOS in the buffer.
+/* Write to descriptor DESC the NCHARS chars starting at POS of STRING.
+ If STRING is nil, POS is the character position in the current buffer.
Intersperse with them the annotations from *ANNOT
- which fall within the range of byte positions BYTEPOS to BYTEPOS + NBYTES,
+ which fall within the range of POS to POS + NCHARS,
each at its appropriate position.
We modify *ANNOT by discarding elements as we use them up.
The return value is negative in case of system call failure. */
static int
-a_write (desc, addr, nbytes, bytepos, annot, coding)
+a_write (desc, string, pos, nchars, annot, coding)
int desc;
- register char *addr;
- register int nbytes;
- int bytepos;
+ Lisp_Object string;
+ register int nchars;
+ int pos;
Lisp_Object *annot;
struct coding_system *coding;
{
Lisp_Object tem;
int nextpos;
- int lastpos = bytepos + nbytes;
+ int lastpos = pos + nchars;
while (NILP (*annot) || CONSP (*annot))
{
tem = Fcar_safe (Fcar (*annot));
- nextpos = bytepos - 1;
+ nextpos = pos - 1;
if (INTEGERP (tem))
- nextpos = CHAR_TO_BYTE (XFASTINT (tem));
+ nextpos = XFASTINT (tem);
/* If there are no more annotations in this range,
output the rest of the range all at once. */
- if (! (nextpos >= bytepos && nextpos <= lastpos))
- return e_write (desc, addr, lastpos - bytepos, coding);
+ if (! (nextpos >= pos && nextpos <= lastpos))
+ return e_write (desc, string, pos, lastpos, coding);
/* Output buffer text up to the next annotation's position. */
- if (nextpos > bytepos)
+ if (nextpos > pos)
{
- if (0 > e_write (desc, addr, nextpos - bytepos, coding))
+ if (0 > e_write (desc, string, pos, nextpos, coding))
return -1;
- addr += nextpos - bytepos;
- bytepos = nextpos;
+ pos = nextpos;
}
/* Output the annotation. */
tem = Fcdr (Fcar (*annot));
if (STRINGP (tem))
{
- if (0 > e_write (desc, XSTRING (tem)->data, STRING_BYTES (XSTRING (tem)),
- coding))
+ if (0 > e_write (desc, tem, 0, XSTRING (tem)->size, coding))
return -1;
}
*annot = Fcdr (*annot);
#define WRITE_BUF_SIZE (16 * 1024)
#endif
-/* Write NBYTES bytes starting at ADDR into descriptor DESC,
- encoding them with coding system CODING. */
+/* Write text in the range START and END into descriptor DESC,
+ encoding them with coding system CODING. If STRING is nil, START
+ and END are character positions of the current buffer, else they
+ are indexes to the string STRING. */
static int
-e_write (desc, addr, nbytes, coding)
+e_write (desc, string, start, end, coding)
int desc;
- register char *addr;
- register int nbytes;
+ Lisp_Object string;
+ int start, end;
struct coding_system *coding;
{
+ register char *addr;
+ register int nbytes;
char buf[WRITE_BUF_SIZE];
+ int return_val = 0;
+
+ if (start >= end)
+ coding->composing = COMPOSITION_DISABLED;
+ if (coding->composing != COMPOSITION_DISABLED)
+ coding_save_composition (coding, start, end, string);
+
+ if (STRINGP (string))
+ {
+ addr = XSTRING (string)->data;
+ nbytes = STRING_BYTES (XSTRING (string));
+ coding->src_multibyte = STRING_MULTIBYTE (string);
+ }
+ else if (start < end)
+ {
+ /* It is assured that the gap is not in the range START and END-1. */
+ addr = CHAR_POS_ADDR (start);
+ nbytes = CHAR_TO_BYTE (end) - CHAR_TO_BYTE (start);
+ coding->src_multibyte
+ = !NILP (current_buffer->enable_multibyte_characters);
+ }
+ else
+ {
+ addr = "";
+ nbytes = 0;
+ coding->src_multibyte = 1;
+ }
/* We used to have a code for handling selective display here. But,
now it is handled within encode_coding. */
int result;
result = encode_coding (coding, addr, buf, nbytes, WRITE_BUF_SIZE);
- nbytes -= coding->consumed, addr += coding->consumed;
if (coding->produced > 0)
{
- coding->produced -= write (desc, buf, coding->produced);
- if (coding->produced) return -1;
+ coding->produced -= emacs_write (desc, buf, coding->produced);
+ if (coding->produced)
+ {
+ return_val = -1;
+ break;
+ }
}
- if (result == CODING_FINISH_INSUFFICIENT_SRC)
+ nbytes -= coding->consumed;
+ addr += coding->consumed;
+ if (result == CODING_FINISH_INSUFFICIENT_SRC
+ && nbytes > 0)
{
/* The source text ends by an incomplete multibyte form.
There's no way other than write it out as is. */
- nbytes -= write (desc, addr, nbytes);
- if (nbytes) return -1;
+ nbytes -= emacs_write (desc, addr, nbytes);
+ if (nbytes)
+ {
+ return_val = -1;
+ break;
+ }
}
if (nbytes <= 0)
break;
+ start += coding->consumed_char;
+ if (coding->cmp_data)
+ coding_adjust_composition_offset (coding, start);
}
- return 0;
+
+ if (coding->cmp_data)
+ coding_free_composition_data (coding);
+
+ return return_val;
}
\f
DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,
- Sverify_visited_file_modtime, 1, 1, 0,
- "Return t if last mod time of BUF's visited file matches what BUF records.\n\
-This means that the file has not been changed since it was visited or saved.")
- (buf)
+ Sverify_visited_file_modtime, 1, 1, 0,
+ doc: /* Return t if last mod time of BUF's visited file matches what BUF records.
+This means that the file has not been changed since it was visited or saved. */)
+ (buf)
Lisp_Object buf;
{
struct buffer *b;
Lisp_Object handler;
Lisp_Object filename;
- CHECK_BUFFER (buf, 0);
+ CHECK_BUFFER (buf);
b = XBUFFER (buf);
if (!STRINGP (b->filename)) return Qt;
}
DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,
- Sclear_visited_file_modtime, 0, 0, 0,
- "Clear out records of last mod time of visited file.\n\
-Next attempt to save will certainly not complain of a discrepancy.")
- ()
+ Sclear_visited_file_modtime, 0, 0, 0,
+ doc: /* Clear out records of last mod time of visited file.
+Next attempt to save will certainly not complain of a discrepancy. */)
+ ()
{
current_buffer->modtime = 0;
return Qnil;
}
DEFUN ("visited-file-modtime", Fvisited_file_modtime,
- Svisited_file_modtime, 0, 0, 0,
- "Return the current buffer's recorded visited file modification time.\n\
-The value is a list of the form (HIGH . LOW), like the time values\n\
-that `file-attributes' returns.")
- ()
+ Svisited_file_modtime, 0, 0, 0,
+ doc: /* Return the current buffer's recorded visited file modification time.
+The value is a list of the form (HIGH . LOW), like the time values
+that `file-attributes' returns. */)
+ ()
{
return long_to_cons ((unsigned long) current_buffer->modtime);
}
DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
- Sset_visited_file_modtime, 0, 1, 0,
- "Update buffer's recorded modification time from the visited file's time.\n\
-Useful if the buffer was not read from the file normally\n\
-or if the file itself has been changed for some known benign reason.\n\
-An argument specifies the modification time value to use\n\
-\(instead of that of the visited file), in the form of a list\n\
-\(HIGH . LOW) or (HIGH LOW).")
- (time_list)
+ Sset_visited_file_modtime, 0, 1, 0,
+ doc: /* Update buffer's recorded modification time from the visited file's time.
+Useful if the buffer was not read from the file normally
+or if the file itself has been changed for some known benign reason.
+An argument specifies the modification time value to use
+\(instead of that of the visited file), in the form of a list
+\(HIGH . LOW) or (HIGH LOW). */)
+ (time_list)
Lisp_Object time_list;
{
if (!NILP (time_list))
}
\f
Lisp_Object
-auto_save_error ()
+auto_save_error (error)
+ Lisp_Object error;
{
+ Lisp_Object args[3], msg;
+ int i, nbytes;
+ struct gcpro gcpro1;
+
ring_bell ();
- message_with_string ("Autosaving...error for %s", current_buffer->name, 1);
- Fsleep_for (make_number (1), Qnil);
- message_with_string ("Autosaving...error for %s", current_buffer->name, 0);
- Fsleep_for (make_number (1), Qnil);
- message_with_string ("Autosaving...error for %s", current_buffer->name, 0);
- Fsleep_for (make_number (1), Qnil);
+
+ args[0] = build_string ("Auto-saving %s: %s");
+ args[1] = current_buffer->name;
+ args[2] = Ferror_message_string (error);
+ msg = Fformat (3, args);
+ GCPRO1 (msg);
+ nbytes = STRING_BYTES (XSTRING (msg));
+
+ for (i = 0; i < 3; ++i)
+ {
+ if (i == 0)
+ message2 (XSTRING (msg)->data, nbytes, STRING_MULTIBYTE (msg));
+ else
+ message2_nolog (XSTRING (msg)->data, nbytes, STRING_MULTIBYTE (msg));
+ Fsleep_for (make_number (1), Qnil);
+ }
+
+ UNGCPRO;
return Qnil;
}
Lisp_Object
auto_save_1 ()
{
- unsigned char *fn;
struct stat st;
/* Get visited file's mode to become the auto save file's mode. */
- if (stat (XSTRING (current_buffer->filename)->data, &st) >= 0)
+ if (! NILP (current_buffer->filename)
+ && stat (XSTRING (current_buffer->filename)->data, &st) >= 0)
/* But make sure we can overwrite it later! */
auto_save_mode_bits = st.st_mode | 0600;
else
{
auto_saving = 0;
if (!NILP (stream))
- fclose ((FILE *) (XFASTINT (XCONS (stream)->car) << 16
- | XFASTINT (XCONS (stream)->cdr)));
+ fclose ((FILE *) (XFASTINT (XCAR (stream)) << 16
+ | XFASTINT (XCDR (stream))));
+ pop_message ();
return Qnil;
}
}
DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 2, "",
- "Auto-save all buffers that need it.\n\
-This is all buffers that have auto-saving enabled\n\
-and are changed since last auto-saved.\n\
-Auto-saving writes the buffer into a file\n\
-so that your editing is not lost if the system crashes.\n\
-This file is not the file you visited; that changes only when you save.\n\
-Normally we run the normal hook `auto-save-hook' before saving.\n\n\
-A non-nil NO-MESSAGE argument means do not print any message if successful.\n\
-A non-nil CURRENT-ONLY argument means save only current buffer.")
- (no_message, current_only)
+ doc: /* Auto-save all buffers that need it.
+This is all buffers that have auto-saving enabled
+and are changed since last auto-saved.
+Auto-saving writes the buffer into a file
+so that your editing is not lost if the system crashes.
+This file is not the file you visited; that changes only when you save.
+Normally we run the normal hook `auto-save-hook' before saving.
+
+A non-nil NO-MESSAGE argument means do not print any message if successful.
+A non-nil CURRENT-ONLY argument means save only current buffer. */)
+ (no_message, current_only)
Lisp_Object no_message, current_only;
{
struct buffer *old = current_buffer, *b;
FILE *stream;
Lisp_Object lispstream;
int count = specpdl_ptr - specpdl;
- int *ptr;
int orig_minibuffer_auto_raise = minibuffer_auto_raise;
- int message_p = push_message ();
+ int message_p = 0;
+
+ if (max_specpdl_size < specpdl_size + 40)
+ max_specpdl_size = specpdl_size + 40;
+
+ if (minibuf_level)
+ no_message = Qt;
+
+ if (NILP (no_message));
+ message_p = push_message ();
/* Ordinarily don't quit within this function,
but don't make it impossible to quit (in case we get hung in I/O). */
/* No GCPRO needed, because (when it matters) all Lisp_Object variables
point to non-strings reached from Vbuffer_alist. */
- if (minibuf_level)
- no_message = Qt;
-
if (!NILP (Vrun_hooks))
call1 (Vrun_hooks, intern ("auto-save-hook"));
if (STRINGP (Vauto_save_list_file_name))
{
Lisp_Object listfile;
+
listfile = Fexpand_file_name (Vauto_save_list_file_name, Qnil);
+
+ /* Don't try to create the directory when shutting down Emacs,
+ because creating the directory might signal an error, and
+ that would leave Emacs in a strange state. */
+ if (!NILP (Vrun_hooks))
+ {
+ Lisp_Object dir;
+ dir = Ffile_name_directory (listfile);
+ if (NILP (Ffile_directory_p (dir)))
+ call2 (Qmake_directory, dir, Qt);
+ }
+
stream = fopen (XSTRING (listfile)->data, "w");
if (stream != NULL)
{
/* Arrange to close that file whether or not we get an error.
Also reset auto_saving to 0. */
lispstream = Fcons (Qnil, Qnil);
- XSETFASTINT (XCONS (lispstream)->car, (EMACS_UINT)stream >> 16);
- XSETFASTINT (XCONS (lispstream)->cdr, (EMACS_UINT)stream & 0xffff);
+ XSETCARFASTINT (lispstream, (EMACS_UINT)stream >> 16);
+ XSETCDRFASTINT (lispstream, (EMACS_UINT)stream & 0xffff);
}
else
lispstream = Qnil;
autosave perfectly ordinary files because it couldn't handle some
ange-ftp'd file. */
for (do_handled_files = 0; do_handled_files < 2; do_handled_files++)
- for (tail = Vbuffer_alist; GC_CONSP (tail); tail = XCONS (tail)->cdr)
+ for (tail = Vbuffer_alist; GC_CONSP (tail); tail = XCDR (tail))
{
- buf = XCONS (XCONS (tail)->car)->cdr;
+ buf = XCDR (XCAR (tail));
b = XBUFFER (buf);
/* Record all the buffers that have auto save mode
{
/* It has shrunk too much; turn off auto-saving here. */
minibuffer_auto_raise = orig_minibuffer_auto_raise;
- message_with_string ("Buffer %s has shrunk a lot; auto save turned off there",
+ message_with_string ("Buffer %s has shrunk a lot; auto save disabled in that buffer until next real save",
b->name, 1);
minibuffer_auto_raise = 0;
/* Turn off auto-saving until there's a real save,
Vquit_flag = oquit;
- pop_message ();
unbind_to (count, Qnil);
return Qnil;
}
DEFUN ("set-buffer-auto-saved", Fset_buffer_auto_saved,
- Sset_buffer_auto_saved, 0, 0, 0,
- "Mark current buffer as auto-saved with its current text.\n\
-No auto-save file will be written until the buffer changes again.")
- ()
+ Sset_buffer_auto_saved, 0, 0, 0,
+ doc: /* Mark current buffer as auto-saved with its current text.
+No auto-save file will be written until the buffer changes again. */)
+ ()
{
current_buffer->auto_save_modified = MODIFF;
XSETFASTINT (current_buffer->save_length, Z - BEG);
}
DEFUN ("clear-buffer-auto-save-failure", Fclear_buffer_auto_save_failure,
- Sclear_buffer_auto_save_failure, 0, 0, 0,
- "Clear any record of a recent auto-save failure in the current buffer.")
- ()
+ Sclear_buffer_auto_save_failure, 0, 0, 0,
+ doc: /* Clear any record of a recent auto-save failure in the current buffer. */)
+ ()
{
current_buffer->auto_save_failure_time = -1;
return Qnil;
}
DEFUN ("recent-auto-save-p", Frecent_auto_save_p, Srecent_auto_save_p,
- 0, 0, 0,
- "Return t if buffer has been auto-saved since last read in or saved.")
- ()
+ 0, 0, 0,
+ doc: /* Return t if buffer has been auto-saved since last read in or saved. */)
+ ()
{
return (SAVE_MODIFF < current_buffer->auto_save_modified) ? Qt : Qnil;
}
}
DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_internal,
- 3, 3, 0,
- "Internal subroutine for read-file-name. Do not call this.")
- (string, dir, action)
+ 3, 3, 0,
+ doc: /* Internal subroutine for read-file-name. Do not call this. */)
+ (string, dir, action)
Lisp_Object string, dir, action;
/* action is nil for complete, t for return list of completions,
lambda for verify final value */
int changed;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
- CHECK_STRING (string, 0);
+ CHECK_STRING (string);
realdir = dir;
name = string;
}
DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 5, 0,
- "Read file name, prompting with PROMPT and completing in directory DIR.\n\
-Value is not expanded---you must call `expand-file-name' yourself.\n\
-Default name to DEFAULT-FILENAME if user enters a null string.\n\
- (If DEFAULT-FILENAME is omitted, the visited file name is used,\n\
- except that if INITIAL is specified, that combined with DIR is used.)\n\
-Fourth arg MUSTMATCH non-nil means require existing file's name.\n\
- Non-nil and non-t means also require confirmation after completion.\n\
-Fifth arg INITIAL specifies text to start with.\n\
-DIR defaults to current buffer's directory default.")
- (prompt, dir, default_filename, mustmatch, initial)
+ doc: /* Read file name, prompting with PROMPT and completing in directory DIR.
+Value is not expanded---you must call `expand-file-name' yourself.
+Default name to DEFAULT-FILENAME if user enters a null string.
+ (If DEFAULT-FILENAME is omitted, the visited file name is used,
+ except that if INITIAL is specified, that combined with DIR is used.)
+Fourth arg MUSTMATCH non-nil means require existing file's name.
+ Non-nil and non-t means also require confirmation after completion.
+Fifth arg INITIAL specifies text to start with.
+DIR defaults to current buffer's directory default.
+
+If this command was invoked with the mouse, use a file dialog box if
+`use-dialog-box' is non-nil, and the window system or X toolkit in use
+provides a file dialog box. */)
+ (prompt, dir, default_filename, mustmatch, initial)
Lisp_Object prompt, dir, default_filename, mustmatch, initial;
{
Lisp_Object val, insdef, tem;
/* If dir starts with user's homedir, change that to ~. */
homedir = (char *) egetenv ("HOME");
#ifdef DOS_NT
- homedir = strcpy (alloca (strlen (homedir) + 1), homedir);
- CORRECT_DIR_SEPS (homedir);
+ /* homedir can be NULL in temacs, since Vprocess_environment is not
+ yet set up. We shouldn't crash in that case. */
+ if (homedir != 0)
+ {
+ homedir = strcpy (alloca (strlen (homedir) + 1), homedir);
+ CORRECT_DIR_SEPS (homedir);
+ }
#endif
if (homedir != 0
&& STRINGP (dir)
}
if (!NILP (default_filename))
{
- CHECK_STRING (default_filename, 3);
+ CHECK_STRING (default_filename);
default_filename = double_dollars (default_filename);
}
GCPRO2 (insdef, default_filename);
-#ifdef USE_MOTIF
+#if defined (USE_MOTIF) || defined (HAVE_NTGUI)
if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
&& use_dialog_box
&& have_menus_p ())
{
+ /* If DIR contains a file name, split it. */
+ Lisp_Object file;
+ file = Ffile_name_nondirectory (dir);
+ if (XSTRING (file)->size && NILP (default_filename))
+ {
+ default_filename = file;
+ dir = Ffile_name_directory (dir);
+ }
+ if (!NILP(default_filename))
+ default_filename = Fexpand_file_name (default_filename, dir);
val = Fx_file_dialog (prompt, dir, default_filename, mustmatch);
add_to_history = 1;
}
Qfile_name_history, default_filename, Qnil);
tem = Fsymbol_value (Qfile_name_history);
- if (CONSP (tem) && EQ (XCONS (tem)->car, val))
+ if (CONSP (tem) && EQ (XCAR (tem), val))
replace_in_history = 1;
/* If Fcompleting_read returned the inserted default string itself
if (replace_in_history)
/* Replace what Fcompleting_read added to the history
with what we will actually return. */
- XCONS (Fsymbol_value (Qfile_name_history))->car = double_dollars (val);
+ XSETCAR (Fsymbol_value (Qfile_name_history), double_dollars (val));
else if (add_to_history)
{
/* Add the value to the history--but not if it matches
the last value already there. */
Lisp_Object val1 = double_dollars (val);
tem = Fsymbol_value (Qfile_name_history);
- if (! CONSP (tem) || NILP (Fequal (XCONS (tem)->car, val1)))
+ if (! CONSP (tem) || NILP (Fequal (XCAR (tem), val1)))
Fset (Qfile_name_history,
Fcons (val1, tem));
}
Qfile_name_as_directory = intern ("file-name-as-directory");
Qcopy_file = intern ("copy-file");
Qmake_directory_internal = intern ("make-directory-internal");
+ Qmake_directory = intern ("make-directory");
Qdelete_directory = intern ("delete-directory");
Qdelete_file = intern ("delete-file");
Qrename_file = intern ("rename-file");
staticpro (&Qfile_name_as_directory);
staticpro (&Qcopy_file);
staticpro (&Qmake_directory_internal);
+ staticpro (&Qmake_directory);
staticpro (&Qdelete_directory);
staticpro (&Qdelete_file);
staticpro (&Qrename_file);
#endif /* DOS_NT */
DEFVAR_LISP ("file-name-coding-system", &Vfile_name_coding_system,
- "*Coding system for encoding file names.\n\
-If it is nil, default-file-name-coding-system (which see) is used.");
+ doc: /* *Coding system for encoding file names.
+If it is nil, `default-file-name-coding-system' (which see) is used. */);
Vfile_name_coding_system = Qnil;
DEFVAR_LISP ("default-file-name-coding-system",
&Vdefault_file_name_coding_system,
- "Default coding system for encoding file names.\n\
-This variable is used only when file-name-coding-system is nil.\n\
-\n\
-This variable is set/changed by the command set-language-environment.\n\
-User should not set this variable manually,\n\
-instead use file-name-coding-system to get a constant encoding\n\
-of file names regardless of the current language environment.");
+ doc: /* Default coding system for encoding file names.
+This variable is used only when `file-name-coding-system' is nil.
+
+This variable is set/changed by the command `set-language-environment'.
+User should not set this variable manually,
+instead use `file-name-coding-system' to get a constant encoding
+of file names regardless of the current language environment. */);
Vdefault_file_name_coding_system = Qnil;
DEFVAR_LISP ("auto-save-file-format", &Vauto_save_file_format,
- "*Format in which to write auto-save files.\n\
-Should be a list of symbols naming formats that are defined in `format-alist'.\n\
-If it is t, which is the default, auto-save files are written in the\n\
-same format as a regular save would use.");
+ doc: /* *Format in which to write auto-save files.
+Should be a list of symbols naming formats that are defined in `format-alist'.
+If it is t, which is the default, auto-save files are written in the
+same format as a regular save would use. */);
Vauto_save_file_format = Qt;
Qformat_decode = intern ("format-decode");
build_string ("Cannot set file date"));
DEFVAR_BOOL ("insert-default-directory", &insert_default_directory,
- "*Non-nil means when reading a filename start with default dir in minibuffer.");
+ doc: /* *Non-nil means when reading a filename start with default dir in minibuffer. */);
insert_default_directory = 1;
DEFVAR_BOOL ("vms-stmlf-recfm", &vms_stmlf_recfm,
- "*Non-nil means write new files with record format `stmlf'.\n\
-nil means use format `var'. This variable is meaningful only on VMS.");
+ doc: /* *Non-nil means write new files with record format `stmlf'.
+nil means use format `var'. This variable is meaningful only on VMS. */);
vms_stmlf_recfm = 0;
DEFVAR_LISP ("directory-sep-char", &Vdirectory_sep_char,
- "Directory separator character for built-in functions that return file names.\n\
-The value should be either ?/ or ?\\ (any other value is treated as ?\\).\n\
-This variable affects the built-in functions only on Windows,\n\
-on other platforms, it is initialized so that Lisp code can find out\n\
-what the normal separator is.");
+ doc: /* Directory separator character for built-in functions that return file names.
+The value should be either ?/ or ?\\ (any other value is treated as ?\\).
+This variable affects the built-in functions only on Windows,
+on other platforms, it is initialized so that Lisp code can find out
+what the normal separator is.
+
+WARNING: This variable is deprecated and will be removed in the near
+future. DO NOT USE IT. */);
DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist,
- "*Alist of elements (REGEXP . HANDLER) for file names handled specially.\n\
-If a file name matches REGEXP, then all I/O on that file is done by calling\n\
-HANDLER.\n\
-\n\
-The first argument given to HANDLER is the name of the I/O primitive\n\
-to be handled; the remaining arguments are the arguments that were\n\
-passed to that primitive. For example, if you do\n\
- (file-exists-p FILENAME)\n\
-and FILENAME is handled by HANDLER, then HANDLER is called like this:\n\
- (funcall HANDLER 'file-exists-p FILENAME)\n\
-The function `find-file-name-handler' checks this list for a handler\n\
-for its argument.");
+ doc: /* *Alist of elements (REGEXP . HANDLER) for file names handled specially.
+If a file name matches REGEXP, then all I/O on that file is done by calling
+HANDLER.
+
+The first argument given to HANDLER is the name of the I/O primitive
+to be handled; the remaining arguments are the arguments that were
+passed to that primitive. For example, if you do
+ (file-exists-p FILENAME)
+and FILENAME is handled by HANDLER, then HANDLER is called like this:
+ (funcall HANDLER 'file-exists-p FILENAME)
+The function `find-file-name-handler' checks this list for a handler
+for its argument. */);
Vfile_name_handler_alist = Qnil;
DEFVAR_LISP ("set-auto-coding-function",
&Vset_auto_coding_function,
- "If non-nil, a function to call to decide a coding system of file.\n\
-Two arguments are passed to this function: the file name\n\
-and the length of a file contents following the point.\n\
-This function should return a coding system to decode the file contents.\n\
-It should check the file name against `auto-coding-alist'.\n\
-If no coding system is decided, it should check a coding system\n\
-specified in the heading lines with the format:\n\
- -*- ... coding: CODING-SYSTEM; ... -*-\n\
-or local variable spec of the tailing lines with `coding:' tag.");
+ doc: /* If non-nil, a function to call to decide a coding system of file.
+Two arguments are passed to this function: the file name
+and the length of a file contents following the point.
+This function should return a coding system to decode the file contents.
+It should check the file name against `auto-coding-alist'.
+If no coding system is decided, it should check a coding system
+specified in the heading lines with the format:
+ -*- ... coding: CODING-SYSTEM; ... -*-
+or local variable spec of the tailing lines with `coding:' tag. */);
Vset_auto_coding_function = Qnil;
DEFVAR_LISP ("after-insert-file-functions", &Vafter_insert_file_functions,
- "A list of functions to be called at the end of `insert-file-contents'.\n\
-Each is passed one argument, the number of bytes inserted. It should return\n\
-the new byte count, and leave point the same. If `insert-file-contents' is\n\
-intercepted by a handler from `file-name-handler-alist', that handler is\n\
-responsible for calling the after-insert-file-functions if appropriate.");
+ doc: /* A list of functions to be called at the end of `insert-file-contents'.
+Each is passed one argument, the number of bytes inserted. It should return
+the new byte count, and leave point the same. If `insert-file-contents' is
+intercepted by a handler from `file-name-handler-alist', that handler is
+responsible for calling the after-insert-file-functions if appropriate. */);
Vafter_insert_file_functions = Qnil;
DEFVAR_LISP ("write-region-annotate-functions", &Vwrite_region_annotate_functions,
- "A list of functions to be called at the start of `write-region'.\n\
-Each is passed two arguments, START and END as for `write-region'.\n\
-These are usually two numbers but not always; see the documentation\n\
-for `write-region'. The function should return a list of pairs\n\
-of the form (POSITION . STRING), consisting of strings to be effectively\n\
-inserted at the specified positions of the file being written (1 means to\n\
-insert before the first byte written). The POSITIONs must be sorted into\n\
-increasing order. If there are several functions in the list, the several\n\
-lists are merged destructively.");
+ doc: /* A list of functions to be called at the start of `write-region'.
+Each is passed two arguments, START and END as for `write-region'.
+These are usually two numbers but not always; see the documentation
+for `write-region'. The function should return a list of pairs
+of the form (POSITION . STRING), consisting of strings to be effectively
+inserted at the specified positions of the file being written (1 means to
+insert before the first byte written). The POSITIONs must be sorted into
+increasing order. If there are several functions in the list, the several
+lists are merged destructively. */);
Vwrite_region_annotate_functions = Qnil;
DEFVAR_LISP ("write-region-annotations-so-far",
&Vwrite_region_annotations_so_far,
- "When an annotation function is called, this holds the previous annotations.\n\
-These are the annotations made by other annotation functions\n\
-that were already called. See also `write-region-annotate-functions'.");
+ doc: /* When an annotation function is called, this holds the previous annotations.
+These are the annotations made by other annotation functions
+that were already called. See also `write-region-annotate-functions'. */);
Vwrite_region_annotations_so_far = Qnil;
DEFVAR_LISP ("inhibit-file-name-handlers", &Vinhibit_file_name_handlers,
- "A list of file name handlers that temporarily should not be used.\n\
-This applies only to the operation `inhibit-file-name-operation'.");
+ doc: /* A list of file name handlers that temporarily should not be used.
+This applies only to the operation `inhibit-file-name-operation'. */);
Vinhibit_file_name_handlers = Qnil;
DEFVAR_LISP ("inhibit-file-name-operation", &Vinhibit_file_name_operation,
- "The operation for which `inhibit-file-name-handlers' is applicable.");
+ doc: /* The operation for which `inhibit-file-name-handlers' is applicable. */);
Vinhibit_file_name_operation = Qnil;
DEFVAR_LISP ("auto-save-list-file-name", &Vauto_save_list_file_name,
- "File name in which we write a list of all auto save file names.\n\
-This variable is initialized automatically from `auto-save-list-file-prefix'\n\
-shortly after Emacs reads your `.emacs' file, if you have not yet given it\n\
-a non-nil value.");
+ doc: /* File name in which we write a list of all auto save file names.
+This variable is initialized automatically from `auto-save-list-file-prefix'
+shortly after Emacs reads your `.emacs' file, if you have not yet given it
+a non-nil value. */);
Vauto_save_list_file_name = Qnil;
defsubr (&Sfind_file_name_handler);
defsubr (&Sunix_sync);
#endif
}
+