make: rename context and ctxt to scope
This continues the previous commit, in which VAR_GLOBAL, VAR_INTERNAL and VAR_CMDLINE were renamed. Renaming the variable 'ctxt' was trivial since that word is used nowhere else. In the comments though, each occurrence of the word 'context' had to be checked individually since the word 'context' was not only used for referring to a variable scope. It is also used to distinguish different situations where characters are escaped in a certain way ('parsing context') and in a few other expressions.
This commit is contained in:
parent
480e3d5e6f
commit
4dc2cd5c6f
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: arch.c,v 1.195 2021/02/04 19:50:29 rillig Exp $ */
|
/* $NetBSD: arch.c,v 1.196 2021/02/04 21:42:46 rillig Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1988, 1989, 1990, 1993
|
* Copyright (c) 1988, 1989, 1990, 1993
|
||||||
@ -126,7 +126,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
/* "@(#)arch.c 8.2 (Berkeley) 1/2/94" */
|
/* "@(#)arch.c 8.2 (Berkeley) 1/2/94" */
|
||||||
MAKE_RCSID("$NetBSD: arch.c,v 1.195 2021/02/04 19:50:29 rillig Exp $");
|
MAKE_RCSID("$NetBSD: arch.c,v 1.196 2021/02/04 21:42:46 rillig Exp $");
|
||||||
|
|
||||||
typedef struct List ArchList;
|
typedef struct List ArchList;
|
||||||
typedef struct ListNode ArchListNode;
|
typedef struct ListNode ArchListNode;
|
||||||
@ -176,14 +176,14 @@ ArchFree(void *ap)
|
|||||||
* Input:
|
* Input:
|
||||||
* pp The start of the specification.
|
* pp The start of the specification.
|
||||||
* gns The list on which to place the nodes.
|
* gns The list on which to place the nodes.
|
||||||
* ctxt The context in which to expand variables.
|
* scope The scope in which to expand variables.
|
||||||
*
|
*
|
||||||
* Output:
|
* Output:
|
||||||
* return TRUE if it was a valid specification.
|
* return TRUE if it was a valid specification.
|
||||||
* *pp Points to the first non-space after the archive spec.
|
* *pp Points to the first non-space after the archive spec.
|
||||||
*/
|
*/
|
||||||
Boolean
|
Boolean
|
||||||
Arch_ParseArchive(char **pp, GNodeList *gns, GNode *ctxt)
|
Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
|
||||||
{
|
{
|
||||||
char *cp; /* Pointer into line */
|
char *cp; /* Pointer into line */
|
||||||
GNode *gn; /* New node */
|
GNode *gn; /* New node */
|
||||||
@ -206,7 +206,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *ctxt)
|
|||||||
Boolean isError;
|
Boolean isError;
|
||||||
|
|
||||||
/* XXX: is expanded twice: once here and once below */
|
/* XXX: is expanded twice: once here and once below */
|
||||||
(void)Var_Parse(&nested_p, ctxt,
|
(void)Var_Parse(&nested_p, scope,
|
||||||
VARE_WANTRES | VARE_UNDEFERR, &result);
|
VARE_WANTRES | VARE_UNDEFERR, &result);
|
||||||
/* TODO: handle errors */
|
/* TODO: handle errors */
|
||||||
isError = result.str == var_Error;
|
isError = result.str == var_Error;
|
||||||
@ -223,7 +223,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *ctxt)
|
|||||||
*cp++ = '\0';
|
*cp++ = '\0';
|
||||||
if (expandLibName) {
|
if (expandLibName) {
|
||||||
char *expanded;
|
char *expanded;
|
||||||
(void)Var_Subst(libName.str, ctxt,
|
(void)Var_Subst(libName.str, scope,
|
||||||
VARE_WANTRES | VARE_UNDEFERR, &expanded);
|
VARE_WANTRES | VARE_UNDEFERR, &expanded);
|
||||||
/* TODO: handle errors */
|
/* TODO: handle errors */
|
||||||
libName = MFStr_InitOwn(expanded);
|
libName = MFStr_InitOwn(expanded);
|
||||||
@ -249,7 +249,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *ctxt)
|
|||||||
Boolean isError;
|
Boolean isError;
|
||||||
const char *nested_p = cp;
|
const char *nested_p = cp;
|
||||||
|
|
||||||
(void)Var_Parse(&nested_p, ctxt,
|
(void)Var_Parse(&nested_p, scope,
|
||||||
VARE_WANTRES | VARE_UNDEFERR,
|
VARE_WANTRES | VARE_UNDEFERR,
|
||||||
&result);
|
&result);
|
||||||
/* TODO: handle errors */
|
/* TODO: handle errors */
|
||||||
@ -306,7 +306,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *ctxt)
|
|||||||
char *p;
|
char *p;
|
||||||
char *unexpandedMemName = memName;
|
char *unexpandedMemName = memName;
|
||||||
|
|
||||||
(void)Var_Subst(memName, ctxt,
|
(void)Var_Subst(memName, scope,
|
||||||
VARE_WANTRES | VARE_UNDEFERR,
|
VARE_WANTRES | VARE_UNDEFERR,
|
||||||
&memName);
|
&memName);
|
||||||
/* TODO: handle errors */
|
/* TODO: handle errors */
|
||||||
@ -330,7 +330,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *ctxt)
|
|||||||
gn->type |= OP_ARCHV;
|
gn->type |= OP_ARCHV;
|
||||||
Lst_Append(gns, gn);
|
Lst_Append(gns, gn);
|
||||||
|
|
||||||
} else if (!Arch_ParseArchive(&p, gns, ctxt)) {
|
} else if (!Arch_ParseArchive(&p, gns, scope)) {
|
||||||
/* Error in nested call. */
|
/* Error in nested call. */
|
||||||
free(fullName);
|
free(fullName);
|
||||||
/* XXX: does unexpandedMemName leak? */
|
/* XXX: does unexpandedMemName leak? */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: compat.c,v 1.222 2021/02/02 17:47:56 rillig Exp $ */
|
/* $NetBSD: compat.c,v 1.223 2021/02/04 21:42:46 rillig Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||||
@ -96,7 +96,7 @@
|
|||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
|
|
||||||
/* "@(#)compat.c 8.2 (Berkeley) 3/19/94" */
|
/* "@(#)compat.c 8.2 (Berkeley) 3/19/94" */
|
||||||
MAKE_RCSID("$NetBSD: compat.c,v 1.222 2021/02/02 17:47:56 rillig Exp $");
|
MAKE_RCSID("$NetBSD: compat.c,v 1.223 2021/02/04 21:42:46 rillig Exp $");
|
||||||
|
|
||||||
static GNode *curTarg = NULL;
|
static GNode *curTarg = NULL;
|
||||||
static pid_t compatChild;
|
static pid_t compatChild;
|
||||||
@ -257,7 +257,7 @@ Compat_RunCommand(const char *cmdp, GNode *gn, StringListNode *ln)
|
|||||||
/*
|
/*
|
||||||
* Append the expanded command, to prevent the
|
* Append the expanded command, to prevent the
|
||||||
* local variables from being interpreted in the
|
* local variables from being interpreted in the
|
||||||
* context of the .END node.
|
* scope of the .END node.
|
||||||
*
|
*
|
||||||
* A probably unintended side effect of this is that
|
* A probably unintended side effect of this is that
|
||||||
* the expanded command will be expanded again in the
|
* the expanded command will be expanded again in the
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.\" $NetBSD: make.1,v 1.295 2020/12/23 13:49:12 rillig Exp $
|
.\" $NetBSD: make.1,v 1.296 2021/02/04 21:42:46 rillig Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 1990, 1993
|
.\" Copyright (c) 1990, 1993
|
||||||
.\" The Regents of the University of California. All rights reserved.
|
.\" The Regents of the University of California. All rights reserved.
|
||||||
@ -99,7 +99,7 @@ is equivalent to
|
|||||||
.It Fl D Ar variable
|
.It Fl D Ar variable
|
||||||
Define
|
Define
|
||||||
.Ar variable
|
.Ar variable
|
||||||
to be 1, in the global context.
|
to be 1, in the global scope.
|
||||||
.It Fl d Ar [-]flags
|
.It Fl d Ar [-]flags
|
||||||
Turn on debugging, and specify which portions of
|
Turn on debugging, and specify which portions of
|
||||||
.Nm
|
.Nm
|
||||||
@ -355,7 +355,7 @@ Do not build any targets.
|
|||||||
Multiple instances of this option may be specified;
|
Multiple instances of this option may be specified;
|
||||||
the variables will be printed one per line,
|
the variables will be printed one per line,
|
||||||
with a blank line for each null or undefined variable.
|
with a blank line for each null or undefined variable.
|
||||||
The value printed is extracted from the global context after all
|
The value printed is extracted from the global scope after all
|
||||||
makefiles have been read.
|
makefiles have been read.
|
||||||
By default, the raw variable contents (which may
|
By default, the raw variable contents (which may
|
||||||
include additional unexpanded variable references) are shown.
|
include additional unexpanded variable references) are shown.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: make.c,v 1.240 2021/02/02 21:26:51 rillig Exp $ */
|
/* $NetBSD: make.c,v 1.241 2021/02/04 21:42:46 rillig Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1988, 1989, 1990, 1993
|
* Copyright (c) 1988, 1989, 1990, 1993
|
||||||
@ -78,8 +78,8 @@
|
|||||||
* Make_Update After a target is made, update all its parents.
|
* Make_Update After a target is made, update all its parents.
|
||||||
* Perform various bookkeeping chores like the updating
|
* Perform various bookkeeping chores like the updating
|
||||||
* of the youngestChild field of the parent, filling
|
* of the youngestChild field of the parent, filling
|
||||||
* of the IMPSRC context variable, etc. Place the parent
|
* of the IMPSRC variable, etc. Place the parent on the
|
||||||
* on the toBeMade queue if it should be.
|
* toBeMade queue if it should be.
|
||||||
*
|
*
|
||||||
* GNode_UpdateYoungestChild
|
* GNode_UpdateYoungestChild
|
||||||
* Update the node's youngestChild field based on the
|
* Update the node's youngestChild field based on the
|
||||||
@ -103,7 +103,7 @@
|
|||||||
#include "job.h"
|
#include "job.h"
|
||||||
|
|
||||||
/* "@(#)make.c 8.1 (Berkeley) 6/6/93" */
|
/* "@(#)make.c 8.1 (Berkeley) 6/6/93" */
|
||||||
MAKE_RCSID("$NetBSD: make.c,v 1.240 2021/02/02 21:26:51 rillig Exp $");
|
MAKE_RCSID("$NetBSD: make.c,v 1.241 2021/02/04 21:42:46 rillig Exp $");
|
||||||
|
|
||||||
/* Sequence # to detect recursion. */
|
/* Sequence # to detect recursion. */
|
||||||
static unsigned int checked_seqno = 1;
|
static unsigned int checked_seqno = 1;
|
||||||
@ -1032,9 +1032,9 @@ MakeStartJobs(void)
|
|||||||
if (gn->type & OP_JOIN) {
|
if (gn->type & OP_JOIN) {
|
||||||
/*
|
/*
|
||||||
* Even for an up-to-date .JOIN node, we
|
* Even for an up-to-date .JOIN node, we
|
||||||
* need it to have its context variables so
|
* need it to have its local variables so
|
||||||
* references to it get the correct value
|
* references to it get the correct value
|
||||||
* for .TARGET when building up the context
|
* for .TARGET when building up the local
|
||||||
* variables of its parent(s)...
|
* variables of its parent(s)...
|
||||||
*/
|
*/
|
||||||
Make_DoAllVar(gn);
|
Make_DoAllVar(gn);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: make.h,v 1.252 2021/02/04 21:33:13 rillig Exp $ */
|
/* $NetBSD: make.h,v 1.253 2021/02/04 21:42:46 rillig Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1988, 1989, 1990, 1993
|
* Copyright (c) 1988, 1989, 1990, 1993
|
||||||
@ -500,7 +500,7 @@ extern GNode *defaultNode;
|
|||||||
* by makefiles.
|
* by makefiles.
|
||||||
*/
|
*/
|
||||||
extern GNode *SCOPE_INTERNAL;
|
extern GNode *SCOPE_INTERNAL;
|
||||||
/* Variables defined in a global context, e.g in the Makefile itself. */
|
/* Variables defined in a global scope, e.g in the Makefile itself. */
|
||||||
extern GNode *SCOPE_GLOBAL;
|
extern GNode *SCOPE_GLOBAL;
|
||||||
/* Variables defined on the command line. */
|
/* Variables defined on the command line. */
|
||||||
extern GNode *SCOPE_CMDLINE;
|
extern GNode *SCOPE_CMDLINE;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: parse.c,v 1.545 2021/02/04 21:33:14 rillig Exp $ */
|
/* $NetBSD: parse.c,v 1.546 2021/02/04 21:42:46 rillig Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1988, 1989, 1990, 1993
|
* Copyright (c) 1988, 1989, 1990, 1993
|
||||||
@ -109,7 +109,7 @@
|
|||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
|
|
||||||
/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
|
/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
|
||||||
MAKE_RCSID("$NetBSD: parse.c,v 1.545 2021/02/04 21:33:14 rillig Exp $");
|
MAKE_RCSID("$NetBSD: parse.c,v 1.546 2021/02/04 21:42:46 rillig Exp $");
|
||||||
|
|
||||||
/* types and constants */
|
/* types and constants */
|
||||||
|
|
||||||
@ -1871,13 +1871,13 @@ Parse_IsVar(const char *p, VarAssign *out_var)
|
|||||||
* Check for syntax errors such as unclosed expressions or unknown modifiers.
|
* Check for syntax errors such as unclosed expressions or unknown modifiers.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
VarCheckSyntax(VarAssignOp type, const char *uvalue, GNode *ctxt)
|
VarCheckSyntax(VarAssignOp type, const char *uvalue, GNode *scope)
|
||||||
{
|
{
|
||||||
if (opts.strict) {
|
if (opts.strict) {
|
||||||
if (type != VAR_SUBST && strchr(uvalue, '$') != NULL) {
|
if (type != VAR_SUBST && strchr(uvalue, '$') != NULL) {
|
||||||
char *expandedValue;
|
char *expandedValue;
|
||||||
|
|
||||||
(void)Var_Subst(uvalue, ctxt, VARE_NONE,
|
(void)Var_Subst(uvalue, scope, VARE_NONE,
|
||||||
&expandedValue);
|
&expandedValue);
|
||||||
/* TODO: handle errors */
|
/* TODO: handle errors */
|
||||||
free(expandedValue);
|
free(expandedValue);
|
||||||
@ -1886,7 +1886,7 @@ VarCheckSyntax(VarAssignOp type, const char *uvalue, GNode *ctxt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
VarAssign_EvalSubst(const char *name, const char *uvalue, GNode *ctxt,
|
VarAssign_EvalSubst(const char *name, const char *uvalue, GNode *scope,
|
||||||
FStr *out_avalue)
|
FStr *out_avalue)
|
||||||
{
|
{
|
||||||
char *evalue;
|
char *evalue;
|
||||||
@ -1898,20 +1898,20 @@ VarAssign_EvalSubst(const char *name, const char *uvalue, GNode *ctxt,
|
|||||||
* TODO: Add a test that demonstrates why this code is needed,
|
* TODO: Add a test that demonstrates why this code is needed,
|
||||||
* apart from making the debug log longer.
|
* apart from making the debug log longer.
|
||||||
*/
|
*/
|
||||||
if (!Var_ExistsExpand(name, ctxt))
|
if (!Var_ExistsExpand(name, scope))
|
||||||
Var_SetExpand(name, "", ctxt);
|
Var_SetExpand(name, "", scope);
|
||||||
|
|
||||||
(void)Var_Subst(uvalue, ctxt,
|
(void)Var_Subst(uvalue, scope,
|
||||||
VARE_WANTRES | VARE_KEEP_DOLLAR | VARE_KEEP_UNDEF, &evalue);
|
VARE_WANTRES | VARE_KEEP_DOLLAR | VARE_KEEP_UNDEF, &evalue);
|
||||||
/* TODO: handle errors */
|
/* TODO: handle errors */
|
||||||
|
|
||||||
Var_SetExpand(name, evalue, ctxt);
|
Var_SetExpand(name, evalue, scope);
|
||||||
|
|
||||||
*out_avalue = FStr_InitOwn(evalue);
|
*out_avalue = FStr_InitOwn(evalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
VarAssign_EvalShell(const char *name, const char *uvalue, GNode *ctxt,
|
VarAssign_EvalShell(const char *name, const char *uvalue, GNode *scope,
|
||||||
FStr *out_avalue)
|
FStr *out_avalue)
|
||||||
{
|
{
|
||||||
FStr cmd;
|
FStr cmd;
|
||||||
@ -1928,7 +1928,7 @@ VarAssign_EvalShell(const char *name, const char *uvalue, GNode *ctxt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmdOut = Cmd_Exec(cmd.str, &errfmt);
|
cmdOut = Cmd_Exec(cmd.str, &errfmt);
|
||||||
Var_SetExpand(name, cmdOut, ctxt);
|
Var_SetExpand(name, cmdOut, scope);
|
||||||
*out_avalue = FStr_InitOwn(cmdOut);
|
*out_avalue = FStr_InitOwn(cmdOut);
|
||||||
|
|
||||||
if (errfmt != NULL)
|
if (errfmt != NULL)
|
||||||
@ -1950,22 +1950,22 @@ VarAssign_EvalShell(const char *name, const char *uvalue, GNode *ctxt,
|
|||||||
*/
|
*/
|
||||||
static Boolean
|
static Boolean
|
||||||
VarAssign_Eval(const char *name, VarAssignOp op, const char *uvalue,
|
VarAssign_Eval(const char *name, VarAssignOp op, const char *uvalue,
|
||||||
GNode *ctxt, FStr *out_TRUE_avalue)
|
GNode *scope, FStr *out_TRUE_avalue)
|
||||||
{
|
{
|
||||||
FStr avalue = FStr_InitRefer(uvalue);
|
FStr avalue = FStr_InitRefer(uvalue);
|
||||||
|
|
||||||
if (op == VAR_APPEND)
|
if (op == VAR_APPEND)
|
||||||
Var_AppendExpand(name, uvalue, ctxt);
|
Var_AppendExpand(name, uvalue, scope);
|
||||||
else if (op == VAR_SUBST)
|
else if (op == VAR_SUBST)
|
||||||
VarAssign_EvalSubst(name, uvalue, ctxt, &avalue);
|
VarAssign_EvalSubst(name, uvalue, scope, &avalue);
|
||||||
else if (op == VAR_SHELL)
|
else if (op == VAR_SHELL)
|
||||||
VarAssign_EvalShell(name, uvalue, ctxt, &avalue);
|
VarAssign_EvalShell(name, uvalue, scope, &avalue);
|
||||||
else {
|
else {
|
||||||
if (op == VAR_DEFAULT && Var_ExistsExpand(name, ctxt))
|
if (op == VAR_DEFAULT && Var_ExistsExpand(name, scope))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Normal assignment -- just do it. */
|
/* Normal assignment -- just do it. */
|
||||||
Var_SetExpand(name, uvalue, ctxt);
|
Var_SetExpand(name, uvalue, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
*out_TRUE_avalue = avalue;
|
*out_TRUE_avalue = avalue;
|
||||||
@ -1991,14 +1991,14 @@ VarAssignSpecial(const char *name, const char *avalue)
|
|||||||
Var_ExportVars(avalue);
|
Var_ExportVars(avalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform the variable variable assignment in the given context. */
|
/* Perform the variable variable assignment in the given scope. */
|
||||||
void
|
void
|
||||||
Parse_DoVar(VarAssign *var, GNode *ctxt)
|
Parse_DoVar(VarAssign *var, GNode *scope)
|
||||||
{
|
{
|
||||||
FStr avalue; /* actual value (maybe expanded) */
|
FStr avalue; /* actual value (maybe expanded) */
|
||||||
|
|
||||||
VarCheckSyntax(var->op, var->value, ctxt);
|
VarCheckSyntax(var->op, var->value, scope);
|
||||||
if (VarAssign_Eval(var->varname, var->op, var->value, ctxt, &avalue)) {
|
if (VarAssign_Eval(var->varname, var->op, var->value, scope, &avalue)) {
|
||||||
VarAssignSpecial(var->varname, avalue.str);
|
VarAssignSpecial(var->varname, avalue.str);
|
||||||
FStr_Done(&avalue);
|
FStr_Done(&avalue);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: suff.c,v 1.343 2021/02/03 08:08:18 rillig Exp $ */
|
/* $NetBSD: suff.c,v 1.344 2021/02/04 21:42:46 rillig Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1988, 1989, 1990, 1993
|
* Copyright (c) 1988, 1989, 1990, 1993
|
||||||
@ -114,7 +114,7 @@
|
|||||||
#include "dir.h"
|
#include "dir.h"
|
||||||
|
|
||||||
/* "@(#)suff.c 8.4 (Berkeley) 3/21/94" */
|
/* "@(#)suff.c 8.4 (Berkeley) 3/21/94" */
|
||||||
MAKE_RCSID("$NetBSD: suff.c,v 1.343 2021/02/03 08:08:18 rillig Exp $");
|
MAKE_RCSID("$NetBSD: suff.c,v 1.344 2021/02/04 21:42:46 rillig Exp $");
|
||||||
|
|
||||||
typedef List SuffixList;
|
typedef List SuffixList;
|
||||||
typedef ListNode SuffixListNode;
|
typedef ListNode SuffixListNode;
|
||||||
@ -1388,9 +1388,9 @@ ExpandChildren(GNodeListNode *cln, GNode *pgn)
|
|||||||
|
|
||||||
if (cgn->type & OP_ARCHV) {
|
if (cgn->type & OP_ARCHV) {
|
||||||
/*
|
/*
|
||||||
* Node was an archive(member) target, so we want to
|
* Node was an 'archive(member)' target, so
|
||||||
* call on the Arch module to find the nodes for us,
|
* call on the Arch module to find the nodes for us,
|
||||||
* expanding variables in the parent's context.
|
* expanding variables in the parent's scope.
|
||||||
*/
|
*/
|
||||||
char *p = cp;
|
char *p = cp;
|
||||||
(void)Arch_ParseArchive(&p, &members, pgn);
|
(void)Arch_ParseArchive(&p, &members, pgn);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: targ.c,v 1.164 2021/02/04 21:33:14 rillig Exp $ */
|
/* $NetBSD: targ.c,v 1.165 2021/02/04 21:42:46 rillig Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1988, 1989, 1990, 1993
|
* Copyright (c) 1988, 1989, 1990, 1993
|
||||||
@ -113,7 +113,7 @@
|
|||||||
#include "dir.h"
|
#include "dir.h"
|
||||||
|
|
||||||
/* "@(#)targ.c 8.2 (Berkeley) 3/19/94" */
|
/* "@(#)targ.c 8.2 (Berkeley) 3/19/94" */
|
||||||
MAKE_RCSID("$NetBSD: targ.c,v 1.164 2021/02/04 21:33:14 rillig Exp $");
|
MAKE_RCSID("$NetBSD: targ.c,v 1.165 2021/02/04 21:42:46 rillig Exp $");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All target nodes that appeared on the left-hand side of one of the
|
* All target nodes that appeared on the left-hand side of one of the
|
||||||
@ -246,7 +246,7 @@ GNode_Free(void *gnp)
|
|||||||
* SCOPE_GLOBAL), it should be safe to free the variables as well,
|
* SCOPE_GLOBAL), it should be safe to free the variables as well,
|
||||||
* since each node manages the memory for all its variables itself.
|
* since each node manages the memory for all its variables itself.
|
||||||
*
|
*
|
||||||
* XXX: The GNodes that are only used as variable contexts (VAR_CMD,
|
* XXX: The GNodes that are only used as variable scopes (VAR_CMD,
|
||||||
* SCOPE_GLOBAL, SCOPE_INTERNAL) are not freed at all (see Var_End,
|
* SCOPE_GLOBAL, SCOPE_INTERNAL) are not freed at all (see Var_End,
|
||||||
* where they are not mentioned). These might be freed at all, if
|
* where they are not mentioned). These might be freed at all, if
|
||||||
* their variable values are indeed not used anywhere else (see
|
* their variable values are indeed not used anywhere else (see
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# $NetBSD: envfirst.mk,v 1.4 2020/11/09 20:50:56 rillig Exp $
|
# $NetBSD: envfirst.mk,v 1.5 2021/02/04 21:42:47 rillig Exp $
|
||||||
#
|
#
|
||||||
# The -e option makes environment variables stronger than global variables.
|
# The -e option makes environment variables stronger than global variables.
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ FROM_ENV?= default
|
|||||||
. error ${FROM_ENV}
|
. error ${FROM_ENV}
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
# Even .undef doesn't work since it only affects the global context,
|
# Even .undef doesn't work since it only affects the global scope,
|
||||||
# which is independent from the environment variables.
|
# which is independent from the environment variables.
|
||||||
.undef FROM_ENV
|
.undef FROM_ENV
|
||||||
.if ${FROM_ENV} != value-from-env
|
.if ${FROM_ENV} != value-from-env
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# $NetBSD: vardebug.mk,v 1.6 2020/10/31 13:15:10 rillig Exp $
|
# $NetBSD: vardebug.mk,v 1.7 2021/02/04 21:42:47 rillig Exp $
|
||||||
#
|
#
|
||||||
# Demonstrates the debugging output for var.c.
|
# Demonstrates the debugging output for var.c.
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ VAR+= 3
|
|||||||
.endif
|
.endif
|
||||||
|
|
||||||
# By default, .SHELL is not defined and thus can be set. As soon as it is
|
# By default, .SHELL is not defined and thus can be set. As soon as it is
|
||||||
# accessed, it is initialized in the command line context (during VarFind),
|
# accessed, it is initialized in the command line scope (during VarFind),
|
||||||
# where it is set to read-only. Assigning to it is ignored.
|
# where it is set to read-only. Assigning to it is ignored.
|
||||||
.MAKEFLAGS: .SHELL=overwritten
|
.MAKEFLAGS: .SHELL=overwritten
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# $NetBSD: varmisc.mk,v 1.29 2020/11/28 14:08:37 rillig Exp $
|
# $NetBSD: varmisc.mk,v 1.30 2021/02/04 21:42:47 rillig Exp $
|
||||||
#
|
#
|
||||||
# Miscellaneous variable tests.
|
# Miscellaneous variable tests.
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ VAR.${param}= ${param}
|
|||||||
.endif
|
.endif
|
||||||
|
|
||||||
# Appending to a variable from the environment creates a copy of that variable
|
# Appending to a variable from the environment creates a copy of that variable
|
||||||
# in the global context.
|
# in the global scope.
|
||||||
# The appended value is not exported automatically.
|
# The appended value is not exported automatically.
|
||||||
# When a variable is exported, the exported value is taken at the time of the
|
# When a variable is exported, the exported value is taken at the time of the
|
||||||
# .export directive. Later changes to the variable have no effect.
|
# .export directive. Later changes to the variable have no effect.
|
||||||
@ -152,8 +152,8 @@ export-appended:
|
|||||||
# begin parse-dynamic
|
# begin parse-dynamic
|
||||||
#
|
#
|
||||||
# Demonstrate that the target-specific variables are not evaluated in
|
# Demonstrate that the target-specific variables are not evaluated in
|
||||||
# the global context. They are preserved until there is a local context
|
# the global scope. Their expressions are preserved until there is a local
|
||||||
# in which resolving them makes sense.
|
# scope in which resolving them makes sense.
|
||||||
|
|
||||||
# There are different code paths for short names ...
|
# There are different code paths for short names ...
|
||||||
${:U>}= before
|
${:U>}= before
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# $NetBSD: varmod-loop.mk,v 1.8 2020/11/12 00:40:55 rillig Exp $
|
# $NetBSD: varmod-loop.mk,v 1.9 2021/02/04 21:42:47 rillig Exp $
|
||||||
#
|
#
|
||||||
# Tests for the :@var@...${var}...@ variable modifier.
|
# Tests for the :@var@...${var}...@ variable modifier.
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ mod-loop-varname:
|
|||||||
@echo empty: :${:U1 2 3:@@x${}y@}:
|
@echo empty: :${:U1 2 3:@@x${}y@}:
|
||||||
|
|
||||||
# The :@ modifier resolves the variables a little more often than expected.
|
# The :@ modifier resolves the variables a little more often than expected.
|
||||||
# In particular, it resolves _all_ variables from the context, and not only
|
# In particular, it resolves _all_ variables from the scope, and not only
|
||||||
# the loop variable (in this case v).
|
# the loop variable (in this case v).
|
||||||
#
|
#
|
||||||
# The d means direct reference, the i means indirect reference.
|
# The d means direct reference, the i means indirect reference.
|
||||||
@ -77,7 +77,7 @@ mod-loop-dollar:
|
|||||||
# for the loop variable. These modifiers influence each other.
|
# for the loop variable. These modifiers influence each other.
|
||||||
#
|
#
|
||||||
# As of 2020-10-18, the :@ modifier is implemented by actually setting a
|
# As of 2020-10-18, the :@ modifier is implemented by actually setting a
|
||||||
# variable in the context of the expression and deleting it again after the
|
# variable in the scope of the expression and deleting it again after the
|
||||||
# loop. This is different from the .for loops, which substitute the variable
|
# loop. This is different from the .for loops, which substitute the variable
|
||||||
# expression with ${:Uvalue}, leading to different unwanted side effects.
|
# expression with ${:Uvalue}, leading to different unwanted side effects.
|
||||||
#
|
#
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# $NetBSD: varname-dot-shell.mk,v 1.6 2020/10/30 16:09:56 rillig Exp $
|
# $NetBSD: varname-dot-shell.mk,v 1.7 2021/02/04 21:42:47 rillig Exp $
|
||||||
#
|
#
|
||||||
# Tests for the special .SHELL variable, which contains the shell used for
|
# Tests for the special .SHELL variable, which contains the shell used for
|
||||||
# running the commands.
|
# running the commands.
|
||||||
@ -22,8 +22,8 @@ ORIG_SHELL:= ${.SHELL}
|
|||||||
.endif
|
.endif
|
||||||
|
|
||||||
# Trying to delete the variable.
|
# Trying to delete the variable.
|
||||||
# This has no effect since the variable is not defined in the global context,
|
# This has no effect since the variable is not defined in the global scope,
|
||||||
# but in the command-line context.
|
# but in the command-line scope.
|
||||||
.undef .SHELL
|
.undef .SHELL
|
||||||
.SHELL= newly overwritten
|
.SHELL= newly overwritten
|
||||||
.if ${.SHELL} != ${ORIG_SHELL}
|
.if ${.SHELL} != ${ORIG_SHELL}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# $NetBSD: varparse-dynamic.mk,v 1.3 2020/11/21 15:48:05 rillig Exp $
|
# $NetBSD: varparse-dynamic.mk,v 1.4 2021/02/04 21:42:47 rillig Exp $
|
||||||
|
|
||||||
# Before 2020-07-27, there was an off-by-one error in Var_Parse that skipped
|
# Before 2020-07-27, there was an off-by-one error in Var_Parse that skipped
|
||||||
# the last character in the variable name.
|
# the last character in the variable name.
|
||||||
@ -11,7 +11,7 @@
|
|||||||
.endif
|
.endif
|
||||||
|
|
||||||
# When a dynamic variable (such as .TARGET) is evaluated in the global
|
# When a dynamic variable (such as .TARGET) is evaluated in the global
|
||||||
# context, it is not yet ready to be expanded. Therefore the complete
|
# scope, it is not yet ready to be expanded. Therefore the complete
|
||||||
# expression is returned as the variable value, hoping that it can be
|
# expression is returned as the variable value, hoping that it can be
|
||||||
# resolved at a later point.
|
# resolved at a later point.
|
||||||
#
|
#
|
||||||
@ -21,7 +21,7 @@
|
|||||||
. error
|
. error
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
# If a dynamic variable is expanded in a non-local context, the expression
|
# If a dynamic variable is expanded in a non-local scope, the expression
|
||||||
# based on this variable is not expanded. But there may be nested variable
|
# based on this variable is not expanded. But there may be nested variable
|
||||||
# expressions in the modifiers, and these are kept unexpanded as well.
|
# expressions in the modifiers, and these are kept unexpanded as well.
|
||||||
.if ${.TARGET:M${:Ufallback}} != "\${.TARGET:M\${:Ufallback}}"
|
.if ${.TARGET:M${:Ufallback}} != "\${.TARGET:M\${:Ufallback}}"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: var.c,v 1.801 2021/02/04 21:33:14 rillig Exp $ */
|
/* $NetBSD: var.c,v 1.802 2021/02/04 21:42:46 rillig Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1988, 1989, 1990, 1993
|
* Copyright (c) 1988, 1989, 1990, 1993
|
||||||
@ -118,7 +118,7 @@
|
|||||||
* Debugging:
|
* Debugging:
|
||||||
* Var_Stats Print out hashing statistics if in -dh mode.
|
* Var_Stats Print out hashing statistics if in -dh mode.
|
||||||
*
|
*
|
||||||
* Var_Dump Print out all variables defined in the given context.
|
* Var_Dump Print out all variables defined in the given scope.
|
||||||
*
|
*
|
||||||
* XXX: There's a lot of duplication in these functions.
|
* XXX: There's a lot of duplication in these functions.
|
||||||
*/
|
*/
|
||||||
@ -139,7 +139,7 @@
|
|||||||
#include "metachar.h"
|
#include "metachar.h"
|
||||||
|
|
||||||
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
|
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
|
||||||
MAKE_RCSID("$NetBSD: var.c,v 1.801 2021/02/04 21:33:14 rillig Exp $");
|
MAKE_RCSID("$NetBSD: var.c,v 1.802 2021/02/04 21:42:46 rillig Exp $");
|
||||||
|
|
||||||
typedef enum VarFlags {
|
typedef enum VarFlags {
|
||||||
VAR_NONE = 0,
|
VAR_NONE = 0,
|
||||||
@ -187,11 +187,11 @@ typedef enum VarFlags {
|
|||||||
* value can be queried by expressions such as $V, ${VAR}, or with modifiers
|
* value can be queried by expressions such as $V, ${VAR}, or with modifiers
|
||||||
* such as ${VAR:S,from,to,g:Q}.
|
* such as ${VAR:S,from,to,g:Q}.
|
||||||
*
|
*
|
||||||
* There are 3 kinds of variables: context variables, environment variables,
|
* There are 3 kinds of variables: scope variables, environment variables,
|
||||||
* undefined variables.
|
* undefined variables.
|
||||||
*
|
*
|
||||||
* Context variables are stored in a GNode.context. The only way to undefine
|
* Scope variables are stored in a GNode.scope. The only way to undefine
|
||||||
* a context variable is using the .undef directive. In particular, it must
|
* a scope variable is using the .undef directive. In particular, it must
|
||||||
* not be possible to undefine a variable during the evaluation of an
|
* not be possible to undefine a variable during the evaluation of an
|
||||||
* expression, or Var.name might point nowhere.
|
* expression, or Var.name might point nowhere.
|
||||||
*
|
*
|
||||||
@ -204,7 +204,7 @@ typedef enum VarFlags {
|
|||||||
typedef struct Var {
|
typedef struct Var {
|
||||||
/*
|
/*
|
||||||
* The name of the variable, once set, doesn't change anymore.
|
* The name of the variable, once set, doesn't change anymore.
|
||||||
* For context variables, it aliases the corresponding HashEntry name.
|
* For scope variables, it aliases the corresponding HashEntry name.
|
||||||
* For environment and undefined variables, it is allocated.
|
* For environment and undefined variables, it is allocated.
|
||||||
*/
|
*/
|
||||||
FStr name;
|
FStr name;
|
||||||
@ -289,18 +289,17 @@ static char varUndefined[] = "";
|
|||||||
static Boolean save_dollars = TRUE;
|
static Boolean save_dollars = TRUE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internally, variables are contained in four different contexts.
|
* Internally, variables are contained in four different scopes.
|
||||||
* 1) the environment. They cannot be changed. If an environment
|
* 1) the environment. They cannot be changed. If an environment
|
||||||
* variable is appended to, the result is placed in the global
|
* variable is appended to, the result is placed in the global
|
||||||
* context.
|
* scope.
|
||||||
* 2) the global context. Variables set in the makefiles are located
|
* 2) the global scope. Variables set in the makefiles are located
|
||||||
* here.
|
* here.
|
||||||
* 3) the command-line context. All variables set on the command line
|
* 3) the command-line scope. All variables set on the command line
|
||||||
* are placed in this context.
|
* are placed in this scope.
|
||||||
* 4) the local context. Each target has associated with it a context
|
* 4) the local scope, containing only the 7 local variables such as
|
||||||
* list. On this list are located the structures describing such
|
* '.TARGET'.
|
||||||
* local variables as $(@) and $(*)
|
* The four scopes are searched in the reverse order from which they are
|
||||||
* The four contexts are searched in the reverse order from which they are
|
|
||||||
* listed (but see opts.checkEnvFirst).
|
* listed (but see opts.checkEnvFirst).
|
||||||
*/
|
*/
|
||||||
GNode *SCOPE_INTERNAL; /* variables from make itself */
|
GNode *SCOPE_INTERNAL; /* variables from make itself */
|
||||||
@ -372,18 +371,18 @@ CanonicalVarname(const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Var *
|
static Var *
|
||||||
GNode_FindVar(GNode *ctxt, const char *varname, unsigned int hash)
|
GNode_FindVar(GNode *scope, const char *varname, unsigned int hash)
|
||||||
{
|
{
|
||||||
return HashTable_FindValueHash(&ctxt->vars, varname, hash);
|
return HashTable_FindValueHash(&scope->vars, varname, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the variable in the context, and maybe in other contexts as well.
|
* Find the variable in the scope, and maybe in other scopes as well.
|
||||||
*
|
*
|
||||||
* Input:
|
* Input:
|
||||||
* name name to find, is not expanded any further
|
* name name to find, is not expanded any further
|
||||||
* ctxt context in which to look first
|
* scope scope in which to look first
|
||||||
* elsewhere TRUE to look in other contexts as well
|
* elsewhere TRUE to look in other scopes as well
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* The found variable, or NULL if the variable does not exist.
|
* The found variable, or NULL if the variable does not exist.
|
||||||
@ -391,7 +390,7 @@ GNode_FindVar(GNode *ctxt, const char *varname, unsigned int hash)
|
|||||||
* VarFreeEnv after use.
|
* VarFreeEnv after use.
|
||||||
*/
|
*/
|
||||||
static Var *
|
static Var *
|
||||||
VarFind(const char *name, GNode *ctxt, Boolean elsewhere)
|
VarFind(const char *name, GNode *scope, Boolean elsewhere)
|
||||||
{
|
{
|
||||||
Var *var;
|
Var *var;
|
||||||
unsigned int nameHash;
|
unsigned int nameHash;
|
||||||
@ -405,21 +404,21 @@ VarFind(const char *name, GNode *ctxt, Boolean elsewhere)
|
|||||||
name = CanonicalVarname(name);
|
name = CanonicalVarname(name);
|
||||||
nameHash = Hash_Hash(name);
|
nameHash = Hash_Hash(name);
|
||||||
|
|
||||||
/* First look for the variable in the given context. */
|
/* First look for the variable in the given scope. */
|
||||||
var = GNode_FindVar(ctxt, name, nameHash);
|
var = GNode_FindVar(scope, name, nameHash);
|
||||||
if (!elsewhere)
|
if (!elsewhere)
|
||||||
return var;
|
return var;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The variable was not found in the given context.
|
* The variable was not found in the given scope.
|
||||||
* Now look for it in the other contexts as well.
|
* Now look for it in the other scopes as well.
|
||||||
*/
|
*/
|
||||||
if (var == NULL && ctxt != SCOPE_CMDLINE)
|
if (var == NULL && scope != SCOPE_CMDLINE)
|
||||||
var = GNode_FindVar(SCOPE_CMDLINE, name, nameHash);
|
var = GNode_FindVar(SCOPE_CMDLINE, name, nameHash);
|
||||||
|
|
||||||
if (!opts.checkEnvFirst && var == NULL && ctxt != SCOPE_GLOBAL) {
|
if (!opts.checkEnvFirst && var == NULL && scope != SCOPE_GLOBAL) {
|
||||||
var = GNode_FindVar(SCOPE_GLOBAL, name, nameHash);
|
var = GNode_FindVar(SCOPE_GLOBAL, name, nameHash);
|
||||||
if (var == NULL && ctxt != SCOPE_INTERNAL) {
|
if (var == NULL && scope != SCOPE_INTERNAL) {
|
||||||
/* SCOPE_INTERNAL is subordinate to SCOPE_GLOBAL */
|
/* SCOPE_INTERNAL is subordinate to SCOPE_GLOBAL */
|
||||||
var = GNode_FindVar(SCOPE_INTERNAL, name, nameHash);
|
var = GNode_FindVar(SCOPE_INTERNAL, name, nameHash);
|
||||||
}
|
}
|
||||||
@ -433,9 +432,9 @@ VarFind(const char *name, GNode *ctxt, Boolean elsewhere)
|
|||||||
return VarNew(FStr_InitOwn(varname), env, VAR_FROM_ENV);
|
return VarNew(FStr_InitOwn(varname), env, VAR_FROM_ENV);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.checkEnvFirst && ctxt != SCOPE_GLOBAL) {
|
if (opts.checkEnvFirst && scope != SCOPE_GLOBAL) {
|
||||||
var = GNode_FindVar(SCOPE_GLOBAL, name, nameHash);
|
var = GNode_FindVar(SCOPE_GLOBAL, name, nameHash);
|
||||||
if (var == NULL && ctxt != SCOPE_INTERNAL)
|
if (var == NULL && scope != SCOPE_INTERNAL)
|
||||||
var = GNode_FindVar(SCOPE_INTERNAL, name,
|
var = GNode_FindVar(SCOPE_INTERNAL, name,
|
||||||
nameHash);
|
nameHash);
|
||||||
return var;
|
return var;
|
||||||
@ -473,52 +472,52 @@ VarFreeEnv(Var *v, Boolean freeValue)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a new variable of the given name and value to the given context.
|
* Add a new variable of the given name and value to the given scope.
|
||||||
* The name and val arguments are duplicated so they may safely be freed.
|
* The name and val arguments are duplicated so they may safely be freed.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
VarAdd(const char *name, const char *val, GNode *ctxt, VarSetFlags flags)
|
VarAdd(const char *name, const char *val, GNode *scope, VarSetFlags flags)
|
||||||
{
|
{
|
||||||
HashEntry *he = HashTable_CreateEntry(&ctxt->vars, name, NULL);
|
HashEntry *he = HashTable_CreateEntry(&scope->vars, name, NULL);
|
||||||
Var *v = VarNew(FStr_InitRefer(/* aliased to */ he->key), val,
|
Var *v = VarNew(FStr_InitRefer(/* aliased to */ he->key), val,
|
||||||
flags & VAR_SET_READONLY ? VAR_READONLY : VAR_NONE);
|
flags & VAR_SET_READONLY ? VAR_READONLY : VAR_NONE);
|
||||||
HashEntry_Set(he, v);
|
HashEntry_Set(he, v);
|
||||||
DEBUG3(VAR, "%s:%s = %s\n", ctxt->name, name, val);
|
DEBUG3(VAR, "%s:%s = %s\n", scope->name, name, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove a variable from a context, freeing all related memory as well.
|
* Remove a variable from a scope, freeing all related memory as well.
|
||||||
* The variable name is kept as-is, it is not expanded.
|
* The variable name is kept as-is, it is not expanded.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
Var_Delete(const char *varname, GNode *ctxt)
|
Var_Delete(const char *varname, GNode *scope)
|
||||||
{
|
{
|
||||||
HashEntry *he = HashTable_FindEntry(&ctxt->vars, varname);
|
HashEntry *he = HashTable_FindEntry(&scope->vars, varname);
|
||||||
Var *v;
|
Var *v;
|
||||||
|
|
||||||
if (he == NULL) {
|
if (he == NULL) {
|
||||||
DEBUG2(VAR, "%s:delete %s (not found)\n", ctxt->name, varname);
|
DEBUG2(VAR, "%s:delete %s (not found)\n", scope->name, varname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG2(VAR, "%s:delete %s\n", ctxt->name, varname);
|
DEBUG2(VAR, "%s:delete %s\n", scope->name, varname);
|
||||||
v = HashEntry_Get(he);
|
v = HashEntry_Get(he);
|
||||||
if (v->flags & VAR_EXPORTED)
|
if (v->flags & VAR_EXPORTED)
|
||||||
unsetenv(v->name.str);
|
unsetenv(v->name.str);
|
||||||
if (strcmp(v->name.str, MAKE_EXPORTED) == 0)
|
if (strcmp(v->name.str, MAKE_EXPORTED) == 0)
|
||||||
var_exportedVars = VAR_EXPORTED_NONE;
|
var_exportedVars = VAR_EXPORTED_NONE;
|
||||||
assert(v->name.freeIt == NULL);
|
assert(v->name.freeIt == NULL);
|
||||||
HashTable_DeleteEntry(&ctxt->vars, he);
|
HashTable_DeleteEntry(&scope->vars, he);
|
||||||
Buf_Done(&v->val);
|
Buf_Done(&v->val);
|
||||||
free(v);
|
free(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove a variable from a context, freeing all related memory as well.
|
* Remove a variable from a scope, freeing all related memory as well.
|
||||||
* The variable name is expanded once.
|
* The variable name is expanded once.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
Var_DeleteExpand(const char *name, GNode *ctxt)
|
Var_DeleteExpand(const char *name, GNode *scope)
|
||||||
{
|
{
|
||||||
FStr varname = FStr_InitRefer(name);
|
FStr varname = FStr_InitRefer(name);
|
||||||
|
|
||||||
@ -530,7 +529,7 @@ Var_DeleteExpand(const char *name, GNode *ctxt)
|
|||||||
varname = FStr_InitOwn(expanded);
|
varname = FStr_InitOwn(expanded);
|
||||||
}
|
}
|
||||||
|
|
||||||
Var_Delete(varname.str, ctxt);
|
Var_Delete(varname.str, scope);
|
||||||
FStr_Done(&varname);
|
FStr_Done(&varname);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,8 +581,8 @@ MayExport(const char *name)
|
|||||||
if (name[1] == '\0') {
|
if (name[1] == '\0') {
|
||||||
/*
|
/*
|
||||||
* A single char.
|
* A single char.
|
||||||
* If it is one of the vars that should only appear in
|
* If it is one of the variables that should only appear in
|
||||||
* local context, skip it, else we can get Var_Subst
|
* local scope, skip it, else we can get Var_Subst
|
||||||
* into a loop.
|
* into a loop.
|
||||||
*/
|
*/
|
||||||
switch (name[0]) {
|
switch (name[0]) {
|
||||||
@ -920,7 +919,7 @@ Var_UnExport(Boolean isEnv, const char *arg)
|
|||||||
|
|
||||||
/* Set the variable to the value; the name is not expanded. */
|
/* Set the variable to the value; the name is not expanded. */
|
||||||
void
|
void
|
||||||
Var_SetWithFlags(const char *name, const char *val, GNode *ctxt,
|
Var_SetWithFlags(const char *name, const char *val, GNode *scope,
|
||||||
VarSetFlags flags)
|
VarSetFlags flags)
|
||||||
{
|
{
|
||||||
Var *v;
|
Var *v;
|
||||||
@ -931,12 +930,12 @@ Var_SetWithFlags(const char *name, const char *val, GNode *ctxt,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxt == SCOPE_GLOBAL) {
|
if (scope == SCOPE_GLOBAL) {
|
||||||
v = VarFind(name, SCOPE_CMDLINE, FALSE);
|
v = VarFind(name, SCOPE_CMDLINE, FALSE);
|
||||||
if (v != NULL) {
|
if (v != NULL) {
|
||||||
if (v->flags & VAR_FROM_CMD) {
|
if (v->flags & VAR_FROM_CMD) {
|
||||||
DEBUG3(VAR, "%s:%s = %s ignored!\n",
|
DEBUG3(VAR, "%s:%s = %s ignored!\n",
|
||||||
ctxt->name, name, val);
|
scope->name, name, val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
VarFreeEnv(v, TRUE);
|
VarFreeEnv(v, TRUE);
|
||||||
@ -944,13 +943,13 @@ Var_SetWithFlags(const char *name, const char *val, GNode *ctxt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We only look for a variable in the given context since anything set
|
* Only look for a variable in the given scope since anything set
|
||||||
* here will override anything in a lower context, so there's not much
|
* here will override anything in a lower scope, so there's not much
|
||||||
* point in searching them all just to save a bit of memory...
|
* point in searching them all just to save a bit of memory...
|
||||||
*/
|
*/
|
||||||
v = VarFind(name, ctxt, FALSE);
|
v = VarFind(name, scope, FALSE);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
if (ctxt == SCOPE_CMDLINE && !(flags & VAR_SET_NO_EXPORT)) {
|
if (scope == SCOPE_CMDLINE && !(flags & VAR_SET_NO_EXPORT)) {
|
||||||
/*
|
/*
|
||||||
* This var would normally prevent the same name being
|
* This var would normally prevent the same name being
|
||||||
* added to SCOPE_GLOBAL, so delete it from there if
|
* added to SCOPE_GLOBAL, so delete it from there if
|
||||||
@ -959,17 +958,17 @@ Var_SetWithFlags(const char *name, const char *val, GNode *ctxt,
|
|||||||
/* XXX: name is expanded for the second time */
|
/* XXX: name is expanded for the second time */
|
||||||
Var_DeleteExpand(name, SCOPE_GLOBAL);
|
Var_DeleteExpand(name, SCOPE_GLOBAL);
|
||||||
}
|
}
|
||||||
VarAdd(name, val, ctxt, flags);
|
VarAdd(name, val, scope, flags);
|
||||||
} else {
|
} else {
|
||||||
if ((v->flags & VAR_READONLY) && !(flags & VAR_SET_READONLY)) {
|
if ((v->flags & VAR_READONLY) && !(flags & VAR_SET_READONLY)) {
|
||||||
DEBUG3(VAR, "%s:%s = %s ignored (read-only)\n",
|
DEBUG3(VAR, "%s:%s = %s ignored (read-only)\n",
|
||||||
ctxt->name, name, val);
|
scope->name, name, val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Buf_Empty(&v->val);
|
Buf_Empty(&v->val);
|
||||||
Buf_AddStr(&v->val, val);
|
Buf_AddStr(&v->val, val);
|
||||||
|
|
||||||
DEBUG3(VAR, "%s:%s = %s\n", ctxt->name, name, val);
|
DEBUG3(VAR, "%s:%s = %s\n", scope->name, name, val);
|
||||||
if (v->flags & VAR_EXPORTED)
|
if (v->flags & VAR_EXPORTED)
|
||||||
ExportVar(name, VEM_PLAIN);
|
ExportVar(name, VEM_PLAIN);
|
||||||
}
|
}
|
||||||
@ -978,10 +977,10 @@ Var_SetWithFlags(const char *name, const char *val, GNode *ctxt,
|
|||||||
* to the environment (as per POSIX standard)
|
* to the environment (as per POSIX standard)
|
||||||
* Other than internals.
|
* Other than internals.
|
||||||
*/
|
*/
|
||||||
if (ctxt == SCOPE_CMDLINE && !(flags & VAR_SET_NO_EXPORT) &&
|
if (scope == SCOPE_CMDLINE && !(flags & VAR_SET_NO_EXPORT) &&
|
||||||
name[0] != '.') {
|
name[0] != '.') {
|
||||||
if (v == NULL)
|
if (v == NULL)
|
||||||
v = VarFind(name, ctxt, FALSE); /* we just added it */
|
v = VarFind(name, scope, FALSE); /* we just added it */
|
||||||
v->flags |= VAR_FROM_CMD;
|
v->flags |= VAR_FROM_CMD;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1004,7 +1003,7 @@ Var_SetWithFlags(const char *name, const char *val, GNode *ctxt,
|
|||||||
|
|
||||||
/* See Var_Set for documentation. */
|
/* See Var_Set for documentation. */
|
||||||
void
|
void
|
||||||
Var_SetExpandWithFlags(const char *name, const char *val, GNode *ctxt,
|
Var_SetExpandWithFlags(const char *name, const char *val, GNode *scope,
|
||||||
VarSetFlags flags)
|
VarSetFlags flags)
|
||||||
{
|
{
|
||||||
const char *unexpanded_name = name;
|
const char *unexpanded_name = name;
|
||||||
@ -1014,7 +1013,7 @@ Var_SetExpandWithFlags(const char *name, const char *val, GNode *ctxt,
|
|||||||
|
|
||||||
if (strchr(varname.str, '$') != NULL) {
|
if (strchr(varname.str, '$') != NULL) {
|
||||||
char *expanded;
|
char *expanded;
|
||||||
(void)Var_Subst(varname.str, ctxt, VARE_WANTRES, &expanded);
|
(void)Var_Subst(varname.str, scope, VARE_WANTRES, &expanded);
|
||||||
/* TODO: handle errors */
|
/* TODO: handle errors */
|
||||||
varname = FStr_InitOwn(expanded);
|
varname = FStr_InitOwn(expanded);
|
||||||
}
|
}
|
||||||
@ -1024,19 +1023,19 @@ Var_SetExpandWithFlags(const char *name, const char *val, GNode *ctxt,
|
|||||||
"name expands to empty string - ignored\n",
|
"name expands to empty string - ignored\n",
|
||||||
unexpanded_name, val);
|
unexpanded_name, val);
|
||||||
} else
|
} else
|
||||||
Var_SetWithFlags(varname.str, val, ctxt, flags);
|
Var_SetWithFlags(varname.str, val, scope, flags);
|
||||||
|
|
||||||
FStr_Done(&varname);
|
FStr_Done(&varname);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Var_Set(const char *name, const char *val, GNode *ctxt)
|
Var_Set(const char *name, const char *val, GNode *scope)
|
||||||
{
|
{
|
||||||
Var_SetWithFlags(name, val, ctxt, VAR_SET_NONE);
|
Var_SetWithFlags(name, val, scope, VAR_SET_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the variable name to the value val in the given context.
|
* Set the variable name to the value val in the given scope.
|
||||||
*
|
*
|
||||||
* If the variable doesn't yet exist, it is created.
|
* If the variable doesn't yet exist, it is created.
|
||||||
* Otherwise the new value overwrites and replaces the old value.
|
* Otherwise the new value overwrites and replaces the old value.
|
||||||
@ -1044,12 +1043,12 @@ Var_Set(const char *name, const char *val, GNode *ctxt)
|
|||||||
* Input:
|
* Input:
|
||||||
* name name of the variable to set, is expanded once
|
* name name of the variable to set, is expanded once
|
||||||
* val value to give to the variable
|
* val value to give to the variable
|
||||||
* ctxt context in which to set it
|
* scope scope in which to set it
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
Var_SetExpand(const char *name, const char *val, GNode *ctxt)
|
Var_SetExpand(const char *name, const char *val, GNode *scope)
|
||||||
{
|
{
|
||||||
Var_SetExpandWithFlags(name, val, ctxt, VAR_SET_NONE);
|
Var_SetExpandWithFlags(name, val, scope, VAR_SET_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1071,27 +1070,27 @@ Global_SetExpand(const char *name, const char *value)
|
|||||||
* and the given value are appended.
|
* and the given value are appended.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
Var_Append(const char *name, const char *val, GNode *ctxt)
|
Var_Append(const char *name, const char *val, GNode *scope)
|
||||||
{
|
{
|
||||||
Var *v;
|
Var *v;
|
||||||
|
|
||||||
v = VarFind(name, ctxt, ctxt == SCOPE_GLOBAL);
|
v = VarFind(name, scope, scope == SCOPE_GLOBAL);
|
||||||
|
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
Var_SetWithFlags(name, val, ctxt, VAR_SET_NONE);
|
Var_SetWithFlags(name, val, scope, VAR_SET_NONE);
|
||||||
} else if (v->flags & VAR_READONLY) {
|
} else if (v->flags & VAR_READONLY) {
|
||||||
DEBUG1(VAR, "Ignoring append to %s since it is read-only\n",
|
DEBUG1(VAR, "Ignoring append to %s since it is read-only\n",
|
||||||
name);
|
name);
|
||||||
} else if (ctxt == SCOPE_CMDLINE || !(v->flags & VAR_FROM_CMD)) {
|
} else if (scope == SCOPE_CMDLINE || !(v->flags & VAR_FROM_CMD)) {
|
||||||
Buf_AddByte(&v->val, ' ');
|
Buf_AddByte(&v->val, ' ');
|
||||||
Buf_AddStr(&v->val, val);
|
Buf_AddStr(&v->val, val);
|
||||||
|
|
||||||
DEBUG3(VAR, "%s:%s = %s\n", ctxt->name, name, v->val.data);
|
DEBUG3(VAR, "%s:%s = %s\n", scope->name, name, v->val.data);
|
||||||
|
|
||||||
if (v->flags & VAR_FROM_ENV) {
|
if (v->flags & VAR_FROM_ENV) {
|
||||||
/*
|
/*
|
||||||
* If the original variable came from the environment,
|
* If the original variable came from the environment,
|
||||||
* we have to install it in the global context (we
|
* we have to install it in the global scope (we
|
||||||
* could place it in the environment, but then we
|
* could place it in the environment, but then we
|
||||||
* should provide a way to export other variables...)
|
* should provide a way to export other variables...)
|
||||||
*/
|
*/
|
||||||
@ -1099,16 +1098,16 @@ Var_Append(const char *name, const char *val, GNode *ctxt)
|
|||||||
/*
|
/*
|
||||||
* This is the only place where a variable is
|
* This is the only place where a variable is
|
||||||
* created whose v->name is not the same as
|
* created whose v->name is not the same as
|
||||||
* ctxt->context->key.
|
* scope->vars->key.
|
||||||
*/
|
*/
|
||||||
HashTable_Set(&ctxt->vars, name, v);
|
HashTable_Set(&scope->vars, name, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The variable of the given name has the given value appended to it in the
|
* The variable of the given name has the given value appended to it in the
|
||||||
* given context.
|
* given scope.
|
||||||
*
|
*
|
||||||
* If the variable doesn't exist, it is created. Otherwise the strings are
|
* If the variable doesn't exist, it is created. Otherwise the strings are
|
||||||
* concatenated, with a space in between.
|
* concatenated, with a space in between.
|
||||||
@ -1116,18 +1115,18 @@ Var_Append(const char *name, const char *val, GNode *ctxt)
|
|||||||
* Input:
|
* Input:
|
||||||
* name name of the variable to modify, is expanded once
|
* name name of the variable to modify, is expanded once
|
||||||
* val string to append to it
|
* val string to append to it
|
||||||
* ctxt context in which this should occur
|
* scope scope in which this should occur
|
||||||
*
|
*
|
||||||
* Notes:
|
* Notes:
|
||||||
* Only if the variable is being sought in the global context is the
|
* Only if the variable is being sought in the global scope is the
|
||||||
* environment searched.
|
* environment searched.
|
||||||
* XXX: Knows its calling circumstances in that if called with ctxt
|
* XXX: Knows its calling circumstances in that if called with scope
|
||||||
* an actual target, it will only search that context since only
|
* an actual target, it will only search that scope since only
|
||||||
* a local variable could be being appended to. This is actually
|
* a local variable could be being appended to. This is actually
|
||||||
* a big win and must be tolerated.
|
* a big win and must be tolerated.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
Var_AppendExpand(const char *name, const char *val, GNode *ctxt)
|
Var_AppendExpand(const char *name, const char *val, GNode *scope)
|
||||||
{
|
{
|
||||||
char *name_freeIt = NULL;
|
char *name_freeIt = NULL;
|
||||||
|
|
||||||
@ -1135,7 +1134,7 @@ Var_AppendExpand(const char *name, const char *val, GNode *ctxt)
|
|||||||
|
|
||||||
if (strchr(name, '$') != NULL) {
|
if (strchr(name, '$') != NULL) {
|
||||||
const char *unexpanded_name = name;
|
const char *unexpanded_name = name;
|
||||||
(void)Var_Subst(name, ctxt, VARE_WANTRES, &name_freeIt);
|
(void)Var_Subst(name, scope, VARE_WANTRES, &name_freeIt);
|
||||||
/* TODO: handle errors */
|
/* TODO: handle errors */
|
||||||
name = name_freeIt;
|
name = name_freeIt;
|
||||||
if (name[0] == '\0') {
|
if (name[0] == '\0') {
|
||||||
@ -1148,7 +1147,7 @@ Var_AppendExpand(const char *name, const char *val, GNode *ctxt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Var_Append(name, val, ctxt);
|
Var_Append(name, val, scope);
|
||||||
|
|
||||||
free(name_freeIt);
|
free(name_freeIt);
|
||||||
}
|
}
|
||||||
@ -1160,9 +1159,9 @@ Global_Append(const char *name, const char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Boolean
|
Boolean
|
||||||
Var_Exists(const char *name, GNode *ctxt)
|
Var_Exists(const char *name, GNode *scope)
|
||||||
{
|
{
|
||||||
Var *v = VarFind(name, ctxt, TRUE);
|
Var *v = VarFind(name, scope, TRUE);
|
||||||
if (v == NULL)
|
if (v == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -1171,38 +1170,38 @@ Var_Exists(const char *name, GNode *ctxt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See if the given variable exists, in the given context or in other
|
* See if the given variable exists, in the given scope or in other
|
||||||
* fallback contexts.
|
* fallback scopes.
|
||||||
*
|
*
|
||||||
* Input:
|
* Input:
|
||||||
* name Variable to find, is expanded once
|
* name Variable to find, is expanded once
|
||||||
* ctxt Context in which to start search
|
* scope Scope in which to start search
|
||||||
*/
|
*/
|
||||||
Boolean
|
Boolean
|
||||||
Var_ExistsExpand(const char *name, GNode *ctxt)
|
Var_ExistsExpand(const char *name, GNode *scope)
|
||||||
{
|
{
|
||||||
FStr varname = FStr_InitRefer(name);
|
FStr varname = FStr_InitRefer(name);
|
||||||
Boolean exists;
|
Boolean exists;
|
||||||
|
|
||||||
if (strchr(varname.str, '$') != NULL) {
|
if (strchr(varname.str, '$') != NULL) {
|
||||||
char *expanded;
|
char *expanded;
|
||||||
(void)Var_Subst(varname.str, ctxt, VARE_WANTRES, &expanded);
|
(void)Var_Subst(varname.str, scope, VARE_WANTRES, &expanded);
|
||||||
/* TODO: handle errors */
|
/* TODO: handle errors */
|
||||||
varname = FStr_InitOwn(expanded);
|
varname = FStr_InitOwn(expanded);
|
||||||
}
|
}
|
||||||
|
|
||||||
exists = Var_Exists(varname.str, ctxt);
|
exists = Var_Exists(varname.str, scope);
|
||||||
FStr_Done(&varname);
|
FStr_Done(&varname);
|
||||||
return exists;
|
return exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the unexpanded value of the given variable in the given context,
|
* Return the unexpanded value of the given variable in the given scope,
|
||||||
* or the usual contexts.
|
* or the usual scopes.
|
||||||
*
|
*
|
||||||
* Input:
|
* Input:
|
||||||
* name name to find, is not expanded any further
|
* name name to find, is not expanded any further
|
||||||
* ctxt context in which to search for it
|
* scope scope in which to search for it
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* The value if the variable exists, NULL if it doesn't.
|
* The value if the variable exists, NULL if it doesn't.
|
||||||
@ -1210,9 +1209,9 @@ Var_ExistsExpand(const char *name, GNode *ctxt)
|
|||||||
* out_freeIt when the returned value is no longer needed.
|
* out_freeIt when the returned value is no longer needed.
|
||||||
*/
|
*/
|
||||||
FStr
|
FStr
|
||||||
Var_Value(const char *name, GNode *ctxt)
|
Var_Value(const char *name, GNode *scope)
|
||||||
{
|
{
|
||||||
Var *v = VarFind(name, ctxt, TRUE);
|
Var *v = VarFind(name, scope, TRUE);
|
||||||
char *value;
|
char *value;
|
||||||
|
|
||||||
if (v == NULL)
|
if (v == NULL)
|
||||||
@ -1226,12 +1225,12 @@ Var_Value(const char *name, GNode *ctxt)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the unexpanded variable value from this node, without trying to look
|
* Return the unexpanded variable value from this node, without trying to look
|
||||||
* up the variable in any other context.
|
* up the variable in any other scope.
|
||||||
*/
|
*/
|
||||||
const char *
|
const char *
|
||||||
Var_ValueDirect(const char *name, GNode *ctxt)
|
Var_ValueDirect(const char *name, GNode *scope)
|
||||||
{
|
{
|
||||||
Var *v = VarFind(name, ctxt, FALSE);
|
Var *v = VarFind(name, scope, FALSE);
|
||||||
return v != NULL ? v->val.data : NULL;
|
return v != NULL ? v->val.data : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2056,7 +2055,7 @@ typedef struct ApplyModifiersState {
|
|||||||
/* '\0' or '}' or ')' */
|
/* '\0' or '}' or ')' */
|
||||||
const char endc;
|
const char endc;
|
||||||
Var *const var;
|
Var *const var;
|
||||||
GNode *const ctxt;
|
GNode *const scope;
|
||||||
const VarEvalFlags eflags;
|
const VarEvalFlags eflags;
|
||||||
/*
|
/*
|
||||||
* The new value of the expression, after applying the modifier,
|
* The new value of the expression, after applying the modifier,
|
||||||
@ -2169,7 +2168,7 @@ ParseModifierPartSubst(
|
|||||||
VarEvalFlags nested_eflags =
|
VarEvalFlags nested_eflags =
|
||||||
eflags & ~(unsigned)VARE_KEEP_DOLLAR;
|
eflags & ~(unsigned)VARE_KEEP_DOLLAR;
|
||||||
|
|
||||||
(void)Var_Parse(&nested_p, st->ctxt, nested_eflags,
|
(void)Var_Parse(&nested_p, st->scope, nested_eflags,
|
||||||
&nested_val);
|
&nested_val);
|
||||||
/* TODO: handle errors */
|
/* TODO: handle errors */
|
||||||
Buf_AddStr(&buf, nested_val.str);
|
Buf_AddStr(&buf, nested_val.str);
|
||||||
@ -2348,7 +2347,7 @@ ApplyModifier_Loop(const char **pp, const char *val, ApplyModifiersState *st)
|
|||||||
char prev_sep;
|
char prev_sep;
|
||||||
VarParseResult res;
|
VarParseResult res;
|
||||||
|
|
||||||
args.ctx = st->ctxt;
|
args.ctx = st->scope;
|
||||||
|
|
||||||
(*pp)++; /* Skip the first '@' */
|
(*pp)++; /* Skip the first '@' */
|
||||||
res = ParseModifierPart(pp, '@', VARE_NONE, st, &args.tvar);
|
res = ParseModifierPart(pp, '@', VARE_NONE, st, &args.tvar);
|
||||||
@ -2373,7 +2372,7 @@ ApplyModifier_Loop(const char **pp, const char *val, ApplyModifiersState *st)
|
|||||||
ModifyWords(val, ModifyWord_Loop, &args, st->oneBigWord, st->sep));
|
ModifyWords(val, ModifyWord_Loop, &args, st->oneBigWord, st->sep));
|
||||||
st->sep = prev_sep;
|
st->sep = prev_sep;
|
||||||
/* XXX: Consider restoring the previous variable instead of deleting. */
|
/* XXX: Consider restoring the previous variable instead of deleting. */
|
||||||
Var_DeleteExpand(args.tvar, st->ctxt);
|
Var_DeleteExpand(args.tvar, st->scope);
|
||||||
free(args.tvar);
|
free(args.tvar);
|
||||||
free(args.str);
|
free(args.str);
|
||||||
return AMR_OK;
|
return AMR_OK;
|
||||||
@ -2414,7 +2413,7 @@ ApplyModifier_Defined(const char **pp, const char *val, ApplyModifiersState *st)
|
|||||||
if (*p == '$') {
|
if (*p == '$') {
|
||||||
FStr nested_val;
|
FStr nested_val;
|
||||||
|
|
||||||
(void)Var_Parse(&p, st->ctxt, eflags, &nested_val);
|
(void)Var_Parse(&p, st->scope, eflags, &nested_val);
|
||||||
/* TODO: handle errors */
|
/* TODO: handle errors */
|
||||||
Buf_AddStr(&buf, nested_val.str);
|
Buf_AddStr(&buf, nested_val.str);
|
||||||
FStr_Done(&nested_val);
|
FStr_Done(&nested_val);
|
||||||
@ -2696,7 +2695,7 @@ ApplyModifier_Match(const char **pp, const char *val, ApplyModifiersState *st)
|
|||||||
|
|
||||||
if (needSubst) {
|
if (needSubst) {
|
||||||
char *old_pattern = pattern;
|
char *old_pattern = pattern;
|
||||||
(void)Var_Subst(pattern, st->ctxt, st->eflags, &pattern);
|
(void)Var_Subst(pattern, st->scope, st->eflags, &pattern);
|
||||||
/* TODO: handle errors */
|
/* TODO: handle errors */
|
||||||
free(old_pattern);
|
free(old_pattern);
|
||||||
}
|
}
|
||||||
@ -3245,7 +3244,7 @@ ApplyModifier_IfElse(const char **pp, ApplyModifiersState *st)
|
|||||||
static ApplyModifierResult
|
static ApplyModifierResult
|
||||||
ApplyModifier_Assign(const char **pp, ApplyModifiersState *st)
|
ApplyModifier_Assign(const char **pp, ApplyModifiersState *st)
|
||||||
{
|
{
|
||||||
GNode *ctxt;
|
GNode *scope;
|
||||||
char delim;
|
char delim;
|
||||||
char *val;
|
char *val;
|
||||||
VarParseResult res;
|
VarParseResult res;
|
||||||
@ -3265,11 +3264,11 @@ ok:
|
|||||||
return AMR_BAD;
|
return AMR_BAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxt = st->ctxt; /* context where v belongs */
|
scope = st->scope; /* scope where v belongs */
|
||||||
if (st->exprStatus == VES_NONE && st->ctxt != SCOPE_GLOBAL) {
|
if (st->exprStatus == VES_NONE && st->scope != SCOPE_GLOBAL) {
|
||||||
Var *gv = VarFind(st->var->name.str, st->ctxt, FALSE);
|
Var *gv = VarFind(st->var->name.str, st->scope, FALSE);
|
||||||
if (gv == NULL)
|
if (gv == NULL)
|
||||||
ctxt = SCOPE_GLOBAL;
|
scope = SCOPE_GLOBAL;
|
||||||
else
|
else
|
||||||
VarFreeEnv(gv, TRUE);
|
VarFreeEnv(gv, TRUE);
|
||||||
}
|
}
|
||||||
@ -3296,7 +3295,7 @@ ok:
|
|||||||
if (st->eflags & VARE_WANTRES) {
|
if (st->eflags & VARE_WANTRES) {
|
||||||
switch (op[0]) {
|
switch (op[0]) {
|
||||||
case '+':
|
case '+':
|
||||||
Var_AppendExpand(st->var->name.str, val, ctxt);
|
Var_AppendExpand(st->var->name.str, val, scope);
|
||||||
break;
|
break;
|
||||||
case '!': {
|
case '!': {
|
||||||
const char *errfmt;
|
const char *errfmt;
|
||||||
@ -3305,7 +3304,7 @@ ok:
|
|||||||
Error(errfmt, val);
|
Error(errfmt, val);
|
||||||
else
|
else
|
||||||
Var_SetExpand(st->var->name.str, cmd_output,
|
Var_SetExpand(st->var->name.str, cmd_output,
|
||||||
ctxt);
|
scope);
|
||||||
free(cmd_output);
|
free(cmd_output);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3314,7 +3313,7 @@ ok:
|
|||||||
break;
|
break;
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
default:
|
default:
|
||||||
Var_SetExpand(st->var->name.str, val, ctxt);
|
Var_SetExpand(st->var->name.str, val, scope);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3338,11 +3337,11 @@ ApplyModifier_Remember(const char **pp, const char *val,
|
|||||||
if (mod[1] == '=') {
|
if (mod[1] == '=') {
|
||||||
size_t n = strcspn(mod + 2, ":)}");
|
size_t n = strcspn(mod + 2, ":)}");
|
||||||
char *name = bmake_strldup(mod + 2, n);
|
char *name = bmake_strldup(mod + 2, n);
|
||||||
Var_SetExpand(name, val, st->ctxt);
|
Var_SetExpand(name, val, st->scope);
|
||||||
free(name);
|
free(name);
|
||||||
*pp = mod + 2 + n;
|
*pp = mod + 2 + n;
|
||||||
} else {
|
} else {
|
||||||
Var_Set("_", val, st->ctxt);
|
Var_Set("_", val, st->scope);
|
||||||
*pp = mod + 1;
|
*pp = mod + 1;
|
||||||
}
|
}
|
||||||
st->newVal = FStr_InitRefer(val);
|
st->newVal = FStr_InitRefer(val);
|
||||||
@ -3422,7 +3421,7 @@ ApplyModifier_SysV(const char **pp, const char *val, ApplyModifiersState *st)
|
|||||||
if (lhs[0] == '\0' && val[0] == '\0') {
|
if (lhs[0] == '\0' && val[0] == '\0') {
|
||||||
st->newVal = FStr_InitRefer(val); /* special case */
|
st->newVal = FStr_InitRefer(val); /* special case */
|
||||||
} else {
|
} else {
|
||||||
struct ModifyWord_SYSVSubstArgs args = { st->ctxt, lhs, rhs };
|
struct ModifyWord_SYSVSubstArgs args = { st->scope, lhs, rhs };
|
||||||
st->newVal = FStr_InitOwn(
|
st->newVal = FStr_InitOwn(
|
||||||
ModifyWords(val, ModifyWord_SYSVSubst, &args,
|
ModifyWords(val, ModifyWord_SYSVSubst, &args,
|
||||||
st->oneBigWord, st->sep));
|
st->oneBigWord, st->sep));
|
||||||
@ -3590,7 +3589,7 @@ ApplyModifiersIndirect(ApplyModifiersState *st, const char **pp,
|
|||||||
const char *p = *pp;
|
const char *p = *pp;
|
||||||
FStr mods;
|
FStr mods;
|
||||||
|
|
||||||
(void)Var_Parse(&p, st->ctxt, st->eflags, &mods);
|
(void)Var_Parse(&p, st->scope, st->eflags, &mods);
|
||||||
/* TODO: handle errors */
|
/* TODO: handle errors */
|
||||||
|
|
||||||
if (mods.str[0] != '\0' && *p != '\0' && *p != ':' && *p != st->endc) {
|
if (mods.str[0] != '\0' && *p != '\0' && *p != ':' && *p != st->endc) {
|
||||||
@ -3604,7 +3603,7 @@ ApplyModifiersIndirect(ApplyModifiersState *st, const char **pp,
|
|||||||
if (mods.str[0] != '\0') {
|
if (mods.str[0] != '\0') {
|
||||||
const char *modsp = mods.str;
|
const char *modsp = mods.str;
|
||||||
FStr newVal = ApplyModifiers(&modsp, *inout_value, '\0', '\0',
|
FStr newVal = ApplyModifiers(&modsp, *inout_value, '\0', '\0',
|
||||||
st->var, &st->exprStatus, st->ctxt, st->eflags);
|
st->var, &st->exprStatus, st->scope, st->eflags);
|
||||||
*inout_value = newVal;
|
*inout_value = newVal;
|
||||||
if (newVal.str == var_Error || *modsp != '\0') {
|
if (newVal.str == var_Error || *modsp != '\0') {
|
||||||
FStr_Done(&mods);
|
FStr_Done(&mods);
|
||||||
@ -3701,12 +3700,12 @@ ApplyModifiers(
|
|||||||
char endc, /* ')' or '}', or '\0' for indirect modifiers */
|
char endc, /* ')' or '}', or '\0' for indirect modifiers */
|
||||||
Var *v,
|
Var *v,
|
||||||
VarExprStatus *exprStatus,
|
VarExprStatus *exprStatus,
|
||||||
GNode *ctxt, /* for looking up and modifying variables */
|
GNode *scope, /* for looking up and modifying variables */
|
||||||
VarEvalFlags eflags
|
VarEvalFlags eflags
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ApplyModifiersState st = {
|
ApplyModifiersState st = {
|
||||||
startc, endc, v, ctxt, eflags,
|
startc, endc, v, scope, eflags,
|
||||||
#if defined(lint)
|
#if defined(lint)
|
||||||
/* lint cannot parse C99 struct initializers yet. */
|
/* lint cannot parse C99 struct initializers yet. */
|
||||||
{ var_Error, NULL },
|
{ var_Error, NULL },
|
||||||
@ -3802,11 +3801,11 @@ VarnameIsDynamic(const char *name, size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
UndefinedShortVarValue(char varname, const GNode *ctxt)
|
UndefinedShortVarValue(char varname, const GNode *scope)
|
||||||
{
|
{
|
||||||
if (ctxt == SCOPE_CMDLINE || ctxt == SCOPE_GLOBAL) {
|
if (scope == SCOPE_CMDLINE || scope == SCOPE_GLOBAL) {
|
||||||
/*
|
/*
|
||||||
* If substituting a local variable in a non-local context,
|
* If substituting a local variable in a non-local scope,
|
||||||
* assume it's for dynamic source stuff. We have to handle
|
* assume it's for dynamic source stuff. We have to handle
|
||||||
* this specially and return the longhand for the variable
|
* this specially and return the longhand for the variable
|
||||||
* with the dollar sign escaped so it makes it back to the
|
* with the dollar sign escaped so it makes it back to the
|
||||||
@ -3834,7 +3833,7 @@ UndefinedShortVarValue(char varname, const GNode *ctxt)
|
|||||||
*/
|
*/
|
||||||
static char *
|
static char *
|
||||||
ParseVarname(const char **pp, char startc, char endc,
|
ParseVarname(const char **pp, char startc, char endc,
|
||||||
GNode *ctxt, VarEvalFlags eflags,
|
GNode *scope, VarEvalFlags eflags,
|
||||||
size_t *out_varname_len)
|
size_t *out_varname_len)
|
||||||
{
|
{
|
||||||
Buffer buf;
|
Buffer buf;
|
||||||
@ -3857,7 +3856,7 @@ ParseVarname(const char **pp, char startc, char endc,
|
|||||||
/* A variable inside a variable, expand. */
|
/* A variable inside a variable, expand. */
|
||||||
if (*p == '$') {
|
if (*p == '$') {
|
||||||
FStr nested_val;
|
FStr nested_val;
|
||||||
(void)Var_Parse(&p, ctxt, eflags, &nested_val);
|
(void)Var_Parse(&p, scope, eflags, &nested_val);
|
||||||
/* TODO: handle errors */
|
/* TODO: handle errors */
|
||||||
Buf_AddStr(&buf, nested_val.str);
|
Buf_AddStr(&buf, nested_val.str);
|
||||||
FStr_Done(&nested_val);
|
FStr_Done(&nested_val);
|
||||||
@ -3905,7 +3904,7 @@ ValidShortVarname(char varname, const char *start)
|
|||||||
* Return whether to continue parsing.
|
* Return whether to continue parsing.
|
||||||
*/
|
*/
|
||||||
static Boolean
|
static Boolean
|
||||||
ParseVarnameShort(char startc, const char **pp, GNode *ctxt,
|
ParseVarnameShort(char startc, const char **pp, GNode *scope,
|
||||||
VarEvalFlags eflags,
|
VarEvalFlags eflags,
|
||||||
VarParseResult *out_FALSE_res, const char **out_FALSE_val,
|
VarParseResult *out_FALSE_res, const char **out_FALSE_val,
|
||||||
Var **out_TRUE_var)
|
Var **out_TRUE_var)
|
||||||
@ -3930,12 +3929,12 @@ ParseVarnameShort(char startc, const char **pp, GNode *ctxt,
|
|||||||
|
|
||||||
name[0] = startc;
|
name[0] = startc;
|
||||||
name[1] = '\0';
|
name[1] = '\0';
|
||||||
v = VarFind(name, ctxt, TRUE);
|
v = VarFind(name, scope, TRUE);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
const char *val;
|
const char *val;
|
||||||
*pp += 2;
|
*pp += 2;
|
||||||
|
|
||||||
val = UndefinedShortVarValue(startc, ctxt);
|
val = UndefinedShortVarValue(startc, scope);
|
||||||
if (val == NULL)
|
if (val == NULL)
|
||||||
val = eflags & VARE_UNDEFERR ? var_Error : varUndefined;
|
val = eflags & VARE_UNDEFERR ? var_Error : varUndefined;
|
||||||
|
|
||||||
@ -3968,11 +3967,11 @@ ParseVarnameShort(char startc, const char **pp, GNode *ctxt,
|
|||||||
|
|
||||||
/* Find variables like @F or <D. */
|
/* Find variables like @F or <D. */
|
||||||
static Var *
|
static Var *
|
||||||
FindLocalLegacyVar(const char *varname, size_t namelen, GNode *ctxt,
|
FindLocalLegacyVar(const char *varname, size_t namelen, GNode *scope,
|
||||||
const char **out_extraModifiers)
|
const char **out_extraModifiers)
|
||||||
{
|
{
|
||||||
/* Only resolve these variables if ctxt is a "real" target. */
|
/* Only resolve these variables if scope is a "real" target. */
|
||||||
if (ctxt == SCOPE_CMDLINE || ctxt == SCOPE_GLOBAL)
|
if (scope == SCOPE_CMDLINE || scope == SCOPE_GLOBAL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (namelen != 2)
|
if (namelen != 2)
|
||||||
@ -3984,7 +3983,7 @@ FindLocalLegacyVar(const char *varname, size_t namelen, GNode *ctxt,
|
|||||||
|
|
||||||
{
|
{
|
||||||
char name[] = { varname[0], '\0' };
|
char name[] = { varname[0], '\0' };
|
||||||
Var *v = VarFind(name, ctxt, FALSE);
|
Var *v = VarFind(name, scope, FALSE);
|
||||||
|
|
||||||
if (v != NULL) {
|
if (v != NULL) {
|
||||||
if (varname[1] == 'D') {
|
if (varname[1] == 'D') {
|
||||||
@ -4037,7 +4036,7 @@ static Boolean
|
|||||||
ParseVarnameLong(
|
ParseVarnameLong(
|
||||||
const char *p,
|
const char *p,
|
||||||
char startc,
|
char startc,
|
||||||
GNode *ctxt,
|
GNode *scope,
|
||||||
VarEvalFlags eflags,
|
VarEvalFlags eflags,
|
||||||
|
|
||||||
const char **out_FALSE_pp,
|
const char **out_FALSE_pp,
|
||||||
@ -4063,7 +4062,7 @@ ParseVarnameLong(
|
|||||||
char endc = startc == '(' ? ')' : '}';
|
char endc = startc == '(' ? ')' : '}';
|
||||||
|
|
||||||
p += 2; /* skip "${" or "$(" or "y(" */
|
p += 2; /* skip "${" or "$(" or "y(" */
|
||||||
varname = ParseVarname(&p, startc, endc, ctxt, eflags, &namelen);
|
varname = ParseVarname(&p, startc, endc, scope, eflags, &namelen);
|
||||||
|
|
||||||
if (*p == ':') {
|
if (*p == ':') {
|
||||||
haveModifier = TRUE;
|
haveModifier = TRUE;
|
||||||
@ -4078,23 +4077,23 @@ ParseVarnameLong(
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
v = VarFind(varname, ctxt, TRUE);
|
v = VarFind(varname, scope, TRUE);
|
||||||
|
|
||||||
/* At this point, p points just after the variable name,
|
/* At this point, p points just after the variable name,
|
||||||
* either at ':' or at endc. */
|
* either at ':' or at endc. */
|
||||||
|
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
v = FindLocalLegacyVar(varname, namelen, ctxt,
|
v = FindLocalLegacyVar(varname, namelen, scope,
|
||||||
out_TRUE_extraModifiers);
|
out_TRUE_extraModifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
/*
|
/*
|
||||||
* Defer expansion of dynamic variables if they appear in
|
* Defer expansion of dynamic variables if they appear in
|
||||||
* non-local context since they are not defined there.
|
* non-local scope since they are not defined there.
|
||||||
*/
|
*/
|
||||||
dynamic = VarnameIsDynamic(varname, namelen) &&
|
dynamic = VarnameIsDynamic(varname, namelen) &&
|
||||||
(ctxt == SCOPE_CMDLINE || ctxt == SCOPE_GLOBAL);
|
(scope == SCOPE_CMDLINE || scope == SCOPE_GLOBAL);
|
||||||
|
|
||||||
if (!haveModifier) {
|
if (!haveModifier) {
|
||||||
p++; /* skip endc */
|
p++; /* skip endc */
|
||||||
@ -4157,7 +4156,7 @@ FreeEnvVar(void **out_val_freeIt, Var *v, const char *value)
|
|||||||
* When parsing a condition in ParseEmptyArg, it may also
|
* When parsing a condition in ParseEmptyArg, it may also
|
||||||
* point to the "y" of "empty(VARNAME:Modifiers)", which
|
* point to the "y" of "empty(VARNAME:Modifiers)", which
|
||||||
* is syntactically the same.
|
* is syntactically the same.
|
||||||
* ctxt The context for finding variables
|
* scope The scope for finding variables
|
||||||
* eflags Control the exact details of parsing
|
* eflags Control the exact details of parsing
|
||||||
*
|
*
|
||||||
* Output:
|
* Output:
|
||||||
@ -4185,7 +4184,7 @@ FreeEnvVar(void **out_val_freeIt, Var *v, const char *value)
|
|||||||
*/
|
*/
|
||||||
/* coverity[+alloc : arg-*4] */
|
/* coverity[+alloc : arg-*4] */
|
||||||
VarParseResult
|
VarParseResult
|
||||||
Var_Parse(const char **pp, GNode *ctxt, VarEvalFlags eflags, FStr *out_val)
|
Var_Parse(const char **pp, GNode *scope, VarEvalFlags eflags, FStr *out_val)
|
||||||
{
|
{
|
||||||
const char *p = *pp;
|
const char *p = *pp;
|
||||||
const char *const start = p;
|
const char *const start = p;
|
||||||
@ -4197,7 +4196,7 @@ Var_Parse(const char **pp, GNode *ctxt, VarEvalFlags eflags, FStr *out_val)
|
|||||||
char endc;
|
char endc;
|
||||||
/*
|
/*
|
||||||
* TRUE if the variable is local and we're expanding it in a
|
* TRUE if the variable is local and we're expanding it in a
|
||||||
* non-local context. This is done to support dynamic sources.
|
* non-local scope. This is done to support dynamic sources.
|
||||||
* The result is just the expression, unaltered.
|
* The result is just the expression, unaltered.
|
||||||
*/
|
*/
|
||||||
Boolean dynamic;
|
Boolean dynamic;
|
||||||
@ -4223,14 +4222,14 @@ Var_Parse(const char **pp, GNode *ctxt, VarEvalFlags eflags, FStr *out_val)
|
|||||||
startc = p[1];
|
startc = p[1];
|
||||||
if (startc != '(' && startc != '{') {
|
if (startc != '(' && startc != '{') {
|
||||||
VarParseResult res;
|
VarParseResult res;
|
||||||
if (!ParseVarnameShort(startc, pp, ctxt, eflags, &res,
|
if (!ParseVarnameShort(startc, pp, scope, eflags, &res,
|
||||||
&out_val->str, &v))
|
&out_val->str, &v))
|
||||||
return res;
|
return res;
|
||||||
haveModifier = FALSE;
|
haveModifier = FALSE;
|
||||||
p++;
|
p++;
|
||||||
} else {
|
} else {
|
||||||
VarParseResult res;
|
VarParseResult res;
|
||||||
if (!ParseVarnameLong(p, startc, ctxt, eflags,
|
if (!ParseVarnameLong(p, startc, scope, eflags,
|
||||||
pp, &res, out_val,
|
pp, &res, out_val,
|
||||||
&endc, &p, &v, &haveModifier, &extramodifiers,
|
&endc, &p, &v, &haveModifier, &extramodifiers,
|
||||||
&dynamic, &exprStatus))
|
&dynamic, &exprStatus))
|
||||||
@ -4261,7 +4260,7 @@ Var_Parse(const char **pp, GNode *ctxt, VarEvalFlags eflags, FStr *out_val)
|
|||||||
if (opts.strict)
|
if (opts.strict)
|
||||||
nested_eflags &= ~(unsigned)VARE_UNDEFERR;
|
nested_eflags &= ~(unsigned)VARE_UNDEFERR;
|
||||||
v->flags |= VAR_IN_USE;
|
v->flags |= VAR_IN_USE;
|
||||||
(void)Var_Subst(value.str, ctxt, nested_eflags, &expanded);
|
(void)Var_Subst(value.str, scope, nested_eflags, &expanded);
|
||||||
v->flags &= ~(unsigned)VAR_IN_USE;
|
v->flags &= ~(unsigned)VAR_IN_USE;
|
||||||
/* TODO: handle errors */
|
/* TODO: handle errors */
|
||||||
value = FStr_InitOwn(expanded);
|
value = FStr_InitOwn(expanded);
|
||||||
@ -4271,14 +4270,14 @@ Var_Parse(const char **pp, GNode *ctxt, VarEvalFlags eflags, FStr *out_val)
|
|||||||
if (extramodifiers != NULL) {
|
if (extramodifiers != NULL) {
|
||||||
const char *em = extramodifiers;
|
const char *em = extramodifiers;
|
||||||
value = ApplyModifiers(&em, value, '\0', '\0',
|
value = ApplyModifiers(&em, value, '\0', '\0',
|
||||||
v, &exprStatus, ctxt, eflags);
|
v, &exprStatus, scope, eflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (haveModifier) {
|
if (haveModifier) {
|
||||||
p++; /* Skip initial colon. */
|
p++; /* Skip initial colon. */
|
||||||
|
|
||||||
value = ApplyModifiers(&p, value, startc, endc,
|
value = ApplyModifiers(&p, value, startc, endc,
|
||||||
v, &exprStatus, ctxt, eflags);
|
v, &exprStatus, scope, eflags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4328,14 +4327,14 @@ VarSubstDollarDollar(const char **pp, Buffer *res, VarEvalFlags eflags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
VarSubstExpr(const char **pp, Buffer *buf, GNode *ctxt,
|
VarSubstExpr(const char **pp, Buffer *buf, GNode *scope,
|
||||||
VarEvalFlags eflags, Boolean *inout_errorReported)
|
VarEvalFlags eflags, Boolean *inout_errorReported)
|
||||||
{
|
{
|
||||||
const char *p = *pp;
|
const char *p = *pp;
|
||||||
const char *nested_p = p;
|
const char *nested_p = p;
|
||||||
FStr val;
|
FStr val;
|
||||||
|
|
||||||
(void)Var_Parse(&nested_p, ctxt, eflags, &val);
|
(void)Var_Parse(&nested_p, scope, eflags, &val);
|
||||||
/* TODO: handle errors */
|
/* TODO: handle errors */
|
||||||
|
|
||||||
if (val.str == var_Error || val.str == varUndefined) {
|
if (val.str == var_Error || val.str == varUndefined) {
|
||||||
@ -4403,12 +4402,12 @@ VarSubstPlain(const char **pp, Buffer *res)
|
|||||||
* Input:
|
* Input:
|
||||||
* str The string in which the variable expressions are
|
* str The string in which the variable expressions are
|
||||||
* expanded.
|
* expanded.
|
||||||
* ctxt The context in which to start searching for
|
* scope The scope in which to start searching for
|
||||||
* variables. The other contexts are searched as well.
|
* variables. The other scopes are searched as well.
|
||||||
* eflags Special effects during expansion.
|
* eflags Special effects during expansion.
|
||||||
*/
|
*/
|
||||||
VarParseResult
|
VarParseResult
|
||||||
Var_Subst(const char *str, GNode *ctxt, VarEvalFlags eflags, char **out_res)
|
Var_Subst(const char *str, GNode *scope, VarEvalFlags eflags, char **out_res)
|
||||||
{
|
{
|
||||||
const char *p = str;
|
const char *p = str;
|
||||||
Buffer res;
|
Buffer res;
|
||||||
@ -4425,7 +4424,7 @@ Var_Subst(const char *str, GNode *ctxt, VarEvalFlags eflags, char **out_res)
|
|||||||
if (p[0] == '$' && p[1] == '$')
|
if (p[0] == '$' && p[1] == '$')
|
||||||
VarSubstDollarDollar(&p, &res, eflags);
|
VarSubstDollarDollar(&p, &res, eflags);
|
||||||
else if (p[0] == '$')
|
else if (p[0] == '$')
|
||||||
VarSubstExpr(&p, &res, ctxt, eflags, &errorReported);
|
VarSubstExpr(&p, &res, scope, eflags, &errorReported);
|
||||||
else
|
else
|
||||||
VarSubstPlain(&p, &res);
|
VarSubstPlain(&p, &res);
|
||||||
}
|
}
|
||||||
@ -4453,12 +4452,12 @@ Var_End(void)
|
|||||||
void
|
void
|
||||||
Var_Stats(void)
|
Var_Stats(void)
|
||||||
{
|
{
|
||||||
HashTable_DebugStats(&SCOPE_GLOBAL->vars, "VAR_GLOBAL");
|
HashTable_DebugStats(&SCOPE_GLOBAL->vars, "Global variables");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print all variables in a context, sorted by name. */
|
/* Print all variables in a scope, sorted by name. */
|
||||||
void
|
void
|
||||||
Var_Dump(GNode *ctxt)
|
Var_Dump(GNode *scope)
|
||||||
{
|
{
|
||||||
Vector /* of const char * */ vec;
|
Vector /* of const char * */ vec;
|
||||||
HashIter hi;
|
HashIter hi;
|
||||||
@ -4467,7 +4466,7 @@ Var_Dump(GNode *ctxt)
|
|||||||
|
|
||||||
Vector_Init(&vec, sizeof(const char *));
|
Vector_Init(&vec, sizeof(const char *));
|
||||||
|
|
||||||
HashIter_Init(&hi, &ctxt->vars);
|
HashIter_Init(&hi, &scope->vars);
|
||||||
while (HashIter_Next(&hi) != NULL)
|
while (HashIter_Next(&hi) != NULL)
|
||||||
*(const char **)Vector_Push(&vec) = hi.entry->key;
|
*(const char **)Vector_Push(&vec) = hi.entry->key;
|
||||||
varnames = vec.items;
|
varnames = vec.items;
|
||||||
@ -4476,7 +4475,7 @@ Var_Dump(GNode *ctxt)
|
|||||||
|
|
||||||
for (i = 0; i < vec.len; i++) {
|
for (i = 0; i < vec.len; i++) {
|
||||||
const char *varname = varnames[i];
|
const char *varname = varnames[i];
|
||||||
Var *var = HashTable_FindValue(&ctxt->vars, varname);
|
Var *var = HashTable_FindValue(&scope->vars, varname);
|
||||||
debug_printf("%-16s = %s\n", varname, var->val.data);
|
debug_printf("%-16s = %s\n", varname, var->val.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user