| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: var.c,v 1.354 2020/07/29 19:48:33 rillig Exp $ */ | | 1 | /* $NetBSD: var.c,v 1.355 2020/07/29 20:33:38 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.354 2020/07/29 19:48:33 rillig Exp $"; | | 72 | static char rcsid[] = "$NetBSD: var.c,v 1.355 2020/07/29 20:33:38 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.354 2020/07/29 19:48:33 rillig Exp $"); | | 79 | __RCSID("$NetBSD: var.c,v 1.355 2020/07/29 20:33:38 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 | * |
| @@ -2565,27 +2565,27 @@ ApplyModifier_ToSep(const char *sep, App | | | @@ -2565,27 +2565,27 @@ ApplyModifier_ToSep(const char *sep, App |
2565 | } else { | | 2565 | } else { |
2566 | return FALSE; /* Found ":ts<unrecognised><unrecognised>". */ | | 2566 | return FALSE; /* Found ":ts<unrecognised><unrecognised>". */ |
2567 | } | | 2567 | } |
2568 | | | 2568 | |
2569 | st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->val, | | 2569 | st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->val, |
2570 | ModifyWord_Copy, NULL); | | 2570 | ModifyWord_Copy, NULL); |
2571 | return TRUE; | | 2571 | return TRUE; |
2572 | } | | 2572 | } |
2573 | | | 2573 | |
2574 | /* :tA, :tu, :tl, :ts<separator>, etc. */ | | 2574 | /* :tA, :tu, :tl, :ts<separator>, etc. */ |
2575 | static Boolean | | 2575 | static Boolean |
2576 | ApplyModifier_To(const char *mod, ApplyModifiersState *st) | | 2576 | ApplyModifier_To(const char *mod, ApplyModifiersState *st) |
2577 | { | | 2577 | { |
2578 | st->next = mod + 1; /* make sure it is set */ | | 2578 | st->next = mod + 1; /* make sure it is set */ |
2579 | if (mod[1] == st->endc || mod[1] == ':') | | 2579 | if (mod[1] == st->endc || mod[1] == ':') |
2580 | return FALSE; /* Found ":t<endc>" or ":t:". */ | | 2580 | return FALSE; /* Found ":t<endc>" or ":t:". */ |
2581 | | | 2581 | |
2582 | if (mod[1] == 's') | | 2582 | if (mod[1] == 's') |
2583 | return ApplyModifier_ToSep(mod + 2, st); | | 2583 | return ApplyModifier_ToSep(mod + 2, st); |
2584 | | | 2584 | |
2585 | if (mod[2] != st->endc && mod[2] != ':') | | 2585 | if (mod[2] != st->endc && mod[2] != ':') |
2586 | return FALSE; /* Found ":t<unrecognised><unrecognised>". */ | | 2586 | return FALSE; /* Found ":t<unrecognised><unrecognised>". */ |
2587 | | | 2587 | |
2588 | /* Check for two-character options: ":tu", ":tl" */ | | 2588 | /* Check for two-character options: ":tu", ":tl" */ |
2589 | if (mod[1] == 'A') { /* absolute path */ | | 2589 | if (mod[1] == 'A') { /* absolute path */ |
2590 | st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->val, | | 2590 | st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->val, |
2591 | ModifyWord_Realpath, NULL); | | 2591 | ModifyWord_Realpath, NULL); |
| @@ -2808,28 +2808,30 @@ ApplyModifier_IfElse(const char *mod, Ap | | | @@ -2808,28 +2808,30 @@ ApplyModifier_IfElse(const char *mod, Ap |
2808 | * variable. | | 2808 | * variable. |
2809 | */ | | 2809 | */ |
2810 | static int | | 2810 | static int |
2811 | ApplyModifier_Assign(const char *mod, ApplyModifiersState *st) | | 2811 | ApplyModifier_Assign(const char *mod, ApplyModifiersState *st) |
2812 | { | | 2812 | { |
2813 | const char *op = mod + 1; | | 2813 | const char *op = mod + 1; |
2814 | if (!(op[0] == '=' || | | 2814 | if (!(op[0] == '=' || |
2815 | (op[1] == '=' && | | 2815 | (op[1] == '=' && |
2816 | (op[0] == '!' || op[0] == '+' || op[0] == '?')))) | | 2816 | (op[0] == '!' || op[0] == '+' || op[0] == '?')))) |
2817 | return 'd'; /* "::<unrecognised>" */ | | 2817 | return 'd'; /* "::<unrecognised>" */ |
2818 | | | 2818 | |
2819 | GNode *v_ctxt; /* context where v belongs */ | | 2819 | GNode *v_ctxt; /* context where v belongs */ |
2820 | | | 2820 | |
2821 | if (st->v->name[0] == 0) | | 2821 | if (st->v->name[0] == 0) { |
| | | 2822 | st->next = mod + 1; |
2822 | return 'b'; | | 2823 | return 'b'; |
| | | 2824 | } |
2823 | | | 2825 | |
2824 | v_ctxt = st->ctxt; | | 2826 | v_ctxt = st->ctxt; |
2825 | char *sv_name = NULL; | | 2827 | char *sv_name = NULL; |
2826 | if (st->v->flags & VAR_JUNK) { | | 2828 | if (st->v->flags & VAR_JUNK) { |
2827 | /* | | 2829 | /* |
2828 | * We need to bmake_strdup() it incase ParseModifierPart() recurses. | | 2830 | * We need to bmake_strdup() it incase ParseModifierPart() recurses. |
2829 | */ | | 2831 | */ |
2830 | sv_name = st->v->name; | | 2832 | sv_name = st->v->name; |
2831 | st->v->name = bmake_strdup(st->v->name); | | 2833 | st->v->name = bmake_strdup(st->v->name); |
2832 | } else if (st->ctxt != VAR_GLOBAL) { | | 2834 | } else if (st->ctxt != VAR_GLOBAL) { |
2833 | Var *gv = VarFind(st->v->name, st->ctxt, 0); | | 2835 | Var *gv = VarFind(st->v->name, st->ctxt, 0); |
2834 | if (gv == NULL) | | 2836 | if (gv == NULL) |
2835 | v_ctxt = VAR_GLOBAL; | | 2837 | v_ctxt = VAR_GLOBAL; |
| @@ -3107,26 +3109,27 @@ ApplyModifiers(char *val, const char * c | | | @@ -3107,26 +3109,27 @@ ApplyModifiers(char *val, const char * c |
3107 | Error("Unclosed variable specification after complex " | | 3109 | Error("Unclosed variable specification after complex " |
3108 | "modifier (expecting '%c') for %s", st.endc, st.v->name); | | 3110 | "modifier (expecting '%c') for %s", st.endc, st.v->name); |
3109 | goto out; | | 3111 | goto out; |
3110 | } | | 3112 | } |
3111 | continue; | | 3113 | continue; |
3112 | } | | 3114 | } |
3113 | apply_mods: | | 3115 | apply_mods: |
3114 | if (DEBUG(VAR)) { | | 3116 | if (DEBUG(VAR)) { |
3115 | fprintf(debug_file, "Applying[%s] :%c to \"%s\"\n", st.v->name, | | 3117 | fprintf(debug_file, "Applying[%s] :%c to \"%s\"\n", st.v->name, |
3116 | *p, st.val); | | 3118 | *p, st.val); |
3117 | } | | 3119 | } |
3118 | st.newVal = var_Error; | | 3120 | st.newVal = var_Error; |
3119 | char modifier = *p; | | 3121 | char modifier = *p; |
| | | 3122 | st.next = NULL; /* fail fast if an ApplyModifier forgets to set this */ |
3120 | switch (modifier) { | | 3123 | switch (modifier) { |
3121 | case ':': | | 3124 | case ':': |
3122 | { | | 3125 | { |
3123 | int res = ApplyModifier_Assign(p, &st); | | 3126 | int res = ApplyModifier_Assign(p, &st); |
3124 | if (res == 'b') | | 3127 | if (res == 'b') |
3125 | goto bad_modifier; | | 3128 | goto bad_modifier; |
3126 | if (res == 'c') | | 3129 | if (res == 'c') |
3127 | goto cleanup; | | 3130 | goto cleanup; |
3128 | if (res == 'd') | | 3131 | if (res == 'd') |
3129 | goto default_case; | | 3132 | goto default_case; |
3130 | break; | | 3133 | break; |
3131 | } | | 3134 | } |
3132 | case '@': | | 3135 | case '@': |