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