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