| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: var.c,v 1.872 2021/03/14 18:10:57 rillig Exp $ */ | | 1 | /* $NetBSD: var.c,v 1.873 2021/03/14 18:23:44 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. |
| @@ -130,27 +130,27 @@ | | | @@ -130,27 +130,27 @@ |
130 | #include <regex.h> | | 130 | #include <regex.h> |
131 | #endif | | 131 | #endif |
132 | #include <errno.h> | | 132 | #include <errno.h> |
133 | #include <inttypes.h> | | 133 | #include <inttypes.h> |
134 | #include <limits.h> | | 134 | #include <limits.h> |
135 | #include <time.h> | | 135 | #include <time.h> |
136 | | | 136 | |
137 | #include "make.h" | | 137 | #include "make.h" |
138 | #include "dir.h" | | 138 | #include "dir.h" |
139 | #include "job.h" | | 139 | #include "job.h" |
140 | #include "metachar.h" | | 140 | #include "metachar.h" |
141 | | | 141 | |
142 | /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ | | 142 | /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ |
143 | MAKE_RCSID("$NetBSD: var.c,v 1.872 2021/03/14 18:10:57 rillig Exp $"); | | 143 | MAKE_RCSID("$NetBSD: var.c,v 1.873 2021/03/14 18:23:44 rillig Exp $"); |
144 | | | 144 | |
145 | typedef enum VarFlags { | | 145 | typedef enum VarFlags { |
146 | VFL_NONE = 0, | | 146 | VFL_NONE = 0, |
147 | | | 147 | |
148 | /* | | 148 | /* |
149 | * The variable's value is currently being used by Var_Parse or | | 149 | * The variable's value is currently being used by Var_Parse or |
150 | * Var_Subst. This marker is used to avoid endless recursion. | | 150 | * Var_Subst. This marker is used to avoid endless recursion. |
151 | */ | | 151 | */ |
152 | VFL_IN_USE = 1 << 0, | | 152 | VFL_IN_USE = 1 << 0, |
153 | | | 153 | |
154 | /* | | 154 | /* |
155 | * The variable comes from the environment. | | 155 | * The variable comes from the environment. |
156 | * These variables are not registered in any GNode, therefore they | | 156 | * These variables are not registered in any GNode, therefore they |
| @@ -2601,41 +2601,45 @@ ApplyModifier_Localtime(const char **pp, | | | @@ -2601,41 +2601,45 @@ ApplyModifier_Localtime(const char **pp, |
2601 | VarStrftime(st->expr->value.str, FALSE, utc)); | | 2601 | VarStrftime(st->expr->value.str, FALSE, utc)); |
2602 | | | 2602 | |
2603 | return AMR_OK; | | 2603 | return AMR_OK; |
2604 | } | | 2604 | } |
2605 | | | 2605 | |
2606 | /* :hash */ | | 2606 | /* :hash */ |
2607 | static ApplyModifierResult | | 2607 | static ApplyModifierResult |
2608 | ApplyModifier_Hash(const char **pp, ApplyModifiersState *st) | | 2608 | ApplyModifier_Hash(const char **pp, ApplyModifiersState *st) |
2609 | { | | 2609 | { |
2610 | if (!ModMatch(*pp, "hash", st)) | | 2610 | if (!ModMatch(*pp, "hash", st)) |
2611 | return AMR_UNKNOWN; | | 2611 | return AMR_UNKNOWN; |
2612 | *pp += 4; | | 2612 | *pp += 4; |
2613 | | | 2613 | |
2614 | Expr_SetValueOwn(st->expr, VarHash(st->expr->value.str)); | | 2614 | if (st->expr->eflags & VARE_WANTRES) |
| | | 2615 | Expr_SetValueOwn(st->expr, VarHash(st->expr->value.str)); |
2615 | | | 2616 | |
2616 | return AMR_OK; | | 2617 | return AMR_OK; |
2617 | } | | 2618 | } |
2618 | | | 2619 | |
2619 | /* :P */ | | 2620 | /* :P */ |
2620 | static ApplyModifierResult | | 2621 | static ApplyModifierResult |
2621 | ApplyModifier_Path(const char **pp, ApplyModifiersState *st) | | 2622 | ApplyModifier_Path(const char **pp, ApplyModifiersState *st) |
2622 | { | | 2623 | { |
2623 | Expr *expr = st->expr; | | 2624 | Expr *expr = st->expr; |
2624 | GNode *gn; | | 2625 | GNode *gn; |
2625 | char *path; | | 2626 | char *path; |
2626 | | | 2627 | |
2627 | (*pp)++; | | 2628 | (*pp)++; |
2628 | | | 2629 | |
| | | 2630 | if (!(st->expr->eflags & VARE_WANTRES)) |
| | | 2631 | return AMR_OK; |
| | | 2632 | |
2629 | Expr_Define(expr); | | 2633 | Expr_Define(expr); |
2630 | | | 2634 | |
2631 | gn = Targ_FindNode(expr->var->name.str); | | 2635 | gn = Targ_FindNode(expr->var->name.str); |
2632 | if (gn == NULL || gn->type & OP_NOPATH) { | | 2636 | if (gn == NULL || gn->type & OP_NOPATH) { |
2633 | path = NULL; | | 2637 | path = NULL; |
2634 | } else if (gn->path != NULL) { | | 2638 | } else if (gn->path != NULL) { |
2635 | path = bmake_strdup(gn->path); | | 2639 | path = bmake_strdup(gn->path); |
2636 | } else { | | 2640 | } else { |
2637 | SearchPath *searchPath = Suff_FindPath(gn); | | 2641 | SearchPath *searchPath = Suff_FindPath(gn); |
2638 | path = Dir_FindFile(expr->var->name.str, searchPath); | | 2642 | path = Dir_FindFile(expr->var->name.str, searchPath); |
2639 | } | | 2643 | } |
2640 | if (path == NULL) | | 2644 | if (path == NULL) |
2641 | path = bmake_strdup(expr->var->name.str); | | 2645 | path = bmake_strdup(expr->var->name.str); |
| @@ -2690,26 +2694,29 @@ ApplyModifier_Range(const char **pp, App | | | @@ -2690,26 +2694,29 @@ ApplyModifier_Range(const char **pp, App |
2690 | const char *p = mod + 6; | | 2694 | const char *p = mod + 6; |
2691 | if (!TryParseSize(&p, &n)) { | | 2695 | if (!TryParseSize(&p, &n)) { |
2692 | Parse_Error(PARSE_FATAL, | | 2696 | Parse_Error(PARSE_FATAL, |
2693 | "Invalid number \"%s\" for ':range' modifier", | | 2697 | "Invalid number \"%s\" for ':range' modifier", |
2694 | mod + 6); | | 2698 | mod + 6); |
2695 | return AMR_CLEANUP; | | 2699 | return AMR_CLEANUP; |
2696 | } | | 2700 | } |
2697 | *pp = p; | | 2701 | *pp = p; |
2698 | } else { | | 2702 | } else { |
2699 | n = 0; | | 2703 | n = 0; |
2700 | *pp = mod + 5; | | 2704 | *pp = mod + 5; |
2701 | } | | 2705 | } |
2702 | | | 2706 | |
| | | 2707 | if (!(st->expr->eflags & VARE_WANTRES)) |
| | | 2708 | return AMR_OK; |
| | | 2709 | |
2703 | if (n == 0) { | | 2710 | if (n == 0) { |
2704 | Words words = Str_Words(st->expr->value.str, FALSE); | | 2711 | Words words = Str_Words(st->expr->value.str, FALSE); |
2705 | n = words.len; | | 2712 | n = words.len; |
2706 | Words_Free(words); | | 2713 | Words_Free(words); |
2707 | } | | 2714 | } |
2708 | | | 2715 | |
2709 | Buf_Init(&buf); | | 2716 | Buf_Init(&buf); |
2710 | | | 2717 | |
2711 | for (i = 0; i < n; i++) { | | 2718 | for (i = 0; i < n; i++) { |
2712 | if (i != 0) { | | 2719 | if (i != 0) { |
2713 | /* XXX: Use st->sep instead of ' ', for consistency. */ | | 2720 | /* XXX: Use st->sep instead of ' ', for consistency. */ |
2714 | Buf_AddByte(&buf, ' '); | | 2721 | Buf_AddByte(&buf, ' '); |
2715 | } | | 2722 | } |
| @@ -2939,44 +2946,53 @@ ApplyModifier_Regex(const char **pp, App | | | @@ -2939,44 +2946,53 @@ ApplyModifier_Regex(const char **pp, App |
2939 | } | | 2946 | } |
2940 | | | 2947 | |
2941 | #endif | | 2948 | #endif |
2942 | | | 2949 | |
2943 | /* :Q, :q */ | | 2950 | /* :Q, :q */ |
2944 | static ApplyModifierResult | | 2951 | static ApplyModifierResult |
2945 | ApplyModifier_Quote(const char **pp, ApplyModifiersState *st) | | 2952 | ApplyModifier_Quote(const char **pp, ApplyModifiersState *st) |
2946 | { | | 2953 | { |
2947 | Boolean quoteDollar = **pp == 'q'; | | 2954 | Boolean quoteDollar = **pp == 'q'; |
2948 | if (!IsDelimiter((*pp)[1], st)) | | 2955 | if (!IsDelimiter((*pp)[1], st)) |
2949 | return AMR_UNKNOWN; | | 2956 | return AMR_UNKNOWN; |
2950 | (*pp)++; | | 2957 | (*pp)++; |
2951 | | | 2958 | |
2952 | Expr_SetValueOwn(st->expr, VarQuote(st->expr->value.str, quoteDollar)); | | 2959 | if (st->expr->eflags & VARE_WANTRES) |
| | | 2960 | Expr_SetValueOwn(st->expr, |
| | | 2961 | VarQuote(st->expr->value.str, quoteDollar)); |
2953 | | | 2962 | |
2954 | return AMR_OK; | | 2963 | return AMR_OK; |
2955 | } | | 2964 | } |
2956 | | | 2965 | |
2957 | /*ARGSUSED*/ | | 2966 | /*ARGSUSED*/ |
2958 | static void | | 2967 | static void |
2959 | ModifyWord_Copy(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED) | | 2968 | ModifyWord_Copy(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED) |
2960 | { | | 2969 | { |
2961 | SepBuf_AddStr(buf, word); | | 2970 | SepBuf_AddStr(buf, word); |
2962 | } | | 2971 | } |
2963 | | | 2972 | |
2964 | /* :ts<separator> */ | | 2973 | /* :ts<separator> */ |
2965 | static ApplyModifierResult | | 2974 | static ApplyModifierResult |
2966 | ApplyModifier_ToSep(const char **pp, ApplyModifiersState *st) | | 2975 | ApplyModifier_ToSep(const char **pp, ApplyModifiersState *st) |
2967 | { | | 2976 | { |
2968 | const char *sep = *pp + 2; | | 2977 | const char *sep = *pp + 2; |
2969 | | | 2978 | |
| | | 2979 | /* |
| | | 2980 | * Even if VARE_WANTRES is not set, proceed as normal since there is |
| | | 2981 | * neither any observable side effect nor a performance penalty. |
| | | 2982 | * Checking for VARE_WANTRES for every single piece of code in here |
| | | 2983 | * would make the code in this function too hard to read. |
| | | 2984 | */ |
| | | 2985 | |
2970 | /* ":ts<any><endc>" or ":ts<any>:" */ | | 2986 | /* ":ts<any><endc>" or ":ts<any>:" */ |
2971 | if (sep[0] != st->endc && IsDelimiter(sep[1], st)) { | | 2987 | if (sep[0] != st->endc && IsDelimiter(sep[1], st)) { |
2972 | *pp = sep + 1; | | 2988 | *pp = sep + 1; |
2973 | st->sep = sep[0]; | | 2989 | st->sep = sep[0]; |
2974 | goto ok; | | 2990 | goto ok; |
2975 | } | | 2991 | } |
2976 | | | 2992 | |
2977 | /* ":ts<endc>" or ":ts:" */ | | 2993 | /* ":ts<endc>" or ":ts:" */ |
2978 | if (IsDelimiter(sep[0], st)) { | | 2994 | if (IsDelimiter(sep[0], st)) { |
2979 | *pp = sep; | | 2995 | *pp = sep; |
2980 | st->sep = '\0'; /* no separator */ | | 2996 | st->sep = '\0'; /* no separator */ |
2981 | goto ok; | | 2997 | goto ok; |
2982 | } | | 2998 | } |
| @@ -3079,33 +3095,35 @@ ApplyModifier_To(const char **pp, ApplyM | | | @@ -3079,33 +3095,35 @@ ApplyModifier_To(const char **pp, ApplyM |
3079 | if (!IsDelimiter(mod[2], st)) { /* :t<unrecognized> */ | | 3095 | if (!IsDelimiter(mod[2], st)) { /* :t<unrecognized> */ |
3080 | *pp = mod + 1; | | 3096 | *pp = mod + 1; |
3081 | return AMR_BAD; | | 3097 | return AMR_BAD; |
3082 | } | | 3098 | } |
3083 | | | 3099 | |
3084 | if (mod[1] == 'A') { /* :tA */ | | 3100 | if (mod[1] == 'A') { /* :tA */ |
3085 | *pp = mod + 2; | | 3101 | *pp = mod + 2; |
3086 | ModifyWords(st, ModifyWord_Realpath, NULL, st->oneBigWord); | | 3102 | ModifyWords(st, ModifyWord_Realpath, NULL, st->oneBigWord); |
3087 | return AMR_OK; | | 3103 | return AMR_OK; |
3088 | } | | 3104 | } |
3089 | | | 3105 | |
3090 | if (mod[1] == 'u') { /* :tu */ | | 3106 | if (mod[1] == 'u') { /* :tu */ |
3091 | *pp = mod + 2; | | 3107 | *pp = mod + 2; |
3092 | Expr_SetValueOwn(expr, str_toupper(expr->value.str)); | | 3108 | if (st->expr->eflags & VARE_WANTRES) |
| | | 3109 | Expr_SetValueOwn(expr, str_toupper(expr->value.str)); |
3093 | return AMR_OK; | | 3110 | return AMR_OK; |
3094 | } | | 3111 | } |
3095 | | | 3112 | |
3096 | if (mod[1] == 'l') { /* :tl */ | | 3113 | if (mod[1] == 'l') { /* :tl */ |
3097 | *pp = mod + 2; | | 3114 | *pp = mod + 2; |
3098 | Expr_SetValueOwn(expr, str_tolower(expr->value.str)); | | 3115 | if (st->expr->eflags & VARE_WANTRES) |
| | | 3116 | Expr_SetValueOwn(expr, str_tolower(expr->value.str)); |
3099 | return AMR_OK; | | 3117 | return AMR_OK; |
3100 | } | | 3118 | } |
3101 | | | 3119 | |
3102 | if (mod[1] == 'W' || mod[1] == 'w') { /* :tW, :tw */ | | 3120 | if (mod[1] == 'W' || mod[1] == 'w') { /* :tW, :tw */ |
3103 | *pp = mod + 2; | | 3121 | *pp = mod + 2; |
3104 | st->oneBigWord = mod[1] == 'W'; | | 3122 | st->oneBigWord = mod[1] == 'W'; |
3105 | return AMR_OK; | | 3123 | return AMR_OK; |
3106 | } | | 3124 | } |
3107 | | | 3125 | |
3108 | /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */ | | 3126 | /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */ |
3109 | *pp = mod + 1; /* XXX: unnecessary but observable */ | | 3127 | *pp = mod + 1; /* XXX: unnecessary but observable */ |
3110 | return AMR_BAD; | | 3128 | return AMR_BAD; |
3111 | } | | 3129 | } |
| @@ -3454,39 +3472,41 @@ ApplyModifier_Remember(const char **pp, | | | @@ -3454,39 +3472,41 @@ ApplyModifier_Remember(const char **pp, |
3454 | | | 3472 | |
3455 | /* | | 3473 | /* |
3456 | * Apply the given function to each word of the variable value, | | 3474 | * Apply the given function to each word of the variable value, |
3457 | * for a single-letter modifier such as :H, :T. | | 3475 | * for a single-letter modifier such as :H, :T. |
3458 | */ | | 3476 | */ |
3459 | static ApplyModifierResult | | 3477 | static ApplyModifierResult |
3460 | ApplyModifier_WordFunc(const char **pp, ApplyModifiersState *st, | | 3478 | ApplyModifier_WordFunc(const char **pp, ApplyModifiersState *st, |
3461 | ModifyWordProc modifyWord) | | 3479 | ModifyWordProc modifyWord) |
3462 | { | | 3480 | { |
3463 | if (!IsDelimiter((*pp)[1], st)) | | 3481 | if (!IsDelimiter((*pp)[1], st)) |
3464 | return AMR_UNKNOWN; | | 3482 | return AMR_UNKNOWN; |
3465 | (*pp)++; | | 3483 | (*pp)++; |
3466 | | | 3484 | |
3467 | ModifyWords(st, modifyWord, NULL, st->oneBigWord); | | 3485 | if (st->expr->eflags & VARE_WANTRES) |
| | | 3486 | ModifyWords(st, modifyWord, NULL, st->oneBigWord); |
3468 | | | 3487 | |
3469 | return AMR_OK; | | 3488 | return AMR_OK; |
3470 | } | | 3489 | } |
3471 | | | 3490 | |
3472 | static ApplyModifierResult | | 3491 | static ApplyModifierResult |
3473 | ApplyModifier_Unique(const char **pp, ApplyModifiersState *st) | | 3492 | ApplyModifier_Unique(const char **pp, ApplyModifiersState *st) |
3474 | { | | 3493 | { |
3475 | if (!IsDelimiter((*pp)[1], st)) | | 3494 | if (!IsDelimiter((*pp)[1], st)) |
3476 | return AMR_UNKNOWN; | | 3495 | return AMR_UNKNOWN; |
3477 | (*pp)++; | | 3496 | (*pp)++; |
3478 | | | 3497 | |
3479 | Expr_SetValueOwn(st->expr, VarUniq(st->expr->value.str)); | | 3498 | if (st->expr->eflags & VARE_WANTRES) |
| | | 3499 | Expr_SetValueOwn(st->expr, VarUniq(st->expr->value.str)); |
3480 | | | 3500 | |
3481 | return AMR_OK; | | 3501 | return AMR_OK; |
3482 | } | | 3502 | } |
3483 | | | 3503 | |
3484 | #ifdef SYSVVARSUB | | 3504 | #ifdef SYSVVARSUB |
3485 | /* :from=to */ | | 3505 | /* :from=to */ |
3486 | static ApplyModifierResult | | 3506 | static ApplyModifierResult |
3487 | ApplyModifier_SysV(const char **pp, ApplyModifiersState *st) | | 3507 | ApplyModifier_SysV(const char **pp, ApplyModifiersState *st) |
3488 | { | | 3508 | { |
3489 | Expr *expr = st->expr; | | 3509 | Expr *expr = st->expr; |
3490 | char *lhs, *rhs; | | 3510 | char *lhs, *rhs; |
3491 | VarParseResult res; | | 3511 | VarParseResult res; |
3492 | | | 3512 | |