aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Rumney2009-03-24 14:14:53 +0000
committerJason Rumney2009-03-24 14:14:53 +0000
commit58aec0d679ff3c5f56ea384702f9a23fecccfe33 (patch)
tree748208a0b9fae639fbd17f5597e221513d910172
parent5e5b7cb12c7caf9a4d6cd996372dc925aedf8e82 (diff)
downloademacs-58aec0d679ff3c5f56ea384702f9a23fecccfe33.tar.gz
emacs-58aec0d679ff3c5f56ea384702f9a23fecccfe33.zip
(Fsubstitute_in_file_name): Always work on a copy.
Calculate total size precisely. Decode environment variables before substituting. (Bug#38)
-rw-r--r--src/ChangeLog6
-rw-r--r--src/fileio.c53
2 files changed, 39 insertions, 20 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 7389c561f82..dc0fbd183d1 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,9 @@
12009-03-24 Jason Rumney <jasonr@gnu.org>
2
3 * fileio.c (Fsubstitute_in_file_name): Always work on a copy.
4 Calculate total size precisely. Decode environment variables
5 before substituting. (Bug#38)
6
12009-03-24 Kenichi Handa <handa@m17n.org> 72009-03-24 Kenichi Handa <handa@m17n.org>
2 8
3 * font.c (find_font_encoding): Return Qnil for unsupported 9 * font.c (find_font_encoding): Return Qnil for unsupported
diff --git a/src/fileio.c b/src/fileio.c
index ae64be4ba03..4f3573b02d7 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -1629,11 +1629,14 @@ those `/' is discarded. */)
1629 unsigned char *target = NULL; 1629 unsigned char *target = NULL;
1630 int total = 0; 1630 int total = 0;
1631 int substituted = 0; 1631 int substituted = 0;
1632 int multibyte;
1632 unsigned char *xnm; 1633 unsigned char *xnm;
1633 Lisp_Object handler; 1634 Lisp_Object handler;
1634 1635
1635 CHECK_STRING (filename); 1636 CHECK_STRING (filename);
1636 1637
1638 multibyte = STRING_MULTIBYTE (filename);
1639
1637 /* If the file name has special constructs in it, 1640 /* If the file name has special constructs in it,
1638 call the corresponding file handler. */ 1641 call the corresponding file handler. */
1639 handler = Ffind_file_name_handler (filename, Qsubstitute_in_file_name); 1642 handler = Ffind_file_name_handler (filename, Qsubstitute_in_file_name);
@@ -1641,8 +1644,11 @@ those `/' is discarded. */)
1641 return call2 (handler, Qsubstitute_in_file_name, filename); 1644 return call2 (handler, Qsubstitute_in_file_name, filename);
1642 1645
1643 nm = SDATA (filename); 1646 nm = SDATA (filename);
1644#ifdef DOS_NT 1647 /* Always work on a copy of the string, in case GC happens during
1648 decode of environment variables, causing the original Lisp_String
1649 data to be relocated. */
1645 nm = strcpy (alloca (strlen (nm) + 1), nm); 1650 nm = strcpy (alloca (strlen (nm) + 1), nm);
1651#ifdef DOS_NT
1646 CORRECT_DIR_SEPS (nm); 1652 CORRECT_DIR_SEPS (nm);
1647 substituted = (strcmp (nm, SDATA (filename)) != 0); 1653 substituted = (strcmp (nm, SDATA (filename)) != 0);
1648#endif 1654#endif
@@ -1655,9 +1661,7 @@ those `/' is discarded. */)
1655 again. Important with filenames like "/home/foo//:/hello///there" 1661 again. Important with filenames like "/home/foo//:/hello///there"
1656 which whould substitute to "/:/hello///there" rather than "/there". */ 1662 which whould substitute to "/:/hello///there" rather than "/there". */
1657 return Fsubstitute_in_file_name 1663 return Fsubstitute_in_file_name
1658 (make_specified_string (p, -1, endp - p, 1664 (make_specified_string (p, -1, endp - p, multibyte));
1659 STRING_MULTIBYTE (filename)));
1660
1661 1665
1662 /* See if any variables are substituted into the string 1666 /* See if any variables are substituted into the string
1663 and find the total length of their values in `total' */ 1667 and find the total length of their values in `total' */
@@ -1703,8 +1707,16 @@ those `/' is discarded. */)
1703 /* Get variable value */ 1707 /* Get variable value */
1704 o = (unsigned char *) egetenv (target); 1708 o = (unsigned char *) egetenv (target);
1705 if (o) 1709 if (o)
1706 { /* Eight-bit chars occupy upto 2 bytes in multibyte. */ 1710 {
1707 total += strlen (o) * (STRING_MULTIBYTE (filename) ? 2 : 1); 1711 /* Don't try to guess a maximum length - UTF8 can use up to
1712 four bytes per character. This code is unlikely to run
1713 in a situation that requires performance, so decoding the
1714 env variables twice should be acceptable. Note that
1715 decoding may cause a garbage collect. */
1716 Lisp_Object orig, decoded;
1717 orig = make_unibyte_string (o, strlen (o));
1718 decoded = DECODE_FILE (orig);
1719 total += SBYTES (decoded);
1708 substituted = 1; 1720 substituted = 1;
1709 } 1721 }
1710 else if (*p == '}') 1722 else if (*p == '}')
@@ -1762,21 +1774,22 @@ those `/' is discarded. */)
1762 *x++ = '$'; 1774 *x++ = '$';
1763 strcpy (x, target); x+= strlen (target); 1775 strcpy (x, target); x+= strlen (target);
1764 } 1776 }
1765 else if (STRING_MULTIBYTE (filename))
1766 {
1767 /* If the original string is multibyte,
1768 convert what we substitute into multibyte. */
1769 while (*o)
1770 {
1771 int c = *o++;
1772 c = unibyte_char_to_multibyte (c);
1773 x += CHAR_STRING (c, x);
1774 }
1775 }
1776 else 1777 else
1777 { 1778 {
1778 strcpy (x, o); 1779 Lisp_Object orig, decoded;
1779 x += strlen (o); 1780 int orig_length, decoded_length;
1781 orig_length = strlen (o);
1782 orig = make_unibyte_string (o, orig_length);
1783 decoded = DECODE_FILE (orig);
1784 decoded_length = SBYTES (decoded);
1785 strncpy (x, SDATA (decoded), decoded_length);
1786 x += decoded_length;
1787
1788 /* If environment variable needed decoding, return value
1789 needs to be multibyte. */
1790 if (decoded_length != orig_length
1791 || strncmp (SDATA (decoded), o, orig_length))
1792 multibyte = 1;
1780 } 1793 }
1781 } 1794 }
1782 1795
@@ -1789,7 +1802,7 @@ those `/' is discarded. */)
1789 need to quote some $ to $$ first. */ 1802 need to quote some $ to $$ first. */
1790 xnm = p; 1803 xnm = p;
1791 1804
1792 return make_specified_string (xnm, -1, x - xnm, STRING_MULTIBYTE (filename)); 1805 return make_specified_string (xnm, -1, x - xnm, multibyte);
1793 1806
1794 badsubst: 1807 badsubst:
1795 error ("Bad format environment-variable substitution"); 1808 error ("Bad format environment-variable substitution");