Import bmake-20160307

This commit is contained in:
Simon J. Gerraty 2016-03-11 00:37:02 +00:00
parent 6c770d664f
commit d58aa1959c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/NetBSD/bmake/dist/; revision=296635
svn path=/vendor/NetBSD/bmake/20160307/; revision=296636; tag=vendor/NetBSD/bmake/20160307
38 changed files with 778 additions and 483 deletions

View File

@ -1,3 +1,41 @@
2016-03-07 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20160307
Merge with NetBSD make, pick up
o var.c: fix :ts\nnn to be octal by default.
o meta.c: meta_finish() to cleanup memory.
2016-02-26 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20160226
Merge with NetBSD make, pick up
o meta.c: allow meta file for makeDepend if makefiles want it.
2016-02-19 Simon J. Gerraty <sjg@bad.crufty.net>
* var.c: default .MAKE.SAVE_DOLLARS to FALSE
for backwards compatability.
* Makefile (MAKE_VERSION): 20160220
Merge with NetBSD make, pick up
o var.c: add knob to control handling of '$$' in :=
2016-02-18 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20160218
Merge with NetBSD make, pick up
o var.c: add .export-literal allows us to fix sys.clean-env.mk
post the changes to Var_Subst.
Var_Subst now takes flags, and does not consume '$$' in :=
2016-02-17 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20160217
Merge with NetBSD make, pick up
o var.c: preserve '$$' in :=
o parse.c: add .dinclude for handling included
makefile like .depend
2015-12-20 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20151220

View File

@ -1,7 +1,7 @@
# $Id: Makefile,v 1.49 2015/12/20 22:54:40 sjg Exp $
# $Id: Makefile,v 1.55 2016/03/07 22:02:47 sjg Exp $
# Base version on src date
MAKE_VERSION= 20151220
MAKE_VERSION= 20160307
PROG= bmake

48
arch.c
View File

@ -1,4 +1,4 @@
/* $NetBSD: arch.c,v 1.64 2015/10/11 04:51:24 sjg Exp $ */
/* $NetBSD: arch.c,v 1.68 2016/02/18 18:29:14 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: arch.c,v 1.64 2015/10/11 04:51:24 sjg Exp $";
static char rcsid[] = "$NetBSD: arch.c,v 1.68 2016/02/18 18:29:14 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94";
#else
__RCSID("$NetBSD: arch.c,v 1.64 2015/10/11 04:51:24 sjg Exp $");
__RCSID("$NetBSD: arch.c,v 1.68 2016/02/18 18:29:14 christos Exp $");
#endif
#endif /* not lint */
#endif
@ -136,7 +136,6 @@ __RCSID("$NetBSD: arch.c,v 1.64 2015/10/11 04:51:24 sjg Exp $");
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/param.h>
#include <ctype.h>
#ifdef HAVE_AR_H
#include <ar.h>
#else
@ -156,7 +155,6 @@ struct ar_hdr {
#if defined(HAVE_RANLIB_H) && !(defined(__ELF__) || defined(NO_RANLIB))
#include <ranlib.h>
#endif
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UTIME_H
@ -254,8 +252,7 @@ ArchFree(void *ap)
free(Hash_GetValue(entry));
free(a->name);
if (a->fnametab)
free(a->fnametab);
free(a->fnametab);
Hash_DeleteTable(&a->members);
free(a);
}
@ -310,9 +307,10 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
void *freeIt;
char *result;
result = Var_Parse(cp, ctxt, TRUE, TRUE, &length, &freeIt);
if (freeIt)
free(freeIt);
result = Var_Parse(cp, ctxt, VARF_UNDEFERR|VARF_WANTRES,
&length, &freeIt);
free(freeIt);
if (result == var_Error) {
return(FAILURE);
} else {
@ -325,7 +323,7 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
*cp++ = '\0';
if (subLibName) {
libName = Var_Subst(NULL, libName, ctxt, TRUE, TRUE);
libName = Var_Subst(NULL, libName, ctxt, VARF_UNDEFERR|VARF_WANTRES);
}
@ -351,9 +349,10 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
void *freeIt;
char *result;
result = Var_Parse(cp, ctxt, TRUE, TRUE, &length, &freeIt);
if (freeIt)
free(freeIt);
result = Var_Parse(cp, ctxt, VARF_UNDEFERR|VARF_WANTRES,
&length, &freeIt);
free(freeIt);
if (result == var_Error) {
return(FAILURE);
} else {
@ -404,7 +403,8 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
char *oldMemName = memName;
size_t sz;
memName = Var_Subst(NULL, memName, ctxt, TRUE, TRUE);
memName = Var_Subst(NULL, memName, ctxt,
VARF_UNDEFERR|VARF_WANTRES);
/*
* Now form an archive spec and recurse to deal with nested
@ -759,8 +759,7 @@ ArchStatMember(char *archive, char *member, Boolean hash)
badarch:
fclose(arch);
Hash_DeleteTable(&ar->members);
if (ar->fnametab)
free(ar->fnametab);
free(ar->fnametab);
free(ar);
return NULL;
}
@ -1045,10 +1044,10 @@ Arch_Touch(GNode *gn)
arch = ArchFindMember(Var_Value(ARCHIVE, gn, &p1),
Var_Value(MEMBER, gn, &p2),
&arh, "r+");
if (p1)
free(p1);
if (p2)
free(p2);
free(p1);
free(p2);
snprintf(arh.AR_DATE, sizeof(arh.AR_DATE), "%-12ld", (long) now);
if (arch != NULL) {
@ -1127,10 +1126,9 @@ Arch_MTime(GNode *gn)
arhPtr = ArchStatMember(Var_Value(ARCHIVE, gn, &p1),
Var_Value(MEMBER, gn, &p2),
TRUE);
if (p1)
free(p1);
if (p2)
free(p2);
free(p1);
free(p2);
if (arhPtr != NULL) {
modTime = (time_t)strtol(arhPtr->AR_DATE, NULL, 10);

47
bmake.1
View File

@ -1,4 +1,4 @@
.\" $NetBSD: make.1,v 1.249 2015/06/05 07:33:40 wiz Exp $
.\" $NetBSD: make.1,v 1.254 2016/02/20 01:43:28 wiz Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -29,7 +29,7 @@
.\"
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
.\"
.Dd June 4, 2015
.Dd February 19, 2016
.Dt MAKE 1
.Os
.Sh NAME
@ -293,7 +293,7 @@ then
will search for the specified file or directory named in the remaining part
of the argument string.
The search starts with the current directory of
the Makefile and then works upward towards the root of the filesystem.
the Makefile and then works upward towards the root of the file system.
If the search is successful, then the resulting directory replaces the
.Qq \&.../
specification in the
@ -868,7 +868,7 @@ This can be overridden by setting
.Va bf
to a value which represents True.
.It Pa env
For debugging, it can be useful to inlcude the environment
For debugging, it can be useful to include the environment
in the .meta file.
.It Pa verbose
If in "meta" mode, print a clue about the target being built.
@ -918,7 +918,7 @@ The default value is:
This variable is used to record the names of variables assigned to
on the command line, so that they may be exported as part of
.Ql Ev MAKEFLAGS .
This behaviour can be disabled by assigning an empty value to
This behavior can be disabled by assigning an empty value to
.Ql Va .MAKEOVERRIDES
within a makefile.
Extra variables can be exported from a makefile
@ -941,6 +941,19 @@ The process-id of
.It Va .MAKE.PPID
The parent process-id of
.Nm .
.It Va .MAKE.SAVE_DOLLARS
value should be a boolean that controls whether
.Ql $$
are preserved when doing
.Ql :=
assignments.
The default is false, for backwards compatibility.
Set to true for compatability with other makes.
If set to false,
.Ql $$
becomes
.Ql $
per normal evaluation rules.
.It Va MAKE_PRINT_VAR_ON_ERROR
When
.Nm
@ -1044,7 +1057,7 @@ sets
to the value of
.Ql Ev PWD
instead.
This behaviour is disabled if
This behavior is disabled if
.Ql Ev MAKEOBJDIRPREFIX
is set or
.Ql Ev MAKEOBJDIR
@ -1114,7 +1127,7 @@ The wildcard characters may be escaped with a backslash
As a consequence of the way values are split into words, matched,
and then joined, a construct like
.Dl ${VAR:M*}
will normalise the inter-word spacing, removing all leading and
will normalize the inter-word spacing, removing all leading and
trailing space, and converting multiple consecutive spaces
to single spaces.
.
@ -1134,7 +1147,7 @@ Randomize words in variable.
The results will be different each time you are referring to the
modified variable; use the assignment with expansion
.Pq Ql Cm \&:=
to prevent such behaviour.
to prevent such behavior.
For example,
.Bd -literal -offset indent
LIST= uno due tre quattro
@ -1166,7 +1179,7 @@ The value is a format string for
using the current
.Xr gmtime 3 .
.It Cm \&:hash
Compute a 32bit hash of the value and encode it as hex digits.
Compute a 32-bit hash of the value and encode it as hex digits.
.It Cm \&:localtime
The value is a format string for
.Xr strftime 3 ,
@ -1444,7 +1457,7 @@ value is divided into words.
.Pp
Ordinarily, a value is treated as a sequence of words
delimited by white space.
Some modifiers suppress this behaviour,
Some modifiers suppress this behavior,
causing a value to be treated as a single word
(possibly containing embedded white space).
An empty value, or a value that consists entirely of white-space,
@ -1530,12 +1543,20 @@ For compatibility with other versions of
.Nm
.Ql include file ...
is also accepted.
.Pp
If the include statement is written as
.Cm .-include
or as
.Cm .sinclude
then errors locating and/or opening include files are ignored.
.Pp
If the include statement is written as
.Cm .dinclude
not only are errors locating and/or opening include files ignored,
but stale dependencies within the included file will be ignored
just like
.Va .MAKE.DEPENDFILE .
.Pp
Conditional expressions are also preceded by a single dot as the first
character of a line.
The possible conditionals are as follows:
@ -1571,6 +1592,10 @@ This allows exporting a value to the environment which is different from that
used by
.Nm
internally.
.It Ic .export-literal Ar variable ...
The same as
.Ql .export-env ,
except that variables in the value are not expanded.
.It Ic .info Ar message
The message is printed along with the name of the makefile and line number.
.It Ic .undef Ar variable
@ -2068,7 +2093,7 @@ The sources are a set of
pairs.
.Bl -tag -width hasErrCtls
.It Ar name
This is the minimal specification, used to select one of the builtin
This is the minimal specification, used to select one of the built-in
shell specs;
.Ar sh ,
.Ar ksh ,

View File

@ -178,11 +178,11 @@ DDEESSCCRRIIPPTTIIOONN
then bbmmaakkee will search for the specified file or directory named
in the remaining part of the argument string. The search starts
with the current directory of the Makefile and then works upward
towards the root of the filesystem. If the search is successful,
then the resulting directory replaces the ".../" specification in
the --mm argument. If used, this feature allows bbmmaakkee to easily
search in the current source tree for customized sys.mk files
(e.g., by using ".../mk/sys.mk" as an argument).
towards the root of the file system. If the search is success-
ful, then the resulting directory replaces the ".../" specifica-
tion in the --mm argument. If used, this feature allows bbmmaakkee to
easily search in the current source tree for customized sys.mk
files (e.g., by using ".../mk/sys.mk" as an argument).
--nn Display the commands that would have been executed, but do not
actually execute them unless the target depends on the .MAKE spe-
@ -543,7 +543,7 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
in `_._C_U_R_D_I_R'. This can be overridden by set-
ting _b_f to a value which represents True.
_e_n_v For debugging, it can be useful to inlcude
_e_n_v For debugging, it can be useful to include
the environment in the .meta file.
_v_e_r_b_o_s_e If in "meta" mode, print a clue about the
@ -591,7 +591,7 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
_._M_A_K_E_O_V_E_R_R_I_D_E_S This variable is used to record the names of variables
assigned to on the command line, so that they may be
exported as part of `MAKEFLAGS'. This behaviour can be
exported as part of `MAKEFLAGS'. This behavior can be
disabled by assigning an empty value to `_._M_A_K_E_O_V_E_R_R_I_D_E_S'
within a makefile. Extra variables can be exported from
a makefile by appending their names to `_._M_A_K_E_O_V_E_R_R_I_D_E_S'.
@ -607,6 +607,13 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
_._M_A_K_E_._P_P_I_D The parent process-id of bbmmaakkee.
_._M_A_K_E_._S_A_V_E___D_O_L_L_A_R_S
value should be a boolean that controls whether `$$' are
preserved when doing `:=' assignments. The default is
false, for backwards compatibility. Set to true for com-
patability with other makes. If set to false, `$$'
becomes `$' per normal evaluation rules.
_M_A_K_E___P_R_I_N_T___V_A_R___O_N___E_R_R_O_R
When bbmmaakkee stops due to an error, it prints its name and
the value of `_._C_U_R_D_I_R' as well as the value of any vari-
@ -670,7 +677,7 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
sets `_._C_U_R_D_I_R' to the canonical path given by getcwd(3).
However, if the environment variable `PWD' is set and
gives a path to the current directory, then bbmmaakkee sets
`_._C_U_R_D_I_R' to the value of `PWD' instead. This behaviour
`_._C_U_R_D_I_R' to the value of `PWD' instead. This behavior
is disabled if `MAKEOBJDIRPREFIX' is set or `MAKEOBJDIR'
contains a variable transform. `PWD' is set to the value
of `_._O_B_J_D_I_R' for all programs which bbmmaakkee executes.
@ -717,7 +724,7 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
of the way values are split into words, matched, and then joined, a
construct like
${VAR:M*}
will normalise the inter-word spacing, removing all leading and
will normalize the inter-word spacing, removing all leading and
trailing space, and converting multiple consecutive spaces to single
spaces.
@ -730,7 +737,7 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
::OOxx Randomize words in variable. The results will be different each
time you are referring to the modified variable; use the assignment
with expansion (`::==') to prevent such behaviour. For example,
with expansion (`::==') to prevent such behavior. For example,
LIST= uno due tre quattro
RANDOM_LIST= ${LIST:Ox}
@ -758,7 +765,7 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
gmtime(3).
::hhaasshh
Compute a 32bit hash of the value and encode it as hex digits.
Compute a 32-bit hash of the value and encode it as hex digits.
::llooccaallttiimmee
The value is a format string for strftime(3), using the current
@ -914,13 +921,13 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
tions related to the way in which the value is divided into words.
Ordinarily, a value is treated as a sequence of words delimited by
white space. Some modifiers suppress this behaviour, causing a
value to be treated as a single word (possibly containing embedded
white space). An empty value, or a value that consists entirely of
white-space, is treated as a single word. For the purposes of the
`::[[]]' modifier, the words are indexed both forwards using positive
integers (where index 1 represents the first word), and backwards
using negative integers (where index -1 represents the last word).
white space. Some modifiers suppress this behavior, causing a value
to be treated as a single word (possibly containing embedded white
space). An empty value, or a value that consists entirely of white-
space, is treated as a single word. For the purposes of the `::[[]]'
modifier, the words are indexed both forwards using positive inte-
gers (where index 1 represents the first word), and backwards using
negative integers (where index -1 represents the last word).
The _r_a_n_g_e is subjected to variable expansion, and the expanded
result is then interpreted as follows:
@ -957,8 +964,14 @@ IINNCCLLUUDDEE SSTTAATTEEMMEENNTTSS,, CCOONNDDIITTIIOO
used, the including makefile's directory and any directories specified
using the --II option are searched before the system makefile directory.
For compatibility with other versions of bbmmaakkee `include file ...' is also
accepted. If the include statement is written as ..--iinncclluuddee or as
..ssiinncclluuddee then errors locating and/or opening include files are ignored.
accepted.
If the include statement is written as ..--iinncclluuddee or as ..ssiinncclluuddee then
errors locating and/or opening include files are ignored.
If the include statement is written as ..ddiinncclluuddee not only are errors
locating and/or opening include files ignored, but stale dependencies
within the included file will be ignored just like _._M_A_K_E_._D_E_P_E_N_D_F_I_L_E.
Conditional expressions are also preceded by a single dot as the first
character of a line. The possible conditionals are as follows:
@ -982,6 +995,10 @@ IINNCCLLUUDDEE SSTTAATTEEMMEENNTTSS,, CCOONNDDIITTIIOO
to _._M_A_K_E_._E_X_P_O_R_T_E_D. This allows exporting a value to the environ-
ment which is different from that used by bbmmaakkee internally.
..eexxppoorrtt--lliitteerraall _v_a_r_i_a_b_l_e _._._.
The same as `.export-env', except that variables in the value are
not expanded.
..iinnffoo _m_e_s_s_a_g_e
The message is printed along with the name of the makefile and
line number.
@ -1307,7 +1324,7 @@ SSPPEECCIIAALL TTAARRGGEETTSS
sources are a set of _f_i_e_l_d_=_v_a_l_u_e pairs.
_n_a_m_e This is the minimal specification, used to select
one of the builtin shell specs; _s_h, _k_s_h, and _c_s_h.
one of the built-in shell specs; _s_h, _k_s_h, and _c_s_h.
_p_a_t_h Specifies the path to the shell.
@ -1452,4 +1469,4 @@ BBUUGGSS
There is no way of escaping a space character in a filename.
NetBSD 5.1 June 4, 2015 NetBSD 5.1
NetBSD 5.1 February 19, 2016 NetBSD 5.1

View File

@ -1,4 +1,4 @@
/* $NetBSD: compat.c,v 1.101 2015/10/11 04:51:24 sjg Exp $ */
/* $NetBSD: compat.c,v 1.104 2016/02/18 18:29:14 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -70,14 +70,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: compat.c,v 1.101 2015/10/11 04:51:24 sjg Exp $";
static char rcsid[] = "$NetBSD: compat.c,v 1.104 2016/02/18 18:29:14 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)compat.c 8.2 (Berkeley) 3/19/94";
#else
__RCSID("$NetBSD: compat.c,v 1.101 2015/10/11 04:51:24 sjg Exp $");
__RCSID("$NetBSD: compat.c,v 1.104 2016/02/18 18:29:14 christos Exp $");
#endif
#endif /* not lint */
#endif
@ -146,8 +146,8 @@ CompatInterrupt(int signo)
if (!noExecute && eunlink(file) != -1) {
Error("*** %s removed", file);
}
if (p1)
free(p1);
free(p1);
/*
* Run .INTERRUPT only if hit with interrupt signal
@ -213,7 +213,7 @@ CompatRunCommand(void *cmdp, void *gnp)
doIt = FALSE;
cmdNode = Lst_Member(gn->commands, cmd);
cmdStart = Var_Subst(NULL, cmd, gn, FALSE, TRUE);
cmdStart = Var_Subst(NULL, cmd, gn, VARF_WANTRES);
/*
* brk_string will return an argv with a NULL in av[0], thus causing
@ -374,10 +374,10 @@ CompatRunCommand(void *cmdp, void *gnp)
execError("exec", av[0]);
_exit(1);
}
if (mav)
free(mav);
if (bp)
free(bp);
free(mav);
free(bp);
Lst_Replace(cmdNode, NULL);
#ifdef USE_META
@ -516,8 +516,7 @@ Compat_Make(void *gnp, void *pgnp)
if (Lst_Member(gn->iParents, pgn) != NULL) {
char *p1;
Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), pgn, 0);
if (p1)
free(p1);
free(p1);
}
/*
@ -620,8 +619,7 @@ Compat_Make(void *gnp, void *pgnp)
if (Lst_Member(gn->iParents, pgn) != NULL) {
char *p1;
Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), pgn, 0);
if (p1)
free(p1);
free(p1);
}
switch(gn->made) {
case BEINGMADE:

38
cond.c
View File

@ -1,4 +1,4 @@
/* $NetBSD: cond.c,v 1.71 2015/12/02 00:28:24 sjg Exp $ */
/* $NetBSD: cond.c,v 1.74 2016/02/18 18:29:14 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -70,14 +70,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: cond.c,v 1.71 2015/12/02 00:28:24 sjg Exp $";
static char rcsid[] = "$NetBSD: cond.c,v 1.74 2016/02/18 18:29:14 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)cond.c 8.2 (Berkeley) 1/2/94";
#else
__RCSID("$NetBSD: cond.c,v 1.71 2015/12/02 00:28:24 sjg Exp $");
__RCSID("$NetBSD: cond.c,v 1.74 2016/02/18 18:29:14 christos Exp $");
#endif
#endif /* not lint */
#endif
@ -289,10 +289,10 @@ CondGetArg(char **linePtr, char **argPtr, const char *func)
int len;
void *freeIt;
cp2 = Var_Parse(cp, VAR_CMD, TRUE, TRUE, &len, &freeIt);
cp2 = Var_Parse(cp, VAR_CMD, VARF_UNDEFERR|VARF_WANTRES,
&len, &freeIt);
Buf_AddBytes(&buf, strlen(cp2), cp2);
if (freeIt)
free(freeIt);
free(freeIt);
cp += len;
continue;
}
@ -346,8 +346,8 @@ CondDoDefined(int argLen MAKE_ATTR_UNUSED, const char *arg)
} else {
result = FALSE;
}
if (p1)
free(p1);
free(p1);
return (result);
}
@ -574,8 +574,9 @@ CondGetString(Boolean doEval, Boolean *quoted, void **freeIt, Boolean strictLHS)
break;
case '$':
/* if we are in quotes, then an undefined variable is ok */
str = Var_Parse(condExpr, VAR_CMD, (qt ? 0 : doEval),
TRUE, &len, freeIt);
str = Var_Parse(condExpr, VAR_CMD,
((!qt && doEval) ? VARF_UNDEFERR : 0) |
VARF_WANTRES, &len, freeIt);
if (str == var_Error) {
if (*freeIt) {
free(*freeIt);
@ -805,10 +806,8 @@ compare_expression(Boolean doEval)
}
done:
if (lhsFree)
free(lhsFree);
if (rhsFree)
free(rhsFree);
free(lhsFree);
free(rhsFree);
return t;
}
@ -827,7 +826,7 @@ get_mpt_arg(char **linePtr, char **argPtr, const char *func MAKE_ATTR_UNUSED)
/* We do all the work here and return the result as the length */
*argPtr = NULL;
val = Var_Parse(cp - 1, VAR_CMD, FALSE, TRUE, &length, &freeIt);
val = Var_Parse(cp - 1, VAR_CMD, VARF_WANTRES, &length, &freeIt);
/*
* Advance *linePtr to beyond the closing ). Note that
* we subtract one because 'length' is calculated from 'cp - 1'.
@ -848,8 +847,7 @@ get_mpt_arg(char **linePtr, char **argPtr, const char *func MAKE_ATTR_UNUSED)
* true/false here.
*/
length = *val ? 2 : 1;
if (freeIt)
free(freeIt);
free(freeIt);
return length;
}
@ -900,8 +898,7 @@ compare_function(Boolean doEval)
}
/* Evaluate the argument using the required function. */
t = !doEval || fn_def->fn_proc(arglen, arg);
if (arg)
free(arg);
free(arg);
condExpr = cp;
return t;
}
@ -933,8 +930,7 @@ compare_function(Boolean doEval)
* be empty - even if it contained a variable expansion.
*/
t = !doEval || if_info->defProc(arglen, arg) != if_info->doNot;
if (arg)
free(arg);
free(arg);
return t;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: dirname.c,v 1.11 2009/11/24 13:34:20 tnozaki Exp $ */
/* $NetBSD: dirname.c,v 1.13 2014/07/16 10:52:26 christos Exp $ */
/*-
* Copyright (c) 1997, 2002 The NetBSD Foundation, Inc.
@ -35,7 +35,10 @@
#ifndef HAVE_DIRNAME
#include <sys/cdefs.h>
#include <sys/param.h>
#ifdef HAVE_LIBGEN_H
#include <libgen.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
@ -45,51 +48,73 @@
#ifndef PATH_MAX
# define PATH_MAX 1024
#endif
#ifndef MIN
# define MIN(a, b) ((a < b) ? a : b)
#endif
char *
dirname(char *path)
static size_t
xdirname_r(const char *path, char *buf, size_t buflen)
{
static char result[PATH_MAX];
const char *lastp;
const char *endp;
size_t len;
/*
* If `path' is a null pointer or points to an empty string,
* return a pointer to the string ".".
*/
if ((path == NULL) || (*path == '\0'))
goto singledot;
if (path == NULL || *path == '\0') {
path = ".";
len = 1;
goto out;
}
/* Strip trailing slashes, if any. */
lastp = path + strlen(path) - 1;
while (lastp != path && *lastp == '/')
lastp--;
endp = path + strlen(path) - 1;
while (endp != path && *endp == '/')
endp--;
/* Terminate path at the last occurence of '/'. */
do {
if (*lastp == '/') {
/* Strip trailing slashes, if any. */
while (lastp != path && *lastp == '/')
lastp--;
/* Find the start of the dir */
while (endp > path && *endp != '/')
endp--;
/* ...and copy the result into the result buffer. */
len = (lastp - path) + 1 /* last char */;
if (len > (PATH_MAX - 1))
len = PATH_MAX - 1;
if (endp == path) {
path = *endp == '/' ? "/" : ".";
len = 1;
goto out;
}
memcpy(result, path, len);
result[len] = '\0';
do
endp--;
while (endp > path && *endp == '/');
return (result);
}
} while (--lastp >= path);
len = endp - path + 1;
out:
if (buf != NULL && buflen != 0) {
buflen = MIN(len, buflen - 1);
memcpy(buf, path, buflen);
buf[buflen] = '\0';
}
return len;
}
/* No /'s found, return a pointer to the string ".". */
singledot:
result[0] = '.';
result[1] = '\0';
char *
dirname(char *path)
{
static char result[PATH_MAX];
(void)xdirname_r(path, result, sizeof(result));
return result;
}
return (result);
#ifdef MAIN
#include <stdlib.h>
#include <stdio.h>
int
main(int argc, char *argv[])
{
printf("%s\n", dirname(argv[1]));
exit(0);
}
#endif
#endif

