* dired.c (directory_files_internal): Use SSET.
[bpt/emacs.git] / src / fileio.c
CommitLineData
570d7624 1/* File IO for GNU Emacs.
38119822 2 Copyright (C) 1985,86,87,88,93,94,95,96,97,98,99,2000, 2001
43fb7d9a 3 Free Software Foundation, Inc.
570d7624
JB
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
4746118a 9the Free Software Foundation; either version 2, or (at your option)
570d7624
JB
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
570d7624 21
07590973
DL
22#define _GNU_SOURCE /* for euidaccess */
23
18160b98 24#include <config.h>
570d7624 25
8a2a6032 26#if defined (USG5) || defined (BSD_SYSTEM) || defined (GNU_LINUX)
bb369dc6
RS
27#include <fcntl.h>
28#endif
29
1b335d29 30#include <stdio.h>
570d7624
JB
31#include <sys/types.h>
32#include <sys/stat.h>
bfb61299 33
29beb080
RS
34#ifdef HAVE_UNISTD_H
35#include <unistd.h>
36#endif
37
f73b0ada
BF
38#if !defined (S_ISLNK) && defined (S_IFLNK)
39# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
40#endif
41
bb369dc6
RS
42#if !defined (S_ISFIFO) && defined (S_IFIFO)
43# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
44#endif
45
f73b0ada
BF
46#if !defined (S_ISREG) && defined (S_IFREG)
47# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
48#endif
49
bfb61299 50#ifdef VMS
de5bf5d3 51#include "vms-pwd.h"
bfb61299 52#else
570d7624 53#include <pwd.h>
bfb61299
JB
54#endif
55
570d7624 56#include <ctype.h>
bfb61299
JB
57
58#ifdef VMS
3d9f5ce2 59#include "vmsdir.h"
bfb61299
JB
60#include <perror.h>
61#include <stddef.h>
62#include <string.h>
bfb61299
JB
63#endif
64
570d7624
JB
65#include <errno.h>
66
bfb61299 67#ifndef vax11c
f12ef5eb 68#ifndef USE_CRT_DLL
570d7624 69extern int errno;
570d7624 70#endif
f12ef5eb 71#endif
570d7624 72
570d7624
JB
73#ifdef APOLLO
74#include <sys/time.h>
75#endif
76
6e23c83e
JB
77#ifndef USG
78#ifndef VMS
79#ifndef BSD4_1
5e570b75 80#ifndef WINDOWSNT
6e23c83e
JB
81#define HAVE_FSYNC
82#endif
83#endif
84#endif
5e570b75 85#endif
6e23c83e 86
570d7624 87#include "lisp.h"
8d4e077b 88#include "intervals.h"
570d7624 89#include "buffer.h"
6fdaa9a0
KH
90#include "charset.h"
91#include "coding.h"
570d7624
JB
92#include "window.h"
93
5e570b75
RS
94#ifdef WINDOWSNT
95#define NOMINMAX 1
96#include <windows.h>
97#include <stdlib.h>
98#include <fcntl.h>
99#endif /* not WINDOWSNT */
100
7990d02a
EZ
101#ifdef MSDOS
102#include "msdos.h"
103#include <sys/param.h>
104#if __DJGPP__ >= 2
105#include <fcntl.h>
106#include <string.h>
107#endif
108#endif
109
199607e4
RS
110#ifdef DOS_NT
111#define CORRECT_DIR_SEPS(s) \
112 do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \
113 else unixtodos_filename (s); \
114 } while (0)
115/* On Windows, drive letters must be alphabetic - on DOS, the Netware
116 redirector allows the six letters between 'Z' and 'a' as well. */
117#ifdef MSDOS
118#define IS_DRIVE(x) ((x) >= 'A' && (x) <= 'z')
119#endif
120#ifdef WINDOWSNT
121#define IS_DRIVE(x) isalpha (x)
122#endif
f54b565c
MB
123/* Need to lower-case the drive letter, or else expanded
124 filenames will sometimes compare inequal, because
125 `expand-file-name' doesn't always down-case the drive letter. */
126#define DRIVE_LETTER(x) (tolower (x))
199607e4
RS
127#endif
128
570d7624 129#ifdef VMS
570d7624
JB
130#include <file.h>
131#include <rmsdef.h>
132#include <fab.h>
133#include <nam.h>
134#endif
135
de5bf5d3 136#include "systime.h"
570d7624
JB
137
138#ifdef HPUX
139#include <netio.h>
9b7828a5 140#ifndef HPUX8
47e7b9e5 141#ifndef HPUX9
570d7624
JB
142#include <errnet.h>
143#endif
9b7828a5 144#endif
47e7b9e5 145#endif
570d7624 146
9c856db9
GM
147#include "commands.h"
148extern int use_dialog_box;
149
570d7624
JB
150#ifndef O_WRONLY
151#define O_WRONLY 1
152#endif
153
4018b5ef
RS
154#ifndef O_RDONLY
155#define O_RDONLY 0
156#endif
157
8f6df9b5
EZ
158#ifndef S_ISLNK
159# define lstat stat
160#endif
161
570d7624
JB
162/* Nonzero during writing of auto-save files */
163int auto_saving;
164
165/* Set by auto_save_1 to mode of original file so Fwrite_region will create
166 a new file with the same mode as the original */
167int auto_save_mode_bits;
168
b1d1b865
RS
169/* Coding system for file names, or nil if none. */
170Lisp_Object Vfile_name_coding_system;
171
cd913586
KH
172/* Coding system for file names used only when
173 Vfile_name_coding_system is nil. */
174Lisp_Object Vdefault_file_name_coding_system;
175
199607e4 176/* Alist of elements (REGEXP . HANDLER) for file names
32f4334d
RS
177 whose I/O is done with a special handler. */
178Lisp_Object Vfile_name_handler_alist;
179
0d420e88
BG
180/* Format for auto-save files */
181Lisp_Object Vauto_save_file_format;
182
183/* Lisp functions for translating file formats */
184Lisp_Object Qformat_decode, Qformat_annotate_function;
185
c9e82392 186/* Function to be called to decide a coding system of a reading file. */
0414b394 187Lisp_Object Vset_auto_coding_function;
c9e82392 188
d6a3cc15
RS
189/* Functions to be called to process text properties in inserted file. */
190Lisp_Object Vafter_insert_file_functions;
191
192/* Functions to be called to create text property annotations for file. */
193Lisp_Object Vwrite_region_annotate_functions;
194
6fc6f94b
RS
195/* During build_annotations, each time an annotation function is called,
196 this holds the annotations made by the previous functions. */
197Lisp_Object Vwrite_region_annotations_so_far;
198
e54d3b5d
RS
199/* File name in which we write a list of all our auto save files. */
200Lisp_Object Vauto_save_list_file_name;
201
59ffe07d
KS
202/* Function to call to read a file name. */
203Lisp_Object Vread_file_name_function;
204
205/* Current predicate used by read_file_name_internal. */
206Lisp_Object Vread_file_name_predicate;
207
570d7624
JB
208/* Nonzero means, when reading a filename in the minibuffer,
209 start out by inserting the default directory into the minibuffer. */
210int insert_default_directory;
211
212/* On VMS, nonzero means write new files with record format stmlf.
213 Zero means use var format. */
214int vms_stmlf_recfm;
215
199607e4
RS
216/* On NT, specifies the directory separator character, used (eg.) when
217 expanding file names. This can be bound to / or \. */
218Lisp_Object Vdirectory_sep_char;
219
84f6296a
RS
220extern Lisp_Object Vuser_login_name;
221
c1c4693e
RS
222#ifdef WINDOWSNT
223extern Lisp_Object Vw32_get_true_file_attributes;
224#endif
225
84f6296a
RS
226extern int minibuf_level;
227
a8c828be
RS
228extern int minibuffer_auto_raise;
229
a65970a0
RS
230/* These variables describe handlers that have "already" had a chance
231 to handle the current operation.
232
233 Vinhibit_file_name_handlers is a list of file name handlers.
234 Vinhibit_file_name_operation is the operation being handled.
235 If we try to handle that operation, we ignore those handlers. */
236
82c2d839 237static Lisp_Object Vinhibit_file_name_handlers;
a65970a0 238static Lisp_Object Vinhibit_file_name_operation;
82c2d839 239
c0b7b21c 240Lisp_Object Qfile_error, Qfile_already_exists, Qfile_date_error;
505ab9bc 241Lisp_Object Qexcl;
15c65264
RS
242Lisp_Object Qfile_name_history;
243
d6a3cc15
RS
244Lisp_Object Qcar_less_than_car;
245
ce51c54c 246static int a_write P_ ((int, Lisp_Object, int, int,
b9013200 247 Lisp_Object *, struct coding_system *));
ce51c54c
KH
248static int e_write P_ ((int, Lisp_Object, int, int, struct coding_system *));
249
ec7adf26 250\f
5d01d666 251void
570d7624
JB
252report_file_error (string, data)
253 char *string;
254 Lisp_Object data;
255{
256 Lisp_Object errstring;
505ab9bc 257 int errorno = errno;
570d7624 258
ca9c0567 259 synchronize_system_messages_locale ();
68c45bf0
PE
260 errstring = code_convert_string_norecord (build_string (strerror (errorno)),
261 Vlocale_coding_system, 0);
262
570d7624 263 while (1)
505ab9bc
RS
264 switch (errorno)
265 {
266 case EEXIST:
267 Fsignal (Qfile_already_exists, Fcons (errstring, data));
268 break;
269 default:
270 /* System error messages are capitalized. Downcase the initial
271 unless it is followed by a slash. */
d5db4077
KR
272 if (SREF (errstring, 1) != '/')
273 SREF (errstring, 0) = DOWNCASE (SREF (errstring, 0));
505ab9bc
RS
274
275 Fsignal (Qfile_error,
276 Fcons (build_string (string), Fcons (errstring, data)));
277 }
570d7624 278}
b5148e85 279
b27a1703 280Lisp_Object
b5148e85
RS
281close_file_unwind (fd)
282 Lisp_Object fd;
283{
68c45bf0 284 emacs_close (XFASTINT (fd));
b27a1703 285 return Qnil;
b5148e85 286}
a1d2b64a
RS
287
288/* Restore point, having saved it as a marker. */
289
ec7adf26 290static Lisp_Object
a1d2b64a 291restore_point_unwind (location)
199607e4 292 Lisp_Object location;
a1d2b64a 293{
ec7adf26 294 Fgoto_char (location);
a1d2b64a 295 Fset_marker (location, Qnil, Qnil);
b27a1703 296 return Qnil;
a1d2b64a 297}
570d7624 298\f
0bf2eed2 299Lisp_Object Qexpand_file_name;
273e0829 300Lisp_Object Qsubstitute_in_file_name;
0bf2eed2
RS
301Lisp_Object Qdirectory_file_name;
302Lisp_Object Qfile_name_directory;
303Lisp_Object Qfile_name_nondirectory;
642ef245 304Lisp_Object Qunhandled_file_name_directory;
0bf2eed2 305Lisp_Object Qfile_name_as_directory;
32f4334d 306Lisp_Object Qcopy_file;
a6e6e718 307Lisp_Object Qmake_directory_internal;
b272d624 308Lisp_Object Qmake_directory;
32f4334d
RS
309Lisp_Object Qdelete_directory;
310Lisp_Object Qdelete_file;
311Lisp_Object Qrename_file;
312Lisp_Object Qadd_name_to_file;
313Lisp_Object Qmake_symbolic_link;
314Lisp_Object Qfile_exists_p;
315Lisp_Object Qfile_executable_p;
316Lisp_Object Qfile_readable_p;
32f4334d 317Lisp_Object Qfile_writable_p;
1f8653eb
RS
318Lisp_Object Qfile_symlink_p;
319Lisp_Object Qaccess_file;
32f4334d 320Lisp_Object Qfile_directory_p;
adedc71d 321Lisp_Object Qfile_regular_p;
32f4334d
RS
322Lisp_Object Qfile_accessible_directory_p;
323Lisp_Object Qfile_modes;
324Lisp_Object Qset_file_modes;
325Lisp_Object Qfile_newer_than_file_p;
326Lisp_Object Qinsert_file_contents;
327Lisp_Object Qwrite_region;
328Lisp_Object Qverify_visited_file_modtime;
3ec46acd 329Lisp_Object Qset_visited_file_modtime;
32f4334d 330
49307295 331DEFUN ("find-file-name-handler", Ffind_file_name_handler, Sfind_file_name_handler, 2, 2, 0,
8c1a1077
PJ
332 doc: /* Return FILENAME's handler function for OPERATION, if it has one.
333Otherwise, return nil.
334A file name is handled if one of the regular expressions in
335`file-name-handler-alist' matches it.
336
337If OPERATION equals `inhibit-file-name-operation', then we ignore
338any handlers that are members of `inhibit-file-name-handlers',
339but we still do run any other handlers. This lets handlers
340use the standard functions without calling themselves recursively. */)
341 (filename, operation)
342 Lisp_Object filename, operation;
32f4334d 343{
642ef245 344 /* This function must not munge the match data. */
204ee271 345 Lisp_Object chain, inhibited_handlers, result;
8d2ced53 346 int pos = -1;
642ef245 347
204ee271 348 result = Qnil;
b7826503 349 CHECK_STRING (filename);
e4432095 350
a65970a0
RS
351 if (EQ (operation, Vinhibit_file_name_operation))
352 inhibited_handlers = Vinhibit_file_name_handlers;
353 else
354 inhibited_handlers = Qnil;
82c2d839 355
93c30b5f 356 for (chain = Vfile_name_handler_alist; CONSP (chain);
03699b14 357 chain = XCDR (chain))
32f4334d
RS
358 {
359 Lisp_Object elt;
03699b14 360 elt = XCAR (chain);
93c30b5f 361 if (CONSP (elt))
32f4334d
RS
362 {
363 Lisp_Object string;
8d2ced53 364 int match_pos;
03699b14 365 string = XCAR (elt);
8d2ced53
SM
366 if (STRINGP (string)
367 && (match_pos = fast_string_match (string, filename)) > pos)
a65970a0
RS
368 {
369 Lisp_Object handler, tem;
370
03699b14 371 handler = XCDR (elt);
a65970a0
RS
372 tem = Fmemq (handler, inhibited_handlers);
373 if (NILP (tem))
8d2ced53
SM
374 {
375 result = handler;
376 pos = match_pos;
377 }
a65970a0 378 }
32f4334d 379 }
642ef245
JB
380
381 QUIT;
32f4334d 382 }
8d2ced53 383 return result;
32f4334d
RS
384}
385\f
570d7624 386DEFUN ("file-name-directory", Ffile_name_directory, Sfile_name_directory,
8c1a1077
PJ
387 1, 1, 0,
388 doc: /* Return the directory component in file name FILENAME.
389Return nil if FILENAME does not include a directory.
390Otherwise return a directory spec.
391Given a Unix syntax file name, returns a string ending in slash;
392on VMS, perhaps instead a string ending in `:', `]' or `>'. */)
393 (filename)
3b7f6e60 394 Lisp_Object filename;
570d7624
JB
395{
396 register unsigned char *beg;
397 register unsigned char *p;
0bf2eed2 398 Lisp_Object handler;
570d7624 399
b7826503 400 CHECK_STRING (filename);
570d7624 401
0bf2eed2
RS
402 /* If the file name has special constructs in it,
403 call the corresponding file handler. */
3b7f6e60 404 handler = Ffind_file_name_handler (filename, Qfile_name_directory);
0bf2eed2 405 if (!NILP (handler))
3b7f6e60 406 return call2 (handler, Qfile_name_directory, filename);
0bf2eed2 407
4c3c22f3 408#ifdef FILE_SYSTEM_CASE
3b7f6e60 409 filename = FILE_SYSTEM_CASE (filename);
4c3c22f3 410#endif
d5db4077 411 beg = SDATA (filename);
199607e4
RS
412#ifdef DOS_NT
413 beg = strcpy (alloca (strlen (beg) + 1), beg);
414#endif
d5db4077 415 p = beg + SBYTES (filename);
570d7624 416
199607e4 417 while (p != beg && !IS_DIRECTORY_SEP (p[-1])
570d7624
JB
418#ifdef VMS
419 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
420#endif /* VMS */
199607e4 421#ifdef DOS_NT
ba14e174
RS
422 /* only recognise drive specifier at the beginning */
423 && !(p[-1] == ':'
424 /* handle the "/:d:foo" and "/:foo" cases correctly */
425 && ((p == beg + 2 && !IS_DIRECTORY_SEP (*beg))
426 || (p == beg + 4 && IS_DIRECTORY_SEP (*beg))))
199607e4 427#endif
570d7624
JB
428 ) p--;
429
430 if (p == beg)
431 return Qnil;
5e570b75 432#ifdef DOS_NT
4c3c22f3 433 /* Expansion of "c:" to drive and default directory. */
ba14e174 434 if (p[-1] == ':')
4c3c22f3 435 {
4c3c22f3 436 /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */
199607e4 437 unsigned char *res = alloca (MAXPATHLEN + 1);
ba14e174
RS
438 unsigned char *r = res;
439
440 if (p == beg + 4 && IS_DIRECTORY_SEP (*beg) && beg[1] == ':')
441 {
442 strncpy (res, beg, 2);
443 beg += 2;
444 r += 2;
445 }
446
447 if (getdefdir (toupper (*beg) - 'A' + 1, r))
4c3c22f3 448 {
199607e4 449 if (!IS_DIRECTORY_SEP (res[strlen (res) - 1]))
4c3c22f3
RS
450 strcat (res, "/");
451 beg = res;
452 p = beg + strlen (beg);
453 }
454 }
199607e4 455 CORRECT_DIR_SEPS (beg);
5e570b75 456#endif /* DOS_NT */
60d67b83
RS
457
458 if (STRING_MULTIBYTE (filename))
459 return make_string (beg, p - beg);
460 return make_unibyte_string (beg, p - beg);
570d7624
JB
461}
462
60d67b83
RS
463DEFUN ("file-name-nondirectory", Ffile_name_nondirectory,
464 Sfile_name_nondirectory, 1, 1, 0,
8c1a1077
PJ
465 doc: /* Return file name FILENAME sans its directory.
466For example, in a Unix-syntax file name,
467this is everything after the last slash,
468or the entire name if it contains no slash. */)
469 (filename)
3b7f6e60 470 Lisp_Object filename;
570d7624
JB
471{
472 register unsigned char *beg, *p, *end;
0bf2eed2 473 Lisp_Object handler;
570d7624 474
b7826503 475 CHECK_STRING (filename);
570d7624 476
0bf2eed2
RS
477 /* If the file name has special constructs in it,
478 call the corresponding file handler. */
3b7f6e60 479 handler = Ffind_file_name_handler (filename, Qfile_name_nondirectory);
0bf2eed2 480 if (!NILP (handler))
3b7f6e60 481 return call2 (handler, Qfile_name_nondirectory, filename);
0bf2eed2 482
d5db4077
KR
483 beg = SDATA (filename);
484 end = p = beg + SBYTES (filename);
570d7624 485
199607e4 486 while (p != beg && !IS_DIRECTORY_SEP (p[-1])
570d7624
JB
487#ifdef VMS
488 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
489#endif /* VMS */
199607e4
RS
490#ifdef DOS_NT
491 /* only recognise drive specifier at beginning */
ba14e174
RS
492 && !(p[-1] == ':'
493 /* handle the "/:d:foo" case correctly */
494 && (p == beg + 2 || (p == beg + 4 && IS_DIRECTORY_SEP (*beg))))
199607e4 495#endif
60d67b83
RS
496 )
497 p--;
570d7624 498
60d67b83
RS
499 if (STRING_MULTIBYTE (filename))
500 return make_string (p, end - p);
501 return make_unibyte_string (p, end - p);
570d7624 502}
642ef245 503
60d67b83
RS
504DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory,
505 Sunhandled_file_name_directory, 1, 1, 0,
8c1a1077
PJ
506 doc: /* Return a directly usable directory name somehow associated with FILENAME.
507A `directly usable' directory name is one that may be used without the
508intervention of any file handler.
509If FILENAME is a directly usable file itself, return
510\(file-name-directory FILENAME).
511The `call-process' and `start-process' functions use this function to
512get a current directory to run processes in. */)
513 (filename)
514 Lisp_Object filename;
642ef245
JB
515{
516 Lisp_Object handler;
517
518 /* If the file name has special constructs in it,
519 call the corresponding file handler. */
49307295 520 handler = Ffind_file_name_handler (filename, Qunhandled_file_name_directory);
642ef245
JB
521 if (!NILP (handler))
522 return call2 (handler, Qunhandled_file_name_directory, filename);
523
524 return Ffile_name_directory (filename);
525}
526
570d7624
JB
527\f
528char *
529file_name_as_directory (out, in)
530 char *out, *in;
531{
532 int size = strlen (in) - 1;
533
534 strcpy (out, in);
535
8aa3a244
RS
536 if (size < 0)
537 {
154a307d
KH
538 out[0] = '.';
539 out[1] = '/';
540 out[2] = 0;
8aa3a244
RS
541 return out;
542 }
543
570d7624
JB
544#ifdef VMS
545 /* Is it already a directory string? */
546 if (in[size] == ':' || in[size] == ']' || in[size] == '>')
547 return out;
548 /* Is it a VMS directory file name? If so, hack VMS syntax. */
549 else if (! index (in, '/')
550 && ((size > 3 && ! strcmp (&in[size - 3], ".DIR"))
551 || (size > 3 && ! strcmp (&in[size - 3], ".dir"))
552 || (size > 5 && (! strncmp (&in[size - 5], ".DIR", 4)
553 || ! strncmp (&in[size - 5], ".dir", 4))
554 && (in[size - 1] == '.' || in[size - 1] == ';')
555 && in[size] == '1')))
556 {
557 register char *p, *dot;
558 char brack;
559
560 /* x.dir -> [.x]
561 dir:x.dir --> dir:[x]
562 dir:[x]y.dir --> dir:[x.y] */
563 p = in + size;
564 while (p != in && *p != ':' && *p != '>' && *p != ']') p--;
565 if (p != in)
566 {
567 strncpy (out, in, p - in);
568 out[p - in] = '\0';
569 if (*p == ':')
570 {
571 brack = ']';
572 strcat (out, ":[");
573 }
574 else
575 {
576 brack = *p;
577 strcat (out, ".");
578 }
579 p++;
580 }
581 else
582 {
583 brack = ']';
584 strcpy (out, "[.");
585 }
bfb61299
JB
586 dot = index (p, '.');
587 if (dot)
570d7624
JB
588 {
589 /* blindly remove any extension */
590 size = strlen (out) + (dot - p);
591 strncat (out, p, dot - p);
592 }
593 else
594 {
595 strcat (out, p);
596 size = strlen (out);
597 }
598 out[size++] = brack;
599 out[size] = '\0';
600 }
601#else /* not VMS */
602 /* For Unix syntax, Append a slash if necessary */
199607e4 603 if (!IS_DIRECTORY_SEP (out[size]))
5e570b75
RS
604 {
605 out[size + 1] = DIRECTORY_SEP;
606 out[size + 2] = '\0';
607 }
199607e4
RS
608#ifdef DOS_NT
609 CORRECT_DIR_SEPS (out);
610#endif
570d7624
JB
611#endif /* not VMS */
612 return out;
613}
614
615DEFUN ("file-name-as-directory", Ffile_name_as_directory,
616 Sfile_name_as_directory, 1, 1, 0,
8c1a1077
PJ
617 doc: /* Return a string representing file FILENAME interpreted as a directory.
618This operation exists because a directory is also a file, but its name as
619a directory is different from its name as a file.
620The result can be used as the value of `default-directory'
621or passed as second argument to `expand-file-name'.
622For a Unix-syntax file name, just appends a slash.
623On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc. */)
624 (file)
570d7624
JB
625 Lisp_Object file;
626{
627 char *buf;
0bf2eed2 628 Lisp_Object handler;
570d7624 629
b7826503 630 CHECK_STRING (file);
265a9e55 631 if (NILP (file))
570d7624 632 return Qnil;
0bf2eed2
RS
633
634 /* If the file name has special constructs in it,
635 call the corresponding file handler. */
49307295 636 handler = Ffind_file_name_handler (file, Qfile_name_as_directory);
0bf2eed2
RS
637 if (!NILP (handler))
638 return call2 (handler, Qfile_name_as_directory, file);
639
d5db4077
KR
640 buf = (char *) alloca (SBYTES (file) + 10);
641 return build_string (file_name_as_directory (buf, SDATA (file)));
570d7624
JB
642}
643\f
644/*
645 * Convert from directory name to filename.
646 * On VMS:
647 * xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
648 * xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
199607e4 649 * On UNIX, it's simple: just make sure there isn't a terminating /
570d7624
JB
650
651 * Value is nonzero if the string output is different from the input.
652 */
653
dfcf069d 654int
570d7624
JB
655directory_file_name (src, dst)
656 char *src, *dst;
657{
658 long slen;
659#ifdef VMS
660 long rlen;
661 char * ptr, * rptr;
662 char bracket;
663 struct FAB fab = cc$rms_fab;
664 struct NAM nam = cc$rms_nam;
665 char esa[NAM$C_MAXRSS];
666#endif /* VMS */
667
668 slen = strlen (src);
669#ifdef VMS
670 if (! index (src, '/')
671 && (src[slen - 1] == ']'
672 || src[slen - 1] == ':'
673 || src[slen - 1] == '>'))
674 {
675 /* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */
676 fab.fab$l_fna = src;
677 fab.fab$b_fns = slen;
678 fab.fab$l_nam = &nam;
679 fab.fab$l_fop = FAB$M_NAM;
680
681 nam.nam$l_esa = esa;
682 nam.nam$b_ess = sizeof esa;
683 nam.nam$b_nop |= NAM$M_SYNCHK;
684
685 /* We call SYS$PARSE to handle such things as [--] for us. */
199607e4 686 if (SYS$PARSE (&fab, 0, 0) == RMS$_NORMAL)
570d7624
JB
687 {
688 slen = nam.nam$b_esl;
689 if (esa[slen - 1] == ';' && esa[slen - 2] == '.')
690 slen -= 2;
691 esa[slen] = '\0';
692 src = esa;
693 }
694 if (src[slen - 1] != ']' && src[slen - 1] != '>')
695 {
696 /* what about when we have logical_name:???? */
697 if (src[slen - 1] == ':')
5e570b75 698 { /* Xlate logical name and see what we get */
570d7624
JB
699 ptr = strcpy (dst, src); /* upper case for getenv */
700 while (*ptr)
701 {
702 if ('a' <= *ptr && *ptr <= 'z')
703 *ptr -= 040;
704 ptr++;
705 }
5e570b75 706 dst[slen - 1] = 0; /* remove colon */
570d7624
JB
707 if (!(src = egetenv (dst)))
708 return 0;
709 /* should we jump to the beginning of this procedure?
710 Good points: allows us to use logical names that xlate
711 to Unix names,
712 Bad points: can be a problem if we just translated to a device
713 name...
714 For now, I'll punt and always expect VMS names, and hope for
715 the best! */
716 slen = strlen (src);
717 if (src[slen - 1] != ']' && src[slen - 1] != '>')
718 { /* no recursion here! */
719 strcpy (dst, src);
720 return 0;
721 }
722 }
723 else
5e570b75 724 { /* not a directory spec */
570d7624
JB
725 strcpy (dst, src);
726 return 0;
727 }
728 }
729 bracket = src[slen - 1];
730
731 /* If bracket is ']' or '>', bracket - 2 is the corresponding
732 opening bracket. */
bfb61299
JB
733 ptr = index (src, bracket - 2);
734 if (ptr == 0)
570d7624
JB
735 { /* no opening bracket */
736 strcpy (dst, src);
737 return 0;
738 }
739 if (!(rptr = rindex (src, '.')))
740 rptr = ptr;
741 slen = rptr - src;
742 strncpy (dst, src, slen);
743 dst[slen] = '\0';
744 if (*rptr == '.')
745 {
746 dst[slen++] = bracket;
747 dst[slen] = '\0';
748 }
749 else
750 {
751 /* If we have the top-level of a rooted directory (i.e. xx:[000000]),
752 then translate the device and recurse. */
753 if (dst[slen - 1] == ':'
5e570b75 754 && dst[slen - 2] != ':' /* skip decnet nodes */
199607e4 755 && strcmp (src + slen, "[000000]") == 0)
570d7624
JB
756 {
757 dst[slen - 1] = '\0';
758 if ((ptr = egetenv (dst))
759 && (rlen = strlen (ptr) - 1) > 0
760 && (ptr[rlen] == ']' || ptr[rlen] == '>')
761 && ptr[rlen - 1] == '.')
762 {
72b21817
RS
763 char * buf = (char *) alloca (strlen (ptr) + 1);
764 strcpy (buf, ptr);
765 buf[rlen - 1] = ']';
766 buf[rlen] = '\0';
767 return directory_file_name (buf, dst);
570d7624
JB
768 }
769 else
770 dst[slen - 1] = ':';
771 }
772 strcat (dst, "[000000]");
773 slen += 8;
774 }
775 rptr++;
776 rlen = strlen (rptr) - 1;
777 strncat (dst, rptr, rlen);
778 dst[slen + rlen] = '\0';
779 strcat (dst, ".DIR.1");
780 return 1;
781 }
782#endif /* VMS */
783 /* Process as Unix format: just remove any final slash.
784 But leave "/" unchanged; do not change it to "". */
785 strcpy (dst, src);
125feee8
RS
786#ifdef APOLLO
787 /* Handle // as root for apollo's. */
788 if ((slen > 2 && dst[slen - 1] == '/')
789 || (slen > 1 && dst[0] != '/' && dst[slen - 1] == '/'))
790 dst[slen - 1] = 0;
791#else
199607e4 792 if (slen > 1
5e570b75 793 && IS_DIRECTORY_SEP (dst[slen - 1])
4592782e
RS
794#ifdef DOS_NT
795 && !IS_ANY_SEP (dst[slen - 2])
796#endif
797 )
570d7624 798 dst[slen - 1] = 0;
199607e4
RS
799#endif
800#ifdef DOS_NT
801 CORRECT_DIR_SEPS (dst);
125feee8 802#endif
570d7624
JB
803 return 1;
804}
805
806DEFUN ("directory-file-name", Fdirectory_file_name, Sdirectory_file_name,
8c1a1077
PJ
807 1, 1, 0,
808 doc: /* Returns the file name of the directory named DIRECTORY.
809This is the name of the file that holds the data for the directory DIRECTORY.
810This operation exists because a directory is also a file, but its name as
811a directory is different from its name as a file.
812In Unix-syntax, this function just removes the final slash.
813On VMS, given a VMS-syntax directory name such as \"[X.Y]\",
814it returns a file name such as \"[X]Y.DIR.1\". */)
815 (directory)
570d7624
JB
816 Lisp_Object directory;
817{
818 char *buf;
0bf2eed2 819 Lisp_Object handler;
570d7624 820
b7826503 821 CHECK_STRING (directory);
570d7624 822
265a9e55 823 if (NILP (directory))
570d7624 824 return Qnil;
0bf2eed2
RS
825
826 /* If the file name has special constructs in it,
827 call the corresponding file handler. */
49307295 828 handler = Ffind_file_name_handler (directory, Qdirectory_file_name);
0bf2eed2
RS
829 if (!NILP (handler))
830 return call2 (handler, Qdirectory_file_name, directory);
831
570d7624
JB
832#ifdef VMS
833 /* 20 extra chars is insufficient for VMS, since we might perform a
834 logical name translation. an equivalence string can be up to 255
835 chars long, so grab that much extra space... - sss */
d5db4077 836 buf = (char *) alloca (SBYTES (directory) + 20 + 255);
570d7624 837#else
d5db4077 838 buf = (char *) alloca (SBYTES (directory) + 20);
570d7624 839#endif
d5db4077 840 directory_file_name (SDATA (directory), buf);
570d7624
JB
841 return build_string (buf);
842}
843
3ce839e4
RS
844static char make_temp_name_tbl[64] =
845{
846 'A','B','C','D','E','F','G','H',
847 'I','J','K','L','M','N','O','P',
848 'Q','R','S','T','U','V','W','X',
849 'Y','Z','a','b','c','d','e','f',
850 'g','h','i','j','k','l','m','n',
851 'o','p','q','r','s','t','u','v',
852 'w','x','y','z','0','1','2','3',
853 '4','5','6','7','8','9','-','_'
854};
cb613bb8 855
3ce839e4
RS
856static unsigned make_temp_name_count, make_temp_name_count_initialized_p;
857
cb613bb8
GM
858/* Value is a temporary file name starting with PREFIX, a string.
859
860 The Emacs process number forms part of the result, so there is
861 no danger of generating a name being used by another process.
862 In addition, this function makes an attempt to choose a name
863 which has no existing file. To make this work, PREFIX should be
864 an absolute file name.
865
866 BASE64_P non-zero means add the pid as 3 characters in base64
867 encoding. In this case, 6 characters will be added to PREFIX to
868 form the file name. Otherwise, if Emacs is running on a system
869 with long file names, add the pid as a decimal number.
870
871 This function signals an error if no unique file name could be
872 generated. */
873
874Lisp_Object
875make_temp_name (prefix, base64_p)
570d7624 876 Lisp_Object prefix;
cb613bb8 877 int base64_p;
570d7624
JB
878{
879 Lisp_Object val;
3ce839e4
RS
880 int len;
881 int pid;
882 unsigned char *p, *data;
883 char pidbuf[20];
884 int pidlen;
cb613bb8 885
b7826503 886 CHECK_STRING (prefix);
3ce839e4
RS
887
888 /* VAL is created by adding 6 characters to PREFIX. The first
889 three are the PID of this process, in base 64, and the second
890 three are incremented if the file already exists. This ensures
891 262144 unique file names per PID per PREFIX. */
892
893 pid = (int) getpid ();
894
cb613bb8
GM
895 if (base64_p)
896 {
897 pidbuf[0] = make_temp_name_tbl[pid & 63], pid >>= 6;
898 pidbuf[1] = make_temp_name_tbl[pid & 63], pid >>= 6;
899 pidbuf[2] = make_temp_name_tbl[pid & 63], pid >>= 6;
900 pidlen = 3;
901 }
902 else
903 {
3ce839e4 904#ifdef HAVE_LONG_FILE_NAMES
cb613bb8
GM
905 sprintf (pidbuf, "%d", pid);
906 pidlen = strlen (pidbuf);
3a3bfb18 907#else
cb613bb8
GM
908 pidbuf[0] = make_temp_name_tbl[pid & 63], pid >>= 6;
909 pidbuf[1] = make_temp_name_tbl[pid & 63], pid >>= 6;
910 pidbuf[2] = make_temp_name_tbl[pid & 63], pid >>= 6;
911 pidlen = 3;
3ce839e4 912#endif
cb613bb8
GM
913 }
914
d5db4077 915 len = SCHARS (prefix);
3ce839e4 916 val = make_uninit_string (len + 3 + pidlen);
d5db4077
KR
917 data = SDATA (val);
918 bcopy(SDATA (prefix), data, len);
3ce839e4
RS
919 p = data + len;
920
921 bcopy (pidbuf, p, pidlen);
922 p += pidlen;
923
924 /* Here we try to minimize useless stat'ing when this function is
925 invoked many times successively with the same PREFIX. We achieve
926 this by initializing count to a random value, and incrementing it
f6a492a9
RS
927 afterwards.
928
929 We don't want make-temp-name to be called while dumping,
930 because then make_temp_name_count_initialized_p would get set
931 and then make_temp_name_count would not be set when Emacs starts. */
932
3ce839e4
RS
933 if (!make_temp_name_count_initialized_p)
934 {
935 make_temp_name_count = (unsigned) time (NULL);
936 make_temp_name_count_initialized_p = 1;
937 }
938
939 while (1)
940 {
941 struct stat ignored;
8a7777fc 942 unsigned num = make_temp_name_count;
3ce839e4
RS
943
944 p[0] = make_temp_name_tbl[num & 63], num >>= 6;
945 p[1] = make_temp_name_tbl[num & 63], num >>= 6;
946 p[2] = make_temp_name_tbl[num & 63], num >>= 6;
947
8a7777fc
RS
948 /* Poor man's congruential RN generator. Replace with
949 ++make_temp_name_count for debugging. */
950 make_temp_name_count += 25229;
951 make_temp_name_count %= 225307;
952
3ce839e4
RS
953 if (stat (data, &ignored) < 0)
954 {
955 /* We want to return only if errno is ENOENT. */
956 if (errno == ENOENT)
957 return val;
958 else
959 /* The error here is dubious, but there is little else we
960 can do. The alternatives are to return nil, which is
961 as bad as (and in many cases worse than) throwing the
962 error, or to ignore the error, which will likely result
8a7777fc
RS
963 in looping through 225307 stat's, which is not only
964 dog-slow, but also useless since it will fallback to
965 the errow below, anyway. */
9869bb0b 966 report_file_error ("Cannot create temporary name for prefix",
3ce839e4
RS
967 Fcons (prefix, Qnil));
968 /* not reached */
969 }
970 }
971
972 error ("Cannot create temporary name for prefix `%s'",
d5db4077 973 SDATA (prefix));
3ce839e4 974 return Qnil;
570d7624 975}
3ce839e4 976
cb613bb8
GM
977
978DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0,
8c1a1077
PJ
979 doc: /* Generate temporary file name (string) starting with PREFIX (a string).
980The Emacs process number forms part of the result,
981so there is no danger of generating a name being used by another process.
982
983In addition, this function makes an attempt to choose a name
984which has no existing file. To make this work,
985PREFIX should be an absolute file name.
986
987There is a race condition between calling `make-temp-name' and creating the
988file which opens all kinds of security holes. For that reason, you should
f9e6f049
RS
989probably use `make-temp-file' instead, except in three circumstances:
990
991* If you are creating the file in the user's home directory.
992* If you are creating a directory rather than an ordinary file.
993* If you are taking special precautions as `make-temp-file' does. */)
8c1a1077 994 (prefix)
cb613bb8
GM
995 Lisp_Object prefix;
996{
997 return make_temp_name (prefix, 0);
998}
999
1000
570d7624
JB
1001\f
1002DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
8c1a1077
PJ
1003 doc: /* Convert filename NAME to absolute, and canonicalize it.
1004Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative
1005 (does not start with slash); if DEFAULT-DIRECTORY is nil or missing,
1006the current buffer's value of default-directory is used.
1007File name components that are `.' are removed, and
1008so are file name components followed by `..', along with the `..' itself;
1009note that these simplifications are done without checking the resulting
1010file names in the file system.
1011An initial `~/' expands to your home directory.
1012An initial `~USER/' expands to USER's home directory.
1013See also the function `substitute-in-file-name'. */)
1014 (name, default_directory)
3b7f6e60 1015 Lisp_Object name, default_directory;
570d7624
JB
1016{
1017 unsigned char *nm;
199607e4 1018
570d7624
JB
1019 register unsigned char *newdir, *p, *o;
1020 int tlen;
1021 unsigned char *target;
1022 struct passwd *pw;
570d7624
JB
1023#ifdef VMS
1024 unsigned char * colon = 0;
1025 unsigned char * close = 0;
1026 unsigned char * slash = 0;
1027 unsigned char * brack = 0;
1028 int lbrack = 0, rbrack = 0;
1029 int dots = 0;
1030#endif /* VMS */
5e570b75 1031#ifdef DOS_NT
199607e4 1032 int drive = 0;
9a1dc3be 1033 int collapse_newdir = 1;
f0f95d31 1034 int is_escaped = 0;
5e570b75 1035#endif /* DOS_NT */
199607e4 1036 int length;
0bf2eed2 1037 Lisp_Object handler;
199607e4 1038
b7826503 1039 CHECK_STRING (name);
570d7624 1040
0bf2eed2
RS
1041 /* If the file name has special constructs in it,
1042 call the corresponding file handler. */
49307295 1043 handler = Ffind_file_name_handler (name, Qexpand_file_name);
0bf2eed2 1044 if (!NILP (handler))
3b7f6e60 1045 return call3 (handler, Qexpand_file_name, name, default_directory);
58fc9587 1046
3b7f6e60
EN
1047 /* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */
1048 if (NILP (default_directory))
1049 default_directory = current_buffer->directory;
82330e7f 1050 if (! STRINGP (default_directory))
dd693537
EZ
1051 {
1052#ifdef DOS_NT
1053 /* "/" is not considered a root directory on DOS_NT, so using "/"
1054 here causes an infinite recursion in, e.g., the following:
1055
1056 (let (default-directory)
1057 (expand-file-name "a"))
1058
1059 To avoid this, we set default_directory to the root of the
1060 current drive. */
1061 extern char *emacs_root_dir (void);
1062
1063 default_directory = build_string (emacs_root_dir ());
1064#else
1065 default_directory = build_string ("/");
1066#endif
1067 }
58fc9587 1068
3b7f6e60 1069 if (!NILP (default_directory))
273e0829 1070 {
3b7f6e60 1071 handler = Ffind_file_name_handler (default_directory, Qexpand_file_name);
273e0829 1072 if (!NILP (handler))
3b7f6e60 1073 return call3 (handler, Qexpand_file_name, name, default_directory);
273e0829 1074 }
0bf2eed2 1075
d5db4077 1076 o = SDATA (default_directory);
5e570b75 1077
3b7f6e60 1078 /* Make sure DEFAULT_DIRECTORY is properly expanded.
f14b1c68 1079 It would be better to do this down below where we actually use
3b7f6e60 1080 default_directory. Unfortunately, calling Fexpand_file_name recursively
f14b1c68
JB
1081 could invoke GC, and the strings might be relocated. This would
1082 be annoying because we have pointers into strings lying around
1083 that would need adjusting, and people would add new pointers to
1084 the code and forget to adjust them, resulting in intermittent bugs.
4ad827c5
RS
1085 Putting this call here avoids all that crud.
1086
1087 The EQ test avoids infinite recursion. */
3b7f6e60 1088 if (! NILP (default_directory) && !EQ (default_directory, name)
199607e4
RS
1089 /* Save time in some common cases - as long as default_directory
1090 is not relative, it can be canonicalized with name below (if it
1091 is needed at all) without requiring it to be expanded now. */
01937013 1092#ifdef DOS_NT
199607e4 1093 /* Detect MSDOS file names with drive specifiers. */
f0f95d31 1094 && ! (IS_DRIVE (o[0]) && IS_DEVICE_SEP (o[1]) && IS_DIRECTORY_SEP (o[2]))
199607e4
RS
1095#ifdef WINDOWSNT
1096 /* Detect Windows file names in UNC format. */
1097 && ! (IS_DIRECTORY_SEP (o[0]) && IS_DIRECTORY_SEP (o[1]))
01937013 1098#endif
199607e4
RS
1099#else /* not DOS_NT */
1100 /* Detect Unix absolute file names (/... alone is not absolute on
1101 DOS or Windows). */
1102 && ! (IS_DIRECTORY_SEP (o[0]))
1103#endif /* not DOS_NT */
1104 )
f14b1c68
JB
1105 {
1106 struct gcpro gcpro1;
1107
1108 GCPRO1 (name);
3b7f6e60 1109 default_directory = Fexpand_file_name (default_directory, Qnil);
f14b1c68
JB
1110 UNGCPRO;
1111 }
1112
570d7624
JB
1113#ifdef VMS
1114 /* Filenames on VMS are always upper case. */
1115 name = Fupcase (name);
1116#endif
4c3c22f3
RS
1117#ifdef FILE_SYSTEM_CASE
1118 name = FILE_SYSTEM_CASE (name);
1119#endif
570d7624 1120
d5db4077 1121 nm = SDATA (name);
a5a1cc06 1122
5e570b75 1123#ifdef DOS_NT
199607e4
RS
1124 /* We will force directory separators to be either all \ or /, so make
1125 a local copy to modify, even if there ends up being no change. */
1126 nm = strcpy (alloca (strlen (nm) + 1), nm);
1127
f0f95d31
RS
1128 /* Note if special escape prefix is present, but remove for now. */
1129 if (nm[0] == '/' && nm[1] == ':')
1130 {
1131 is_escaped = 1;
1132 nm += 2;
1133 }
1134
199607e4 1135 /* Find and remove drive specifier if present; this makes nm absolute
f0f95d31
RS
1136 even if the rest of the name appears to be relative. Only look for
1137 drive specifier at the beginning. */
1138 if (IS_DRIVE (nm[0]) && IS_DEVICE_SEP (nm[1]))
1139 {
1140 drive = nm[0];
1141 nm += 2;
1142 }
bb1ff1f4
GV
1143
1144#ifdef WINDOWSNT
1145 /* If we see "c://somedir", we want to strip the first slash after the
1146 colon when stripping the drive letter. Otherwise, this expands to
1147 "//somedir". */
1148 if (drive && IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
1149 nm++;
1150#endif /* WINDOWSNT */
5e570b75 1151#endif /* DOS_NT */
4c3c22f3 1152
199607e4
RS
1153#ifdef WINDOWSNT
1154 /* Discard any previous drive specifier if nm is now in UNC format. */
1155 if (IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
1156 {
1157 drive = 0;
1158 }
1159#endif
1160
214378ec
GM
1161 /* If nm is absolute, look for `/./' or `/../' or `//''sequences; if
1162 none are found, we can probably return right away. We will avoid
1163 allocating a new string if name is already fully expanded. */
570d7624 1164 if (
5e570b75 1165 IS_DIRECTORY_SEP (nm[0])
199607e4 1166#ifdef MSDOS
f0f95d31 1167 && drive && !is_escaped
199607e4
RS
1168#endif
1169#ifdef WINDOWSNT
f0f95d31 1170 && (drive || IS_DIRECTORY_SEP (nm[1])) && !is_escaped
199607e4 1171#endif
570d7624
JB
1172#ifdef VMS
1173 || index (nm, ':')
1174#endif /* VMS */
1175 )
1176 {
f14b1c68
JB
1177 /* If it turns out that the filename we want to return is just a
1178 suffix of FILENAME, we don't need to go through and edit
1179 things; we just need to construct a new string using data
1180 starting at the middle of FILENAME. If we set lose to a
1181 non-zero value, that means we've discovered that we can't do
1182 that cool trick. */
1183 int lose = 0;
1184
570d7624 1185 p = nm;
570d7624
JB
1186 while (*p)
1187 {
199607e4 1188 /* Since we know the name is absolute, we can assume that each
c77d647e
JB
1189 element starts with a "/". */
1190
c77d647e 1191 /* "." and ".." are hairy. */
5e570b75 1192 if (IS_DIRECTORY_SEP (p[0])
c77d647e 1193 && p[1] == '.'
5e570b75 1194 && (IS_DIRECTORY_SEP (p[2])
c77d647e 1195 || p[2] == 0
5e570b75 1196 || (p[2] == '.' && (IS_DIRECTORY_SEP (p[3])
c77d647e 1197 || p[3] == 0))))
570d7624 1198 lose = 1;
214378ec
GM
1199 /* We want to replace multiple `/' in a row with a single
1200 slash. */
1201 else if (p > nm
1202 && IS_DIRECTORY_SEP (p[0])
1203 && IS_DIRECTORY_SEP (p[1]))
1204 lose = 1;
1205
570d7624
JB
1206#ifdef VMS
1207 if (p[0] == '\\')
1208 lose = 1;
1209 if (p[0] == '/') {
1210 /* if dev:[dir]/, move nm to / */
1211 if (!slash && p > nm && (brack || colon)) {
1212 nm = (brack ? brack + 1 : colon + 1);
1213 lbrack = rbrack = 0;
1214 brack = 0;
1215 colon = 0;
1216 }
1217 slash = p;
1218 }
1219 if (p[0] == '-')
1220#ifndef VMS4_4
1221 /* VMS pre V4.4,convert '-'s in filenames. */
1222 if (lbrack == rbrack)
1223 {
5e570b75 1224 if (dots < 2) /* this is to allow negative version numbers */
570d7624
JB
1225 p[0] = '_';
1226 }
1227 else
1228#endif /* VMS4_4 */
1229 if (lbrack > rbrack &&
1230 ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<') &&
1231 (p[1] == '.' || p[1] == ']' || p[1] == '>')))
1232 lose = 1;
1233#ifndef VMS4_4
1234 else
1235 p[0] = '_';
1236#endif /* VMS4_4 */
1237 /* count open brackets, reset close bracket pointer */
1238 if (p[0] == '[' || p[0] == '<')
1239 lbrack++, brack = 0;
1240 /* count close brackets, set close bracket pointer */
1241 if (p[0] == ']' || p[0] == '>')
1242 rbrack++, brack = p;
1243 /* detect ][ or >< */
1244 if ((p[0] == ']' || p[0] == '>') && (p[1] == '[' || p[1] == '<'))
1245 lose = 1;
1246 if ((p[0] == ':' || p[0] == ']' || p[0] == '>') && p[1] == '~')
1247 nm = p + 1, lose = 1;
1248 if (p[0] == ':' && (colon || slash))
1249 /* if dev1:[dir]dev2:, move nm to dev2: */
1250 if (brack)
1251 {
1252 nm = brack + 1;
1253 brack = 0;
1254 }
199607e4 1255 /* if /name/dev:, move nm to dev: */
570d7624
JB
1256 else if (slash)
1257 nm = slash + 1;
1258 /* if node::dev:, move colon following dev */
1259 else if (colon && colon[-1] == ':')
1260 colon = p;
1261 /* if dev1:dev2:, move nm to dev2: */
1262 else if (colon && colon[-1] != ':')
1263 {
1264 nm = colon + 1;
1265 colon = 0;
1266 }
1267 if (p[0] == ':' && !colon)
1268 {
1269 if (p[1] == ':')
1270 p++;
1271 colon = p;
1272 }
1273 if (lbrack == rbrack)
1274 if (p[0] == ';')
1275 dots = 2;
1276 else if (p[0] == '.')
1277 dots++;
1278#endif /* VMS */
1279 p++;
1280 }
1281 if (!lose)
1282 {
1283#ifdef VMS
1284 if (index (nm, '/'))
1285 return build_string (sys_translate_unix (nm));
1286#endif /* VMS */
199607e4
RS
1287#ifdef DOS_NT
1288 /* Make sure directories are all separated with / or \ as
1289 desired, but avoid allocation of a new string when not
1290 required. */
1291 CORRECT_DIR_SEPS (nm);
1292#ifdef WINDOWSNT
1293 if (IS_DIRECTORY_SEP (nm[1]))
1294 {
d5db4077 1295 if (strcmp (nm, SDATA (name)) != 0)
199607e4
RS
1296 name = build_string (nm);
1297 }
1298 else
1299#endif
1300 /* drive must be set, so this is okay */
d5db4077 1301 if (strcmp (nm - 2, SDATA (name)) != 0)
199607e4
RS
1302 {
1303 name = make_string (nm - 2, p - nm + 2);
d5db4077
KR
1304 SREF (name, 0) = DRIVE_LETTER (drive);
1305 SREF (name, 1) = ':';
199607e4
RS
1306 }
1307 return name;
1308#else /* not DOS_NT */
d5db4077 1309 if (nm == SDATA (name))
570d7624
JB
1310 return name;
1311 return build_string (nm);
5e570b75 1312#endif /* not DOS_NT */
570d7624
JB
1313 }
1314 }
1315
199607e4
RS
1316 /* At this point, nm might or might not be an absolute file name. We
1317 need to expand ~ or ~user if present, otherwise prefix nm with
1318 default_directory if nm is not absolute, and finally collapse /./
1319 and /foo/../ sequences.
1320
1321 We set newdir to be the appropriate prefix if one is needed:
1322 - the relevant user directory if nm starts with ~ or ~user
1323 - the specified drive's working dir (DOS/NT only) if nm does not
1324 start with /
1325 - the value of default_directory.
1326
1327 Note that these prefixes are not guaranteed to be absolute (except
1328 for the working dir of a drive). Therefore, to ensure we always
1329 return an absolute name, if the final prefix is not absolute we
1330 append it to the current working directory. */
570d7624
JB
1331
1332 newdir = 0;
1333
1334 if (nm[0] == '~') /* prefix ~ */
c77d647e 1335 {
5e570b75 1336 if (IS_DIRECTORY_SEP (nm[1])
570d7624 1337#ifdef VMS
c77d647e 1338 || nm[1] == ':'
5e570b75 1339#endif /* VMS */
c77d647e
JB
1340 || nm[1] == 0) /* ~ by itself */
1341 {
1342 if (!(newdir = (unsigned char *) egetenv ("HOME")))
1343 newdir = (unsigned char *) "";
199607e4 1344 nm++;
5e570b75 1345#ifdef DOS_NT
9a1dc3be 1346 collapse_newdir = 0;
4c3c22f3 1347#endif
570d7624 1348#ifdef VMS
c77d647e 1349 nm++; /* Don't leave the slash in nm. */
5e570b75 1350#endif /* VMS */
c77d647e
JB
1351 }
1352 else /* ~user/filename */
1353 {
5e570b75 1354 for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)
570d7624 1355#ifdef VMS
c77d647e 1356 && *p != ':'
5e570b75 1357#endif /* VMS */
c77d647e
JB
1358 ); p++);
1359 o = (unsigned char *) alloca (p - nm + 1);
1360 bcopy ((char *) nm, o, p - nm);
1361 o [p - nm] = 0;
1362
1363 pw = (struct passwd *) getpwnam (o + 1);
1364 if (pw)
1365 {
1366 newdir = (unsigned char *) pw -> pw_dir;
570d7624 1367#ifdef VMS
c77d647e 1368 nm = p + 1; /* skip the terminator */
570d7624 1369#else
c77d647e 1370 nm = p;
199607e4 1371#ifdef DOS_NT
9a1dc3be 1372 collapse_newdir = 0;
199607e4 1373#endif
5e570b75 1374#endif /* VMS */
c77d647e 1375 }
e5d77022 1376
c77d647e
JB
1377 /* If we don't find a user of that name, leave the name
1378 unchanged; don't move nm forward to p. */
1379 }
1380 }
570d7624 1381
5e570b75 1382#ifdef DOS_NT
199607e4
RS
1383 /* On DOS and Windows, nm is absolute if a drive name was specified;
1384 use the drive's current directory as the prefix if needed. */
1385 if (!newdir && drive)
1386 {
1387 /* Get default directory if needed to make nm absolute. */
1388 if (!IS_DIRECTORY_SEP (nm[0]))
1389 {
1390 newdir = alloca (MAXPATHLEN + 1);
1391 if (!getdefdir (toupper (drive) - 'A' + 1, newdir))
1392 newdir = NULL;
1393 }
1394 if (!newdir)
1395 {
1396 /* Either nm starts with /, or drive isn't mounted. */
1397 newdir = alloca (4);
f94988a7 1398 newdir[0] = DRIVE_LETTER (drive);
199607e4
RS
1399 newdir[1] = ':';
1400 newdir[2] = '/';
1401 newdir[3] = 0;
1402 }
1403 }
5e570b75 1404#endif /* DOS_NT */
199607e4
RS
1405
1406 /* Finally, if no prefix has been specified and nm is not absolute,
1407 then it must be expanded relative to default_directory. */
1408
34097368 1409 if (1
199607e4
RS
1410#ifndef DOS_NT
1411 /* /... alone is not absolute on DOS and Windows. */
34097368 1412 && !IS_DIRECTORY_SEP (nm[0])
199607e4
RS
1413#endif
1414#ifdef WINDOWSNT
34097368 1415 && !(IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
199607e4
RS
1416#endif
1417#ifdef VMS
1418 && !index (nm, ':')
1419#endif
570d7624
JB
1420 && !newdir)
1421 {
d5db4077 1422 newdir = SDATA (default_directory);
f0f95d31
RS
1423#ifdef DOS_NT
1424 /* Note if special escape prefix is present, but remove for now. */
1425 if (newdir[0] == '/' && newdir[1] == ':')
1426 {
1427 is_escaped = 1;
1428 newdir += 2;
1429 }
1430#endif
570d7624
JB
1431 }
1432
5e570b75 1433#ifdef DOS_NT
199607e4
RS
1434 if (newdir)
1435 {
1436 /* First ensure newdir is an absolute name. */
1437 if (
1438 /* Detect MSDOS file names with drive specifiers. */
1439 ! (IS_DRIVE (newdir[0])
1440 && IS_DEVICE_SEP (newdir[1]) && IS_DIRECTORY_SEP (newdir[2]))
1441#ifdef WINDOWSNT
1442 /* Detect Windows file names in UNC format. */
1443 && ! (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1]))
1444#endif
1445 )
1446 {
1447 /* Effectively, let newdir be (expand-file-name newdir cwd).
1448 Because of the admonition against calling expand-file-name
1449 when we have pointers into lisp strings, we accomplish this
1450 indirectly by prepending newdir to nm if necessary, and using
1451 cwd (or the wd of newdir's drive) as the new newdir. */
1452
1453 if (IS_DRIVE (newdir[0]) && newdir[1] == ':')
1454 {
1455 drive = newdir[0];
1456 newdir += 2;
1457 }
1458 if (!IS_DIRECTORY_SEP (nm[0]))
1459 {
1460 char * tmp = alloca (strlen (newdir) + strlen (nm) + 2);
1461 file_name_as_directory (tmp, newdir);
1462 strcat (tmp, nm);
1463 nm = tmp;
1464 }
1465 newdir = alloca (MAXPATHLEN + 1);
1466 if (drive)
1467 {
1468 if (!getdefdir (toupper (drive) - 'A' + 1, newdir))
1469 newdir = "/";
1470 }
1471 else
1472 getwd (newdir);
1473 }
1474
1475 /* Strip off drive name from prefix, if present. */
1476 if (IS_DRIVE (newdir[0]) && newdir[1] == ':')
1477 {
1478 drive = newdir[0];
1479 newdir += 2;
1480 }
1481
1482 /* Keep only a prefix from newdir if nm starts with slash
82330e7f 1483 (//server/share for UNC, nothing otherwise). */
9a1dc3be 1484 if (IS_DIRECTORY_SEP (nm[0]) && collapse_newdir)
199607e4
RS
1485 {
1486#ifdef WINDOWSNT
1487 if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1]))
1488 {
1489 newdir = strcpy (alloca (strlen (newdir) + 1), newdir);
1490 p = newdir + 2;
1491 while (*p && !IS_DIRECTORY_SEP (*p)) p++;
1492 p++;
1493 while (*p && !IS_DIRECTORY_SEP (*p)) p++;
1494 *p = 0;
1495 }
1496 else
1497#endif
1498 newdir = "";
1499 }
1500 }
5e570b75 1501#endif /* DOS_NT */
199607e4
RS
1502
1503 if (newdir)
bfb61299 1504 {
57676091 1505 /* Get rid of any slash at the end of newdir, unless newdir is
f0f95d31 1506 just / or // (an incomplete UNC name). */
199607e4 1507 length = strlen (newdir);
f0f95d31 1508 if (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1])
57676091
RS
1509#ifdef WINDOWSNT
1510 && !(length == 2 && IS_DIRECTORY_SEP (newdir[0]))
1511#endif
1512 )
bfb61299
JB
1513 {
1514 unsigned char *temp = (unsigned char *) alloca (length);
1515 bcopy (newdir, temp, length - 1);
1516 temp[length - 1] = 0;
1517 newdir = temp;
1518 }
1519 tlen = length + 1;
1520 }
1521 else
1522 tlen = 0;
570d7624 1523
bfb61299
JB
1524 /* Now concatenate the directory and name to new space in the stack frame */
1525 tlen += strlen (nm) + 1;
5e570b75 1526#ifdef DOS_NT
f0f95d31
RS
1527 /* Reserve space for drive specifier and escape prefix, since either
1528 or both may need to be inserted. (The Microsoft x86 compiler
5e570b75 1529 produces incorrect code if the following two lines are combined.) */
f0f95d31
RS
1530 target = (unsigned char *) alloca (tlen + 4);
1531 target += 4;
5e570b75 1532#else /* not DOS_NT */
570d7624 1533 target = (unsigned char *) alloca (tlen);
5e570b75 1534#endif /* not DOS_NT */
570d7624
JB
1535 *target = 0;
1536
1537 if (newdir)
1538 {
1539#ifndef VMS
5e570b75 1540 if (nm[0] == 0 || IS_DIRECTORY_SEP (nm[0]))
f5321b5c 1541 {
3ea2d8b2 1542#ifdef DOS_NT
f5321b5c
RS
1543 /* If newdir is effectively "C:/", then the drive letter will have
1544 been stripped and newdir will be "/". Concatenating with an
1545 absolute directory in nm produces "//", which will then be
1546 incorrectly treated as a network share. Ignore newdir in
1547 this case (keeping the drive letter). */
1548 if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0])
1549 && newdir[1] == '\0'))
1550#endif
1551 strcpy (target, newdir);
1552 }
570d7624
JB
1553 else
1554#endif
c77d647e 1555 file_name_as_directory (target, newdir);
570d7624
JB
1556 }
1557
1558 strcat (target, nm);
1559#ifdef VMS
1560 if (index (target, '/'))
1561 strcpy (target, sys_translate_unix (target));
1562#endif /* VMS */
1563
199607e4
RS
1564 /* ASSERT (IS_DIRECTORY_SEP (target[0])) if not VMS */
1565
214378ec
GM
1566 /* Now canonicalize by removing `//', `/.' and `/foo/..' if they
1567 appear. */
570d7624
JB
1568
1569 p = target;
1570 o = target;
1571
1572 while (*p)
1573 {
1574#ifdef VMS
1575 if (*p != ']' && *p != '>' && *p != '-')
1576 {
1577 if (*p == '\\')
1578 p++;
1579 *o++ = *p++;
1580 }
1581 else if ((p[0] == ']' || p[0] == '>') && p[0] == p[1] + 2)
1582 /* brackets are offset from each other by 2 */
1583 {
1584 p += 2;
1585 if (*p != '.' && *p != '-' && o[-1] != '.')
1586 /* convert [foo][bar] to [bar] */
1587 while (o[-1] != '[' && o[-1] != '<')
1588 o--;
1589 else if (*p == '-' && *o != '.')
1590 *--p = '.';
1591 }
1592 else if (p[0] == '-' && o[-1] == '.' &&
1593 (p[1] == '.' || p[1] == ']' || p[1] == '>'))
1594 /* flush .foo.- ; leave - if stopped by '[' or '<' */
1595 {
1596 do
1597 o--;
1598 while (o[-1] != '.' && o[-1] != '[' && o[-1] != '<');
5e570b75 1599 if (p[1] == '.') /* foo.-.bar ==> bar. */
570d7624
JB
1600 p += 2;
1601 else if (o[-1] == '.') /* '.foo.-]' ==> ']' */
1602 p++, o--;
1603 /* else [foo.-] ==> [-] */
1604 }
1605 else
1606 {
1607#ifndef VMS4_4
1608 if (*p == '-' &&
1609 o[-1] != '[' && o[-1] != '<' && o[-1] != '.' &&
1610 p[1] != ']' && p[1] != '>' && p[1] != '.')
1611 *p = '_';
1612#endif /* VMS4_4 */
1613 *o++ = *p++;
1614 }
1615#else /* not VMS */
5e570b75
RS
1616 if (!IS_DIRECTORY_SEP (*p))
1617 {
570d7624
JB
1618 *o++ = *p++;
1619 }
5e570b75 1620 else if (IS_DIRECTORY_SEP (p[0])
c77d647e 1621 && p[1] == '.'
5e570b75 1622 && (IS_DIRECTORY_SEP (p[2])
c77d647e
JB
1623 || p[2] == 0))
1624 {
1625 /* If "/." is the entire filename, keep the "/". Otherwise,
1626 just delete the whole "/.". */
1627 if (o == target && p[2] == '\0')
1628 *o++ = *p;
1629 p += 2;
1630 }
c0fa5a0b 1631 else if (IS_DIRECTORY_SEP (p[0]) && p[1] == '.' && p[2] == '.'
570d7624
JB
1632 /* `/../' is the "superroot" on certain file systems. */
1633 && o != target
5e570b75 1634 && (IS_DIRECTORY_SEP (p[3]) || p[3] == 0))
570d7624 1635 {
5e570b75 1636 while (o != target && (--o) && !IS_DIRECTORY_SEP (*o))
570d7624 1637 ;
795de720
RS
1638 /* Keep initial / only if this is the whole name. */
1639 if (o == target && IS_ANY_SEP (*o) && p[3] == 0)
51b1d12e 1640 ++o;
570d7624
JB
1641 p += 3;
1642 }
214378ec
GM
1643 else if (p > target
1644 && IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1]))
1645 {
1646 /* Collapse multiple `/' in a row. */
1647 *o++ = *p++;
1648 while (IS_DIRECTORY_SEP (*p))
1649 ++p;
1650 }
570d7624 1651 else
5e570b75 1652 {
570d7624
JB
1653 *o++ = *p++;
1654 }
1655#endif /* not VMS */
1656 }
1657
5e570b75 1658#ifdef DOS_NT
199607e4 1659 /* At last, set drive name. */
5e570b75 1660#ifdef WINDOWSNT
199607e4
RS
1661 /* Except for network file name. */
1662 if (!(IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1])))
5e570b75 1663#endif /* WINDOWSNT */
4c3c22f3 1664 {
199607e4 1665 if (!drive) abort ();
4c3c22f3 1666 target -= 2;
f94988a7 1667 target[0] = DRIVE_LETTER (drive);
4c3c22f3
RS
1668 target[1] = ':';
1669 }
f0f95d31
RS
1670 /* Reinsert the escape prefix if required. */
1671 if (is_escaped)
1672 {
1673 target -= 2;
1674 target[0] = '/';
1675 target[1] = ':';
1676 }
199607e4 1677 CORRECT_DIR_SEPS (target);
5e570b75 1678#endif /* DOS_NT */
4c3c22f3 1679
570d7624
JB
1680 return make_string (target, o - target);
1681}
5e570b75 1682
4887597a
EZ
1683#if 0
1684/* PLEASE DO NOT DELETE THIS COMMENTED-OUT VERSION!
1685 This is the old version of expand-file-name, before it was thoroughly
1686 rewritten for Emacs 10.31. We leave this version here commented-out,
1687 because the code is very complex and likely to have subtle bugs. If
1688 bugs _are_ found, it might be of interest to look at the old code and
1689 see what did it do in the relevant situation.
1690
1691 Don't remove this code: it's true that it will be accessible via CVS,
1692 but a few years from deletion, people will forget it is there. */
1693
1694/* Changed this DEFUN to a DEAFUN, so as not to confuse `make-docfile'. */
1695DEAFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
1696 "Convert FILENAME to absolute, and canonicalize it.\n\
1697Second arg DEFAULT is directory to start with if FILENAME is relative\n\
1698 (does not start with slash); if DEFAULT is nil or missing,\n\
1699the current buffer's value of default-directory is used.\n\
1700Filenames containing `.' or `..' as components are simplified;\n\
1701initial `~/' expands to your home directory.\n\
1702See also the function `substitute-in-file-name'.")
1703 (name, defalt)
1704 Lisp_Object name, defalt;
1705{
1706 unsigned char *nm;
1707
1708 register unsigned char *newdir, *p, *o;
1709 int tlen;
1710 unsigned char *target;
1711 struct passwd *pw;
1712 int lose;
1713#ifdef VMS
1714 unsigned char * colon = 0;
1715 unsigned char * close = 0;
1716 unsigned char * slash = 0;
1717 unsigned char * brack = 0;
1718 int lbrack = 0, rbrack = 0;
1719 int dots = 0;
1720#endif /* VMS */
1721
b7826503 1722 CHECK_STRING (name);
4887597a
EZ
1723
1724#ifdef VMS
1725 /* Filenames on VMS are always upper case. */
1726 name = Fupcase (name);
1727#endif
1728
d5db4077 1729 nm = SDATA (name);
4887597a
EZ
1730
1731 /* If nm is absolute, flush ...// and detect /./ and /../.
1732 If no /./ or /../ we can return right away. */
1733 if (
1734 nm[0] == '/'
1735#ifdef VMS
1736 || index (nm, ':')
1737#endif /* VMS */
1738 )
1739 {
1740 p = nm;
1741 lose = 0;
1742 while (*p)
1743 {
1744 if (p[0] == '/' && p[1] == '/'
1745#ifdef APOLLO
1746 /* // at start of filename is meaningful on Apollo system. */
1747 && nm != p
1748#endif /* APOLLO */
1749 )
1750 nm = p + 1;
1751 if (p[0] == '/' && p[1] == '~')
1752 nm = p + 1, lose = 1;
1753 if (p[0] == '/' && p[1] == '.'
1754 && (p[2] == '/' || p[2] == 0
1755 || (p[2] == '.' && (p[3] == '/' || p[3] == 0))))
1756 lose = 1;
1757#ifdef VMS
1758 if (p[0] == '\\')
1759 lose = 1;
1760 if (p[0] == '/') {
1761 /* if dev:[dir]/, move nm to / */
1762 if (!slash && p > nm && (brack || colon)) {
1763 nm = (brack ? brack + 1 : colon + 1);
1764 lbrack = rbrack = 0;
1765 brack = 0;
1766 colon = 0;
1767 }
1768 slash = p;
1769 }
1770 if (p[0] == '-')
1771#ifndef VMS4_4
1772 /* VMS pre V4.4,convert '-'s in filenames. */
1773 if (lbrack == rbrack)
1774 {
1775 if (dots < 2) /* this is to allow negative version numbers */
1776 p[0] = '_';
1777 }
1778 else
1779#endif /* VMS4_4 */
1780 if (lbrack > rbrack &&
1781 ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<') &&
1782 (p[1] == '.' || p[1] == ']' || p[1] == '>')))
1783 lose = 1;
1784#ifndef VMS4_4
1785 else
1786 p[0] = '_';
1787#endif /* VMS4_4 */
1788 /* count open brackets, reset close bracket pointer */
1789 if (p[0] == '[' || p[0] == '<')
1790 lbrack++, brack = 0;
1791 /* count close brackets, set close bracket pointer */
1792 if (p[0] == ']' || p[0] == '>')
1793 rbrack++, brack = p;
1794 /* detect ][ or >< */
1795 if ((p[0] == ']' || p[0] == '>') && (p[1] == '[' || p[1] == '<'))
1796 lose = 1;
1797 if ((p[0] == ':' || p[0] == ']' || p[0] == '>') && p[1] == '~')
1798 nm = p + 1, lose = 1;
1799 if (p[0] == ':' && (colon || slash))
1800 /* if dev1:[dir]dev2:, move nm to dev2: */
1801 if (brack)
1802 {
1803 nm = brack + 1;
1804 brack = 0;
1805 }
1806 /* If /name/dev:, move nm to dev: */
1807 else if (slash)
1808 nm = slash + 1;
1809 /* If node::dev:, move colon following dev */
1810 else if (colon && colon[-1] == ':')
1811 colon = p;
1812 /* If dev1:dev2:, move nm to dev2: */
1813 else if (colon && colon[-1] != ':')
1814 {
1815 nm = colon + 1;
1816 colon = 0;
1817 }
1818 if (p[0] == ':' && !colon)
1819 {
1820 if (p[1] == ':')
1821 p++;
1822 colon = p;
1823 }
1824 if (lbrack == rbrack)
1825 if (p[0] == ';')
1826 dots = 2;
1827 else if (p[0] == '.')
1828 dots++;
1829#endif /* VMS */
1830 p++;
1831 }
1832 if (!lose)
1833 {
1834#ifdef VMS
1835 if (index (nm, '/'))
1836 return build_string (sys_translate_unix (nm));
1837#endif /* VMS */
d5db4077 1838 if (nm == SDATA (name))
4887597a
EZ
1839 return name;
1840 return build_string (nm);
1841 }
1842 }
1843
1844 /* Now determine directory to start with and put it in NEWDIR */
1845
1846 newdir = 0;
1847
1848 if (nm[0] == '~') /* prefix ~ */
1849 if (nm[1] == '/'
1850#ifdef VMS
1851 || nm[1] == ':'
1852#endif /* VMS */
1853 || nm[1] == 0)/* ~/filename */
1854 {
1855 if (!(newdir = (unsigned char *) egetenv ("HOME")))
1856 newdir = (unsigned char *) "";
1857 nm++;
1858#ifdef VMS
1859 nm++; /* Don't leave the slash in nm. */
1860#endif /* VMS */
1861 }
1862 else /* ~user/filename */
1863 {
1864 /* Get past ~ to user */
1865 unsigned char *user = nm + 1;
1866 /* Find end of name. */
1867 unsigned char *ptr = (unsigned char *) index (user, '/');
1868 int len = ptr ? ptr - user : strlen (user);
1869#ifdef VMS
1870 unsigned char *ptr1 = index (user, ':');
1871 if (ptr1 != 0 && ptr1 - user < len)
1872 len = ptr1 - user;
1873#endif /* VMS */
1874 /* Copy the user name into temp storage. */
1875 o = (unsigned char *) alloca (len + 1);
1876 bcopy ((char *) user, o, len);
1877 o[len] = 0;
1878
1879 /* Look up the user name. */
1880 pw = (struct passwd *) getpwnam (o + 1);
1881 if (!pw)
1882 error ("\"%s\" isn't a registered user", o + 1);
1883
1884 newdir = (unsigned char *) pw->pw_dir;
1885
1886 /* Discard the user name from NM. */
1887 nm += len;
1888 }
1889
1890 if (nm[0] != '/'
1891#ifdef VMS
1892 && !index (nm, ':')
1893#endif /* not VMS */
1894 && !newdir)
1895 {
1896 if (NILP (defalt))
1897 defalt = current_buffer->directory;
b7826503 1898 CHECK_STRING (defalt);
d5db4077 1899 newdir = SDATA (defalt);
4887597a
EZ
1900 }
1901
1902 /* Now concatenate the directory and name to new space in the stack frame */
1903
1904 tlen = (newdir ? strlen (newdir) + 1 : 0) + strlen (nm) + 1;
1905 target = (unsigned char *) alloca (tlen);
1906 *target = 0;
1907
1908 if (newdir)
1909 {
1910#ifndef VMS
1911 if (nm[0] == 0 || nm[0] == '/')
1912 strcpy (target, newdir);
1913 else
1914#endif
1915 file_name_as_directory (target, newdir);
1916 }
1917
1918 strcat (target, nm);
1919#ifdef VMS
1920 if (index (target, '/'))
1921 strcpy (target, sys_translate_unix (target));
1922#endif /* VMS */
1923
1924 /* Now canonicalize by removing /. and /foo/.. if they appear */
1925
1926 p = target;
1927 o = target;
1928
1929 while (*p)
1930 {
1931#ifdef VMS
1932 if (*p != ']' && *p != '>' && *p != '-')
1933 {
1934 if (*p == '\\')
1935 p++;
1936 *o++ = *p++;
1937 }
1938 else if ((p[0] == ']' || p[0] == '>') && p[0] == p[1] + 2)
1939 /* brackets are offset from each other by 2 */
1940 {
1941 p += 2;
1942 if (*p != '.' && *p != '-' && o[-1] != '.')
1943 /* convert [foo][bar] to [bar] */
1944 while (o[-1] != '[' && o[-1] != '<')
1945 o--;
1946 else if (*p == '-' && *o != '.')
1947 *--p = '.';
1948 }
1949 else if (p[0] == '-' && o[-1] == '.' &&
1950 (p[1] == '.' || p[1] == ']' || p[1] == '>'))
1951 /* flush .foo.- ; leave - if stopped by '[' or '<' */
1952 {
1953 do
1954 o--;
1955 while (o[-1] != '.' && o[-1] != '[' && o[-1] != '<');
1956 if (p[1] == '.') /* foo.-.bar ==> bar. */
1957 p += 2;
1958 else if (o[-1] == '.') /* '.foo.-]' ==> ']' */
1959 p++, o--;
1960 /* else [foo.-] ==> [-] */
1961 }
1962 else
1963 {
1964#ifndef VMS4_4
1965 if (*p == '-' &&
1966 o[-1] != '[' && o[-1] != '<' && o[-1] != '.' &&
1967 p[1] != ']' && p[1] != '>' && p[1] != '.')
1968 *p = '_';
1969#endif /* VMS4_4 */
1970 *o++ = *p++;
1971 }
1972#else /* not VMS */
1973 if (*p != '/')
1974 {
1975 *o++ = *p++;
1976 }
1977 else if (!strncmp (p, "//", 2)
1978#ifdef APOLLO
1979 /* // at start of filename is meaningful in Apollo system. */
1980 && o != target
1981#endif /* APOLLO */
1982 )
1983 {
1984 o = target;
1985 p++;
1986 }
1987 else if (p[0] == '/' && p[1] == '.' &&
1988 (p[2] == '/' || p[2] == 0))
1989 p += 2;
1990 else if (!strncmp (p, "/..", 3)
1991 /* `/../' is the "superroot" on certain file systems. */
1992 && o != target
1993 && (p[3] == '/' || p[3] == 0))
1994 {
1995 while (o != target && *--o != '/')
1996 ;
1997#ifdef APOLLO
1998 if (o == target + 1 && o[-1] == '/' && o[0] == '/')
1999 ++o;
2000 else
2001#endif /* APOLLO */
2002 if (o == target && *o == '/')
2003 ++o;
2004 p += 3;
2005 }
2006 else
2007 {
2008 *o++ = *p++;
2009 }
2010#endif /* not VMS */
2011 }
2012
2013 return make_string (target, o - target);
2014}
2015#endif
570d7624
JB
2016\f
2017DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name,
8c1a1077
PJ
2018 Ssubstitute_in_file_name, 1, 1, 0,
2019 doc: /* Substitute environment variables referred to in FILENAME.
2020`$FOO' where FOO is an environment variable name means to substitute
2021the value of that variable. The variable name should be terminated
2022with a character not a letter, digit or underscore; otherwise, enclose
2023the entire variable name in braces.
2024If `/~' appears, all of FILENAME through that `/' is discarded.
2025
2026On VMS, `$' substitution is not done; this function does little and only
2027duplicates what `expand-file-name' does. */)
2028 (filename)
3b7f6e60 2029 Lisp_Object filename;
570d7624
JB
2030{
2031 unsigned char *nm;
2032
2033 register unsigned char *s, *p, *o, *x, *endp;
6bbd7a29 2034 unsigned char *target = NULL;
570d7624
JB
2035 int total = 0;
2036 int substituted = 0;
2037 unsigned char *xnm;
dba493fe 2038 struct passwd *pw;
8ce069f5 2039 Lisp_Object handler;
570d7624 2040
b7826503 2041 CHECK_STRING (filename);
570d7624 2042
8ce069f5
RS
2043 /* If the file name has special constructs in it,
2044 call the corresponding file handler. */
3b7f6e60 2045 handler = Ffind_file_name_handler (filename, Qsubstitute_in_file_name);
8ce069f5 2046 if (!NILP (handler))
3b7f6e60 2047 return call2 (handler, Qsubstitute_in_file_name, filename);
8ce069f5 2048
d5db4077 2049 nm = SDATA (filename);
199607e4
RS
2050#ifdef DOS_NT
2051 nm = strcpy (alloca (strlen (nm) + 1), nm);
2052 CORRECT_DIR_SEPS (nm);
d5db4077 2053 substituted = (strcmp (nm, SDATA (filename)) != 0);
a5a1cc06 2054#endif
d5db4077 2055 endp = nm + SBYTES (filename);
570d7624 2056
82330e7f 2057 /* If /~ or // appears, discard everything through first slash. */
570d7624
JB
2058
2059 for (p = nm; p != endp; p++)
2060 {
199607e4
RS
2061 if ((p[0] == '~'
2062#if defined (APOLLO) || defined (WINDOWSNT)
2063 /* // at start of file name is meaningful in Apollo and
82330e7f 2064 WindowsNT systems. */
199607e4
RS
2065 || (IS_DIRECTORY_SEP (p[0]) && p - 1 != nm)
2066#else /* not (APOLLO || WINDOWSNT) */
2067 || IS_DIRECTORY_SEP (p[0])
2068#endif /* not (APOLLO || WINDOWSNT) */
570d7624 2069 )
5e570b75
RS
2070 && p != nm
2071 && (0
570d7624 2072#ifdef VMS
5e570b75 2073 || p[-1] == ':' || p[-1] == ']' || p[-1] == '>'
570d7624 2074#endif /* VMS */
5e570b75 2075 || IS_DIRECTORY_SEP (p[-1])))
570d7624 2076 {
dba493fe
EZ
2077 for (s = p; *s && (!IS_DIRECTORY_SEP (*s)
2078#ifdef VMS
2079 && *s != ':'
2080#endif /* VMS */
2081 ); s++);
b135bd4c 2082 if (p[0] == '~' && s > p + 1) /* we've got "/~something/" */
dba493fe
EZ
2083 {
2084 o = (unsigned char *) alloca (s - p + 1);
2085 bcopy ((char *) p, o, s - p);
2086 o [s - p] = 0;
2087
2088 pw = (struct passwd *) getpwnam (o + 1);
2089 }
2090 /* If we have ~/ or ~user and `user' exists, discard
2091 everything up to ~. But if `user' does not exist, leave
2092 ~user alone, it might be a literal file name. */
b135bd4c 2093 if (IS_DIRECTORY_SEP (p[0]) || s == p + 1 || pw)
dba493fe
EZ
2094 {
2095 nm = p;
2096 substituted = 1;
2097 }
570d7624 2098 }
5e570b75 2099#ifdef DOS_NT
199607e4
RS
2100 /* see comment in expand-file-name about drive specifiers */
2101 else if (IS_DRIVE (p[0]) && p[1] == ':'
2102 && p > nm && IS_DIRECTORY_SEP (p[-1]))
4c3c22f3
RS
2103 {
2104 nm = p;
2105 substituted = 1;
2106 }
5e570b75 2107#endif /* DOS_NT */
570d7624
JB
2108 }
2109
2110#ifdef VMS
2111 return build_string (nm);
2112#else
2113
2114 /* See if any variables are substituted into the string
2115 and find the total length of their values in `total' */
2116
2117 for (p = nm; p != endp;)
2118 if (*p != '$')
2119 p++;
2120 else
2121 {
2122 p++;
2123 if (p == endp)
2124 goto badsubst;
2125 else if (*p == '$')
2126 {
2127 /* "$$" means a single "$" */
2128 p++;
2129 total -= 1;
2130 substituted = 1;
2131 continue;
2132 }
2133 else if (*p == '{')
2134 {
2135 o = ++p;
2136 while (p != endp && *p != '}') p++;
2137 if (*p != '}') goto missingclose;
2138 s = p;
2139 }
2140 else
2141 {
2142 o = p;
2143 while (p != endp && (isalnum (*p) || *p == '_')) p++;
2144 s = p;
2145 }
2146
2147 /* Copy out the variable name */
2148 target = (unsigned char *) alloca (s - o + 1);
2149 strncpy (target, o, s - o);
2150 target[s - o] = 0;
5e570b75 2151#ifdef DOS_NT
4c3c22f3 2152 strupr (target); /* $home == $HOME etc. */
5e570b75 2153#endif /* DOS_NT */
570d7624
JB
2154
2155 /* Get variable value */
2156 o = (unsigned char *) egetenv (target);
8d2ced53
SM
2157 if (o)
2158 {
2159 total += strlen (o);
2160 substituted = 1;
2161 }
2162 else if (*p == '}')
2163 goto badvar;
570d7624
JB
2164 }
2165
2166 if (!substituted)
3b7f6e60 2167 return filename;
570d7624
JB
2168
2169 /* If substitution required, recopy the string and do it */
2170 /* Make space in stack frame for the new copy */
d5db4077 2171 xnm = (unsigned char *) alloca (SBYTES (filename) + total + 1);
570d7624
JB
2172 x = xnm;
2173
2174 /* Copy the rest of the name through, replacing $ constructs with values */
2175 for (p = nm; *p;)
2176 if (*p != '$')
2177 *x++ = *p++;
2178 else
2179 {
2180 p++;
2181 if (p == endp)
2182 goto badsubst;
2183 else if (*p == '$')
2184 {
2185 *x++ = *p++;
2186 continue;
2187 }
2188 else if (*p == '{')
2189 {
2190 o = ++p;
2191 while (p != endp && *p != '}') p++;
2192 if (*p != '}') goto missingclose;
2193 s = p++;
2194 }
2195 else
2196 {
2197 o = p;
2198 while (p != endp && (isalnum (*p) || *p == '_')) p++;
2199 s = p;
2200 }
2201
2202 /* Copy out the variable name */
2203 target = (unsigned char *) alloca (s - o + 1);
2204 strncpy (target, o, s - o);
2205 target[s - o] = 0;
5e570b75 2206#ifdef DOS_NT
4c3c22f3 2207 strupr (target); /* $home == $HOME etc. */
5e570b75 2208#endif /* DOS_NT */
570d7624
JB
2209
2210 /* Get variable value */
2211 o = (unsigned char *) egetenv (target);
570d7624 2212 if (!o)
8d2ced53
SM
2213 {
2214 *x++ = '$';
2215 strcpy (x, target); x+= strlen (target);
2216 }
2217 else if (STRING_MULTIBYTE (filename))
60d67b83
RS
2218 {
2219 /* If the original string is multibyte,
2220 convert what we substitute into multibyte. */
60d67b83
RS
2221 while (*o)
2222 {
ce51c54c
KH
2223 int c = unibyte_char_to_multibyte (*o++);
2224 x += CHAR_STRING (c, x);
60d67b83
RS
2225 }
2226 }
2227 else
2228 {
2229 strcpy (x, o);
2230 x += strlen (o);
2231 }
570d7624
JB
2232 }
2233
2234 *x = 0;
2235
82330e7f 2236 /* If /~ or // appears, discard everything through first slash. */
570d7624
JB
2237
2238 for (p = xnm; p != x; p++)
5e570b75 2239 if ((p[0] == '~'
199607e4 2240#if defined (APOLLO) || defined (WINDOWSNT)
5e570b75 2241 || (IS_DIRECTORY_SEP (p[0]) && p - 1 != xnm)
199607e4
RS
2242#else /* not (APOLLO || WINDOWSNT) */
2243 || IS_DIRECTORY_SEP (p[0])
2244#endif /* not (APOLLO || WINDOWSNT) */
570d7624 2245 )
ac5b7072 2246 && p != xnm && IS_DIRECTORY_SEP (p[-1]))
570d7624 2247 xnm = p;
5e570b75 2248#ifdef DOS_NT
199607e4 2249 else if (IS_DRIVE (p[0]) && p[1] == ':'
4488d7e1 2250 && p > xnm && IS_DIRECTORY_SEP (p[-1]))
199607e4 2251 xnm = p;
4c3c22f3 2252#endif
570d7624 2253
60d67b83
RS
2254 if (STRING_MULTIBYTE (filename))
2255 return make_string (xnm, x - xnm);
2256 return make_unibyte_string (xnm, x - xnm);
570d7624
JB
2257
2258 badsubst:
2259 error ("Bad format environment-variable substitution");
2260 missingclose:
2261 error ("Missing \"}\" in environment-variable substitution");
2262 badvar:
2263 error ("Substituting nonexistent environment variable \"%s\"", target);
2264
2265 /* NOTREACHED */
2266#endif /* not VMS */
6bbd7a29 2267 return Qnil;
570d7624
JB
2268}
2269\f
067ffa38 2270/* A slightly faster and more convenient way to get
298b760e 2271 (directory-file-name (expand-file-name FOO)). */
067ffa38 2272
570d7624
JB
2273Lisp_Object
2274expand_and_dir_to_file (filename, defdir)
2275 Lisp_Object filename, defdir;
2276{
199607e4 2277 register Lisp_Object absname;
570d7624 2278
199607e4 2279 absname = Fexpand_file_name (filename, defdir);
570d7624
JB
2280#ifdef VMS
2281 {
d5db4077 2282 register int c = SREF (absname, SBYTES (absname) - 1);
570d7624 2283 if (c == ':' || c == ']' || c == '>')
199607e4 2284 absname = Fdirectory_file_name (absname);
570d7624
JB
2285 }
2286#else
199607e4 2287 /* Remove final slash, if any (unless this is the root dir).
570d7624 2288 stat behaves differently depending! */
d5db4077
KR
2289 if (SCHARS (absname) > 1
2290 && IS_DIRECTORY_SEP (SREF (absname, SBYTES (absname) - 1))
2291 && !IS_DEVICE_SEP (SREF (absname, SBYTES (absname)-2)))
ddc61f46 2292 /* We cannot take shortcuts; they might be wrong for magic file names. */
199607e4 2293 absname = Fdirectory_file_name (absname);
570d7624 2294#endif
199607e4 2295 return absname;
570d7624
JB
2296}
2297\f
3ed15d97
RS
2298/* Signal an error if the file ABSNAME already exists.
2299 If INTERACTIVE is nonzero, ask the user whether to proceed,
2300 and bypass the error if the user says to go ahead.
2301 QUERYSTRING is a name for the action that is being considered
2302 to alter the file.
de1d0127 2303
3ed15d97 2304 *STATPTR is used to store the stat information if the file exists.
de1d0127 2305 If the file does not exist, STATPTR->st_mode is set to 0.
b8b29dc9
RS
2306 If STATPTR is null, we don't store into it.
2307
2308 If QUICK is nonzero, we ask for y or n, not yes or no. */
3ed15d97 2309
c4df73f9 2310void
b8b29dc9 2311barf_or_query_if_file_exists (absname, querystring, interactive, statptr, quick)
570d7624
JB
2312 Lisp_Object absname;
2313 unsigned char *querystring;
2314 int interactive;
3ed15d97 2315 struct stat *statptr;
b8b29dc9 2316 int quick;
570d7624 2317{
643c73b9 2318 register Lisp_Object tem, encoded_filename;
4018b5ef 2319 struct stat statbuf;
570d7624
JB
2320 struct gcpro gcpro1;
2321
643c73b9
RS
2322 encoded_filename = ENCODE_FILE (absname);
2323
4018b5ef
RS
2324 /* stat is a good way to tell whether the file exists,
2325 regardless of what access permissions it has. */
d5db4077 2326 if (stat (SDATA (encoded_filename), &statbuf) >= 0)
570d7624
JB
2327 {
2328 if (! interactive)
2329 Fsignal (Qfile_already_exists,
2330 Fcons (build_string ("File already exists"),
2331 Fcons (absname, Qnil)));
2332 GCPRO1 (absname);
b8b29dc9 2333 tem = format1 ("File %s already exists; %s anyway? ",
d5db4077 2334 SDATA (absname), querystring);
b8b29dc9
RS
2335 if (quick)
2336 tem = Fy_or_n_p (tem);
2337 else
2338 tem = do_yes_or_no_p (tem);
570d7624 2339 UNGCPRO;
265a9e55 2340 if (NILP (tem))
570d7624
JB
2341 Fsignal (Qfile_already_exists,
2342 Fcons (build_string ("File already exists"),
2343 Fcons (absname, Qnil)));
3ed15d97
RS
2344 if (statptr)
2345 *statptr = statbuf;
2346 }
2347 else
2348 {
2349 if (statptr)
2350 statptr->st_mode = 0;
570d7624
JB
2351 }
2352 return;
2353}
2354
2355DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 4,
8c1a1077
PJ
2356 "fCopy file: \nFCopy %s to file: \np\nP",
2357 doc: /* Copy FILE to NEWNAME. Both args must be strings.
2358If NEWNAME names a directory, copy FILE there.
2359Signals a `file-already-exists' error if file NEWNAME already exists,
2360unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.
2361A number as third arg means request confirmation if NEWNAME already exists.
2362This is what happens in interactive use with M-x.
2363Fourth arg KEEP-TIME non-nil means give the new file the same
2364last-modified time as the old one. (This works on only some systems.)
2365A prefix arg makes KEEP-TIME non-nil. */)
2366 (file, newname, ok_if_already_exists, keep_time)
8ca6602c 2367 Lisp_Object file, newname, ok_if_already_exists, keep_time;
570d7624
JB
2368{
2369 int ifd, ofd, n;
2370 char buf[16 * 1024];
3ed15d97 2371 struct stat st, out_st;
32f4334d 2372 Lisp_Object handler;
b1d1b865 2373 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
aed13378 2374 int count = SPECPDL_INDEX ();
f73b0ada 2375 int input_file_statable_p;
b1d1b865 2376 Lisp_Object encoded_file, encoded_newname;
570d7624 2377
b1d1b865
RS
2378 encoded_file = encoded_newname = Qnil;
2379 GCPRO4 (file, newname, encoded_file, encoded_newname);
b7826503
PJ
2380 CHECK_STRING (file);
2381 CHECK_STRING (newname);
b1d1b865 2382
a9d14e54
GM
2383 if (!NILP (Ffile_directory_p (newname)))
2384 newname = Fexpand_file_name (file, newname);
2385 else
2386 newname = Fexpand_file_name (newname, Qnil);
2387
3b7f6e60 2388 file = Fexpand_file_name (file, Qnil);
32f4334d 2389
0bf2eed2 2390 /* If the input file name has special constructs in it,
32f4334d 2391 call the corresponding file handler. */
3b7f6e60 2392 handler = Ffind_file_name_handler (file, Qcopy_file);
0bf2eed2 2393 /* Likewise for output file name. */
51cf6d37 2394 if (NILP (handler))
49307295 2395 handler = Ffind_file_name_handler (newname, Qcopy_file);
32f4334d 2396 if (!NILP (handler))
3b7f6e60 2397 RETURN_UNGCPRO (call5 (handler, Qcopy_file, file, newname,
8ca6602c 2398 ok_if_already_exists, keep_time));
32f4334d 2399
b1d1b865
RS
2400 encoded_file = ENCODE_FILE (file);
2401 encoded_newname = ENCODE_FILE (newname);
2402
265a9e55 2403 if (NILP (ok_if_already_exists)
93c30b5f 2404 || INTEGERP (ok_if_already_exists))
b1d1b865 2405 barf_or_query_if_file_exists (encoded_newname, "copy to it",
b8b29dc9 2406 INTEGERP (ok_if_already_exists), &out_st, 0);
d5db4077 2407 else if (stat (SDATA (encoded_newname), &out_st) < 0)
3ed15d97 2408 out_st.st_mode = 0;
570d7624 2409
e8691c59 2410#ifdef WINDOWSNT
d5db4077
KR
2411 if (!CopyFile (SDATA (encoded_file),
2412 SDATA (encoded_newname),
e8691c59
GM
2413 FALSE))
2414 report_file_error ("Copying file", Fcons (file, Fcons (newname, Qnil)));
2415 else if (NILP (keep_time))
2416 {
2417 EMACS_TIME now;
ad497129
JR
2418 DWORD attributes;
2419 char * filename;
2420
e8691c59 2421 EMACS_GET_TIME (now);
d5db4077 2422 filename = SDATA (encoded_newname);
ad497129
JR
2423
2424 /* Ensure file is writable while its modified time is set. */
2425 attributes = GetFileAttributes (filename);
02cca86b 2426 SetFileAttributes (filename, attributes & ~FILE_ATTRIBUTE_READONLY);
ad497129
JR
2427 if (set_file_times (filename, now, now))
2428 {
2429 /* Restore original attributes. */
2430 SetFileAttributes (filename, attributes);
2431 Fsignal (Qfile_date_error,
2432 Fcons (build_string ("Cannot set file date"),
2433 Fcons (newname, Qnil)));
2434 }
2435 /* Restore original attributes. */
2436 SetFileAttributes (filename, attributes);
e8691c59
GM
2437 }
2438#else /* not WINDOWSNT */
d5db4077 2439 ifd = emacs_open (SDATA (encoded_file), O_RDONLY, 0);
570d7624 2440 if (ifd < 0)
3b7f6e60 2441 report_file_error ("Opening input file", Fcons (file, Qnil));
570d7624 2442
b5148e85
RS
2443 record_unwind_protect (close_file_unwind, make_number (ifd));
2444
f73b0ada
BF
2445 /* We can only copy regular files and symbolic links. Other files are not
2446 copyable by us. */
2447 input_file_statable_p = (fstat (ifd, &st) >= 0);
2448
f9ba66ce 2449#if !defined (DOS_NT) || __DJGPP__ > 1
3ed15d97
RS
2450 if (out_st.st_mode != 0
2451 && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
2452 {
2453 errno = 0;
2454 report_file_error ("Input and output files are the same",
3b7f6e60 2455 Fcons (file, Fcons (newname, Qnil)));
3ed15d97
RS
2456 }
2457#endif
2458
f73b0ada
BF
2459#if defined (S_ISREG) && defined (S_ISLNK)
2460 if (input_file_statable_p)
2461 {
2462 if (!(S_ISREG (st.st_mode)) && !(S_ISLNK (st.st_mode)))
2463 {
2464#if defined (EISDIR)
2465 /* Get a better looking error message. */
2466 errno = EISDIR;
2467#endif /* EISDIR */
3b7f6e60 2468 report_file_error ("Non-regular file", Fcons (file, Qnil));
f73b0ada
BF
2469 }
2470 }
2471#endif /* S_ISREG && S_ISLNK */
2472
570d7624
JB
2473#ifdef VMS
2474 /* Create the copy file with the same record format as the input file */
d5db4077 2475 ofd = sys_creat (SDATA (encoded_newname), 0666, ifd);
570d7624 2476#else
4c3c22f3
RS
2477#ifdef MSDOS
2478 /* System's default file type was set to binary by _fmode in emacs.c. */
d5db4077 2479 ofd = creat (SDATA (encoded_newname), S_IREAD | S_IWRITE);
4c3c22f3 2480#else /* not MSDOS */
d5db4077 2481 ofd = creat (SDATA (encoded_newname), 0666);
4c3c22f3 2482#endif /* not MSDOS */
570d7624
JB
2483#endif /* VMS */
2484 if (ofd < 0)
3ed15d97 2485 report_file_error ("Opening output file", Fcons (newname, Qnil));
b5148e85
RS
2486
2487 record_unwind_protect (close_file_unwind, make_number (ofd));
570d7624 2488
b5148e85
RS
2489 immediate_quit = 1;
2490 QUIT;
68c45bf0
PE
2491 while ((n = emacs_read (ifd, buf, sizeof buf)) > 0)
2492 if (emacs_write (ofd, buf, n) != n)
3ed15d97 2493 report_file_error ("I/O error", Fcons (newname, Qnil));
b5148e85 2494 immediate_quit = 0;
570d7624 2495
5acac34e 2496 /* Closing the output clobbers the file times on some systems. */
68c45bf0 2497 if (emacs_close (ofd) < 0)
5acac34e
RS
2498 report_file_error ("I/O error", Fcons (newname, Qnil));
2499
f73b0ada 2500 if (input_file_statable_p)
570d7624 2501 {
8ca6602c 2502 if (!NILP (keep_time))
570d7624 2503 {
de5bf5d3
JB
2504 EMACS_TIME atime, mtime;
2505 EMACS_SET_SECS_USECS (atime, st.st_atime, 0);
2506 EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0);
d5db4077 2507 if (set_file_times (SDATA (encoded_newname),
b1d1b865 2508 atime, mtime))
c0b7b21c 2509 Fsignal (Qfile_date_error,
d1b9ed63 2510 Fcons (build_string ("Cannot set file date"),
3dbcf3f6 2511 Fcons (newname, Qnil)));
570d7624 2512 }
2dc3be7e 2513#ifndef MSDOS
d5db4077 2514 chmod (SDATA (encoded_newname), st.st_mode & 07777);
2dc3be7e
RS
2515#else /* MSDOS */
2516#if defined (__DJGPP__) && __DJGPP__ > 1
2517 /* In DJGPP v2.0 and later, fstat usually returns true file mode bits,
2518 and if it can't, it tells so. Otherwise, under MSDOS we usually
2519 get only the READ bit, which will make the copied file read-only,
2520 so it's better not to chmod at all. */
2521 if ((_djstat_flags & _STFAIL_WRITEBIT) == 0)
d5db4077 2522 chmod (SDATA (encoded_newname), st.st_mode & 07777);
2dc3be7e
RS
2523#endif /* DJGPP version 2 or newer */
2524#endif /* MSDOS */
570d7624
JB
2525 }
2526
68c45bf0 2527 emacs_close (ifd);
e8691c59 2528#endif /* WINDOWSNT */
5acac34e 2529
b5148e85
RS
2530 /* Discard the unwind protects. */
2531 specpdl_ptr = specpdl + count;
2532
570d7624
JB
2533 UNGCPRO;
2534 return Qnil;
2535}
385b6cc7 2536\f
9bbe01fb 2537DEFUN ("make-directory-internal", Fmake_directory_internal,
353cfc19 2538 Smake_directory_internal, 1, 1, 0,
8c1a1077
PJ
2539 doc: /* Create a new directory named DIRECTORY. */)
2540 (directory)
3b7f6e60 2541 Lisp_Object directory;
570d7624
JB
2542{
2543 unsigned char *dir;
32f4334d 2544 Lisp_Object handler;
b1d1b865 2545 Lisp_Object encoded_dir;
570d7624 2546
b7826503 2547 CHECK_STRING (directory);
3b7f6e60 2548 directory = Fexpand_file_name (directory, Qnil);
32f4334d 2549
3b7f6e60 2550 handler = Ffind_file_name_handler (directory, Qmake_directory_internal);
32f4334d 2551 if (!NILP (handler))
3b7f6e60 2552 return call2 (handler, Qmake_directory_internal, directory);
9bbe01fb 2553
b1d1b865
RS
2554 encoded_dir = ENCODE_FILE (directory);
2555
d5db4077 2556 dir = SDATA (encoded_dir);
570d7624 2557
5e570b75
RS
2558#ifdef WINDOWSNT
2559 if (mkdir (dir) != 0)
2560#else
570d7624 2561 if (mkdir (dir, 0777) != 0)
5e570b75 2562#endif
3b7f6e60 2563 report_file_error ("Creating directory", Flist (1, &directory));
570d7624 2564
32f4334d 2565 return Qnil;
570d7624
JB
2566}
2567
aa734e17 2568DEFUN ("delete-directory", Fdelete_directory, Sdelete_directory, 1, 1, "FDelete directory: ",
8c1a1077
PJ
2569 doc: /* Delete the directory named DIRECTORY. */)
2570 (directory)
3b7f6e60 2571 Lisp_Object directory;
570d7624
JB
2572{
2573 unsigned char *dir;
32f4334d 2574 Lisp_Object handler;
b1d1b865 2575 Lisp_Object encoded_dir;
570d7624 2576
b7826503 2577 CHECK_STRING (directory);
3b7f6e60 2578 directory = Fdirectory_file_name (Fexpand_file_name (directory, Qnil));
570d7624 2579
3b7f6e60 2580 handler = Ffind_file_name_handler (directory, Qdelete_directory);
32f4334d 2581 if (!NILP (handler))
3b7f6e60 2582 return call2 (handler, Qdelete_directory, directory);
32f4334d 2583
b1d1b865
RS
2584 encoded_dir = ENCODE_FILE (directory);
2585
d5db4077 2586 dir = SDATA (encoded_dir);
b1d1b865 2587
570d7624 2588 if (rmdir (dir) != 0)
3b7f6e60 2589 report_file_error ("Removing directory", Flist (1, &directory));
570d7624
JB
2590
2591 return Qnil;
2592}
2593
2594DEFUN ("delete-file", Fdelete_file, Sdelete_file, 1, 1, "fDelete file: ",
8c1a1077
PJ
2595 doc: /* Delete file named FILENAME.
2596If file has multiple names, it continues to exist with the other names. */)
2597 (filename)
570d7624
JB
2598 Lisp_Object filename;
2599{
32f4334d 2600 Lisp_Object handler;
b1d1b865
RS
2601 Lisp_Object encoded_file;
2602
b7826503 2603 CHECK_STRING (filename);
570d7624 2604 filename = Fexpand_file_name (filename, Qnil);
32f4334d 2605
49307295 2606 handler = Ffind_file_name_handler (filename, Qdelete_file);
32f4334d 2607 if (!NILP (handler))
8a9b0da9 2608 return call2 (handler, Qdelete_file, filename);
32f4334d 2609
b1d1b865
RS
2610 encoded_file = ENCODE_FILE (filename);
2611
d5db4077 2612 if (0 > unlink (SDATA (encoded_file)))
570d7624 2613 report_file_error ("Removing old name", Flist (1, &filename));
8a9b0da9 2614 return Qnil;
570d7624
JB
2615}
2616
385b6cc7
RS
2617static Lisp_Object
2618internal_delete_file_1 (ignore)
2619 Lisp_Object ignore;
2620{
2621 return Qt;
2622}
2623
2624/* Delete file FILENAME, returning 1 if successful and 0 if failed. */
2625
2626int
2627internal_delete_file (filename)
2628 Lisp_Object filename;
2629{
2630 return NILP (internal_condition_case_1 (Fdelete_file, filename,
2631 Qt, internal_delete_file_1));
2632}
2633\f
570d7624 2634DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
8c1a1077
PJ
2635 "fRename file: \nFRename %s to file: \np",
2636 doc: /* Rename FILE as NEWNAME. Both args strings.
2637If file has names other than FILE, it continues to have those names.
2638Signals a `file-already-exists' error if a file NEWNAME already exists
2639unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.
2640A number as third arg means request confirmation if NEWNAME already exists.
2641This is what happens in interactive use with M-x. */)
2642 (file, newname, ok_if_already_exists)
3b7f6e60 2643 Lisp_Object file, newname, ok_if_already_exists;
570d7624
JB
2644{
2645#ifdef NO_ARG_ARRAY
2646 Lisp_Object args[2];
2647#endif
32f4334d 2648 Lisp_Object handler;
b1d1b865
RS
2649 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2650 Lisp_Object encoded_file, encoded_newname;
570d7624 2651
b1d1b865
RS
2652 encoded_file = encoded_newname = Qnil;
2653 GCPRO4 (file, newname, encoded_file, encoded_newname);
b7826503
PJ
2654 CHECK_STRING (file);
2655 CHECK_STRING (newname);
3b7f6e60 2656 file = Fexpand_file_name (file, Qnil);
570d7624 2657 newname = Fexpand_file_name (newname, Qnil);
32f4334d
RS
2658
2659 /* If the file name has special constructs in it,
2660 call the corresponding file handler. */
3b7f6e60 2661 handler = Ffind_file_name_handler (file, Qrename_file);
51cf6d37 2662 if (NILP (handler))
49307295 2663 handler = Ffind_file_name_handler (newname, Qrename_file);
32f4334d 2664 if (!NILP (handler))
36712b0a 2665 RETURN_UNGCPRO (call4 (handler, Qrename_file,
3b7f6e60 2666 file, newname, ok_if_already_exists));
32f4334d 2667
b1d1b865
RS
2668 encoded_file = ENCODE_FILE (file);
2669 encoded_newname = ENCODE_FILE (newname);
2670
bc77278f
EZ
2671#ifdef DOS_NT
2672 /* If the file names are identical but for the case, don't ask for
2673 confirmation: they simply want to change the letter-case of the
2674 file name. */
2675 if (NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname))))
2676#endif
265a9e55 2677 if (NILP (ok_if_already_exists)
93c30b5f 2678 || INTEGERP (ok_if_already_exists))
b1d1b865 2679 barf_or_query_if_file_exists (encoded_newname, "rename to it",
b8b29dc9 2680 INTEGERP (ok_if_already_exists), 0, 0);
570d7624 2681#ifndef BSD4_1
d5db4077 2682 if (0 > rename (SDATA (encoded_file), SDATA (encoded_newname)))
570d7624 2683#else
d5db4077
KR
2684 if (0 > link (SDATA (encoded_file), SDATA (encoded_newname))
2685 || 0 > unlink (SDATA (encoded_file)))
570d7624
JB
2686#endif
2687 {
2688 if (errno == EXDEV)
2689 {
3b7f6e60 2690 Fcopy_file (file, newname,
d093c3ac
RM
2691 /* We have already prompted if it was an integer,
2692 so don't have copy-file prompt again. */
2693 NILP (ok_if_already_exists) ? Qnil : Qt, Qt);
3b7f6e60 2694 Fdelete_file (file);
570d7624
JB
2695 }
2696 else
2697#ifdef NO_ARG_ARRAY
2698 {
3b7f6e60 2699 args[0] = file;
570d7624
JB
2700 args[1] = newname;
2701 report_file_error ("Renaming", Flist (2, args));
2702 }
2703#else
3b7f6e60 2704 report_file_error ("Renaming", Flist (2, &file));
570d7624
JB
2705#endif
2706 }
2707 UNGCPRO;
2708 return Qnil;
2709}
2710
2711DEFUN ("add-name-to-file", Fadd_name_to_file, Sadd_name_to_file, 2, 3,
8c1a1077
PJ
2712 "fAdd name to file: \nFName to add to %s: \np",
2713 doc: /* Give FILE additional name NEWNAME. Both args strings.
2714Signals a `file-already-exists' error if a file NEWNAME already exists
2715unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.
2716A number as third arg means request confirmation if NEWNAME already exists.
2717This is what happens in interactive use with M-x. */)
2718 (file, newname, ok_if_already_exists)
3b7f6e60 2719 Lisp_Object file, newname, ok_if_already_exists;
570d7624
JB
2720{
2721#ifdef NO_ARG_ARRAY
2722 Lisp_Object args[2];
2723#endif
32f4334d 2724 Lisp_Object handler;
b1d1b865
RS
2725 Lisp_Object encoded_file, encoded_newname;
2726 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
570d7624 2727
b1d1b865
RS
2728 GCPRO4 (file, newname, encoded_file, encoded_newname);
2729 encoded_file = encoded_newname = Qnil;
b7826503
PJ
2730 CHECK_STRING (file);
2731 CHECK_STRING (newname);
3b7f6e60 2732 file = Fexpand_file_name (file, Qnil);
570d7624 2733 newname = Fexpand_file_name (newname, Qnil);
32f4334d
RS
2734
2735 /* If the file name has special constructs in it,
2736 call the corresponding file handler. */
3b7f6e60 2737 handler = Ffind_file_name_handler (file, Qadd_name_to_file);
32f4334d 2738 if (!NILP (handler))
3b7f6e60 2739 RETURN_UNGCPRO (call4 (handler, Qadd_name_to_file, file,
36712b0a 2740 newname, ok_if_already_exists));
32f4334d 2741
adc6741c
RS
2742 /* If the new name has special constructs in it,
2743 call the corresponding file handler. */
2744 handler = Ffind_file_name_handler (newname, Qadd_name_to_file);
2745 if (!NILP (handler))
3b7f6e60 2746 RETURN_UNGCPRO (call4 (handler, Qadd_name_to_file, file,
adc6741c
RS
2747 newname, ok_if_already_exists));
2748
b1d1b865
RS
2749 encoded_file = ENCODE_FILE (file);
2750 encoded_newname = ENCODE_FILE (newname);
2751
265a9e55 2752 if (NILP (ok_if_already_exists)
93c30b5f 2753 || INTEGERP (ok_if_already_exists))
b1d1b865 2754 barf_or_query_if_file_exists (encoded_newname, "make it a new name",
b8b29dc9 2755 INTEGERP (ok_if_already_exists), 0, 0);
5e570b75 2756
d5db4077
KR
2757 unlink (SDATA (newname));
2758 if (0 > link (SDATA (encoded_file), SDATA (encoded_newname)))
570d7624
JB
2759 {
2760#ifdef NO_ARG_ARRAY
3b7f6e60 2761 args[0] = file;
570d7624
JB
2762 args[1] = newname;
2763 report_file_error ("Adding new name", Flist (2, args));
2764#else
3b7f6e60 2765 report_file_error ("Adding new name", Flist (2, &file));
570d7624
JB
2766#endif
2767 }
2768
2769 UNGCPRO;
2770 return Qnil;
2771}
2772
2773#ifdef S_IFLNK
2774DEFUN ("make-symbolic-link", Fmake_symbolic_link, Smake_symbolic_link, 2, 3,
8c1a1077
PJ
2775 "FMake symbolic link to file: \nFMake symbolic link to file %s: \np",
2776 doc: /* Make a symbolic link to FILENAME, named LINKNAME. Both args strings.
2777Signals a `file-already-exists' error if a file LINKNAME already exists
2778unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.
2779A number as third arg means request confirmation if LINKNAME already exists.
2780This happens for interactive use with M-x. */)
2781 (filename, linkname, ok_if_already_exists)
e5d77022 2782 Lisp_Object filename, linkname, ok_if_already_exists;
570d7624
JB
2783{
2784#ifdef NO_ARG_ARRAY
2785 Lisp_Object args[2];
2786#endif
32f4334d 2787 Lisp_Object handler;
b1d1b865
RS
2788 Lisp_Object encoded_filename, encoded_linkname;
2789 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
570d7624 2790
b1d1b865
RS
2791 GCPRO4 (filename, linkname, encoded_filename, encoded_linkname);
2792 encoded_filename = encoded_linkname = Qnil;
b7826503
PJ
2793 CHECK_STRING (filename);
2794 CHECK_STRING (linkname);
d9bc1c99
RS
2795 /* If the link target has a ~, we must expand it to get
2796 a truly valid file name. Otherwise, do not expand;
2797 we want to permit links to relative file names. */
d5db4077 2798 if (SREF (filename, 0) == '~')
d9bc1c99 2799 filename = Fexpand_file_name (filename, Qnil);
e5d77022 2800 linkname = Fexpand_file_name (linkname, Qnil);
32f4334d
RS
2801
2802 /* If the file name has special constructs in it,
2803 call the corresponding file handler. */
49307295 2804 handler = Ffind_file_name_handler (filename, Qmake_symbolic_link);
32f4334d 2805 if (!NILP (handler))
36712b0a
KH
2806 RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename,
2807 linkname, ok_if_already_exists));
32f4334d 2808
adc6741c
RS
2809 /* If the new link name has special constructs in it,
2810 call the corresponding file handler. */
2811 handler = Ffind_file_name_handler (linkname, Qmake_symbolic_link);
2812 if (!NILP (handler))
2813 RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename,
2814 linkname, ok_if_already_exists));
2815
b1d1b865
RS
2816 encoded_filename = ENCODE_FILE (filename);
2817 encoded_linkname = ENCODE_FILE (linkname);
2818
265a9e55 2819 if (NILP (ok_if_already_exists)
93c30b5f 2820 || INTEGERP (ok_if_already_exists))
b1d1b865 2821 barf_or_query_if_file_exists (encoded_linkname, "make it a link",
b8b29dc9 2822 INTEGERP (ok_if_already_exists), 0, 0);
d5db4077
KR
2823 if (0 > symlink (SDATA (encoded_filename),
2824 SDATA (encoded_linkname)))
570d7624
JB
2825 {
2826 /* If we didn't complain already, silently delete existing file. */
2827 if (errno == EEXIST)
2828 {
d5db4077
KR
2829 unlink (SDATA (encoded_linkname));
2830 if (0 <= symlink (SDATA (encoded_filename),
2831 SDATA (encoded_linkname)))
1a04498e
KH
2832 {
2833 UNGCPRO;
2834 return Qnil;
2835 }
570d7624
JB
2836 }
2837
2838#ifdef NO_ARG_ARRAY
2839 args[0] = filename;
e5d77022 2840 args[1] = linkname;
570d7624
JB
2841 report_file_error ("Making symbolic link", Flist (2, args));
2842#else
2843 report_file_error ("Making symbolic link", Flist (2, &filename));
2844#endif
2845 }
2846 UNGCPRO;
2847 return Qnil;
2848}
2849#endif /* S_IFLNK */
2850
2851#ifdef VMS
2852
2853DEFUN ("define-logical-name", Fdefine_logical_name, Sdefine_logical_name,
2854 2, 2, "sDefine logical name: \nsDefine logical name %s as: ",
8c1a1077
PJ
2855 doc: /* Define the job-wide logical name NAME to have the value STRING.
2856If STRING is nil or a null string, the logical name NAME is deleted. */)
2857 (name, string)
3b7f6e60 2858 Lisp_Object name;
570d7624
JB
2859 Lisp_Object string;
2860{
b7826503 2861 CHECK_STRING (name);
265a9e55 2862 if (NILP (string))
d5db4077 2863 delete_logical_name (SDATA (name));
570d7624
JB
2864 else
2865 {
b7826503 2866 CHECK_STRING (string);
570d7624 2867
d5db4077
KR
2868 if (SCHARS (string) == 0)
2869 delete_logical_name (SDATA (name));
570d7624 2870 else
d5db4077 2871 define_logical_name (SDATA (name), SDATA (string));
570d7624
JB
2872 }
2873
2874 return string;
2875}
2876#endif /* VMS */
2877
2878#ifdef HPUX_NET
2879
2880DEFUN ("sysnetunam", Fsysnetunam, Ssysnetunam, 2, 2, 0,
8c1a1077 2881 doc: /* Open a network connection to PATH using LOGIN as the login string. */)
570d7624
JB
2882 (path, login)
2883 Lisp_Object path, login;
2884{
2885 int netresult;
199607e4 2886
b7826503
PJ
2887 CHECK_STRING (path);
2888 CHECK_STRING (login);
199607e4 2889
d5db4077 2890 netresult = netunam (SDATA (path), SDATA (login));
570d7624
JB
2891
2892 if (netresult == -1)
2893 return Qnil;
2894 else
2895 return Qt;
2896}
2897#endif /* HPUX_NET */
2898\f
2899DEFUN ("file-name-absolute-p", Ffile_name_absolute_p, Sfile_name_absolute_p,
2900 1, 1, 0,
8c1a1077
PJ
2901 doc: /* Return t if file FILENAME specifies an absolute file name.
2902On Unix, this is a name starting with a `/' or a `~'. */)
570d7624
JB
2903 (filename)
2904 Lisp_Object filename;
2905{
2906 unsigned char *ptr;
2907
b7826503 2908 CHECK_STRING (filename);
d5db4077 2909 ptr = SDATA (filename);
5e570b75 2910 if (IS_DIRECTORY_SEP (*ptr) || *ptr == '~'
570d7624
JB
2911#ifdef VMS
2912/* ??? This criterion is probably wrong for '<'. */
2913 || index (ptr, ':') || index (ptr, '<')
2914 || (*ptr == '[' && (ptr[1] != '-' || (ptr[2] != '.' && ptr[2] != ']'))
2915 && ptr[1] != '.')
2916#endif /* VMS */
5e570b75 2917#ifdef DOS_NT
199607e4 2918 || (IS_DRIVE (*ptr) && ptr[1] == ':' && IS_DIRECTORY_SEP (ptr[2]))
4c3c22f3 2919#endif
570d7624
JB
2920 )
2921 return Qt;
2922 else
2923 return Qnil;
2924}
3beeedfe
RS
2925\f
2926/* Return nonzero if file FILENAME exists and can be executed. */
2927
2928static int
2929check_executable (filename)
2930 char *filename;
2931{
3be3c08e
RS
2932#ifdef DOS_NT
2933 int len = strlen (filename);
2934 char *suffix;
2935 struct stat st;
2936 if (stat (filename, &st) < 0)
2937 return 0;
34ead71a 2938#if defined (WINDOWSNT) || (defined (MSDOS) && __DJGPP__ > 1)
199607e4
RS
2939 return ((st.st_mode & S_IEXEC) != 0);
2940#else
3be3c08e
RS
2941 return (S_ISREG (st.st_mode)
2942 && len >= 5
2943 && (stricmp ((suffix = filename + len-4), ".com") == 0
2944 || stricmp (suffix, ".exe") == 0
2dc3be7e
RS
2945 || stricmp (suffix, ".bat") == 0)
2946 || (st.st_mode & S_IFMT) == S_IFDIR);
199607e4 2947#endif /* not WINDOWSNT */
3be3c08e 2948#else /* not DOS_NT */
de0be7dd
RS
2949#ifdef HAVE_EUIDACCESS
2950 return (euidaccess (filename, 1) >= 0);
3beeedfe
RS
2951#else
2952 /* Access isn't quite right because it uses the real uid
2953 and we really want to test with the effective uid.
2954 But Unix doesn't give us a right way to do it. */
2955 return (access (filename, 1) >= 0);
2956#endif
3be3c08e 2957#endif /* not DOS_NT */
3beeedfe
RS
2958}
2959
2960/* Return nonzero if file FILENAME exists and can be written. */
2961
2962static int
2963check_writable (filename)
2964 char *filename;
2965{
3be3c08e
RS
2966#ifdef MSDOS
2967 struct stat st;
2968 if (stat (filename, &st) < 0)
2969 return 0;
2970 return (st.st_mode & S_IWRITE || (st.st_mode & S_IFMT) == S_IFDIR);
2971#else /* not MSDOS */
41f3fb38
KH
2972#ifdef HAVE_EUIDACCESS
2973 return (euidaccess (filename, 2) >= 0);
3beeedfe
RS
2974#else
2975 /* Access isn't quite right because it uses the real uid
2976 and we really want to test with the effective uid.
2977 But Unix doesn't give us a right way to do it.
2978 Opening with O_WRONLY could work for an ordinary file,
2979 but would lose for directories. */
2980 return (access (filename, 2) >= 0);
2981#endif
3be3c08e 2982#endif /* not MSDOS */
3beeedfe 2983}
570d7624
JB
2984
2985DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0,
8c1a1077
PJ
2986 doc: /* Return t if file FILENAME exists. (This does not mean you can read it.)
2987See also `file-readable-p' and `file-attributes'. */)
2988 (filename)
570d7624
JB
2989 Lisp_Object filename;
2990{
199607e4 2991 Lisp_Object absname;
32f4334d 2992 Lisp_Object handler;
4018b5ef 2993 struct stat statbuf;
570d7624 2994
b7826503 2995 CHECK_STRING (filename);
199607e4 2996 absname = Fexpand_file_name (filename, Qnil);
32f4334d
RS
2997
2998 /* If the file name has special constructs in it,
2999 call the corresponding file handler. */
199607e4 3000 handler = Ffind_file_name_handler (absname, Qfile_exists_p);
32f4334d 3001 if (!NILP (handler))
199607e4 3002 return call2 (handler, Qfile_exists_p, absname);
32f4334d 3003
b1d1b865
RS
3004 absname = ENCODE_FILE (absname);
3005
d5db4077 3006 return (stat (SDATA (absname), &statbuf) >= 0) ? Qt : Qnil;
570d7624
JB
3007}
3008
3009DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
8c1a1077
PJ
3010 doc: /* Return t if FILENAME can be executed by you.
3011For a directory, this means you can access files in that directory. */)
3012 (filename)
3013 Lisp_Object filename;
570d7624 3014{
199607e4 3015 Lisp_Object absname;
32f4334d 3016 Lisp_Object handler;
570d7624 3017
b7826503 3018 CHECK_STRING (filename);
199607e4 3019 absname = Fexpand_file_name (filename, Qnil);
32f4334d
RS
3020
3021 /* If the file name has special constructs in it,
3022 call the corresponding file handler. */
199607e4 3023 handler = Ffind_file_name_handler (absname, Qfile_executable_p);
32f4334d 3024 if (!NILP (handler))
199607e4 3025 return call2 (handler, Qfile_executable_p, absname);
32f4334d 3026
b1d1b865
RS
3027 absname = ENCODE_FILE (absname);
3028
d5db4077 3029 return (check_executable (SDATA (absname)) ? Qt : Qnil);
570d7624
JB
3030}
3031
3032DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0,
8c1a1077
PJ
3033 doc: /* Return t if file FILENAME exists and you can read it.
3034See also `file-exists-p' and `file-attributes'. */)
3035 (filename)
570d7624
JB
3036 Lisp_Object filename;
3037{
199607e4 3038 Lisp_Object absname;
32f4334d 3039 Lisp_Object handler;
4018b5ef 3040 int desc;
bb369dc6
RS
3041 int flags;
3042 struct stat statbuf;
570d7624 3043
b7826503 3044 CHECK_STRING (filename);
199607e4 3045 absname = Fexpand_file_name (filename, Qnil);
32f4334d
RS
3046
3047 /* If the file name has special constructs in it,
3048 call the corresponding file handler. */
199607e4 3049 handler = Ffind_file_name_handler (absname, Qfile_readable_p);
32f4334d 3050 if (!NILP (handler))
199607e4 3051 return call2 (handler, Qfile_readable_p, absname);
32f4334d 3052
b1d1b865
RS
3053 absname = ENCODE_FILE (absname);
3054
fb4c6c96
AC
3055#if defined(DOS_NT) || defined(macintosh)
3056 /* Under MS-DOS, Windows, and Macintosh, open does not work for
3057 directories. */
d5db4077 3058 if (access (SDATA (absname), 0) == 0)
a8a7d065
RS
3059 return Qt;
3060 return Qnil;
fb4c6c96 3061#else /* not DOS_NT and not macintosh */
bb369dc6
RS
3062 flags = O_RDONLY;
3063#if defined (S_ISFIFO) && defined (O_NONBLOCK)
3064 /* Opening a fifo without O_NONBLOCK can wait.
3065 We don't want to wait. But we don't want to mess wth O_NONBLOCK
3066 except in the case of a fifo, on a system which handles it. */
d5db4077 3067 desc = stat (SDATA (absname), &statbuf);
bb369dc6
RS
3068 if (desc < 0)
3069 return Qnil;
3070 if (S_ISFIFO (statbuf.st_mode))
3071 flags |= O_NONBLOCK;
3072#endif
d5db4077 3073 desc = emacs_open (SDATA (absname), flags, 0);
4018b5ef
RS
3074 if (desc < 0)
3075 return Qnil;
68c45bf0 3076 emacs_close (desc);
4018b5ef 3077 return Qt;
fb4c6c96 3078#endif /* not DOS_NT and not macintosh */
570d7624
JB
3079}
3080
f793dc6c
RS
3081/* Having this before file-symlink-p mysteriously caused it to be forgotten
3082 on the RT/PC. */
3083DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
8c1a1077
PJ
3084 doc: /* Return t if file FILENAME can be written or created by you. */)
3085 (filename)
f793dc6c
RS
3086 Lisp_Object filename;
3087{
b1d1b865 3088 Lisp_Object absname, dir, encoded;
f793dc6c
RS
3089 Lisp_Object handler;
3090 struct stat statbuf;
3091
b7826503 3092 CHECK_STRING (filename);
199607e4 3093 absname = Fexpand_file_name (filename, Qnil);
f793dc6c
RS
3094
3095 /* If the file name has special constructs in it,
3096 call the corresponding file handler. */
199607e4 3097 handler = Ffind_file_name_handler (absname, Qfile_writable_p);
f793dc6c 3098 if (!NILP (handler))
199607e4 3099 return call2 (handler, Qfile_writable_p, absname);
f793dc6c 3100
b1d1b865 3101 encoded = ENCODE_FILE (absname);
d5db4077
KR
3102 if (stat (SDATA (encoded), &statbuf) >= 0)
3103 return (check_writable (SDATA (encoded))
f793dc6c 3104 ? Qt : Qnil);
b1d1b865 3105
199607e4 3106 dir = Ffile_name_directory (absname);
f793dc6c
RS
3107#ifdef VMS
3108 if (!NILP (dir))
3109 dir = Fdirectory_file_name (dir);
3110#endif /* VMS */
3111#ifdef MSDOS
3112 if (!NILP (dir))
3113 dir = Fdirectory_file_name (dir);
3114#endif /* MSDOS */
b1d1b865
RS
3115
3116 dir = ENCODE_FILE (dir);
e3e8a75a
GM
3117#ifdef WINDOWSNT
3118 /* The read-only attribute of the parent directory doesn't affect
3119 whether a file or directory can be created within it. Some day we
3120 should check ACLs though, which do affect this. */
d5db4077 3121 if (stat (SDATA (dir), &statbuf) < 0)
e3e8a75a
GM
3122 return Qnil;
3123 return (statbuf.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil;
3124#else
d5db4077 3125 return (check_writable (!NILP (dir) ? (char *) SDATA (dir) : "")
f793dc6c 3126 ? Qt : Qnil);
e3e8a75a 3127#endif
f793dc6c
RS
3128}
3129\f
1f8653eb 3130DEFUN ("access-file", Faccess_file, Saccess_file, 2, 2, 0,
8c1a1077
PJ
3131 doc: /* Access file FILENAME, and get an error if that does not work.
3132The second argument STRING is used in the error message.
3133If there is no error, we return nil. */)
3134 (filename, string)
1f8653eb
RS
3135 Lisp_Object filename, string;
3136{
49475635 3137 Lisp_Object handler, encoded_filename, absname;
1f8653eb
RS
3138 int fd;
3139
b7826503 3140 CHECK_STRING (filename);
49475635
EZ
3141 absname = Fexpand_file_name (filename, Qnil);
3142
b7826503 3143 CHECK_STRING (string);
1f8653eb
RS
3144
3145 /* If the file name has special constructs in it,
3146 call the corresponding file handler. */
49475635 3147 handler = Ffind_file_name_handler (absname, Qaccess_file);
1f8653eb 3148 if (!NILP (handler))
49475635 3149 return call3 (handler, Qaccess_file, absname, string);
1f8653eb 3150
49475635 3151 encoded_filename = ENCODE_FILE (absname);
b1d1b865 3152
d5db4077 3153 fd = emacs_open (SDATA (encoded_filename), O_RDONLY, 0);
1f8653eb 3154 if (fd < 0)
d5db4077 3155 report_file_error (SDATA (string), Fcons (filename, Qnil));
68c45bf0 3156 emacs_close (fd);
1f8653eb
RS
3157
3158 return Qnil;
3159}
3160\f
570d7624 3161DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0,
8c1a1077
PJ
3162 doc: /* Return non-nil if file FILENAME is the name of a symbolic link.
3163The value is the name of the file to which it is linked.
3164Otherwise returns nil. */)
3165 (filename)
570d7624
JB
3166 Lisp_Object filename;
3167{
3168#ifdef S_IFLNK
3169 char *buf;
3170 int bufsize;
3171 int valsize;
3172 Lisp_Object val;
32f4334d 3173 Lisp_Object handler;
570d7624 3174
b7826503 3175 CHECK_STRING (filename);
570d7624
JB
3176 filename = Fexpand_file_name (filename, Qnil);
3177
32f4334d
RS
3178 /* If the file name has special constructs in it,
3179 call the corresponding file handler. */
49307295 3180 handler = Ffind_file_name_handler (filename, Qfile_symlink_p);
32f4334d
RS
3181 if (!NILP (handler))
3182 return call2 (handler, Qfile_symlink_p, filename);
3183
b1d1b865
RS
3184 filename = ENCODE_FILE (filename);
3185
81c3310d
GM
3186 bufsize = 50;
3187 buf = NULL;
3188 do
570d7624 3189 {
81c3310d
GM
3190 bufsize *= 2;
3191 buf = (char *) xrealloc (buf, bufsize);
570d7624 3192 bzero (buf, bufsize);
81c3310d
GM
3193
3194 errno = 0;
d5db4077 3195 valsize = readlink (SDATA (filename), buf, bufsize);
bcdd93b3
GM
3196 if (valsize == -1)
3197 {
81c3310d
GM
3198#ifdef ERANGE
3199 /* HP-UX reports ERANGE if buffer is too small. */
bcdd93b3
GM
3200 if (errno == ERANGE)
3201 valsize = bufsize;
3202 else
81c3310d 3203#endif
bcdd93b3
GM
3204 {
3205 xfree (buf);
3206 return Qnil;
3207 }
81c3310d 3208 }
570d7624 3209 }
81c3310d
GM
3210 while (valsize >= bufsize);
3211
570d7624 3212 val = make_string (buf, valsize);
69ac1891
GM
3213 if (buf[0] == '/' && index (buf, ':'))
3214 val = concat2 (build_string ("/:"), val);
9ac0d9e0 3215 xfree (buf);
cd913586
KH
3216 val = DECODE_FILE (val);
3217 return val;
570d7624
JB
3218#else /* not S_IFLNK */
3219 return Qnil;
3220#endif /* not S_IFLNK */
3221}
3222
570d7624 3223DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0,
8c1a1077
PJ
3224 doc: /* Return t if FILENAME names an existing directory.
3225Symbolic links to directories count as directories.
3226See `file-symlink-p' to distinguish symlinks. */)
3227 (filename)
570d7624
JB
3228 Lisp_Object filename;
3229{
199607e4 3230 register Lisp_Object absname;
570d7624 3231 struct stat st;
32f4334d 3232 Lisp_Object handler;
570d7624 3233
199607e4 3234 absname = expand_and_dir_to_file (filename, current_buffer->directory);
570d7624 3235
32f4334d
RS
3236 /* If the file name has special constructs in it,
3237 call the corresponding file handler. */
199607e4 3238 handler = Ffind_file_name_handler (absname, Qfile_directory_p);
32f4334d 3239 if (!NILP (handler))
199607e4 3240 return call2 (handler, Qfile_directory_p, absname);
32f4334d 3241
b1d1b865
RS
3242 absname = ENCODE_FILE (absname);
3243
d5db4077 3244 if (stat (SDATA (absname), &st) < 0)
570d7624
JB
3245 return Qnil;
3246 return (st.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil;
3247}
3248
b72dea2a 3249DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p, Sfile_accessible_directory_p, 1, 1, 0,
e385ec41
RS
3250 doc: /* Return t if file FILENAME names a directory you can open.
3251For the value to be t, FILENAME must specify the name of a directory as a file,
3252and the directory must allow you to open files in it. In order to use a
8c1a1077
PJ
3253directory as a buffer's current directory, this predicate must return true.
3254A directory name spec may be given instead; then the value is t
3255if the directory so specified exists and really is a readable and
3256searchable directory. */)
3257 (filename)
b72dea2a
JB
3258 Lisp_Object filename;
3259{
32f4334d 3260 Lisp_Object handler;
1a04498e 3261 int tem;
d26859eb 3262 struct gcpro gcpro1;
32f4334d
RS
3263
3264 /* If the file name has special constructs in it,
3265 call the corresponding file handler. */
49307295 3266 handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p);
32f4334d
RS
3267 if (!NILP (handler))
3268 return call2 (handler, Qfile_accessible_directory_p, filename);
3269
d26859eb
KH
3270 /* It's an unlikely combination, but yes we really do need to gcpro:
3271 Suppose that file-accessible-directory-p has no handler, but
3272 file-directory-p does have a handler; this handler causes a GC which
3273 relocates the string in `filename'; and finally file-directory-p
3274 returns non-nil. Then we would end up passing a garbaged string
3275 to file-executable-p. */
3276 GCPRO1 (filename);
1a04498e
KH
3277 tem = (NILP (Ffile_directory_p (filename))
3278 || NILP (Ffile_executable_p (filename)));
d26859eb 3279 UNGCPRO;
1a04498e 3280 return tem ? Qnil : Qt;
b72dea2a
JB
3281}
3282
f793dc6c 3283DEFUN ("file-regular-p", Ffile_regular_p, Sfile_regular_p, 1, 1, 0,
8c1a1077
PJ
3284 doc: /* Return t if file FILENAME is the name of a regular file.
3285This is the sort of file that holds an ordinary stream of data bytes. */)
3286 (filename)
f793dc6c
RS
3287 Lisp_Object filename;
3288{
199607e4 3289 register Lisp_Object absname;
f793dc6c
RS
3290 struct stat st;
3291 Lisp_Object handler;
3292
199607e4 3293 absname = expand_and_dir_to_file (filename, current_buffer->directory);
f793dc6c
RS
3294
3295 /* If the file name has special constructs in it,
3296 call the corresponding file handler. */
199607e4 3297 handler = Ffind_file_name_handler (absname, Qfile_regular_p);
f793dc6c 3298 if (!NILP (handler))
199607e4 3299 return call2 (handler, Qfile_regular_p, absname);
f793dc6c 3300
b1d1b865
RS
3301 absname = ENCODE_FILE (absname);
3302
c1c4693e
RS
3303#ifdef WINDOWSNT
3304 {
3305 int result;
3306 Lisp_Object tem = Vw32_get_true_file_attributes;
3307
3308 /* Tell stat to use expensive method to get accurate info. */
3309 Vw32_get_true_file_attributes = Qt;
d5db4077 3310 result = stat (SDATA (absname), &st);
c1c4693e
RS
3311 Vw32_get_true_file_attributes = tem;
3312
3313 if (result < 0)
3314 return Qnil;
3315 return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
3316 }
3317#else
d5db4077 3318 if (stat (SDATA (absname), &st) < 0)
f793dc6c
RS
3319 return Qnil;
3320 return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
c1c4693e 3321#endif
f793dc6c
RS
3322}
3323\f
570d7624 3324DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
8c1a1077
PJ
3325 doc: /* Return mode bits of file named FILENAME, as an integer. */)
3326 (filename)
570d7624
JB
3327 Lisp_Object filename;
3328{
199607e4 3329 Lisp_Object absname;
570d7624 3330 struct stat st;
32f4334d 3331 Lisp_Object handler;
570d7624 3332
199607e4 3333 absname = expand_and_dir_to_file (filename, current_buffer->directory);
570d7624 3334
32f4334d
RS
3335 /* If the file name has special constructs in it,
3336 call the corresponding file handler. */
199607e4 3337 handler = Ffind_file_name_handler (absname, Qfile_modes);
32f4334d 3338 if (!NILP (handler))
199607e4 3339 return call2 (handler, Qfile_modes, absname);
32f4334d 3340
b1d1b865
RS
3341 absname = ENCODE_FILE (absname);
3342
d5db4077 3343 if (stat (SDATA (absname), &st) < 0)
570d7624 3344 return Qnil;
34ead71a 3345#if defined (MSDOS) && __DJGPP__ < 2
d5db4077 3346 if (check_executable (SDATA (absname)))
3be3c08e 3347 st.st_mode |= S_IEXEC;
34ead71a 3348#endif /* MSDOS && __DJGPP__ < 2 */
3ace87e3 3349
570d7624
JB
3350 return make_number (st.st_mode & 07777);
3351}
3352
3353DEFUN ("set-file-modes", Fset_file_modes, Sset_file_modes, 2, 2, 0,
8c1a1077
PJ
3354 doc: /* Set mode bits of file named FILENAME to MODE (an integer).
3355Only the 12 low bits of MODE are used. */)
570d7624
JB
3356 (filename, mode)
3357 Lisp_Object filename, mode;
3358{
b1d1b865 3359 Lisp_Object absname, encoded_absname;
32f4334d 3360 Lisp_Object handler;
570d7624 3361
199607e4 3362 absname = Fexpand_file_name (filename, current_buffer->directory);
b7826503 3363 CHECK_NUMBER (mode);
570d7624 3364
32f4334d
RS
3365 /* If the file name has special constructs in it,
3366 call the corresponding file handler. */
199607e4 3367 handler = Ffind_file_name_handler (absname, Qset_file_modes);
32f4334d 3368 if (!NILP (handler))
199607e4 3369 return call3 (handler, Qset_file_modes, absname, mode);
32f4334d 3370
b1d1b865
RS
3371 encoded_absname = ENCODE_FILE (absname);
3372
d5db4077 3373 if (chmod (SDATA (encoded_absname), XINT (mode)) < 0)
199607e4 3374 report_file_error ("Doing chmod", Fcons (absname, Qnil));
570d7624
JB
3375
3376 return Qnil;
3377}
3378
c24e9a53 3379DEFUN ("set-default-file-modes", Fset_default_file_modes, Sset_default_file_modes, 1, 1, 0,
8c1a1077
PJ
3380 doc: /* Set the file permission bits for newly created files.
3381The argument MODE should be an integer; only the low 9 bits are used.
3382This setting is inherited by subprocesses. */)
3383 (mode)
5f85ea58 3384 Lisp_Object mode;
36a8c287 3385{
b7826503 3386 CHECK_NUMBER (mode);
199607e4 3387
5f85ea58 3388 umask ((~ XINT (mode)) & 0777);
36a8c287
JB
3389
3390 return Qnil;
3391}
3392
c24e9a53 3393DEFUN ("default-file-modes", Fdefault_file_modes, Sdefault_file_modes, 0, 0, 0,
8c1a1077
PJ
3394 doc: /* Return the default file protection for created files.
3395The value is an integer. */)
3396 ()
36a8c287 3397{
5f85ea58
RS
3398 int realmask;
3399 Lisp_Object value;
36a8c287 3400
5f85ea58
RS
3401 realmask = umask (0);
3402 umask (realmask);
36a8c287 3403
46283abe 3404 XSETINT (value, (~ realmask) & 0777);
5f85ea58 3405 return value;
36a8c287 3406}
5df5e07c 3407
f793dc6c 3408\f
5df5e07c
GM
3409#ifdef __NetBSD__
3410#define unix 42
3411#endif
85ffea93 3412
5df5e07c 3413#ifdef unix
85ffea93 3414DEFUN ("unix-sync", Funix_sync, Sunix_sync, 0, 0, "",
8c1a1077
PJ
3415 doc: /* Tell Unix to finish all pending disk updates. */)
3416 ()
85ffea93
RS
3417{
3418 sync ();
3419 return Qnil;
3420}
3421
3422#endif /* unix */
3423
570d7624 3424DEFUN ("file-newer-than-file-p", Ffile_newer_than_file_p, Sfile_newer_than_file_p, 2, 2, 0,
8c1a1077
PJ
3425 doc: /* Return t if file FILE1 is newer than file FILE2.
3426If FILE1 does not exist, the answer is nil;
3427otherwise, if FILE2 does not exist, the answer is t. */)
3428 (file1, file2)
570d7624
JB
3429 Lisp_Object file1, file2;
3430{
199607e4 3431 Lisp_Object absname1, absname2;
570d7624
JB
3432 struct stat st;
3433 int mtime1;
32f4334d 3434 Lisp_Object handler;
09121adc 3435 struct gcpro gcpro1, gcpro2;
570d7624 3436
b7826503
PJ
3437 CHECK_STRING (file1);
3438 CHECK_STRING (file2);
570d7624 3439
199607e4
RS
3440 absname1 = Qnil;
3441 GCPRO2 (absname1, file2);
3442 absname1 = expand_and_dir_to_file (file1, current_buffer->directory);
3443 absname2 = expand_and_dir_to_file (file2, current_buffer->directory);
09121adc 3444 UNGCPRO;
570d7624 3445
32f4334d
RS
3446 /* If the file name has special constructs in it,
3447 call the corresponding file handler. */
199607e4 3448 handler = Ffind_file_name_handler (absname1, Qfile_newer_than_file_p);
51cf6d37 3449 if (NILP (handler))
199607e4 3450 handler = Ffind_file_name_handler (absname2, Qfile_newer_than_file_p);
32f4334d 3451 if (!NILP (handler))
199607e4 3452 return call3 (handler, Qfile_newer_than_file_p, absname1, absname2);
32f4334d 3453
b1d1b865
RS
3454 GCPRO2 (absname1, absname2);
3455 absname1 = ENCODE_FILE (absname1);
3456 absname2 = ENCODE_FILE (absname2);
3457 UNGCPRO;
3458
d5db4077 3459 if (stat (SDATA (absname1), &st) < 0)
570d7624
JB
3460 return Qnil;
3461
3462 mtime1 = st.st_mtime;
3463
d5db4077 3464 if (stat (SDATA (absname2), &st) < 0)
570d7624
JB
3465 return Qt;
3466
3467 return (mtime1 > st.st_mtime) ? Qt : Qnil;
3468}
3469\f
5e570b75 3470#ifdef DOS_NT
4c3c22f3 3471Lisp_Object Qfind_buffer_file_type;
5e570b75 3472#endif /* DOS_NT */
4c3c22f3 3473
6fdaa9a0
KH
3474#ifndef READ_BUF_SIZE
3475#define READ_BUF_SIZE (64 << 10)
3476#endif
3477
98a7d268
KH
3478extern void adjust_markers_for_delete P_ ((int, int, int, int));
3479
3480/* This function is called after Lisp functions to decide a coding
3481 system are called, or when they cause an error. Before they are
3482 called, the current buffer is set unibyte and it contains only a
3483 newly inserted text (thus the buffer was empty before the
3484 insertion).
3485
3486 The functions may set markers, overlays, text properties, or even
3487 alter the buffer contents, change the current buffer.
3488
3489 Here, we reset all those changes by:
3490 o set back the current buffer.
3491 o move all markers and overlays to BEG.
3492 o remove all text properties.
3493 o set back the buffer multibyteness. */
f736ffbf
KH
3494
3495static Lisp_Object
98a7d268
KH
3496decide_coding_unwind (unwind_data)
3497 Lisp_Object unwind_data;
f736ffbf 3498{
98a7d268 3499 Lisp_Object multibyte, undo_list, buffer;
f736ffbf 3500
98a7d268
KH
3501 multibyte = XCAR (unwind_data);
3502 unwind_data = XCDR (unwind_data);
3503 undo_list = XCAR (unwind_data);
3504 buffer = XCDR (unwind_data);
3505
3506 if (current_buffer != XBUFFER (buffer))
3507 set_buffer_internal (XBUFFER (buffer));
3508 adjust_markers_for_delete (BEG, BEG_BYTE, Z, Z_BYTE);
3509 adjust_overlays_for_delete (BEG, Z - BEG);
3510 BUF_INTERVALS (current_buffer) = 0;
3511 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
3512
3513 /* Now we are safe to change the buffer's multibyteness directly. */
3514 current_buffer->enable_multibyte_characters = multibyte;
3515 current_buffer->undo_list = undo_list;
f736ffbf
KH
3516
3517 return Qnil;
3518}
3519
55587f8a 3520
1b978129 3521/* Used to pass values from insert-file-contents to read_non_regular. */
55587f8a 3522
1b978129
GM
3523static int non_regular_fd;
3524static int non_regular_inserted;
3525static int non_regular_nbytes;
55587f8a 3526
55587f8a 3527
1b978129
GM
3528/* Read from a non-regular file.
3529 Read non_regular_trytry bytes max from non_regular_fd.
3530 Non_regular_inserted specifies where to put the read bytes.
3531 Value is the number of bytes read. */
55587f8a
GM
3532
3533static Lisp_Object
1b978129 3534read_non_regular ()
55587f8a 3535{
1b978129
GM
3536 int nbytes;
3537
3538 immediate_quit = 1;
3539 QUIT;
3540 nbytes = emacs_read (non_regular_fd,
28c3eb5a 3541 BEG_ADDR + PT_BYTE - BEG_BYTE + non_regular_inserted,
1b978129 3542 non_regular_nbytes);
1b978129
GM
3543 immediate_quit = 0;
3544 return make_number (nbytes);
3545}
55587f8a 3546
d0e2444e 3547
1b978129
GM
3548/* Condition-case handler used when reading from non-regular files
3549 in insert-file-contents. */
3550
3551static Lisp_Object
3552read_non_regular_quit ()
3553{
55587f8a
GM
3554 return Qnil;
3555}
3556
3557
570d7624 3558DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
8c1a1077
PJ
3559 1, 5, 0,
3560 doc: /* Insert contents of file FILENAME after point.
3561Returns list of absolute file name and number of bytes inserted.
3562If second argument VISIT is non-nil, the buffer's visited filename
3563and last save file modtime are set, and it is marked unmodified.
3564If visiting and the file does not exist, visiting is completed
3565before the error is signaled.
3566The optional third and fourth arguments BEG and END
3567specify what portion of the file to insert.
3568These arguments count bytes in the file, not characters in the buffer.
3569If VISIT is non-nil, BEG and END must be nil.
3570
3571If optional fifth argument REPLACE is non-nil,
3572it means replace the current buffer contents (in the accessible portion)
3573with the file contents. This is better than simply deleting and inserting
3574the whole thing because (1) it preserves some marker positions
3575and (2) it puts less data in the undo list.
3576When REPLACE is non-nil, the value is the number of characters actually read,
3577which is often less than the number of characters to be read.
3578
3579This does code conversion according to the value of
3580`coding-system-for-read' or `file-coding-system-alist',
3581and sets the variable `last-coding-system-used' to the coding system
3582actually used. */)
3583 (filename, visit, beg, end, replace)
3d0387c0 3584 Lisp_Object filename, visit, beg, end, replace;
570d7624
JB
3585{
3586 struct stat st;
3587 register int fd;
ec7adf26 3588 int inserted = 0;
570d7624 3589 register int how_much;
6fdaa9a0 3590 register int unprocessed;
331379bf 3591 int count = SPECPDL_INDEX ();
b1d1b865
RS
3592 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3593 Lisp_Object handler, val, insval, orig_filename;
d6a3cc15 3594 Lisp_Object p;
6bbd7a29 3595 int total = 0;
53c34c46 3596 int not_regular = 0;
feb9dc27 3597 unsigned char read_buf[READ_BUF_SIZE];
6fdaa9a0 3598 struct coding_system coding;
3dbcf3f6 3599 unsigned char buffer[1 << 14];
727a0b4a 3600 int replace_handled = 0;
ec7adf26 3601 int set_coding_system = 0;
f736ffbf 3602 int coding_system_decided = 0;
1b978129 3603 int read_quit = 0;
32f4334d 3604
95385625
RS
3605 if (current_buffer->base_buffer && ! NILP (visit))
3606 error ("Cannot do file visiting in an indirect buffer");
3607
3608 if (!NILP (current_buffer->read_only))
3609 Fbarf_if_buffer_read_only ();
3610
32f4334d 3611 val = Qnil;
d6a3cc15 3612 p = Qnil;
b1d1b865 3613 orig_filename = Qnil;
32f4334d 3614
b1d1b865 3615 GCPRO4 (filename, val, p, orig_filename);
570d7624 3616
b7826503 3617 CHECK_STRING (filename);
570d7624
JB
3618 filename = Fexpand_file_name (filename, Qnil);
3619
32f4334d
RS
3620 /* If the file name has special constructs in it,
3621 call the corresponding file handler. */
49307295 3622 handler = Ffind_file_name_handler (filename, Qinsert_file_contents);
32f4334d
RS
3623 if (!NILP (handler))
3624 {
3d0387c0
RS
3625 val = call6 (handler, Qinsert_file_contents, filename,
3626 visit, beg, end, replace);
03699b14
KR
3627 if (CONSP (val) && CONSP (XCDR (val)))
3628 inserted = XINT (XCAR (XCDR (val)));
32f4334d
RS
3629 goto handled;
3630 }
3631
b1d1b865
RS
3632 orig_filename = filename;
3633 filename = ENCODE_FILE (filename);
3634
570d7624
JB
3635 fd = -1;
3636
c1c4693e
RS
3637#ifdef WINDOWSNT
3638 {
3639 Lisp_Object tem = Vw32_get_true_file_attributes;
3640
3641 /* Tell stat to use expensive method to get accurate info. */
3642 Vw32_get_true_file_attributes = Qt;
d5db4077 3643 total = stat (SDATA (filename), &st);
c1c4693e
RS
3644 Vw32_get_true_file_attributes = tem;
3645 }
3646 if (total < 0)
3647#else
570d7624 3648#ifndef APOLLO
d5db4077 3649 if (stat (SDATA (filename), &st) < 0)
570d7624 3650#else
d5db4077 3651 if ((fd = emacs_open (SDATA (filename), O_RDONLY, 0)) < 0
570d7624
JB
3652 || fstat (fd, &st) < 0)
3653#endif /* not APOLLO */
c1c4693e 3654#endif /* WINDOWSNT */
570d7624 3655 {
68c45bf0 3656 if (fd >= 0) emacs_close (fd);
99bc28f4 3657 badopen:
265a9e55 3658 if (NILP (visit))
b1d1b865 3659 report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
570d7624
JB
3660 st.st_mtime = -1;
3661 how_much = 0;
0de6b8f4 3662 if (!NILP (Vcoding_system_for_read))
22d92d6b 3663 Fset (Qbuffer_file_coding_system, Vcoding_system_for_read);
570d7624
JB
3664 goto notfound;
3665 }
3666
99bc28f4 3667#ifdef S_IFREG
be53b411
JB
3668 /* This code will need to be changed in order to work on named
3669 pipes, and it's probably just not worth it. So we should at
3670 least signal an error. */
99bc28f4 3671 if (!S_ISREG (st.st_mode))
330bfe57 3672 {
d4b8687b
RS
3673 not_regular = 1;
3674
3675 if (! NILP (visit))
3676 goto notfound;
3677
3678 if (! NILP (replace) || ! NILP (beg) || ! NILP (end))
330bfe57
RS
3679 Fsignal (Qfile_error,
3680 Fcons (build_string ("not a regular file"),
b1d1b865 3681 Fcons (orig_filename, Qnil)));
330bfe57 3682 }
be53b411
JB
3683#endif
3684
99bc28f4 3685 if (fd < 0)
d5db4077 3686 if ((fd = emacs_open (SDATA (filename), O_RDONLY, 0)) < 0)
99bc28f4
KH
3687 goto badopen;
3688
3689 /* Replacement should preserve point as it preserves markers. */
3690 if (!NILP (replace))
3691 record_unwind_protect (restore_point_unwind, Fpoint_marker ());
3692
3693 record_unwind_protect (close_file_unwind, make_number (fd));
3694
570d7624 3695 /* Supposedly happens on VMS. */
d4b8687b 3696 if (! not_regular && st.st_size < 0)
570d7624 3697 error ("File size is negative");
be53b411 3698
9c856db9
GM
3699 /* Prevent redisplay optimizations. */
3700 current_buffer->clip_changed = 1;
3701
9f57b6b4
KH
3702 if (!NILP (visit))
3703 {
3704 if (!NILP (beg) || !NILP (end))
3705 error ("Attempt to visit less than an entire file");
3706 if (BEG < Z && NILP (replace))
3707 error ("Cannot do file visiting in a non-empty buffer");
3708 }
7fded690
JB
3709
3710 if (!NILP (beg))
b7826503 3711 CHECK_NUMBER (beg);
7fded690 3712 else
2acfd7ae 3713 XSETFASTINT (beg, 0);
7fded690
JB
3714
3715 if (!NILP (end))
b7826503 3716 CHECK_NUMBER (end);
7fded690
JB
3717 else
3718 {
d4b8687b
RS
3719 if (! not_regular)
3720 {
3721 XSETINT (end, st.st_size);
68c45bf0
PE
3722
3723 /* Arithmetic overflow can occur if an Emacs integer cannot
3724 represent the file size, or if the calculations below
3725 overflow. The calculations below double the file size
3726 twice, so check that it can be multiplied by 4 safely. */
3727 if (XINT (end) != st.st_size
3728 || ((int) st.st_size * 4) / 4 != st.st_size)
d4b8687b 3729 error ("Maximum buffer size exceeded");
d21dd12d
GM
3730
3731 /* The file size returned from stat may be zero, but data
3732 may be readable nonetheless, for example when this is a
3733 file in the /proc filesystem. */
3734 if (st.st_size == 0)
3735 XSETINT (end, READ_BUF_SIZE);
d4b8687b 3736 }
7fded690
JB
3737 }
3738
f736ffbf
KH
3739 if (BEG < Z)
3740 {
3741 /* Decide the coding system to use for reading the file now
3742 because we can't use an optimized method for handling
3743 `coding:' tag if the current buffer is not empty. */
3744 Lisp_Object val;
3745 val = Qnil;
feb9dc27 3746
f736ffbf
KH
3747 if (!NILP (Vcoding_system_for_read))
3748 val = Vcoding_system_for_read;
3749 else if (! NILP (replace))
3750 /* In REPLACE mode, we can use the same coding system
3751 that was used to visit the file. */
3752 val = current_buffer->buffer_file_coding_system;
3753 else
3754 {
3755 /* Don't try looking inside a file for a coding system
3756 specification if it is not seekable. */
3757 if (! not_regular && ! NILP (Vset_auto_coding_function))
3758 {
3759 /* Find a coding system specified in the heading two
3760 lines or in the tailing several lines of the file.
3761 We assume that the 1K-byte and 3K-byte for heading
003a7eaa 3762 and tailing respectively are sufficient for this
f736ffbf 3763 purpose. */
07590973 3764 int nread;
f736ffbf
KH
3765
3766 if (st.st_size <= (1024 * 4))
68c45bf0 3767 nread = emacs_read (fd, read_buf, 1024 * 4);
f736ffbf
KH
3768 else
3769 {
68c45bf0 3770 nread = emacs_read (fd, read_buf, 1024);
f736ffbf
KH
3771 if (nread >= 0)
3772 {
3773 if (lseek (fd, st.st_size - (1024 * 3), 0) < 0)
3774 report_file_error ("Setting file position",
3775 Fcons (orig_filename, Qnil));
68c45bf0 3776 nread += emacs_read (fd, read_buf + nread, 1024 * 3);
f736ffbf
KH
3777 }
3778 }
feb9dc27 3779
f736ffbf
KH
3780 if (nread < 0)
3781 error ("IO error reading %s: %s",
d5db4077 3782 SDATA (orig_filename), emacs_strerror (errno));
f736ffbf
KH
3783 else if (nread > 0)
3784 {
f736ffbf 3785 struct buffer *prev = current_buffer;
685fc579
RS
3786 Lisp_Object buffer;
3787 struct buffer *buf;
f736ffbf
KH
3788
3789 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
1d92afcd 3790
685fc579
RS
3791 buffer = Fget_buffer_create (build_string (" *code-converting-work*"));
3792 buf = XBUFFER (buffer);
3793
3794 buf->directory = current_buffer->directory;
3795 buf->read_only = Qnil;
3796 buf->filename = Qnil;
3797 buf->undo_list = Qt;
3798 buf->overlays_before = Qnil;
3799 buf->overlays_after = Qnil;
1d92afcd 3800
685fc579
RS
3801 set_buffer_internal (buf);
3802 Ferase_buffer ();
3803 buf->enable_multibyte_characters = Qnil;
3804
f736ffbf
KH
3805 insert_1_both (read_buf, nread, nread, 0, 0, 0);
3806 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
1255deb9
KH
3807 val = call2 (Vset_auto_coding_function,
3808 filename, make_number (nread));
f736ffbf 3809 set_buffer_internal (prev);
1d92afcd 3810
f736ffbf
KH
3811 /* Discard the unwind protect for recovering the
3812 current buffer. */
3813 specpdl_ptr--;
3814
3815 /* Rewind the file for the actual read done later. */
3816 if (lseek (fd, 0, 0) < 0)
3817 report_file_error ("Setting file position",
3818 Fcons (orig_filename, Qnil));
3819 }
3820 }
feb9dc27 3821
f736ffbf
KH
3822 if (NILP (val))
3823 {
3824 /* If we have not yet decided a coding system, check
3825 file-coding-system-alist. */
3826 Lisp_Object args[6], coding_systems;
3827
3828 args[0] = Qinsert_file_contents, args[1] = orig_filename;
3829 args[2] = visit, args[3] = beg, args[4] = end, args[5] = replace;
3830 coding_systems = Ffind_operation_coding_system (6, args);
3831 if (CONSP (coding_systems))
03699b14 3832 val = XCAR (coding_systems);
f736ffbf
KH
3833 }
3834 }
c9e82392 3835
f736ffbf 3836 setup_coding_system (Fcheck_coding_system (val), &coding);
f8569325
DL
3837 /* Ensure we set Vlast_coding_system_used. */
3838 set_coding_system = 1;
c8a6d68a 3839
237a6fd2
RS
3840 if (NILP (current_buffer->enable_multibyte_characters)
3841 && ! NILP (val))
3842 /* We must suppress all character code conversion except for
3843 end-of-line conversion. */
57515cfe 3844 setup_raw_text_coding_system (&coding);
54369368 3845
8c3b9441
KH
3846 coding.src_multibyte = 0;
3847 coding.dst_multibyte
3848 = !NILP (current_buffer->enable_multibyte_characters);
f736ffbf
KH
3849 coding_system_decided = 1;
3850 }
6cf71bf1 3851
3d0387c0
RS
3852 /* If requested, replace the accessible part of the buffer
3853 with the file contents. Avoid replacing text at the
3854 beginning or end of the buffer that matches the file contents;
3dbcf3f6
RS
3855 that preserves markers pointing to the unchanged parts.
3856
3857 Here we implement this feature in an optimized way
3858 for the case where code conversion is NOT needed.
3859 The following if-statement handles the case of conversion
727a0b4a
RS
3860 in a less optimal way.
3861
3862 If the code conversion is "automatic" then we try using this
3863 method and hope for the best.
3864 But if we discover the need for conversion, we give up on this method
3865 and let the following if-statement handle the replace job. */
3dbcf3f6 3866 if (!NILP (replace)
f736ffbf 3867 && BEGV < ZV
8c3b9441 3868 && !(coding.common_flags & CODING_REQUIRE_DECODING_MASK))
3d0387c0 3869 {
ec7adf26
RS
3870 /* same_at_start and same_at_end count bytes,
3871 because file access counts bytes
3872 and BEG and END count bytes. */
3873 int same_at_start = BEGV_BYTE;
3874 int same_at_end = ZV_BYTE;
9c28748f 3875 int overlap;
6fdaa9a0
KH
3876 /* There is still a possibility we will find the need to do code
3877 conversion. If that happens, we set this variable to 1 to
727a0b4a 3878 give up on handling REPLACE in the optimized way. */
6fdaa9a0 3879 int giveup_match_end = 0;
9c28748f 3880
4d2a0879
RS
3881 if (XINT (beg) != 0)
3882 {
3883 if (lseek (fd, XINT (beg), 0) < 0)
3884 report_file_error ("Setting file position",
b1d1b865 3885 Fcons (orig_filename, Qnil));
4d2a0879
RS
3886 }
3887
3d0387c0
RS
3888 immediate_quit = 1;
3889 QUIT;
3890 /* Count how many chars at the start of the file
3891 match the text at the beginning of the buffer. */
3892 while (1)
3893 {
3894 int nread, bufpos;
3895
68c45bf0 3896 nread = emacs_read (fd, buffer, sizeof buffer);
3d0387c0
RS
3897 if (nread < 0)
3898 error ("IO error reading %s: %s",
d5db4077 3899 SDATA (orig_filename), emacs_strerror (errno));
3d0387c0
RS
3900 else if (nread == 0)
3901 break;
6fdaa9a0 3902
0ef69138 3903 if (coding.type == coding_type_undecided)
727a0b4a 3904 detect_coding (&coding, buffer, nread);
8c3b9441 3905 if (coding.common_flags & CODING_REQUIRE_DECODING_MASK)
727a0b4a
RS
3906 /* We found that the file should be decoded somehow.
3907 Let's give up here. */
3908 {
3909 giveup_match_end = 1;
3910 break;
3911 }
3912
0ef69138 3913 if (coding.eol_type == CODING_EOL_UNDECIDED)
727a0b4a 3914 detect_eol (&coding, buffer, nread);
1b335d29 3915 if (coding.eol_type != CODING_EOL_UNDECIDED
70ec4328 3916 && coding.eol_type != CODING_EOL_LF)
727a0b4a
RS
3917 /* We found that the format of eol should be decoded.
3918 Let's give up here. */
3919 {
3920 giveup_match_end = 1;
3921 break;
3922 }
3923
3d0387c0 3924 bufpos = 0;
ec7adf26 3925 while (bufpos < nread && same_at_start < ZV_BYTE
6fdaa9a0 3926 && FETCH_BYTE (same_at_start) == buffer[bufpos])
3d0387c0
RS
3927 same_at_start++, bufpos++;
3928 /* If we found a discrepancy, stop the scan.
8e6208c5 3929 Otherwise loop around and scan the next bufferful. */
3d0387c0
RS
3930 if (bufpos != nread)
3931 break;
3932 }
3933 immediate_quit = 0;
3934 /* If the file matches the buffer completely,
3935 there's no need to replace anything. */
ec7adf26 3936 if (same_at_start - BEGV_BYTE == XINT (end))
3d0387c0 3937 {
68c45bf0 3938 emacs_close (fd);
a1d2b64a 3939 specpdl_ptr--;
1051b3b3 3940 /* Truncate the buffer to the size of the file. */
7dae4502 3941 del_range_1 (same_at_start, same_at_end, 0, 0);
3d0387c0
RS
3942 goto handled;
3943 }
3944 immediate_quit = 1;
3945 QUIT;
3946 /* Count how many chars at the end of the file
6fdaa9a0
KH
3947 match the text at the end of the buffer. But, if we have
3948 already found that decoding is necessary, don't waste time. */
3949 while (!giveup_match_end)
3d0387c0
RS
3950 {
3951 int total_read, nread, bufpos, curpos, trial;
3952
3953 /* At what file position are we now scanning? */
ec7adf26 3954 curpos = XINT (end) - (ZV_BYTE - same_at_end);
fc81fa9e
KH
3955 /* If the entire file matches the buffer tail, stop the scan. */
3956 if (curpos == 0)
3957 break;
3d0387c0
RS
3958 /* How much can we scan in the next step? */
3959 trial = min (curpos, sizeof buffer);
3960 if (lseek (fd, curpos - trial, 0) < 0)
3961 report_file_error ("Setting file position",
b1d1b865 3962 Fcons (orig_filename, Qnil));
3d0387c0 3963
b02439c8 3964 total_read = nread = 0;
3d0387c0
RS
3965 while (total_read < trial)
3966 {
68c45bf0 3967 nread = emacs_read (fd, buffer + total_read, trial - total_read);
2bd2273e 3968 if (nread < 0)
3d0387c0 3969 error ("IO error reading %s: %s",
d5db4077 3970 SDATA (orig_filename), emacs_strerror (errno));
2bd2273e
GM
3971 else if (nread == 0)
3972 break;
3d0387c0
RS
3973 total_read += nread;
3974 }
2bd2273e 3975
8e6208c5 3976 /* Scan this bufferful from the end, comparing with
3d0387c0
RS
3977 the Emacs buffer. */
3978 bufpos = total_read;
2bd2273e 3979
3d0387c0
RS
3980 /* Compare with same_at_start to avoid counting some buffer text
3981 as matching both at the file's beginning and at the end. */
3982 while (bufpos > 0 && same_at_end > same_at_start
6fdaa9a0 3983 && FETCH_BYTE (same_at_end - 1) == buffer[bufpos - 1])
3d0387c0 3984 same_at_end--, bufpos--;
727a0b4a 3985
3d0387c0 3986 /* If we found a discrepancy, stop the scan.
8e6208c5 3987 Otherwise loop around and scan the preceding bufferful. */
3d0387c0 3988 if (bufpos != 0)
727a0b4a
RS
3989 {
3990 /* If this discrepancy is because of code conversion,
3991 we cannot use this method; giveup and try the other. */
3992 if (same_at_end > same_at_start
3993 && FETCH_BYTE (same_at_end - 1) >= 0200
71312b68 3994 && ! NILP (current_buffer->enable_multibyte_characters)
c8a6d68a 3995 && (CODING_MAY_REQUIRE_DECODING (&coding)))
727a0b4a
RS
3996 giveup_match_end = 1;
3997 break;
3998 }
b02439c8
GM
3999
4000 if (nread == 0)
4001 break;
3d0387c0
RS
4002 }
4003 immediate_quit = 0;
9c28748f 4004
727a0b4a
RS
4005 if (! giveup_match_end)
4006 {
ec7adf26
RS
4007 int temp;
4008
727a0b4a 4009 /* We win! We can handle REPLACE the optimized way. */
9c28748f 4010
20f6783d
RS
4011 /* Extend the start of non-matching text area to multibyte
4012 character boundary. */
4013 if (! NILP (current_buffer->enable_multibyte_characters))
4014 while (same_at_start > BEGV_BYTE
4015 && ! CHAR_HEAD_P (FETCH_BYTE (same_at_start)))
4016 same_at_start--;
4017
4018 /* Extend the end of non-matching text area to multibyte
71312b68
RS
4019 character boundary. */
4020 if (! NILP (current_buffer->enable_multibyte_characters))
ec7adf26
RS
4021 while (same_at_end < ZV_BYTE
4022 && ! CHAR_HEAD_P (FETCH_BYTE (same_at_end)))
71312b68
RS
4023 same_at_end++;
4024
727a0b4a 4025 /* Don't try to reuse the same piece of text twice. */
ec7adf26
RS
4026 overlap = (same_at_start - BEGV_BYTE
4027 - (same_at_end + st.st_size - ZV));
727a0b4a
RS
4028 if (overlap > 0)
4029 same_at_end += overlap;
9c28748f 4030
727a0b4a 4031 /* Arrange to read only the nonmatching middle part of the file. */
ec7adf26
RS
4032 XSETFASTINT (beg, XINT (beg) + (same_at_start - BEGV_BYTE));
4033 XSETFASTINT (end, XINT (end) - (ZV_BYTE - same_at_end));
3dbcf3f6 4034
ec7adf26 4035 del_range_byte (same_at_start, same_at_end, 0);
727a0b4a 4036 /* Insert from the file at the proper position. */
ec7adf26
RS
4037 temp = BYTE_TO_CHAR (same_at_start);
4038 SET_PT_BOTH (temp, same_at_start);
727a0b4a
RS
4039
4040 /* If display currently starts at beginning of line,
4041 keep it that way. */
4042 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
4043 XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
4044
4045 replace_handled = 1;
4046 }
3dbcf3f6
RS
4047 }
4048
4049 /* If requested, replace the accessible part of the buffer
4050 with the file contents. Avoid replacing text at the
4051 beginning or end of the buffer that matches the file contents;
4052 that preserves markers pointing to the unchanged parts.
4053
4054 Here we implement this feature for the case where code conversion
4055 is needed, in a simple way that needs a lot of memory.
4056 The preceding if-statement handles the case of no conversion
4057 in a more optimized way. */
f736ffbf 4058 if (!NILP (replace) && ! replace_handled && BEGV < ZV)
3dbcf3f6 4059 {
ec7adf26
RS
4060 int same_at_start = BEGV_BYTE;
4061 int same_at_end = ZV_BYTE;
3dbcf3f6
RS
4062 int overlap;
4063 int bufpos;
4064 /* Make sure that the gap is large enough. */
4065 int bufsize = 2 * st.st_size;
b00ca0d7 4066 unsigned char *conversion_buffer = (unsigned char *) xmalloc (bufsize);
ec7adf26 4067 int temp;
3dbcf3f6
RS
4068
4069 /* First read the whole file, performing code conversion into
4070 CONVERSION_BUFFER. */
4071
727a0b4a
RS
4072 if (lseek (fd, XINT (beg), 0) < 0)
4073 {
68cfd853 4074 xfree (conversion_buffer);
727a0b4a 4075 report_file_error ("Setting file position",
b1d1b865 4076 Fcons (orig_filename, Qnil));
727a0b4a
RS
4077 }
4078
3dbcf3f6
RS
4079 total = st.st_size; /* Total bytes in the file. */
4080 how_much = 0; /* Bytes read from file so far. */
4081 inserted = 0; /* Bytes put into CONVERSION_BUFFER so far. */
4082 unprocessed = 0; /* Bytes not processed in previous loop. */
4083
4084 while (how_much < total)
4085 {
4086 /* try is reserved in some compilers (Microsoft C) */
4087 int trytry = min (total - how_much, READ_BUF_SIZE - unprocessed);
cadf50ff 4088 unsigned char *destination = read_buf + unprocessed;
3dbcf3f6
RS
4089 int this;
4090
4091 /* Allow quitting out of the actual I/O. */
4092 immediate_quit = 1;
4093 QUIT;
68c45bf0 4094 this = emacs_read (fd, destination, trytry);
3dbcf3f6
RS
4095 immediate_quit = 0;
4096
4097 if (this < 0 || this + unprocessed == 0)
4098 {
4099 how_much = this;
4100 break;
4101 }
4102
4103 how_much += this;
4104
c8a6d68a 4105 if (CODING_MAY_REQUIRE_DECODING (&coding))
3dbcf3f6 4106 {
c8a6d68a 4107 int require, result;
3dbcf3f6
RS
4108
4109 this += unprocessed;
4110
4111 /* If we are using more space than estimated,
4112 make CONVERSION_BUFFER bigger. */
4113 require = decoding_buffer_size (&coding, this);
4114 if (inserted + require + 2 * (total - how_much) > bufsize)
4115 {
4116 bufsize = inserted + require + 2 * (total - how_much);
92cf1086 4117 conversion_buffer = (unsigned char *) xrealloc (conversion_buffer, bufsize);
3dbcf3f6
RS
4118 }
4119
4120 /* Convert this batch with results in CONVERSION_BUFFER. */
4121 if (how_much >= total) /* This is the last block. */
c8a6d68a 4122 coding.mode |= CODING_MODE_LAST_BLOCK;
1ddb09f5
GM
4123 if (coding.composing != COMPOSITION_DISABLED)
4124 coding_allocate_composition_data (&coding, BEGV);
c8a6d68a
KH
4125 result = decode_coding (&coding, read_buf,
4126 conversion_buffer + inserted,
4127 this, bufsize - inserted);
3dbcf3f6
RS
4128
4129 /* Save for next iteration whatever we didn't convert. */
c8a6d68a
KH
4130 unprocessed = this - coding.consumed;
4131 bcopy (read_buf + coding.consumed, read_buf, unprocessed);
8c3b9441
KH
4132 if (!NILP (current_buffer->enable_multibyte_characters))
4133 this = coding.produced;
4134 else
4135 this = str_as_unibyte (conversion_buffer + inserted,
4136 coding.produced);
3dbcf3f6
RS
4137 }
4138
4139 inserted += this;
4140 }
4141
c8a6d68a 4142 /* At this point, INSERTED is how many characters (i.e. bytes)
3dbcf3f6
RS
4143 are present in CONVERSION_BUFFER.
4144 HOW_MUCH should equal TOTAL,
4145 or should be <= 0 if we couldn't read the file. */
4146
4147 if (how_much < 0)
4148 {
a36837e4 4149 xfree (conversion_buffer);
3dbcf3f6
RS
4150
4151 if (how_much == -1)
4152 error ("IO error reading %s: %s",
d5db4077 4153 SDATA (orig_filename), emacs_strerror (errno));
3dbcf3f6
RS
4154 else if (how_much == -2)
4155 error ("maximum buffer size exceeded");
4156 }
4157
4158 /* Compare the beginning of the converted file
4159 with the buffer text. */
4160
4161 bufpos = 0;
4162 while (bufpos < inserted && same_at_start < same_at_end
4163 && FETCH_BYTE (same_at_start) == conversion_buffer[bufpos])
4164 same_at_start++, bufpos++;
4165
4166 /* If the file matches the buffer completely,
4167 there's no need to replace anything. */
4168
4169 if (bufpos == inserted)
4170 {
a36837e4 4171 xfree (conversion_buffer);
68c45bf0 4172 emacs_close (fd);
3dbcf3f6
RS
4173 specpdl_ptr--;
4174 /* Truncate the buffer to the size of the file. */
427f5aab
KH
4175 del_range_byte (same_at_start, same_at_end, 0);
4176 inserted = 0;
3dbcf3f6
RS
4177 goto handled;
4178 }
4179
20f6783d
RS
4180 /* Extend the start of non-matching text area to multibyte
4181 character boundary. */
4182 if (! NILP (current_buffer->enable_multibyte_characters))
4183 while (same_at_start > BEGV_BYTE
4184 && ! CHAR_HEAD_P (FETCH_BYTE (same_at_start)))
4185 same_at_start--;
4186
3dbcf3f6
RS
4187 /* Scan this bufferful from the end, comparing with
4188 the Emacs buffer. */
4189 bufpos = inserted;
4190
4191 /* Compare with same_at_start to avoid counting some buffer text
4192 as matching both at the file's beginning and at the end. */
4193 while (bufpos > 0 && same_at_end > same_at_start
4194 && FETCH_BYTE (same_at_end - 1) == conversion_buffer[bufpos - 1])
4195 same_at_end--, bufpos--;
4196
20f6783d
RS
4197 /* Extend the end of non-matching text area to multibyte
4198 character boundary. */
4199 if (! NILP (current_buffer->enable_multibyte_characters))
4200 while (same_at_end < ZV_BYTE
4201 && ! CHAR_HEAD_P (FETCH_BYTE (same_at_end)))
4202 same_at_end++;
4203
3dbcf3f6 4204 /* Don't try to reuse the same piece of text twice. */
ec7adf26 4205 overlap = same_at_start - BEGV_BYTE - (same_at_end + inserted - ZV_BYTE);
3dbcf3f6
RS
4206 if (overlap > 0)
4207 same_at_end += overlap;
4208
727a0b4a
RS
4209 /* If display currently starts at beginning of line,
4210 keep it that way. */
4211 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
4212 XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
4213
3dbcf3f6
RS
4214 /* Replace the chars that we need to replace,
4215 and update INSERTED to equal the number of bytes
4216 we are taking from the file. */
ec7adf26 4217 inserted -= (Z_BYTE - same_at_end) + (same_at_start - BEG_BYTE);
427f5aab 4218
643c73b9 4219 if (same_at_end != same_at_start)
427f5aab
KH
4220 {
4221 del_range_byte (same_at_start, same_at_end, 0);
4222 temp = GPT;
4223 same_at_start = GPT_BYTE;
4224 }
643c73b9
RS
4225 else
4226 {
643c73b9 4227 temp = BYTE_TO_CHAR (same_at_start);
643c73b9 4228 }
427f5aab
KH
4229 /* Insert from the file at the proper position. */
4230 SET_PT_BOTH (temp, same_at_start);
ec7adf26
RS
4231 insert_1 (conversion_buffer + same_at_start - BEG_BYTE, inserted,
4232 0, 0, 0);
1ddb09f5
GM
4233 if (coding.cmp_data && coding.cmp_data->used)
4234 coding_restore_composition (&coding, Fcurrent_buffer ());
4235 coding_free_composition_data (&coding);
4236
427f5aab
KH
4237 /* Set `inserted' to the number of inserted characters. */
4238 inserted = PT - temp;
3dbcf3f6 4239
93184560 4240 xfree (conversion_buffer);
68c45bf0 4241 emacs_close (fd);
3dbcf3f6
RS
4242 specpdl_ptr--;
4243
3dbcf3f6 4244 goto handled;
3d0387c0
RS
4245 }
4246
d4b8687b
RS
4247 if (! not_regular)
4248 {
4249 register Lisp_Object temp;
7fded690 4250
d4b8687b 4251 total = XINT (end) - XINT (beg);
570d7624 4252
d4b8687b
RS
4253 /* Make sure point-max won't overflow after this insertion. */
4254 XSETINT (temp, total);
4255 if (total != XINT (temp))
4256 error ("Maximum buffer size exceeded");
4257 }
4258 else
4259 /* For a special file, all we can do is guess. */
4260 total = READ_BUF_SIZE;
570d7624 4261
57d8d468 4262 if (NILP (visit) && total > 0)
6c478ee2 4263 prepare_to_modify_buffer (PT, PT, NULL);
570d7624 4264
7fe52289 4265 move_gap (PT);
7fded690
JB
4266 if (GAP_SIZE < total)
4267 make_gap (total - GAP_SIZE);
4268
a1d2b64a 4269 if (XINT (beg) != 0 || !NILP (replace))
7fded690
JB
4270 {
4271 if (lseek (fd, XINT (beg), 0) < 0)
b1d1b865
RS
4272 report_file_error ("Setting file position",
4273 Fcons (orig_filename, Qnil));
7fded690
JB
4274 }
4275
6fdaa9a0 4276 /* In the following loop, HOW_MUCH contains the total bytes read so
c8a6d68a
KH
4277 far for a regular file, and not changed for a special file. But,
4278 before exiting the loop, it is set to a negative value if I/O
4279 error occurs. */
a1d2b64a 4280 how_much = 0;
1b978129 4281
6fdaa9a0
KH
4282 /* Total bytes inserted. */
4283 inserted = 0;
1b978129 4284
c8a6d68a
KH
4285 /* Here, we don't do code conversion in the loop. It is done by
4286 code_convert_region after all data are read into the buffer. */
1b978129
GM
4287 {
4288 int gap_size = GAP_SIZE;
4289
4290 while (how_much < total)
4291 {
5e570b75 4292 /* try is reserved in some compilers (Microsoft C) */
1b978129
GM
4293 int trytry = min (total - how_much, READ_BUF_SIZE);
4294 int this;
570d7624 4295
1b978129
GM
4296 if (not_regular)
4297 {
4298 Lisp_Object val;
570d7624 4299
1b978129
GM
4300 /* Maybe make more room. */
4301 if (gap_size < trytry)
4302 {
4303 make_gap (total - gap_size);
4304 gap_size = GAP_SIZE;
4305 }
4306
4307 /* Read from the file, capturing `quit'. When an
4308 error occurs, end the loop, and arrange for a quit
4309 to be signaled after decoding the text we read. */
4310 non_regular_fd = fd;
4311 non_regular_inserted = inserted;
4312 non_regular_nbytes = trytry;
4313 val = internal_condition_case_1 (read_non_regular, Qnil, Qerror,
4314 read_non_regular_quit);
4315 if (NILP (val))
4316 {
4317 read_quit = 1;
4318 break;
4319 }
4320
4321 this = XINT (val);
4322 }
4323 else
4324 {
4325 /* Allow quitting out of the actual I/O. We don't make text
4326 part of the buffer until all the reading is done, so a C-g
4327 here doesn't do any harm. */
4328 immediate_quit = 1;
4329 QUIT;
28c3eb5a 4330 this = emacs_read (fd, BEG_ADDR + PT_BYTE - BEG_BYTE + inserted, trytry);
1b978129
GM
4331 immediate_quit = 0;
4332 }
4333
4334 if (this <= 0)
4335 {
4336 how_much = this;
4337 break;
4338 }
4339
4340 gap_size -= this;
4341
4342 /* For a regular file, where TOTAL is the real size,
4343 count HOW_MUCH to compare with it.
4344 For a special file, where TOTAL is just a buffer size,
4345 so don't bother counting in HOW_MUCH.
4346 (INSERTED is where we count the number of characters inserted.) */
4347 if (! not_regular)
4348 how_much += this;
4349 inserted += this;
4350 }
4351 }
4352
4353 /* Make the text read part of the buffer. */
4354 GAP_SIZE -= inserted;
4355 GPT += inserted;
4356 GPT_BYTE += inserted;
4357 ZV += inserted;
4358 ZV_BYTE += inserted;
4359 Z += inserted;
4360 Z_BYTE += inserted;
6fdaa9a0 4361
c8a6d68a
KH
4362 if (GAP_SIZE > 0)
4363 /* Put an anchor to ensure multi-byte form ends at gap. */
4364 *GPT_ADDR = 0;
d4b8687b 4365
68c45bf0 4366 emacs_close (fd);
6fdaa9a0 4367
c8a6d68a
KH
4368 /* Discard the unwind protect for closing the file. */
4369 specpdl_ptr--;
6fdaa9a0 4370
c8a6d68a
KH
4371 if (how_much < 0)
4372 error ("IO error reading %s: %s",
d5db4077 4373 SDATA (orig_filename), emacs_strerror (errno));
ec7adf26 4374
f8569325
DL
4375 notfound:
4376
2df42e09 4377 if (! coding_system_decided)
c8a6d68a 4378 {
2df42e09 4379 /* The coding system is not yet decided. Decide it by an
dfe35e7b
RS
4380 optimized method for handling `coding:' tag.
4381
4382 Note that we can get here only if the buffer was empty
4383 before the insertion. */
2df42e09
KH
4384 Lisp_Object val;
4385 val = Qnil;
f736ffbf 4386
2df42e09
KH
4387 if (!NILP (Vcoding_system_for_read))
4388 val = Vcoding_system_for_read;
4389 else
4390 {
98a7d268
KH
4391 /* Since we are sure that the current buffer was empty
4392 before the insertion, we can toggle
4393 enable-multibyte-characters directly here without taking
4394 care of marker adjustment and byte combining problem. By
4395 this way, we can run Lisp program safely before decoding
4396 the inserted text. */
4397 Lisp_Object unwind_data;
aed13378 4398 int count = SPECPDL_INDEX ();
2df42e09 4399
98a7d268
KH
4400 unwind_data = Fcons (current_buffer->enable_multibyte_characters,
4401 Fcons (current_buffer->undo_list,
4402 Fcurrent_buffer ()));
2df42e09 4403 current_buffer->enable_multibyte_characters = Qnil;
98a7d268
KH
4404 current_buffer->undo_list = Qt;
4405 record_unwind_protect (decide_coding_unwind, unwind_data);
4406
4407 if (inserted > 0 && ! NILP (Vset_auto_coding_function))
4408 {
1255deb9
KH
4409 val = call2 (Vset_auto_coding_function,
4410 filename, make_number (inserted));
2df42e09 4411 }
f736ffbf 4412
2df42e09
KH
4413 if (NILP (val))
4414 {
4415 /* If the coding system is not yet decided, check
4416 file-coding-system-alist. */
4417 Lisp_Object args[6], coding_systems;
f736ffbf 4418
2df42e09
KH
4419 args[0] = Qinsert_file_contents, args[1] = orig_filename;
4420 args[2] = visit, args[3] = beg, args[4] = end, args[5] = Qnil;
4421 coding_systems = Ffind_operation_coding_system (6, args);
4422 if (CONSP (coding_systems))
03699b14 4423 val = XCAR (coding_systems);
f736ffbf 4424 }
98a7d268
KH
4425
4426 unbind_to (count, Qnil);
4427 inserted = Z_BYTE - BEG_BYTE;
2df42e09 4428 }
f736ffbf 4429
2df42e09
KH
4430 /* The following kludgy code is to avoid some compiler bug.
4431 We can't simply do
4432 setup_coding_system (val, &coding);
4433 on some system. */
4434 {
4435 struct coding_system temp_coding;
4436 setup_coding_system (val, &temp_coding);
4437 bcopy (&temp_coding, &coding, sizeof coding);
4438 }
f8569325
DL
4439 /* Ensure we set Vlast_coding_system_used. */
4440 set_coding_system = 1;
f736ffbf 4441
237a6fd2
RS
4442 if (NILP (current_buffer->enable_multibyte_characters)
4443 && ! NILP (val))
4444 /* We must suppress all character code conversion except for
2df42e09
KH
4445 end-of-line conversion. */
4446 setup_raw_text_coding_system (&coding);
6db43875
KH
4447 coding.src_multibyte = 0;
4448 coding.dst_multibyte
4449 = !NILP (current_buffer->enable_multibyte_characters);
2df42e09 4450 }
f736ffbf 4451
8c3b9441 4452 if (!NILP (visit)
24766480
GM
4453 /* Can't do this if part of the buffer might be preserved. */
4454 && NILP (replace)
8c3b9441
KH
4455 && (coding.type == coding_type_no_conversion
4456 || coding.type == coding_type_raw_text))
4457 {
24766480
GM
4458 /* Visiting a file with these coding system makes the buffer
4459 unibyte. */
4460 current_buffer->enable_multibyte_characters = Qnil;
e1249666 4461 coding.dst_multibyte = 0;
8c3b9441
KH
4462 }
4463
c91beee2 4464 if (inserted > 0 || coding.type == coding_type_ccl)
2df42e09 4465 {
c8a6d68a 4466 if (CODING_MAY_REQUIRE_DECODING (&coding))
64e0ae2a
KH
4467 {
4468 code_convert_region (PT, PT_BYTE, PT + inserted, PT_BYTE + inserted,
4469 &coding, 0, 0);
8c3b9441 4470 inserted = coding.produced_char;
f8198e19 4471 }
e9cea947
AS
4472 else
4473 adjust_after_insert (PT, PT_BYTE, PT + inserted, PT_BYTE + inserted,
8c3b9441 4474 inserted);
2df42e09 4475 }
570d7624 4476
04e6f79c 4477#ifdef DOS_NT
2df42e09
KH
4478 /* Use the conversion type to determine buffer-file-type
4479 (find-buffer-file-type is now used to help determine the
4480 conversion). */
4481 if ((coding.eol_type == CODING_EOL_UNDECIDED
4482 || coding.eol_type == CODING_EOL_LF)
4483 && ! CODING_REQUIRE_DECODING (&coding))
4484 current_buffer->buffer_file_type = Qt;
4485 else
4486 current_buffer->buffer_file_type = Qnil;
04e6f79c 4487#endif
570d7624 4488
32f4334d 4489 handled:
570d7624 4490
265a9e55 4491 if (!NILP (visit))
570d7624 4492 {
cfadd376
RS
4493 if (!EQ (current_buffer->undo_list, Qt))
4494 current_buffer->undo_list = Qnil;
570d7624 4495#ifdef APOLLO
d5db4077 4496 stat (SDATA (filename), &st);
570d7624 4497#endif
62bcf009 4498
a7e82472
RS
4499 if (NILP (handler))
4500 {
4501 current_buffer->modtime = st.st_mtime;
b1d1b865 4502 current_buffer->filename = orig_filename;
a7e82472 4503 }
62bcf009 4504
95385625 4505 SAVE_MODIFF = MODIFF;
570d7624 4506 current_buffer->auto_save_modified = MODIFF;
2acfd7ae 4507 XSETFASTINT (current_buffer->save_length, Z - BEG);
570d7624 4508#ifdef CLASH_DETECTION
32f4334d
RS
4509 if (NILP (handler))
4510 {
f471f4c2
RS
4511 if (!NILP (current_buffer->file_truename))
4512 unlock_file (current_buffer->file_truename);
32f4334d
RS
4513 unlock_file (filename);
4514 }
570d7624 4515#endif /* CLASH_DETECTION */
330bfe57
RS
4516 if (not_regular)
4517 Fsignal (Qfile_error,
4518 Fcons (build_string ("not a regular file"),
b1d1b865 4519 Fcons (orig_filename, Qnil)));
570d7624
JB
4520 }
4521
0d420e88 4522 /* Decode file format */
c8a6d68a 4523 if (inserted > 0)
0d420e88 4524 {
ed8e506f
GM
4525 int empty_undo_list_p = 0;
4526
4527 /* If we're anyway going to discard undo information, don't
4528 record it in the first place. The buffer's undo list at this
4529 point is either nil or t when visiting a file. */
4530 if (!NILP (visit))
4531 {
4532 empty_undo_list_p = NILP (current_buffer->undo_list);
4533 current_buffer->undo_list = Qt;
4534 }
4535
199607e4 4536 insval = call3 (Qformat_decode,
c8a6d68a 4537 Qnil, make_number (inserted), visit);
b7826503 4538 CHECK_NUMBER (insval);
c8a6d68a 4539 inserted = XFASTINT (insval);
ed8e506f
GM
4540
4541 if (!NILP (visit))
4542 current_buffer->undo_list = empty_undo_list_p ? Qnil : Qt;
0d420e88
BG
4543 }
4544
ce51c54c
KH
4545 if (set_coding_system)
4546 Vlast_coding_system_used = coding.symbol;
4547
0342d8c5
RS
4548 /* Call after-change hooks for the inserted text, aside from the case
4549 of normal visiting (not with REPLACE), which is done in a new buffer
4550 "before" the buffer is changed. */
c8a6d68a 4551 if (inserted > 0 && total > 0
0342d8c5 4552 && (NILP (visit) || !NILP (replace)))
ce51c54c
KH
4553 {
4554 signal_after_change (PT, 0, inserted);
4555 update_compositions (PT, PT, CHECK_BORDER);
4556 }
b56567b5 4557
f8569325 4558 p = Vafter_insert_file_functions;
28c3eb5a 4559 while (CONSP (p))
d6a3cc15 4560 {
28c3eb5a 4561 insval = call1 (XCAR (p), make_number (inserted));
f8569325 4562 if (!NILP (insval))
d6a3cc15 4563 {
b7826503 4564 CHECK_NUMBER (insval);
f8569325 4565 inserted = XFASTINT (insval);
d6a3cc15 4566 }
f8569325 4567 QUIT;
28c3eb5a 4568 p = XCDR (p);
f8569325
DL
4569 }
4570
4571 if (!NILP (visit)
4572 && current_buffer->modtime == -1)
4573 {
4574 /* If visiting nonexistent file, return nil. */
4575 report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
d6a3cc15
RS
4576 }
4577
1b978129
GM
4578 if (read_quit)
4579 Fsignal (Qquit, Qnil);
4580
ec7adf26 4581 /* ??? Retval needs to be dealt with in all cases consistently. */
a1d2b64a 4582 if (NILP (val))
b1d1b865 4583 val = Fcons (orig_filename,
a1d2b64a
RS
4584 Fcons (make_number (inserted),
4585 Qnil));
4586
4587 RETURN_UNGCPRO (unbind_to (count, val));
570d7624 4588}
7fded690 4589\f
236a12f2
SM
4590static Lisp_Object build_annotations P_ ((Lisp_Object, Lisp_Object));
4591static Lisp_Object build_annotations_2 P_ ((Lisp_Object, Lisp_Object,
4592 Lisp_Object, Lisp_Object));
d6a3cc15 4593
6fc6f94b 4594/* If build_annotations switched buffers, switch back to BUF.
6fdaa9a0
KH
4595 Kill the temporary buffer that was selected in the meantime.
4596
4597 Since this kill only the last temporary buffer, some buffers remain
4598 not killed if build_annotations switched buffers more than once.
4599 -- K.Handa */
6fc6f94b 4600
199607e4 4601static Lisp_Object
6fc6f94b
RS
4602build_annotations_unwind (buf)
4603 Lisp_Object buf;
4604{
4605 Lisp_Object tembuf;
4606
4607 if (XBUFFER (buf) == current_buffer)
4608 return Qnil;
4609 tembuf = Fcurrent_buffer ();
4610 Fset_buffer (buf);
4611 Fkill_buffer (tembuf);
4612 return Qnil;
4613}
4614
7c82a4a9
SM
4615/* Decide the coding-system to encode the data with. */
4616
4617void
4618choose_write_coding_system (start, end, filename,
4619 append, visit, lockname, coding)
4620 Lisp_Object start, end, filename, append, visit, lockname;
4621 struct coding_system *coding;
4622{
4623 Lisp_Object val;
4624
4625 if (auto_saving)
4626 val = Qnil;
4627 else if (!NILP (Vcoding_system_for_write))
4628 val = Vcoding_system_for_write;
4629 else
4630 {
4631 /* If the variable `buffer-file-coding-system' is set locally,
4632 it means that the file was read with some kind of code
4633 conversion or the variable is explicitly set by users. We
4634 had better write it out with the same coding system even if
4635 `enable-multibyte-characters' is nil.
4636
4637 If it is not set locally, we anyway have to convert EOL
4638 format if the default value of `buffer-file-coding-system'
4639 tells that it is not Unix-like (LF only) format. */
4640 int using_default_coding = 0;
4641 int force_raw_text = 0;
4642
4643 val = current_buffer->buffer_file_coding_system;
4644 if (NILP (val)
4645 || NILP (Flocal_variable_p (Qbuffer_file_coding_system, Qnil)))
4646 {
4647 val = Qnil;
4648 if (NILP (current_buffer->enable_multibyte_characters))
4649 force_raw_text = 1;
4650 }
4651
4652 if (NILP (val))
4653 {
4654 /* Check file-coding-system-alist. */
4655 Lisp_Object args[7], coding_systems;
4656
4657 args[0] = Qwrite_region; args[1] = start; args[2] = end;
4658 args[3] = filename; args[4] = append; args[5] = visit;
4659 args[6] = lockname;
4660 coding_systems = Ffind_operation_coding_system (7, args);
4661 if (CONSP (coding_systems) && !NILP (XCDR (coding_systems)))
4662 val = XCDR (coding_systems);
4663 }
4664
4665 if (NILP (val)
4666 && !NILP (current_buffer->buffer_file_coding_system))
4667 {
4668 /* If we still have not decided a coding system, use the
4669 default value of buffer-file-coding-system. */
4670 val = current_buffer->buffer_file_coding_system;
4671 using_default_coding = 1;
4672 }
4673
4674 if (!force_raw_text
4675 && !NILP (Ffboundp (Vselect_safe_coding_system_function)))
4676 /* Confirm that VAL can surely encode the current region. */
905a4276
PJ
4677 val = call5 (Vselect_safe_coding_system_function,
4678 start, end, val, Qnil, filename);
7c82a4a9
SM
4679
4680 setup_coding_system (Fcheck_coding_system (val), coding);
4681 if (coding->eol_type == CODING_EOL_UNDECIDED
4682 && !using_default_coding)
4683 {
4684 if (! EQ (default_buffer_file_coding.symbol,
4685 buffer_defaults.buffer_file_coding_system))
4686 setup_coding_system (buffer_defaults.buffer_file_coding_system,
4687 &default_buffer_file_coding);
4688 if (default_buffer_file_coding.eol_type != CODING_EOL_UNDECIDED)
4689 {
4690 Lisp_Object subsidiaries;
4691
4692 coding->eol_type = default_buffer_file_coding.eol_type;
4693 subsidiaries = Fget (coding->symbol, Qeol_type);
4694 if (VECTORP (subsidiaries)
4695 && XVECTOR (subsidiaries)->size == 3)
4696 coding->symbol
4697 = XVECTOR (subsidiaries)->contents[coding->eol_type];
4698 }
4699 }
4700
4701 if (force_raw_text)
4702 setup_raw_text_coding_system (coding);
4703 goto done_setup_coding;
4704 }
4705
4706 setup_coding_system (Fcheck_coding_system (val), coding);
4707
4708 done_setup_coding:
4709 if (!STRINGP (start) && !NILP (current_buffer->selective_display))
4710 coding->mode |= CODING_MODE_SELECTIVE_DISPLAY;
4711}
4712
de1d0127 4713DEFUN ("write-region", Fwrite_region, Swrite_region, 3, 7,
8c1a1077
PJ
4714 "r\nFWrite region to file: \ni\ni\ni\np",
4715 doc: /* Write current region into specified file.
c2efea25
RS
4716When called from a program, requires three arguments:
4717START, END and FILENAME. START and END are normally buffer positions
4718specifying the part of the buffer to write.
4719If START is nil, that means to use the entire buffer contents.
4720If START is a string, then output that string to the file
4721instead of any buffer contents; END is ignored.
4722
8c1a1077
PJ
4723Optional fourth argument APPEND if non-nil means
4724 append to existing file contents (if any). If it is an integer,
4725 seek to that offset in the file before writing.
4726Optional fifth argument VISIT if t means
4727 set the last-save-file-modtime of buffer to this file's modtime
4728 and mark buffer not modified.
4729If VISIT is a string, it is a second file name;
4730 the output goes to FILENAME, but the buffer is marked as visiting VISIT.
4731 VISIT is also the file name to lock and unlock for clash detection.
4732If VISIT is neither t nor nil nor a string,
5f4e6aa9 4733 that means do not display the \"Wrote file\" message.
8c1a1077
PJ
4734The optional sixth arg LOCKNAME, if non-nil, specifies the name to
4735 use for locking and unlocking, overriding FILENAME and VISIT.
4736The optional seventh arg MUSTBENEW, if non-nil, insists on a check
4737 for an existing file with the same name. If MUSTBENEW is `excl',
4738 that means to get an error if the file already exists; never overwrite.
4739 If MUSTBENEW is neither nil nor `excl', that means ask for
4740 confirmation before overwriting, but do go ahead and overwrite the file
4741 if the user confirms.
8c1a1077
PJ
4742
4743This does code conversion according to the value of
4744`coding-system-for-write', `buffer-file-coding-system', or
4745`file-coding-system-alist', and sets the variable
4746`last-coding-system-used' to the coding system actually used. */)
4747 (start, end, filename, append, visit, lockname, mustbenew)
f7b4065f 4748 Lisp_Object start, end, filename, append, visit, lockname, mustbenew;
570d7624
JB
4749{
4750 register int desc;
4751 int failure;
6bbd7a29 4752 int save_errno = 0;
570d7624
JB
4753 unsigned char *fn;
4754 struct stat st;
c975dd7a 4755 int tem;
aed13378 4756 int count = SPECPDL_INDEX ();
6fc6f94b 4757 int count1;
570d7624 4758#ifdef VMS
5e570b75 4759 unsigned char *fname = 0; /* If non-0, original filename (must rename) */
570d7624 4760#endif /* VMS */
3eac9910 4761 Lisp_Object handler;
4ad827c5 4762 Lisp_Object visit_file;
65b7d3e7 4763 Lisp_Object annotations;
b1d1b865 4764 Lisp_Object encoded_filename;
d3a67486
SM
4765 int visiting = (EQ (visit, Qt) || STRINGP (visit));
4766 int quietly = !NILP (visit);
7204a979 4767 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
6fc6f94b 4768 struct buffer *given_buffer;
5e570b75 4769#ifdef DOS_NT
fa228724 4770 int buffer_file_type = O_BINARY;
5e570b75 4771#endif /* DOS_NT */
6fdaa9a0 4772 struct coding_system coding;
570d7624 4773
d3a67486 4774 if (current_buffer->base_buffer && visiting)
95385625
RS
4775 error ("Cannot do file visiting in an indirect buffer");
4776
561cb8e1 4777 if (!NILP (start) && !STRINGP (start))
570d7624
JB
4778 validate_region (&start, &end);
4779
59fac292 4780 GCPRO5 (start, filename, visit, visit_file, lockname);
b56567b5 4781
570d7624 4782 filename = Fexpand_file_name (filename, Qnil);
de1d0127 4783
236a12f2 4784 if (!NILP (mustbenew) && !EQ (mustbenew, Qexcl))
b8b29dc9 4785 barf_or_query_if_file_exists (filename, "overwrite", 1, 0, 1);
de1d0127 4786
561cb8e1 4787 if (STRINGP (visit))
e5176bae 4788 visit_file = Fexpand_file_name (visit, Qnil);
4ad827c5
RS
4789 else
4790 visit_file = filename;
4791
7204a979
RS
4792 if (NILP (lockname))
4793 lockname = visit_file;
4794
65b7d3e7
RS
4795 annotations = Qnil;
4796
32f4334d
RS
4797 /* If the file name has special constructs in it,
4798 call the corresponding file handler. */
49307295 4799 handler = Ffind_file_name_handler (filename, Qwrite_region);
b56ad927 4800 /* If FILENAME has no handler, see if VISIT has one. */
93c30b5f 4801 if (NILP (handler) && STRINGP (visit))
199607e4 4802 handler = Ffind_file_name_handler (visit, Qwrite_region);
3eac9910 4803
32f4334d
RS
4804 if (!NILP (handler))
4805 {
32f4334d 4806 Lisp_Object val;
51cf6d37
RS
4807 val = call6 (handler, Qwrite_region, start, end,
4808 filename, append, visit);
32f4334d 4809
d6a3cc15 4810 if (visiting)
32f4334d 4811 {
95385625 4812 SAVE_MODIFF = MODIFF;
2acfd7ae 4813 XSETFASTINT (current_buffer->save_length, Z - BEG);
3b7792ed 4814 current_buffer->filename = visit_file;
32f4334d 4815 }
09121adc 4816 UNGCPRO;
32f4334d
RS
4817 return val;
4818 }
4819
561cb8e1
RS
4820 /* Special kludge to simplify auto-saving. */
4821 if (NILP (start))
4822 {
2acfd7ae
KH
4823 XSETFASTINT (start, BEG);
4824 XSETFASTINT (end, Z);
561cb8e1
RS
4825 }
4826
6fc6f94b 4827 record_unwind_protect (build_annotations_unwind, Fcurrent_buffer ());
aed13378 4828 count1 = SPECPDL_INDEX ();
6fc6f94b
RS
4829
4830 given_buffer = current_buffer;
bf3428a1
RS
4831
4832 if (!STRINGP (start))
236a12f2 4833 {
bf3428a1
RS
4834 annotations = build_annotations (start, end);
4835
4836 if (current_buffer != given_buffer)
4837 {
4838 XSETFASTINT (start, BEGV);
4839 XSETFASTINT (end, ZV);
4840 }
236a12f2
SM
4841 }
4842
4843 UNGCPRO;
4844
4845 GCPRO5 (start, filename, annotations, visit_file, lockname);
4846
59fac292
SM
4847 /* Decide the coding-system to encode the data with.
4848 We used to make this choice before calling build_annotations, but that
4849 leads to problems when a write-annotate-function takes care of
4850 unsavable chars (as was the case with X-Symbol). */
4851 choose_write_coding_system (start, end, filename,
4852 append, visit, lockname, &coding);
4853 Vlast_coding_system_used = coding.symbol;
4854
236a12f2 4855 given_buffer = current_buffer;
bf3428a1 4856 if (! STRINGP (start))
6fc6f94b 4857 {
bf3428a1
RS
4858 annotations = build_annotations_2 (start, end,
4859 coding.pre_write_conversion, annotations);
4860 if (current_buffer != given_buffer)
4861 {
4862 XSETFASTINT (start, BEGV);
4863 XSETFASTINT (end, ZV);
4864 }
6fc6f94b 4865 }
d6a3cc15 4866
570d7624
JB
4867#ifdef CLASH_DETECTION
4868 if (!auto_saving)
84f6296a 4869 {
a9171faa 4870#if 0 /* This causes trouble for GNUS. */
84f6296a
RS
4871 /* If we've locked this file for some other buffer,
4872 query before proceeding. */
4873 if (!visiting && EQ (Ffile_locked_p (lockname), Qt))
bffd00b0 4874 call2 (intern ("ask-user-about-lock"), filename, Vuser_login_name);
a9171faa 4875#endif
84f6296a
RS
4876
4877 lock_file (lockname);
4878 }
570d7624
JB
4879#endif /* CLASH_DETECTION */
4880
b1d1b865
RS
4881 encoded_filename = ENCODE_FILE (filename);
4882
d5db4077 4883 fn = SDATA (encoded_filename);
570d7624 4884 desc = -1;
265a9e55 4885 if (!NILP (append))
5e570b75 4886#ifdef DOS_NT
68c45bf0 4887 desc = emacs_open (fn, O_WRONLY | buffer_file_type, 0);
5e570b75 4888#else /* not DOS_NT */
68c45bf0 4889 desc = emacs_open (fn, O_WRONLY, 0);
5e570b75 4890#endif /* not DOS_NT */
570d7624 4891
b1d1b865 4892 if (desc < 0 && (NILP (append) || errno == ENOENT))
570d7624 4893#ifdef VMS
5e570b75 4894 if (auto_saving) /* Overwrite any previous version of autosave file */
570d7624 4895 {
5e570b75 4896 vms_truncate (fn); /* if fn exists, truncate to zero length */
68c45bf0 4897 desc = emacs_open (fn, O_RDWR, 0);
570d7624 4898 if (desc < 0)
561cb8e1 4899 desc = creat_copy_attrs (STRINGP (current_buffer->filename)
d5db4077 4900 ? SDATA (current_buffer->filename) : 0,
b72dea2a 4901 fn);
570d7624 4902 }
5e570b75 4903 else /* Write to temporary name and rename if no errors */
570d7624
JB
4904 {
4905 Lisp_Object temp_name;
4906 temp_name = Ffile_name_directory (filename);
4907
265a9e55 4908 if (!NILP (temp_name))
570d7624
JB
4909 {
4910 temp_name = Fmake_temp_name (concat2 (temp_name,
4911 build_string ("$$SAVE$$")));
d5db4077
KR
4912 fname = SDATA (filename);
4913 fn = SDATA (temp_name);
570d7624
JB
4914 desc = creat_copy_attrs (fname, fn);
4915 if (desc < 0)
4916 {
4917 /* If we can't open the temporary file, try creating a new
4918 version of the original file. VMS "creat" creates a
4919 new version rather than truncating an existing file. */
4920 fn = fname;
4921 fname = 0;
4922 desc = creat (fn, 0666);
4923#if 0 /* This can clobber an existing file and fail to replace it,
4924 if the user runs out of space. */
4925 if (desc < 0)
4926 {
4927 /* We can't make a new version;
4928 try to truncate and rewrite existing version if any. */
4929 vms_truncate (fn);
68c45bf0 4930 desc = emacs_open (fn, O_RDWR, 0);
570d7624
JB
4931 }
4932#endif
4933 }
4934 }
4935 else
4936 desc = creat (fn, 0666);
4937 }
4938#else /* not VMS */
5e570b75 4939#ifdef DOS_NT
68c45bf0 4940 desc = emacs_open (fn,
95522746
GM
4941 O_WRONLY | O_CREAT | buffer_file_type
4942 | (EQ (mustbenew, Qexcl) ? O_EXCL : O_TRUNC),
68c45bf0 4943 S_IREAD | S_IWRITE);
5e570b75 4944#else /* not DOS_NT */
68c45bf0 4945 desc = emacs_open (fn, O_WRONLY | O_TRUNC | O_CREAT
7c752c80 4946 | (EQ (mustbenew, Qexcl) ? O_EXCL : 0),
68c45bf0 4947 auto_saving ? auto_save_mode_bits : 0666);
5e570b75 4948#endif /* not DOS_NT */
570d7624
JB
4949#endif /* not VMS */
4950
4951 if (desc < 0)
4952 {
4953#ifdef CLASH_DETECTION
4954 save_errno = errno;
7204a979 4955 if (!auto_saving) unlock_file (lockname);
570d7624
JB
4956 errno = save_errno;
4957#endif /* CLASH_DETECTION */
43fb7d9a 4958 UNGCPRO;
570d7624
JB
4959 report_file_error ("Opening output file", Fcons (filename, Qnil));
4960 }
4961
4962 record_unwind_protect (close_file_unwind, make_number (desc));
4963
c1c4693e 4964 if (!NILP (append) && !NILP (Ffile_regular_p (filename)))
43fb7d9a
DL
4965 {
4966 long ret;
4967
4968 if (NUMBERP (append))
4969 ret = lseek (desc, XINT (append), 1);
4970 else
4971 ret = lseek (desc, 0, 2);
4972 if (ret < 0)
4973 {
570d7624 4974#ifdef CLASH_DETECTION
43fb7d9a 4975 if (!auto_saving) unlock_file (lockname);
570d7624 4976#endif /* CLASH_DETECTION */
43fb7d9a
DL
4977 UNGCPRO;
4978 report_file_error ("Lseek error", Fcons (filename, Qnil));
4979 }
4980 }
4981
4982 UNGCPRO;
570d7624
JB
4983
4984#ifdef VMS
4985/*
4986 * Kludge Warning: The VMS C RTL likes to insert carriage returns
4987 * if we do writes that don't end with a carriage return. Furthermore
4988 * it cannot handle writes of more then 16K. The modified
4989 * version of "sys_write" in SYSDEP.C (see comment there) copes with
4990 * this EXCEPT for the last record (iff it doesn't end with a carriage
4991 * return). This implies that if your buffer doesn't end with a carriage
4992 * return, you get one free... tough. However it also means that if
4993 * we make two calls to sys_write (a la the following code) you can
4994 * get one at the gap as well. The easiest way to fix this (honest)
4995 * is to move the gap to the next newline (or the end of the buffer).
4996 * Thus this change.
4997 *
4998 * Yech!
4999 */
5000 if (GPT > BEG && GPT_ADDR[-1] != '\n')
5001 move_gap (find_next_newline (GPT, 1));
cdfb0f1d
KH
5002#else
5003 /* Whether VMS or not, we must move the gap to the next of newline
5004 when we must put designation sequences at beginning of line. */
5005 if (INTEGERP (start)
5006 && coding.type == coding_type_iso2022
5007 && coding.flags & CODING_FLAG_ISO_DESIGNATE_AT_BOL
5008 && GPT > BEG && GPT_ADDR[-1] != '\n')
ec7adf26
RS
5009 {
5010 int opoint = PT, opoint_byte = PT_BYTE;
5011 scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 0);
5012 move_gap_both (PT, PT_BYTE);
5013 SET_PT_BOTH (opoint, opoint_byte);
5014 }
570d7624
JB
5015#endif
5016
5017 failure = 0;
5018 immediate_quit = 1;
5019
561cb8e1 5020 if (STRINGP (start))
570d7624 5021 {
d5db4077 5022 failure = 0 > a_write (desc, start, 0, SCHARS (start),
ce51c54c 5023 &annotations, &coding);
570d7624
JB
5024 save_errno = errno;
5025 }
5026 else if (XINT (start) != XINT (end))
5027 {
ec7adf26
RS
5028 tem = CHAR_TO_BYTE (XINT (start));
5029
570d7624
JB
5030 if (XINT (start) < GPT)
5031 {
ce51c54c
KH
5032 failure = 0 > a_write (desc, Qnil, XINT (start),
5033 min (GPT, XINT (end)) - XINT (start),
5034 &annotations, &coding);
570d7624
JB
5035 save_errno = errno;
5036 }
5037
5038 if (XINT (end) > GPT && !failure)
5039 {
ce51c54c
KH
5040 tem = max (XINT (start), GPT);
5041 failure = 0 > a_write (desc, Qnil, tem , XINT (end) - tem,
5042 &annotations, &coding);
d6a3cc15
RS
5043 save_errno = errno;
5044 }
69f6e679
RS
5045 }
5046 else
5047 {
5048 /* If file was empty, still need to write the annotations */
c8a6d68a 5049 coding.mode |= CODING_MODE_LAST_BLOCK;
ce51c54c 5050 failure = 0 > a_write (desc, Qnil, XINT (end), 0, &annotations, &coding);
6fdaa9a0
KH
5051 save_errno = errno;
5052 }
5053
c8a6d68a
KH
5054 if (CODING_REQUIRE_FLUSHING (&coding)
5055 && !(coding.mode & CODING_MODE_LAST_BLOCK)
1354debd 5056 && ! failure)
6fdaa9a0
KH
5057 {
5058 /* We have to flush out a data. */
c8a6d68a 5059 coding.mode |= CODING_MODE_LAST_BLOCK;
ce51c54c 5060 failure = 0 > e_write (desc, Qnil, 0, 0, &coding);
69f6e679 5061 save_errno = errno;
570d7624
JB
5062 }
5063
5064 immediate_quit = 0;
5065
6e23c83e 5066#ifdef HAVE_FSYNC
570d7624
JB
5067 /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun).
5068 Disk full in NFS may be reported here. */
1daffa1c
RS
5069 /* mib says that closing the file will try to write as fast as NFS can do
5070 it, and that means the fsync here is not crucial for autosave files. */
5071 if (!auto_saving && fsync (desc) < 0)
cb33c142
KH
5072 {
5073 /* If fsync fails with EINTR, don't treat that as serious. */
5074 if (errno != EINTR)
5075 failure = 1, save_errno = errno;
5076 }
570d7624
JB
5077#endif
5078
199607e4 5079 /* Spurious "file has changed on disk" warnings have been
570d7624
JB
5080 observed on Suns as well.
5081 It seems that `close' can change the modtime, under nfs.
5082
5083 (This has supposedly been fixed in Sunos 4,
5084 but who knows about all the other machines with NFS?) */
5085#if 0
5086
5087 /* On VMS and APOLLO, must do the stat after the close
5088 since closing changes the modtime. */
5089#ifndef VMS
5090#ifndef APOLLO
5091 /* Recall that #if defined does not work on VMS. */
5092#define FOO
5093 fstat (desc, &st);
5094#endif
5095#endif
5096#endif
5097
5098 /* NFS can report a write failure now. */
68c45bf0 5099 if (emacs_close (desc) < 0)
570d7624
JB
5100 failure = 1, save_errno = errno;
5101
5102#ifdef VMS
5103 /* If we wrote to a temporary name and had no errors, rename to real name. */
5104 if (fname)
5105 {
5106 if (!failure)
5107 failure = (rename (fn, fname) != 0), save_errno = errno;
5108 fn = fname;
5109 }
5110#endif /* VMS */
5111
5112#ifndef FOO
5113 stat (fn, &st);
5114#endif
6fc6f94b
RS
5115 /* Discard the unwind protect for close_file_unwind. */
5116 specpdl_ptr = specpdl + count1;
5117 /* Restore the original current buffer. */
98295b48 5118 visit_file = unbind_to (count, visit_file);
570d7624
JB
5119
5120#ifdef CLASH_DETECTION
5121 if (!auto_saving)
7204a979 5122 unlock_file (lockname);
570d7624
JB
5123#endif /* CLASH_DETECTION */
5124
5125 /* Do this before reporting IO error
5126 to avoid a "file has changed on disk" warning on
5127 next attempt to save. */
d6a3cc15 5128 if (visiting)
570d7624
JB
5129 current_buffer->modtime = st.st_mtime;
5130
5131 if (failure)
d5db4077 5132 error ("IO error writing %s: %s", SDATA (filename),
68c45bf0 5133 emacs_strerror (save_errno));
570d7624 5134
d6a3cc15 5135 if (visiting)
570d7624 5136 {
95385625 5137 SAVE_MODIFF = MODIFF;
2acfd7ae 5138 XSETFASTINT (current_buffer->save_length, Z - BEG);
3b7792ed 5139 current_buffer->filename = visit_file;
f4226e89 5140 update_mode_lines++;
570d7624 5141 }
d6a3cc15 5142 else if (quietly)
570d7624
JB
5143 return Qnil;
5144
5145 if (!auto_saving)
60d67b83 5146 message_with_string ("Wrote %s", visit_file, 1);
570d7624
JB
5147
5148 return Qnil;
5149}
ec7adf26 5150\f
d6a3cc15
RS
5151Lisp_Object merge ();
5152
5153DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0,
8c1a1077
PJ
5154 doc: /* Return t if (car A) is numerically less than (car B). */)
5155 (a, b)
d6a3cc15
RS
5156 Lisp_Object a, b;
5157{
5158 return Flss (Fcar (a), Fcar (b));
5159}
5160
5161/* Build the complete list of annotations appropriate for writing out
5162 the text between START and END, by calling all the functions in
6fc6f94b
RS
5163 write-region-annotate-functions and merging the lists they return.
5164 If one of these functions switches to a different buffer, we assume
5165 that buffer contains altered text. Therefore, the caller must
5166 make sure to restore the current buffer in all cases,
5167 as save-excursion would do. */
d6a3cc15
RS
5168
5169static Lisp_Object
236a12f2
SM
5170build_annotations (start, end)
5171 Lisp_Object start, end;
d6a3cc15
RS
5172{
5173 Lisp_Object annotations;
5174 Lisp_Object p, res;
5175 struct gcpro gcpro1, gcpro2;
0a20b684 5176 Lisp_Object original_buffer;
532ed661 5177 int i;
0a20b684
RS
5178
5179 XSETBUFFER (original_buffer, current_buffer);
d6a3cc15
RS
5180
5181 annotations = Qnil;
5182 p = Vwrite_region_annotate_functions;
5183 GCPRO2 (annotations, p);
28c3eb5a 5184 while (CONSP (p))
d6a3cc15 5185 {
6fc6f94b
RS
5186 struct buffer *given_buffer = current_buffer;
5187 Vwrite_region_annotations_so_far = annotations;
28c3eb5a 5188 res = call2 (XCAR (p), start, end);
6fc6f94b
RS
5189 /* If the function makes a different buffer current,
5190 assume that means this buffer contains altered text to be output.
5191 Reset START and END from the buffer bounds
5192 and discard all previous annotations because they should have
5193 been dealt with by this function. */
5194 if (current_buffer != given_buffer)
5195 {
3cf29f61
RS
5196 XSETFASTINT (start, BEGV);
5197 XSETFASTINT (end, ZV);
6fc6f94b
RS
5198 annotations = Qnil;
5199 }
d6a3cc15
RS
5200 Flength (res); /* Check basic validity of return value */
5201 annotations = merge (annotations, res, Qcar_less_than_car);
28c3eb5a 5202 p = XCDR (p);
d6a3cc15 5203 }
0d420e88
BG
5204
5205 /* Now do the same for annotation functions implied by the file-format */
5206 if (auto_saving && (!EQ (Vauto_save_file_format, Qt)))
5207 p = Vauto_save_file_format;
5208 else
5209 p = current_buffer->file_format;
28c3eb5a 5210 for (i = 0; CONSP (p); p = XCDR (p), ++i)
0d420e88
BG
5211 {
5212 struct buffer *given_buffer = current_buffer;
532ed661 5213
0d420e88 5214 Vwrite_region_annotations_so_far = annotations;
532ed661
GM
5215
5216 /* Value is either a list of annotations or nil if the function
5217 has written annotations to a temporary buffer, which is now
5218 current. */
28c3eb5a 5219 res = call5 (Qformat_annotate_function, XCAR (p), start, end,
532ed661 5220 original_buffer, make_number (i));
0d420e88
BG
5221 if (current_buffer != given_buffer)
5222 {
3cf29f61
RS
5223 XSETFASTINT (start, BEGV);
5224 XSETFASTINT (end, ZV);
0d420e88
BG
5225 annotations = Qnil;
5226 }
532ed661
GM
5227
5228 if (CONSP (res))
5229 annotations = merge (annotations, res, Qcar_less_than_car);
0d420e88 5230 }
6fdaa9a0 5231
236a12f2
SM
5232 UNGCPRO;
5233 return annotations;
5234}
5235
5236static Lisp_Object
5237build_annotations_2 (start, end, pre_write_conversion, annotations)
5238 Lisp_Object start, end, pre_write_conversion, annotations;
5239{
5240 struct gcpro gcpro1;
5241 Lisp_Object res;
5242
5243 GCPRO1 (annotations);
6fdaa9a0
KH
5244 /* At last, do the same for the function PRE_WRITE_CONVERSION
5245 implied by the current coding-system. */
5246 if (!NILP (pre_write_conversion))
5247 {
5248 struct buffer *given_buffer = current_buffer;
5249 Vwrite_region_annotations_so_far = annotations;
5250 res = call2 (pre_write_conversion, start, end);
6fdaa9a0 5251 Flength (res);
cdfb0f1d
KH
5252 annotations = (current_buffer != given_buffer
5253 ? res
5254 : merge (annotations, res, Qcar_less_than_car));
6fdaa9a0
KH
5255 }
5256
d6a3cc15
RS
5257 UNGCPRO;
5258 return annotations;
5259}
ec7adf26 5260\f
ce51c54c
KH
5261/* Write to descriptor DESC the NCHARS chars starting at POS of STRING.
5262 If STRING is nil, POS is the character position in the current buffer.
d6a3cc15 5263 Intersperse with them the annotations from *ANNOT
ce51c54c 5264 which fall within the range of POS to POS + NCHARS,
d6a3cc15
RS
5265 each at its appropriate position.
5266
ec7adf26
RS
5267 We modify *ANNOT by discarding elements as we use them up.
5268
d6a3cc15
RS
5269 The return value is negative in case of system call failure. */
5270
ec7adf26 5271static int
ce51c54c 5272a_write (desc, string, pos, nchars, annot, coding)
d6a3cc15 5273 int desc;
ce51c54c
KH
5274 Lisp_Object string;
5275 register int nchars;
5276 int pos;
d6a3cc15 5277 Lisp_Object *annot;
6fdaa9a0 5278 struct coding_system *coding;
d6a3cc15
RS
5279{
5280 Lisp_Object tem;
5281 int nextpos;
ce51c54c 5282 int lastpos = pos + nchars;
d6a3cc15 5283
eb15aa18 5284 while (NILP (*annot) || CONSP (*annot))
d6a3cc15
RS
5285 {
5286 tem = Fcar_safe (Fcar (*annot));
ce51c54c 5287 nextpos = pos - 1;
ec7adf26 5288 if (INTEGERP (tem))
ce51c54c 5289 nextpos = XFASTINT (tem);
ec7adf26
RS
5290
5291 /* If there are no more annotations in this range,
5292 output the rest of the range all at once. */
ce51c54c
KH
5293 if (! (nextpos >= pos && nextpos <= lastpos))
5294 return e_write (desc, string, pos, lastpos, coding);
ec7adf26
RS
5295
5296 /* Output buffer text up to the next annotation's position. */
ce51c54c 5297 if (nextpos > pos)
d6a3cc15 5298 {
055a28c9 5299 if (0 > e_write (desc, string, pos, nextpos, coding))
d6a3cc15 5300 return -1;
ce51c54c 5301 pos = nextpos;
d6a3cc15 5302 }
ec7adf26 5303 /* Output the annotation. */
d6a3cc15
RS
5304 tem = Fcdr (Fcar (*annot));
5305 if (STRINGP (tem))
5306 {
d5db4077 5307 if (0 > e_write (desc, tem, 0, SCHARS (tem), coding))
d6a3cc15
RS
5308 return -1;
5309 }
5310 *annot = Fcdr (*annot);
5311 }
dfcf069d 5312 return 0;
d6a3cc15
RS
5313}
5314
6fdaa9a0
KH
5315#ifndef WRITE_BUF_SIZE
5316#define WRITE_BUF_SIZE (16 * 1024)
5317#endif
5318
ce51c54c
KH
5319/* Write text in the range START and END into descriptor DESC,
5320 encoding them with coding system CODING. If STRING is nil, START
5321 and END are character positions of the current buffer, else they
5322 are indexes to the string STRING. */
ec7adf26
RS
5323
5324static int
ce51c54c 5325e_write (desc, string, start, end, coding)
570d7624 5326 int desc;
ce51c54c
KH
5327 Lisp_Object string;
5328 int start, end;
6fdaa9a0 5329 struct coding_system *coding;
570d7624 5330{
ce51c54c
KH
5331 register char *addr;
5332 register int nbytes;
6fdaa9a0 5333 char buf[WRITE_BUF_SIZE];
ce51c54c
KH
5334 int return_val = 0;
5335
5336 if (start >= end)
5337 coding->composing = COMPOSITION_DISABLED;
5338 if (coding->composing != COMPOSITION_DISABLED)
5339 coding_save_composition (coding, start, end, string);
5340
5341 if (STRINGP (string))
5342 {
d5db4077
KR
5343 addr = SDATA (string);
5344 nbytes = SBYTES (string);
8c3b9441 5345 coding->src_multibyte = STRING_MULTIBYTE (string);
ce51c54c
KH
5346 }
5347 else if (start < end)
5348 {
5349 /* It is assured that the gap is not in the range START and END-1. */
5350 addr = CHAR_POS_ADDR (start);
5351 nbytes = CHAR_TO_BYTE (end) - CHAR_TO_BYTE (start);
8c3b9441
KH
5352 coding->src_multibyte
5353 = !NILP (current_buffer->enable_multibyte_characters);
ce51c54c
KH
5354 }
5355 else
5356 {
5357 addr = "";
5358 nbytes = 0;
8c3b9441 5359 coding->src_multibyte = 1;
ce51c54c 5360 }
570d7624 5361
6fdaa9a0
KH
5362 /* We used to have a code for handling selective display here. But,
5363 now it is handled within encode_coding. */
5364 while (1)
570d7624 5365 {
b4132433
KH
5366 int result;
5367
5368 result = encode_coding (coding, addr, buf, nbytes, WRITE_BUF_SIZE);
c8a6d68a 5369 if (coding->produced > 0)
6fdaa9a0 5370 {
68c45bf0 5371 coding->produced -= emacs_write (desc, buf, coding->produced);
ce51c54c
KH
5372 if (coding->produced)
5373 {
5374 return_val = -1;
5375 break;
5376 }
570d7624 5377 }
ca91fb26
KH
5378 nbytes -= coding->consumed;
5379 addr += coding->consumed;
5380 if (result == CODING_FINISH_INSUFFICIENT_SRC
5381 && nbytes > 0)
b4132433
KH
5382 {
5383 /* The source text ends by an incomplete multibyte form.
5384 There's no way other than write it out as is. */
68c45bf0 5385 nbytes -= emacs_write (desc, addr, nbytes);
ce51c54c
KH
5386 if (nbytes)
5387 {
5388 return_val = -1;
5389 break;
5390 }
b4132433 5391 }
ec7adf26 5392 if (nbytes <= 0)
6fdaa9a0 5393 break;
ce51c54c
KH
5394 start += coding->consumed_char;
5395 if (coding->cmp_data)
5396 coding_adjust_composition_offset (coding, start);
570d7624 5397 }
0c41a39c
KH
5398
5399 if (coding->cmp_data)
5400 coding_free_composition_data (coding);
5401
055a28c9 5402 return return_val;
570d7624 5403}
ec7adf26 5404\f
570d7624 5405DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,
8c1a1077
PJ
5406 Sverify_visited_file_modtime, 1, 1, 0,
5407 doc: /* Return t if last mod time of BUF's visited file matches what BUF records.
5408This means that the file has not been changed since it was visited or saved. */)
5409 (buf)
570d7624
JB
5410 Lisp_Object buf;
5411{
5412 struct buffer *b;
5413 struct stat st;
32f4334d 5414 Lisp_Object handler;
b1d1b865 5415 Lisp_Object filename;
570d7624 5416
b7826503 5417 CHECK_BUFFER (buf);
570d7624
JB
5418 b = XBUFFER (buf);
5419
93c30b5f 5420 if (!STRINGP (b->filename)) return Qt;
570d7624
JB
5421 if (b->modtime == 0) return Qt;
5422
32f4334d
RS
5423 /* If the file name has special constructs in it,
5424 call the corresponding file handler. */
49307295
KH
5425 handler = Ffind_file_name_handler (b->filename,
5426 Qverify_visited_file_modtime);
32f4334d 5427 if (!NILP (handler))
09121adc 5428 return call2 (handler, Qverify_visited_file_modtime, buf);
32f4334d 5429
b1d1b865
RS
5430 filename = ENCODE_FILE (b->filename);
5431
d5db4077 5432 if (stat (SDATA (filename), &st) < 0)
570d7624
JB
5433 {
5434 /* If the file doesn't exist now and didn't exist before,
5435 we say that it isn't modified, provided the error is a tame one. */
5436 if (errno == ENOENT || errno == EACCES || errno == ENOTDIR)
5437 st.st_mtime = -1;
5438 else
5439 st.st_mtime = 0;
5440 }
5441 if (st.st_mtime == b->modtime
5442 /* If both are positive, accept them if they are off by one second. */
5443 || (st.st_mtime > 0 && b->modtime > 0
5444 && (st.st_mtime == b->modtime + 1
5445 || st.st_mtime == b->modtime - 1)))
5446 return Qt;
5447 return Qnil;
5448}
5449
5450DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,
8c1a1077
PJ
5451 Sclear_visited_file_modtime, 0, 0, 0,
5452 doc: /* Clear out records of last mod time of visited file.
5453Next attempt to save will certainly not complain of a discrepancy. */)
5454 ()
570d7624
JB
5455{
5456 current_buffer->modtime = 0;
5457 return Qnil;
5458}
5459
f5d5eccf 5460DEFUN ("visited-file-modtime", Fvisited_file_modtime,
8c1a1077
PJ
5461 Svisited_file_modtime, 0, 0, 0,
5462 doc: /* Return the current buffer's recorded visited file modification time.
5463The value is a list of the form (HIGH . LOW), like the time values
5464that `file-attributes' returns. */)
5465 ()
f5d5eccf 5466{
b50536bb 5467 return long_to_cons ((unsigned long) current_buffer->modtime);
f5d5eccf
RS
5468}
5469
570d7624 5470DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
8c1a1077
PJ
5471 Sset_visited_file_modtime, 0, 1, 0,
5472 doc: /* Update buffer's recorded modification time from the visited file's time.
5473Useful if the buffer was not read from the file normally
5474or if the file itself has been changed for some known benign reason.
5475An argument specifies the modification time value to use
5476\(instead of that of the visited file), in the form of a list
5477\(HIGH . LOW) or (HIGH LOW). */)
5478 (time_list)
f5d5eccf 5479 Lisp_Object time_list;
570d7624 5480{
f5d5eccf
RS
5481 if (!NILP (time_list))
5482 current_buffer->modtime = cons_to_long (time_list);
5483 else
5484 {
5485 register Lisp_Object filename;
5486 struct stat st;
5487 Lisp_Object handler;
570d7624 5488
f5d5eccf 5489 filename = Fexpand_file_name (current_buffer->filename, Qnil);
32f4334d 5490
f5d5eccf
RS
5491 /* If the file name has special constructs in it,
5492 call the corresponding file handler. */
49307295 5493 handler = Ffind_file_name_handler (filename, Qset_visited_file_modtime);
f5d5eccf 5494 if (!NILP (handler))
caf3c431 5495 /* The handler can find the file name the same way we did. */
76c881b0 5496 return call2 (handler, Qset_visited_file_modtime, Qnil);
b1d1b865
RS
5497
5498 filename = ENCODE_FILE (filename);
5499
d5db4077 5500 if (stat (SDATA (filename), &st) >= 0)
f5d5eccf
RS
5501 current_buffer->modtime = st.st_mtime;
5502 }
570d7624
JB
5503
5504 return Qnil;
5505}
5506\f
5507Lisp_Object
d7f31e22
GM
5508auto_save_error (error)
5509 Lisp_Object error;
570d7624 5510{
d7f31e22
GM
5511 Lisp_Object args[3], msg;
5512 int i, nbytes;
5513 struct gcpro gcpro1;
5514
570d7624 5515 ring_bell ();
d7f31e22
GM
5516
5517 args[0] = build_string ("Auto-saving %s: %s");
5518 args[1] = current_buffer->name;
5519 args[2] = Ferror_message_string (error);
5520 msg = Fformat (3, args);
5521 GCPRO1 (msg);
d5db4077 5522 nbytes = SBYTES (msg);
d7f31e22
GM
5523
5524 for (i = 0; i < 3; ++i)
5525 {
5526 if (i == 0)
d5db4077 5527 message2 (SDATA (msg), nbytes, STRING_MULTIBYTE (msg));
d7f31e22 5528 else
d5db4077 5529 message2_nolog (SDATA (msg), nbytes, STRING_MULTIBYTE (msg));
d7f31e22
GM
5530 Fsleep_for (make_number (1), Qnil);
5531 }
5532
5533 UNGCPRO;
570d7624
JB
5534 return Qnil;
5535}
5536
5537Lisp_Object
5538auto_save_1 ()
5539{
570d7624
JB
5540 struct stat st;
5541
5542 /* Get visited file's mode to become the auto save file's mode. */
8801a864 5543 if (! NILP (current_buffer->filename)
d5db4077 5544 && stat (SDATA (current_buffer->filename), &st) >= 0)
570d7624
JB
5545 /* But make sure we can overwrite it later! */
5546 auto_save_mode_bits = st.st_mode | 0600;
5547 else
5548 auto_save_mode_bits = 0666;
5549
5550 return
5551 Fwrite_region (Qnil, Qnil,
5552 current_buffer->auto_save_file_name,
de1d0127 5553 Qnil, Qlambda, Qnil, Qnil);
570d7624
JB
5554}
5555
e54d3b5d 5556static Lisp_Object
1b335d29
RS
5557do_auto_save_unwind (stream) /* used as unwind-protect function */
5558 Lisp_Object stream;
e54d3b5d 5559{
3be3c08e 5560 auto_saving = 0;
1b335d29 5561 if (!NILP (stream))
03699b14
KR
5562 fclose ((FILE *) (XFASTINT (XCAR (stream)) << 16
5563 | XFASTINT (XCDR (stream))));
38119822 5564 pop_message ();
e54d3b5d
RS
5565 return Qnil;
5566}
5567
a8c828be
RS
5568static Lisp_Object
5569do_auto_save_unwind_1 (value) /* used as unwind-protect function */
5570 Lisp_Object value;
5571{
5572 minibuffer_auto_raise = XINT (value);
5573 return Qnil;
5574}
5575
570d7624 5576DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 2, "",
8c1a1077
PJ
5577 doc: /* Auto-save all buffers that need it.
5578This is all buffers that have auto-saving enabled
5579and are changed since last auto-saved.
5580Auto-saving writes the buffer into a file
5581so that your editing is not lost if the system crashes.
5582This file is not the file you visited; that changes only when you save.
5583Normally we run the normal hook `auto-save-hook' before saving.
5584
5585A non-nil NO-MESSAGE argument means do not print any message if successful.
5586A non-nil CURRENT-ONLY argument means save only current buffer. */)
5587 (no_message, current_only)
17857782 5588 Lisp_Object no_message, current_only;
570d7624
JB
5589{
5590 struct buffer *old = current_buffer, *b;
5591 Lisp_Object tail, buf;
5592 int auto_saved = 0;
f14b1c68 5593 int do_handled_files;
ff4c9993 5594 Lisp_Object oquit;
1b335d29
RS
5595 FILE *stream;
5596 Lisp_Object lispstream;
aed13378 5597 int count = SPECPDL_INDEX ();
a8c828be 5598 int orig_minibuffer_auto_raise = minibuffer_auto_raise;
38da540d
RS
5599 int message_p = 0;
5600
5601 if (max_specpdl_size < specpdl_size + 40)
5602 max_specpdl_size = specpdl_size + 40;
5603
5604 if (minibuf_level)
5605 no_message = Qt;
5606
5607 if (NILP (no_message));
5608 message_p = push_message ();
9c856db9 5609
ff4c9993
RS
5610 /* Ordinarily don't quit within this function,
5611 but don't make it impossible to quit (in case we get hung in I/O). */
5612 oquit = Vquit_flag;
5613 Vquit_flag = Qnil;
570d7624
JB
5614
5615 /* No GCPRO needed, because (when it matters) all Lisp_Object variables
5616 point to non-strings reached from Vbuffer_alist. */
5617
265a9e55 5618 if (!NILP (Vrun_hooks))
570d7624
JB
5619 call1 (Vrun_hooks, intern ("auto-save-hook"));
5620
e54d3b5d
RS
5621 if (STRINGP (Vauto_save_list_file_name))
5622 {
0894672f 5623 Lisp_Object listfile;
b272d624 5624
258fd2cb 5625 listfile = Fexpand_file_name (Vauto_save_list_file_name, Qnil);
0894672f
GM
5626
5627 /* Don't try to create the directory when shutting down Emacs,
5628 because creating the directory might signal an error, and
5629 that would leave Emacs in a strange state. */
5630 if (!NILP (Vrun_hooks))
5631 {
5632 Lisp_Object dir;
5633 dir = Ffile_name_directory (listfile);
5634 if (NILP (Ffile_directory_p (dir)))
5635 call2 (Qmake_directory, dir, Qt);
5636 }
b272d624 5637
d5db4077 5638 stream = fopen (SDATA (listfile), "w");
0eff1f85
RS
5639 if (stream != NULL)
5640 {
5641 /* Arrange to close that file whether or not we get an error.
5642 Also reset auto_saving to 0. */
5643 lispstream = Fcons (Qnil, Qnil);
f3fbd155
KR
5644 XSETCARFASTINT (lispstream, (EMACS_UINT)stream >> 16);
5645 XSETCDRFASTINT (lispstream, (EMACS_UINT)stream & 0xffff);
0eff1f85
RS
5646 }
5647 else
5648 lispstream = Qnil;
e54d3b5d
RS
5649 }
5650 else
1b335d29
RS
5651 {
5652 stream = NULL;
5653 lispstream = Qnil;
5654 }
199607e4 5655
1b335d29 5656 record_unwind_protect (do_auto_save_unwind, lispstream);
a8c828be
RS
5657 record_unwind_protect (do_auto_save_unwind_1,
5658 make_number (minibuffer_auto_raise));
5659 minibuffer_auto_raise = 0;
3be3c08e
RS
5660 auto_saving = 1;
5661
f14b1c68
JB
5662 /* First, save all files which don't have handlers. If Emacs is
5663 crashing, the handlers may tweak what is causing Emacs to crash
5664 in the first place, and it would be a shame if Emacs failed to
5665 autosave perfectly ordinary files because it couldn't handle some
5666 ange-ftp'd file. */
5667 for (do_handled_files = 0; do_handled_files < 2; do_handled_files++)
03699b14 5668 for (tail = Vbuffer_alist; GC_CONSP (tail); tail = XCDR (tail))
f14b1c68 5669 {
03699b14 5670 buf = XCDR (XCAR (tail));
f14b1c68 5671 b = XBUFFER (buf);
199607e4 5672
e54d3b5d 5673 /* Record all the buffers that have auto save mode
258fd2cb
RS
5674 in the special file that lists them. For each of these buffers,
5675 Record visited name (if any) and auto save name. */
93c30b5f 5676 if (STRINGP (b->auto_save_file_name)
1b335d29 5677 && stream != NULL && do_handled_files == 0)
e54d3b5d 5678 {
258fd2cb
RS
5679 if (!NILP (b->filename))
5680 {
d5db4077
KR
5681 fwrite (SDATA (b->filename), 1,
5682 SBYTES (b->filename), stream);
258fd2cb 5683 }
1b335d29 5684 putc ('\n', stream);
d5db4077
KR
5685 fwrite (SDATA (b->auto_save_file_name), 1,
5686 SBYTES (b->auto_save_file_name), stream);
1b335d29 5687 putc ('\n', stream);
e54d3b5d 5688 }
17857782 5689
f14b1c68
JB
5690 if (!NILP (current_only)
5691 && b != current_buffer)
5692 continue;
e54d3b5d 5693
95385625
RS
5694 /* Don't auto-save indirect buffers.
5695 The base buffer takes care of it. */
5696 if (b->base_buffer)
5697 continue;
5698
f14b1c68
JB
5699 /* Check for auto save enabled
5700 and file changed since last auto save
5701 and file changed since last real save. */
93c30b5f 5702 if (STRINGP (b->auto_save_file_name)
95385625 5703 && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)
f14b1c68 5704 && b->auto_save_modified < BUF_MODIFF (b)
82c2d839
RS
5705 /* -1 means we've turned off autosaving for a while--see below. */
5706 && XINT (b->save_length) >= 0
f14b1c68 5707 && (do_handled_files
49307295
KH
5708 || NILP (Ffind_file_name_handler (b->auto_save_file_name,
5709 Qwrite_region))))
f14b1c68 5710 {
b60247d9
RS
5711 EMACS_TIME before_time, after_time;
5712
5713 EMACS_GET_TIME (before_time);
5714
5715 /* If we had a failure, don't try again for 20 minutes. */
5716 if (b->auto_save_failure_time >= 0
5717 && EMACS_SECS (before_time) - b->auto_save_failure_time < 1200)
5718 continue;
5719
f14b1c68
JB
5720 if ((XFASTINT (b->save_length) * 10
5721 > (BUF_Z (b) - BUF_BEG (b)) * 13)
5722 /* A short file is likely to change a large fraction;
5723 spare the user annoying messages. */
5724 && XFASTINT (b->save_length) > 5000
5725 /* These messages are frequent and annoying for `*mail*'. */
5726 && !EQ (b->filename, Qnil)
5727 && NILP (no_message))
5728 {
5729 /* It has shrunk too much; turn off auto-saving here. */
a8c828be 5730 minibuffer_auto_raise = orig_minibuffer_auto_raise;
fd91d0d4 5731 message_with_string ("Buffer %s has shrunk a lot; auto save disabled in that buffer until next real save",
60d67b83 5732 b->name, 1);
a8c828be 5733 minibuffer_auto_raise = 0;
82c2d839
RS
5734 /* Turn off auto-saving until there's a real save,
5735 and prevent any more warnings. */
46283abe 5736 XSETINT (b->save_length, -1);
f14b1c68
JB
5737 Fsleep_for (make_number (1), Qnil);
5738 continue;
5739 }
5740 set_buffer_internal (b);
5741 if (!auto_saved && NILP (no_message))
5742 message1 ("Auto-saving...");
5743 internal_condition_case (auto_save_1, Qt, auto_save_error);
5744 auto_saved++;
5745 b->auto_save_modified = BUF_MODIFF (b);
2acfd7ae 5746 XSETFASTINT (current_buffer->save_length, Z - BEG);
f14b1c68 5747 set_buffer_internal (old);
b60247d9
RS
5748
5749 EMACS_GET_TIME (after_time);
5750
5751 /* If auto-save took more than 60 seconds,
5752 assume it was an NFS failure that got a timeout. */
5753 if (EMACS_SECS (after_time) - EMACS_SECS (before_time) > 60)
5754 b->auto_save_failure_time = EMACS_SECS (after_time);
f14b1c68
JB
5755 }
5756 }
570d7624 5757
b67f2ca5
RS
5758 /* Prevent another auto save till enough input events come in. */
5759 record_auto_save ();
570d7624 5760
17857782 5761 if (auto_saved && NILP (no_message))
f05b275b 5762 {
c71106e5 5763 if (message_p)
31f3d831 5764 {
22e59fa7 5765 sit_for (1, 0, 0, 0, 0);
c71106e5 5766 restore_message ();
31f3d831 5767 }
f05b275b
KH
5768 else
5769 message1 ("Auto-saving...done");
5770 }
570d7624 5771
ff4c9993
RS
5772 Vquit_flag = oquit;
5773
e54d3b5d 5774 unbind_to (count, Qnil);
570d7624
JB
5775 return Qnil;
5776}
5777
5778DEFUN ("set-buffer-auto-saved", Fset_buffer_auto_saved,
8c1a1077
PJ
5779 Sset_buffer_auto_saved, 0, 0, 0,
5780 doc: /* Mark current buffer as auto-saved with its current text.
5781No auto-save file will be written until the buffer changes again. */)
5782 ()
570d7624
JB
5783{
5784 current_buffer->auto_save_modified = MODIFF;
2acfd7ae 5785 XSETFASTINT (current_buffer->save_length, Z - BEG);
b60247d9
RS
5786 current_buffer->auto_save_failure_time = -1;
5787 return Qnil;
5788}
5789
5790DEFUN ("clear-buffer-auto-save-failure", Fclear_buffer_auto_save_failure,
8c1a1077
PJ
5791 Sclear_buffer_auto_save_failure, 0, 0, 0,
5792 doc: /* Clear any record of a recent auto-save failure in the current buffer. */)
5793 ()
b60247d9
RS
5794{
5795 current_buffer->auto_save_failure_time = -1;
570d7624
JB
5796 return Qnil;
5797}
5798
5799DEFUN ("recent-auto-save-p", Frecent_auto_save_p, Srecent_auto_save_p,
8c1a1077
PJ
5800 0, 0, 0,
5801 doc: /* Return t if buffer has been auto-saved since last read in or saved. */)
5802 ()
570d7624 5803{
95385625 5804 return (SAVE_MODIFF < current_buffer->auto_save_modified) ? Qt : Qnil;
570d7624
JB
5805}
5806\f
5807/* Reading and completing file names */
5808extern Lisp_Object Ffile_name_completion (), Ffile_name_all_completions ();
5809
6e710ae5
RS
5810/* In the string VAL, change each $ to $$ and return the result. */
5811
5812static Lisp_Object
5813double_dollars (val)
5814 Lisp_Object val;
5815{
5816 register unsigned char *old, *new;
5817 register int n;
5818 int osize, count;
5819
d5db4077 5820 osize = SBYTES (val);
60d67b83
RS
5821
5822 /* Count the number of $ characters. */
d5db4077 5823 for (n = osize, count = 0, old = SDATA (val); n > 0; n--)
6e710ae5
RS
5824 if (*old++ == '$') count++;
5825 if (count > 0)
5826 {
d5db4077
KR
5827 old = SDATA (val);
5828 val = make_uninit_multibyte_string (SCHARS (val) + count,
60d67b83 5829 osize + count);
d5db4077 5830 new = SDATA (val);
6e710ae5
RS
5831 for (n = osize; n > 0; n--)
5832 if (*old != '$')
5833 *new++ = *old++;
5834 else
5835 {
5836 *new++ = '$';
5837 *new++ = '$';
5838 old++;
5839 }
5840 }
5841 return val;
5842}
5843
59ffe07d
KS
5844static Lisp_Object
5845read_file_name_cleanup (arg)
5846 Lisp_Object arg;
5847{
c4174fbb 5848 return (current_buffer->directory = arg);
59ffe07d
KS
5849}
5850
570d7624 5851DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_internal,
8c1a1077
PJ
5852 3, 3, 0,
5853 doc: /* Internal subroutine for read-file-name. Do not call this. */)
5854 (string, dir, action)
570d7624
JB
5855 Lisp_Object string, dir, action;
5856 /* action is nil for complete, t for return list of completions,
5857 lambda for verify final value */
5858{
5859 Lisp_Object name, specdir, realdir, val, orig_string;
09121adc 5860 int changed;
8ce069f5 5861 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
09121adc 5862
b7826503 5863 CHECK_STRING (string);
58cc3710 5864
09121adc
RS
5865 realdir = dir;
5866 name = string;
5867 orig_string = Qnil;
5868 specdir = Qnil;
5869 changed = 0;
5870 /* No need to protect ACTION--we only compare it with t and nil. */
8ce069f5 5871 GCPRO5 (string, realdir, name, specdir, orig_string);
570d7624 5872
d5db4077 5873 if (SCHARS (string) == 0)
570d7624 5874 {
570d7624 5875 if (EQ (action, Qlambda))
09121adc
RS
5876 {
5877 UNGCPRO;
5878 return Qnil;
5879 }
570d7624
JB
5880 }
5881 else
5882 {
5883 orig_string = string;
5884 string = Fsubstitute_in_file_name (string);
09121adc 5885 changed = NILP (Fstring_equal (string, orig_string));
570d7624 5886 name = Ffile_name_nondirectory (string);
09121adc
RS
5887 val = Ffile_name_directory (string);
5888 if (! NILP (val))
5889 realdir = Fexpand_file_name (val, realdir);
570d7624
JB
5890 }
5891
265a9e55 5892 if (NILP (action))
570d7624
JB
5893 {
5894 specdir = Ffile_name_directory (string);
5895 val = Ffile_name_completion (name, realdir);
09121adc 5896 UNGCPRO;
93c30b5f 5897 if (!STRINGP (val))
570d7624 5898 {
09121adc 5899 if (changed)
dbd04e01 5900 return double_dollars (string);
09121adc 5901 return val;
570d7624
JB
5902 }
5903
265a9e55 5904 if (!NILP (specdir))
570d7624
JB
5905 val = concat2 (specdir, val);
5906#ifndef VMS
6e710ae5
RS
5907 return double_dollars (val);
5908#else /* not VMS */
09121adc 5909 return val;
6e710ae5 5910#endif /* not VMS */
570d7624 5911 }
09121adc 5912 UNGCPRO;
570d7624
JB
5913
5914 if (EQ (action, Qt))
59ffe07d
KS
5915 {
5916 Lisp_Object all = Ffile_name_all_completions (name, realdir);
5917 Lisp_Object comp;
5918 int count;
5919
5920 if (NILP (Vread_file_name_predicate)
5921 || EQ (Vread_file_name_predicate, Qfile_exists_p))
5922 return all;
da46f04f
KS
5923
5924#ifndef VMS
5925 if (EQ (Vread_file_name_predicate, Qfile_directory_p))
5926 {
5927 /* Brute-force speed up for directory checking:
5928 Discard strings which don't end in a slash. */
5929 for (comp = Qnil; CONSP (all); all = XCDR (all))
5930 {
5931 Lisp_Object tem = XCAR (all);
5932 int len;
5933 if (STRINGP (tem) &&
d5db4077
KR
5934 (len = SCHARS (tem), len > 0) &&
5935 IS_DIRECTORY_SEP (SREF (tem, len-1)))
da46f04f
KS
5936 comp = Fcons (tem, comp);
5937 }
5938 }
5939 else
5940#endif
5941 {
5942 /* Must do it the hard (and slow) way. */
5943 GCPRO3 (all, comp, specdir);
aed13378 5944 count = SPECPDL_INDEX ();
da46f04f
KS
5945 record_unwind_protect (read_file_name_cleanup, current_buffer->directory);
5946 current_buffer->directory = realdir;
5947 for (comp = Qnil; CONSP (all); all = XCDR (all))
5948 if (!NILP (call1 (Vread_file_name_predicate, XCAR (all))))
5949 comp = Fcons (XCAR (all), comp);
5950 unbind_to (count, Qnil);
5951 UNGCPRO;
5952 }
59ffe07d
KS
5953 return Fnreverse (comp);
5954 }
5955
570d7624
JB
5956 /* Only other case actually used is ACTION = lambda */
5957#ifdef VMS
5958 /* Supposedly this helps commands such as `cd' that read directory names,
5959 but can someone explain how it helps them? -- RMS */
d5db4077 5960 if (SCHARS (name) == 0)
570d7624
JB
5961 return Qt;
5962#endif /* VMS */
59ffe07d
KS
5963 if (!NILP (Vread_file_name_predicate))
5964 return call1 (Vread_file_name_predicate, string);
570d7624
JB
5965 return Ffile_exists_p (string);
5966}
5967
59ffe07d 5968DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 6, 0,
8c1a1077
PJ
5969 doc: /* Read file name, prompting with PROMPT and completing in directory DIR.
5970Value is not expanded---you must call `expand-file-name' yourself.
5971Default name to DEFAULT-FILENAME if user enters a null string.
5972 (If DEFAULT-FILENAME is omitted, the visited file name is used,
5973 except that if INITIAL is specified, that combined with DIR is used.)
5974Fourth arg MUSTMATCH non-nil means require existing file's name.
5975 Non-nil and non-t means also require confirmation after completion.
5976Fifth arg INITIAL specifies text to start with.
59ffe07d
KS
5977If optional sixth arg PREDICATE is non-nil, possible completions and the
5978resulting file name must satisfy (funcall PREDICATE NAME).
8c1a1077
PJ
5979DIR defaults to current buffer's directory default.
5980
5981If this command was invoked with the mouse, use a file dialog box if
5982`use-dialog-box' is non-nil, and the window system or X toolkit in use
5983provides a file dialog box. */)
59ffe07d
KS
5984 (prompt, dir, default_filename, mustmatch, initial, predicate)
5985 Lisp_Object prompt, dir, default_filename, mustmatch, initial, predicate;
570d7624 5986{
8d6d9fef 5987 Lisp_Object val, insdef, tem;
570d7624
JB
5988 struct gcpro gcpro1, gcpro2;
5989 register char *homedir;
62f555a5
RS
5990 int replace_in_history = 0;
5991 int add_to_history = 0;
570d7624
JB
5992 int count;
5993
265a9e55 5994 if (NILP (dir))
570d7624 5995 dir = current_buffer->directory;
3b7f6e60 5996 if (NILP (default_filename))
3beeedfe
RS
5997 {
5998 if (! NILP (initial))
3b7f6e60 5999 default_filename = Fexpand_file_name (initial, dir);
3beeedfe 6000 else
3b7f6e60 6001 default_filename = current_buffer->filename;
3beeedfe 6002 }
570d7624
JB
6003
6004 /* If dir starts with user's homedir, change that to ~. */
6005 homedir = (char *) egetenv ("HOME");
199607e4 6006#ifdef DOS_NT
417c884a
EZ
6007 /* homedir can be NULL in temacs, since Vprocess_environment is not
6008 yet set up. We shouldn't crash in that case. */
6009 if (homedir != 0)
6010 {
6011 homedir = strcpy (alloca (strlen (homedir) + 1), homedir);
6012 CORRECT_DIR_SEPS (homedir);
6013 }
199607e4 6014#endif
570d7624 6015 if (homedir != 0
93c30b5f 6016 && STRINGP (dir)
d5db4077
KR
6017 && !strncmp (homedir, SDATA (dir), strlen (homedir))
6018 && IS_DIRECTORY_SEP (SDATA (dir)[strlen (homedir)]))
570d7624 6019 {
d5db4077
KR
6020 dir = make_string (SDATA (dir) + strlen (homedir) - 1,
6021 SBYTES (dir) - strlen (homedir) + 1);
6022 SREF (dir, 0) = '~';
570d7624 6023 }
8d6d9fef
AS
6024 /* Likewise for default_filename. */
6025 if (homedir != 0
6026 && STRINGP (default_filename)
d5db4077
KR
6027 && !strncmp (homedir, SDATA (default_filename), strlen (homedir))
6028 && IS_DIRECTORY_SEP (SDATA (default_filename)[strlen (homedir)]))
8d6d9fef
AS
6029 {
6030 default_filename
d5db4077
KR
6031 = make_string (SDATA (default_filename) + strlen (homedir) - 1,
6032 SBYTES (default_filename) - strlen (homedir) + 1);
6033 SREF (default_filename, 0) = '~';
8d6d9fef
AS
6034 }
6035 if (!NILP (default_filename))
b537a6c7 6036 {
b7826503 6037 CHECK_STRING (default_filename);
b537a6c7
RS
6038 default_filename = double_dollars (default_filename);
6039 }
570d7624 6040
58cc3710 6041 if (insert_default_directory && STRINGP (dir))
570d7624
JB
6042 {
6043 insdef = dir;
265a9e55 6044 if (!NILP (initial))
570d7624 6045 {
15c65264 6046 Lisp_Object args[2], pos;
570d7624
JB
6047
6048 args[0] = insdef;
6049 args[1] = initial;
6050 insdef = Fconcat (2, args);
d5db4077 6051 pos = make_number (SCHARS (double_dollars (dir)));
8d6d9fef 6052 insdef = Fcons (double_dollars (insdef), pos);
570d7624 6053 }
6e710ae5 6054 else
8d6d9fef 6055 insdef = double_dollars (insdef);
570d7624 6056 }
58cc3710 6057 else if (STRINGP (initial))
8d6d9fef 6058 insdef = Fcons (double_dollars (initial), make_number (0));
570d7624 6059 else
8d6d9fef 6060 insdef = Qnil;
570d7624 6061
59ffe07d
KS
6062 if (!NILP (Vread_file_name_function))
6063 {
6064 Lisp_Object args[7];
6065
6066 GCPRO2 (insdef, default_filename);
6067 args[0] = Vread_file_name_function;
6068 args[1] = prompt;
6069 args[2] = dir;
6070 args[3] = default_filename;
6071 args[4] = mustmatch;
6072 args[5] = initial;
6073 args[6] = predicate;
6074 RETURN_UNGCPRO (Ffuncall (7, args));
6075 }
6076
aed13378 6077 count = SPECPDL_INDEX ();
a79485af 6078#ifdef VMS
570d7624
JB
6079 specbind (intern ("completion-ignore-case"), Qt);
6080#endif
6081
a79485af 6082 specbind (intern ("minibuffer-completing-file-name"), Qt);
59ffe07d
KS
6083 specbind (intern ("read-file-name-predicate"),
6084 (NILP (predicate) ? Qfile_exists_p : predicate));
a79485af 6085
3b7f6e60 6086 GCPRO2 (insdef, default_filename);
9c856db9 6087
f73f57bd 6088#if defined (USE_MOTIF) || defined (HAVE_NTGUI)
9c856db9
GM
6089 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
6090 && use_dialog_box
6091 && have_menus_p ())
6092 {
9172b88d
GM
6093 /* If DIR contains a file name, split it. */
6094 Lisp_Object file;
6095 file = Ffile_name_nondirectory (dir);
d5db4077 6096 if (SCHARS (file) && NILP (default_filename))
9172b88d
GM
6097 {
6098 default_filename = file;
6099 dir = Ffile_name_directory (dir);
6100 }
f73f57bd
JR
6101 if (!NILP(default_filename))
6102 default_filename = Fexpand_file_name (default_filename, dir);
9c856db9
GM
6103 val = Fx_file_dialog (prompt, dir, default_filename, mustmatch);
6104 add_to_history = 1;
6105 }
6106 else
6107#endif
6108 val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
6109 dir, mustmatch, insdef,
6110 Qfile_name_history, default_filename, Qnil);
62f555a5
RS
6111
6112 tem = Fsymbol_value (Qfile_name_history);
03699b14 6113 if (CONSP (tem) && EQ (XCAR (tem), val))
62f555a5
RS
6114 replace_in_history = 1;
6115
6116 /* If Fcompleting_read returned the inserted default string itself
a8c828be
RS
6117 (rather than a new string with the same contents),
6118 it has to mean that the user typed RET with the minibuffer empty.
6119 In that case, we really want to return ""
6120 so that commands such as set-visited-file-name can distinguish. */
6121 if (EQ (val, default_filename))
62f555a5
RS
6122 {
6123 /* In this case, Fcompleting_read has not added an element
6124 to the history. Maybe we should. */
6125 if (! replace_in_history)
6126 add_to_history = 1;
6127
6128 val = build_string ("");
6129 }
570d7624 6130
570d7624 6131 unbind_to (count, Qnil);
570d7624 6132 UNGCPRO;
265a9e55 6133 if (NILP (val))
570d7624 6134 error ("No file name specified");
62f555a5 6135
8d6d9fef 6136 tem = Fstring_equal (val, CONSP (insdef) ? XCAR (insdef) : insdef);
62f555a5 6137
3b7f6e60 6138 if (!NILP (tem) && !NILP (default_filename))
62f555a5 6139 val = default_filename;
d5db4077 6140 else if (SCHARS (val) == 0 && NILP (insdef))
d9bc1c99 6141 {
3b7f6e60 6142 if (!NILP (default_filename))
62f555a5 6143 val = default_filename;
d9bc1c99
RS
6144 else
6145 error ("No default file name");
6146 }
62f555a5 6147 val = Fsubstitute_in_file_name (val);
570d7624 6148
62f555a5
RS
6149 if (replace_in_history)
6150 /* Replace what Fcompleting_read added to the history
6151 with what we will actually return. */
f3fbd155 6152 XSETCAR (Fsymbol_value (Qfile_name_history), double_dollars (val));
62f555a5 6153 else if (add_to_history)
570d7624 6154 {
62f555a5
RS
6155 /* Add the value to the history--but not if it matches
6156 the last value already there. */
8d6d9fef 6157 Lisp_Object val1 = double_dollars (val);
62f555a5 6158 tem = Fsymbol_value (Qfile_name_history);
03699b14 6159 if (! CONSP (tem) || NILP (Fequal (XCAR (tem), val1)))
62f555a5 6160 Fset (Qfile_name_history,
8d6d9fef 6161 Fcons (val1, tem));
570d7624 6162 }
9c856db9 6163
62f555a5 6164 return val;
570d7624 6165}
9c856db9 6166
570d7624 6167\f
dbda5089
GV
6168void
6169init_fileio_once ()
6170{
6171 /* Must be set before any path manipulation is performed. */
6172 XSETFASTINT (Vdirectory_sep_char, '/');
6173}
6174
9c856db9 6175\f
dfcf069d 6176void
570d7624
JB
6177syms_of_fileio ()
6178{
0bf2eed2 6179 Qexpand_file_name = intern ("expand-file-name");
273e0829 6180 Qsubstitute_in_file_name = intern ("substitute-in-file-name");
0bf2eed2
RS
6181 Qdirectory_file_name = intern ("directory-file-name");
6182 Qfile_name_directory = intern ("file-name-directory");
6183 Qfile_name_nondirectory = intern ("file-name-nondirectory");
642ef245 6184 Qunhandled_file_name_directory = intern ("unhandled-file-name-directory");
0bf2eed2 6185 Qfile_name_as_directory = intern ("file-name-as-directory");
32f4334d 6186 Qcopy_file = intern ("copy-file");
a6e6e718 6187 Qmake_directory_internal = intern ("make-directory-internal");
b272d624 6188 Qmake_directory = intern ("make-directory");
32f4334d
RS
6189 Qdelete_directory = intern ("delete-directory");
6190 Qdelete_file = intern ("delete-file");
6191 Qrename_file = intern ("rename-file");
6192 Qadd_name_to_file = intern ("add-name-to-file");
6193 Qmake_symbolic_link = intern ("make-symbolic-link");
6194 Qfile_exists_p = intern ("file-exists-p");
6195 Qfile_executable_p = intern ("file-executable-p");
6196 Qfile_readable_p = intern ("file-readable-p");
32f4334d 6197 Qfile_writable_p = intern ("file-writable-p");
1f8653eb
RS
6198 Qfile_symlink_p = intern ("file-symlink-p");
6199 Qaccess_file = intern ("access-file");
32f4334d 6200 Qfile_directory_p = intern ("file-directory-p");
adedc71d 6201 Qfile_regular_p = intern ("file-regular-p");
32f4334d
RS
6202 Qfile_accessible_directory_p = intern ("file-accessible-directory-p");
6203 Qfile_modes = intern ("file-modes");
6204 Qset_file_modes = intern ("set-file-modes");
6205 Qfile_newer_than_file_p = intern ("file-newer-than-file-p");
6206 Qinsert_file_contents = intern ("insert-file-contents");
6207 Qwrite_region = intern ("write-region");
6208 Qverify_visited_file_modtime = intern ("verify-visited-file-modtime");
3ec46acd 6209 Qset_visited_file_modtime = intern ("set-visited-file-modtime");
32f4334d 6210
642ef245 6211 staticpro (&Qexpand_file_name);
273e0829 6212 staticpro (&Qsubstitute_in_file_name);
642ef245
JB
6213 staticpro (&Qdirectory_file_name);
6214 staticpro (&Qfile_name_directory);
6215 staticpro (&Qfile_name_nondirectory);
6216 staticpro (&Qunhandled_file_name_directory);
6217 staticpro (&Qfile_name_as_directory);
15c65264 6218 staticpro (&Qcopy_file);
c34b559d 6219 staticpro (&Qmake_directory_internal);
b272d624 6220 staticpro (&Qmake_directory);
15c65264
RS
6221 staticpro (&Qdelete_directory);
6222 staticpro (&Qdelete_file);
6223 staticpro (&Qrename_file);
6224 staticpro (&Qadd_name_to_file);
6225 staticpro (&Qmake_symbolic_link);
6226 staticpro (&Qfile_exists_p);
6227 staticpro (&Qfile_executable_p);
6228 staticpro (&Qfile_readable_p);
15c65264 6229 staticpro (&Qfile_writable_p);
1f8653eb
RS
6230 staticpro (&Qaccess_file);
6231 staticpro (&Qfile_symlink_p);
15c65264 6232 staticpro (&Qfile_directory_p);
adedc71d 6233 staticpro (&Qfile_regular_p);
15c65264
RS
6234 staticpro (&Qfile_accessible_directory_p);
6235 staticpro (&Qfile_modes);
6236 staticpro (&Qset_file_modes);
6237 staticpro (&Qfile_newer_than_file_p);
6238 staticpro (&Qinsert_file_contents);
6239 staticpro (&Qwrite_region);
6240 staticpro (&Qverify_visited_file_modtime);
0a61794b 6241 staticpro (&Qset_visited_file_modtime);
642ef245
JB
6242
6243 Qfile_name_history = intern ("file-name-history");
6244 Fset (Qfile_name_history, Qnil);
15c65264
RS
6245 staticpro (&Qfile_name_history);
6246
570d7624
JB
6247 Qfile_error = intern ("file-error");
6248 staticpro (&Qfile_error);
199607e4 6249 Qfile_already_exists = intern ("file-already-exists");
570d7624 6250 staticpro (&Qfile_already_exists);
c0b7b21c
RS
6251 Qfile_date_error = intern ("file-date-error");
6252 staticpro (&Qfile_date_error);
505ab9bc
RS
6253 Qexcl = intern ("excl");
6254 staticpro (&Qexcl);
570d7624 6255
5e570b75 6256#ifdef DOS_NT
4c3c22f3
RS
6257 Qfind_buffer_file_type = intern ("find-buffer-file-type");
6258 staticpro (&Qfind_buffer_file_type);
5e570b75 6259#endif /* DOS_NT */
4c3c22f3 6260
b1d1b865 6261 DEFVAR_LISP ("file-name-coding-system", &Vfile_name_coding_system,
8c1a1077 6262 doc: /* *Coding system for encoding file names.
346ebf53 6263If it is nil, `default-file-name-coding-system' (which see) is used. */);
b1d1b865
RS
6264 Vfile_name_coding_system = Qnil;
6265
cd913586
KH
6266 DEFVAR_LISP ("default-file-name-coding-system",
6267 &Vdefault_file_name_coding_system,
8c1a1077 6268 doc: /* Default coding system for encoding file names.
346ebf53 6269This variable is used only when `file-name-coding-system' is nil.
8c1a1077 6270
346ebf53 6271This variable is set/changed by the command `set-language-environment'.
8c1a1077 6272User should not set this variable manually,
346ebf53 6273instead use `file-name-coding-system' to get a constant encoding
8c1a1077 6274of file names regardless of the current language environment. */);
cd913586
KH
6275 Vdefault_file_name_coding_system = Qnil;
6276
0d420e88 6277 DEFVAR_LISP ("auto-save-file-format", &Vauto_save_file_format,
8c1a1077
PJ
6278 doc: /* *Format in which to write auto-save files.
6279Should be a list of symbols naming formats that are defined in `format-alist'.
6280If it is t, which is the default, auto-save files are written in the
6281same format as a regular save would use. */);
0d420e88
BG
6282 Vauto_save_file_format = Qt;
6283
6284 Qformat_decode = intern ("format-decode");
6285 staticpro (&Qformat_decode);
6286 Qformat_annotate_function = intern ("format-annotate-function");
6287 staticpro (&Qformat_annotate_function);
6288
d6a3cc15
RS
6289 Qcar_less_than_car = intern ("car-less-than-car");
6290 staticpro (&Qcar_less_than_car);
6291
570d7624
JB
6292 Fput (Qfile_error, Qerror_conditions,
6293 Fcons (Qfile_error, Fcons (Qerror, Qnil)));
6294 Fput (Qfile_error, Qerror_message,
6295 build_string ("File error"));
6296
6297 Fput (Qfile_already_exists, Qerror_conditions,
6298 Fcons (Qfile_already_exists,
6299 Fcons (Qfile_error, Fcons (Qerror, Qnil))));
6300 Fput (Qfile_already_exists, Qerror_message,
6301 build_string ("File already exists"));
6302
c0b7b21c
RS
6303 Fput (Qfile_date_error, Qerror_conditions,
6304 Fcons (Qfile_date_error,
6305 Fcons (Qfile_error, Fcons (Qerror, Qnil))));
6306 Fput (Qfile_date_error, Qerror_message,
6307 build_string ("Cannot set file date"));
6308
59ffe07d
KS
6309 DEFVAR_LISP ("read-file-name-function", &Vread_file_name_function,
6310 doc: /* If this is non-nil, `read-file-name' does its work by calling this function. */);
6311 Vread_file_name_function = Qnil;
6312
6313 DEFVAR_LISP ("read-file-name-predicate", &Vread_file_name_predicate,
6314 doc: /* Current predicate used by `read-file-name-internal'. */);
6315 Vread_file_name_predicate = Qnil;
6316
570d7624 6317 DEFVAR_BOOL ("insert-default-directory", &insert_default_directory,
8c1a1077 6318 doc: /* *Non-nil means when reading a filename start with default dir in minibuffer. */);
570d7624
JB
6319 insert_default_directory = 1;
6320
6321 DEFVAR_BOOL ("vms-stmlf-recfm", &vms_stmlf_recfm,
8c1a1077
PJ
6322 doc: /* *Non-nil means write new files with record format `stmlf'.
6323nil means use format `var'. This variable is meaningful only on VMS. */);
570d7624
JB
6324 vms_stmlf_recfm = 0;
6325
199607e4 6326 DEFVAR_LISP ("directory-sep-char", &Vdirectory_sep_char,
8c1a1077
PJ
6327 doc: /* Directory separator character for built-in functions that return file names.
6328The value should be either ?/ or ?\\ (any other value is treated as ?\\).
6329This variable affects the built-in functions only on Windows,
6330on other platforms, it is initialized so that Lisp code can find out
6331what the normal separator is.
6332
6333WARNING: This variable is deprecated and will be removed in the near
6334future. DO NOT USE IT. */);
199607e4 6335
1d1826db 6336 DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist,
8c1a1077
PJ
6337 doc: /* *Alist of elements (REGEXP . HANDLER) for file names handled specially.
6338If a file name matches REGEXP, then all I/O on that file is done by calling
6339HANDLER.
6340
6341The first argument given to HANDLER is the name of the I/O primitive
6342to be handled; the remaining arguments are the arguments that were
6343passed to that primitive. For example, if you do
6344 (file-exists-p FILENAME)
6345and FILENAME is handled by HANDLER, then HANDLER is called like this:
6346 (funcall HANDLER 'file-exists-p FILENAME)
6347The function `find-file-name-handler' checks this list for a handler
6348for its argument. */);
09121adc
RS
6349 Vfile_name_handler_alist = Qnil;
6350
0414b394
KH
6351 DEFVAR_LISP ("set-auto-coding-function",
6352 &Vset_auto_coding_function,
8c1a1077
PJ
6353 doc: /* If non-nil, a function to call to decide a coding system of file.
6354Two arguments are passed to this function: the file name
6355and the length of a file contents following the point.
6356This function should return a coding system to decode the file contents.
6357It should check the file name against `auto-coding-alist'.
6358If no coding system is decided, it should check a coding system
6359specified in the heading lines with the format:
6360 -*- ... coding: CODING-SYSTEM; ... -*-
6361or local variable spec of the tailing lines with `coding:' tag. */);
0414b394 6362 Vset_auto_coding_function = Qnil;
c9e82392 6363
d6a3cc15 6364 DEFVAR_LISP ("after-insert-file-functions", &Vafter_insert_file_functions,
8c1a1077
PJ
6365 doc: /* A list of functions to be called at the end of `insert-file-contents'.
6366Each is passed one argument, the number of bytes inserted. It should return
6367the new byte count, and leave point the same. If `insert-file-contents' is
6368intercepted by a handler from `file-name-handler-alist', that handler is
6369responsible for calling the after-insert-file-functions if appropriate. */);
d6a3cc15
RS
6370 Vafter_insert_file_functions = Qnil;
6371
6372 DEFVAR_LISP ("write-region-annotate-functions", &Vwrite_region_annotate_functions,
8c1a1077
PJ
6373 doc: /* A list of functions to be called at the start of `write-region'.
6374Each is passed two arguments, START and END as for `write-region'.
6375These are usually two numbers but not always; see the documentation
6376for `write-region'. The function should return a list of pairs
6377of the form (POSITION . STRING), consisting of strings to be effectively
6378inserted at the specified positions of the file being written (1 means to
6379insert before the first byte written). The POSITIONs must be sorted into
6380increasing order. If there are several functions in the list, the several
28c3eb5a
SM
6381lists are merged destructively. Alternatively, the function can return
6382with a different buffer current and value nil.*/);
d6a3cc15
RS
6383 Vwrite_region_annotate_functions = Qnil;
6384
6fc6f94b
RS
6385 DEFVAR_LISP ("write-region-annotations-so-far",
6386 &Vwrite_region_annotations_so_far,
8c1a1077
PJ
6387 doc: /* When an annotation function is called, this holds the previous annotations.
6388These are the annotations made by other annotation functions
6389that were already called. See also `write-region-annotate-functions'. */);
6fc6f94b
RS
6390 Vwrite_region_annotations_so_far = Qnil;
6391
82c2d839 6392 DEFVAR_LISP ("inhibit-file-name-handlers", &Vinhibit_file_name_handlers,
8c1a1077
PJ
6393 doc: /* A list of file name handlers that temporarily should not be used.
6394This applies only to the operation `inhibit-file-name-operation'. */);
82c2d839
RS
6395 Vinhibit_file_name_handlers = Qnil;
6396
a65970a0 6397 DEFVAR_LISP ("inhibit-file-name-operation", &Vinhibit_file_name_operation,
8c1a1077 6398 doc: /* The operation for which `inhibit-file-name-handlers' is applicable. */);
a65970a0
RS
6399 Vinhibit_file_name_operation = Qnil;
6400
e54d3b5d 6401 DEFVAR_LISP ("auto-save-list-file-name", &Vauto_save_list_file_name,
8c1a1077
PJ
6402 doc: /* File name in which we write a list of all auto save file names.
6403This variable is initialized automatically from `auto-save-list-file-prefix'
6404shortly after Emacs reads your `.emacs' file, if you have not yet given it
6405a non-nil value. */);
e54d3b5d
RS
6406 Vauto_save_list_file_name = Qnil;
6407
642ef245 6408 defsubr (&Sfind_file_name_handler);
570d7624
JB
6409 defsubr (&Sfile_name_directory);
6410 defsubr (&Sfile_name_nondirectory);
642ef245 6411 defsubr (&Sunhandled_file_name_directory);
570d7624
JB
6412 defsubr (&Sfile_name_as_directory);
6413 defsubr (&Sdirectory_file_name);
6414 defsubr (&Smake_temp_name);
6415 defsubr (&Sexpand_file_name);
6416 defsubr (&Ssubstitute_in_file_name);
6417 defsubr (&Scopy_file);
9bbe01fb 6418 defsubr (&Smake_directory_internal);
aa734e17 6419 defsubr (&Sdelete_directory);
570d7624
JB
6420 defsubr (&Sdelete_file);
6421 defsubr (&Srename_file);
6422 defsubr (&Sadd_name_to_file);
6423#ifdef S_IFLNK
6424 defsubr (&Smake_symbolic_link);
6425#endif /* S_IFLNK */
6426#ifdef VMS
6427 defsubr (&Sdefine_logical_name);
6428#endif /* VMS */
6429#ifdef HPUX_NET
6430 defsubr (&Ssysnetunam);
6431#endif /* HPUX_NET */
6432 defsubr (&Sfile_name_absolute_p);
6433 defsubr (&Sfile_exists_p);
6434 defsubr (&Sfile_executable_p);
6435 defsubr (&Sfile_readable_p);
6436 defsubr (&Sfile_writable_p);
1f8653eb 6437 defsubr (&Saccess_file);
570d7624
JB
6438 defsubr (&Sfile_symlink_p);
6439 defsubr (&Sfile_directory_p);
b72dea2a 6440 defsubr (&Sfile_accessible_directory_p);
f793dc6c 6441 defsubr (&Sfile_regular_p);
570d7624
JB
6442 defsubr (&Sfile_modes);
6443 defsubr (&Sset_file_modes);
c24e9a53
RS
6444 defsubr (&Sset_default_file_modes);
6445 defsubr (&Sdefault_file_modes);
570d7624
JB
6446 defsubr (&Sfile_newer_than_file_p);
6447 defsubr (&Sinsert_file_contents);
6448 defsubr (&Swrite_region);
d6a3cc15 6449 defsubr (&Scar_less_than_car);
570d7624
JB
6450 defsubr (&Sverify_visited_file_modtime);
6451 defsubr (&Sclear_visited_file_modtime);
f5d5eccf 6452 defsubr (&Svisited_file_modtime);
570d7624
JB
6453 defsubr (&Sset_visited_file_modtime);
6454 defsubr (&Sdo_auto_save);
6455 defsubr (&Sset_buffer_auto_saved);
b60247d9 6456 defsubr (&Sclear_buffer_auto_save_failure);
570d7624
JB
6457 defsubr (&Srecent_auto_save_p);
6458
6459 defsubr (&Sread_file_name_internal);
6460 defsubr (&Sread_file_name);
85ffea93 6461
483a2e10 6462#ifdef unix
85ffea93 6463 defsubr (&Sunix_sync);
483a2e10 6464#endif
570d7624 6465}
71e1147d 6466