#include <pwd.h>
#endif
-#ifdef MSDOS
-#include "msdos.h"
-#include <sys/param.h>
-#if __DJGPP__ >= 2
-#include <fcntl.h>
-#include <string.h>
-#endif
-#endif
-
#include <ctype.h>
#ifdef VMS
#include <fcntl.h>
#endif /* not WINDOWSNT */
+#ifdef MSDOS
+#include "msdos.h"
+#include <sys/param.h>
+#if __DJGPP__ >= 2
+#include <fcntl.h>
+#include <string.h>
+#endif
+#endif
+
#ifdef DOS_NT
#define CORRECT_DIR_SEPS(s) \
do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \
#define O_RDONLY 0
#endif
+#ifndef S_ISLNK
+# define lstat stat
+#endif
+
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
extern Lisp_Object Vuser_login_name;
+#ifdef WINDOWSNT
+extern Lisp_Object Vw32_get_true_file_attributes;
+#endif
+
extern int minibuf_level;
extern int minibuffer_auto_raise;
#ifdef DOS_NT
beg = strcpy (alloca (strlen (beg) + 1), beg);
#endif
- p = beg + XSTRING (filename)->size_byte;
+ p = beg + STRING_BYTES (XSTRING (filename));
while (p != beg && !IS_DIRECTORY_SEP (p[-1])
#ifdef VMS
&& p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
#endif /* VMS */
#ifdef DOS_NT
- /* only recognise drive specifier at beginning */
- && !(p[-1] == ':' && p == beg + 2)
+ /* only recognise drive specifier at the beginning */
+ && !(p[-1] == ':'
+ /* handle the "/:d:foo" and "/:foo" cases correctly */
+ && ((p == beg + 2 && !IS_DIRECTORY_SEP (*beg))
+ || (p == beg + 4 && IS_DIRECTORY_SEP (*beg))))
#endif
) p--;
return Qnil;
#ifdef DOS_NT
/* Expansion of "c:" to drive and default directory. */
- if (p == beg + 2 && beg[1] == ':')
+ if (p[-1] == ':')
{
/* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */
unsigned char *res = alloca (MAXPATHLEN + 1);
- if (getdefdir (toupper (*beg) - 'A' + 1, res))
+ unsigned char *r = res;
+
+ if (p == beg + 4 && IS_DIRECTORY_SEP (*beg) && beg[1] == ':')
+ {
+ strncpy (res, beg, 2);
+ beg += 2;
+ r += 2;
+ }
+
+ if (getdefdir (toupper (*beg) - 'A' + 1, r))
{
if (!IS_DIRECTORY_SEP (res[strlen (res) - 1]))
strcat (res, "/");
return call2 (handler, Qfile_name_nondirectory, filename);
beg = XSTRING (filename)->data;
- end = p = beg + XSTRING (filename)->size_byte;
+ end = p = beg + STRING_BYTES (XSTRING (filename));
while (p != beg && !IS_DIRECTORY_SEP (p[-1])
#ifdef VMS
#endif /* VMS */
#ifdef DOS_NT
/* only recognise drive specifier at beginning */
- && !(p[-1] == ':' && p == beg + 2)
+ && !(p[-1] == ':'
+ /* handle the "/:d:foo" case correctly */
+ && (p == beg + 2 || (p == beg + 4 && IS_DIRECTORY_SEP (*beg))))
#endif
)
p--;
if (size < 0)
{
- out[0] = '/';
- out[1] = 0;
+ out[0] = '.';
+ out[1] = '/';
+ out[2] = 0;
return out;
}
if (!NILP (handler))
return call2 (handler, Qfile_name_as_directory, file);
- buf = (char *) alloca (XSTRING (file)->size_byte + 10);
+ buf = (char *) alloca (STRING_BYTES (XSTRING (file)) + 10);
return build_string (file_name_as_directory (buf, XSTRING (file)->data));
}
\f
* Value is nonzero if the string output is different from the input.
*/
+int
directory_file_name (src, dst)
char *src, *dst;
{
/* 20 extra chars is insufficient for VMS, since we might perform a
logical name translation. an equivalence string can be up to 255
chars long, so grab that much extra space... - sss */
- buf = (char *) alloca (XSTRING (directory)->size_byte + 20 + 255);
+ buf = (char *) alloca (STRING_BYTES (XSTRING (directory)) + 20 + 255);
#else
- buf = (char *) alloca (XSTRING (directory)->size_byte + 20);
+ buf = (char *) alloca (STRING_BYTES (XSTRING (directory)) + 20);
#endif
directory_file_name (XSTRING (directory)->data, buf);
return build_string (buf);
}
+static char make_temp_name_tbl[64] =
+{
+ 'A','B','C','D','E','F','G','H',
+ 'I','J','K','L','M','N','O','P',
+ 'Q','R','S','T','U','V','W','X',
+ 'Y','Z','a','b','c','d','e','f',
+ 'g','h','i','j','k','l','m','n',
+ 'o','p','q','r','s','t','u','v',
+ '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.")
+which has no existing file. To make this work,\n\
+PREFIX should be an absolute file name.")
(prefix)
Lisp_Object prefix;
{
Lisp_Object val;
-#ifdef MSDOS
- /* Don't use too many characters of the restricted 8+3 DOS
- filename space. */
- val = concat2 (prefix, build_string ("a.XXX"));
+ int len;
+ int pid;
+ unsigned char *p, *data;
+ char pidbuf[20];
+ int pidlen;
+
+ CHECK_STRING (prefix, 0);
+
+ /* VAL is created by adding 6 characters to PREFIX. The first
+ three are the PID of this process, in base 64, and the second
+ three are incremented if the file already exists. This ensures
+ 262144 unique file names per PID per PREFIX. */
+
+ pid = (int) getpid ();
+
+#ifdef HAVE_LONG_FILE_NAMES
+ sprintf (pidbuf, "%d", pid);
+ pidlen = strlen (pidbuf);
#else
- val = concat2 (prefix, build_string ("XXXXXX"));
-#endif
- mktemp (XSTRING (val)->data);
-#ifdef DOS_NT
- CORRECT_DIR_SEPS (XSTRING (val)->data);
+ 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
- return val;
+
+ len = XSTRING (prefix)->size;
+ val = make_uninit_string (len + 3 + pidlen);
+ data = XSTRING (val)->data;
+ bcopy(XSTRING (prefix)->data, data, len);
+ p = data + len;
+
+ bcopy (pidbuf, p, pidlen);
+ p += pidlen;
+
+ /* Here we try to minimize useless stat'ing when this function is
+ invoked many times successively with the same PREFIX. We achieve
+ this by initializing count to a random value, and incrementing it
+ afterwards.
+
+ We don't want make-temp-name to be called while dumping,
+ because then make_temp_name_count_initialized_p would get set
+ and then make_temp_name_count would not be set when Emacs starts. */
+
+ if (!make_temp_name_count_initialized_p)
+ {
+ make_temp_name_count = (unsigned) time (NULL);
+ make_temp_name_count_initialized_p = 1;
+ }
+
+ while (1)
+ {
+ struct stat ignored;
+ unsigned num = make_temp_name_count;
+
+ p[0] = make_temp_name_tbl[num & 63], num >>= 6;
+ p[1] = make_temp_name_tbl[num & 63], num >>= 6;
+ p[2] = make_temp_name_tbl[num & 63], num >>= 6;
+
+ /* Poor man's congruential RN generator. Replace with
+ ++make_temp_name_count for debugging. */
+ make_temp_name_count += 25229;
+ make_temp_name_count %= 225307;
+
+ if (stat (data, &ignored) < 0)
+ {
+ /* We want to return only if errno is ENOENT. */
+ if (errno == ENOENT)
+ return val;
+ else
+ /* The error here is dubious, but there is little else we
+ can do. The alternatives are to return nil, which is
+ as bad as (and in many cases worse than) throwing the
+ error, or to ignore the error, which will likely result
+ 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'",
+ Fcons (prefix, Qnil));
+ /* not reached */
+ }
+ }
+
+ error ("Cannot create temporary name for prefix `%s'",
+ XSTRING (prefix)->data);
+ return Qnil;
}
+
\f
DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
"Convert filename NAME to absolute, and canonicalize it.\n\
#ifdef DOS_NT
int drive = 0;
int collapse_newdir = 1;
+ int is_escaped = 0;
#endif /* DOS_NT */
int length;
Lisp_Object handler;
is needed at all) without requiring it to be expanded now. */
#ifdef DOS_NT
/* Detect MSDOS file names with drive specifiers. */
- && ! (IS_DRIVE (o[0]) && (IS_DEVICE_SEP (o[1]) && IS_DIRECTORY_SEP (o[2])))
+ && ! (IS_DRIVE (o[0]) && IS_DEVICE_SEP (o[1]) && IS_DIRECTORY_SEP (o[2]))
#ifdef WINDOWSNT
/* Detect Windows file names in UNC format. */
&& ! (IS_DIRECTORY_SEP (o[0]) && IS_DIRECTORY_SEP (o[1]))
a local copy to modify, even if there ends up being no change. */
nm = strcpy (alloca (strlen (nm) + 1), nm);
+ /* Note if special escape prefix is present, but remove for now. */
+ if (nm[0] == '/' && nm[1] == ':')
+ {
+ is_escaped = 1;
+ nm += 2;
+ }
+
/* Find and remove drive specifier if present; this makes nm absolute
- even if the rest of the name appears to be relative. */
- {
- unsigned char *colon = rindex (nm, ':');
-
- if (colon)
- /* Only recognize colon as part of drive specifier if there is a
- single alphabetic character preceeding the colon (and if the
- character before the drive letter, if present, is a directory
- separator); this is to support the remote system syntax used by
- ange-ftp, and the "po:username" syntax for POP mailboxes. */
- look_again:
- if (nm == colon)
- nm++;
- else if (IS_DRIVE (colon[-1])
- && (colon == nm + 1 || IS_DIRECTORY_SEP (colon[-2])))
- {
- drive = colon[-1];
- nm = colon + 1;
- }
- else
- {
- while (--colon >= nm)
- if (colon[0] == ':')
- goto look_again;
- }
- }
+ even if the rest of the name appears to be relative. Only look for
+ drive specifier at the beginning. */
+ if (IS_DRIVE (nm[0]) && IS_DEVICE_SEP (nm[1]))
+ {
+ drive = nm[0];
+ nm += 2;
+ }
#ifdef WINDOWSNT
/* If we see "c://somedir", we want to strip the first slash after the
if (
IS_DIRECTORY_SEP (nm[0])
#ifdef MSDOS
- && drive
+ && drive && !is_escaped
#endif
#ifdef WINDOWSNT
- && (drive || IS_DIRECTORY_SEP (nm[1]))
+ && (drive || IS_DIRECTORY_SEP (nm[1])) && !is_escaped
#endif
#ifdef VMS
|| index (nm, ':')
&& !newdir)
{
newdir = XSTRING (default_directory)->data;
+#ifdef DOS_NT
+ /* Note if special escape prefix is present, but remove for now. */
+ if (newdir[0] == '/' && newdir[1] == ':')
+ {
+ is_escaped = 1;
+ newdir += 2;
+ }
+#endif
}
#ifdef DOS_NT
if (newdir)
{
/* Get rid of any slash at the end of newdir, unless newdir is
- just // (an incomplete UNC name). */
+ just / or // (an incomplete UNC name). */
length = strlen (newdir);
- if (length > 0 && IS_DIRECTORY_SEP (newdir[length - 1])
+ if (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1])
#ifdef WINDOWSNT
&& !(length == 2 && IS_DIRECTORY_SEP (newdir[0]))
#endif
/* Now concatenate the directory and name to new space in the stack frame */
tlen += strlen (nm) + 1;
#ifdef DOS_NT
- /* Add reserved space for drive name. (The Microsoft x86 compiler
+ /* Reserve space for drive specifier and escape prefix, since either
+ or both may need to be inserted. (The Microsoft x86 compiler
produces incorrect code if the following two lines are combined.) */
- target = (unsigned char *) alloca (tlen + 2);
- target += 2;
+ target = (unsigned char *) alloca (tlen + 4);
+ target += 4;
#else /* not DOS_NT */
target = (unsigned char *) alloca (tlen);
#endif /* not DOS_NT */
{
#ifndef VMS
if (nm[0] == 0 || IS_DIRECTORY_SEP (nm[0]))
- strcpy (target, newdir);
+ {
+#ifdef DOS_NT
+ /* If newdir is effectively "C:/", then the drive letter will have
+ been stripped and newdir will be "/". Concatenating with an
+ absolute directory in nm produces "//", which will then be
+ incorrectly treated as a network share. Ignore newdir in
+ this case (keeping the drive letter). */
+ if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0])
+ && newdir[1] == '\0'))
+#endif
+ strcpy (target, newdir);
+ }
else
#endif
file_name_as_directory (target, newdir);
target[0] = DRIVE_LETTER (drive);
target[1] = ':';
}
+ /* Reinsert the escape prefix if required. */
+ if (is_escaped)
+ {
+ target -= 2;
+ target[0] = '/';
+ target[1] = ':';
+ }
CORRECT_DIR_SEPS (target);
#endif /* DOS_NT */
CORRECT_DIR_SEPS (nm);
substituted = (strcmp (nm, XSTRING (filename)->data) != 0);
#endif
- endp = nm + XSTRING (filename)->size_byte;
+ endp = nm + STRING_BYTES (XSTRING (filename));
/* If /~ or // appears, discard everything through first slash. */
/* If substitution required, recopy the string and do it */
/* Make space in stack frame for the new copy */
- xnm = (unsigned char *) alloca (XSTRING (filename)->size_byte + total + 1);
+ xnm = (unsigned char *) alloca (STRING_BYTES (XSTRING (filename)) + total + 1);
x = xnm;
/* Copy the rest of the name through, replacing $ constructs with values */
xnm = p;
#ifdef DOS_NT
else if (IS_DRIVE (p[0]) && p[1] == ':'
- && p > nm && IS_DIRECTORY_SEP (p[-1]))
+ && p > xnm && IS_DIRECTORY_SEP (p[-1]))
xnm = p;
#endif
absname = Fexpand_file_name (filename, defdir);
#ifdef VMS
{
- register int c = XSTRING (absname)->data[XSTRING (absname)->size_byte - 1];
+ register int c = XSTRING (absname)->data[STRING_BYTES (XSTRING (absname)) - 1];
if (c == ':' || c == ']' || c == '>')
absname = Fdirectory_file_name (absname);
}
/* Remove final slash, if any (unless this is the root dir).
stat behaves differently depending! */
if (XSTRING (absname)->size > 1
- && IS_DIRECTORY_SEP (XSTRING (absname)->data[XSTRING (absname)->size_byte - 1])
- && !IS_DEVICE_SEP (XSTRING (absname)->data[XSTRING (absname)->size_byte-2]))
+ && IS_DIRECTORY_SEP (XSTRING (absname)->data[STRING_BYTES (XSTRING (absname)) - 1])
+ && !IS_DEVICE_SEP (XSTRING (absname)->data[STRING_BYTES (XSTRING (absname))-2]))
/* We cannot take shortcuts; they might be wrong for magic file names. */
absname = Fdirectory_file_name (absname);
#endif
*STATPTR is used to store the stat information if the file exists.
If the file does not exist, STATPTR->st_mode is set to 0.
- If STATPTR is null, we don't store into it. */
+ If STATPTR is null, we don't store into it.
+
+ If QUICK is nonzero, we ask for y or n, not yes or no. */
void
-barf_or_query_if_file_exists (absname, querystring, interactive, statptr)
+barf_or_query_if_file_exists (absname, querystring, interactive, statptr, quick)
Lisp_Object absname;
unsigned char *querystring;
int interactive;
struct stat *statptr;
+ int quick;
{
- register Lisp_Object tem;
+ register Lisp_Object tem, encoded_filename;
struct stat statbuf;
struct gcpro gcpro1;
+ encoded_filename = ENCODE_FILE (absname);
+
/* stat is a good way to tell whether the file exists,
regardless of what access permissions it has. */
- if (stat (XSTRING (absname)->data, &statbuf) >= 0)
+ if (stat (XSTRING (encoded_filename)->data, &statbuf) >= 0)
{
if (! interactive)
Fsignal (Qfile_already_exists,
Fcons (build_string ("File already exists"),
Fcons (absname, Qnil)));
GCPRO1 (absname);
- tem = do_yes_or_no_p (format1 ("File %s already exists; %s anyway? ",
- XSTRING (absname)->data, querystring));
+ tem = format1 ("File %s already exists; %s anyway? ",
+ XSTRING (absname)->data, querystring);
+ if (quick)
+ tem = Fy_or_n_p (tem);
+ else
+ tem = do_yes_or_no_p (tem);
UNGCPRO;
if (NILP (tem))
Fsignal (Qfile_already_exists,
if (NILP (ok_if_already_exists)
|| INTEGERP (ok_if_already_exists))
barf_or_query_if_file_exists (encoded_newname, "copy to it",
- INTEGERP (ok_if_already_exists), &out_st);
+ INTEGERP (ok_if_already_exists), &out_st, 0);
else if (stat (XSTRING (encoded_newname)->data, &out_st) < 0)
out_st.st_mode = 0;
copyable by us. */
input_file_statable_p = (fstat (ifd, &st) >= 0);
-#if !defined (MSDOS) || __DJGPP__ > 1
+#if !defined (DOS_NT) || __DJGPP__ > 1
if (out_st.st_mode != 0
&& st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
{
if (NILP (ok_if_already_exists)
|| INTEGERP (ok_if_already_exists))
barf_or_query_if_file_exists (encoded_newname, "rename to it",
- INTEGERP (ok_if_already_exists), 0);
+ INTEGERP (ok_if_already_exists), 0, 0);
#ifndef BSD4_1
if (0 > rename (XSTRING (encoded_file)->data, XSTRING (encoded_newname)->data))
#else
if (NILP (ok_if_already_exists)
|| INTEGERP (ok_if_already_exists))
barf_or_query_if_file_exists (encoded_newname, "make it a new name",
- INTEGERP (ok_if_already_exists), 0);
+ INTEGERP (ok_if_already_exists), 0, 0);
unlink (XSTRING (newname)->data);
if (0 > link (XSTRING (encoded_file)->data, XSTRING (encoded_newname)->data))
if (NILP (ok_if_already_exists)
|| INTEGERP (ok_if_already_exists))
barf_or_query_if_file_exists (encoded_linkname, "make it a link",
- INTEGERP (ok_if_already_exists), 0);
+ INTEGERP (ok_if_already_exists), 0, 0);
if (0 > symlink (XSTRING (encoded_filename)->data,
XSTRING (encoded_linkname)->data))
{
int fd;
CHECK_STRING (filename, 0);
+ CHECK_STRING (string, 1);
/* If the file name has special constructs in it,
call the corresponding file handler. */
}
DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0,
- "Return t if FILENAME names an existing directory.")
+ "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)
Lisp_Object filename;
{
absname = ENCODE_FILE (absname);
+#ifdef WINDOWSNT
+ {
+ int result;
+ Lisp_Object tem = Vw32_get_true_file_attributes;
+
+ /* Tell stat to use expensive method to get accurate info. */
+ Vw32_get_true_file_attributes = Qt;
+ result = stat (XSTRING (absname)->data, &st);
+ Vw32_get_true_file_attributes = tem;
+
+ if (result < 0)
+ return Qnil;
+ return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
+ }
+#else
if (stat (XSTRING (absname)->data, &st) < 0)
return Qnil;
return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
+#endif
}
\f
DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
#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. */
+
+static Lisp_Object
+set_auto_coding_unwind (multibyte)
+ Lisp_Object multibyte;
+{
+ int inserted = Z_BYTE - BEG_BYTE;
+
+ if (!NILP (multibyte))
+ inserted = multibyte_chars_in_text (GPT_ADDR - inserted, inserted);
+ adjust_after_insert (PT, PT_BYTE, Z, Z_BYTE, inserted);
+
+ return Qnil;
+}
+
DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
1, 5, 0,
"Insert contents of file FILENAME after point.\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.")
+`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)
Lisp_Object filename, visit, beg, end, replace;
{
Lisp_Object p;
int total;
int not_regular = 0;
- char read_buf[READ_BUF_SIZE];
+ unsigned char read_buf[READ_BUF_SIZE];
struct coding_system coding;
unsigned char buffer[1 << 14];
int replace_handled = 0;
int set_coding_system = 0;
+ int coding_system_decided = 0;
if (current_buffer->base_buffer && ! NILP (visit))
error ("Cannot do file visiting in an indirect buffer");
{
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);
goto handled;
}
fd = -1;
+#ifdef WINDOWSNT
+ {
+ Lisp_Object tem = Vw32_get_true_file_attributes;
+
+ /* Tell stat to use expensive method to get accurate info. */
+ Vw32_get_true_file_attributes = Qt;
+ total = stat (XSTRING (filename)->data, &st);
+ Vw32_get_true_file_attributes = tem;
+ }
+ if (total < 0)
+#else
#ifndef APOLLO
if (stat (XSTRING (filename)->data, &st) < 0)
#else
if ((fd = open (XSTRING (filename)->data, O_RDONLY)) < 0
|| fstat (fd, &st) < 0)
#endif /* not APOLLO */
+#endif /* WINDOWSNT */
{
if (fd >= 0) close (fd);
badopen:
}
}
- /* Decide the coding-system of the file. */
- {
- Lisp_Object val = Qnil;
+ if (BEG < Z)
+ {
+ /* Decide the coding system to use for reading the file now
+ because we can't use an optimized method for handling
+ `coding:' tag if the current buffer is not empty. */
+ Lisp_Object val;
+ val = Qnil;
- if (!NILP (Vcoding_system_for_read))
- val = Vcoding_system_for_read;
- else
- {
- if (! NILP (Vset_auto_coding_function))
- {
- /* Find a coding system specified in the heading two lines
- or in the tailing several lines of the file. We assume
- that the 1K-byte and 3K-byte for heading and tailing
- respectively are sufficient fot this purpose. */
- int how_many, nread;
-
- if (st.st_size <= (1024 * 4))
- nread = read (fd, read_buf, 1024 * 4);
- else
- {
- nread = 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);
- }
- }
-
- if (nread < 0)
- error ("IO error reading %s: %s",
- XSTRING (orig_filename)->data, strerror (errno));
- else if (nread > 0)
- {
- Lisp_Object tem;
- /* Always make this a unibyte string
- because we have not yet decoded it. */
- tem = make_unibyte_string (read_buf, nread);
- val = call1 (Vset_auto_coding_function, tem);
- /* Rewind the file for the actual read done later. */
- if (lseek (fd, 0, 0) < 0)
- report_file_error ("Setting file position",
- Fcons (orig_filename, Qnil));
- }
- }
- if (NILP (val))
- {
- Lisp_Object args[6], coding_systems;
+ if (!NILP (Vcoding_system_for_read))
+ val = Vcoding_system_for_read;
+ else if (! NILP (replace))
+ /* In REPLACE mode, we can use the same coding system
+ that was used to visit the file. */
+ val = current_buffer->buffer_file_coding_system;
+ else
+ {
+ /* Don't try looking inside a file for a coding system
+ specification if it is not seekable. */
+ if (! not_regular && ! NILP (Vset_auto_coding_function))
+ {
+ /* Find a coding system specified in the heading two
+ lines or in the tailing several lines of the file.
+ We assume that the 1K-byte and 3K-byte for heading
+ and tailing respectively are sufficient for this
+ purpose. */
+ int how_many, nread;
+
+ if (st.st_size <= (1024 * 4))
+ nread = read (fd, read_buf, 1024 * 4);
+ else
+ {
+ nread = 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);
+ }
+ }
- args[0] = Qinsert_file_contents, args[1] = orig_filename,
+ if (nread < 0)
+ error ("IO error reading %s: %s",
+ XSTRING (orig_filename)->data, strerror (errno));
+ else if (nread > 0)
+ {
+ int count = specpdl_ptr - specpdl;
+ struct buffer *prev = current_buffer;
+
+ 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;
+ 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--;
+
+ /* Rewind the file for the actual read done later. */
+ if (lseek (fd, 0, 0) < 0)
+ report_file_error ("Setting file position",
+ Fcons (orig_filename, Qnil));
+ }
+ }
+
+ if (NILP (val))
+ {
+ /* If we have not yet decided a coding system, check
+ file-coding-system-alist. */
+ Lisp_Object args[6], coding_systems;
+
+ args[0] = Qinsert_file_contents, args[1] = orig_filename;
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;
- }
- }
+ coding_systems = Ffind_operation_coding_system (6, args);
+ if (CONSP (coding_systems))
+ val = XCONS (coding_systems)->car;
+ }
+ }
- if (NILP (Vcoding_system_for_read)
- && NILP (current_buffer->enable_multibyte_characters))
- {
+ setup_coding_system (Fcheck_coding_system (val), &coding);
+
+ if (NILP (Vcoding_system_for_read)
+ && NILP (current_buffer->enable_multibyte_characters))
/* We must suppress all text conversion except for end-of-line
conversion. */
- struct coding_system coding_temp;
+ setup_raw_text_coding_system (&coding);
- setup_coding_system (Fcheck_coding_system (val), &coding_temp);
- setup_coding_system (Qraw_text, &coding);
- coding.eol_type = coding_temp.eol_type;
- }
- else
- setup_coding_system (Fcheck_coding_system (val), &coding);
- }
+ 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
But if we discover the need for conversion, we give up on this method
and let the following if-statement handle the replace job. */
if (!NILP (replace)
- && ! CODING_REQUIRE_DECODING (&coding))
+ && BEGV < ZV
+ && ! CODING_REQUIRE_DECODING (&coding)
+ && (coding.eol_type == CODING_EOL_UNDECIDED
+ || coding.eol_type == CODING_EOL_LF))
{
/* same_at_start and same_at_end count bytes,
because file access counts bytes
/* We win! We can handle REPLACE the optimized way. */
- /* Extends the end of non-matching text area to multibyte
+ /* Extend the start of non-matching text area to multibyte
+ character boundary. */
+ if (! NILP (current_buffer->enable_multibyte_characters))
+ while (same_at_start > BEGV_BYTE
+ && ! CHAR_HEAD_P (FETCH_BYTE (same_at_start)))
+ same_at_start--;
+
+ /* Extend the end of non-matching text area to multibyte
character boundary. */
if (! NILP (current_buffer->enable_multibyte_characters))
while (same_at_end < ZV_BYTE
is needed, in a simple way that needs a lot of memory.
The preceding if-statement handles the case of no conversion
in a more optimized way. */
- if (!NILP (replace) && ! replace_handled)
+ if (!NILP (replace) && ! replace_handled && BEGV < ZV)
{
int same_at_start = BEGV_BYTE;
int same_at_end = ZV_BYTE;
if (lseek (fd, XINT (beg), 0) < 0)
{
- free (conversion_buffer);
+ xfree (conversion_buffer);
report_file_error ("Setting file position",
Fcons (orig_filename, Qnil));
}
{
/* try is reserved in some compilers (Microsoft C) */
int trytry = min (total - how_much, READ_BUF_SIZE - unprocessed);
- char *destination = read_buf + unprocessed;
+ unsigned char *destination = read_buf + unprocessed;
int this;
/* Allow quitting out of the actual I/O. */
goto handled;
}
+ /* Extend the start of non-matching text area to multibyte
+ character boundary. */
+ if (! NILP (current_buffer->enable_multibyte_characters))
+ while (same_at_start > BEGV_BYTE
+ && ! CHAR_HEAD_P (FETCH_BYTE (same_at_start)))
+ same_at_start--;
+
/* Scan this bufferful from the end, comparing with
the Emacs buffer. */
bufpos = inserted;
&& FETCH_BYTE (same_at_end - 1) == conversion_buffer[bufpos - 1])
same_at_end--, bufpos--;
+ /* Extend the end of non-matching text area to multibyte
+ character boundary. */
+ if (! NILP (current_buffer->enable_multibyte_characters))
+ while (same_at_end < ZV_BYTE
+ && ! CHAR_HEAD_P (FETCH_BYTE (same_at_end)))
+ same_at_end++;
+
/* Don't try to reuse the same piece of text twice. */
overlap = same_at_start - BEGV_BYTE - (same_at_end + inserted - ZV_BYTE);
if (overlap > 0)
we are taking from the file. */
inserted -= (Z_BYTE - same_at_end) + (same_at_start - BEG_BYTE);
del_range_byte (same_at_start, same_at_end, 0);
- SET_PT_BOTH (GPT, GPT_BYTE);
+ if (same_at_end != same_at_start)
+ SET_PT_BOTH (GPT, GPT_BYTE);
+ else
+ {
+ /* Insert from the file at the proper position. */
+ temp = BYTE_TO_CHAR (same_at_start);
+ SET_PT_BOTH (temp, same_at_start);
+ }
insert_1 (conversion_buffer + same_at_start - BEG_BYTE, inserted,
0, 0, 0);
error ("IO error reading %s: %s",
XSTRING (orig_filename)->data, strerror (errno));
- if (inserted > 0)
+ if (! coding_system_decided)
+ {
+ /* The coding system is not yet decided. Decide it by an
+ optimized method for handling `coding:' tag. */
+ Lisp_Object val;
+ val = Qnil;
+
+ if (!NILP (Vcoding_system_for_read))
+ 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;
+ int count = specpdl_ptr - specpdl;
+
+ prev_multibyte = current_buffer->enable_multibyte_characters;
+ current_buffer->enable_multibyte_characters = Qnil;
+ record_unwind_protect (set_auto_coding_unwind,
+ prev_multibyte);
+ 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))
+ {
+ /* If the coding system is not yet decided, check
+ file-coding-system-alist. */
+ Lisp_Object args[6], coding_systems;
+
+ args[0] = Qinsert_file_contents, args[1] = orig_filename;
+ 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;
+ }
+ }
+
+ /* The following kludgy code is to avoid some compiler bug.
+ We can't simply do
+ setup_coding_system (val, &coding);
+ on some system. */
+ {
+ struct coding_system temp_coding;
+ setup_coding_system (val, &temp_coding);
+ bcopy (&temp_coding, &coding, sizeof coding);
+ }
+
+ if (NILP (Vcoding_system_for_read)
+ && NILP (current_buffer->enable_multibyte_characters))
+ /* We must suppress all text conversion except for
+ end-of-line conversion. */
+ setup_raw_text_coding_system (&coding);
+ }
+
+ 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)
{
int inserted_byte = inserted;
- /* At first, reset positions to the state of before
- insertion. */
- GAP_SIZE += inserted;
- GPT_BYTE -= inserted;
- ZV_BYTE -= inserted;
- Z_BYTE -= inserted;
- GPT -= inserted;
- ZV -= inserted;
- Z -= inserted;
-
- /* Then adjust positions. */
- inserted = multibyte_chars_in_text (GPT_ADDR, inserted);
- adjust_after_replace (PT, PT_BYTE, PT, PT_BYTE,
- inserted, inserted_byte);
+ /* 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);
}
-
-#ifdef DOS_NT
- /* Use the conversion type to determine buffer-file-type
- (find-buffer-file-type is now used to help determine the
- conversion). */
- if (coding.eol_type != CODING_EOL_UNDECIDED
- && coding.eol_type != CODING_EOL_LF)
- current_buffer->buffer_file_type = Qnil;
else
- current_buffer->buffer_file_type = Qt;
-#endif
+ adjust_after_insert (PT, PT_BYTE, PT + inserted, PT_BYTE + inserted,
+ inserted);
}
- set_coding_system = 1;
+#ifdef DOS_NT
+ /* Use the conversion type to determine buffer-file-type
+ (find-buffer-file-type is now used to help determine the
+ conversion). */
+ if ((coding.eol_type == CODING_EOL_UNDECIDED
+ || coding.eol_type == CODING_EOL_LF)
+ && ! CODING_REQUIRE_DECODING (&coding))
+ current_buffer->buffer_file_type = Qt;
+ else
+ current_buffer->buffer_file_type = Qnil;
+#endif
notfound:
handled:
The optional seventh arg CONFIRM, if non-nil, says ask for confirmation\n\
before overwriting an existing file.\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.")
+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, confirm)
Lisp_Object start, end, filename, append, visit, lockname, confirm;
{
val = Qnil;
else if (!NILP (Vcoding_system_for_write))
val = Vcoding_system_for_write;
- else if (NILP (current_buffer->enable_multibyte_characters))
+ else
{
/* If the variable `buffer-file-coding-system' is set locally,
it means that the file was read with some kind of code
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 (Flocal_variable_p (Qbuffer_file_coding_system, Qnil)))
+ if (NILP (val)
+ || NILP (Flocal_variable_p (Qbuffer_file_coding_system, Qnil)))
{
- struct coding_system coding_temp;
+ 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;
+ }
- setup_coding_system (Fcheck_coding_system (val), &coding_temp);
- if (coding_temp.eol_type == CODING_EOL_CRLF
- || coding_temp.eol_type == CODING_EOL_CR)
+ 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)
{
- setup_coding_system (Qraw_text, &coding);
- coding.eol_type = coding_temp.eol_type;
- goto done_setup_coding;
+ 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];
}
- val = Qnil;
}
+
+ if (force_raw_text)
+ setup_raw_text_coding_system (&coding);
+ goto done_setup_coding;
}
- else
- {
- 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);
- val = (CONSP (coding_systems) && !NILP (XCONS (coding_systems)->cdr)
- ? XCONS (coding_systems)->cdr
- : current_buffer->buffer_file_coding_system);
- /* Confirm that VAL can surely encode the current region. */
- if (Ffboundp (Vselect_safe_coding_system_function))
- val = call3 (Vselect_safe_coding_system_function, start, end, val);
- }
- setup_coding_system (Fcheck_coding_system (val), &coding);
+
+ setup_coding_system (Fcheck_coding_system (val), &coding);
done_setup_coding:
if (!STRINGP (start) && !NILP (current_buffer->selective_display))
filename = Fexpand_file_name (filename, Qnil);
if (! NILP (confirm))
- barf_or_query_if_file_exists (filename, "overwrite", 1, 0);
+ barf_or_query_if_file_exists (filename, "overwrite", 1, 0, 1);
if (STRINGP (visit))
visit_file = Fexpand_file_name (visit, Qnil);
record_unwind_protect (close_file_unwind, make_number (desc));
- if (!NILP (append))
+ if (!NILP (append) && !NILP (Ffile_regular_p (filename)))
if (lseek (desc, 0, 2) < 0)
{
#ifdef CLASH_DETECTION
if (STRINGP (start))
{
failure = 0 > a_write (desc, XSTRING (start)->data,
- XSTRING (start)->size_byte, 0, &annotations,
+ STRING_BYTES (XSTRING (start)), 0, &annotations,
&coding);
save_errno = errno;
}
tem = Fcdr (Fcar (*annot));
if (STRINGP (tem))
{
- if (0 > e_write (desc, XSTRING (tem)->data, XSTRING (tem)->size_byte,
+ if (0 > e_write (desc, XSTRING (tem)->data, STRING_BYTES (XSTRING (tem)),
coding))
return -1;
}
*annot = Fcdr (*annot);
}
+ return 0;
}
#ifndef WRITE_BUF_SIZE
now it is handled within encode_coding. */
while (1)
{
- encode_coding (coding, addr, buf, nbytes, WRITE_BUF_SIZE);
+ 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;
}
+ if (result == CODING_FINISH_INSUFFICIENT_SRC)
+ {
+ /* 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;
+ }
if (nbytes <= 0)
break;
}
if (!NILP (b->filename))
{
fwrite (XSTRING (b->filename)->data, 1,
- XSTRING (b->filename)->size_byte, stream);
+ STRING_BYTES (XSTRING (b->filename)), stream);
}
putc ('\n', stream);
fwrite (XSTRING (b->auto_save_file_name)->data, 1,
- XSTRING (b->auto_save_file_name)->size_byte, stream);
+ STRING_BYTES (XSTRING (b->auto_save_file_name)), stream);
putc ('\n', stream);
}
register int n;
int osize, count;
- osize = XSTRING (val)->size_byte;
+ osize = STRING_BYTES (XSTRING (val));
/* Count the number of $ characters. */
for (n = osize, count = 0, old = XSTRING (val)->data; n > 0; n--)
(prompt, dir, default_filename, mustmatch, initial)
Lisp_Object prompt, dir, default_filename, mustmatch, initial;
{
- Lisp_Object val, insdef, insdef1, tem;
+ Lisp_Object val, insdef, tem;
struct gcpro gcpro1, gcpro2;
register char *homedir;
int replace_in_history = 0;
&& IS_DIRECTORY_SEP (XSTRING (dir)->data[strlen (homedir)]))
{
dir = make_string (XSTRING (dir)->data + strlen (homedir) - 1,
- XSTRING (dir)->size_byte - strlen (homedir) + 1);
+ STRING_BYTES (XSTRING (dir)) - strlen (homedir) + 1);
XSTRING (dir)->data[0] = '~';
}
+ /* Likewise for default_filename. */
+ if (homedir != 0
+ && STRINGP (default_filename)
+ && !strncmp (homedir, XSTRING (default_filename)->data, strlen (homedir))
+ && IS_DIRECTORY_SEP (XSTRING (default_filename)->data[strlen (homedir)]))
+ {
+ default_filename
+ = make_string (XSTRING (default_filename)->data + strlen (homedir) - 1,
+ STRING_BYTES (XSTRING (default_filename)) - strlen (homedir) + 1);
+ XSTRING (default_filename)->data[0] = '~';
+ }
+ if (!NILP (default_filename))
+ default_filename = double_dollars (default_filename);
if (insert_default_directory && STRINGP (dir))
{
args[1] = initial;
insdef = Fconcat (2, args);
pos = make_number (XSTRING (double_dollars (dir))->size);
- insdef1 = Fcons (double_dollars (insdef), pos);
+ insdef = Fcons (double_dollars (insdef), pos);
}
else
- insdef1 = double_dollars (insdef);
+ insdef = double_dollars (insdef);
}
else if (STRINGP (initial))
- {
- insdef = initial;
- insdef1 = Fcons (double_dollars (insdef), make_number (0));
- }
+ insdef = Fcons (double_dollars (initial), make_number (0));
else
- insdef = Qnil, insdef1 = Qnil;
+ insdef = Qnil;
-#ifdef VMS
count = specpdl_ptr - specpdl;
+#ifdef VMS
specbind (intern ("completion-ignore-case"), Qt);
#endif
+ specbind (intern ("minibuffer-completing-file-name"), Qt);
+
GCPRO2 (insdef, default_filename);
val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
- dir, mustmatch, insdef1,
+ dir, mustmatch, insdef,
Qfile_name_history, default_filename, Qnil);
tem = Fsymbol_value (Qfile_name_history);
val = build_string ("");
}
-#ifdef VMS
unbind_to (count, Qnil);
-#endif
-
UNGCPRO;
if (NILP (val))
error ("No file name specified");
- tem = Fstring_equal (val, insdef);
+ tem = Fstring_equal (val, CONSP (insdef) ? XCAR (insdef) : insdef);
if (!NILP (tem) && !NILP (default_filename))
val = default_filename;
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 = val;
+ XCONS (Fsymbol_value (Qfile_name_history))->car = 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, val)))
+ if (! CONSP (tem) || NILP (Fequal (XCONS (tem)->car, val1)))
Fset (Qfile_name_history,
- Fcons (val, tem));
+ Fcons (val1, tem));
}
return val;
}
\f
+void
+init_fileio_once ()
+{
+ /* Must be set before any path manipulation is performed. */
+ XSETFASTINT (Vdirectory_sep_char, '/');
+}
+
+void
syms_of_fileio ()
{
Qexpand_file_name = intern ("expand-file-name");
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.");
- XSETFASTINT (Vdirectory_sep_char, '/');
DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist,
"*Alist of elements (REGEXP . HANDLER) for file names handled specially.\n\
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\
-One argument is passed to this function: the string of concatination\n\
-or the heading 1K-byte and the tailing 3K-byte of a file to be read.\n\
-This function should return a coding system to decode the file contents\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.");