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