8
for.c
View File

@ -1,4 +1,4 @@
/* $NetBSD: for.c,v 1.50 2015/10/11 04:51:24 sjg Exp $ */
/* $NetBSD: for.c,v 1.52 2016/02/18 18:29:14 christos Exp $ */
/*
* Copyright (c) 1992, The Regents of the University of California.
@ -30,14 +30,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: for.c,v 1.50 2015/10/11 04:51:24 sjg Exp $";
static char rcsid[] = "$NetBSD: for.c,v 1.52 2016/02/18 18:29:14 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)for.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: for.c,v 1.50 2015/10/11 04:51:24 sjg Exp $");
__RCSID("$NetBSD: for.c,v 1.52 2016/02/18 18:29:14 christos Exp $");
#endif
#endif /* not lint */
#endif
@ -216,7 +216,7 @@ For_Eval(char *line)
* We can't do the escapes here - because we don't know whether
* we are substuting into ${...} or $(...).
*/
sub = Var_Subst(NULL, ptr, VAR_GLOBAL, FALSE, TRUE);
sub = Var_Subst(NULL, ptr, VAR_GLOBAL, VARF_WANTRES);
/*
* Split into words allowing for quoted strings.

View File

@ -1,3 +1,5 @@
/* $NetBSD: getopt.c,v 1.29 2014/06/05 22:00:22 christos Exp $ */
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
@ -10,11 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
@ -35,11 +33,7 @@
# include "config.h"
#endif
#if !defined(HAVE_GETOPT) || defined(WANT_GETOPT_LONG) || defined(BROKEN_GETOPT)
#if defined(LIBC_SCCS) && !defined(lint)
/* static char sccsid[] = "from: @(#)getopt.c 8.2 (Berkeley) 4/2/94"; */
static char *rcsid = "$Id: getopt.c,v 1.3 1999/01/08 02:14:18 sjg Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
#include <stdio.h>
#include <stdlib.h>
@ -61,13 +55,10 @@ char *optarg; /* argument associated with option */
* Parse argc/argv argument vector.
*/
int
getopt(nargc, nargv, ostr)
int nargc;
char * const *nargv;
const char *ostr;
getopt(int nargc, char * const nargv[], const char *ostr)
{
extern char *__progname;
static char *place = EMSG; /* option letter processing */
static const char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
#ifndef BSD4_4
@ -79,43 +70,63 @@ getopt(nargc, nargv, ostr)
}
#endif
if (optreset || !*place) { /* update scanning pointer */
if (optreset || *place == 0) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc || *(place = nargv[optind]) != '-') {
place = nargv[optind];
if (optind >= nargc || *place++ != '-') {
/* Argument is absent or is not an option */
place = EMSG;
return (-1);
}
if (place[1] && *++place == '-' /* found "--" */
&& !place[1]) { /* and not "--foo" */
optopt = *place++;
if (optopt == '-' && *place == 0) {
/* "--" => end of options */
++optind;
place = EMSG;
return (-1);
}
} /* option letter okay? */
if ((optopt = (int)*place++) == (int)':' ||
!(oli = strchr(ostr, optopt))) {
/*
* if the user didn't specify '-' as an option,
* assume it means -1.
*/
if (optopt == (int)'-')
return (-1);
if (!*place)
if (optopt == 0) {
/* Solitary '-', treat as a '-' option
if the program (eg su) is looking for it. */
place = EMSG;
if (strchr(ostr, '-') == NULL)
return -1;
optopt = '-';
}
} else
optopt = *place++;
/* See if option letter is one the caller wanted... */
if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) {
if (*place == 0)
++optind;
if (opterr && *ostr != ':')
(void)fprintf(stderr,
"%s: illegal option -- %c\n", __progname, optopt);
"%s: unknown option -- %c\n", __progname, optopt);
return (BADCH);
}
if (*++oli != ':') { /* don't need argument */
/* Does this option need an argument? */
if (oli[1] != ':') {
/* don't need argument */
optarg = NULL;
if (!*place)
if (*place == 0)
++optind;
}
else { /* need an argument */
if (*place) /* no white space */
optarg = place;
else if (nargc <= ++optind) { /* no arg */
} else {
/* Option-argument is either the rest of this argument or the
entire next argument. */
if (*place)
optarg = __UNCONST(place);
else if (oli[2] == ':')
/*
* GNU Extension, for optional arguments if the rest of
* the argument is empty, we return NULL
*/
optarg = NULL;
else if (nargc > ++optind)
optarg = nargv[optind];
else {
/* option-argument absent */
place = EMSG;
if (*ostr == ':')
return (BADARG);
@ -125,12 +136,10 @@ getopt(nargc, nargv, ostr)
__progname, optopt);
return (BADCH);
}
else /* white space */
optarg = nargv[optind];
place = EMSG;
++optind;
}
return (optopt); /* dump back option letter */
return (optopt); /* return option letter */
}
#endif
#ifdef MAIN

