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