Make: Updates from NetBSD

Needed for pkgsrc
This commit is contained in:
Arun Thomas 2010-06-25 23:25:48 +00:00
parent e10916476a
commit 8e0253ac3d
13 changed files with 503 additions and 178 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.49 2009/04/14 22:15:23 lukem Exp $
# $NetBSD: Makefile,v 1.50 2010/04/22 19:15:23 sjg Exp $
# @(#)Makefile 5.2 (Berkeley) 12/28/90
PROG= make
@ -35,4 +35,4 @@ CPPFLAGS+= -DTARGET_MACHINE=\"${MACHINE}\" \
# A simple unit-test driver to help catch regressions
accept test:
cd ${.CURDIR}/unit-tests && ${.MAKE:S,^./,${.CURDIR}/,} TEST_MAKE=${TEST_MAKE:U${.OBJDIR}/${PROG:T}} ${.TARGET}
cd ${.CURDIR}/unit-tests && ${.MAKE} -r -m / TEST_MAKE=${TEST_MAKE:U${.OBJDIR}/${PROG:T}} ${.TARGET}

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.49 2009/04/14 22:15:23 lukem Exp $
# $NetBSD: Makefile,v 1.50 2010/04/22 19:15:23 sjg Exp $
# @(#)Makefile 5.2 (Berkeley) 12/28/90
PROG= make
@ -37,4 +37,4 @@ DPADD+=${LIBUTIL}
# A simple unit-test driver to help catch regressions
accept test:
cd ${.CURDIR}/unit-tests && ${.MAKE:S,^./,${.CURDIR}/,} TEST_MAKE=${TEST_MAKE:U${.OBJDIR}/${PROG:T}} ${.TARGET}
cd ${.CURDIR}/unit-tests && ${.MAKE} -r -m / TEST_MAKE=${TEST_MAKE:U${.OBJDIR}/${PROG:T}} ${.TARGET}

View File