35
job.c
View File

@ -1,4 +1,4 @@
/* $NetBSD: job.c,v 1.181 2015/10/11 04:51:24 sjg Exp $ */
/* $NetBSD: job.c,v 1.186 2016/02/18 18:29:14 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -70,14 +70,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: job.c,v 1.181 2015/10/11 04:51:24 sjg Exp $";
static char rcsid[] = "$NetBSD: job.c,v 1.186 2016/02/18 18:29:14 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)job.c 8.2 (Berkeley) 3/19/94";
#else
__RCSID("$NetBSD: job.c,v 1.181 2015/10/11 04:51:24 sjg Exp $");
__RCSID("$NetBSD: job.c,v 1.186 2016/02/18 18:29:14 christos Exp $");
#endif
#endif /* not lint */
#endif
@ -144,7 +144,6 @@ __RCSID("$NetBSD: job.c,v 1.181 2015/10/11 04:51:24 sjg Exp $");
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#if !defined(USE_SELECT) && defined(HAVE_POLL_H)
#include <poll.h>
#else
@ -425,8 +424,8 @@ JobCreatePipe(Job *job, int minfd)
}
/* Set close-on-exec flag for both */
(void)fcntl(job->jobPipe[0], F_SETFD, 1);
(void)fcntl(job->jobPipe[1], F_SETFD, 1);
(void)fcntl(job->jobPipe[0], F_SETFD, FD_CLOEXEC);
(void)fcntl(job->jobPipe[1], F_SETFD, FD_CLOEXEC);
/*
* We mark the input side of the pipe non-blocking; we poll(2) the
@ -715,7 +714,7 @@ JobPrintCommand(void *cmdp, void *jobp)
numCommands += 1;
cmdStart = cmd = Var_Subst(NULL, cmd, job->node, FALSE, TRUE);
cmdStart = cmd = Var_Subst(NULL, cmd, job->node, VARF_WANTRES);
cmdTemplate = "%s\n";
@ -866,8 +865,7 @@ JobPrintCommand(void *cmdp, void *jobp)
DBPRINTF(cmdTemplate, cmd);
free(cmdStart);
if (escCmd)
free(escCmd);
free(escCmd);
if (errOff) {
/*
* If echoing is already off, there's no point in issuing the
@ -903,7 +901,7 @@ JobPrintCommand(void *cmdp, void *jobp)
static int
JobSaveCommand(void *cmd, void *gn)
{
cmd = Var_Subst(NULL, (char *)cmd, (GNode *)gn, FALSE, TRUE);
cmd = Var_Subst(NULL, (char *)cmd, (GNode *)gn, VARF_WANTRES);
(void)Lst_AtEnd(postCommands->commands, cmd);
return(0);
}
@ -1234,8 +1232,7 @@ Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...))
*/
Make_HandleUse(DEFAULT, gn);
Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), gn, 0);
if (p1)
free(p1);
free(p1);
} else if (Dir_MTime(gn, 0) == 0 && (gn->type & OP_SPECIAL) == 0) {
/*
* The node wasn't the target of an operator we have no .DEFAULT
@ -1598,7 +1595,7 @@ JobStart(GNode *gn, int flags)
if (job->cmdFILE == NULL) {
Punt("Could not fdopen %s", tfile);
}
(void)fcntl(FILENO(job->cmdFILE), F_SETFD, 1);
(void)fcntl(FILENO(job->cmdFILE), F_SETFD, FD_CLOEXEC);
/*
* Send the commands to the command file, flush all its buffers then
* rewind and remove the thing.
@ -2195,7 +2192,7 @@ Job_SetPrefix(void)
}
targPrefix = Var_Subst(NULL, "${" MAKE_JOB_PREFIX "}",
VAR_GLOBAL, FALSE, TRUE);
VAR_GLOBAL, VARF_WANTRES);
}
/*-
@ -2402,8 +2399,7 @@ Job_ParseShell(char *line)
line++;
}
if (shellArgv)
free(UNCONST(shellArgv));
free(UNCONST(shellArgv));
memset(&newShell, 0, sizeof(newShell));
@ -2651,8 +2647,7 @@ void
Job_End(void)
{
#ifdef CLEANUP
if (shellArgv)
free(shellArgv);
free(shellArgv);
#endif
}
@ -2851,8 +2846,8 @@ Job_ServerStart(int max_tokens, int jp_0, int jp_1)
/* Pipe passed in from parent */
tokenWaitJob.inPipe = jp_0;
tokenWaitJob.outPipe = jp_1;
(void)fcntl(jp_0, F_SETFD, 1);
(void)fcntl(jp_1, F_SETFD, 1);
(void)fcntl(jp_0, F_SETFD, FD_CLOEXEC);
(void)fcntl(jp_1, F_SETFD, FD_CLOEXEC);
return;
}

114
main.c
View File

@ -1,4 +1,4 @@
/* $NetBSD: main.c,v 1.235 2015/10/25 05:24:44 sjg Exp $ */
/* $NetBSD: main.c,v 1.242 2016/03/07 21:45:43 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -69,7 +69,7 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: main.c,v 1.235 2015/10/25 05:24:44 sjg Exp $";
static char rcsid[] = "$NetBSD: main.c,v 1.242 2016/03/07 21:45:43 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
@ -81,7 +81,7 @@ __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\
#if 0
static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94";
#else
__RCSID("$NetBSD: main.c,v 1.235 2015/10/25 05:24:44 sjg Exp $");
__RCSID("$NetBSD: main.c,v 1.242 2016/03/07 21:45:43 christos Exp $");
#endif
#endif /* not lint */
#endif
@ -125,7 +125,6 @@ __RCSID("$NetBSD: main.c,v 1.235 2015/10/25 05:24:44 sjg Exp $");
#include "wait.h"
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
@ -696,8 +695,7 @@ Main_ParseArgLine(const char *line)
#endif
buf = bmake_malloc(len = strlen(line) + strlen(argv0) + 2);
(void)snprintf(buf, len, "%s %s", argv0, line);
if (p1)
free(p1);
free(p1);
argv = brk_string(buf, &argc, TRUE, &args);
if (argv == NULL) {
@ -723,7 +721,7 @@ Main_SetObjdir(const char *path)
/* expand variable substitutions */
if (strchr(path, '$') != 0) {
snprintf(buf, MAXPATHLEN, "%s", path);
path = p = Var_Subst(NULL, buf, VAR_GLOBAL, FALSE, TRUE);
path = p = Var_Subst(NULL, buf, VAR_GLOBAL, VARF_WANTRES);
}
if (path[0] != '/') {
@ -747,8 +745,7 @@ Main_SetObjdir(const char *path)
}
}
if (p)
free(p);
free(p);
return rc;
}
@ -807,7 +804,7 @@ MakeMode(const char *mode)
if (!mode)
mode = mp = Var_Subst(NULL, "${" MAKE_MODE ":tl}",
VAR_GLOBAL, FALSE, TRUE);
VAR_GLOBAL, VARF_WANTRES);
if (mode && *mode) {
if (strstr(mode, "compat")) {
@ -819,8 +816,8 @@ MakeMode(const char *mode)
meta_mode_init(mode);
#endif
}
if (mp)
free(mp);
free(mp);
}
/*-
@ -1253,7 +1250,7 @@ main(int argc, char **argv)
(char *)Lst_Datum(ln));
} else {
p1 = Var_Subst(NULL, "${" MAKEFILE_PREFERENCE "}",
VAR_CMD, FALSE, TRUE);
VAR_CMD, VARF_WANTRES);
if (p1) {
(void)str2Lst_Append(makefiles, p1, NULL);
(void)Lst_Find(makefiles, NULL, ReadMakefile);
@ -1264,7 +1261,7 @@ main(int argc, char **argv)
/* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */
if (!noBuiltins || !printVars) {
makeDependfile = Var_Subst(NULL, "${.MAKE.DEPENDFILE:T}",
VAR_CMD, FALSE, TRUE);
VAR_CMD, VARF_WANTRES);
doing_depend = TRUE;
(void)ReadMakefile(makeDependfile, NULL);
doing_depend = FALSE;
@ -1276,8 +1273,7 @@ main(int argc, char **argv)
MakeMode(NULL);
Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
if (p1)
free(p1);
free(p1);
if (!compatMake)
Job_ServerStart(maxJobTokens, jp_0, jp_1);
@ -1302,7 +1298,7 @@ main(int argc, char **argv)
*/
static char VPATH[] = "${VPATH}";
vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE, TRUE);
vpath = Var_Subst(NULL, VPATH, VAR_CMD, VARF_WANTRES);
path = vpath;
do {
/* skip to end of directory */
@ -1350,7 +1346,7 @@ main(int argc, char **argv)
if (strchr(var, '$')) {
value = p1 = Var_Subst(NULL, var, VAR_GLOBAL,
FALSE, TRUE);
VARF_WANTRES);
} else if (expandVars) {
char tmp[128];
@ -1358,13 +1354,12 @@ main(int argc, char **argv)
Fatal("%s: variable name too big: %s",
progname, var);
value = p1 = Var_Subst(NULL, tmp, VAR_GLOBAL,
FALSE, TRUE);
VARF_WANTRES);
} else {
value = Var_Value(var, VAR_GLOBAL, &p1);
}
printf("%s\n", value ? value : "");
if (p1)
free(p1);
free(p1);
}
} else {
/*
@ -1420,6 +1415,9 @@ main(int argc, char **argv)
if (enterFlag)
printf("%s: Leaving directory `%s'\n", progname, curdir);
#ifdef USE_META
meta_finish();
#endif
Suff_End();
Targ_End();
Arch_End();
@ -1488,8 +1486,7 @@ ReadMakefile(const void *p, const void *q MAKE_ATTR_UNUSED)
name = Dir_FindFile(fname,
Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath);
if (!name || (fd = open(name, O_RDONLY)) == -1) {
if (name)
free(name);
free(name);
free(path);
return(-1);
}
@ -1896,7 +1893,7 @@ PrintOnError(GNode *gn, const char *s)
}
strncpy(tmp, "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
sizeof(tmp) - 1);
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, FALSE, TRUE);
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
if (cp) {
if (*cp)
printf("%s", cp);
@ -1927,7 +1924,7 @@ Main_ExportMAKEFLAGS(Boolean first)
strncpy(tmp, "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}",
sizeof(tmp));
s = Var_Subst(NULL, tmp, VAR_CMD, FALSE, TRUE);
s = Var_Subst(NULL, tmp, VAR_CMD, VARF_WANTRES);
if (s && *s) {
#ifdef POSIX
setenv("MAKEFLAGS", s, 1);
@ -1950,7 +1947,7 @@ getTmpdir(void)
* Ensure it ends with /.
*/
tmpdir = Var_Subst(NULL, "${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL,
FALSE, TRUE);
VARF_WANTRES);
if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {
free(tmpdir);
tmpdir = bmake_strdup(_PATH_TMP);
@ -1990,6 +1987,44 @@ mkTempFile(const char *pattern, char **fnamep)
return fd;
}
/*
* Convert a string representation of a boolean.
* Anything that looks like "No", "False", "Off", "0" etc,
* is FALSE, otherwise TRUE.
*/
Boolean
s2Boolean(const char *s, Boolean bf)
{
if (s) {
switch(*s) {
case '\0': /* not set - the default wins */
break;
case '0':
case 'F':
case 'f':
case 'N':
case 'n':
bf = FALSE;
break;
case 'O':
case 'o':
switch (s[1]) {
case 'F':
case 'f':
bf = FALSE;
break;
default:
bf = TRUE;
break;
}
break;
default:
bf = TRUE;
break;
}
}
return (bf);
}
/*
* Return a Boolean based on setting of a knob.
@ -2004,32 +2039,11 @@ getBoolean(const char *name, Boolean bf)
char tmp[64];
char *cp;
if (snprintf(tmp, sizeof(tmp), "${%s:tl}", name) < (int)(sizeof(tmp))) {
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, FALSE, TRUE);
if (snprintf(tmp, sizeof(tmp), "${%s:U:tl}", name) < (int)(sizeof(tmp))) {
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
if (cp) {
switch(*cp) {
case '\0': /* not set - the default wins */
break;
case '0':
case 'f':
case 'n':
bf = FALSE;
break;
case 'o':
switch (cp[1]) {
case 'f':
bf = FALSE;
break;
default:
bf = TRUE;
break;
}
break;
default:
bf = TRUE;
break;
}
bf = s2Boolean(cp, bf);
free(cp);
}
}

47
make.1
View File

@ -1,4 +1,4 @@
.\" $NetBSD: make.1,v 1.249 2015/06/05 07:33:40 wiz Exp $
.\" $NetBSD: make.1,v 1.254 2016/02/20 01:43:28 wiz Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -29,7 +29,7 @@
.\"
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
.\"
.Dd June 4, 2015
.Dd February 19, 2016
.Dt MAKE 1
.Os
.Sh NAME
@ -293,7 +293,7 @@ then
will search for the specified file or directory named in the remaining part
of the argument string.
The search starts with the current directory of
the Makefile and then works upward towards the root of the filesystem.
the Makefile and then works upward towards the root of the file system.
If the search is successful, then the resulting directory replaces the
.Qq \&.../
specification in the
@ -868,7 +868,7 @@ This can be overridden by setting
.Va bf
to a value which represents True.
.It Pa env
For debugging, it can be useful to inlcude the environment
For debugging, it can be useful to include the environment
in the .meta file.
.It Pa verbose
If in "meta" mode, print a clue about the target being built.
@ -918,7 +918,7 @@ The default value is:
This variable is used to record the names of variables assigned to
on the command line, so that they may be exported as part of
.Ql Ev MAKEFLAGS .
This behaviour can be disabled by assigning an empty value to
This behavior can be disabled by assigning an empty value to
.Ql Va .MAKEOVERRIDES
within a makefile.
Extra variables can be exported from a makefile
@ -941,6 +941,19 @@ The process-id of
.It Va .MAKE.PPID
The parent process-id of
.Nm .
.It Va .MAKE.SAVE_DOLLARS
value should be a boolean that controls whether
.Ql $$
are preserved when doing
.Ql :=
assignments.
The default is false, for backwards compatibility.
Set to true for compatability with other makes.
If set to false,
.Ql $$
becomes
.Ql $
per normal evaluation rules.
.It Va MAKE_PRINT_VAR_ON_ERROR
When
.Nm
@ -1044,7 +1057,7 @@ sets
to the value of
.Ql Ev PWD
instead.
This behaviour is disabled if
This behavior is disabled if
.Ql Ev MAKEOBJDIRPREFIX
is set or
.Ql Ev MAKEOBJDIR
@ -1114,7 +1127,7 @@ The wildcard characters may be escaped with a backslash
As a consequence of the way values are split into words, matched,
and then joined, a construct like
.Dl ${VAR:M*}
will normalise the inter-word spacing, removing all leading and
will normalize the inter-word spacing, removing all leading and
trailing space, and converting multiple consecutive spaces
to single spaces.
.
@ -1134,7 +1147,7 @@ Randomize words in variable.
The results will be different each time you are referring to the
modified variable; use the assignment with expansion
.Pq Ql Cm \&:=
to prevent such behaviour.
to prevent such behavior.
For example,
.Bd -literal -offset indent
LIST= uno due tre quattro
@ -1166,7 +1179,7 @@ The value is a format string for
using the current
.Xr gmtime 3 .
.It Cm \&:hash
Compute a 32bit hash of the value and encode it as hex digits.
Compute a 32-bit hash of the value and encode it as hex digits.
.It Cm \&:localtime
The value is a format string for
.Xr strftime 3 ,
@ -1444,7 +1457,7 @@ value is divided into words.
.Pp
Ordinarily, a value is treated as a sequence of words
delimited by white space.
Some modifiers suppress this behaviour,
Some modifiers suppress this behavior,
causing a value to be treated as a single word
(possibly containing embedded white space).
An empty value, or a value that consists entirely of white-space,
@ -1530,12 +1543,20 @@ For compatibility with other versions of
.Nm
.Ql include file ...
is also accepted.
.Pp
If the include statement is written as
.Cm .-include
or as
.Cm .sinclude
then errors locating and/or opening include files are ignored.
.Pp
If the include statement is written as
.Cm .dinclude
not only are errors locating and/or opening include files ignored,
but stale dependencies within the included file will be ignored
just like
.Va .MAKE.DEPENDFILE .
.Pp
Conditional expressions are also preceded by a single dot as the first
character of a line.
The possible conditionals are as follows:
@ -1571,6 +1592,10 @@ This allows exporting a value to the environment which is different from that
used by
.Nm
internally.
.It Ic .export-literal Ar variable ...
The same as
.Ql .export-env ,
except that variables in the value are not expanded.
.It Ic .info Ar message
The message is printed along with the name of the makefile and line number.
.It Ic .undef Ar variable
@ -2068,7 +2093,7 @@ The sources are a set of
pairs.
.Bl -tag -width hasErrCtls
.It Ar name
This is the minimal specification, used to select one of the builtin
This is the minimal specification, used to select one of the built-in
shell specs;
.Ar sh ,
.Ar ksh ,

