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