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