26
make.c
View File

@ -1,4 +1,4 @@
/* $NetBSD: make.c,v 1.92 2015/10/11 04:51:24 sjg Exp $ */
/* $NetBSD: make.c,v 1.95 2016/02/18 18:29:14 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: make.c,v 1.92 2015/10/11 04:51:24 sjg Exp $";
static char rcsid[] = "$NetBSD: make.c,v 1.95 2016/02/18 18:29:14 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)make.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: make.c,v 1.92 2015/10/11 04:51:24 sjg Exp $");
__RCSID("$NetBSD: make.c,v 1.95 2016/02/18 18:29:14 christos Exp $");
#endif
#endif /* not lint */
#endif
@ -482,10 +482,9 @@ Make_HandleUse(GNode *cgn, GNode *pgn)
if (gn->uname == NULL) {
gn->uname = gn->name;
} else {
if (gn->name)
free(gn->name);
free(gn->name);
}
gn->name = Var_Subst(NULL, gn->uname, pgn, FALSE, TRUE);
gn->name = Var_Subst(NULL, gn->uname, pgn, VARF_WANTRES);
if (gn->name && gn->uname && strcmp(gn->name, gn->uname) != 0) {
/* See if we have a target for this node. */
tgn = Targ_FindNode(gn->name, TARG_NOCREATE);
@ -692,8 +691,7 @@ Make_Update(GNode *cgn)
checked++;
cname = Var_Value(TARGET, cgn, &p1);
if (p1)
free(p1);
free(p1);
if (DEBUG(MAKE))
fprintf(debug_file, "Make_Update: %s%s\n", cgn->name, cgn->cohort_num);
@ -838,8 +836,7 @@ Make_Update(GNode *cgn)
Var_Set(PREFIX, cpref, pgn, 0);
}
}
if (p1)
free(p1);
free(p1);
Lst_Close(cgn->iParents);
}
}
@ -907,8 +904,7 @@ MakeAddAllSrc(void *cgnp, void *pgnp)
}
if (allsrc != NULL)
Var_Append(ALLSRC, allsrc, pgn);
if (p2)
free(p2);
free(p2);
if (pgn->type & OP_JOIN) {
if (cgn->made == MADE) {
Var_Append(OODATE, child, pgn);
@ -934,8 +930,7 @@ MakeAddAllSrc(void *cgnp, void *pgnp)
*/
Var_Append(OODATE, child, pgn);
}
if (p1)
free(p1);
free(p1);
}
return (0);
}
@ -981,8 +976,7 @@ Make_DoAllVar(GNode *gn)
if (gn->type & OP_JOIN) {
char *p1;
Var_Set(TARGET, Var_Value(ALLSRC, gn, &p1), gn, 0);
if (p1)
free(p1);
free(p1);
}
gn->flags |= DONE_ALLSRC;
}

11
make.h
View File

@ -1,4 +1,4 @@
/* $NetBSD: make.h,v 1.96 2015/09/21 21:50:16 pooka Exp $ */
/* $NetBSD: make.h,v 1.98 2016/02/18 18:29:14 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -88,6 +88,7 @@
#include <sys/param.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
@ -98,6 +99,10 @@
#include <unistd.h>
#include <sys/cdefs.h>
#ifndef FD_CLOEXEC
#define FD_CLOEXEC 1
#endif
#if defined(__GNUC__)
#define MAKE_GNUC_PREREQ(x, y) \
((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || \
@ -501,6 +506,10 @@ Boolean Main_SetObjdir(const char *);
int mkTempFile(const char *, char **);
int str2Lst_Append(Lst, char *, const char *);
#define VARF_UNDEFERR 1
#define VARF_WANTRES 2
#define VARF_ASSIGN 4
#ifdef __GNUC__
#define UNCONST(ptr) ({ \
union __unconst { \

82
meta.c
View File

@ -1,4 +1,4 @@
/* $NetBSD: meta.c,v 1.41 2015/11/30 23:37:56 sjg Exp $ */
/* $NetBSD: meta.c,v 1.53 2016/03/07 21:45:43 christos Exp $ */
/*
* Implement 'meta' mode.
@ -6,7 +6,7 @@
* --sjg
*/
/*
* Copyright (c) 2009-2010, Juniper Networks, Inc.
* Copyright (c) 2009-2016, Juniper Networks, Inc.
* Portions Copyright (c) 2009, John Birrell.
*
* Redistribution and use in source and binary forms, with or without
@ -37,7 +37,6 @@
#endif
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#ifdef HAVE_LIBGEN_H
#include <libgen.h>
#elif !defined(HAVE_DIRNAME)
@ -60,7 +59,9 @@ char * dirname(char *);
static BuildMon Mybm; /* for compat */
static Lst metaBailiwick; /* our scope of control */
static char *metaBailiwickStr; /* string storage for the list */
static Lst metaIgnorePaths; /* paths we deliberately ignore */
static char *metaIgnorePathsStr; /* string storage for the list */
#ifndef MAKE_META_IGNORE_PATHS
#define MAKE_META_IGNORE_PATHS ".MAKE.META.IGNORE_PATHS"
@ -148,8 +149,8 @@ filemon_open(BuildMon *pbm)
err(1, "Could not set filemon file descriptor!");
}
/* we don't need these once we exec */
(void)fcntl(pbm->mon_fd, F_SETFD, 1);
(void)fcntl(pbm->filemon_fd, F_SETFD, 1);
(void)fcntl(pbm->mon_fd, F_SETFD, FD_CLOEXEC);
(void)fcntl(pbm->filemon_fd, F_SETFD, FD_CLOEXEC);
}
/*
@ -300,8 +301,7 @@ meta_name(struct GNode *gn, char *mname, size_t mnamelen,
}
free(tp);
for (i--; i >= 0; i--) {
if (p[i])
free(p[i]);
free(p[i]);
}
return (mname);
}
@ -328,7 +328,7 @@ is_submake(void *cmdp, void *gnp)
}
cp = strchr(cmd, '$');
if ((cp)) {
mp = Var_Subst(NULL, cmd, gn, FALSE, TRUE);
mp = Var_Subst(NULL, cmd, gn, VARF_WANTRES);
cmd = mp;
}
cp2 = strstr(cmd, p_make);
@ -353,8 +353,7 @@ is_submake(void *cmdp, void *gnp)
}
}
}
if (mp)
free(mp);
free(mp);
return (rc);
}
@ -371,11 +370,10 @@ printCMD(void *cmdp, void *mfpp)
char *cp = NULL;
if (strchr(cmd, '$')) {
cmd = cp = Var_Subst(NULL, cmd, mfp->gn, FALSE, TRUE);
cmd = cp = Var_Subst(NULL, cmd, mfp->gn, VARF_WANTRES);
}
fprintf(mfp->fp, "CMD %s\n", cmd);
if (cp)
free(cp);
free(cp);
return 0;
}
@ -466,7 +464,7 @@ meta_create(BuildMon *pbm, GNode *gn)
char *mp;
/* Describe the target we are building */
mp = Var_Subst(NULL, "${" MAKE_META_PREFIX "}", gn, FALSE, TRUE);
mp = Var_Subst(NULL, "${" MAKE_META_PREFIX "}", gn, VARF_WANTRES);
if (*mp)
fprintf(stdout, "%s\n", mp);
free(mp);
@ -480,9 +478,6 @@ meta_create(BuildMon *pbm, GNode *gn)
fflush(stdout);
if (strcmp(cp, makeDependfile) == 0)
goto out;
if (!writeMeta)
/* Don't create meta data. */
goto out;
@ -524,8 +519,7 @@ meta_create(BuildMon *pbm, GNode *gn)
}
out:
for (i--; i >= 0; i--) {
if (p[i])
free(p[i]);
free(p[i]);
}
return (mf.fp);
@ -609,10 +603,10 @@ meta_mode_init(const char *make_mode)
* We consider ourselves master of all within ${.MAKE.META.BAILIWICK}
*/
metaBailiwick = Lst_Init(FALSE);
cp = Var_Subst(NULL, "${.MAKE.META.BAILIWICK:O:u:tA}", VAR_GLOBAL,
FALSE, TRUE);
if (cp) {
str2Lst_Append(metaBailiwick, cp, NULL);
metaBailiwickStr = Var_Subst(NULL, "${.MAKE.META.BAILIWICK:O:u:tA}",
VAR_GLOBAL, VARF_WANTRES);
if (metaBailiwickStr) {
str2Lst_Append(metaBailiwick, metaBailiwickStr, NULL);
}
/*
* We ignore any paths that start with ${.MAKE.META.IGNORE_PATHS}
@ -620,11 +614,11 @@ meta_mode_init(const char *make_mode)
metaIgnorePaths = Lst_Init(FALSE);
Var_Append(MAKE_META_IGNORE_PATHS,
"/dev /etc /proc /tmp /var/run /var/tmp ${TMPDIR}", VAR_GLOBAL);
cp = Var_Subst(NULL,
metaIgnorePathsStr = Var_Subst(NULL,
"${" MAKE_META_IGNORE_PATHS ":O:u:tA}", VAR_GLOBAL,
FALSE, TRUE);
if (cp) {
str2Lst_Append(metaIgnorePaths, cp, NULL);
VARF_WANTRES);
if (metaIgnorePathsStr) {
str2Lst_Append(metaIgnorePaths, metaIgnorePathsStr, NULL);
}
}
@ -693,9 +687,9 @@ meta_job_error(Job *job, GNode *gn, int flags, int status)
if (job != NULL) {
pbm = &job->bm;
} else {
if (!gn)
gn = job->node;
} else {
pbm = &Mybm;
}
if (pbm->mfp != NULL) {
@ -709,7 +703,7 @@ meta_job_error(Job *job, GNode *gn, int flags, int status)
}
getcwd(cwd, sizeof(cwd));
Var_Set(".ERROR_CWD", cwd, VAR_GLOBAL, 0);
if (pbm && pbm->meta_fname[0]) {
if (pbm->meta_fname[0]) {
Var_Set(".ERROR_META_FILE", pbm->meta_fname, VAR_GLOBAL, 0);
}
meta_job_finish(job);
@ -734,7 +728,7 @@ meta_job_output(Job *job, char *cp, const char *nl)
char *cp2;
meta_prefix = Var_Subst(NULL, "${" MAKE_META_PREFIX "}",
VAR_GLOBAL, FALSE, TRUE);
VAR_GLOBAL, VARF_WANTRES);
if ((cp2 = strchr(meta_prefix, '$')))
meta_prefix_len = cp2 - meta_prefix;
else
@ -785,6 +779,15 @@ meta_job_finish(Job *job)
}
}
void
meta_finish(void)
{
Lst_Destroy(metaBailiwick, NULL);
free(metaBailiwickStr);
Lst_Destroy(metaIgnorePaths, NULL);
free(metaIgnorePathsStr);
}
/*
* Fetch a full line from fp - growing bufp if needed
* Return length in bufp.
@ -1035,14 +1038,12 @@ meta_oodate(GNode *gn, Boolean oodate)
ldir = Var_Value(ldir_vname, VAR_GLOBAL, &tp);
if (ldir) {
strlcpy(latestdir, ldir, sizeof(latestdir));
if (tp)
free(tp);
free(tp);
}
ldir = Var_Value(lcwd_vname, VAR_GLOBAL, &tp);
if (ldir) {
strlcpy(lcwd, ldir, sizeof(lcwd));
if (tp)
free(tp);
free(tp);
}
}
/* Skip past the pid. */
@ -1320,7 +1321,7 @@ meta_oodate(GNode *gn, Boolean oodate)
if (DEBUG(META))
fprintf(debug_file, "%s: %d: cannot compare command using .OODATE\n", fname, lineno);
}
cmd = Var_Subst(NULL, cmd, gn, TRUE, TRUE);
cmd = Var_Subst(NULL, cmd, gn, VARF_WANTRES|VARF_UNDEFERR);
if ((cp = strchr(cmd, '\n'))) {
int n;
@ -1382,7 +1383,6 @@ meta_oodate(GNode *gn, Boolean oodate)
fprintf(debug_file, "%s: missing files: %s...\n",
fname, (char *)Lst_Datum(Lst_First(missingFiles)));
oodate = TRUE;
Lst_Destroy(missingFiles, (FreeProc *)free);
}
} else {
if ((gn->type & OP_META)) {
@ -1391,6 +1391,9 @@ meta_oodate(GNode *gn, Boolean oodate)
oodate = TRUE;
}
}
Lst_Destroy(missingFiles, (FreeProc *)free);
if (oodate && needOODATE) {
/*
* Target uses .OODATE which is empty; or we wouldn't be here.
@ -1399,8 +1402,7 @@ meta_oodate(GNode *gn, Boolean oodate)
*/
Var_Delete(OODATE, gn);
Var_Set(OODATE, Var_Value(ALLSRC, gn, &cp), gn, 0);
if (cp)
free(cp);
free(cp);
}
return oodate;
}
@ -1427,8 +1429,8 @@ meta_compat_start(void)
if (pipe(childPipe) < 0)
Punt("Cannot create pipe: %s", strerror(errno));
/* Set close-on-exec flag for both */
(void)fcntl(childPipe[0], F_SETFD, 1);
(void)fcntl(childPipe[1], F_SETFD, 1);
(void)fcntl(childPipe[0], F_SETFD, FD_CLOEXEC);
(void)fcntl(childPipe[1], F_SETFD, FD_CLOEXEC);
}
void

3
meta.h
View File

