mirror of
https://github.com/mirror/make.git
synced 2025-03-26 12:04:42 +08:00
Add support for "::=" simple assignment operator.
The next POSIX standard will define "::=" to have the same behavior as GNU make's ":=", so add support for this new operator.
This commit is contained in:
parent
fca11f6039
commit
ef6461611b
12
ChangeLog
12
ChangeLog
@ -1,5 +1,17 @@
|
|||||||
2012-01-29 Paul Smith <psmith@gnu.org>
|
2012-01-29 Paul Smith <psmith@gnu.org>
|
||||||
|
|
||||||
|
* variable.c (parse_variable_definition): New POSIX assignment ::=
|
||||||
|
Take a struct variable to return more information after parsing.
|
||||||
|
(assign_variable_definition): New parse_variable_definition() call.
|
||||||
|
* variable.h: New declaration of parse_variable_definition().
|
||||||
|
* read.c (do_define): New parse_variable_definition() call.
|
||||||
|
(parse_var_assignment): Ditto.
|
||||||
|
(get_next_mword): Parse ::= as a variable assignment.
|
||||||
|
* doc/make.texi (Flavors): Describe the new ::= syntax.
|
||||||
|
* NEWS: Mention the ::= operator.
|
||||||
|
|
||||||
|
* variable.h (struct variable): Rearrange elts to reduce struct size.
|
||||||
|
|
||||||
* function.c (func_file): Create a new function, $(file ...)
|
* function.c (func_file): Create a new function, $(file ...)
|
||||||
* doc/make.texi (File Function): Document the $(file ..) function.
|
* doc/make.texi (File Function): Document the $(file ..) function.
|
||||||
* NEWS: Announce it.
|
* NEWS: Announce it.
|
||||||
|
6
NEWS
6
NEWS
@ -38,6 +38,12 @@ http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=101&set
|
|||||||
interpreted as shell assignment. Change your assignment to add whitespace
|
interpreted as shell assignment. Change your assignment to add whitespace
|
||||||
between the "!" and "=": "variable! = value"
|
between the "!" and "=": "variable! = value"
|
||||||
|
|
||||||
|
* New feature: "::=" simple assignment operator as defined by POSIX in 2012.
|
||||||
|
This operator has identical functionality to ":=" in GNU make, but will be
|
||||||
|
portable to any implementation of make conforming to a sufficiently new
|
||||||
|
version of POSIX (see http://austingroupbugs.net/view.php?id=330). It is
|
||||||
|
not necessary to define the .POSIX target to access this operator.
|
||||||
|
|
||||||
* New feature: GNU Guile integration
|
* New feature: GNU Guile integration
|
||||||
This version of GNU make can be compiled with GNU Guile integration.
|
This version of GNU make can be compiled with GNU Guile integration.
|
||||||
GNU Guile serves as an embedded extension language for make.
|
GNU Guile serves as an embedded extension language for make.
|
||||||
|
@ -1399,6 +1399,7 @@ Variable definitions are parsed as follows:
|
|||||||
@var{immediate} = @var{deferred}
|
@var{immediate} = @var{deferred}
|
||||||
@var{immediate} ?= @var{deferred}
|
@var{immediate} ?= @var{deferred}
|
||||||
@var{immediate} := @var{immediate}
|
@var{immediate} := @var{immediate}
|
||||||
|
@var{immediate} ::= @var{immediate}
|
||||||
@var{immediate} += @var{deferred} or @var{immediate}
|
@var{immediate} += @var{deferred} or @var{immediate}
|
||||||
@var{immediate} != @var{immediate}
|
@var{immediate} != @var{immediate}
|
||||||
|
|
||||||
@ -1418,6 +1419,10 @@ define @var{immediate} :=
|
|||||||
@var{immediate}
|
@var{immediate}
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
define @var{immediate} ::=
|
||||||
|
@var{immediate}
|
||||||
|
endef
|
||||||
|
|
||||||
define @var{immediate} +=
|
define @var{immediate} +=
|
||||||
@var{deferred} or @var{immediate}
|
@var{deferred} or @var{immediate}
|
||||||
endef
|
endef
|
||||||
@ -1429,7 +1434,7 @@ endef
|
|||||||
|
|
||||||
For the append operator, @samp{+=}, the right-hand side is considered
|
For the append operator, @samp{+=}, the right-hand side is considered
|
||||||
immediate if the variable was previously set as a simple variable
|
immediate if the variable was previously set as a simple variable
|
||||||
(@samp{:=}), and deferred otherwise.
|
(@samp{:=} or @samp{::=}), and deferred otherwise.
|
||||||
|
|
||||||
For the shell assignment operator, @samp{!=}, the right-hand side is
|
For the shell assignment operator, @samp{!=}, the right-hand side is
|
||||||
evaluated immediately and handed to the shell. The result is stored in the
|
evaluated immediately and handed to the shell. The result is stored in the
|
||||||
@ -4967,9 +4972,9 @@ all:;echo $(foo)
|
|||||||
will echo @samp{Huh?}: @samp{$(foo)} expands to @samp{$(bar)} which
|
will echo @samp{Huh?}: @samp{$(foo)} expands to @samp{$(bar)} which
|
||||||
expands to @samp{$(ugh)} which finally expands to @samp{Huh?}.@refill
|
expands to @samp{$(ugh)} which finally expands to @samp{Huh?}.@refill
|
||||||
|
|
||||||
This flavor of variable is the only sort supported by other versions of
|
This flavor of variable is the only sort supported by most other
|
||||||
@code{make}. It has its advantages and its disadvantages. An advantage
|
versions of @code{make}. It has its advantages and its disadvantages.
|
||||||
(most would say) is that:
|
An advantage (most would say) is that:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
CFLAGS = $(include_dirs) -O
|
CFLAGS = $(include_dirs) -O
|
||||||
@ -5005,8 +5010,14 @@ variables, there is another flavor: simply expanded variables.
|
|||||||
@cindex simply expanded variables
|
@cindex simply expanded variables
|
||||||
@cindex variables, simply expanded
|
@cindex variables, simply expanded
|
||||||
@cindex :=
|
@cindex :=
|
||||||
|
@cindex ::=
|
||||||
@dfn{Simply expanded variables} are defined by lines using @samp{:=}
|
@dfn{Simply expanded variables} are defined by lines using @samp{:=}
|
||||||
(@pxref{Setting, ,Setting Variables}).
|
or @samp{::=} (@pxref{Setting, ,Setting Variables}). Both forms are
|
||||||
|
equivalent in GNU @code{make}; however only the @samp{::=} form is
|
||||||
|
described by the POSIX standard (support for @samp{::=} was added to
|
||||||
|
the POSIX standard in 2012, so older versions of @code{make} won't
|
||||||
|
accept this form either).
|
||||||
|
|
||||||
The value of a simply expanded variable is scanned
|
The value of a simply expanded variable is scanned
|
||||||
once and for all, expanding any references to other variables and
|
once and for all, expanding any references to other variables and
|
||||||
functions, when the variable is defined. The actual value of the simply
|
functions, when the variable is defined. The actual value of the simply
|
||||||
@ -5425,12 +5436,14 @@ Several variables have constant initial values.
|
|||||||
@cindex variables, setting
|
@cindex variables, setting
|
||||||
@cindex =
|
@cindex =
|
||||||
@cindex :=
|
@cindex :=
|
||||||
|
@cindex ::=
|
||||||
@cindex ?=
|
@cindex ?=
|
||||||
@cindex !=
|
@cindex !=
|
||||||
|
|
||||||
To set a variable from the makefile, write a line starting with the
|
To set a variable from the makefile, write a line starting with the
|
||||||
variable name followed by @samp{=} or @samp{:=}. Whatever follows the
|
variable name followed by @samp{=} @samp{:=}, or @samp{::=}. Whatever
|
||||||
@samp{=} or @samp{:=} on the line becomes the value. For example,
|
follows the @samp{=}, @samp{:=}, or @samp{::=} on the line becomes the
|
||||||
|
value. For example,
|
||||||
|
|
||||||
@example
|
@example
|
||||||
objects = main.o foo.o bar.o utils.o
|
objects = main.o foo.o bar.o utils.o
|
||||||
@ -5440,10 +5453,11 @@ objects = main.o foo.o bar.o utils.o
|
|||||||
defines a variable named @code{objects}. Whitespace around the variable
|
defines a variable named @code{objects}. Whitespace around the variable
|
||||||
name and immediately after the @samp{=} is ignored.
|
name and immediately after the @samp{=} is ignored.
|
||||||
|
|
||||||
Variables defined with @samp{=} are @dfn{recursively expanded} variables.
|
Variables defined with @samp{=} are @dfn{recursively expanded}
|
||||||
Variables defined with @samp{:=} are @dfn{simply expanded} variables; these
|
variables. Variables defined with @samp{:=} or @samp{::=} are
|
||||||
definitions can contain variable references which will be expanded before
|
@dfn{simply expanded} variables; these definitions can contain
|
||||||
the definition is made. @xref{Flavors, ,The Two Flavors of Variables}.
|
variable references which will be expanded before the definition is
|
||||||
|
made. @xref{Flavors, ,The Two Flavors of Variables}.
|
||||||
|
|
||||||
The variable name may contain function and variable references, which
|
The variable name may contain function and variable references, which
|
||||||
are expanded when the line is read to find the actual variable name to use.
|
are expanded when the line is read to find the actual variable name to use.
|
||||||
@ -5553,12 +5567,12 @@ explanation of the two flavors of variables.
|
|||||||
|
|
||||||
When you add to a variable's value with @samp{+=}, @code{make} acts
|
When you add to a variable's value with @samp{+=}, @code{make} acts
|
||||||
essentially as if you had included the extra text in the initial
|
essentially as if you had included the extra text in the initial
|
||||||
definition of the variable. If you defined it first with @samp{:=},
|
definition of the variable. If you defined it first with @samp{:=} or
|
||||||
making it a simply-expanded variable, @samp{+=} adds to that
|
@samp{::=}, making it a simply-expanded variable, @samp{+=} adds to
|
||||||
simply-expanded definition, and expands the new text before appending it
|
that simply-expanded definition, and expands the new text before
|
||||||
to the old value just as @samp{:=} does
|
appending it to the old value just as @samp{:=} does (see
|
||||||
(see @ref{Setting, ,Setting Variables}, for a full explanation of @samp{:=}).
|
@ref{Setting, ,Setting Variables}, for a full explanation of
|
||||||
In fact,
|
@samp{:=} or @samp{::=}). In fact,
|
||||||
|
|
||||||
@example
|
@example
|
||||||
variable := value
|
variable := value
|
||||||
@ -5898,13 +5912,13 @@ Multiple @var{target} values create a target-specific variable value for
|
|||||||
each member of the target list individually.
|
each member of the target list individually.
|
||||||
|
|
||||||
The @var{variable-assignment} can be any valid form of assignment;
|
The @var{variable-assignment} can be any valid form of assignment;
|
||||||
recursive (@samp{=}), simple (@samp{:=}), appending (@samp{+=}), or
|
recursive (@samp{=}), simple (@samp{:=} or @samp{::=}), appending
|
||||||
conditional (@samp{?=}). All variables that appear within the
|
(@samp{+=}), or conditional (@samp{?=}). All variables that appear
|
||||||
@var{variable-assignment} are evaluated within the context of the
|
within the @var{variable-assignment} are evaluated within the context
|
||||||
target: thus, any previously-defined target-specific variable values
|
of the target: thus, any previously-defined target-specific variable
|
||||||
will be in effect. Note that this variable is actually distinct from
|
values will be in effect. Note that this variable is actually
|
||||||
any ``global'' value: the two variables do not have to have the same
|
distinct from any ``global'' value: the two variables do not have to
|
||||||
flavor (recursive vs.@: simple).
|
have the same flavor (recursive vs.@: simple).
|
||||||
|
|
||||||
Target-specific variables have the same priority as any other makefile
|
Target-specific variables have the same priority as any other makefile
|
||||||
variable. Variables provided on the command line (and in the
|
variable. Variables provided on the command line (and in the
|
||||||
@ -8463,10 +8477,10 @@ makefile works by changing the variables.
|
|||||||
When you override a variable with a command line argument, you can
|
When you override a variable with a command line argument, you can
|
||||||
define either a recursively-expanded variable or a simply-expanded
|
define either a recursively-expanded variable or a simply-expanded
|
||||||
variable. The examples shown above make a recursively-expanded
|
variable. The examples shown above make a recursively-expanded
|
||||||
variable; to make a simply-expanded variable, write @samp{:=} instead
|
variable; to make a simply-expanded variable, write @samp{:=} or
|
||||||
of @samp{=}. But, unless you want to include a variable reference or
|
@samp{::=} instead of @samp{=}. But, unless you want to include a
|
||||||
function call in the @emph{value} that you specify, it makes no
|
variable reference or function call in the @emph{value} that you
|
||||||
difference which kind of variable you create.
|
specify, it makes no difference which kind of variable you create.
|
||||||
|
|
||||||
There is one way that the makefile can change a variable that you have
|
There is one way that the makefile can change a variable that you have
|
||||||
overridden. This is to use the @code{override} directive, which is a line
|
overridden. This is to use the @code{override} directive, which is a line
|
||||||
@ -11024,6 +11038,7 @@ Here is a summary of the directives GNU @code{make} recognizes:
|
|||||||
@item define @var{variable}
|
@item define @var{variable}
|
||||||
@itemx define @var{variable} =
|
@itemx define @var{variable} =
|
||||||
@itemx define @var{variable} :=
|
@itemx define @var{variable} :=
|
||||||
|
@itemx define @var{variable} ::=
|
||||||
@itemx define @var{variable} +=
|
@itemx define @var{variable} +=
|
||||||
@itemx define @var{variable} ?=
|
@itemx define @var{variable} ?=
|
||||||
@itemx endef
|
@itemx endef
|
||||||
@ -11479,9 +11494,9 @@ prerequisites, etc., one of them depended on @var{xxx} again.
|
|||||||
@item Recursive variable `@var{xxx}' references itself (eventually). Stop.
|
@item Recursive variable `@var{xxx}' references itself (eventually). Stop.
|
||||||
This means you've defined a normal (recursive) @code{make} variable
|
This means you've defined a normal (recursive) @code{make} variable
|
||||||
@var{xxx} that, when it's expanded, will refer to itself (@var{xxx}).
|
@var{xxx} that, when it's expanded, will refer to itself (@var{xxx}).
|
||||||
This is not allowed; either use simply-expanded variables (@code{:=}) or
|
This is not allowed; either use simply-expanded variables (@samp{:=}
|
||||||
use the append operator (@code{+=}). @xref{Using Variables, ,How to Use
|
or @samp{::=}) or use the append operator (@samp{+=}). @xref{Using
|
||||||
Variables}.
|
Variables, ,How to Use Variables}.
|
||||||
|
|
||||||
@item Unterminated variable reference. Stop.
|
@item Unterminated variable reference. Stop.
|
||||||
This means you forgot to provide the proper closing parenthesis
|
This means you forgot to provide the proper closing parenthesis
|
||||||
|
37
read.c
37
read.c
@ -495,9 +495,9 @@ parse_var_assignment (const char *line, struct vmodifiers *vmod)
|
|||||||
{
|
{
|
||||||
int wlen;
|
int wlen;
|
||||||
const char *p2;
|
const char *p2;
|
||||||
enum variable_flavor flavor;
|
struct variable v;
|
||||||
|
|
||||||
p2 = parse_variable_definition (p, &flavor);
|
p2 = parse_variable_definition (p, &v);
|
||||||
|
|
||||||
/* If this is a variable assignment, we're done. */
|
/* If this is a variable assignment, we're done. */
|
||||||
if (p2)
|
if (p2)
|
||||||
@ -1342,33 +1342,33 @@ static struct variable *
|
|||||||
do_define (char *name, enum variable_origin origin, struct ebuffer *ebuf)
|
do_define (char *name, enum variable_origin origin, struct ebuffer *ebuf)
|
||||||
{
|
{
|
||||||
struct variable *v;
|
struct variable *v;
|
||||||
enum variable_flavor flavor;
|
struct variable var;
|
||||||
struct floc defstart;
|
struct floc defstart;
|
||||||
int nlevels = 1;
|
int nlevels = 1;
|
||||||
unsigned int length = 100;
|
unsigned int length = 100;
|
||||||
char *definition = xmalloc (length);
|
char *definition = xmalloc (length);
|
||||||
unsigned int idx = 0;
|
unsigned int idx = 0;
|
||||||
char *p, *var;
|
char *p, *n;
|
||||||
|
|
||||||
defstart = ebuf->floc;
|
defstart = ebuf->floc;
|
||||||
|
|
||||||
p = parse_variable_definition (name, &flavor);
|
p = parse_variable_definition (name, &var);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
/* No assignment token, so assume recursive. */
|
/* No assignment token, so assume recursive. */
|
||||||
flavor = f_recursive;
|
var.flavor = f_recursive;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (*(next_token (p)) != '\0')
|
if (var.value[0] != '\0')
|
||||||
error (&defstart, _("extraneous text after `define' directive"));
|
error (&defstart, _("extraneous text after `define' directive"));
|
||||||
|
|
||||||
/* Chop the string before the assignment token to get the name. */
|
/* Chop the string before the assignment token to get the name. */
|
||||||
p[flavor == f_recursive ? -1 : -2] = '\0';
|
var.name[var.length] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expand the variable name and find the beginning (NAME) and end. */
|
/* Expand the variable name and find the beginning (NAME) and end. */
|
||||||
var = allocated_variable_expand (name);
|
n = allocated_variable_expand (name);
|
||||||
name = next_token (var);
|
name = next_token (n);
|
||||||
if (*name == '\0')
|
if (name[0] == '\0')
|
||||||
fatal (&defstart, _("empty variable name"));
|
fatal (&defstart, _("empty variable name"));
|
||||||
p = name + strlen (name) - 1;
|
p = name + strlen (name) - 1;
|
||||||
while (p > name && isblank ((unsigned char)*p))
|
while (p > name && isblank ((unsigned char)*p))
|
||||||
@ -1439,9 +1439,10 @@ do_define (char *name, enum variable_origin origin, struct ebuffer *ebuf)
|
|||||||
else
|
else
|
||||||
definition[idx - 1] = '\0';
|
definition[idx - 1] = '\0';
|
||||||
|
|
||||||
v = do_variable_definition (&defstart, name, definition, origin, flavor, 0);
|
v = do_variable_definition (&defstart, name,
|
||||||
|
definition, origin, var.flavor, 0);
|
||||||
free (definition);
|
free (definition);
|
||||||
free (var);
|
free (n);
|
||||||
return (v);
|
return (v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2467,7 +2468,7 @@ readline (struct ebuffer *ebuf)
|
|||||||
w_colon A colon
|
w_colon A colon
|
||||||
w_dcolon A double-colon
|
w_dcolon A double-colon
|
||||||
w_semicolon A semicolon
|
w_semicolon A semicolon
|
||||||
w_varassign A variable assignment operator (=, :=, +=, ?=, or !=)
|
w_varassign A variable assignment operator (=, :=, ::=, +=, ?=, or !=)
|
||||||
|
|
||||||
Note that this function is only used when reading certain parts of the
|
Note that this function is only used when reading certain parts of the
|
||||||
makefile. Don't use it where special rules hold sway (RHS of a variable,
|
makefile. Don't use it where special rules hold sway (RHS of a variable,
|
||||||
@ -2506,7 +2507,13 @@ get_next_mword (char *buffer, char *delim, char **startp, unsigned int *length)
|
|||||||
{
|
{
|
||||||
case ':':
|
case ':':
|
||||||
++p;
|
++p;
|
||||||
wtype = w_dcolon;
|
if (p[1] != '=')
|
||||||
|
wtype = w_dcolon;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wtype = w_varassign;
|
||||||
|
++p;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '=':
|
case '=':
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
2012-01-29 Paul Smith <psmith@gnu.org>
|
2012-01-29 Paul Smith <psmith@gnu.org>
|
||||||
|
|
||||||
|
* scripts/variables/flavors: Add tests for ::=
|
||||||
|
* scripts/variables/define: Ditto
|
||||||
|
|
||||||
* scripts/functions/file: Test the new $(file ...) function.
|
* scripts/functions/file: Test the new $(file ...) function.
|
||||||
|
|
||||||
2012-01-12 Paul Smith <psmith@gnu.org>
|
2012-01-12 Paul Smith <psmith@gnu.org>
|
||||||
|
@ -30,6 +30,10 @@ define simple :=
|
|||||||
@echo $(FOO)
|
@echo $(FOO)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
define posix ::=
|
||||||
|
@echo $(FOO)
|
||||||
|
endef
|
||||||
|
|
||||||
append = @echo a
|
append = @echo a
|
||||||
|
|
||||||
define append +=
|
define append +=
|
||||||
@ -49,10 +53,54 @@ FOO = there
|
|||||||
|
|
||||||
all: ; $(multi)
|
all: ; $(multi)
|
||||||
$(simple)
|
$(simple)
|
||||||
|
$(posix)
|
||||||
$(append)
|
$(append)
|
||||||
$(cond)
|
$(cond)
|
||||||
',
|
',
|
||||||
'', "echo hi\nhi\nthere\nfoo\na\nb\nfirst\n");
|
'', "echo hi\nhi\nthere\nfoo\nfoo\na\nb\nfirst\n");
|
||||||
|
|
||||||
|
# TEST 1a: Various new-style define/endef, with no spaces
|
||||||
|
|
||||||
|
run_make_test('
|
||||||
|
FOO = foo
|
||||||
|
|
||||||
|
define multi=
|
||||||
|
echo hi
|
||||||
|
@echo $(FOO)
|
||||||
|
endef # this is the end
|
||||||
|
|
||||||
|
define simple:=
|
||||||
|
@echo $(FOO)
|
||||||
|
endef
|
||||||
|
|
||||||
|
define posix::=
|
||||||
|
@echo $(FOO)
|
||||||
|
endef
|
||||||
|
|
||||||
|
append = @echo a
|
||||||
|
|
||||||
|
define append+=
|
||||||
|
|
||||||
|
@echo b
|
||||||
|
endef
|
||||||
|
|
||||||
|
define cond?= # this is a conditional
|
||||||
|
@echo first
|
||||||
|
endef
|
||||||
|
|
||||||
|
define cond?=
|
||||||
|
@echo second
|
||||||
|
endef
|
||||||
|
|
||||||
|
FOO = there
|
||||||
|
|
||||||
|
all: ; $(multi)
|
||||||
|
$(simple)
|
||||||
|
$(posix)
|
||||||
|
$(append)
|
||||||
|
$(cond)
|
||||||
|
',
|
||||||
|
'', "echo hi\nhi\nthere\nfoo\nfoo\na\nb\nfirst\n");
|
||||||
|
|
||||||
# TEST 2: define in true section of conditional (containing conditional)
|
# TEST 2: define in true section of conditional (containing conditional)
|
||||||
|
|
||||||
|
@ -73,4 +73,24 @@ all: ; @echo $(foo)
|
|||||||
',
|
',
|
||||||
'', "Hello\n");
|
'', "Hello\n");
|
||||||
|
|
||||||
|
# TEST 6: Simple using POSIX syntax
|
||||||
|
run_make_test('
|
||||||
|
bar = Goodbye
|
||||||
|
foo ::= $(bar)
|
||||||
|
bar = ${ugh}
|
||||||
|
ugh = Hello
|
||||||
|
all: ; @echo $(foo)
|
||||||
|
',
|
||||||
|
'', "Goodbye\n");
|
||||||
|
|
||||||
|
# TEST 7: POSIX syntax no spaces
|
||||||
|
run_make_test('
|
||||||
|
bar = Goodbye
|
||||||
|
foo::=$(bar)
|
||||||
|
bar = ${ugh}
|
||||||
|
ugh = Hello
|
||||||
|
all: ; @echo $(foo)
|
||||||
|
',
|
||||||
|
'', "Goodbye\n");
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
76
variable.c
76
variable.c
@ -1396,17 +1396,27 @@ do_variable_definition (const struct floc *flocp, const char *varname,
|
|||||||
|
|
||||||
/* Parse P (a null-terminated string) as a variable definition.
|
/* Parse P (a null-terminated string) as a variable definition.
|
||||||
|
|
||||||
If it is not a variable definition, return NULL.
|
If it is not a variable definition, return NULL and the contents of *VAR
|
||||||
|
are undefined, except NAME is set to the first non-space character or NIL.
|
||||||
|
|
||||||
If it is a variable definition, return a pointer to the char after the
|
If it is a variable definition, return a pointer to the char after the
|
||||||
assignment token and set *FLAVOR to the type of variable assignment. */
|
assignment token and set the following fields (only) of *VAR:
|
||||||
|
name : name of the variable (ALWAYS SET) (NOT NUL-TERMINATED!)
|
||||||
|
length : length of the variable name
|
||||||
|
value : value of the variable (nul-terminated)
|
||||||
|
flavor : flavor of the variable
|
||||||
|
Other values in *VAR are unchanged.
|
||||||
|
*/
|
||||||
|
|
||||||
char *
|
char *
|
||||||
parse_variable_definition (const char *p, enum variable_flavor *flavor)
|
parse_variable_definition (const char *p, struct variable *var)
|
||||||
{
|
{
|
||||||
int wspace = 0;
|
int wspace = 0;
|
||||||
|
const char *e = NULL;
|
||||||
|
|
||||||
p = next_token (p);
|
p = next_token (p);
|
||||||
|
var->name = (char *)p;
|
||||||
|
var->length = 0;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
@ -1451,6 +1461,7 @@ parse_variable_definition (const char *p, enum variable_flavor *flavor)
|
|||||||
if (isblank ((unsigned char)c))
|
if (isblank ((unsigned char)c))
|
||||||
{
|
{
|
||||||
wspace = 1;
|
wspace = 1;
|
||||||
|
e = p - 1;
|
||||||
p = next_token (p);
|
p = next_token (p);
|
||||||
c = *p;
|
c = *p;
|
||||||
if (c == '\0')
|
if (c == '\0')
|
||||||
@ -1461,8 +1472,10 @@ parse_variable_definition (const char *p, enum variable_flavor *flavor)
|
|||||||
|
|
||||||
if (c == '=')
|
if (c == '=')
|
||||||
{
|
{
|
||||||
*flavor = f_recursive;
|
var->flavor = f_recursive;
|
||||||
return (char *)p;
|
if (! e)
|
||||||
|
e = p - 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Match assignment variants (:=, +=, ?=, !=) */
|
/* Match assignment variants (:=, +=, ?=, !=) */
|
||||||
@ -1471,16 +1484,16 @@ parse_variable_definition (const char *p, enum variable_flavor *flavor)
|
|||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case ':':
|
case ':':
|
||||||
*flavor = f_simple;
|
var->flavor = f_simple;
|
||||||
break;
|
break;
|
||||||
case '+':
|
case '+':
|
||||||
*flavor = f_append;
|
var->flavor = f_append;
|
||||||
break;
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
*flavor = f_conditional;
|
var->flavor = f_conditional;
|
||||||
break;
|
break;
|
||||||
case '!':
|
case '!':
|
||||||
*flavor = f_shell;
|
var->flavor = f_shell;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* If we skipped whitespace, non-assignments means no var. */
|
/* If we skipped whitespace, non-assignments means no var. */
|
||||||
@ -1490,17 +1503,34 @@ parse_variable_definition (const char *p, enum variable_flavor *flavor)
|
|||||||
/* Might be assignment, or might be $= or #=. Check. */
|
/* Might be assignment, or might be $= or #=. Check. */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return (char *)++p;
|
if (! e)
|
||||||
|
e = p - 1;
|
||||||
|
++p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for POSIX ::= syntax */
|
||||||
|
if (c == ':')
|
||||||
|
{
|
||||||
|
/* A colon other than :=/::= is not a variable defn. */
|
||||||
|
if (*p != ':' || p[1] != '=')
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* POSIX allows ::= to be the same as GNU make's := */
|
||||||
|
var->flavor = f_simple;
|
||||||
|
if (! e)
|
||||||
|
e = p - 1;
|
||||||
|
p += 2;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (c == ':')
|
|
||||||
/* A colon other than := is a rule line, not a variable defn. */
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* If we skipped whitespace, non-assignments means no var. */
|
/* If we skipped whitespace, non-assignments means no var. */
|
||||||
if (wspace)
|
if (wspace)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var->length = e - var->name;
|
||||||
|
var->value = next_token (p);
|
||||||
return (char *)p;
|
return (char *)p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1513,27 +1543,15 @@ parse_variable_definition (const char *p, enum variable_flavor *flavor)
|
|||||||
struct variable *
|
struct variable *
|
||||||
assign_variable_definition (struct variable *v, char *line)
|
assign_variable_definition (struct variable *v, char *line)
|
||||||
{
|
{
|
||||||
char *beg;
|
|
||||||
char *end;
|
|
||||||
enum variable_flavor flavor;
|
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
beg = next_token (line);
|
if (!parse_variable_definition (line, v))
|
||||||
line = parse_variable_definition (beg, &flavor);
|
|
||||||
if (!line)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
end = line - (flavor == f_recursive ? 1 : 2);
|
|
||||||
while (end > beg && isblank ((unsigned char)end[-1]))
|
|
||||||
--end;
|
|
||||||
line = next_token (line);
|
|
||||||
v->value = line;
|
|
||||||
v->flavor = flavor;
|
|
||||||
|
|
||||||
/* Expand the name, so "$(foo)bar = baz" works. */
|
/* Expand the name, so "$(foo)bar = baz" works. */
|
||||||
name = alloca (end - beg + 1);
|
name = alloca (v->length + 1);
|
||||||
memcpy (name, beg, end - beg);
|
memcpy (name, v->name, v->length);
|
||||||
name[end - beg] = '\0';
|
name[v->length] = '\0';
|
||||||
v->name = allocated_variable_expand (name);
|
v->name = allocated_variable_expand (name);
|
||||||
|
|
||||||
if (v->name[0] == '\0')
|
if (v->name[0] == '\0')
|
||||||
|
@ -35,7 +35,7 @@ enum variable_origin
|
|||||||
enum variable_flavor
|
enum variable_flavor
|
||||||
{
|
{
|
||||||
f_bogus, /* Bogus (error) */
|
f_bogus, /* Bogus (error) */
|
||||||
f_simple, /* Simple definition (:=) */
|
f_simple, /* Simple definition (:= or ::=) */
|
||||||
f_recursive, /* Recursive definition (=) */
|
f_recursive, /* Recursive definition (=) */
|
||||||
f_append, /* Appending definition (+=) */
|
f_append, /* Appending definition (+=) */
|
||||||
f_conditional, /* Conditional definition (?=) */
|
f_conditional, /* Conditional definition (?=) */
|
||||||
@ -52,9 +52,9 @@ enum variable_flavor
|
|||||||
struct variable
|
struct variable
|
||||||
{
|
{
|
||||||
char *name; /* Variable name. */
|
char *name; /* Variable name. */
|
||||||
int length; /* strlen (name) */
|
|
||||||
char *value; /* Variable value. */
|
char *value; /* Variable value. */
|
||||||
struct floc fileinfo; /* Where the variable was defined. */
|
struct floc fileinfo; /* Where the variable was defined. */
|
||||||
|
int length; /* strlen (name) */
|
||||||
unsigned int recursive:1; /* Gets recursively re-evaluated. */
|
unsigned int recursive:1; /* Gets recursively re-evaluated. */
|
||||||
unsigned int append:1; /* Nonzero if an appending target-specific
|
unsigned int append:1; /* Nonzero if an appending target-specific
|
||||||
variable. */
|
variable. */
|
||||||
@ -160,7 +160,7 @@ struct variable *do_variable_definition (const struct floc *flocp,
|
|||||||
enum variable_flavor flavor,
|
enum variable_flavor flavor,
|
||||||
int target_var);
|
int target_var);
|
||||||
char *parse_variable_definition (const char *line,
|
char *parse_variable_definition (const char *line,
|
||||||
enum variable_flavor *flavor);
|
struct variable *v);
|
||||||
struct variable *assign_variable_definition (struct variable *v, char *line);
|
struct variable *assign_variable_definition (struct variable *v, char *line);
|
||||||
struct variable *try_variable_definition (const struct floc *flocp, char *line,
|
struct variable *try_variable_definition (const struct floc *flocp, char *line,
|
||||||
enum variable_origin origin,
|
enum variable_origin origin,
|
||||||
|
Loading…
Reference in New Issue
Block a user