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