@ -1,4 +1,4 @@
/* $NetBSD: meta.h,v 1.3 2013/03/23 05:31:29 sjg Exp $ */
/* $NetBSD: meta.h,v 1.4 2016/03/07 21:45:43 christos Exp $ */
/*
* Things needed for 'meta' mode.
@ -42,6 +42,7 @@ extern Boolean useMeta;
struct Job; /* not defined yet */
void meta_init(void);
void meta_finish(void);
void meta_mode_init(const char *);
void meta_job_start(struct Job *, GNode *);
void meta_job_child(struct Job *);

View File

@ -1,3 +1,42 @@
2016-03-02 Simon J. Gerraty <sjg@bad.crufty.net>
* meta2deps.sh: don't ignore subdirs.
patch from Bryan Drewery
2016-02-26 Simon J. Gerraty <sjg@bad.crufty.net>
* install-mk (MK_VERSION): 20160226
* gendirdeps.mk: mark _DEPENDFILE .NOMETA
2016-02-20 Simon J. Gerraty <sjg@bad.crufty.net>
* dirdeps.mk: we shouldn't normally include .depend but if we do
use .dinclude if we can.
2016-02-18 Simon J. Gerraty <sjg@bad.crufty.net>
* install-mk (MK_VERSION): 20160218
* sys.clean-env.mk: with recent change to Var_Subst()
we cannot use the '$$' trick, but .export-literal does the job
we need.
* auto.dep.mk: make use .dinclude if we can.
2016-02-05 Simon J. Gerraty <sjg@bad.crufty.net>
* dirdeps.mk:
Add _build_all_dirs such that local.dirdeps.mk can
add fully qualified dirs to it.
These will be built normally but the current
DEP_RELDIR will not depend on then (to avoid cycles).
This makes it easy to hook things like unit-tests into build.
2016-01-21 Simon J. Gerraty <sjg@bad.crufty.net>
* dirdeps.mk: add bootstrap-empty
2015-12-12 Simon J. Gerraty <sjg@bad.crufty.net>
* install-mk (MK_VERSION): 20151212

View File

@ -1,6 +1,6 @@
#
# RCSid:
# $Id: auto.dep.mk,v 1.3 2014/08/04 05:19:10 sjg Exp $
# $Id: auto.dep.mk,v 1.4 2016/02/18 21:16:39 sjg Exp $
#
# @(#) Copyright (c) 2010, Simon J. Gerraty
#
@ -45,6 +45,7 @@ CXXFLAGS += ${CFLAGS_MD} ${CFLAGS_MF}
CLEANFILES += .depend ${.MAKE.DEPENDFILE} *.d
.if ${MAKE_VERSION} < 20160218
# skip generating dependfile for misc targets
.if ${.TARGETS:Uall:M*all} != ""
.END: ${.MAKE.DEPENDFILE}
@ -60,5 +61,14 @@ ${.MAKE.DEPENDFILE}: ${OBJS} ${POBJS} ${SOBJS}
-@for f in ${.ALLSRC:M*o:T:O:u:%=%.d}; do \
echo ".-include \"$$f\""; \
done > $@
.else
# we have .dinclude
.if empty(_SKIP_BUILD)
_all_objs = ${OBJS} ${POBJS} ${SOBJS}
.for d in ${_all_objs:M*o:T:O:u:%=%.d}
.dinclude "$d"
.endfor
.endif
.endif
.endif

View File

@ -1,4 +1,4 @@
# $Id: dirdeps.mk,v 1.55 2015/10/20 22:04:53 sjg Exp $
# $Id: dirdeps.mk,v 1.59 2016/02/26 23:32:29 sjg Exp $
# Copyright (c) 2010-2013, Juniper Networks, Inc.
# All rights reserved.
@ -121,6 +121,9 @@ _DIRDEP_USE_LEVEL?= 0
# and non-specific Makefile.depend*
.if !target(_DIRDEP_USE)
# make sure we get the behavior we expect
.MAKE.SAVE_DOLLARS = no
# do some setup we only need once
_CURDIR ?= ${.CURDIR}
_OBJDIR ?= ${.OBJDIR}
@ -256,11 +259,8 @@ DEP_RELDIR := ${DIRDEPS:R:[1]}
MK_DIRDEPS_CACHE = no
.endif
# pickup customizations
# as below you can use !target(_DIRDEP_USE) to protect things
# which should only be done once.
.-include "local.dirdeps.mk"
# reset each time through
_build_all_dirs =
# the first time we are included the _DIRDEP_USE target will not be defined
# we can use this as a clue to do initialization and other one time things.
@ -280,6 +280,14 @@ DEBUG_DIRDEPS ?= no
# remember the initial value of DEP_RELDIR - we test for it below.
_DEP_RELDIR := ${DEP_RELDIR}
.endif
# pickup customizations
# as below you can use !target(_DIRDEP_USE) to protect things
# which should only be done once.
.-include "local.dirdeps.mk"
.if !target(_DIRDEP_USE)
# things we skip for host tools
SKIP_HOSTDIR ?=
@ -399,6 +407,7 @@ ${DIRDEPS_CACHE}: .META .NOMETA_CMP
MAKEFLAGS= ${.MAKE} -C ${_CURDIR} -f ${BUILD_DIRDEPS_MAKEFILE} \
${BUILD_DIRDEPS_TARGETS} BUILD_DIRDEPS_CACHE=yes \
.MAKE.DEPENDFILE=.none \
${.MAKEFLAGS:tW:S,-D ,-D,g:tw:M*WITH*} \
3>&1 1>&2 | sed 's,${SRCTOP},$${SRCTOP},g' >> ${.TARGET}.new && \
mv ${.TARGET}.new ${.TARGET}
@ -479,7 +488,11 @@ _build_dirs += ${_machines:@m@${_CURDIR}.$m@}
_build_dirs += ${_machines:N${DEP_TARGET_SPEC}:@m@${_CURDIR}.$m@}
.if ${DEP_TARGET_SPEC} == ${TARGET_SPEC}
# pickup local dependencies now
.if ${MAKE_VERSION} < 20160220
.-include <.depend>
.else
.dinclude <.depend>
.endif
.endif
.endif
.endif
@ -531,22 +544,25 @@ _build_dirs += \
# qualify everything now
_build_dirs := ${_build_dirs:${M_dep_qual_fixes:ts:}:O:u}
_build_all_dirs += ${_build_dirs}
_build_all_dirs := ${_build_all_dirs:O:u}
.endif # empty DIRDEPS
# Normally if doing make -V something,
# we do not want to waste time chasing DIRDEPS
# but if we want to count the number of Makefile.depend* read, we do.
.if ${.MAKEFLAGS:M-V${_V_READ_DIRDEPS}} == ""
.if !empty(_build_dirs)
.if !empty(_build_all_dirs)
.if ${BUILD_DIRDEPS_CACHE} == "yes"
x!= { echo; echo '\# ${DEP_RELDIR}.${DEP_TARGET_SPEC}'; \
echo 'dirdeps: ${_build_dirs:${M_oneperline}}'; echo; } >&3; echo
x!= { ${_build_dirs:@x@${target($x):?:echo '$x: _DIRDEP_USE';}@} echo; } >&3; echo
echo 'dirdeps: ${_build_all_dirs:${M_oneperline}}'; echo; } >&3; echo
x!= { ${_build_all_dirs:@x@${target($x):?:echo '$x: _DIRDEP_USE';}@} echo; } >&3; echo
.else
# this makes it all happen
dirdeps: ${_build_dirs}
dirdeps: ${_build_all_dirs}
.endif
${_build_dirs}: _DIRDEP_USE
${_build_all_dirs}: _DIRDEP_USE
.if ${_debug_reldir}
.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: needs: ${_build_dirs}
@ -580,14 +596,14 @@ ${_this_dir}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m}
.endif
# Now find more dependencies - and recurse.
.for d in ${_build_dirs}
.for d in ${_build_all_dirs}
.if ${_DIRDEP_CHECKED:M$d} == ""
# once only
_DIRDEP_CHECKED += $d
.if ${_debug_search}
.info checking $d
.endif
# Note: _build_dirs is fully qualifed so d:R is always the directory
# Note: _build_all_dirs is fully qualifed so d:R is always the directory
.if exists(${d:R})
# Warning: there is an assumption here that MACHINE is always
# the first entry in TARGET_SPEC_VARS.
@ -627,28 +643,37 @@ DIRDEPS =
DEP_RELDIR := ${RELDIR}
_DEP_RELDIR := ${RELDIR}
# pickup local dependencies
.if ${MAKE_VERSION} < 20160220
.-include <.depend>
.else
.dinclude <.depend>
.endif
.endif
# bootstrapping new dependencies made easy?
.if (make(bootstrap) || make(bootstrap-recurse)) && !target(bootstrap)
.if !target(bootstrap) && (make(bootstrap) || \
make(bootstrap-this) || \
make(bootstrap-recurse) || \
make(bootstrap-empty))
.if exists(${.CURDIR}/${.MAKE.DEPENDFILE:T})
# stop here
${.TARGETS:Mboot*}:
.else
.elif !make(bootstrap-empty)
# find a Makefile.depend to use as _src
_src != cd ${.CURDIR} && for m in ${.MAKE.DEPENDFILE_PREFERENCE:T:S,${MACHINE},*,}; do test -s $$m || continue; echo $$m; break; done; echo
.if empty(_src)
.error cannot find any of ${.MAKE.DEPENDFILE_PREFERENCE:T}
.error cannot find any of ${.MAKE.DEPENDFILE_PREFERENCE:T}${.newline}Use: bootstrap-empty
.endif
_src?= ${.MAKE.DEPENDFILE:T}
# just create Makefile.depend* for this dir
bootstrap-this: .NOTMAIN
@echo Bootstrapping ${RELDIR}/${.MAKE.DEPENDFILE:T} from ${_src:T}
(cd ${.CURDIR} && sed 's,${_src:E},${MACHINE},g' ${_src} > ${.MAKE.DEPENDFILE:T})
# create Makefile.depend* for this dir and its dependencies
bootstrap: bootstrap-recurse
bootstrap-recurse: bootstrap-this
@ -663,4 +688,11 @@ bootstrap-recurse: .NOTMAIN .MAKE
done
.endif
# create an empty Makefile.depend* to get the ball rolling.
bootstrap-empty: .NOTMAIN .NOMETA
@echo Creating empty ${RELDIR}/${.MAKE.DEPENDFILE:T}; \
echo You need to build ${RELDIR} to correctly populate it.
@{ echo DIRDEPS=; echo ".include <dirdeps.mk>"; } > ${.CURDIR}/${.MAKE.DEPENDFILE:T}
.endif

View File