@ -1,4 +1,4 @@
/* $NetBSD: compat.c,v 1.76 2009/02/22 07:33:00 dholland Exp $ */
/* $NetBSD: compat.c,v 1.79 2010/06/03 15:40:15 sjg 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.76 2009/02/22 07:33:00 dholland Exp $";
static char rcsid[] = "$NetBSD: compat.c,v 1.79 2010/06/03 15:40:15 sjg 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.76 2009/02/22 07:33:00 dholland Exp $");
__RCSID("$NetBSD: compat.c,v 1.79 2010/06/03 15:40:15 sjg Exp $");
#endif
#endif /* not lint */
#endif
@ -355,11 +355,7 @@ again:
/*
* Fork and execute the single command. If the fork fails, we abort.
*/
#if defined(__minix)
cpid = fork();
#else
cpid = vfork();
#endif
cpid = vFork();
if (cpid < 0) {
Fatal("Could not fork");
}
@ -578,7 +574,7 @@ Compat_Make(void *gnp, void *pgnp)
} else if (keepgoing) {
pgn->flags &= ~REMAKE;
} else {
PrintOnError("\n\nStop.");
PrintOnError(gn, "\n\nStop.");
exit(1);
}
} else if (gn->made == ERROR) {
@ -645,17 +641,17 @@ Compat_Run(Lst targs)
Compat_Init();
if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
signal(SIGINT, CompatInterrupt);
if (bmake_signal(SIGINT, SIG_IGN) != SIG_IGN) {
bmake_signal(SIGINT, CompatInterrupt);
}
if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
signal(SIGTERM, CompatInterrupt);
if (bmake_signal(SIGTERM, SIG_IGN) != SIG_IGN) {
bmake_signal(SIGTERM, CompatInterrupt);
}
if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
signal(SIGHUP, CompatInterrupt);
if (bmake_signal(SIGHUP, SIG_IGN) != SIG_IGN) {
bmake_signal(SIGHUP, CompatInterrupt);
}
if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) {
signal(SIGQUIT, CompatInterrupt);
if (bmake_signal(SIGQUIT, SIG_IGN) != SIG_IGN) {
bmake_signal(SIGQUIT, CompatInterrupt);
}
ENDNode = Targ_FindNode(".END", TARG_CREATE);
@ -669,7 +665,7 @@ Compat_Run(Lst targs)
if (gn != NULL) {
Compat_Make(gn, gn);
if (gn->made == ERROR) {
PrintOnError("\n\nStop.");
PrintOnError(gn, "\n\nStop.");
exit(1);
}
}
@ -710,7 +706,7 @@ Compat_Run(Lst targs)
if (errors == 0) {
Compat_Make(ENDNode, ENDNode);
if (gn->made == ERROR) {
PrintOnError("\n\nStop.");
PrintOnError(gn, "\n\nStop.");
exit(1);
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: for.c,v 1.46 2009/01/17 13:29:37 dsl Exp $ */
/* $NetBSD: for.c,v 1.47 2010/02/06 20:37:13 dholland 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.46 2009/01/17 13:29:37 dsl Exp $";
static char rcsid[] = "$NetBSD: for.c,v 1.47 2010/02/06 20:37:13 dholland 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.46 2009/01/17 13:29:37 dsl Exp $");
__RCSID("$NetBSD: for.c,v 1.47 2010/02/06 20:37:13 dholland Exp $");
#endif
#endif /* not lint */
#endif
@ -237,7 +237,8 @@ For_Eval(char *line)
if (strlist_num(&new_for->items) % strlist_num(&new_for->vars)) {
Parse_Error(PARSE_FATAL,
"Wrong number of words in .for substitution list %d %d",
"Wrong number of words (%d) in .for substitution list"
" with %d vars",
strlist_num(&new_for->items), strlist_num(&new_for->vars));
/*
* Return 'success' so that the body of the .for loop is accumulated.

View File

@ -1,4 +1,4 @@
/* $NetBSD: job.c,v 1.146 2009/06/26 01:26:32 sjg Exp $ */
/* $NetBSD: job.c,v 1.151 2010/06/17 03:36:05 sjg 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.146 2009/06/26 01:26:32 sjg Exp $";
static char rcsid[] = "$NetBSD: job.c,v 1.151 2010/06/17 03:36:05 sjg 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.146 2009/06/26 01:26:32 sjg Exp $");
__RCSID("$NetBSD: job.c,v 1.151 2010/06/17 03:36:05 sjg Exp $");
#endif
#endif /* not lint */
#endif
@ -342,8 +342,6 @@ static sigset_t caught_signals; /* Set of signals we handle */
#define KILLPG(pid, sig) killpg((pid), (sig))
#endif
static char *tmpdir; /* directory name, always ending with "/" */
static void JobChildSig(int);
static void JobContinueSig(int);
static Job *JobFindPid(int, int);
@ -1022,8 +1020,11 @@ JobFinish(Job *job, int status)
job->node->name,
WEXITSTATUS(status),
(job->flags & JOB_IGNERR) ? "(ignored)" : "");
if (job->flags & JOB_IGNERR)
if (job->flags & JOB_IGNERR) {
status = 0;
} else {
PrintOnError(job->node, NULL);
}
} else if (DEBUG(JOB)) {
if (job->node != lastNode) {
MESSAGE(stdout, job->node);
@ -1225,8 +1226,8 @@ Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...))
static const char msg[] = ": don't know how to make";
if (gn->flags & FROM_DEPEND) {
fprintf(stdout, "%s: ignoring stale .depend for %s\n",
progname, gn->name);
fprintf(stdout, "%s: ignoring stale %s for %s\n",
progname, makeDependfile, gn->name);
return TRUE;
}
@ -1301,11 +1302,7 @@ JobExec(Job *job, char **argv)
/* Pre-emptively mark job running, pid still zero though */
job->job_state = JOB_ST_RUNNING;
#if defined(__minix)
cpid = fork();
#else
cpid = vfork();
#endif
cpid = vFork();
if (cpid == -1)
Punt("Cannot vfork: %s", strerror(errno));
@ -1559,11 +1556,7 @@ JobStart(GNode *gn, int flags)
}
JobSigLock(&mask);
tfile = bmake_malloc(strlen(tmpdir) + sizeof(TMPPAT));
strcpy(tfile, tmpdir);
strcat(tfile, TMPPAT);
if ((tfd = mkstemp(tfile)) == -1)
Punt("Could not create temporary file %s", strerror(errno));
tfd = mkTempFile(TMPPAT, &tfile);
if (!DEBUG(SCRIPT))
(void)eunlink(tfile);
JobSigUnlock(&mask);
@ -1901,7 +1894,7 @@ JobRun(GNode *targ)
#else
Compat_Make(targ, targ);
if (targ->made == ERROR) {
PrintOnError("\n\nStop.");
PrintOnError(targ, "\n\nStop.");
exit(1);
}
#endif
@ -2126,8 +2119,6 @@ void
Job_Init(void)
{
GNode *begin; /* node for commands to do at the very start */
const char *p;
size_t len;
/* Allocate space for all the job info */
job_table = bmake_malloc(maxJobs * sizeof *job_table);
@ -2140,18 +2131,6 @@ Job_Init(void)
lastNode = NULL;
/* set tmpdir, and ensure that it ends with "/" */
p = getenv("TMPDIR");
if (p == NULL || *p == '\0') {
p = _PATH_TMP;
}
len = strlen(p);
tmpdir = bmake_malloc(len + 2);
strcpy(tmpdir, p);
if (tmpdir[len - 1] != '/') {
strcat(tmpdir, "/");
}
if (maxJobs == 1) {
/*
* If only one job can run at a time, there's no need for a banner,
@ -2195,13 +2174,13 @@ Job_Init(void)
/*
* Install a SIGCHLD handler.
*/
(void)signal(SIGCHLD, JobChildSig);
(void)bmake_signal(SIGCHLD, JobChildSig);
sigaddset(&caught_signals, SIGCHLD);
#define ADDSIG(s,h) \
if (signal(s, SIG_IGN) != SIG_IGN) { \
if (bmake_signal(s, SIG_IGN) != SIG_IGN) { \
sigaddset(&caught_signals, s); \
(void)signal(s, h); \
(void)bmake_signal(s, h); \
}
/*
@ -2231,7 +2210,7 @@ Job_Init(void)
if (begin != NULL) {
JobRun(begin);
if (begin->made == ERROR) {
PrintOnError("\n\nStop.");
PrintOnError(begin, "\n\nStop.");
exit(1);
}
}
@ -2242,7 +2221,7 @@ static void JobSigReset(void)
{
#define DELSIG(s) \
if (sigismember(&caught_signals, s)) { \
(void)signal(s, SIG_DFL); \
(void)bmake_signal(s, SIG_DFL); \
}
DELSIG(SIGINT)
@ -2255,7 +2234,7 @@ static void JobSigReset(void)
DELSIG(SIGWINCH)
DELSIG(SIGCONT)
#undef DELSIG
(void)signal(SIGCHLD, SIG_DFL);
(void)bmake_signal(SIGCHLD, SIG_DFL);
}
/*-

View File

@ -1,4 +1,4 @@
/* $NetBSD: main.c,v 1.174 2009/09/09 17:09:49 sjg Exp $ */
/* $NetBSD: main.c,v 1.188 2010/06/03 15:40:16 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -69,7 +69,7 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: main.c,v 1.174 2009/09/09 17:09:49 sjg Exp $";
static char rcsid[] = "$NetBSD: main.c,v 1.188 2010/06/03 15:40:16 sjg 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.174 2009/09/09 17:09:49 sjg Exp $");
__RCSID("$NetBSD: main.c,v 1.188 2010/06/03 15:40:16 sjg Exp $");
#endif
#endif /* not lint */
#endif
@ -184,6 +184,8 @@ static Boolean ignorePWD; /* if we use -C, PWD is meaningless */
static char curdir[MAXPATHLEN + 1]; /* startup directory */
static char objdir[MAXPATHLEN + 1]; /* where we chdir'ed to */
char *progname; /* the program name */
char *makeDependfile;
pid_t myPid;
Boolean forceJobs = FALSE;
@ -384,6 +386,7 @@ rearg:
case 'B':
compatMake = TRUE;
Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL);
Var_Set(MAKE_MODE, "compat", VAR_GLOBAL, 0);
break;
case 'C':
if (chdir(argvalue) == -1) {
@ -393,6 +396,10 @@ rearg:
strerror(errno));
exit(1);
}
if (getcwd(curdir, MAXPATHLEN) == NULL) {
(void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno));
exit(2);
}
ignorePWD = TRUE;
break;
case 'D':
@ -495,6 +502,7 @@ rearg:
}
Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
Var_Set(".MAKE.JOBS", argvalue, VAR_GLOBAL, 0);
maxJobTokens = maxJobs;
break;
case 'k':
@ -509,7 +517,6 @@ rearg:
found_path, sizeof(found_path)))
break; /* nothing doing */
(void)Dir_AddDir(sysIncPath, found_path);
} else {
(void)Dir_AddDir(sysIncPath, argvalue);
}
@ -677,6 +684,22 @@ ReadAllMakefiles(const void *p, const void *q)
return (ReadMakefile(p, q) == 0);
}
static int
str2Lst_Append(Lst lp, char *str, const char *sep)
{
char *cp;
int n;
if (!sep)
sep = " \t";
for (n = 0, cp = strtok(str, sep); cp; cp = strtok(NULL, sep)) {
(void)Lst_AtEnd(lp, cp);
n++;
}
return (n);
}
#ifdef SIGINFO
/*ARGSUSED*/
static void
@ -693,6 +716,27 @@ siginfo(int signo)
}
#endif
/*
* Allow makefiles some control over the mode we run in.
*/
void
MakeMode(const char *mode)
{
char *mp = NULL;
if (!mode)
mode = mp = Var_Subst(NULL, "${" MAKE_MODE ":tl}", VAR_GLOBAL, 0);
if (mode && *mode) {
if (strstr(mode, "compat")) {
compatMake = TRUE;
forceJobs = FALSE;
}
}
if (mp)
free(mp);
}
/*-
* main --
* The main function, for obvious reasons. Initializes variables
@ -735,7 +779,7 @@ main(int argc, char **argv)
debug_file = stderr;
#ifdef SIGINFO
(void)signal(SIGINFO, siginfo);
(void)bmake_signal(SIGINFO, siginfo);
#endif
/*
* Set the seed to produce a different random sequence
@ -799,6 +843,8 @@ main(int argc, char **argv)
#endif
}
myPid = getpid(); /* remember this for vFork() */
/*
* Just in case MAKEOBJDIR wants us to do something tricky.
*/
@ -810,6 +856,15 @@ main(int argc, char **argv)
Var_Set("MAKE_VERSION", MAKE_VERSION, VAR_GLOBAL, 0);
#endif
Var_Set(".newline", "\n", VAR_GLOBAL, 0); /* handy for :@ loops */
/*
* This is the traditional preference for makefiles.
*/
#ifndef MAKEFILE_PREFERENCE_LIST
# define MAKEFILE_PREFERENCE_LIST "makefile Makefile"
#endif
Var_Set(MAKEFILE_PREFERENCE, MAKEFILE_PREFERENCE_LIST,
VAR_GLOBAL, 0);
Var_Set(MAKE_DEPENDFILE, ".depend", VAR_GLOBAL, 0);
create = Lst_Init(FALSE);
makefiles = Lst_Init(FALSE);
@ -845,8 +900,24 @@ main(int argc, char **argv)
* MFLAGS also gets initialized empty, for compatibility.
*/
Parse_Init();
Var_Set("MAKE", argv[0], VAR_GLOBAL, 0);
Var_Set(".MAKE", argv[0], VAR_GLOBAL, 0);
if (argv[0][0] == '/' || strchr(argv[0], '/') == NULL) {
/*
* Leave alone if it is an absolute path, or if it does
* not contain a '/' in which case we need to find it in
* the path, like execvp(3) and the shells do.
*/
p1 = argv[0];
} else {
/*
* A relative path, canonicalize it.
*/
p1 = realpath(argv[0], mdpath);
if (!p1 || *p1 != '/' || stat(p1, &sb) < 0) {
p1 = argv[0]; /* realpath failed */
}
}
Var_Set("MAKE", p1, VAR_GLOBAL, 0);
Var_Set(".MAKE", p1, VAR_GLOBAL, 0);
Var_Set(MAKEFLAGS, "", VAR_GLOBAL, 0);
Var_Set(MAKEOVERRIDES, "", VAR_GLOBAL, 0);
Var_Set("MFLAGS", "", VAR_GLOBAL, 0);
@ -863,7 +934,7 @@ main(int argc, char **argv)
ep = "0";
}
Var_Set(MAKE_LEVEL, ep, VAR_GLOBAL, 0);
snprintf(tmp, sizeof(tmp), "%u", getpid());
snprintf(tmp, sizeof(tmp), "%u", myPid);
Var_Set(".MAKE.PID", tmp, VAR_GLOBAL, 0);
snprintf(tmp, sizeof(tmp), "%u", getppid());
Var_Set(".MAKE.PPID", tmp, VAR_GLOBAL, 0);
@ -881,18 +952,20 @@ main(int argc, char **argv)
Main_ParseArgLine(getenv("MAKE"));
#endif
MainParseArgs(argc, argv);
/*
* Find where we are (now) and take care of PWD for the automounter...
* All this code is so that we know where we are when we start up
* on a different machine with pmake.
* Find where we are (now).
* We take care of PWD for the automounter below...
*/
if (getcwd(curdir, MAXPATHLEN) == NULL) {
(void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno));
exit(2);
}
MainParseArgs(argc, argv);
/*
* Verify that cwd is sane.
*/
if (stat(curdir, &sa) == -1) {
(void)fprintf(stderr, "%s: %s: %s.\n",
progname, curdir, strerror(errno));
@ -900,6 +973,8 @@ main(int argc, char **argv)
}
/*
* All this code is so that we know where we are when we start up
* on a different machine with pmake.
* Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX
* since the value of curdir can vary depending on how we got
* here. Ie sitting at a shell prompt (shell that provides $PWD)
@ -1044,16 +1119,27 @@ main(int argc, char **argv)
if (ln != NULL)
Fatal("%s: cannot open %s.", progname,
(char *)Lst_Datum(ln));
} else if (ReadMakefile("makefile", NULL) != 0)
(void)ReadMakefile("Makefile", NULL);
} else {
p1 = Var_Subst(NULL, "${" MAKEFILE_PREFERENCE "}",
VAR_CMD, 0);
if (p1) {
(void)str2Lst_Append(makefiles, p1, NULL);
(void)Lst_Find(makefiles, NULL, ReadMakefile);
free(p1);
}
}
/* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */
if (!noBuiltins || !printVars) {
doing_depend = TRUE;
(void)ReadMakefile(".depend", NULL);
doing_depend = FALSE;
makeDependfile = Var_Subst(NULL, "${.MAKE.DEPENDFILE:T}",
VAR_CMD, 0);
doing_depend = TRUE;
(void)ReadMakefile(makeDependfile, NULL);
doing_depend = FALSE;
}
MakeMode(NULL);
Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
if (p1)
free(p1);
@ -1212,14 +1298,11 @@ ReadMakefile(const void *p, const void *q __unused)
int fd;
size_t len = MAXPATHLEN;
char *name, *path = bmake_malloc(len);
int setMAKEFILE;
if (!strcmp(fname, "-")) {
Parse_File("(stdin)", dup(fileno(stdin)));
Var_Set("MAKEFILE", "", VAR_GLOBAL, 0);
} else {
setMAKEFILE = strcmp(fname, ".depend");
/* if we've chdir'd, rebuild the path name */
if (strcmp(curdir, objdir) && *fname != '/') {
size_t plen = strlen(curdir) + strlen(fname) + 2;
@ -1266,7 +1349,7 @@ ReadMakefile(const void *p, const void *q __unused)
* makefile specified, as it is set by SysV make.
*/
found:
if (setMAKEFILE)
if (!doing_depend)
Var_Set("MAKEFILE", fname, VAR_GLOBAL, 0);
Parse_File(fname, fd);
}
@ -1509,11 +1592,7 @@ Cmd_Exec(const char *cmd, const char **errnum)
/*
* Fork
*/
#if defined(__minix)
switch (cpid = fork()) {
#else
switch (cpid = vfork()) {
#endif
switch (cpid = vFork()) {
case 0:
/*
* Close input side of pipe
@ -1624,6 +1703,7 @@ Error(const char *fmt, ...)
err_file = debug_file;
if (err_file == stdout)
err_file = stderr;
(void)fflush(stdout);
for (;;) {
va_start(ap, fmt);
fprintf(err_file, "%s: ", progname);
@ -1658,12 +1738,13 @@ Fatal(const char *fmt, ...)
if (jobsRunning)
Job_Wait();
(void)fflush(stdout);
(void)vfprintf(stderr, fmt, ap);
va_end(ap);
(void)fprintf(stderr, "\n");
(void)fflush(stderr);
PrintOnError(NULL);
PrintOnError(NULL, NULL);
if (DEBUG(GRAPH2) || DEBUG(GRAPH3))
Targ_PrintGraph(2);
@ -1689,13 +1770,14 @@ Punt(const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
(void)fflush(stdout);
(void)fprintf(stderr, "%s: ", progname);
(void)vfprintf(stderr, fmt, ap);
va_end(ap);
(void)fprintf(stderr, "\n");
(void)fflush(stderr);
PrintOnError(NULL);
PrintOnError(NULL, NULL);
DieHorribly();
}
@ -1816,22 +1898,40 @@ PrintAddr(void *a, void *b)
void
PrintOnError(const char *s)
PrintOnError(GNode *gn, const char *s)
{
static GNode *en = NULL;
char tmp[64];
char *cp;
if (s)
printf("%s", s);
printf("%s", s);
printf("\n%s: stopped in %s\n", progname, curdir);
if (en)
return; /* we've been here! */
if (gn) {
/*
* We can print this even if there is no .ERROR target.
*/
Var_Set(".ERROR_TARGET", gn->name, VAR_GLOBAL, 0);
}
strncpy(tmp, "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
sizeof(tmp) - 1);
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
if (cp) {
if (*cp)
printf("%s", cp);
free(cp);
if (*cp)
printf("%s", cp);
free(cp);
}
/*
* Finally, see if there is a .ERROR target, and run it if so.
*/
en = Targ_FindNode(".ERROR", TARG_NOCREATE);
if (en) {
en->type |= OP_SPECIAL;
Compat_Make(en, en);
}
}
@ -1857,3 +1957,46 @@ Main_ExportMAKEFLAGS(Boolean first)
#endif
}
}
/*
* Create and open a temp file using "pattern".
* If "fnamep" is provided set it to a copy of the filename created.
* Otherwise unlink the file once open.
*/
int
mkTempFile(const char *pattern, char **fnamep)
{
static char *tmpdir = NULL;
char tfile[MAXPATHLEN];
int fd;
if (!pattern)
pattern = TMPPAT;
if (!tmpdir) {
struct stat st;
/*
* Honor $TMPDIR but only if it is valid.
* Ensure it ends with /.
*/
tmpdir = Var_Subst(NULL, "${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL, 0);
if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {
free(tmpdir);
tmpdir = bmake_strdup(_PATH_TMP);
}
}
if (pattern[0] == '/') {
snprintf(tfile, sizeof(tfile), "%s", pattern);
} else {
snprintf(tfile, sizeof(tfile), "%s%s", tmpdir, pattern);
}
if ((fd = mkstemp(tfile)) < 0)
Punt("Could not create temporary file %s: %s", tfile, strerror(errno));
if (fnamep) {
*fnamep = bmake_strdup(tfile);
} else {
unlink(tfile); /* we just want the descriptor */
}
return fd;
}

View File

@ -1,4 +1,4 @@
.\" $NetBSD: make.1,v 1.166 2009/11/19 06:48:37 wiz Exp $
.\" $NetBSD: make.1,v 1.176 2010/06/10 18:35:22 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 November 15, 2009
.Dd June 9, 2010
.Dt MAKE 1
.Os
.Sh NAME
@ -536,11 +536,48 @@ If the result of expanding a variable contains a dollar sign
.Pq Ql \&$
the string is expanded again.
.Pp
Variable substitution occurs at two distinct times, depending on where
Variable substitution occurs at three distinct times, depending on where
the variable is being used.
.Bl -enum
.It
Variables in dependency lines are expanded as the line is read.
.It
Variables in shell commands are expanded when the shell command is
executed.
.It
.Dq .for
loop index variables are expanded on each loop iteration.
Note that other variables are not expanded inside loops so
the following example code:
.Bd -literal -offset indent
.Dv .for i in 1 2 3
a+= ${i}
j= ${i}
b+= ${j}
.Dv .endfor
all:
@echo ${a}
@echo ${b}
.Ed
will print:
.Bd -literal -offset indent
1 2 3
3 3 3
.Ed
Because while ${a} contains
.Dq 1 2 3
after the loop is executed, ${b}
contains
.Dq ${j} ${j} ${j}
which expands to
.Dq 3 3 3
since after the loop completes ${j} contains
.Dq 3 .
.El
.Ss Variable classes
The four different classes of variables (in order of increasing precedence)
are:
@ -652,31 +689,17 @@ The preferred variable to use is the environment variable
because it is more compatible with other versions of
.Nm
and cannot be confused with the special target with the same name.
.It Va .MAKE.DEPENDFILE
Names the makefile (default
.Ql Pa .depend )
from which generated dependencies are read.
.It Va .MAKE.EXPORTED
The list of variables exported by
.Nm .
.It Va .MAKE.MAKEFILES
The list of makefiles read by
.Nm ,
which is useful for tracking dependencies.
Each makefile is recorded only once, regardless of the number of times read.
.It Va .MAKE.LEVEL
The recursion depth of
.Nm .
The initial instance of
.Nm
will be 0, and an incremented value is put into the environment
to be seen by the next generation.
This allows tests like:
.Li .if ${.MAKE.LEVEL} == 0
to protect things which should only be evaluated in the initial instance of
.Nm .
.It Va .MAKE.PID
The process-id of
.Nm .
.It Va .MAKE.PPID
The parent process-id of
.Nm .
.It Va .MAKE.JOBS
The argument to the
.Fl j
option.
.It Va .MAKE.JOB.PREFIX
If
.Nm
@ -707,6 +730,38 @@ variable which is then
entered into the environment for all programs which
.Nm
executes.
.It Va .MAKE.LEVEL
The recursion depth of
.Nm .
The initial instance of
.Nm
will be 0, and an incremented value is put into the environment
to be seen by the next generation.
This allows tests like:
.Li .if ${.MAKE.LEVEL} == 0
to protect things which should only be evaluated in the initial instance of
.Nm .
.It Va .MAKE.MAKEFILE_PREFERENCE
The ordered list of makefile names
(default
.Ql Pa makefile ,
.Ql Pa Makefile )
that
.Nm
will look for.
.It Va .MAKE.MAKEFILES
The list of makefiles read by
.Nm ,
which is useful for tracking dependencies.
Each makefile is recorded only once, regardless of the number of times read.
.It Va .MAKE.MODE
Processed after reading all makefiles.
Can affect the mode that
.Nm
runs in.
Currently just
.Ql Pa compat
mode.
.It Va .MAKEOVERRIDES
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
@ -721,6 +776,12 @@ by appending their names to
is re-exported whenever
.Ql Va .MAKEOVERRIDES
is modified.
.It Va .MAKE.PID
The process-id of
.Nm .
.It Va .MAKE.PPID
The parent process-id of
.Nm .
.It Va MAKE_PRINT_VAR_ON_ERROR
When
.Nm
@ -767,8 +828,10 @@ is set in the environment or on the command line.)
.Pp
Variable expansion is performed on the value before it's used,
so expressions such as
.Dl ${.CURDIR:C,^/usr/src,/var/obj,}
.Dl ${.CURDIR:S,^/usr/src,/var/obj,}
may be used.
This is especially useful with
.Ql Ev MAKEOBJDIR .
.Pp
.Ql Va .OBJDIR
may be modified in the makefile as a global variable.
@ -878,7 +941,7 @@ The standard shell wildcard characters
.Pf ( Ql * ,
.Ql \&? ,
and
.Ql Op )
.Ql Oo Oc )
may
be used.
The wildcard characters may be escaped with a backslash
@ -925,6 +988,10 @@ safely through recursive invocations of
.Nm .
.It Cm \&:R
Replaces each word in the variable with everything but its suffix.
.It Cm \&:tA
Attempt to convert variable to an absolute path using
.Xr realpath 3 ,
if that fails, the value is unchanged.
.It Cm \&:tl
Converts variable to lower-case letters.
.It Cm \&:ts Ns Ar c
@ -934,6 +1001,7 @@ This modifier sets the separator to the character
If
.Ar c
is omitted, then no separator is used.
The common escapes (including octal numeric codes), work as expected.
.It Cm \&:tu
Converts variable to upper-case letters.
.It Cm \&:tW
@ -1274,6 +1342,11 @@ Conditional expressions are also preceded by a single dot as the first
character of a line.
The possible conditionals are as follows:
.Bl -tag -width Ds
.It Ic .error Ar message
The message is printed along with the name of the makefile and line number,
then
.Nm
will exit.
.It Ic .export Ar variable ...
Export the specified global variable.
If no variable list is provided, all globals are exported
@ -1286,6 +1359,20 @@ flag, so should be used with caution.
Appending a variable name to
.Va .MAKE.EXPORTED
is equivalent to exporting a variable.
.It Ic .export-env Ar variable ...
The same as
.Ql .export ,
except that the variable is not appended to
.Va .MAKE.EXPORTED .
This allows exporting a value to the environment which is different from that
used by
.Nm
internally.
.It Ic .info Ar message
The message is printed along with the name of the makefile and line number.
.It Ic .undef Ar variable
Un-define the specified global variable.
Only global variables may be un-defined.
.It Ic .unexport Ar variable ...
The opposite of
.Ql .export .
@ -1322,9 +1409,10 @@ which is the minimal useful environment.
Actually
.Ql Ev .MAKE.LEVEL
will also be pushed into the new environment.
.It Ic .undef Ar variable
Un-define the specified global variable.
Only global variables may be un-defined.
.It Ic .warning Ar message
The message prefixed by
.Ql Pa warning:
is printed along with the name of the makefile and line number.
.It Ic \&.if Oo \&! Oc Ns Ar expression Op Ar operator expression ...
Test the value of an expression.
.It Ic .ifdef Oo \&! Oc Ns Ar variable Op Ar operator variable ...
@ -1627,6 +1715,13 @@ to the target's own name.
.It Ic .END
Any command lines attached to this target are executed after everything
else is done.
.It Ic .ERROR
Any command lines attached to this target are executed when another target fails.
The
.Ic .ERROR_TARGET
variable is set to the target that failed.
See also
.Ic MAKE_PRINT_VAR_ON_ERROR .
.It Ic .IGNORE
Mark each of the sources with the
.Ic .IGNORE
@ -1750,10 +1845,10 @@ character when used outside of any quoting characters.
.El
Example:
.Bd -literal
\&.SHELL: name=ksh path=/bin/ksh hasErrCtl=true \\
check="set -e" ignore="set +e" \\
echo="set -v" quiet="set +v" filter="set +v" \\
echoFlag=v errFlag=e newline="'\\n'"
\&.SHELL: name=ksh path=/bin/ksh hasErrCtl=true \e
check="set -e" ignore="set +e" \e
echo="set -v" quiet="set +v" filter="set +v" \e
echoFlag=v errFlag=e newline="'\en'"
.Ed
.It Ic .SILENT
Apply the

