diff options
| author | Stefan Monnier | 2013-10-10 17:42:38 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2013-10-10 17:42:38 -0400 |
| commit | ee041f2d07b6ed485dc34c115588f973f046c9d4 (patch) | |
| tree | 8152e54e2d2552d52629c7455837f85d07ee9503 /src | |
| parent | 00036e1dd2f2194fbc7938076defbe2d7228c8a3 (diff) | |
| download | emacs-ee041f2d07b6ed485dc34c115588f973f046c9d4.tar.gz emacs-ee041f2d07b6ed485dc34c115588f973f046c9d4.zip | |
* src/fileio.c (Fsubstitute_in_file_name): Use substitute-env-in-file-name.
(Qsubstitute_env_in_file_name): New var.
(syms_of_fileio): Define it.
* lisp/env.el (substitute-env-in-file-name): New function.
(substitute-env-vars): Extend the meaning of the optional arg.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 6 | ||||
| -rw-r--r-- | src/fileio.c | 161 |
2 files changed, 29 insertions, 138 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 4bd46642f43..39d576f2c40 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,9 @@ | |||
| 1 | 2013-10-10 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * fileio.c (Fsubstitute_in_file_name): Use substitute-env-in-file-name. | ||
| 4 | (Qsubstitute_env_in_file_name): New var. | ||
| 5 | (syms_of_fileio): Define it. | ||
| 6 | |||
| 1 | 2013-10-10 Eli Zaretskii <eliz@gnu.org> | 7 | 2013-10-10 Eli Zaretskii <eliz@gnu.org> |
| 2 | 8 | ||
| 3 | * xdisp.c (deep_copy_glyph_row): Assert that the 'used' counts of | 9 | * xdisp.c (deep_copy_glyph_row): Assert that the 'used' counts of |
diff --git a/src/fileio.c b/src/fileio.c index c7125534e63..a80145ae42c 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -143,6 +143,8 @@ static Lisp_Object Qcopy_directory; | |||
| 143 | /* Lisp function for recursively deleting directories. */ | 143 | /* Lisp function for recursively deleting directories. */ |
| 144 | static Lisp_Object Qdelete_directory; | 144 | static Lisp_Object Qdelete_directory; |
| 145 | 145 | ||
| 146 | static Lisp_Object Qsubstitute_env_in_file_name; | ||
| 147 | |||
| 146 | #ifdef WINDOWSNT | 148 | #ifdef WINDOWSNT |
| 147 | #endif | 149 | #endif |
| 148 | 150 | ||
| @@ -1664,10 +1666,8 @@ If `//' appears, everything up to and including the first of | |||
| 1664 | those `/' is discarded. */) | 1666 | those `/' is discarded. */) |
| 1665 | (Lisp_Object filename) | 1667 | (Lisp_Object filename) |
| 1666 | { | 1668 | { |
| 1667 | char *nm, *s, *p, *o, *x, *endp; | 1669 | char *nm, *p, *x, *endp; |
| 1668 | char *target = NULL; | 1670 | bool substituted = false; |
| 1669 | ptrdiff_t total = 0; | ||
| 1670 | bool substituted = 0; | ||
| 1671 | bool multibyte; | 1671 | bool multibyte; |
| 1672 | char *xnm; | 1672 | char *xnm; |
| 1673 | Lisp_Object handler; | 1673 | Lisp_Object handler; |
| @@ -1708,66 +1708,19 @@ those `/' is discarded. */) | |||
| 1708 | return Fsubstitute_in_file_name | 1708 | return Fsubstitute_in_file_name |
| 1709 | (make_specified_string (p, -1, endp - p, multibyte)); | 1709 | (make_specified_string (p, -1, endp - p, multibyte)); |
| 1710 | 1710 | ||
| 1711 | /* See if any variables are substituted into the string | 1711 | /* See if any variables are substituted into the string. */ |
| 1712 | and find the total length of their values in `total'. */ | ||
| 1713 | |||
| 1714 | for (p = nm; p != endp;) | ||
| 1715 | if (*p != '$') | ||
| 1716 | p++; | ||
| 1717 | else | ||
| 1718 | { | ||
| 1719 | p++; | ||
| 1720 | if (p == endp) | ||
| 1721 | goto badsubst; | ||
| 1722 | else if (*p == '$') | ||
| 1723 | { | ||
| 1724 | /* "$$" means a single "$". */ | ||
| 1725 | p++; | ||
| 1726 | total -= 1; | ||
| 1727 | substituted = 1; | ||
| 1728 | continue; | ||
| 1729 | } | ||
| 1730 | else if (*p == '{') | ||
| 1731 | { | ||
| 1732 | o = ++p; | ||
| 1733 | p = memchr (p, '}', endp - p); | ||
| 1734 | if (! p) | ||
| 1735 | goto missingclose; | ||
| 1736 | s = p; | ||
| 1737 | } | ||
| 1738 | else | ||
| 1739 | { | ||
| 1740 | o = p; | ||
| 1741 | while (p != endp && (c_isalnum (*p) || *p == '_')) p++; | ||
| 1742 | s = p; | ||
| 1743 | } | ||
| 1744 | |||
| 1745 | /* Copy out the variable name. */ | ||
| 1746 | target = alloca (s - o + 1); | ||
| 1747 | memcpy (target, o, s - o); | ||
| 1748 | target[s - o] = 0; | ||
| 1749 | #ifdef DOS_NT | ||
| 1750 | strupr (target); /* $home == $HOME etc. */ | ||
| 1751 | #endif /* DOS_NT */ | ||
| 1752 | 1712 | ||
| 1753 | /* Get variable value. */ | 1713 | if (!NILP (Ffboundp (Qsubstitute_env_in_file_name))) |
| 1754 | o = egetenv (target); | 1714 | { |
| 1755 | if (o) | 1715 | Lisp_Object name |
| 1756 | { | 1716 | = (!substituted ? filename |
| 1757 | /* Don't try to guess a maximum length - UTF8 can use up to | 1717 | : make_specified_string (nm, -1, endp - nm, multibyte)); |
| 1758 | four bytes per character. This code is unlikely to run | 1718 | Lisp_Object tmp = call1 (Qsubstitute_env_in_file_name, name); |
| 1759 | in a situation that requires performance, so decoding the | 1719 | CHECK_STRING (tmp); |
| 1760 | env variables twice should be acceptable. Note that | 1720 | if (!EQ (tmp, name)) |
| 1761 | decoding may cause a garbage collect. */ | 1721 | substituted = true; |
| 1762 | Lisp_Object orig, decoded; | 1722 | filename = tmp; |
| 1763 | orig = build_unibyte_string (o); | 1723 | } |
| 1764 | decoded = DECODE_FILE (orig); | ||
| 1765 | total += SBYTES (decoded); | ||
| 1766 | substituted = 1; | ||
| 1767 | } | ||
| 1768 | else if (*p == '}') | ||
| 1769 | goto badvar; | ||
| 1770 | } | ||
| 1771 | 1724 | ||
| 1772 | if (!substituted) | 1725 | if (!substituted) |
| 1773 | { | 1726 | { |
| @@ -1778,73 +1731,9 @@ those `/' is discarded. */) | |||
| 1778 | return filename; | 1731 | return filename; |
| 1779 | } | 1732 | } |
| 1780 | 1733 | ||
| 1781 | /* If substitution required, recopy the string and do it. */ | 1734 | xnm = SSDATA (filename); |
| 1782 | /* Make space in stack frame for the new copy. */ | 1735 | x = xnm + SBYTES (filename); |
| 1783 | xnm = alloca (SBYTES (filename) + total + 1); | 1736 | |
| 1784 | x = xnm; | ||
| 1785 | |||
| 1786 | /* Copy the rest of the name through, replacing $ constructs with values. */ | ||
| 1787 | for (p = nm; *p;) | ||
| 1788 | if (*p != '$') | ||
| 1789 | *x++ = *p++; | ||
| 1790 | else | ||
| 1791 | { | ||
| 1792 | p++; | ||
| 1793 | if (p == endp) | ||
| 1794 | goto badsubst; | ||
| 1795 | else if (*p == '$') | ||
| 1796 | { | ||
| 1797 | *x++ = *p++; | ||
| 1798 | continue; | ||
| 1799 | } | ||
| 1800 | else if (*p == '{') | ||
| 1801 | { | ||
| 1802 | o = ++p; | ||
| 1803 | p = memchr (p, '}', endp - p); | ||
| 1804 | if (! p) | ||
| 1805 | goto missingclose; | ||
| 1806 | s = p++; | ||
| 1807 | } | ||
| 1808 | else | ||
| 1809 | { | ||
| 1810 | o = p; | ||
| 1811 | while (p != endp && (c_isalnum (*p) || *p == '_')) p++; | ||
| 1812 | s = p; | ||
| 1813 | } | ||
| 1814 | |||
| 1815 | /* Copy out the variable name. */ | ||
| 1816 | target = alloca (s - o + 1); | ||
| 1817 | memcpy (target, o, s - o); | ||
| 1818 | target[s - o] = 0; | ||
| 1819 | |||
| 1820 | /* Get variable value. */ | ||
| 1821 | o = egetenv (target); | ||
| 1822 | if (!o) | ||
| 1823 | { | ||
| 1824 | *x++ = '$'; | ||
| 1825 | strcpy (x, target); x+= strlen (target); | ||
| 1826 | } | ||
| 1827 | else | ||
| 1828 | { | ||
| 1829 | Lisp_Object orig, decoded; | ||
| 1830 | ptrdiff_t orig_length, decoded_length; | ||
| 1831 | orig_length = strlen (o); | ||
| 1832 | orig = make_unibyte_string (o, orig_length); | ||
| 1833 | decoded = DECODE_FILE (orig); | ||
| 1834 | decoded_length = SBYTES (decoded); | ||
| 1835 | memcpy (x, SDATA (decoded), decoded_length); | ||
| 1836 | x += decoded_length; | ||
| 1837 | |||
| 1838 | /* If environment variable needed decoding, return value | ||
| 1839 | needs to be multibyte. */ | ||
| 1840 | if (decoded_length != orig_length | ||
| 1841 | || memcmp (SDATA (decoded), o, orig_length)) | ||
| 1842 | multibyte = 1; | ||
| 1843 | } | ||
| 1844 | } | ||
| 1845 | |||
| 1846 | *x = 0; | ||
| 1847 | |||
| 1848 | /* If /~ or // appears, discard everything through first slash. */ | 1737 | /* If /~ or // appears, discard everything through first slash. */ |
| 1849 | while ((p = search_embedded_absfilename (xnm, x)) != NULL) | 1738 | while ((p = search_embedded_absfilename (xnm, x)) != NULL) |
| 1850 | /* This time we do not start over because we've already expanded envvars | 1739 | /* This time we do not start over because we've already expanded envvars |
| @@ -1862,14 +1751,9 @@ those `/' is discarded. */) | |||
| 1862 | } | 1751 | } |
| 1863 | else | 1752 | else |
| 1864 | #endif | 1753 | #endif |
| 1865 | return make_specified_string (xnm, -1, x - xnm, multibyte); | 1754 | return (xnm == SSDATA (filename) |
| 1866 | 1755 | ? filename | |
| 1867 | badsubst: | 1756 | : make_specified_string (xnm, -1, x - xnm, multibyte)); |
| 1868 | error ("Bad format environment-variable substitution"); | ||
| 1869 | missingclose: | ||
| 1870 | error ("Missing \"}\" in environment-variable substitution"); | ||
| 1871 | badvar: | ||
| 1872 | error ("Substituting nonexistent environment variable \"%s\"", target); | ||
| 1873 | } | 1757 | } |
| 1874 | 1758 | ||
| 1875 | /* A slightly faster and more convenient way to get | 1759 | /* A slightly faster and more convenient way to get |
| @@ -6108,6 +5992,7 @@ This includes interactive calls to `delete-file' and | |||
| 6108 | DEFSYM (Qmove_file_to_trash, "move-file-to-trash"); | 5992 | DEFSYM (Qmove_file_to_trash, "move-file-to-trash"); |
| 6109 | DEFSYM (Qcopy_directory, "copy-directory"); | 5993 | DEFSYM (Qcopy_directory, "copy-directory"); |
| 6110 | DEFSYM (Qdelete_directory, "delete-directory"); | 5994 | DEFSYM (Qdelete_directory, "delete-directory"); |
| 5995 | DEFSYM (Qsubstitute_env_in_file_name, "substitute-env-in-file-name"); | ||
| 6111 | 5996 | ||
| 6112 | defsubr (&Sfind_file_name_handler); | 5997 | defsubr (&Sfind_file_name_handler); |
| 6113 | defsubr (&Sfile_name_directory); | 5998 | defsubr (&Sfile_name_directory); |