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