| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: var.c,v 1.484 2020/09/02 06:25:48 rillig Exp $ */ | | 1 | /* $NetBSD: var.c,v 1.485 2020/09/03 18:19:15 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.484 2020/09/02 06:25:48 rillig Exp $"; | | 72 | static char rcsid[] = "$NetBSD: var.c,v 1.485 2020/09/03 18:19:15 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.484 2020/09/02 06:25:48 rillig Exp $"); | | 79 | __RCSID("$NetBSD: var.c,v 1.485 2020/09/03 18:19:15 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 | * |
| @@ -1669,35 +1669,36 @@ ParseModifierPart( | | | @@ -1669,35 +1669,36 @@ ParseModifierPart( |
1669 | continue; | | 1669 | continue; |
1670 | } | | 1670 | } |
1671 | | | 1671 | |
1672 | if (p[1] == delim) { /* Unescaped $ at end of pattern */ | | 1672 | if (p[1] == delim) { /* Unescaped $ at end of pattern */ |
1673 | if (out_pflags != NULL) | | 1673 | if (out_pflags != NULL) |
1674 | *out_pflags |= VARP_ANCHOR_END; | | 1674 | *out_pflags |= VARP_ANCHOR_END; |
1675 | else | | 1675 | else |
1676 | Buf_AddByte(&buf, *p); | | 1676 | Buf_AddByte(&buf, *p); |
1677 | p++; | | 1677 | p++; |
1678 | continue; | | 1678 | continue; |
1679 | } | | 1679 | } |
1680 | | | 1680 | |
1681 | if (eflags & VARE_WANTRES) { /* Nested variable, evaluated */ | | 1681 | if (eflags & VARE_WANTRES) { /* Nested variable, evaluated */ |
1682 | const char *cp2; | | 1682 | const char *nested_p = p; |
1683 | int len; | | 1683 | const char *nested_val; |
1684 | void *freeIt; | | 1684 | void *nested_val_freeIt; |
1685 | VarEvalFlags nested_eflags = eflags & ~(unsigned)VARE_ASSIGN; | | 1685 | VarEvalFlags nested_eflags = eflags & ~(unsigned)VARE_ASSIGN; |
1686 | | | 1686 | |
1687 | cp2 = Var_Parse(p, ctxt, nested_eflags, &len, &freeIt); | | 1687 | nested_val = Var_ParsePP(&nested_p, ctxt, nested_eflags, |
1688 | Buf_AddStr(&buf, cp2); | | 1688 | &nested_val_freeIt); |
1689 | free(freeIt); | | 1689 | Buf_AddStr(&buf, nested_val); |
1690 | p += len; | | 1690 | free(nested_val_freeIt); |
| | | 1691 | p += nested_p - p; |
1691 | continue; | | 1692 | continue; |
1692 | } | | 1693 | } |
1693 | | | 1694 | |
1694 | /* XXX: This whole block is very similar to Var_Parse without | | 1695 | /* XXX: This whole block is very similar to Var_Parse without |
1695 | * VARE_WANTRES. There may be subtle edge cases though that are | | 1696 | * VARE_WANTRES. There may be subtle edge cases though that are |
1696 | * not yet covered in the unit tests and that are parsed differently, | | 1697 | * not yet covered in the unit tests and that are parsed differently, |
1697 | * depending on whether they are evaluated or not. | | 1698 | * depending on whether they are evaluated or not. |
1698 | * | | 1699 | * |
1699 | * This subtle difference is not documented in the manual page, | | 1700 | * This subtle difference is not documented in the manual page, |
1700 | * neither is the difference between parsing :D and :M documented. | | 1701 | * neither is the difference between parsing :D and :M documented. |
1701 | * No code should ever depend on these details, but who knows. */ | | 1702 | * No code should ever depend on these details, but who knows. */ |
1702 | | | 1703 | |
1703 | varstart = p; /* Nested variable, only parsed */ | | 1704 | varstart = p; /* Nested variable, only parsed */ |
| @@ -3614,26 +3615,35 @@ Var_Parse(const char * const str, GNode | | | @@ -3614,26 +3615,35 @@ Var_Parse(const char * const str, GNode |
3614 | *freePtr = nstr; | | 3615 | *freePtr = nstr; |
3615 | } else { | | 3616 | } else { |
3616 | nstr = (eflags & VARE_UNDEFERR) ? var_Error : varNoError; | | 3617 | nstr = (eflags & VARE_UNDEFERR) ? var_Error : varNoError; |
3617 | } | | 3618 | } |
3618 | } | | 3619 | } |
3619 | if (nstr != Buf_GetAll(&v->val, NULL)) | | 3620 | if (nstr != Buf_GetAll(&v->val, NULL)) |
3620 | Buf_Destroy(&v->val, TRUE); | | 3621 | Buf_Destroy(&v->val, TRUE); |
3621 | free(v->name); | | 3622 | free(v->name); |
3622 | free(v); | | 3623 | free(v); |
3623 | } | | 3624 | } |
3624 | return nstr; | | 3625 | return nstr; |
3625 | } | | 3626 | } |
3626 | | | 3627 | |
| | | 3628 | const char * |
| | | 3629 | Var_ParsePP(const char **pp, GNode *ctxt, VarEvalFlags eflags, void **freePtr) |
| | | 3630 | { |
| | | 3631 | int len; |
| | | 3632 | const char *val = Var_Parse(*pp, ctxt, eflags, &len, freePtr); |
| | | 3633 | *pp += len; |
| | | 3634 | return val; |
| | | 3635 | } |
| | | 3636 | |
3627 | /* Substitute for all variables in the given string in the given context. | | 3637 | /* Substitute for all variables in the given string in the given context. |
3628 | * | | 3638 | * |
3629 | * If eflags & VARE_UNDEFERR, Parse_Error will be called when an undefined | | 3639 | * If eflags & VARE_UNDEFERR, Parse_Error will be called when an undefined |
3630 | * variable is encountered. | | 3640 | * variable is encountered. |
3631 | * | | 3641 | * |
3632 | * If eflags & VARE_WANTRES, any effects from the modifiers, such as ::=, | | 3642 | * If eflags & VARE_WANTRES, any effects from the modifiers, such as ::=, |
3633 | * :sh or !cmd! take place. | | 3643 | * :sh or !cmd! take place. |
3634 | * | | 3644 | * |
3635 | * Input: | | 3645 | * Input: |
3636 | * str the string which to substitute | | 3646 | * str the string which to substitute |
3637 | * ctxt the context wherein to find variables | | 3647 | * ctxt the context wherein to find variables |
3638 | * eflags VARE_UNDEFERR if undefineds are an error | | 3648 | * eflags VARE_UNDEFERR if undefineds are an error |
3639 | * VARE_WANTRES if we actually want the result | | 3649 | * VARE_WANTRES if we actually want the result |