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