| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: var.c,v 1.391 2020/08/02 09:36:54 rillig Exp $ */ | | 1 | /* $NetBSD: var.c,v 1.392 2020/08/02 09:43:22 rillig Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1988, 1989, 1990, 1993 | | 4 | * Copyright (c) 1988, 1989, 1990, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to Berkeley by | | 7 | * This code is derived from software contributed to Berkeley by |
8 | * Adam de Boor. | | 8 | * Adam de Boor. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -59,34 +59,34 @@ | | | @@ -59,34 +59,34 @@ |
59 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 59 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
60 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 60 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
61 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 61 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
62 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 62 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
63 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 63 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
64 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 64 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
65 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 65 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
66 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 66 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
67 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 67 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
68 | * SUCH DAMAGE. | | 68 | * SUCH DAMAGE. |
69 | */ | | 69 | */ |
70 | | | 70 | |
71 | #ifndef MAKE_NATIVE | | 71 | #ifndef MAKE_NATIVE |
72 | static char rcsid[] = "$NetBSD: var.c,v 1.391 2020/08/02 09:36:54 rillig Exp $"; | | 72 | static char rcsid[] = "$NetBSD: var.c,v 1.392 2020/08/02 09:43:22 rillig Exp $"; |
73 | #else | | 73 | #else |
74 | #include <sys/cdefs.h> | | 74 | #include <sys/cdefs.h> |
75 | #ifndef lint | | 75 | #ifndef lint |
76 | #if 0 | | 76 | #if 0 |
77 | static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94"; | | 77 | static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94"; |
78 | #else | | 78 | #else |
79 | __RCSID("$NetBSD: var.c,v 1.391 2020/08/02 09:36:54 rillig Exp $"); | | 79 | __RCSID("$NetBSD: var.c,v 1.392 2020/08/02 09:43:22 rillig Exp $"); |
80 | #endif | | 80 | #endif |
81 | #endif /* not lint */ | | 81 | #endif /* not lint */ |
82 | #endif | | 82 | #endif |
83 | | | 83 | |
84 | /*- | | 84 | /*- |
85 | * var.c -- | | 85 | * var.c -- |
86 | * Variable-handling functions | | 86 | * Variable-handling functions |
87 | * | | 87 | * |
88 | * Interface: | | 88 | * Interface: |
89 | * Var_Set Set the value of a variable in the given | | 89 | * Var_Set Set the value of a variable in the given |
90 | * context. The variable is created if it doesn't | | 90 | * context. The variable is created if it doesn't |
91 | * yet exist. | | 91 | * yet exist. |
92 | * | | 92 | * |
| @@ -1721,124 +1721,124 @@ VarUniq(const char *str) | | | @@ -1721,124 +1721,124 @@ VarUniq(const char *str) |
1721 | } | | 1721 | } |
1722 | | | 1722 | |
1723 | | | 1723 | |
1724 | /*- | | 1724 | /*- |
1725 | * Parse a text part of a modifier such as the "from" and "to" in :S/from/to/ | | 1725 | * Parse a text part of a modifier such as the "from" and "to" in :S/from/to/ |
1726 | * or the :@ modifier, until the next unescaped delimiter. The delimiter, as | | 1726 | * or the :@ modifier, until the next unescaped delimiter. The delimiter, as |
1727 | * well as the backslash or the dollar, can be escaped with a backslash. | | 1727 | * well as the backslash or the dollar, can be escaped with a backslash. |
1728 | * | | 1728 | * |
1729 | * Return the parsed (and possibly expanded) string, or NULL if no delimiter | | 1729 | * Return the parsed (and possibly expanded) string, or NULL if no delimiter |
1730 | * was found. | | 1730 | * was found. |
1731 | */ | | 1731 | */ |
1732 | static char * | | 1732 | static char * |
1733 | ParseModifierPart( | | 1733 | ParseModifierPart( |
1734 | const char **tstr, /* The parsing position, updated upon return */ | | 1734 | const char **pp, /* The parsing position, updated upon return */ |
1735 | int delim, /* Parsing stops at this delimiter */ | | 1735 | int delim, /* Parsing stops at this delimiter */ |
1736 | VarEvalFlags eflags, /* Flags for evaluating nested variables; | | 1736 | VarEvalFlags eflags, /* Flags for evaluating nested variables; |
1737 | * if VARE_WANTRES is not set, the text is | | 1737 | * if VARE_WANTRES is not set, the text is |
1738 | * only parsed */ | | 1738 | * only parsed */ |
1739 | GNode *ctxt, /* For looking up nested variables */ | | 1739 | GNode *ctxt, /* For looking up nested variables */ |
1740 | size_t *out_length, /* Optionally stores the length of the returned | | 1740 | size_t *out_length, /* Optionally stores the length of the returned |
1741 | * string, just to save another strlen call. */ | | 1741 | * string, just to save another strlen call. */ |
1742 | VarPatternFlags *out_pflags,/* For the first part of the :S modifier, | | 1742 | VarPatternFlags *out_pflags,/* For the first part of the :S modifier, |
1743 | * sets the VARP_ANCHOR_END flag if the last | | 1743 | * sets the VARP_ANCHOR_END flag if the last |
1744 | * character of the pattern is a $. */ | | 1744 | * character of the pattern is a $. */ |
1745 | ModifyWord_SubstArgs *subst /* For the second part of the :S modifier, | | 1745 | ModifyWord_SubstArgs *subst /* For the second part of the :S modifier, |
1746 | * allow ampersands to be escaped and replace | | 1746 | * allow ampersands to be escaped and replace |
1747 | * unescaped ampersands with subst->lhs. */ | | 1747 | * unescaped ampersands with subst->lhs. */ |
1748 | ) { | | 1748 | ) { |
1749 | const char *cp; | | | |
1750 | char *rstr; | | 1749 | char *rstr; |
1751 | Buffer buf; | | 1750 | Buffer buf; |
1752 | VarEvalFlags errnum = eflags & VARE_UNDEFERR; | | 1751 | VarEvalFlags errnum = eflags & VARE_UNDEFERR; |
1753 | | | 1752 | |
1754 | Buf_InitZ(&buf, 0); | | 1753 | Buf_InitZ(&buf, 0); |
1755 | | | 1754 | |
1756 | /* | | 1755 | /* |
1757 | * Skim through until the matching delimiter is found; | | 1756 | * Skim through until the matching delimiter is found; |
1758 | * pick up variable substitutions on the way. Also allow | | 1757 | * pick up variable substitutions on the way. Also allow |
1759 | * backslashes to quote the delimiter, $, and \, but don't | | 1758 | * backslashes to quote the delimiter, $, and \, but don't |
1760 | * touch other backslashes. | | 1759 | * touch other backslashes. |
1761 | */ | | 1760 | */ |
1762 | for (cp = *tstr; *cp != '\0' && *cp != delim; cp++) { | | 1761 | const char *p; |
1763 | Boolean is_escaped = cp[0] == '\\' && ( | | 1762 | for (p = *pp; *p != '\0' && *p != delim; p++) { |
1764 | cp[1] == delim || cp[1] == '\\' || cp[1] == '$' || | | 1763 | Boolean is_escaped = p[0] == '\\' && ( |
1765 | (cp[1] == '&' && subst != NULL)); | | 1764 | p[1] == delim || p[1] == '\\' || p[1] == '$' || |
| | | 1765 | (p[1] == '&' && subst != NULL)); |
1766 | if (is_escaped) { | | 1766 | if (is_escaped) { |
1767 | Buf_AddByte(&buf, cp[1]); | | 1767 | Buf_AddByte(&buf, p[1]); |
1768 | cp++; | | 1768 | p++; |
1769 | continue; | | 1769 | continue; |
1770 | } | | 1770 | } |
1771 | | | 1771 | |
1772 | if (*cp != '$') { /* Unescaped, simple text */ | | 1772 | if (*p != '$') { /* Unescaped, simple text */ |
1773 | if (subst != NULL && *cp == '&') | | 1773 | if (subst != NULL && *p == '&') |
1774 | Buf_AddBytesZ(&buf, subst->lhs, subst->lhsLen); | | 1774 | Buf_AddBytesZ(&buf, subst->lhs, subst->lhsLen); |
1775 | else | | 1775 | else |
1776 | Buf_AddByte(&buf, *cp); | | 1776 | Buf_AddByte(&buf, *p); |
1777 | continue; | | 1777 | continue; |
1778 | } | | 1778 | } |
1779 | | | 1779 | |
1780 | if (cp[1] == delim) { /* Unescaped $ at end of pattern */ | | 1780 | if (p[1] == delim) { /* Unescaped $ at end of pattern */ |
1781 | if (out_pflags != NULL) | | 1781 | if (out_pflags != NULL) |
1782 | *out_pflags |= VARP_ANCHOR_END; | | 1782 | *out_pflags |= VARP_ANCHOR_END; |
1783 | else | | 1783 | else |
1784 | Buf_AddByte(&buf, *cp); | | 1784 | Buf_AddByte(&buf, *p); |
1785 | continue; | | 1785 | continue; |
1786 | } | | 1786 | } |
1787 | | | 1787 | |
1788 | if (eflags & VARE_WANTRES) { /* Nested variable, evaluated */ | | 1788 | if (eflags & VARE_WANTRES) { /* Nested variable, evaluated */ |
1789 | const char *cp2; | | 1789 | const char *cp2; |
1790 | int len; | | 1790 | int len; |
1791 | void *freeIt; | | 1791 | void *freeIt; |
1792 | | | 1792 | |
1793 | cp2 = Var_Parse(cp, ctxt, errnum | (eflags & VARE_WANTRES), | | 1793 | cp2 = Var_Parse(p, ctxt, errnum | (eflags & VARE_WANTRES), |
1794 | &len, &freeIt); | | 1794 | &len, &freeIt); |
1795 | Buf_AddStr(&buf, cp2); | | 1795 | Buf_AddStr(&buf, cp2); |
1796 | free(freeIt); | | 1796 | free(freeIt); |
1797 | cp += len - 1; | | 1797 | p += len - 1; |
1798 | continue; | | 1798 | continue; |
1799 | } | | 1799 | } |
1800 | | | 1800 | |
1801 | const char *cp2 = &cp[1]; /* Nested variable, only parsed */ | | 1801 | const char *cp2 = &p[1]; /* Nested variable, only parsed */ |
1802 | if (*cp2 == PROPEN || *cp2 == BROPEN) { | | 1802 | if (*cp2 == PROPEN || *cp2 == BROPEN) { |
1803 | /* | | 1803 | /* |
1804 | * Find the end of this variable reference | | 1804 | * Find the end of this variable reference |
1805 | * and suck it in without further ado. | | 1805 | * and suck it in without further ado. |
1806 | * It will be interpreted later. | | 1806 | * It will be interpreted later. |
1807 | */ | | 1807 | */ |
1808 | int have = *cp2; | | 1808 | int have = *cp2; |
1809 | int want = *cp2 == PROPEN ? PRCLOSE : BRCLOSE; | | 1809 | int want = *cp2 == PROPEN ? PRCLOSE : BRCLOSE; |
1810 | int depth = 1; | | 1810 | int depth = 1; |
1811 | | | 1811 | |
1812 | for (++cp2; *cp2 != '\0' && depth > 0; ++cp2) { | | 1812 | for (++cp2; *cp2 != '\0' && depth > 0; ++cp2) { |
1813 | if (cp2[-1] != '\\') { | | 1813 | if (cp2[-1] != '\\') { |
1814 | if (*cp2 == have) | | 1814 | if (*cp2 == have) |
1815 | ++depth; | | 1815 | ++depth; |
1816 | if (*cp2 == want) | | 1816 | if (*cp2 == want) |
1817 | --depth; | | 1817 | --depth; |
1818 | } | | 1818 | } |
1819 | } | | 1819 | } |
1820 | Buf_AddBytesBetween(&buf, cp, cp2); | | 1820 | Buf_AddBytesBetween(&buf, p, cp2); |
1821 | cp = --cp2; | | 1821 | p = --cp2; |
1822 | } else | | 1822 | } else |
1823 | Buf_AddByte(&buf, *cp); | | 1823 | Buf_AddByte(&buf, *p); |
1824 | } | | 1824 | } |
1825 | | | 1825 | |
1826 | if (*cp != delim) { | | 1826 | if (*p != delim) { |
1827 | *tstr = cp; | | 1827 | *pp = p; |
1828 | return NULL; | | 1828 | return NULL; |
1829 | } | | 1829 | } |
1830 | | | 1830 | |
1831 | *tstr = ++cp; | | 1831 | *pp = ++p; |
1832 | if (out_length != NULL) | | 1832 | if (out_length != NULL) |
1833 | *out_length = Buf_Size(&buf); | | 1833 | *out_length = Buf_Size(&buf); |
1834 | rstr = Buf_Destroy(&buf, FALSE); | | 1834 | rstr = Buf_Destroy(&buf, FALSE); |
1835 | if (DEBUG(VAR)) | | 1835 | if (DEBUG(VAR)) |
1836 | fprintf(debug_file, "Modifier part: \"%s\"\n", rstr); | | 1836 | fprintf(debug_file, "Modifier part: \"%s\"\n", rstr); |
1837 | return rstr; | | 1837 | return rstr; |
1838 | } | | 1838 | } |
1839 | | | 1839 | |
1840 | /*- | | 1840 | /*- |
1841 | *----------------------------------------------------------------------- | | 1841 | *----------------------------------------------------------------------- |
1842 | * VarQuote -- | | 1842 | * VarQuote -- |
1843 | * Quote shell meta-characters and space characters in the string | | 1843 | * Quote shell meta-characters and space characters in the string |
1844 | * if quoteDollar is set, also quote and double any '$' characters. | | 1844 | * if quoteDollar is set, also quote and double any '$' characters. |