Mercurial > hg > xemacs-beta
comparison src/fileio.c @ 265:8efd647ea9ca r20-5b31
Import from CVS: tag r20-5b31
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:25:37 +0200 |
parents | 727739f917cb |
children | 966663fcf606 |
comparison
equal
deleted
inserted
replaced
264:682d2a9d41a5 | 265:8efd647ea9ca |
---|---|
54 #endif /* HPUX */ | 54 #endif /* HPUX */ |
55 | 55 |
56 #ifdef WINDOWSNT | 56 #ifdef WINDOWSNT |
57 #define NOMINMAX 1 | 57 #define NOMINMAX 1 |
58 #include <windows.h> | 58 #include <windows.h> |
59 #include <direct.h> | |
60 #include <fcntl.h> | |
59 #include <stdlib.h> | 61 #include <stdlib.h> |
60 #include <fcntl.h> | |
61 #endif /* not WINDOWSNT */ | 62 #endif /* not WINDOWSNT */ |
62 | 63 |
63 #ifdef DOS_NT | 64 #ifdef WINDOWSNT |
64 #define CORRECT_DIR_SEPS(s) \ | 65 #define CORRECT_DIR_SEPS(s) \ |
65 do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \ | 66 do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \ |
66 else unixtodos_filename (s); \ | 67 else unixtodos_filename (s); \ |
67 } while (0) | 68 } 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') | |
72 #endif | |
73 #ifdef WINDOWSNT | |
74 #define IS_DRIVE(x) isalpha (x) | 69 #define IS_DRIVE(x) isalpha (x) |
75 #endif | |
76 /* Need to lower-case the drive letter, or else expanded | 70 /* Need to lower-case the drive letter, or else expanded |
77 filenames will sometimes compare inequal, because | 71 filenames will sometimes compare inequal, because |
78 `expand-file-name' doesn't always down-case the drive letter. */ | 72 `expand-file-name' doesn't always down-case the drive letter. */ |
79 #define DRIVE_LETTER(x) (tolower (x)) | 73 #define DRIVE_LETTER(x) (tolower (x)) |
80 #endif /* DOS_NT */ | 74 #endif /* WINDOWSNT */ |
81 | 75 |
82 /* Nonzero during writing of auto-save files */ | 76 /* Nonzero during writing of auto-save files */ |
83 static int auto_saving; | 77 static int auto_saving; |
84 | 78 |
85 /* Set by auto_save_1 to mode of original file so Fwrite_region_internal | 79 /* Set by auto_save_1 to mode of original file so Fwrite_region_internal |
121 expanding file names. This can be bound to / or \. | 115 expanding file names. This can be bound to / or \. |
122 | 116 |
123 This needs to be initialized statically, because file name functions | 117 This needs to be initialized statically, because file name functions |
124 are called during initialization. */ | 118 are called during initialization. */ |
125 Lisp_Object Vdirectory_sep_char; | 119 Lisp_Object Vdirectory_sep_char; |
126 | |
127 #ifdef DOS_NT | |
128 /* Until we can figure out how to deal with the functions in this file in | |
129 a civilized fashion, this will remain #ifdef'ed out. -slb */ | |
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 */ | |
135 | 120 |
136 /* These variables describe handlers that have "already" had a chance | 121 /* These variables describe handlers that have "already" had a chance |
137 to handle the current operation. | 122 to handle the current operation. |
138 | 123 |
139 Vinhibit_file_name_handlers is a list of file name handlers. | 124 Vinhibit_file_name_handlers is a list of file name handlers. |
459 #endif | 444 #endif |
460 beg = XSTRING_DATA (file); | 445 beg = XSTRING_DATA (file); |
461 p = beg + XSTRING_LENGTH (file); | 446 p = beg + XSTRING_LENGTH (file); |
462 | 447 |
463 while (p != beg && !IS_ANY_SEP (p[-1]) | 448 while (p != beg && !IS_ANY_SEP (p[-1]) |
464 #ifdef DOS_NT | 449 #ifdef WINDOWSNT |
465 /* only recognise drive specifier at beginning */ | 450 /* only recognise drive specifier at beginning */ |
466 && !(p[-1] == ':' && p == beg + 2) | 451 && !(p[-1] == ':' && p == beg + 2) |
467 #endif | 452 #endif |
468 ) p--; | 453 ) p--; |
469 | 454 |
470 if (p == beg) | 455 if (p == beg) |
471 return Qnil; | 456 return Qnil; |
472 #ifdef DOS_NT | 457 #ifdef WINDOWSNT |
473 /* Expansion of "c:" to drive and default directory. */ | 458 /* Expansion of "c:" to drive and default directory. */ |
474 /* (NT does the right thing.) */ | 459 /* (NT does the right thing.) */ |
475 if (p == beg + 2 && beg[1] == ':') | 460 if (p == beg + 2 && beg[1] == ':') |
476 { | 461 { |
477 /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */ | 462 /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */ |
483 beg = res; | 468 beg = res; |
484 p = beg + strlen ((char *) beg); | 469 p = beg + strlen ((char *) beg); |
485 } | 470 } |
486 } | 471 } |
487 CORRECT_DIR_SEPS (beg); | 472 CORRECT_DIR_SEPS (beg); |
488 #endif /* DOS_NT */ | 473 #endif /* WINDOWSNT */ |
489 return make_string (beg, p - beg); | 474 return make_string (beg, p - beg); |
490 } | 475 } |
491 | 476 |
492 DEFUN ("file-name-nondirectory", Ffile_name_nondirectory, 1, 1, 0, /* | 477 DEFUN ("file-name-nondirectory", Ffile_name_nondirectory, 1, 1, 0, /* |
493 Return file name NAME sans its directory. | 478 Return file name NAME sans its directory. |
511 | 496 |
512 beg = XSTRING_DATA (file); | 497 beg = XSTRING_DATA (file); |
513 end = p = beg + XSTRING_LENGTH (file); | 498 end = p = beg + XSTRING_LENGTH (file); |
514 | 499 |
515 while (p != beg && !IS_ANY_SEP (p[-1]) | 500 while (p != beg && !IS_ANY_SEP (p[-1]) |
516 #ifdef DOS_NT | 501 #ifdef WINDOWSNT |
517 /* only recognise drive specifier at beginning */ | 502 /* only recognise drive specifier at beginning */ |
518 && !(p[-1] == ':' && p == beg + 2) | 503 && !(p[-1] == ':' && p == beg + 2) |
519 #endif | 504 #endif |
520 ) p--; | 505 ) p--; |
521 | 506 |
558 if (!IS_ANY_SEP (out[size])) | 543 if (!IS_ANY_SEP (out[size])) |
559 { | 544 { |
560 out[size + 1] = DIRECTORY_SEP; | 545 out[size + 1] = DIRECTORY_SEP; |
561 out[size + 2] = '\0'; | 546 out[size + 2] = '\0'; |
562 } | 547 } |
563 #ifdef DOS_NT | 548 #ifdef WINDOWSNT |
564 CORRECT_DIR_SEPS (out); | 549 CORRECT_DIR_SEPS (out); |
565 #endif | 550 #endif |
566 return out; | 551 return out; |
567 } | 552 } |
568 | 553 |
594 } | 579 } |
595 | 580 |
596 /* | 581 /* |
597 * Convert from directory name to filename. | 582 * Convert from directory name to filename. |
598 * On UNIX, it's simple: just make sure there isn't a terminating / | 583 * On UNIX, it's simple: just make sure there isn't a terminating / |
599 | 584 * |
600 * Value is nonzero if the string output is different from the input. | 585 * Value is nonzero if the string output is different from the input. |
601 */ | 586 */ |
602 | 587 |
603 static int | 588 static int |
604 directory_file_name (CONST char *src, char *dst) | 589 directory_file_name (CONST char *src, char *dst) |
615 || (slen > 1 && dst[0] != '/' && dst[slen - 1] == '/')) | 600 || (slen > 1 && dst[0] != '/' && dst[slen - 1] == '/')) |
616 dst[slen - 1] = 0; | 601 dst[slen - 1] = 0; |
617 #else | 602 #else |
618 if (slen > 1 | 603 if (slen > 1 |
619 && IS_DIRECTORY_SEP (dst[slen - 1]) | 604 && IS_DIRECTORY_SEP (dst[slen - 1]) |
620 #ifdef DOS_NT | 605 #ifdef WINDOWSNT |
621 && !IS_ANY_SEP (dst[slen - 2]) | 606 && !IS_ANY_SEP (dst[slen - 2]) |
622 #endif /* DOS_NT */ | 607 #endif /* WINDOWSNT */ |
623 ) | 608 ) |
624 dst[slen - 1] = 0; | 609 dst[slen - 1] = 0; |
625 #endif /* APOLLO */ | 610 #endif /* APOLLO */ |
626 #ifdef DOS_NT | 611 #ifdef WINDOWSNT |
627 CORRECT_DIR_SEPS (dst); | 612 CORRECT_DIR_SEPS (dst); |
628 #endif /* DOS_NT */ | 613 #endif /* WINDOWSNT */ |
629 return 1; | 614 return 1; |
630 } | 615 } |
631 | 616 |
632 DEFUN ("directory-file-name", Fdirectory_file_name, 1, 1, 0, /* | 617 DEFUN ("directory-file-name", Fdirectory_file_name, 1, 1, 0, /* |
633 Return the file name of the directory named DIR. | 618 Return the file name of the directory named DIR. |
678 memcpy (data, XSTRING_DATA (prefix), len); | 663 memcpy (data, XSTRING_DATA (prefix), len); |
679 memcpy (data + len, suffix, countof (suffix)); | 664 memcpy (data + len, suffix, countof (suffix)); |
680 /* !!#### does mktemp() Mule-encapsulate? */ | 665 /* !!#### does mktemp() Mule-encapsulate? */ |
681 mktemp ((char *) data); | 666 mktemp ((char *) data); |
682 | 667 |
683 #ifdef DOS_NT | 668 #ifdef WINDOWSNT |
684 CORRECT_DIR_SEPS (XSTRING_DATA (val)); | 669 CORRECT_DIR_SEPS (XSTRING_DATA (val)); |
685 #endif /* DOS_NT */ | 670 #endif /* WINDOWSNT */ |
686 return val; | 671 return val; |
687 } | 672 } |
688 | 673 |
689 DEFUN ("expand-file-name", Fexpand_file_name, 1, 2, 0, /* | 674 DEFUN ("expand-file-name", Fexpand_file_name, 1, 2, 0, /* |
690 Convert filename NAME to absolute, and canonicalize it. | 675 Convert filename NAME to absolute, and canonicalize it. |
705 Bufbyte *nm; | 690 Bufbyte *nm; |
706 | 691 |
707 Bufbyte *newdir, *p, *o; | 692 Bufbyte *newdir, *p, *o; |
708 int tlen; | 693 int tlen; |
709 Bufbyte *target; | 694 Bufbyte *target; |
710 struct passwd *pw; | 695 #ifdef WINDOWSNT |
711 #ifdef DOS_NT | |
712 int drive = 0; | 696 int drive = 0; |
713 int collapse_newdir = 1; | 697 int collapse_newdir = 1; |
714 #endif /* DOS_NT */ | 698 #else |
699 struct passwd *pw; | |
700 #endif /* WINDOWSNT */ | |
715 int length; | 701 int length; |
716 Lisp_Object handler; | 702 Lisp_Object handler; |
717 | 703 |
718 CHECK_STRING (name); | 704 CHECK_STRING (name); |
719 | 705 |
751 The EQ test avoids infinite recursion. */ | 737 The EQ test avoids infinite recursion. */ |
752 if (! NILP (default_directory) && !EQ (default_directory, name) | 738 if (! NILP (default_directory) && !EQ (default_directory, name) |
753 /* Save time in some common cases - as long as default_directory | 739 /* Save time in some common cases - as long as default_directory |
754 is not relative, it can be canonicalized with name below (if it | 740 is not relative, it can be canonicalized with name below (if it |
755 is needed at all) without requiring it to be expanded now. */ | 741 is needed at all) without requiring it to be expanded now. */ |
756 #ifdef DOS_NT | 742 #ifdef WINDOWSNT |
757 /* Detect MSDOS file names with drive specifiers. */ | 743 /* Detect MSDOS file names with drive specifiers. */ |
758 && ! (IS_DRIVE (o[0]) && (IS_DEVICE_SEP (o[1]) && IS_DIRECTORY_SEP (o[2]))) | 744 && ! (IS_DRIVE (o[0]) && (IS_DEVICE_SEP (o[1]) && IS_DIRECTORY_SEP (o[2]))) |
759 #ifdef WINDOWSNT | |
760 /* Detect Windows file names in UNC format. */ | 745 /* Detect Windows file names in UNC format. */ |
761 && ! (IS_DIRECTORY_SEP (o[0]) && IS_DIRECTORY_SEP (o[1])) | 746 && ! (IS_DIRECTORY_SEP (o[0]) && IS_DIRECTORY_SEP (o[1])) |
762 #endif | 747 |
763 #else /* not DOS_NT */ | 748 #else /* not WINDOWSNT */ |
749 | |
764 /* Detect Unix absolute file names (/... alone is not absolute on | 750 /* Detect Unix absolute file names (/... alone is not absolute on |
765 DOS or Windows). */ | 751 DOS or Windows). */ |
766 && ! (IS_DIRECTORY_SEP (o[0])) | 752 && ! (IS_DIRECTORY_SEP (o[0])) |
767 #endif /* not DOS_NT */ | 753 #endif /* not WINDOWSNT */ |
768 ) | 754 ) |
769 { | 755 { |
770 struct gcpro gcpro1; | 756 struct gcpro gcpro1; |
771 | 757 |
772 GCPRO1 (name); | 758 GCPRO1 (name); |
780 | 766 |
781 /* #### dmoore - this is ugly, clean this up. Looks like nm pointing | 767 /* #### dmoore - this is ugly, clean this up. Looks like nm pointing |
782 into name should be safe during all of this, though. */ | 768 into name should be safe during all of this, though. */ |
783 nm = XSTRING_DATA (name); | 769 nm = XSTRING_DATA (name); |
784 | 770 |
785 #ifdef DOS_NT | 771 #ifdef WINDOWSNT |
786 /* We will force directory separators to be either all \ or /, so make | 772 /* We will force directory separators to be either all \ or /, so make |
787 a local copy to modify, even if there ends up being no change. */ | 773 a local copy to modify, even if there ends up being no change. */ |
788 nm = strcpy (alloca (strlen (nm) + 1), nm); | 774 nm = strcpy (alloca (strlen (nm) + 1), nm); |
789 | 775 |
790 /* Find and remove drive specifier if present; this makes nm absolute | 776 /* Find and remove drive specifier if present; this makes nm absolute |
813 if (colon[0] == ':') | 799 if (colon[0] == ':') |
814 goto look_again; | 800 goto look_again; |
815 } | 801 } |
816 } | 802 } |
817 | 803 |
818 #ifdef WINDOWSNT | |
819 /* If we see "c://somedir", we want to strip the first slash after the | 804 /* If we see "c://somedir", we want to strip the first slash after the |
820 colon when stripping the drive letter. Otherwise, this expands to | 805 colon when stripping the drive letter. Otherwise, this expands to |
821 "//somedir". */ | 806 "//somedir". */ |
822 if (drive && IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])) | 807 if (drive && IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])) |
823 nm++; | 808 nm++; |
824 #endif /* WINDOWSNT */ | 809 |
825 #endif /* DOS_NT */ | |
826 | |
827 #ifdef WINDOWSNT | |
828 /* Discard any previous drive specifier if nm is now in UNC format. */ | 810 /* Discard any previous drive specifier if nm is now in UNC format. */ |
829 if (IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])) | 811 if (IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])) |
830 { | 812 { |
831 drive = 0; | 813 drive = 0; |
832 } | 814 } |
835 /* If nm is absolute, look for /./ or /../ sequences; if none are | 817 /* If nm is absolute, look for /./ or /../ sequences; if none are |
836 found, we can probably return right away. We will avoid allocating | 818 found, we can probably return right away. We will avoid allocating |
837 a new string if name is already fully expanded. */ | 819 a new string if name is already fully expanded. */ |
838 if ( | 820 if ( |
839 IS_DIRECTORY_SEP (nm[0]) | 821 IS_DIRECTORY_SEP (nm[0]) |
840 #ifdef MSDOS | |
841 && drive | |
842 #endif | |
843 #ifdef WINDOWSNT | 822 #ifdef WINDOWSNT |
844 && (drive || IS_DIRECTORY_SEP (nm[1])) | 823 && (drive || IS_DIRECTORY_SEP (nm[1])) |
845 #endif | 824 #endif |
846 ) | 825 ) |
847 { | 826 { |
869 lose = 1; | 848 lose = 1; |
870 p++; | 849 p++; |
871 } | 850 } |
872 if (!lose) | 851 if (!lose) |
873 { | 852 { |
874 #ifdef DOS_NT | 853 #ifdef WINDOWSNT |
875 /* Make sure directories are all separated with / or \ as | 854 /* Make sure directories are all separated with / or \ as |
876 desired, but avoid allocation of a new string when not | 855 desired, but avoid allocation of a new string when not |
877 required. */ | 856 required. */ |
878 CORRECT_DIR_SEPS (nm); | 857 CORRECT_DIR_SEPS (nm); |
879 #ifdef WINDOWSNT | |
880 if (IS_DIRECTORY_SEP (nm[1])) | 858 if (IS_DIRECTORY_SEP (nm[1])) |
881 { | 859 { |
882 if (strcmp (nm, XSTRING_DATA (name)) != 0) | 860 if (strcmp (nm, XSTRING_DATA (name)) != 0) |
883 name = build_string (nm); | 861 name = build_string (nm); |
884 } | 862 } |
885 else | |
886 #endif | |
887 /* drive must be set, so this is okay */ | 863 /* drive must be set, so this is okay */ |
888 if (strcmp (nm - 2, XSTRING_DATA (name)) != 0) | 864 else if (strcmp (nm - 2, XSTRING_DATA (name)) != 0) |
889 { | 865 { |
890 name = make_string (nm - 2, p - nm + 2); | 866 name = make_string (nm - 2, p - nm + 2); |
891 XSTRING_DATA (name)[0] = DRIVE_LETTER (drive); | 867 XSTRING_DATA (name)[0] = DRIVE_LETTER (drive); |
892 XSTRING_DATA (name)[1] = ':'; | 868 XSTRING_DATA (name)[1] = ':'; |
893 } | 869 } |
894 return name; | 870 return name; |
895 #else /* not DOS_NT */ | 871 #else /* not WINDOWSNT */ |
896 if (nm == XSTRING_DATA (name)) | 872 if (nm == XSTRING_DATA (name)) |
897 return name; | 873 return name; |
898 return build_string (nm); | 874 return build_string (nm); |
899 #endif /* not DOS_NT */ | 875 #endif /* not WINDOWSNT */ |
900 } | 876 } |
901 } | 877 } |
902 | 878 |
903 /* At this point, nm might or might not be an absolute file name. We | 879 /* At this point, nm might or might not be an absolute file name. We |
904 need to expand ~ or ~user if present, otherwise prefix nm with | 880 need to expand ~ or ~user if present, otherwise prefix nm with |
924 || nm[1] == 0) /* ~ by itself */ | 900 || nm[1] == 0) /* ~ by itself */ |
925 { | 901 { |
926 if (!(newdir = (Bufbyte *) egetenv ("HOME"))) | 902 if (!(newdir = (Bufbyte *) egetenv ("HOME"))) |
927 newdir = (Bufbyte *) ""; | 903 newdir = (Bufbyte *) ""; |
928 nm++; | 904 nm++; |
929 #ifdef DOS_NT | 905 #ifdef WINDOWSNT |
930 collapse_newdir = 0; | 906 collapse_newdir = 0; |
931 #endif | 907 #endif |
932 } | 908 } |
933 else /* ~user/filename */ | 909 else /* ~user/filename */ |
934 { | 910 { |
969 /* If we don't find a user of that name, leave the name | 945 /* If we don't find a user of that name, leave the name |
970 unchanged; don't move nm forward to p. */ | 946 unchanged; don't move nm forward to p. */ |
971 } | 947 } |
972 } | 948 } |
973 | 949 |
974 #ifdef DOS_NT | 950 #ifdef WINDOWSNT |
975 /* On DOS and Windows, nm is absolute if a drive name was specified; | 951 /* On DOS and Windows, nm is absolute if a drive name was specified; |
976 use the drive's current directory as the prefix if needed. */ | 952 use the drive's current directory as the prefix if needed. */ |
977 if (!newdir && drive) | 953 if (!newdir && drive) |
978 { | 954 { |
979 /* Get default directory if needed to make nm absolute. */ | 955 /* Get default directory if needed to make nm absolute. */ |
991 newdir[1] = ':'; | 967 newdir[1] = ':'; |
992 newdir[2] = '/'; | 968 newdir[2] = '/'; |
993 newdir[3] = 0; | 969 newdir[3] = 0; |
994 } | 970 } |
995 } | 971 } |
996 #endif /* DOS_NT */ | 972 #endif /* WINDOWSNT */ |
997 | 973 |
998 /* Finally, if no prefix has been specified and nm is not absolute, | 974 /* Finally, if no prefix has been specified and nm is not absolute, |
999 then it must be expanded relative to default_directory. */ | 975 then it must be expanded relative to default_directory. */ |
1000 | 976 |
1001 if (1 | 977 if (1 |
1002 #ifndef DOS_NT | 978 #ifndef WINDOWSNT |
1003 /* /... alone is not absolute on DOS and Windows. */ | 979 /* /... alone is not absolute on DOS and Windows. */ |
1004 && !IS_DIRECTORY_SEP (nm[0]) | 980 && !IS_DIRECTORY_SEP (nm[0]) |
1005 #endif | 981 #else |
1006 #ifdef WINDOWSNT | |
1007 && !(IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])) | 982 && !(IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])) |
1008 #endif | 983 #endif |
1009 && !newdir) | 984 && !newdir) |
1010 { | 985 { |
1011 newdir = XSTRING_DATA (default_directory); | 986 newdir = XSTRING_DATA (default_directory); |
1012 } | 987 } |
1013 | 988 |
1014 #ifdef DOS_NT | 989 #ifdef WINDOWSNT |
1015 if (newdir) | 990 if (newdir) |
1016 { | 991 { |
1017 /* First ensure newdir is an absolute name. */ | 992 /* First ensure newdir is an absolute name. */ |
1018 if ( | 993 if ( |
1019 /* Detect MSDOS file names with drive specifiers. */ | 994 /* Detect MSDOS file names with drive specifiers. */ |
1020 ! (IS_DRIVE (newdir[0]) | 995 ! (IS_DRIVE (newdir[0]) |
1021 && IS_DEVICE_SEP (newdir[1]) && IS_DIRECTORY_SEP (newdir[2])) | 996 && IS_DEVICE_SEP (newdir[1]) && IS_DIRECTORY_SEP (newdir[2])) |
1022 #ifdef WINDOWSNT | |
1023 /* Detect Windows file names in UNC format. */ | 997 /* Detect Windows file names in UNC format. */ |
1024 && ! (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1])) | 998 && ! (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1])) |
1025 #endif | |
1026 ) | 999 ) |
1027 { | 1000 { |
1028 /* Effectively, let newdir be (expand-file-name newdir cwd). | 1001 /* Effectively, let newdir be (expand-file-name newdir cwd). |
1029 Because of the admonition against calling expand-file-name | 1002 Because of the admonition against calling expand-file-name |
1030 when we have pointers into lisp strings, we accomplish this | 1003 when we have pointers into lisp strings, we accomplish this |
1062 | 1035 |
1063 /* Keep only a prefix from newdir if nm starts with slash | 1036 /* Keep only a prefix from newdir if nm starts with slash |
1064 (/ /server/share for UNC, nothing otherwise). */ | 1037 (/ /server/share for UNC, nothing otherwise). */ |
1065 if (IS_DIRECTORY_SEP (nm[0]) && collapse_newdir) | 1038 if (IS_DIRECTORY_SEP (nm[0]) && collapse_newdir) |
1066 { | 1039 { |
1067 #ifdef WINDOWSNT | |
1068 if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1])) | 1040 if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1])) |
1069 { | 1041 { |
1070 newdir = strcpy (alloca (strlen (newdir) + 1), newdir); | 1042 newdir = strcpy (alloca (strlen (newdir) + 1), newdir); |
1071 p = newdir + 2; | 1043 p = newdir + 2; |
1072 while (*p && !IS_DIRECTORY_SEP (*p)) p++; | 1044 while (*p && !IS_DIRECTORY_SEP (*p)) p++; |
1073 p++; | 1045 p++; |
1074 while (*p && !IS_DIRECTORY_SEP (*p)) p++; | 1046 while (*p && !IS_DIRECTORY_SEP (*p)) p++; |
1075 *p = 0; | 1047 *p = 0; |
1076 } | 1048 } |
1077 else | 1049 else |
1078 #endif | |
1079 newdir = ""; | 1050 newdir = ""; |
1080 } | 1051 } |
1081 } | 1052 } |
1082 #endif /* DOS_NT */ | 1053 #endif /* WINDOWSNT */ |
1083 | 1054 |
1084 if (newdir) | 1055 if (newdir) |
1085 { | 1056 { |
1086 /* Get rid of any slash at the end of newdir, unless newdir is | 1057 /* Get rid of any slash at the end of newdir, unless newdir is |
1087 just // (an incomplete UNC name). */ | 1058 just // (an incomplete UNC name). */ |
1102 else | 1073 else |
1103 tlen = 0; | 1074 tlen = 0; |
1104 | 1075 |
1105 /* Now concatenate the directory and name to new space in the stack frame */ | 1076 /* Now concatenate the directory and name to new space in the stack frame */ |
1106 tlen += strlen (nm) + 1; | 1077 tlen += strlen (nm) + 1; |
1107 #ifdef DOS_NT | 1078 #ifdef WINDOWSNT |
1108 /* Add reserved space for drive name. (The Microsoft x86 compiler | 1079 /* Add reserved space for drive name. (The Microsoft x86 compiler |
1109 produces incorrect code if the following two lines are combined.) */ | 1080 produces incorrect code if the following two lines are combined.) */ |
1110 target = (Bufbyte *) alloca (tlen + 2); | 1081 target = (Bufbyte *) alloca (tlen + 2); |
1111 target += 2; | 1082 target += 2; |
1112 #else /* not DOS_NT */ | 1083 #else /* not WINDOWSNT */ |
1113 target = (Bufbyte *) alloca (tlen); | 1084 target = (Bufbyte *) alloca (tlen); |
1114 #endif /* not DOS_NT */ | 1085 #endif /* not WINDOWSNT */ |
1115 *target = 0; | 1086 *target = 0; |
1116 | 1087 |
1117 if (newdir) | 1088 if (newdir) |
1118 { | 1089 { |
1119 if (nm[0] == 0 || IS_DIRECTORY_SEP (nm[0])) | 1090 if (nm[0] == 0 || IS_DIRECTORY_SEP (nm[0])) |
1164 { | 1135 { |
1165 *o++ = *p++; | 1136 *o++ = *p++; |
1166 } | 1137 } |
1167 } | 1138 } |
1168 | 1139 |
1169 #ifdef DOS_NT | |
1170 /* At last, set drive name. */ | |
1171 #ifdef WINDOWSNT | 1140 #ifdef WINDOWSNT |
1172 /* Except for network file name. */ | 1141 /* At last, set drive name, except for network file name. */ |
1173 if (!(IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1]))) | 1142 if (!(IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1]))) |
1174 #endif /* WINDOWSNT */ | |
1175 { | 1143 { |
1176 if (!drive) abort (); | 1144 if (!drive) abort (); |
1177 target -= 2; | 1145 target -= 2; |
1178 target[0] = DRIVE_LETTER (drive); | 1146 target[0] = DRIVE_LETTER (drive); |
1179 target[1] = ':'; | 1147 target[1] = ':'; |
1180 } | 1148 } |
1181 CORRECT_DIR_SEPS (target); | 1149 CORRECT_DIR_SEPS (target); |
1182 #endif /* DOS_NT */ | 1150 #endif /* WINDOWSNT */ |
1183 | 1151 |
1184 return make_string (target, o - target); | 1152 return make_string (target, o - target); |
1185 } | 1153 } |
1186 | 1154 |
1187 #if 0 /* FSFmacs */ | 1155 #if 0 /* FSFmacs */ |
1336 if (!NILP (handler)) | 1304 if (!NILP (handler)) |
1337 return call2_check_string_or_nil (handler, Qsubstitute_in_file_name, | 1305 return call2_check_string_or_nil (handler, Qsubstitute_in_file_name, |
1338 string); | 1306 string); |
1339 | 1307 |
1340 nm = XSTRING_DATA (string); | 1308 nm = XSTRING_DATA (string); |
1341 #ifdef DOS_NT | 1309 #ifdef WINDOWSNT |
1342 nm = strcpy (alloca (strlen (nm) + 1), nm); | 1310 nm = strcpy (alloca (strlen (nm) + 1), nm); |
1343 CORRECT_DIR_SEPS (nm); | 1311 CORRECT_DIR_SEPS (nm); |
1344 substituted = (strcmp (nm, XSTRING_DATA (string)) != 0); | 1312 substituted = (strcmp (nm, XSTRING_DATA (string)) != 0); |
1345 #endif | 1313 #endif |
1346 endp = nm + XSTRING_LENGTH (string); | 1314 endp = nm + XSTRING_LENGTH (string); |
1362 && (IS_DIRECTORY_SEP (p[-1]))) | 1330 && (IS_DIRECTORY_SEP (p[-1]))) |
1363 { | 1331 { |
1364 nm = p; | 1332 nm = p; |
1365 substituted = 1; | 1333 substituted = 1; |
1366 } | 1334 } |
1367 #ifdef DOS_NT | 1335 #ifdef WINDOWSNT |
1368 /* see comment in expand-file-name about drive specifiers */ | 1336 /* see comment in expand-file-name about drive specifiers */ |
1369 else if (IS_DRIVE (p[0]) && p[1] == ':' | 1337 else if (IS_DRIVE (p[0]) && p[1] == ':' |
1370 && p > nm && IS_DIRECTORY_SEP (p[-1])) | 1338 && p > nm && IS_DIRECTORY_SEP (p[-1])) |
1371 { | 1339 { |
1372 nm = p; | 1340 nm = p; |
1373 substituted = 1; | 1341 substituted = 1; |
1374 } | 1342 } |
1375 #endif /* DOS_NT */ | 1343 #endif /* WINDOWSNT */ |
1376 } | 1344 } |
1377 | 1345 |
1378 /* See if any variables are substituted into the string | 1346 /* See if any variables are substituted into the string |
1379 and find the total length of their values in `total' */ | 1347 and find the total length of their values in `total' */ |
1380 | 1348 |
1410 | 1378 |
1411 /* Copy out the variable name */ | 1379 /* Copy out the variable name */ |
1412 target = (Bufbyte *) alloca (s - o + 1); | 1380 target = (Bufbyte *) alloca (s - o + 1); |
1413 strncpy ((char *) target, (char *) o, s - o); | 1381 strncpy ((char *) target, (char *) o, s - o); |
1414 target[s - o] = 0; | 1382 target[s - o] = 0; |
1415 #ifdef DOS_NT | 1383 #ifdef WINDOWSNT |
1416 strupr (target); /* $home == $HOME etc. */ | 1384 strupr (target); /* $home == $HOME etc. */ |
1417 #endif /* DOS_NT */ | 1385 #endif /* WINDOWSNT */ |
1418 | 1386 |
1419 /* Get variable value */ | 1387 /* Get variable value */ |
1420 o = (Bufbyte *) egetenv ((char *) target); | 1388 o = (Bufbyte *) egetenv ((char *) target); |
1421 if (!o) goto badvar; | 1389 if (!o) goto badvar; |
1422 total += strlen ((char *) o); | 1390 total += strlen ((char *) o); |
1461 | 1429 |
1462 /* Copy out the variable name */ | 1430 /* Copy out the variable name */ |
1463 target = (Bufbyte *) alloca (s - o + 1); | 1431 target = (Bufbyte *) alloca (s - o + 1); |
1464 strncpy ((char *) target, (char *) o, s - o); | 1432 strncpy ((char *) target, (char *) o, s - o); |
1465 target[s - o] = 0; | 1433 target[s - o] = 0; |
1466 #ifdef DOS_NT | 1434 #ifdef WINDOWSNT |
1467 strupr (target); /* $home == $HOME etc. */ | 1435 strupr (target); /* $home == $HOME etc. */ |
1468 #endif /* DOS_NT */ | 1436 #endif /* WINDOWSNT */ |
1469 | 1437 |
1470 /* Get variable value */ | 1438 /* Get variable value */ |
1471 o = (Bufbyte *) egetenv ((char *) target); | 1439 o = (Bufbyte *) egetenv ((char *) target); |
1472 if (!o) | 1440 if (!o) |
1473 goto badvar; | 1441 goto badvar; |
1489 #endif /* APOLLO || WINDOWSNT */ | 1457 #endif /* APOLLO || WINDOWSNT */ |
1490 ) | 1458 ) |
1491 /* don't do p[-1] if that would go off the beginning --jwz */ | 1459 /* don't do p[-1] if that would go off the beginning --jwz */ |
1492 && p != nm && p > xnm && IS_DIRECTORY_SEP (p[-1])) | 1460 && p != nm && p > xnm && IS_DIRECTORY_SEP (p[-1])) |
1493 xnm = p; | 1461 xnm = p; |
1494 #ifdef DOS_NT | 1462 #ifdef WINDOWSNT |
1495 else if (IS_DRIVE (p[0]) && p[1] == ':' | 1463 else if (IS_DRIVE (p[0]) && p[1] == ':' |
1496 && p > nm && IS_DIRECTORY_SEP (p[-1])) | 1464 && p > nm && IS_DIRECTORY_SEP (p[-1])) |
1497 xnm = p; | 1465 xnm = p; |
1498 #endif | 1466 #endif |
1499 | 1467 |
1664 | 1632 |
1665 /* We can only copy regular files and symbolic links. Other files are not | 1633 /* We can only copy regular files and symbolic links. Other files are not |
1666 copyable by us. */ | 1634 copyable by us. */ |
1667 input_file_statable_p = (fstat (ifd, &st) >= 0); | 1635 input_file_statable_p = (fstat (ifd, &st) >= 0); |
1668 | 1636 |
1669 #ifndef DOS_NT | 1637 #ifndef WINDOWSNT |
1670 if (out_st.st_mode != 0 | 1638 if (out_st.st_mode != 0 |
1671 && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino) | 1639 && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino) |
1672 { | 1640 { |
1673 errno = 0; | 1641 errno = 0; |
1674 report_file_error ("Input and output files are the same", | 1642 report_file_error ("Input and output files are the same", |
1693 report_file_error ("Non-regular file", list1 (filename)); | 1661 report_file_error ("Non-regular file", list1 (filename)); |
1694 } | 1662 } |
1695 } | 1663 } |
1696 #endif /* S_ISREG && S_ISLNK */ | 1664 #endif /* S_ISREG && S_ISLNK */ |
1697 | 1665 |
1698 #ifdef MSDOS | |
1699 /* System's default file type was set to binary by _fmode in emacs.c. */ | |
1700 ofd = creat ((char *) XSTRING_DATA (newname), S_IREAD | S_IWRITE); | |
1701 #else /* not MSDOS */ | |
1702 ofd = open( (char *) XSTRING_DATA (newname), | 1666 ofd = open( (char *) XSTRING_DATA (newname), |
1703 O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY, CREAT_MODE); | 1667 O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY, CREAT_MODE); |
1704 #endif /* not MSDOS */ | |
1705 if (ofd < 0) | 1668 if (ofd < 0) |
1706 report_file_error ("Opening output file", list1 (newname)); | 1669 report_file_error ("Opening output file", list1 (newname)); |
1707 | 1670 |
1708 { | 1671 { |
1709 Lisp_Object ofd_locative = noseeum_cons (make_int (ofd), Qnil); | 1672 Lisp_Object ofd_locative = noseeum_cons (make_int (ofd), Qnil); |
1729 EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0); | 1692 EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0); |
1730 if (set_file_times ((char *) XSTRING_DATA (newname), atime, | 1693 if (set_file_times ((char *) XSTRING_DATA (newname), atime, |
1731 mtime)) | 1694 mtime)) |
1732 report_file_error ("I/O error", list1 (newname)); | 1695 report_file_error ("I/O error", list1 (newname)); |
1733 } | 1696 } |
1734 #ifndef MSDOS | |
1735 chmod ((CONST char *) XSTRING_DATA (newname), | 1697 chmod ((CONST char *) XSTRING_DATA (newname), |
1736 st.st_mode & 07777); | 1698 st.st_mode & 07777); |
1737 #else /* MSDOS */ | |
1738 #if defined (__DJGPP__) && __DJGPP__ > 1 | |
1739 /* In DJGPP v2.0 and later, fstat usually returns true file mode bits, | |
1740 and if it can't, it tells so. Otherwise, under MSDOS we usually | |
1741 get only the READ bit, which will make the copied file read-only, | |
1742 so it's better not to chmod at all. */ | |
1743 if ((_djstat_flags & _STFAIL_WRITEBIT) == 0) | |
1744 chmod ((char *) XSTRING_DATA (newname), st.st_mode & 07777); | |
1745 #endif /* DJGPP version 2 or newer */ | |
1746 #endif /* MSDOS */ | |
1747 } | 1699 } |
1748 | 1700 |
1749 /* We'll close it by hand */ | 1701 /* We'll close it by hand */ |
1750 XCAR (ofd_locative) = Qnil; | 1702 XCAR (ofd_locative) = Qnil; |
1751 | 1703 |
2110 Bufbyte *ptr; | 2062 Bufbyte *ptr; |
2111 | 2063 |
2112 CHECK_STRING (filename); | 2064 CHECK_STRING (filename); |
2113 ptr = XSTRING_DATA (filename); | 2065 ptr = XSTRING_DATA (filename); |
2114 if (IS_DIRECTORY_SEP (*ptr) || *ptr == '~' | 2066 if (IS_DIRECTORY_SEP (*ptr) || *ptr == '~' |
2115 #ifdef DOS_NT | 2067 #ifdef WINDOWSNT |
2116 || (IS_DRIVE (*ptr) && ptr[1] == ':' && IS_DIRECTORY_SEP (ptr[2])) | 2068 || (IS_DRIVE (*ptr) && ptr[1] == ':' && IS_DIRECTORY_SEP (ptr[2])) |
2117 #endif | 2069 #endif |
2118 ) | 2070 ) |
2119 return Qt; | 2071 return Qt; |
2120 else | 2072 else |
2124 /* Return nonzero if file FILENAME exists and can be executed. */ | 2076 /* Return nonzero if file FILENAME exists and can be executed. */ |
2125 | 2077 |
2126 static int | 2078 static int |
2127 check_executable (char *filename) | 2079 check_executable (char *filename) |
2128 { | 2080 { |
2129 #ifdef DOS_NT | 2081 #ifdef WINDOWSNT |
2130 int len = strlen (filename); | |
2131 char *suffix; | |
2132 struct stat st; | 2082 struct stat st; |
2133 if (stat (filename, &st) < 0) | 2083 if (stat (filename, &st) < 0) |
2134 return 0; | 2084 return 0; |
2135 #if defined (WINDOWSNT) | |
2136 return ((st.st_mode & S_IEXEC) != 0); | 2085 return ((st.st_mode & S_IEXEC) != 0); |
2137 #else | 2086 #else /* not WINDOWSNT */ |
2138 return (S_ISREG (st.st_mode) | |
2139 && len >= 5 | |
2140 && (stricmp ((suffix = filename + len-4), ".com") == 0 | |
2141 || stricmp (suffix, ".exe") == 0 | |
2142 || stricmp (suffix, ".bat") == 0) | |
2143 || (st.st_mode & S_IFMT) == S_IFDIR); | |
2144 #endif /* not WINDOWSNT */ | |
2145 #else /* not DOS_NT */ | |
2146 #ifdef HAVE_EACCESS | 2087 #ifdef HAVE_EACCESS |
2147 return eaccess (filename, 1) >= 0; | 2088 return eaccess (filename, 1) >= 0; |
2148 #else | 2089 #else |
2149 /* Access isn't quite right because it uses the real uid | 2090 /* Access isn't quite right because it uses the real uid |
2150 and we really want to test with the effective uid. | 2091 and we really want to test with the effective uid. |
2151 But Unix doesn't give us a right way to do it. */ | 2092 But Unix doesn't give us a right way to do it. */ |
2152 return access (filename, 1) >= 0; | 2093 return access (filename, 1) >= 0; |
2153 #endif /* HAVE_EACCESS */ | 2094 #endif /* HAVE_EACCESS */ |
2154 #endif /* not DOS_NT */ | 2095 #endif /* not WINDOWSNT */ |
2155 } | 2096 } |
2156 | 2097 |
2157 /* Return nonzero if file FILENAME exists and can be written. */ | 2098 /* Return nonzero if file FILENAME exists and can be written. */ |
2158 | 2099 |
2159 static int | 2100 static int |
2160 check_writable (CONST char *filename) | 2101 check_writable (CONST char *filename) |
2161 { | 2102 { |
2162 #ifdef MSDOS | |
2163 struct stat st; | |
2164 if (stat (filename, &st) < 0) | |
2165 return 0; | |
2166 return (st.st_mode & S_IWRITE || (st.st_mode & S_IFMT) == S_IFDIR); | |
2167 #else /* not MSDOS */ | |
2168 #ifdef HAVE_EACCESS | 2103 #ifdef HAVE_EACCESS |
2169 return (eaccess (filename, 2) >= 0); | 2104 return (eaccess (filename, 2) >= 0); |
2170 #else | 2105 #else |
2171 /* Access isn't quite right because it uses the real uid | 2106 /* Access isn't quite right because it uses the real uid |
2172 and we really want to test with the effective uid. | 2107 and we really want to test with the effective uid. |
2173 But Unix doesn't give us a right way to do it. | 2108 But Unix doesn't give us a right way to do it. |
2174 Opening with O_WRONLY could work for an ordinary file, | 2109 Opening with O_WRONLY could work for an ordinary file, |
2175 but would lose for directories. */ | 2110 but would lose for directories. */ |
2176 return (access (filename, 2) >= 0); | 2111 return (access (filename, 2) >= 0); |
2177 #endif | 2112 #endif |
2178 #endif /* not MSDOS */ | |
2179 } | 2113 } |
2180 | 2114 |
2181 DEFUN ("file-exists-p", Ffile_exists_p, 1, 1, 0, /* | 2115 DEFUN ("file-exists-p", Ffile_exists_p, 1, 1, 0, /* |
2182 Return t if file FILENAME exists. (This does not mean you can read it.) | 2116 Return t if file FILENAME exists. (This does not mean you can read it.) |
2183 See also `file-readable-p' and `file-attributes'. | 2117 See also `file-readable-p' and `file-attributes'. |
2241 (filename)) | 2175 (filename)) |
2242 { | 2176 { |
2243 /* This function can GC */ | 2177 /* This function can GC */ |
2244 Lisp_Object abspath = Qnil; | 2178 Lisp_Object abspath = Qnil; |
2245 Lisp_Object handler; | 2179 Lisp_Object handler; |
2246 int desc; | |
2247 struct gcpro gcpro1; | 2180 struct gcpro gcpro1; |
2248 GCPRO1 (abspath); | 2181 GCPRO1 (abspath); |
2249 | 2182 |
2250 CHECK_STRING (filename); | 2183 CHECK_STRING (filename); |
2251 abspath = Fexpand_file_name (filename, Qnil); | 2184 abspath = Fexpand_file_name (filename, Qnil); |
2254 call the corresponding file handler. */ | 2187 call the corresponding file handler. */ |
2255 handler = Ffind_file_name_handler (abspath, Qfile_readable_p); | 2188 handler = Ffind_file_name_handler (abspath, Qfile_readable_p); |
2256 if (!NILP (handler)) | 2189 if (!NILP (handler)) |
2257 RETURN_UNGCPRO (call2 (handler, Qfile_readable_p, abspath)); | 2190 RETURN_UNGCPRO (call2 (handler, Qfile_readable_p, abspath)); |
2258 | 2191 |
2259 #ifdef DOS_NT | 2192 #ifdef WINDOWSNT |
2260 /* Under MS-DOS and Windows, open does not work for directories. */ | 2193 /* Under MS-DOS and Windows, open does not work for directories. */ |
2261 if (access (XSTRING_DATA (abspath), 0) == 0) | 2194 if (access (XSTRING_DATA (abspath), 0) == 0) |
2262 return Qt; | 2195 return Qt; |
2263 return Qnil; | 2196 return Qnil; |
2264 #else /* not DOS_NT */ | 2197 #else /* not WINDOWSNT */ |
2265 desc = interruptible_open ((char *) XSTRING_DATA (abspath), O_RDONLY | OPEN_BINARY, 0); | 2198 { |
2266 UNGCPRO; | 2199 int desc = interruptible_open ((char *) XSTRING_DATA (abspath), O_RDONLY | OPEN_BINARY, 0); |
2267 if (desc < 0) | 2200 UNGCPRO; |
2268 return Qnil; | 2201 if (desc < 0) |
2269 close (desc); | 2202 return Qnil; |
2270 return Qt; | 2203 close (desc); |
2271 #endif /* not DOS_NT */ | 2204 return Qt; |
2205 } | |
2206 #endif /* not WINDOWSNT */ | |
2272 } | 2207 } |
2273 | 2208 |
2274 /* Having this before file-symlink-p mysteriously caused it to be forgotten | 2209 /* Having this before file-symlink-p mysteriously caused it to be forgotten |
2275 on the RT/PC. */ | 2210 on the RT/PC. */ |
2276 DEFUN ("file-writable-p", Ffile_writable_p, 1, 1, 0, /* | 2211 DEFUN ("file-writable-p", Ffile_writable_p, 1, 1, 0, /* |
2301 | 2236 |
2302 | 2237 |
2303 GCPRO1 (abspath); | 2238 GCPRO1 (abspath); |
2304 dir = Ffile_name_directory (abspath); | 2239 dir = Ffile_name_directory (abspath); |
2305 UNGCPRO; | 2240 UNGCPRO; |
2306 #ifdef MSDOS | |
2307 if (!NILP (dir)) | |
2308 { | |
2309 GCPRO1(dir); | |
2310 dir = Fdirectory_file_name (dir); | |
2311 UNGCPRO; | |
2312 } | |
2313 #endif /* MSDOS */ | |
2314 return (check_writable (!NILP (dir) ? (char *) XSTRING_DATA (dir) | 2241 return (check_writable (!NILP (dir) ? (char *) XSTRING_DATA (dir) |
2315 : "") | 2242 : "") |
2316 ? Qt : Qnil); | 2243 ? Qt : Qnil); |
2317 } | 2244 } |
2318 | 2245 |
2416 handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p); | 2343 handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p); |
2417 if (!NILP (handler)) | 2344 if (!NILP (handler)) |
2418 return call2 (handler, Qfile_accessible_directory_p, | 2345 return call2 (handler, Qfile_accessible_directory_p, |
2419 filename); | 2346 filename); |
2420 | 2347 |
2421 #if !defined(DOS_NT) | 2348 #if !defined(WINDOWSNT) |
2422 if (NILP (Ffile_directory_p (filename))) | 2349 if (NILP (Ffile_directory_p (filename))) |
2423 return (Qnil); | 2350 return (Qnil); |
2424 else | 2351 else |
2425 return Ffile_executable_p (filename); | 2352 return Ffile_executable_p (filename); |
2426 #else | 2353 #else |
2437 tem = (NILP (Ffile_directory_p (filename)) | 2364 tem = (NILP (Ffile_directory_p (filename)) |
2438 || NILP (Ffile_executable_p (filename))); | 2365 || NILP (Ffile_executable_p (filename))); |
2439 UNGCPRO; | 2366 UNGCPRO; |
2440 return tem ? Qnil : Qt; | 2367 return tem ? Qnil : Qt; |
2441 } | 2368 } |
2442 #endif /* !defined(DOS_NT) */ | 2369 #endif /* !defined(WINDOWSNT) */ |
2443 } | 2370 } |
2444 | 2371 |
2445 DEFUN ("file-regular-p", Ffile_regular_p, 1, 1, 0, /* | 2372 DEFUN ("file-regular-p", Ffile_regular_p, 1, 1, 0, /* |
2446 "Return t if file FILENAME is the name of a regular file. | 2373 "Return t if file FILENAME is the name of a regular file. |
2447 This is the sort of file that holds an ordinary stream of data bytes. | 2374 This is the sort of file that holds an ordinary stream of data bytes. |
2627 | 2554 |
2628 return (mtime1 > st.st_mtime) ? Qt : Qnil; | 2555 return (mtime1 > st.st_mtime) ? Qt : Qnil; |
2629 } | 2556 } |
2630 | 2557 |
2631 | 2558 |
2632 #ifdef DOS_NT | |
2633 Lisp_Object Qfind_buffer_file_type; | |
2634 | |
2635 /* Return 1 if buffer is text, 0 if binary. */ | |
2636 static int | |
2637 decide_buffer_type (unsigned char * buffer, int nbytes) | |
2638 { | |
2639 /* Buffer is binary if we find any LF chars not preceeded by CR or if | |
2640 the buffer doesn't contain at least 1 line. */ | |
2641 unsigned lines = 0; | |
2642 unsigned char *p, *q; | |
2643 | |
2644 for (p = buffer; nbytes > 0 && (q = memchr (p, '\n', nbytes)) != NULL; | |
2645 p = q + 1 ) | |
2646 { | |
2647 nbytes -= (q + 1 - p); | |
2648 lines++; | |
2649 if (q > buffer && q[-1] != '\r') | |
2650 return 0; | |
2651 } | |
2652 | |
2653 /* If we haven't seen any line endings yet, return -1 (meaning type is | |
2654 undecided) so we can examine the next bufferful as well. */ | |
2655 return (lines > 0) ? 1 : -1; | |
2656 } | |
2657 | |
2658 /* XEmacs addition: like decide_buffer_type(), but working on a XEmacs buffer: | |
2659 first arg is a byte index position instead of a char pointer; | |
2660 we check each char sequentially. --marcpa */ | |
2661 static int | |
2662 buf_decide_buffer_type (struct buffer *buf, Bytind start, int nbytes) | |
2663 { | |
2664 /* Buffer is binary if we find any LF chars not preceeded by CR or if | |
2665 the buffer doesn't contain at least 1 line. */ | |
2666 unsigned lines = 0; | |
2667 Bytind cur = start; | |
2668 | |
2669 while (nbytes) | |
2670 { | |
2671 if (BI_BUF_FETCH_CHAR(buf, cur) == '\n') | |
2672 { | |
2673 lines++; | |
2674 if (cur != start && BI_BUF_FETCH_CHAR(buf, cur - 1) != '\r') | |
2675 return 0; | |
2676 } | |
2677 nbytes--; | |
2678 } | |
2679 | |
2680 /* If we haven't seen any line endings yet, return -1 (meaning type is | |
2681 undecided) so we can examine the next bufferful as well. */ | |
2682 return (lines > 0) ? 1 : -1; | |
2683 } | |
2684 #endif /* DOS_NT */ | |
2685 | |
2686 /* Stack sizes > 2**16 is a good way to elicit compiler bugs */ | 2559 /* Stack sizes > 2**16 is a good way to elicit compiler bugs */ |
2687 /* #define READ_BUF_SIZE (2 << 16) */ | 2560 /* #define READ_BUF_SIZE (2 << 16) */ |
2688 #define READ_BUF_SIZE (1 << 15) | 2561 #define READ_BUF_SIZE (1 << 15) |
2689 | 2562 |
2690 DEFUN ("insert-file-contents-internal", | 2563 DEFUN ("insert-file-contents-internal", |
2719 Bufbyte read_buf[READ_BUF_SIZE]; | 2592 Bufbyte read_buf[READ_BUF_SIZE]; |
2720 int mc_count; | 2593 int mc_count; |
2721 struct buffer *buf = current_buffer; | 2594 struct buffer *buf = current_buffer; |
2722 Lisp_Object curbuf; | 2595 Lisp_Object curbuf; |
2723 int not_regular = 0; | 2596 int not_regular = 0; |
2724 #ifdef DOS_NT | |
2725 int crlf_conversion_required = 0; | |
2726 unsigned crlf_count = 0; | |
2727 unsigned lf_count = 0; | |
2728 #endif | |
2729 | 2597 |
2730 if (buf->base_buffer && ! NILP (visit)) | 2598 if (buf->base_buffer && ! NILP (visit)) |
2731 error ("Cannot do file visiting in an indirect buffer"); | 2599 error ("Cannot do file visiting in an indirect buffer"); |
2732 | 2600 |
2733 /* No need to call Fbarf_if_buffer_read_only() here. | 2601 /* No need to call Fbarf_if_buffer_read_only() here. |
2841 { | 2709 { |
2842 end = make_int (st.st_size); | 2710 end = make_int (st.st_size); |
2843 if (XINT (end) != st.st_size) | 2711 if (XINT (end) != st.st_size) |
2844 error ("Maximum buffer size exceeded"); | 2712 error ("Maximum buffer size exceeded"); |
2845 } | 2713 } |
2846 | |
2847 #ifdef DOS_NT | |
2848 /* Permit old behaviour if desired. */ | |
2849 if (NILP (Vinsert_file_contents_allow_replace) && !NILP (replace)) | |
2850 { | |
2851 replace = Qnil; | |
2852 /* Surely this was never right! */ | |
2853 /* XSETFASTINT (beg, 0); | |
2854 XSETFASTINT (end, st.st_size); */ | |
2855 buffer_delete_range (buf, BUF_BEGV(buf), BUF_ZV(buf), | |
2856 !NILP (visit) ? INSDEL_NO_LOCKING : 0); | |
2857 } | |
2858 #endif /* DOS_NT */ | |
2859 } | 2714 } |
2860 | 2715 |
2861 /* If requested, replace the accessible part of the buffer | 2716 /* If requested, replace the accessible part of the buffer |
2862 with the file contents. Avoid replacing text at the | 2717 with the file contents. Avoid replacing text at the |
2863 beginning or end of the buffer that matches the file contents; | 2718 beginning or end of the buffer that matches the file contents; |
2866 /* The replace-mode code currently only works when the assumption | 2721 /* The replace-mode code currently only works when the assumption |
2867 'one byte == one char' holds true. This fails Mule because | 2722 'one byte == one char' holds true. This fails Mule because |
2868 files may contain multibyte characters. It holds under Windows NT | 2723 files may contain multibyte characters. It holds under Windows NT |
2869 provided we convert CRLF into LF. */ | 2724 provided we convert CRLF into LF. */ |
2870 # define FSFMACS_SPEEDY_INSERT | 2725 # define FSFMACS_SPEEDY_INSERT |
2871 #endif | 2726 #endif /* !defined (FILE_CODING) */ |
2727 | |
2872 #ifndef FSFMACS_SPEEDY_INSERT | 2728 #ifndef FSFMACS_SPEEDY_INSERT |
2873 if (!NILP (replace)) | 2729 if (!NILP (replace)) |
2874 { | 2730 { |
2875 buffer_delete_range (buf, BUF_BEG (buf), BUF_Z (buf), | 2731 buffer_delete_range (buf, BUF_BEG (buf), BUF_Z (buf), |
2876 !NILP (visit) ? INSDEL_NO_LOCKING : 0); | 2732 !NILP (visit) ? INSDEL_NO_LOCKING : 0); |
2880 { | 2736 { |
2881 char buffer[1 << 14]; | 2737 char buffer[1 << 14]; |
2882 Bufpos same_at_start = BUF_BEGV (buf); | 2738 Bufpos same_at_start = BUF_BEGV (buf); |
2883 Bufpos same_at_end = BUF_ZV (buf); | 2739 Bufpos same_at_end = BUF_ZV (buf); |
2884 int overlap; | 2740 int overlap; |
2885 #ifdef DOS_NT | |
2886 /* Syncing with 19.34.6 note: same_at_start_in_file and | |
2887 same_at_end_in_file are not in XEmacs 20.4. | |
2888 First try to introduce them as-is and see what happens. | |
2889 Might be necessary to use constructs like | |
2890 st.st_size - (BUF_ZV (buf) - same_at_end) | |
2891 instead. | |
2892 --marcpa | |
2893 */ | |
2894 /* Offset into the file where discrepancy begins. */ | |
2895 int same_at_start_in_file = 0; | |
2896 /* Offset into the file where discrepancy ends. */ | |
2897 int same_at_end_in_file = st.st_size; | |
2898 /* DOS_NT only: is there a `\r' character left in the buffer? */ | |
2899 int cr_left_in_buffer = 0; | |
2900 /* DOS_NT only: was `\n' the first character in previous bufferful? */ | |
2901 int last_was_lf = 0; | |
2902 | |
2903 /* Demacs 1.1.1 91/10/16 HIRANO Satoshi, MW July 1993 */ | |
2904 /* Determine file type (text/binary) from its name. | |
2905 Note that the buffer_file_type changes here when the file | |
2906 being inserted is not of the same type as the original buffer. */ | |
2907 current_buffer->buffer_file_type = call1 (Qfind_buffer_file_type, filename); | |
2908 if (NILP (current_buffer->buffer_file_type)) | |
2909 crlf_conversion_required = 1; | |
2910 else if (current_buffer->buffer_file_type != Qt) | |
2911 /* Use heuristic to decide whether file is text or binary (based | |
2912 on the first bufferful) if buffer-file-type is not nil or t. | |
2913 If no decision is made (because no line endings were ever | |
2914 seen) then let buffer-file-type default to nil. */ | |
2915 crlf_conversion_required = -1; | |
2916 #endif /* DOS_NT */ | |
2917 | 2741 |
2918 /* Count how many chars at the start of the file | 2742 /* Count how many chars at the start of the file |
2919 match the text at the beginning of the buffer. */ | 2743 match the text at the beginning of the buffer. */ |
2920 while (1) | 2744 while (1) |
2921 { | 2745 { |
2922 int nread; | 2746 int nread; |
2923 Bufpos bufpos; | 2747 Bufpos bufpos; |
2924 #ifdef DOS_NT | |
2925 if (cr_left_in_buffer) | |
2926 { | |
2927 nread = read_allowing_quit (fd, buffer + 1, sizeof(buffer) - 1); | |
2928 cr_left_in_buffer = 0; | |
2929 if (nread >= 0) | |
2930 nread++; | |
2931 } | |
2932 else | |
2933 #endif /* DOS_NT */ | |
2934 nread = read_allowing_quit (fd, buffer, sizeof buffer); | 2748 nread = read_allowing_quit (fd, buffer, sizeof buffer); |
2935 if (nread < 0) | 2749 if (nread < 0) |
2936 error ("IO error reading %s: %s", | 2750 error ("IO error reading %s: %s", |
2937 XSTRING_DATA (filename), strerror (errno)); | 2751 XSTRING_DATA (filename), strerror (errno)); |
2938 else if (nread == 0) | 2752 else if (nread == 0) |
2939 break; | 2753 break; |
2940 bufpos = 0; | 2754 bufpos = 0; |
2941 #ifdef DOS_NT | |
2942 /* If requested, we do a simple check on the first bufferful | |
2943 to decide whether the file is binary or text. (If text, we | |
2944 count LF and CRLF occurences to determine whether the file | |
2945 was in Unix or DOS format.) */ | |
2946 if (crlf_conversion_required < 0) | |
2947 { | |
2948 crlf_conversion_required = decide_buffer_type (buffer, nread); | |
2949 current_buffer->buffer_file_type = | |
2950 crlf_conversion_required ? Qnil : Qt; | |
2951 } | |
2952 | |
2953 /* DOS_NT text files require that we ignore a `\r' before a `\n'. */ | |
2954 if (crlf_conversion_required > 0) | |
2955 while (bufpos < nread && same_at_start < BUF_ZV (buf)) | |
2956 { | |
2957 int filec = buffer[bufpos]; | |
2958 int bufc = BUF_FETCH_CHAR (buf, same_at_start); | |
2959 | |
2960 if (filec == '\n') | |
2961 lf_count++; | |
2962 | |
2963 if (filec == bufc) | |
2964 same_at_start++, bufpos++, same_at_start_in_file++; | |
2965 else if (filec == '\r' && bufc == '\n') | |
2966 { | |
2967 /* If the `\r' is the last character in this buffer, | |
2968 it will be examined with the next bufferful. */ | |
2969 if (bufpos == nread) | |
2970 { | |
2971 buffer[0] = filec; | |
2972 cr_left_in_buffer = 1; | |
2973 } | |
2974 else if (buffer[bufpos + 1] == bufc) | |
2975 { | |
2976 bufpos += 2; | |
2977 same_at_start_in_file += 2; | |
2978 same_at_start++; | |
2979 crlf_count++; | |
2980 lf_count++; | |
2981 } | |
2982 else | |
2983 break; | |
2984 } | |
2985 else | |
2986 break; | |
2987 } | |
2988 else | |
2989 #endif /* DOS_NT */ | |
2990 while (bufpos < nread && same_at_start < BUF_ZV (buf) | 2755 while (bufpos < nread && same_at_start < BUF_ZV (buf) |
2991 && BUF_FETCH_CHAR (buf, same_at_start) == buffer[bufpos]) | 2756 && BUF_FETCH_CHAR (buf, same_at_start) == buffer[bufpos]) |
2992 #ifdef DOS_NT | |
2993 same_at_start_in_file++, | |
2994 #endif | |
2995 same_at_start++, bufpos++; | 2757 same_at_start++, bufpos++; |
2996 /* If we found a discrepancy, stop the scan. | 2758 /* If we found a discrepancy, stop the scan. |
2997 Otherwise loop around and scan the next bufferful. */ | 2759 Otherwise loop around and scan the next bufferful. */ |
2998 if (bufpos != nread) | 2760 if (bufpos != nread) |
2999 break; | 2761 break; |
3000 } | 2762 } |
3001 /* If the file matches the buffer completely, | 2763 /* If the file matches the buffer completely, |
3002 there's no need to replace anything. */ | 2764 there's no need to replace anything. */ |
3003 #ifdef DOS_NT | |
3004 if (same_at_start_in_file == st.st_size) | |
3005 #else | |
3006 if (same_at_start - BUF_BEGV (buf) == st.st_size) | 2765 if (same_at_start - BUF_BEGV (buf) == st.st_size) |
3007 #endif /* DOS_NT */ | |
3008 { | 2766 { |
3009 close (fd); | 2767 close (fd); |
3010 unbind_to (speccount, Qnil); | 2768 unbind_to (speccount, Qnil); |
3011 /* Truncate the buffer to the size of the file. */ | 2769 /* Truncate the buffer to the size of the file. */ |
3012 buffer_delete_range (buf, same_at_start, same_at_end, | 2770 buffer_delete_range (buf, same_at_start, same_at_end, |
3019 { | 2777 { |
3020 int total_read, nread; | 2778 int total_read, nread; |
3021 Bufpos bufpos, curpos, trial; | 2779 Bufpos bufpos, curpos, trial; |
3022 | 2780 |
3023 /* At what file position are we now scanning? */ | 2781 /* At what file position are we now scanning? */ |
3024 #ifdef DOS_NT | |
3025 curpos = same_at_end_in_file; | |
3026 #else | |
3027 curpos = st.st_size - (BUF_ZV (buf) - same_at_end); | 2782 curpos = st.st_size - (BUF_ZV (buf) - same_at_end); |
3028 #endif /* DOS_NT */ | |
3029 /* If the entire file matches the buffer tail, stop the scan. */ | 2783 /* If the entire file matches the buffer tail, stop the scan. */ |
3030 if (curpos == 0) | 2784 if (curpos == 0) |
3031 break; | 2785 break; |
3032 /* How much can we scan in the next step? */ | 2786 /* How much can we scan in the next step? */ |
3033 trial = min (curpos, sizeof buffer); | 2787 trial = min (curpos, sizeof buffer); |
3044 total_read += nread; | 2798 total_read += nread; |
3045 } | 2799 } |
3046 /* Scan this bufferful from the end, comparing with | 2800 /* Scan this bufferful from the end, comparing with |
3047 the Emacs buffer. */ | 2801 the Emacs buffer. */ |
3048 bufpos = total_read; | 2802 bufpos = total_read; |
3049 #ifdef DOS_NT | |
3050 /* DOS_NT text files require that we ignore a `\r' before a `\n'. */ | |
3051 if (crlf_conversion_required) | |
3052 #endif /* DOS_NT */ | |
3053 /* Compare with same_at_start to avoid counting some buffer text | 2803 /* Compare with same_at_start to avoid counting some buffer text |
3054 as matching both at the file's beginning and at the end. */ | 2804 as matching both at the file's beginning and at the end. */ |
3055 #if !defined(DOS_NT) | |
3056 while (bufpos > 0 && same_at_end > same_at_start | 2805 while (bufpos > 0 && same_at_end > same_at_start |
3057 && BUF_FETCH_CHAR (buf, same_at_end - 1) == | 2806 && BUF_FETCH_CHAR (buf, same_at_end - 1) == |
3058 buffer[bufpos - 1]) | 2807 buffer[bufpos - 1]) |
3059 same_at_end--, bufpos--; | 2808 same_at_end--, bufpos--; |
3060 #else /* DOS_NT */ | |
3061 while (bufpos > 0 && same_at_end > same_at_start | |
3062 && same_at_end_in_file > same_at_start_in_file) | |
3063 { | |
3064 int filec = buffer[bufpos - 1]; | |
3065 int bufc = BUF_FETCH_CHAR (buf, same_at_end - 1); | |
3066 | |
3067 /* Account for `\n' in previous bufferful. */ | |
3068 if (last_was_lf && filec == '\r') | |
3069 { | |
3070 same_at_end_in_file--, bufpos--; | |
3071 last_was_lf = 0; | |
3072 crlf_count++; | |
3073 } | |
3074 else if (filec == bufc) | |
3075 { | |
3076 last_was_lf = 0; | |
3077 same_at_end--, same_at_end_in_file--, bufpos--; | |
3078 if (bufc == '\n') | |
3079 { | |
3080 lf_count++; | |
3081 if (bufpos <= 0) | |
3082 last_was_lf = 1; | |
3083 else if (same_at_end_in_file <= same_at_start_in_file) | |
3084 break; | |
3085 else if (buffer[bufpos - 1] == '\r') | |
3086 same_at_end_in_file--, bufpos--, crlf_count++; | |
3087 } | |
3088 } | |
3089 else | |
3090 { | |
3091 last_was_lf = 0; | |
3092 break; | |
3093 } | |
3094 } | |
3095 else | |
3096 while (bufpos > 0 && same_at_end > same_at_start | |
3097 && same_at_end_in_file > same_at_start_in_file | |
3098 && BUF_FETCH_CHAR (buf, same_at_end - 1) == | |
3099 buffer[bufpos - 1]) | |
3100 same_at_end--, same_at_end_in_file--, bufpos--; | |
3101 #endif /* !defined(DOS_NT) */ | |
3102 /* If we found a discrepancy, stop the scan. | 2809 /* If we found a discrepancy, stop the scan. |
3103 Otherwise loop around and scan the preceding bufferful. */ | 2810 Otherwise loop around and scan the preceding bufferful. */ |
3104 if (bufpos != 0) | 2811 if (bufpos != 0) |
3105 break; | 2812 break; |
3106 /* If display current starts at beginning of line, | 2813 /* If display current starts at beginning of line, |
3115 (same_at_end + st.st_size - BUF_ZV (buf)); | 2822 (same_at_end + st.st_size - BUF_ZV (buf)); |
3116 if (overlap > 0) | 2823 if (overlap > 0) |
3117 same_at_end += overlap; | 2824 same_at_end += overlap; |
3118 | 2825 |
3119 /* Arrange to read only the nonmatching middle part of the file. */ | 2826 /* Arrange to read only the nonmatching middle part of the file. */ |
3120 #ifdef DOS_NT | |
3121 beg = make_int (same_at_start_in_file); | |
3122 end = make_int (same_at_end_in_file); | |
3123 #else | |
3124 beg = make_int (same_at_start - BUF_BEGV (buf)); | 2827 beg = make_int (same_at_start - BUF_BEGV (buf)); |
3125 end = make_int (st.st_size - (BUF_ZV (buf) - same_at_end)); | 2828 end = make_int (st.st_size - (BUF_ZV (buf) - same_at_end)); |
3126 #endif /* DOS_NT */ | |
3127 | 2829 |
3128 buffer_delete_range (buf, same_at_start, same_at_end, | 2830 buffer_delete_range (buf, same_at_start, same_at_end, |
3129 !NILP (visit) ? INSDEL_NO_LOCKING : 0); | 2831 !NILP (visit) ? INSDEL_NO_LOCKING : 0); |
3130 /* Insert from the file at the proper position. */ | 2832 /* Insert from the file at the proper position. */ |
3131 BUF_SET_PT (buf, same_at_start); | 2833 BUF_SET_PT (buf, same_at_start); |
3190 { | 2892 { |
3191 if (this_len < 0) | 2893 if (this_len < 0) |
3192 saverrno = errno; | 2894 saverrno = errno; |
3193 break; | 2895 break; |
3194 } | 2896 } |
3195 #ifdef DOS_NT | |
3196 /* XEmacs (--marcpa) change: FSF does buffer_insert_raw_string_1() first | |
3197 then checks if conversion is needed, calling lisp | |
3198 (find-buffer-file-type) which can call a user-function that | |
3199 might look at the unconverted buffer to decide if | |
3200 conversion is needed. | |
3201 I removed the possibility for lisp functions called from | |
3202 find-buffer-file-type to look at the buffer's content, for | |
3203 simplicity reasons: it is easier to do the CRLF -> LF | |
3204 conversion on read_buf than on buffer contents because | |
3205 BUF_FETCH_CHAR does not return a pointer to an unsigned | |
3206 char memory location, and because we must cope with bytind | |
3207 VS bufpos in XEmacs, thus complicating crlf_to_lf(). | |
3208 This decision (of doing Lstream_read(), crlf_to_lf() then | |
3209 buffer_insert_raw_string_1()) is debatable. | |
3210 --marcpa | |
3211 */ | |
3212 /* Following FSF note no longer apply now. See comment above. | |
3213 --marcpa*/ | |
3214 /* For compatability with earlier versions that did not support the | |
3215 REPLACE funtionality, we call find-buffer-file-type after inserting | |
3216 the contents to allow it to inspect the inserted data. (This was | |
3217 not intentional usage, but proved to be quite useful.) */ | |
3218 if (NILP (replace)) | |
3219 { | |
3220 /* Demacs 1.1.1 91/10/16 HIRANO Satoshi, MW July 1993 */ | |
3221 /* Determine file type (text/binary) from its name. | |
3222 Note that the buffer_file_type changes here when the file | |
3223 being inserted is not of the same type as the original buffer. */ | |
3224 current_buffer->buffer_file_type = call1 (Qfind_buffer_file_type, filename); | |
3225 if (NILP (current_buffer->buffer_file_type)) | |
3226 crlf_conversion_required = 1; | |
3227 else if (current_buffer->buffer_file_type != Qt) | |
3228 /* Use heuristic to decide whether file is text or binary (based | |
3229 on the first bufferful) if buffer-file-type is not nil or t. | |
3230 If no decision is made (because no line endings were ever | |
3231 seen) then let buffer-file-type default to nil. */ | |
3232 crlf_conversion_required = -1; | |
3233 } | |
3234 | |
3235 /* If requested, we check the inserted data to decide whether the file | |
3236 is binary or text. (If text, we count LF and CRLF occurences to | |
3237 determine whether the file was in Unix or DOS format.) */ | |
3238 if (crlf_conversion_required < 0) | |
3239 { | |
3240 crlf_conversion_required = | |
3241 decide_buffer_type (read_buf, this_len); | |
3242 current_buffer->buffer_file_type = | |
3243 crlf_conversion_required ? Qnil : Qt; | |
3244 } | |
3245 | |
3246 /* Demacs 1.1.1 91/10/16 HIRANO Satoshi, MW July 1993 */ | |
3247 /* Remove CRs from CR-LFs if the file is deemed to be a text file. */ | |
3248 if (crlf_conversion_required) | |
3249 { | |
3250 int reduced_size | |
3251 = this_len - crlf_to_lf (this_len, read_buf, | |
3252 &lf_count); | |
3253 crlf_count += reduced_size; | |
3254 /* XEmacs (--marcpa) change: No need for this since we havent | |
3255 inserted in buffer yet. */ | |
3256 #if 0 | |
3257 ZV -= reduced_size; | |
3258 Z -= reduced_size; | |
3259 GPT -= reduced_size; | |
3260 GAP_SIZE += reduced_size; | |
3261 inserted -= reduced_size; | |
3262 #endif | |
3263 this_len -= reduced_size; | |
3264 | |
3265 /* Change buffer_file_type back to binary if Unix eol format. */ | |
3266 if (crlf_count == 0 && lf_count > 0) | |
3267 current_buffer->buffer_file_type = Qt; | |
3268 } | |
3269 | |
3270 /* Make crlf_count and lf_count available for inspection. */ | |
3271 Fset (intern ("buffer-file-lines"), make_int (lf_count)); | |
3272 Fset (intern ("buffer-file-dos-lines"), make_int (crlf_count)); | |
3273 #endif /* DOS_NT */ | |
3274 | 2897 |
3275 cc_inserted = buffer_insert_raw_string_1 (buf, cur_point, read_buf, | 2898 cc_inserted = buffer_insert_raw_string_1 (buf, cur_point, read_buf, |
3276 this_len, | 2899 this_len, |
3277 !NILP (visit) | 2900 !NILP (visit) |
3278 ? INSDEL_NO_LOCKING : 0); | 2901 ? INSDEL_NO_LOCKING : 0); |
3432 we should signal an error rather than blissfully continuing | 3055 we should signal an error rather than blissfully continuing |
3433 along. ARGH, this function is going to lose lose lose. We need | 3056 along. ARGH, this function is going to lose lose lose. We need |
3434 to protect the current_buffer from being destroyed, but the | 3057 to protect the current_buffer from being destroyed, but the |
3435 multiple return points make this a pain in the butt. */ | 3058 multiple return points make this a pain in the butt. */ |
3436 | 3059 |
3437 #ifdef DOS_NT | |
3438 int buffer_file_type | |
3439 = NILP (current_buffer->buffer_file_type) ? O_TEXT : O_BINARY; | |
3440 #endif /* DOS_NT */ | |
3441 | |
3442 #ifdef FILE_CODING | 3060 #ifdef FILE_CODING |
3443 codesys = Fget_coding_system (codesys); | 3061 codesys = Fget_coding_system (codesys); |
3444 #endif /* MULE */ | 3062 #endif /* MULE */ |
3445 | 3063 |
3446 if (current_buffer->base_buffer && ! NILP (visit)) | 3064 if (current_buffer->base_buffer && ! NILP (visit)) |
3520 } | 3138 } |
3521 | 3139 |
3522 fn = filename; | 3140 fn = filename; |
3523 desc = -1; | 3141 desc = -1; |
3524 if (!NILP (append)) | 3142 if (!NILP (append)) |
3525 #ifdef DOS_NT | 3143 { |
3526 desc = open ((char *) XSTRING_DATA (fn), | 3144 desc = open ((char *) XSTRING_DATA (fn), O_WRONLY | OPEN_BINARY, 0); |
3527 (O_WRONLY | buffer_file_type), 0); | 3145 } |
3528 #else /* not DOS_NT */ | |
3529 desc = open ((char *) XSTRING_DATA (fn), O_WRONLY | OPEN_BINARY, 0); | |
3530 #endif /* not DOS_NT */ | |
3531 | |
3532 if (desc < 0) | 3146 if (desc < 0) |
3533 { | 3147 { |
3534 #ifdef DOS_NT | |
3535 desc = open ((char *) XSTRING_DATA (fn), | |
3536 (O_WRONLY | O_TRUNC | O_CREAT | buffer_file_type), | |
3537 (S_IREAD | S_IWRITE)); | |
3538 #else /* not DOS_NT */ | |
3539 desc = open ((char *) XSTRING_DATA (fn), | 3148 desc = open ((char *) XSTRING_DATA (fn), |
3540 (O_WRONLY | O_TRUNC | O_CREAT | OPEN_BINARY), | 3149 (O_WRONLY | O_TRUNC | O_CREAT | OPEN_BINARY), |
3541 ((auto_saving) ? auto_save_mode_bits : CREAT_MODE)); | 3150 ((auto_saving) ? auto_save_mode_bits : CREAT_MODE)); |
3542 #endif /* DOS_NT */ | |
3543 } | 3151 } |
3544 | 3152 |
3545 if (desc < 0) | 3153 if (desc < 0) |
3546 { | 3154 { |
3547 #ifdef CLASH_DETECTION | 3155 #ifdef CLASH_DETECTION |
4284 /* Open the auto-save list file, if necessary. | 3892 /* Open the auto-save list file, if necessary. |
4285 We only do this now so that the file only exists | 3893 We only do this now so that the file only exists |
4286 if we actually auto-saved any files. */ | 3894 if we actually auto-saved any files. */ |
4287 if (!auto_saved && GC_STRINGP (listfile) && listdesc < 0) | 3895 if (!auto_saved && GC_STRINGP (listfile) && listdesc < 0) |
4288 { | 3896 { |
4289 #ifdef DOS_NT | |
4290 listdesc = open ((char *) XSTRING_DATA (listfile), | |
4291 O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, | |
4292 S_IREAD | S_IWRITE); | |
4293 #else /* not DOS_NT */ | |
4294 listdesc = open ((char *) XSTRING_DATA (listfile), | 3897 listdesc = open ((char *) XSTRING_DATA (listfile), |
4295 O_WRONLY | O_TRUNC | O_CREAT | OPEN_BINARY, | 3898 O_WRONLY | O_TRUNC | O_CREAT | OPEN_BINARY, |
4296 CREAT_MODE); | 3899 CREAT_MODE); |
4297 #endif /* not DOS_NT */ | |
4298 | 3900 |
4299 /* Arrange to close that file whether or not we get | 3901 /* Arrange to close that file whether or not we get |
4300 an error. */ | 3902 an error. */ |
4301 if (listdesc >= 0) | 3903 if (listdesc >= 0) |
4302 record_unwind_protect (do_auto_save_unwind, | 3904 record_unwind_protect (do_auto_save_unwind, |
4463 defsymbol (&Qfile_newer_than_file_p, "file-newer-than-file-p"); | 4065 defsymbol (&Qfile_newer_than_file_p, "file-newer-than-file-p"); |
4464 defsymbol (&Qinsert_file_contents, "insert-file-contents"); | 4066 defsymbol (&Qinsert_file_contents, "insert-file-contents"); |
4465 defsymbol (&Qwrite_region, "write-region"); | 4067 defsymbol (&Qwrite_region, "write-region"); |
4466 defsymbol (&Qverify_visited_file_modtime, "verify-visited-file-modtime"); | 4068 defsymbol (&Qverify_visited_file_modtime, "verify-visited-file-modtime"); |
4467 defsymbol (&Qset_visited_file_modtime, "set-visited-file-modtime"); | 4069 defsymbol (&Qset_visited_file_modtime, "set-visited-file-modtime"); |
4468 #ifdef DOS_NT | |
4469 defsymbol (&Qfind_buffer_file_type, "find-buffer-file-type"); | |
4470 #endif /* DOS_NT */ | |
4471 defsymbol (&Qcar_less_than_car, "car-less-than-car"); /* Vomitous! */ | 4070 defsymbol (&Qcar_less_than_car, "car-less-than-car"); /* Vomitous! */ |
4472 | 4071 |
4473 defsymbol (&Qfile_name_handler_alist, "file-name-handler-alist"); | 4072 defsymbol (&Qfile_name_handler_alist, "file-name-handler-alist"); |
4474 defsymbol (&Qauto_save_hook, "auto-save-hook"); | 4073 defsymbol (&Qauto_save_hook, "auto-save-hook"); |
4475 defsymbol (&Qauto_save_error, "auto-save-error"); | 4074 defsymbol (&Qauto_save_error, "auto-save-error"); |
4627 This variable affects the built-in functions only on Windows, | 4226 This variable affects the built-in functions only on Windows, |
4628 on other platforms, it is initialized so that Lisp code can find out | 4227 on other platforms, it is initialized so that Lisp code can find out |
4629 what the normal separator is. | 4228 what the normal separator is. |
4630 */ ); | 4229 */ ); |
4631 Vdirectory_sep_char = make_char('/'); | 4230 Vdirectory_sep_char = make_char('/'); |
4632 | 4231 } |
4633 #ifdef DOS_NT | |
4634 DEFVAR_LISP ("insert-file-contents-allow-replace", &Vinsert_file_contents_allow_replace /* | |
4635 *Allow REPLACE option of insert-file-contents to preserve markers. | |
4636 If non-nil, the REPLACE option works as described, preserving markers. | |
4637 If nil, the REPLACE option is implemented by deleting the visible region | |
4638 then inserting the file contents as if REPLACE was nil. | |
4639 | |
4640 This option is only meaningful on Windows. | |
4641 */ ); | |
4642 Vinsert_file_contents_allow_replace = Qt; | |
4643 #endif | |
4644 } |