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