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