| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: var.c,v 1.880 2021/03/14 20:09:26 rillig Exp $ */ | | 1 | /* $NetBSD: var.c,v 1.881 2021/03/14 20:12:16 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.880 2021/03/14 20:09:26 rillig Exp $"); | | 143 | MAKE_RCSID("$NetBSD: var.c,v 1.881 2021/03/14 20:12:16 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 |
| @@ -3362,69 +3362,67 @@ ApplyModifier_IfElse(const char **pp, Ap | | | @@ -3362,69 +3362,67 @@ ApplyModifier_IfElse(const char **pp, Ap |
3362 | * it was not already set. | | 3362 | * it was not already set. |
3363 | * ::+=<str> Appends <str> to variable. | | 3363 | * ::+=<str> Appends <str> to variable. |
3364 | * ::!=<cmd> Assigns output of <cmd> as the new value of | | 3364 | * ::!=<cmd> Assigns output of <cmd> as the new value of |
3365 | * variable. | | 3365 | * variable. |
3366 | */ | | 3366 | */ |
3367 | static ApplyModifierResult | | 3367 | static ApplyModifierResult |
3368 | ApplyModifier_Assign(const char **pp, ApplyModifiersState *st) | | 3368 | ApplyModifier_Assign(const char **pp, ApplyModifiersState *st) |
3369 | { | | 3369 | { |
3370 | Expr *expr = st->expr; | | 3370 | Expr *expr = st->expr; |
3371 | GNode *scope; | | 3371 | GNode *scope; |
3372 | char *val; | | 3372 | char *val; |
3373 | VarParseResult res; | | 3373 | VarParseResult res; |
3374 | | | 3374 | |
3375 | /* TODO: separate parsing from evaluating */ | | | |
3376 | | | | |
3377 | const char *mod = *pp; | | 3375 | const char *mod = *pp; |
3378 | const char *op = mod + 1; | | 3376 | const char *op = mod + 1; |
3379 | | | 3377 | |
3380 | if (op[0] == '=') | | 3378 | if (op[0] == '=') |
3381 | goto ok; | | 3379 | goto ok; |
3382 | if ((op[0] == '!' || op[0] == '+' || op[0] == '?') && op[1] == '=') | | 3380 | if ((op[0] == '!' || op[0] == '+' || op[0] == '?') && op[1] == '=') |
3383 | goto ok; | | 3381 | goto ok; |
3384 | return AMR_UNKNOWN; /* "::<unrecognised>" */ | | 3382 | return AMR_UNKNOWN; /* "::<unrecognised>" */ |
3385 | | | 3383 | |
3386 | ok: | | 3384 | ok: |
3387 | if (expr->var->name.str[0] == '\0') { | | 3385 | if (expr->var->name.str[0] == '\0') { |
3388 | *pp = mod + 1; | | 3386 | *pp = mod + 1; |
3389 | return AMR_BAD; | | 3387 | return AMR_BAD; |
3390 | } | | 3388 | } |
3391 | | | 3389 | |
3392 | scope = expr->scope; /* scope where v belongs */ | | | |
3393 | if (expr->defined == DEF_REGULAR && expr->scope != SCOPE_GLOBAL) { | | | |
3394 | Var *gv = VarFind(expr->var->name.str, expr->scope, FALSE); | | | |
3395 | if (gv == NULL) | | | |
3396 | scope = SCOPE_GLOBAL; | | | |
3397 | else | | | |
3398 | VarFreeEnv(gv); | | | |
3399 | } | | | |
3400 | | | | |
3401 | switch (op[0]) { | | 3390 | switch (op[0]) { |
3402 | case '+': | | 3391 | case '+': |
3403 | case '?': | | 3392 | case '?': |
3404 | case '!': | | 3393 | case '!': |
3405 | *pp = mod + 3; | | 3394 | *pp = mod + 3; |
3406 | break; | | 3395 | break; |
3407 | default: | | 3396 | default: |
3408 | *pp = mod + 2; | | 3397 | *pp = mod + 2; |
3409 | break; | | 3398 | break; |
3410 | } | | 3399 | } |
3411 | | | 3400 | |
3412 | res = ParseModifierPart(pp, st->endc, expr->eflags, st, &val); | | 3401 | res = ParseModifierPart(pp, st->endc, expr->eflags, st, &val); |
3413 | if (res != VPR_OK) | | 3402 | if (res != VPR_OK) |
3414 | return AMR_CLEANUP; | | 3403 | return AMR_CLEANUP; |
3415 | | | 3404 | |
3416 | (*pp)--; /* Go back to the st->endc. */ | | 3405 | (*pp)--; /* Go back to the st->endc. */ |
3417 | | | 3406 | |
| | | 3407 | scope = expr->scope; /* scope where v belongs */ |
| | | 3408 | if (expr->defined == DEF_REGULAR && expr->scope != SCOPE_GLOBAL) { |
| | | 3409 | Var *gv = VarFind(expr->var->name.str, expr->scope, FALSE); |
| | | 3410 | if (gv == NULL) |
| | | 3411 | scope = SCOPE_GLOBAL; |
| | | 3412 | else |
| | | 3413 | VarFreeEnv(gv); |
| | | 3414 | } |
| | | 3415 | |
3418 | /* XXX: Expanding the variable name at this point sounds wrong. */ | | 3416 | /* XXX: Expanding the variable name at this point sounds wrong. */ |
3419 | if (expr->eflags & VARE_WANTRES) { | | 3417 | if (expr->eflags & VARE_WANTRES) { |
3420 | switch (op[0]) { | | 3418 | switch (op[0]) { |
3421 | case '+': | | 3419 | case '+': |
3422 | Var_AppendExpand(scope, expr->var->name.str, val); | | 3420 | Var_AppendExpand(scope, expr->var->name.str, val); |
3423 | break; | | 3421 | break; |
3424 | case '!': { | | 3422 | case '!': { |
3425 | const char *errfmt; | | 3423 | const char *errfmt; |
3426 | char *cmd_output = Cmd_Exec(val, &errfmt); | | 3424 | char *cmd_output = Cmd_Exec(val, &errfmt); |
3427 | if (errfmt != NULL) | | 3425 | if (errfmt != NULL) |
3428 | Error(errfmt, val); | | 3426 | Error(errfmt, val); |
3429 | else | | 3427 | else |
3430 | Var_SetExpand(scope, | | 3428 | Var_SetExpand(scope, |