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