comparison src/fileio.c @ 4324:5e526366d533

Don't error on unknown environment variables, #'substitute-in-file-name. SUPERSEDES 18270.47509.666061.606519@parhasard.net APPROVE COMMIT src/fileio.c addition: 2007-12-11 Aidan Kehoe <kehoea@parhasard.net> * fileio.c (Fsubstitute_in_file_name): On encountering non-existent environment variables or incorrect syntax for specifying environment variables (as is routine on Windows) don't error, instead pass the original strings through. tests/ChangeLog addition: 2007-12-11 Aidan Kehoe <kehoea@parhasard.net> * automated/syntax-tests.el: Check that substitute-in-file-name doesn't error when handed non-existing environment variables, passing through the specified string instead. Also check that existing environment variables are correctly substituted. Also check that double slashes in the middle of a path name are treated as re-starting the path.
author Aidan Kehoe <kehoea@parhasard.net>
date Tue, 11 Dec 2007 21:50:22 +0100
parents c5a2b80bc4fa
children 1e04b9c8125b
comparison
equal deleted inserted replaced
4323:94509abd0ef0 4324:5e526366d533
1516 (filename)) 1516 (filename))
1517 { 1517 {
1518 /* This function can GC. GC checked 2000-07-28 ben. */ 1518 /* This function can GC. GC checked 2000-07-28 ben. */
1519 Ibyte *nm; 1519 Ibyte *nm;
1520 1520
1521 Ibyte *s, *p, *o, *x, *endp; 1521 Ibyte *s, *p, *o, *x, *endp, *got;
1522 Ibyte *target = 0; 1522 Ibyte *target = 0;
1523 int total = 0; 1523 int total = 0;
1524 int substituted = 0; 1524 int substituted = 0, seen_braces;
1525 Ibyte *xnm; 1525 Ibyte *xnm;
1526 Lisp_Object handler; 1526 Lisp_Object handler;
1527 1527
1528 CHECK_STRING (filename); 1528 CHECK_STRING (filename);
1529 1529
1574 p++; 1574 p++;
1575 else 1575 else
1576 { 1576 {
1577 p++; 1577 p++;
1578 if (p == endp) 1578 if (p == endp)
1579 goto badsubst; 1579 {
1580 /* No substitution, no error. */
1581 break;
1582 }
1580 else if (*p == '$') 1583 else if (*p == '$')
1581 { 1584 {
1582 /* "$$" means a single "$" */ 1585 /* "$$" means a single "$" */
1583 p++; 1586 p++;
1584 total -= 1; 1587 total -= 1;
1587 } 1590 }
1588 else if (*p == '{') 1591 else if (*p == '{')
1589 { 1592 {
1590 o = ++p; 1593 o = ++p;
1591 while (p != endp && *p != '}') p++; 1594 while (p != endp && *p != '}') p++;
1592 if (*p != '}') goto missingclose; 1595 if (*p != '}')
1596 {
1597 /* No substitution, no error. Keep looking. */
1598 p = o;
1599 continue;
1600 }
1593 s = p; 1601 s = p;
1594 } 1602 }
1595 else 1603 else
1596 { 1604 {
1597 o = p; 1605 o = p;
1606 #ifdef WIN32_NATIVE 1614 #ifdef WIN32_NATIVE
1607 qxestrupr (target); /* $home == $HOME etc. */ 1615 qxestrupr (target); /* $home == $HOME etc. */
1608 #endif /* WIN32_NATIVE */ 1616 #endif /* WIN32_NATIVE */
1609 1617
1610 /* Get variable value */ 1618 /* Get variable value */
1611 o = egetenv ((CIbyte *) target); 1619 got = egetenv ((CIbyte *) target);
1612 if (!o) goto badvar; 1620 if (got)
1613 total += qxestrlen (o); 1621 {
1614 substituted = 1; 1622 total += qxestrlen (got);
1623 substituted = 1;
1624 }
1615 } 1625 }
1616 1626
1617 if (!substituted) 1627 if (!substituted)
1618 return filename; 1628 return filename;
1619 1629
1627 if (*p != '$') 1637 if (*p != '$')
1628 *x++ = *p++; 1638 *x++ = *p++;
1629 else 1639 else
1630 { 1640 {
1631 p++; 1641 p++;
1642 seen_braces = 0;
1632 if (p == endp) 1643 if (p == endp)
1633 goto badsubst; 1644 {
1645 *x++ = '$';
1646 break;
1647 }
1634 else if (*p == '$') 1648 else if (*p == '$')
1635 { 1649 {
1636 *x++ = *p++; 1650 *x++ = *p++;
1637 continue; 1651 continue;
1638 } 1652 }
1639 else if (*p == '{') 1653 else if (*p == '{')
1640 { 1654 {
1655 seen_braces = 1;
1641 o = ++p; 1656 o = ++p;
1642 while (p != endp && *p != '}') p++; 1657 while (p != endp && *p != '}') p++;
1643 if (*p != '}') goto missingclose; 1658 if (*p != '}')
1659 {
1660 /* Don't syntax error, don't substitute */
1661 *x++ = '{';
1662 p = o;
1663 continue;
1664 }
1644 s = p++; 1665 s = p++;
1645 } 1666 }
1646 else 1667 else
1647 { 1668 {
1648 o = p; 1669 o = p;
1657 #ifdef WIN32_NATIVE 1678 #ifdef WIN32_NATIVE
1658 qxestrupr (target); /* $home == $HOME etc. */ 1679 qxestrupr (target); /* $home == $HOME etc. */
1659 #endif /* WIN32_NATIVE */ 1680 #endif /* WIN32_NATIVE */
1660 1681
1661 /* Get variable value */ 1682 /* Get variable value */
1662 o = egetenv ((CIbyte *) target); 1683 got = egetenv ((CIbyte *) target);
1663 if (!o) 1684 if (got)
1664 goto badvar; 1685 {
1665 1686 qxestrcpy (x, got);
1666 qxestrcpy (x, o); 1687 x += qxestrlen (got);
1667 x += qxestrlen (o); 1688 }
1689 else
1690 {
1691 *x++ = '$';
1692 if (seen_braces)
1693 {
1694 *x++ = '{';
1695 /* Preserve the original case. */
1696 qxestrncpy (x, o, s - o);
1697 x += s - o;
1698 *x++ = '}';
1699 }
1700 else
1701 {
1702 /* Preserve the original case. */
1703 qxestrncpy (x, o, s - o);
1704 x += s - o;
1705 }
1706 }
1668 } 1707 }
1669 1708
1670 *x = 0; 1709 *x = 0;
1671 1710
1672 /* If /~ or // appears, discard everything through first slash. */ 1711 /* If /~ or // appears, discard everything through first slash. */
1687 && p > nm && IS_DIRECTORY_SEP (p[-1])) 1726 && p > nm && IS_DIRECTORY_SEP (p[-1]))
1688 xnm = p; 1727 xnm = p;
1689 #endif 1728 #endif
1690 1729
1691 return make_string (xnm, x - xnm); 1730 return make_string (xnm, x - xnm);
1692
1693 badsubst:
1694 syntax_error ("Bad format environment-variable substitution", filename);
1695 missingclose:
1696 syntax_error ("Missing \"}\" in environment-variable substitution",
1697 filename);
1698 badvar:
1699 syntax_error_2 ("Substituting nonexistent environment variable",
1700 filename, build_intstring (target));
1701
1702 RETURN_NOT_REACHED (Qnil);
1703 } 1731 }
1704 1732
1705 /* A slightly faster and more convenient way to get 1733 /* A slightly faster and more convenient way to get
1706 (directory-file-name (expand-file-name FOO)). */ 1734 (directory-file-name (expand-file-name FOO)). */
1707 1735