comparison src/fileio.c @ 211:78478c60bfcd r20-4b4

Import from CVS: tag r20-4b4
author cvs
date Mon, 13 Aug 2007 10:05:51 +0200
parents 41ff10fd062f
children 78f53ef88e17
comparison
equal deleted inserted replaced
210:49f55ca3ba57 211:78478c60bfcd
18 along with XEmacs; see the file COPYING. If not, write to 18 along with XEmacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */ 20 Boston, MA 02111-1307, USA. */
21 21
22 /* Synched up with: Mule 2.0, FSF 19.30. */ 22 /* Synched up with: Mule 2.0, FSF 19.30. */
23 /* More syncing: FSF Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */
23 24
24 #include <config.h> 25 #include <config.h>
25 #include "lisp.h" 26 #include "lisp.h"
26 27
27 #include "buffer.h" 28 #include "buffer.h"
47 48
48 #ifdef HPUX 49 #ifdef HPUX
49 #include <netio.h> 50 #include <netio.h>
50 #ifdef HPUX_PRE_8_0 51 #ifdef HPUX_PRE_8_0
51 #include <errnet.h> 52 #include <errnet.h>
53 #endif /* HPUX_PRE_8_0 */
54 #endif /* HPUX */
55
56 #ifdef WINDOWSNT
57 #define NOMINMAX 1
58 #include <windows.h>
59 #include <stdlib.h>
60 #include <fcntl.h>
61 #endif /* not WINDOWSNT */
62
63 #ifdef DOS_NT
64 #define CORRECT_DIR_SEPS(s) \
65 do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \
66 else unixtodos_filename (s); \
67 } while (0)
68 /* On Windows, drive letters must be alphabetic - on DOS, the Netware
69 redirector allows the six letters between 'Z' and 'a' as well. */
70 #ifdef MSDOS
71 #define IS_DRIVE(x) ((x) >= 'A' && (x) <= 'z')
52 #endif 72 #endif
53 #endif /* HPUX */ 73 #ifdef WINDOWSNT
74 #define IS_DRIVE(x) isalpha (x)
75 #endif
76 /* Need to lower-case the drive letter, or else expanded
77 filenames will sometimes compare inequal, because
78 `expand-file-name' doesn't always down-case the drive letter. */
79 #define DRIVE_LETTER(x) (tolower (x))
80 #endif /* DOS_NT */
54 81
55 /* Nonzero during writing of auto-save files */ 82 /* Nonzero during writing of auto-save files */
56 static int auto_saving; 83 static int auto_saving;
57 84
58 /* Set by auto_save_1 to mode of original file so Fwrite_region_internal 85 /* Set by auto_save_1 to mode of original file so Fwrite_region_internal
83 Lisp_Object Vauto_save_list_file_name; 110 Lisp_Object Vauto_save_list_file_name;
84 111
85 int disable_auto_save_when_buffer_shrinks; 112 int disable_auto_save_when_buffer_shrinks;
86 113
87 Lisp_Object Qfile_name_handler_alist; 114 Lisp_Object Qfile_name_handler_alist;
115
116 #ifdef DOS_NT
117 /* Until we can figure out how to deal with the functions in this file in
118 a civilized fashion, this will remain #ifdef'ed out. -slb */
119 /* Syncing with FSF 19.34.6 note: although labelled as NT-specific, these
120 two lisp variables are compiled in even when not defined(DOS_NT).
121 Need to check if we should bracket them between #ifdef's.
122 --marcpa */
123 /* On NT, specifies the directory separator character, used (eg.) when
124 expanding file names. This can be bound to / or \.
125
126 This needs to be initialized statically, because file name functions
127 are called during initialization. */
128 Lisp_Object Vdirectory_sep_char = '/';
129
130 /* For the benefit of backwards compatability with earlier versions of
131 Emacs on DOS_NT, provide a way to disable the REPLACE option support
132 in insert-file-contents. */
133 Lisp_Object Vinsert_file_contents_allow_replace;
134 #endif /* DOS_NT */
88 135
89 /* These variables describe handlers that have "already" had a chance 136 /* These variables describe handlers that have "already" had a chance
90 to handle the current operation. 137 to handle the current operation.
91 138
92 Vinhibit_file_name_handlers is a list of file name handlers. 139 Vinhibit_file_name_handlers is a list of file name handlers.
413 file = FILE_SYSTEM_CASE (file); 460 file = FILE_SYSTEM_CASE (file);
414 #endif 461 #endif
415 beg = XSTRING_DATA (file); 462 beg = XSTRING_DATA (file);
416 p = beg + XSTRING_LENGTH (file); 463 p = beg + XSTRING_LENGTH (file);
417 464
418 while (p != beg && !IS_ANY_SEP (p[-1])) 465 while (p != beg && !IS_ANY_SEP (p[-1])
419 p--; 466 #ifdef DOS_NT
467 /* only recognise drive specifier at beginning */
468 && !(p[-1] == ':' && p == beg + 2)
469 #endif
470 ) p--;
420 471
421 if (p == beg) 472 if (p == beg)
422 return Qnil; 473 return Qnil;
423 #ifdef DOS_NT 474 #ifdef DOS_NT
424 /* Expansion of "c:" to drive and default directory. */ 475 /* Expansion of "c:" to drive and default directory. */
425 /* (NT does the right thing.) */ 476 /* (NT does the right thing.) */
426 if (p == beg + 2 && beg[1] == ':') 477 if (p == beg + 2 && beg[1] == ':')
427 { 478 {
428 int drive = (*beg) - 'a';
429 /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */ 479 /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */
430 Bufbyte *res = (Bufbyte *) alloca (MAXPATHLEN + 5); 480 Bufbyte *res = alloca (MAXPATHLEN + 1);
431 unsigned char *res1; 481 if (getdefdir (toupper (*beg) - 'A' + 1, res))
432 #ifdef WINDOWSNT
433 res1 = res;
434 /* The NT version places the drive letter at the beginning already. */
435 #else /* not WINDOWSNT */
436 /* On MSDOG we must put the drive letter in by hand. */
437 res1 = res + 2;
438 #endif /* not WINDOWSNT */
439 if (getdefdir (drive + 1, res))
440 { 482 {
441 #ifdef MSDOS 483 if (!IS_DIRECTORY_SEP (res[strlen ((char *) res) - 1]))
442 res[0] = drive + 'a';
443 res[1] = ':';
444 #endif /* MSDOS */
445 if (IS_DIRECTORY_SEP (res[strlen ((char *) res) - 1]))
446 strcat ((char *) res, "/"); 484 strcat ((char *) res, "/");
447 beg = res; 485 beg = res;
448 p = beg + strlen ((char *) beg); 486 p = beg + strlen ((char *) beg);
449 } 487 }
450 } 488 }
489 CORRECT_DIR_SEPS (beg);
451 #endif /* DOS_NT */ 490 #endif /* DOS_NT */
452 return make_string (beg, p - beg); 491 return make_string (beg, p - beg);
453 } 492 }
454 493
455 DEFUN ("file-name-nondirectory", Ffile_name_nondirectory, 1, 1, 0, /* 494 DEFUN ("file-name-nondirectory", Ffile_name_nondirectory, 1, 1, 0, /*
473 return call2_check_string (handler, Qfile_name_nondirectory, file); 512 return call2_check_string (handler, Qfile_name_nondirectory, file);
474 513
475 beg = XSTRING_DATA (file); 514 beg = XSTRING_DATA (file);
476 end = p = beg + XSTRING_LENGTH (file); 515 end = p = beg + XSTRING_LENGTH (file);
477 516
478 while (p != beg && !IS_ANY_SEP (p[-1])) 517 while (p != beg && !IS_ANY_SEP (p[-1])
479 p--; 518 #ifdef DOS_NT
519 /* only recognise drive specifier at beginning */
520 && !(p[-1] == ':' && p == beg + 2)
521 #endif
522 ) p--;
480 523
481 return make_string (p, end - p); 524 return make_string (p, end - p);
482 } 525 }
483 526
484 DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory, 1, 1, 0, /* 527 DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory, 1, 1, 0, /*
549 (buf, (char *) XSTRING_DATA (file))); 592 (buf, (char *) XSTRING_DATA (file)));
550 } 593 }
551 594
552 /* 595 /*
553 * Convert from directory name to filename. 596 * Convert from directory name to filename.
554 * On UNIX, it's simple: just make sure there is a terminating / 597 * On UNIX, it's simple: just make sure there isn't a terminating /
555 598
556 * Value is nonzero if the string output is different from the input. 599 * Value is nonzero if the string output is different from the input.
557 */ 600 */
558 601
559 static int 602 static int
573 #else 616 #else
574 if (slen > 1 617 if (slen > 1
575 && IS_DIRECTORY_SEP (dst[slen - 1]) 618 && IS_DIRECTORY_SEP (dst[slen - 1])
576 #ifdef DOS_NT 619 #ifdef DOS_NT
577 && !IS_ANY_SEP (dst[slen - 2]) 620 && !IS_ANY_SEP (dst[slen - 2])
578 #endif 621 #endif /* DOS_NT */
579 ) 622 )
580 dst[slen - 1] = 0; 623 dst[slen - 1] = 0;
581 #endif 624 #endif /* APOLLO */
625 #ifdef DOS_NT
626 CORRECT_DIR_SEPS (dst);
627 #endif /* DOS_NT */
582 return 1; 628 return 1;
583 } 629 }
584 630
585 DEFUN ("directory-file-name", Fdirectory_file_name, 1, 1, 0, /* 631 DEFUN ("directory-file-name", Fdirectory_file_name, 1, 1, 0, /*
586 Return the file name of the directory named DIR. 632 Return the file name of the directory named DIR.
631 memcpy (data, XSTRING_DATA (prefix), len); 677 memcpy (data, XSTRING_DATA (prefix), len);
632 memcpy (data + len, suffix, countof (suffix)); 678 memcpy (data + len, suffix, countof (suffix));
633 /* !!#### does mktemp() Mule-encapsulate? */ 679 /* !!#### does mktemp() Mule-encapsulate? */
634 mktemp ((char *) data); 680 mktemp ((char *) data);
635 681
682 #ifdef DOS_NT
683 CORRECT_DIR_SEPS (XSTRING_DATA (val));
684 #endif /* DOS_NT */
636 return val; 685 return val;
637 } 686 }
638 687
639 DEFUN ("expand-file-name", Fexpand_file_name, 1, 2, 0, /* 688 DEFUN ("expand-file-name", Fexpand_file_name, 1, 2, 0, /*
640 Convert FILENAME to absolute, and canonicalize it. 689 Convert FILENAME to absolute, and canonicalize it.
657 Bufbyte *newdir, *p, *o; 706 Bufbyte *newdir, *p, *o;
658 int tlen; 707 int tlen;
659 Bufbyte *target; 708 Bufbyte *target;
660 struct passwd *pw; 709 struct passwd *pw;
661 #ifdef DOS_NT 710 #ifdef DOS_NT
662 /* Demacs 1.1.2 91/10/20 Manabu Higashida */ 711 int drive = 0;
663 int drive = -1; 712 int collapse_newdir = 1;
664 int relpath = 0; 713 int length;
665 Bufbyte *tmp, *defdir;
666 #endif /* DOS_NT */ 714 #endif /* DOS_NT */
667 Lisp_Object handler; 715 Lisp_Object handler;
668 716
669 CHECK_STRING (name); 717 CHECK_STRING (name);
670 718
710 the code and forget to adjust them, resulting in intermittent bugs. 758 the code and forget to adjust them, resulting in intermittent bugs.
711 Putting this call here avoids all that crud. 759 Putting this call here avoids all that crud.
712 760
713 The EQ test avoids infinite recursion. */ 761 The EQ test avoids infinite recursion. */
714 if (! NILP(default_) && !EQ (default_, name) 762 if (! NILP(default_) && !EQ (default_, name)
715 /* This saves time in a common case. */ 763 /* Save time in some common cases - as long as default_directory
764 is not relative, it can be canonicalized with name below (if it
765 is needed at all) without requiring it to be expanded now. */
716 && ! (XSTRING_LENGTH (default_) >= 3 766 && ! (XSTRING_LENGTH (default_) >= 3
767 #ifdef DOS_NT
768 /* Detect MSDOS file names with drive specifiers. */
769 && (IS_DRIVE (XSTRING_BYTE (default_, 0))
770 && (IS_DEVICE_SEP (XSTRING_BYTE (default_, 1))
771 IS_DIRECTORY_SEP (XSTRING_BYTE (default_, 2)))))
772 #ifdef WINDOWSNT
773 /* Detect Windows file names in UNC format. */
774 && ! (XSTRING_LENGTH (default_) >= 2
775 && IS_DIRECTORY_SEP (XSTRING_BYTE (default_, 0))
776 && IS_DIRECTORY_SEP (XSTRING_BYTE (default_, 1)))
777 #endif
778 #else /* not DOS_NT */
779 /* Detect Unix absolute file names (/... alone is not absolute on
780 DOS or Windows). */
717 && (IS_DIRECTORY_SEP (XSTRING_BYTE (default_, 0)) 781 && (IS_DIRECTORY_SEP (XSTRING_BYTE (default_, 0))
718 || IS_DEVICE_SEP (XSTRING_BYTE (default_, 1))))) 782 || IS_DEVICE_SEP (XSTRING_BYTE (default_, 1))))
783 #endif /* not DOS_NT */
784 )
719 { 785 {
720 struct gcpro gcpro1; 786 struct gcpro gcpro1;
721 787
722 GCPRO1 (default_); /* may be current_buffer->directory */ 788 GCPRO1 (default_); /* may be current_buffer->directory */
723 default_ = Fexpand_file_name (default_, Qnil); 789 default_ = Fexpand_file_name (default_, Qnil);
730 796
731 /* #### dmoore - this is ugly, clean this up. Looks like nm 797 /* #### dmoore - this is ugly, clean this up. Looks like nm
732 pointing into name should be safe during all of this, though. */ 798 pointing into name should be safe during all of this, though. */
733 nm = XSTRING_DATA (name); 799 nm = XSTRING_DATA (name);
734 800
735 #ifdef MSDOS
736 /* First map all backslashes to slashes. */
737 dostounix_filename (nm = strcpy (alloca (strlen (nm) + 1), nm));
738 #endif
739
740 #ifdef DOS_NT 801 #ifdef DOS_NT
741 /* Now strip drive name. */ 802 /* We will force directory separators to be either all \ or /, so make
803 a local copy to modify, even if there ends up being no change. */
804 nm = strcpy (alloca (strlen (nm) + 1), nm);
805
806 /* Find and remove drive specifier if present; this makes nm absolute
807 even if the rest of the name appears to be relative. */
742 { 808 {
743 Bufbyte *colon = strrchr (nm, ':'); 809 Bufbyte *colon = strrchr (nm, ':');
744 if (colon) 810 if (colon)
811 /* Only recognize colon as part of drive specifier if there is a
812 single alphabetic character preceeding the colon (and if the
813 character before the drive letter, if present, is a directory
814 separator); this is to support the remote system syntax used by
815 ange-ftp, and the "po:username" syntax for POP mailboxes. */
816 look_again:
745 if (nm == colon) 817 if (nm == colon)
746 nm++; 818 nm++;
747 else 819 else if (IS_DRIVE (colon[-1])
820 && (colon == nm + 1 || IS_DIRECTORY_SEP (colon[-2])))
748 { 821 {
749 drive = colon[-1]; 822 drive = colon[-1];
750 nm = colon + 1; 823 nm = colon + 1;
751 if (!IS_DIRECTORY_SEP (*nm)) 824 }
752 { 825 else
753 defdir = alloca (MAXPATHLEN + 1); 826 {
754 relpath = getdefdir (tolower (drive) - 'a' + 1, defdir); 827 while (--colon >= nm)
755 } 828 if (colon[0] == ':')
829 goto look_again;
756 } 830 }
757 } 831 }
832
833 #ifdef WINDOWSNT
834 /* If we see "c://somedir", we want to strip the first slash after the
835 colon when stripping the drive letter. Otherwise, this expands to
836 "//somedir". */
837 if (drive && IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
838 nm++;
839 #endif /* WINDOWSNT */
758 #endif /* DOS_NT */ 840 #endif /* DOS_NT */
759 841
760 /* We *don't* want to handle // and /~ that way. */ 842 /* We *don't* want to handle // and /~ that way. */
761 #if 0 843 #if 0
762 /* Handle // and /~ in middle of file name 844 /* Handle // and /~ in middle of file name
782 if (IS_DIRECTORY_SEP (p[0]) && p[1] == '~') 864 if (IS_DIRECTORY_SEP (p[0]) && p[1] == '~')
783 nm = p + 1; 865 nm = p + 1;
784 866
785 p++; 867 p++;
786 } 868 }
869
870 #endif /* 0 */
871
872 #ifdef WINDOWSNT
873 /* Discard any previous drive specifier if nm is now in UNC format. */
874 if (IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
875 {
876 drive = 0;
877 }
878 #endif /* WINDOWSNT */
879
880 /* If nm is absolute, look for /./ or /../ sequences; if none are
881 found, we can probably return right away. We will avoid allocating
882 a new string if name is already fully expanded. */
883 if (IS_DIRECTORY_SEP (nm[0])
884 #ifdef WINDOWSNT
885 && (drive || IS_DIRECTORY_SEP (nm[1]))
787 #endif 886 #endif
788 887 )
789 /* If nm is absolute, flush ...// and detect /./ and /../.
790 If no /./ or /../ we can return right away. */
791 if (IS_DIRECTORY_SEP (nm[0]))
792 { 888 {
793 /* If it turns out that the filename we want to return is just a 889 /* If it turns out that the filename we want to return is just a
794 suffix of FILENAME, we don't need to go through and edit 890 suffix of FILENAME, we don't need to go through and edit
795 things; we just need to construct a new string using data 891 things; we just need to construct a new string using data
796 starting at the middle of FILENAME. If we set lose to a 892 starting at the middle of FILENAME. If we set lose to a
814 lose = 1; 910 lose = 1;
815 p++; 911 p++;
816 } 912 }
817 if (!lose) 913 if (!lose)
818 { 914 {
819 #ifndef DOS_NT 915 #ifdef DOS_NT
916 /* Make sure directories are all separated with / or \ as
917 desired, but avoid allocation of a new string when not
918 required. */
919 CORRECT_DIR_SEPS (nm);
920 #ifdef WINDOWSNT
921 if (IS_DIRECTORY_SEP (nm[1]))
922 {
923 if (strcmp (nm, XSTRING_DATA (name)) != 0)
924 name = build_string (nm);
925 }
926 else
927 #endif
928 /* drive must be set, so this is okay */
929 if (strcmp (nm - 2, XSTRING_DATA (name)) != 0)
930 {
931 name = make_string (nm - 2, p - nm + 2);
932 XSTRING_DATA (name)[0] = DRIVE_LETTER (drive);
933 XSTRING_DATA (name)[1] = ':';
934 }
935 return name;
936 #else /* not DOS_NT */
937 /* Unix */
820 if (nm == XSTRING_DATA (name)) 938 if (nm == XSTRING_DATA (name))
821 return name; 939 return name;
822 return build_string ((char *) nm); 940 return build_string ((char *) nm);
823 #endif /* not DOS_NT */ 941 #endif /* DOS_NT */
824 } 942 }
825 } 943 }
826 944
827 /* Now determine directory to start with and put it in newdir */ 945 /* At this point, nm might or might not be an absolute file name. We
946 need to expand ~ or ~user if present, otherwise prefix nm with
947 default_directory if nm is not absolute, and finally collapse /./
948 and /foo/../ sequences.
949
950 We set newdir to be the appropriate prefix if one is needed:
951 - the relevant user directory if nm starts with ~ or ~user
952 - the specified drive's working dir (DOS/NT only) if nm does not
953 start with /
954 - the value of default_directory.
955
956 Note that these prefixes are not guaranteed to be absolute (except
957 for the working dir of a drive). Therefore, to ensure we always
958 return an absolute name, if the final prefix is not absolute we
959 append it to the current working directory. */
828 960
829 newdir = 0; 961 newdir = 0;
830 962
831 if (nm[0] == '~') /* prefix ~ */ 963 if (nm[0] == '~') /* prefix ~ */
832 { 964 {
833 if (IS_DIRECTORY_SEP (nm[1]) 965 if (IS_DIRECTORY_SEP (nm[1])
834 || nm[1] == 0) /* ~ by itself */ 966 || nm[1] == 0) /* ~ by itself */
835 { 967 {
836 if (!(newdir = (Bufbyte *) egetenv ("HOME"))) 968 if (!(newdir = (Bufbyte *) egetenv ("HOME")))
837 newdir = (Bufbyte *) ""; 969 newdir = (Bufbyte *) "";
970 /* Syncing with FSF 19.34.6 note: this is not in FSF. Since it is dated 1995,
971 I doubt it is coming from XEmacs. I (#if 0) it but let the code
972 stay there just in case. --marcpa */
973 #if 0
838 #ifdef DOS_NT 974 #ifdef DOS_NT
839 /* Problem when expanding "~\" if HOME is not on current drive. 975 /* Problem when expanding "~\" if HOME is not on current drive.
840 Ulrich Leodolter, Wed Jan 11 10:20:35 1995 */ 976 Ulrich Leodolter, Wed Jan 11 10:20:35 1995 */
841 if (newdir[1] == ':') 977 if (newdir[1] == ':')
842 drive = newdir[0]; 978 drive = newdir[0];
843 dostounix_filename (newdir); 979 dostounix_filename (newdir);
844 #endif /* DOS_NT */ 980 #endif /* DOS_NT */
981 #endif /* 0 */
845 nm++; 982 nm++;
983 #ifdef DOS_NT
984 collapse_newdir = 0;
985 #endif /* DOS_NT */
846 } 986 }
847 else /* ~user/filename */ 987 else /* ~user/filename */
848 { 988 {
849 for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)); p++); 989 for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)); p++);
850 o = (Bufbyte *) alloca (p - nm + 1); 990 o = (Bufbyte *) alloca (p - nm + 1);
851 memcpy (o, (char *) nm, p - nm); 991 memcpy (o, (char *) nm, p - nm);
852 o [p - nm] = 0; 992 o [p - nm] = 0;
853 993
994 /* Syncing with FSF 19.34.6 note: FSF uses getpwnam even on NT, which does
995 not work. The following works only if ~USER names the user who runs
996 this instance of XEmacs. While NT is single-user (for the moment) you
997 still can have multiple user profiles users defined, each with its
998 HOME. Therefore, the following should be reworked to handle this case.
999 --marcpa */
854 #ifdef WINDOWSNT 1000 #ifdef WINDOWSNT
855 /* 1001 /*
856 ** Now if the file given is "~foo/file" and HOME="c:/", then we 1002 ** Now if the file given is "~foo/file" and HOME="c:/", then we
857 ** want the file to be named "c:/file" ("~foo" becomes "c:/"). 1003 ** want the file to be named "c:/file" ("~foo" becomes "c:/").
858 ** The variable o has "~foo", so we can use the length of 1004 ** The variable o has "~foo", so we can use the length of
859 ** that string to offset nm. August Hill, 31 Aug 1998. 1005 ** that string to offset nm. August Hill, 31 Aug 1998.
860 */ 1006 */
861 newdir = (unsigned char *) egetenv ("HOME"); 1007 newdir = (Bufbyte *) egetenv ("HOME");
862 dostounix_filename (newdir); 1008 dostounix_filename (newdir);
863 nm += strlen(o) + 1; 1009 nm += strlen(o) + 1;
864 #else /* not WINDOWSNT */ 1010 #else /* not WINDOWSNT */
865 /* Jamie reports that getpwnam() can get wedged by SIGIO/SIGALARM 1011 /* Jamie reports that getpwnam() can get wedged by SIGIO/SIGALARM
866 occurring in it. (It can call select()). */ 1012 occurring in it. (It can call select()). */
877 /* If we don't find a user of that name, leave the name 1023 /* If we don't find a user of that name, leave the name
878 unchanged; don't move nm forward to p. */ 1024 unchanged; don't move nm forward to p. */
879 } 1025 }
880 } 1026 }
881 1027
882 if (!IS_ANY_SEP (nm[0])
883 #ifdef DOS_NT 1028 #ifdef DOS_NT
884 && drive == -1 1029 /* On DOS and Windows, nm is absolute if a drive name was specified;
1030 use the drive's current directory as the prefix if needed. */
1031 if (!newdir && drive)
1032 {
1033 /* Get default directory if needed to make nm absolute. */
1034 if (!IS_DIRECTORY_SEP (nm[0]))
1035 {
1036 newdir = alloca (MAXPATHLEN + 1);
1037 if (!getdefdir (toupper (drive) - 'A' + 1, newdir))
1038 newdir = NULL;
1039 }
1040 if (!newdir)
1041 {
1042 /* Either nm starts with /, or drive isn't mounted. */
1043 newdir = alloca (4);
1044 newdir[0] = DRIVE_LETTER (drive);
1045 newdir[1] = ':';
1046 newdir[2] = '/';
1047 newdir[3] = 0;
1048 }
1049 }
885 #endif /* DOS_NT */ 1050 #endif /* DOS_NT */
1051
1052 /* Finally, if no prefix has been specified and nm is not absolute,
1053 then it must be expanded relative to default_directory. */
1054 if (1
1055 #ifndef DOS_NT
1056 && !IS_ANY_SEP (nm[0])
1057 #endif /* not DOS_NT */
1058 #ifdef WINDOWSNT
1059 && !(IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
1060 #endif
886 && !newdir 1061 && !newdir
887 && STRINGP (default_)) 1062 && STRINGP (default_))
888 { 1063 {
889 newdir = XSTRING_DATA (default_); 1064 newdir = XSTRING_DATA (default_);
890 } 1065 }
891 1066
892 #ifdef DOS_NT 1067 #ifdef DOS_NT
893 if (newdir == 0 && relpath) 1068 if (newdir)
894 newdir = defdir; 1069 {
1070 /* First ensure newdir is an absolute name. */
1071 if (
1072 /* Detect MSDOS file names with drive specifiers. */
1073 ! (IS_DRIVE (newdir[0])
1074 && IS_DEVICE_SEP (newdir[1]) && IS_DIRECTORY_SEP (newdir[2]))
1075 #ifdef WINDOWSNT
1076 /* Detect Windows file names in UNC format. */
1077 && ! (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1]))
1078 #endif
1079 )
1080 {
1081 /* Effectively, let newdir be (expand-file-name newdir cwd).
1082 Because of the admonition against calling expand-file-name
1083 when we have pointers into lisp strings, we accomplish this
1084 indirectly by prepending newdir to nm if necessary, and using
1085 cwd (or the wd of newdir's drive) as the new newdir. */
1086
1087 if (IS_DRIVE (newdir[0]) && newdir[1] == ':')
1088 {
1089 drive = newdir[0];
1090 newdir += 2;
1091 }
1092 if (!IS_DIRECTORY_SEP (nm[0]))
1093 {
1094 char * tmp = alloca (strlen (newdir) + strlen (nm) + 2);
1095 file_name_as_directory (tmp, newdir);
1096 strcat (tmp, nm);
1097 nm = tmp;
1098 }
1099 newdir = alloca (MAXPATHLEN + 1);
1100 if (drive)
1101 {
1102 if (!getdefdir (toupper (drive) - 'A' + 1, newdir))
1103 newdir = "/";
1104 }
1105 else
1106 getwd (newdir);
1107 }
1108
1109 /* Strip off drive name from prefix, if present. */
1110 if (IS_DRIVE (newdir[0]) && newdir[1] == ':')
1111 {
1112 drive = newdir[0];
1113 newdir += 2;
1114 }
1115
1116 /* Keep only a prefix from newdir if nm starts with slash
1117 (//server/share for UNC, nothing otherwise). */
1118 if (IS_DIRECTORY_SEP (nm[0]) && collapse_newdir)
1119 {
1120 #ifdef WINDOWSNT
1121 if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1]))
1122 {
1123 newdir = strcpy (alloca (strlen (newdir) + 1), newdir);
1124 p = newdir + 2;
1125 while (*p && !IS_DIRECTORY_SEP (*p)) p++;
1126 p++;
1127 while (*p && !IS_DIRECTORY_SEP (*p)) p++;
1128 *p = 0;
1129 }
1130 else
1131 #endif
1132 newdir = "";
1133 }
1134 }
895 #endif /* DOS_NT */ 1135 #endif /* DOS_NT */
896 if (newdir != 0) 1136 if (newdir != 0)
897 { 1137 {
898 /* Get rid of any slash at the end of newdir. */ 1138 /* Get rid of any slash at the end of newdir, unless newdir is
1139 just // (an incomplete UNC name). */
899 int length = strlen ((char *) newdir); 1140 int length = strlen ((char *) newdir);
900 /* Adding `length > 1 &&' makes ~ expand into / when homedir 1141 /* Adding `length > 1 &&' makes ~ expand into / when homedir
901 is the root dir. People disagree about whether that is right. 1142 is the root dir. People disagree about whether that is right.
902 Anyway, we can't take the risk of this change now. */ 1143 Anyway, we can't take the risk of this change now. */
903 #ifdef DOS_NT 1144 /* Syncing with FSF 19.34.6 note: FSF does the above. */
904 if (newdir[1] != ':' && length > 1) 1145 if (IS_DIRECTORY_SEP (newdir[length - 1])
1146 #ifdef WINDOWSNT
1147 && !(length == 2 && IS_DIRECTORY_SEP (newdir[0]))
905 #endif 1148 #endif
906 if (IS_DIRECTORY_SEP (newdir[length - 1])) 1149 )
907 { 1150 {
908 Bufbyte *temp = (Bufbyte *) alloca (length); 1151 Bufbyte *temp = (Bufbyte *) alloca (length);
909 memcpy (temp, newdir, length - 1); 1152 memcpy (temp, newdir, length - 1);
910 temp[length - 1] = 0; 1153 temp[length - 1] = 0;
911 newdir = temp; 1154 newdir = temp;
922 produces incorrect code if the following two lines are combined.) */ 1165 produces incorrect code if the following two lines are combined.) */
923 target = (Bufbyte *) alloca (tlen + 2); 1166 target = (Bufbyte *) alloca (tlen + 2);
924 target += 2; 1167 target += 2;
925 #else /* not DOS_NT */ 1168 #else /* not DOS_NT */
926 target = (Bufbyte *) alloca (tlen); 1169 target = (Bufbyte *) alloca (tlen);
927 #endif /* not DOS_NT */ 1170 #endif /* DOS_NT */
928 *target = 0; 1171 *target = 0;
929 1172
930 if (newdir) 1173 if (newdir)
931 { 1174 {
932 if (nm[0] == 0 || IS_DIRECTORY_SEP (nm[0])) 1175 if (nm[0] == 0 || IS_DIRECTORY_SEP (nm[0]))
951 else if (IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1]) 1194 else if (IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1])
952 #if defined (APOLLO) || defined (WINDOWSNT) 1195 #if defined (APOLLO) || defined (WINDOWSNT)
953 /* // at start of filename is meaningful in Apollo 1196 /* // at start of filename is meaningful in Apollo
954 and WindowsNT systems */ 1197 and WindowsNT systems */
955 && o != target 1198 && o != target
956 #endif /* APOLLO */ 1199 #endif /* APOLLO || WINDOWSNT */
957 ) 1200 )
958 { 1201 {
959 o = target; 1202 o = target;
960 p++; 1203 p++;
961 } 1204 }
975 && o != target 1218 && o != target
976 && (IS_DIRECTORY_SEP (p[3]) || p[3] == 0)) 1219 && (IS_DIRECTORY_SEP (p[3]) || p[3] == 0))
977 { 1220 {
978 while (o != target && (--o) && !IS_DIRECTORY_SEP (*o)) 1221 while (o != target && (--o) && !IS_DIRECTORY_SEP (*o))
979 ; 1222 ;
980 #if defined (APOLLO) || defined (WINDOWSNT) 1223 if (o == target && IS_ANY_SEP (*o)
981 if (o == target + 1 1224 #ifdef DOS_NT
982 && IS_DIRECTORY_SEP (o[-1]) && IS_DIRECTORY_SEP (o[0])) 1225 && p[3] == 0
983 ++o; 1226 #endif
984 else 1227 )
985 #endif /* APOLLO || WINDOWSNT */
986 if (o == target && IS_ANY_SEP (*o))
987 ++o; 1228 ++o;
988 p += 3; 1229 p += 3;
989 } 1230 }
990 else 1231 else
991 { 1232 {
992 *o++ = *p++; 1233 *o++ = *p++;
993 } 1234 }
994 } 1235 }
995 1236
996 #ifdef DOS_NT 1237 #ifdef DOS_NT
997 /* at last, set drive name. */ 1238 /* At last, set drive name. */
998 if (target[1] != ':'
999 #ifdef WINDOWSNT 1239 #ifdef WINDOWSNT
1000 /* Allow network paths that look like "\\foo" */ 1240 /* Except for network file name. */
1001 && !(IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1])) 1241 if (!(IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1])))
1002 #endif /* WINDOWSNT */ 1242 #endif /* WINDOWSNT */
1003 ) 1243 {
1004 { 1244 if (!drive) abort ();
1005 target -= 2; 1245 target -= 2;
1006 target[0] = (drive < 0 ? getdisk () + 'A' : drive); 1246 target[0] = DRIVE_LETTER (drive);
1007 target[1] = ':'; 1247 target[1] = ':';
1008 } 1248 }
1249 CORRECT_DIR_SEPS (target);
1009 #endif /* DOS_NT */ 1250 #endif /* DOS_NT */
1010 1251
1011 return make_string (target, o - target); 1252 return make_string (target, o - target);
1012 } 1253 }
1013 1254
1163 if (!NILP (handler)) 1404 if (!NILP (handler))
1164 return call2_check_string_or_nil (handler, Qsubstitute_in_file_name, 1405 return call2_check_string_or_nil (handler, Qsubstitute_in_file_name,
1165 string); 1406 string);
1166 1407
1167 nm = XSTRING_DATA (string); 1408 nm = XSTRING_DATA (string);
1168 #ifdef MSDOS 1409 #ifdef DOS_NT
1169 dostounix_filename (nm = strcpy (alloca (strlen (nm) + 1), nm)); 1410 nm = strcpy (alloca (strlen (nm) + 1), nm);
1170 substituted = !strcmp (nm, XSTRING_DATA (string)); 1411 CORRECT_DIR_SEPS (nm);
1412 substituted = (strcmp (nm, XSTRING_DATA (string)) != 0);
1171 #endif 1413 #endif
1172 endp = nm + XSTRING_LENGTH (string); 1414 endp = nm + XSTRING_LENGTH (string);
1173 1415
1174 /* If /~ or // appears, discard everything through first slash. */ 1416 /* If /~ or // appears, discard everything through first slash. */
1175 1417
1176 for (p = nm; p != endp; p++) 1418 for (p = nm; p != endp; p++)
1177 { 1419 {
1178 if ((p[0] == '~' || 1420 if ((p[0] == '~'
1179 #ifdef APOLLO 1421 #if defined (APOLLO) || defined (WINDOWSNT)
1180 /* // at start of file name is meaningful in Apollo system */ 1422 /* // at start of file name is meaningful in Apollo and
1181 (p[0] == '/' && p - 1 != nm) 1423 WindowsNT systems */
1182 #else /* not APOLLO */ 1424 || (IS_DIRECTORY_SEP (p[0]) && p - 1 != nm)
1183 #ifdef WINDOWSNT 1425 #else /* not (APOLLO || WINDOWSNT) */
1184 (IS_DIRECTORY_SEP (p[0]) && p - 1 != nm) 1426 || IS_DIRECTORY_SEP (p[0])
1185 #else /* not WINDOWSNT */ 1427 #endif /* not (APOLLO || WINDOWSNT) */
1186 p[0] == '/'
1187 #endif /* not WINDOWSNT */
1188 #endif /* not APOLLO */
1189 ) 1428 )
1190 && p != nm 1429 && p != nm
1191 && (IS_DIRECTORY_SEP (p[-1]))) 1430 && (IS_DIRECTORY_SEP (p[-1])))
1192 { 1431 {
1193 nm = p; 1432 nm = p;
1194 substituted = 1; 1433 substituted = 1;
1195 } 1434 }
1196 #ifdef DOS_NT 1435 #ifdef DOS_NT
1197 if (p[0] && p[1] == ':') 1436 /* see comment in expand-file-name about drive specifiers */
1437 else if (IS_DRIVE (p[0]) && p[1] == ':'
1438 && p > nm && IS_DIRECTORY_SEP (p[-1]))
1198 { 1439 {
1199 nm = p; 1440 nm = p;
1200 substituted = 1; 1441 substituted = 1;
1201 } 1442 }
1202 #endif /* DOS_NT */ 1443 #endif /* DOS_NT */
1307 1548
1308 /* If /~ or // appears, discard everything through first slash. */ 1549 /* If /~ or // appears, discard everything through first slash. */
1309 1550
1310 for (p = xnm; p != x; p++) 1551 for (p = xnm; p != x; p++)
1311 if ((p[0] == '~' 1552 if ((p[0] == '~'
1312 #ifdef APOLLO 1553 #if defined (APOLLO) || defined (WINDOWSNT)
1313 /* // at start of file name is meaningful in Apollo system */
1314 || (p[0] == '/' && p - 1 != xnm)
1315 #else /* not APOLLO */
1316 #ifdef WINDOWSNT
1317 || (IS_DIRECTORY_SEP (p[0]) && p - 1 != xnm) 1554 || (IS_DIRECTORY_SEP (p[0]) && p - 1 != xnm)
1318 #else /* not WINDOWSNT */ 1555 #else /* not (APOLLO || WINDOWSNT) */
1319 || p[0] == '/' 1556 || IS_DIRECTORY_SEP (p[0])
1320 #endif /* not WINDOWSNT */ 1557 #endif /* APOLLO || WINDOWSNT */
1321 #endif /* not APOLLO */
1322 ) 1558 )
1323 /* don't do p[-1] if that would go off the beginning --jwz */ 1559 /* don't do p[-1] if that would go off the beginning --jwz */
1324 && p != nm && p > xnm && IS_DIRECTORY_SEP (p[-1])) 1560 && p != nm && p > xnm && IS_DIRECTORY_SEP (p[-1]))
1325 xnm = p; 1561 xnm = p;
1326 #ifdef DOS_NT 1562 #ifdef DOS_NT
1327 else if (p[0] && p[1] == ':') 1563 else if (IS_DRIVE (p[0]) && p[1] == ':'
1564 && p > nm && IS_DIRECTORY_SEP (p[-1]))
1328 xnm = p; 1565 xnm = p;
1329 #endif 1566 #endif
1330 1567
1331 return make_string (xnm, x - xnm); 1568 return make_string (xnm, x - xnm);
1332 1569
1340 1577
1341 /* NOTREACHED */ 1578 /* NOTREACHED */
1342 return Qnil; /* suppress compiler warning */ 1579 return Qnil; /* suppress compiler warning */
1343 } 1580 }
1344 1581
1345 /* (directory-file-name (expand-file-name FOO)) */ 1582 /* A slightly faster and more convenient way to get
1583 (directory-file-name (expand-file-name FOO)). */
1346 1584
1347 Lisp_Object 1585 Lisp_Object
1348 expand_and_dir_to_file (Lisp_Object filename, Lisp_Object defdir) 1586 expand_and_dir_to_file (Lisp_Object filename, Lisp_Object defdir)
1349 { 1587 {
1350 /* This function can call lisp */ 1588 /* This function can call lisp */
1750 if (NILP (ok_if_already_exists) 1988 if (NILP (ok_if_already_exists)
1751 || INTP (ok_if_already_exists)) 1989 || INTP (ok_if_already_exists))
1752 barf_or_query_if_file_exists (newname, "rename to it", 1990 barf_or_query_if_file_exists (newname, "rename to it",
1753 INTP (ok_if_already_exists), 0); 1991 INTP (ok_if_already_exists), 0);
1754 1992
1755 #ifdef WINDOWSNT 1993 /* Syncing with FSF 19.34.6 note: FSF does not have conditional code for
1756 if (!MoveFile (XSTRING (filename)->_data, XSTRING (newname)->_data)) 1994 WINDOWSNT here; I've removed it. --marcpa */
1757 #else /* not WINDOWSNT */ 1995
1758 /* FSFmacs only calls rename() here under BSD 4.1, and calls 1996 /* FSFmacs only calls rename() here under BSD 4.1, and calls
1759 link() and unlink() otherwise, but that's bogus. Sometimes 1997 link() and unlink() otherwise, but that's bogus. Sometimes
1760 rename() succeeds where link()/unlink() fail, and we have 1998 rename() succeeds where link()/unlink() fail, and we have
1761 configure check for rename() and emulate using link()/unlink() 1999 configure check for rename() and emulate using link()/unlink()
1762 if necessary. */ 2000 if necessary. */
1763 if (0 > rename ((char *) XSTRING_DATA (filename), 2001 if (0 > rename ((char *) XSTRING_DATA (filename),
1764 (char *) XSTRING_DATA (newname))) 2002 (char *) XSTRING_DATA (newname)))
1765 #endif /* not WINDOWSNT */ 2003 {
1766 {
1767 #ifdef WINDOWSNT
1768 /* Why two? And why doesn't MS document what MoveFile will return? */
1769 if (GetLastError () == ERROR_FILE_EXISTS
1770 || GetLastError () == ERROR_ALREADY_EXISTS)
1771 #else /* not WINDOWSNT */
1772 if (errno == EXDEV) 2004 if (errno == EXDEV)
1773 #endif /* not WINDOWSNT */
1774 { 2005 {
1775 Fcopy_file (filename, newname, 2006 Fcopy_file (filename, newname,
1776 /* We have already prompted if it was an integer, 2007 /* We have already prompted if it was an integer,
1777 so don't have copy-file prompt again. */ 2008 so don't have copy-file prompt again. */
1778 ((NILP (ok_if_already_exists)) ? Qnil : Qt), 2009 ((NILP (ok_if_already_exists)) ? Qnil : Qt),
1824 2055
1825 if (NILP (ok_if_already_exists) 2056 if (NILP (ok_if_already_exists)
1826 || INTP (ok_if_already_exists)) 2057 || INTP (ok_if_already_exists))
1827 barf_or_query_if_file_exists (newname, "make it a new name", 2058 barf_or_query_if_file_exists (newname, "make it a new name",
1828 INTP (ok_if_already_exists), 0); 2059 INTP (ok_if_already_exists), 0);
1829 #ifdef WINDOWSNT 2060 /* Syncing with FSF 19.34.6 note: FSF does not report a file error
2061 on NT here. --marcpa */
2062 #if 0 /* defined(WINDOWSNT) */
1830 /* Windows does not support this operation. */ 2063 /* Windows does not support this operation. */
1831 report_file_error ("Adding new name", Flist (2, &filename)); 2064 report_file_error ("Adding new name", Flist (2, &filename));
1832 #else /* not WINDOWSNT */ 2065 #else /* not 0 -- defined(WINDOWSNT) */
1833 2066
1834 unlink ((char *) XSTRING_DATA (newname)); 2067 unlink ((char *) XSTRING_DATA (newname));
1835 if (0 > link ((char *) XSTRING_DATA (filename), 2068 if (0 > link ((char *) XSTRING_DATA (filename),
1836 (char *) XSTRING_DATA (newname))) 2069 (char *) XSTRING_DATA (newname)))
1837 { 2070 {
1838 report_file_error ("Adding new name", 2071 report_file_error ("Adding new name",
1839 list2 (filename, newname)); 2072 list2 (filename, newname));
1840 } 2073 }
1841 #endif /* not WINDOWSNT */ 2074 #endif /* 0 -- defined(WINDOWSNT) */
1842 2075
1843 UNGCPRO; 2076 UNGCPRO;
1844 return Qnil; 2077 return Qnil;
1845 } 2078 }
1846 2079
1863 CHECK_STRING (filename); 2096 CHECK_STRING (filename);
1864 CHECK_STRING (linkname); 2097 CHECK_STRING (linkname);
1865 /* If the link target has a ~, we must expand it to get 2098 /* If the link target has a ~, we must expand it to get
1866 a truly valid file name. Otherwise, do not expand; 2099 a truly valid file name. Otherwise, do not expand;
1867 we want to permit links to relative file names. */ 2100 we want to permit links to relative file names. */
1868 if (XSTRING_BYTE (filename, 0) == '~') /* #### Un*x-specific */ 2101 if (XSTRING_BYTE (filename, 0) == '~')
1869 filename = Fexpand_file_name (filename, Qnil); 2102 filename = Fexpand_file_name (filename, Qnil);
1870 linkname = Fexpand_file_name (linkname, Qnil); 2103 linkname = Fexpand_file_name (linkname, Qnil);
1871 2104
1872 /* If the file name has special constructs in it, 2105 /* If the file name has special constructs in it,
1873 call the corresponding file handler. */ 2106 call the corresponding file handler. */
1942 2175
1943 CHECK_STRING (filename); 2176 CHECK_STRING (filename);
1944 ptr = XSTRING_DATA (filename); 2177 ptr = XSTRING_DATA (filename);
1945 if (IS_DIRECTORY_SEP (*ptr) || *ptr == '~' 2178 if (IS_DIRECTORY_SEP (*ptr) || *ptr == '~'
1946 #ifdef DOS_NT 2179 #ifdef DOS_NT
1947 || (*ptr != 0 && ptr[1] == ':' && (ptr[2] == '/' || ptr[2] == '\\')) 2180 || (IS_DRIVE (*ptr) && ptr[1] == ':' && IS_DIRECTORY_SEP (ptr[2]))
1948 #endif 2181 #endif
1949 ) 2182 )
1950 return Qt; 2183 return Qt;
1951 else 2184 else
1952 return Qnil; 2185 return Qnil;
1961 int len = strlen (filename); 2194 int len = strlen (filename);
1962 char *suffix; 2195 char *suffix;
1963 struct stat st; 2196 struct stat st;
1964 if (stat (filename, &st) < 0) 2197 if (stat (filename, &st) < 0)
1965 return 0; 2198 return 0;
2199 #if defined (WINDOWSNT)
2200 return ((st.st_mode & S_IEXEC) != 0);
2201 #else
1966 return (S_ISREG (st.st_mode) 2202 return (S_ISREG (st.st_mode)
1967 && len >= 5 2203 && len >= 5
1968 && (stricmp ((suffix = filename + len-4), ".com") == 0 2204 && (stricmp ((suffix = filename + len-4), ".com") == 0
1969 || stricmp (suffix, ".exe") == 0 2205 || stricmp (suffix, ".exe") == 0
1970 || stricmp (suffix, ".bat") == 0) 2206 || stricmp (suffix, ".bat") == 0)
1971 || (st.st_mode & S_IFMT) == S_IFDIR); 2207 || (st.st_mode & S_IFMT) == S_IFDIR);
2208 #endif /* not WINDOWSNT */
1972 #else /* not DOS_NT */ 2209 #else /* not DOS_NT */
1973 #ifdef HAVE_EACCESS 2210 #ifdef HAVE_EACCESS
1974 return eaccess (filename, 1) >= 0; 2211 return eaccess (filename, 1) >= 0;
1975 #else 2212 #else
1976 /* Access isn't quite right because it uses the real uid 2213 /* Access isn't quite right because it uses the real uid
2082 handler = Ffind_file_name_handler (abspath, Qfile_readable_p); 2319 handler = Ffind_file_name_handler (abspath, Qfile_readable_p);
2083 UNGCPRO; 2320 UNGCPRO;
2084 if (!NILP (handler)) 2321 if (!NILP (handler))
2085 return call2 (handler, Qfile_readable_p, abspath); 2322 return call2 (handler, Qfile_readable_p, abspath);
2086 2323
2324 #ifdef DOS_NT
2325 /* Under MS-DOS and Windows, open does not work for directories. */
2326 if (access (XSTRING_DATA (abspath), 0) == 0)
2327 return Qt;
2328 return Qnil;
2329 #else /* not DOS_NT */
2087 desc = open ((char *) XSTRING_DATA (abspath), O_RDONLY, 0); 2330 desc = open ((char *) XSTRING_DATA (abspath), O_RDONLY, 0);
2088 if (desc < 0) 2331 if (desc < 0)
2089 return Qnil; 2332 return Qnil;
2090 close (desc); 2333 close (desc);
2091 return Qt; 2334 return Qt;
2335 #endif /* not DOS_NT */
2092 } 2336 }
2093 2337
2094 /* Having this before file-symlink-p mysteriously caused it to be forgotten 2338 /* Having this before file-symlink-p mysteriously caused it to be forgotten
2095 on the RT/PC. */ 2339 on the RT/PC. */
2096 DEFUN ("file-writable-p", Ffile_writable_p, 1, 1, 0, /* 2340 DEFUN ("file-writable-p", Ffile_writable_p, 1, 1, 0, /*
2236 handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p); 2480 handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p);
2237 if (!NILP (handler)) 2481 if (!NILP (handler))
2238 return call2 (handler, Qfile_accessible_directory_p, 2482 return call2 (handler, Qfile_accessible_directory_p,
2239 filename); 2483 filename);
2240 2484
2485 #if !defined(DOS_NT)
2241 if (NILP (Ffile_directory_p (filename))) 2486 if (NILP (Ffile_directory_p (filename)))
2242 return (Qnil); 2487 return (Qnil);
2243 else 2488 else
2244 return Ffile_executable_p (filename); 2489 return Ffile_executable_p (filename);
2490 #else
2491 {
2492 int tem;
2493 struct gcpro gcpro1;
2494 /* It's an unlikely combination, but yes we really do need to gcpro:
2495 Suppose that file-accessible-directory-p has no handler, but
2496 file-directory-p does have a handler; this handler causes a GC which
2497 relocates the string in `filename'; and finally file-directory-p
2498 returns non-nil. Then we would end up passing a garbaged string
2499 to file-executable-p. */
2500 GCPRO1 (filename);
2501 tem = (NILP (Ffile_directory_p (filename))
2502 || NILP (Ffile_executable_p (filename)));
2503 UNGCPRO;
2504 return tem ? Qnil : Qt;
2505 }
2506 #endif /* !defined(DOS_NT) */
2245 } 2507 }
2246 2508
2247 DEFUN ("file-regular-p", Ffile_regular_p, 1, 1, 0, /* 2509 DEFUN ("file-regular-p", Ffile_regular_p, 1, 1, 0, /*
2248 "Return t if file FILENAME is the name of a regular file. 2510 "Return t if file FILENAME is the name of a regular file.
2249 This is the sort of file that holds an ordinary stream of data bytes. 2511 This is the sort of file that holds an ordinary stream of data bytes.
2297 if (!NILP (handler)) 2559 if (!NILP (handler))
2298 return call2 (handler, Qfile_modes, abspath); 2560 return call2 (handler, Qfile_modes, abspath);
2299 2561
2300 if (stat ((char *) XSTRING_DATA (abspath), &st) < 0) 2562 if (stat ((char *) XSTRING_DATA (abspath), &st) < 0)
2301 return Qnil; 2563 return Qnil;
2564 /* Syncing with FSF 19.34.6 note: not in FSF, #if 0'ed out here. */
2565 #if 0
2302 #ifdef DOS_NT 2566 #ifdef DOS_NT
2303 if (check_executable (XSTRING (abspath)->_data)) 2567 if (check_executable (XSTRING (abspath)->_data))
2304 st.st_mode |= S_IEXEC; 2568 st.st_mode |= S_IEXEC;
2305 #endif /* DOS_NT */ 2569 #endif /* DOS_NT */
2570 #endif /* 0 */
2306 2571
2307 return make_int (st.st_mode & 07777); 2572 return make_int (st.st_mode & 07777);
2308 } 2573 }
2309 2574
2310 DEFUN ("set-file-modes", Fset_file_modes, 2, 2, 0, /* 2575 DEFUN ("set-file-modes", Fset_file_modes, 2, 2, 0, /*
2428 } 2693 }
2429 2694
2430 2695
2431 #ifdef DOS_NT 2696 #ifdef DOS_NT
2432 Lisp_Object Qfind_buffer_file_type; 2697 Lisp_Object Qfind_buffer_file_type;
2698
2699 /* Return 1 if buffer is text, 0 if binary. */
2700 static int
2701 decide_buffer_type (unsigned char * buffer, int nbytes)
2702 {
2703 /* Buffer is binary if we find any LF chars not preceeded by CR or if
2704 the buffer doesn't contain at least 1 line. */
2705 unsigned lines = 0;
2706 unsigned char *p, *q;
2707
2708 for (p = buffer; nbytes > 0 && (q = memchr (p, '\n', nbytes)) != NULL;
2709 p = q + 1 )
2710 {
2711 nbytes -= (q + 1 - p);
2712 lines++;
2713 if (q > buffer && q[-1] != '\r')
2714 return 0;
2715 }
2716
2717 /* If we haven't seen any line endings yet, return -1 (meaning type is
2718 undecided) so we can examine the next bufferful as well. */
2719 return (lines > 0) ? 1 : -1;
2720 }
2721
2722 /* XEmacs addition: like decide_buffer_type(), but working on a XEmacs buffer:
2723 first arg is a byte index position instead of a char pointer;
2724 we check each char sequentially. --marcpa */
2725 static int
2726 buf_decide_buffer_type (struct buffer *buf, Bytind start, int nbytes)
2727 {
2728 /* Buffer is binary if we find any LF chars not preceeded by CR or if
2729 the buffer doesn't contain at least 1 line. */
2730 unsigned lines = 0;
2731 Bytind cur = start;
2732
2733 while (nbytes)
2734 {
2735 if (BI_BUF_FETCH_CHAR(buf, cur) == '\n')
2736 {
2737 lines++;
2738 if (cur != start && BI_BUF_FETCH_CHAR(buf, cur - 1) != '\r')
2739 return 0;
2740 }
2741 nbytes--;
2742 }
2743
2744 /* If we haven't seen any line endings yet, return -1 (meaning type is
2745 undecided) so we can examine the next bufferful as well. */
2746 return (lines > 0) ? 1 : -1;
2747 }
2433 #endif /* DOS_NT */ 2748 #endif /* DOS_NT */
2434 2749
2435 /* Stack sizes > 2**16 is a good way to elicit compiler bugs */ 2750 /* Stack sizes > 2**16 is a good way to elicit compiler bugs */
2436 /* #define READ_BUF_SIZE (2 << 16) */ 2751 /* #define READ_BUF_SIZE (2 << 16) */
2437 #define READ_BUF_SIZE (1 << 15) 2752 #define READ_BUF_SIZE (1 << 15)
2468 Bufbyte read_buf[READ_BUF_SIZE]; 2783 Bufbyte read_buf[READ_BUF_SIZE];
2469 int mc_count; 2784 int mc_count;
2470 struct buffer *buf = current_buffer; 2785 struct buffer *buf = current_buffer;
2471 Lisp_Object curbuf; 2786 Lisp_Object curbuf;
2472 int not_regular = 0; 2787 int not_regular = 0;
2788 #ifdef DOS_NT
2789 int crlf_conversion_required = 0;
2790 unsigned crlf_count = 0;
2791 unsigned lf_count = 0;
2792 #endif
2473 2793
2474 if (buf->base_buffer && ! NILP (visit)) 2794 if (buf->base_buffer && ! NILP (visit))
2475 error ("Cannot do file visiting in an indirect buffer"); 2795 error ("Cannot do file visiting in an indirect buffer");
2476 2796
2477 /* No need to call Fbarf_if_buffer_read_only() here. 2797 /* No need to call Fbarf_if_buffer_read_only() here.
2584 { 2904 {
2585 end = make_int (st.st_size); 2905 end = make_int (st.st_size);
2586 if (XINT (end) != st.st_size) 2906 if (XINT (end) != st.st_size)
2587 error ("Maximum buffer size exceeded"); 2907 error ("Maximum buffer size exceeded");
2588 } 2908 }
2909
2910 #ifdef DOS_NT
2911 /* Permit old behaviour if desired. */
2912 if (NILP (Vinsert_file_contents_allow_replace) && !NILP (replace))
2913 {
2914 replace = Qnil;
2915 /* Surely this was never right! */
2916 /* XSETFASTINT (beg, 0);
2917 XSETFASTINT (end, st.st_size); */
2918 buffer_delete_range (buf, BUF_BEGV(buf), BUF_ZV(buf),
2919 !NILP (visit) ? INSDEL_NO_LOCKING : 0);
2920 }
2921 #endif /* DOS_NT */
2589 } 2922 }
2590 2923
2591 /* If requested, replace the accessible part of the buffer 2924 /* If requested, replace the accessible part of the buffer
2592 with the file contents. Avoid replacing text at the 2925 with the file contents. Avoid replacing text at the
2593 beginning or end of the buffer that matches the file contents; 2926 beginning or end of the buffer that matches the file contents;
2594 that preserves markers pointing to the unchanged parts. */ 2927 that preserves markers pointing to the unchanged parts. */
2595 #if !defined (DOS_NT) && !defined (MULE) 2928 #if !defined (MULE)
2596 /* The replace-mode code currently only works when the assumption 2929 /* The replace-mode code currently only works when the assumption
2597 'one byte == one char' holds true. This fails under MSDOS and 2930 'one byte == one char' holds true. This fails Mule because
2598 Windows NT (because newlines are represented as CR-LF in text 2931 files may contain multibyte characters. It holds under Windows NT
2599 files) and under Mule because files may contain multibyte characters. */ 2932 provided we convert CRLF into LF. */
2600 # define FSFMACS_SPEEDY_INSERT 2933 # define FSFMACS_SPEEDY_INSERT
2601 #endif 2934 #endif
2602 #ifndef FSFMACS_SPEEDY_INSERT 2935 #ifndef FSFMACS_SPEEDY_INSERT
2603 if (!NILP (replace)) 2936 if (!NILP (replace))
2604 { 2937 {
2610 { 2943 {
2611 char buffer[1 << 14]; 2944 char buffer[1 << 14];
2612 Bufpos same_at_start = BUF_BEGV (buf); 2945 Bufpos same_at_start = BUF_BEGV (buf);
2613 Bufpos same_at_end = BUF_ZV (buf); 2946 Bufpos same_at_end = BUF_ZV (buf);
2614 int overlap; 2947 int overlap;
2948 #ifdef DOS_NT
2949 /* Syncing with 19.34.6 note: same_at_start_in_file and
2950 same_at_end_in_file are not in XEmacs 20.4.
2951 First try to introduce them as-is and see what happens.
2952 Might be necessary to use constructs like
2953 st.st_size - (BUF_ZV (buf) - same_at_end)
2954 instead.
2955 --marcpa
2956 */
2957 /* Offset into the file where discrepancy begins. */
2958 int same_at_start_in_file = 0;
2959 /* Offset into the file where discrepancy ends. */
2960 int same_at_end_in_file = st.st_size;
2961 /* DOS_NT only: is there a `\r' character left in the buffer? */
2962 int cr_left_in_buffer = 0;
2963 /* DOS_NT only: was `\n' the first character in previous bufferful? */
2964 int last_was_lf = 0;
2965
2966 /* Demacs 1.1.1 91/10/16 HIRANO Satoshi, MW July 1993 */
2967 /* Determine file type (text/binary) from its name.
2968 Note that the buffer_file_type changes here when the file
2969 being inserted is not of the same type as the original buffer. */
2970 current_buffer->buffer_file_type = call1 (Qfind_buffer_file_type, filename);
2971 if (NILP (current_buffer->buffer_file_type))
2972 crlf_conversion_required = 1;
2973 else if (current_buffer->buffer_file_type != Qt)
2974 /* Use heuristic to decide whether file is text or binary (based
2975 on the first bufferful) if buffer-file-type is not nil or t.
2976 If no decision is made (because no line endings were ever
2977 seen) then let buffer-file-type default to nil. */
2978 crlf_conversion_required = -1;
2979 #endif /* DOS_NT */
2615 2980
2616 /* Count how many chars at the start of the file 2981 /* Count how many chars at the start of the file
2617 match the text at the beginning of the buffer. */ 2982 match the text at the beginning of the buffer. */
2618 while (1) 2983 while (1)
2619 { 2984 {
2620 int nread; 2985 int nread;
2621 Bufpos bufpos; 2986 Bufpos bufpos;
2622 2987 #ifdef DOS_NT
2988 if (cr_left_in_buffer)
2989 {
2990 nread = read_allowing_quit (fd, buffer + 1, sizeof(buffer) - 1);
2991 cr_left_in_buffer = 0;
2992 if (nread >= 0)
2993 nread++;
2994 }
2995 else
2996 #endif /* DOS_NT */
2623 nread = read_allowing_quit (fd, buffer, sizeof buffer); 2997 nread = read_allowing_quit (fd, buffer, sizeof buffer);
2624 if (nread < 0) 2998 if (nread < 0)
2625 error ("IO error reading %s: %s", 2999 error ("IO error reading %s: %s",
2626 XSTRING_DATA (filename), strerror (errno)); 3000 XSTRING_DATA (filename), strerror (errno));
2627 else if (nread == 0) 3001 else if (nread == 0)
2628 break; 3002 break;
2629 bufpos = 0; 3003 bufpos = 0;
3004 #ifdef DOS_NT
3005 /* If requested, we do a simple check on the first bufferful
3006 to decide whether the file is binary or text. (If text, we
3007 count LF and CRLF occurences to determine whether the file
3008 was in Unix or DOS format.) */
3009 if (crlf_conversion_required < 0)
3010 {
3011 crlf_conversion_required = decide_buffer_type (buffer, nread);
3012 current_buffer->buffer_file_type =
3013 crlf_conversion_required ? Qnil : Qt;
3014 }
3015
3016 /* DOS_NT text files require that we ignore a `\r' before a `\n'. */
3017 if (crlf_conversion_required > 0)
3018 while (bufpos < nread && same_at_start < BUF_ZV (buf))
3019 {
3020 int filec = buffer[bufpos];
3021 int bufc = BUF_FETCH_CHAR (buf, same_at_start);
3022
3023 if (filec == '\n')
3024 lf_count++;
3025
3026 if (filec == bufc)
3027 same_at_start++, bufpos++, same_at_start_in_file++;
3028 else if (filec == '\r' && bufc == '\n')
3029 {
3030 /* If the `\r' is the last character in this buffer,
3031 it will be examined with the next bufferful. */
3032 if (bufpos == nread)
3033 {
3034 buffer[0] = filec;
3035 cr_left_in_buffer = 1;
3036 }
3037 else if (buffer[bufpos + 1] == bufc)
3038 {
3039 bufpos += 2;
3040 same_at_start_in_file += 2;
3041 same_at_start++;
3042 crlf_count++;
3043 lf_count++;
3044 }
3045 else
3046 break;
3047 }
3048 else
3049 break;
3050 }
3051 else
3052 #endif /* DOS_NT */
2630 while (bufpos < nread && same_at_start < BUF_ZV (buf) 3053 while (bufpos < nread && same_at_start < BUF_ZV (buf)
2631 && BUF_FETCH_CHAR (buf, same_at_start) == buffer[bufpos]) 3054 && BUF_FETCH_CHAR (buf, same_at_start) == buffer[bufpos])
3055 #ifdef DOS_NT
3056 same_at_start_in_file++,
3057 #endif
2632 same_at_start++, bufpos++; 3058 same_at_start++, bufpos++;
2633 /* If we found a discrepancy, stop the scan. 3059 /* If we found a discrepancy, stop the scan.
2634 Otherwise loop around and scan the next bufferfull. */ 3060 Otherwise loop around and scan the next bufferful. */
2635 if (bufpos != nread) 3061 if (bufpos != nread)
2636 break; 3062 break;
2637 } 3063 }
2638 /* If the file matches the buffer completely, 3064 /* If the file matches the buffer completely,
2639 there's no need to replace anything. */ 3065 there's no need to replace anything. */
3066 #ifdef DOS_NT
3067 if (same_at_start_in_file == st.st_size)
3068 #else
2640 if (same_at_start - BUF_BEGV (buf) == st.st_size) 3069 if (same_at_start - BUF_BEGV (buf) == st.st_size)
3070 #endif /* DOS_NT */
2641 { 3071 {
2642 close (fd); 3072 close (fd);
2643 unbind_to (speccount, Qnil); 3073 unbind_to (speccount, Qnil);
2644 /* Truncate the buffer to the size of the file. */ 3074 /* Truncate the buffer to the size of the file. */
2645 buffer_delete_range (buf, same_at_start, same_at_end, 3075 buffer_delete_range (buf, same_at_start, same_at_end,
2652 { 3082 {
2653 int total_read, nread; 3083 int total_read, nread;
2654 Bufpos bufpos, curpos, trial; 3084 Bufpos bufpos, curpos, trial;
2655 3085
2656 /* At what file position are we now scanning? */ 3086 /* At what file position are we now scanning? */
3087 #ifdef DOS_NT
3088 curpos = same_at_end_in_file;
3089 #else
2657 curpos = st.st_size - (BUF_ZV (buf) - same_at_end); 3090 curpos = st.st_size - (BUF_ZV (buf) - same_at_end);
3091 #endif /* DOS_NT */
2658 /* If the entire file matches the buffer tail, stop the scan. */ 3092 /* If the entire file matches the buffer tail, stop the scan. */
2659 if (curpos == 0) 3093 if (curpos == 0)
2660 break; 3094 break;
2661 /* How much can we scan in the next step? */ 3095 /* How much can we scan in the next step? */
2662 trial = min (curpos, sizeof buffer); 3096 trial = min (curpos, sizeof buffer);
2672 if (nread <= 0) 3106 if (nread <= 0)
2673 error ("IO error reading %s: %s", 3107 error ("IO error reading %s: %s",
2674 XSTRING_DATA (filename), strerror (errno)); 3108 XSTRING_DATA (filename), strerror (errno));
2675 total_read += nread; 3109 total_read += nread;
2676 } 3110 }
2677 /* Scan this bufferfull from the end, comparing with 3111 /* Scan this bufferful from the end, comparing with
2678 the Emacs buffer. */ 3112 the Emacs buffer. */
2679 bufpos = total_read; 3113 bufpos = total_read;
3114 #ifdef DOS_NT
3115 /* DOS_NT text files require that we ignore a `\r' before a `\n'. */
3116 if (crlf_conversion_required)
3117 #endif /* DOS_NT */
2680 /* Compare with same_at_start to avoid counting some buffer text 3118 /* Compare with same_at_start to avoid counting some buffer text
2681 as matching both at the file's beginning and at the end. */ 3119 as matching both at the file's beginning and at the end. */
3120 #if !defined(DOS_NT)
2682 while (bufpos > 0 && same_at_end > same_at_start 3121 while (bufpos > 0 && same_at_end > same_at_start
2683 && BUF_FETCH_CHAR (buf, same_at_end - 1) == 3122 && BUF_FETCH_CHAR (buf, same_at_end - 1) ==
2684 buffer[bufpos - 1]) 3123 buffer[bufpos - 1])
2685 same_at_end--, bufpos--; 3124 same_at_end--, bufpos--;
3125 #else /* DOS_NT */
3126 while (bufpos > 0 && same_at_end > same_at_start
3127 && same_at_end_in_file > same_at_start_in_file)
3128 {
3129 int filec = buffer[bufpos - 1];
3130 int bufc = BUF_FETCH_CHAR (buf, same_at_end - 1);
3131
3132 /* Account for `\n' in previous bufferful. */
3133 if (last_was_lf && filec == '\r')
3134 {
3135 same_at_end_in_file--, bufpos--;
3136 last_was_lf = 0;
3137 crlf_count++;
3138 }
3139 else if (filec == bufc)
3140 {
3141 last_was_lf = 0;
3142 same_at_end--, same_at_end_in_file--, bufpos--;
3143 if (bufc == '\n')
3144 {
3145 lf_count++;
3146 if (bufpos <= 0)
3147 last_was_lf = 1;
3148 else if (same_at_end_in_file <= same_at_start_in_file)
3149 break;
3150 else if (buffer[bufpos - 1] == '\r')
3151 same_at_end_in_file--, bufpos--, crlf_count++;
3152 }
3153 }
3154 else
3155 {
3156 last_was_lf = 0;
3157 break;
3158 }
3159 }
3160 else
3161 while (bufpos > 0 && same_at_end > same_at_start
3162 && same_at_end_in_file > same_at_start_in_file
3163 && BUF_FETCH_CHAR (buf, same_at_end - 1) ==
3164 buffer[bufpos - 1])
3165 same_at_end--, same_at_end_in_file--, bufpos--;
3166 #endif /* !defined(DOS_NT) */
2686 /* If we found a discrepancy, stop the scan. 3167 /* If we found a discrepancy, stop the scan.
2687 Otherwise loop around and scan the preceding bufferfull. */ 3168 Otherwise loop around and scan the preceding bufferful. */
2688 if (bufpos != 0) 3169 if (bufpos != 0)
2689 break; 3170 break;
2690 /* If display current starts at beginning of line, 3171 /* If display current starts at beginning of line,
2691 keep it that way. */ 3172 keep it that way. */
2692 if (XBUFFER (XWINDOW (Fselected_window (Qnil))->buffer) == buf) 3173 if (XBUFFER (XWINDOW (Fselected_window (Qnil))->buffer) == buf)
2699 (same_at_end + st.st_size - BUF_ZV (buf)); 3180 (same_at_end + st.st_size - BUF_ZV (buf));
2700 if (overlap > 0) 3181 if (overlap > 0)
2701 same_at_end += overlap; 3182 same_at_end += overlap;
2702 3183
2703 /* Arrange to read only the nonmatching middle part of the file. */ 3184 /* Arrange to read only the nonmatching middle part of the file. */
3185 #ifdef DOS_NT
3186 beg = make_int (same_at_start_in_file);
3187 end = make_int (same_at_end_in_file);
3188 #else
2704 beg = make_int (same_at_start - BUF_BEGV (buf)); 3189 beg = make_int (same_at_start - BUF_BEGV (buf));
2705 end = make_int (st.st_size - (BUF_ZV (buf) - same_at_end)); 3190 end = make_int (st.st_size - (BUF_ZV (buf) - same_at_end));
3191 #endif /* DOS_NT */
2706 3192
2707 buffer_delete_range (buf, same_at_start, same_at_end, 3193 buffer_delete_range (buf, same_at_start, same_at_end,
2708 !NILP (visit) ? INSDEL_NO_LOCKING : 0); 3194 !NILP (visit) ? INSDEL_NO_LOCKING : 0);
2709 /* Insert from the file at the proper position. */ 3195 /* Insert from the file at the proper position. */
2710 BUF_SET_PT (buf, same_at_start); 3196 BUF_SET_PT (buf, same_at_start);
2773 { 3259 {
2774 if (this_len < 0) 3260 if (this_len < 0)
2775 saverrno = errno; 3261 saverrno = errno;
2776 break; 3262 break;
2777 } 3263 }
3264 #ifdef DOS_NT
3265 /* XEmacs (--marcpa) change: FSF does buffer_insert_raw_string_1() first
3266 then checks if conversion is needed, calling lisp
3267 (find-buffer-file-type) which can call a user-function that
3268 might look at the unconverted buffer to decide if
3269 conversion is needed.
3270 I removed the possibility for lisp functions called from
3271 find-buffer-file-type to look at the buffer's content, for
3272 simplicity reasons: it is easier to do the CRLF -> LF
3273 conversion on read_buf than on buffer contents because
3274 BUF_FETCH_CHAR does not return a pointer to an unsigned
3275 char memory location, and because we must cope with bytind
3276 VS bufpos in XEmacs, thus complicating crlf_to_lf().
3277 This decision (of doing Lstream_read(), crlf_to_lf() then
3278 buffer_insert_raw_string_1()) is debatable.
3279 --marcpa
3280 */
3281 /* Following FSF note no longer apply now. See comment above.
3282 --marcpa*/
3283 /* For compatability with earlier versions that did not support the
3284 REPLACE funtionality, we call find-buffer-file-type after inserting
3285 the contents to allow it to inspect the inserted data. (This was
3286 not intentional usage, but proved to be quite useful.) */
3287 if (NILP (replace))
3288 {
3289 /* Demacs 1.1.1 91/10/16 HIRANO Satoshi, MW July 1993 */
3290 /* Determine file type (text/binary) from its name.
3291 Note that the buffer_file_type changes here when the file
3292 being inserted is not of the same type as the original buffer. */
3293 current_buffer->buffer_file_type = call1 (Qfind_buffer_file_type, filename);
3294 if (NILP (current_buffer->buffer_file_type))
3295 crlf_conversion_required = 1;
3296 else if (current_buffer->buffer_file_type != Qt)
3297 /* Use heuristic to decide whether file is text or binary (based
3298 on the first bufferful) if buffer-file-type is not nil or t.
3299 If no decision is made (because no line endings were ever
3300 seen) then let buffer-file-type default to nil. */
3301 crlf_conversion_required = -1;
3302 }
3303
3304 /* If requested, we check the inserted data to decide whether the file
3305 is binary or text. (If text, we count LF and CRLF occurences to
3306 determine whether the file was in Unix or DOS format.) */
3307 if (crlf_conversion_required < 0)
3308 {
3309 crlf_conversion_required =
3310 decide_buffer_type (read_buf, this_len);
3311 current_buffer->buffer_file_type =
3312 crlf_conversion_required ? Qnil : Qt;
3313 }
3314
3315 /* Demacs 1.1.1 91/10/16 HIRANO Satoshi, MW July 1993 */
3316 /* Remove CRs from CR-LFs if the file is deemed to be a text file. */
3317 if (crlf_conversion_required)
3318 {
3319 int reduced_size
3320 = this_len - crlf_to_lf (this_len, read_buf,
3321 &lf_count);
3322 crlf_count += reduced_size;
3323 /* XEmacs (--marcpa) change: No need for this since we havent
3324 inserted in buffer yet. */
3325 #if 0
3326 ZV -= reduced_size;
3327 Z -= reduced_size;
3328 GPT -= reduced_size;
3329 GAP_SIZE += reduced_size;
3330 inserted -= reduced_size;
3331 #endif
3332 this_len -= reduced_size;
3333
3334 /* Change buffer_file_type back to binary if Unix eol format. */
3335 if (crlf_count == 0 && lf_count > 0)
3336 current_buffer->buffer_file_type = Qt;
3337 }
3338
3339 /* Make crlf_count and lf_count available for inspection. */
3340 Fset (intern ("buffer-file-lines"), make_int (lf_count));
3341 Fset (intern ("buffer-file-dos-lines"), make_int (crlf_count));
3342 #endif /* DOS_NT */
2778 3343
2779 cc_inserted = buffer_insert_raw_string_1 (buf, cur_point, read_buf, 3344 cc_inserted = buffer_insert_raw_string_1 (buf, cur_point, read_buf,
2780 this_len, 3345 this_len,
2781 !NILP (visit) 3346 !NILP (visit)
2782 ? INSDEL_NO_LOCKING : 0); 3347 ? INSDEL_NO_LOCKING : 0);
2790 XCODING_SYSTEM_NAME (decoding_stream_coding_system (XLSTREAM (stream)))); 3355 XCODING_SYSTEM_NAME (decoding_stream_coding_system (XLSTREAM (stream))));
2791 } 3356 }
2792 #endif /* MULE */ 3357 #endif /* MULE */
2793 NUNGCPRO; 3358 NUNGCPRO;
2794 } 3359 }
2795
2796 #if 0
2797 /* XXXX Why the #### ? Bogus anyway. If they are there, display em! */
2798 #ifdef DOS_NT
2799 /* Determine file type from name and remove LFs from CR-LFs if the file
2800 is deemed to be a text file. */
2801 {
2802 struct gcpro gcpro1;
2803 GCPRO1 (filename);
2804 buf->buffer_file_type
2805 = call1_in_buffer (buf, Qfind_buffer_file_type, filename);
2806 UNGCPRO;
2807 if (NILP (buf->buffer_file_type))
2808 {
2809 buffer_do_msdos_crlf_to_lf (buf, ####);
2810 }
2811 }
2812 #endif
2813 #endif /* 0 */
2814 3360
2815 /* Close the file/stream */ 3361 /* Close the file/stream */
2816 unbind_to (speccount, Qnil); 3362 unbind_to (speccount, Qnil);
2817 3363
2818 if (saverrno != 0) 3364 if (saverrno != 0)
2956 we should signal an error rather than blissfully continuing 3502 we should signal an error rather than blissfully continuing
2957 along. ARGH, this function is going to lose lose lose. We need 3503 along. ARGH, this function is going to lose lose lose. We need
2958 to protect the current_buffer from being destroyed, but the 3504 to protect the current_buffer from being destroyed, but the
2959 multiple return points make this a pain in the butt. */ 3505 multiple return points make this a pain in the butt. */
2960 3506
2961 #if 0
2962 #ifdef DOS_NT 3507 #ifdef DOS_NT
2963 int buffer_file_type 3508 int buffer_file_type
2964 = NILP (current_buffer->buffer_file_type) ? O_TEXT : O_BINARY; 3509 = NILP (current_buffer->buffer_file_type) ? O_TEXT : O_BINARY;
2965 #endif /* DOS_NT */ 3510 #endif /* DOS_NT */
2966 #endif /* 0 */
2967 3511
2968 #ifdef MULE 3512 #ifdef MULE
2969 codesys = Fget_coding_system (codesys); 3513 codesys = Fget_coding_system (codesys);
2970 #endif /* MULE */ 3514 #endif /* MULE */
2971 3515
3048 fn = filename; 3592 fn = filename;
3049 desc = -1; 3593 desc = -1;
3050 if (!NILP (append)) 3594 if (!NILP (append))
3051 #ifdef DOS_NT 3595 #ifdef DOS_NT
3052 desc = open ((char *) XSTRING_DATA (fn), 3596 desc = open ((char *) XSTRING_DATA (fn),
3053 (O_WRONLY | O_BINARY), 0); 3597 (O_WRONLY | buffer_file_type), 0);
3054 #else /* not DOS_NT */ 3598 #else /* not DOS_NT */
3055 desc = open ((char *) XSTRING_DATA (fn), O_WRONLY, 0); 3599 desc = open ((char *) XSTRING_DATA (fn), O_WRONLY, 0);
3056 #endif /* not DOS_NT */ 3600 #endif /* not DOS_NT */
3057 3601
3058 if (desc < 0) 3602 if (desc < 0)
3059 { 3603 {
3060 #ifdef DOS_NT 3604 #ifdef DOS_NT
3061 desc = open ((char *) XSTRING_DATA (fn), 3605 desc = open ((char *) XSTRING_DATA (fn),
3062 (O_WRONLY | O_TRUNC | O_CREAT | O_BINARY), 3606 (O_WRONLY | O_TRUNC | O_CREAT | buffer_file_type),
3063 (S_IREAD | S_IWRITE)); 3607 (S_IREAD | S_IWRITE));
3064 #else /* not DOS_NT */ 3608 #else /* not DOS_NT */
3065 desc = creat ((char *) XSTRING_DATA (fn), 3609 desc = creat ((char *) XSTRING_DATA (fn),
3066 ((auto_saving) ? auto_save_mode_bits : 0666)); 3610 ((auto_saving) ? auto_save_mode_bits : 0666));
3067 #endif /* DOS_NT */ 3611 #endif /* DOS_NT */
4219 This is to prevent you from losing your edits if you accidentally 4763 This is to prevent you from losing your edits if you accidentally
4220 delete a large chunk of the buffer and don't notice it until too late. 4764 delete a large chunk of the buffer and don't notice it until too late.
4221 Saving the buffer normally turns auto-save back on. 4765 Saving the buffer normally turns auto-save back on.
4222 */ ); 4766 */ );
4223 disable_auto_save_when_buffer_shrinks = 1; 4767 disable_auto_save_when_buffer_shrinks = 1;
4224 } 4768 #ifdef DOS_NT
4769 DEFVAR_LISP ("directory-sep-char", &Vdirectory_sep_char /*
4770 *Directory separator character for built-in functions that return file names.
4771 The value should be either ?/ or ?\\ (any other value is treated as ?\\).
4772 This variable affects the built-in functions only on Windows,
4773 on other platforms, it is initialized so that Lisp code can find out
4774 what the normal separator is.
4775 */ );
4776 Vdirectory_sep_char = '/';
4777
4778 DEFVAR_LISP ("insert-file-contents-allow-replace", &Vinsert_file_contents_allow_replace /*
4779 *Allow REPLACE option of insert-file-contents to preserve markers.
4780 If non-nil, the REPLACE option works as described, preserving markers.
4781 If nil, the REPLACE option is implemented by deleting the visible region
4782 then inserting the file contents as if REPLACE was nil.
4783
4784 This option is only meaningful on Windows.
4785 */ );
4786 Vinsert_file_contents_allow_replace = Qt;
4787 #endif
4788 }