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