aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2013-10-10 17:42:38 -0400
committerStefan Monnier2013-10-10 17:42:38 -0400
commitee041f2d07b6ed485dc34c115588f973f046c9d4 (patch)
tree8152e54e2d2552d52629c7455837f85d07ee9503
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.
-rw-r--r--lisp/ChangeLog5
-rw-r--r--lisp/env.el30
-rw-r--r--src/ChangeLog6
-rw-r--r--src/fileio.c161
4 files changed, 57 insertions, 145 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index a06055ddb9b..1a312606ee0 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,8 @@
12013-10-10 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * env.el (substitute-env-in-file-name): New function.
4 (substitute-env-vars): Extend the meaning of the optional arg.
5
12013-10-10 Eli Zaretskii <eliz@gnu.org> 62013-10-10 Eli Zaretskii <eliz@gnu.org>
2 7
3 * term/w32-win.el (dynamic-library-alist): Define separate lists 8 * term/w32-win.el (dynamic-library-alist): Define separate lists
diff --git a/lisp/env.el b/lisp/env.el
index 5618404cb67..044673d5e68 100644
--- a/lisp/env.el
+++ b/lisp/env.el
@@ -1,4 +1,4 @@
1;;; env.el --- functions to manipulate environment variables 1;;; env.el --- functions to manipulate environment variables -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 1991, 1994, 2000-2013 Free Software Foundation, Inc. 3;; Copyright (C) 1991, 1994, 2000-2013 Free Software Foundation, Inc.
4 4
@@ -60,30 +60,46 @@ If it is also not t, RET does not exit if it does non-null completion."
60(defconst env--substitute-vars-regexp 60(defconst env--substitute-vars-regexp
61 "\\$\\(?:\\(?1:[[:alnum:]_]+\\)\\|{\\(?1:[^{}]+\\)}\\|\\$\\)") 61 "\\$\\(?:\\(?1:[[:alnum:]_]+\\)\\|{\\(?1:[^{}]+\\)}\\|\\$\\)")
62 62
63(defun substitute-env-vars (string &optional only-defined) 63(defun substitute-env-vars (string &optional when-undefined)
64 "Substitute environment variables referred to in STRING. 64 "Substitute environment variables referred to in STRING.
65`$FOO' where FOO is an environment variable name means to substitute 65`$FOO' where FOO is an environment variable name means to substitute
66the value of that variable. The variable name should be terminated 66the value of that variable. The variable name should be terminated
67with a character not a letter, digit or underscore; otherwise, enclose 67with a character not a letter, digit or underscore; otherwise, enclose
68the entire variable name in braces. For instance, in `ab$cd-x', 68the entire variable name in braces. For instance, in `ab$cd-x',
69`$cd' is treated as an environment variable. 69`$cd' is treated as an environment variable.
70If ONLY-DEFINED is nil, references to undefined environment variables 70
71are replaced by the empty string; if it is non-nil, they are left unchanged. 71If WHEN-DEFINED is nil, references to undefined environment variables
72are replaced by the empty string; if it is a function, the function is called
73with the variable name as argument and should return the text with which
74to replace it or nil to leave it unchanged.
75If it is non-nil and not a function, references to undefined variables are
76left unchanged.
72 77
73Use `$$' to insert a single dollar sign." 78Use `$$' to insert a single dollar sign."
74 (let ((start 0)) 79 (let ((start 0))
75 (while (string-match env--substitute-vars-regexp string start) 80 (while (string-match env--substitute-vars-regexp string start)
76 (cond ((match-beginning 1) 81 (cond ((match-beginning 1)
77 (let ((value (getenv (match-string 1 string)))) 82 (let* ((var (match-string 1 string))
78 (if (and (null value) only-defined) 83 (value (getenv var)))
84 (if (and (null value)
85 (if (functionp when-undefined)
86 (null (setq value (funcall when-undefined var)))
87 when-undefined))
79 (setq start (match-end 0)) 88 (setq start (match-end 0))
80 (setq string (replace-match (or value "") t t string) 89 (setq string (replace-match (or value "") t t string)
81 start (+ (match-beginning 0) (length value)))))) 90 start (+ (match-beginning 0) (length value))))))
82 (t 91 (t
83 (setq string (replace-match "$" t t string) 92 (setq string (replace-match "$" t t string)
84 start (+ (match-beginning 0) 1))))) 93 start (+ (match-beginning 0) 1)))))
85 string)) 94 string))
86 95
96(defun substitute-env-in-file-name (filename)
97 (substitute-env-vars filename
98 ;; How 'bout we lookup other tables than the env?
99 ;; E.g. we could accept bookmark names as well!
100 (if (memq system-type '(windows-nt ms-dos))
101 (lambda (var) (getenv (upcase var)))
102 t)))
87 103
88(defun setenv-internal (env variable value keep-empty) 104(defun setenv-internal (env variable value keep-empty)
89 "Set VARIABLE to VALUE in ENV, adding empty entries if KEEP-EMPTY. 105 "Set VARIABLE to VALUE in ENV, adding empty entries if KEEP-EMPTY.
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);