@ -1,4 +1,4 @@
# $Id: gendirdeps.mk,v 1.29 2015/10/03 05:00:46 sjg Exp $
# $Id: gendirdeps.mk,v 1.30 2016/02/27 00:20:39 sjg Exp $
# Copyright (c) 2010-2013, Juniper Networks, Inc.
# All rights reserved.
@ -309,7 +309,7 @@ CAT_DEPEND ?= .depend
# .depend may contain things we don't want.
# The sed command at the end of the stream, allows for the filters
# to output _{VAR} tokens which we will turn into proper ${VAR} references.
${_DEPENDFILE}: ${CAT_DEPEND:M.depend} ${META_FILES:O:u:@m@${exists($m):?$m:}@} ${_this} ${META2DEPS}
${_DEPENDFILE}: .NOMETA ${CAT_DEPEND:M.depend} ${META_FILES:O:u:@m@${exists($m):?$m:}@} ${_this} ${META2DEPS}
@(${GENDIRDEPS_HEADER} echo '# Autogenerated - do NOT edit!'; echo; \
echo 'DIRDEPS = \'; \
echo '${DIRDEPS:@d@ $d \\${.newline}@}'; echo; \
@ -329,7 +329,7 @@ DIRDEPS := ${SUBDIR:S,^,${RELDIR}/,:O:u}
all: ${_DEPENDFILE}
${_DEPENDFILE}: ${MAKEFILE} ${_this}
${_DEPENDFILE}: .NOMETA ${MAKEFILE} ${_this}
@(${GENDIRDEPS_HEADER} echo '# Autogenerated - do NOT edit!'; echo; \
echo 'DIRDEPS = \'; \
echo '${DIRDEPS:@d@ $d \\${.newline}@}'; echo; \

View File

@ -55,7 +55,7 @@
# Simon J. Gerraty <sjg@crufty.net>
# RCSid:
# $Id: install-mk,v 1.118 2015/12/16 01:57:06 sjg Exp $
# $Id: install-mk,v 1.121 2016/02/27 00:23:02 sjg Exp $
#
# @(#) Copyright (c) 1994 Simon J. Gerraty
#
@ -70,7 +70,7 @@
# sjg@crufty.net
#
MK_VERSION=20151212
MK_VERSION=20160226
OWNER=
GROUP=
MODE=444

View File

@ -1,4 +1,4 @@
# $Id: meta.autodep.mk,v 1.39 2015/12/07 04:35:32 sjg Exp $
# $Id: meta.autodep.mk,v 1.40 2016/02/22 22:44:58 sjg Exp $
#
# @(#) Copyright (c) 2010, Simon J. Gerraty
@ -86,7 +86,7 @@ WANT_UPDATE_DEPENDFILE ?= yes
.endif
.if ${WANT_UPDATE_DEPENDFILE:Uno:tl} != "no"
.if ${.MAKE.MODE:Mmeta*} == "" || ${.MAKE.MODE:M*read*} != ""
.if ${.MAKE.MODE:Uno:Mmeta*} == "" || ${.MAKE.MODE:Uno:M*read*} != ""
UPDATE_DEPENDFILE = no
.endif

View File

@ -1,4 +1,4 @@
# $Id: meta.stage.mk,v 1.41 2015/11/13 17:34:04 sjg Exp $
# $Id: meta.stage.mk,v 1.43 2016/02/24 18:46:32 sjg Exp $
#
# @(#) Copyright (c) 2011, Simon J. Gerraty
#
@ -26,7 +26,7 @@ _dirdep = ${RELDIR}
CLEANFILES+= .dirdep
# this allows us to trace dependencies back to their src dir
.dirdep:
.dirdep: .NOPATH
@echo '${_dirdep}' > $@
.if defined(NO_POSIX_SHELL) || ${type printf:L:sh:Mbuiltin} == ""
@ -241,7 +241,7 @@ CLEANFILES += ${STAGE_TARGETS} stage_incs stage_includes
# for non-jobs mode the order here matters
staging: ${STAGE_TARGETS:N*_links} ${STAGE_TARGETS:M*_links}
.if ${.MAKE.JOBS:U0} > 0 && ${STAGE_TARGETS:M*_links} != ""
.if ${.MAKE.JOBS:U0} > 0 && ${STAGE_TARGETS:U:M*_links} != ""
# the above isn't sufficient
.for t in ${STAGE_TARGETS:N*links:O:u}
.ORDER: $t stage_links

View File

@ -1,4 +1,4 @@
# $Id: meta.sys.mk,v 1.26 2015/11/14 21:16:13 sjg Exp $
# $Id: meta.sys.mk,v 1.27 2016/02/22 22:44:58 sjg Exp $
#
# @(#) Copyright (c) 2010, Simon J. Gerraty
@ -102,7 +102,7 @@ META_COOKIE_TOUCH=
# some targets need to be .PHONY in non-meta mode
META_NOPHONY= .PHONY
# Are we, after all, in meta mode?
.if ${.MAKE.MODE:Mmeta*} != ""
.if ${.MAKE.MODE:Uno:Mmeta*} != ""
MKDEP_MK = meta.autodep.mk
.if ${.MAKE.MAKEFILES:M*sys.dependfile.mk} == ""

View File

@ -77,7 +77,7 @@
# RCSid:
# $Id: meta2deps.sh,v 1.9 2015/04/03 18:23:25 sjg Exp $
# $Id: meta2deps.sh,v 1.10 2016/03/02 18:53:36 sjg Exp $
# Copyright (c) 2010-2013, Juniper Networks, Inc.
# All rights reserved.
@ -309,7 +309,7 @@ meta2deps() {
*) seen=$dir;;
esac
case "$dir" in
${CURDIR:-.}|${CURDIR:-.}/*|"") continue;;
${CURDIR:-.}|"") continue;;
$src_re)
# avoid repeating ourselves...
case "$DPDEPS,$seensrc," in

View File

@ -1,4 +1,4 @@
# $Id: sys.clean-env.mk,v 1.20 2012/11/12 06:56:04 sjg Exp $
# $Id: sys.clean-env.mk,v 1.21 2016/02/18 21:16:40 sjg Exp $
#
# @(#) Copyright (c) 2009, Simon J. Gerraty
#
@ -94,6 +94,7 @@ _tricky_env_vars = MAKEOBJDIR OBJTOP
# MAKEOBJDIR='${.CURDIR:S,${SRCTOP},${OBJTOP},}'
_srctop := ${SRCTOP:U${SB_SRC:U${SB}/src}}
_objroot := ${OBJROOT:U${SB_OBJROOT:U${SB}/${SB_OBJPREFIX}}}
.if ${MAKE_VERSION} < 20160218
_objtop := ${OBJTOP:U${_objroot}${MACHINE}}
# Take care of ${MACHINE}
.if ${MACHINE} == "host" || ${OBJTOP} == ${HOST_OBJTOP:Uno}
@ -113,7 +114,17 @@ MAKEOBJDIR = $${.CURDIR:S,${_srctop},$${OBJTOP},}
.for v in ${_tricky_env_vars}
$v := ${$v}
.endfor
.else
# we cannot use the '$$' trick, anymore
# but we can export a literal (unexpanded) value
SRCTOP := ${_srctop}
OBJROOT := ${_objroot}
OBJTOP = ${OBJROOT}${MACHINE}
MAKEOBJDIR = ${.CURDIR:S,${SRCTOP},${OBJTOP},}
.export-literal SRCTOP OBJROOT ${_tricky_env_vars}
.endif
#.info ${_tricky_env_vars:@v@${.newline}$v=${$v}@}
#showenv:
# @env | egrep 'OBJ|SRC'
.endif # MAKEOBJDIR
.endif # level 0

View File

@ -1,4 +1,4 @@
# $Id: sys.dependfile.mk,v 1.6 2014/08/02 18:02:06 sjg Exp $
# $Id: sys.dependfile.mk,v 1.7 2016/02/20 01:57:39 sjg Exp $
#
# @(#) Copyright (c) 2012, Simon J. Gerraty
#
@ -49,7 +49,9 @@ _e := ${.MAKE.DEPENDFILE_PREFERENCE:@m@${exists($m):?$m:}@}
# If any already exist, we should follow suit.
_aml = ${ALL_MACHINE_LIST:Uarm amd64 i386 powerpc:N${MACHINE}} ${MACHINE}
# MACHINE must be the last entry in _aml ;-)
_m := ${MACHINE}
_e := ${_aml:@MACHINE@${.MAKE.DEPENDFILE_PREFERENCE:@m@${exists($m):?$m:}@}@}
MACHINE := ${_m}
.if !empty(_e)
.MAKE.DEPENDFILE ?= ${.MAKE.DEPENDFILE_PREFERENCE:M*${MACHINE}:[1]}
.endif

View File

@ -1,5 +1,5 @@
# RCSid:
# $Id: warnings.mk,v 1.8 2014/04/02 19:20:23 sjg Exp $
# $Id: warnings.mk,v 1.9 2016/02/20 02:00:58 sjg Exp $
#
# @(#) Copyright (c) 2002, Simon J. Gerraty
#
@ -15,6 +15,8 @@
#
.ifndef _w_cflags
# make sure we get the behavior we expect
.MAKE.SAVE_DOLLARS = no
# Any number of warnings sets can be added.
.-include "warnings-sets.mk"

View File

@ -1,4 +1,4 @@
/* $NetBSD: nonints.h,v 1.69 2015/10/11 04:51:24 sjg Exp $ */
/* $NetBSD: nonints.h,v 1.72 2016/02/18 20:25:08 sjg Exp $ */
/*-
* Copyright (c) 1988, 1989, 1990, 1993
@ -120,6 +120,7 @@ void Finish(int) MAKE_ATTR_DEAD;
int eunlink(const char *);
void execError(const char *, const char *);
char *getTmpdir(void);
Boolean s2Boolean(const char *, Boolean);
Boolean getBoolean(const char *, Boolean);
/* parse.c */
@ -184,8 +185,8 @@ void Var_Set(const char *, const char *, GNode *, int);
void Var_Append(const char *, const char *, GNode *);
Boolean Var_Exists(const char *, GNode *);
char *Var_Value(const char *, GNode *, char **);
char *Var_Parse(const char *, GNode *, Boolean, Boolean, int *, void **);
char *Var_Subst(const char *, const char *, GNode *, Boolean, Boolean);
char *Var_Parse(const char *, GNode *, int, int *, void **);
char *Var_Subst(const char *, const char *, GNode *, int);
char *Var_GetTail(const char *);
char *Var_GetHead(const char *);
void Var_Init(void);

46
parse.c
View File

@ -1,4 +1,4 @@
/* $NetBSD: parse.c,v 1.206 2015/11/26 00:23:04 sjg Exp $ */
/* $NetBSD: parse.c,v 1.212 2016/02/19 06:19:06 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: parse.c,v 1.206 2015/11/26 00:23:04 sjg Exp $";
static char rcsid[] = "$NetBSD: parse.c,v 1.212 2016/02/19 06:19:06 sjg Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94";
#else
__RCSID("$NetBSD: parse.c,v 1.206 2015/11/26 00:23:04 sjg Exp $");
__RCSID("$NetBSD: parse.c,v 1.212 2016/02/19 06:19:06 sjg Exp $");
#endif
#endif /* not lint */
#endif
@ -128,7 +128,6 @@ __RCSID("$NetBSD: parse.c,v 1.206 2015/11/26 00:23:04 sjg Exp $");
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
@ -161,6 +160,7 @@ typedef struct IFile {
int lineno; /* current line number in file */
int first_lineno; /* line number of start of text */
int cond_depth; /* 'if' nesting when file opened */
Boolean depending; /* state of doing_depend on EOF */
char *P_str; /* point to base of string buffer */
char *P_ptr; /* point to next char of string buffer */
char *P_end; /* point to the end of string buffer */
@ -816,7 +816,7 @@ ParseMessage(char *line)
while (isspace((u_char)*line))
line++;
line = Var_Subst(NULL, line, VAR_CMD, FALSE, TRUE);
line = Var_Subst(NULL, line, VAR_CMD, VARF_WANTRES);
Parse_Error(mtype, "%s", line);
free(line);
@ -1233,9 +1233,9 @@ ParseDoDependency(char *line)
int length;
void *freeIt;
(void)Var_Parse(cp, VAR_CMD, TRUE, TRUE, &length, &freeIt);
if (freeIt)
free(freeIt);
(void)Var_Parse(cp, VAR_CMD, VARF_UNDEFERR|VARF_WANTRES,
&length, &freeIt);
free(freeIt);
cp += length-1;
}
}
@ -1948,7 +1948,7 @@ Parse_DoVar(char *line, GNode *ctxt)
if (!Var_Exists(line, ctxt))
Var_Set(line, "", ctxt, 0);
cp = Var_Subst(NULL, cp, ctxt, FALSE, TRUE);
cp = Var_Subst(NULL, cp, ctxt, VARF_WANTRES|VARF_ASSIGN);
oldVars = oldOldVars;
freeCp = TRUE;
@ -1963,7 +1963,7 @@ Parse_DoVar(char *line, GNode *ctxt)
* expansion on the whole thing. The resulting string will need
* freeing when we're done, so set freeCmd to TRUE.
*/
cp = Var_Subst(NULL, cp, VAR_CMD, TRUE, TRUE);
cp = Var_Subst(NULL, cp, VAR_CMD, VARF_UNDEFERR|VARF_WANTRES);
freeCp = TRUE;
}
@ -2155,7 +2155,7 @@ Parse_AddIncludeDir(char *dir)
*/
static void
Parse_include_file(char *file, Boolean isSystem, int silent)
Parse_include_file(char *file, Boolean isSystem, Boolean depinc, int silent)
{
struct loadedfile *lf;
char *fullname; /* full pathname of file */
@ -2255,6 +2255,8 @@ Parse_include_file(char *file, Boolean isSystem, int silent)
/* Start reading from this file next */
Parse_SetInput(fullname, 0, -1, loadedfile_nextbuf, lf);
curFile->lf = lf;
if (depinc)
doing_depend = depinc; /* only turn it on */
}
static void
@ -2302,9 +2304,9 @@ ParseDoInclude(char *line)
* Substitute for any variables in the file name before trying to
* find the thing.
*/
file = Var_Subst(NULL, file, VAR_CMD, FALSE, TRUE);
file = Var_Subst(NULL, file, VAR_CMD, VARF_WANTRES);
Parse_include_file(file, endc == '>', silent);
Parse_include_file(file, endc == '>', (*line == 'd'), silent);
free(file);
}
@ -2339,10 +2341,8 @@ ParseSetIncludedFile(void)
fprintf(debug_file, "%s: ${.INCLUDEDFROMDIR} = `%s' "
"${.INCLUDEDFROMFILE} = `%s'\n", __func__, pd, pf);
if (fp)
free(fp);
if (dp)
free(dp);
free(fp);
free(dp);
}
/*-
*---------------------------------------------------------------------
@ -2472,6 +2472,7 @@ Parse_SetInput(const char *name, int line, int fd,
curFile->nextbuf = nextbuf;
curFile->nextbuf_arg = arg;
curFile->lf = NULL;
curFile->depending = doing_depend; /* restore this on EOF */
assert(nextbuf != NULL);
@ -2532,7 +2533,7 @@ ParseTraditionalInclude(char *line)
* Substitute for any variables in the file name before trying to
* find the thing.
*/
all_files = Var_Subst(NULL, file, VAR_CMD, FALSE, TRUE);
all_files = Var_Subst(NULL, file, VAR_CMD, VARF_WANTRES);
if (*file == '\0') {
Parse_Error(PARSE_FATAL,
@ -2550,7 +2551,7 @@ ParseTraditionalInclude(char *line)
else
done = 1;
Parse_include_file(file, FALSE, silent);
Parse_include_file(file, FALSE, FALSE, silent);
}
free(all_files);
}
@ -2600,7 +2601,7 @@ ParseGmakeExport(char *line)
/*
* Expand the value before putting it in the environment.
*/
value = Var_Subst(NULL, value, VAR_CMD, FALSE, TRUE);
value = Var_Subst(NULL, value, VAR_CMD, VARF_WANTRES);
setenv(variable, value, 1);
}
#endif
@ -2628,6 +2629,7 @@ ParseEOF(void)
assert(curFile->nextbuf != NULL);
doing_depend = curFile->depending; /* restore this */
/* get next input buffer, if any */
ptr = curFile->nextbuf(curFile->nextbuf_arg, &len);
curFile->P_ptr = ptr;
@ -2990,7 +2992,7 @@ Parse_File(const char *name, int fd)
continue;
}
if (strncmp(cp, "include", 7) == 0 ||
((cp[0] == 's' || cp[0] == '-') &&
((cp[0] == 'd' || cp[0] == 's' || cp[0] == '-') &&
strncmp(&cp[1], "include", 7) == 0)) {
ParseDoInclude(cp);
continue;
@ -3149,7 +3151,7 @@ Parse_File(const char *name, int fd)
* variables expanded before being parsed. Tell the variable
* module to complain if some variable is undefined...
*/
line = Var_Subst(NULL, line, VAR_CMD, TRUE, TRUE);
line = Var_Subst(NULL, line, VAR_CMD, VARF_UNDEFERR|VARF_WANTRES);
/*
* Need a non-circular list for the target nodes

17
suff.c
View File

@ -1,4 +1,4 @@
/* $NetBSD: suff.c,v 1.75 2015/12/20 22:44:10 sjg Exp $ */
/* $NetBSD: suff.c,v 1.78 2016/02/18 18:29:14 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: suff.c,v 1.75 2015/12/20 22:44:10 sjg Exp $";
static char rcsid[] = "$NetBSD: suff.c,v 1.78 2016/02/18 18:29:14 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)suff.c 8.4 (Berkeley) 3/21/94";
#else
__RCSID("$NetBSD: suff.c,v 1.75 2015/12/20 22:44:10 sjg Exp $");
__RCSID("$NetBSD: suff.c,v 1.78 2016/02/18 18:29:14 christos Exp $");
#endif
#endif /* not lint */
#endif
@ -1556,7 +1556,7 @@ SuffExpandChildren(LstNode cln, GNode *pgn)
if (DEBUG(SUFF)) {
fprintf(debug_file, "Expanding \"%s\"...", cgn->name);
}
cp = Var_Subst(NULL, cgn->name, pgn, TRUE, TRUE);
cp = Var_Subst(NULL, cgn->name, pgn, VARF_UNDEFERR|VARF_WANTRES);
if (cp != NULL) {
Lst members = Lst_Init(FALSE);
@ -1609,13 +1609,13 @@ SuffExpandChildren(LstNode cln, GNode *pgn)
int len;
void *freeIt;
junk = Var_Parse(cp, pgn, TRUE, TRUE, &len, &freeIt);
junk = Var_Parse(cp, pgn, VARF_UNDEFERR|VARF_WANTRES,
&len, &freeIt);
if (junk != var_Error) {
cp += len - 1;
}
if (freeIt)
free(freeIt);
free(freeIt);
} else if (*cp == '\\' && *cp != '\0') {
/*
* Escaped something -- skip over it
@ -1933,8 +1933,7 @@ SuffFindArchiveDeps(GNode *gn, Lst slst)
for (i = (sizeof(copy)/sizeof(copy[0]))-1; i >= 0; i--) {
char *p1;
Var_Set(copy[i], Var_Value(copy[i], mem, &p1), gn, 0);
if (p1)
free(p1);
free(p1);
}

12
targ.c
View File

@ -1,4 +1,4 @@
/* $NetBSD: targ.c,v 1.60 2015/05/25 09:01:06 manu Exp $ */
/* $NetBSD: targ.c,v 1.61 2016/01/17 17:45:21 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: targ.c,v 1.60 2015/05/25 09:01:06 manu Exp $";
static char rcsid[] = "$NetBSD: targ.c,v 1.61 2016/01/17 17:45:21 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)targ.c 8.2 (Berkeley) 3/19/94";
#else
__RCSID("$NetBSD: targ.c,v 1.60 2015/05/25 09:01:06 manu Exp $");
__RCSID("$NetBSD: targ.c,v 1.61 2016/01/17 17:45:21 christos Exp $");
#endif
#endif /* not lint */
#endif
@ -292,10 +292,8 @@ TargFreeGN(void *gnp)
free(gn->name);
if (gn->uname)
free(gn->uname);
if (gn->path)
free(gn->path);
free(gn->uname);
free(gn->path);
/* gn->fname points to name allocated when file was opened, don't free */
Lst_Destroy(gn->iParents, NULL);

View File

@ -2,8 +2,10 @@ make:
UT_TEST=export-env.mk
UT_ENV=not-exported
UT_EXP=not-exported
UT_LIT=literal export-env.mk
env:
UT_TEST=export-env.mk
UT_ENV=exported
UT_EXP=exported
UT_LIT=literal ${UT_TEST}
exit status 0

View File

@ -1,4 +1,4 @@
# $Id: export-env.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $
# $Id: export-env.mk,v 1.1.1.2 2016/02/18 20:35:24 sjg Exp $
# our normal .export, subsequent changes affect the environment
UT_TEST=this
@ -15,9 +15,12 @@ UT_EXP=before-export
export UT_EXP=exported
UT_EXP=not-exported
UT_LIT= literal ${UT_TEST}
.export-literal UT_LIT
all:
@echo make:; ${UT_TEST UT_ENV UT_EXP:L:@v@echo $v=${$v};@}
@echo env:; ${UT_TEST UT_ENV UT_EXP:L:@v@echo $v=$${$v};@}
@echo make:; ${UT_TEST UT_ENV UT_EXP UT_LIT:L:@v@echo $v=${$v};@}
@echo env:; ${UT_TEST UT_ENV UT_EXP UT_LIT:L:@v@echo $v=$${$v};@}

View File

@ -23,10 +23,16 @@ THREE
FOUR
FIVE
SIX"
LIST:ts/xa:tu="ONE
TWO
THREE
FOUR
FIVE
SIX"
make: Bad modifier `:tx' for LIST
LIST:tx="}"
make: Bad modifier `:ts\x' for LIST
LIST:ts/x:tu="\x:tu}"
make: Bad modifier `:ts\X' for LIST
LIST:ts/x:tu="\X:tu}"
FU_mod-ts="a/b/cool"
FU_mod-ts:ts:T="cool" == cool?
B.${AAA:ts}="Baaa" == Baaa?

View File

@ -36,8 +36,9 @@ mod-ts:
@${PRINT} 'LIST:ts/n="${LIST:ts\n}"'
@${PRINT} 'LIST:ts/t="${LIST:ts\t}"'
@${PRINT} 'LIST:ts/012:tu="${LIST:ts\012:tu}"'
@${PRINT} 'LIST:ts/xa:tu="${LIST:ts\xa:tu}"'
@${PRINT} 'LIST:tx="${LIST:tx}"'
@${PRINT} 'LIST:ts/x:tu="${LIST:ts\x:tu}"'
@${PRINT} 'LIST:ts/x:tu="${LIST:ts\X:tu}"'
@${PRINT} 'FU_$@="${FU_${@:ts}:ts}"'
@${PRINT} 'FU_$@:ts:T="${FU_${@:ts}:ts:T}" == cool?'
@${PRINT} 'B.$${AAA:ts}="${B.${AAA:ts}}" == Baaa?'

223
var.c
View File

@ -1,4 +1,4 @@
/* $NetBSD: var.c,v 1.200 2015/12/01 07:26:08 sjg Exp $ */
/* $NetBSD: var.c,v 1.206 2016/03/07 20:20:35 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: var.c,v 1.200 2015/12/01 07:26:08 sjg Exp $";
static char rcsid[] = "$NetBSD: var.c,v 1.206 2016/03/07 20:20:35 sjg Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94";
#else
__RCSID("$NetBSD: var.c,v 1.200 2015/12/01 07:26:08 sjg Exp $");
__RCSID("$NetBSD: var.c,v 1.206 2016/03/07 20:20:35 sjg Exp $");
#endif
#endif /* not lint */
#endif
@ -154,12 +154,22 @@ char **savedEnv = NULL;
char var_Error[] = "";
/*
* Similar to var_Error, but returned when the 'errnum' flag for Var_Parse is
* set false. Why not just use a constant? Well, gcc likes to condense
* identical string instances...
* Similar to var_Error, but returned when the 'VARF_UNDEFERR' flag for
* Var_Parse is not set. Why not just use a constant? Well, gcc likes
* to condense identical string instances...
*/
static char varNoError[] = "";
/*
* Traditionally we consume $$ during := like any other expansion.
* Other make's do not.
* This knob allows controlling the behavior.
* FALSE for old behavior.
* TRUE for new compatible.
*/
#define SAVE_DOLLARS ".MAKE.SAVE_DOLLARS"
static Boolean save_dollars = FALSE;
/*
* Internally, variables are contained in four different contexts.
* 1) the environment. They may not be changed. If an environment
@ -216,7 +226,11 @@ static int var_exportedVars = VAR_EXPORTED_NONE;
* We pass this to Var_Export when doing the initial export
* or after updating an exported var.
*/
#define VAR_EXPORT_PARENT 1
#define VAR_EXPORT_PARENT 1
/*
* We pass this to Var_Export1 to tell it to leave the value alone.
*/
#define VAR_EXPORT_LITERAL 2
/* Var*Pattern flags */
#define VAR_SUB_GLOBAL 0x01 /* Apply substitution globally */
@ -541,7 +555,7 @@ Var_Delete(const char *name, GNode *ctxt)
char *cp;
if (strchr(name, '$')) {
cp = Var_Subst(NULL, name, VAR_GLOBAL, FALSE, TRUE);
cp = Var_Subst(NULL, name, VAR_GLOBAL, VARF_WANTRES);
} else {
cp = (char *)name;
}
@ -580,12 +594,13 @@ Var_Delete(const char *name, GNode *ctxt)
* We only manipulate flags of vars if 'parent' is set.
*/
static int
Var_Export1(const char *name, int parent)
Var_Export1(const char *name, int flags)
{
char tmp[BUFSIZ];
Var *v;
char *val = NULL;
int n;
int parent = (flags & VAR_EXPORT_PARENT);
if (*name == '.')
return 0; /* skip internals */
@ -613,7 +628,7 @@ Var_Export1(const char *name, int parent)
return 0; /* nothing to do */
}
val = Buf_GetAll(&v->val, NULL);
if (strchr(val, '$')) {
if ((flags & VAR_EXPORT_LITERAL) == 0 && strchr(val, '$')) {
if (parent) {
/*
* Flag this as something we need to re-export.
@ -632,7 +647,7 @@ Var_Export1(const char *name, int parent)
}
n = snprintf(tmp, sizeof(tmp), "${%s}", name);
if (n < (int)sizeof(tmp)) {
val = Var_Subst(NULL, tmp, VAR_GLOBAL, FALSE, TRUE);
val = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
setenv(name, val, 1);
free(val);
}
@ -700,7 +715,7 @@ Var_ExportVars(void)
int ac;
int i;
val = Var_Subst(NULL, tmp, VAR_GLOBAL, FALSE, TRUE);
val = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
if (*val) {
av = brk_string(val, &ac, FALSE, &as);
for (i = 0; i < ac; i++) {
@ -725,7 +740,7 @@ Var_Export(char *str, int isExport)
char *val;
char **av;
char *as;
int track;
int flags;
int ac;
int i;
@ -734,13 +749,16 @@ Var_Export(char *str, int isExport)
return;
}
flags = 0;
if (strncmp(str, "-env", 4) == 0) {
track = 0;
str += 4;
} else if (strncmp(str, "-literal", 8) == 0) {
str += 8;
flags |= VAR_EXPORT_LITERAL;
} else {
track = VAR_EXPORT_PARENT;
flags |= VAR_EXPORT_PARENT;
}
val = Var_Subst(NULL, str, VAR_GLOBAL, FALSE, TRUE);
val = Var_Subst(NULL, str, VAR_GLOBAL, VARF_WANTRES);
if (*val) {
av = brk_string(val, &ac, FALSE, &as);
for (i = 0; i < ac; i++) {
@ -760,10 +778,10 @@ Var_Export(char *str, int isExport)
continue;
}
}
if (Var_Export1(name, track)) {
if (Var_Export1(name, flags)) {
if (VAR_EXPORTED_ALL != var_exportedVars)
var_exportedVars = VAR_EXPORTED_YES;
if (isExport && track) {
if (isExport && (flags & VAR_EXPORT_PARENT)) {
Var_Append(MAKE_EXPORTED, name, VAR_GLOBAL);
}
}
@ -830,7 +848,7 @@ Var_UnExport(char *str)
/* Using .MAKE.EXPORTED */
n = snprintf(tmp, sizeof(tmp), "${" MAKE_EXPORTED ":O:u}");
if (n < (int)sizeof(tmp)) {
vlist = Var_Subst(NULL, tmp, VAR_GLOBAL, FALSE, TRUE);
vlist = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
}
}
if (vlist) {
@ -860,7 +878,7 @@ Var_UnExport(char *str)
n = snprintf(tmp, sizeof(tmp),
"${" MAKE_EXPORTED ":N%s}", v->name);
if (n < (int)sizeof(tmp)) {
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, FALSE, TRUE);
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
Var_Set(MAKE_EXPORTED, cp, VAR_GLOBAL, 0);
free(cp);
}
@ -915,7 +933,7 @@ Var_Set(const char *name, const char *val, GNode *ctxt, int flags)
* point in searching them all just to save a bit of memory...
*/
if (strchr(name, '$') != NULL) {
expanded_name = Var_Subst(NULL, name, ctxt, FALSE, TRUE);
expanded_name = Var_Subst(NULL, name, ctxt, VARF_WANTRES);
if (expanded_name[0] == 0) {
if (DEBUG(VAR)) {
fprintf(debug_file, "Var_Set(\"%s\", \"%s\", ...) "
@ -983,7 +1001,11 @@ Var_Set(const char *name, const char *val, GNode *ctxt, int flags)
Var_Append(MAKEOVERRIDES, name, VAR_GLOBAL);
}
if (*name == '.') {
if (strcmp(name, SAVE_DOLLARS) == 0)
save_dollars = s2Boolean(val, save_dollars);
}
out:
free(expanded_name);
if (v != NULL)
@ -1025,7 +1047,7 @@ Var_Append(const char *name, const char *val, GNode *ctxt)
char *expanded_name = NULL;
if (strchr(name, '$') != NULL) {
expanded_name = Var_Subst(NULL, name, ctxt, FALSE, TRUE);
expanded_name = Var_Subst(NULL, name, ctxt, VARF_WANTRES);
if (expanded_name[0] == 0) {
if (DEBUG(VAR)) {
fprintf(debug_file, "Var_Append(\"%s\", \"%s\", ...) "
@ -1090,7 +1112,7 @@ Var_Exists(const char *name, GNode *ctxt)
char *cp;
if ((cp = strchr(name, '$')) != NULL) {
cp = Var_Subst(NULL, name, ctxt, FALSE, TRUE);
cp = Var_Subst(NULL, name, ctxt, VARF_WANTRES);
}
v = VarFind(cp ? cp : name, ctxt, FIND_CMD|FIND_GLOBAL|FIND_ENV);
free(cp);
@ -1388,7 +1410,7 @@ VarSYSVMatch(GNode *ctx, Var_Parse_State *vpstate,
addSpace = TRUE;
if ((ptr = Str_SYSVMatch(word, pat->lhs, &len)) != NULL) {
varexp = Var_Subst(NULL, pat->rhs, ctx, FALSE, TRUE);
varexp = Var_Subst(NULL, pat->rhs, ctx, VARF_WANTRES);
Str_SYSVSubst(buf, varexp, ptr, len);
free(varexp);
} else {
@ -1628,14 +1650,14 @@ VarSubstitute(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
*-----------------------------------------------------------------------
*/
static void
VarREError(int errnum, regex_t *pat, const char *str)
VarREError(int reerr, regex_t *pat, const char *str)
{
char *errbuf;
int errlen;
errlen = regerror(errnum, pat, 0, 0);
errlen = regerror(reerr, pat, 0, 0);
errbuf = bmake_malloc(errlen);
regerror(errnum, pat, errbuf, errlen);
regerror(reerr, pat, errbuf, errlen);
Error("%s: %s", str, errbuf);
free(errbuf);
}
@ -1808,7 +1830,7 @@ VarLoopExpand(GNode *ctx MAKE_ATTR_UNUSED,
if (word && *word) {
Var_Set(loop->tvar, word, loop->ctxt, VAR_NO_EXPORT);
s = Var_Subst(NULL, loop->str, loop->ctxt, loop->errnum, TRUE);
s = Var_Subst(NULL, loop->str, loop->ctxt, loop->errnum | VARF_WANTRES);
if (s != NULL && *s != '\0') {
if (addSpace && *s != '\n')
Buf_AddByte(buf, ' ');
@ -2142,13 +2164,14 @@ VarUniq(const char *str)
*/
static char *
VarGetPattern(GNode *ctxt, Var_Parse_State *vpstate MAKE_ATTR_UNUSED,
int errnum, const char **tstr, int delim, int *flags,
int flags, const char **tstr, int delim, int *vflags,
int *length, VarPattern *pattern)
{
const char *cp;
char *rstr;
Buffer buf;
int junk;
int errnum = flags & VARF_UNDEFERR;
Buf_Init(&buf, 0);
if (length == NULL)
@ -2170,16 +2193,16 @@ VarGetPattern(GNode *ctxt, Var_Parse_State *vpstate MAKE_ATTR_UNUSED,
cp++;
} else if (*cp == '$') {
if (cp[1] == delim) {
if (flags == NULL)
if (vflags == NULL)
Buf_AddByte(&buf, *cp);
else
/*
* Unescaped $ at end of pattern => anchor
* pattern at end.
*/
*flags |= VAR_MATCH_END;
*vflags |= VAR_MATCH_END;
} else {
if (flags == NULL || (*flags & VAR_NOSUBST) == 0) {
if (vflags == NULL || (*vflags & VAR_NOSUBST) == 0) {
char *cp2;
int len;
void *freeIt;
@ -2189,7 +2212,8 @@ VarGetPattern(GNode *ctxt, Var_Parse_State *vpstate MAKE_ATTR_UNUSED,
* delimiter, assume it's a variable
* substitution and recurse.
*/
cp2 = Var_Parse(cp, ctxt, errnum, TRUE, &len, &freeIt);
cp2 = Var_Parse(cp, ctxt, errnum | VARF_WANTRES, &len,
&freeIt);
Buf_AddBytes(&buf, strlen(cp2), cp2);
free(freeIt);
cp += len - 1;
@ -2462,7 +2486,7 @@ VarStrftime(const char *fmt, int zulu)
static char *
ApplyModifiers(char *nstr, const char *tstr,
int startc, int endc,
Var *v, GNode *ctxt, Boolean errnum, Boolean wantit,
Var *v, GNode *ctxt, int flags,
int *lengthPtr, void **freePtr)
{
const char *start;
@ -2493,7 +2517,7 @@ ApplyModifiers(char *nstr, const char *tstr,
int rlen;
int c;
rval = Var_Parse(tstr, ctxt, errnum, wantit, &rlen, &freeIt);
rval = Var_Parse(tstr, ctxt, flags, &rlen, &freeIt);
/*
* If we have not parsed up to endc or ':',
@ -2518,10 +2542,9 @@ ApplyModifiers(char *nstr, const char *tstr,
int used;
nstr = ApplyModifiers(nstr, rval,
0, 0,
v, ctxt, errnum, wantit, &used, freePtr);
0, 0, v, ctxt, flags, &used, freePtr);
if (nstr == var_Error
|| (nstr == varNoError && errnum == 0)
|| (nstr == varNoError && (flags & VARF_UNDEFERR) == 0)
|| strlen(rval) != (size_t) used) {
free(freeIt);
goto out; /* error already reported */
@ -2556,7 +2579,7 @@ ApplyModifiers(char *nstr, const char *tstr,
char *sv_name;
VarPattern pattern;
int how;
int flags;
int vflags;
if (v->name[0] == 0)
goto bad_modifier;
@ -2592,9 +2615,9 @@ ApplyModifiers(char *nstr, const char *tstr,
delim = startc == PROPEN ? PRCLOSE : BRCLOSE;
pattern.flags = 0;
flags = (wantit) ? 0 : VAR_NOSUBST;
pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
&cp, delim, &flags,
vflags = (flags & VARF_WANTRES) ? 0 : VAR_NOSUBST;
pattern.rhs = VarGetPattern(ctxt, &parsestate, flags,
&cp, delim, &vflags,
&pattern.rightLen,
NULL);
if (v->flags & VAR_JUNK) {
@ -2608,7 +2631,7 @@ ApplyModifiers(char *nstr, const char *tstr,
termc = *--cp;
delim = '\0';
if (wantit) {
if (flags & VARF_WANTRES) {
switch (how) {
case '+':
Var_Append(v->name, pattern.rhs, v_ctxt);
@ -2639,29 +2662,30 @@ ApplyModifiers(char *nstr, const char *tstr,
case '@':
{
VarLoop_t loop;
int flags = VAR_NOSUBST;
int vflags = VAR_NOSUBST;
cp = ++tstr;
delim = '@';
if ((loop.tvar = VarGetPattern(ctxt, &parsestate, errnum,
if ((loop.tvar = VarGetPattern(ctxt, &parsestate, flags,
&cp, delim,
&flags, &loop.tvarLen,
&vflags, &loop.tvarLen,
NULL)) == NULL)
goto cleanup;
if ((loop.str = VarGetPattern(ctxt, &parsestate, errnum,
if ((loop.str = VarGetPattern(ctxt, &parsestate, flags,
&cp, delim,
&flags, &loop.strLen,
&vflags, &loop.strLen,
NULL)) == NULL)
goto cleanup;
termc = *cp;
delim = '\0';
loop.errnum = errnum;
loop.errnum = flags & VARF_UNDEFERR;
loop.ctxt = ctxt;
newStr = VarModify(ctxt, &parsestate, nstr, VarLoopExpand,
&loop);
Var_Delete(loop.tvar, ctxt);
free(loop.tvar);
free(loop.str);
break;
@ -2670,15 +2694,19 @@ ApplyModifiers(char *nstr, const char *tstr,
case 'U':
{
Buffer buf; /* Buffer for patterns */
int wantit_; /* want data in buffer */
int nflags;
if (wantit) {
if (flags & VARF_WANTRES) {
int wantres;
if (*tstr == 'U')
wantit_ = ((v->flags & VAR_JUNK) != 0);
wantres = ((v->flags & VAR_JUNK) != 0);
else
wantit_ = ((v->flags & VAR_JUNK) == 0);
wantres = ((v->flags & VAR_JUNK) == 0);
nflags = flags & ~VARF_WANTRES;
if (wantres)
nflags |= VARF_WANTRES;
} else
wantit_ = wantit;
nflags = flags;
/*
* Pass through tstr looking for 1) escaped delimiters,
* '$'s and backslashes (place the escaped character in
@ -2707,7 +2735,7 @@ ApplyModifiers(char *nstr, const char *tstr,
int len;
void *freeIt;
cp2 = Var_Parse(cp, ctxt, errnum, wantit_, &len, &freeIt);
cp2 = Var_Parse(cp, ctxt, nflags, &len, &freeIt);
Buf_AddBytes(&buf, strlen(cp2), cp2);
free(freeIt);
cp += len - 1;
@ -2720,7 +2748,7 @@ ApplyModifiers(char *nstr, const char *tstr,
if ((v->flags & VAR_JUNK) != 0)
v->flags |= VAR_KEEP;
if (wantit_) {
if (nflags & VARF_WANTRES) {
newStr = Buf_Destroy(&buf, FALSE);
} else {
newStr = nstr;
@ -2767,12 +2795,12 @@ ApplyModifiers(char *nstr, const char *tstr,
delim = '!';
emsg = NULL;
cp = ++tstr;
if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, flags,
&cp, delim,
NULL, &pattern.rightLen,
NULL)) == NULL)
goto cleanup;
if (wantit)
if (flags & VARF_WANTRES)
newStr = Cmd_Exec(pattern.rhs, &emsg);
else
newStr = varNoError;
@ -2800,7 +2828,7 @@ ApplyModifiers(char *nstr, const char *tstr,
cp = tstr+1; /* point to char after '[' */
delim = ']'; /* look for closing ']' */
estr = VarGetPattern(ctxt, &parsestate,
errnum, &cp, delim,
flags, &cp, delim,
NULL, NULL, NULL);
if (estr == NULL)
goto cleanup; /* report missing ']' */
@ -2977,6 +3005,9 @@ ApplyModifiers(char *nstr, const char *tstr,
parsestate.varSpace = 0; /* no separator */
cp = tstr + 2;
} else if (tstr[2] == '\\') {
const char *xp = &tstr[3];
int base = 8; /* assume octal */
switch (tstr[3]) {
case 'n':
parsestate.varSpace = '\n';
@ -2986,12 +3017,20 @@ ApplyModifiers(char *nstr, const char *tstr,
parsestate.varSpace = '\t';
cp = tstr + 4;
break;
case 'x':
base = 16;
xp++;
goto get_numeric;
case '0':
base = 0;
goto get_numeric;
default:
if (isdigit((unsigned char)tstr[3])) {
char *ep;
get_numeric:
parsestate.varSpace =
strtoul(&tstr[3], &ep, 0);
strtoul(xp, &ep, base);
if (*ep != ':' && *ep != endc)
goto bad_modifier;
cp = ep;
@ -3151,7 +3190,7 @@ ApplyModifiers(char *nstr, const char *tstr,
* expand it.
*/
cp2 = pattern;
pattern = Var_Subst(NULL, cp2, ctxt, errnum, TRUE);
pattern = Var_Subst(NULL, cp2, ctxt, flags | VARF_WANTRES);
free(cp2);
}
if (DEBUG(VAR))
@ -3187,14 +3226,14 @@ ApplyModifiers(char *nstr, const char *tstr,
}
cp = tstr;
if ((pattern.lhs = VarGetPattern(ctxt, &parsestate, errnum,
if ((pattern.lhs = VarGetPattern(ctxt, &parsestate, flags,
&cp, delim,
&pattern.flags,
&pattern.leftLen,
NULL)) == NULL)
goto cleanup;
if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, flags,
&cp, delim, NULL,
&pattern.rightLen,
&pattern)) == NULL)
@ -3241,7 +3280,7 @@ ApplyModifiers(char *nstr, const char *tstr,
int lhs_flags, rhs_flags;
/* find ':', and then substitute accordingly */
if (wantit) {
if (flags & VARF_WANTRES) {
cond_rc = Cond_EvalExpression(NULL, v->name, &value, 0, FALSE);
if (cond_rc == COND_INVALID) {
lhs_flags = rhs_flags = VAR_NOSUBST;
@ -3261,7 +3300,7 @@ ApplyModifiers(char *nstr, const char *tstr,
cp = ++tstr;
delim = ':';
if ((pattern.lhs = VarGetPattern(ctxt, &parsestate, errnum,
if ((pattern.lhs = VarGetPattern(ctxt, &parsestate, flags,
&cp, delim, &lhs_flags,
&pattern.leftLen,
NULL)) == NULL)
@ -3269,7 +3308,7 @@ ApplyModifiers(char *nstr, const char *tstr,
/* BROPEN or PROPEN */
delim = endc;
if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, flags,
&cp, delim, &rhs_flags,
&pattern.rightLen,
NULL)) == NULL)
@ -3310,12 +3349,12 @@ ApplyModifiers(char *nstr, const char *tstr,
cp = tstr;
if ((re = VarGetPattern(ctxt, &parsestate, errnum, &cp, delim,
if ((re = VarGetPattern(ctxt, &parsestate, flags, &cp, delim,
NULL, NULL, NULL)) == NULL)
goto cleanup;
if ((pattern.replace = VarGetPattern(ctxt, &parsestate,
errnum, &cp, delim, NULL,
flags, &cp, delim, NULL,
NULL, NULL)) == NULL){
free(re);
goto cleanup;
@ -3439,7 +3478,7 @@ ApplyModifiers(char *nstr, const char *tstr,
case 's':
if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) {
const char *emsg;
if (wantit) {
if (flags & VARF_WANTRES) {
newStr = Cmd_Exec(nstr, &emsg);
if (emsg)
Error(emsg, nstr);
@ -3492,12 +3531,12 @@ ApplyModifiers(char *nstr, const char *tstr,
delim='=';
cp = tstr;
if ((pattern.lhs = VarGetPattern(ctxt, &parsestate,
errnum, &cp, delim, &pattern.flags,
flags, &cp, delim, &pattern.flags,
&pattern.leftLen, NULL)) == NULL)
goto cleanup;
delim = endc;
if ((pattern.rhs = VarGetPattern(ctxt, &parsestate,
errnum, &cp, delim, NULL, &pattern.rightLen,
flags, &cp, delim, NULL, &pattern.rightLen,
&pattern)) == NULL)
goto cleanup;
@ -3580,8 +3619,9 @@ ApplyModifiers(char *nstr, const char *tstr,
* Input:
* str The string to parse
* ctxt The context for the variable
* errnum TRUE if undefined variables are an error
* wantit TRUE if we actually want the result
* flags VARF_UNDEFERR if undefineds are an error
* VARF_WANTRES if we actually want the result
* VARF_ASSIGN if we are in a := assignment
* lengthPtr OUT: The length of the specification
* freePtr OUT: Non-NULL if caller should free *freePtr
*
@ -3600,9 +3640,8 @@ ApplyModifiers(char *nstr, const char *tstr,
*/
/* coverity[+alloc : arg-*4] */
char *
Var_Parse(const char *str, GNode *ctxt,
Boolean errnum, Boolean wantit,
int *lengthPtr, void **freePtr)
Var_Parse(const char *str, GNode *ctxt, int flags,
int *lengthPtr, void **freePtr)
{
const char *tstr; /* Pointer into str */
Var *v; /* Variable in invocation */
@ -3670,7 +3709,7 @@ Var_Parse(const char *str, GNode *ctxt,
/*
* Error
*/
return (errnum ? var_Error : varNoError);
return (flags & VARF_UNDEFERR) ? var_Error : varNoError;
} else {
haveModifier = FALSE;
tstr = &str[1];
@ -3707,7 +3746,7 @@ Var_Parse(const char *str, GNode *ctxt,
if (*tstr == '$') {
int rlen;
void *freeIt;
char *rval = Var_Parse(tstr, ctxt, errnum, wantit, &rlen, &freeIt);
char *rval = Var_Parse(tstr, ctxt, flags, &rlen, &freeIt);
if (rval != NULL) {
Buf_AddBytes(&buf, strlen(rval), rval);
}
@ -3820,7 +3859,7 @@ Var_Parse(const char *str, GNode *ctxt,
return(pstr);
} else {
Buf_Destroy(&buf, TRUE);
return (errnum ? var_Error : varNoError);
return (flags & VARF_UNDEFERR) ? var_Error : varNoError;
}
} else {
/*
@ -3854,7 +3893,7 @@ Var_Parse(const char *str, GNode *ctxt,
*/
nstr = Buf_GetAll(&v->val, NULL);
if (strchr(nstr, '$') != NULL) {
nstr = Var_Subst(NULL, nstr, ctxt, errnum, wantit);
nstr = Var_Subst(NULL, nstr, ctxt, flags);
*freePtr = nstr;
}
@ -3867,7 +3906,7 @@ Var_Parse(const char *str, GNode *ctxt,
extraFree = NULL;
if (extramodifiers != NULL) {
nstr = ApplyModifiers(nstr, extramodifiers, '(', ')',
v, ctxt, errnum, wantit, &used, &extraFree);
v, ctxt, flags, &used, &extraFree);
}
if (haveModifier) {
@ -3875,7 +3914,7 @@ Var_Parse(const char *str, GNode *ctxt,
tstr++;
nstr = ApplyModifiers(nstr, tstr, startc, endc,
v, ctxt, errnum, wantit, &used, freePtr);
v, ctxt, flags, &used, freePtr);
tstr += used;
free(extraFree);
} else {
@ -3916,7 +3955,7 @@ Var_Parse(const char *str, GNode *ctxt,
nstr = bmake_strndup(start, *lengthPtr);
*freePtr = nstr;
} else {
nstr = errnum ? var_Error : varNoError;
nstr = (flags & VARF_UNDEFERR) ? var_Error : varNoError;
}
}
if (nstr != Buf_GetAll(&v->val, NULL))
@ -3931,15 +3970,16 @@ Var_Parse(const char *str, GNode *ctxt,
*-----------------------------------------------------------------------
* Var_Subst --
* Substitute for all variables in the given string in the given context
* If undefErr is TRUE, Parse_Error will be called when an undefined
* If flags & VARF_UNDEFERR, Parse_Error will be called when an undefined
* variable is encountered.
*
* Input:
* var Named variable || NULL for all
* str the string which to substitute
* ctxt the context wherein to find variables
* undefErr TRUE if undefineds are an error
* wantit TRUE if we actually want the result
* flags VARF_UNDEFERR if undefineds are an error
* VARF_WANTRES if we actually want the result
* VARF_ASSIGN if we are in a := assignment
*
* Results:
* The resulting string.
@ -3949,8 +3989,7 @@ Var_Parse(const char *str, GNode *ctxt,
*-----------------------------------------------------------------------
*/
char *
Var_Subst(const char *var, const char *str, GNode *ctxt,
Boolean undefErr, Boolean wantit)
Var_Subst(const char *var, const char *str, GNode *ctxt, int flags)
{
Buffer buf; /* Buffer for forming things */
char *val; /* Value to substitute for a variable */
@ -3974,6 +4013,8 @@ Var_Subst(const char *var, const char *str, GNode *ctxt,
* In such a case, we skip over the escape character and store the
* dollar sign into the buffer directly.
*/
if (save_dollars && (flags & VARF_ASSIGN))
Buf_AddByte(&buf, *str);
str++;
Buf_AddByte(&buf, *str);
str++;
@ -4048,7 +4089,7 @@ Var_Subst(const char *var, const char *str, GNode *ctxt,
continue;
}
val = Var_Parse(str, ctxt, undefErr, wantit, &length, &freeIt);
val = Var_Parse(str, ctxt, flags, &length, &freeIt);
/*
* When we come down here, val should either point to the
@ -4065,7 +4106,7 @@ Var_Subst(const char *var, const char *str, GNode *ctxt,
*/
if (oldVars) {
str += length;
} else if (undefErr || val == var_Error) {
} else if ((flags & VARF_UNDEFERR) || val == var_Error) {
/*
* If variable is undefined, complain and skip the
* variable. The complaint will stop us from doing anything