diff options
| author | Eli Zaretskii | 2001-10-25 13:33:01 +0000 |
|---|---|---|
| committer | Eli Zaretskii | 2001-10-25 13:33:01 +0000 |
| commit | 4887597a1c52b8277eabeb4d9484c75b1bc9429d (patch) | |
| tree | 949f97173f3c79e008fc6ea2dba47b9682ba74a0 /src | |
| parent | dfe92a6aca66555ae7bb0ca36c5d5d7c12fe91ca (diff) | |
| download | emacs-4887597a1c52b8277eabeb4d9484c75b1bc9429d.tar.gz emacs-4887597a1c52b8277eabeb4d9484c75b1bc9429d.zip | |
Revert last change (which removed old commented-out
version of expand-file-name). Add a comment that explains why
this old version should not be removed.
Diffstat (limited to 'src')
| -rw-r--r-- | src/fileio.c | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/src/fileio.c b/src/fileio.c index d1c35aeddb2..a5c9972692b 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -1647,6 +1647,339 @@ See also the function `substitute-in-file-name'. */) | |||
| 1647 | return make_string (target, o - target); | 1647 | return make_string (target, o - target); |
| 1648 | } | 1648 | } |
| 1649 | 1649 | ||
| 1650 | #if 0 | ||
| 1651 | /* PLEASE DO NOT DELETE THIS COMMENTED-OUT VERSION! | ||
| 1652 | This is the old version of expand-file-name, before it was thoroughly | ||
| 1653 | rewritten for Emacs 10.31. We leave this version here commented-out, | ||
| 1654 | because the code is very complex and likely to have subtle bugs. If | ||
| 1655 | bugs _are_ found, it might be of interest to look at the old code and | ||
| 1656 | see what did it do in the relevant situation. | ||
| 1657 | |||
| 1658 | Don't remove this code: it's true that it will be accessible via CVS, | ||
| 1659 | but a few years from deletion, people will forget it is there. */ | ||
| 1660 | |||
| 1661 | /* Changed this DEFUN to a DEAFUN, so as not to confuse `make-docfile'. */ | ||
| 1662 | DEAFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0, | ||
| 1663 | "Convert FILENAME to absolute, and canonicalize it.\n\ | ||
| 1664 | Second arg DEFAULT is directory to start with if FILENAME is relative\n\ | ||
| 1665 | (does not start with slash); if DEFAULT is nil or missing,\n\ | ||
| 1666 | the current buffer's value of default-directory is used.\n\ | ||
| 1667 | Filenames containing `.' or `..' as components are simplified;\n\ | ||
| 1668 | initial `~/' expands to your home directory.\n\ | ||
| 1669 | See also the function `substitute-in-file-name'.") | ||
| 1670 | (name, defalt) | ||
| 1671 | Lisp_Object name, defalt; | ||
| 1672 | { | ||
| 1673 | unsigned char *nm; | ||
| 1674 | |||
| 1675 | register unsigned char *newdir, *p, *o; | ||
| 1676 | int tlen; | ||
| 1677 | unsigned char *target; | ||
| 1678 | struct passwd *pw; | ||
| 1679 | int lose; | ||
| 1680 | #ifdef VMS | ||
| 1681 | unsigned char * colon = 0; | ||
| 1682 | unsigned char * close = 0; | ||
| 1683 | unsigned char * slash = 0; | ||
| 1684 | unsigned char * brack = 0; | ||
| 1685 | int lbrack = 0, rbrack = 0; | ||
| 1686 | int dots = 0; | ||
| 1687 | #endif /* VMS */ | ||
| 1688 | |||
| 1689 | CHECK_STRING (name, 0); | ||
| 1690 | |||
| 1691 | #ifdef VMS | ||
| 1692 | /* Filenames on VMS are always upper case. */ | ||
| 1693 | name = Fupcase (name); | ||
| 1694 | #endif | ||
| 1695 | |||
| 1696 | nm = XSTRING (name)->data; | ||
| 1697 | |||
| 1698 | /* If nm is absolute, flush ...// and detect /./ and /../. | ||
| 1699 | If no /./ or /../ we can return right away. */ | ||
| 1700 | if ( | ||
| 1701 | nm[0] == '/' | ||
| 1702 | #ifdef VMS | ||
| 1703 | || index (nm, ':') | ||
| 1704 | #endif /* VMS */ | ||
| 1705 | ) | ||
| 1706 | { | ||
| 1707 | p = nm; | ||
| 1708 | lose = 0; | ||
| 1709 | while (*p) | ||
| 1710 | { | ||
| 1711 | if (p[0] == '/' && p[1] == '/' | ||
| 1712 | #ifdef APOLLO | ||
| 1713 | /* // at start of filename is meaningful on Apollo system. */ | ||
| 1714 | && nm != p | ||
| 1715 | #endif /* APOLLO */ | ||
| 1716 | ) | ||
| 1717 | nm = p + 1; | ||
| 1718 | if (p[0] == '/' && p[1] == '~') | ||
| 1719 | nm = p + 1, lose = 1; | ||
| 1720 | if (p[0] == '/' && p[1] == '.' | ||
| 1721 | && (p[2] == '/' || p[2] == 0 | ||
| 1722 | || (p[2] == '.' && (p[3] == '/' || p[3] == 0)))) | ||
| 1723 | lose = 1; | ||
| 1724 | #ifdef VMS | ||
| 1725 | if (p[0] == '\\') | ||
| 1726 | lose = 1; | ||
| 1727 | if (p[0] == '/') { | ||
| 1728 | /* if dev:[dir]/, move nm to / */ | ||
| 1729 | if (!slash && p > nm && (brack || colon)) { | ||
| 1730 | nm = (brack ? brack + 1 : colon + 1); | ||
| 1731 | lbrack = rbrack = 0; | ||
| 1732 | brack = 0; | ||
| 1733 | colon = 0; | ||
| 1734 | } | ||
| 1735 | slash = p; | ||
| 1736 | } | ||
| 1737 | if (p[0] == '-') | ||
| 1738 | #ifndef VMS4_4 | ||
| 1739 | /* VMS pre V4.4,convert '-'s in filenames. */ | ||
| 1740 | if (lbrack == rbrack) | ||
| 1741 | { | ||
| 1742 | if (dots < 2) /* this is to allow negative version numbers */ | ||
| 1743 | p[0] = '_'; | ||
| 1744 | } | ||
| 1745 | else | ||
| 1746 | #endif /* VMS4_4 */ | ||
| 1747 | if (lbrack > rbrack && | ||
| 1748 | ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<') && | ||
| 1749 | (p[1] == '.' || p[1] == ']' || p[1] == '>'))) | ||
| 1750 | lose = 1; | ||
| 1751 | #ifndef VMS4_4 | ||
| 1752 | else | ||
| 1753 | p[0] = '_'; | ||
| 1754 | #endif /* VMS4_4 */ | ||
| 1755 | /* count open brackets, reset close bracket pointer */ | ||
| 1756 | if (p[0] == '[' || p[0] == '<') | ||
| 1757 | lbrack++, brack = 0; | ||
| 1758 | /* count close brackets, set close bracket pointer */ | ||
| 1759 | if (p[0] == ']' || p[0] == '>') | ||
| 1760 | rbrack++, brack = p; | ||
| 1761 | /* detect ][ or >< */ | ||
| 1762 | if ((p[0] == ']' || p[0] == '>') && (p[1] == '[' || p[1] == '<')) | ||
| 1763 | lose = 1; | ||
| 1764 | if ((p[0] == ':' || p[0] == ']' || p[0] == '>') && p[1] == '~') | ||
| 1765 | nm = p + 1, lose = 1; | ||
| 1766 | if (p[0] == ':' && (colon || slash)) | ||
| 1767 | /* if dev1:[dir]dev2:, move nm to dev2: */ | ||
| 1768 | if (brack) | ||
| 1769 | { | ||
| 1770 | nm = brack + 1; | ||
| 1771 | brack = 0; | ||
| 1772 | } | ||
| 1773 | /* If /name/dev:, move nm to dev: */ | ||
| 1774 | else if (slash) | ||
| 1775 | nm = slash + 1; | ||
| 1776 | /* If node::dev:, move colon following dev */ | ||
| 1777 | else if (colon && colon[-1] == ':') | ||
| 1778 | colon = p; | ||
| 1779 | /* If dev1:dev2:, move nm to dev2: */ | ||
| 1780 | else if (colon && colon[-1] != ':') | ||
| 1781 | { | ||
| 1782 | nm = colon + 1; | ||
| 1783 | colon = 0; | ||
| 1784 | } | ||
| 1785 | if (p[0] == ':' && !colon) | ||
| 1786 | { | ||
| 1787 | if (p[1] == ':') | ||
| 1788 | p++; | ||
| 1789 | colon = p; | ||
| 1790 | } | ||
| 1791 | if (lbrack == rbrack) | ||
| 1792 | if (p[0] == ';') | ||
| 1793 | dots = 2; | ||
| 1794 | else if (p[0] == '.') | ||
| 1795 | dots++; | ||
| 1796 | #endif /* VMS */ | ||
| 1797 | p++; | ||
| 1798 | } | ||
| 1799 | if (!lose) | ||
| 1800 | { | ||
| 1801 | #ifdef VMS | ||
| 1802 | if (index (nm, '/')) | ||
| 1803 | return build_string (sys_translate_unix (nm)); | ||
| 1804 | #endif /* VMS */ | ||
| 1805 | if (nm == XSTRING (name)->data) | ||
| 1806 | return name; | ||
| 1807 | return build_string (nm); | ||
| 1808 | } | ||
| 1809 | } | ||
| 1810 | |||
| 1811 | /* Now determine directory to start with and put it in NEWDIR */ | ||
| 1812 | |||
| 1813 | newdir = 0; | ||
| 1814 | |||
| 1815 | if (nm[0] == '~') /* prefix ~ */ | ||
| 1816 | if (nm[1] == '/' | ||
| 1817 | #ifdef VMS | ||
| 1818 | || nm[1] == ':' | ||
| 1819 | #endif /* VMS */ | ||
| 1820 | || nm[1] == 0)/* ~/filename */ | ||
| 1821 | { | ||
| 1822 | if (!(newdir = (unsigned char *) egetenv ("HOME"))) | ||
| 1823 | newdir = (unsigned char *) ""; | ||
| 1824 | nm++; | ||
| 1825 | #ifdef VMS | ||
| 1826 | nm++; /* Don't leave the slash in nm. */ | ||
| 1827 | #endif /* VMS */ | ||
| 1828 | } | ||
| 1829 | else /* ~user/filename */ | ||
| 1830 | { | ||
| 1831 | /* Get past ~ to user */ | ||
| 1832 | unsigned char *user = nm + 1; | ||
| 1833 | /* Find end of name. */ | ||
| 1834 | unsigned char *ptr = (unsigned char *) index (user, '/'); | ||
| 1835 | int len = ptr ? ptr - user : strlen (user); | ||
| 1836 | #ifdef VMS | ||
| 1837 | unsigned char *ptr1 = index (user, ':'); | ||
| 1838 | if (ptr1 != 0 && ptr1 - user < len) | ||
| 1839 | len = ptr1 - user; | ||
| 1840 | #endif /* VMS */ | ||
| 1841 | /* Copy the user name into temp storage. */ | ||
| 1842 | o = (unsigned char *) alloca (len + 1); | ||
| 1843 | bcopy ((char *) user, o, len); | ||
| 1844 | o[len] = 0; | ||
| 1845 | |||
| 1846 | /* Look up the user name. */ | ||
| 1847 | pw = (struct passwd *) getpwnam (o + 1); | ||
| 1848 | if (!pw) | ||
| 1849 | error ("\"%s\" isn't a registered user", o + 1); | ||
| 1850 | |||
| 1851 | newdir = (unsigned char *) pw->pw_dir; | ||
| 1852 | |||
| 1853 | /* Discard the user name from NM. */ | ||
| 1854 | nm += len; | ||
| 1855 | } | ||
| 1856 | |||
| 1857 | if (nm[0] != '/' | ||
| 1858 | #ifdef VMS | ||
| 1859 | && !index (nm, ':') | ||
| 1860 | #endif /* not VMS */ | ||
| 1861 | && !newdir) | ||
| 1862 | { | ||
| 1863 | if (NILP (defalt)) | ||
| 1864 | defalt = current_buffer->directory; | ||
| 1865 | CHECK_STRING (defalt, 1); | ||
| 1866 | newdir = XSTRING (defalt)->data; | ||
| 1867 | } | ||
| 1868 | |||
| 1869 | /* Now concatenate the directory and name to new space in the stack frame */ | ||
| 1870 | |||
| 1871 | tlen = (newdir ? strlen (newdir) + 1 : 0) + strlen (nm) + 1; | ||
| 1872 | target = (unsigned char *) alloca (tlen); | ||
| 1873 | *target = 0; | ||
| 1874 | |||
| 1875 | if (newdir) | ||
| 1876 | { | ||
| 1877 | #ifndef VMS | ||
| 1878 | if (nm[0] == 0 || nm[0] == '/') | ||
| 1879 | strcpy (target, newdir); | ||
| 1880 | else | ||
| 1881 | #endif | ||
| 1882 | file_name_as_directory (target, newdir); | ||
| 1883 | } | ||
| 1884 | |||
| 1885 | strcat (target, nm); | ||
| 1886 | #ifdef VMS | ||
| 1887 | if (index (target, '/')) | ||
| 1888 | strcpy (target, sys_translate_unix (target)); | ||
| 1889 | #endif /* VMS */ | ||
| 1890 | |||
| 1891 | /* Now canonicalize by removing /. and /foo/.. if they appear */ | ||
| 1892 | |||
| 1893 | p = target; | ||
| 1894 | o = target; | ||
| 1895 | |||
| 1896 | while (*p) | ||
| 1897 | { | ||
| 1898 | #ifdef VMS | ||
| 1899 | if (*p != ']' && *p != '>' && *p != '-') | ||
| 1900 | { | ||
| 1901 | if (*p == '\\') | ||
| 1902 | p++; | ||
| 1903 | *o++ = *p++; | ||
| 1904 | } | ||
| 1905 | else if ((p[0] == ']' || p[0] == '>') && p[0] == p[1] + 2) | ||
| 1906 | /* brackets are offset from each other by 2 */ | ||
| 1907 | { | ||
| 1908 | p += 2; | ||
| 1909 | if (*p != '.' && *p != '-' && o[-1] != '.') | ||
| 1910 | /* convert [foo][bar] to [bar] */ | ||
| 1911 | while (o[-1] != '[' && o[-1] != '<') | ||
| 1912 | o--; | ||
| 1913 | else if (*p == '-' && *o != '.') | ||
| 1914 | *--p = '.'; | ||
| 1915 | } | ||
| 1916 | else if (p[0] == '-' && o[-1] == '.' && | ||
| 1917 | (p[1] == '.' || p[1] == ']' || p[1] == '>')) | ||
| 1918 | /* flush .foo.- ; leave - if stopped by '[' or '<' */ | ||
| 1919 | { | ||
| 1920 | do | ||
| 1921 | o--; | ||
| 1922 | while (o[-1] != '.' && o[-1] != '[' && o[-1] != '<'); | ||
| 1923 | if (p[1] == '.') /* foo.-.bar ==> bar. */ | ||
| 1924 | p += 2; | ||
| 1925 | else if (o[-1] == '.') /* '.foo.-]' ==> ']' */ | ||
| 1926 | p++, o--; | ||
| 1927 | /* else [foo.-] ==> [-] */ | ||
| 1928 | } | ||
| 1929 | else | ||
| 1930 | { | ||
| 1931 | #ifndef VMS4_4 | ||
| 1932 | if (*p == '-' && | ||
| 1933 | o[-1] != '[' && o[-1] != '<' && o[-1] != '.' && | ||
| 1934 | p[1] != ']' && p[1] != '>' && p[1] != '.') | ||
| 1935 | *p = '_'; | ||
| 1936 | #endif /* VMS4_4 */ | ||
| 1937 | *o++ = *p++; | ||
| 1938 | } | ||
| 1939 | #else /* not VMS */ | ||
| 1940 | if (*p != '/') | ||
| 1941 | { | ||
| 1942 | *o++ = *p++; | ||
| 1943 | } | ||
| 1944 | else if (!strncmp (p, "//", 2) | ||
| 1945 | #ifdef APOLLO | ||
| 1946 | /* // at start of filename is meaningful in Apollo system. */ | ||
| 1947 | && o != target | ||
| 1948 | #endif /* APOLLO */ | ||
| 1949 | ) | ||
| 1950 | { | ||
| 1951 | o = target; | ||
| 1952 | p++; | ||
| 1953 | } | ||
| 1954 | else if (p[0] == '/' && p[1] == '.' && | ||
| 1955 | (p[2] == '/' || p[2] == 0)) | ||
| 1956 | p += 2; | ||
| 1957 | else if (!strncmp (p, "/..", 3) | ||
| 1958 | /* `/../' is the "superroot" on certain file systems. */ | ||
| 1959 | && o != target | ||
| 1960 | && (p[3] == '/' || p[3] == 0)) | ||
| 1961 | { | ||
| 1962 | while (o != target && *--o != '/') | ||
| 1963 | ; | ||
| 1964 | #ifdef APOLLO | ||
| 1965 | if (o == target + 1 && o[-1] == '/' && o[0] == '/') | ||
| 1966 | ++o; | ||
| 1967 | else | ||
| 1968 | #endif /* APOLLO */ | ||
| 1969 | if (o == target && *o == '/') | ||
| 1970 | ++o; | ||
| 1971 | p += 3; | ||
| 1972 | } | ||
| 1973 | else | ||
| 1974 | { | ||
| 1975 | *o++ = *p++; | ||
| 1976 | } | ||
| 1977 | #endif /* not VMS */ | ||
| 1978 | } | ||
| 1979 | |||
| 1980 | return make_string (target, o - target); | ||
| 1981 | } | ||
| 1982 | #endif | ||
| 1650 | 1983 | ||
| 1651 | DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name, | 1984 | DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name, |
| 1652 | Ssubstitute_in_file_name, 1, 1, 0, | 1985 | Ssubstitute_in_file_name, 1, 1, 0, |