aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Monnier2013-10-10 17:42:38 -0400
committerStefan Monnier2013-10-10 17:42:38 -0400
commitee041f2d07b6ed485dc34c115588f973f046c9d4 (patch)
tree8152e54e2d2552d52629c7455837f85d07ee9503 /src
parent00036e1dd2f2194fbc7938076defbe2d7228c8a3 (diff)
downloademacs-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/ChangeLog6
-rw-r--r--src/fileio.c161
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 @@
12013-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
12013-10-10 Eli Zaretskii <eliz@gnu.org> 72013-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. */
144static Lisp_Object Qdelete_directory; 144static Lisp_Object Qdelete_directory;
145 145
146static 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
1664those `/' is discarded. */) 1666those `/' 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);