(CHECK_FRAME, CHECK_LIVE_FRAME): Remove unused argument `i' in macros.
[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
e4432095
JB
341 CHECK_STRING (filename, 0);
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
3b7f6e60 387 CHECK_STRING (filename, 0);
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
3b7f6e60 462 CHECK_STRING (filename, 0);
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
JB
616
617 CHECK_STRING (file, 0);
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
JB
807
808 CHECK_STRING (directory, 0);
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
3ce839e4
RS
873 CHECK_STRING (prefix, 0);
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
570d7624
JB
1022 CHECK_STRING (name, 0);
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
1689 CHECK_STRING (name, 0);
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;
1865 CHECK_STRING (defalt, 1);
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
3b7f6e60 2007 CHECK_STRING (filename, 0);
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);
3b7f6e60 2321 CHECK_STRING (file, 0);
570d7624 2322 CHECK_STRING (newname, 1);
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
3b7f6e60
EN
2475 CHECK_STRING (directory, 0);
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
3b7f6e60
EN
2505 CHECK_STRING (directory, 0);
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
570d7624
JB
2531 CHECK_STRING (filename, 0);
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);
3b7f6e60 2582 CHECK_STRING (file, 0);
570d7624 2583 CHECK_STRING (newname, 1);
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;
3b7f6e60 2658 CHECK_STRING (file, 0);
570d7624 2659 CHECK_STRING (newname, 1);
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;
570d7624 2721 CHECK_STRING (filename, 0);
e5d77022 2722 CHECK_STRING (linkname, 1);
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{
3b7f6e60 2789 CHECK_STRING (name, 0);
265a9e55 2790 if (NILP (string))
3b7f6e60 2791 delete_logical_name (XSTRING (name)->data);
570d7624
JB
2792 else
2793 {
2794 CHECK_STRING (string, 1);
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
570d7624 2815 CHECK_STRING (path, 0);
199607e4
RS
2816 CHECK_STRING (login, 0);
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
2836 CHECK_STRING (filename, 0);
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
JB
2922
2923 CHECK_STRING (filename, 0);
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
JB
2945
2946 CHECK_STRING (filename, 0);
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
JB
2971
2972 CHECK_STRING (filename, 0);
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
3020 CHECK_STRING (filename, 0);
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
3068 CHECK_STRING (filename, 0);
49475635
EZ
3069 absname = Fexpand_file_name (filename, Qnil);
3070
a79485af 3071 CHECK_STRING (string, 1);
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
JB
3102
3103 CHECK_STRING (filename, 0);
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,
8c1a1077
PJ
3178 doc: /* Return t if file FILENAME is the name of a directory as a file,
3179and files in that directory can be opened by you. In order to use a
3180directory as a buffer's current directory, this predicate must return true.
3181A directory name spec may be given instead; then the value is t
3182if the directory so specified exists and really is a readable and
3183searchable directory. */)
3184 (filename)
b72dea2a
JB
3185 Lisp_Object filename;
3186{
32f4334d 3187 Lisp_Object handler;
1a04498e 3188 int tem;
d26859eb 3189 struct gcpro gcpro1;
32f4334d
RS
3190
3191 /* If the file name has special constructs in it,
3192 call the corresponding file handler. */
49307295 3193 handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p);
32f4334d
RS
3194 if (!NILP (handler))
3195 return call2 (handler, Qfile_accessible_directory_p, filename);
3196
d26859eb
KH
3197 /* It's an unlikely combination, but yes we really do need to gcpro:
3198 Suppose that file-accessible-directory-p has no handler, but
3199 file-directory-p does have a handler; this handler causes a GC which
3200 relocates the string in `filename'; and finally file-directory-p
3201 returns non-nil. Then we would end up passing a garbaged string
3202 to file-executable-p. */
3203 GCPRO1 (filename);
1a04498e
KH
3204 tem = (NILP (Ffile_directory_p (filename))
3205 || NILP (Ffile_executable_p (filename)));
d26859eb 3206 UNGCPRO;
1a04498e 3207 return tem ? Qnil : Qt;
b72dea2a
JB
3208}
3209
f793dc6c 3210DEFUN ("file-regular-p", Ffile_regular_p, Sfile_regular_p, 1, 1, 0,
8c1a1077
PJ
3211 doc: /* Return t if file FILENAME is the name of a regular file.
3212This is the sort of file that holds an ordinary stream of data bytes. */)
3213 (filename)
f793dc6c
RS
3214 Lisp_Object filename;
3215{
199607e4 3216 register Lisp_Object absname;
f793dc6c
RS
3217 struct stat st;
3218 Lisp_Object handler;
3219
199607e4 3220 absname = expand_and_dir_to_file (filename, current_buffer->directory);
f793dc6c
RS
3221
3222 /* If the file name has special constructs in it,
3223 call the corresponding file handler. */
199607e4 3224 handler = Ffind_file_name_handler (absname, Qfile_regular_p);
f793dc6c 3225 if (!NILP (handler))
199607e4 3226 return call2 (handler, Qfile_regular_p, absname);
f793dc6c 3227
b1d1b865
RS
3228 absname = ENCODE_FILE (absname);
3229
c1c4693e
RS
3230#ifdef WINDOWSNT
3231 {
3232 int result;
3233 Lisp_Object tem = Vw32_get_true_file_attributes;
3234
3235 /* Tell stat to use expensive method to get accurate info. */
3236 Vw32_get_true_file_attributes = Qt;
3237 result = stat (XSTRING (absname)->data, &st);
3238 Vw32_get_true_file_attributes = tem;
3239
3240 if (result < 0)
3241 return Qnil;
3242 return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
3243 }
3244#else
4cd8344a 3245 if (stat (XSTRING (absname)->data, &st) < 0)
f793dc6c
RS
3246 return Qnil;
3247 return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
c1c4693e 3248#endif
f793dc6c
RS
3249}
3250\f
570d7624 3251DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
8c1a1077
PJ
3252 doc: /* Return mode bits of file named FILENAME, as an integer. */)
3253 (filename)
570d7624
JB
3254 Lisp_Object filename;
3255{
199607e4 3256 Lisp_Object absname;
570d7624 3257 struct stat st;
32f4334d 3258 Lisp_Object handler;
570d7624 3259
199607e4 3260 absname = expand_and_dir_to_file (filename, current_buffer->directory);
570d7624 3261
32f4334d
RS
3262 /* If the file name has special constructs in it,
3263 call the corresponding file handler. */
199607e4 3264 handler = Ffind_file_name_handler (absname, Qfile_modes);
32f4334d 3265 if (!NILP (handler))
199607e4 3266 return call2 (handler, Qfile_modes, absname);
32f4334d 3267
b1d1b865
RS
3268 absname = ENCODE_FILE (absname);
3269
199607e4 3270 if (stat (XSTRING (absname)->data, &st) < 0)
570d7624 3271 return Qnil;
34ead71a 3272#if defined (MSDOS) && __DJGPP__ < 2
199607e4 3273 if (check_executable (XSTRING (absname)->data))
3be3c08e 3274 st.st_mode |= S_IEXEC;
34ead71a 3275#endif /* MSDOS && __DJGPP__ < 2 */
3ace87e3 3276
570d7624
JB
3277 return make_number (st.st_mode & 07777);
3278}
3279
3280DEFUN ("set-file-modes", Fset_file_modes, Sset_file_modes, 2, 2, 0,
8c1a1077
PJ
3281 doc: /* Set mode bits of file named FILENAME to MODE (an integer).
3282Only the 12 low bits of MODE are used. */)
570d7624
JB
3283 (filename, mode)
3284 Lisp_Object filename, mode;
3285{
b1d1b865 3286 Lisp_Object absname, encoded_absname;
32f4334d 3287 Lisp_Object handler;
570d7624 3288
199607e4 3289 absname = Fexpand_file_name (filename, current_buffer->directory);
570d7624
JB
3290 CHECK_NUMBER (mode, 1);
3291
32f4334d
RS
3292 /* If the file name has special constructs in it,
3293 call the corresponding file handler. */
199607e4 3294 handler = Ffind_file_name_handler (absname, Qset_file_modes);
32f4334d 3295 if (!NILP (handler))
199607e4 3296 return call3 (handler, Qset_file_modes, absname, mode);
32f4334d 3297
b1d1b865
RS
3298 encoded_absname = ENCODE_FILE (absname);
3299
3300 if (chmod (XSTRING (encoded_absname)->data, XINT (mode)) < 0)
199607e4 3301 report_file_error ("Doing chmod", Fcons (absname, Qnil));
570d7624
JB
3302
3303 return Qnil;
3304}
3305
c24e9a53 3306DEFUN ("set-default-file-modes", Fset_default_file_modes, Sset_default_file_modes, 1, 1, 0,
8c1a1077
PJ
3307 doc: /* Set the file permission bits for newly created files.
3308The argument MODE should be an integer; only the low 9 bits are used.
3309This setting is inherited by subprocesses. */)
3310 (mode)
5f85ea58 3311 Lisp_Object mode;
36a8c287 3312{
5f85ea58 3313 CHECK_NUMBER (mode, 0);
199607e4 3314
5f85ea58 3315 umask ((~ XINT (mode)) & 0777);
36a8c287
JB
3316
3317 return Qnil;
3318}
3319
c24e9a53 3320DEFUN ("default-file-modes", Fdefault_file_modes, Sdefault_file_modes, 0, 0, 0,
8c1a1077
PJ
3321 doc: /* Return the default file protection for created files.
3322The value is an integer. */)
3323 ()
36a8c287 3324{
5f85ea58
RS
3325 int realmask;
3326 Lisp_Object value;
36a8c287 3327
5f85ea58
RS
3328 realmask = umask (0);
3329 umask (realmask);
36a8c287 3330
46283abe 3331 XSETINT (value, (~ realmask) & 0777);
5f85ea58 3332 return value;
36a8c287 3333}
5df5e07c 3334
f793dc6c 3335\f
5df5e07c
GM
3336#ifdef __NetBSD__
3337#define unix 42
3338#endif
85ffea93 3339
5df5e07c 3340#ifdef unix
85ffea93 3341DEFUN ("unix-sync", Funix_sync, Sunix_sync, 0, 0, "",
8c1a1077
PJ
3342 doc: /* Tell Unix to finish all pending disk updates. */)
3343 ()
85ffea93
RS
3344{
3345 sync ();
3346 return Qnil;
3347}
3348
3349#endif /* unix */
3350
570d7624 3351DEFUN ("file-newer-than-file-p", Ffile_newer_than_file_p, Sfile_newer_than_file_p, 2, 2, 0,
8c1a1077
PJ
3352 doc: /* Return t if file FILE1 is newer than file FILE2.
3353If FILE1 does not exist, the answer is nil;
3354otherwise, if FILE2 does not exist, the answer is t. */)
3355 (file1, file2)
570d7624
JB
3356 Lisp_Object file1, file2;
3357{
199607e4 3358 Lisp_Object absname1, absname2;
570d7624
JB
3359 struct stat st;
3360 int mtime1;
32f4334d 3361 Lisp_Object handler;
09121adc 3362 struct gcpro gcpro1, gcpro2;
570d7624
JB
3363
3364 CHECK_STRING (file1, 0);
3365 CHECK_STRING (file2, 0);
3366
199607e4
RS
3367 absname1 = Qnil;
3368 GCPRO2 (absname1, file2);
3369 absname1 = expand_and_dir_to_file (file1, current_buffer->directory);
3370 absname2 = expand_and_dir_to_file (file2, current_buffer->directory);
09121adc 3371 UNGCPRO;
570d7624 3372
32f4334d
RS
3373 /* If the file name has special constructs in it,
3374 call the corresponding file handler. */
199607e4 3375 handler = Ffind_file_name_handler (absname1, Qfile_newer_than_file_p);
51cf6d37 3376 if (NILP (handler))
199607e4 3377 handler = Ffind_file_name_handler (absname2, Qfile_newer_than_file_p);
32f4334d 3378 if (!NILP (handler))
199607e4 3379 return call3 (handler, Qfile_newer_than_file_p, absname1, absname2);
32f4334d 3380
b1d1b865
RS
3381 GCPRO2 (absname1, absname2);
3382 absname1 = ENCODE_FILE (absname1);
3383 absname2 = ENCODE_FILE (absname2);
3384 UNGCPRO;
3385
199607e4 3386 if (stat (XSTRING (absname1)->data, &st) < 0)
570d7624
JB
3387 return Qnil;
3388
3389 mtime1 = st.st_mtime;
3390
199607e4 3391 if (stat (XSTRING (absname2)->data, &st) < 0)
570d7624
JB
3392 return Qt;
3393
3394 return (mtime1 > st.st_mtime) ? Qt : Qnil;
3395}
3396\f
5e570b75 3397#ifdef DOS_NT
4c3c22f3 3398Lisp_Object Qfind_buffer_file_type;
5e570b75 3399#endif /* DOS_NT */
4c3c22f3 3400
6fdaa9a0
KH
3401#ifndef READ_BUF_SIZE
3402#define READ_BUF_SIZE (64 << 10)
3403#endif
3404
98a7d268
KH
3405extern void adjust_markers_for_delete P_ ((int, int, int, int));
3406
3407/* This function is called after Lisp functions to decide a coding
3408 system are called, or when they cause an error. Before they are
3409 called, the current buffer is set unibyte and it contains only a
3410 newly inserted text (thus the buffer was empty before the
3411 insertion).
3412
3413 The functions may set markers, overlays, text properties, or even
3414 alter the buffer contents, change the current buffer.
3415
3416 Here, we reset all those changes by:
3417 o set back the current buffer.
3418 o move all markers and overlays to BEG.
3419 o remove all text properties.
3420 o set back the buffer multibyteness. */
f736ffbf
KH
3421
3422static Lisp_Object
98a7d268
KH
3423decide_coding_unwind (unwind_data)
3424 Lisp_Object unwind_data;
f736ffbf 3425{
98a7d268 3426 Lisp_Object multibyte, undo_list, buffer;
f736ffbf 3427
98a7d268
KH
3428 multibyte = XCAR (unwind_data);
3429 unwind_data = XCDR (unwind_data);
3430 undo_list = XCAR (unwind_data);
3431 buffer = XCDR (unwind_data);
3432
3433 if (current_buffer != XBUFFER (buffer))
3434 set_buffer_internal (XBUFFER (buffer));
3435 adjust_markers_for_delete (BEG, BEG_BYTE, Z, Z_BYTE);
3436 adjust_overlays_for_delete (BEG, Z - BEG);
3437 BUF_INTERVALS (current_buffer) = 0;
3438 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
3439
3440 /* Now we are safe to change the buffer's multibyteness directly. */
3441 current_buffer->enable_multibyte_characters = multibyte;
3442 current_buffer->undo_list = undo_list;
f736ffbf
KH
3443
3444 return Qnil;
3445}
3446
55587f8a 3447
1b978129 3448/* Used to pass values from insert-file-contents to read_non_regular. */
55587f8a 3449
1b978129
GM
3450static int non_regular_fd;
3451static int non_regular_inserted;
3452static int non_regular_nbytes;
55587f8a 3453
55587f8a 3454
1b978129
GM
3455/* Read from a non-regular file.
3456 Read non_regular_trytry bytes max from non_regular_fd.
3457 Non_regular_inserted specifies where to put the read bytes.
3458 Value is the number of bytes read. */
55587f8a
GM
3459
3460static Lisp_Object
1b978129 3461read_non_regular ()
55587f8a 3462{
1b978129
GM
3463 int nbytes;
3464
3465 immediate_quit = 1;
3466 QUIT;
3467 nbytes = emacs_read (non_regular_fd,
3468 BEG_ADDR + PT_BYTE - 1 + non_regular_inserted,
3469 non_regular_nbytes);
3470 Fsignal (Qquit, Qnil);
3471 immediate_quit = 0;
3472 return make_number (nbytes);
3473}
55587f8a 3474
d0e2444e 3475
1b978129
GM
3476/* Condition-case handler used when reading from non-regular files
3477 in insert-file-contents. */
3478
3479static Lisp_Object
3480read_non_regular_quit ()
3481{
55587f8a
GM
3482 return Qnil;
3483}
3484
3485
570d7624 3486DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
8c1a1077
PJ
3487 1, 5, 0,
3488 doc: /* Insert contents of file FILENAME after point.
3489Returns list of absolute file name and number of bytes inserted.
3490If second argument VISIT is non-nil, the buffer's visited filename
3491and last save file modtime are set, and it is marked unmodified.
3492If visiting and the file does not exist, visiting is completed
3493before the error is signaled.
3494The optional third and fourth arguments BEG and END
3495specify what portion of the file to insert.
3496These arguments count bytes in the file, not characters in the buffer.
3497If VISIT is non-nil, BEG and END must be nil.
3498
3499If optional fifth argument REPLACE is non-nil,
3500it means replace the current buffer contents (in the accessible portion)
3501with the file contents. This is better than simply deleting and inserting
3502the whole thing because (1) it preserves some marker positions
3503and (2) it puts less data in the undo list.
3504When REPLACE is non-nil, the value is the number of characters actually read,
3505which is often less than the number of characters to be read.
3506
3507This does code conversion according to the value of
3508`coding-system-for-read' or `file-coding-system-alist',
3509and sets the variable `last-coding-system-used' to the coding system
3510actually used. */)
3511 (filename, visit, beg, end, replace)
3d0387c0 3512 Lisp_Object filename, visit, beg, end, replace;
570d7624
JB
3513{
3514 struct stat st;
3515 register int fd;
ec7adf26 3516 int inserted = 0;
570d7624 3517 register int how_much;
6fdaa9a0 3518 register int unprocessed;
ed8e506f 3519 int count = BINDING_STACK_SIZE ();
b1d1b865
RS
3520 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3521 Lisp_Object handler, val, insval, orig_filename;
d6a3cc15 3522 Lisp_Object p;
6bbd7a29 3523 int total = 0;
53c34c46 3524 int not_regular = 0;
feb9dc27 3525 unsigned char read_buf[READ_BUF_SIZE];
6fdaa9a0 3526 struct coding_system coding;
3dbcf3f6 3527 unsigned char buffer[1 << 14];
727a0b4a 3528 int replace_handled = 0;
ec7adf26 3529 int set_coding_system = 0;
f736ffbf 3530 int coding_system_decided = 0;
1b978129 3531 int read_quit = 0;
32f4334d 3532
95385625
RS
3533 if (current_buffer->base_buffer && ! NILP (visit))
3534 error ("Cannot do file visiting in an indirect buffer");
3535
3536 if (!NILP (current_buffer->read_only))
3537 Fbarf_if_buffer_read_only ();
3538
32f4334d 3539 val = Qnil;
d6a3cc15 3540 p = Qnil;
b1d1b865 3541 orig_filename = Qnil;
32f4334d 3542
b1d1b865 3543 GCPRO4 (filename, val, p, orig_filename);
570d7624
JB
3544
3545 CHECK_STRING (filename, 0);
3546 filename = Fexpand_file_name (filename, Qnil);
3547
32f4334d
RS
3548 /* If the file name has special constructs in it,
3549 call the corresponding file handler. */
49307295 3550 handler = Ffind_file_name_handler (filename, Qinsert_file_contents);
32f4334d
RS
3551 if (!NILP (handler))
3552 {
3d0387c0
RS
3553 val = call6 (handler, Qinsert_file_contents, filename,
3554 visit, beg, end, replace);
03699b14
KR
3555 if (CONSP (val) && CONSP (XCDR (val)))
3556 inserted = XINT (XCAR (XCDR (val)));
32f4334d
RS
3557 goto handled;
3558 }
3559
b1d1b865
RS
3560 orig_filename = filename;
3561 filename = ENCODE_FILE (filename);
3562
570d7624
JB
3563 fd = -1;
3564
c1c4693e
RS
3565#ifdef WINDOWSNT
3566 {
3567 Lisp_Object tem = Vw32_get_true_file_attributes;
3568
3569 /* Tell stat to use expensive method to get accurate info. */
3570 Vw32_get_true_file_attributes = Qt;
3571 total = stat (XSTRING (filename)->data, &st);
3572 Vw32_get_true_file_attributes = tem;
3573 }
3574 if (total < 0)
3575#else
570d7624 3576#ifndef APOLLO
99bc28f4 3577 if (stat (XSTRING (filename)->data, &st) < 0)
570d7624 3578#else
68c45bf0 3579 if ((fd = emacs_open (XSTRING (filename)->data, O_RDONLY, 0)) < 0
570d7624
JB
3580 || fstat (fd, &st) < 0)
3581#endif /* not APOLLO */
c1c4693e 3582#endif /* WINDOWSNT */
570d7624 3583 {
68c45bf0 3584 if (fd >= 0) emacs_close (fd);
99bc28f4 3585 badopen:
265a9e55 3586 if (NILP (visit))
b1d1b865 3587 report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
570d7624
JB
3588 st.st_mtime = -1;
3589 how_much = 0;
0de6b8f4 3590 if (!NILP (Vcoding_system_for_read))
22d92d6b 3591 Fset (Qbuffer_file_coding_system, Vcoding_system_for_read);
570d7624
JB
3592 goto notfound;
3593 }
3594
99bc28f4 3595#ifdef S_IFREG
be53b411
JB
3596 /* This code will need to be changed in order to work on named
3597 pipes, and it's probably just not worth it. So we should at
3598 least signal an error. */
99bc28f4 3599 if (!S_ISREG (st.st_mode))
330bfe57 3600 {
d4b8687b
RS
3601 not_regular = 1;
3602
3603 if (! NILP (visit))
3604 goto notfound;
3605
3606 if (! NILP (replace) || ! NILP (beg) || ! NILP (end))
330bfe57
RS
3607 Fsignal (Qfile_error,
3608 Fcons (build_string ("not a regular file"),
b1d1b865 3609 Fcons (orig_filename, Qnil)));
330bfe57 3610 }
be53b411
JB
3611#endif
3612
99bc28f4 3613 if (fd < 0)
68c45bf0 3614 if ((fd = emacs_open (XSTRING (filename)->data, O_RDONLY, 0)) < 0)
99bc28f4
KH
3615 goto badopen;
3616
3617 /* Replacement should preserve point as it preserves markers. */
3618 if (!NILP (replace))
3619 record_unwind_protect (restore_point_unwind, Fpoint_marker ());
3620
3621 record_unwind_protect (close_file_unwind, make_number (fd));
3622
570d7624 3623 /* Supposedly happens on VMS. */
d4b8687b 3624 if (! not_regular && st.st_size < 0)
570d7624 3625 error ("File size is negative");
be53b411 3626
9c856db9
GM
3627 /* Prevent redisplay optimizations. */
3628 current_buffer->clip_changed = 1;
3629
9f57b6b4
KH
3630 if (!NILP (visit))
3631 {
3632 if (!NILP (beg) || !NILP (end))
3633 error ("Attempt to visit less than an entire file");
3634 if (BEG < Z && NILP (replace))
3635 error ("Cannot do file visiting in a non-empty buffer");
3636 }
7fded690
JB
3637
3638 if (!NILP (beg))
3639 CHECK_NUMBER (beg, 0);
3640 else
2acfd7ae 3641 XSETFASTINT (beg, 0);
7fded690
JB
3642
3643 if (!NILP (end))
3644 CHECK_NUMBER (end, 0);
3645 else
3646 {
d4b8687b
RS
3647 if (! not_regular)
3648 {
3649 XSETINT (end, st.st_size);
68c45bf0
PE
3650
3651 /* Arithmetic overflow can occur if an Emacs integer cannot
3652 represent the file size, or if the calculations below
3653 overflow. The calculations below double the file size
3654 twice, so check that it can be multiplied by 4 safely. */
3655 if (XINT (end) != st.st_size
3656 || ((int) st.st_size * 4) / 4 != st.st_size)
d4b8687b 3657 error ("Maximum buffer size exceeded");
d21dd12d
GM
3658
3659 /* The file size returned from stat may be zero, but data
3660 may be readable nonetheless, for example when this is a
3661 file in the /proc filesystem. */
3662 if (st.st_size == 0)
3663 XSETINT (end, READ_BUF_SIZE);
d4b8687b 3664 }
7fded690
JB
3665 }
3666
f736ffbf
KH
3667 if (BEG < Z)
3668 {
3669 /* Decide the coding system to use for reading the file now
3670 because we can't use an optimized method for handling
3671 `coding:' tag if the current buffer is not empty. */
3672 Lisp_Object val;
3673 val = Qnil;
feb9dc27 3674
f736ffbf
KH
3675 if (!NILP (Vcoding_system_for_read))
3676 val = Vcoding_system_for_read;
3677 else if (! NILP (replace))
3678 /* In REPLACE mode, we can use the same coding system
3679 that was used to visit the file. */
3680 val = current_buffer->buffer_file_coding_system;
3681 else
3682 {
3683 /* Don't try looking inside a file for a coding system
3684 specification if it is not seekable. */
3685 if (! not_regular && ! NILP (Vset_auto_coding_function))
3686 {
3687 /* Find a coding system specified in the heading two
3688 lines or in the tailing several lines of the file.
3689 We assume that the 1K-byte and 3K-byte for heading
003a7eaa 3690 and tailing respectively are sufficient for this
f736ffbf 3691 purpose. */
07590973 3692 int nread;
f736ffbf
KH
3693
3694 if (st.st_size <= (1024 * 4))
68c45bf0 3695 nread = emacs_read (fd, read_buf, 1024 * 4);
f736ffbf
KH
3696 else
3697 {
68c45bf0 3698 nread = emacs_read (fd, read_buf, 1024);
f736ffbf
KH
3699 if (nread >= 0)
3700 {
3701 if (lseek (fd, st.st_size - (1024 * 3), 0) < 0)
3702 report_file_error ("Setting file position",
3703 Fcons (orig_filename, Qnil));
68c45bf0 3704 nread += emacs_read (fd, read_buf + nread, 1024 * 3);
f736ffbf
KH
3705 }
3706 }
feb9dc27 3707
f736ffbf
KH
3708 if (nread < 0)
3709 error ("IO error reading %s: %s",
68c45bf0 3710 XSTRING (orig_filename)->data, emacs_strerror (errno));
f736ffbf
KH
3711 else if (nread > 0)
3712 {
f736ffbf 3713 struct buffer *prev = current_buffer;
1d92afcd 3714 int count1;
f736ffbf
KH
3715
3716 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
1d92afcd
GM
3717
3718 /* The call to temp_output_buffer_setup binds
3719 standard-output. */
3720 count1 = specpdl_ptr - specpdl;
f736ffbf 3721 temp_output_buffer_setup (" *code-converting-work*");
1d92afcd 3722
f736ffbf
KH
3723 set_buffer_internal (XBUFFER (Vstandard_output));
3724 current_buffer->enable_multibyte_characters = Qnil;
3725 insert_1_both (read_buf, nread, nread, 0, 0, 0);
3726 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
1255deb9
KH
3727 val = call2 (Vset_auto_coding_function,
3728 filename, make_number (nread));
f736ffbf 3729 set_buffer_internal (prev);
1d92afcd
GM
3730
3731 /* Remove the binding for standard-output. */
3732 unbind_to (count1, Qnil);
3733
f736ffbf
KH
3734 /* Discard the unwind protect for recovering the
3735 current buffer. */
3736 specpdl_ptr--;
3737
3738 /* Rewind the file for the actual read done later. */
3739 if (lseek (fd, 0, 0) < 0)
3740 report_file_error ("Setting file position",
3741 Fcons (orig_filename, Qnil));
3742 }
3743 }
feb9dc27 3744
f736ffbf
KH
3745 if (NILP (val))
3746 {
3747 /* If we have not yet decided a coding system, check
3748 file-coding-system-alist. */
3749 Lisp_Object args[6], coding_systems;
3750
3751 args[0] = Qinsert_file_contents, args[1] = orig_filename;
3752 args[2] = visit, args[3] = beg, args[4] = end, args[5] = replace;
3753 coding_systems = Ffind_operation_coding_system (6, args);
3754 if (CONSP (coding_systems))
03699b14 3755 val = XCAR (coding_systems);
f736ffbf
KH
3756 }
3757 }
c9e82392 3758
f736ffbf 3759 setup_coding_system (Fcheck_coding_system (val), &coding);
f8569325
DL
3760 /* Ensure we set Vlast_coding_system_used. */
3761 set_coding_system = 1;
c8a6d68a 3762
237a6fd2
RS
3763 if (NILP (current_buffer->enable_multibyte_characters)
3764 && ! NILP (val))
3765 /* We must suppress all character code conversion except for
3766 end-of-line conversion. */
57515cfe 3767 setup_raw_text_coding_system (&coding);
54369368 3768
8c3b9441
KH
3769 coding.src_multibyte = 0;
3770 coding.dst_multibyte
3771 = !NILP (current_buffer->enable_multibyte_characters);
f736ffbf
KH
3772 coding_system_decided = 1;
3773 }
6cf71bf1 3774
3d0387c0
RS
3775 /* If requested, replace the accessible part of the buffer
3776 with the file contents. Avoid replacing text at the
3777 beginning or end of the buffer that matches the file contents;
3dbcf3f6
RS
3778 that preserves markers pointing to the unchanged parts.
3779
3780 Here we implement this feature in an optimized way
3781 for the case where code conversion is NOT needed.
3782 The following if-statement handles the case of conversion
727a0b4a
RS
3783 in a less optimal way.
3784
3785 If the code conversion is "automatic" then we try using this
3786 method and hope for the best.
3787 But if we discover the need for conversion, we give up on this method
3788 and let the following if-statement handle the replace job. */
3dbcf3f6 3789 if (!NILP (replace)
f736ffbf 3790 && BEGV < ZV
8c3b9441 3791 && !(coding.common_flags & CODING_REQUIRE_DECODING_MASK))
3d0387c0 3792 {
ec7adf26
RS
3793 /* same_at_start and same_at_end count bytes,
3794 because file access counts bytes
3795 and BEG and END count bytes. */
3796 int same_at_start = BEGV_BYTE;
3797 int same_at_end = ZV_BYTE;
9c28748f 3798 int overlap;
6fdaa9a0
KH
3799 /* There is still a possibility we will find the need to do code
3800 conversion. If that happens, we set this variable to 1 to
727a0b4a 3801 give up on handling REPLACE in the optimized way. */
6fdaa9a0 3802 int giveup_match_end = 0;
9c28748f 3803
4d2a0879
RS
3804 if (XINT (beg) != 0)
3805 {
3806 if (lseek (fd, XINT (beg), 0) < 0)
3807 report_file_error ("Setting file position",
b1d1b865 3808 Fcons (orig_filename, Qnil));
4d2a0879
RS
3809 }
3810
3d0387c0
RS
3811 immediate_quit = 1;
3812 QUIT;
3813 /* Count how many chars at the start of the file
3814 match the text at the beginning of the buffer. */
3815 while (1)
3816 {
3817 int nread, bufpos;
3818
68c45bf0 3819 nread = emacs_read (fd, buffer, sizeof buffer);
3d0387c0
RS
3820 if (nread < 0)
3821 error ("IO error reading %s: %s",
68c45bf0 3822 XSTRING (orig_filename)->data, emacs_strerror (errno));
3d0387c0
RS
3823 else if (nread == 0)
3824 break;
6fdaa9a0 3825
0ef69138 3826 if (coding.type == coding_type_undecided)
727a0b4a 3827 detect_coding (&coding, buffer, nread);
8c3b9441 3828 if (coding.common_flags & CODING_REQUIRE_DECODING_MASK)
727a0b4a
RS
3829 /* We found that the file should be decoded somehow.
3830 Let's give up here. */
3831 {
3832 giveup_match_end = 1;
3833 break;
3834 }
3835
0ef69138 3836 if (coding.eol_type == CODING_EOL_UNDECIDED)
727a0b4a 3837 detect_eol (&coding, buffer, nread);
1b335d29 3838 if (coding.eol_type != CODING_EOL_UNDECIDED
70ec4328 3839 && coding.eol_type != CODING_EOL_LF)
727a0b4a
RS
3840 /* We found that the format of eol should be decoded.
3841 Let's give up here. */
3842 {
3843 giveup_match_end = 1;
3844 break;
3845 }
3846
3d0387c0 3847 bufpos = 0;
ec7adf26 3848 while (bufpos < nread && same_at_start < ZV_BYTE
6fdaa9a0 3849 && FETCH_BYTE (same_at_start) == buffer[bufpos])
3d0387c0
RS
3850 same_at_start++, bufpos++;
3851 /* If we found a discrepancy, stop the scan.
8e6208c5 3852 Otherwise loop around and scan the next bufferful. */
3d0387c0
RS
3853 if (bufpos != nread)
3854 break;
3855 }
3856 immediate_quit = 0;
3857 /* If the file matches the buffer completely,
3858 there's no need to replace anything. */
ec7adf26 3859 if (same_at_start - BEGV_BYTE == XINT (end))
3d0387c0 3860 {
68c45bf0 3861 emacs_close (fd);
a1d2b64a 3862 specpdl_ptr--;
1051b3b3 3863 /* Truncate the buffer to the size of the file. */
7dae4502 3864 del_range_1 (same_at_start, same_at_end, 0, 0);
3d0387c0
RS
3865 goto handled;
3866 }
3867 immediate_quit = 1;
3868 QUIT;
3869 /* Count how many chars at the end of the file
6fdaa9a0
KH
3870 match the text at the end of the buffer. But, if we have
3871 already found that decoding is necessary, don't waste time. */
3872 while (!giveup_match_end)
3d0387c0
RS
3873 {
3874 int total_read, nread, bufpos, curpos, trial;
3875
3876 /* At what file position are we now scanning? */
ec7adf26 3877 curpos = XINT (end) - (ZV_BYTE - same_at_end);
fc81fa9e
KH
3878 /* If the entire file matches the buffer tail, stop the scan. */
3879 if (curpos == 0)
3880 break;
3d0387c0
RS
3881 /* How much can we scan in the next step? */
3882 trial = min (curpos, sizeof buffer);
3883 if (lseek (fd, curpos - trial, 0) < 0)
3884 report_file_error ("Setting file position",
b1d1b865 3885 Fcons (orig_filename, Qnil));
3d0387c0 3886
b02439c8 3887 total_read = nread = 0;
3d0387c0
RS
3888 while (total_read < trial)
3889 {
68c45bf0 3890 nread = emacs_read (fd, buffer + total_read, trial - total_read);
2bd2273e 3891 if (nread < 0)
3d0387c0 3892 error ("IO error reading %s: %s",
68c45bf0 3893 XSTRING (orig_filename)->data, emacs_strerror (errno));
2bd2273e
GM
3894 else if (nread == 0)
3895 break;
3d0387c0
RS
3896 total_read += nread;
3897 }
2bd2273e 3898
8e6208c5 3899 /* Scan this bufferful from the end, comparing with
3d0387c0
RS
3900 the Emacs buffer. */
3901 bufpos = total_read;
2bd2273e 3902
3d0387c0
RS
3903 /* Compare with same_at_start to avoid counting some buffer text
3904 as matching both at the file's beginning and at the end. */
3905 while (bufpos > 0 && same_at_end > same_at_start
6fdaa9a0 3906 && FETCH_BYTE (same_at_end - 1) == buffer[bufpos - 1])
3d0387c0 3907 same_at_end--, bufpos--;
727a0b4a 3908
3d0387c0 3909 /* If we found a discrepancy, stop the scan.
8e6208c5 3910 Otherwise loop around and scan the preceding bufferful. */
3d0387c0 3911 if (bufpos != 0)
727a0b4a
RS
3912 {
3913 /* If this discrepancy is because of code conversion,
3914 we cannot use this method; giveup and try the other. */
3915 if (same_at_end > same_at_start
3916 && FETCH_BYTE (same_at_end - 1) >= 0200
71312b68 3917 && ! NILP (current_buffer->enable_multibyte_characters)
c8a6d68a 3918 && (CODING_MAY_REQUIRE_DECODING (&coding)))
727a0b4a
RS
3919 giveup_match_end = 1;
3920 break;
3921 }
b02439c8
GM
3922
3923 if (nread == 0)
3924 break;
3d0387c0
RS
3925 }
3926 immediate_quit = 0;
9c28748f 3927
727a0b4a
RS
3928 if (! giveup_match_end)
3929 {
ec7adf26
RS
3930 int temp;
3931
727a0b4a 3932 /* We win! We can handle REPLACE the optimized way. */
9c28748f 3933
20f6783d
RS
3934 /* Extend the start of non-matching text area to multibyte
3935 character boundary. */
3936 if (! NILP (current_buffer->enable_multibyte_characters))
3937 while (same_at_start > BEGV_BYTE
3938 && ! CHAR_HEAD_P (FETCH_BYTE (same_at_start)))
3939 same_at_start--;
3940
3941 /* Extend the end of non-matching text area to multibyte
71312b68
RS
3942 character boundary. */
3943 if (! NILP (current_buffer->enable_multibyte_characters))
ec7adf26
RS
3944 while (same_at_end < ZV_BYTE
3945 && ! CHAR_HEAD_P (FETCH_BYTE (same_at_end)))
71312b68
RS
3946 same_at_end++;
3947
727a0b4a 3948 /* Don't try to reuse the same piece of text twice. */
ec7adf26
RS
3949 overlap = (same_at_start - BEGV_BYTE
3950 - (same_at_end + st.st_size - ZV));
727a0b4a
RS
3951 if (overlap > 0)
3952 same_at_end += overlap;
9c28748f 3953
727a0b4a 3954 /* Arrange to read only the nonmatching middle part of the file. */
ec7adf26
RS
3955 XSETFASTINT (beg, XINT (beg) + (same_at_start - BEGV_BYTE));
3956 XSETFASTINT (end, XINT (end) - (ZV_BYTE - same_at_end));
3dbcf3f6 3957
ec7adf26 3958 del_range_byte (same_at_start, same_at_end, 0);
727a0b4a 3959 /* Insert from the file at the proper position. */
ec7adf26
RS
3960 temp = BYTE_TO_CHAR (same_at_start);
3961 SET_PT_BOTH (temp, same_at_start);
727a0b4a
RS
3962
3963 /* If display currently starts at beginning of line,
3964 keep it that way. */
3965 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
3966 XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
3967
3968 replace_handled = 1;
3969 }
3dbcf3f6
RS
3970 }
3971
3972 /* If requested, replace the accessible part of the buffer
3973 with the file contents. Avoid replacing text at the
3974 beginning or end of the buffer that matches the file contents;
3975 that preserves markers pointing to the unchanged parts.
3976
3977 Here we implement this feature for the case where code conversion
3978 is needed, in a simple way that needs a lot of memory.
3979 The preceding if-statement handles the case of no conversion
3980 in a more optimized way. */
f736ffbf 3981 if (!NILP (replace) && ! replace_handled && BEGV < ZV)
3dbcf3f6 3982 {
ec7adf26
RS
3983 int same_at_start = BEGV_BYTE;
3984 int same_at_end = ZV_BYTE;
3dbcf3f6
RS
3985 int overlap;
3986 int bufpos;
3987 /* Make sure that the gap is large enough. */
3988 int bufsize = 2 * st.st_size;
b00ca0d7 3989 unsigned char *conversion_buffer = (unsigned char *) xmalloc (bufsize);
ec7adf26 3990 int temp;
3dbcf3f6
RS
3991
3992 /* First read the whole file, performing code conversion into
3993 CONVERSION_BUFFER. */
3994
727a0b4a
RS
3995 if (lseek (fd, XINT (beg), 0) < 0)
3996 {
68cfd853 3997 xfree (conversion_buffer);
727a0b4a 3998 report_file_error ("Setting file position",
b1d1b865 3999 Fcons (orig_filename, Qnil));
727a0b4a
RS
4000 }
4001
3dbcf3f6
RS
4002 total = st.st_size; /* Total bytes in the file. */
4003 how_much = 0; /* Bytes read from file so far. */
4004 inserted = 0; /* Bytes put into CONVERSION_BUFFER so far. */
4005 unprocessed = 0; /* Bytes not processed in previous loop. */
4006
4007 while (how_much < total)
4008 {
4009 /* try is reserved in some compilers (Microsoft C) */
4010 int trytry = min (total - how_much, READ_BUF_SIZE - unprocessed);
cadf50ff 4011 unsigned char *destination = read_buf + unprocessed;
3dbcf3f6
RS
4012 int this;
4013
4014 /* Allow quitting out of the actual I/O. */
4015 immediate_quit = 1;
4016 QUIT;
68c45bf0 4017 this = emacs_read (fd, destination, trytry);
3dbcf3f6
RS
4018 immediate_quit = 0;
4019
4020 if (this < 0 || this + unprocessed == 0)
4021 {
4022 how_much = this;
4023 break;
4024 }
4025
4026 how_much += this;
4027
c8a6d68a 4028 if (CODING_MAY_REQUIRE_DECODING (&coding))
3dbcf3f6 4029 {
c8a6d68a 4030 int require, result;
3dbcf3f6
RS
4031
4032 this += unprocessed;
4033
4034 /* If we are using more space than estimated,
4035 make CONVERSION_BUFFER bigger. */
4036 require = decoding_buffer_size (&coding, this);
4037 if (inserted + require + 2 * (total - how_much) > bufsize)
4038 {
4039 bufsize = inserted + require + 2 * (total - how_much);
92cf1086 4040 conversion_buffer = (unsigned char *) xrealloc (conversion_buffer, bufsize);
3dbcf3f6
RS
4041 }
4042
4043 /* Convert this batch with results in CONVERSION_BUFFER. */
4044 if (how_much >= total) /* This is the last block. */
c8a6d68a 4045 coding.mode |= CODING_MODE_LAST_BLOCK;
1ddb09f5
GM
4046 if (coding.composing != COMPOSITION_DISABLED)
4047 coding_allocate_composition_data (&coding, BEGV);
c8a6d68a
KH
4048 result = decode_coding (&coding, read_buf,
4049 conversion_buffer + inserted,
4050 this, bufsize - inserted);
3dbcf3f6
RS
4051
4052 /* Save for next iteration whatever we didn't convert. */
c8a6d68a
KH
4053 unprocessed = this - coding.consumed;
4054 bcopy (read_buf + coding.consumed, read_buf, unprocessed);
8c3b9441
KH
4055 if (!NILP (current_buffer->enable_multibyte_characters))
4056 this = coding.produced;
4057 else
4058 this = str_as_unibyte (conversion_buffer + inserted,
4059 coding.produced);
3dbcf3f6
RS
4060 }
4061
4062 inserted += this;
4063 }
4064
c8a6d68a 4065 /* At this point, INSERTED is how many characters (i.e. bytes)
3dbcf3f6
RS
4066 are present in CONVERSION_BUFFER.
4067 HOW_MUCH should equal TOTAL,
4068 or should be <= 0 if we couldn't read the file. */
4069
4070 if (how_much < 0)
4071 {
a36837e4 4072 xfree (conversion_buffer);
3dbcf3f6
RS
4073
4074 if (how_much == -1)
4075 error ("IO error reading %s: %s",
68c45bf0 4076 XSTRING (orig_filename)->data, emacs_strerror (errno));
3dbcf3f6
RS
4077 else if (how_much == -2)
4078 error ("maximum buffer size exceeded");
4079 }
4080
4081 /* Compare the beginning of the converted file
4082 with the buffer text. */
4083
4084 bufpos = 0;
4085 while (bufpos < inserted && same_at_start < same_at_end
4086 && FETCH_BYTE (same_at_start) == conversion_buffer[bufpos])
4087 same_at_start++, bufpos++;
4088
4089 /* If the file matches the buffer completely,
4090 there's no need to replace anything. */
4091
4092 if (bufpos == inserted)
4093 {
a36837e4 4094 xfree (conversion_buffer);
68c45bf0 4095 emacs_close (fd);
3dbcf3f6
RS
4096 specpdl_ptr--;
4097 /* Truncate the buffer to the size of the file. */
427f5aab
KH
4098 del_range_byte (same_at_start, same_at_end, 0);
4099 inserted = 0;
3dbcf3f6
RS
4100 goto handled;
4101 }
4102
20f6783d
RS
4103 /* Extend the start of non-matching text area to multibyte
4104 character boundary. */
4105 if (! NILP (current_buffer->enable_multibyte_characters))
4106 while (same_at_start > BEGV_BYTE
4107 && ! CHAR_HEAD_P (FETCH_BYTE (same_at_start)))
4108 same_at_start--;
4109
3dbcf3f6
RS
4110 /* Scan this bufferful from the end, comparing with
4111 the Emacs buffer. */
4112 bufpos = inserted;
4113
4114 /* Compare with same_at_start to avoid counting some buffer text
4115 as matching both at the file's beginning and at the end. */
4116 while (bufpos > 0 && same_at_end > same_at_start
4117 && FETCH_BYTE (same_at_end - 1) == conversion_buffer[bufpos - 1])
4118 same_at_end--, bufpos--;
4119
20f6783d
RS
4120 /* Extend the end of non-matching text area to multibyte
4121 character boundary. */
4122 if (! NILP (current_buffer->enable_multibyte_characters))
4123 while (same_at_end < ZV_BYTE
4124 && ! CHAR_HEAD_P (FETCH_BYTE (same_at_end)))
4125 same_at_end++;
4126
3dbcf3f6 4127 /* Don't try to reuse the same piece of text twice. */
ec7adf26 4128 overlap = same_at_start - BEGV_BYTE - (same_at_end + inserted - ZV_BYTE);
3dbcf3f6
RS
4129 if (overlap > 0)
4130 same_at_end += overlap;
4131
727a0b4a
RS
4132 /* If display currently starts at beginning of line,
4133 keep it that way. */
4134 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
4135 XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
4136
3dbcf3f6
RS
4137 /* Replace the chars that we need to replace,
4138 and update INSERTED to equal the number of bytes
4139 we are taking from the file. */
ec7adf26 4140 inserted -= (Z_BYTE - same_at_end) + (same_at_start - BEG_BYTE);
427f5aab 4141
643c73b9 4142 if (same_at_end != same_at_start)
427f5aab
KH
4143 {
4144 del_range_byte (same_at_start, same_at_end, 0);
4145 temp = GPT;
4146 same_at_start = GPT_BYTE;
4147 }
643c73b9
RS
4148 else
4149 {
643c73b9 4150 temp = BYTE_TO_CHAR (same_at_start);
643c73b9 4151 }
427f5aab
KH
4152 /* Insert from the file at the proper position. */
4153 SET_PT_BOTH (temp, same_at_start);
ec7adf26
RS
4154 insert_1 (conversion_buffer + same_at_start - BEG_BYTE, inserted,
4155 0, 0, 0);
1ddb09f5
GM
4156 if (coding.cmp_data && coding.cmp_data->used)
4157 coding_restore_composition (&coding, Fcurrent_buffer ());
4158 coding_free_composition_data (&coding);
4159
427f5aab
KH
4160 /* Set `inserted' to the number of inserted characters. */
4161 inserted = PT - temp;
3dbcf3f6 4162
93184560 4163 xfree (conversion_buffer);
68c45bf0 4164 emacs_close (fd);
3dbcf3f6
RS
4165 specpdl_ptr--;
4166
3dbcf3f6 4167 goto handled;
3d0387c0
RS
4168 }
4169
d4b8687b
RS
4170 if (! not_regular)
4171 {
4172 register Lisp_Object temp;
7fded690 4173
d4b8687b 4174 total = XINT (end) - XINT (beg);
570d7624 4175
d4b8687b
RS
4176 /* Make sure point-max won't overflow after this insertion. */
4177 XSETINT (temp, total);
4178 if (total != XINT (temp))
4179 error ("Maximum buffer size exceeded");
4180 }
4181 else
4182 /* For a special file, all we can do is guess. */
4183 total = READ_BUF_SIZE;
570d7624 4184
57d8d468 4185 if (NILP (visit) && total > 0)
6c478ee2 4186 prepare_to_modify_buffer (PT, PT, NULL);
570d7624 4187
7fe52289 4188 move_gap (PT);
7fded690
JB
4189 if (GAP_SIZE < total)
4190 make_gap (total - GAP_SIZE);
4191
a1d2b64a 4192 if (XINT (beg) != 0 || !NILP (replace))
7fded690
JB
4193 {
4194 if (lseek (fd, XINT (beg), 0) < 0)
b1d1b865
RS
4195 report_file_error ("Setting file position",
4196 Fcons (orig_filename, Qnil));
7fded690
JB
4197 }
4198
6fdaa9a0 4199 /* In the following loop, HOW_MUCH contains the total bytes read so
c8a6d68a
KH
4200 far for a regular file, and not changed for a special file. But,
4201 before exiting the loop, it is set to a negative value if I/O
4202 error occurs. */
a1d2b64a 4203 how_much = 0;
1b978129 4204
6fdaa9a0
KH
4205 /* Total bytes inserted. */
4206 inserted = 0;
1b978129 4207
c8a6d68a
KH
4208 /* Here, we don't do code conversion in the loop. It is done by
4209 code_convert_region after all data are read into the buffer. */
1b978129
GM
4210 {
4211 int gap_size = GAP_SIZE;
4212
4213 while (how_much < total)
4214 {
5e570b75 4215 /* try is reserved in some compilers (Microsoft C) */
1b978129
GM
4216 int trytry = min (total - how_much, READ_BUF_SIZE);
4217 int this;
570d7624 4218
1b978129
GM
4219 if (not_regular)
4220 {
4221 Lisp_Object val;
570d7624 4222
1b978129
GM
4223 /* Maybe make more room. */
4224 if (gap_size < trytry)
4225 {
4226 make_gap (total - gap_size);
4227 gap_size = GAP_SIZE;
4228 }
4229
4230 /* Read from the file, capturing `quit'. When an
4231 error occurs, end the loop, and arrange for a quit
4232 to be signaled after decoding the text we read. */
4233 non_regular_fd = fd;
4234 non_regular_inserted = inserted;
4235 non_regular_nbytes = trytry;
4236 val = internal_condition_case_1 (read_non_regular, Qnil, Qerror,
4237 read_non_regular_quit);
4238 if (NILP (val))
4239 {
4240 read_quit = 1;
4241 break;
4242 }
4243
4244 this = XINT (val);
4245 }
4246 else
4247 {
4248 /* Allow quitting out of the actual I/O. We don't make text
4249 part of the buffer until all the reading is done, so a C-g
4250 here doesn't do any harm. */
4251 immediate_quit = 1;
4252 QUIT;
4253 this = emacs_read (fd, BEG_ADDR + PT_BYTE - 1 + inserted, trytry);
4254 immediate_quit = 0;
4255 }
4256
4257 if (this <= 0)
4258 {
4259 how_much = this;
4260 break;
4261 }
4262
4263 gap_size -= this;
4264
4265 /* For a regular file, where TOTAL is the real size,
4266 count HOW_MUCH to compare with it.
4267 For a special file, where TOTAL is just a buffer size,
4268 so don't bother counting in HOW_MUCH.
4269 (INSERTED is where we count the number of characters inserted.) */
4270 if (! not_regular)
4271 how_much += this;
4272 inserted += this;
4273 }
4274 }
4275
4276 /* Make the text read part of the buffer. */
4277 GAP_SIZE -= inserted;
4278 GPT += inserted;
4279 GPT_BYTE += inserted;
4280 ZV += inserted;
4281 ZV_BYTE += inserted;
4282 Z += inserted;
4283 Z_BYTE += inserted;
6fdaa9a0 4284
c8a6d68a
KH
4285 if (GAP_SIZE > 0)
4286 /* Put an anchor to ensure multi-byte form ends at gap. */
4287 *GPT_ADDR = 0;
d4b8687b 4288
68c45bf0 4289 emacs_close (fd);
6fdaa9a0 4290
c8a6d68a
KH
4291 /* Discard the unwind protect for closing the file. */
4292 specpdl_ptr--;
6fdaa9a0 4293
c8a6d68a
KH
4294 if (how_much < 0)
4295 error ("IO error reading %s: %s",
68c45bf0 4296 XSTRING (orig_filename)->data, emacs_strerror (errno));
ec7adf26 4297
f8569325
DL
4298 notfound:
4299
2df42e09 4300 if (! coding_system_decided)
c8a6d68a 4301 {
2df42e09 4302 /* The coding system is not yet decided. Decide it by an
dfe35e7b
RS
4303 optimized method for handling `coding:' tag.
4304
4305 Note that we can get here only if the buffer was empty
4306 before the insertion. */
2df42e09
KH
4307 Lisp_Object val;
4308 val = Qnil;
f736ffbf 4309
2df42e09
KH
4310 if (!NILP (Vcoding_system_for_read))
4311 val = Vcoding_system_for_read;
4312 else
4313 {
98a7d268
KH
4314 /* Since we are sure that the current buffer was empty
4315 before the insertion, we can toggle
4316 enable-multibyte-characters directly here without taking
4317 care of marker adjustment and byte combining problem. By
4318 this way, we can run Lisp program safely before decoding
4319 the inserted text. */
4320 Lisp_Object unwind_data;
2df42e09
KH
4321 int count = specpdl_ptr - specpdl;
4322
98a7d268
KH
4323 unwind_data = Fcons (current_buffer->enable_multibyte_characters,
4324 Fcons (current_buffer->undo_list,
4325 Fcurrent_buffer ()));
2df42e09 4326 current_buffer->enable_multibyte_characters = Qnil;
98a7d268
KH
4327 current_buffer->undo_list = Qt;
4328 record_unwind_protect (decide_coding_unwind, unwind_data);
4329
4330 if (inserted > 0 && ! NILP (Vset_auto_coding_function))
4331 {
1255deb9
KH
4332 val = call2 (Vset_auto_coding_function,
4333 filename, make_number (inserted));
2df42e09 4334 }
f736ffbf 4335
2df42e09
KH
4336 if (NILP (val))
4337 {
4338 /* If the coding system is not yet decided, check
4339 file-coding-system-alist. */
4340 Lisp_Object args[6], coding_systems;
f736ffbf 4341
2df42e09
KH
4342 args[0] = Qinsert_file_contents, args[1] = orig_filename;
4343 args[2] = visit, args[3] = beg, args[4] = end, args[5] = Qnil;
4344 coding_systems = Ffind_operation_coding_system (6, args);
4345 if (CONSP (coding_systems))
03699b14 4346 val = XCAR (coding_systems);
f736ffbf 4347 }
98a7d268
KH
4348
4349 unbind_to (count, Qnil);
4350 inserted = Z_BYTE - BEG_BYTE;
2df42e09 4351 }
f736ffbf 4352
2df42e09
KH
4353 /* The following kludgy code is to avoid some compiler bug.
4354 We can't simply do
4355 setup_coding_system (val, &coding);
4356 on some system. */
4357 {
4358 struct coding_system temp_coding;
4359 setup_coding_system (val, &temp_coding);
4360 bcopy (&temp_coding, &coding, sizeof coding);
4361 }
f8569325
DL
4362 /* Ensure we set Vlast_coding_system_used. */
4363 set_coding_system = 1;
f736ffbf 4364
237a6fd2
RS
4365 if (NILP (current_buffer->enable_multibyte_characters)
4366 && ! NILP (val))
4367 /* We must suppress all character code conversion except for
2df42e09
KH
4368 end-of-line conversion. */
4369 setup_raw_text_coding_system (&coding);
6db43875
KH
4370 coding.src_multibyte = 0;
4371 coding.dst_multibyte
4372 = !NILP (current_buffer->enable_multibyte_characters);
2df42e09 4373 }
f736ffbf 4374
8c3b9441 4375 if (!NILP (visit)
24766480
GM
4376 /* Can't do this if part of the buffer might be preserved. */
4377 && NILP (replace)
8c3b9441
KH
4378 && (coding.type == coding_type_no_conversion
4379 || coding.type == coding_type_raw_text))
4380 {
24766480
GM
4381 /* Visiting a file with these coding system makes the buffer
4382 unibyte. */
4383 current_buffer->enable_multibyte_characters = Qnil;
e1249666 4384 coding.dst_multibyte = 0;
8c3b9441
KH
4385 }
4386
c91beee2 4387 if (inserted > 0 || coding.type == coding_type_ccl)
2df42e09 4388 {
c8a6d68a 4389 if (CODING_MAY_REQUIRE_DECODING (&coding))
64e0ae2a
KH
4390 {
4391 code_convert_region (PT, PT_BYTE, PT + inserted, PT_BYTE + inserted,
4392 &coding, 0, 0);
8c3b9441 4393 inserted = coding.produced_char;
f8198e19 4394 }
e9cea947
AS
4395 else
4396 adjust_after_insert (PT, PT_BYTE, PT + inserted, PT_BYTE + inserted,
8c3b9441 4397 inserted);
2df42e09 4398 }
570d7624 4399
04e6f79c 4400#ifdef DOS_NT
2df42e09
KH
4401 /* Use the conversion type to determine buffer-file-type
4402 (find-buffer-file-type is now used to help determine the
4403 conversion). */
4404 if ((coding.eol_type == CODING_EOL_UNDECIDED
4405 || coding.eol_type == CODING_EOL_LF)
4406 && ! CODING_REQUIRE_DECODING (&coding))
4407 current_buffer->buffer_file_type = Qt;
4408 else
4409 current_buffer->buffer_file_type = Qnil;
04e6f79c 4410#endif
570d7624 4411
32f4334d 4412 handled:
570d7624 4413
265a9e55 4414 if (!NILP (visit))
570d7624 4415 {
cfadd376
RS
4416 if (!EQ (current_buffer->undo_list, Qt))
4417 current_buffer->undo_list = Qnil;
570d7624
JB
4418#ifdef APOLLO
4419 stat (XSTRING (filename)->data, &st);
4420#endif
62bcf009 4421
a7e82472
RS
4422 if (NILP (handler))
4423 {
4424 current_buffer->modtime = st.st_mtime;
b1d1b865 4425 current_buffer->filename = orig_filename;
a7e82472 4426 }
62bcf009 4427
95385625 4428 SAVE_MODIFF = MODIFF;
570d7624 4429 current_buffer->auto_save_modified = MODIFF;
2acfd7ae 4430 XSETFASTINT (current_buffer->save_length, Z - BEG);
570d7624 4431#ifdef CLASH_DETECTION
32f4334d
RS
4432 if (NILP (handler))
4433 {
f471f4c2
RS
4434 if (!NILP (current_buffer->file_truename))
4435 unlock_file (current_buffer->file_truename);
32f4334d
RS
4436 unlock_file (filename);
4437 }
570d7624 4438#endif /* CLASH_DETECTION */
330bfe57
RS
4439 if (not_regular)
4440 Fsignal (Qfile_error,
4441 Fcons (build_string ("not a regular file"),
b1d1b865 4442 Fcons (orig_filename, Qnil)));
570d7624
JB
4443 }
4444
0d420e88 4445 /* Decode file format */
c8a6d68a 4446 if (inserted > 0)
0d420e88 4447 {
ed8e506f
GM
4448 int empty_undo_list_p = 0;
4449
4450 /* If we're anyway going to discard undo information, don't
4451 record it in the first place. The buffer's undo list at this
4452 point is either nil or t when visiting a file. */
4453 if (!NILP (visit))
4454 {
4455 empty_undo_list_p = NILP (current_buffer->undo_list);
4456 current_buffer->undo_list = Qt;
4457 }
4458
199607e4 4459 insval = call3 (Qformat_decode,
c8a6d68a 4460 Qnil, make_number (inserted), visit);
0d420e88 4461 CHECK_NUMBER (insval, 0);
c8a6d68a 4462 inserted = XFASTINT (insval);
ed8e506f
GM
4463
4464 if (!NILP (visit))
4465 current_buffer->undo_list = empty_undo_list_p ? Qnil : Qt;
0d420e88
BG
4466 }
4467
ce51c54c
KH
4468 if (set_coding_system)
4469 Vlast_coding_system_used = coding.symbol;
4470
0342d8c5
RS
4471 /* Call after-change hooks for the inserted text, aside from the case
4472 of normal visiting (not with REPLACE), which is done in a new buffer
4473 "before" the buffer is changed. */
c8a6d68a 4474 if (inserted > 0 && total > 0
0342d8c5 4475 && (NILP (visit) || !NILP (replace)))
ce51c54c
KH
4476 {
4477 signal_after_change (PT, 0, inserted);
4478 update_compositions (PT, PT, CHECK_BORDER);
4479 }
b56567b5 4480
f8569325
DL
4481 p = Vafter_insert_file_functions;
4482 while (!NILP (p))
d6a3cc15 4483 {
f8569325
DL
4484 insval = call1 (Fcar (p), make_number (inserted));
4485 if (!NILP (insval))
d6a3cc15 4486 {
f8569325
DL
4487 CHECK_NUMBER (insval, 0);
4488 inserted = XFASTINT (insval);
d6a3cc15 4489 }
f8569325
DL
4490 QUIT;
4491 p = Fcdr (p);
4492 }
4493
4494 if (!NILP (visit)
4495 && current_buffer->modtime == -1)
4496 {
4497 /* If visiting nonexistent file, return nil. */
4498 report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
d6a3cc15
RS
4499 }
4500
1b978129
GM
4501 if (read_quit)
4502 Fsignal (Qquit, Qnil);
4503
ec7adf26 4504 /* ??? Retval needs to be dealt with in all cases consistently. */
a1d2b64a 4505 if (NILP (val))
b1d1b865 4506 val = Fcons (orig_filename,
a1d2b64a
RS
4507 Fcons (make_number (inserted),
4508 Qnil));
4509
4510 RETURN_UNGCPRO (unbind_to (count, val));
570d7624 4511}
7fded690 4512\f
ec7adf26
RS
4513static Lisp_Object build_annotations P_ ((Lisp_Object, Lisp_Object,
4514 Lisp_Object));
d6a3cc15 4515
6fc6f94b 4516/* If build_annotations switched buffers, switch back to BUF.
6fdaa9a0
KH
4517 Kill the temporary buffer that was selected in the meantime.
4518
4519 Since this kill only the last temporary buffer, some buffers remain
4520 not killed if build_annotations switched buffers more than once.
4521 -- K.Handa */
6fc6f94b 4522
199607e4 4523static Lisp_Object
6fc6f94b
RS
4524build_annotations_unwind (buf)
4525 Lisp_Object buf;
4526{
4527 Lisp_Object tembuf;
4528
4529 if (XBUFFER (buf) == current_buffer)
4530 return Qnil;
4531 tembuf = Fcurrent_buffer ();
4532 Fset_buffer (buf);
4533 Fkill_buffer (tembuf);
4534 return Qnil;
4535}
4536
de1d0127 4537DEFUN ("write-region", Fwrite_region, Swrite_region, 3, 7,
8c1a1077
PJ
4538 "r\nFWrite region to file: \ni\ni\ni\np",
4539 doc: /* Write current region into specified file.
4540When called from a program, takes three arguments:
4541START, END and FILENAME. START and END are buffer positions.
4542Optional fourth argument APPEND if non-nil means
4543 append to existing file contents (if any). If it is an integer,
4544 seek to that offset in the file before writing.
4545Optional fifth argument VISIT if t means
4546 set the last-save-file-modtime of buffer to this file's modtime
4547 and mark buffer not modified.
4548If VISIT is a string, it is a second file name;
4549 the output goes to FILENAME, but the buffer is marked as visiting VISIT.
4550 VISIT is also the file name to lock and unlock for clash detection.
4551If VISIT is neither t nor nil nor a string,
4552 that means do not print the \"Wrote file\" message.
4553The optional sixth arg LOCKNAME, if non-nil, specifies the name to
4554 use for locking and unlocking, overriding FILENAME and VISIT.
4555The optional seventh arg MUSTBENEW, if non-nil, insists on a check
4556 for an existing file with the same name. If MUSTBENEW is `excl',
4557 that means to get an error if the file already exists; never overwrite.
4558 If MUSTBENEW is neither nil nor `excl', that means ask for
4559 confirmation before overwriting, but do go ahead and overwrite the file
4560 if the user confirms.
4561Kludgy feature: if START is a string, then that string is written
4562to the file, instead of any buffer contents, and END is ignored.
4563
4564This does code conversion according to the value of
4565`coding-system-for-write', `buffer-file-coding-system', or
4566`file-coding-system-alist', and sets the variable
4567`last-coding-system-used' to the coding system actually used. */)
4568 (start, end, filename, append, visit, lockname, mustbenew)
f7b4065f 4569 Lisp_Object start, end, filename, append, visit, lockname, mustbenew;
570d7624
JB
4570{
4571 register int desc;
4572 int failure;
6bbd7a29 4573 int save_errno = 0;
570d7624
JB
4574 unsigned char *fn;
4575 struct stat st;
c975dd7a 4576 int tem;
570d7624 4577 int count = specpdl_ptr - specpdl;
6fc6f94b 4578 int count1;
570d7624 4579#ifdef VMS
5e570b75 4580 unsigned char *fname = 0; /* If non-0, original filename (must rename) */
570d7624 4581#endif /* VMS */
3eac9910 4582 Lisp_Object handler;
4ad827c5 4583 Lisp_Object visit_file;
d6a3cc15 4584 Lisp_Object annotations;
b1d1b865 4585 Lisp_Object encoded_filename;
d3a67486
SM
4586 int visiting = (EQ (visit, Qt) || STRINGP (visit));
4587 int quietly = !NILP (visit);
7204a979 4588 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
6fc6f94b 4589 struct buffer *given_buffer;
5e570b75 4590#ifdef DOS_NT
fa228724 4591 int buffer_file_type = O_BINARY;
5e570b75 4592#endif /* DOS_NT */
6fdaa9a0 4593 struct coding_system coding;
570d7624 4594
d3a67486 4595 if (current_buffer->base_buffer && visiting)
95385625
RS
4596 error ("Cannot do file visiting in an indirect buffer");
4597
561cb8e1 4598 if (!NILP (start) && !STRINGP (start))
570d7624
JB
4599 validate_region (&start, &end);
4600
115af127 4601 GCPRO4 (start, filename, visit, lockname);
cdfb0f1d 4602
b1d1b865 4603 /* Decide the coding-system to encode the data with. */
cdfb0f1d
KH
4604 {
4605 Lisp_Object val;
4606
cbc64b2a 4607 if (auto_saving)
cdfb0f1d 4608 val = Qnil;
cdfb0f1d
KH
4609 else if (!NILP (Vcoding_system_for_write))
4610 val = Vcoding_system_for_write;
1255deb9 4611 else
450c1a67
KH
4612 {
4613 /* If the variable `buffer-file-coding-system' is set locally,
4614 it means that the file was read with some kind of code
8c27da0a 4615 conversion or the variable is explicitly set by users. We
450c1a67
KH
4616 had better write it out with the same coding system even if
4617 `enable-multibyte-characters' is nil.
4618
c8a6d68a 4619 If it is not set locally, we anyway have to convert EOL
450c1a67
KH
4620 format if the default value of `buffer-file-coding-system'
4621 tells that it is not Unix-like (LF only) format. */
ef38927f
KH
4622 int using_default_coding = 0;
4623 int force_raw_text = 0;
4624
450c1a67 4625 val = current_buffer->buffer_file_coding_system;
1255deb9
KH
4626 if (NILP (val)
4627 || NILP (Flocal_variable_p (Qbuffer_file_coding_system, Qnil)))
450c1a67 4628 {
450c1a67 4629 val = Qnil;
ef38927f
KH
4630 if (NILP (current_buffer->enable_multibyte_characters))
4631 force_raw_text = 1;
450c1a67 4632 }
ef38927f 4633
1255deb9
KH
4634 if (NILP (val))
4635 {
4636 /* Check file-coding-system-alist. */
4637 Lisp_Object args[7], coding_systems;
4638
4639 args[0] = Qwrite_region; args[1] = start; args[2] = end;
4640 args[3] = filename; args[4] = append; args[5] = visit;
4641 args[6] = lockname;
4642 coding_systems = Ffind_operation_coding_system (7, args);
03699b14
KR
4643 if (CONSP (coding_systems) && !NILP (XCDR (coding_systems)))
4644 val = XCDR (coding_systems);
1255deb9
KH
4645 }
4646
ef38927f
KH
4647 if (NILP (val)
4648 && !NILP (current_buffer->buffer_file_coding_system))
4649 {
4650 /* If we still have not decided a coding system, use the
4651 default value of buffer-file-coding-system. */
4652 val = current_buffer->buffer_file_coding_system;
4653 using_default_coding = 1;
4654 }
1255deb9 4655
ef38927f 4656 if (!force_raw_text
1255deb9
KH
4657 && !NILP (Ffboundp (Vselect_safe_coding_system_function)))
4658 /* Confirm that VAL can surely encode the current region. */
c8a6d68a 4659 val = call3 (Vselect_safe_coding_system_function, start, end, val);
ef38927f
KH
4660
4661 setup_coding_system (Fcheck_coding_system (val), &coding);
4662 if (coding.eol_type == CODING_EOL_UNDECIDED
4663 && !using_default_coding)
4664 {
4665 if (! EQ (default_buffer_file_coding.symbol,
4666 buffer_defaults.buffer_file_coding_system))
4667 setup_coding_system (buffer_defaults.buffer_file_coding_system,
4668 &default_buffer_file_coding);
4669 if (default_buffer_file_coding.eol_type != CODING_EOL_UNDECIDED)
4670 {
4671 Lisp_Object subsidiaries;
4672
4673 coding.eol_type = default_buffer_file_coding.eol_type;
4674 subsidiaries = Fget (coding.symbol, Qeol_type);
4675 if (VECTORP (subsidiaries)
4676 && XVECTOR (subsidiaries)->size == 3)
4677 coding.symbol
4678 = XVECTOR (subsidiaries)->contents[coding.eol_type];
4679 }
4680 }
4681
4682 if (force_raw_text)
4683 setup_raw_text_coding_system (&coding);
4684 goto done_setup_coding;
cdfb0f1d 4685 }
ef38927f 4686
1255deb9 4687 setup_coding_system (Fcheck_coding_system (val), &coding);
450c1a67
KH
4688
4689 done_setup_coding:
cdfb0f1d 4690 if (!STRINGP (start) && !NILP (current_buffer->selective_display))
c8a6d68a 4691 coding.mode |= CODING_MODE_SELECTIVE_DISPLAY;
cdfb0f1d
KH
4692 }
4693
b56567b5
KH
4694 Vlast_coding_system_used = coding.symbol;
4695
570d7624 4696 filename = Fexpand_file_name (filename, Qnil);
de1d0127 4697
7c752c80 4698 if (! NILP (mustbenew) && !EQ (mustbenew, Qexcl))
b8b29dc9 4699 barf_or_query_if_file_exists (filename, "overwrite", 1, 0, 1);
de1d0127 4700
561cb8e1 4701 if (STRINGP (visit))
e5176bae 4702 visit_file = Fexpand_file_name (visit, Qnil);
4ad827c5
RS
4703 else
4704 visit_file = filename;
1a04498e 4705 UNGCPRO;
4ad827c5 4706
d6a3cc15
RS
4707 annotations = Qnil;
4708
7204a979
RS
4709 if (NILP (lockname))
4710 lockname = visit_file;
4711
4712 GCPRO5 (start, filename, annotations, visit_file, lockname);
570d7624 4713
32f4334d
RS
4714 /* If the file name has special constructs in it,
4715 call the corresponding file handler. */
49307295 4716 handler = Ffind_file_name_handler (filename, Qwrite_region);
b56ad927 4717 /* If FILENAME has no handler, see if VISIT has one. */
93c30b5f 4718 if (NILP (handler) && STRINGP (visit))
199607e4 4719 handler = Ffind_file_name_handler (visit, Qwrite_region);
3eac9910 4720
32f4334d
RS
4721 if (!NILP (handler))
4722 {
32f4334d 4723 Lisp_Object val;
51cf6d37
RS
4724 val = call6 (handler, Qwrite_region, start, end,
4725 filename, append, visit);
32f4334d 4726
d6a3cc15 4727 if (visiting)
32f4334d 4728 {
95385625 4729 SAVE_MODIFF = MODIFF;
2acfd7ae 4730 XSETFASTINT (current_buffer->save_length, Z - BEG);
3b7792ed 4731 current_buffer->filename = visit_file;
32f4334d 4732 }
09121adc 4733 UNGCPRO;
32f4334d
RS
4734 return val;
4735 }
4736
561cb8e1
RS
4737 /* Special kludge to simplify auto-saving. */
4738 if (NILP (start))
4739 {
2acfd7ae
KH
4740 XSETFASTINT (start, BEG);
4741 XSETFASTINT (end, Z);
561cb8e1
RS
4742 }
4743
6fc6f94b
RS
4744 record_unwind_protect (build_annotations_unwind, Fcurrent_buffer ());
4745 count1 = specpdl_ptr - specpdl;
4746
4747 given_buffer = current_buffer;
6fdaa9a0 4748 annotations = build_annotations (start, end, coding.pre_write_conversion);
6fc6f94b
RS
4749 if (current_buffer != given_buffer)
4750 {
3cf29f61
RS
4751 XSETFASTINT (start, BEGV);
4752 XSETFASTINT (end, ZV);
6fc6f94b 4753 }
d6a3cc15 4754
570d7624
JB
4755#ifdef CLASH_DETECTION
4756 if (!auto_saving)
84f6296a 4757 {
a9171faa 4758#if 0 /* This causes trouble for GNUS. */
84f6296a
RS
4759 /* If we've locked this file for some other buffer,
4760 query before proceeding. */
4761 if (!visiting && EQ (Ffile_locked_p (lockname), Qt))
bffd00b0 4762 call2 (intern ("ask-user-about-lock"), filename, Vuser_login_name);
a9171faa 4763#endif
84f6296a
RS
4764
4765 lock_file (lockname);
4766 }
570d7624
JB
4767#endif /* CLASH_DETECTION */
4768
b1d1b865
RS
4769 encoded_filename = ENCODE_FILE (filename);
4770
4771 fn = XSTRING (encoded_filename)->data;
570d7624 4772 desc = -1;
265a9e55 4773 if (!NILP (append))
5e570b75 4774#ifdef DOS_NT
68c45bf0 4775 desc = emacs_open (fn, O_WRONLY | buffer_file_type, 0);
5e570b75 4776#else /* not DOS_NT */
68c45bf0 4777 desc = emacs_open (fn, O_WRONLY, 0);
5e570b75 4778#endif /* not DOS_NT */
570d7624 4779
b1d1b865 4780 if (desc < 0 && (NILP (append) || errno == ENOENT))
570d7624 4781#ifdef VMS
5e570b75 4782 if (auto_saving) /* Overwrite any previous version of autosave file */
570d7624 4783 {
5e570b75 4784 vms_truncate (fn); /* if fn exists, truncate to zero length */
68c45bf0 4785 desc = emacs_open (fn, O_RDWR, 0);
570d7624 4786 if (desc < 0)
561cb8e1 4787 desc = creat_copy_attrs (STRINGP (current_buffer->filename)
b72dea2a
JB
4788 ? XSTRING (current_buffer->filename)->data : 0,
4789 fn);
570d7624 4790 }
5e570b75 4791 else /* Write to temporary name and rename if no errors */
570d7624
JB
4792 {
4793 Lisp_Object temp_name;
4794 temp_name = Ffile_name_directory (filename);
4795
265a9e55 4796 if (!NILP (temp_name))
570d7624
JB
4797 {
4798 temp_name = Fmake_temp_name (concat2 (temp_name,
4799 build_string ("$$SAVE$$")));
4800 fname = XSTRING (filename)->data;
4801 fn = XSTRING (temp_name)->data;
4802 desc = creat_copy_attrs (fname, fn);
4803 if (desc < 0)
4804 {
4805 /* If we can't open the temporary file, try creating a new
4806 version of the original file. VMS "creat" creates a
4807 new version rather than truncating an existing file. */
4808 fn = fname;
4809 fname = 0;
4810 desc = creat (fn, 0666);
4811#if 0 /* This can clobber an existing file and fail to replace it,
4812 if the user runs out of space. */
4813 if (desc < 0)
4814 {
4815 /* We can't make a new version;
4816 try to truncate and rewrite existing version if any. */
4817 vms_truncate (fn);
68c45bf0 4818 desc = emacs_open (fn, O_RDWR, 0);
570d7624
JB
4819 }
4820#endif
4821 }
4822 }
4823 else
4824 desc = creat (fn, 0666);
4825 }
4826#else /* not VMS */
5e570b75 4827#ifdef DOS_NT
68c45bf0 4828 desc = emacs_open (fn,
95522746
GM
4829 O_WRONLY | O_CREAT | buffer_file_type
4830 | (EQ (mustbenew, Qexcl) ? O_EXCL : O_TRUNC),
68c45bf0 4831 S_IREAD | S_IWRITE);
5e570b75 4832#else /* not DOS_NT */
68c45bf0 4833 desc = emacs_open (fn, O_WRONLY | O_TRUNC | O_CREAT
7c752c80 4834 | (EQ (mustbenew, Qexcl) ? O_EXCL : 0),
68c45bf0 4835 auto_saving ? auto_save_mode_bits : 0666);
5e570b75 4836#endif /* not DOS_NT */
570d7624
JB
4837#endif /* not VMS */
4838
4839 if (desc < 0)
4840 {
4841#ifdef CLASH_DETECTION
4842 save_errno = errno;
7204a979 4843 if (!auto_saving) unlock_file (lockname);
570d7624
JB
4844 errno = save_errno;
4845#endif /* CLASH_DETECTION */
43fb7d9a 4846 UNGCPRO;
570d7624
JB
4847 report_file_error ("Opening output file", Fcons (filename, Qnil));
4848 }
4849
4850 record_unwind_protect (close_file_unwind, make_number (desc));
4851
c1c4693e 4852 if (!NILP (append) && !NILP (Ffile_regular_p (filename)))
43fb7d9a
DL
4853 {
4854 long ret;
4855
4856 if (NUMBERP (append))
4857 ret = lseek (desc, XINT (append), 1);
4858 else
4859 ret = lseek (desc, 0, 2);
4860 if (ret < 0)
4861 {
570d7624 4862#ifdef CLASH_DETECTION
43fb7d9a 4863 if (!auto_saving) unlock_file (lockname);
570d7624 4864#endif /* CLASH_DETECTION */
43fb7d9a
DL
4865 UNGCPRO;
4866 report_file_error ("Lseek error", Fcons (filename, Qnil));
4867 }
4868 }
4869
4870 UNGCPRO;
570d7624
JB
4871
4872#ifdef VMS
4873/*
4874 * Kludge Warning: The VMS C RTL likes to insert carriage returns
4875 * if we do writes that don't end with a carriage return. Furthermore
4876 * it cannot handle writes of more then 16K. The modified
4877 * version of "sys_write" in SYSDEP.C (see comment there) copes with
4878 * this EXCEPT for the last record (iff it doesn't end with a carriage
4879 * return). This implies that if your buffer doesn't end with a carriage
4880 * return, you get one free... tough. However it also means that if
4881 * we make two calls to sys_write (a la the following code) you can
4882 * get one at the gap as well. The easiest way to fix this (honest)
4883 * is to move the gap to the next newline (or the end of the buffer).
4884 * Thus this change.
4885 *
4886 * Yech!
4887 */
4888 if (GPT > BEG && GPT_ADDR[-1] != '\n')
4889 move_gap (find_next_newline (GPT, 1));
cdfb0f1d
KH
4890#else
4891 /* Whether VMS or not, we must move the gap to the next of newline
4892 when we must put designation sequences at beginning of line. */
4893 if (INTEGERP (start)
4894 && coding.type == coding_type_iso2022
4895 && coding.flags & CODING_FLAG_ISO_DESIGNATE_AT_BOL
4896 && GPT > BEG && GPT_ADDR[-1] != '\n')
ec7adf26
RS
4897 {
4898 int opoint = PT, opoint_byte = PT_BYTE;
4899 scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 0);
4900 move_gap_both (PT, PT_BYTE);
4901 SET_PT_BOTH (opoint, opoint_byte);
4902 }
570d7624
JB
4903#endif
4904
4905 failure = 0;
4906 immediate_quit = 1;
4907
561cb8e1 4908 if (STRINGP (start))
570d7624 4909 {
ce51c54c
KH
4910 failure = 0 > a_write (desc, start, 0, XSTRING (start)->size,
4911 &annotations, &coding);
570d7624
JB
4912 save_errno = errno;
4913 }
4914 else if (XINT (start) != XINT (end))
4915 {
ec7adf26
RS
4916 tem = CHAR_TO_BYTE (XINT (start));
4917
570d7624
JB
4918 if (XINT (start) < GPT)
4919 {
ce51c54c
KH
4920 failure = 0 > a_write (desc, Qnil, XINT (start),
4921 min (GPT, XINT (end)) - XINT (start),
4922 &annotations, &coding);
570d7624
JB
4923 save_errno = errno;
4924 }
4925
4926 if (XINT (end) > GPT && !failure)
4927 {
ce51c54c
KH
4928 tem = max (XINT (start), GPT);
4929 failure = 0 > a_write (desc, Qnil, tem , XINT (end) - tem,
4930 &annotations, &coding);
d6a3cc15
RS
4931 save_errno = errno;
4932 }
69f6e679
RS
4933 }
4934 else
4935 {
4936 /* If file was empty, still need to write the annotations */
c8a6d68a 4937 coding.mode |= CODING_MODE_LAST_BLOCK;
ce51c54c 4938 failure = 0 > a_write (desc, Qnil, XINT (end), 0, &annotations, &coding);
6fdaa9a0
KH
4939 save_errno = errno;
4940 }
4941
c8a6d68a
KH
4942 if (CODING_REQUIRE_FLUSHING (&coding)
4943 && !(coding.mode & CODING_MODE_LAST_BLOCK)
1354debd 4944 && ! failure)
6fdaa9a0
KH
4945 {
4946 /* We have to flush out a data. */
c8a6d68a 4947 coding.mode |= CODING_MODE_LAST_BLOCK;
ce51c54c 4948 failure = 0 > e_write (desc, Qnil, 0, 0, &coding);
69f6e679 4949 save_errno = errno;
570d7624
JB
4950 }
4951
4952 immediate_quit = 0;
4953
6e23c83e 4954#ifdef HAVE_FSYNC
570d7624
JB
4955 /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun).
4956 Disk full in NFS may be reported here. */
1daffa1c
RS
4957 /* mib says that closing the file will try to write as fast as NFS can do
4958 it, and that means the fsync here is not crucial for autosave files. */
4959 if (!auto_saving && fsync (desc) < 0)
cb33c142
KH
4960 {
4961 /* If fsync fails with EINTR, don't treat that as serious. */
4962 if (errno != EINTR)
4963 failure = 1, save_errno = errno;
4964 }
570d7624
JB
4965#endif
4966
199607e4 4967 /* Spurious "file has changed on disk" warnings have been
570d7624
JB
4968 observed on Suns as well.
4969 It seems that `close' can change the modtime, under nfs.
4970
4971 (This has supposedly been fixed in Sunos 4,
4972 but who knows about all the other machines with NFS?) */
4973#if 0
4974
4975 /* On VMS and APOLLO, must do the stat after the close
4976 since closing changes the modtime. */
4977#ifndef VMS
4978#ifndef APOLLO
4979 /* Recall that #if defined does not work on VMS. */
4980#define FOO
4981 fstat (desc, &st);
4982#endif
4983#endif
4984#endif
4985
4986 /* NFS can report a write failure now. */
68c45bf0 4987 if (emacs_close (desc) < 0)
570d7624
JB
4988 failure = 1, save_errno = errno;
4989
4990#ifdef VMS
4991 /* If we wrote to a temporary name and had no errors, rename to real name. */
4992 if (fname)
4993 {
4994 if (!failure)
4995 failure = (rename (fn, fname) != 0), save_errno = errno;
4996 fn = fname;
4997 }
4998#endif /* VMS */
4999
5000#ifndef FOO
5001 stat (fn, &st);
5002#endif
6fc6f94b
RS
5003 /* Discard the unwind protect for close_file_unwind. */
5004 specpdl_ptr = specpdl + count1;
5005 /* Restore the original current buffer. */
98295b48 5006 visit_file = unbind_to (count, visit_file);
570d7624
JB
5007
5008#ifdef CLASH_DETECTION
5009 if (!auto_saving)
7204a979 5010 unlock_file (lockname);
570d7624
JB
5011#endif /* CLASH_DETECTION */
5012
5013 /* Do this before reporting IO error
5014 to avoid a "file has changed on disk" warning on
5015 next attempt to save. */
d6a3cc15 5016 if (visiting)
570d7624
JB
5017 current_buffer->modtime = st.st_mtime;
5018
5019 if (failure)
b1d1b865 5020 error ("IO error writing %s: %s", XSTRING (filename)->data,
68c45bf0 5021 emacs_strerror (save_errno));
570d7624 5022
d6a3cc15 5023 if (visiting)
570d7624 5024 {
95385625 5025 SAVE_MODIFF = MODIFF;
2acfd7ae 5026 XSETFASTINT (current_buffer->save_length, Z - BEG);
3b7792ed 5027 current_buffer->filename = visit_file;
f4226e89 5028 update_mode_lines++;
570d7624 5029 }
d6a3cc15 5030 else if (quietly)
570d7624
JB
5031 return Qnil;
5032
5033 if (!auto_saving)
60d67b83 5034 message_with_string ("Wrote %s", visit_file, 1);
570d7624
JB
5035
5036 return Qnil;
5037}
ec7adf26 5038\f
d6a3cc15
RS
5039Lisp_Object merge ();
5040
5041DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0,
8c1a1077
PJ
5042 doc: /* Return t if (car A) is numerically less than (car B). */)
5043 (a, b)
d6a3cc15
RS
5044 Lisp_Object a, b;
5045{
5046 return Flss (Fcar (a), Fcar (b));
5047}
5048
5049/* Build the complete list of annotations appropriate for writing out
5050 the text between START and END, by calling all the functions in
6fc6f94b
RS
5051 write-region-annotate-functions and merging the lists they return.
5052 If one of these functions switches to a different buffer, we assume
5053 that buffer contains altered text. Therefore, the caller must
5054 make sure to restore the current buffer in all cases,
5055 as save-excursion would do. */
d6a3cc15
RS
5056
5057static Lisp_Object
6fdaa9a0
KH
5058build_annotations (start, end, pre_write_conversion)
5059 Lisp_Object start, end, pre_write_conversion;
d6a3cc15
RS
5060{
5061 Lisp_Object annotations;
5062 Lisp_Object p, res;
5063 struct gcpro gcpro1, gcpro2;
0a20b684 5064 Lisp_Object original_buffer;
532ed661 5065 int i;
0a20b684
RS
5066
5067 XSETBUFFER (original_buffer, current_buffer);
d6a3cc15
RS
5068
5069 annotations = Qnil;
5070 p = Vwrite_region_annotate_functions;
5071 GCPRO2 (annotations, p);
5072 while (!NILP (p))
5073 {
6fc6f94b
RS
5074 struct buffer *given_buffer = current_buffer;
5075 Vwrite_region_annotations_so_far = annotations;
d6a3cc15 5076 res = call2 (Fcar (p), start, end);
6fc6f94b
RS
5077 /* If the function makes a different buffer current,
5078 assume that means this buffer contains altered text to be output.
5079 Reset START and END from the buffer bounds
5080 and discard all previous annotations because they should have
5081 been dealt with by this function. */
5082 if (current_buffer != given_buffer)
5083 {
3cf29f61
RS
5084 XSETFASTINT (start, BEGV);
5085 XSETFASTINT (end, ZV);
6fc6f94b
RS
5086 annotations = Qnil;
5087 }
d6a3cc15
RS
5088 Flength (res); /* Check basic validity of return value */
5089 annotations = merge (annotations, res, Qcar_less_than_car);
5090 p = Fcdr (p);
5091 }
0d420e88
BG
5092
5093 /* Now do the same for annotation functions implied by the file-format */
5094 if (auto_saving && (!EQ (Vauto_save_file_format, Qt)))
5095 p = Vauto_save_file_format;
5096 else
5097 p = current_buffer->file_format;
532ed661 5098 for (i = 0; !NILP (p); p = Fcdr (p), ++i)
0d420e88
BG
5099 {
5100 struct buffer *given_buffer = current_buffer;
532ed661 5101
0d420e88 5102 Vwrite_region_annotations_so_far = annotations;
532ed661
GM
5103
5104 /* Value is either a list of annotations or nil if the function
5105 has written annotations to a temporary buffer, which is now
5106 current. */
5107 res = call5 (Qformat_annotate_function, Fcar (p), start, end,
5108 original_buffer, make_number (i));
0d420e88
BG
5109 if (current_buffer != given_buffer)
5110 {
3cf29f61
RS
5111 XSETFASTINT (start, BEGV);
5112 XSETFASTINT (end, ZV);
0d420e88
BG
5113 annotations = Qnil;
5114 }
532ed661
GM
5115
5116 if (CONSP (res))
5117 annotations = merge (annotations, res, Qcar_less_than_car);
0d420e88 5118 }
6fdaa9a0
KH
5119
5120 /* At last, do the same for the function PRE_WRITE_CONVERSION
5121 implied by the current coding-system. */
5122 if (!NILP (pre_write_conversion))
5123 {
5124 struct buffer *given_buffer = current_buffer;
5125 Vwrite_region_annotations_so_far = annotations;
5126 res = call2 (pre_write_conversion, start, end);
6fdaa9a0 5127 Flength (res);
cdfb0f1d
KH
5128 annotations = (current_buffer != given_buffer
5129 ? res
5130 : merge (annotations, res, Qcar_less_than_car));
6fdaa9a0
KH
5131 }
5132
d6a3cc15
RS
5133 UNGCPRO;
5134 return annotations;
5135}
ec7adf26 5136\f
ce51c54c
KH
5137/* Write to descriptor DESC the NCHARS chars starting at POS of STRING.
5138 If STRING is nil, POS is the character position in the current buffer.
d6a3cc15 5139 Intersperse with them the annotations from *ANNOT
ce51c54c 5140 which fall within the range of POS to POS + NCHARS,
d6a3cc15
RS
5141 each at its appropriate position.
5142
ec7adf26
RS
5143 We modify *ANNOT by discarding elements as we use them up.
5144
d6a3cc15
RS
5145 The return value is negative in case of system call failure. */
5146
ec7adf26 5147static int
ce51c54c 5148a_write (desc, string, pos, nchars, annot, coding)
d6a3cc15 5149 int desc;
ce51c54c
KH
5150 Lisp_Object string;
5151 register int nchars;
5152 int pos;
d6a3cc15 5153 Lisp_Object *annot;
6fdaa9a0 5154 struct coding_system *coding;
d6a3cc15
RS
5155{
5156 Lisp_Object tem;
5157 int nextpos;
ce51c54c 5158 int lastpos = pos + nchars;
d6a3cc15 5159
eb15aa18 5160 while (NILP (*annot) || CONSP (*annot))
d6a3cc15
RS
5161 {
5162 tem = Fcar_safe (Fcar (*annot));
ce51c54c 5163 nextpos = pos - 1;
ec7adf26 5164 if (INTEGERP (tem))
ce51c54c 5165 nextpos = XFASTINT (tem);
ec7adf26
RS
5166
5167 /* If there are no more annotations in this range,
5168 output the rest of the range all at once. */
ce51c54c
KH
5169 if (! (nextpos >= pos && nextpos <= lastpos))
5170 return e_write (desc, string, pos, lastpos, coding);
ec7adf26
RS
5171
5172 /* Output buffer text up to the next annotation's position. */
ce51c54c 5173 if (nextpos > pos)
d6a3cc15 5174 {
055a28c9 5175 if (0 > e_write (desc, string, pos, nextpos, coding))
d6a3cc15 5176 return -1;
ce51c54c 5177 pos = nextpos;
d6a3cc15 5178 }
ec7adf26 5179 /* Output the annotation. */
d6a3cc15
RS
5180 tem = Fcdr (Fcar (*annot));
5181 if (STRINGP (tem))
5182 {
055a28c9 5183 if (0 > e_write (desc, tem, 0, XSTRING (tem)->size, coding))
d6a3cc15
RS
5184 return -1;
5185 }
5186 *annot = Fcdr (*annot);
5187 }
dfcf069d 5188 return 0;
d6a3cc15
RS
5189}
5190
6fdaa9a0
KH
5191#ifndef WRITE_BUF_SIZE
5192#define WRITE_BUF_SIZE (16 * 1024)
5193#endif
5194
ce51c54c
KH
5195/* Write text in the range START and END into descriptor DESC,
5196 encoding them with coding system CODING. If STRING is nil, START
5197 and END are character positions of the current buffer, else they
5198 are indexes to the string STRING. */
ec7adf26
RS
5199
5200static int
ce51c54c 5201e_write (desc, string, start, end, coding)
570d7624 5202 int desc;
ce51c54c
KH
5203 Lisp_Object string;
5204 int start, end;
6fdaa9a0 5205 struct coding_system *coding;
570d7624 5206{
ce51c54c
KH
5207 register char *addr;
5208 register int nbytes;
6fdaa9a0 5209 char buf[WRITE_BUF_SIZE];
ce51c54c
KH
5210 int return_val = 0;
5211
5212 if (start >= end)
5213 coding->composing = COMPOSITION_DISABLED;
5214 if (coding->composing != COMPOSITION_DISABLED)
5215 coding_save_composition (coding, start, end, string);
5216
5217 if (STRINGP (string))
5218 {
5219 addr = XSTRING (string)->data;
5220 nbytes = STRING_BYTES (XSTRING (string));
8c3b9441 5221 coding->src_multibyte = STRING_MULTIBYTE (string);
ce51c54c
KH
5222 }
5223 else if (start < end)
5224 {
5225 /* It is assured that the gap is not in the range START and END-1. */
5226 addr = CHAR_POS_ADDR (start);
5227 nbytes = CHAR_TO_BYTE (end) - CHAR_TO_BYTE (start);
8c3b9441
KH
5228 coding->src_multibyte
5229 = !NILP (current_buffer->enable_multibyte_characters);
ce51c54c
KH
5230 }
5231 else
5232 {
5233 addr = "";
5234 nbytes = 0;
8c3b9441 5235 coding->src_multibyte = 1;
ce51c54c 5236 }
570d7624 5237
6fdaa9a0
KH
5238 /* We used to have a code for handling selective display here. But,
5239 now it is handled within encode_coding. */
5240 while (1)
570d7624 5241 {
b4132433
KH
5242 int result;
5243
5244 result = encode_coding (coding, addr, buf, nbytes, WRITE_BUF_SIZE);
c8a6d68a 5245 if (coding->produced > 0)
6fdaa9a0 5246 {
68c45bf0 5247 coding->produced -= emacs_write (desc, buf, coding->produced);
ce51c54c
KH
5248 if (coding->produced)
5249 {
5250 return_val = -1;
5251 break;
5252 }
570d7624 5253 }
ca91fb26
KH
5254 nbytes -= coding->consumed;
5255 addr += coding->consumed;
5256 if (result == CODING_FINISH_INSUFFICIENT_SRC
5257 && nbytes > 0)
b4132433
KH
5258 {
5259 /* The source text ends by an incomplete multibyte form.
5260 There's no way other than write it out as is. */
68c45bf0 5261 nbytes -= emacs_write (desc, addr, nbytes);
ce51c54c
KH
5262 if (nbytes)
5263 {
5264 return_val = -1;
5265 break;
5266 }
b4132433 5267 }
ec7adf26 5268 if (nbytes <= 0)
6fdaa9a0 5269 break;
ce51c54c
KH
5270 start += coding->consumed_char;
5271 if (coding->cmp_data)
5272 coding_adjust_composition_offset (coding, start);
570d7624 5273 }
0c41a39c
KH
5274
5275 if (coding->cmp_data)
5276 coding_free_composition_data (coding);
5277
055a28c9 5278 return return_val;
570d7624 5279}
ec7adf26 5280\f
570d7624 5281DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,
8c1a1077
PJ
5282 Sverify_visited_file_modtime, 1, 1, 0,
5283 doc: /* Return t if last mod time of BUF's visited file matches what BUF records.
5284This means that the file has not been changed since it was visited or saved. */)
5285 (buf)
570d7624
JB
5286 Lisp_Object buf;
5287{
5288 struct buffer *b;
5289 struct stat st;
32f4334d 5290 Lisp_Object handler;
b1d1b865 5291 Lisp_Object filename;
570d7624
JB
5292
5293 CHECK_BUFFER (buf, 0);
5294 b = XBUFFER (buf);
5295
93c30b5f 5296 if (!STRINGP (b->filename)) return Qt;
570d7624
JB
5297 if (b->modtime == 0) return Qt;
5298
32f4334d
RS
5299 /* If the file name has special constructs in it,
5300 call the corresponding file handler. */
49307295
KH
5301 handler = Ffind_file_name_handler (b->filename,
5302 Qverify_visited_file_modtime);
32f4334d 5303 if (!NILP (handler))
09121adc 5304 return call2 (handler, Qverify_visited_file_modtime, buf);
32f4334d 5305
b1d1b865
RS
5306 filename = ENCODE_FILE (b->filename);
5307
5308 if (stat (XSTRING (filename)->data, &st) < 0)
570d7624
JB
5309 {
5310 /* If the file doesn't exist now and didn't exist before,
5311 we say that it isn't modified, provided the error is a tame one. */
5312 if (errno == ENOENT || errno == EACCES || errno == ENOTDIR)
5313 st.st_mtime = -1;
5314 else
5315 st.st_mtime = 0;
5316 }
5317 if (st.st_mtime == b->modtime
5318 /* If both are positive, accept them if they are off by one second. */
5319 || (st.st_mtime > 0 && b->modtime > 0
5320 && (st.st_mtime == b->modtime + 1
5321 || st.st_mtime == b->modtime - 1)))
5322 return Qt;
5323 return Qnil;
5324}
5325
5326DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,
8c1a1077
PJ
5327 Sclear_visited_file_modtime, 0, 0, 0,
5328 doc: /* Clear out records of last mod time of visited file.
5329Next attempt to save will certainly not complain of a discrepancy. */)
5330 ()
570d7624
JB
5331{
5332 current_buffer->modtime = 0;
5333 return Qnil;
5334}
5335
f5d5eccf 5336DEFUN ("visited-file-modtime", Fvisited_file_modtime,
8c1a1077
PJ
5337 Svisited_file_modtime, 0, 0, 0,
5338 doc: /* Return the current buffer's recorded visited file modification time.
5339The value is a list of the form (HIGH . LOW), like the time values
5340that `file-attributes' returns. */)
5341 ()
f5d5eccf 5342{
b50536bb 5343 return long_to_cons ((unsigned long) current_buffer->modtime);
f5d5eccf
RS
5344}
5345
570d7624 5346DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
8c1a1077
PJ
5347 Sset_visited_file_modtime, 0, 1, 0,
5348 doc: /* Update buffer's recorded modification time from the visited file's time.
5349Useful if the buffer was not read from the file normally
5350or if the file itself has been changed for some known benign reason.
5351An argument specifies the modification time value to use
5352\(instead of that of the visited file), in the form of a list
5353\(HIGH . LOW) or (HIGH LOW). */)
5354 (time_list)
f5d5eccf 5355 Lisp_Object time_list;
570d7624 5356{
f5d5eccf
RS
5357 if (!NILP (time_list))
5358 current_buffer->modtime = cons_to_long (time_list);
5359 else
5360 {
5361 register Lisp_Object filename;
5362 struct stat st;
5363 Lisp_Object handler;
570d7624 5364
f5d5eccf 5365 filename = Fexpand_file_name (current_buffer->filename, Qnil);
32f4334d 5366
f5d5eccf
RS
5367 /* If the file name has special constructs in it,
5368 call the corresponding file handler. */
49307295 5369 handler = Ffind_file_name_handler (filename, Qset_visited_file_modtime);
f5d5eccf 5370 if (!NILP (handler))
caf3c431 5371 /* The handler can find the file name the same way we did. */
76c881b0 5372 return call2 (handler, Qset_visited_file_modtime, Qnil);
b1d1b865
RS
5373
5374 filename = ENCODE_FILE (filename);
5375
5376 if (stat (XSTRING (filename)->data, &st) >= 0)
f5d5eccf
RS
5377 current_buffer->modtime = st.st_mtime;
5378 }
570d7624
JB
5379
5380 return Qnil;
5381}
5382\f
5383Lisp_Object
d7f31e22
GM
5384auto_save_error (error)
5385 Lisp_Object error;
570d7624 5386{
d7f31e22
GM
5387 Lisp_Object args[3], msg;
5388 int i, nbytes;
5389 struct gcpro gcpro1;
5390
570d7624 5391 ring_bell ();
d7f31e22
GM
5392
5393 args[0] = build_string ("Auto-saving %s: %s");
5394 args[1] = current_buffer->name;
5395 args[2] = Ferror_message_string (error);
5396 msg = Fformat (3, args);
5397 GCPRO1 (msg);
5398 nbytes = STRING_BYTES (XSTRING (msg));
5399
5400 for (i = 0; i < 3; ++i)
5401 {
5402 if (i == 0)
5403 message2 (XSTRING (msg)->data, nbytes, STRING_MULTIBYTE (msg));
5404 else
5405 message2_nolog (XSTRING (msg)->data, nbytes, STRING_MULTIBYTE (msg));
5406 Fsleep_for (make_number (1), Qnil);
5407 }
5408
5409 UNGCPRO;
570d7624
JB
5410 return Qnil;
5411}
5412
5413Lisp_Object
5414auto_save_1 ()
5415{
570d7624
JB
5416 struct stat st;
5417
5418 /* Get visited file's mode to become the auto save file's mode. */
8801a864
KR
5419 if (! NILP (current_buffer->filename)
5420 && stat (XSTRING (current_buffer->filename)->data, &st) >= 0)
570d7624
JB
5421 /* But make sure we can overwrite it later! */
5422 auto_save_mode_bits = st.st_mode | 0600;
5423 else
5424 auto_save_mode_bits = 0666;
5425
5426 return
5427 Fwrite_region (Qnil, Qnil,
5428 current_buffer->auto_save_file_name,
de1d0127 5429 Qnil, Qlambda, Qnil, Qnil);
570d7624
JB
5430}
5431
e54d3b5d 5432static Lisp_Object
1b335d29
RS
5433do_auto_save_unwind (stream) /* used as unwind-protect function */
5434 Lisp_Object stream;
e54d3b5d 5435{
3be3c08e 5436 auto_saving = 0;
1b335d29 5437 if (!NILP (stream))
03699b14
KR
5438 fclose ((FILE *) (XFASTINT (XCAR (stream)) << 16
5439 | XFASTINT (XCDR (stream))));
38119822 5440 pop_message ();
e54d3b5d
RS
5441 return Qnil;
5442}
5443
a8c828be
RS
5444static Lisp_Object
5445do_auto_save_unwind_1 (value) /* used as unwind-protect function */
5446 Lisp_Object value;
5447{
5448 minibuffer_auto_raise = XINT (value);
5449 return Qnil;
5450}
5451
570d7624 5452DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 2, "",
8c1a1077
PJ
5453 doc: /* Auto-save all buffers that need it.
5454This is all buffers that have auto-saving enabled
5455and are changed since last auto-saved.
5456Auto-saving writes the buffer into a file
5457so that your editing is not lost if the system crashes.
5458This file is not the file you visited; that changes only when you save.
5459Normally we run the normal hook `auto-save-hook' before saving.
5460
5461A non-nil NO-MESSAGE argument means do not print any message if successful.
5462A non-nil CURRENT-ONLY argument means save only current buffer. */)
5463 (no_message, current_only)
17857782 5464 Lisp_Object no_message, current_only;
570d7624
JB
5465{
5466 struct buffer *old = current_buffer, *b;
5467 Lisp_Object tail, buf;
5468 int auto_saved = 0;
f14b1c68 5469 int do_handled_files;
ff4c9993 5470 Lisp_Object oquit;
1b335d29
RS
5471 FILE *stream;
5472 Lisp_Object lispstream;
e54d3b5d 5473 int count = specpdl_ptr - specpdl;
a8c828be 5474 int orig_minibuffer_auto_raise = minibuffer_auto_raise;
c71106e5 5475 int message_p = push_message ();
9c856db9 5476
ff4c9993
RS
5477 /* Ordinarily don't quit within this function,
5478 but don't make it impossible to quit (in case we get hung in I/O). */
5479 oquit = Vquit_flag;
5480 Vquit_flag = Qnil;
570d7624
JB
5481
5482 /* No GCPRO needed, because (when it matters) all Lisp_Object variables
5483 point to non-strings reached from Vbuffer_alist. */
5484
570d7624 5485 if (minibuf_level)
17857782 5486 no_message = Qt;
570d7624 5487
265a9e55 5488 if (!NILP (Vrun_hooks))
570d7624
JB
5489 call1 (Vrun_hooks, intern ("auto-save-hook"));
5490
e54d3b5d
RS
5491 if (STRINGP (Vauto_save_list_file_name))
5492 {
0894672f 5493 Lisp_Object listfile;
b272d624 5494
258fd2cb 5495 listfile = Fexpand_file_name (Vauto_save_list_file_name, Qnil);
0894672f
GM
5496
5497 /* Don't try to create the directory when shutting down Emacs,
5498 because creating the directory might signal an error, and
5499 that would leave Emacs in a strange state. */
5500 if (!NILP (Vrun_hooks))
5501 {
5502 Lisp_Object dir;
5503 dir = Ffile_name_directory (listfile);
5504 if (NILP (Ffile_directory_p (dir)))
5505 call2 (Qmake_directory, dir, Qt);
5506 }
b272d624 5507
1b335d29 5508 stream = fopen (XSTRING (listfile)->data, "w");
0eff1f85
RS
5509 if (stream != NULL)
5510 {
5511 /* Arrange to close that file whether or not we get an error.
5512 Also reset auto_saving to 0. */
5513 lispstream = Fcons (Qnil, Qnil);
f3fbd155
KR
5514 XSETCARFASTINT (lispstream, (EMACS_UINT)stream >> 16);
5515 XSETCDRFASTINT (lispstream, (EMACS_UINT)stream & 0xffff);
0eff1f85
RS
5516 }
5517 else
5518 lispstream = Qnil;
e54d3b5d
RS
5519 }
5520 else
1b335d29
RS
5521 {
5522 stream = NULL;
5523 lispstream = Qnil;
5524 }
199607e4 5525
1b335d29 5526 record_unwind_protect (do_auto_save_unwind, lispstream);
a8c828be
RS
5527 record_unwind_protect (do_auto_save_unwind_1,
5528 make_number (minibuffer_auto_raise));
5529 minibuffer_auto_raise = 0;
3be3c08e
RS
5530 auto_saving = 1;
5531
f14b1c68
JB
5532 /* First, save all files which don't have handlers. If Emacs is
5533 crashing, the handlers may tweak what is causing Emacs to crash
5534 in the first place, and it would be a shame if Emacs failed to
5535 autosave perfectly ordinary files because it couldn't handle some
5536 ange-ftp'd file. */
5537 for (do_handled_files = 0; do_handled_files < 2; do_handled_files++)
03699b14 5538 for (tail = Vbuffer_alist; GC_CONSP (tail); tail = XCDR (tail))
f14b1c68 5539 {
03699b14 5540 buf = XCDR (XCAR (tail));
f14b1c68 5541 b = XBUFFER (buf);
199607e4 5542
e54d3b5d 5543 /* Record all the buffers that have auto save mode
258fd2cb
RS
5544 in the special file that lists them. For each of these buffers,
5545 Record visited name (if any) and auto save name. */
93c30b5f 5546 if (STRINGP (b->auto_save_file_name)
1b335d29 5547 && stream != NULL && do_handled_files == 0)
e54d3b5d 5548 {
258fd2cb
RS
5549 if (!NILP (b->filename))
5550 {
1b335d29 5551 fwrite (XSTRING (b->filename)->data, 1,
fc932ac6 5552 STRING_BYTES (XSTRING (b->filename)), stream);
258fd2cb 5553 }
1b335d29
RS
5554 putc ('\n', stream);
5555 fwrite (XSTRING (b->auto_save_file_name)->data, 1,
fc932ac6 5556 STRING_BYTES (XSTRING (b->auto_save_file_name)), stream);
1b335d29 5557 putc ('\n', stream);
e54d3b5d 5558 }
17857782 5559
f14b1c68
JB
5560 if (!NILP (current_only)
5561 && b != current_buffer)
5562 continue;
e54d3b5d 5563
95385625
RS
5564 /* Don't auto-save indirect buffers.
5565 The base buffer takes care of it. */
5566 if (b->base_buffer)
5567 continue;
5568
f14b1c68
JB
5569 /* Check for auto save enabled
5570 and file changed since last auto save
5571 and file changed since last real save. */
93c30b5f 5572 if (STRINGP (b->auto_save_file_name)
95385625 5573 && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)
f14b1c68 5574 && b->auto_save_modified < BUF_MODIFF (b)
82c2d839
RS
5575 /* -1 means we've turned off autosaving for a while--see below. */
5576 && XINT (b->save_length) >= 0
f14b1c68 5577 && (do_handled_files
49307295
KH
5578 || NILP (Ffind_file_name_handler (b->auto_save_file_name,
5579 Qwrite_region))))
f14b1c68 5580 {
b60247d9
RS
5581 EMACS_TIME before_time, after_time;
5582
5583 EMACS_GET_TIME (before_time);
5584
5585 /* If we had a failure, don't try again for 20 minutes. */
5586 if (b->auto_save_failure_time >= 0
5587 && EMACS_SECS (before_time) - b->auto_save_failure_time < 1200)
5588 continue;
5589
f14b1c68
JB
5590 if ((XFASTINT (b->save_length) * 10
5591 > (BUF_Z (b) - BUF_BEG (b)) * 13)
5592 /* A short file is likely to change a large fraction;
5593 spare the user annoying messages. */
5594 && XFASTINT (b->save_length) > 5000
5595 /* These messages are frequent and annoying for `*mail*'. */
5596 && !EQ (b->filename, Qnil)
5597 && NILP (no_message))
5598 {
5599 /* It has shrunk too much; turn off auto-saving here. */
a8c828be 5600 minibuffer_auto_raise = orig_minibuffer_auto_raise;
60d67b83
RS
5601 message_with_string ("Buffer %s has shrunk a lot; auto save turned off there",
5602 b->name, 1);
a8c828be 5603 minibuffer_auto_raise = 0;
82c2d839
RS
5604 /* Turn off auto-saving until there's a real save,
5605 and prevent any more warnings. */
46283abe 5606 XSETINT (b->save_length, -1);
f14b1c68
JB
5607 Fsleep_for (make_number (1), Qnil);
5608 continue;
5609 }
5610 set_buffer_internal (b);
5611 if (!auto_saved && NILP (no_message))
5612 message1 ("Auto-saving...");
5613 internal_condition_case (auto_save_1, Qt, auto_save_error);
5614 auto_saved++;
5615 b->auto_save_modified = BUF_MODIFF (b);
2acfd7ae 5616 XSETFASTINT (current_buffer->save_length, Z - BEG);
f14b1c68 5617 set_buffer_internal (old);
b60247d9
RS
5618
5619 EMACS_GET_TIME (after_time);
5620
5621 /* If auto-save took more than 60 seconds,
5622 assume it was an NFS failure that got a timeout. */
5623 if (EMACS_SECS (after_time) - EMACS_SECS (before_time) > 60)
5624 b->auto_save_failure_time = EMACS_SECS (after_time);
f14b1c68
JB
5625 }
5626 }
570d7624 5627
b67f2ca5
RS
5628 /* Prevent another auto save till enough input events come in. */
5629 record_auto_save ();
570d7624 5630
17857782 5631 if (auto_saved && NILP (no_message))
f05b275b 5632 {
c71106e5 5633 if (message_p)
31f3d831 5634 {
22e59fa7 5635 sit_for (1, 0, 0, 0, 0);
c71106e5 5636 restore_message ();
31f3d831 5637 }
f05b275b
KH
5638 else
5639 message1 ("Auto-saving...done");
5640 }
570d7624 5641
ff4c9993
RS
5642 Vquit_flag = oquit;
5643
e54d3b5d 5644 unbind_to (count, Qnil);
570d7624
JB
5645 return Qnil;
5646}
5647
5648DEFUN ("set-buffer-auto-saved", Fset_buffer_auto_saved,
8c1a1077
PJ
5649 Sset_buffer_auto_saved, 0, 0, 0,
5650 doc: /* Mark current buffer as auto-saved with its current text.
5651No auto-save file will be written until the buffer changes again. */)
5652 ()
570d7624
JB
5653{
5654 current_buffer->auto_save_modified = MODIFF;
2acfd7ae 5655 XSETFASTINT (current_buffer->save_length, Z - BEG);
b60247d9
RS
5656 current_buffer->auto_save_failure_time = -1;
5657 return Qnil;
5658}
5659
5660DEFUN ("clear-buffer-auto-save-failure", Fclear_buffer_auto_save_failure,
8c1a1077
PJ
5661 Sclear_buffer_auto_save_failure, 0, 0, 0,
5662 doc: /* Clear any record of a recent auto-save failure in the current buffer. */)
5663 ()
b60247d9
RS
5664{
5665 current_buffer->auto_save_failure_time = -1;
570d7624
JB
5666 return Qnil;
5667}
5668
5669DEFUN ("recent-auto-save-p", Frecent_auto_save_p, Srecent_auto_save_p,
8c1a1077
PJ
5670 0, 0, 0,
5671 doc: /* Return t if buffer has been auto-saved since last read in or saved. */)
5672 ()
570d7624 5673{
95385625 5674 return (SAVE_MODIFF < current_buffer->auto_save_modified) ? Qt : Qnil;
570d7624
JB
5675}
5676\f
5677/* Reading and completing file names */
5678extern Lisp_Object Ffile_name_completion (), Ffile_name_all_completions ();
5679
6e710ae5
RS
5680/* In the string VAL, change each $ to $$ and return the result. */
5681
5682static Lisp_Object
5683double_dollars (val)
5684 Lisp_Object val;
5685{
5686 register unsigned char *old, *new;
5687 register int n;
5688 int osize, count;
5689
fc932ac6 5690 osize = STRING_BYTES (XSTRING (val));
60d67b83
RS
5691
5692 /* Count the number of $ characters. */
6e710ae5
RS
5693 for (n = osize, count = 0, old = XSTRING (val)->data; n > 0; n--)
5694 if (*old++ == '$') count++;
5695 if (count > 0)
5696 {
5697 old = XSTRING (val)->data;
60d67b83
RS
5698 val = make_uninit_multibyte_string (XSTRING (val)->size + count,
5699 osize + count);
6e710ae5
RS
5700 new = XSTRING (val)->data;
5701 for (n = osize; n > 0; n--)
5702 if (*old != '$')
5703 *new++ = *old++;
5704 else
5705 {
5706 *new++ = '$';
5707 *new++ = '$';
5708 old++;
5709 }
5710 }
5711 return val;
5712}
5713
570d7624 5714DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_internal,
8c1a1077
PJ
5715 3, 3, 0,
5716 doc: /* Internal subroutine for read-file-name. Do not call this. */)
5717 (string, dir, action)
570d7624
JB
5718 Lisp_Object string, dir, action;
5719 /* action is nil for complete, t for return list of completions,
5720 lambda for verify final value */
5721{
5722 Lisp_Object name, specdir, realdir, val, orig_string;
09121adc 5723 int changed;
8ce069f5 5724 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
09121adc 5725
58cc3710
RS
5726 CHECK_STRING (string, 0);
5727
09121adc
RS
5728 realdir = dir;
5729 name = string;
5730 orig_string = Qnil;
5731 specdir = Qnil;
5732 changed = 0;
5733 /* No need to protect ACTION--we only compare it with t and nil. */
8ce069f5 5734 GCPRO5 (string, realdir, name, specdir, orig_string);
570d7624
JB
5735
5736 if (XSTRING (string)->size == 0)
5737 {
570d7624 5738 if (EQ (action, Qlambda))
09121adc
RS
5739 {
5740 UNGCPRO;
5741 return Qnil;
5742 }
570d7624
JB
5743 }
5744 else
5745 {
5746 orig_string = string;
5747 string = Fsubstitute_in_file_name (string);
09121adc 5748 changed = NILP (Fstring_equal (string, orig_string));
570d7624 5749 name = Ffile_name_nondirectory (string);
09121adc
RS
5750 val = Ffile_name_directory (string);
5751 if (! NILP (val))
5752 realdir = Fexpand_file_name (val, realdir);
570d7624
JB
5753 }
5754
265a9e55 5755 if (NILP (action))
570d7624
JB
5756 {
5757 specdir = Ffile_name_directory (string);
5758 val = Ffile_name_completion (name, realdir);
09121adc 5759 UNGCPRO;
93c30b5f 5760 if (!STRINGP (val))
570d7624 5761 {
09121adc 5762 if (changed)
dbd04e01 5763 return double_dollars (string);
09121adc 5764 return val;
570d7624
JB
5765 }
5766
265a9e55 5767 if (!NILP (specdir))
570d7624
JB
5768 val = concat2 (specdir, val);
5769#ifndef VMS
6e710ae5
RS
5770 return double_dollars (val);
5771#else /* not VMS */
09121adc 5772 return val;
6e710ae5 5773#endif /* not VMS */
570d7624 5774 }
09121adc 5775 UNGCPRO;
570d7624
JB
5776
5777 if (EQ (action, Qt))
5778 return Ffile_name_all_completions (name, realdir);
5779 /* Only other case actually used is ACTION = lambda */
5780#ifdef VMS
5781 /* Supposedly this helps commands such as `cd' that read directory names,
5782 but can someone explain how it helps them? -- RMS */
5783 if (XSTRING (name)->size == 0)
5784 return Qt;
5785#endif /* VMS */
5786 return Ffile_exists_p (string);
5787}
5788
5789DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 5, 0,
8c1a1077
PJ
5790 doc: /* Read file name, prompting with PROMPT and completing in directory DIR.
5791Value is not expanded---you must call `expand-file-name' yourself.
5792Default name to DEFAULT-FILENAME if user enters a null string.
5793 (If DEFAULT-FILENAME is omitted, the visited file name is used,
5794 except that if INITIAL is specified, that combined with DIR is used.)
5795Fourth arg MUSTMATCH non-nil means require existing file's name.
5796 Non-nil and non-t means also require confirmation after completion.
5797Fifth arg INITIAL specifies text to start with.
5798DIR defaults to current buffer's directory default.
5799
5800If this command was invoked with the mouse, use a file dialog box if
5801`use-dialog-box' is non-nil, and the window system or X toolkit in use
5802provides a file dialog box. */)
5803 (prompt, dir, default_filename, mustmatch, initial)
3b7f6e60 5804 Lisp_Object prompt, dir, default_filename, mustmatch, initial;
570d7624 5805{
8d6d9fef 5806 Lisp_Object val, insdef, tem;
570d7624
JB
5807 struct gcpro gcpro1, gcpro2;
5808 register char *homedir;
62f555a5
RS
5809 int replace_in_history = 0;
5810 int add_to_history = 0;
570d7624
JB
5811 int count;
5812
265a9e55 5813 if (NILP (dir))
570d7624 5814 dir = current_buffer->directory;
3b7f6e60 5815 if (NILP (default_filename))
3beeedfe
RS
5816 {
5817 if (! NILP (initial))
3b7f6e60 5818 default_filename = Fexpand_file_name (initial, dir);
3beeedfe 5819 else
3b7f6e60 5820 default_filename = current_buffer->filename;
3beeedfe 5821 }
570d7624
JB
5822
5823 /* If dir starts with user's homedir, change that to ~. */
5824 homedir = (char *) egetenv ("HOME");
199607e4 5825#ifdef DOS_NT
417c884a
EZ
5826 /* homedir can be NULL in temacs, since Vprocess_environment is not
5827 yet set up. We shouldn't crash in that case. */
5828 if (homedir != 0)
5829 {
5830 homedir = strcpy (alloca (strlen (homedir) + 1), homedir);
5831 CORRECT_DIR_SEPS (homedir);
5832 }
199607e4 5833#endif
570d7624 5834 if (homedir != 0
93c30b5f 5835 && STRINGP (dir)
570d7624 5836 && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))
5e570b75 5837 && IS_DIRECTORY_SEP (XSTRING (dir)->data[strlen (homedir)]))
570d7624
JB
5838 {
5839 dir = make_string (XSTRING (dir)->data + strlen (homedir) - 1,
fc932ac6 5840 STRING_BYTES (XSTRING (dir)) - strlen (homedir) + 1);
570d7624
JB
5841 XSTRING (dir)->data[0] = '~';
5842 }
8d6d9fef
AS
5843 /* Likewise for default_filename. */
5844 if (homedir != 0
5845 && STRINGP (default_filename)
5846 && !strncmp (homedir, XSTRING (default_filename)->data, strlen (homedir))
5847 && IS_DIRECTORY_SEP (XSTRING (default_filename)->data[strlen (homedir)]))
5848 {
5849 default_filename
5850 = make_string (XSTRING (default_filename)->data + strlen (homedir) - 1,
5851 STRING_BYTES (XSTRING (default_filename)) - strlen (homedir) + 1);
5852 XSTRING (default_filename)->data[0] = '~';
5853 }
5854 if (!NILP (default_filename))
b537a6c7
RS
5855 {
5856 CHECK_STRING (default_filename, 3);
5857 default_filename = double_dollars (default_filename);
5858 }
570d7624 5859
58cc3710 5860 if (insert_default_directory && STRINGP (dir))
570d7624
JB
5861 {
5862 insdef = dir;
265a9e55 5863 if (!NILP (initial))
570d7624 5864 {
15c65264 5865 Lisp_Object args[2], pos;
570d7624
JB
5866
5867 args[0] = insdef;
5868 args[1] = initial;
5869 insdef = Fconcat (2, args);
351bd676 5870 pos = make_number (XSTRING (double_dollars (dir))->size);
8d6d9fef 5871 insdef = Fcons (double_dollars (insdef), pos);
570d7624 5872 }
6e710ae5 5873 else
8d6d9fef 5874 insdef = double_dollars (insdef);
570d7624 5875 }
58cc3710 5876 else if (STRINGP (initial))
8d6d9fef 5877 insdef = Fcons (double_dollars (initial), make_number (0));
570d7624 5878 else
8d6d9fef 5879 insdef = Qnil;
570d7624 5880
570d7624 5881 count = specpdl_ptr - specpdl;
a79485af 5882#ifdef VMS
570d7624
JB
5883 specbind (intern ("completion-ignore-case"), Qt);
5884#endif
5885
a79485af
RS
5886 specbind (intern ("minibuffer-completing-file-name"), Qt);
5887
3b7f6e60 5888 GCPRO2 (insdef, default_filename);
9c856db9 5889
f73f57bd 5890#if defined (USE_MOTIF) || defined (HAVE_NTGUI)
9c856db9
GM
5891 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
5892 && use_dialog_box
5893 && have_menus_p ())
5894 {
9172b88d
GM
5895 /* If DIR contains a file name, split it. */
5896 Lisp_Object file;
5897 file = Ffile_name_nondirectory (dir);
5898 if (XSTRING (file)->size && NILP (default_filename))
5899 {
5900 default_filename = file;
5901 dir = Ffile_name_directory (dir);
5902 }
f73f57bd
JR
5903 if (!NILP(default_filename))
5904 default_filename = Fexpand_file_name (default_filename, dir);
9c856db9
GM
5905 val = Fx_file_dialog (prompt, dir, default_filename, mustmatch);
5906 add_to_history = 1;
5907 }
5908 else
5909#endif
5910 val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
5911 dir, mustmatch, insdef,
5912 Qfile_name_history, default_filename, Qnil);
62f555a5
RS
5913
5914 tem = Fsymbol_value (Qfile_name_history);
03699b14 5915 if (CONSP (tem) && EQ (XCAR (tem), val))
62f555a5
RS
5916 replace_in_history = 1;
5917
5918 /* If Fcompleting_read returned the inserted default string itself
a8c828be
RS
5919 (rather than a new string with the same contents),
5920 it has to mean that the user typed RET with the minibuffer empty.
5921 In that case, we really want to return ""
5922 so that commands such as set-visited-file-name can distinguish. */
5923 if (EQ (val, default_filename))
62f555a5
RS
5924 {
5925 /* In this case, Fcompleting_read has not added an element
5926 to the history. Maybe we should. */
5927 if (! replace_in_history)
5928 add_to_history = 1;
5929
5930 val = build_string ("");
5931 }
570d7624 5932
570d7624 5933 unbind_to (count, Qnil);
570d7624 5934 UNGCPRO;
265a9e55 5935 if (NILP (val))
570d7624 5936 error ("No file name specified");
62f555a5 5937
8d6d9fef 5938 tem = Fstring_equal (val, CONSP (insdef) ? XCAR (insdef) : insdef);
62f555a5 5939
3b7f6e60 5940 if (!NILP (tem) && !NILP (default_filename))
62f555a5
RS
5941 val = default_filename;
5942 else if (XSTRING (val)->size == 0 && NILP (insdef))
d9bc1c99 5943 {
3b7f6e60 5944 if (!NILP (default_filename))
62f555a5 5945 val = default_filename;
d9bc1c99
RS
5946 else
5947 error ("No default file name");
5948 }
62f555a5 5949 val = Fsubstitute_in_file_name (val);
570d7624 5950
62f555a5
RS
5951 if (replace_in_history)
5952 /* Replace what Fcompleting_read added to the history
5953 with what we will actually return. */
f3fbd155 5954 XSETCAR (Fsymbol_value (Qfile_name_history), double_dollars (val));
62f555a5 5955 else if (add_to_history)
570d7624 5956 {
62f555a5
RS
5957 /* Add the value to the history--but not if it matches
5958 the last value already there. */
8d6d9fef 5959 Lisp_Object val1 = double_dollars (val);
62f555a5 5960 tem = Fsymbol_value (Qfile_name_history);
03699b14 5961 if (! CONSP (tem) || NILP (Fequal (XCAR (tem), val1)))
62f555a5 5962 Fset (Qfile_name_history,
8d6d9fef 5963 Fcons (val1, tem));
570d7624 5964 }
9c856db9 5965
62f555a5 5966 return val;
570d7624 5967}
9c856db9 5968
570d7624 5969\f
dbda5089
GV
5970void
5971init_fileio_once ()
5972{
5973 /* Must be set before any path manipulation is performed. */
5974 XSETFASTINT (Vdirectory_sep_char, '/');
5975}
5976
9c856db9 5977\f
dfcf069d 5978void
570d7624
JB
5979syms_of_fileio ()
5980{
0bf2eed2 5981 Qexpand_file_name = intern ("expand-file-name");
273e0829 5982 Qsubstitute_in_file_name = intern ("substitute-in-file-name");
0bf2eed2
RS
5983 Qdirectory_file_name = intern ("directory-file-name");
5984 Qfile_name_directory = intern ("file-name-directory");
5985 Qfile_name_nondirectory = intern ("file-name-nondirectory");
642ef245 5986 Qunhandled_file_name_directory = intern ("unhandled-file-name-directory");
0bf2eed2 5987 Qfile_name_as_directory = intern ("file-name-as-directory");
32f4334d 5988 Qcopy_file = intern ("copy-file");
a6e6e718 5989 Qmake_directory_internal = intern ("make-directory-internal");
b272d624 5990 Qmake_directory = intern ("make-directory");
32f4334d
RS
5991 Qdelete_directory = intern ("delete-directory");
5992 Qdelete_file = intern ("delete-file");
5993 Qrename_file = intern ("rename-file");
5994 Qadd_name_to_file = intern ("add-name-to-file");
5995 Qmake_symbolic_link = intern ("make-symbolic-link");
5996 Qfile_exists_p = intern ("file-exists-p");
5997 Qfile_executable_p = intern ("file-executable-p");
5998 Qfile_readable_p = intern ("file-readable-p");
32f4334d 5999 Qfile_writable_p = intern ("file-writable-p");
1f8653eb
RS
6000 Qfile_symlink_p = intern ("file-symlink-p");
6001 Qaccess_file = intern ("access-file");
32f4334d 6002 Qfile_directory_p = intern ("file-directory-p");
adedc71d 6003 Qfile_regular_p = intern ("file-regular-p");
32f4334d
RS
6004 Qfile_accessible_directory_p = intern ("file-accessible-directory-p");
6005 Qfile_modes = intern ("file-modes");
6006 Qset_file_modes = intern ("set-file-modes");
6007 Qfile_newer_than_file_p = intern ("file-newer-than-file-p");
6008 Qinsert_file_contents = intern ("insert-file-contents");
6009 Qwrite_region = intern ("write-region");
6010 Qverify_visited_file_modtime = intern ("verify-visited-file-modtime");
3ec46acd 6011 Qset_visited_file_modtime = intern ("set-visited-file-modtime");
32f4334d 6012
642ef245 6013 staticpro (&Qexpand_file_name);
273e0829 6014 staticpro (&Qsubstitute_in_file_name);
642ef245
JB
6015 staticpro (&Qdirectory_file_name);
6016 staticpro (&Qfile_name_directory);
6017 staticpro (&Qfile_name_nondirectory);
6018 staticpro (&Qunhandled_file_name_directory);
6019 staticpro (&Qfile_name_as_directory);
15c65264 6020 staticpro (&Qcopy_file);
c34b559d 6021 staticpro (&Qmake_directory_internal);
b272d624 6022 staticpro (&Qmake_directory);
15c65264
RS
6023 staticpro (&Qdelete_directory);
6024 staticpro (&Qdelete_file);
6025 staticpro (&Qrename_file);
6026 staticpro (&Qadd_name_to_file);
6027 staticpro (&Qmake_symbolic_link);
6028 staticpro (&Qfile_exists_p);
6029 staticpro (&Qfile_executable_p);
6030 staticpro (&Qfile_readable_p);
15c65264 6031 staticpro (&Qfile_writable_p);
1f8653eb
RS
6032 staticpro (&Qaccess_file);
6033 staticpro (&Qfile_symlink_p);
15c65264 6034 staticpro (&Qfile_directory_p);
adedc71d 6035 staticpro (&Qfile_regular_p);
15c65264
RS
6036 staticpro (&Qfile_accessible_directory_p);
6037 staticpro (&Qfile_modes);
6038 staticpro (&Qset_file_modes);
6039 staticpro (&Qfile_newer_than_file_p);
6040 staticpro (&Qinsert_file_contents);
6041 staticpro (&Qwrite_region);
6042 staticpro (&Qverify_visited_file_modtime);
0a61794b 6043 staticpro (&Qset_visited_file_modtime);
642ef245
JB
6044
6045 Qfile_name_history = intern ("file-name-history");
6046 Fset (Qfile_name_history, Qnil);
15c65264
RS
6047 staticpro (&Qfile_name_history);
6048
570d7624
JB
6049 Qfile_error = intern ("file-error");
6050 staticpro (&Qfile_error);
199607e4 6051 Qfile_already_exists = intern ("file-already-exists");
570d7624 6052 staticpro (&Qfile_already_exists);
c0b7b21c
RS
6053 Qfile_date_error = intern ("file-date-error");
6054 staticpro (&Qfile_date_error);
505ab9bc
RS
6055 Qexcl = intern ("excl");
6056 staticpro (&Qexcl);
570d7624 6057
5e570b75 6058#ifdef DOS_NT
4c3c22f3
RS
6059 Qfind_buffer_file_type = intern ("find-buffer-file-type");
6060 staticpro (&Qfind_buffer_file_type);
5e570b75 6061#endif /* DOS_NT */
4c3c22f3 6062
b1d1b865 6063 DEFVAR_LISP ("file-name-coding-system", &Vfile_name_coding_system,
8c1a1077
PJ
6064 doc: /* *Coding system for encoding file names.
6065If it is nil, default-file-name-coding-system (which see) is used. */);
b1d1b865
RS
6066 Vfile_name_coding_system = Qnil;
6067
cd913586
KH
6068 DEFVAR_LISP ("default-file-name-coding-system",
6069 &Vdefault_file_name_coding_system,
8c1a1077
PJ
6070 doc: /* Default coding system for encoding file names.
6071This variable is used only when file-name-coding-system is nil.
6072
6073This variable is set/changed by the command set-language-environment.
6074User should not set this variable manually,
6075instead use file-name-coding-system to get a constant encoding
6076of file names regardless of the current language environment. */);
cd913586
KH
6077 Vdefault_file_name_coding_system = Qnil;
6078
0d420e88 6079 DEFVAR_LISP ("auto-save-file-format", &Vauto_save_file_format,
8c1a1077
PJ
6080 doc: /* *Format in which to write auto-save files.
6081Should be a list of symbols naming formats that are defined in `format-alist'.
6082If it is t, which is the default, auto-save files are written in the
6083same format as a regular save would use. */);
0d420e88
BG
6084 Vauto_save_file_format = Qt;
6085
6086 Qformat_decode = intern ("format-decode");
6087 staticpro (&Qformat_decode);
6088 Qformat_annotate_function = intern ("format-annotate-function");
6089 staticpro (&Qformat_annotate_function);
6090
d6a3cc15
RS
6091 Qcar_less_than_car = intern ("car-less-than-car");
6092 staticpro (&Qcar_less_than_car);
6093
570d7624
JB
6094 Fput (Qfile_error, Qerror_conditions,
6095 Fcons (Qfile_error, Fcons (Qerror, Qnil)));
6096 Fput (Qfile_error, Qerror_message,
6097 build_string ("File error"));
6098
6099 Fput (Qfile_already_exists, Qerror_conditions,
6100 Fcons (Qfile_already_exists,
6101 Fcons (Qfile_error, Fcons (Qerror, Qnil))));
6102 Fput (Qfile_already_exists, Qerror_message,
6103 build_string ("File already exists"));
6104
c0b7b21c
RS
6105 Fput (Qfile_date_error, Qerror_conditions,
6106 Fcons (Qfile_date_error,
6107 Fcons (Qfile_error, Fcons (Qerror, Qnil))));
6108 Fput (Qfile_date_error, Qerror_message,
6109 build_string ("Cannot set file date"));
6110
570d7624 6111 DEFVAR_BOOL ("insert-default-directory", &insert_default_directory,
8c1a1077 6112 doc: /* *Non-nil means when reading a filename start with default dir in minibuffer. */);
570d7624
JB
6113 insert_default_directory = 1;
6114
6115 DEFVAR_BOOL ("vms-stmlf-recfm", &vms_stmlf_recfm,
8c1a1077
PJ
6116 doc: /* *Non-nil means write new files with record format `stmlf'.
6117nil means use format `var'. This variable is meaningful only on VMS. */);
570d7624
JB
6118 vms_stmlf_recfm = 0;
6119
199607e4 6120 DEFVAR_LISP ("directory-sep-char", &Vdirectory_sep_char,
8c1a1077
PJ
6121 doc: /* Directory separator character for built-in functions that return file names.
6122The value should be either ?/ or ?\\ (any other value is treated as ?\\).
6123This variable affects the built-in functions only on Windows,
6124on other platforms, it is initialized so that Lisp code can find out
6125what the normal separator is.
6126
6127WARNING: This variable is deprecated and will be removed in the near
6128future. DO NOT USE IT. */);
199607e4 6129
1d1826db 6130 DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist,
8c1a1077
PJ
6131 doc: /* *Alist of elements (REGEXP . HANDLER) for file names handled specially.
6132If a file name matches REGEXP, then all I/O on that file is done by calling
6133HANDLER.
6134
6135The first argument given to HANDLER is the name of the I/O primitive
6136to be handled; the remaining arguments are the arguments that were
6137passed to that primitive. For example, if you do
6138 (file-exists-p FILENAME)
6139and FILENAME is handled by HANDLER, then HANDLER is called like this:
6140 (funcall HANDLER 'file-exists-p FILENAME)
6141The function `find-file-name-handler' checks this list for a handler
6142for its argument. */);
09121adc
RS
6143 Vfile_name_handler_alist = Qnil;
6144
0414b394
KH
6145 DEFVAR_LISP ("set-auto-coding-function",
6146 &Vset_auto_coding_function,
8c1a1077
PJ
6147 doc: /* If non-nil, a function to call to decide a coding system of file.
6148Two arguments are passed to this function: the file name
6149and the length of a file contents following the point.
6150This function should return a coding system to decode the file contents.
6151It should check the file name against `auto-coding-alist'.
6152If no coding system is decided, it should check a coding system
6153specified in the heading lines with the format:
6154 -*- ... coding: CODING-SYSTEM; ... -*-
6155or local variable spec of the tailing lines with `coding:' tag. */);
0414b394 6156 Vset_auto_coding_function = Qnil;
c9e82392 6157
d6a3cc15 6158 DEFVAR_LISP ("after-insert-file-functions", &Vafter_insert_file_functions,
8c1a1077
PJ
6159 doc: /* A list of functions to be called at the end of `insert-file-contents'.
6160Each is passed one argument, the number of bytes inserted. It should return
6161the new byte count, and leave point the same. If `insert-file-contents' is
6162intercepted by a handler from `file-name-handler-alist', that handler is
6163responsible for calling the after-insert-file-functions if appropriate. */);
d6a3cc15
RS
6164 Vafter_insert_file_functions = Qnil;
6165
6166 DEFVAR_LISP ("write-region-annotate-functions", &Vwrite_region_annotate_functions,
8c1a1077
PJ
6167 doc: /* A list of functions to be called at the start of `write-region'.
6168Each is passed two arguments, START and END as for `write-region'.
6169These are usually two numbers but not always; see the documentation
6170for `write-region'. The function should return a list of pairs
6171of the form (POSITION . STRING), consisting of strings to be effectively
6172inserted at the specified positions of the file being written (1 means to
6173insert before the first byte written). The POSITIONs must be sorted into
6174increasing order. If there are several functions in the list, the several
6175lists are merged destructively. */);
d6a3cc15
RS
6176 Vwrite_region_annotate_functions = Qnil;
6177
6fc6f94b
RS
6178 DEFVAR_LISP ("write-region-annotations-so-far",
6179 &Vwrite_region_annotations_so_far,
8c1a1077
PJ
6180 doc: /* When an annotation function is called, this holds the previous annotations.
6181These are the annotations made by other annotation functions
6182that were already called. See also `write-region-annotate-functions'. */);
6fc6f94b
RS
6183 Vwrite_region_annotations_so_far = Qnil;
6184
82c2d839 6185 DEFVAR_LISP ("inhibit-file-name-handlers", &Vinhibit_file_name_handlers,
8c1a1077
PJ
6186 doc: /* A list of file name handlers that temporarily should not be used.
6187This applies only to the operation `inhibit-file-name-operation'. */);
82c2d839
RS
6188 Vinhibit_file_name_handlers = Qnil;
6189
a65970a0 6190 DEFVAR_LISP ("inhibit-file-name-operation", &Vinhibit_file_name_operation,
8c1a1077 6191 doc: /* The operation for which `inhibit-file-name-handlers' is applicable. */);
a65970a0
RS
6192 Vinhibit_file_name_operation = Qnil;
6193
e54d3b5d 6194 DEFVAR_LISP ("auto-save-list-file-name", &Vauto_save_list_file_name,
8c1a1077
PJ
6195 doc: /* File name in which we write a list of all auto save file names.
6196This variable is initialized automatically from `auto-save-list-file-prefix'
6197shortly after Emacs reads your `.emacs' file, if you have not yet given it
6198a non-nil value. */);
e54d3b5d
RS
6199 Vauto_save_list_file_name = Qnil;
6200
642ef245 6201 defsubr (&Sfind_file_name_handler);
570d7624
JB
6202 defsubr (&Sfile_name_directory);
6203 defsubr (&Sfile_name_nondirectory);
642ef245 6204 defsubr (&Sunhandled_file_name_directory);
570d7624
JB
6205 defsubr (&Sfile_name_as_directory);
6206 defsubr (&Sdirectory_file_name);
6207 defsubr (&Smake_temp_name);
6208 defsubr (&Sexpand_file_name);
6209 defsubr (&Ssubstitute_in_file_name);
6210 defsubr (&Scopy_file);
9bbe01fb 6211 defsubr (&Smake_directory_internal);
aa734e17 6212 defsubr (&Sdelete_directory);
570d7624
JB
6213 defsubr (&Sdelete_file);
6214 defsubr (&Srename_file);
6215 defsubr (&Sadd_name_to_file);
6216#ifdef S_IFLNK
6217 defsubr (&Smake_symbolic_link);
6218#endif /* S_IFLNK */
6219#ifdef VMS
6220 defsubr (&Sdefine_logical_name);
6221#endif /* VMS */
6222#ifdef HPUX_NET
6223 defsubr (&Ssysnetunam);
6224#endif /* HPUX_NET */
6225 defsubr (&Sfile_name_absolute_p);
6226 defsubr (&Sfile_exists_p);
6227 defsubr (&Sfile_executable_p);
6228 defsubr (&Sfile_readable_p);
6229 defsubr (&Sfile_writable_p);
1f8653eb 6230 defsubr (&Saccess_file);
570d7624
JB
6231 defsubr (&Sfile_symlink_p);
6232 defsubr (&Sfile_directory_p);
b72dea2a 6233 defsubr (&Sfile_accessible_directory_p);
f793dc6c 6234 defsubr (&Sfile_regular_p);
570d7624
JB
6235 defsubr (&Sfile_modes);
6236 defsubr (&Sset_file_modes);
c24e9a53
RS
6237 defsubr (&Sset_default_file_modes);
6238 defsubr (&Sdefault_file_modes);
570d7624
JB
6239 defsubr (&Sfile_newer_than_file_p);
6240 defsubr (&Sinsert_file_contents);
6241 defsubr (&Swrite_region);
d6a3cc15 6242 defsubr (&Scar_less_than_car);
570d7624
JB
6243 defsubr (&Sverify_visited_file_modtime);
6244 defsubr (&Sclear_visited_file_modtime);
f5d5eccf 6245 defsubr (&Svisited_file_modtime);
570d7624
JB
6246 defsubr (&Sset_visited_file_modtime);
6247 defsubr (&Sdo_auto_save);
6248 defsubr (&Sset_buffer_auto_saved);
b60247d9 6249 defsubr (&Sclear_buffer_auto_save_failure);
570d7624
JB
6250 defsubr (&Srecent_auto_save_p);
6251
6252 defsubr (&Sread_file_name_internal);
6253 defsubr (&Sread_file_name);
85ffea93 6254
483a2e10 6255#ifdef unix
85ffea93 6256 defsubr (&Sunix_sync);
483a2e10 6257#endif
570d7624 6258}
71e1147d 6259