| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: var.c,v 1.560 2020/10/03 12:30:17 rillig Exp $ */ | | 1 | /* $NetBSD: var.c,v 1.561 2020/10/03 12:46:52 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. |
| @@ -111,27 +111,27 @@ | | | @@ -111,27 +111,27 @@ |
111 | #include <sys/types.h> | | 111 | #include <sys/types.h> |
112 | #include <regex.h> | | 112 | #include <regex.h> |
113 | #endif | | 113 | #endif |
114 | #include <inttypes.h> | | 114 | #include <inttypes.h> |
115 | #include <limits.h> | | 115 | #include <limits.h> |
116 | #include <time.h> | | 116 | #include <time.h> |
117 | | | 117 | |
118 | #include "make.h" | | 118 | #include "make.h" |
119 | #include "dir.h" | | 119 | #include "dir.h" |
120 | #include "job.h" | | 120 | #include "job.h" |
121 | #include "metachar.h" | | 121 | #include "metachar.h" |
122 | | | 122 | |
123 | /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ | | 123 | /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ |
124 | MAKE_RCSID("$NetBSD: var.c,v 1.560 2020/10/03 12:30:17 rillig Exp $"); | | 124 | MAKE_RCSID("$NetBSD: var.c,v 1.561 2020/10/03 12:46:52 rillig Exp $"); |
125 | | | 125 | |
126 | #define VAR_DEBUG1(fmt, arg1) DEBUG1(VAR, fmt, arg1) | | 126 | #define VAR_DEBUG1(fmt, arg1) DEBUG1(VAR, fmt, arg1) |
127 | #define VAR_DEBUG2(fmt, arg1, arg2) DEBUG2(VAR, fmt, arg1, arg2) | | 127 | #define VAR_DEBUG2(fmt, arg1, arg2) DEBUG2(VAR, fmt, arg1, arg2) |
128 | #define VAR_DEBUG3(fmt, arg1, arg2, arg3) DEBUG3(VAR, fmt, arg1, arg2, arg3) | | 128 | #define VAR_DEBUG3(fmt, arg1, arg2, arg3) DEBUG3(VAR, fmt, arg1, arg2, arg3) |
129 | #define VAR_DEBUG4(fmt, arg1, arg2, arg3, arg4) DEBUG4(VAR, fmt, arg1, arg2, arg3, arg4) | | 129 | #define VAR_DEBUG4(fmt, arg1, arg2, arg3, arg4) DEBUG4(VAR, fmt, arg1, arg2, arg3, arg4) |
130 | | | 130 | |
131 | ENUM_FLAGS_RTTI_3(VarEvalFlags, | | 131 | ENUM_FLAGS_RTTI_3(VarEvalFlags, |
132 | VARE_UNDEFERR, VARE_WANTRES, VARE_ASSIGN); | | 132 | VARE_UNDEFERR, VARE_WANTRES, VARE_ASSIGN); |
133 | | | 133 | |
134 | /* | | 134 | /* |
135 | * This lets us tell if we have replaced the original environ | | 135 | * This lets us tell if we have replaced the original environ |
136 | * (which we cannot free). | | 136 | * (which we cannot free). |
137 | */ | | 137 | */ |
| @@ -2917,26 +2917,37 @@ static ApplyModifierResult | | | @@ -2917,26 +2917,37 @@ static ApplyModifierResult |
2917 | ApplyModifier_WordFunc(const char **pp, ApplyModifiersState *st, | | 2917 | ApplyModifier_WordFunc(const char **pp, ApplyModifiersState *st, |
2918 | ModifyWordsCallback modifyWord) | | 2918 | ModifyWordsCallback modifyWord) |
2919 | { | | 2919 | { |
2920 | char delim = (*pp)[1]; | | 2920 | char delim = (*pp)[1]; |
2921 | if (delim != st->endc && delim != ':') | | 2921 | if (delim != st->endc && delim != ':') |
2922 | return AMR_UNKNOWN; | | 2922 | return AMR_UNKNOWN; |
2923 | | | 2923 | |
2924 | st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, | | 2924 | st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, |
2925 | st->val, modifyWord, NULL); | | 2925 | st->val, modifyWord, NULL); |
2926 | (*pp)++; | | 2926 | (*pp)++; |
2927 | return AMR_OK; | | 2927 | return AMR_OK; |
2928 | } | | 2928 | } |
2929 | | | 2929 | |
| | | 2930 | static ApplyModifierResult |
| | | 2931 | ApplyModifier_Unique(const char **pp, ApplyModifiersState *st) |
| | | 2932 | { |
| | | 2933 | if ((*pp)[1] == st->endc || (*pp)[1] == ':') { |
| | | 2934 | st->newVal = VarUniq(st->val); |
| | | 2935 | (*pp)++; |
| | | 2936 | return AMR_OK; |
| | | 2937 | } else |
| | | 2938 | return AMR_UNKNOWN; |
| | | 2939 | } |
| | | 2940 | |
2930 | #ifdef SYSVVARSUB | | 2941 | #ifdef SYSVVARSUB |
2931 | /* :from=to */ | | 2942 | /* :from=to */ |
2932 | static ApplyModifierResult | | 2943 | static ApplyModifierResult |
2933 | ApplyModifier_SysV(const char **pp, ApplyModifiersState *st) | | 2944 | ApplyModifier_SysV(const char **pp, ApplyModifiersState *st) |
2934 | { | | 2945 | { |
2935 | char *lhs, *rhs; | | 2946 | char *lhs, *rhs; |
2936 | VarParseResult res; | | 2947 | VarParseResult res; |
2937 | | | 2948 | |
2938 | const char *mod = *pp; | | 2949 | const char *mod = *pp; |
2939 | Boolean eqFound = FALSE; | | 2950 | Boolean eqFound = FALSE; |
2940 | | | 2951 | |
2941 | /* | | 2952 | /* |
2942 | * First we make a pass through the string trying | | 2953 | * First we make a pass through the string trying |
| @@ -3100,32 +3111,27 @@ ApplyModifier(const char **pp, ApplyModi | | | @@ -3100,32 +3111,27 @@ ApplyModifier(const char **pp, ApplyModi |
3100 | case 'T': | | 3111 | case 'T': |
3101 | return ApplyModifier_WordFunc(pp, st, ModifyWord_Tail); | | 3112 | return ApplyModifier_WordFunc(pp, st, ModifyWord_Tail); |
3102 | case 'H': | | 3113 | case 'H': |
3103 | return ApplyModifier_WordFunc(pp, st, ModifyWord_Head); | | 3114 | return ApplyModifier_WordFunc(pp, st, ModifyWord_Head); |
3104 | case 'E': | | 3115 | case 'E': |
3105 | return ApplyModifier_WordFunc(pp, st, ModifyWord_Suffix); | | 3116 | return ApplyModifier_WordFunc(pp, st, ModifyWord_Suffix); |
3106 | case 'R': | | 3117 | case 'R': |
3107 | return ApplyModifier_WordFunc(pp, st, ModifyWord_Root); | | 3118 | return ApplyModifier_WordFunc(pp, st, ModifyWord_Root); |
3108 | case 'r': | | 3119 | case 'r': |
3109 | return ApplyModifier_Range(pp, st); | | 3120 | return ApplyModifier_Range(pp, st); |
3110 | case 'O': | | 3121 | case 'O': |
3111 | return ApplyModifier_Order(pp, st); | | 3122 | return ApplyModifier_Order(pp, st); |
3112 | case 'u': | | 3123 | case 'u': |
3113 | if ((*pp)[1] == st->endc || (*pp)[1] == ':') { | | 3124 | return ApplyModifier_Unique(pp, st); |
3114 | st->newVal = VarUniq(st->val); | | | |
3115 | (*pp)++; | | | |
3116 | return AMR_OK; | | | |
3117 | } else | | | |
3118 | return AMR_UNKNOWN; | | | |
3119 | #ifdef SUNSHCMD | | 3125 | #ifdef SUNSHCMD |
3120 | case 's': | | 3126 | case 's': |
3121 | return ApplyModifier_SunShell(pp, st); | | 3127 | return ApplyModifier_SunShell(pp, st); |
3122 | #endif | | 3128 | #endif |
3123 | default: | | 3129 | default: |
3124 | return AMR_UNKNOWN; | | 3130 | return AMR_UNKNOWN; |
3125 | } | | 3131 | } |
3126 | } | | 3132 | } |
3127 | | | 3133 | |
3128 | /* Apply any modifiers (such as :Mpattern or :@var@loop@ or :Q or ::=value). */ | | 3134 | /* Apply any modifiers (such as :Mpattern or :@var@loop@ or :Q or ::=value). */ |
3129 | static char * | | 3135 | static char * |
3130 | ApplyModifiers( | | 3136 | ApplyModifiers( |
3131 | const char **pp, /* the parsing position, updated upon return */ | | 3137 | const char **pp, /* the parsing position, updated upon return */ |