View File

@ -1,4 +1,4 @@
/* $NetBSD: make.c,v 1.78 2009/01/23 21:26:30 dsl Exp $ */
/* $NetBSD: make.c,v 1.79 2010/04/07 00:11:27 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: make.c,v 1.78 2009/01/23 21:26:30 dsl Exp $";
static char rcsid[] = "$NetBSD: make.c,v 1.79 2010/04/07 00:11:27 sjg 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.78 2009/01/23 21:26:30 dsl Exp $");
__RCSID("$NetBSD: make.c,v 1.79 2010/04/07 00:11:27 sjg Exp $");
#endif
#endif /* not lint */
#endif
@ -958,6 +958,9 @@ MakeAddAllSrc(void *cgnp, void *pgnp)
void
Make_DoAllVar(GNode *gn)
{
if (gn->flags & DONE_ALLSRC)
return;
Lst_ForEach(gn->children, MakeUnmark, gn);
Lst_ForEach(gn->children, MakeAddAllSrc, gn);
@ -974,6 +977,7 @@ Make_DoAllVar(GNode *gn)
if (p1)
free(p1);
}
gn->flags |= DONE_ALLSRC;
}
/*-

View File

@ -1,4 +1,4 @@
/* $NetBSD: make.h,v 1.79 2009/09/08 17:29:20 sjg Exp $ */
/* $NetBSD: make.h,v 1.82 2010/04/23 00:18:50 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -164,6 +164,7 @@ typedef struct GNode {
#define DONE_WAIT 0x8 /* Set by Make_ProcessWait() */
#define DONE_ORDER 0x10 /* Build requested by .ORDER processing */
#define FROM_DEPEND 0x20 /* Node created from .depend */
#define DONE_ALLSRC 0x40 /* We do it once only */
#define CYCLE 0x1000 /* Used by MakePrintStatus */
#define DONECYCLE 0x2000 /* Used by MakePrintStatus */
enum enum_made {
@ -392,6 +393,18 @@ extern Lst sysIncPath; /* The system include path. */
extern Lst defIncPath; /* The default include path. */
extern char *progname; /* The program name */
extern char *makeDependfile; /* .depend */
/*
* We cannot vfork() in a child of vfork().
* Most systems do not enforce this but some do.
*/
#if defined(__minix)
#define vFork() fork()
#else
#define vFork() ((getpid() == myPid) ? vfork() : fork())
#endif
extern pid_t myPid;
#define MAKEFLAGS ".MAKEFLAGS"
#define MAKEOVERRIDES ".MAKEOVERRIDES"
@ -399,6 +412,9 @@ extern char *progname; /* The program name */
#define MAKE_EXPORTED ".MAKE.EXPORTED" /* variables we export */
#define MAKE_MAKEFILES ".MAKE.MAKEFILES" /* all the makefiles we read */
#define MAKE_LEVEL ".MAKE.LEVEL" /* recursion level */
#define MAKEFILE_PREFERENCE ".MAKE.MAKEFILE_PREFERENCE"
#define MAKE_DEPENDFILE ".MAKE.DEPENDFILE" /* .depend */
#define MAKE_MODE ".MAKE.MODE"
/*
* debug control:
@ -442,9 +458,10 @@ void Make_DoAllVar(GNode *);
Boolean Make_Run(Lst);
char * Check_Cwd_Cmd(const char *);
void Check_Cwd(const char **);
void PrintOnError(const char *);
void PrintOnError(GNode *, const char *);
void Main_ExportMAKEFLAGS(Boolean);
Boolean Main_SetObjdir(const char *);
int mkTempFile(const char *, char **);
#ifdef __GNUC__
#define UNCONST(ptr) ({ \

View File

@ -1,4 +1,4 @@
/* $NetBSD: nonints.h,v 1.57 2009/11/19 00:30:24 sjg Exp $ */
/* $NetBSD: nonints.h,v 1.59 2010/06/03 15:40:16 sjg Exp $ */
/*-
* Copyright (c) 1988, 1989, 1990, 1993
@ -108,6 +108,7 @@ void For_Run(int);
/* main.c */
void Main_ParseArgLine(const char *);
void MakeMode(const char *);
int main(int, char **);
char *Cmd_Exec(const char *, const char **);
void Error(const char *, ...) __attribute__((__format__(__printf__, 1, 2)));
@ -194,3 +195,6 @@ void Var_Dump(GNode *);
void Var_ExportVars(void);
void Var_Export(char *, int);
void Var_UnExport(char *);
/* util.c */
void (*bmake_signal(int, void (*)(int)))(int);

View File

@ -1,4 +1,4 @@
/* $NetBSD: parse.c,v 1.160 2009/11/19 00:30:25 sjg Exp $ */
/* $NetBSD: parse.c,v 1.164 2010/05/24 21:04:49 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: parse.c,v 1.160 2009/11/19 00:30:25 sjg Exp $";
static char rcsid[] = "$NetBSD: parse.c,v 1.164 2010/05/24 21:04:49 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.160 2009/11/19 00:30:25 sjg Exp $");
__RCSID("$NetBSD: parse.c,v 1.164 2010/05/24 21:04:49 sjg Exp $");
#endif
#endif /* not lint */
#endif
@ -191,6 +191,7 @@ typedef enum {
Begin, /* .BEGIN */
Default, /* .DEFAULT */
End, /* .END */
dotError, /* .ERROR */
Ignore, /* .IGNORE */
Includes, /* .INCLUDES */
Interrupt, /* .INTERRUPT */
@ -245,6 +246,7 @@ static struct {
{ ".BEGIN", Begin, 0 },
{ ".DEFAULT", Default, 0 },
{ ".END", End, 0 },
{ ".ERROR", dotError, 0 },
{ ".EXEC", Attribute, OP_EXEC },
{ ".IGNORE", Ignore, OP_IGNORE },
{ ".INCLUDES", Includes, 0 },
@ -449,6 +451,7 @@ ParseErrorInternal(const char *cfname, size_t clineno, int type,
va_list ap;
va_start(ap, fmt);
(void)fflush(stdout);
ParseVErrorInternal(stderr, cfname, clineno, type, fmt, ap);
va_end(ap);
@ -487,6 +490,7 @@ Parse_Error(int type, const char *fmt, ...)
}
va_start(ap, fmt);
(void)fflush(stdout);
ParseVErrorInternal(stderr, fname, lineno, type, fmt, ap);
va_end(ap);
@ -497,6 +501,53 @@ Parse_Error(int type, const char *fmt, ...)
}
}
/*
* ParseMessage
* Parse a .info .warning or .error directive
*
* The input is the line minus the ".". We substitute
* variables, print the message and exit(1) (for .error) or just print
* a warning if the directive is malformed.
*/
static Boolean
ParseMessage(char *line)
{
int mtype;
switch(*line) {
case 'i':
mtype = 0;
break;
case 'w':
mtype = PARSE_WARNING;
break;
case 'e':
mtype = PARSE_FATAL;
break;
default:
Parse_Error(PARSE_WARNING, "invalid syntax: \".%s\"", line);
return FALSE;
}
while (isalpha((u_char)*line))
line++;
if (!isspace((u_char)*line))
return FALSE; /* not for us */
while (isspace((u_char)*line))
line++;
line = Var_Subst(NULL, line, VAR_CMD, 0);
Parse_Error(mtype, "%s", line);
free(line);
if (mtype == PARSE_FATAL) {
/* Terminate immediately. */
exit(1);
}
return TRUE;
}
/*-
*---------------------------------------------------------------------
* ParseLinkSrc --
@ -973,6 +1024,7 @@ ParseDoDependency(char *line)
* .NOPATH Don't search for file in the path
* .BEGIN
* .END
* .ERROR
* .INTERRUPT Are not to be considered the
* main target.
* .NOTPARALLEL Make only one target at a time.
@ -993,6 +1045,7 @@ ParseDoDependency(char *line)
break;
case Begin:
case End:
case dotError:
case Interrupt:
gn = Targ_FindNode(line, TARG_CREATE);
gn->type |= OP_NOTMAIN|OP_SPECIAL;
@ -1122,6 +1175,7 @@ ParseDoDependency(char *line)
case Default:
case Begin:
case End:
case dotError:
case Interrupt:
/*
* These four create nodes on which to hang commands, so
@ -2513,7 +2567,12 @@ Parse_File(const char *name, int fd)
} else if (strncmp(cp, "unexport", 8) == 0) {
Var_UnExport(cp);
continue;
}
} else if (strncmp(cp, "info", 4) == 0 ||
strncmp(cp, "error", 5) == 0 ||
strncmp(cp, "warning", 7) == 0) {
if (ParseMessage(cp))
continue;
}
}
if (*line == '\t') {
@ -2658,10 +2717,11 @@ Parse_File(const char *name, int fd)
} while (ParseEOF() == CONTINUE);
if (fatals) {
(void)fflush(stdout);
(void)fprintf(stderr,
"%s: Fatal errors encountered -- cannot continue\n",
progname);
PrintOnError(NULL);
PrintOnError(NULL, NULL);
exit(1);
}
}

View File

@ -1,15 +1,15 @@
/* $NetBSD: util.c,v 1.48 2009/01/29 09:03:04 dholland Exp $ */
/* $NetBSD: util.c,v 1.50 2010/06/03 15:40:16 sjg Exp $ */
/*
* Missing stuff from OS's
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: util.c,v 1.48 2009/01/29 09:03:04 dholland Exp $";
static char rcsid[] = "$NetBSD: util.c,v 1.50 2010/06/03 15:40:16 sjg Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: util.c,v 1.48 2009/01/29 09:03:04 dholland Exp $");
__RCSID("$NetBSD: util.c,v 1.50 2010/06/03 15:40:16 sjg Exp $");
#endif
#endif
@ -18,6 +18,7 @@ __RCSID("$NetBSD: util.c,v 1.48 2009/01/29 09:03:04 dholland Exp $");
#include <errno.h>
#include <stdio.h>
#include <time.h>
#include <signal.h>
#include "make.h"
@ -231,24 +232,6 @@ random(void)
}
#endif
/* turn into bsd signals */
void (*
signal(int s, void (*a)(int)))(int)
{
struct sigvec osv, sv;
(void)sigvector(s, NULL, &osv);
sv = osv;
sv.sv_handler = a;
#ifdef SV_BSDSIG
sv.sv_flags = SV_BSDSIG;
#endif
if (sigvector(s, &sv, NULL) == -1)
return (BADSIG);
return (osv.sv_handler);
}
#if !defined(__hpux__) && !defined(__hpux)
int
utimes(char *file, struct timeval tvp[2])
@ -370,12 +353,9 @@ getwd(char *pathname)
} /* end getwd */
#endif /* __hpux */
#if defined(sun) && defined(__svr4__)
#include <signal.h>
/* turn into bsd signals */
/* force posix signals */
void (*
signal(int s, void (*a)(int)))(int)
bmake_signal(int s, void (*a)(int)))(int)
{
struct sigaction sa, osa;
@ -388,7 +368,6 @@ signal(int s, void (*a)(int)))(int)
else
return osa.sa_handler;
}
#endif
#if !defined(MAKE_NATIVE) && !defined(HAVE_VSNPRINTF)
#include <stdarg.h>

