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