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