View File

@ -1,4 +1,4 @@
/* $NetBSD: var.c,v 1.155 2009/11/19 00:30:25 sjg Exp $ */
/* $NetBSD: var.c,v 1.159 2010/06/06 01:13:12 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: var.c,v 1.155 2009/11/19 00:30:25 sjg Exp $";
static char rcsid[] = "$NetBSD: var.c,v 1.159 2010/06/06 01:13:12 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.155 2009/11/19 00:30:25 sjg Exp $");
__RCSID("$NetBSD: var.c,v 1.159 2010/06/06 01:13:12 sjg Exp $");
#endif
#endif /* not lint */
#endif
@ -123,6 +123,7 @@ __RCSID("$NetBSD: var.c,v 1.155 2009/11/19 00:30:25 sjg Exp $");
* XXX: There's a lot of duplication in these functions.
*/
#include <sys/stat.h>
#ifndef NO_REGEX
#include <sys/types.h>
#include <regex.h>
@ -590,6 +591,13 @@ Var_Export1(const char *name, int parent)
v->flags |= (VAR_EXPORTED|VAR_REEXPORT);
return 1;
}
if (v->flags & VAR_IN_USE) {
/*
* We recursed while exporting in a child.
* This isn't going to end well, just skip it.
*/
return 0;
}
n = snprintf(tmp, sizeof(tmp), "${%s}", name);
if (n < (int)sizeof(tmp)) {
val = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
@ -674,6 +682,7 @@ Var_Export(char *str, int isExport)
char *val;
char **av;
char *as;
int track;
int ac;
int i;
@ -682,6 +691,12 @@ Var_Export(char *str, int isExport)
return;
}
if (strncmp(str, "-env", 4) == 0) {
track = 0;
str += 4;
} else {
track = VAR_EXPORT_PARENT;
}
val = Var_Subst(NULL, str, VAR_GLOBAL, 0);
av = brk_string(val, &ac, FALSE, &as);
for (i = 0; i < ac; i++) {
@ -701,10 +716,10 @@ Var_Export(char *str, int isExport)
continue;
}
}
if (Var_Export1(name, VAR_EXPORT_PARENT)) {
if (Var_Export1(name, track)) {
if (VAR_EXPORTED_ALL != var_exportedVars)
var_exportedVars = VAR_EXPORTED_YES;
if (isExport) {
if (isExport && track) {
Var_Append(MAKE_EXPORTED, name, VAR_GLOBAL);
}
}
@ -1859,6 +1874,33 @@ VarSelectWords(GNode *ctx __unused, Var_Parse_State *vpstate,
return Buf_Destroy(&buf, FALSE);
}
/*-
* VarRealpath --
* Replace each word with the result of realpath()
* if successful.
*/
static Boolean
VarRealpath(GNode *ctx __unused, Var_Parse_State *vpstate,
char *word, Boolean addSpace, Buffer *buf,
void *patternp __unused)
{
struct stat st;
char rbuf[MAXPATHLEN];
char *rp;
if (addSpace && vpstate->varSpace) {
Buf_AddByte(buf, vpstate->varSpace);
}
addSpace = TRUE;
rp = realpath(word, rbuf);
if (rp && *rp == '/' && stat(rp, &st) == 0)
word = rp;
Buf_AddBytes(buf, strlen(word), word);
return(addSpace);
}
/*-
*-----------------------------------------------------------------------
* VarModify --
@ -2849,7 +2891,12 @@ ApplyModifiers(char *nstr, const char *tstr,
* Check for two-character options:
* ":tu", ":tl"
*/
if (tstr[1] == 'u' || tstr[1] == 'l') {
if (tstr[1] == 'A') { /* absolute path */
newStr = VarModify(ctxt, &parsestate, nstr,
VarRealpath, NULL);
cp = tstr + 2;
termc = *cp;
} else if (tstr[1] == 'u' || tstr[1] == 'l') {
newStr = VarChangeCase(nstr, (tstr[1] == 'u'));
cp = tstr + 2;
termc = *cp;