| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: var.c,v 1.1012 2022/02/11 21:44:10 rillig Exp $ */ | | 1 | /* $NetBSD: var.c,v 1.1013 2022/03/03 19:52:41 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. |
| @@ -129,27 +129,27 @@ | | | @@ -129,27 +129,27 @@ |
129 | #include <regex.h> | | 129 | #include <regex.h> |
130 | #endif | | 130 | #endif |
131 | #include <errno.h> | | 131 | #include <errno.h> |
132 | #include <inttypes.h> | | 132 | #include <inttypes.h> |
133 | #include <limits.h> | | 133 | #include <limits.h> |
134 | #include <time.h> | | 134 | #include <time.h> |
135 | | | 135 | |
136 | #include "make.h" | | 136 | #include "make.h" |
137 | #include "dir.h" | | 137 | #include "dir.h" |
138 | #include "job.h" | | 138 | #include "job.h" |
139 | #include "metachar.h" | | 139 | #include "metachar.h" |
140 | | | 140 | |
141 | /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ | | 141 | /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ |
142 | MAKE_RCSID("$NetBSD: var.c,v 1.1012 2022/02/11 21:44:10 rillig Exp $"); | | 142 | MAKE_RCSID("$NetBSD: var.c,v 1.1013 2022/03/03 19:52:41 rillig Exp $"); |
143 | | | 143 | |
144 | /* | | 144 | /* |
145 | * Variables are defined using one of the VAR=value assignments. Their | | 145 | * Variables are defined using one of the VAR=value assignments. Their |
146 | * value can be queried by expressions such as $V, ${VAR}, or with modifiers | | 146 | * value can be queried by expressions such as $V, ${VAR}, or with modifiers |
147 | * such as ${VAR:S,from,to,g:Q}. | | 147 | * such as ${VAR:S,from,to,g:Q}. |
148 | * | | 148 | * |
149 | * There are 3 kinds of variables: scope variables, environment variables, | | 149 | * There are 3 kinds of variables: scope variables, environment variables, |
150 | * undefined variables. | | 150 | * undefined variables. |
151 | * | | 151 | * |
152 | * Scope variables are stored in a GNode.scope. The only way to undefine | | 152 | * Scope variables are stored in a GNode.scope. The only way to undefine |
153 | * a scope variable is using the .undef directive. In particular, it must | | 153 | * a scope variable is using the .undef directive. In particular, it must |
154 | * not be possible to undefine a variable during the evaluation of an | | 154 | * not be possible to undefine a variable during the evaluation of an |
155 | * expression, or Var.name might point nowhere. (There is another, | | 155 | * expression, or Var.name might point nowhere. (There is another, |
| @@ -2685,29 +2685,28 @@ ApplyModifier_Range(const char **pp, Mod | | | @@ -2685,29 +2685,28 @@ ApplyModifier_Range(const char **pp, Mod |
2685 | /* | | 2685 | /* |
2686 | * XXX: Use ch->sep instead of ' ', for consistency. | | 2686 | * XXX: Use ch->sep instead of ' ', for consistency. |
2687 | */ | | 2687 | */ |
2688 | Buf_AddByte(&buf, ' '); | | 2688 | Buf_AddByte(&buf, ' '); |
2689 | } | | 2689 | } |
2690 | Buf_AddInt(&buf, 1 + (int)i); | | 2690 | Buf_AddInt(&buf, 1 + (int)i); |
2691 | } | | 2691 | } |
2692 | | | 2692 | |
2693 | Expr_SetValueOwn(ch->expr, Buf_DoneData(&buf)); | | 2693 | Expr_SetValueOwn(ch->expr, Buf_DoneData(&buf)); |
2694 | return AMR_OK; | | 2694 | return AMR_OK; |
2695 | } | | 2695 | } |
2696 | | | 2696 | |
2697 | /* Parse a ':M' or ':N' modifier. */ | | 2697 | /* Parse a ':M' or ':N' modifier. */ |
2698 | static void | | 2698 | static char * |
2699 | ParseModifier_Match(const char **pp, const ModChain *ch, | | 2699 | ParseModifier_Match(const char **pp, const ModChain *ch) |
2700 | char **out_pattern) | | | |
2701 | { | | 2700 | { |
2702 | const char *mod = *pp; | | 2701 | const char *mod = *pp; |
2703 | Expr *expr = ch->expr; | | 2702 | Expr *expr = ch->expr; |
2704 | bool copy = false; /* pattern should be, or has been, copied */ | | 2703 | bool copy = false; /* pattern should be, or has been, copied */ |
2705 | bool needSubst = false; | | 2704 | bool needSubst = false; |
2706 | const char *endpat; | | 2705 | const char *endpat; |
2707 | char *pattern; | | 2706 | char *pattern; |
2708 | | | 2707 | |
2709 | /* | | 2708 | /* |
2710 | * In the loop below, ignore ':' unless we are at (or back to) the | | 2709 | * In the loop below, ignore ':' unless we are at (or back to) the |
2711 | * original brace level. | | 2710 | * original brace level. |
2712 | * XXX: This will likely not work right if $() and ${} are intermixed. | | 2711 | * XXX: This will likely not work right if $() and ${} are intermixed. |
2713 | */ | | 2712 | */ |
| @@ -2751,44 +2750,48 @@ ParseModifier_Match(const char **pp, con | | | @@ -2751,44 +2750,48 @@ ParseModifier_Match(const char **pp, con |
2751 | if (src[0] == '\\' && src + 1 < endpat && | | 2750 | if (src[0] == '\\' && src + 1 < endpat && |
2752 | /* XXX: ch->startc is missing here; see above */ | | 2751 | /* XXX: ch->startc is missing here; see above */ |
2753 | IsDelimiter(src[1], ch)) | | 2752 | IsDelimiter(src[1], ch)) |
2754 | src++; | | 2753 | src++; |
2755 | *dst = *src; | | 2754 | *dst = *src; |
2756 | } | | 2755 | } |
2757 | *dst = '\0'; | | 2756 | *dst = '\0'; |
2758 | } else { | | 2757 | } else { |
2759 | pattern = bmake_strsedup(mod + 1, endpat); | | 2758 | pattern = bmake_strsedup(mod + 1, endpat); |
2760 | } | | 2759 | } |
2761 | | | 2760 | |
2762 | if (needSubst) { | | 2761 | if (needSubst) { |
2763 | char *old_pattern = pattern; | | 2762 | char *old_pattern = pattern; |
| | | 2763 | /* |
| | | 2764 | * XXX: Contrary to ParseModifierPart, a dollar in a ':M' or |
| | | 2765 | * ':N' modifier must be escaped as '$$', not as '\$'. |
| | | 2766 | */ |
2764 | (void)Var_Subst(pattern, expr->scope, expr->emode, &pattern); | | 2767 | (void)Var_Subst(pattern, expr->scope, expr->emode, &pattern); |
2765 | /* TODO: handle errors */ | | 2768 | /* TODO: handle errors */ |
2766 | free(old_pattern); | | 2769 | free(old_pattern); |
2767 | } | | 2770 | } |
2768 | | | 2771 | |
2769 | DEBUG2(VAR, "Pattern for ':%c' is \"%s\"\n", mod[0], pattern); | | 2772 | DEBUG2(VAR, "Pattern for ':%c' is \"%s\"\n", mod[0], pattern); |
2770 | | | 2773 | |
2771 | *out_pattern = pattern; | | 2774 | return pattern; |
2772 | } | | 2775 | } |
2773 | | | 2776 | |
2774 | /* :Mpattern or :Npattern */ | | 2777 | /* :Mpattern or :Npattern */ |
2775 | static ApplyModifierResult | | 2778 | static ApplyModifierResult |
2776 | ApplyModifier_Match(const char **pp, ModChain *ch) | | 2779 | ApplyModifier_Match(const char **pp, ModChain *ch) |
2777 | { | | 2780 | { |
2778 | char mod = **pp; | | 2781 | char mod = **pp; |
2779 | char *pattern; | | 2782 | char *pattern; |
2780 | | | 2783 | |
2781 | ParseModifier_Match(pp, ch, &pattern); | | 2784 | pattern = ParseModifier_Match(pp, ch); |
2782 | | | 2785 | |
2783 | if (ModChain_ShouldEval(ch)) { | | 2786 | if (ModChain_ShouldEval(ch)) { |
2784 | ModifyWordProc modifyWord = | | 2787 | ModifyWordProc modifyWord = |
2785 | mod == 'M' ? ModifyWord_Match : ModifyWord_NoMatch; | | 2788 | mod == 'M' ? ModifyWord_Match : ModifyWord_NoMatch; |
2786 | ModifyWords(ch, modifyWord, pattern, ch->oneBigWord); | | 2789 | ModifyWords(ch, modifyWord, pattern, ch->oneBigWord); |
2787 | } | | 2790 | } |
2788 | | | 2791 | |
2789 | free(pattern); | | 2792 | free(pattern); |
2790 | return AMR_OK; | | 2793 | return AMR_OK; |
2791 | } | | 2794 | } |
2792 | | | 2795 | |
2793 | static void | | 2796 | static void |
2794 | ParsePatternFlags(const char **pp, PatternFlags *pflags, bool *oneBigWord) | | 2797 | ParsePatternFlags(const char **pp, PatternFlags *pflags, bool *oneBigWord) |