Mercurial > hg > xemacs-beta
comparison src/fileio.c @ 243:f220cc83d72e r20-5b20
Import from CVS: tag r20-5b20
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:17:07 +0200 |
parents | 85a06df23a9a |
children | 677f6a0ee643 |
comparison
equal
deleted
inserted
replaced
242:fc816b73a05f | 243:f220cc83d72e |
---|---|
684 #endif /* DOS_NT */ | 684 #endif /* DOS_NT */ |
685 return val; | 685 return val; |
686 } | 686 } |
687 | 687 |
688 DEFUN ("expand-file-name", Fexpand_file_name, 1, 2, 0, /* | 688 DEFUN ("expand-file-name", Fexpand_file_name, 1, 2, 0, /* |
689 Convert FILENAME to absolute, and canonicalize it. | 689 Convert filename NAME to absolute, and canonicalize it. |
690 Second arg DEFAULT is directory to start with if FILENAME is relative | 690 Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative |
691 (does not start with slash); if DEFAULT is nil or missing, | 691 (does not start with slash); if DEFAULT-DIRECTORY is nil or missing, |
692 the current buffer's value of default-directory is used. | 692 the current buffer's value of default-directory is used. |
693 Path components that are `.' are removed, and | 693 File name components that are `.' are removed, and |
694 path components followed by `..' are removed, along with the `..' itself; | 694 so are file name components followed by `..', along with the `..' itself; |
695 note that these simplifications are done without checking the resulting | 695 note that these simplifications are done without checking the resulting |
696 paths in the file system. | 696 file names in the file system. |
697 An initial `~/' expands to your home directory. | 697 An initial `~/' expands to your home directory. |
698 An initial `~USER/' expands to USER's home directory. | 698 An initial `~USER/' expands to USER's home directory. |
699 See also the function `substitute-in-file-name'. | 699 See also the function `substitute-in-file-name'. |
700 */ | 700 */ |
701 (name, default_)) | 701 (name, default_directory)) |
702 { | 702 { |
703 /* This function can GC. GC checked 1997.04.06. */ | 703 /* This function can GC */ |
704 Bufbyte *nm; | 704 Bufbyte *nm; |
705 | 705 |
706 Bufbyte *newdir, *p, *o; | 706 Bufbyte *newdir, *p, *o; |
707 int tlen; | 707 int tlen; |
708 Bufbyte *target; | 708 Bufbyte *target; |
709 struct passwd *pw; | 709 struct passwd *pw; |
710 #ifdef DOS_NT | 710 #ifdef DOS_NT |
711 int drive = 0; | 711 int drive = 0; |
712 int collapse_newdir = 1; | 712 int collapse_newdir = 1; |
713 #endif /* DOS_NT */ | |
713 int length; | 714 int length; |
714 #endif /* DOS_NT */ | |
715 Lisp_Object handler; | 715 Lisp_Object handler; |
716 | 716 |
717 CHECK_STRING (name); | 717 CHECK_STRING (name); |
718 | 718 |
719 /* If the file name has special constructs in it, | 719 /* If the file name has special constructs in it, |
720 call the corresponding file handler. */ | 720 call the corresponding file handler. */ |
721 handler = Ffind_file_name_handler (name, Qexpand_file_name); | 721 handler = Ffind_file_name_handler (name, Qexpand_file_name); |
722 if (!NILP (handler)) | 722 if (!NILP (handler)) |
723 return call3_check_string (handler, Qexpand_file_name, name, default_); | 723 return call3_check_string (handler, Qexpand_file_name, name, |
724 | 724 default_directory); |
725 /* Use the buffer's default-directory if DEFAULT_ is omitted. */ | 725 |
726 if (NILP (default_)) | 726 /* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */ |
727 default_ = current_buffer->directory; | 727 if (NILP (default_directory)) |
728 if (NILP (default_)) /* this should be a meaningful error */ | 728 default_directory = current_buffer->directory; |
729 { | 729 if (! STRINGP (default_directory)) |
730 /* #### If we had a minibuffer-only frame up then current_buffer | 730 default_directory = build_string ("/"); |
731 is likely to not have a directory setting. We should | 731 |
732 probably redo things to make sure that current_buffer stays | 732 if (!NILP (default_directory)) |
733 set to something sensible. */ | 733 { |
734 if (!preparing_for_armageddon) | 734 handler = Ffind_file_name_handler (default_directory, Qexpand_file_name); |
735 signal_simple_error ("default-directory is not set", | |
736 make_buffer (current_buffer)); | |
737 } | |
738 else | |
739 CHECK_STRING (default_); | |
740 | |
741 if (!NILP (default_)) | |
742 { | |
743 struct gcpro gcpro1; | |
744 | |
745 GCPRO1 (default_); /* might be current_buffer->directory */ | |
746 handler = Ffind_file_name_handler (default_, Qexpand_file_name); | |
747 UNGCPRO; | |
748 if (!NILP (handler)) | 735 if (!NILP (handler)) |
749 return call3 (handler, Qexpand_file_name, name, default_); | 736 return call3 (handler, Qexpand_file_name, name, default_directory); |
750 } | 737 } |
751 | 738 |
752 /* Make sure DEFAULT_ is properly expanded. | 739 o = XSTRING_DATA (default_directory); |
740 | |
741 /* Make sure DEFAULT_DIRECTORY is properly expanded. | |
753 It would be better to do this down below where we actually use | 742 It would be better to do this down below where we actually use |
754 default_. Unfortunately, calling Fexpand_file_name recursively | 743 default_directory. Unfortunately, calling Fexpand_file_name recursively |
755 could invoke GC, and the strings might be relocated. This would | 744 could invoke GC, and the strings might be relocated. This would |
756 be annoying because we have pointers into strings lying around | 745 be annoying because we have pointers into strings lying around |
757 that would need adjusting, and people would add new pointers to | 746 that would need adjusting, and people would add new pointers to |
758 the code and forget to adjust them, resulting in intermittent bugs. | 747 the code and forget to adjust them, resulting in intermittent bugs. |
759 Putting this call here avoids all that crud. | 748 Putting this call here avoids all that crud. |
760 | 749 |
761 The EQ test avoids infinite recursion. */ | 750 The EQ test avoids infinite recursion. */ |
762 if (! NILP(default_) && !EQ (default_, name) | 751 if (! NILP (default_directory) && !EQ (default_directory, name) |
763 /* Save time in some common cases - as long as default_directory | 752 /* Save time in some common cases - as long as default_directory |
764 is not relative, it can be canonicalized with name below (if it | 753 is not relative, it can be canonicalized with name below (if it |
765 is needed at all) without requiring it to be expanded now. */ | 754 is needed at all) without requiring it to be expanded now. */ |
766 && ! (XSTRING_LENGTH (default_) >= 3 | |
767 #ifdef DOS_NT | 755 #ifdef DOS_NT |
768 /* Detect MSDOS file names with drive specifiers. */ | 756 /* Detect MSDOS file names with drive specifiers. */ |
769 && (IS_DRIVE (XSTRING_BYTE (default_, 0)) | 757 && ! (IS_DRIVE (o[0]) && (IS_DEVICE_SEP (o[1]) && IS_DIRECTORY_SEP (o[2]))) |
770 && (IS_DEVICE_SEP (XSTRING_BYTE (default_, 1)) | |
771 && IS_DIRECTORY_SEP (XSTRING_BYTE (default_, 2)))) | |
772 #ifdef WINDOWSNT | 758 #ifdef WINDOWSNT |
773 /* Detect Windows file names in UNC format. */ | 759 /* Detect Windows file names in UNC format. */ |
774 && ! (XSTRING_LENGTH (default_) >= 2 | 760 && ! (IS_DIRECTORY_SEP (o[0]) && IS_DIRECTORY_SEP (o[1])) |
775 && IS_DIRECTORY_SEP (XSTRING_BYTE (default_, 0)) | |
776 && IS_DIRECTORY_SEP (XSTRING_BYTE (default_, 1))) | |
777 #endif | 761 #endif |
778 #else /* not DOS_NT */ | 762 #else /* not DOS_NT */ |
779 /* Detect Unix absolute file names (/... alone is not absolute on | 763 /* Detect Unix absolute file names (/... alone is not absolute on |
780 DOS or Windows). */ | 764 DOS or Windows). */ |
781 && (IS_DIRECTORY_SEP (XSTRING_BYTE (default_, 0)) | 765 && ! (IS_DIRECTORY_SEP (o[0])) |
782 || IS_DEVICE_SEP (XSTRING_BYTE (default_, 1))) | |
783 #endif /* not DOS_NT */ | 766 #endif /* not DOS_NT */ |
784 )) | 767 ) |
785 { | 768 { |
786 struct gcpro gcpro1; | 769 struct gcpro gcpro1; |
787 | 770 |
788 GCPRO1 (default_); /* may be current_buffer->directory */ | 771 GCPRO1 (name); |
789 default_ = Fexpand_file_name (default_, Qnil); | 772 default_directory = Fexpand_file_name (default_directory, Qnil); |
790 UNGCPRO; | 773 UNGCPRO; |
791 } | 774 } |
792 | 775 |
793 #ifdef FILE_SYSTEM_CASE | 776 #ifdef FILE_SYSTEM_CASE |
794 name = FILE_SYSTEM_CASE (name); | 777 name = FILE_SYSTEM_CASE (name); |
795 #endif | 778 #endif |
796 | 779 |
797 /* #### dmoore - this is ugly, clean this up. Looks like nm | 780 /* #### dmoore - this is ugly, clean this up. Looks like nm pointing |
798 pointing into name should be safe during all of this, though. */ | 781 into name should be safe during all of this, though. */ |
799 nm = XSTRING_DATA (name); | 782 nm = XSTRING_DATA (name); |
800 | 783 |
801 #ifdef DOS_NT | 784 #ifdef DOS_NT |
802 /* We will force directory separators to be either all \ or /, so make | 785 /* 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. */ | 786 a local copy to modify, even if there ends up being no change. */ |
805 | 788 |
806 /* Find and remove drive specifier if present; this makes nm absolute | 789 /* Find and remove drive specifier if present; this makes nm absolute |
807 even if the rest of the name appears to be relative. */ | 790 even if the rest of the name appears to be relative. */ |
808 { | 791 { |
809 Bufbyte *colon = strrchr (nm, ':'); | 792 Bufbyte *colon = strrchr (nm, ':'); |
793 | |
810 if (colon) | 794 if (colon) |
811 /* Only recognize colon as part of drive specifier if there is a | 795 /* Only recognize colon as part of drive specifier if there is a |
812 single alphabetic character preceeding the colon (and if the | 796 single alphabetic character preceeding the colon (and if the |
813 character before the drive letter, if present, is a directory | 797 character before the drive letter, if present, is a directory |
814 separator); this is to support the remote system syntax used by | 798 separator); this is to support the remote system syntax used by |
815 ange-ftp, and the "po:username" syntax for POP mailboxes. */ | 799 ange-ftp, and the "po:username" syntax for POP mailboxes. */ |
816 look_again: | 800 look_again: |
817 if (nm == colon) | 801 if (nm == colon) |
818 nm++; | 802 nm++; |
819 else if (IS_DRIVE (colon[-1]) | 803 else if (IS_DRIVE (colon[-1]) |
820 && (colon == nm + 1 || IS_DIRECTORY_SEP (colon[-2]))) | 804 && (colon == nm + 1 || IS_DIRECTORY_SEP (colon[-2]))) |
821 { | 805 { |
837 if (drive && IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])) | 821 if (drive && IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])) |
838 nm++; | 822 nm++; |
839 #endif /* WINDOWSNT */ | 823 #endif /* WINDOWSNT */ |
840 #endif /* DOS_NT */ | 824 #endif /* DOS_NT */ |
841 | 825 |
842 /* We *don't* want to handle // and /~ that way. */ | |
843 #if 0 | |
844 /* Handle // and /~ in middle of file name | |
845 by discarding everything through the first / of that sequence. */ | |
846 p = nm; | |
847 while (*p) | |
848 { | |
849 /* Since we know the path is absolute, we can assume that each | |
850 element starts with a "/". */ | |
851 | |
852 /* "//" anywhere isn't necessarily hairy; we just start afresh | |
853 with the second slash. */ | |
854 if (IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1]) | |
855 #if defined (APOLLO) || defined (WINDOWSNT) | |
856 /* // at start of filename is meaningful on Apollo | |
857 and WindowsNT systems */ | |
858 && nm != p | |
859 #endif /* APOLLO || WINDOWSNT */ | |
860 ) | |
861 nm = p + 1; | |
862 | |
863 /* "~" is hairy as the start of any path element. */ | |
864 if (IS_DIRECTORY_SEP (p[0]) && p[1] == '~') | |
865 nm = p + 1; | |
866 | |
867 p++; | |
868 } | |
869 | |
870 #endif /* 0 */ | |
871 | |
872 #ifdef WINDOWSNT | 826 #ifdef WINDOWSNT |
873 /* Discard any previous drive specifier if nm is now in UNC format. */ | 827 /* Discard any previous drive specifier if nm is now in UNC format. */ |
874 if (IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])) | 828 if (IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])) |
875 { | 829 { |
876 drive = 0; | 830 drive = 0; |
878 #endif /* WINDOWSNT */ | 832 #endif /* WINDOWSNT */ |
879 | 833 |
880 /* If nm is absolute, look for /./ or /../ sequences; if none are | 834 /* If nm is absolute, look for /./ or /../ sequences; if none are |
881 found, we can probably return right away. We will avoid allocating | 835 found, we can probably return right away. We will avoid allocating |
882 a new string if name is already fully expanded. */ | 836 a new string if name is already fully expanded. */ |
883 if (IS_DIRECTORY_SEP (nm[0]) | 837 if ( |
838 IS_DIRECTORY_SEP (nm[0]) | |
839 #ifdef MSDOS | |
840 && drive | |
841 #endif | |
884 #ifdef WINDOWSNT | 842 #ifdef WINDOWSNT |
885 && (drive || IS_DIRECTORY_SEP (nm[1])) | 843 && (drive || IS_DIRECTORY_SEP (nm[1])) |
886 #endif | 844 #endif |
887 ) | 845 ) |
888 { | 846 { |
895 int lose = 0; | 853 int lose = 0; |
896 | 854 |
897 p = nm; | 855 p = nm; |
898 while (*p) | 856 while (*p) |
899 { | 857 { |
900 /* Since we know the path is absolute, we can assume that each | 858 /* Since we know the name is absolute, we can assume that each |
901 element starts with a "/". */ | 859 element starts with a "/". */ |
902 | 860 |
903 /* "." and ".." are hairy. */ | 861 /* "." and ".." are hairy. */ |
904 if (IS_DIRECTORY_SEP (p[0]) | 862 if (IS_DIRECTORY_SEP (p[0]) |
905 && p[1] == '.' | 863 && p[1] == '.' |
923 if (strcmp (nm, XSTRING_DATA (name)) != 0) | 881 if (strcmp (nm, XSTRING_DATA (name)) != 0) |
924 name = build_string (nm); | 882 name = build_string (nm); |
925 } | 883 } |
926 else | 884 else |
927 #endif | 885 #endif |
928 /* drive must be set, so this is okay */ | 886 /* drive must be set, so this is okay */ |
929 if (strcmp (nm - 2, XSTRING_DATA (name)) != 0) | 887 if (strcmp (nm - 2, XSTRING_DATA (name)) != 0) |
930 { | 888 { |
931 name = make_string (nm - 2, p - nm + 2); | 889 name = make_string (nm - 2, p - nm + 2); |
932 XSTRING_DATA (name)[0] = DRIVE_LETTER (drive); | 890 XSTRING_DATA (name)[0] = DRIVE_LETTER (drive); |
933 XSTRING_DATA (name)[1] = ':'; | 891 XSTRING_DATA (name)[1] = ':'; |
934 } | 892 } |
935 return name; | 893 return name; |
936 #else /* not DOS_NT */ | 894 #else /* not DOS_NT */ |
937 /* Unix */ | |
938 if (nm == XSTRING_DATA (name)) | 895 if (nm == XSTRING_DATA (name)) |
939 return name; | 896 return name; |
940 return build_string ((char *) nm); | 897 return build_string (nm); |
941 #endif /* DOS_NT */ | 898 #endif /* not DOS_NT */ |
942 } | 899 } |
943 } | 900 } |
944 | 901 |
945 /* At this point, nm might or might not be an absolute file name. We | 902 /* 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 | 903 need to expand ~ or ~user if present, otherwise prefix nm with |
947 default_directory if nm is not absolute, and finally collapse /./ | 904 default_directory if nm is not absolute, and finally collapse /./ |
948 and /foo/../ sequences. | 905 and /foo/../ sequences. |
949 | 906 |
950 We set newdir to be the appropriate prefix if one is needed: | 907 We set newdir to be the appropriate prefix if one is needed: |
951 - the relevant user directory if nm starts with ~ or ~user | 908 - the relevant user directory if nm starts with ~ or ~user |
952 - the specified drive's working dir (DOS/NT only) if nm does not | 909 - the specified drive's working dir (DOS/NT only) if nm does not |
953 start with / | 910 start with / |
954 - the value of default_directory. | 911 - the value of default_directory. |
955 | 912 |
956 Note that these prefixes are not guaranteed to be absolute (except | 913 Note that these prefixes are not guaranteed to be absolute (except |
957 for the working dir of a drive). Therefore, to ensure we always | 914 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 | 915 return an absolute name, if the final prefix is not absolute we |
959 append it to the current working directory. */ | 916 append it to the current working directory. */ |
961 newdir = 0; | 918 newdir = 0; |
962 | 919 |
963 if (nm[0] == '~') /* prefix ~ */ | 920 if (nm[0] == '~') /* prefix ~ */ |
964 { | 921 { |
965 if (IS_DIRECTORY_SEP (nm[1]) | 922 if (IS_DIRECTORY_SEP (nm[1]) |
966 || nm[1] == 0) /* ~ by itself */ | 923 || nm[1] == 0) /* ~ by itself */ |
967 { | 924 { |
968 if (!(newdir = (Bufbyte *) egetenv ("HOME"))) | 925 if (!(newdir = (Bufbyte *) egetenv ("HOME"))) |
969 newdir = (Bufbyte *) ""; | 926 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 | |
974 #ifdef DOS_NT | |
975 /* Problem when expanding "~\" if HOME is not on current drive. | |
976 Ulrich Leodolter, Wed Jan 11 10:20:35 1995 */ | |
977 if (newdir[1] == ':') | |
978 drive = newdir[0]; | |
979 dostounix_filename (newdir); | |
980 #endif /* DOS_NT */ | |
981 #endif /* 0 */ | |
982 nm++; | 927 nm++; |
983 #ifdef DOS_NT | 928 #ifdef DOS_NT |
984 collapse_newdir = 0; | 929 collapse_newdir = 0; |
985 #endif /* DOS_NT */ | 930 #endif |
986 } | 931 } |
987 else /* ~user/filename */ | 932 else /* ~user/filename */ |
988 { | 933 { |
989 for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)); p++); | 934 for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)); p++); |
990 o = (Bufbyte *) alloca (p - nm + 1); | 935 o = (Bufbyte *) alloca (p - nm + 1); |
991 memcpy (o, (char *) nm, p - nm); | 936 memcpy (o, (char *) nm, p - nm); |
992 o [p - nm] = 0; | 937 o [p - nm] = 0; |
993 | 938 |
994 /* Syncing with FSF 19.34.6 note: FSF uses getpwnam even on NT, which does | 939 /* #### marcpa's syncing note: FSF uses getpwnam even on NT, |
995 not work. The following works only if ~USER names the user who runs | 940 which does not work. The following works only if ~USER |
996 this instance of XEmacs. While NT is single-user (for the moment) you | 941 names the user who runs this instance of XEmacs. While |
997 still can have multiple user profiles users defined, each with its | 942 NT is single-user (for the moment) you still can have |
998 HOME. Therefore, the following should be reworked to handle this case. | 943 multiple user profiles users defined, each with its HOME. |
999 --marcpa */ | 944 Therefore, the following should be reworked to handle |
945 this case. */ | |
1000 #ifdef WINDOWSNT | 946 #ifdef WINDOWSNT |
1001 /* | 947 /* Now if the file given is "~foo/file" and HOME="c:/", then |
1002 ** Now if the file given is "~foo/file" and HOME="c:/", then we | 948 we want the file to be named "c:/file" ("~foo" becomes |
1003 ** want the file to be named "c:/file" ("~foo" becomes "c:/"). | 949 "c:/"). The variable o has "~foo", so we can use the |
1004 ** The variable o has "~foo", so we can use the length of | 950 length of that string to offset nm. August Hill, 31 Aug |
1005 ** that string to offset nm. August Hill, 31 Aug 1998. | 951 1998. */ |
1006 */ | |
1007 newdir = (Bufbyte *) egetenv ("HOME"); | 952 newdir = (Bufbyte *) egetenv ("HOME"); |
1008 dostounix_filename (newdir); | 953 dostounix_filename (newdir); |
1009 nm += strlen(o) + 1; | 954 nm += strlen(o) + 1; |
1010 #else /* not WINDOWSNT */ | 955 #else /* not WINDOWSNT */ |
1011 /* Jamie reports that getpwnam() can get wedged by SIGIO/SIGALARM | 956 /* Jamie reports that getpwnam() can get wedged by SIGIO/SIGALARM |
1049 } | 994 } |
1050 #endif /* DOS_NT */ | 995 #endif /* DOS_NT */ |
1051 | 996 |
1052 /* Finally, if no prefix has been specified and nm is not absolute, | 997 /* Finally, if no prefix has been specified and nm is not absolute, |
1053 then it must be expanded relative to default_directory. */ | 998 then it must be expanded relative to default_directory. */ |
999 | |
1054 if (1 | 1000 if (1 |
1055 #ifndef DOS_NT | 1001 #ifndef DOS_NT |
1056 && !IS_ANY_SEP (nm[0]) | 1002 /* /... alone is not absolute on DOS and Windows. */ |
1057 #endif /* not DOS_NT */ | 1003 && !IS_DIRECTORY_SEP (nm[0]) |
1004 #endif | |
1058 #ifdef WINDOWSNT | 1005 #ifdef WINDOWSNT |
1059 && !(IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])) | 1006 && !(IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])) |
1060 #endif | 1007 #endif |
1061 && !newdir | 1008 && !newdir) |
1062 && STRINGP (default_)) | 1009 { |
1063 { | 1010 newdir = XSTRING_DATA (default_directory); |
1064 newdir = XSTRING_DATA (default_); | |
1065 } | 1011 } |
1066 | 1012 |
1067 #ifdef DOS_NT | 1013 #ifdef DOS_NT |
1068 if (newdir) | 1014 if (newdir) |
1069 { | 1015 { |
1131 #endif | 1077 #endif |
1132 newdir = ""; | 1078 newdir = ""; |
1133 } | 1079 } |
1134 } | 1080 } |
1135 #endif /* DOS_NT */ | 1081 #endif /* DOS_NT */ |
1136 if (newdir != 0) | 1082 |
1083 if (newdir) | |
1137 { | 1084 { |
1138 /* Get rid of any slash at the end of newdir, unless newdir is | 1085 /* Get rid of any slash at the end of newdir, unless newdir is |
1139 just // (an incomplete UNC name). */ | 1086 just // (an incomplete UNC name). */ |
1140 int length = strlen ((char *) newdir); | 1087 length = strlen (newdir); |
1141 /* Adding `length > 1 &&' makes ~ expand into / when homedir | 1088 if (length > 0 && IS_DIRECTORY_SEP (newdir[length - 1]) |
1142 is the root dir. People disagree about whether that is right. | |
1143 Anyway, we can't take the risk of this change now. */ | |
1144 /* Syncing with FSF 19.34.6 note: FSF does the above. */ | |
1145 if (IS_DIRECTORY_SEP (newdir[length - 1]) | |
1146 #ifdef WINDOWSNT | 1089 #ifdef WINDOWSNT |
1147 && !(length == 2 && IS_DIRECTORY_SEP (newdir[0])) | 1090 && !(length == 2 && IS_DIRECTORY_SEP (newdir[0])) |
1148 #endif | 1091 #endif |
1149 ) | 1092 ) |
1150 { | 1093 { |
1157 } | 1100 } |
1158 else | 1101 else |
1159 tlen = 0; | 1102 tlen = 0; |
1160 | 1103 |
1161 /* Now concatenate the directory and name to new space in the stack frame */ | 1104 /* Now concatenate the directory and name to new space in the stack frame */ |
1162 tlen += strlen ((char *) nm) + 1; | 1105 tlen += strlen (nm) + 1; |
1163 #ifdef DOS_NT | 1106 #ifdef DOS_NT |
1164 /* Add reserved space for drive name. (The Microsoft x86 compiler | 1107 /* Add reserved space for drive name. (The Microsoft x86 compiler |
1165 produces incorrect code if the following two lines are combined.) */ | 1108 produces incorrect code if the following two lines are combined.) */ |
1166 target = (Bufbyte *) alloca (tlen + 2); | 1109 target = (Bufbyte *) alloca (tlen + 2); |
1167 target += 2; | 1110 target += 2; |
1168 #else /* not DOS_NT */ | 1111 #else /* not DOS_NT */ |
1169 target = (Bufbyte *) alloca (tlen); | 1112 target = (Bufbyte *) alloca (tlen); |
1170 #endif /* DOS_NT */ | 1113 #endif /* not DOS_NT */ |
1171 *target = 0; | 1114 *target = 0; |
1172 | 1115 |
1173 if (newdir) | 1116 if (newdir) |
1174 { | 1117 { |
1175 if (nm[0] == 0 || IS_DIRECTORY_SEP (nm[0])) | 1118 if (nm[0] == 0 || IS_DIRECTORY_SEP (nm[0])) |
1176 strcpy ((char *) target, (char *) newdir); | 1119 strcpy (target, newdir); |
1177 else | 1120 else |
1178 file_name_as_directory ((char *) target, (char *) newdir); | 1121 file_name_as_directory (target, newdir); |
1179 } | 1122 } |
1180 | 1123 |
1181 strcat ((char *) target, (char *) nm); | 1124 strcat (target, nm); |
1125 | |
1126 /* ASSERT (IS_DIRECTORY_SEP (target[0])) if not VMS */ | |
1182 | 1127 |
1183 /* Now canonicalize by removing /. and /foo/.. if they appear. */ | 1128 /* Now canonicalize by removing /. and /foo/.. if they appear. */ |
1184 | 1129 |
1185 p = target; | 1130 p = target; |
1186 o = target; | 1131 o = target; |
1189 { | 1134 { |
1190 if (!IS_DIRECTORY_SEP (*p)) | 1135 if (!IS_DIRECTORY_SEP (*p)) |
1191 { | 1136 { |
1192 *o++ = *p++; | 1137 *o++ = *p++; |
1193 } | 1138 } |
1194 else if (IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1]) | |
1195 #if defined (APOLLO) || defined (WINDOWSNT) | |
1196 /* // at start of filename is meaningful in Apollo | |
1197 and WindowsNT systems */ | |
1198 && o != target | |
1199 #endif /* APOLLO || WINDOWSNT */ | |
1200 ) | |
1201 { | |
1202 o = target; | |
1203 p++; | |
1204 } | |
1205 else if (IS_DIRECTORY_SEP (p[0]) | 1139 else if (IS_DIRECTORY_SEP (p[0]) |
1206 && p[1] == '.' | 1140 && p[1] == '.' |
1207 && (IS_DIRECTORY_SEP (p[2]) | 1141 && (IS_DIRECTORY_SEP (p[2]) |
1208 || p[2] == 0)) | 1142 || p[2] == 0)) |
1209 { | 1143 { |
1210 /* If "/." is the entire filename, keep the "/". Otherwise, | 1144 /* If "/." is the entire filename, keep the "/". Otherwise, |
1211 just delete the whole "/.". */ | 1145 just delete the whole "/.". */ |
1218 && o != target | 1152 && o != target |
1219 && (IS_DIRECTORY_SEP (p[3]) || p[3] == 0)) | 1153 && (IS_DIRECTORY_SEP (p[3]) || p[3] == 0)) |
1220 { | 1154 { |
1221 while (o != target && (--o) && !IS_DIRECTORY_SEP (*o)) | 1155 while (o != target && (--o) && !IS_DIRECTORY_SEP (*o)) |
1222 ; | 1156 ; |
1223 if (o == target && IS_ANY_SEP (*o) | 1157 /* Keep initial / only if this is the whole name. */ |
1224 #ifdef DOS_NT | 1158 if (o == target && IS_ANY_SEP (*o) && p[3] == 0) |
1225 && p[3] == 0 | |
1226 #endif | |
1227 ) | |
1228 ++o; | 1159 ++o; |
1229 p += 3; | 1160 p += 3; |
1230 } | 1161 } |
1231 else | 1162 else |
1232 { | 1163 { |