Import bmake-20210621
Lots more unit tests and code cleanup Relevant changes from ChangeLog o job.c: Print -de error information when running multiple jobs o var.c: only report error for unmatched regex subexpression when linting (-dL) since we cannot tell when an unmatched subexpression is an expected result. reduce memory allocations in the modifiers ':D' and ':U' reduce memory allocation and strlen calls in modifier ':from=to' in the ':Q' modifier, only allocate memory if necessary improve performance for LazyBuf reduce debug logging and memory allocation for ${:U...} reduce verbosity of the -dv debug logging for standard cases fix double varname expansion in the variable modifier '::=' o var.c: avoid evaluating many modifiers in parse only mode in strict mode (-dL) many variable references are parsed twice, the first time just to report parse errors early, so we want to avoid side effects and wasted effort to the extent possible.
This commit is contained in:
parent
8b6f73e37b
commit
ee914ef902
113
ChangeLog
113
ChangeLog
@ -1,3 +1,116 @@
|
||||
2021-06-21 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20210621
|
||||
Merge with NetBSD make, pick up
|
||||
o var.c: only report error for unmatched regex subexpression
|
||||
when linting (-dL) since we cannot tell when an unmatched
|
||||
subexpression is an expected result.
|
||||
o move unmatched regex subexpression tests to
|
||||
varmod-subst-regex.mk and enable strict (lint) mode
|
||||
|
||||
2021-06-16 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20210616
|
||||
Merge with NetBSD make, pick up
|
||||
o more unit tests
|
||||
o cond.c: rename If_Eval to EvalBare
|
||||
improve function names for parsing conditions
|
||||
o job.c: fix error handling of targets that cannot be made
|
||||
o var.c: uncompress code in ApplyModifier_Unique
|
||||
|
||||
2021-05-18 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20210518
|
||||
Merge with NetBSD make, pick up
|
||||
o fix unit-tests/opt-chdir to cope with /nonexistent existing.
|
||||
o job.c: Print -de error information when running multiple jobs
|
||||
|
||||
2021-04-20 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20210420
|
||||
Merge with NetBSD make, pick up
|
||||
o use C99 bool type
|
||||
o convert VarEvalFlags back into an enum
|
||||
o cond.c: do not complain when skipping the condition 'no >= 10'
|
||||
o hash.c: avoid allocating memory for simple variable names
|
||||
o job.c: use distinct wording for writing to the shell commands file
|
||||
remove type name for the abort status in job handling
|
||||
rename PrintOutput to PrintFilteredOutput to avoid confusion
|
||||
o main.c: avoid double slash in name of temporary directory
|
||||
o var.c: use straight quotes for error 'Bad conditional expression'
|
||||
reduce memory allocations in the modifiers ':D' and ':U'
|
||||
rename members of ModifyWord_LoopArgs
|
||||
clean up pattern flags for the modifiers ':S' and ':C'
|
||||
reduce memory allocation and strlen calls in modifier ':from=to'
|
||||
in the ':Q' modifier, only allocate memory if necessary
|
||||
improve performance for LazyBuf
|
||||
remove redundant parameter from ParseVarnameLong
|
||||
migrate ParseModifierPart to use Substring
|
||||
avoid unnecessary calls to strlen when evaluating modifiers
|
||||
migrate ModifyWord functions to use Substring
|
||||
migrate handling of the modifier ':S,from,to,' to Substring
|
||||
reduce debug logging and memory allocation for ${:U...}
|
||||
reduce verbosity of the -dv debug logging for standard cases
|
||||
clean up debug logging for ':M' and ':N'
|
||||
disallow '$' in the variable name of the modifier ':@'
|
||||
simplify access to the name of an expression during evaluation
|
||||
|
||||
2021-03-30 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20210330
|
||||
Merge with NetBSD make, pick up
|
||||
o replace enum bit-field with struct bit-field for VarEvalFlags
|
||||
o rename VARE_NONE to VARE_PARSE_ONLY
|
||||
o var.c: rename ApplyModifiersState to ModChain
|
||||
fix double varname expansion in the variable modifier '::='
|
||||
change debug log for variable evaluation flags to lowercase
|
||||
|
||||
2021-03-14 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20210314
|
||||
Merge with NetBSD make, pick up
|
||||
o var.c: avoid evaluating many modifiers in parse only mode
|
||||
in strict mode (-dL) many variable references are parsed twice,
|
||||
the first time just to report parse errors early, so we want to
|
||||
avoid side effects and wasted effort to the extent possible.
|
||||
|
||||
2021-02-26 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20210226
|
||||
Merge with NetBSD make, pick up
|
||||
o remove freestanding freeIt variables
|
||||
link via FStr
|
||||
o var.c: restructure code in ParseVarname to target human readers
|
||||
improve error message for;
|
||||
bad modifier in variable expression
|
||||
unclosed modifier
|
||||
unknown modifier
|
||||
remove redundant parameter of ApplySingleModifier
|
||||
explain non-obvious code around indirect variable modifiers
|
||||
quote ':S' in error message about missing delimiter
|
||||
extract ParseModifier_Match into separate function
|
||||
add context information to error message about ':range' modifier
|
||||
add quotes around variable name in an error message
|
||||
reorder code in ModifyWords
|
||||
use more common parameter order for VarSelectWords
|
||||
make ModifyWord_Subst a little easier to understand
|
||||
do not expand variable name from the command line twice
|
||||
extract ExistsInCmdline from Var_SetWithFlags
|
||||
save a hash map lookup when defining a cmdline variable
|
||||
clean up VarAdd, Var_Delete, Var_ReexportVars
|
||||
use bit-shift expressions for VarFlags constants
|
||||
rename constants for VarFlags
|
||||
rename ExprDefined constants for debug logging
|
||||
rename ExprStatus to ExprDefined
|
||||
split parameters for evaluating variable expressions
|
||||
reduce redundant code around ModifyWords
|
||||
print error about failed shell command before overwriting variable
|
||||
clean up ValidShortVarname, ParseVarnameShort
|
||||
rename VarExprStatus to ExprStatus
|
||||
add functions for assigning the value of an expression
|
||||
rename ApplyModifiersState_Define to Expr_Define
|
||||
condense the code for parsing :S and :C modifiers
|
||||
|
||||
2021-02-06 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20210206
|
||||
|
13
FILES
13
FILES
@ -63,6 +63,7 @@ realpath.c
|
||||
setenv.c
|
||||
sigcompat.c
|
||||
str.c
|
||||
str.h
|
||||
stresep.c
|
||||
strlcpy.c
|
||||
suff.c
|
||||
@ -399,6 +400,10 @@ unit-tests/job-flags.exp
|
||||
unit-tests/job-flags.mk
|
||||
unit-tests/job-output-long-lines.exp
|
||||
unit-tests/job-output-long-lines.mk
|
||||
unit-tests/job-output-null.exp
|
||||
unit-tests/job-output-null.mk
|
||||
unit-tests/jobs-empty-commands-error.exp
|
||||
unit-tests/jobs-empty-commands-error.mk
|
||||
unit-tests/jobs-empty-commands.exp
|
||||
unit-tests/jobs-empty-commands.mk
|
||||
unit-tests/jobs-error-indirect.exp
|
||||
@ -439,6 +444,8 @@ unit-tests/opt-debug-curdir.exp
|
||||
unit-tests/opt-debug-curdir.mk
|
||||
unit-tests/opt-debug-dir.exp
|
||||
unit-tests/opt-debug-dir.mk
|
||||
unit-tests/opt-debug-errors-jobs.exp
|
||||
unit-tests/opt-debug-errors-jobs.mk
|
||||
unit-tests/opt-debug-errors.exp
|
||||
unit-tests/opt-debug-errors.mk
|
||||
unit-tests/opt-debug-file.exp
|
||||
@ -627,6 +634,8 @@ unit-tests/var-class-local.exp
|
||||
unit-tests/var-class-local.mk
|
||||
unit-tests/var-class.exp
|
||||
unit-tests/var-class.mk
|
||||
unit-tests/var-eval-short.exp
|
||||
unit-tests/var-eval-short.mk
|
||||
unit-tests/var-op-append.exp
|
||||
unit-tests/var-op-append.mk
|
||||
unit-tests/var-op-assign.exp
|
||||
@ -675,6 +684,8 @@ unit-tests/varmod-l-name-to-value.exp
|
||||
unit-tests/varmod-l-name-to-value.mk
|
||||
unit-tests/varmod-localtime.exp
|
||||
unit-tests/varmod-localtime.mk
|
||||
unit-tests/varmod-loop-varname.exp
|
||||
unit-tests/varmod-loop-varname.mk
|
||||
unit-tests/varmod-loop.exp
|
||||
unit-tests/varmod-loop.mk
|
||||
unit-tests/varmod-match-escape.exp
|
||||
@ -709,6 +720,8 @@ unit-tests/varmod-subst-regex.exp
|
||||
unit-tests/varmod-subst-regex.mk
|
||||
unit-tests/varmod-subst.exp
|
||||
unit-tests/varmod-subst.mk
|
||||
unit-tests/varmod-sun-shell.exp
|
||||
unit-tests/varmod-sun-shell.mk
|
||||
unit-tests/varmod-sysv.exp
|
||||
unit-tests/varmod-sysv.mk
|
||||
unit-tests/varmod-tail.exp
|
||||
|
2
VERSION
2
VERSION
@ -1,2 +1,2 @@
|
||||
# keep this compatible with sh and make
|
||||
_MAKE_VERSION=20210206
|
||||
_MAKE_VERSION=20210621
|
||||
|
104
arch.c
104
arch.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: arch.c,v 1.197 2021/02/05 05:15:12 rillig Exp $ */
|
||||
/* $NetBSD: arch.c,v 1.200 2021/05/30 21:16:54 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -147,7 +147,7 @@ struct ar_hdr {
|
||||
#include "dir.h"
|
||||
|
||||
/* "@(#)arch.c 8.2 (Berkeley) 1/2/94" */
|
||||
MAKE_RCSID("$NetBSD: arch.c,v 1.197 2021/02/05 05:15:12 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: arch.c,v 1.200 2021/05/30 21:16:54 rillig Exp $");
|
||||
|
||||
typedef struct List ArchList;
|
||||
typedef struct ListNode ArchListNode;
|
||||
@ -216,6 +216,19 @@ ArchFree(void *ap)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return "archive(member)". */
|
||||
static char *
|
||||
FullName(const char *archive, const char *member)
|
||||
{
|
||||
size_t len1 = strlen(archive);
|
||||
size_t len3 = strlen(member);
|
||||
char *result = bmake_malloc(len1 + 1 + len3 + 1 + 1);
|
||||
memcpy(result, archive, len1);
|
||||
memcpy(result + len1, "(", 1);
|
||||
memcpy(result + len1 + 1, member, len3);
|
||||
memcpy(result + len1 + 1 + len3, ")", 1 + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse an archive specification such as "archive.a(member1 member2.${EXT})",
|
||||
@ -228,10 +241,10 @@ ArchFree(void *ap)
|
||||
* scope The scope in which to expand variables.
|
||||
*
|
||||
* Output:
|
||||
* return TRUE if it was a valid specification.
|
||||
* return True if it was a valid specification.
|
||||
* *pp Points to the first non-space after the archive spec.
|
||||
*/
|
||||
Boolean
|
||||
bool
|
||||
Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
|
||||
{
|
||||
char *cp; /* Pointer into line */
|
||||
@ -239,12 +252,12 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
|
||||
MFStr libName; /* Library-part of specification */
|
||||
char *memName; /* Member-part of specification */
|
||||
char saveChar; /* Ending delimiter of member-name */
|
||||
Boolean expandLibName; /* Whether the parsed libName contains
|
||||
bool expandLibName; /* Whether the parsed libName contains
|
||||
* variable expressions that need to be
|
||||
* expanded */
|
||||
|
||||
libName = MFStr_InitRefer(*pp);
|
||||
expandLibName = FALSE;
|
||||
expandLibName = false;
|
||||
|
||||
for (cp = libName.str; *cp != '(' && *cp != '\0';) {
|
||||
if (*cp == '$') {
|
||||
@ -252,18 +265,18 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
|
||||
/* XXX: This code can probably be shortened. */
|
||||
const char *nested_p = cp;
|
||||
FStr result;
|
||||
Boolean isError;
|
||||
bool isError;
|
||||
|
||||
/* XXX: is expanded twice: once here and once below */
|
||||
(void)Var_Parse(&nested_p, scope,
|
||||
VARE_WANTRES | VARE_UNDEFERR, &result);
|
||||
VARE_UNDEFERR, &result);
|
||||
/* TODO: handle errors */
|
||||
isError = result.str == var_Error;
|
||||
FStr_Done(&result);
|
||||
if (isError)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
expandLibName = TRUE;
|
||||
expandLibName = true;
|
||||
cp += nested_p - cp;
|
||||
} else
|
||||
cp++;
|
||||
@ -272,8 +285,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
|
||||
*cp++ = '\0';
|
||||
if (expandLibName) {
|
||||
char *expanded;
|
||||
(void)Var_Subst(libName.str, scope,
|
||||
VARE_WANTRES | VARE_UNDEFERR, &expanded);
|
||||
(void)Var_Subst(libName.str, scope, VARE_UNDEFERR, &expanded);
|
||||
/* TODO: handle errors */
|
||||
libName = MFStr_InitOwn(expanded);
|
||||
}
|
||||
@ -285,7 +297,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
|
||||
* place and skip to the end of it (either white-space or
|
||||
* a close paren).
|
||||
*/
|
||||
Boolean doSubst = FALSE;
|
||||
bool doSubst = false;
|
||||
|
||||
pp_skip_whitespace(&cp);
|
||||
|
||||
@ -295,20 +307,19 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
|
||||
/* Expand nested variable expressions. */
|
||||
/* XXX: This code can probably be shortened. */
|
||||
FStr result;
|
||||
Boolean isError;
|
||||
bool isError;
|
||||
const char *nested_p = cp;
|
||||
|
||||
(void)Var_Parse(&nested_p, scope,
|
||||
VARE_WANTRES | VARE_UNDEFERR,
|
||||
&result);
|
||||
VARE_UNDEFERR, &result);
|
||||
/* TODO: handle errors */
|
||||
isError = result.str == var_Error;
|
||||
FStr_Done(&result);
|
||||
|
||||
if (isError)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
doSubst = TRUE;
|
||||
doSubst = true;
|
||||
cp += nested_p - cp;
|
||||
} else {
|
||||
cp++;
|
||||
@ -325,7 +336,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
|
||||
Parse_Error(PARSE_FATAL,
|
||||
"No closing parenthesis "
|
||||
"in archive specification");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -355,16 +366,15 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
|
||||
char *p;
|
||||
char *unexpandedMemName = memName;
|
||||
|
||||
(void)Var_Subst(memName, scope,
|
||||
VARE_WANTRES | VARE_UNDEFERR,
|
||||
&memName);
|
||||
(void)Var_Subst(memName, scope, VARE_UNDEFERR,
|
||||
&memName);
|
||||
/* TODO: handle errors */
|
||||
|
||||
/*
|
||||
* Now form an archive spec and recurse to deal with
|
||||
* nested variables and multi-word variable values.
|
||||
*/
|
||||
fullName = str_concat4(libName.str, "(", memName, ")");
|
||||
fullName = FullName(libName.str, memName);
|
||||
p = fullName;
|
||||
|
||||
if (strchr(memName, '$') != NULL &&
|
||||
@ -383,7 +393,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
|
||||
/* Error in nested call. */
|
||||
free(fullName);
|
||||
/* XXX: does unexpandedMemName leak? */
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
free(fullName);
|
||||
/* XXX: does unexpandedMemName leak? */
|
||||
@ -394,8 +404,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
|
||||
|
||||
while (!Lst_IsEmpty(&members)) {
|
||||
char *member = Lst_Dequeue(&members);
|
||||
char *fullname = str_concat4(libName.str, "(",
|
||||
member, ")");
|
||||
char *fullname = FullName(libName.str, member);
|
||||
free(member);
|
||||
|
||||
gn = Targ_GetNode(fullname);
|
||||
@ -407,8 +416,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
|
||||
Lst_Done(&members);
|
||||
|
||||
} else {
|
||||
char *fullname = str_concat4(libName.str, "(", memName,
|
||||
")");
|
||||
char *fullname = FullName(libName.str, memName);
|
||||
gn = Targ_GetNode(fullname);
|
||||
free(fullname);
|
||||
|
||||
@ -434,7 +442,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
|
||||
/* We promised that pp would be set up at the next non-space. */
|
||||
pp_skip_whitespace(&cp);
|
||||
*pp = cp;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -444,7 +452,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
|
||||
* Input:
|
||||
* archive Path to the archive
|
||||
* member Name of member; only its basename is used.
|
||||
* addToCache TRUE if archive should be cached if not already so.
|
||||
* addToCache True if archive should be cached if not already so.
|
||||
*
|
||||
* Results:
|
||||
* The ar_hdr for the member, or NULL.
|
||||
@ -452,7 +460,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
|
||||
* See ArchFindMember for an almost identical copy of this code.
|
||||
*/
|
||||
static struct ar_hdr *
|
||||
ArchStatMember(const char *archive, const char *member, Boolean addToCache)
|
||||
ArchStatMember(const char *archive, const char *member, bool addToCache)
|
||||
{
|
||||
#define AR_MAX_NAME_LEN (sizeof arh.ar_name - 1)
|
||||
FILE *arch;
|
||||
@ -713,7 +721,7 @@ ArchSVR4Entry(Arch *ar, char *inout_name, size_t size, FILE *arch)
|
||||
#endif
|
||||
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
ArchiveMember_HasName(const struct ar_hdr *hdr,
|
||||
const char *name, size_t namelen)
|
||||
{
|
||||
@ -721,22 +729,22 @@ ArchiveMember_HasName(const struct ar_hdr *hdr,
|
||||
const char *ar_name = hdr->AR_NAME;
|
||||
|
||||
if (strncmp(ar_name, name, namelen) != 0)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
if (namelen >= ar_name_len)
|
||||
return namelen == ar_name_len;
|
||||
|
||||
/* hdr->AR_NAME is space-padded to the right. */
|
||||
if (ar_name[namelen] == ' ')
|
||||
return TRUE;
|
||||
return true;
|
||||
|
||||
/* In archives created by GNU binutils 2.27, the member names end with
|
||||
* a slash. */
|
||||
if (ar_name[namelen] == '/' &&
|
||||
(namelen == ar_name_len || ar_name[namelen + 1] == ' '))
|
||||
return TRUE;
|
||||
return true;
|
||||
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -951,7 +959,7 @@ Arch_UpdateMTime(GNode *gn)
|
||||
{
|
||||
struct ar_hdr *arh;
|
||||
|
||||
arh = ArchStatMember(GNode_VarArchive(gn), GNode_VarMember(gn), TRUE);
|
||||
arh = ArchStatMember(GNode_VarArchive(gn), GNode_VarMember(gn), true);
|
||||
if (arh != NULL)
|
||||
gn->mtime = (time_t)strtol(arh->ar_date, NULL, 10);
|
||||
else
|
||||
@ -1058,26 +1066,26 @@ Arch_FindLib(GNode *gn, SearchPath *path)
|
||||
* since this is used by 'ar' rules that affect the data contents of the
|
||||
* archive, not by ranlib rules, which affect the TOC.
|
||||
*/
|
||||
Boolean
|
||||
bool
|
||||
Arch_LibOODate(GNode *gn)
|
||||
{
|
||||
Boolean oodate;
|
||||
bool oodate;
|
||||
|
||||
if (gn->type & OP_PHONY) {
|
||||
oodate = TRUE;
|
||||
oodate = true;
|
||||
} else if (!GNode_IsTarget(gn) && Lst_IsEmpty(&gn->children)) {
|
||||
oodate = FALSE;
|
||||
oodate = false;
|
||||
} else if ((!Lst_IsEmpty(&gn->children) && gn->youngestChild == NULL) ||
|
||||
(gn->mtime > now) ||
|
||||
(gn->youngestChild != NULL &&
|
||||
gn->mtime < gn->youngestChild->mtime)) {
|
||||
oodate = TRUE;
|
||||
oodate = true;
|
||||
} else {
|
||||
#ifdef RANLIBMAG
|
||||
struct ar_hdr *arh; /* Header for __.SYMDEF */
|
||||
int modTimeTOC; /* The table-of-contents' mod time */
|
||||
|
||||
arh = ArchStatMember(gn->path, RANLIBMAG, FALSE);
|
||||
arh = ArchStatMember(gn->path, RANLIBMAG, false);
|
||||
|
||||
if (arh != NULL) {
|
||||
modTimeTOC = (int)strtol(arh->ar_date, NULL, 10);
|
||||
@ -1094,10 +1102,10 @@ Arch_LibOODate(GNode *gn)
|
||||
*/
|
||||
if (DEBUG(ARCH) || DEBUG(MAKE))
|
||||
debug_printf("no toc...");
|
||||
oodate = TRUE;
|
||||
oodate = true;
|
||||
}
|
||||
#else
|
||||
oodate = FALSE;
|
||||
oodate = false;
|
||||
#endif
|
||||
}
|
||||
return oodate;
|
||||
@ -1119,7 +1127,7 @@ Arch_End(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
Boolean
|
||||
bool
|
||||
Arch_IsLib(GNode *gn)
|
||||
{
|
||||
static const char armag[] = "!<arch>\n";
|
||||
@ -1127,11 +1135,11 @@ Arch_IsLib(GNode *gn)
|
||||
int fd;
|
||||
|
||||
if ((fd = open(gn->path, O_RDONLY)) == -1)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
if (read(fd, buf, sizeof buf) != sizeof buf) {
|
||||
(void)close(fd);
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
(void)close(fd);
|
||||
|
4
buf.h
4
buf.h
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: buf.h,v 1.42 2021/01/30 21:25:10 rillig Exp $ */
|
||||
/* $NetBSD: buf.h,v 1.43 2021/04/03 11:08:40 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||
@ -101,7 +101,7 @@ Buf_AddByte(Buffer *buf, char byte)
|
||||
end[1] = '\0';
|
||||
}
|
||||
|
||||
MAKE_INLINE Boolean
|
||||
MAKE_INLINE bool
|
||||
Buf_EndsWith(const Buffer *buf, char ch)
|
||||
{
|
||||
return buf->len > 0 && buf->data[buf->len - 1] == ch;
|
||||
|
42
compat.c
42
compat.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: compat.c,v 1.224 2021/02/05 05:15:12 rillig Exp $ */
|
||||
/* $NetBSD: compat.c,v 1.227 2021/04/27 15:19:25 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||
@ -99,7 +99,7 @@
|
||||
#include "pathnames.h"
|
||||
|
||||
/* "@(#)compat.c 8.2 (Berkeley) 3/19/94" */
|
||||
MAKE_RCSID("$NetBSD: compat.c,v 1.224 2021/02/05 05:15:12 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: compat.c,v 1.227 2021/04/27 15:19:25 christos Exp $");
|
||||
|
||||
static GNode *curTarg = NULL;
|
||||
static pid_t compatChild;
|
||||
@ -164,7 +164,7 @@ CompatInterrupt(int signo)
|
||||
}
|
||||
|
||||
static void
|
||||
DebugFailedTarget(const char *cmd, GNode *gn)
|
||||
DebugFailedTarget(const char *cmd, const GNode *gn)
|
||||
{
|
||||
const char *p = cmd;
|
||||
debug_printf("\n*** Failed target: %s\n*** Failed command: ",
|
||||
@ -184,7 +184,7 @@ DebugFailedTarget(const char *cmd, GNode *gn)
|
||||
debug_printf("\n");
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
UseShell(const char *cmd MAKE_ATTR_UNUSED)
|
||||
{
|
||||
#if !defined(MAKE_NATIVE)
|
||||
@ -194,7 +194,7 @@ UseShell(const char *cmd MAKE_ATTR_UNUSED)
|
||||
* behaviour. Or perhaps the shell has been replaced with something
|
||||
* that does extra logging, and that should not be bypassed.
|
||||
*/
|
||||
return TRUE;
|
||||
return true;
|
||||
#else
|
||||
/*
|
||||
* Search for meta characters in the command. If there are no meta
|
||||
@ -227,22 +227,22 @@ Compat_RunCommand(const char *cmdp, GNode *gn, StringListNode *ln)
|
||||
{
|
||||
char *cmdStart; /* Start of expanded command */
|
||||
char *bp;
|
||||
Boolean silent; /* Don't print command */
|
||||
Boolean doIt; /* Execute even if -n */
|
||||
volatile Boolean errCheck; /* Check errors */
|
||||
bool silent; /* Don't print command */
|
||||
bool doIt; /* Execute even if -n */
|
||||
volatile bool errCheck; /* Check errors */
|
||||
WAIT_T reason; /* Reason for child's death */
|
||||
WAIT_T status; /* Description of child's death */
|
||||
pid_t cpid; /* Child actually found */
|
||||
pid_t retstat; /* Result of wait */
|
||||
const char **volatile av; /* Argument vector for thing to exec */
|
||||
char **volatile mav; /* Copy of the argument vector for freeing */
|
||||
Boolean useShell; /* TRUE if command should be executed
|
||||
bool useShell; /* True if command should be executed
|
||||
* using a shell */
|
||||
const char *volatile cmd = cmdp;
|
||||
|
||||
silent = (gn->type & OP_SILENT) != 0;
|
||||
errCheck = !(gn->type & OP_IGNORE);
|
||||
doIt = FALSE;
|
||||
doIt = false;
|
||||
|
||||
(void)Var_Subst(cmd, gn, VARE_WANTRES, &cmdStart);
|
||||
/* TODO: handle errors */
|
||||
@ -281,9 +281,9 @@ Compat_RunCommand(const char *cmdp, GNode *gn, StringListNode *ln)
|
||||
if (*cmd == '@')
|
||||
silent = !DEBUG(LOUD);
|
||||
else if (*cmd == '-')
|
||||
errCheck = FALSE;
|
||||
errCheck = false;
|
||||
else if (*cmd == '+') {
|
||||
doIt = TRUE;
|
||||
doIt = true;
|
||||
if (shellName == NULL) /* we came here from jobs */
|
||||
Shell_Init();
|
||||
} else
|
||||
@ -343,7 +343,7 @@ Compat_RunCommand(const char *cmdp, GNode *gn, StringListNode *ln)
|
||||
* command into words to form an argument vector we can
|
||||
* execute.
|
||||
*/
|
||||
Words words = Str_Words(cmd, FALSE);
|
||||
Words words = Str_Words(cmd, false);
|
||||
mav = words.words;
|
||||
bp = words.freeIt;
|
||||
av = (void *)mav;
|
||||
@ -392,7 +392,7 @@ Compat_RunCommand(const char *cmdp, GNode *gn, StringListNode *ln)
|
||||
*/
|
||||
while ((retstat = wait(&reason)) != cpid) {
|
||||
if (retstat > 0)
|
||||
JobReapChild(retstat, reason, FALSE); /* not ours? */
|
||||
JobReapChild(retstat, reason, false); /* not ours? */
|
||||
if (retstat == -1 && errno != EINTR) {
|
||||
break;
|
||||
}
|
||||
@ -425,7 +425,7 @@ Compat_RunCommand(const char *cmdp, GNode *gn, StringListNode *ln)
|
||||
if (errCheck) {
|
||||
#ifdef USE_META
|
||||
if (useMeta) {
|
||||
meta_job_error(NULL, gn, FALSE, status);
|
||||
meta_job_error(NULL, gn, false, status);
|
||||
}
|
||||
#endif
|
||||
gn->made = ERROR;
|
||||
@ -483,7 +483,7 @@ MakeNodes(GNodeList *gnodes, GNode *pgn)
|
||||
}
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
MakeUnmade(GNode *gn, GNode *pgn)
|
||||
{
|
||||
|
||||
@ -493,7 +493,7 @@ MakeUnmade(GNode *gn, GNode *pgn)
|
||||
* First mark ourselves to be made, then apply whatever transformations
|
||||
* the suffix module thinks are necessary. Once that's done, we can
|
||||
* descend and make all our children. If any of them has an error
|
||||
* but the -k flag was given, our 'make' field will be set to FALSE
|
||||
* but the -k flag was given, our 'make' field will be set to false
|
||||
* again. This is our signal to not attempt to do anything but abort
|
||||
* our parent as well.
|
||||
*/
|
||||
@ -508,7 +508,7 @@ MakeUnmade(GNode *gn, GNode *pgn)
|
||||
if (!(gn->flags & REMAKE)) {
|
||||
gn->made = ABORTED;
|
||||
pgn->flags &= ~(unsigned)REMAKE;
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Lst_FindDatum(&gn->implicitParents, pgn) != NULL)
|
||||
@ -524,7 +524,7 @@ MakeUnmade(GNode *gn, GNode *pgn)
|
||||
if (!GNode_IsOODate(gn)) {
|
||||
gn->made = UPTODATE;
|
||||
DEBUG0(MAKE, "up-to-date.\n");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -539,7 +539,7 @@ MakeUnmade(GNode *gn, GNode *pgn)
|
||||
* We need to be re-made.
|
||||
* Ensure that $? (.OODATE) and $> (.ALLSRC) are both set.
|
||||
*/
|
||||
Make_DoAllVar(gn);
|
||||
GNode_SetLocalVars(gn);
|
||||
|
||||
/*
|
||||
* Alter our type to tell if errors should be ignored or things
|
||||
@ -596,7 +596,7 @@ MakeUnmade(GNode *gn, GNode *pgn)
|
||||
PrintOnError(gn, "\nStop.");
|
||||
exit(1);
|
||||
}
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
|
279
cond.c
279
cond.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cond.c,v 1.256 2021/02/05 05:15:12 rillig Exp $ */
|
||||
/* $NetBSD: cond.c,v 1.267 2021/06/11 14:52:03 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||
@ -95,7 +95,7 @@
|
||||
#include "dir.h"
|
||||
|
||||
/* "@(#)cond.c 8.2 (Berkeley) 1/2/94" */
|
||||
MAKE_RCSID("$NetBSD: cond.c,v 1.256 2021/02/05 05:15:12 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: cond.c,v 1.267 2021/06/11 14:52:03 rillig Exp $");
|
||||
|
||||
/*
|
||||
* The parsing of conditional expressions is based on this grammar:
|
||||
@ -148,11 +148,11 @@ typedef struct CondParser {
|
||||
* expression has length > 0. The other '.if' variants delegate
|
||||
* to evalBare instead.
|
||||
*/
|
||||
Boolean plain;
|
||||
bool plain;
|
||||
|
||||
/* The function to apply on unquoted bare words. */
|
||||
Boolean (*evalBare)(size_t, const char *);
|
||||
Boolean negateEvalBare;
|
||||
bool (*evalBare)(size_t, const char *);
|
||||
bool negateEvalBare;
|
||||
|
||||
const char *p; /* The remaining condition to parse */
|
||||
Token curr; /* Single push-back token used in parsing */
|
||||
@ -163,10 +163,10 @@ typedef struct CondParser {
|
||||
* specific one, therefore it makes sense to suppress the standard
|
||||
* "Malformed conditional" message.
|
||||
*/
|
||||
Boolean printedError;
|
||||
bool printedError;
|
||||
} CondParser;
|
||||
|
||||
static CondResult CondParser_Or(CondParser *par, Boolean);
|
||||
static CondResult CondParser_Or(CondParser *par, bool);
|
||||
|
||||
static unsigned int cond_depth = 0; /* current .if nesting level */
|
||||
static unsigned int cond_min_depth = 0; /* depth at makefile open */
|
||||
@ -178,21 +178,21 @@ static const char *opname[] = { "<", "<=", ">", ">=", "==", "!=" };
|
||||
* In strict mode, the lhs must be a variable expression or a string literal
|
||||
* in quotes. In non-strict mode it may also be an unquoted string literal.
|
||||
*
|
||||
* TRUE when CondEvalExpression is called from Cond_EvalLine (.if etc)
|
||||
* FALSE when CondEvalExpression is called from ApplyModifier_IfElse
|
||||
* True when CondEvalExpression is called from Cond_EvalLine (.if etc).
|
||||
* False when CondEvalExpression is called from ApplyModifier_IfElse
|
||||
* since lhs is already expanded, and at that point we cannot tell if
|
||||
* it was a variable reference or not.
|
||||
*/
|
||||
static Boolean lhsStrict;
|
||||
static bool lhsStrict;
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
is_token(const char *str, const char *tok, size_t len)
|
||||
{
|
||||
return strncmp(str, tok, len) == 0 && !ch_isalpha(str[len]);
|
||||
}
|
||||
|
||||
static Token
|
||||
ToToken(Boolean cond)
|
||||
ToToken(bool cond)
|
||||
{
|
||||
return cond ? TOK_TRUE : TOK_FALSE;
|
||||
}
|
||||
@ -228,7 +228,7 @@ CondParser_SkipWhitespace(CondParser *par)
|
||||
* Return the length of the argument, or 0 on error.
|
||||
*/
|
||||
static size_t
|
||||
ParseFuncArg(CondParser *par, const char **pp, Boolean doEval, const char *func,
|
||||
ParseFuncArg(CondParser *par, const char **pp, bool doEval, const char *func,
|
||||
char **out_arg)
|
||||
{
|
||||
const char *p = *pp;
|
||||
@ -264,11 +264,11 @@ ParseFuncArg(CondParser *par, const char **pp, Boolean doEval, const char *func,
|
||||
* so we don't need to do it. Nor do we return an
|
||||
* error, though perhaps we should.
|
||||
*/
|
||||
VarEvalFlags eflags = doEval
|
||||
? VARE_WANTRES | VARE_UNDEFERR
|
||||
: VARE_NONE;
|
||||
VarEvalMode emode = doEval
|
||||
? VARE_UNDEFERR
|
||||
: VARE_PARSE_ONLY;
|
||||
FStr nestedVal;
|
||||
(void)Var_Parse(&p, SCOPE_CMDLINE, eflags, &nestedVal);
|
||||
(void)Var_Parse(&p, SCOPE_CMDLINE, emode, &nestedVal);
|
||||
/* TODO: handle errors */
|
||||
Buf_AddStr(&argBuf, nestedVal.str);
|
||||
FStr_Done(&nestedVal);
|
||||
@ -290,7 +290,7 @@ ParseFuncArg(CondParser *par, const char **pp, Boolean doEval, const char *func,
|
||||
if (func != NULL && *p++ != ')') {
|
||||
Parse_Error(PARSE_FATAL,
|
||||
"Missing closing parenthesis for %s()", func);
|
||||
par->printedError = TRUE;
|
||||
par->printedError = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -300,34 +300,34 @@ ParseFuncArg(CondParser *par, const char **pp, Boolean doEval, const char *func,
|
||||
|
||||
/* Test whether the given variable is defined. */
|
||||
/*ARGSUSED*/
|
||||
static Boolean
|
||||
static bool
|
||||
FuncDefined(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
|
||||
{
|
||||
FStr value = Var_Value(SCOPE_CMDLINE, arg);
|
||||
Boolean result = value.str != NULL;
|
||||
bool result = value.str != NULL;
|
||||
FStr_Done(&value);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* See if the given target is being made. */
|
||||
/*ARGSUSED*/
|
||||
static Boolean
|
||||
static bool
|
||||
FuncMake(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
|
||||
{
|
||||
StringListNode *ln;
|
||||
|
||||
for (ln = opts.create.first; ln != NULL; ln = ln->next)
|
||||
if (Str_Match(ln->datum, arg))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* See if the given file exists. */
|
||||
/*ARGSUSED*/
|
||||
static Boolean
|
||||
static bool
|
||||
FuncExists(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
|
||||
{
|
||||
Boolean result;
|
||||
bool result;
|
||||
char *path;
|
||||
|
||||
path = Dir_FindFile(arg, &dirSearchPath);
|
||||
@ -340,7 +340,7 @@ FuncExists(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
|
||||
|
||||
/* See if the given node exists and is an actual target. */
|
||||
/*ARGSUSED*/
|
||||
static Boolean
|
||||
static bool
|
||||
FuncTarget(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
|
||||
{
|
||||
GNode *gn = Targ_FindNode(arg);
|
||||
@ -352,7 +352,7 @@ FuncTarget(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
|
||||
* associated with it.
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
static Boolean
|
||||
static bool
|
||||
FuncCommands(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
|
||||
{
|
||||
GNode *gn = Targ_FindNode(arg);
|
||||
@ -365,10 +365,10 @@ FuncCommands(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
|
||||
* then we try a floating point conversion instead.
|
||||
*
|
||||
* Results:
|
||||
* Returns TRUE if the conversion succeeded.
|
||||
* Returns true if the conversion succeeded.
|
||||
* Sets 'out_value' to the converted number.
|
||||
*/
|
||||
static Boolean
|
||||
static bool
|
||||
TryParseNumber(const char *str, double *out_value)
|
||||
{
|
||||
char *end;
|
||||
@ -378,29 +378,30 @@ TryParseNumber(const char *str, double *out_value)
|
||||
errno = 0;
|
||||
if (str[0] == '\0') { /* XXX: why is an empty string a number? */
|
||||
*out_value = 0.0;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
ul_val = strtoul(str, &end, str[1] == 'x' ? 16 : 10);
|
||||
if (*end == '\0' && errno != ERANGE) {
|
||||
*out_value = str[0] == '-' ? -(double)-ul_val : (double)ul_val;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (*end != '\0' && *end != '.' && *end != 'e' && *end != 'E')
|
||||
return FALSE; /* skip the expensive strtod call */
|
||||
return false; /* skip the expensive strtod call */
|
||||
dbl_val = strtod(str, &end);
|
||||
if (*end != '\0')
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
*out_value = dbl_val;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
is_separator(char ch)
|
||||
{
|
||||
return ch == '\0' || ch_isspace(ch) || strchr("!=><)", ch) != NULL;
|
||||
return ch == '\0' || ch_isspace(ch) || ch == '!' || ch == '=' ||
|
||||
ch == '>' || ch == '<' || ch == ')' /* but not '(' */;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -409,24 +410,24 @@ is_separator(char ch)
|
||||
*
|
||||
* Example: .if x${CENTER}y == "${PREFIX}${SUFFIX}" || 0x${HEX}
|
||||
*/
|
||||
static Boolean
|
||||
static bool
|
||||
CondParser_StringExpr(CondParser *par, const char *start,
|
||||
Boolean const doEval, Boolean const quoted,
|
||||
bool const doEval, bool const quoted,
|
||||
Buffer *buf, FStr *const inout_str)
|
||||
{
|
||||
VarEvalFlags eflags;
|
||||
VarEvalMode emode;
|
||||
const char *nested_p;
|
||||
Boolean atStart;
|
||||
bool atStart;
|
||||
VarParseResult parseResult;
|
||||
|
||||
/* if we are in quotes, an undefined variable is ok */
|
||||
eflags = doEval && !quoted ? VARE_WANTRES | VARE_UNDEFERR
|
||||
emode = doEval && !quoted ? VARE_UNDEFERR
|
||||
: doEval ? VARE_WANTRES
|
||||
: VARE_NONE;
|
||||
: VARE_PARSE_ONLY;
|
||||
|
||||
nested_p = par->p;
|
||||
atStart = nested_p == start;
|
||||
parseResult = Var_Parse(&nested_p, SCOPE_CMDLINE, eflags, inout_str);
|
||||
parseResult = Var_Parse(&nested_p, SCOPE_CMDLINE, emode, inout_str);
|
||||
/* TODO: handle errors */
|
||||
if (inout_str->str == var_Error) {
|
||||
if (parseResult == VPR_ERR) {
|
||||
@ -436,11 +437,11 @@ CondParser_StringExpr(CondParser *par, const char *start,
|
||||
*
|
||||
* See cond-token-plain.mk $$$$$$$$.
|
||||
*/
|
||||
par->printedError = TRUE;
|
||||
par->printedError = true;
|
||||
}
|
||||
/*
|
||||
* XXX: Can there be any situation in which a returned
|
||||
* var_Error requires freeIt?
|
||||
* var_Error needs to be freed?
|
||||
*/
|
||||
FStr_Done(inout_str);
|
||||
/*
|
||||
@ -448,7 +449,7 @@ CondParser_StringExpr(CondParser *par, const char *start,
|
||||
* what getting var_Error back with !doEval means.
|
||||
*/
|
||||
*inout_str = FStr_InitRefer(NULL);
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
par->p = nested_p;
|
||||
|
||||
@ -458,30 +459,30 @@ CondParser_StringExpr(CondParser *par, const char *start,
|
||||
* comparison operator or is the end of the expression, we are done.
|
||||
*/
|
||||
if (atStart && is_separator(par->p[0]))
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
Buf_AddStr(buf, inout_str->str);
|
||||
FStr_Done(inout_str);
|
||||
*inout_str = FStr_InitRefer(NULL); /* not finished yet */
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a string from a variable reference or an optionally quoted
|
||||
* string. This is called for the lhs and rhs of string comparisons.
|
||||
* Parse a string from a variable expression or an optionally quoted
|
||||
* string. This is called for the left-hand and right-hand sides of
|
||||
* comparisons.
|
||||
*
|
||||
* Results:
|
||||
* Returns the string, absent any quotes, or NULL on error.
|
||||
* Sets out_quoted if the string was quoted.
|
||||
* Sets out_freeIt.
|
||||
* Sets out_quoted if the leaf was a quoted string literal.
|
||||
*/
|
||||
static void
|
||||
CondParser_String(CondParser *par, Boolean doEval, Boolean strictLHS,
|
||||
FStr *out_str, Boolean *out_quoted)
|
||||
CondParser_Leaf(CondParser *par, bool doEval, bool strictLHS,
|
||||
FStr *out_str, bool *out_quoted)
|
||||
{
|
||||
Buffer buf;
|
||||
FStr str;
|
||||
Boolean quoted;
|
||||
bool quoted;
|
||||
const char *start;
|
||||
|
||||
Buf_Init(&buf);
|
||||
@ -541,14 +542,14 @@ CondParser_String(CondParser *par, Boolean doEval, Boolean strictLHS,
|
||||
got_str:
|
||||
str = FStr_InitOwn(buf.data);
|
||||
cleanup:
|
||||
Buf_DoneData(&buf);
|
||||
Buf_DoneData(&buf); /* XXX: memory leak on failure? */
|
||||
*out_str = str;
|
||||
}
|
||||
|
||||
static Boolean
|
||||
If_Eval(const CondParser *par, const char *arg, size_t arglen)
|
||||
static bool
|
||||
EvalBare(const CondParser *par, const char *arg, size_t arglen)
|
||||
{
|
||||
Boolean res = par->evalBare(arglen, arg);
|
||||
bool res = par->evalBare(arglen, arg);
|
||||
return par->negateEvalBare ? !res : res;
|
||||
}
|
||||
|
||||
@ -556,8 +557,8 @@ If_Eval(const CondParser *par, const char *arg, size_t arglen)
|
||||
* Evaluate a "comparison without operator", such as in ".if ${VAR}" or
|
||||
* ".if 0".
|
||||
*/
|
||||
static Boolean
|
||||
EvalNotEmpty(CondParser *par, const char *value, Boolean quoted)
|
||||
static bool
|
||||
EvalNotEmpty(CondParser *par, const char *value, bool quoted)
|
||||
{
|
||||
double num;
|
||||
|
||||
@ -576,11 +577,11 @@ EvalNotEmpty(CondParser *par, const char *value, Boolean quoted)
|
||||
if (par->plain)
|
||||
return value[0] != '\0';
|
||||
|
||||
return If_Eval(par, value, strlen(value));
|
||||
return EvalBare(par, value, strlen(value));
|
||||
}
|
||||
|
||||
/* Evaluate a numerical comparison, such as in ".if ${VAR} >= 9". */
|
||||
static Boolean
|
||||
static bool
|
||||
EvalCompareNum(double lhs, ComparisonOp op, double rhs)
|
||||
{
|
||||
DEBUG3(COND, "lhs = %f, rhs = %f, op = %.2s\n", lhs, rhs, opname[op]);
|
||||
@ -608,7 +609,7 @@ EvalCompareStr(CondParser *par, const char *lhs,
|
||||
if (op != EQ && op != NE) {
|
||||
Parse_Error(PARSE_FATAL,
|
||||
"String comparison operator must be either == or !=");
|
||||
par->printedError = TRUE;
|
||||
par->printedError = true;
|
||||
return TOK_ERROR;
|
||||
}
|
||||
|
||||
@ -619,8 +620,8 @@ EvalCompareStr(CondParser *par, const char *lhs,
|
||||
|
||||
/* Evaluate a comparison, such as "${VAR} == 12345". */
|
||||
static Token
|
||||
EvalCompare(CondParser *par, const char *lhs, Boolean lhsQuoted,
|
||||
ComparisonOp op, const char *rhs, Boolean rhsQuoted)
|
||||
EvalCompare(CondParser *par, const char *lhs, bool lhsQuoted,
|
||||
ComparisonOp op, const char *rhs, bool rhsQuoted)
|
||||
{
|
||||
double left, right;
|
||||
|
||||
@ -631,7 +632,7 @@ EvalCompare(CondParser *par, const char *lhs, Boolean lhsQuoted,
|
||||
return EvalCompareStr(par, lhs, op, rhs);
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
CondParser_ComparisonOp(CondParser *par, ComparisonOp *out_op)
|
||||
{
|
||||
const char *p = par->p;
|
||||
@ -655,14 +656,14 @@ CondParser_ComparisonOp(CondParser *par, ComparisonOp *out_op)
|
||||
*out_op = NE;
|
||||
goto length_2;
|
||||
}
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
length_2:
|
||||
par->p = p + 2;
|
||||
return TRUE;
|
||||
return true;
|
||||
length_1:
|
||||
par->p = p + 1;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -674,18 +675,18 @@ CondParser_ComparisonOp(CondParser *par, ComparisonOp *out_op)
|
||||
* ${VAR:U0} < 12345
|
||||
*/
|
||||
static Token
|
||||
CondParser_Comparison(CondParser *par, Boolean doEval)
|
||||
CondParser_Comparison(CondParser *par, bool doEval)
|
||||
{
|
||||
Token t = TOK_ERROR;
|
||||
FStr lhs, rhs;
|
||||
ComparisonOp op;
|
||||
Boolean lhsQuoted, rhsQuoted;
|
||||
bool lhsQuoted, rhsQuoted;
|
||||
|
||||
/*
|
||||
* Parse the variable spec and skip over it, saving its
|
||||
* value in lhs.
|
||||
*/
|
||||
CondParser_String(par, doEval, lhsStrict, &lhs, &lhsQuoted);
|
||||
CondParser_Leaf(par, doEval, lhsStrict, &lhs, &lhsQuoted);
|
||||
if (lhs.str == NULL)
|
||||
goto done_lhs;
|
||||
|
||||
@ -702,11 +703,11 @@ CondParser_Comparison(CondParser *par, Boolean doEval)
|
||||
if (par->p[0] == '\0') {
|
||||
Parse_Error(PARSE_FATAL,
|
||||
"Missing right-hand-side of operator '%s'", opname[op]);
|
||||
par->printedError = TRUE;
|
||||
par->printedError = true;
|
||||
goto done_lhs;
|
||||
}
|
||||
|
||||
CondParser_String(par, doEval, FALSE, &rhs, &rhsQuoted);
|
||||
CondParser_Leaf(par, doEval, false, &rhs, &rhsQuoted);
|
||||
if (rhs.str == NULL)
|
||||
goto done_rhs;
|
||||
|
||||
@ -731,7 +732,7 @@ CondParser_Comparison(CondParser *par, Boolean doEval)
|
||||
/*ARGSUSED*/
|
||||
static size_t
|
||||
ParseEmptyArg(CondParser *par MAKE_ATTR_UNUSED, const char **pp,
|
||||
Boolean doEval, const char *func MAKE_ATTR_UNUSED,
|
||||
bool doEval, const char *func MAKE_ATTR_UNUSED,
|
||||
char **out_arg)
|
||||
{
|
||||
FStr val;
|
||||
@ -741,8 +742,8 @@ ParseEmptyArg(CondParser *par MAKE_ATTR_UNUSED, const char **pp,
|
||||
*out_arg = NULL;
|
||||
|
||||
(*pp)--; /* Make (*pp)[1] point to the '('. */
|
||||
(void)Var_Parse(pp, SCOPE_CMDLINE, doEval ? VARE_WANTRES : VARE_NONE,
|
||||
&val);
|
||||
(void)Var_Parse(pp, SCOPE_CMDLINE,
|
||||
doEval ? VARE_WANTRES : VARE_PARSE_ONLY, &val);
|
||||
/* TODO: handle errors */
|
||||
/* If successful, *pp points beyond the closing ')' now. */
|
||||
|
||||
@ -767,22 +768,23 @@ ParseEmptyArg(CondParser *par MAKE_ATTR_UNUSED, const char **pp,
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static Boolean
|
||||
static bool
|
||||
FuncEmpty(size_t arglen, const char *arg MAKE_ATTR_UNUSED)
|
||||
{
|
||||
/* Magic values ahead, see ParseEmptyArg. */
|
||||
return arglen == 1;
|
||||
}
|
||||
|
||||
static Boolean
|
||||
CondParser_Func(CondParser *par, Boolean doEval, Token *out_token)
|
||||
/* Parse a function call expression, such as 'defined(${file})'. */
|
||||
static bool
|
||||
CondParser_FuncCall(CondParser *par, bool doEval, Token *out_token)
|
||||
{
|
||||
static const struct fn_def {
|
||||
const char *fn_name;
|
||||
size_t fn_name_len;
|
||||
size_t (*fn_parse)(CondParser *, const char **, Boolean,
|
||||
size_t (*fn_parse)(CondParser *, const char **, bool,
|
||||
const char *, char **);
|
||||
Boolean (*fn_eval)(size_t, const char *);
|
||||
bool (*fn_eval)(size_t, const char *);
|
||||
} fns[] = {
|
||||
{ "defined", 7, ParseFuncArg, FuncDefined },
|
||||
{ "make", 4, ParseFuncArg, FuncMake },
|
||||
@ -810,25 +812,25 @@ CondParser_Func(CondParser *par, Boolean doEval, Token *out_token)
|
||||
if (arglen == 0 || arglen == (size_t)-1) {
|
||||
par->p = cp;
|
||||
*out_token = arglen == 0 ? TOK_FALSE : TOK_ERROR;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Evaluate the argument using the required function. */
|
||||
*out_token = ToToken(!doEval || fn->fn_eval(arglen, arg));
|
||||
free(arg);
|
||||
par->p = cp;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a function call, a number, a variable expression or a string
|
||||
* literal.
|
||||
* Parse a comparison such as '${VAR} == "value"', or a simple leaf without
|
||||
* operator, which is a number, a variable expression or a string literal.
|
||||
*/
|
||||
static Token
|
||||
CondParser_LeafToken(CondParser *par, Boolean doEval)
|
||||
CondParser_ComparisonOrLeaf(CondParser *par, bool doEval)
|
||||
{
|
||||
Token t;
|
||||
char *arg = NULL;
|
||||
@ -836,9 +838,6 @@ CondParser_LeafToken(CondParser *par, Boolean doEval)
|
||||
const char *cp;
|
||||
const char *cp1;
|
||||
|
||||
if (CondParser_Func(par, doEval, &t))
|
||||
return t;
|
||||
|
||||
/* Push anything numeric through the compare expression */
|
||||
cp = par->p;
|
||||
if (ch_isdigit(cp[0]) || cp[0] == '-' || cp[0] == '+')
|
||||
@ -852,10 +851,14 @@ CondParser_LeafToken(CondParser *par, Boolean doEval)
|
||||
* syntax would be invalid if we did "defined(a)" - so instead treat
|
||||
* as an expression.
|
||||
*/
|
||||
/*
|
||||
* XXX: Is it possible to have a variable expression evaluated twice
|
||||
* at this point?
|
||||
*/
|
||||
arglen = ParseFuncArg(par, &cp, doEval, NULL, &arg);
|
||||
cp1 = cp;
|
||||
cpp_skip_whitespace(&cp1);
|
||||
if (*cp1 == '=' || *cp1 == '!')
|
||||
if (*cp1 == '=' || *cp1 == '!' || *cp1 == '<' || *cp1 == '>')
|
||||
return CondParser_Comparison(par, doEval);
|
||||
par->p = cp;
|
||||
|
||||
@ -865,14 +868,14 @@ CondParser_LeafToken(CondParser *par, Boolean doEval)
|
||||
* after .if must have been taken literally, so the argument cannot
|
||||
* be empty - even if it contained a variable expansion.
|
||||
*/
|
||||
t = ToToken(!doEval || If_Eval(par, arg, arglen));
|
||||
t = ToToken(!doEval || EvalBare(par, arg, arglen));
|
||||
free(arg);
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Return the next token or comparison result from the parser. */
|
||||
static Token
|
||||
CondParser_Token(CondParser *par, Boolean doEval)
|
||||
CondParser_Token(CondParser *par, bool doEval)
|
||||
{
|
||||
Token t;
|
||||
|
||||
@ -900,7 +903,7 @@ CondParser_Token(CondParser *par, Boolean doEval)
|
||||
par->p++;
|
||||
else if (opts.strict) {
|
||||
Parse_Error(PARSE_FATAL, "Unknown operator '|'");
|
||||
par->printedError = TRUE;
|
||||
par->printedError = true;
|
||||
return TOK_ERROR;
|
||||
}
|
||||
return TOK_OR;
|
||||
@ -911,7 +914,7 @@ CondParser_Token(CondParser *par, Boolean doEval)
|
||||
par->p++;
|
||||
else if (opts.strict) {
|
||||
Parse_Error(PARSE_FATAL, "Unknown operator '&'");
|
||||
par->printedError = TRUE;
|
||||
par->printedError = true;
|
||||
return TOK_ERROR;
|
||||
}
|
||||
return TOK_AND;
|
||||
@ -931,7 +934,9 @@ CondParser_Token(CondParser *par, Boolean doEval)
|
||||
return CondParser_Comparison(par, doEval);
|
||||
|
||||
default:
|
||||
return CondParser_LeafToken(par, doEval);
|
||||
if (CondParser_FuncCall(par, doEval, &t))
|
||||
return t;
|
||||
return CondParser_ComparisonOrLeaf(par, doEval);
|
||||
}
|
||||
}
|
||||
|
||||
@ -942,7 +947,7 @@ CondParser_Token(CondParser *par, Boolean doEval)
|
||||
* Term -> Leaf
|
||||
*/
|
||||
static CondResult
|
||||
CondParser_Term(CondParser *par, Boolean doEval)
|
||||
CondParser_Term(CondParser *par, bool doEval)
|
||||
{
|
||||
CondResult res;
|
||||
Token t;
|
||||
@ -979,7 +984,7 @@ CondParser_Term(CondParser *par, Boolean doEval)
|
||||
* And -> Term
|
||||
*/
|
||||
static CondResult
|
||||
CondParser_And(CondParser *par, Boolean doEval)
|
||||
CondParser_And(CondParser *par, bool doEval)
|
||||
{
|
||||
CondResult res;
|
||||
Token op;
|
||||
@ -992,7 +997,7 @@ CondParser_And(CondParser *par, Boolean doEval)
|
||||
if (op == TOK_AND) {
|
||||
if (res == CR_TRUE)
|
||||
return CondParser_And(par, doEval);
|
||||
if (CondParser_And(par, FALSE) == CR_ERROR)
|
||||
if (CondParser_And(par, false) == CR_ERROR)
|
||||
return CR_ERROR;
|
||||
return res;
|
||||
}
|
||||
@ -1006,7 +1011,7 @@ CondParser_And(CondParser *par, Boolean doEval)
|
||||
* Or -> And
|
||||
*/
|
||||
static CondResult
|
||||
CondParser_Or(CondParser *par, Boolean doEval)
|
||||
CondParser_Or(CondParser *par, bool doEval)
|
||||
{
|
||||
CondResult res;
|
||||
Token op;
|
||||
@ -1019,7 +1024,7 @@ CondParser_Or(CondParser *par, Boolean doEval)
|
||||
if (op == TOK_OR) {
|
||||
if (res == CR_FALSE)
|
||||
return CondParser_Or(par, doEval);
|
||||
if (CondParser_Or(par, FALSE) == CR_ERROR)
|
||||
if (CondParser_Or(par, false) == CR_ERROR)
|
||||
return CR_ERROR;
|
||||
return res;
|
||||
}
|
||||
@ -1029,17 +1034,17 @@ CondParser_Or(CondParser *par, Boolean doEval)
|
||||
}
|
||||
|
||||
static CondEvalResult
|
||||
CondParser_Eval(CondParser *par, Boolean *out_value)
|
||||
CondParser_Eval(CondParser *par, bool *out_value)
|
||||
{
|
||||
CondResult res;
|
||||
|
||||
DEBUG1(COND, "CondParser_Eval: %s\n", par->p);
|
||||
|
||||
res = CondParser_Or(par, TRUE);
|
||||
res = CondParser_Or(par, true);
|
||||
if (res == CR_ERROR)
|
||||
return COND_INVALID;
|
||||
|
||||
if (CondParser_Token(par, FALSE) != TOK_EOF)
|
||||
if (CondParser_Token(par, false) != TOK_EOF)
|
||||
return COND_INVALID;
|
||||
|
||||
*out_value = res == CR_TRUE;
|
||||
@ -1058,9 +1063,9 @@ CondParser_Eval(CondParser *par, Boolean *out_value)
|
||||
* (*value) is set to the boolean value of the condition
|
||||
*/
|
||||
static CondEvalResult
|
||||
CondEvalExpression(const char *cond, Boolean *out_value, Boolean plain,
|
||||
Boolean (*evalBare)(size_t, const char *), Boolean negate,
|
||||
Boolean eprint, Boolean strictLHS)
|
||||
CondEvalExpression(const char *cond, bool *out_value, bool plain,
|
||||
bool (*evalBare)(size_t, const char *), bool negate,
|
||||
bool eprint, bool strictLHS)
|
||||
{
|
||||
CondParser par;
|
||||
CondEvalResult rval;
|
||||
@ -1074,7 +1079,7 @@ CondEvalExpression(const char *cond, Boolean *out_value, Boolean plain,
|
||||
par.negateEvalBare = negate;
|
||||
par.p = cond;
|
||||
par.curr = TOK_NONE;
|
||||
par.printedError = FALSE;
|
||||
par.printedError = false;
|
||||
|
||||
rval = CondParser_Eval(&par, out_value);
|
||||
|
||||
@ -1089,33 +1094,33 @@ CondEvalExpression(const char *cond, Boolean *out_value, Boolean plain,
|
||||
* ${"${VAR}" == value:?yes:no}.
|
||||
*/
|
||||
CondEvalResult
|
||||
Cond_EvalCondition(const char *cond, Boolean *out_value)
|
||||
Cond_EvalCondition(const char *cond, bool *out_value)
|
||||
{
|
||||
return CondEvalExpression(cond, out_value, TRUE,
|
||||
FuncDefined, FALSE, FALSE, FALSE);
|
||||
return CondEvalExpression(cond, out_value, true,
|
||||
FuncDefined, false, false, false);
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
IsEndif(const char *p)
|
||||
{
|
||||
return p[0] == 'e' && p[1] == 'n' && p[2] == 'd' &&
|
||||
p[3] == 'i' && p[4] == 'f' && !ch_isalpha(p[5]);
|
||||
}
|
||||
|
||||
static Boolean
|
||||
DetermineKindOfConditional(const char **pp, Boolean *out_plain,
|
||||
Boolean (**out_evalBare)(size_t, const char *),
|
||||
Boolean *out_negate)
|
||||
static bool
|
||||
DetermineKindOfConditional(const char **pp, bool *out_plain,
|
||||
bool (**out_evalBare)(size_t, const char *),
|
||||
bool *out_negate)
|
||||
{
|
||||
const char *p = *pp;
|
||||
|
||||
p += 2;
|
||||
*out_plain = FALSE;
|
||||
*out_plain = false;
|
||||
*out_evalBare = FuncDefined;
|
||||
*out_negate = FALSE;
|
||||
*out_negate = false;
|
||||
if (*p == 'n') {
|
||||
p++;
|
||||
*out_negate = TRUE;
|
||||
*out_negate = true;
|
||||
}
|
||||
if (is_token(p, "def", 3)) { /* .ifdef and .ifndef */
|
||||
p += 3;
|
||||
@ -1123,7 +1128,7 @@ DetermineKindOfConditional(const char **pp, Boolean *out_plain,
|
||||
p += 4;
|
||||
*out_evalBare = FuncMake;
|
||||
} else if (is_token(p, "", 0) && !*out_negate) { /* plain .if */
|
||||
*out_plain = TRUE;
|
||||
*out_plain = true;
|
||||
} else {
|
||||
/*
|
||||
* TODO: Add error message about unknown directive,
|
||||
@ -1132,11 +1137,11 @@ DetermineKindOfConditional(const char **pp, Boolean *out_plain,
|
||||
*
|
||||
* Example: .elifx 123
|
||||
*/
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
*pp = p;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1161,9 +1166,9 @@ DetermineKindOfConditional(const char **pp, Boolean *out_plain,
|
||||
*
|
||||
* Results:
|
||||
* COND_PARSE to continue parsing the lines that follow the
|
||||
* conditional (when <cond> evaluates to TRUE)
|
||||
* conditional (when <cond> evaluates to true)
|
||||
* COND_SKIP to skip the lines after the conditional
|
||||
* (when <cond> evaluates to FALSE, or when a previous
|
||||
* (when <cond> evaluates to false, or when a previous
|
||||
* branch has already been taken)
|
||||
* COND_INVALID if the conditional was not valid, either because of
|
||||
* a syntax error or because some variable was undefined
|
||||
@ -1174,17 +1179,17 @@ Cond_EvalLine(const char *line)
|
||||
{
|
||||
typedef enum IfState {
|
||||
|
||||
/* None of the previous <cond> evaluated to TRUE. */
|
||||
/* None of the previous <cond> evaluated to true. */
|
||||
IFS_INITIAL = 0,
|
||||
|
||||
/* The previous <cond> evaluated to TRUE.
|
||||
/* The previous <cond> evaluated to true.
|
||||
* The lines following this condition are interpreted. */
|
||||
IFS_ACTIVE = 1 << 0,
|
||||
|
||||
/* The previous directive was an '.else'. */
|
||||
IFS_SEEN_ELSE = 1 << 1,
|
||||
|
||||
/* One of the previous <cond> evaluated to TRUE. */
|
||||
/* One of the previous <cond> evaluated to true. */
|
||||
IFS_WAS_ACTIVE = 1 << 2
|
||||
|
||||
} IfState;
|
||||
@ -1192,11 +1197,11 @@ Cond_EvalLine(const char *line)
|
||||
static enum IfState *cond_states = NULL;
|
||||
static unsigned int cond_states_cap = 128;
|
||||
|
||||
Boolean plain;
|
||||
Boolean (*evalBare)(size_t, const char *);
|
||||
Boolean negate;
|
||||
Boolean isElif;
|
||||
Boolean value;
|
||||
bool plain;
|
||||
bool (*evalBare)(size_t, const char *);
|
||||
bool negate;
|
||||
bool isElif;
|
||||
bool value;
|
||||
IfState state;
|
||||
const char *p = line;
|
||||
|
||||
@ -1265,9 +1270,9 @@ Cond_EvalLine(const char *line)
|
||||
return state & IFS_ACTIVE ? COND_PARSE : COND_SKIP;
|
||||
}
|
||||
/* Assume for now it is an elif */
|
||||
isElif = TRUE;
|
||||
isElif = true;
|
||||
} else
|
||||
isElif = FALSE;
|
||||
isElif = false;
|
||||
|
||||
if (p[0] != 'i' || p[1] != 'f') {
|
||||
/*
|
||||
@ -1323,7 +1328,7 @@ Cond_EvalLine(const char *line)
|
||||
|
||||
/* And evaluate the conditional expression */
|
||||
if (CondEvalExpression(p, &value, plain, evalBare, negate,
|
||||
TRUE, TRUE) == COND_INVALID) {
|
||||
true, true) == COND_INVALID) {
|
||||
/* Syntax error in conditional, error message already output. */
|
||||
/* Skip everything to matching .endif */
|
||||
/* XXX: An extra '.else' is not detected in this case. */
|
||||
|
62
dir.c
62
dir.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: dir.c,v 1.270 2021/02/05 05:48:19 rillig Exp $ */
|
||||
/* $NetBSD: dir.c,v 1.272 2021/04/04 10:13:09 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||
@ -86,7 +86,7 @@
|
||||
* Dir_SetPATH Set ${.PATH} to reflect state of dirSearchPath.
|
||||
*
|
||||
* Dir_HasWildcards
|
||||
* Returns TRUE if the name given it needs to
|
||||
* Returns true if the name given it needs to
|
||||
* be wildcard-expanded.
|
||||
*
|
||||
* SearchPath_Expand
|
||||
@ -138,7 +138,7 @@
|
||||
#include "job.h"
|
||||
|
||||
/* "@(#)dir.c 8.2 (Berkeley) 1/2/94" */
|
||||
MAKE_RCSID("$NetBSD: dir.c,v 1.270 2021/02/05 05:48:19 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: dir.c,v 1.272 2021/04/04 10:13:09 rillig Exp $");
|
||||
|
||||
/*
|
||||
* A search path is a list of CachedDir structures. A CachedDir has in it the
|
||||
@ -217,7 +217,7 @@ struct CachedDir {
|
||||
* and "./." are different.
|
||||
*
|
||||
* Not sure what happens when .CURDIR is assigned a new value; see
|
||||
* Parse_DoVar.
|
||||
* Parse_Var.
|
||||
*/
|
||||
char *name;
|
||||
|
||||
@ -547,14 +547,14 @@ void
|
||||
Dir_SetPATH(void)
|
||||
{
|
||||
CachedDirListNode *ln;
|
||||
Boolean seenDotLast = FALSE; /* true if we should search '.' last */
|
||||
bool seenDotLast = false; /* true if we should search '.' last */
|
||||
|
||||
Global_Delete(".PATH");
|
||||
|
||||
if ((ln = dirSearchPath.dirs.first) != NULL) {
|
||||
CachedDir *dir = ln->datum;
|
||||
if (dir == dotLast) {
|
||||
seenDotLast = TRUE;
|
||||
seenDotLast = true;
|
||||
Global_Append(".PATH", dotLast->name);
|
||||
}
|
||||
}
|
||||
@ -591,34 +591,34 @@ Dir_SetPATH(void)
|
||||
* that make(1) should be expanding patterns, because then you have to set a
|
||||
* mechanism for escaping the expansion!
|
||||
*
|
||||
* Return TRUE if the word should be expanded, FALSE otherwise.
|
||||
* Return true if the word should be expanded, false otherwise.
|
||||
*/
|
||||
Boolean
|
||||
bool
|
||||
Dir_HasWildcards(const char *name)
|
||||
{
|
||||
const char *p;
|
||||
Boolean wild = FALSE;
|
||||
bool wild = false;
|
||||
int braces = 0, brackets = 0;
|
||||
|
||||
for (p = name; *p != '\0'; p++) {
|
||||
switch (*p) {
|
||||
case '{':
|
||||
braces++;
|
||||
wild = TRUE;
|
||||
wild = true;
|
||||
break;
|
||||
case '}':
|
||||
braces--;
|
||||
break;
|
||||
case '[':
|
||||
brackets++;
|
||||
wild = TRUE;
|
||||
wild = true;
|
||||
break;
|
||||
case ']':
|
||||
brackets--;
|
||||
break;
|
||||
case '?':
|
||||
case '*':
|
||||
wild = TRUE;
|
||||
wild = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -647,7 +647,7 @@ static void
|
||||
DirMatchFiles(const char *pattern, CachedDir *dir, StringList *expansions)
|
||||
{
|
||||
const char *dirName = dir->name;
|
||||
Boolean isDot = dirName[0] == '.' && dirName[1] == '\0';
|
||||
bool isDot = dirName[0] == '.' && dirName[1] == '\0';
|
||||
HashIter hi;
|
||||
|
||||
/*
|
||||
@ -725,7 +725,7 @@ separator_comma(const char *p)
|
||||
return p;
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
contains_wildcard(const char *p)
|
||||
{
|
||||
for (; *p != '\0'; p++) {
|
||||
@ -734,10 +734,10 @@ contains_wildcard(const char *p)
|
||||
case '?':
|
||||
case '{':
|
||||
case '[':
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
static char *
|
||||
@ -1064,19 +1064,19 @@ DirFindDot(const char *name, const char *base)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Boolean
|
||||
FindFileRelative(SearchPath *path, Boolean seenDotLast,
|
||||
static bool
|
||||
FindFileRelative(SearchPath *path, bool seenDotLast,
|
||||
const char *name, char **out_file)
|
||||
{
|
||||
SearchPathNode *ln;
|
||||
Boolean checkedDot = FALSE;
|
||||
bool checkedDot = false;
|
||||
char *file;
|
||||
|
||||
DEBUG0(DIR, " Trying subdirectories...\n");
|
||||
|
||||
if (!seenDotLast) {
|
||||
if (dot != NULL) {
|
||||
checkedDot = TRUE;
|
||||
checkedDot = true;
|
||||
if ((file = DirLookupSubdir(dot, name)) != NULL)
|
||||
goto found;
|
||||
}
|
||||
@ -1092,7 +1092,7 @@ FindFileRelative(SearchPath *path, Boolean seenDotLast,
|
||||
if (dir == dot) {
|
||||
if (checkedDot)
|
||||
continue;
|
||||
checkedDot = TRUE;
|
||||
checkedDot = true;
|
||||
}
|
||||
if ((file = DirLookupSubdir(dir, name)) != NULL)
|
||||
goto found;
|
||||
@ -1100,7 +1100,7 @@ FindFileRelative(SearchPath *path, Boolean seenDotLast,
|
||||
|
||||
if (seenDotLast) {
|
||||
if (dot != NULL && !checkedDot) {
|
||||
checkedDot = TRUE;
|
||||
checkedDot = true;
|
||||
if ((file = DirLookupSubdir(dot, name)) != NULL)
|
||||
goto found;
|
||||
}
|
||||
@ -1119,15 +1119,15 @@ FindFileRelative(SearchPath *path, Boolean seenDotLast,
|
||||
goto found;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
found:
|
||||
*out_file = file;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
static Boolean
|
||||
FindFileAbsolute(SearchPath *path, Boolean const seenDotLast,
|
||||
static bool
|
||||
FindFileAbsolute(SearchPath *path, bool const seenDotLast,
|
||||
const char *const name, const char *const base,
|
||||
char **out_file)
|
||||
{
|
||||
@ -1162,7 +1162,7 @@ FindFileAbsolute(SearchPath *path, Boolean const seenDotLast,
|
||||
((file = DirLookupAbs(cur, name, base)) != NULL))
|
||||
goto found;
|
||||
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
found:
|
||||
if (file[0] == '\0') {
|
||||
@ -1170,7 +1170,7 @@ FindFileAbsolute(SearchPath *path, Boolean const seenDotLast,
|
||||
file = NULL;
|
||||
}
|
||||
*out_file = file;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1194,7 +1194,7 @@ char *
|
||||
Dir_FindFile(const char *name, SearchPath *path)
|
||||
{
|
||||
char *file; /* the current filename to check */
|
||||
Boolean seenDotLast = FALSE; /* true if we should search dot last */
|
||||
bool seenDotLast = false; /* true if we should search dot last */
|
||||
struct cached_stat cst; /* Buffer for stat, if necessary */
|
||||
const char *trailing_dot = ".";
|
||||
const char *base = str_basename(name);
|
||||
@ -1210,7 +1210,7 @@ Dir_FindFile(const char *name, SearchPath *path)
|
||||
if (path->dirs.first != NULL) {
|
||||
CachedDir *dir = path->dirs.first->datum;
|
||||
if (dir == dotLast) {
|
||||
seenDotLast = TRUE;
|
||||
seenDotLast = true;
|
||||
DEBUG0(DIR, "[dot last]...");
|
||||
}
|
||||
}
|
||||
@ -1471,7 +1471,7 @@ ResolveFullName(GNode *gn)
|
||||
* The found file is stored in gn->path, unless the node already had a path.
|
||||
*/
|
||||
void
|
||||
Dir_UpdateMTime(GNode *gn, Boolean recheck)
|
||||
Dir_UpdateMTime(GNode *gn, bool recheck)
|
||||
{
|
||||
char *fullName;
|
||||
struct cached_stat cst;
|
||||
|
6
dir.h
6
dir.h
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: dir.h,v 1.43 2021/02/05 05:48:19 rillig Exp $ */
|
||||
/* $NetBSD: dir.h,v 1.44 2021/04/03 11:08:40 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||
@ -82,11 +82,11 @@ void Dir_InitCur(const char *);
|
||||
void Dir_InitDot(void);
|
||||
void Dir_End(void);
|
||||
void Dir_SetPATH(void);
|
||||
Boolean Dir_HasWildcards(const char *);
|
||||
bool Dir_HasWildcards(const char *);
|
||||
void SearchPath_Expand(SearchPath *, const char *, StringList *);
|
||||
char *Dir_FindFile(const char *, SearchPath *);
|
||||
char *Dir_FindHereOrAbove(const char *, const char *);
|
||||
void Dir_UpdateMTime(GNode *, Boolean);
|
||||
void Dir_UpdateMTime(GNode *, bool);
|
||||
CachedDir *SearchPath_Add(SearchPath *, const char *);
|
||||
char *SearchPath_ToFlags(SearchPath *, const char *);
|
||||
void SearchPath_Clear(SearchPath *);
|
||||
|
62
enum.h
62
enum.h
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: enum.h,v 1.18 2021/02/02 21:26:51 rillig Exp $ */
|
||||
/* $NetBSD: enum.h,v 1.19 2021/03/15 16:00:05 rillig Exp $ */
|
||||
|
||||
/*
|
||||
Copyright (c) 2020 Roland Illig <rillig@NetBSD.org>
|
||||
@ -112,19 +112,6 @@ const char *Enum_FlagsToString(char *, size_t, int, const EnumToStringSpec *);
|
||||
} \
|
||||
extern void enum_flags_rtti_dummy(void)
|
||||
|
||||
/*
|
||||
* Declare the necessary data structures for calling Enum_FlagsToString
|
||||
* for an enum with 2 flags.
|
||||
*/
|
||||
#define ENUM_FLAGS_RTTI_2(typnam, v1, v2) \
|
||||
ENUM__FLAGS_RTTI(typnam, \
|
||||
ENUM__SPECS_2( \
|
||||
ENUM__SPEC_1(v1), \
|
||||
ENUM__SPEC_1(v2)), \
|
||||
ENUM__JOIN_2( \
|
||||
ENUM__JOIN_STR_1(v1), \
|
||||
ENUM__JOIN_STR_1(v2)))
|
||||
|
||||
/*
|
||||
* Declare the necessary data structures for calling Enum_FlagsToString
|
||||
* for an enum with 3 flags.
|
||||
@ -138,19 +125,6 @@ const char *Enum_FlagsToString(char *, size_t, int, const EnumToStringSpec *);
|
||||
ENUM__JOIN_STR_2(v1, v2), \
|
||||
ENUM__JOIN_STR_1(v3)))
|
||||
|
||||
/*
|
||||
* Declare the necessary data structures for calling Enum_FlagsToString
|
||||
* for an enum with 4 flags.
|
||||
*/
|
||||
#define ENUM_FLAGS_RTTI_4(typnam, v1, v2, v3, v4) \
|
||||
ENUM__FLAGS_RTTI(typnam, \
|
||||
ENUM__SPECS_2( \
|
||||
ENUM__SPEC_2(v1, v2), \
|
||||
ENUM__SPEC_2(v3, v4)), \
|
||||
ENUM__JOIN_2( \
|
||||
ENUM__JOIN_STR_2(v1, v2), \
|
||||
ENUM__JOIN_STR_2(v3, v4)))
|
||||
|
||||
/*
|
||||
* Declare the necessary data structures for calling Enum_FlagsToString
|
||||
* for an enum with 6 flags.
|
||||
@ -164,19 +138,6 @@ const char *Enum_FlagsToString(char *, size_t, int, const EnumToStringSpec *);
|
||||
ENUM__JOIN_STR_4(v1, v2, v3, v4), \
|
||||
ENUM__JOIN_STR_2(v5, v6)))
|
||||
|
||||
/*
|
||||
* Declare the necessary data structures for calling Enum_FlagsToString
|
||||
* for an enum with 8 flags.
|
||||
*/
|
||||
#define ENUM_FLAGS_RTTI_8(typnam, v1, v2, v3, v4, v5, v6, v7, v8) \
|
||||
ENUM__FLAGS_RTTI(typnam, \
|
||||
ENUM__SPECS_2( \
|
||||
ENUM__SPEC_4(v1, v2, v3, v4), \
|
||||
ENUM__SPEC_4(v5, v6, v7, v8)), \
|
||||
ENUM__JOIN_2( \
|
||||
ENUM__JOIN_STR_4(v1, v2, v3, v4), \
|
||||
ENUM__JOIN_STR_4(v5, v6, v7, v8)))
|
||||
|
||||
/*
|
||||
* Declare the necessary data structures for calling Enum_FlagsToString
|
||||
* for an enum with 9 flags.
|
||||
@ -215,25 +176,4 @@ const char *Enum_FlagsToString(char *, size_t, int, const EnumToStringSpec *);
|
||||
ENUM__JOIN_STR_2(v29, v30), \
|
||||
ENUM__JOIN_STR_1(v31)))
|
||||
|
||||
/*
|
||||
* Declare the necessary data structures for calling Enum_FlagsToString
|
||||
* for an enum with 32 flags.
|
||||
*/
|
||||
#define ENUM_FLAGS_RTTI_32(typnam, \
|
||||
v01, v02, v03, v04, v05, v06, v07, v08, \
|
||||
v09, v10, v11, v12, v13, v14, v15, v16, \
|
||||
v17, v18, v19, v20, v21, v22, v23, v24, \
|
||||
v25, v26, v27, v28, v29, v30, v31, v32) \
|
||||
ENUM__FLAGS_RTTI(typnam, \
|
||||
ENUM__SPECS_2( \
|
||||
ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \
|
||||
v09, v10, v11, v12, v13, v14, v15, v16), \
|
||||
ENUM__SPEC_16(v17, v18, v19, v20, v21, v22, v23, v24, \
|
||||
v25, v26, v27, v28, v29, v30, v31, v32)), \
|
||||
ENUM__JOIN_2( \
|
||||
ENUM__JOIN_STR_16(v01, v02, v03, v04, v05, v06, v07, v08, \
|
||||
v09, v10, v11, v12, v13, v14, v15, v16), \
|
||||
ENUM__JOIN_STR_16(v17, v18, v19, v20, v21, v22, v23, v24, \
|
||||
v25, v26, v27, v28, v29, v30, v31, v32)))
|
||||
|
||||
#endif
|
||||
|
46
for.c
46
for.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: for.c,v 1.141 2021/02/04 21:33:13 rillig Exp $ */
|
||||
/* $NetBSD: for.c,v 1.142 2021/04/03 11:08:40 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, The Regents of the University of California.
|
||||
@ -58,7 +58,7 @@
|
||||
#include "make.h"
|
||||
|
||||
/* "@(#)for.c 8.1 (Berkeley) 6/6/93" */
|
||||
MAKE_RCSID("$NetBSD: for.c,v 1.141 2021/02/04 21:33:13 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: for.c,v 1.142 2021/04/03 11:08:40 rillig Exp $");
|
||||
|
||||
|
||||
/* One of the variables to the left of the "in" in a .for loop. */
|
||||
@ -75,7 +75,7 @@ typedef struct ForLoop {
|
||||
/* Is any of the names 1 character long? If so, when the variable values
|
||||
* are substituted, the parser must handle $V expressions as well, not
|
||||
* only ${V} and $(V). */
|
||||
Boolean short_var;
|
||||
bool short_var;
|
||||
unsigned int sub_next; /* Where to continue iterating */
|
||||
} ForLoop;
|
||||
|
||||
@ -94,7 +94,7 @@ ForLoop_New(void)
|
||||
f->items.words = NULL;
|
||||
f->items.freeIt = NULL;
|
||||
Buf_Init(&f->curBody);
|
||||
f->short_var = FALSE;
|
||||
f->short_var = false;
|
||||
f->sub_next = 0;
|
||||
|
||||
return f;
|
||||
@ -125,7 +125,7 @@ ForLoop_AddVar(ForLoop *f, const char *name, size_t len)
|
||||
var->nameLen = len;
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
ForLoop_ParseVarnames(ForLoop *f, const char **pp)
|
||||
{
|
||||
const char *p = *pp;
|
||||
@ -136,7 +136,7 @@ ForLoop_ParseVarnames(ForLoop *f, const char **pp)
|
||||
cpp_skip_whitespace(&p);
|
||||
if (*p == '\0') {
|
||||
Parse_Error(PARSE_FATAL, "missing `in' in for");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -151,7 +151,7 @@ ForLoop_ParseVarnames(ForLoop *f, const char **pp)
|
||||
break;
|
||||
}
|
||||
if (len == 1)
|
||||
f->short_var = TRUE;
|
||||
f->short_var = true;
|
||||
|
||||
ForLoop_AddVar(f, p, len);
|
||||
p += len;
|
||||
@ -159,14 +159,14 @@ ForLoop_ParseVarnames(ForLoop *f, const char **pp)
|
||||
|
||||
if (f->vars.len == 0) {
|
||||
Parse_Error(PARSE_FATAL, "no iteration variables in for");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
*pp = p;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
ForLoop_ParseItems(ForLoop *f, const char *p)
|
||||
{
|
||||
char *items;
|
||||
@ -175,10 +175,10 @@ ForLoop_ParseItems(ForLoop *f, const char *p)
|
||||
|
||||
if (Var_Subst(p, SCOPE_GLOBAL, VARE_WANTRES, &items) != VPR_OK) {
|
||||
Parse_Error(PARSE_FATAL, "Error in .for loop items");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
f->items = Str_Words(items, FALSE);
|
||||
f->items = Str_Words(items, false);
|
||||
free(items);
|
||||
|
||||
if (f->items.len == 1 && f->items.words[0][0] == '\0')
|
||||
@ -189,19 +189,19 @@ ForLoop_ParseItems(ForLoop *f, const char *p)
|
||||
"Wrong number of words (%u) in .for "
|
||||
"substitution list with %u variables",
|
||||
(unsigned)f->items.len, (unsigned)f->vars.len);
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
IsFor(const char *p)
|
||||
{
|
||||
return p[0] == 'f' && p[1] == 'o' && p[2] == 'r' && ch_isspace(p[3]);
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
IsEndfor(const char *p)
|
||||
{
|
||||
return p[0] == 'e' && strncmp(p, "endfor", 6) == 0 &&
|
||||
@ -257,9 +257,9 @@ For_Eval(const char *line)
|
||||
|
||||
/*
|
||||
* Add another line to the .for loop that is being built up.
|
||||
* Returns FALSE when the matching .endfor is reached.
|
||||
* Returns false when the matching .endfor is reached.
|
||||
*/
|
||||
Boolean
|
||||
bool
|
||||
For_Accum(const char *line)
|
||||
{
|
||||
const char *p = line;
|
||||
@ -271,7 +271,7 @@ For_Accum(const char *line)
|
||||
if (IsEndfor(p)) {
|
||||
DEBUG1(FOR, "For: end for %d\n", forLevel);
|
||||
if (--forLevel <= 0)
|
||||
return FALSE;
|
||||
return false;
|
||||
} else if (IsFor(p)) {
|
||||
forLevel++;
|
||||
DEBUG1(FOR, "For: new loop %d\n", forLevel);
|
||||
@ -280,7 +280,7 @@ For_Accum(const char *line)
|
||||
|
||||
Buf_AddStr(&accumFor->body, line);
|
||||
Buf_AddByte(&accumFor->body, '\n');
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -319,16 +319,16 @@ for_var_len(const char *var)
|
||||
* The .for loop substitutes the items as ${:U<value>...}, which means
|
||||
* that characters that break this syntax must be backslash-escaped.
|
||||
*/
|
||||
static Boolean
|
||||
static bool
|
||||
NeedsEscapes(const char *value, char endc)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
for (p = value; *p != '\0'; p++) {
|
||||
if (*p == ':' || *p == '$' || *p == '\\' || *p == endc)
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
68
hash.c
68
hash.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: hash.c,v 1.61 2021/02/01 17:32:10 rillig Exp $ */
|
||||
/* $NetBSD: hash.c,v 1.64 2021/04/11 12:46:54 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||
@ -74,7 +74,7 @@
|
||||
#include "make.h"
|
||||
|
||||
/* "@(#)hash.c 8.1 (Berkeley) 6/6/93" */
|
||||
MAKE_RCSID("$NetBSD: hash.c,v 1.61 2021/02/01 17:32:10 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: hash.c,v 1.64 2021/04/11 12:46:54 rillig Exp $");
|
||||
|
||||
/*
|
||||
* The ratio of # entries to # buckets at which we rebuild the table to
|
||||
@ -84,7 +84,7 @@ MAKE_RCSID("$NetBSD: hash.c,v 1.61 2021/02/01 17:32:10 rillig Exp $");
|
||||
|
||||
/* This hash function matches Gosling's Emacs and java.lang.String. */
|
||||
static unsigned int
|
||||
hash(const char *key, size_t *out_keylen)
|
||||
Hash_String(const char *key, size_t *out_keylen)
|
||||
{
|
||||
unsigned int h;
|
||||
const char *p;
|
||||
@ -98,10 +98,17 @@ hash(const char *key, size_t *out_keylen)
|
||||
return h;
|
||||
}
|
||||
|
||||
/* This hash function matches Gosling's Emacs and java.lang.String. */
|
||||
unsigned int
|
||||
Hash_Hash(const char *key)
|
||||
Hash_Substring(Substring key)
|
||||
{
|
||||
return hash(key, NULL);
|
||||
unsigned int h;
|
||||
const char *p;
|
||||
|
||||
h = 0;
|
||||
for (p = key.start; p != key.end; p++)
|
||||
h = 31 * h + (unsigned char)*p;
|
||||
return h;
|
||||
}
|
||||
|
||||
static HashEntry *
|
||||
@ -126,6 +133,41 @@ HashTable_Find(HashTable *t, unsigned int h, const char *key)
|
||||
return e;
|
||||
}
|
||||
|
||||
static bool
|
||||
HashEntry_KeyEquals(const HashEntry *he, Substring key)
|
||||
{
|
||||
const char *heKey, *p;
|
||||
|
||||
heKey = he->key;
|
||||
for (p = key.start; p != key.end; p++, heKey++)
|
||||
if (*p != *heKey || *heKey == '\0')
|
||||
return false;
|
||||
return *heKey == '\0';
|
||||
}
|
||||
|
||||
static HashEntry *
|
||||
HashTable_FindEntryBySubstring(HashTable *t, Substring key, unsigned int h)
|
||||
{
|
||||
HashEntry *e;
|
||||
unsigned int chainlen = 0;
|
||||
|
||||
#ifdef DEBUG_HASH_LOOKUP
|
||||
DEBUG4(HASH, "%s: %p h=%08x key=%.*s\n", __func__, t, h,
|
||||
(int)Substring_Length(key), key.start);
|
||||
#endif
|
||||
|
||||
for (e = t->buckets[h & t->bucketsMask]; e != NULL; e = e->next) {
|
||||
chainlen++;
|
||||
if (e->key_hash == h && HashEntry_KeyEquals(e, key))
|
||||
break;
|
||||
}
|
||||
|
||||
if (chainlen > t->maxchain)
|
||||
t->maxchain = chainlen;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
/* Set up the hash table. */
|
||||
void
|
||||
HashTable_Init(HashTable *t)
|
||||
@ -171,7 +213,7 @@ HashTable_Done(HashTable *t)
|
||||
HashEntry *
|
||||
HashTable_FindEntry(HashTable *t, const char *key)
|
||||
{
|
||||
unsigned int h = hash(key, NULL);
|
||||
unsigned int h = Hash_String(key, NULL);
|
||||
return HashTable_Find(t, h, key);
|
||||
}
|
||||
|
||||
@ -188,9 +230,9 @@ HashTable_FindValue(HashTable *t, const char *key)
|
||||
* or return NULL.
|
||||
*/
|
||||
void *
|
||||
HashTable_FindValueHash(HashTable *t, const char *key, unsigned int h)
|
||||
HashTable_FindValueBySubstringHash(HashTable *t, Substring key, unsigned int h)
|
||||
{
|
||||
HashEntry *he = HashTable_Find(t, h, key);
|
||||
HashEntry *he = HashTable_FindEntryBySubstring(t, key, h);
|
||||
return he != NULL ? he->value : NULL;
|
||||
}
|
||||
|
||||
@ -227,7 +269,7 @@ HashTable_Enlarge(HashTable *t)
|
||||
t->bucketsMask = newMask;
|
||||
t->buckets = newBuckets;
|
||||
DEBUG5(HASH, "%s: %p size=%d entries=%d maxchain=%d\n",
|
||||
__func__, t, t->bucketsSize, t->numEntries, t->maxchain);
|
||||
__func__, (void *)t, t->bucketsSize, t->numEntries, t->maxchain);
|
||||
t->maxchain = 0;
|
||||
}
|
||||
|
||||
@ -236,15 +278,15 @@ HashTable_Enlarge(HashTable *t)
|
||||
* Return in out_isNew whether a new entry has been created.
|
||||
*/
|
||||
HashEntry *
|
||||
HashTable_CreateEntry(HashTable *t, const char *key, Boolean *out_isNew)
|
||||
HashTable_CreateEntry(HashTable *t, const char *key, bool *out_isNew)
|
||||
{
|
||||
size_t keylen;
|
||||
unsigned int h = hash(key, &keylen);
|
||||
unsigned int h = Hash_String(key, &keylen);
|
||||
HashEntry *he = HashTable_Find(t, h, key);
|
||||
|
||||
if (he != NULL) {
|
||||
if (out_isNew != NULL)
|
||||
*out_isNew = FALSE;
|
||||
*out_isNew = false;
|
||||
return he;
|
||||
}
|
||||
|
||||
@ -261,7 +303,7 @@ HashTable_CreateEntry(HashTable *t, const char *key, Boolean *out_isNew)
|
||||
t->numEntries++;
|
||||
|
||||
if (out_isNew != NULL)
|
||||
*out_isNew = TRUE;
|
||||
*out_isNew = true;
|
||||
return he;
|
||||
}
|
||||
|
||||
|
14
hash.h
14
hash.h
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: hash.h,v 1.38 2020/12/15 01:23:55 rillig Exp $ */
|
||||
/* $NetBSD: hash.h,v 1.40 2021/04/11 12:46:54 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||
@ -124,9 +124,9 @@ void HashTable_Init(HashTable *);
|
||||
void HashTable_Done(HashTable *);
|
||||
HashEntry *HashTable_FindEntry(HashTable *, const char *);
|
||||
void *HashTable_FindValue(HashTable *, const char *);
|
||||
unsigned int Hash_Hash(const char *);
|
||||
void *HashTable_FindValueHash(HashTable *, const char *, unsigned int);
|
||||
HashEntry *HashTable_CreateEntry(HashTable *, const char *, Boolean *);
|
||||
unsigned int Hash_Substring(Substring);
|
||||
void *HashTable_FindValueBySubstringHash(HashTable *, Substring, unsigned int);
|
||||
HashEntry *HashTable_CreateEntry(HashTable *, const char *, bool *);
|
||||
HashEntry *HashTable_Set(HashTable *, const char *, void *);
|
||||
void HashTable_DeleteEntry(HashTable *, HashEntry *);
|
||||
void HashTable_DebugStats(HashTable *, const char *);
|
||||
@ -146,16 +146,16 @@ HashSet_Done(HashSet *set)
|
||||
HashTable_Done(&set->tbl);
|
||||
}
|
||||
|
||||
MAKE_INLINE Boolean
|
||||
MAKE_INLINE bool
|
||||
HashSet_Add(HashSet *set, const char *key)
|
||||
{
|
||||
Boolean isNew;
|
||||
bool isNew;
|
||||
|
||||
(void)HashTable_CreateEntry(&set->tbl, key, &isNew);
|
||||
return isNew;
|
||||
}
|
||||
|
||||
MAKE_INLINE Boolean
|
||||
MAKE_INLINE bool
|
||||
HashSet_Contains(HashSet *set, const char *key)
|
||||
{
|
||||
return HashTable_FindEntry(&set->tbl, key) != NULL;
|
||||
|
17
import.sh
17
import.sh
@ -68,19 +68,24 @@ VERSION=`grep '^_MAKE_VERSION' VERSION | sed 's,.*=[[:space:]]*,,'`
|
||||
rm -f *~
|
||||
mkdir -p ../tmp
|
||||
|
||||
# new files are handled automatically
|
||||
# but we need to rm if needed
|
||||
# FILES are kept sorted so we can determine what was added and deleted
|
||||
# but we need to take care dealing with re-ordering
|
||||
(${GIT} diff FILES | sed -n '/^[+-][^+-]/p'; \
|
||||
${GIT} diff mk/FILES | sed -n '/^[+-][^+-]/s,.,&mk/,p' ) > $TF.diffs
|
||||
grep '^+' $TF.diffs | sed 's,^.,,' | sort > $TF.adds
|
||||
grep '^-' $TF.diffs | sed 's,^.,,' | sort > $TF.rms
|
||||
comm -13 $TF.adds $TF.rms > $TF.rm
|
||||
|
||||
if [ -z "$ECHO" ]; then
|
||||
# new files are handled automatically
|
||||
# but we need to rm if needed
|
||||
$GIT diff FILES | sed -n '/^-[^-]/s,^-,,p' > $TF.rm
|
||||
test -s $TF.rm && xargs rm -f < $TF.rm
|
||||
$GIT add -A
|
||||
$GIT diff --staged | tee ../tmp/bmake-import.diff
|
||||
echo "$GIT tag -a vendor/NetBSD/bmake/$VERSION" > ../tmp/bmake-post.sh
|
||||
echo "After you commit, run $here/../tmp/bmake-post.sh"
|
||||
else
|
||||
# FILES is kept sorted so we can determine what was added and deleted
|
||||
$GIT diff FILES | sed -n '/^+[^+]/s,^+,,p' > $TF.add
|
||||
$GIT diff FILES | sed -n '/^-[^-]/s,^-,,p' > $TF.rm
|
||||
comm -23 $TF.adds $TF.rms > $TF.add
|
||||
test -s $TF.rm && { echo Removing:; cat $TF.rm; }
|
||||
test -s $TF.add && { echo Adding:; cat $TF.add; }
|
||||
$GIT diff
|
||||
|
20
job.h
20
job.h
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: job.h,v 1.72 2021/02/05 19:19:17 sjg Exp $ */
|
||||
/* $NetBSD: job.h,v 1.73 2021/04/03 11:08:40 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||
@ -157,14 +157,14 @@ typedef struct Job {
|
||||
|
||||
JobStatus status;
|
||||
|
||||
Boolean suspended;
|
||||
bool suspended;
|
||||
|
||||
/* Ignore non-zero exits */
|
||||
Boolean ignerr;
|
||||
bool ignerr;
|
||||
/* Output the command before or instead of running it. */
|
||||
Boolean echo;
|
||||
bool echo;
|
||||
/* Target is a special one. */
|
||||
Boolean special;
|
||||
bool special;
|
||||
|
||||
int inPipe; /* Pipe for reading output from job */
|
||||
int outPipe; /* Pipe for writing control commands */
|
||||
@ -188,22 +188,22 @@ extern int jobTokensRunning; /* tokens currently "out" */
|
||||
|
||||
void Shell_Init(void);
|
||||
const char *Shell_GetNewline(void);
|
||||
void Job_Touch(GNode *, Boolean);
|
||||
Boolean Job_CheckCommands(GNode *, void (*abortProc)(const char *, ...));
|
||||
void Job_Touch(GNode *, bool);
|
||||
bool Job_CheckCommands(GNode *, void (*abortProc)(const char *, ...));
|
||||
void Job_CatchChildren(void);
|
||||
void Job_CatchOutput(void);
|
||||
void Job_Make(GNode *);
|
||||
void Job_Init(void);
|
||||
Boolean Job_ParseShell(char *);
|
||||
bool Job_ParseShell(char *);
|
||||
int Job_Finish(void);
|
||||
void Job_End(void);
|
||||
void Job_Wait(void);
|
||||
void Job_AbortAll(void);
|
||||
void Job_TokenReturn(void);
|
||||
Boolean Job_TokenWithdraw(void);
|
||||
bool Job_TokenWithdraw(void);
|
||||
void Job_ServerStart(int, int, int);
|
||||
void Job_SetPrefix(void);
|
||||
Boolean Job_RunTarget(const char *, const char *);
|
||||
bool Job_RunTarget(const char *, const char *);
|
||||
void Job_FlagsToString(const Job *, char *, size_t);
|
||||
int Job_TempFile(const char *, char *, size_t);
|
||||
|
||||
|
10
lst.c
10
lst.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: lst.c,v 1.104 2021/02/01 19:39:31 rillig Exp $ */
|
||||
/* $NetBSD: lst.c,v 1.105 2021/03/15 16:45:30 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -34,7 +34,7 @@
|
||||
|
||||
#include "make.h"
|
||||
|
||||
MAKE_RCSID("$NetBSD: lst.c,v 1.104 2021/02/01 19:39:31 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: lst.c,v 1.105 2021/03/15 16:45:30 rillig Exp $");
|
||||
|
||||
static ListNode *
|
||||
LstNodeNew(ListNode *prev, ListNode *next, void *datum)
|
||||
@ -205,7 +205,7 @@ Lst_FindDatum(List *list, const void *datum)
|
||||
|
||||
/*
|
||||
* Move all nodes from src to the end of dst.
|
||||
* The source list becomes empty but is not freed.
|
||||
* The source list becomes indeterminate.
|
||||
*/
|
||||
void
|
||||
Lst_MoveAll(List *dst, List *src)
|
||||
@ -219,6 +219,10 @@ Lst_MoveAll(List *dst, List *src)
|
||||
|
||||
dst->last = src->last;
|
||||
}
|
||||
#ifdef CLEANUP
|
||||
src->first = NULL;
|
||||
src->last = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Copy the element data from src to the start of dst. */
|
||||
|
12
lst.h
12
lst.h
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: lst.h,v 1.96 2021/02/01 18:55:15 rillig Exp $ */
|
||||
/* $NetBSD: lst.h,v 1.98 2021/04/03 11:08:40 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||
@ -123,15 +123,17 @@ void Lst_Free(List *);
|
||||
MAKE_INLINE void
|
||||
Lst_Init(List *list)
|
||||
{
|
||||
list->first = NULL;
|
||||
list->last = NULL;
|
||||
list->first = NULL;
|
||||
list->last = NULL;
|
||||
}
|
||||
|
||||
/* Get information about a list */
|
||||
|
||||
MAKE_INLINE Boolean
|
||||
MAKE_INLINE bool
|
||||
Lst_IsEmpty(List *list)
|
||||
{ return list->first == NULL; }
|
||||
{
|
||||
return list->first == NULL;
|
||||
}
|
||||
|
||||
/* Find the first node that contains the given datum, or NULL. */
|
||||
ListNode *Lst_FindDatum(List *, const void *);
|
||||
|
248
main.c
248
main.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: main.c,v 1.533 2021/02/05 19:19:17 sjg Exp $ */
|
||||
/* $NetBSD: main.c,v 1.540 2021/06/18 12:54:17 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -111,7 +111,7 @@
|
||||
#include "trace.h"
|
||||
|
||||
/* "@(#)main.c 8.3 (Berkeley) 3/19/94" */
|
||||
MAKE_RCSID("$NetBSD: main.c,v 1.533 2021/02/05 19:19:17 sjg Exp $");
|
||||
MAKE_RCSID("$NetBSD: main.c,v 1.540 2021/06/18 12:54:17 rillig Exp $");
|
||||
#if defined(MAKE_NATIVE) && !defined(lint)
|
||||
__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 "
|
||||
"The Regents of the University of California. "
|
||||
@ -125,20 +125,20 @@ __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 "
|
||||
CmdOpts opts;
|
||||
time_t now; /* Time at start of make */
|
||||
GNode *defaultNode; /* .DEFAULT node */
|
||||
Boolean allPrecious; /* .PRECIOUS given on line by itself */
|
||||
Boolean deleteOnError; /* .DELETE_ON_ERROR: set */
|
||||
bool allPrecious; /* .PRECIOUS given on line by itself */
|
||||
bool deleteOnError; /* .DELETE_ON_ERROR: set */
|
||||
|
||||
static int maxJobTokens; /* -j argument */
|
||||
Boolean enterFlagObj; /* -w and objdir != srcdir */
|
||||
bool enterFlagObj; /* -w and objdir != srcdir */
|
||||
|
||||
static int jp_0 = -1, jp_1 = -1; /* ends of parent job pipe */
|
||||
Boolean doing_depend; /* Set while reading .depend */
|
||||
static Boolean jobsRunning; /* TRUE if the jobs might be running */
|
||||
bool doing_depend; /* Set while reading .depend */
|
||||
static bool jobsRunning; /* true if the jobs might be running */
|
||||
static const char *tracefile;
|
||||
static int ReadMakefile(const char *);
|
||||
static void purge_relative_cached_realpaths(void);
|
||||
|
||||
static Boolean ignorePWD; /* if we use -C, PWD is meaningless */
|
||||
static bool ignorePWD; /* if we use -C, PWD is meaningless */
|
||||
static char objdir[MAXPATHLEN + 1]; /* where we chdir'ed to */
|
||||
char curdir[MAXPATHLEN + 1]; /* Startup directory */
|
||||
const char *progname;
|
||||
@ -146,7 +146,7 @@ char *makeDependfile;
|
||||
pid_t myPid;
|
||||
int makelevel;
|
||||
|
||||
Boolean forceJobs = FALSE;
|
||||
bool forceJobs = false;
|
||||
static int main_errors = 0;
|
||||
static HashTable cached_realpaths;
|
||||
|
||||
@ -293,7 +293,7 @@ MainParseArgDebug(const char *argvalue)
|
||||
debug |= DEBUG_JOB;
|
||||
break;
|
||||
case 'L':
|
||||
opts.strict = TRUE;
|
||||
opts.strict = true;
|
||||
break;
|
||||
case 'l':
|
||||
debug |= DEBUG_LOUD;
|
||||
@ -317,7 +317,7 @@ MainParseArgDebug(const char *argvalue)
|
||||
debug |= DEBUG_TARG;
|
||||
break;
|
||||
case 'V':
|
||||
opts.debugVflag = TRUE;
|
||||
opts.debugVflag = true;
|
||||
break;
|
||||
case 'v':
|
||||
debug |= DEBUG_VAR;
|
||||
@ -350,22 +350,22 @@ MainParseArgDebug(const char *argvalue)
|
||||
}
|
||||
|
||||
/* Is path relative, or does it contain any relative component "." or ".."? */
|
||||
static Boolean
|
||||
static bool
|
||||
IsRelativePath(const char *path)
|
||||
{
|
||||
const char *cp;
|
||||
const char *p;
|
||||
|
||||
if (path[0] != '/')
|
||||
return TRUE;
|
||||
cp = path;
|
||||
while ((cp = strstr(cp, "/.")) != NULL) {
|
||||
cp += 2;
|
||||
if (*cp == '.')
|
||||
cp++;
|
||||
if (cp[0] == '/' || cp[0] == '\0')
|
||||
return TRUE;
|
||||
return true;
|
||||
p = path;
|
||||
while ((p = strstr(p, "/.")) != NULL) {
|
||||
p += 2;
|
||||
if (*p == '.')
|
||||
p++;
|
||||
if (*p == '/' || *p == '\0')
|
||||
return true;
|
||||
}
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -388,7 +388,7 @@ MainParseArgChdir(const char *argvalue)
|
||||
sa.st_ino == sb.st_ino &&
|
||||
sa.st_dev == sb.st_dev)
|
||||
strncpy(curdir, argvalue, MAXPATHLEN);
|
||||
ignorePWD = TRUE;
|
||||
ignorePWD = true;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -411,7 +411,7 @@ MainParseArgJobsInternal(const char *argvalue)
|
||||
#endif
|
||||
jp_0 = -1;
|
||||
jp_1 = -1;
|
||||
opts.compatMake = TRUE;
|
||||
opts.compatMake = true;
|
||||
} else {
|
||||
Global_Append(MAKEFLAGS, "-J");
|
||||
Global_Append(MAKEFLAGS, argvalue);
|
||||
@ -423,7 +423,7 @@ MainParseArgJobs(const char *argvalue)
|
||||
{
|
||||
char *p;
|
||||
|
||||
forceJobs = TRUE;
|
||||
forceJobs = true;
|
||||
opts.maxJobs = (int)strtol(argvalue, &p, 0);
|
||||
if (*p != '\0' || opts.maxJobs < 1) {
|
||||
(void)fprintf(stderr,
|
||||
@ -454,14 +454,14 @@ MainParseArgSysInc(const char *argvalue)
|
||||
Global_Append(MAKEFLAGS, argvalue);
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
MainParseArg(char c, const char *argvalue)
|
||||
{
|
||||
switch (c) {
|
||||
case '\0':
|
||||
break;
|
||||
case 'B':
|
||||
opts.compatMake = TRUE;
|
||||
opts.compatMake = true;
|
||||
Global_Append(MAKEFLAGS, "-B");
|
||||
Global_Set(MAKE_MODE, "compat");
|
||||
break;
|
||||
@ -469,7 +469,7 @@ MainParseArg(char c, const char *argvalue)
|
||||
MainParseArgChdir(argvalue);
|
||||
break;
|
||||
case 'D':
|
||||
if (argvalue[0] == '\0') return FALSE;
|
||||
if (argvalue[0] == '\0') return false;
|
||||
Global_SetExpand(argvalue, "1");
|
||||
Global_Append(MAKEFLAGS, "-D");
|
||||
Global_Append(MAKEFLAGS, argvalue);
|
||||
@ -483,12 +483,12 @@ MainParseArg(char c, const char *argvalue)
|
||||
MainParseArgJobsInternal(argvalue);
|
||||
break;
|
||||
case 'N':
|
||||
opts.noExecute = TRUE;
|
||||
opts.noRecursiveExecute = TRUE;
|
||||
opts.noExecute = true;
|
||||
opts.noRecursiveExecute = true;
|
||||
Global_Append(MAKEFLAGS, "-N");
|
||||
break;
|
||||
case 'S':
|
||||
opts.keepgoing = FALSE;
|
||||
opts.keepgoing = false;
|
||||
Global_Append(MAKEFLAGS, "-S");
|
||||
break;
|
||||
case 'T':
|
||||
@ -505,11 +505,11 @@ MainParseArg(char c, const char *argvalue)
|
||||
Global_Append(MAKEFLAGS, argvalue);
|
||||
break;
|
||||
case 'W':
|
||||
opts.parseWarnFatal = TRUE;
|
||||
opts.parseWarnFatal = true;
|
||||
/* XXX: why no Var_Append? */
|
||||
break;
|
||||
case 'X':
|
||||
opts.varNoExportEnv = TRUE;
|
||||
opts.varNoExportEnv = true;
|
||||
Global_Append(MAKEFLAGS, "-X");
|
||||
break;
|
||||
case 'd':
|
||||
@ -523,21 +523,21 @@ MainParseArg(char c, const char *argvalue)
|
||||
MainParseArgDebug(argvalue);
|
||||
break;
|
||||
case 'e':
|
||||
opts.checkEnvFirst = TRUE;
|
||||
opts.checkEnvFirst = true;
|
||||
Global_Append(MAKEFLAGS, "-e");
|
||||
break;
|
||||
case 'f':
|
||||
Lst_Append(&opts.makefiles, bmake_strdup(argvalue));
|
||||
break;
|
||||
case 'i':
|
||||
opts.ignoreErrors = TRUE;
|
||||
opts.ignoreErrors = true;
|
||||
Global_Append(MAKEFLAGS, "-i");
|
||||
break;
|
||||
case 'j':
|
||||
MainParseArgJobs(argvalue);
|
||||
break;
|
||||
case 'k':
|
||||
opts.keepgoing = TRUE;
|
||||
opts.keepgoing = true;
|
||||
Global_Append(MAKEFLAGS, "-k");
|
||||
break;
|
||||
case 'm':
|
||||
@ -545,35 +545,35 @@ MainParseArg(char c, const char *argvalue)
|
||||
/* XXX: why no Var_Append? */
|
||||
break;
|
||||
case 'n':
|
||||
opts.noExecute = TRUE;
|
||||
opts.noExecute = true;
|
||||
Global_Append(MAKEFLAGS, "-n");
|
||||
break;
|
||||
case 'q':
|
||||
opts.queryFlag = TRUE;
|
||||
opts.queryFlag = true;
|
||||
/* Kind of nonsensical, wot? */
|
||||
Global_Append(MAKEFLAGS, "-q");
|
||||
break;
|
||||
case 'r':
|
||||
opts.noBuiltins = TRUE;
|
||||
opts.noBuiltins = true;
|
||||
Global_Append(MAKEFLAGS, "-r");
|
||||
break;
|
||||
case 's':
|
||||
opts.beSilent = TRUE;
|
||||
opts.beSilent = true;
|
||||
Global_Append(MAKEFLAGS, "-s");
|
||||
break;
|
||||
case 't':
|
||||
opts.touchFlag = TRUE;
|
||||
opts.touchFlag = true;
|
||||
Global_Append(MAKEFLAGS, "-t");
|
||||
break;
|
||||
case 'w':
|
||||
opts.enterFlag = TRUE;
|
||||
opts.enterFlag = true;
|
||||
Global_Append(MAKEFLAGS, "-w");
|
||||
break;
|
||||
default:
|
||||
case '?':
|
||||
usage();
|
||||
}
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -592,13 +592,13 @@ MainParseArgs(int argc, char **argv)
|
||||
int arginc;
|
||||
char *argvalue;
|
||||
char *optscan;
|
||||
Boolean inOption, dashDash = FALSE;
|
||||
bool inOption, dashDash = false;
|
||||
|
||||
const char *optspecs = "BC:D:I:J:NST:V:WXd:ef:ij:km:nqrstv:w";
|
||||
/* Can't actually use getopt(3) because rescanning is not portable */
|
||||
|
||||
rearg:
|
||||
inOption = FALSE;
|
||||
inOption = false;
|
||||
optscan = NULL;
|
||||
while (argc > 1) {
|
||||
const char *optspec;
|
||||
@ -610,20 +610,20 @@ MainParseArgs(int argc, char **argv)
|
||||
if (c == '\0') {
|
||||
argv++;
|
||||
argc--;
|
||||
inOption = FALSE;
|
||||
inOption = false;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (c != '-' || dashDash)
|
||||
break;
|
||||
inOption = TRUE;
|
||||
inOption = true;
|
||||
c = *optscan++;
|
||||
}
|
||||
/* '-' found at some earlier point */
|
||||
optspec = strchr(optspecs, c);
|
||||
if (c != '\0' && optspec != NULL && optspec[1] == ':') {
|
||||
/* -<something> found, and <something> should have an arg */
|
||||
inOption = FALSE;
|
||||
inOption = false;
|
||||
arginc = 1;
|
||||
argvalue = optscan;
|
||||
if (*argvalue == '\0') {
|
||||
@ -638,10 +638,10 @@ MainParseArgs(int argc, char **argv)
|
||||
switch (c) {
|
||||
case '\0':
|
||||
arginc = 1;
|
||||
inOption = FALSE;
|
||||
inOption = false;
|
||||
break;
|
||||
case '-':
|
||||
dashDash = TRUE;
|
||||
dashDash = true;
|
||||
break;
|
||||
default:
|
||||
if (!MainParseArg(c, argvalue))
|
||||
@ -659,7 +659,7 @@ MainParseArgs(int argc, char **argv)
|
||||
for (; argc > 1; argv++, argc--) {
|
||||
VarAssign var;
|
||||
if (Parse_IsVar(argv[1], &var)) {
|
||||
Parse_DoVar(&var, SCOPE_CMDLINE);
|
||||
Parse_Var(&var, SCOPE_CMDLINE);
|
||||
} else {
|
||||
if (argv[1][0] == '\0')
|
||||
Punt("illegal (null) argument.");
|
||||
@ -716,7 +716,7 @@ Main_ParseArgLine(const char *line)
|
||||
FStr_Done(&argv0);
|
||||
}
|
||||
|
||||
words = Str_Words(buf, TRUE);
|
||||
words = Str_Words(buf, true);
|
||||
if (words.words == NULL) {
|
||||
Error("Unterminated quoted string [%s]", buf);
|
||||
free(buf);
|
||||
@ -728,14 +728,14 @@ Main_ParseArgLine(const char *line)
|
||||
Words_Free(words);
|
||||
}
|
||||
|
||||
Boolean
|
||||
Main_SetObjdir(Boolean writable, const char *fmt, ...)
|
||||
bool
|
||||
Main_SetObjdir(bool writable, const char *fmt, ...)
|
||||
{
|
||||
struct stat sb;
|
||||
char *path;
|
||||
char buf[MAXPATHLEN + 1];
|
||||
char buf2[MAXPATHLEN + 1];
|
||||
Boolean rc = FALSE;
|
||||
bool rc = false;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
@ -759,24 +759,24 @@ Main_SetObjdir(Boolean writable, const char *fmt, ...)
|
||||
setenv("PWD", objdir, 1);
|
||||
Dir_InitDot();
|
||||
purge_relative_cached_realpaths();
|
||||
rc = TRUE;
|
||||
rc = true;
|
||||
if (opts.enterFlag && strcmp(objdir, curdir) != 0)
|
||||
enterFlagObj = TRUE;
|
||||
enterFlagObj = true;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static Boolean
|
||||
SetVarObjdir(Boolean writable, const char *var, const char *suffix)
|
||||
static bool
|
||||
SetVarObjdir(bool writable, const char *var, const char *suffix)
|
||||
{
|
||||
FStr path = Var_Value(SCOPE_CMDLINE, var);
|
||||
FStr xpath;
|
||||
|
||||
if (path.str == NULL || path.str[0] == '\0') {
|
||||
FStr_Done(&path);
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* expand variable substitutions */
|
||||
@ -792,7 +792,7 @@ SetVarObjdir(Boolean writable, const char *var, const char *suffix)
|
||||
|
||||
FStr_Done(&xpath);
|
||||
FStr_Done(&path);
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -841,8 +841,8 @@ MakeMode(void)
|
||||
|
||||
if (mode[0] != '\0') {
|
||||
if (strstr(mode, "compat") != NULL) {
|
||||
opts.compatMake = TRUE;
|
||||
forceJobs = FALSE;
|
||||
opts.compatMake = true;
|
||||
forceJobs = false;
|
||||
}
|
||||
#if USE_META
|
||||
if (strstr(mode, "meta") != NULL)
|
||||
@ -854,7 +854,7 @@ MakeMode(void)
|
||||
}
|
||||
|
||||
static void
|
||||
PrintVar(const char *varname, Boolean expandVars)
|
||||
PrintVar(const char *varname, bool expandVars)
|
||||
{
|
||||
if (strchr(varname, '$') != NULL) {
|
||||
char *evalue;
|
||||
@ -880,24 +880,22 @@ PrintVar(const char *varname, Boolean expandVars)
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a Boolean based on a variable.
|
||||
* Return a bool based on a variable.
|
||||
*
|
||||
* If the knob is not set, return the fallback.
|
||||
* If set, anything that looks or smells like "No", "False", "Off", "0", etc.
|
||||
* is FALSE, otherwise TRUE.
|
||||
* is false, otherwise true.
|
||||
*/
|
||||
Boolean
|
||||
GetBooleanVar(const char *varname, Boolean fallback)
|
||||
bool
|
||||
GetBooleanExpr(const char *expr, bool fallback)
|
||||
{
|
||||
char *expr = str_concat3("${", varname, ":U}");
|
||||
char *value;
|
||||
Boolean res;
|
||||
bool res;
|
||||
|
||||
(void)Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES, &value);
|
||||
/* TODO: handle errors */
|
||||
res = ParseBoolean(value, fallback);
|
||||
free(value);
|
||||
free(expr);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -905,14 +903,15 @@ static void
|
||||
doPrintVars(void)
|
||||
{
|
||||
StringListNode *ln;
|
||||
Boolean expandVars;
|
||||
bool expandVars;
|
||||
|
||||
if (opts.printVars == PVM_EXPANDED)
|
||||
expandVars = TRUE;
|
||||
expandVars = true;
|
||||
else if (opts.debugVflag)
|
||||
expandVars = FALSE;
|
||||
expandVars = false;
|
||||
else
|
||||
expandVars = GetBooleanVar(".MAKE.EXPAND_VARIABLES", FALSE);
|
||||
expandVars = GetBooleanExpr("${.MAKE.EXPAND_VARIABLES}",
|
||||
false);
|
||||
|
||||
for (ln = opts.variables.first; ln != NULL; ln = ln->next) {
|
||||
const char *varname = ln->datum;
|
||||
@ -920,11 +919,11 @@ doPrintVars(void)
|
||||
}
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
runTargets(void)
|
||||
{
|
||||
GNodeList targs = LST_INIT; /* target nodes to create */
|
||||
Boolean outOfDate; /* FALSE if all targets up to date */
|
||||
bool outOfDate; /* false if all targets up to date */
|
||||
|
||||
/*
|
||||
* Have now read the entire graph and need to make a list of
|
||||
@ -947,7 +946,7 @@ runTargets(void)
|
||||
*/
|
||||
if (!opts.queryFlag) {
|
||||
Job_Init();
|
||||
jobsRunning = TRUE;
|
||||
jobsRunning = true;
|
||||
}
|
||||
|
||||
/* Traverse the graph, checking on all the targets */
|
||||
@ -958,7 +957,7 @@ runTargets(void)
|
||||
* targets as well as initializing the module.
|
||||
*/
|
||||
Compat_Run(&targs);
|
||||
outOfDate = FALSE;
|
||||
outOfDate = false;
|
||||
}
|
||||
Lst_Done(&targs); /* Don't free the targets themselves. */
|
||||
return outOfDate;
|
||||
@ -1110,11 +1109,11 @@ HandlePWD(const struct stat *curdir_st)
|
||||
static void
|
||||
InitObjdir(const char *machine, const char *machine_arch)
|
||||
{
|
||||
Boolean writable;
|
||||
bool writable;
|
||||
|
||||
Dir_InitCur(curdir);
|
||||
writable = GetBooleanVar("MAKE_OBJDIR_CHECK_WRITABLE", TRUE);
|
||||
(void)Main_SetObjdir(FALSE, "%s", curdir);
|
||||
writable = GetBooleanExpr("${MAKE_OBJDIR_CHECK_WRITABLE}", true);
|
||||
(void)Main_SetObjdir(false, "%s", curdir);
|
||||
|
||||
if (!SetVarObjdir(writable, "MAKEOBJDIRPREFIX", curdir) &&
|
||||
!SetVarObjdir(writable, "MAKEOBJDIR", "") &&
|
||||
@ -1141,27 +1140,27 @@ UnlimitFiles(void)
|
||||
static void
|
||||
CmdOpts_Init(void)
|
||||
{
|
||||
opts.compatMake = FALSE;
|
||||
opts.compatMake = false;
|
||||
opts.debug = DEBUG_NONE;
|
||||
/* opts.debug_file has already been initialized earlier */
|
||||
opts.strict = FALSE;
|
||||
opts.debugVflag = FALSE;
|
||||
opts.checkEnvFirst = FALSE;
|
||||
opts.strict = false;
|
||||
opts.debugVflag = false;
|
||||
opts.checkEnvFirst = false;
|
||||
Lst_Init(&opts.makefiles);
|
||||
opts.ignoreErrors = FALSE; /* Pay attention to non-zero returns */
|
||||
opts.ignoreErrors = false; /* Pay attention to non-zero returns */
|
||||
opts.maxJobs = 1;
|
||||
opts.keepgoing = FALSE; /* Stop on error */
|
||||
opts.noRecursiveExecute = FALSE; /* Execute all .MAKE targets */
|
||||
opts.noExecute = FALSE; /* Execute all commands */
|
||||
opts.queryFlag = FALSE;
|
||||
opts.noBuiltins = FALSE; /* Read the built-in rules */
|
||||
opts.beSilent = FALSE; /* Print commands as executed */
|
||||
opts.touchFlag = FALSE;
|
||||
opts.keepgoing = false; /* Stop on error */
|
||||
opts.noRecursiveExecute = false; /* Execute all .MAKE targets */
|
||||
opts.noExecute = false; /* Execute all commands */
|
||||
opts.queryFlag = false;
|
||||
opts.noBuiltins = false; /* Read the built-in rules */
|
||||
opts.beSilent = false; /* Print commands as executed */
|
||||
opts.touchFlag = false;
|
||||
opts.printVars = PVM_NONE;
|
||||
Lst_Init(&opts.variables);
|
||||
opts.parseWarnFatal = FALSE;
|
||||
opts.enterFlag = FALSE;
|
||||
opts.varNoExportEnv = FALSE;
|
||||
opts.parseWarnFatal = false;
|
||||
opts.enterFlag = false;
|
||||
opts.varNoExportEnv = false;
|
||||
Lst_Init(&opts.create);
|
||||
}
|
||||
|
||||
@ -1286,7 +1285,7 @@ InitMaxJobs(void)
|
||||
|
||||
opts.maxJobs = n;
|
||||
maxJobTokens = opts.maxJobs;
|
||||
forceJobs = TRUE;
|
||||
forceJobs = true;
|
||||
free(value);
|
||||
}
|
||||
|
||||
@ -1427,12 +1426,12 @@ main_Init(int argc, char **argv)
|
||||
Global_Set(MAKE_DEPENDFILE, ".depend");
|
||||
|
||||
CmdOpts_Init();
|
||||
allPrecious = FALSE; /* Remove targets when interrupted */
|
||||
deleteOnError = FALSE; /* Historical default behavior */
|
||||
jobsRunning = FALSE;
|
||||
allPrecious = false; /* Remove targets when interrupted */
|
||||
deleteOnError = false; /* Historical default behavior */
|
||||
jobsRunning = false;
|
||||
|
||||
maxJobTokens = opts.maxJobs;
|
||||
ignorePWD = FALSE;
|
||||
ignorePWD = false;
|
||||
|
||||
/*
|
||||
* Initialize the parsing, directory and variable modules to prepare
|
||||
@ -1575,9 +1574,9 @@ main_PrepareMaking(void)
|
||||
SCOPE_CMDLINE, VARE_WANTRES, &makeDependfile);
|
||||
if (makeDependfile[0] != '\0') {
|
||||
/* TODO: handle errors */
|
||||
doing_depend = TRUE;
|
||||
doing_depend = true;
|
||||
(void)ReadMakefile(makeDependfile);
|
||||
doing_depend = FALSE;
|
||||
doing_depend = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1599,7 +1598,7 @@ main_PrepareMaking(void)
|
||||
* turn compatibility on.
|
||||
*/
|
||||
if (!opts.compatMake && !forceJobs)
|
||||
opts.compatMake = TRUE;
|
||||
opts.compatMake = true;
|
||||
|
||||
if (!opts.compatMake)
|
||||
Job_ServerStart(maxJobTokens, jp_0, jp_1);
|
||||
@ -1607,7 +1606,7 @@ main_PrepareMaking(void)
|
||||
jp_0, jp_1, opts.maxJobs, maxJobTokens, opts.compatMake ? 1 : 0);
|
||||
|
||||
if (opts.printVars == PVM_NONE)
|
||||
Main_ExportMAKEFLAGS(TRUE); /* initial export */
|
||||
Main_ExportMAKEFLAGS(true); /* initial export */
|
||||
|
||||
InitVpath();
|
||||
|
||||
@ -1615,7 +1614,7 @@ main_PrepareMaking(void)
|
||||
* Now that all search paths have been read for suffixes et al, it's
|
||||
* time to add the default search path to their lists...
|
||||
*/
|
||||
Suff_DoPaths();
|
||||
Suff_ExtendPaths();
|
||||
|
||||
/*
|
||||
* Propagate attributes through :: dependency lists.
|
||||
@ -1632,13 +1631,13 @@ main_PrepareMaking(void)
|
||||
* If the -v or -V options are given, print variables instead.
|
||||
* Return whether any of the targets is out-of-date.
|
||||
*/
|
||||
static Boolean
|
||||
static bool
|
||||
main_Run(void)
|
||||
{
|
||||
if (opts.printVars != PVM_NONE) {
|
||||
/* print the values of any variables requested by the user */
|
||||
doPrintVars();
|
||||
return FALSE;
|
||||
return false;
|
||||
} else {
|
||||
return runTargets();
|
||||
}
|
||||
@ -1684,7 +1683,7 @@ main_CleanUp(void)
|
||||
|
||||
/* Determine the exit code. */
|
||||
static int
|
||||
main_Exit(Boolean outOfDate)
|
||||
main_Exit(bool outOfDate)
|
||||
{
|
||||
if (opts.strict && (main_errors > 0 || Parse_GetFatals() > 0))
|
||||
return 2; /* Not 1 so -q can distinguish error */
|
||||
@ -1694,7 +1693,7 @@ main_Exit(Boolean outOfDate)
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
Boolean outOfDate;
|
||||
bool outOfDate;
|
||||
|
||||
main_Init(argc, argv);
|
||||
main_ReadFiles();
|
||||
@ -1862,7 +1861,7 @@ Cmd_Exec(const char *cmd, const char **errfmt)
|
||||
|
||||
/* Wait for the process to exit. */
|
||||
while ((pid = waitpid(cpid, &status, 0)) != cpid && pid >= 0)
|
||||
JobReapChild(pid, status, FALSE);
|
||||
JobReapChild(pid, status, false);
|
||||
|
||||
res_len = buf.len;
|
||||
res = Buf_DoneData(&buf);
|
||||
@ -2107,13 +2106,14 @@ cached_realpath(const char *pathname, char *resolved)
|
||||
* Return true if we should die without noise.
|
||||
* For example our failing child was a sub-make or failure happened elsewhere.
|
||||
*/
|
||||
Boolean
|
||||
bool
|
||||
shouldDieQuietly(GNode *gn, int bf)
|
||||
{
|
||||
static int quietly = -1;
|
||||
|
||||
if (quietly < 0) {
|
||||
if (DEBUG(JOB) || !GetBooleanVar(".MAKE.DIE_QUIETLY", TRUE))
|
||||
if (DEBUG(JOB) ||
|
||||
!GetBooleanExpr("${.MAKE.DIE_QUIETLY}", true))
|
||||
quietly = 0;
|
||||
else if (bf >= 0)
|
||||
quietly = bf;
|
||||
@ -2193,15 +2193,15 @@ PrintOnError(GNode *gn, const char *msg)
|
||||
}
|
||||
|
||||
void
|
||||
Main_ExportMAKEFLAGS(Boolean first)
|
||||
Main_ExportMAKEFLAGS(bool first)
|
||||
{
|
||||
static Boolean once = TRUE;
|
||||
static bool once = true;
|
||||
const char *expr;
|
||||
char *s;
|
||||
|
||||
if (once != first)
|
||||
return;
|
||||
once = FALSE;
|
||||
once = false;
|
||||
|
||||
expr = "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}";
|
||||
(void)Var_Subst(expr, SCOPE_CMDLINE, VARE_WANTRES, &s);
|
||||
@ -2225,7 +2225,7 @@ getTmpdir(void)
|
||||
return tmpdir;
|
||||
|
||||
/* Honor $TMPDIR but only if it is valid. Ensure it ends with '/'. */
|
||||
(void)Var_Subst("${TMPDIR:tA:U" _PATH_TMP "}/",
|
||||
(void)Var_Subst("${TMPDIR:tA:U" _PATH_TMP ":S,/$,,W}/",
|
||||
SCOPE_GLOBAL, VARE_WANTRES, &tmpdir);
|
||||
/* TODO: handle errors */
|
||||
|
||||
@ -2272,18 +2272,18 @@ mkTempFile(const char *pattern, char *tfile, size_t tfile_sz)
|
||||
|
||||
/*
|
||||
* Convert a string representation of a boolean into a boolean value.
|
||||
* Anything that looks like "No", "False", "Off", "0" etc. is FALSE,
|
||||
* the empty string is the fallback, everything else is TRUE.
|
||||
* Anything that looks like "No", "False", "Off", "0" etc. is false,
|
||||
* the empty string is the fallback, everything else is true.
|
||||
*/
|
||||
Boolean
|
||||
ParseBoolean(const char *s, Boolean fallback)
|
||||
bool
|
||||
ParseBoolean(const char *s, bool fallback)
|
||||
{
|
||||
char ch = ch_tolower(s[0]);
|
||||
if (ch == '\0')
|
||||
return fallback;
|
||||
if (ch == '0' || ch == 'f' || ch == 'n')
|
||||
return FALSE;
|
||||
return false;
|
||||
if (ch == 'o')
|
||||
return ch_tolower(s[1]) != 'f';
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
91
make.c
91
make.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: make.c,v 1.242 2021/02/05 05:15:12 rillig Exp $ */
|
||||
/* $NetBSD: make.c,v 1.244 2021/04/04 10:05:08 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -72,7 +72,7 @@
|
||||
* Examination of targets and their suitability for creation.
|
||||
*
|
||||
* Interface:
|
||||
* Make_Run Initialize things for the module. Returns TRUE if
|
||||
* Make_Run Initialize things for the module. Returns true if
|
||||
* work was (or would have been) done.
|
||||
*
|
||||
* Make_Update After a target is made, update all its parents.
|
||||
@ -85,7 +85,8 @@
|
||||
* Update the node's youngestChild field based on the
|
||||
* child's modification time.
|
||||
*
|
||||
* Make_DoAllVar Set up the various local variables for a
|
||||
* GNode_SetLocalVars
|
||||
* Set up the various local variables for a
|
||||
* target, including the .ALLSRC variable, making
|
||||
* sure that any variable that needs to exist
|
||||
* at the very least has the empty value.
|
||||
@ -103,7 +104,7 @@
|
||||
#include "job.h"
|
||||
|
||||
/* "@(#)make.c 8.1 (Berkeley) 6/6/93" */
|
||||
MAKE_RCSID("$NetBSD: make.c,v 1.242 2021/02/05 05:15:12 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: make.c,v 1.244 2021/04/04 10:05:08 rillig Exp $");
|
||||
|
||||
/* Sequence # to detect recursion. */
|
||||
static unsigned int checked_seqno = 1;
|
||||
@ -168,7 +169,7 @@ GNode_FprintDetails(FILE *f, const char *prefix, const GNode *gn,
|
||||
suffix);
|
||||
}
|
||||
|
||||
Boolean
|
||||
bool
|
||||
GNode_ShouldExecute(GNode *gn)
|
||||
{
|
||||
return !((gn->type & OP_MAKE)
|
||||
@ -184,7 +185,7 @@ GNode_UpdateYoungestChild(GNode *gn, GNode *cgn)
|
||||
gn->youngestChild = cgn;
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
IsOODateRegular(GNode *gn)
|
||||
{
|
||||
/* These rules are inherited from the original Make. */
|
||||
@ -193,22 +194,22 @@ IsOODateRegular(GNode *gn)
|
||||
if (gn->mtime < gn->youngestChild->mtime) {
|
||||
DEBUG1(MAKE, "modified before source \"%s\"...",
|
||||
GNode_Path(gn->youngestChild));
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gn->mtime == 0 && !(gn->type & OP_OPTIONAL)) {
|
||||
DEBUG0(MAKE, "nonexistent and no sources...");
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (gn->type & OP_DOUBLEDEP) {
|
||||
DEBUG0(MAKE, ":: operator and no sources...");
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -223,17 +224,17 @@ IsOODateRegular(GNode *gn)
|
||||
* The mtime field of the node and the youngestChild field of its parents
|
||||
* may be changed.
|
||||
*/
|
||||
Boolean
|
||||
bool
|
||||
GNode_IsOODate(GNode *gn)
|
||||
{
|
||||
Boolean oodate;
|
||||
bool oodate;
|
||||
|
||||
/*
|
||||
* Certain types of targets needn't even be sought as their datedness
|
||||
* doesn't depend on their modification time...
|
||||
*/
|
||||
if (!(gn->type & (OP_JOIN | OP_USE | OP_USEBEFORE | OP_EXEC))) {
|
||||
Dir_UpdateMTime(gn, TRUE);
|
||||
Dir_UpdateMTime(gn, true);
|
||||
if (DEBUG(MAKE)) {
|
||||
if (gn->mtime != 0)
|
||||
debug_printf("modified %s...",
|
||||
@ -267,7 +268,7 @@ GNode_IsOODate(GNode *gn)
|
||||
* no matter *what*.
|
||||
*/
|
||||
DEBUG0(MAKE, ".USE node...");
|
||||
oodate = FALSE;
|
||||
oodate = false;
|
||||
} else if ((gn->type & OP_LIB) && (gn->mtime == 0 || Arch_IsLib(gn))) {
|
||||
DEBUG0(MAKE, "library...");
|
||||
|
||||
@ -302,9 +303,9 @@ GNode_IsOODate(GNode *gn)
|
||||
debug_printf(".EXEC node...");
|
||||
}
|
||||
}
|
||||
oodate = TRUE;
|
||||
oodate = true;
|
||||
} else if (IsOODateRegular(gn)) {
|
||||
oodate = TRUE;
|
||||
oodate = true;
|
||||
} else {
|
||||
/*
|
||||
* When a nonexistent child with no sources
|
||||
@ -351,7 +352,7 @@ PretendAllChildrenAreMade(GNode *pgn)
|
||||
GNode *cgn = ln->datum;
|
||||
|
||||
/* This may also update cgn->path. */
|
||||
Dir_UpdateMTime(cgn, FALSE);
|
||||
Dir_UpdateMTime(cgn, false);
|
||||
GNode_UpdateYoungestChild(pgn, cgn);
|
||||
pgn->unmade--;
|
||||
}
|
||||
@ -443,7 +444,7 @@ Make_HandleUse(GNode *cgn, GNode *pgn)
|
||||
static void
|
||||
MakeHandleUse(GNode *cgn, GNode *pgn, GNodeListNode *ln)
|
||||
{
|
||||
Boolean unmarked;
|
||||
bool unmarked;
|
||||
|
||||
unmarked = !(cgn->type & OP_MARK);
|
||||
cgn->type |= OP_MARK;
|
||||
@ -485,7 +486,7 @@ Make_Recheck(GNode *gn)
|
||||
{
|
||||
time_t mtime;
|
||||
|
||||
Dir_UpdateMTime(gn, TRUE);
|
||||
Dir_UpdateMTime(gn, true);
|
||||
mtime = gn->mtime;
|
||||
|
||||
#ifndef RECHECK
|
||||
@ -576,7 +577,7 @@ UpdateImplicitParentsVars(GNode *cgn, const char *cname)
|
||||
}
|
||||
|
||||
/* See if a .ORDER rule stops us from building this node. */
|
||||
static Boolean
|
||||
static bool
|
||||
IsWaitingForOrder(GNode *gn)
|
||||
{
|
||||
GNodeListNode *ln;
|
||||
@ -590,9 +591,9 @@ IsWaitingForOrder(GNode *gn)
|
||||
DEBUG2(MAKE,
|
||||
"IsWaitingForOrder: Waiting for .ORDER node \"%s%s\"\n",
|
||||
ogn->name, ogn->cohort_num);
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void MakeBuildParent(GNode *, GNodeListNode *);
|
||||
@ -868,7 +869,7 @@ MakeAddAllSrc(GNode *cgn, GNode *pgn)
|
||||
* match its ALLSRC variable.
|
||||
*/
|
||||
void
|
||||
Make_DoAllVar(GNode *gn)
|
||||
GNode_SetLocalVars(GNode *gn)
|
||||
{
|
||||
GNodeListNode *ln;
|
||||
|
||||
@ -889,7 +890,7 @@ Make_DoAllVar(GNode *gn)
|
||||
gn->flags |= DONE_ALLSRC;
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
MakeBuildChild(GNode *cn, GNodeListNode *toBeMadeNext)
|
||||
{
|
||||
|
||||
@ -899,13 +900,13 @@ MakeBuildChild(GNode *cn, GNodeListNode *toBeMadeNext)
|
||||
GNode_FprintDetails(opts.debug_file, "", cn, "\n");
|
||||
}
|
||||
if (GNode_IsReady(cn))
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
/* If this node is on the RHS of a .ORDER, check LHSs. */
|
||||
if (IsWaitingForOrder(cn)) {
|
||||
/* Can't build this (or anything else in this child list) yet */
|
||||
cn->made = DEFERRED;
|
||||
return FALSE; /* but keep looking */
|
||||
return false; /* but keep looking */
|
||||
}
|
||||
|
||||
DEBUG2(MAKE, "MakeBuildChild: schedule %s%s\n",
|
||||
@ -961,13 +962,13 @@ MakeChildren(GNode *gn)
|
||||
*
|
||||
* If the -q option was given, no job will be started,
|
||||
* but as soon as an out-of-date target is found, this function
|
||||
* returns TRUE. In all other cases, this function returns FALSE.
|
||||
* returns true. In all other cases, this function returns false.
|
||||
*/
|
||||
static Boolean
|
||||
static bool
|
||||
MakeStartJobs(void)
|
||||
{
|
||||
GNode *gn;
|
||||
Boolean have_token = FALSE;
|
||||
bool have_token = false;
|
||||
|
||||
while (!Lst_IsEmpty(&toBeMade)) {
|
||||
/*
|
||||
@ -976,7 +977,7 @@ MakeStartJobs(void)
|
||||
*/
|
||||
if (!have_token && !Job_TokenWithdraw())
|
||||
break;
|
||||
have_token = TRUE;
|
||||
have_token = true;
|
||||
|
||||
gn = Lst_Dequeue(&toBeMade);
|
||||
DEBUG2(MAKE, "Examining %s%s...\n", gn->name, gn->cohort_num);
|
||||
@ -1022,10 +1023,10 @@ MakeStartJobs(void)
|
||||
if (GNode_IsOODate(gn)) {
|
||||
DEBUG0(MAKE, "out-of-date\n");
|
||||
if (opts.queryFlag)
|
||||
return TRUE;
|
||||
Make_DoAllVar(gn);
|
||||
return true;
|
||||
GNode_SetLocalVars(gn);
|
||||
Job_Make(gn);
|
||||
have_token = FALSE;
|
||||
have_token = false;
|
||||
} else {
|
||||
DEBUG0(MAKE, "up-to-date\n");
|
||||
gn->made = UPTODATE;
|
||||
@ -1037,7 +1038,7 @@ MakeStartJobs(void)
|
||||
* for .TARGET when building up the local
|
||||
* variables of its parent(s)...
|
||||
*/
|
||||
Make_DoAllVar(gn);
|
||||
GNode_SetLocalVars(gn);
|
||||
}
|
||||
Make_Update(gn);
|
||||
}
|
||||
@ -1046,7 +1047,7 @@ MakeStartJobs(void)
|
||||
if (have_token)
|
||||
Job_TokenReturn();
|
||||
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Print the status of a .ORDER node. */
|
||||
@ -1081,7 +1082,7 @@ static void MakePrintStatusList(GNodeList *, int *);
|
||||
* Print the status of a top-level node, viz. it being up-to-date already
|
||||
* or not created due to an error in a lower level.
|
||||
*/
|
||||
static Boolean
|
||||
static bool
|
||||
MakePrintStatus(GNode *gn, int *errors)
|
||||
{
|
||||
if (gn->flags & DONECYCLE) {
|
||||
@ -1089,7 +1090,7 @@ MakePrintStatus(GNode *gn, int *errors)
|
||||
* We've completely processed this node before, don't do
|
||||
* it again.
|
||||
*/
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gn->unmade == 0) {
|
||||
@ -1128,7 +1129,7 @@ MakePrintStatus(GNode *gn, int *errors)
|
||||
gn->name, gn->cohort_num);
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG3(MAKE, "MakePrintStatus: %s%s has %d unmade children\n",
|
||||
@ -1143,7 +1144,7 @@ MakePrintStatus(GNode *gn, int *errors)
|
||||
MakePrintStatusList(&gn->children, errors);
|
||||
/* Mark that this node needn't be processed again */
|
||||
gn->flags |= DONECYCLE;
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Only output the error once per node */
|
||||
@ -1151,11 +1152,11 @@ MakePrintStatus(GNode *gn, int *errors)
|
||||
Error("Graph cycles through `%s%s'", gn->name, gn->cohort_num);
|
||||
if ((*errors)++ > 100)
|
||||
/* Abandon the whole error report */
|
||||
return TRUE;
|
||||
return true;
|
||||
|
||||
/* Reporting for our children will give the rest of the loop */
|
||||
MakePrintStatusList(&gn->children, errors);
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1243,7 +1244,7 @@ Make_ExpandUse(GNodeList *targs)
|
||||
*eon = ')';
|
||||
}
|
||||
|
||||
Dir_UpdateMTime(gn, FALSE);
|
||||
Dir_UpdateMTime(gn, false);
|
||||
Var_Set(gn, TARGET, GNode_Path(gn));
|
||||
UnmarkChildren(gn);
|
||||
HandleUseNodes(gn);
|
||||
@ -1364,14 +1365,14 @@ Make_ProcessWait(GNodeList *targs)
|
||||
* targs the initial list of targets
|
||||
*
|
||||
* Results:
|
||||
* TRUE if work was done. FALSE otherwise.
|
||||
* True if work was done, false otherwise.
|
||||
*
|
||||
* Side Effects:
|
||||
* The make field of all nodes involved in the creation of the given
|
||||
* targets is set to 1. The toBeMade list is set to contain all the
|
||||
* 'leaves' of these subgraphs.
|
||||
*/
|
||||
Boolean
|
||||
bool
|
||||
Make_Run(GNodeList *targs)
|
||||
{
|
||||
int errors; /* Number of errors the Job module reports */
|
||||
|
129
make.h
129
make.h
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: make.h,v 1.256 2021/02/05 19:19:17 sjg Exp $ */
|
||||
/* $NetBSD: make.h,v 1.263 2021/06/21 10:33:11 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -136,55 +136,30 @@
|
||||
#endif
|
||||
|
||||
#define MAKE_INLINE static inline MAKE_ATTR_UNUSED
|
||||
#define MAKE_STATIC static MAKE_ATTR_UNUSED
|
||||
|
||||
/*
|
||||
* A boolean type is defined as an integer, not an enum, for historic reasons.
|
||||
* The only allowed values are the constants TRUE and FALSE (1 and 0).
|
||||
*/
|
||||
#if defined(lint) || defined(USE_C99_BOOLEAN)
|
||||
#if __STDC_VERSION__ >= 199901L || defined(lint) || defined(USE_C99_BOOLEAN)
|
||||
#include <stdbool.h>
|
||||
typedef bool Boolean;
|
||||
#define FALSE false
|
||||
#define TRUE true
|
||||
#elif defined(USE_DOUBLE_BOOLEAN)
|
||||
/* During development, to find type mismatches in function declarations. */
|
||||
typedef double Boolean;
|
||||
#define TRUE 1.0
|
||||
#define FALSE 0.0
|
||||
#elif defined(USE_UCHAR_BOOLEAN)
|
||||
/*
|
||||
* During development, to find code that depends on the exact value of TRUE or
|
||||
* that stores other values in Boolean variables.
|
||||
*/
|
||||
typedef unsigned char Boolean;
|
||||
#define TRUE ((unsigned char)0xFF)
|
||||
#define FALSE ((unsigned char)0x00)
|
||||
#elif defined(USE_CHAR_BOOLEAN)
|
||||
/*
|
||||
* During development, to find code that uses a boolean as array index, via
|
||||
* -Wchar-subscripts.
|
||||
*/
|
||||
typedef char Boolean;
|
||||
#define TRUE ((char)-1)
|
||||
#define FALSE ((char)0x00)
|
||||
#elif defined(USE_ENUM_BOOLEAN)
|
||||
typedef enum Boolean { FALSE, TRUE } Boolean;
|
||||
#else
|
||||
typedef int Boolean;
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#ifndef bool
|
||||
typedef unsigned int Boolean;
|
||||
#define bool Boolean
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#ifndef true
|
||||
#define true 1
|
||||
#endif
|
||||
#ifndef false
|
||||
#define false 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "lst.h"
|
||||
#include "enum.h"
|
||||
#include "make_malloc.h"
|
||||
#include "str.h"
|
||||
#include "hash.h"
|
||||
#include "make-conf.h"
|
||||
#include "buf.h"
|
||||
#include "make_malloc.h"
|
||||
|
||||
/*
|
||||
* some vendors don't have this --sjg
|
||||
@ -247,6 +222,8 @@ typedef enum GNodeMade {
|
||||
* should be made.
|
||||
*
|
||||
* Some of the OP_ constants can be combined, others cannot.
|
||||
*
|
||||
* See the tests depsrc-*.mk and deptgt-*.mk.
|
||||
*/
|
||||
typedef enum GNodeType {
|
||||
OP_NONE = 0,
|
||||
@ -503,11 +480,11 @@ typedef enum CondEvalResult {
|
||||
*/
|
||||
|
||||
/* True if every target is precious */
|
||||
extern Boolean allPrecious;
|
||||
extern bool allPrecious;
|
||||
/* True if failed targets should be deleted */
|
||||
extern Boolean deleteOnError;
|
||||
/* TRUE while processing .depend */
|
||||
extern Boolean doing_depend;
|
||||
extern bool deleteOnError;
|
||||
/* true while processing .depend */
|
||||
extern bool doing_depend;
|
||||
/* .DEFAULT rule */
|
||||
extern GNode *defaultNode;
|
||||
|
||||
@ -606,7 +583,7 @@ void debug_printf(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2);
|
||||
do { \
|
||||
if (DEBUG(module)) \
|
||||
debug_printf args; \
|
||||
} while (/*CONSTCOND*/FALSE)
|
||||
} while (/*CONSTCOND*/false)
|
||||
|
||||
#define DEBUG0(module, text) \
|
||||
DEBUG_IMPL(module, ("%s", text))
|
||||
@ -630,7 +607,7 @@ typedef enum PrintVarsMode {
|
||||
/* Command line options */
|
||||
typedef struct CmdOpts {
|
||||
/* -B: whether we are make compatible */
|
||||
Boolean compatMake;
|
||||
bool compatMake;
|
||||
|
||||
/* -d: debug control: There is one bit per module. It is up to the
|
||||
* module what debug information to print. */
|
||||
@ -643,19 +620,19 @@ typedef struct CmdOpts {
|
||||
*
|
||||
* Runs make in strict mode, with additional checks and better error
|
||||
* handling. */
|
||||
Boolean strict;
|
||||
bool strict;
|
||||
|
||||
/* -dV: for the -V option, print unexpanded variable values */
|
||||
Boolean debugVflag;
|
||||
bool debugVflag;
|
||||
|
||||
/* -e: check environment variables before global variables */
|
||||
Boolean checkEnvFirst;
|
||||
bool checkEnvFirst;
|
||||
|
||||
/* -f: the makefiles to read */
|
||||
StringList makefiles;
|
||||
|
||||
/* -i: if true, ignore all errors from shell commands */
|
||||
Boolean ignoreErrors;
|
||||
bool ignoreErrors;
|
||||
|
||||
/* -j: the maximum number of jobs that can run in parallel;
|
||||
* this is coordinated with the submakes */
|
||||
@ -663,29 +640,29 @@ typedef struct CmdOpts {
|
||||
|
||||
/* -k: if true and an error occurs while making a node, continue
|
||||
* making nodes that do not depend on the erroneous node */
|
||||
Boolean keepgoing;
|
||||
bool keepgoing;
|
||||
|
||||
/* -N: execute no commands from the targets */
|
||||
Boolean noRecursiveExecute;
|
||||
bool noRecursiveExecute;
|
||||
|
||||
/* -n: execute almost no commands from the targets */
|
||||
Boolean noExecute;
|
||||
bool noExecute;
|
||||
|
||||
/*
|
||||
* -q: if true, do not really make anything, just see if the targets
|
||||
* are out-of-date
|
||||
*/
|
||||
Boolean queryFlag;
|
||||
bool queryFlag;
|
||||
|
||||
/* -r: raw mode, do not load the builtin rules. */
|
||||
Boolean noBuiltins;
|
||||
bool noBuiltins;
|
||||
|
||||
/* -s: don't echo the shell commands before executing them */
|
||||
Boolean beSilent;
|
||||
bool beSilent;
|
||||
|
||||
/* -t: touch the targets if they are out-of-date, but don't actually
|
||||
* make them */
|
||||
Boolean touchFlag;
|
||||
bool touchFlag;
|
||||
|
||||
/* -[Vv]: print expanded or unexpanded selected variables */
|
||||
PrintVarsMode printVars;
|
||||
@ -693,14 +670,14 @@ typedef struct CmdOpts {
|
||||
StringList variables;
|
||||
|
||||
/* -W: if true, makefile parsing warnings are treated as errors */
|
||||
Boolean parseWarnFatal;
|
||||
bool parseWarnFatal;
|
||||
|
||||
/* -w: print 'Entering' and 'Leaving' for submakes */
|
||||
Boolean enterFlag;
|
||||
bool enterFlag;
|
||||
|
||||
/* -X: if true, do not export variables set on the command line to the
|
||||
* environment. */
|
||||
Boolean varNoExportEnv;
|
||||
bool varNoExportEnv;
|
||||
|
||||
/* The target names specified on the command line.
|
||||
* Used to resolve .if make(...) statements. */
|
||||
@ -713,24 +690,24 @@ extern CmdOpts opts;
|
||||
#include "nonints.h"
|
||||
|
||||
void GNode_UpdateYoungestChild(GNode *, GNode *);
|
||||
Boolean GNode_IsOODate(GNode *);
|
||||
bool GNode_IsOODate(GNode *);
|
||||
void Make_ExpandUse(GNodeList *);
|
||||
time_t Make_Recheck(GNode *);
|
||||
void Make_HandleUse(GNode *, GNode *);
|
||||
void Make_Update(GNode *);
|
||||
void Make_DoAllVar(GNode *);
|
||||
Boolean Make_Run(GNodeList *);
|
||||
Boolean shouldDieQuietly(GNode *, int);
|
||||
void GNode_SetLocalVars(GNode *);
|
||||
bool Make_Run(GNodeList *);
|
||||
bool shouldDieQuietly(GNode *, int);
|
||||
void PrintOnError(GNode *, const char *);
|
||||
void Main_ExportMAKEFLAGS(Boolean);
|
||||
Boolean Main_SetObjdir(Boolean, const char *, ...) MAKE_ATTR_PRINTFLIKE(2, 3);
|
||||
void Main_ExportMAKEFLAGS(bool);
|
||||
bool Main_SetObjdir(bool, const char *, ...) MAKE_ATTR_PRINTFLIKE(2, 3);
|
||||
int mkTempFile(const char *, char *, size_t);
|
||||
int str2Lst_Append(StringList *, char *);
|
||||
void GNode_FprintDetails(FILE *, const char *, const GNode *, const char *);
|
||||
Boolean GNode_ShouldExecute(GNode *gn);
|
||||
bool GNode_ShouldExecute(GNode *gn);
|
||||
|
||||
/* See if the node was seen on the left-hand side of a dependency operator. */
|
||||
MAKE_INLINE Boolean
|
||||
MAKE_INLINE bool
|
||||
GNode_IsTarget(const GNode *gn)
|
||||
{
|
||||
return (gn->type & OP_OPMASK) != 0;
|
||||
@ -742,25 +719,25 @@ GNode_Path(const GNode *gn)
|
||||
return gn->path != NULL ? gn->path : gn->name;
|
||||
}
|
||||
|
||||
MAKE_INLINE Boolean
|
||||
MAKE_INLINE bool
|
||||
GNode_IsWaitingFor(const GNode *gn)
|
||||
{
|
||||
return (gn->flags & REMAKE) && gn->made <= REQUESTED;
|
||||
}
|
||||
|
||||
MAKE_INLINE Boolean
|
||||
MAKE_INLINE bool
|
||||
GNode_IsReady(const GNode *gn)
|
||||
{
|
||||
return gn->made > DEFERRED;
|
||||
}
|
||||
|
||||
MAKE_INLINE Boolean
|
||||
MAKE_INLINE bool
|
||||
GNode_IsDone(const GNode *gn)
|
||||
{
|
||||
return gn->made >= MADE;
|
||||
}
|
||||
|
||||
MAKE_INLINE Boolean
|
||||
MAKE_INLINE bool
|
||||
GNode_IsError(const GNode *gn)
|
||||
{
|
||||
return gn->made == ERROR || gn->made == ABORTED;
|
||||
@ -781,7 +758,7 @@ GNode_VarArchive(GNode *gn) { return GNode_ValueDirect(gn, ARCHIVE); }
|
||||
MAKE_INLINE const char *
|
||||
GNode_VarMember(GNode *gn) { return GNode_ValueDirect(gn, MEMBER); }
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && __STDC_VERSION__ >= 199901L
|
||||
#define UNCONST(ptr) ({ \
|
||||
union __unconst { \
|
||||
const void *__cp; \
|
||||
@ -809,15 +786,15 @@ GNode_VarMember(GNode *gn) { return GNode_ValueDirect(gn, MEMBER); }
|
||||
#define KILLPG(pid, sig) killpg((pid), (sig))
|
||||
#endif
|
||||
|
||||
MAKE_INLINE Boolean
|
||||
MAKE_INLINE bool
|
||||
ch_isalnum(char ch) { return isalnum((unsigned char)ch) != 0; }
|
||||
MAKE_INLINE Boolean
|
||||
MAKE_INLINE bool
|
||||
ch_isalpha(char ch) { return isalpha((unsigned char)ch) != 0; }
|
||||
MAKE_INLINE Boolean
|
||||
MAKE_INLINE bool
|
||||
ch_isdigit(char ch) { return isdigit((unsigned char)ch) != 0; }
|
||||
MAKE_INLINE Boolean
|
||||
MAKE_INLINE bool
|
||||
ch_isspace(char ch) { return isspace((unsigned char)ch) != 0; }
|
||||
MAKE_INLINE Boolean
|
||||
MAKE_INLINE bool
|
||||
ch_isupper(char ch) { return isupper((unsigned char)ch) != 0; }
|
||||
MAKE_INLINE char
|
||||
ch_tolower(char ch) { return (char)tolower((unsigned char)ch); }
|
||||
|
192
meta.c
192
meta.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: meta.c,v 1.177 2021/02/05 19:19:17 sjg Exp $ */
|
||||
/* $NetBSD: meta.c,v 1.181 2021/04/04 10:05:08 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Implement 'meta' mode.
|
||||
@ -70,20 +70,20 @@ static char *metaIgnorePathsStr; /* string storage for the list */
|
||||
#define MAKE_META_IGNORE_FILTER ".MAKE.META.IGNORE_FILTER"
|
||||
#endif
|
||||
|
||||
Boolean useMeta = FALSE;
|
||||
static Boolean useFilemon = FALSE;
|
||||
static Boolean writeMeta = FALSE;
|
||||
static Boolean metaMissing = FALSE; /* oodate if missing */
|
||||
static Boolean filemonMissing = FALSE; /* oodate if missing */
|
||||
static Boolean metaEnv = FALSE; /* don't save env unless asked */
|
||||
static Boolean metaVerbose = FALSE;
|
||||
static Boolean metaIgnoreCMDs = FALSE; /* ignore CMDs in .meta files */
|
||||
static Boolean metaIgnorePatterns = FALSE; /* do we need to do pattern matches */
|
||||
static Boolean metaIgnoreFilter = FALSE; /* do we have more complex filtering? */
|
||||
static Boolean metaCurdirOk = FALSE; /* write .meta in .CURDIR Ok? */
|
||||
static Boolean metaSilent = FALSE; /* if we have a .meta be SILENT */
|
||||
bool useMeta = false;
|
||||
static bool useFilemon = false;
|
||||
static bool writeMeta = false;
|
||||
static bool metaMissing = false; /* oodate if missing */
|
||||
static bool filemonMissing = false; /* oodate if missing */
|
||||
static bool metaEnv = false; /* don't save env unless asked */
|
||||
static bool metaVerbose = false;
|
||||
static bool metaIgnoreCMDs = false; /* ignore CMDs in .meta files */
|
||||
static bool metaIgnorePatterns = false; /* do we need to do pattern matches */
|
||||
static bool metaIgnoreFilter = false; /* do we have more complex filtering? */
|
||||
static bool metaCurdirOk = false; /* write .meta in .CURDIR Ok? */
|
||||
static bool metaSilent = false; /* if we have a .meta be SILENT */
|
||||
|
||||
extern Boolean forceJobs;
|
||||
extern bool forceJobs;
|
||||
extern char **environ;
|
||||
|
||||
#define MAKE_META_PREFIX ".MAKE.META.PREFIX"
|
||||
@ -133,7 +133,7 @@ meta_open_filemon(BuildMon *pbm)
|
||||
|
||||
pbm->filemon = filemon_open();
|
||||
if (pbm->filemon == NULL) {
|
||||
useFilemon = FALSE;
|
||||
useFilemon = false;
|
||||
warn("Could not open filemon %s", filemon_path());
|
||||
return;
|
||||
}
|
||||
@ -319,7 +319,7 @@ meta_name(char *mname, size_t mnamelen,
|
||||
* Return true if running ${.MAKE}
|
||||
* Bypassed if target is flagged .MAKE
|
||||
*/
|
||||
static Boolean
|
||||
static bool
|
||||
is_submake(const char *cmd, GNode *gn)
|
||||
{
|
||||
static const char *p_make = NULL;
|
||||
@ -327,7 +327,7 @@ is_submake(const char *cmd, GNode *gn)
|
||||
char *mp = NULL;
|
||||
char *cp;
|
||||
char *cp2;
|
||||
Boolean rc = FALSE;
|
||||
bool rc = false;
|
||||
|
||||
if (p_make == NULL) {
|
||||
p_make = Var_Value(gn, ".MAKE").str;
|
||||
@ -346,7 +346,7 @@ is_submake(const char *cmd, GNode *gn)
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
rc = TRUE;
|
||||
rc = true;
|
||||
break;
|
||||
}
|
||||
if (cp2 > cmd && rc) {
|
||||
@ -356,7 +356,7 @@ is_submake(const char *cmd, GNode *gn)
|
||||
case '\n':
|
||||
break;
|
||||
default:
|
||||
rc = FALSE; /* no match */
|
||||
rc = false; /* no match */
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -365,29 +365,31 @@ is_submake(const char *cmd, GNode *gn)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
any_is_submake(GNode *gn)
|
||||
{
|
||||
StringListNode *ln;
|
||||
|
||||
for (ln = gn->commands.first; ln != NULL; ln = ln->next)
|
||||
if (is_submake(ln->datum, gn))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
printCMD(const char *cmd, FILE *fp, GNode *gn)
|
||||
printCMD(const char *ucmd, FILE *fp, GNode *gn)
|
||||
{
|
||||
char *cmd_freeIt = NULL;
|
||||
FStr xcmd = FStr_InitRefer(ucmd);
|
||||
|
||||
if (strchr(cmd, '$') != NULL) {
|
||||
(void)Var_Subst(cmd, gn, VARE_WANTRES, &cmd_freeIt);
|
||||
if (strchr(ucmd, '$') != NULL) {
|
||||
char *expanded;
|
||||
(void)Var_Subst(ucmd, gn, VARE_WANTRES, &expanded);
|
||||
/* TODO: handle errors */
|
||||
cmd = cmd_freeIt;
|
||||
xcmd = FStr_InitOwn(expanded);
|
||||
}
|
||||
fprintf(fp, "CMD %s\n", cmd);
|
||||
free(cmd_freeIt);
|
||||
|
||||
fprintf(fp, "CMD %s\n", xcmd.str);
|
||||
FStr_Done(&xcmd);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -408,17 +410,17 @@ printCMDs(GNode *gn, FILE *fp)
|
||||
debug_printf("Skipping meta for %s: .%s\n", \
|
||||
gn->name, __STRING(_type)); \
|
||||
} \
|
||||
return FALSE; \
|
||||
return false; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/FALSE)
|
||||
} while (/*CONSTCOND*/false)
|
||||
|
||||
|
||||
/*
|
||||
* Do we need/want a .meta file ?
|
||||
*/
|
||||
static Boolean
|
||||
static bool
|
||||
meta_needed(GNode *gn, const char *dname,
|
||||
char *objdir_realpath, Boolean verbose)
|
||||
char *objdir_realpath, bool verbose)
|
||||
{
|
||||
struct cached_stat cst;
|
||||
|
||||
@ -440,13 +442,13 @@ meta_needed(GNode *gn, const char *dname,
|
||||
if (Lst_IsEmpty(&gn->commands)) {
|
||||
if (verbose)
|
||||
debug_printf("Skipping meta for %s: no commands\n", gn->name);
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
if ((gn->type & (OP_META|OP_SUBMAKE)) == OP_SUBMAKE) {
|
||||
/* OP_SUBMAKE is a bit too aggressive */
|
||||
if (any_is_submake(gn)) {
|
||||
DEBUG1(META, "Skipping meta for %s: .SUBMAKE\n", gn->name);
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -454,7 +456,7 @@ meta_needed(GNode *gn, const char *dname,
|
||||
if (cached_stat(dname, &cst) != 0) {
|
||||
if (verbose)
|
||||
debug_printf("Skipping meta for %s: no .OBJDIR\n", gn->name);
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* make sure these are canonical */
|
||||
@ -466,9 +468,9 @@ meta_needed(GNode *gn, const char *dname,
|
||||
if (verbose)
|
||||
debug_printf("Skipping meta for %s: .OBJDIR == .CURDIR\n",
|
||||
gn->name);
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -490,7 +492,7 @@ meta_create(BuildMon *pbm, GNode *gn)
|
||||
tname = GNode_VarTarget(gn);
|
||||
|
||||
/* if this succeeds objdir_realpath is realpath of dname */
|
||||
if (!meta_needed(gn, dname.str, objdir_realpath, TRUE))
|
||||
if (!meta_needed(gn, dname.str, objdir_realpath, true))
|
||||
goto out;
|
||||
dname.str = objdir_realpath;
|
||||
|
||||
@ -554,7 +556,7 @@ meta_create(BuildMon *pbm, GNode *gn)
|
||||
return fp;
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
boolValue(char *s)
|
||||
{
|
||||
switch(*s) {
|
||||
@ -563,9 +565,9 @@ boolValue(char *s)
|
||||
case 'n':
|
||||
case 'F':
|
||||
case 'f':
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -591,25 +593,25 @@ meta_init(void)
|
||||
void
|
||||
meta_mode_init(const char *make_mode)
|
||||
{
|
||||
static Boolean once = FALSE;
|
||||
static bool once = false;
|
||||
char *cp;
|
||||
FStr value;
|
||||
|
||||
useMeta = TRUE;
|
||||
useFilemon = TRUE;
|
||||
writeMeta = TRUE;
|
||||
useMeta = true;
|
||||
useFilemon = true;
|
||||
writeMeta = true;
|
||||
|
||||
if (make_mode != NULL) {
|
||||
if (strstr(make_mode, "env") != NULL)
|
||||
metaEnv = TRUE;
|
||||
metaEnv = true;
|
||||
if (strstr(make_mode, "verb") != NULL)
|
||||
metaVerbose = TRUE;
|
||||
metaVerbose = true;
|
||||
if (strstr(make_mode, "read") != NULL)
|
||||
writeMeta = FALSE;
|
||||
writeMeta = false;
|
||||
if (strstr(make_mode, "nofilemon") != NULL)
|
||||
useFilemon = FALSE;
|
||||
useFilemon = false;
|
||||
if (strstr(make_mode, "ignore-cmd") != NULL)
|
||||
metaIgnoreCMDs = TRUE;
|
||||
metaIgnoreCMDs = true;
|
||||
if (useFilemon)
|
||||
get_mode_bf(filemonMissing, "missing-filemon=");
|
||||
get_mode_bf(metaCurdirOk, "curdirok=");
|
||||
@ -628,7 +630,7 @@ meta_mode_init(const char *make_mode)
|
||||
}
|
||||
if (once)
|
||||
return;
|
||||
once = TRUE;
|
||||
once = true;
|
||||
memset(&Mybm, 0, sizeof Mybm);
|
||||
/*
|
||||
* We consider ourselves master of all within ${.MAKE.META.BAILIWICK}
|
||||
@ -652,12 +654,12 @@ meta_mode_init(const char *make_mode)
|
||||
*/
|
||||
value = Var_Value(SCOPE_GLOBAL, MAKE_META_IGNORE_PATTERNS);
|
||||
if (value.str != NULL) {
|
||||
metaIgnorePatterns = TRUE;
|
||||
metaIgnorePatterns = true;
|
||||
FStr_Done(&value);
|
||||
}
|
||||
value = Var_Value(SCOPE_GLOBAL, MAKE_META_IGNORE_FILTER);
|
||||
if (value.str != NULL) {
|
||||
metaIgnoreFilter = TRUE;
|
||||
metaIgnoreFilter = true;
|
||||
FStr_Done(&value);
|
||||
}
|
||||
}
|
||||
@ -774,7 +776,7 @@ meta_job_event(Job *job)
|
||||
}
|
||||
|
||||
void
|
||||
meta_job_error(Job *job, GNode *gn, Boolean ignerr, int status)
|
||||
meta_job_error(Job *job, GNode *gn, bool ignerr, int status)
|
||||
{
|
||||
char cwd[MAXPATHLEN];
|
||||
BuildMon *pbm;
|
||||
@ -944,7 +946,7 @@ fgetLine(char **bufp, size_t *szp, int o, FILE *fp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
prefix_match(const char *prefix, const char *path)
|
||||
{
|
||||
size_t n = strlen(prefix);
|
||||
@ -952,35 +954,35 @@ prefix_match(const char *prefix, const char *path)
|
||||
return strncmp(path, prefix, n) == 0;
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
has_any_prefix(const char *path, StringList *prefixes)
|
||||
{
|
||||
StringListNode *ln;
|
||||
|
||||
for (ln = prefixes->first; ln != NULL; ln = ln->next)
|
||||
if (prefix_match(ln->datum, path))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* See if the path equals prefix or starts with "prefix/". */
|
||||
static Boolean
|
||||
static bool
|
||||
path_starts_with(const char *path, const char *prefix)
|
||||
{
|
||||
size_t n = strlen(prefix);
|
||||
|
||||
if (strncmp(path, prefix, n) != 0)
|
||||
return FALSE;
|
||||
return false;
|
||||
return path[n] == '\0' || path[n] == '/';
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
meta_ignore(GNode *gn, const char *p)
|
||||
{
|
||||
char fname[MAXPATHLEN];
|
||||
|
||||
if (p == NULL)
|
||||
return TRUE;
|
||||
return true;
|
||||
|
||||
if (*p == '/') {
|
||||
cached_realpath(p, fname); /* clean it up */
|
||||
@ -988,7 +990,7 @@ meta_ignore(GNode *gn, const char *p)
|
||||
#ifdef DEBUG_META_MODE
|
||||
DEBUG1(META, "meta_oodate: ignoring path: %s\n", p);
|
||||
#endif
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1011,7 +1013,7 @@ meta_ignore(GNode *gn, const char *p)
|
||||
DEBUG1(META, "meta_oodate: ignoring pattern: %s\n", p);
|
||||
#endif
|
||||
free(pm);
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
free(pm);
|
||||
}
|
||||
@ -1030,11 +1032,11 @@ meta_ignore(GNode *gn, const char *p)
|
||||
DEBUG1(META, "meta_oodate: ignoring filtered: %s\n", p);
|
||||
#endif
|
||||
free(fm);
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
free(fm);
|
||||
}
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1048,11 +1050,11 @@ meta_ignore(GNode *gn, const char *p)
|
||||
/*
|
||||
* It is possible that a .meta file is corrupted,
|
||||
* if we detect this we want to reproduce it.
|
||||
* Setting oodate TRUE will have that effect.
|
||||
* Setting oodate true will have that effect.
|
||||
*/
|
||||
#define CHECK_VALID_META(p) if (!(p != NULL && *p != '\0')) { \
|
||||
warnx("%s: %d: malformed", fname, lineno); \
|
||||
oodate = TRUE; \
|
||||
oodate = true; \
|
||||
continue; \
|
||||
}
|
||||
|
||||
@ -1074,8 +1076,8 @@ append_if_new(StringList *list, const char *str)
|
||||
Lst_Append(list, bmake_strdup(str));
|
||||
}
|
||||
|
||||
Boolean
|
||||
meta_oodate(GNode *gn, Boolean oodate)
|
||||
bool
|
||||
meta_oodate(GNode *gn, bool oodate)
|
||||
{
|
||||
static char *tmpdir = NULL;
|
||||
static char cwd[MAXPATHLEN];
|
||||
@ -1095,9 +1097,9 @@ meta_oodate(GNode *gn, Boolean oodate)
|
||||
static size_t cwdlen = 0;
|
||||
static size_t tmplen = 0;
|
||||
FILE *fp;
|
||||
Boolean needOODATE = FALSE;
|
||||
bool needOODATE = false;
|
||||
StringList missingFiles;
|
||||
Boolean have_filemon = FALSE;
|
||||
bool have_filemon = false;
|
||||
|
||||
if (oodate)
|
||||
return oodate; /* we're done */
|
||||
@ -1106,7 +1108,7 @@ meta_oodate(GNode *gn, Boolean oodate)
|
||||
tname = GNode_VarTarget(gn);
|
||||
|
||||
/* if this succeeds fname3 is realpath of dname */
|
||||
if (!meta_needed(gn, dname.str, fname3, FALSE))
|
||||
if (!meta_needed(gn, dname.str, fname3, false))
|
||||
goto oodate_out;
|
||||
dname.str = fname3;
|
||||
|
||||
@ -1118,7 +1120,7 @@ meta_oodate(GNode *gn, Boolean oodate)
|
||||
* requires that all variables are set in the same way that they
|
||||
* would be if the target needs to be re-built.
|
||||
*/
|
||||
Make_DoAllVar(gn);
|
||||
GNode_SetLocalVars(gn);
|
||||
|
||||
meta_name(fname, sizeof fname, dname.str, tname, dname.str);
|
||||
|
||||
@ -1164,7 +1166,7 @@ meta_oodate(GNode *gn, Boolean oodate)
|
||||
buf[x - 1] = '\0';
|
||||
else {
|
||||
warnx("%s: %d: line truncated at %u", fname, lineno, x);
|
||||
oodate = TRUE;
|
||||
oodate = true;
|
||||
break;
|
||||
}
|
||||
link_src = NULL;
|
||||
@ -1172,11 +1174,11 @@ meta_oodate(GNode *gn, Boolean oodate)
|
||||
/* Find the start of the build monitor section. */
|
||||
if (!have_filemon) {
|
||||
if (strncmp(buf, "-- filemon", 10) == 0) {
|
||||
have_filemon = TRUE;
|
||||
have_filemon = true;
|
||||
continue;
|
||||
}
|
||||
if (strncmp(buf, "# buildmon", 10) == 0) {
|
||||
have_filemon = TRUE;
|
||||
have_filemon = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -1424,7 +1426,7 @@ meta_oodate(GNode *gn, Boolean oodate)
|
||||
char *sdirs[4];
|
||||
char **sdp;
|
||||
int sdx = 0;
|
||||
Boolean found = FALSE;
|
||||
bool found = false;
|
||||
|
||||
if (*p == '/') {
|
||||
sdirs[sdx++] = p; /* done */
|
||||
@ -1455,7 +1457,7 @@ meta_oodate(GNode *gn, Boolean oodate)
|
||||
fname, lineno, *sdp);
|
||||
#endif
|
||||
if (cached_stat(*sdp, &cst) == 0) {
|
||||
found = TRUE;
|
||||
found = true;
|
||||
p = *sdp;
|
||||
}
|
||||
}
|
||||
@ -1468,7 +1470,7 @@ meta_oodate(GNode *gn, Boolean oodate)
|
||||
cst.cst_mtime > gn->mtime) {
|
||||
DEBUG3(META, "%s: %d: file '%s' is newer than the target...\n",
|
||||
fname, lineno, p);
|
||||
oodate = TRUE;
|
||||
oodate = true;
|
||||
} else if (S_ISDIR(cst.cst_mode)) {
|
||||
/* Update the latest directory. */
|
||||
cached_realpath(p, latestdir);
|
||||
@ -1500,25 +1502,25 @@ meta_oodate(GNode *gn, Boolean oodate)
|
||||
if (cmdNode == NULL) {
|
||||
DEBUG2(META, "%s: %d: there were more build commands in the meta data file than there are now...\n",
|
||||
fname, lineno);
|
||||
oodate = TRUE;
|
||||
oodate = true;
|
||||
} else {
|
||||
const char *cp;
|
||||
char *cmd = cmdNode->datum;
|
||||
Boolean hasOODATE = FALSE;
|
||||
bool hasOODATE = false;
|
||||
|
||||
if (strstr(cmd, "$?") != NULL)
|
||||
hasOODATE = TRUE;
|
||||
hasOODATE = true;
|
||||
else if ((cp = strstr(cmd, ".OODATE")) != NULL) {
|
||||
/* check for $[{(].OODATE[:)}] */
|
||||
if (cp > cmd + 2 && cp[-2] == '$')
|
||||
hasOODATE = TRUE;
|
||||
hasOODATE = true;
|
||||
}
|
||||
if (hasOODATE) {
|
||||
needOODATE = TRUE;
|
||||
needOODATE = true;
|
||||
DEBUG2(META, "%s: %d: cannot compare command using .OODATE\n",
|
||||
fname, lineno);
|
||||
}
|
||||
(void)Var_Subst(cmd, gn, VARE_WANTRES|VARE_UNDEFERR, &cmd);
|
||||
(void)Var_Subst(cmd, gn, VARE_UNDEFERR, &cmd);
|
||||
/* TODO: handle errors */
|
||||
|
||||
if ((cp = strchr(cmd, '\n')) != NULL) {
|
||||
@ -1553,7 +1555,7 @@ meta_oodate(GNode *gn, Boolean oodate)
|
||||
DEBUG4(META, "%s: %d: a build command has changed\n%s\nvs\n%s\n",
|
||||
fname, lineno, p, cmd);
|
||||
if (!metaIgnoreCMDs)
|
||||
oodate = TRUE;
|
||||
oodate = true;
|
||||
}
|
||||
free(cmd);
|
||||
cmdNode = cmdNode->next;
|
||||
@ -1566,13 +1568,13 @@ meta_oodate(GNode *gn, Boolean oodate)
|
||||
if (!oodate && cmdNode != NULL) {
|
||||
DEBUG2(META, "%s: %d: there are extra build commands now that weren't in the meta data file\n",
|
||||
fname, lineno);
|
||||
oodate = TRUE;
|
||||
oodate = true;
|
||||
}
|
||||
CHECK_VALID_META(p);
|
||||
if (strcmp(p, cwd) != 0) {
|
||||
DEBUG4(META, "%s: %d: the current working directory has changed from '%s' to '%s'\n",
|
||||
fname, lineno, p, curdir);
|
||||
oodate = TRUE;
|
||||
oodate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1581,11 +1583,11 @@ meta_oodate(GNode *gn, Boolean oodate)
|
||||
if (!Lst_IsEmpty(&missingFiles)) {
|
||||
DEBUG2(META, "%s: missing files: %s...\n",
|
||||
fname, (char *)missingFiles.first->datum);
|
||||
oodate = TRUE;
|
||||
oodate = true;
|
||||
}
|
||||
if (!oodate && !have_filemon && filemonMissing) {
|
||||
DEBUG1(META, "%s: missing filemon data\n", fname);
|
||||
oodate = TRUE;
|
||||
oodate = true;
|
||||
}
|
||||
} else {
|
||||
if (writeMeta && (metaMissing || (gn->type & OP_META))) {
|
||||
@ -1600,8 +1602,8 @@ meta_oodate(GNode *gn, Boolean oodate)
|
||||
}
|
||||
if (cp == NULL) {
|
||||
DEBUG1(META, "%s: required but missing\n", fname);
|
||||
oodate = TRUE;
|
||||
needOODATE = TRUE; /* assume the worst */
|
||||
oodate = true;
|
||||
needOODATE = true; /* assume the worst */
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1708,7 +1710,7 @@ meta_compat_parent(pid_t child)
|
||||
fflush(stdout);
|
||||
buf[nread] = '\0';
|
||||
meta_job_output(NULL, buf, "");
|
||||
} while (/*CONSTCOND*/FALSE);
|
||||
} while (/*CONSTCOND*/false);
|
||||
if (metafd != -1 && FD_ISSET(metafd, &readfds) != 0) {
|
||||
if (meta_job_event(NULL) <= 0)
|
||||
metafd = -1;
|
||||
|
8
meta.h
8
meta.h
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: meta.h,v 1.9 2020/12/10 20:49:11 rillig Exp $ */
|
||||
/* $NetBSD: meta.h,v 1.10 2021/04/03 11:08:40 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Things needed for 'meta' mode.
|
||||
@ -48,13 +48,13 @@ void meta_job_child(struct Job *);
|
||||
void meta_job_parent(struct Job *, pid_t);
|
||||
int meta_job_fd(struct Job *);
|
||||
int meta_job_event(struct Job *);
|
||||
void meta_job_error(struct Job *, GNode *, Boolean, int);
|
||||
void meta_job_error(struct Job *, GNode *, bool, int);
|
||||
void meta_job_output(struct Job *, char *, const char *);
|
||||
int meta_cmd_finish(void *);
|
||||
int meta_job_finish(struct Job *);
|
||||
Boolean meta_oodate(GNode *, Boolean);
|
||||
bool meta_oodate(GNode *, bool);
|
||||
void meta_compat_start(void);
|
||||
void meta_compat_child(void);
|
||||
void meta_compat_parent(pid_t);
|
||||
|
||||
extern Boolean useMeta;
|
||||
extern bool useMeta;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: metachar.h,v 1.15 2021/01/19 20:51:46 rillig Exp $ */
|
||||
/* $NetBSD: metachar.h,v 1.16 2021/04/03 11:08:40 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 The NetBSD Foundation, Inc.
|
||||
@ -37,7 +37,7 @@ extern unsigned char _metachar[];
|
||||
|
||||
#define is_shell_metachar(c) (_metachar[(c) & 0x7f] != 0)
|
||||
|
||||
MAKE_INLINE Boolean
|
||||
MAKE_INLINE bool
|
||||
needshell(const char *cmd)
|
||||
{
|
||||
while (!is_shell_metachar(*cmd) && *cmd != ':' && *cmd != '=')
|
||||
|
35
mk/ChangeLog
35
mk/ChangeLog
@ -1,3 +1,38 @@
|
||||
2021-06-16 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* install-mk (MK_VERSION): 20210616
|
||||
|
||||
* dirdeps.mk: when using .MAKE.DEPENDFILE_PREFERENCE to find
|
||||
depend files to read, anchor MACHINE at , or end of string
|
||||
to avoid prefix match.
|
||||
|
||||
2021-05-04 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* install-mk (MK_VERSION): 20210504
|
||||
|
||||
* dirdeps.mk: re-implement ALL_MACHINES support to better
|
||||
cater for local complexities, when ONLY_TARGET_SPEC_LIST
|
||||
is not set. local.dirdeps.mk can set
|
||||
DIRDEPS_ALL_MACHINES_FILTER and/or
|
||||
DIRDEPS_ALL_MACHINES_FILTER_XTRAS to filter the results we get
|
||||
from listing all existing Makefile.depend.*
|
||||
|
||||
2021-04-20 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* install-mk (MK_VERSION): 20210420
|
||||
|
||||
* dirdeps.mk: revert previous - not always safe.
|
||||
|
||||
2021-03-20 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* install-mk (MK_VERSION): 20210321
|
||||
|
||||
* dirdeps.mk: when generating dirdeps.cache
|
||||
we only need to hook the initial DIRDEPS to the
|
||||
dirdeps target. That and any _build_xtra_dirs (like tests which
|
||||
should not be hooked directly to the dependency graph - to avoid
|
||||
cycles)
|
||||
|
||||
2021-01-30 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* install-mk (MK_VERSION): 20210130
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: dirdeps.mk,v 1.133 2021/01/31 04:39:22 sjg Exp $
|
||||
# $Id: dirdeps.mk,v 1.140 2021/06/20 23:42:38 sjg Exp $
|
||||
|
||||
# Copyright (c) 2010-2021, Simon J. Gerraty
|
||||
# Copyright (c) 2010-2018, Juniper Networks, Inc.
|
||||
@ -409,23 +409,72 @@ _DIRDEP_USE: .USE .MAKE
|
||||
done
|
||||
|
||||
.ifdef ALL_MACHINES
|
||||
# this is how you limit it to only the machines we have been built for
|
||||
# previously.
|
||||
.if empty(ONLY_TARGET_SPEC_LIST) && empty(ONLY_MACHINE_LIST)
|
||||
.if !empty(ALL_MACHINE_LIST)
|
||||
# ALL_MACHINE_LIST is the list of all legal machines - ignore anything else
|
||||
_machine_list != cd ${_CURDIR} && 'ls' -1 ${ALL_MACHINE_LIST:O:u:@m@${.MAKE.DEPENDFILE:T:R}.$m@} 2> /dev/null; echo
|
||||
.else
|
||||
_machine_list != 'ls' -1 ${_CURDIR}/${.MAKE.DEPENDFILE_PREFIX}.* 2> /dev/null; echo
|
||||
# we start with everything
|
||||
_machine_list != echo; 'ls' -1 ${_CURDIR}/${.MAKE.DEPENDFILE_PREFIX}* 2> /dev/null
|
||||
|
||||
# some things we know we want to ignore
|
||||
DIRDEPS_TARGETS_SKIP_LIST += \
|
||||
*~ \
|
||||
*.bak \
|
||||
*.inc \
|
||||
*.old \
|
||||
*.options \
|
||||
*.orig \
|
||||
*.rej \
|
||||
|
||||
# first trim things we know we want to skip
|
||||
# and provide canonical form
|
||||
_machine_list := ${_machine_list:${DIRDEPS_TARGETS_SKIP_LIST:${M_ListToSkip}}:T:E}
|
||||
|
||||
# cater for local complexities
|
||||
# local.dirdeps.mk can set
|
||||
# DIRDEPS_ALL_MACHINES_FILTER and
|
||||
# DIRDEPS_ALL_MACHINES_FILTER_XTRAS for final tweaks
|
||||
|
||||
.if !empty(ALL_TARGET_SPEC_LIST)
|
||||
.if ${_debug_reldir}
|
||||
.info ALL_TARGET_SPEC_LIST=${ALL_TARGET_SPEC_LIST}
|
||||
.endif
|
||||
_only_machines := ${_machine_list:${NIgnoreFiles:UN*.bak}:E:O:u}
|
||||
DIRDEPS_ALL_MACHINES_FILTER += \
|
||||
@x@$${ALL_TARGET_SPEC_LIST:@s@$${x:M$$s}@}@
|
||||
.elif !empty(ALL_MACHINE_LIST)
|
||||
.if ${_debug_reldir}
|
||||
.info ALL_MACHINE_LIST=${ALL_MACHINE_LIST}
|
||||
.endif
|
||||
.if ${TARGET_SPEC_VARS:[#]} > 1
|
||||
# the space below can result in extraneous ':'
|
||||
DIRDEPS_ALL_MACHINES_FILTER += \
|
||||
@x@$${ALL_MACHINE_LIST:@m@$${x:M$$m,*} $${x:M$$m}@}@
|
||||
.else
|
||||
DIRDEPS_ALL_MACHINES_FILTER += \
|
||||
@x@$${ALL_MACHINE_LIST:@m@$${x:M$$m}@}@
|
||||
.endif
|
||||
.endif
|
||||
# add local XTRAS - default to something benign
|
||||
DIRDEPS_ALL_MACHINES_FILTER += \
|
||||
${DIRDEPS_ALL_MACHINES_FILTER_XTRAS:UNbak}
|
||||
|
||||
.if ${_debug_reldir}
|
||||
.info _machine_list=${_machine_list}
|
||||
.info DIRDEPS_ALL_MACHINES_FILTER=${DIRDEPS_ALL_MACHINES_FILTER}
|
||||
.endif
|
||||
|
||||
_only_machines := ${_machine_list:${DIRDEPS_ALL_MACHINES_FILTER:ts:}:S,:, ,g}
|
||||
.else
|
||||
_only_machines := ${ONLY_TARGET_SPEC_LIST:U} ${ONLY_MACHINE_LIST:U}
|
||||
.endif
|
||||
|
||||
.if empty(_only_machines)
|
||||
# we must be boot-strapping
|
||||
_only_machines := ${TARGET_MACHINE:U${ALL_MACHINE_LIST:U${DEP_MACHINE}}}
|
||||
_only_machines := ${TARGET_MACHINE:U${ALL_TARGET_SPEC_LIST:U${ALL_MACHINE_LIST:U${DEP_MACHINE}}}}
|
||||
.endif
|
||||
|
||||
# cleanup the result
|
||||
_only_machines := ${_only_machines:O:u}
|
||||
|
||||
.if ${_debug_reldir}
|
||||
.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: ALL_MACHINES _only_machines=${_only_machines}
|
||||
.endif
|
||||
|
||||
.else # ! ALL_MACHINES
|
||||
@ -452,6 +501,10 @@ _only_machines := ${_only_machines:${NOT_TARGET_SPEC_LIST:${M_ListToSkip}}}
|
||||
# clean up
|
||||
_only_machines := ${_only_machines:O:u}
|
||||
|
||||
.if ${_debug_reldir}
|
||||
.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: _only_machines=${_only_machines}
|
||||
.endif
|
||||
|
||||
# make sure we have a starting place?
|
||||
DIRDEPS ?= ${RELDIR}
|
||||
.endif # target
|
||||
@ -697,6 +750,7 @@ _cache_deps += ${_build_dirs:M*.$m:N${_this_dir}.$m}
|
||||
.export _cache_deps
|
||||
x!= echo; for x in $$_cache_deps; do echo " $$x \\"; done >&3
|
||||
.endif
|
||||
# anything in _build_xtra_dirs is hooked to dirdeps: only
|
||||
x!= echo; { echo; echo '${_this_dir}.$m: $${DIRDEPS.${_this_dir}.$m}'; \
|
||||
echo; echo 'dirdeps: ${_this_dir}.$m \'; \
|
||||
for x in $$_build_xtra_dirs; do echo " $$x \\"; done; \
|
||||
@ -735,7 +789,7 @@ DEP_MACHINE := ${_DEP_MACHINE}
|
||||
# Warning: there is an assumption here that MACHINE is always
|
||||
# the first entry in TARGET_SPEC_VARS.
|
||||
# If TARGET_SPEC and MACHINE are insufficient, you have a problem.
|
||||
_m := ${.MAKE.DEPENDFILE_PREFERENCE:T:S;${TARGET_SPEC}$;${d:E};:S;${MACHINE};${d:E:C/,.*//};:@m@${exists(${d:R}/$m):?${d:R}/$m:}@:[1]}
|
||||
_m := ${.MAKE.DEPENDFILE_PREFERENCE:T:S;${TARGET_SPEC}$;${d:E};:C;${MACHINE}((,.+)?)$;${d:E:C/,.*//}\1;:@m@${exists(${d:R}/$m):?${d:R}/$m:}@:[1]}
|
||||
.if !empty(_m)
|
||||
# M_dep_qual_fixes isn't geared to Makefile.depend
|
||||
_qm := ${_m:C;(\.depend)$;\1.${d:E};:${M_dep_qual_fixes:ts:}}
|
||||
@ -801,6 +855,7 @@ _reldir_failed: .NOMETA
|
||||
.endif
|
||||
|
||||
# bootstrapping new dependencies made easy?
|
||||
.if !target(bootstrap-empty)
|
||||
.if !target(bootstrap) && (make(bootstrap) || \
|
||||
make(bootstrap-this) || \
|
||||
make(bootstrap-recurse) || \
|
||||
@ -856,3 +911,4 @@ bootstrap-empty: .NOTMAIN .NOMETA
|
||||
@{ echo DIRDEPS=; echo ".include <dirdeps.mk>"; } > ${_want}
|
||||
|
||||
.endif
|
||||
.endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: dpadd.mk,v 1.28 2020/08/19 17:51:53 sjg Exp $
|
||||
# $Id: dpadd.mk,v 1.29 2021/04/20 02:30:44 sjg Exp $
|
||||
#
|
||||
# @(#) Copyright (c) 2004, Simon J. Gerraty
|
||||
#
|
||||
@ -211,8 +211,9 @@ OBJ_${__lib:T:R} ?= ${__lib:H:S,${OBJTOP},${RELOBJTOP},}
|
||||
# If INCLUDES_libfoo is not set, then we'll use ${SRC_libfoo}/h if it exists,
|
||||
# else just ${SRC_libfoo}.
|
||||
#
|
||||
INCLUDES_${__lib:T:R}?= -I${exists(${SRC_${__lib:T:R}}/h):?${SRC_${__lib:T:R}}/h:${SRC_${__lib:T:R}}}
|
||||
|
||||
.if !empty(SRC_${__lib:T:R})
|
||||
INCLUDES_${__lib:T:R} ?= -I${exists(${SRC_${__lib:T:R}}/h):?${SRC_${__lib:T:R}}/h:${SRC_${__lib:T:R}}}
|
||||
.endif
|
||||
.endfor
|
||||
|
||||
# even for staged libs we sometimes
|
||||
|
@ -55,7 +55,7 @@
|
||||
# Simon J. Gerraty <sjg@crufty.net>
|
||||
|
||||
# RCSid:
|
||||
# $Id: install-mk,v 1.191 2021/01/30 23:16:42 sjg Exp $
|
||||
# $Id: install-mk,v 1.196 2021/06/19 15:30:41 sjg Exp $
|
||||
#
|
||||
# @(#) Copyright (c) 1994 Simon J. Gerraty
|
||||
#
|
||||
@ -70,7 +70,7 @@
|
||||
# sjg@crufty.net
|
||||
#
|
||||
|
||||
MK_VERSION=20210130
|
||||
MK_VERSION=20210616
|
||||
OWNER=
|
||||
GROUP=
|
||||
MODE=444
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: meta.autodep.mk,v 1.53 2020/11/08 05:47:56 sjg Exp $
|
||||
# $Id: meta.autodep.mk,v 1.54 2021/03/06 17:03:18 sjg Exp $
|
||||
|
||||
#
|
||||
# @(#) Copyright (c) 2010, Simon J. Gerraty
|
||||
@ -298,16 +298,20 @@ start_utc := ${now_utc}
|
||||
meta_stats= meta=${empty(.MAKE.META.FILES):?0:${.MAKE.META.FILES:[#]}} \
|
||||
created=${empty(.MAKE.META.CREATED):?0:${.MAKE.META.CREATED:[#]}}
|
||||
|
||||
.if !target(_reldir_finish)
|
||||
#.END: _reldir_finish
|
||||
.if target(gendirdeps)
|
||||
_reldir_finish: gendirdeps
|
||||
.endif
|
||||
_reldir_finish: .NOMETA
|
||||
@echo "${TIME_STAMP} Finished ${RELDIR}.${TARGET_SPEC} seconds=$$(( ${now_utc} - ${start_utc} )) ${meta_stats}"
|
||||
.endif
|
||||
|
||||
.if !target(_reldir_failed)
|
||||
#.ERROR: _reldir_failed
|
||||
_reldir_failed: .NOMETA
|
||||
@echo "${TIME_STAMP} Failed ${RELDIR}.${TARGET_SPEC} seconds=$$(( ${now_utc} - ${start_utc} )) ${meta_stats}"
|
||||
.endif
|
||||
|
||||
.if !defined(WITHOUT_META_STATS) && ${.MAKE.LEVEL} > 0
|
||||
.END: _reldir_finish
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
"""
|
||||
RCSid:
|
||||
$Id: meta2deps.py,v 1.34 2020/10/02 03:11:17 sjg Exp $
|
||||
$Id: meta2deps.py,v 1.38 2021/06/17 05:20:08 sjg Exp $
|
||||
|
||||
Copyright (c) 2011-2020, Simon J. Gerraty
|
||||
Copyright (c) 2011-2017, Juniper Networks, Inc.
|
||||
@ -68,12 +68,6 @@
|
||||
|
||||
import os, re, sys
|
||||
|
||||
def getv(dict, key, d=None):
|
||||
"""Lookup key in dict and return value or the supplied default."""
|
||||
if key in dict:
|
||||
return dict[key]
|
||||
return d
|
||||
|
||||
def resolve(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr):
|
||||
"""
|
||||
Return an absolute path, resolving via cwd or last_dir if needed.
|
||||
@ -152,7 +146,10 @@ def abspath(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr):
|
||||
return path
|
||||
|
||||
def sort_unique(list, cmp=None, key=None, reverse=False):
|
||||
list.sort(cmp, key, reverse)
|
||||
if sys.version_info[0] == 2:
|
||||
list.sort(cmp, key, reverse)
|
||||
else:
|
||||
list.sort(reverse=reverse)
|
||||
nl = []
|
||||
le = None
|
||||
for e in list:
|
||||
@ -224,22 +221,22 @@ def __init__(self, name, conf={}):
|
||||
"""
|
||||
|
||||
self.name = name
|
||||
self.debug = getv(conf, 'debug', 0)
|
||||
self.debug_out = getv(conf, 'debug_out', sys.stderr)
|
||||
self.debug = conf.get('debug', 0)
|
||||
self.debug_out = conf.get('debug_out', sys.stderr)
|
||||
|
||||
self.machine = getv(conf, 'MACHINE', '')
|
||||
self.machine_arch = getv(conf, 'MACHINE_ARCH', '')
|
||||
self.target_spec = getv(conf, 'TARGET_SPEC', '')
|
||||
self.curdir = getv(conf, 'CURDIR')
|
||||
self.reldir = getv(conf, 'RELDIR')
|
||||
self.dpdeps = getv(conf, 'DPDEPS')
|
||||
self.machine = conf.get('MACHINE', '')
|
||||
self.machine_arch = conf.get('MACHINE_ARCH', '')
|
||||
self.target_spec = conf.get('TARGET_SPEC', '')
|
||||
self.curdir = conf.get('CURDIR')
|
||||
self.reldir = conf.get('RELDIR')
|
||||
self.dpdeps = conf.get('DPDEPS')
|
||||
self.line = 0
|
||||
|
||||
if not self.conf:
|
||||
# some of the steps below we want to do only once
|
||||
self.conf = conf
|
||||
self.host_target = getv(conf, 'HOST_TARGET')
|
||||
for srctop in getv(conf, 'SRCTOPS', []):
|
||||
self.host_target = conf.get('HOST_TARGET')
|
||||
for srctop in conf.get('SRCTOPS', []):
|
||||
if srctop[-1] != '/':
|
||||
srctop += '/'
|
||||
if not srctop in self.srctops:
|
||||
@ -256,7 +253,7 @@ def __init__(self, name, conf={}):
|
||||
if self.target_spec:
|
||||
trim_list += add_trims(self.target_spec)
|
||||
|
||||
for objroot in getv(conf, 'OBJROOTS', []):
|
||||
for objroot in conf.get('OBJROOTS', []):
|
||||
for e in trim_list:
|
||||
if objroot.endswith(e):
|
||||
# this is not what we want - fix it
|
||||
@ -276,7 +273,7 @@ def __init__(self, name, conf={}):
|
||||
self.srctops.sort(reverse=True)
|
||||
self.objroots.sort(reverse=True)
|
||||
|
||||
self.excludes = getv(conf, 'EXCLUDES', [])
|
||||
self.excludes = conf.get('EXCLUDES', [])
|
||||
|
||||
if self.debug:
|
||||
print("host_target=", self.host_target, file=self.debug_out)
|
||||
@ -468,8 +465,8 @@ def parse(self, name=None, file=None):
|
||||
if pid != last_pid:
|
||||
if last_pid:
|
||||
pid_last_dir[last_pid] = self.last_dir
|
||||
cwd = getv(pid_cwd, pid, self.cwd)
|
||||
self.last_dir = getv(pid_last_dir, pid, self.cwd)
|
||||
cwd = pid_cwd.get(pid, self.cwd)
|
||||
self.last_dir = pid_last_dir.get(pid, self.cwd)
|
||||
last_pid = pid
|
||||
|
||||
# process operations
|
||||
@ -557,7 +554,10 @@ def parse_path(self, path, cwd, op=None, w=[]):
|
||||
# to the src dir, we may need to add dependencies for each
|
||||
rdir = dir
|
||||
dir = abspath(dir, cwd, self.last_dir, self.debug, self.debug_out)
|
||||
rdir = os.path.realpath(dir)
|
||||
if dir:
|
||||
rdir = os.path.realpath(dir)
|
||||
else:
|
||||
dir = rdir
|
||||
if rdir == dir:
|
||||
rdir = None
|
||||
# now put path back together
|
||||
@ -725,7 +725,7 @@ def main(argv, klass=MetaFile, xopts='', xoptf=None):
|
||||
for a in eaten:
|
||||
args.remove(a)
|
||||
|
||||
debug_out = getv(conf, 'debug_out', sys.stderr)
|
||||
debug_out = conf.get('debug_out', sys.stderr)
|
||||
|
||||
if debug:
|
||||
print("config:", file=debug_out)
|
||||
@ -752,9 +752,9 @@ def main(argv, klass=MetaFile, xopts='', xoptf=None):
|
||||
|
||||
print(m.src_dirdeps('\nsrc:'))
|
||||
|
||||
dpdeps = getv(conf, 'DPDEPS')
|
||||
dpdeps = conf.get('DPDEPS')
|
||||
if dpdeps:
|
||||
m.file_depends(open(dpdeps, 'wb'))
|
||||
m.file_depends(open(dpdeps, 'w'))
|
||||
|
||||
return m
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: rst2htm.mk,v 1.11 2020/08/19 17:51:53 sjg Exp $
|
||||
# $Id: rst2htm.mk,v 1.12 2021/05/26 04:20:31 sjg Exp $
|
||||
#
|
||||
# @(#) Copyright (c) 2009, Simon J. Gerraty
|
||||
#
|
||||
@ -21,7 +21,9 @@ TXTSRCS != 'ls' -1t ${.CURDIR}/*.txt ${.CURDIR}/*.rst 2>/dev/null; echo
|
||||
.endif
|
||||
RSTSRCS ?= ${TXTSRCS}
|
||||
HTMFILES ?= ${RSTSRCS:R:T:O:u:%=%.htm}
|
||||
RST2HTML ?= rst2html.py
|
||||
# can be empty, 4 or 5
|
||||
HTML_VERSION ?=
|
||||
RST2HTML ?= rst2html${HTML_VERSION}.py
|
||||
RST2PDF ?= rst2pdf
|
||||
RST2S5 ?= rst2s5.py
|
||||
# the following will run RST2S5 if the target name contains the word 'slides'
|
||||
|
153
nonints.h
153
nonints.h
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: nonints.h,v 1.202 2021/02/05 05:15:12 rillig Exp $ */
|
||||
/* $NetBSD: nonints.h,v 1.213 2021/04/11 13:35:56 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -76,14 +76,14 @@
|
||||
void Arch_Init(void);
|
||||
void Arch_End(void);
|
||||
|
||||
Boolean Arch_ParseArchive(char **, GNodeList *, GNode *);
|
||||
bool Arch_ParseArchive(char **, GNodeList *, GNode *);
|
||||
void Arch_Touch(GNode *);
|
||||
void Arch_TouchLib(GNode *);
|
||||
void Arch_UpdateMTime(GNode *gn);
|
||||
void Arch_UpdateMemberMTime(GNode *gn);
|
||||
void Arch_FindLib(GNode *, SearchPath *);
|
||||
Boolean Arch_LibOODate(GNode *);
|
||||
Boolean Arch_IsLib(GNode *);
|
||||
bool Arch_LibOODate(GNode *);
|
||||
bool Arch_IsLib(GNode *);
|
||||
|
||||
/* compat.c */
|
||||
int Compat_RunCommand(const char *, GNode *, StringListNode *);
|
||||
@ -91,7 +91,7 @@ void Compat_Run(GNodeList *);
|
||||
void Compat_Make(GNode *, GNode *);
|
||||
|
||||
/* cond.c */
|
||||
CondEvalResult Cond_EvalCondition(const char *, Boolean *);
|
||||
CondEvalResult Cond_EvalCondition(const char *, bool *);
|
||||
CondEvalResult Cond_EvalLine(const char *);
|
||||
void Cond_restore_depth(unsigned int);
|
||||
unsigned int Cond_save_depth(void);
|
||||
@ -117,16 +117,16 @@ void SearchPath_Free(SearchPath *);
|
||||
|
||||
/* for.c */
|
||||
int For_Eval(const char *);
|
||||
Boolean For_Accum(const char *);
|
||||
bool For_Accum(const char *);
|
||||
void For_Run(int);
|
||||
|
||||
/* job.c */
|
||||
#ifdef WAIT_T
|
||||
void JobReapChild(pid_t, WAIT_T, Boolean);
|
||||
void JobReapChild(pid_t, WAIT_T, bool);
|
||||
#endif
|
||||
|
||||
/* main.c */
|
||||
Boolean GetBooleanVar(const char *, Boolean);
|
||||
bool GetBooleanExpr(const char *, bool);
|
||||
void Main_ParseArgLine(const char *);
|
||||
char *Cmd_Exec(const char *, const char **);
|
||||
void Error(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2);
|
||||
@ -137,7 +137,7 @@ void Finish(int) MAKE_ATTR_DEAD;
|
||||
int eunlink(const char *);
|
||||
void execDie(const char *, const char *);
|
||||
char *getTmpdir(void);
|
||||
Boolean ParseBoolean(const char *, Boolean);
|
||||
bool ParseBoolean(const char *, bool);
|
||||
char *cached_realpath(const char *, char *);
|
||||
|
||||
/* parse.c */
|
||||
@ -161,86 +161,14 @@ typedef struct VarAssign {
|
||||
typedef char *(*ReadMoreProc)(void *, size_t *);
|
||||
|
||||
void Parse_Error(ParseErrorLevel, const char *, ...) MAKE_ATTR_PRINTFLIKE(2, 3);
|
||||
Boolean Parse_IsVar(const char *, VarAssign *out_var);
|
||||
void Parse_DoVar(VarAssign *, GNode *);
|
||||
bool Parse_IsVar(const char *, VarAssign *out_var);
|
||||
void Parse_Var(VarAssign *, GNode *);
|
||||
void Parse_AddIncludeDir(const char *);
|
||||
void Parse_File(const char *, int);
|
||||
void Parse_SetInput(const char *, int, int, ReadMoreProc, void *);
|
||||
void Parse_MainName(GNodeList *);
|
||||
int Parse_GetFatals(void);
|
||||
|
||||
/* str.c */
|
||||
|
||||
/* A read-only string that may need to be freed after use. */
|
||||
typedef struct FStr {
|
||||
const char *str;
|
||||
void *freeIt;
|
||||
} FStr;
|
||||
|
||||
/* A modifiable string that may need to be freed after use. */
|
||||
typedef struct MFStr {
|
||||
char *str;
|
||||
void *freeIt;
|
||||
} MFStr;
|
||||
|
||||
typedef struct Words {
|
||||
char **words;
|
||||
size_t len;
|
||||
void *freeIt;
|
||||
} Words;
|
||||
|
||||
/* Return a string that is the sole owner of str. */
|
||||
MAKE_INLINE FStr
|
||||
FStr_InitOwn(char *str)
|
||||
{
|
||||
return (FStr){ str, str };
|
||||
}
|
||||
|
||||
/* Return a string that refers to the shared str. */
|
||||
MAKE_INLINE FStr
|
||||
FStr_InitRefer(const char *str)
|
||||
{
|
||||
return (FStr){ str, NULL };
|
||||
}
|
||||
|
||||
MAKE_INLINE void
|
||||
FStr_Done(FStr *fstr)
|
||||
{
|
||||
free(fstr->freeIt);
|
||||
}
|
||||
|
||||
/* Return a string that is the sole owner of str. */
|
||||
MAKE_INLINE MFStr
|
||||
MFStr_InitOwn(char *str)
|
||||
{
|
||||
return (MFStr){ str, str };
|
||||
}
|
||||
|
||||
/* Return a string that refers to the shared str. */
|
||||
MAKE_INLINE MFStr
|
||||
MFStr_InitRefer(char *str)
|
||||
{
|
||||
return (MFStr){ str, NULL };
|
||||
}
|
||||
|
||||
MAKE_INLINE void
|
||||
MFStr_Done(MFStr *mfstr)
|
||||
{
|
||||
free(mfstr->freeIt);
|
||||
}
|
||||
|
||||
Words Str_Words(const char *, Boolean);
|
||||
MAKE_INLINE void
|
||||
Words_Free(Words w)
|
||||
{
|
||||
free(w.words);
|
||||
free(w.freeIt);
|
||||
}
|
||||
|
||||
char *str_concat2(const char *, const char *);
|
||||
char *str_concat3(const char *, const char *, const char *);
|
||||
char *str_concat4(const char *, const char *, const char *, const char *);
|
||||
Boolean Str_Match(const char *, const char *);
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
/* strlcpy.c */
|
||||
@ -252,12 +180,12 @@ void Suff_Init(void);
|
||||
void Suff_End(void);
|
||||
|
||||
void Suff_ClearSuffixes(void);
|
||||
Boolean Suff_IsTransform(const char *);
|
||||
bool Suff_IsTransform(const char *);
|
||||
GNode *Suff_AddTransform(const char *);
|
||||
void Suff_EndTransform(GNode *);
|
||||
void Suff_AddSuffix(const char *, GNode **);
|
||||
SearchPath *Suff_GetPath(const char *);
|
||||
void Suff_DoPaths(void);
|
||||
void Suff_ExtendPaths(void);
|
||||
void Suff_AddInclude(const char *);
|
||||
void Suff_AddLib(const char *);
|
||||
void Suff_FindDeps(GNode *);
|
||||
@ -277,7 +205,7 @@ GNode *Targ_GetNode(const char *);
|
||||
GNode *Targ_NewInternalNode(const char *);
|
||||
GNode *Targ_GetEndNode(void);
|
||||
void Targ_FindList(GNodeList *, StringList *);
|
||||
Boolean Targ_Precious(const GNode *);
|
||||
bool Targ_Precious(const GNode *);
|
||||
void Targ_SetMain(GNode *);
|
||||
void Targ_PrintCmds(GNode *);
|
||||
void Targ_PrintNode(GNode *, int);
|
||||
@ -292,36 +220,40 @@ const char *GNodeMade_Name(GNodeMade);
|
||||
void Var_Init(void);
|
||||
void Var_End(void);
|
||||
|
||||
typedef enum VarEvalFlags {
|
||||
VARE_NONE = 0,
|
||||
typedef enum VarEvalMode {
|
||||
|
||||
/*
|
||||
* Expand and evaluate variables during parsing.
|
||||
* Only parse the expression but don't evaluate any part of it.
|
||||
*
|
||||
* TODO: Document what Var_Parse and Var_Subst return when this flag
|
||||
* is not set.
|
||||
* TODO: Document what Var_Parse and Var_Subst return in this mode.
|
||||
* As of 2021-03-15, they return unspecified, inconsistent results.
|
||||
*/
|
||||
VARE_WANTRES = 1 << 0,
|
||||
VARE_PARSE_ONLY,
|
||||
|
||||
/* Parse and evaluate the expression. */
|
||||
VARE_WANTRES,
|
||||
|
||||
/*
|
||||
* Treat undefined variables as errors.
|
||||
* Must only be used in combination with VARE_WANTRES.
|
||||
* Parse and evaluate the expression. It is an error if a
|
||||
* subexpression evaluates to undefined.
|
||||
*/
|
||||
VARE_UNDEFERR = 1 << 1,
|
||||
VARE_UNDEFERR,
|
||||
|
||||
/*
|
||||
* Keep '$$' as '$$' instead of reducing it to a single '$'.
|
||||
* Parse and evaluate the expression. Keep '$$' as '$$' instead of
|
||||
* reducing it to a single '$'. Subexpressions that evaluate to
|
||||
* undefined expand to an empty string.
|
||||
*
|
||||
* Used in variable assignments using the ':=' operator. It allows
|
||||
* multiple such assignments to be chained without accidentally
|
||||
* expanding '$$file' to '$file' in the first assignment and
|
||||
* interpreting it as '${f}' followed by 'ile' in the next assignment.
|
||||
*/
|
||||
VARE_KEEP_DOLLAR = 1 << 2,
|
||||
VARE_EVAL_KEEP_DOLLAR,
|
||||
|
||||
/*
|
||||
* Keep undefined variables as-is instead of expanding them to an
|
||||
* empty string.
|
||||
* Parse and evaluate the expression. Keep undefined variables as-is
|
||||
* instead of expanding them to an empty string.
|
||||
*
|
||||
* Example for a ':=' assignment:
|
||||
* CFLAGS = $(.INCLUDES)
|
||||
@ -330,8 +262,14 @@ typedef enum VarEvalFlags {
|
||||
* # way) is still undefined, the updated CFLAGS becomes
|
||||
* # "-I.. $(.INCLUDES)".
|
||||
*/
|
||||
VARE_KEEP_UNDEF = 1 << 3
|
||||
} VarEvalFlags;
|
||||
VARE_EVAL_KEEP_UNDEF,
|
||||
|
||||
/*
|
||||
* Parse and evaluate the expression. Keep '$$' as '$$' and preserve
|
||||
* undefined subexpressions.
|
||||
*/
|
||||
VARE_KEEP_DOLLAR_UNDEF
|
||||
} VarEvalMode;
|
||||
|
||||
typedef enum VarSetFlags {
|
||||
VAR_SET_NONE = 0,
|
||||
@ -361,7 +299,8 @@ typedef enum VarParseResult {
|
||||
* Some callers handle this case differently, so return this
|
||||
* information to them, for now.
|
||||
*
|
||||
* TODO: Replace this with a new flag VARE_KEEP_UNDEFINED.
|
||||
* TODO: Instead of having this special return value, rather ensure
|
||||
* that VARE_EVAL_KEEP_UNDEF is processed properly.
|
||||
*/
|
||||
VPR_UNDEF
|
||||
|
||||
@ -385,18 +324,18 @@ void Var_SetWithFlags(GNode *, const char *, const char *, VarSetFlags);
|
||||
void Var_SetExpandWithFlags(GNode *, const char *, const char *, VarSetFlags);
|
||||
void Var_Append(GNode *, const char *, const char *);
|
||||
void Var_AppendExpand(GNode *, const char *, const char *);
|
||||
Boolean Var_Exists(GNode *, const char *);
|
||||
Boolean Var_ExistsExpand(GNode *, const char *);
|
||||
bool Var_Exists(GNode *, const char *);
|
||||
bool Var_ExistsExpand(GNode *, const char *);
|
||||
FStr Var_Value(GNode *, const char *);
|
||||
const char *GNode_ValueDirect(GNode *, const char *);
|
||||
VarParseResult Var_Parse(const char **, GNode *, VarEvalFlags, FStr *);
|
||||
VarParseResult Var_Subst(const char *, GNode *, VarEvalFlags, char **);
|
||||
VarParseResult Var_Parse(const char **, GNode *, VarEvalMode, FStr *);
|
||||
VarParseResult Var_Subst(const char *, GNode *, VarEvalMode, char **);
|
||||
void Var_Stats(void);
|
||||
void Var_Dump(GNode *);
|
||||
void Var_ReexportVars(void);
|
||||
void Var_Export(VarExportMode, const char *);
|
||||
void Var_ExportVars(const char *);
|
||||
void Var_UnExport(Boolean, const char *);
|
||||
void Var_UnExport(bool, const char *);
|
||||
|
||||
void Global_Set(const char *, const char *);
|
||||
void Global_SetExpand(const char *, const char *);
|
||||
|
101
str.c
101
str.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: str.c,v 1.81 2021/02/01 22:36:28 rillig Exp $ */
|
||||
/* $NetBSD: str.c,v 1.85 2021/05/30 21:16:54 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -71,7 +71,7 @@
|
||||
#include "make.h"
|
||||
|
||||
/* "@(#)str.c 5.8 (Berkeley) 6/1/90" */
|
||||
MAKE_RCSID("$NetBSD: str.c,v 1.81 2021/02/01 22:36:28 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: str.c,v 1.85 2021/05/30 21:16:54 rillig Exp $");
|
||||
|
||||
/* Return the concatenation of s1 and s2, freshly allocated. */
|
||||
char *
|
||||
@ -99,39 +99,23 @@ str_concat3(const char *s1, const char *s2, const char *s3)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Return the concatenation of s1, s2, s3 and s4, freshly allocated. */
|
||||
char *
|
||||
str_concat4(const char *s1, const char *s2, const char *s3, const char *s4)
|
||||
{
|
||||
size_t len1 = strlen(s1);
|
||||
size_t len2 = strlen(s2);
|
||||
size_t len3 = strlen(s3);
|
||||
size_t len4 = strlen(s4);
|
||||
char *result = bmake_malloc(len1 + len2 + len3 + len4 + 1);
|
||||
memcpy(result, s1, len1);
|
||||
memcpy(result + len1, s2, len2);
|
||||
memcpy(result + len1 + len2, s3, len3);
|
||||
memcpy(result + len1 + len2 + len3, s4, len4 + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fracture a string into an array of words (as delineated by tabs or spaces)
|
||||
* taking quotation marks into account.
|
||||
*
|
||||
* If expand is TRUE, quotes are removed and escape sequences such as \r, \t,
|
||||
* If expand is true, quotes are removed and escape sequences such as \r, \t,
|
||||
* etc... are expanded. In this case, return NULL on parse errors.
|
||||
*
|
||||
* Returns the fractured words, which must be freed later using Words_Free,
|
||||
* unless the returned Words.words was NULL.
|
||||
*/
|
||||
Words
|
||||
Str_Words(const char *str, Boolean expand)
|
||||
SubstringWords
|
||||
Substring_Words(const char *str, bool expand)
|
||||
{
|
||||
size_t str_len;
|
||||
char *words_buf;
|
||||
size_t words_cap;
|
||||
char **words;
|
||||
Substring *words;
|
||||
size_t words_len;
|
||||
char inquote;
|
||||
char *word_start;
|
||||
@ -146,7 +130,7 @@ Str_Words(const char *str, Boolean expand)
|
||||
words_buf = bmake_malloc(str_len + 1);
|
||||
|
||||
words_cap = str_len / 5 > 50 ? str_len / 5 : 50;
|
||||
words = bmake_malloc((words_cap + 1) * sizeof(char *));
|
||||
words = bmake_malloc((words_cap + 1) * sizeof(words[0]));
|
||||
|
||||
/*
|
||||
* copy the string; at the same time, parse backslashes,
|
||||
@ -205,17 +189,24 @@ Str_Words(const char *str, Boolean expand)
|
||||
*word_end++ = '\0';
|
||||
if (words_len == words_cap) {
|
||||
size_t new_size;
|
||||
words_cap *= 2; /* ramp up fast */
|
||||
new_size = (words_cap + 1) * sizeof(char *);
|
||||
words_cap *= 2;
|
||||
new_size = (words_cap + 1) * sizeof(words[0]);
|
||||
words = bmake_realloc(words, new_size);
|
||||
}
|
||||
words[words_len++] = word_start;
|
||||
words[words_len++] =
|
||||
Substring_Init(word_start, word_end - 1);
|
||||
word_start = NULL;
|
||||
if (ch == '\n' || ch == '\0') {
|
||||
if (expand && inquote != '\0') {
|
||||
SubstringWords res;
|
||||
|
||||
free(words);
|
||||
free(words_buf);
|
||||
return (Words){ NULL, 0, NULL };
|
||||
|
||||
res.words = NULL;
|
||||
res.len = 0;
|
||||
res.freeIt = NULL;
|
||||
return res;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
@ -262,8 +253,40 @@ Str_Words(const char *str, Boolean expand)
|
||||
*word_end++ = ch;
|
||||
}
|
||||
done:
|
||||
words[words_len] = NULL; /* useful for argv */
|
||||
return (Words){ words, words_len, words_buf };
|
||||
words[words_len] = Substring_Init(NULL, NULL); /* useful for argv */
|
||||
|
||||
{
|
||||
SubstringWords result;
|
||||
|
||||
result.words = words;
|
||||
result.len = words_len;
|
||||
result.freeIt = words_buf;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Words
|
||||
Str_Words(const char *str, bool expand)
|
||||
{
|
||||
SubstringWords swords;
|
||||
Words words;
|
||||
size_t i;
|
||||
|
||||
swords = Substring_Words(str, expand);
|
||||
if (swords.words == NULL) {
|
||||
words.words = NULL;
|
||||
words.len = 0;
|
||||
words.freeIt = NULL;
|
||||
return words;
|
||||
}
|
||||
|
||||
words.words = bmake_malloc((swords.len + 1) * sizeof(words.words[0]));
|
||||
words.len = swords.len;
|
||||
words.freeIt = swords.freeIt;
|
||||
for (i = 0; i < swords.len + 1; i++)
|
||||
words.words[i] = UNCONST(swords.words[i].start);
|
||||
free(swords.words);
|
||||
return words;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -272,7 +295,7 @@ Str_Words(const char *str, Boolean expand)
|
||||
*
|
||||
* XXX: this function does not detect or report malformed patterns.
|
||||
*/
|
||||
Boolean
|
||||
bool
|
||||
Str_Match(const char *str, const char *pat)
|
||||
{
|
||||
for (;;) {
|
||||
@ -284,7 +307,7 @@ Str_Match(const char *str, const char *pat)
|
||||
if (*pat == '\0')
|
||||
return *str == '\0';
|
||||
if (*str == '\0' && *pat != '*')
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
/*
|
||||
* A '*' in the pattern matches any substring. We handle this
|
||||
@ -295,13 +318,13 @@ Str_Match(const char *str, const char *pat)
|
||||
while (*pat == '*')
|
||||
pat++;
|
||||
if (*pat == '\0')
|
||||
return TRUE;
|
||||
return true;
|
||||
while (*str != '\0') {
|
||||
if (Str_Match(str, pat))
|
||||
return TRUE;
|
||||
return true;
|
||||
str++;
|
||||
}
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* A '?' in the pattern matches any single character. */
|
||||
@ -315,14 +338,14 @@ Str_Match(const char *str, const char *pat)
|
||||
* character lists, the backslash is an ordinary character.
|
||||
*/
|
||||
if (*pat == '[') {
|
||||
Boolean neg = pat[1] == '^';
|
||||
bool neg = pat[1] == '^';
|
||||
pat += neg ? 2 : 1;
|
||||
|
||||
for (;;) {
|
||||
if (*pat == ']' || *pat == '\0') {
|
||||
if (neg)
|
||||
break;
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* XXX: This naive comparison makes the
|
||||
@ -347,7 +370,7 @@ Str_Match(const char *str, const char *pat)
|
||||
pat++;
|
||||
}
|
||||
if (neg && *pat != ']' && *pat != '\0')
|
||||
return FALSE;
|
||||
return false;
|
||||
while (*pat != ']' && *pat != '\0')
|
||||
pat++;
|
||||
if (*pat == '\0')
|
||||
@ -362,11 +385,11 @@ Str_Match(const char *str, const char *pat)
|
||||
if (*pat == '\\') {
|
||||
pat++;
|
||||
if (*pat == '\0')
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*pat != *str)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
thisCharOK:
|
||||
pat++;
|
||||
|
366
str.h
Normal file
366
str.h
Normal file
@ -0,0 +1,366 @@
|
||||
/* $NetBSD: str.h,v 1.9 2021/05/30 21:16:54 rillig Exp $ */
|
||||
|
||||
/*
|
||||
Copyright (c) 2021 Roland Illig <rillig@NetBSD.org>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
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.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Memory-efficient string handling.
|
||||
*/
|
||||
|
||||
|
||||
/* A read-only string that may need to be freed after use. */
|
||||
typedef struct FStr {
|
||||
const char *str;
|
||||
void *freeIt;
|
||||
} FStr;
|
||||
|
||||
/* A modifiable string that may need to be freed after use. */
|
||||
typedef struct MFStr {
|
||||
char *str;
|
||||
void *freeIt;
|
||||
} MFStr;
|
||||
|
||||
/* A read-only range of a character array, NOT null-terminated. */
|
||||
typedef struct Substring {
|
||||
const char *start;
|
||||
const char *end;
|
||||
} Substring;
|
||||
|
||||
/*
|
||||
* Builds a string, only allocating memory if the string is different from the
|
||||
* expected string.
|
||||
*/
|
||||
typedef struct LazyBuf {
|
||||
char *data;
|
||||
size_t len;
|
||||
size_t cap;
|
||||
const char *expected;
|
||||
void *freeIt;
|
||||
} LazyBuf;
|
||||
|
||||
/* The result of splitting a string into words. */
|
||||
typedef struct Words {
|
||||
char **words;
|
||||
size_t len;
|
||||
void *freeIt;
|
||||
} Words;
|
||||
|
||||
/* The result of splitting a string into words. */
|
||||
typedef struct SubstringWords {
|
||||
Substring *words;
|
||||
size_t len;
|
||||
void *freeIt;
|
||||
} SubstringWords;
|
||||
|
||||
|
||||
MAKE_INLINE FStr
|
||||
FStr_Init(const char *str, void *freeIt)
|
||||
{
|
||||
FStr fstr;
|
||||
fstr.str = str;
|
||||
fstr.freeIt = freeIt;
|
||||
return fstr;
|
||||
}
|
||||
|
||||
/* Return a string that is the sole owner of str. */
|
||||
MAKE_INLINE FStr
|
||||
FStr_InitOwn(char *str)
|
||||
{
|
||||
return FStr_Init(str, str);
|
||||
}
|
||||
|
||||
/* Return a string that refers to the shared str. */
|
||||
MAKE_INLINE FStr
|
||||
FStr_InitRefer(const char *str)
|
||||
{
|
||||
return FStr_Init(str, NULL);
|
||||
}
|
||||
|
||||
MAKE_INLINE void
|
||||
FStr_Done(FStr *fstr)
|
||||
{
|
||||
free(fstr->freeIt);
|
||||
#ifdef CLEANUP
|
||||
fstr->str = NULL;
|
||||
fstr->freeIt = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
MAKE_INLINE MFStr
|
||||
MFStr_Init(char *str, void *freeIt)
|
||||
{
|
||||
MFStr mfstr;
|
||||
mfstr.str = str;
|
||||
mfstr.freeIt = freeIt;
|
||||
return mfstr;
|
||||
}
|
||||
|
||||
/* Return a string that is the sole owner of str. */
|
||||
MAKE_INLINE MFStr
|
||||
MFStr_InitOwn(char *str)
|
||||
{
|
||||
return MFStr_Init(str, str);
|
||||
}
|
||||
|
||||
/* Return a string that refers to the shared str. */
|
||||
MAKE_INLINE MFStr
|
||||
MFStr_InitRefer(char *str)
|
||||
{
|
||||
return MFStr_Init(str, NULL);
|
||||
}
|
||||
|
||||
MAKE_INLINE void
|
||||
MFStr_Done(MFStr *mfstr)
|
||||
{
|
||||
free(mfstr->freeIt);
|
||||
#ifdef CLEANUP
|
||||
mfstr->str = NULL;
|
||||
mfstr->freeIt = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
MAKE_STATIC Substring
|
||||
Substring_Init(const char *start, const char *end)
|
||||
{
|
||||
Substring sub;
|
||||
|
||||
sub.start = start;
|
||||
sub.end = end;
|
||||
return sub;
|
||||
}
|
||||
|
||||
MAKE_INLINE Substring
|
||||
Substring_InitStr(const char *str)
|
||||
{
|
||||
return Substring_Init(str, str + strlen(str));
|
||||
}
|
||||
|
||||
MAKE_STATIC size_t
|
||||
Substring_Length(Substring sub)
|
||||
{
|
||||
return (size_t)(sub.end - sub.start);
|
||||
}
|
||||
|
||||
MAKE_STATIC bool
|
||||
Substring_IsEmpty(Substring sub)
|
||||
{
|
||||
return sub.start == sub.end;
|
||||
}
|
||||
|
||||
MAKE_INLINE bool
|
||||
Substring_Equals(Substring sub, const char *str)
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
return Substring_Length(sub) == len &&
|
||||
memcmp(sub.start, str, len) == 0;
|
||||
}
|
||||
|
||||
MAKE_STATIC Substring
|
||||
Substring_Sub(Substring sub, size_t start, size_t end)
|
||||
{
|
||||
assert(start <= Substring_Length(sub));
|
||||
assert(end <= Substring_Length(sub));
|
||||
return Substring_Init(sub.start + start, sub.start + end);
|
||||
}
|
||||
|
||||
MAKE_STATIC bool
|
||||
Substring_HasPrefix(Substring sub, Substring prefix)
|
||||
{
|
||||
return Substring_Length(sub) >= Substring_Length(prefix) &&
|
||||
memcmp(sub.start, prefix.start, Substring_Length(prefix)) == 0;
|
||||
}
|
||||
|
||||
MAKE_STATIC bool
|
||||
Substring_HasSuffix(Substring sub, Substring suffix)
|
||||
{
|
||||
size_t suffixLen = Substring_Length(suffix);
|
||||
return Substring_Length(sub) >= suffixLen &&
|
||||
memcmp(sub.end - suffixLen, suffix.start, suffixLen) == 0;
|
||||
}
|
||||
|
||||
/* Returns an independent, null-terminated copy of the substring. */
|
||||
MAKE_STATIC FStr
|
||||
Substring_Str(Substring sub)
|
||||
{
|
||||
if (Substring_IsEmpty(sub))
|
||||
return FStr_InitRefer("");
|
||||
return FStr_InitOwn(bmake_strsedup(sub.start, sub.end));
|
||||
}
|
||||
|
||||
MAKE_STATIC const char *
|
||||
Substring_SkipFirst(Substring sub, char ch)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
for (p = sub.start; p != sub.end; p++)
|
||||
if (*p == ch)
|
||||
return p + 1;
|
||||
return sub.start;
|
||||
}
|
||||
|
||||
MAKE_STATIC const char *
|
||||
Substring_LastIndex(Substring sub, char ch)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
for (p = sub.end; p != sub.start; p--)
|
||||
if (p[-1] == ch)
|
||||
return p - 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MAKE_STATIC Substring
|
||||
Substring_Dirname(Substring pathname)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
for (p = pathname.end; p != pathname.start; p--)
|
||||
if (p[-1] == '/')
|
||||
return Substring_Init(pathname.start, p - 1);
|
||||
return Substring_InitStr(".");
|
||||
}
|
||||
|
||||
MAKE_STATIC Substring
|
||||
Substring_Basename(Substring pathname)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
for (p = pathname.end; p != pathname.start; p--)
|
||||
if (p[-1] == '/')
|
||||
return Substring_Init(p, pathname.end);
|
||||
return pathname;
|
||||
}
|
||||
|
||||
|
||||
MAKE_STATIC void
|
||||
LazyBuf_Init(LazyBuf *buf, const char *expected)
|
||||
{
|
||||
buf->data = NULL;
|
||||
buf->len = 0;
|
||||
buf->cap = 0;
|
||||
buf->expected = expected;
|
||||
buf->freeIt = NULL;
|
||||
}
|
||||
|
||||
MAKE_INLINE void
|
||||
LazyBuf_Done(LazyBuf *buf)
|
||||
{
|
||||
free(buf->freeIt);
|
||||
}
|
||||
|
||||
MAKE_STATIC void
|
||||
LazyBuf_Add(LazyBuf *buf, char ch)
|
||||
{
|
||||
|
||||
if (buf->data != NULL) {
|
||||
if (buf->len == buf->cap) {
|
||||
buf->cap *= 2;
|
||||
buf->data = bmake_realloc(buf->data, buf->cap);
|
||||
}
|
||||
buf->data[buf->len++] = ch;
|
||||
|
||||
} else if (ch == buf->expected[buf->len]) {
|
||||
buf->len++;
|
||||
return;
|
||||
|
||||
} else {
|
||||
buf->cap = buf->len + 16;
|
||||
buf->data = bmake_malloc(buf->cap);
|
||||
memcpy(buf->data, buf->expected, buf->len);
|
||||
buf->data[buf->len++] = ch;
|
||||
}
|
||||
}
|
||||
|
||||
MAKE_STATIC void
|
||||
LazyBuf_AddStr(LazyBuf *buf, const char *str)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
for (p = str; *p != '\0'; p++)
|
||||
LazyBuf_Add(buf, *p);
|
||||
}
|
||||
|
||||
MAKE_STATIC void
|
||||
LazyBuf_AddBytesBetween(LazyBuf *buf, const char *start, const char *end)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
for (p = start; p != end; p++)
|
||||
LazyBuf_Add(buf, *p);
|
||||
}
|
||||
|
||||
MAKE_INLINE void
|
||||
LazyBuf_AddSubstring(LazyBuf *buf, Substring sub)
|
||||
{
|
||||
LazyBuf_AddBytesBetween(buf, sub.start, sub.end);
|
||||
}
|
||||
|
||||
MAKE_STATIC Substring
|
||||
LazyBuf_Get(const LazyBuf *buf)
|
||||
{
|
||||
const char *start = buf->data != NULL ? buf->data : buf->expected;
|
||||
return Substring_Init(start, start + buf->len);
|
||||
}
|
||||
|
||||
MAKE_STATIC FStr
|
||||
LazyBuf_DoneGet(LazyBuf *buf)
|
||||
{
|
||||
if (buf->data != NULL) {
|
||||
LazyBuf_Add(buf, '\0');
|
||||
return FStr_InitOwn(buf->data);
|
||||
}
|
||||
return Substring_Str(LazyBuf_Get(buf));
|
||||
}
|
||||
|
||||
|
||||
Words Str_Words(const char *, bool);
|
||||
|
||||
MAKE_INLINE void
|
||||
Words_Free(Words w)
|
||||
{
|
||||
free(w.words);
|
||||
free(w.freeIt);
|
||||
}
|
||||
|
||||
|
||||
SubstringWords Substring_Words(const char *, bool);
|
||||
|
||||
MAKE_INLINE void
|
||||
SubstringWords_Free(SubstringWords w)
|
||||
{
|
||||
free(w.words);
|
||||
free(w.freeIt);
|
||||
}
|
||||
|
||||
|
||||
char *str_concat2(const char *, const char *);
|
||||
char *str_concat3(const char *, const char *, const char *);
|
||||
|
||||
bool Str_Match(const char *, const char *);
|
71
suff.c
71
suff.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: suff.c,v 1.345 2021/02/05 05:15:12 rillig Exp $ */
|
||||
/* $NetBSD: suff.c,v 1.350 2021/04/04 10:05:08 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -77,7 +77,8 @@
|
||||
*
|
||||
* Suff_End Clean up the module.
|
||||
*
|
||||
* Suff_DoPaths Extend the search path of each suffix to include the
|
||||
* Suff_ExtendPaths
|
||||
* Extend the search path of each suffix to include the
|
||||
* default search path.
|
||||
*
|
||||
* Suff_ClearSuffixes
|
||||
@ -114,7 +115,7 @@
|
||||
#include "dir.h"
|
||||
|
||||
/* "@(#)suff.c 8.4 (Berkeley) 3/21/94" */
|
||||
MAKE_RCSID("$NetBSD: suff.c,v 1.345 2021/02/05 05:15:12 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: suff.c,v 1.350 2021/04/04 10:05:08 rillig Exp $");
|
||||
|
||||
typedef List SuffixList;
|
||||
typedef ListNode SuffixListNode;
|
||||
@ -328,7 +329,7 @@ Suffix_TrimSuffix(const Suffix *suff, size_t nameLen, const char *nameEnd)
|
||||
suff->name, suff->nameLen);
|
||||
}
|
||||
|
||||
static Boolean
|
||||
static bool
|
||||
Suffix_IsSuffix(const Suffix *suff, size_t nameLen, const char *nameEnd)
|
||||
{
|
||||
return Suffix_TrimSuffix(suff, nameLen, nameEnd) != NULL;
|
||||
@ -509,9 +510,9 @@ Suff_ClearSuffixes(void)
|
||||
* suffixes (the source ".c" and the target ".o"). If there are no such
|
||||
* suffixes, try a single-suffix transformation as well.
|
||||
*
|
||||
* Return TRUE if the string is a valid transformation.
|
||||
* Return true if the string is a valid transformation.
|
||||
*/
|
||||
static Boolean
|
||||
static bool
|
||||
ParseTransform(const char *str, Suffix **out_src, Suffix **out_targ)
|
||||
{
|
||||
SuffixListNode *ln;
|
||||
@ -536,7 +537,7 @@ ParseTransform(const char *str, Suffix **out_src, Suffix **out_targ)
|
||||
if (targ != NULL) {
|
||||
*out_src = src;
|
||||
*out_targ = targ;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -554,17 +555,17 @@ ParseTransform(const char *str, Suffix **out_src, Suffix **out_targ)
|
||||
*/
|
||||
*out_src = single;
|
||||
*out_targ = nullSuff;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if the given string is a transformation rule, that is, a
|
||||
* Return true if the given string is a transformation rule, that is, a
|
||||
* concatenation of two known suffixes such as ".c.o" or a single suffix
|
||||
* such as ".o".
|
||||
*/
|
||||
Boolean
|
||||
bool
|
||||
Suff_IsTransform(const char *str)
|
||||
{
|
||||
Suffix *src, *targ;
|
||||
@ -616,7 +617,7 @@ Suff_AddTransform(const char *name)
|
||||
|
||||
{
|
||||
/* TODO: Avoid the redundant parsing here. */
|
||||
Boolean ok = ParseTransform(name, &srcSuff, &targSuff);
|
||||
bool ok = ParseTransform(name, &srcSuff, &targSuff);
|
||||
assert(ok);
|
||||
(void)ok;
|
||||
}
|
||||
@ -725,11 +726,11 @@ RebuildGraph(GNode *transform, Suffix *suff)
|
||||
* becomes the main target.
|
||||
*
|
||||
* Results:
|
||||
* TRUE iff a new main target has been selected.
|
||||
* true iff a new main target has been selected.
|
||||
*/
|
||||
static Boolean
|
||||
static bool
|
||||
UpdateTarget(GNode *target, GNode **inout_main, Suffix *suff,
|
||||
Boolean *inout_removedMain)
|
||||
bool *inout_removedMain)
|
||||
{
|
||||
Suffix *srcSuff, *targSuff;
|
||||
char *ptr;
|
||||
@ -740,20 +741,20 @@ UpdateTarget(GNode *target, GNode **inout_main, Suffix *suff,
|
||||
*inout_main = target;
|
||||
Targ_SetMain(target);
|
||||
/*
|
||||
* XXX: Why could it be a good idea to return TRUE here?
|
||||
* XXX: Why could it be a good idea to return true here?
|
||||
* The main task of this function is to turn ordinary nodes
|
||||
* into transformations, no matter whether or not a new .MAIN
|
||||
* node has been found.
|
||||
*/
|
||||
/*
|
||||
* XXX: Even when changing this to FALSE, none of the existing
|
||||
* XXX: Even when changing this to false, none of the existing
|
||||
* unit tests fails.
|
||||
*/
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (target->type == OP_TRANSFORM)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
/*
|
||||
* XXX: What about a transformation ".cpp.c"? If ".c" is added as
|
||||
@ -762,7 +763,7 @@ UpdateTarget(GNode *target, GNode **inout_main, Suffix *suff,
|
||||
*/
|
||||
ptr = strstr(target->name, suff->name);
|
||||
if (ptr == NULL)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
/*
|
||||
* XXX: In suff-rebuild.mk, in the line '.SUFFIXES: .c .b .a', this
|
||||
@ -773,14 +774,14 @@ UpdateTarget(GNode *target, GNode **inout_main, Suffix *suff,
|
||||
* amounts of memory.
|
||||
*/
|
||||
if (ptr == target->name)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
if (ParseTransform(target->name, &srcSuff, &targSuff)) {
|
||||
if (*inout_main == target) {
|
||||
DEBUG1(MAKE,
|
||||
"Setting main node from \"%s\" back to null\n",
|
||||
target->name);
|
||||
*inout_removedMain = TRUE;
|
||||
*inout_removedMain = true;
|
||||
*inout_main = NULL;
|
||||
Targ_SetMain(NULL);
|
||||
}
|
||||
@ -795,7 +796,7 @@ UpdateTarget(GNode *target, GNode **inout_main, Suffix *suff,
|
||||
srcSuff->name, targSuff->name);
|
||||
Relate(srcSuff, targSuff);
|
||||
}
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -808,7 +809,7 @@ UpdateTarget(GNode *target, GNode **inout_main, Suffix *suff,
|
||||
static void
|
||||
UpdateTargets(GNode **inout_main, Suffix *suff)
|
||||
{
|
||||
Boolean removedMain = FALSE;
|
||||
bool removedMain = false;
|
||||
GNodeListNode *ln;
|
||||
|
||||
for (ln = Targ_List()->first; ln != NULL; ln = ln->next) {
|
||||
@ -876,7 +877,7 @@ Suff_GetPath(const char *sname)
|
||||
* ".LIBS" and the flag is '-L'.
|
||||
*/
|
||||
void
|
||||
Suff_DoPaths(void)
|
||||
Suff_ExtendPaths(void)
|
||||
{
|
||||
SuffixListNode *ln;
|
||||
char *flags;
|
||||
@ -1061,7 +1062,7 @@ CandidateList_AddCandidatesFor(CandidateList *list, Candidate *cand)
|
||||
* Free the first candidate in the list that is not referenced anymore.
|
||||
* Return whether a candidate was removed.
|
||||
*/
|
||||
static Boolean
|
||||
static bool
|
||||
RemoveCandidate(CandidateList *srcs)
|
||||
{
|
||||
CandidateListNode *ln;
|
||||
@ -1097,7 +1098,7 @@ RemoveCandidate(CandidateList *srcs)
|
||||
Lst_Remove(srcs, ln);
|
||||
free(src->file);
|
||||
free(src);
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
#ifdef DEBUG_SRC
|
||||
else {
|
||||
@ -1108,7 +1109,7 @@ RemoveCandidate(CandidateList *srcs)
|
||||
#endif
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Find the first existing file/target in srcs. */
|
||||
@ -1282,7 +1283,7 @@ ExpandWildcards(GNodeListNode *cln, GNode *pgn)
|
||||
* add those nodes to the members list.
|
||||
*
|
||||
* Unfortunately, we can't use Str_Words because it doesn't understand about
|
||||
* variable specifications with spaces in them.
|
||||
* variable expressions with spaces in them.
|
||||
*/
|
||||
static void
|
||||
ExpandChildrenRegular(char *cp, GNode *pgn, GNodeList *members)
|
||||
@ -1309,7 +1310,7 @@ ExpandChildrenRegular(char *cp, GNode *pgn, GNodeList *members)
|
||||
const char *nested_p = cp;
|
||||
FStr junk;
|
||||
|
||||
(void)Var_Parse(&nested_p, pgn, VARE_NONE, &junk);
|
||||
(void)Var_Parse(&nested_p, pgn, VARE_PARSE_ONLY, &junk);
|
||||
/* TODO: handle errors */
|
||||
if (junk.str == var_Error) {
|
||||
Parse_Error(PARSE_FATAL,
|
||||
@ -1380,7 +1381,7 @@ ExpandChildren(GNodeListNode *cln, GNode *pgn)
|
||||
}
|
||||
|
||||
DEBUG1(SUFF, "Expanding \"%s\"...", cgn->name);
|
||||
(void)Var_Subst(cgn->name, pgn, VARE_WANTRES | VARE_UNDEFERR, &cp);
|
||||
(void)Var_Subst(cgn->name, pgn, VARE_UNDEFERR, &cp);
|
||||
/* TODO: handle errors */
|
||||
|
||||
{
|
||||
@ -1494,9 +1495,9 @@ Suff_FindPath(GNode *gn)
|
||||
* the sources for the transformation rule.
|
||||
*
|
||||
* Results:
|
||||
* TRUE if successful, FALSE if not.
|
||||
* true if successful, false if not.
|
||||
*/
|
||||
static Boolean
|
||||
static bool
|
||||
ApplyTransform(GNode *tgn, GNode *sgn, Suffix *tsuff, Suffix *ssuff)
|
||||
{
|
||||
GNodeListNode *ln;
|
||||
@ -1515,7 +1516,7 @@ ApplyTransform(GNode *tgn, GNode *sgn, Suffix *tsuff, Suffix *ssuff)
|
||||
|
||||
/* This can happen when linking an OP_MEMBER and OP_ARCHV node. */
|
||||
if (gn == NULL)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
DEBUG3(SUFF, "\tapplying %s -> %s to \"%s\"\n",
|
||||
ssuff->name, tsuff->name, tgn->name);
|
||||
@ -1540,7 +1541,7 @@ ApplyTransform(GNode *tgn, GNode *sgn, Suffix *tsuff, Suffix *ssuff)
|
||||
*/
|
||||
Lst_Append(&sgn->implicitParents, tgn);
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
14
targ.c
14
targ.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: targ.c,v 1.165 2021/02/04 21:42:46 rillig Exp $ */
|
||||
/* $NetBSD: targ.c,v 1.168 2021/04/03 12:01:00 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -93,7 +93,7 @@
|
||||
* Targ_FindList Given a list of names, find nodes for all
|
||||
* of them, creating them as necessary.
|
||||
*
|
||||
* Targ_Precious Return TRUE if the target is precious and
|
||||
* Targ_Precious Return true if the target is precious and
|
||||
* should not be removed if we are interrupted.
|
||||
*
|
||||
* Targ_Propagate Propagate information between related nodes.
|
||||
@ -113,7 +113,7 @@
|
||||
#include "dir.h"
|
||||
|
||||
/* "@(#)targ.c 8.2 (Berkeley) 3/19/94" */
|
||||
MAKE_RCSID("$NetBSD: targ.c,v 1.165 2021/02/04 21:42:46 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: targ.c,v 1.168 2021/04/03 12:01:00 rillig Exp $");
|
||||
|
||||
/*
|
||||
* All target nodes that appeared on the left-hand side of one of the
|
||||
@ -246,7 +246,7 @@ GNode_Free(void *gnp)
|
||||
* SCOPE_GLOBAL), it should be safe to free the variables as well,
|
||||
* since each node manages the memory for all its variables itself.
|
||||
*
|
||||
* XXX: The GNodes that are only used as variable scopes (VAR_CMD,
|
||||
* XXX: The GNodes that are only used as variable scopes (SCOPE_CMD,
|
||||
* SCOPE_GLOBAL, SCOPE_INTERNAL) are not freed at all (see Var_End,
|
||||
* where they are not mentioned). These might be freed at all, if
|
||||
* their variable values are indeed not used anywhere else (see
|
||||
@ -283,7 +283,7 @@ Targ_FindNode(const char *name)
|
||||
GNode *
|
||||
Targ_GetNode(const char *name)
|
||||
{
|
||||
Boolean isNew;
|
||||
bool isNew;
|
||||
HashEntry *he = HashTable_CreateEntry(&allTargetsByName, name, &isNew);
|
||||
if (!isNew)
|
||||
return HashEntry_Get(he);
|
||||
@ -347,7 +347,7 @@ Targ_FindList(GNodeList *gns, StringList *names)
|
||||
}
|
||||
|
||||
/* See if the given target is precious. */
|
||||
Boolean
|
||||
bool
|
||||
Targ_Precious(const GNode *gn)
|
||||
{
|
||||
/* XXX: Why are '::' targets precious? */
|
||||
@ -410,7 +410,7 @@ Targ_FmtTime(time_t tm)
|
||||
static char buf[128];
|
||||
|
||||
struct tm *parts = localtime(&tm);
|
||||
(void)strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts);
|
||||
(void)strftime(buf, sizeof buf, "%H:%M:%S %b %d, %Y", parts);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# $Id: Makefile,v 1.143 2021/02/06 18:31:30 sjg Exp $
|
||||
# $Id: Makefile,v 1.148 2021/06/16 19:18:56 sjg Exp $
|
||||
#
|
||||
# $NetBSD: Makefile,v 1.269 2021/02/06 18:26:03 sjg Exp $
|
||||
# $NetBSD: Makefile,v 1.279 2021/06/16 09:39:48 rillig Exp $
|
||||
#
|
||||
# Unit tests for make(1)
|
||||
#
|
||||
@ -203,7 +203,9 @@ TESTS+= impsrc
|
||||
TESTS+= include-main
|
||||
TESTS+= job-flags
|
||||
#TESTS+= job-output-long-lines
|
||||
TESTS+= job-output-null
|
||||
TESTS+= jobs-empty-commands
|
||||
TESTS+= jobs-empty-commands-error
|
||||
TESTS+= jobs-error-indirect
|
||||
TESTS+= jobs-error-nested
|
||||
TESTS+= jobs-error-nested-make
|
||||
@ -228,6 +230,7 @@ TESTS+= opt-debug-curdir
|
||||
TESTS+= opt-debug-cond
|
||||
TESTS+= opt-debug-dir
|
||||
TESTS+= opt-debug-errors
|
||||
TESTS+= opt-debug-errors-jobs
|
||||
TESTS+= opt-debug-file
|
||||
TESTS+= opt-debug-for
|
||||
TESTS+= opt-debug-graph1
|
||||
@ -321,6 +324,7 @@ TESTS+= var-class-env
|
||||
TESTS+= var-class-global
|
||||
TESTS+= var-class-local
|
||||
TESTS+= var-class-local-legacy
|
||||
TESTS+= var-eval-short
|
||||
TESTS+= var-op
|
||||
TESTS+= var-op-append
|
||||
TESTS+= var-op-assign
|
||||
@ -347,6 +351,7 @@ TESTS+= varmod-indirect
|
||||
TESTS+= varmod-l-name-to-value
|
||||
TESTS+= varmod-localtime
|
||||
TESTS+= varmod-loop
|
||||
TESTS+= varmod-loop-varname
|
||||
TESTS+= varmod-match
|
||||
TESTS+= varmod-match-escape
|
||||
TESTS+= varmod-no-match
|
||||
@ -363,6 +368,7 @@ TESTS+= varmod-select-words
|
||||
TESTS+= varmod-shell
|
||||
TESTS+= varmod-subst
|
||||
TESTS+= varmod-subst-regex
|
||||
TESTS+= varmod-sun-shell
|
||||
TESTS+= varmod-sysv
|
||||
TESTS+= varmod-tail
|
||||
TESTS+= varmod-to-abs
|
||||
@ -484,6 +490,7 @@ SED_CMDS.job-output-long-lines= \
|
||||
${:D marker should always be at the beginning of the line. } \
|
||||
-e '/^aa*--- job-b ---$$/d' \
|
||||
-e '/^bb*--- job-a ---$$/d'
|
||||
SED_CMDS.opt-chdir= -e 's,\(nonexistent\).[1-9][0-9]*,\1,'
|
||||
SED_CMDS.opt-debug-graph1= ${STD_SED_CMDS.dg1}
|
||||
SED_CMDS.opt-debug-graph2= ${STD_SED_CMDS.dg2}
|
||||
SED_CMDS.opt-debug-graph3= ${STD_SED_CMDS.dg3}
|
||||
@ -494,11 +501,12 @@ SED_CMDS.opt-debug-jobs+= -e 's,JobFinish: [0-9][0-9]*,JobFinish: <pid>,'
|
||||
SED_CMDS.opt-debug-jobs+= -e 's,Command: ${.SHELL:T},Command: <shell>,'
|
||||
# The "-q" may be there or not, see jobs.c, variable shells.
|
||||
SED_CMDS.opt-debug-jobs+= -e 's,^\(.Command: <shell>\) -q,\1,'
|
||||
SED_CMDS.opt-debug-lint+= ${STD_SED_CMDS.regex}
|
||||
SED_CMDS.opt-jobs-no-action= ${STD_SED_CMDS.hide-from-output}
|
||||
SED_CMDS.opt-no-action-runflags= ${STD_SED_CMDS.hide-from-output}
|
||||
# For Compat_RunCommand, useShell == FALSE.
|
||||
# For Compat_RunCommand, useShell == false.
|
||||
SED_CMDS.sh-dots= -e 's,^.*\.\.\.:.*,<not found: ...>,'
|
||||
# For Compat_RunCommand, useShell == TRUE.
|
||||
# For Compat_RunCommand, useShell == true.
|
||||
SED_CMDS.sh-dots+= -e 's,^make: exec(\(.*\)) failed (.*)$$,<not found: \1>,'
|
||||
SED_CMDS.sh-dots+= -e 's,^\(\*\*\* Error code \)[1-9][0-9]*,\1<nonzero>,'
|
||||
SED_CMDS.sh-errctl= ${STD_SED_CMDS.dj}
|
||||
@ -509,8 +517,7 @@ SED_CMDS.suff-transform-debug+= ${STD_SED_CMDS.dg1}
|
||||
SED_CMDS.var-op-shell+= ${STD_SED_CMDS.shell}
|
||||
SED_CMDS.var-op-shell+= -e '/command/s,No such.*,not found,'
|
||||
SED_CMDS.vardebug+= -e 's,${.SHELL},</path/to/shell>,'
|
||||
SED_CMDS.varmod-subst-regex+= \
|
||||
-e 's,\(Regex compilation error:\).*,\1 (details omitted),'
|
||||
SED_CMDS.varmod-subst-regex+= ${STD_SED_CMDS.regex}
|
||||
SED_CMDS.varname-dot-parsedir= -e '/in some cases/ s,^make: "[^"]*,make: "<normalized>,'
|
||||
SED_CMDS.varname-dot-parsefile= -e '/in some cases/ s,^make: "[^"]*,make: "<normalized>,'
|
||||
SED_CMDS.varname-dot-shell= -e 's, = /[^ ]*, = (details omitted),g'
|
||||
@ -590,6 +597,11 @@ STD_SED_CMDS.shell+= -e 's,^${.SHELL:T}: line [0-9][0-9]*: ,,'
|
||||
STD_SED_CMDS.shell+= -e 's,^${.SHELL:T}: [0-9][0-9]*: ,,'
|
||||
STD_SED_CMDS.shell+= -e 's,^${.SHELL:T}: ,,'
|
||||
|
||||
# The actual error messages for a failed regcomp or regexec differ between the
|
||||
# implementations.
|
||||
STD_SED_CMDS.regex= \
|
||||
-e 's,\(Regex compilation error:\).*,\1 (details omitted),'
|
||||
|
||||
# End of the configuration helpers section.
|
||||
|
||||
.-include "Makefile.inc"
|
||||
@ -639,8 +651,10 @@ _MKMSG_TEST= :
|
||||
.if ${.OBJDIR} != ${.CURDIR}
|
||||
# easy
|
||||
TMPDIR:= ${.OBJDIR}/tmp
|
||||
.elif defined(TMPDIR)
|
||||
TMPDIR:= ${TMPDIR}/uid${.MAKE.UID}
|
||||
.else
|
||||
TMPDIR:= ${TMPDIR:U/tmp}/uid${.MAKE.UID}
|
||||
TMPDIR:= /tmp/uid${.MAKE.UID}
|
||||
.endif
|
||||
# make sure it exists
|
||||
.if !exist(${TMPDIR})
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: archive.mk,v 1.11 2020/11/15 14:07:53 rillig Exp $
|
||||
# $NetBSD: archive.mk,v 1.12 2021/04/09 14:42:00 christos Exp $
|
||||
#
|
||||
# Very basic demonstration of handling archives, based on the description
|
||||
# in PSD.doc/tutorial.ms.
|
||||
@ -8,11 +8,11 @@
|
||||
# several other tests.
|
||||
|
||||
ARCHIVE= libprog.a
|
||||
FILES= archive.mk modmisc.mk varmisc.mk
|
||||
FILES= archive.mk archive-suffix.mk modmisc.mk ternary.mk varmisc.mk
|
||||
|
||||
all:
|
||||
.if ${.PARSEDIR:tA} != ${.CURDIR:tA}
|
||||
@cd ${MAKEFILE:H} && cp ${FILES} [at]*.mk ${.CURDIR}
|
||||
@cd ${MAKEFILE:H} && cp ${FILES} ${.CURDIR}
|
||||
.endif
|
||||
# The following targets create and remove files. The filesystem cache in
|
||||
# dir.c would probably not handle this correctly, therefore each of the
|
||||
|
@ -3,7 +3,7 @@ make: Unclosed variable "UNCLOSED"
|
||||
: unclosed-variable
|
||||
make: Unclosed variable expression (expecting '}') for "UNCLOSED"
|
||||
: unclosed-modifier
|
||||
make: Unknown modifier 'Z'
|
||||
make: Unknown modifier "Z"
|
||||
: unknown-modifier eol
|
||||
: end eol
|
||||
exit status 0
|
||||
|
@ -3,7 +3,7 @@ make: Unclosed variable "UNCLOSED"
|
||||
: unclosed-variable
|
||||
make: Unclosed variable expression (expecting '}') for "UNCLOSED"
|
||||
: unclosed-modifier
|
||||
make: Unknown modifier 'Z'
|
||||
make: Unknown modifier "Z"
|
||||
: unknown-modifier
|
||||
: end
|
||||
exit status 2
|
||||
|
@ -3,7 +3,7 @@ make: Unclosed variable "UNCLOSED"
|
||||
: unclosed-variable
|
||||
make: Unclosed variable expression (expecting '}') for "UNCLOSED"
|
||||
: unclosed-modifier
|
||||
make: Unknown modifier 'Z'
|
||||
make: Unknown modifier "Z"
|
||||
: unknown-modifier eol
|
||||
: end eol
|
||||
exit status 0
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: cond-func-empty.mk,v 1.11 2020/11/28 14:08:37 rillig Exp $
|
||||
# $NetBSD: cond-func-empty.mk,v 1.14 2021/04/11 13:35:56 rillig Exp $
|
||||
#
|
||||
# Tests for the empty() function in .if conditions, which tests a variable
|
||||
# expression for emptiness.
|
||||
@ -42,7 +42,7 @@ WORD= word
|
||||
.endif
|
||||
|
||||
# The :U modifier modifies expressions based on undefined variables
|
||||
# (VAR_JUNK) by adding the VAR_KEEP flag, which marks the expression
|
||||
# (DEF_UNDEF) by adding the DEF_DEFINED flag, which marks the expression
|
||||
# as "being interesting enough to be further processed".
|
||||
#
|
||||
.if empty(UNDEF:S,^$,value,W:Ufallback)
|
||||
@ -93,8 +93,8 @@ WORD= word
|
||||
# neither leading nor trailing spaces are trimmed in the argument of the
|
||||
# function. If the spaces were trimmed, the variable name would be "" and
|
||||
# that variable is indeed undefined. Since ParseEmptyArg calls Var_Parse
|
||||
# without VARE_UNDEFERR, the value of the undefined variable is returned as
|
||||
# an empty string.
|
||||
# without VARE_UNDEFERR, the value of the undefined variable is
|
||||
# returned as an empty string.
|
||||
${:U }= space
|
||||
.if empty( )
|
||||
. error
|
||||
@ -168,7 +168,7 @@ ${:U WORD }= variable name with spaces
|
||||
# parsing it, this unrealistic variable name should have done no harm.
|
||||
#
|
||||
# The variable expression was expanded though, and this was wrong. The
|
||||
# expansion was done without the VARE_WANTRES flag (called VARF_WANTRES back
|
||||
# expansion was done without VARE_WANTRES (called VARF_WANTRES back
|
||||
# then) though. This had the effect that the ${:U1} from the value of VARNAME
|
||||
# expanded to an empty string. This in turn created the seemingly recursive
|
||||
# definition VARNAME=${VARNAME}, and that definition was never meant to be
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: cond-func-make-main.mk,v 1.1 2020/11/22 19:37:27 rillig Exp $
|
||||
# $NetBSD: cond-func-make-main.mk,v 1.2 2021/04/04 10:13:09 rillig Exp $
|
||||
#
|
||||
# Test how accurately the make() function in .if conditions reflects
|
||||
# what is actually made.
|
||||
@ -33,7 +33,7 @@ first-main-target:
|
||||
# the line. This implies that several main targets can be set at the name
|
||||
# time, but they have to be in the same dependency group.
|
||||
#
|
||||
# See ParseDoDependencyTargetSpecial, branch SP_MAIN.
|
||||
# See ParseDependencyTargetSpecial, branch SP_MAIN.
|
||||
.MAIN: dot-main-target-1a dot-main-target-1b
|
||||
|
||||
.if !make(dot-main-target-1a)
|
||||
@ -47,7 +47,7 @@ dot-main-target-{1,2}{a,b}:
|
||||
: Making ${.TARGET}.
|
||||
|
||||
# At this point, the list of targets to be made (opts.create) is not empty
|
||||
# anymore. ParseDoDependencyTargetSpecial therefore treats the .MAIN as if
|
||||
# anymore. ParseDependencyTargetSpecial therefore treats the .MAIN as if
|
||||
# it were an ordinary target. Since .MAIN is not listed as a dependency
|
||||
# anywhere, it is not made.
|
||||
.if target(.MAIN)
|
||||
|
@ -1,4 +1,4 @@
|
||||
make: Bad conditional expression ` != "no"' in != "no"?:
|
||||
make: Bad conditional expression ' != "no"' in ' != "no"?:'
|
||||
yes
|
||||
no
|
||||
exit status 0
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: cond-short.mk,v 1.15 2020/12/01 19:37:23 rillig Exp $
|
||||
# $NetBSD: cond-short.mk,v 1.16 2021/03/14 11:49:37 rillig Exp $
|
||||
#
|
||||
# Demonstrates that in conditions, the right-hand side of an && or ||
|
||||
# is only evaluated if it can actually influence the result.
|
||||
@ -13,8 +13,11 @@
|
||||
# parse them. They were still evaluated though, the only difference to
|
||||
# relevant variable expressions was that in the irrelevant variable
|
||||
# expressions, undefined variables were allowed.
|
||||
#
|
||||
# See also:
|
||||
# var-eval-short.mk, for short-circuited variable modifiers
|
||||
|
||||
# The && operator.
|
||||
# The && operator:
|
||||
|
||||
.if 0 && ${echo "unexpected and" 1>&2 :L:sh}
|
||||
.endif
|
||||
@ -86,7 +89,7 @@ VAR= # empty again, for the following tests
|
||||
. warning first=${FIRST} last=${LAST} appended=${APPENDED} ran=${RAN}
|
||||
.endif
|
||||
|
||||
# The || operator.
|
||||
# The || operator:
|
||||
|
||||
.if 1 || ${echo "unexpected or" 1>&2 :L:sh}
|
||||
.endif
|
||||
@ -208,9 +211,4 @@ x!= echo '0 || $${iV2:U2} < $${V42}: $x' >&2; echo
|
||||
. error
|
||||
.endif
|
||||
|
||||
# TODO: Test each modifier to make sure it is skipped when it is irrelevant
|
||||
# for the result. Since this test is already quite long, do that in another
|
||||
# test.
|
||||
|
||||
all:
|
||||
@:;:
|
||||
|
@ -1,4 +1,4 @@
|
||||
make: "cond-token-string.mk" line 13: Unknown modifier 'Z'
|
||||
make: "cond-token-string.mk" line 13: Unknown modifier "Z"
|
||||
make: "cond-token-string.mk" line 13: Malformed conditional ("" != "${:Uvalue:Z}")
|
||||
make: "cond-token-string.mk" line 22: xvalue is not defined.
|
||||
make: "cond-token-string.mk" line 28: Malformed conditional (x${:Uvalue} == "")
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: cond-token-var.mk,v 1.5 2020/11/15 14:58:14 rillig Exp $
|
||||
# $NetBSD: cond-token-var.mk,v 1.6 2021/04/25 21:05:38 rillig Exp $
|
||||
#
|
||||
# Tests for variable expressions in .if conditions.
|
||||
#
|
||||
@ -46,3 +46,24 @@ DEF= defined
|
||||
# Since the expression is defined now, it doesn't generate any parse error.
|
||||
.if ${UNDEF:U}
|
||||
.endif
|
||||
|
||||
# If the value of the variable expression is a number, it is compared against
|
||||
# zero.
|
||||
.if ${:U0}
|
||||
. error
|
||||
.endif
|
||||
.if !${:U1}
|
||||
. error
|
||||
.endif
|
||||
|
||||
# If the value of the variable expression is not a number, any non-empty
|
||||
# value evaluates to true, even if there is only whitespace.
|
||||
.if ${:U}
|
||||
. error
|
||||
.endif
|
||||
.if !${:U }
|
||||
. error
|
||||
.endif
|
||||
.if !${:Uanything}
|
||||
. error
|
||||
.endif
|
||||
|
@ -17,7 +17,7 @@ Passed:
|
||||
5 is prime
|
||||
|
||||
make: String comparison operator must be either == or !=
|
||||
make: Bad conditional expression `"0" > 0' in "0" > 0?OK:No
|
||||
make: Bad conditional expression '"0" > 0' in '"0" > 0?OK:No'
|
||||
|
||||
OK
|
||||
exit status 0
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: counter-append.mk,v 1.4 2020/10/17 16:57:17 rillig Exp $
|
||||
# $NetBSD: counter-append.mk,v 1.5 2021/04/04 10:13:09 rillig Exp $
|
||||
#
|
||||
# Demonstrates how to let make count the number of times a variable
|
||||
# is actually accessed, using the ::+= variable modifier.
|
||||
@ -15,7 +15,7 @@ COUNTER= # zero
|
||||
NEXT= ${COUNTER::+=a}${COUNTER:[#]}
|
||||
|
||||
# This variable is first set to empty and then expanded.
|
||||
# See parse.c, function Parse_DoVar, keyword "!Var_Exists".
|
||||
# See parse.c, function Parse_Var, keyword "!Var_Exists".
|
||||
A:= ${NEXT}
|
||||
B:= ${NEXT}
|
||||
C:= ${NEXT}
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: counter.mk,v 1.5 2020/10/17 16:57:17 rillig Exp $
|
||||
# $NetBSD: counter.mk,v 1.6 2021/04/04 10:13:09 rillig Exp $
|
||||
#
|
||||
# Demonstrates how to let make count the number of times a variable
|
||||
# is actually accessed, using the ::= variable modifier.
|
||||
@ -15,7 +15,7 @@ COUNTER= # zero
|
||||
NEXT= ${COUNTER::=${COUNTER} a}${COUNTER:[#]}
|
||||
|
||||
# This variable is first set to empty and then expanded.
|
||||
# See parse.c, function Parse_DoVar, keyword "!Var_Exists".
|
||||
# See parse.c, function Parse_Var, keyword "!Var_Exists".
|
||||
A:= ${NEXT}
|
||||
B:= ${NEXT}
|
||||
C:= ${NEXT}
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: dep-var.mk,v 1.5 2020/09/13 20:04:26 rillig Exp $
|
||||
# $NetBSD: dep-var.mk,v 1.6 2021/04/04 10:13:09 rillig Exp $
|
||||
#
|
||||
# Tests for variable references in dependency declarations.
|
||||
#
|
||||
@ -79,7 +79,7 @@ all: $$$$)
|
||||
# undefined.
|
||||
#
|
||||
# Since 2020-09-13, this generates a parse error in lint mode (-dL), but not
|
||||
# in normal mode since ParseDoDependency does not handle any errors after
|
||||
# in normal mode since ParseDependency does not handle any errors after
|
||||
# calling Var_Parse.
|
||||
undef1 def2 a-def2-b 1-2-$$INDIRECT_2-2-1 ${:U\$)}:
|
||||
@echo ${.TARGET:Q}
|
||||
|
@ -1,10 +1,10 @@
|
||||
Global:delete DOLLAR (not found)
|
||||
Command:DOLLAR = $$$$
|
||||
Global:.MAKEOVERRIDES = VAR DOLLAR
|
||||
Command: DOLLAR = $$$$
|
||||
Global: .MAKEOVERRIDES = VAR DOLLAR
|
||||
CondParser_Eval: ${DOLLAR} != "\$\$"
|
||||
Var_Parse: ${DOLLAR} != "\$\$" with VARE_UNDEFERR|VARE_WANTRES
|
||||
Var_Parse: ${DOLLAR} != "\$\$" (eval-defined)
|
||||
lhs = "$$", rhs = "$$", op = !=
|
||||
Global:.MAKEFLAGS = -r -k -D VAR -D VAR -d cv -d
|
||||
Global:.MAKEFLAGS = -r -k -D VAR -D VAR -d cv -d 0
|
||||
Global: .MAKEFLAGS = -r -k -D VAR -D VAR -d cv -d
|
||||
Global: .MAKEFLAGS = -r -k -D VAR -D VAR -d cv -d 0
|
||||
make: Unterminated quoted string [make VAR=initial UNBALANCED=']
|
||||
exit status 0
|
||||
|
@ -1 +1,4 @@
|
||||
: 'Making two out of one.'
|
||||
: 'Making three out of two.'
|
||||
: 'Making all out of three.'
|
||||
exit status 0
|
||||
|
@ -1,8 +1,18 @@
|
||||
# $NetBSD: deptgt-order.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $
|
||||
# $NetBSD: deptgt-order.mk,v 1.3 2021/06/17 15:25:33 rillig Exp $
|
||||
#
|
||||
# Tests for the special target .ORDER in dependency declarations.
|
||||
|
||||
# TODO: Implementation
|
||||
all one two three: .PHONY
|
||||
|
||||
all:
|
||||
@:;
|
||||
two: one
|
||||
: 'Making $@ out of $>.'
|
||||
three: two
|
||||
: 'Making $@ out of $>.'
|
||||
|
||||
# This .ORDER creates a circular dependency since 'three' depends on 'one'
|
||||
# but 'one' is supposed to be built after 'three'.
|
||||
.ORDER: three one
|
||||
|
||||
# XXX: The circular dependency should be detected here.
|
||||
all: three
|
||||
: 'Making $@ out of $>.'
|
||||
|
@ -1,14 +1,14 @@
|
||||
make: "deptgt.mk" line 10: warning: Extra target ignored
|
||||
make: "deptgt.mk" line 28: Unassociated shell command ": command3 # parse error, since targets == NULL"
|
||||
ParseReadLine (34): '${:U}: empty-source'
|
||||
ParseDoDependency(: empty-source)
|
||||
ParseDependency(: empty-source)
|
||||
ParseReadLine (35): ' : command for empty targets list'
|
||||
ParseReadLine (36): ': empty-source'
|
||||
ParseDoDependency(: empty-source)
|
||||
ParseDependency(: empty-source)
|
||||
ParseReadLine (37): ' : command for empty targets list'
|
||||
ParseReadLine (38): '.MAKEFLAGS: -d0'
|
||||
ParseDoDependency(.MAKEFLAGS: -d0)
|
||||
make: "deptgt.mk" line 46: Unknown modifier 'Z'
|
||||
ParseDependency(.MAKEFLAGS: -d0)
|
||||
make: "deptgt.mk" line 46: Unknown modifier "Z"
|
||||
make: Fatal errors encountered -- cannot continue
|
||||
make: stopped in unit-tests
|
||||
exit status 1
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: deptgt.mk,v 1.10 2020/12/27 18:20:26 rillig Exp $
|
||||
# $NetBSD: deptgt.mk,v 1.11 2021/04/04 10:13:09 rillig Exp $
|
||||
#
|
||||
# Tests for special targets like .BEGIN or .SUFFIXES in dependency
|
||||
# declarations.
|
||||
@ -12,7 +12,7 @@
|
||||
# The following lines demonstrate how 'targets' is set and reset during
|
||||
# parsing of dependencies. To see it in action, set breakpoints in:
|
||||
#
|
||||
# ParseDoDependency at the beginning
|
||||
# ParseDependency at the beginning
|
||||
# FinishDependencyGroup at "targets = NULL"
|
||||
# Parse_File at "Lst_Free(targets)"
|
||||
# Parse_File at "targets = Lst_New()"
|
||||
|
@ -1,56 +1,56 @@
|
||||
ParseReadLine (21): 'UT_VAR= <${REF}>'
|
||||
Global:UT_VAR = <${REF}>
|
||||
Global: UT_VAR = <${REF}>
|
||||
ParseReadLine (28): '.export UT_VAR'
|
||||
Global:.MAKE.EXPORTED = UT_VAR
|
||||
Global: .MAKE.EXPORTED = UT_VAR
|
||||
ParseReadLine (32): ': ${UT_VAR:N*}'
|
||||
Var_Parse: ${UT_VAR:N*} with VARE_UNDEFERR|VARE_WANTRES
|
||||
Var_Parse: ${REF}> with VARE_UNDEFERR|VARE_WANTRES
|
||||
Applying ${UT_VAR:N...} to "<>" (VARE_UNDEFERR|VARE_WANTRES, VAR_EXPORTED|VAR_REEXPORT, none)
|
||||
Pattern[UT_VAR] for [<>] is [*]
|
||||
Var_Parse: ${UT_VAR:N*} (eval-defined)
|
||||
Var_Parse: ${REF}> (eval-defined)
|
||||
Evaluating modifier ${UT_VAR:N...} on value "<>"
|
||||
Pattern for ':N' is "*"
|
||||
ModifyWords: split "<>" into 1 words
|
||||
Result of ${UT_VAR:N*} is "" (VARE_UNDEFERR|VARE_WANTRES, VAR_EXPORTED|VAR_REEXPORT, none)
|
||||
ParseDoDependency(: )
|
||||
Result of ${UT_VAR:N*} is ""
|
||||
ParseDependency(: )
|
||||
CondParser_Eval: ${:!echo "\$UT_VAR"!} != "<>"
|
||||
Var_Parse: ${:!echo "\$UT_VAR"!} != "<>" with VARE_UNDEFERR|VARE_WANTRES
|
||||
Applying ${:!...} to "" (VARE_UNDEFERR|VARE_WANTRES, none, VES_UNDEF)
|
||||
Var_Parse: ${:!echo "\$UT_VAR"!} != "<>" (eval-defined)
|
||||
Evaluating modifier ${:!...} on value "" (eval-defined, undefined)
|
||||
Modifier part: "echo "$UT_VAR""
|
||||
Var_Parse: ${.MAKE.EXPORTED:O:u} with VARE_WANTRES
|
||||
Applying ${.MAKE.EXPORTED:O} to "UT_VAR" (VARE_WANTRES, none, none)
|
||||
Result of ${.MAKE.EXPORTED:O} is "UT_VAR" (VARE_WANTRES, none, none)
|
||||
Applying ${.MAKE.EXPORTED:u} to "UT_VAR" (VARE_WANTRES, none, none)
|
||||
Result of ${.MAKE.EXPORTED:u} is "UT_VAR" (VARE_WANTRES, none, none)
|
||||
Var_Parse: ${UT_VAR} with VARE_WANTRES
|
||||
Var_Parse: ${REF}> with VARE_WANTRES
|
||||
Result of ${:!echo "\$UT_VAR"!} is "<>" (VARE_UNDEFERR|VARE_WANTRES, none, VES_DEF)
|
||||
Var_Parse: ${.MAKE.EXPORTED:O:u} (eval)
|
||||
Evaluating modifier ${.MAKE.EXPORTED:O} on value "UT_VAR"
|
||||
Result of ${.MAKE.EXPORTED:O} is "UT_VAR"
|
||||
Evaluating modifier ${.MAKE.EXPORTED:u} on value "UT_VAR"
|
||||
Result of ${.MAKE.EXPORTED:u} is "UT_VAR"
|
||||
Var_Parse: ${UT_VAR} (eval)
|
||||
Var_Parse: ${REF}> (eval)
|
||||
Result of ${:!echo "\$UT_VAR"!} is "<>" (eval-defined, defined)
|
||||
lhs = "<>", rhs = "<>", op = !=
|
||||
ParseReadLine (49): ': ${UT_VAR:N*}'
|
||||
Var_Parse: ${UT_VAR:N*} with VARE_UNDEFERR|VARE_WANTRES
|
||||
Var_Parse: ${REF}> with VARE_UNDEFERR|VARE_WANTRES
|
||||
Applying ${UT_VAR:N...} to "<>" (VARE_UNDEFERR|VARE_WANTRES, VAR_EXPORTED|VAR_REEXPORT, none)
|
||||
Pattern[UT_VAR] for [<>] is [*]
|
||||
ParseReadLine (50): ': ${UT_VAR:N*}'
|
||||
Var_Parse: ${UT_VAR:N*} (eval-defined)
|
||||
Var_Parse: ${REF}> (eval-defined)
|
||||
Evaluating modifier ${UT_VAR:N...} on value "<>"
|
||||
Pattern for ':N' is "*"
|
||||
ModifyWords: split "<>" into 1 words
|
||||
Result of ${UT_VAR:N*} is "" (VARE_UNDEFERR|VARE_WANTRES, VAR_EXPORTED|VAR_REEXPORT, none)
|
||||
ParseDoDependency(: )
|
||||
ParseReadLine (53): 'REF= defined'
|
||||
Global:REF = defined
|
||||
Result of ${UT_VAR:N*} is ""
|
||||
ParseDependency(: )
|
||||
ParseReadLine (54): 'REF= defined'
|
||||
Global: REF = defined
|
||||
CondParser_Eval: ${:!echo "\$UT_VAR"!} != "<defined>"
|
||||
Var_Parse: ${:!echo "\$UT_VAR"!} != "<defined>" with VARE_UNDEFERR|VARE_WANTRES
|
||||
Applying ${:!...} to "" (VARE_UNDEFERR|VARE_WANTRES, none, VES_UNDEF)
|
||||
Var_Parse: ${:!echo "\$UT_VAR"!} != "<defined>" (eval-defined)
|
||||
Evaluating modifier ${:!...} on value "" (eval-defined, undefined)
|
||||
Modifier part: "echo "$UT_VAR""
|
||||
Var_Parse: ${.MAKE.EXPORTED:O:u} with VARE_WANTRES
|
||||
Applying ${.MAKE.EXPORTED:O} to "UT_VAR" (VARE_WANTRES, none, none)
|
||||
Result of ${.MAKE.EXPORTED:O} is "UT_VAR" (VARE_WANTRES, none, none)
|
||||
Applying ${.MAKE.EXPORTED:u} to "UT_VAR" (VARE_WANTRES, none, none)
|
||||
Result of ${.MAKE.EXPORTED:u} is "UT_VAR" (VARE_WANTRES, none, none)
|
||||
Var_Parse: ${UT_VAR} with VARE_WANTRES
|
||||
Var_Parse: ${REF}> with VARE_WANTRES
|
||||
Result of ${:!echo "\$UT_VAR"!} is "<defined>" (VARE_UNDEFERR|VARE_WANTRES, none, VES_DEF)
|
||||
Var_Parse: ${.MAKE.EXPORTED:O:u} (eval)
|
||||
Evaluating modifier ${.MAKE.EXPORTED:O} on value "UT_VAR"
|
||||
Result of ${.MAKE.EXPORTED:O} is "UT_VAR"
|
||||
Evaluating modifier ${.MAKE.EXPORTED:u} on value "UT_VAR"
|
||||
Result of ${.MAKE.EXPORTED:u} is "UT_VAR"
|
||||
Var_Parse: ${UT_VAR} (eval)
|
||||
Var_Parse: ${REF}> (eval)
|
||||
Result of ${:!echo "\$UT_VAR"!} is "<defined>" (eval-defined, defined)
|
||||
lhs = "<defined>", rhs = "<defined>", op = !=
|
||||
ParseReadLine (61): 'all:'
|
||||
ParseDoDependency(all:)
|
||||
Global:.ALLTARGETS = all
|
||||
ParseReadLine (62): '.MAKEFLAGS: -d0'
|
||||
ParseDoDependency(.MAKEFLAGS: -d0)
|
||||
Global:.MAKEFLAGS = -r -k -d cpv -d
|
||||
Global:.MAKEFLAGS = -r -k -d cpv -d 0
|
||||
ParseReadLine (62): 'all:'
|
||||
ParseDependency(all:)
|
||||
Global: .ALLTARGETS = all
|
||||
ParseReadLine (63): '.MAKEFLAGS: -d0'
|
||||
ParseDependency(.MAKEFLAGS: -d0)
|
||||
Global: .MAKEFLAGS = -r -k -d cpv -d
|
||||
Global: .MAKEFLAGS = -r -k -d cpv -d 0
|
||||
exit status 0
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: directive-export-impl.mk,v 1.1 2020/12/29 01:45:06 rillig Exp $
|
||||
# $NetBSD: directive-export-impl.mk,v 1.3 2021/04/03 23:08:30 rillig Exp $
|
||||
#
|
||||
# Test for the implementation of exporting variables to child processes.
|
||||
# This involves marking variables for export, actually exporting them,
|
||||
@ -8,8 +8,8 @@
|
||||
# Var_Export
|
||||
# ExportVar
|
||||
# VarExportedMode (global)
|
||||
# VAR_EXPORTED (per variable)
|
||||
# VAR_REEXPORT (per variable)
|
||||
# VarFlags.exported (per variable)
|
||||
# VarFlags.reexport (per variable)
|
||||
# VarExportMode (per call of Var_Export and ExportVar)
|
||||
|
||||
: ${:U:sh} # side effect: initialize .SHELL
|
||||
@ -22,13 +22,13 @@ UT_VAR= <${REF}>
|
||||
|
||||
# At this point, ExportVar("UT_VAR", VEM_PLAIN) is called. Since the
|
||||
# variable value refers to another variable, ExportVar does not actually
|
||||
# export the variable but only marks it as VAR_EXPORTED and VAR_REEXPORT.
|
||||
# After that, ExportVars registers the variable name in .MAKE.EXPORTED.
|
||||
# That's all for now.
|
||||
# export the variable but only marks it as VarFlags.exported and
|
||||
# VarFlags.reexport. After that, ExportVars registers the variable name in
|
||||
# .MAKE.EXPORTED. That's all for now.
|
||||
.export UT_VAR
|
||||
|
||||
# Evaluating this expression shows the variable flags in the debug log,
|
||||
# which are VAR_EXPORTED|VAR_REEXPORT.
|
||||
# The following expression has both flags 'exported' and 'reexport' set.
|
||||
# These flags do not show up anywhere, not even in the debug log.
|
||||
: ${UT_VAR:N*}
|
||||
|
||||
# At the last moment before actually forking off the child process for the
|
||||
@ -43,9 +43,10 @@ UT_VAR= <${REF}>
|
||||
. error
|
||||
.endif
|
||||
|
||||
# Evaluating this expression shows the variable flags in the debug log,
|
||||
# which are still VAR_EXPORTED|VAR_REEXPORT, which means that the variable
|
||||
# is still marked as being re-exported for each child process.
|
||||
# The following expression still has 'exported' and 'reexport' set.
|
||||
# These flags do not show up anywhere though, not even in the debug log.
|
||||
# These flags means that the variable is still marked as being re-exported
|
||||
# for each child process.
|
||||
: ${UT_VAR:N*}
|
||||
|
||||
# Now the referenced variable gets defined. This does not influence anything
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: directive-export.mk,v 1.6 2020/12/13 01:07:54 rillig Exp $
|
||||
# $NetBSD: directive-export.mk,v 1.8 2021/02/16 19:01:18 rillig Exp $
|
||||
#
|
||||
# Tests for the .export directive.
|
||||
#
|
||||
@ -28,8 +28,17 @@ VAR= value $$ ${INDIRECT}
|
||||
. error
|
||||
.endif
|
||||
|
||||
# No argument means to export all variables.
|
||||
# No syntactical argument means to export all variables.
|
||||
.export
|
||||
|
||||
# An empty argument means no additional variables to export.
|
||||
.export ${:U}
|
||||
|
||||
|
||||
# Trigger the "This isn't going to end well" in ExportVarEnv.
|
||||
EMPTY_SHELL= ${:sh}
|
||||
.export EMPTY_SHELL # only marked for export at this point
|
||||
_!= :;: # Force the variable to be actually exported.
|
||||
|
||||
|
||||
all:
|
||||
@:;
|
||||
|
@ -13,7 +13,7 @@ make: "directive-for-errors.mk" line 53: Wrong number of words (5) in .for subst
|
||||
make: "directive-for-errors.mk" line 64: missing `in' in for
|
||||
make: "directive-for-errors.mk" line 66: warning: Should not be reached.
|
||||
make: "directive-for-errors.mk" line 67: for-less endfor
|
||||
make: "directive-for-errors.mk" line 73: Unknown modifier 'Z'
|
||||
make: "directive-for-errors.mk" line 73: Unknown modifier "Z"
|
||||
make: "directive-for-errors.mk" line 74: warning: Should not be reached.
|
||||
make: "directive-for-errors.mk" line 74: warning: Should not be reached.
|
||||
make: "directive-for-errors.mk" line 74: warning: Should not be reached.
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: directive-for-errors.mk,v 1.1 2020/12/31 03:05:12 rillig Exp $
|
||||
# $NetBSD: directive-for-errors.mk,v 1.3 2021/04/04 10:13:09 rillig Exp $
|
||||
#
|
||||
# Tests for error handling in .for loops.
|
||||
|
||||
@ -13,8 +13,8 @@
|
||||
# XXX: The error message is misleading though. As of 2020-12-31, it says
|
||||
# "Unknown directive "for"", but that directive is actually known. This is
|
||||
# because ForEval does not detect the .for loop as such, so parsing
|
||||
# continues in ParseLine > ParseDependency > ParseDoDependency >
|
||||
# ParseDoDependencyTargets > ParseErrorNoDependency, and there the directive
|
||||
# continues in ParseLine > ParseDependencyLine > ParseDependency >
|
||||
# ParseDependencyTargets > ParseErrorNoDependency, and there the directive
|
||||
# name is parsed a bit differently.
|
||||
.for/i in 1 2 3
|
||||
. warning ${i}
|
||||
|
@ -1,12 +1,12 @@
|
||||
For: end for 1
|
||||
For: loop body:
|
||||
. info ${:U!"#$%&'()*+,-./0-9\:;<=>?@A-Z[\\]_^a-z{|\}~}
|
||||
make: Unclosed variable specification (expecting '}') for "" (value "!"") modifier U
|
||||
make: Unclosed variable expression, expecting '}' for modifier "U!"" of variable "" with value "!""
|
||||
make: "directive-for-escape.mk" line 19: !"
|
||||
For: end for 1
|
||||
For: loop body:
|
||||
. info ${:U!"\\\\#$%&'()*+,-./0-9\:;<=>?@A-Z[\\]_^a-z{|\}~}
|
||||
make: Unclosed variable specification (expecting '}') for "" (value "!"\\") modifier U
|
||||
make: Unclosed variable expression, expecting '}' for modifier "U!"\\\\" of variable "" with value "!"\\"
|
||||
make: "directive-for-escape.mk" line 29: !"\\
|
||||
For: end for 1
|
||||
For: loop body:
|
||||
@ -37,19 +37,19 @@ make: "directive-for-escape.mk" line 55: end}
|
||||
For: end for 1
|
||||
For: loop body:
|
||||
. info ${:Ubegin<${UNDEF:Ufallback:N{{{}}}}>end}
|
||||
make: "directive-for-escape.mk" line 66: begin<fallback>end
|
||||
make: "directive-for-escape.mk" line 67: begin<fallback>end
|
||||
For: end for 1
|
||||
For: loop body:
|
||||
. info ${:U\$}
|
||||
make: "directive-for-escape.mk" line 74: $
|
||||
make: "directive-for-escape.mk" line 75: $
|
||||
For: end for 1
|
||||
For: loop body:
|
||||
. info ${NUMBERS} ${:Ureplaced}
|
||||
make: "directive-for-escape.mk" line 82: one two three replaced
|
||||
make: "directive-for-escape.mk" line 83: one two three replaced
|
||||
For: end for 1
|
||||
For: loop body:
|
||||
. info ${:Ureplaced}
|
||||
make: "directive-for-escape.mk" line 92: replaced
|
||||
make: "directive-for-escape.mk" line 93: replaced
|
||||
For: end for 1
|
||||
For: loop body:
|
||||
. info . $$i: ${:Uinner}
|
||||
@ -62,14 +62,14 @@ For: loop body:
|
||||
. info . $${i2}: ${i2}
|
||||
. info . $${i,}: ${i,}
|
||||
. info . adjacent: ${:Uinner}${:Uinner}${:Uinner:M*}${:Uinner}
|
||||
make: "directive-for-escape.mk" line 100: . $i: inner
|
||||
make: "directive-for-escape.mk" line 101: . ${i}: inner
|
||||
make: "directive-for-escape.mk" line 102: . ${i:M*}: inner
|
||||
make: "directive-for-escape.mk" line 103: . $(i): inner
|
||||
make: "directive-for-escape.mk" line 104: . $(i:M*): inner
|
||||
make: "directive-for-escape.mk" line 105: . ${i${:U}}: outer
|
||||
make: "directive-for-escape.mk" line 106: . ${i\}}: inner}
|
||||
make: "directive-for-escape.mk" line 107: . ${i2}: two
|
||||
make: "directive-for-escape.mk" line 108: . ${i,}: comma
|
||||
make: "directive-for-escape.mk" line 109: . adjacent: innerinnerinnerinner
|
||||
make: "directive-for-escape.mk" line 101: . $i: inner
|
||||
make: "directive-for-escape.mk" line 102: . ${i}: inner
|
||||
make: "directive-for-escape.mk" line 103: . ${i:M*}: inner
|
||||
make: "directive-for-escape.mk" line 104: . $(i): inner
|
||||
make: "directive-for-escape.mk" line 105: . $(i:M*): inner
|
||||
make: "directive-for-escape.mk" line 106: . ${i${:U}}: outer
|
||||
make: "directive-for-escape.mk" line 107: . ${i\}}: inner}
|
||||
make: "directive-for-escape.mk" line 108: . ${i2}: two
|
||||
make: "directive-for-escape.mk" line 109: . ${i,}: comma
|
||||
make: "directive-for-escape.mk" line 110: . adjacent: innerinnerinnerinner
|
||||
exit status 0
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: directive-for-escape.mk,v 1.6 2021/01/25 19:05:39 rillig Exp $
|
||||
# $NetBSD: directive-for-escape.mk,v 1.7 2021/02/15 07:58:19 rillig Exp $
|
||||
#
|
||||
# Test escaping of special characters in the iteration values of a .for loop.
|
||||
# These values get expanded later using the :U variable modifier, and this
|
||||
@ -7,8 +7,8 @@
|
||||
|
||||
.MAKEFLAGS: -df
|
||||
|
||||
# Even though the .for loops takes quotes into account when splitting the
|
||||
# string into words, the quotes don't need to be balances, as of 2020-12-31.
|
||||
# Even though the .for loops take quotes into account when splitting the
|
||||
# string into words, the quotes don't need to be balanced, as of 2020-12-31.
|
||||
# This could be considered a bug.
|
||||
ASCII= !"\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~
|
||||
|
||||
@ -33,7 +33,7 @@ ASCII.2020-12-31= !"\\\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~
|
||||
#
|
||||
# XXX: It is unexpected that the variable V gets expanded in the loop body.
|
||||
# The double '$$' should prevent exactly this. Probably nobody was
|
||||
# adventurous enough to use literal dollar signs in the values for a .for
|
||||
# adventurous enough to use literal dollar signs in the values of a .for
|
||||
# loop.
|
||||
V= value
|
||||
VALUES= $$ $${V} $${V:=-with-modifier} $$(V) $$(V:=-with-modifier)
|
||||
@ -43,14 +43,14 @@ VALUES= $$ $${V} $${V:=-with-modifier} $$(V) $$(V:=-with-modifier)
|
||||
|
||||
# Try to cover the code for nested '{}' in for_var_len, without success.
|
||||
#
|
||||
# The value of VALUES is not meant to be a variable expression. Instead, it
|
||||
# is meant to represent dollar, lbrace, "UNDEF:U", backslash, dollar,
|
||||
# backslash, dollar, space, nested braces, space, "end}".
|
||||
# The value of the variable VALUES is not meant to be a variable expression.
|
||||
# Instead, it is meant to represent literal text, the only escaping mechanism
|
||||
# being that each '$' is written as '$$'.
|
||||
#
|
||||
# The .for loop splits ${VALUES} into 3 words, at the space characters, since
|
||||
# these are not escaped.
|
||||
VALUES= $${UNDEF:U\$$\$$ {{}} end}
|
||||
# XXX: Where does the '\$$\$$' get converted into a single '\$'?
|
||||
# XXX: Where in the code does the '\$\$' get converted into a single '\$'?
|
||||
.for i in ${VALUES}
|
||||
. info $i
|
||||
.endfor
|
||||
@ -59,8 +59,9 @@ VALUES= $${UNDEF:U\$$\$$ {{}} end}
|
||||
#
|
||||
# XXX: It is wrong that for_var_len requires the braces to be balanced.
|
||||
# Each variable modifier has its own inconsistent way of parsing nested
|
||||
# variable expressions, braces and parentheses. The only sensible thing
|
||||
# to do is therefore to let Var_Parse do all the parsing work.
|
||||
# variable expressions, braces and parentheses. (Compare ':M', ':S', and
|
||||
# ':D' for details.) The only sensible thing to do is therefore to let
|
||||
# Var_Parse do all the parsing work.
|
||||
VALUES= begin<$${UNDEF:Ufallback:N{{{}}}}>end
|
||||
.for i in ${VALUES}
|
||||
. info $i
|
||||
|
@ -16,7 +16,7 @@ make: "directive-for.mk" line 140: ][ ][ ][
|
||||
make: "directive-for.mk" line 140: }{ }{ }{
|
||||
make: "directive-for.mk" line 148: outer value value
|
||||
make: "directive-for.mk" line 148: outer "quoted" \"quoted\"
|
||||
make: "directive-for.mk" line 154: Unknown modifier 'Z'
|
||||
make: "directive-for.mk" line 154: Unknown modifier "Z"
|
||||
make: "directive-for.mk" line 155: XXX: Not reached word1
|
||||
make: "directive-for.mk" line 155: XXX: Not reached word3
|
||||
make: Fatal errors encountered -- cannot continue
|
||||
|
@ -1,5 +1,6 @@
|
||||
make: "directive-undef.mk" line 29: The .undef directive requires an argument
|
||||
make: "directive-undef.mk" line 86: Unknown modifier 'Z'
|
||||
make: "directive-undef.mk" line 86: Unknown modifier "Z"
|
||||
make: "directive-undef.mk" line 103: warning: UT_EXPORTED is still listed in .MAKE.EXPORTED even though spaceit is not exported anymore.
|
||||
make: Fatal errors encountered -- cannot continue
|
||||
make: stopped in unit-tests
|
||||
exit status 1
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: directive-undef.mk,v 1.9 2020/12/22 20:10:21 rillig Exp $
|
||||
# $NetBSD: directive-undef.mk,v 1.10 2021/02/16 18:02:19 rillig Exp $
|
||||
#
|
||||
# Tests for the .undef directive.
|
||||
#
|
||||
@ -86,5 +86,22 @@ ${DOLLAR}= dollar
|
||||
.undef ${VARNAMES:L:Z}
|
||||
|
||||
|
||||
UT_EXPORTED= exported-value
|
||||
.export UT_EXPORTED
|
||||
.if ${:!echo "\${UT_EXPORTED:-not-exported}"!} != "exported-value"
|
||||
. error
|
||||
.endif
|
||||
.if !${.MAKE.EXPORTED:MUT_EXPORTED}
|
||||
. error
|
||||
.endif
|
||||
.undef UT_EXPORTED # XXX: does not update .MAKE.EXPORTED
|
||||
.if ${:!echo "\${UT_EXPORTED:-not-exported}"!} != "not-exported"
|
||||
. error
|
||||
.endif
|
||||
.if ${.MAKE.EXPORTED:MUT_EXPORTED}
|
||||
. warning UT_EXPORTED is still listed in .MAKE.EXPORTED even though $\
|
||||
it is not exported anymore.
|
||||
.endif
|
||||
|
||||
|
||||
all:
|
||||
@:;
|
||||
|
@ -1,18 +1,18 @@
|
||||
make: "directive-unexport-env.mk" line 13: Unknown directive "unexport-en"
|
||||
make: "directive-unexport-env.mk" line 15: Unknown directive "unexport-environment"
|
||||
Global:UT_EXPORTED = value
|
||||
Global:UT_UNEXPORTED = value
|
||||
Global:.MAKE.EXPORTED = UT_EXPORTED
|
||||
Global: UT_EXPORTED = value
|
||||
Global: UT_UNEXPORTED = value
|
||||
Global: .MAKE.EXPORTED = UT_EXPORTED
|
||||
make: "directive-unexport-env.mk" line 21: The directive .unexport-env does not take arguments
|
||||
Var_Parse: ${.MAKE.EXPORTED:O:u} with VARE_WANTRES
|
||||
Applying ${.MAKE.EXPORTED:O} to "UT_EXPORTED" (VARE_WANTRES, none, none)
|
||||
Result of ${.MAKE.EXPORTED:O} is "UT_EXPORTED" (VARE_WANTRES, none, none)
|
||||
Applying ${.MAKE.EXPORTED:u} to "UT_EXPORTED" (VARE_WANTRES, none, none)
|
||||
Result of ${.MAKE.EXPORTED:u} is "UT_EXPORTED" (VARE_WANTRES, none, none)
|
||||
Var_Parse: ${.MAKE.EXPORTED:O:u} (eval)
|
||||
Evaluating modifier ${.MAKE.EXPORTED:O} on value "UT_EXPORTED"
|
||||
Result of ${.MAKE.EXPORTED:O} is "UT_EXPORTED"
|
||||
Evaluating modifier ${.MAKE.EXPORTED:u} on value "UT_EXPORTED"
|
||||
Result of ${.MAKE.EXPORTED:u} is "UT_EXPORTED"
|
||||
Unexporting "UT_EXPORTED"
|
||||
Global:delete .MAKE.EXPORTED
|
||||
Global:.MAKEFLAGS = -r -k -d v -d
|
||||
Global:.MAKEFLAGS = -r -k -d v -d 0
|
||||
Global: .MAKEFLAGS = -r -k -d v -d
|
||||
Global: .MAKEFLAGS = -r -k -d v -d 0
|
||||
make: Fatal errors encountered -- cannot continue
|
||||
make: stopped in unit-tests
|
||||
exit status 1
|
||||
|
@ -2,11 +2,11 @@ make: "directive.mk" line 9: Unknown directive "indented"
|
||||
make: "directive.mk" line 10: Unknown directive "indented"
|
||||
make: "directive.mk" line 11: Unknown directive "indented"
|
||||
make: "directive.mk" line 15: Unknown directive "info"
|
||||
Global:.info =
|
||||
Global:.info = value
|
||||
Global: .info =
|
||||
Global: .info = value
|
||||
make: "directive.mk" line 26: := value
|
||||
Global:.MAKEFLAGS = -r -k -d v -d
|
||||
Global:.MAKEFLAGS = -r -k -d v -d 0
|
||||
Global: .MAKEFLAGS = -r -k -d v -d
|
||||
Global: .MAKEFLAGS = -r -k -d v -d 0
|
||||
make: Fatal errors encountered -- cannot continue
|
||||
make: stopped in unit-tests
|
||||
exit status 1
|
||||
|
@ -9,7 +9,7 @@ make: "include-subsub.mk" line 5: subsub-ok
|
||||
in .for loop from include-sub.mk:29
|
||||
in .include from include-main.mk:27
|
||||
ParseReadLine (6): '.MAKEFLAGS: -d0'
|
||||
ParseDoDependency(.MAKEFLAGS: -d0)
|
||||
ParseDependency(.MAKEFLAGS: -d0)
|
||||
make: "include-sub.mk" line 38: sub-after-ok
|
||||
make: "include-sub.mk" line 45: sub-after-for-ok
|
||||
make: "include-main.mk" line 30: main-after-ok
|
||||
|
4
unit-tests/job-output-null.exp
Normal file
4
unit-tests/job-output-null.exp
Normal file
@ -0,0 +1,4 @@
|
||||
hello
|
||||
hello
|
||||
hello world without newline, hello world without newline, hello world without newline.
|
||||
exit status 0
|
32
unit-tests/job-output-null.mk
Normal file
32
unit-tests/job-output-null.mk
Normal file
@ -0,0 +1,32 @@
|
||||
# $NetBSD: job-output-null.mk,v 1.1 2021/04/15 19:02:29 rillig Exp $
|
||||
#
|
||||
# Test how null bytes in the output of a command are handled. Make processes
|
||||
# them using null-terminated strings, which may cut off some of the output.
|
||||
#
|
||||
# As of 2021-04-15, make handles null bytes from the child process
|
||||
# inconsistently. It's an edge case though since typically the child
|
||||
# processes output text.
|
||||
|
||||
.MAKEFLAGS: -j1 # force jobs mode
|
||||
|
||||
all: .PHONY
|
||||
# The null byte from the command output is kept as-is.
|
||||
# See CollectOutput, which looks like it intended to replace these
|
||||
# null bytes with simple spaces.
|
||||
@printf 'hello\0world%s\n' ''
|
||||
|
||||
# Give the parent process a chance to see the above output, but not
|
||||
# yet the output from the next printf command.
|
||||
@sleep 1
|
||||
|
||||
# All null bytes from the command output are kept as-is.
|
||||
@printf 'hello\0world%s\n' '' '' '' '' '' ''
|
||||
|
||||
@sleep 1
|
||||
|
||||
# The null bytes are replaced with spaces since they are not followed
|
||||
# by a newline.
|
||||
#
|
||||
# The three null bytes in a row test whether this output is
|
||||
# compressed to a single space like in DebugFailedTarget. It isn't.
|
||||
@printf 'hello\0world\0without\0\0\0newline%s' ', ' ', ' '.'
|
5
unit-tests/jobs-empty-commands-error.exp
Normal file
5
unit-tests/jobs-empty-commands-error.exp
Normal file
@ -0,0 +1,5 @@
|
||||
: 'Making existing-target out of nothing.'
|
||||
make: don't know how to make nonexistent-target (continuing)
|
||||
|
||||
make: stopped in unit-tests
|
||||
exit status 2
|
19
unit-tests/jobs-empty-commands-error.mk
Normal file
19
unit-tests/jobs-empty-commands-error.mk
Normal file
@ -0,0 +1,19 @@
|
||||
# $NetBSD: jobs-empty-commands-error.mk,v 1.1 2021/06/16 09:39:48 rillig Exp $
|
||||
#
|
||||
# In jobs mode, the shell commands for creating a target are written to a
|
||||
# temporary file first, which is then run by the shell. In chains of
|
||||
# dependencies, these files would end up empty. Since job.c 1.399 from
|
||||
# 2021-01-29, these empty files are no longer created.
|
||||
#
|
||||
# After 2021-01-29, before job.c 1.435 2021-06-16, targets that could not be
|
||||
# made led to longer error messages than necessary.
|
||||
|
||||
.MAKEFLAGS: -j1
|
||||
|
||||
all: existing-target
|
||||
|
||||
existing-target:
|
||||
: 'Making $@ out of nothing.'
|
||||
|
||||
all: nonexistent-target
|
||||
: 'Not reached'
|
@ -1,143 +1,136 @@
|
||||
mod-unknown-direct:
|
||||
want: Unknown modifier 'Z'
|
||||
make: Unknown modifier 'Z'
|
||||
make: Unknown modifier "Z"
|
||||
VAR:Z=before--after
|
||||
|
||||
mod-unknown-indirect:
|
||||
want: Unknown modifier 'Z'
|
||||
make: Unknown modifier 'Z'
|
||||
make: Unknown modifier "Z"
|
||||
VAR:Z=before-inner}-after
|
||||
|
||||
unclosed-direct:
|
||||
want: Unclosed variable specification (expecting '}') for "VAR" (value "Thevariable") modifier S
|
||||
make: Unclosed variable specification (expecting '}') for "VAR" (value "Thevariable") modifier S
|
||||
want: Unclosed variable expression, expecting '}' for modifier "S,V,v," of variable "VAR" with value "Thevariable"
|
||||
make: Unclosed variable expression, expecting '}' for modifier "S,V,v," of variable "VAR" with value "Thevariable"
|
||||
VAR:S,V,v,=Thevariable
|
||||
|
||||
unclosed-indirect:
|
||||
want: Unclosed variable specification after complex modifier (expecting '}') for VAR
|
||||
make: Unclosed variable specification after complex modifier (expecting '}') for VAR
|
||||
want: Unclosed variable expression after indirect modifier, expecting '}' for variable "VAR"
|
||||
make: Unclosed variable expression after indirect modifier, expecting '}' for variable "VAR"
|
||||
VAR:S,V,v,=Thevariable
|
||||
|
||||
unfinished-indirect:
|
||||
want: Unfinished modifier for VAR (',' missing)
|
||||
make: Unfinished modifier for VAR (',' missing)
|
||||
make: Unfinished modifier for "VAR" (',' missing)
|
||||
VAR:S,V,v=
|
||||
|
||||
unfinished-loop:
|
||||
want: Unfinished modifier for UNDEF ('@' missing)
|
||||
make: Unfinished modifier for UNDEF ('@' missing)
|
||||
make: Unfinished modifier for "UNDEF" ('@' missing)
|
||||
|
||||
want: Unfinished modifier for UNDEF ('@' missing)
|
||||
make: Unfinished modifier for UNDEF ('@' missing)
|
||||
make: Unfinished modifier for "UNDEF" ('@' missing)
|
||||
|
||||
1 2 3
|
||||
|
||||
loop-close:
|
||||
make: Unclosed variable specification (expecting '}') for "UNDEF" (value "1}... 2}... 3}...") modifier @
|
||||
make: Unclosed variable expression, expecting '}' for modifier "@var@${var}}...@" of variable "UNDEF" with value "1}... 2}... 3}..."
|
||||
1}... 2}... 3}...
|
||||
1}... 2}... 3}...
|
||||
|
||||
words:
|
||||
want: Unfinished modifier for UNDEF (']' missing)
|
||||
make: Unfinished modifier for UNDEF (']' missing)
|
||||
make: Unfinished modifier for "UNDEF" (']' missing)
|
||||
|
||||
want: Unfinished modifier for UNDEF (']' missing)
|
||||
make: Unfinished modifier for UNDEF (']' missing)
|
||||
make: Unfinished modifier for "UNDEF" (']' missing)
|
||||
|
||||
13=
|
||||
make: Bad modifier `:[123451234512345123451234512345]' for UNDEF
|
||||
make: Bad modifier ":[123451234512345123451234512345]" for variable "UNDEF"
|
||||
12345=S,^ok,:S,^3ok,}
|
||||
|
||||
exclam:
|
||||
want: Unfinished modifier for VARNAME ('!' missing)
|
||||
make: Unfinished modifier for VARNAME ('!' missing)
|
||||
make: Unfinished modifier for "VARNAME" ('!' missing)
|
||||
|
||||
want: Unfinished modifier for ! ('!' missing)
|
||||
make: Unfinished modifier for ! ('!' missing)
|
||||
make: Unfinished modifier for "!" ('!' missing)
|
||||
|
||||
|
||||
mod-subst-delimiter:
|
||||
make: Missing delimiter for :S modifier
|
||||
make: Missing delimiter for modifier ':S'
|
||||
1:
|
||||
make: Unfinished modifier for VAR (',' missing)
|
||||
make: Unfinished modifier for "VAR" (',' missing)
|
||||
2:
|
||||
make: Unfinished modifier for VAR (',' missing)
|
||||
make: Unfinished modifier for "VAR" (',' missing)
|
||||
3:
|
||||
make: Unfinished modifier for VAR (',' missing)
|
||||
make: Unfinished modifier for "VAR" (',' missing)
|
||||
4:
|
||||
make: Unfinished modifier for VAR (',' missing)
|
||||
make: Unfinished modifier for "VAR" (',' missing)
|
||||
5:
|
||||
make: Unclosed variable specification (expecting '}') for "VAR" (value "TheVariable") modifier S
|
||||
make: Unclosed variable expression, expecting '}' for modifier "S,from,to," of variable "VAR" with value "TheVariable"
|
||||
6: TheVariable
|
||||
7: TheVariable
|
||||
|
||||
mod-regex-delimiter:
|
||||
make: Missing delimiter for :C modifier
|
||||
1:
|
||||
make: Unfinished modifier for VAR (',' missing)
|
||||
make: Unfinished modifier for "VAR" (',' missing)
|
||||
2:
|
||||
make: Unfinished modifier for VAR (',' missing)
|
||||
make: Unfinished modifier for "VAR" (',' missing)
|
||||
3:
|
||||
make: Unfinished modifier for VAR (',' missing)
|
||||
make: Unfinished modifier for "VAR" (',' missing)
|
||||
4:
|
||||
make: Unfinished modifier for VAR (',' missing)
|
||||
make: Unfinished modifier for "VAR" (',' missing)
|
||||
5:
|
||||
make: Unclosed variable specification (expecting '}') for "VAR" (value "TheVariable") modifier C
|
||||
make: Unclosed variable expression, expecting '}' for modifier "C,from,to," of variable "VAR" with value "TheVariable"
|
||||
6: TheVariable
|
||||
7: TheVariable
|
||||
|
||||
mod-regex-undefined-subexpression:
|
||||
one one 2 3 5 8 one3 2one 34
|
||||
make: No match for subexpression \2
|
||||
make: No match for subexpression \2
|
||||
make: No match for subexpression \1
|
||||
make: No match for subexpression \2
|
||||
make: No match for subexpression \1
|
||||
()+() ()+() ()+() 3 5 8 (3)+() ()+(1) 34
|
||||
|
||||
mod-ts-parse:
|
||||
112358132134
|
||||
15152535558513521534
|
||||
make: Bad modifier `:ts\65oct' for FIB
|
||||
make: Bad modifier ":ts\65oct" for variable "FIB"
|
||||
65oct}
|
||||
make: Bad modifier `:tsxy' for FIB
|
||||
make: Bad modifier ":ts\65oct" for variable ""
|
||||
65oct}
|
||||
make: Bad modifier ":tsxy" for variable "FIB"
|
||||
xy}
|
||||
|
||||
mod-t-parse:
|
||||
make: Bad modifier `:t' for FIB
|
||||
make: Bad modifier ":t" for variable "FIB"
|
||||
|
||||
make: Bad modifier `:txy' for FIB
|
||||
make: Bad modifier ":txy" for variable "FIB"
|
||||
y}
|
||||
make: Bad modifier `:t' for FIB
|
||||
make: Bad modifier ":t" for variable "FIB"
|
||||
|
||||
make: Bad modifier `:t' for FIB
|
||||
make: Bad modifier ":t" for variable "FIB"
|
||||
M*}
|
||||
|
||||
mod-ifelse-parse:
|
||||
make: Unfinished modifier for FIB (':' missing)
|
||||
make: Unfinished modifier for "FIB" (':' missing)
|
||||
|
||||
make: Unfinished modifier for FIB (':' missing)
|
||||
make: Unfinished modifier for "FIB" (':' missing)
|
||||
|
||||
make: Unfinished modifier for FIB ('}' missing)
|
||||
make: Unfinished modifier for "FIB" ('}' missing)
|
||||
|
||||
make: Unfinished modifier for FIB ('}' missing)
|
||||
make: Unfinished modifier for "FIB" ('}' missing)
|
||||
|
||||
then
|
||||
|
||||
mod-remember-parse:
|
||||
1 1 2 3 5 8 13 21 34
|
||||
make: Unknown modifier '_'
|
||||
make: Unknown modifier "__"
|
||||
|
||||
|
||||
mod-sysv-parse:
|
||||
make: Unknown modifier '3'
|
||||
make: Unclosed variable specification (expecting '}') for "FIB" (value "") modifier 3
|
||||
make: Unknown modifier "3"
|
||||
make: Unclosed variable expression, expecting '}' for modifier "3" of variable "FIB" with value ""
|
||||
|
||||
make: Unknown modifier '3'
|
||||
make: Unclosed variable specification (expecting '}') for "FIB" (value "") modifier 3
|
||||
make: Unknown modifier "3="
|
||||
make: Unclosed variable expression, expecting '}' for modifier "3=" of variable "FIB" with value ""
|
||||
|
||||
make: Unknown modifier '3'
|
||||
make: Unclosed variable specification (expecting '}') for "FIB" (value "") modifier 3
|
||||
make: Unknown modifier "3=x3"
|
||||
make: Unclosed variable expression, expecting '}' for modifier "3=x3" of variable "FIB" with value ""
|
||||
|
||||
1 1 2 x3 5 8 1x3 21 34
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: moderrs.mk,v 1.25 2020/11/15 20:20:58 rillig Exp $
|
||||
# $NetBSD: moderrs.mk,v 1.30 2021/06/21 08:28:37 rillig Exp $
|
||||
#
|
||||
# various modifier error tests
|
||||
|
||||
@ -19,7 +19,6 @@ all: words
|
||||
all: exclam
|
||||
all: mod-subst-delimiter
|
||||
all: mod-regex-delimiter
|
||||
all: mod-regex-undefined-subexpression
|
||||
all: mod-ts-parse
|
||||
all: mod-t-parse
|
||||
all: mod-ifelse-parse
|
||||
@ -35,11 +34,11 @@ mod-unknown-indirect: print-header print-footer
|
||||
@echo 'VAR:${MOD_UNKN}=before-${VAR:${MOD_UNKN}:inner}-after'
|
||||
|
||||
unclosed-direct: print-header print-footer
|
||||
@echo 'want: Unclosed variable specification (expecting $'}$') for "VAR" (value "Thevariable") modifier S'
|
||||
@echo 'want: Unclosed variable expression, expecting $'}$' for modifier "S,V,v," of variable "VAR" with value "Thevariable"'
|
||||
@echo VAR:S,V,v,=${VAR:S,V,v,
|
||||
|
||||
unclosed-indirect: print-header print-footer
|
||||
@echo 'want: Unclosed variable specification after complex modifier (expecting $'}$') for VAR'
|
||||
@echo 'want: Unclosed variable expression after indirect modifier, expecting $'}$' for variable "VAR"'
|
||||
@echo VAR:${MOD_TERM},=${VAR:${MOD_S}
|
||||
|
||||
unfinished-indirect: print-header print-footer
|
||||
@ -119,27 +118,11 @@ mod-regex-delimiter: print-header print-footer
|
||||
@echo 6: ${VAR:C,from,to,
|
||||
@echo 7: ${VAR:C,from,to,}
|
||||
|
||||
# In regular expressions with alternatives, not all capturing groups are
|
||||
# always set; some may be missing. Warn about these.
|
||||
#
|
||||
# Since there is no way to turn off this warning, the combination of
|
||||
# alternative matches and capturing groups is seldom used, if at all.
|
||||
#
|
||||
# A newly added modifier 'U' such as in :C,(a.)|(b.),\1\2,U might be added
|
||||
# for treating undefined capturing groups as empty, but that would create a
|
||||
# syntactical ambiguity since the :S and :C modifiers are open-ended (see
|
||||
# mod-subst-chain). Luckily the modifier :U does not make sense after :C,
|
||||
# therefore this case does not happen in practice.
|
||||
# The sub-modifier for the :S and :C modifiers would have to be chosen
|
||||
# wisely, to not create ambiguities while parsing.
|
||||
mod-regex-undefined-subexpression: print-header print-footer
|
||||
@echo ${FIB:C,1(.*),one\1,} # all ok
|
||||
@echo ${FIB:C,1(.*)|2(.*),(\1)+(\2),:Q} # no match for subexpression
|
||||
|
||||
mod-ts-parse: print-header print-footer
|
||||
@echo ${FIB:ts}
|
||||
@echo ${FIB:ts\65} # octal 065 == U+0035 == '5'
|
||||
@echo ${FIB:ts\65oct} # bad modifier
|
||||
@echo ${:U${FIB}:ts\65oct} # bad modifier, variable name is ""
|
||||
@echo ${FIB:tsxy} # modifier too long
|
||||
|
||||
mod-t-parse: print-header print-footer
|
||||
|
@ -1,6 +1,6 @@
|
||||
make: Bad modifier `:tx' for LIST
|
||||
make: Bad modifier ":tx" for variable "LIST"
|
||||
LIST:tx="}"
|
||||
make: Bad modifier `:ts\X' for LIST
|
||||
make: Bad modifier ":ts\X" for variable "LIST"
|
||||
LIST:ts/x:tu="\X:tu}"
|
||||
FU_mod-ts="a/b/cool"
|
||||
FU_mod-ts:ts:T="cool" == cool?
|
||||
|
@ -1,4 +1,4 @@
|
||||
make: Bad modifier `:[]' for LIST
|
||||
make: Bad modifier ":[]" for variable "LIST"
|
||||
LIST:[]="" is an error
|
||||
LIST:[0]="one two three four five six"
|
||||
LIST:[0x0]="one two three four five six"
|
||||
@ -37,17 +37,17 @@ REALLYSPACE=" "
|
||||
REALLYSPACE:[1]="" == "" ?
|
||||
REALLYSPACE:[*]:[1]=" " == " " ?
|
||||
LIST:[1]="one"
|
||||
make: Bad modifier `:[1.]' for LIST
|
||||
make: Bad modifier ":[1.]" for variable "LIST"
|
||||
LIST:[1.]="" is an error
|
||||
make: Bad modifier `:[1].' for LIST
|
||||
make: Bad modifier ":[1]." for variable "LIST"
|
||||
LIST:[1].="}" is an error
|
||||
LIST:[2]="two"
|
||||
LIST:[6]="six"
|
||||
LIST:[7]=""
|
||||
LIST:[999]=""
|
||||
make: Bad modifier `:[-]' for LIST
|
||||
make: Bad modifier ":[-]" for variable "LIST"
|
||||
LIST:[-]="" is an error
|
||||
make: Bad modifier `:[--]' for LIST
|
||||
make: Bad modifier ":[--]" for variable "LIST"
|
||||
LIST:[--]="" is an error
|
||||
LIST:[-1]="six"
|
||||
LIST:[-2]="five"
|
||||
@ -67,20 +67,22 @@ LIST:[*]:C/ /,/:[2]=""
|
||||
LIST:[*]:C/ /,/:[*]:[2]=""
|
||||
LIST:[*]:C/ /,/:[@]:[2]="three"
|
||||
LONGLIST:[012..0x12]="10 11 12 13 14 15 16 17 18"
|
||||
make: Bad modifier `:[1.]' for LIST
|
||||
make: Bad modifier ":[1.]" for variable "LIST"
|
||||
LIST:[1.]="" is an error
|
||||
make: Bad modifier `:[1..]' for LIST
|
||||
make: Bad modifier ":[1..]" for variable "LIST"
|
||||
LIST:[1..]="" is an error
|
||||
make: Bad modifier ":[1.. ]" for variable "LIST"
|
||||
LIST:[1.. ]="" is an error
|
||||
LIST:[1..1]="one"
|
||||
make: Bad modifier `:[1..1.]' for LIST
|
||||
make: Bad modifier ":[1..1.]" for variable "LIST"
|
||||
LIST:[1..1.]="" is an error
|
||||
LIST:[1..2]="one two"
|
||||
LIST:[2..1]="two one"
|
||||
LIST:[3..-2]="three four five"
|
||||
LIST:[-4..4]="three four"
|
||||
make: Bad modifier `:[0..1]' for LIST
|
||||
make: Bad modifier ":[0..1]" for variable "LIST"
|
||||
LIST:[0..1]="" is an error
|
||||
make: Bad modifier `:[-1..0]' for LIST
|
||||
make: Bad modifier ":[-1..0]" for variable "LIST"
|
||||
LIST:[-1..0]="" is an error
|
||||
LIST:[-1..1]="six five four three two one"
|
||||
LIST:[0..0]="one two three four five six"
|
||||
@ -95,7 +97,7 @@ LIST:[${ONE}]="one"
|
||||
LIST:[${MINUSONE}]="six"
|
||||
LIST:[${STAR}]="one two three four five six"
|
||||
LIST:[${AT}]="one two three four five six"
|
||||
make: Bad modifier `:[${EMPTY' for LIST
|
||||
make: Bad modifier ":[${EMPTY" for variable "LIST"
|
||||
LIST:[${EMPTY}]="" is an error
|
||||
LIST:[${LONGLIST:[21]:S/2//}]="one"
|
||||
LIST:[${LIST:[#]}]="six"
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: modword.mk,v 1.5 2020/11/15 20:20:58 rillig Exp $
|
||||
# $NetBSD: modword.mk,v 1.6 2021/03/14 16:00:07 rillig Exp $
|
||||
#
|
||||
# Test behaviour of new :[] modifier
|
||||
# TODO: When was this modifier new?
|
||||
@ -99,6 +99,7 @@ mod-squarebrackets-n:
|
||||
mod-squarebrackets-start-end:
|
||||
@echo 'LIST:[1.]="${LIST:[1.]}" is an error'
|
||||
@echo 'LIST:[1..]="${LIST:[1..]}" is an error'
|
||||
@echo 'LIST:[1.. ]="${LIST:[1.. ]}" is an error'
|
||||
@echo 'LIST:[1..1]="${LIST:[1..1]}"'
|
||||
@echo 'LIST:[1..1.]="${LIST:[1..1.]}" is an error'
|
||||
@echo 'LIST:[1..2]="${LIST:[1..2]}"'
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: opt-chdir.mk,v 1.5 2020/11/15 05:43:56 sjg Exp $
|
||||
# $NetBSD: opt-chdir.mk,v 1.6 2021/05/18 17:05:45 sjg Exp $
|
||||
#
|
||||
# Tests for the -C command line option, which changes the directory at the
|
||||
# beginning.
|
||||
@ -23,5 +23,7 @@ chdir-root: .PHONY .IGNORE
|
||||
@MAKE_OBJDIR_CHECK_WRITABLE=no ${MAKE} -C / -V 'cwd: $${.CURDIR}'
|
||||
|
||||
# Trying to change to a nonexistent directory exits immediately.
|
||||
# Note: just because the whole point of /nonexistent is that it should
|
||||
# not exist - doesn't mean it doesn't.
|
||||
chdir-nonexistent: .PHONY .IGNORE
|
||||
@${MAKE} -C /nonexistent
|
||||
@${MAKE} -C /nonexistent.${.MAKE.PID}
|
||||
|
48
unit-tests/opt-debug-errors-jobs.exp
Normal file
48
unit-tests/opt-debug-errors-jobs.exp
Normal file
@ -0,0 +1,48 @@
|
||||
echo '3 spaces'; false
|
||||
3 spaces
|
||||
|
||||
*** Failed target: fail-spaces
|
||||
*** Failed commands:
|
||||
echo '3 spaces'; false
|
||||
*** [fail-spaces] Error code 1
|
||||
|
||||
make: stopped in unit-tests
|
||||
echo \ indented; false
|
||||
indented
|
||||
|
||||
*** Failed target: fail-escaped-space
|
||||
*** Failed commands:
|
||||
echo \ indented; false
|
||||
*** [fail-escaped-space] Error code 1
|
||||
|
||||
make: stopped in unit-tests
|
||||
echo 'line1
|
||||
line2'; false
|
||||
line1
|
||||
line2
|
||||
|
||||
*** Failed target: fail-newline
|
||||
*** Failed commands:
|
||||
echo 'line1${.newline}line2'; false
|
||||
*** [fail-newline] Error code 1
|
||||
|
||||
make: stopped in unit-tests
|
||||
echo 'line1 line2'; false
|
||||
line1 line2
|
||||
|
||||
*** Failed target: fail-multiline
|
||||
*** Failed commands:
|
||||
echo 'line1 line2'; false
|
||||
*** [fail-multiline] Error code 1
|
||||
|
||||
make: stopped in unit-tests
|
||||
echo 'word1' 'word2'; false
|
||||
word1 word2
|
||||
|
||||
*** Failed target: fail-multiline-intention
|
||||
*** Failed commands:
|
||||
echo 'word1' 'word2'; false
|
||||
*** [fail-multiline-intention] Error code 1
|
||||
|
||||
make: stopped in unit-tests
|
||||
exit status 1
|
36
unit-tests/opt-debug-errors-jobs.mk
Normal file
36
unit-tests/opt-debug-errors-jobs.mk
Normal file
@ -0,0 +1,36 @@
|
||||
# $NetBSD: opt-debug-errors-jobs.mk,v 1.1 2021/04/27 16:20:06 rillig Exp $
|
||||
#
|
||||
# Tests for the -de command line option, which adds debug logging for
|
||||
# failed commands and targets; since 2021-04-27 also in jobs mode.
|
||||
|
||||
.MAKEFLAGS: -de -j1
|
||||
|
||||
all: fail-spaces
|
||||
all: fail-escaped-space
|
||||
all: fail-newline
|
||||
all: fail-multiline
|
||||
all: fail-multiline-intention
|
||||
|
||||
fail-spaces:
|
||||
echo '3 spaces'; false
|
||||
|
||||
fail-escaped-space:
|
||||
echo \ indented; false
|
||||
|
||||
fail-newline:
|
||||
echo 'line1${.newline}line2'; false
|
||||
|
||||
# The line continuations in multiline commands are turned into an ordinary
|
||||
# space before the command is actually run.
|
||||
fail-multiline:
|
||||
echo 'line1\
|
||||
line2'; false
|
||||
|
||||
# It is a common style to align the continuation backslashes at the right
|
||||
# of the lines, usually at column 73. All spaces before the continuation
|
||||
# backslash are preserved and are usually outside a shell word and thus
|
||||
# irrelevant. Since "usually" is not "always", these space characters are
|
||||
# not merged into a single space.
|
||||
fail-multiline-intention:
|
||||
echo 'word1' \
|
||||
'word2'; false
|
@ -2,7 +2,7 @@ make: "opt-debug-lint.mk" line 19: Variable "X" is undefined
|
||||
make: "opt-debug-lint.mk" line 41: Variable "UNDEF" is undefined
|
||||
make: "opt-debug-lint.mk" line 61: Missing delimiter ':' after modifier "L"
|
||||
make: "opt-debug-lint.mk" line 61: Missing delimiter ':' after modifier "P"
|
||||
make: "opt-debug-lint.mk" line 69: Unknown modifier '$'
|
||||
make: "opt-debug-lint.mk" line 69: Unknown modifier "${"
|
||||
make: Fatal errors encountered -- cannot continue
|
||||
make: stopped in unit-tests
|
||||
exit status 1
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: opt-debug-lint.mk,v 1.12 2020/12/20 19:10:53 rillig Exp $
|
||||
# $NetBSD: opt-debug-lint.mk,v 1.14 2021/03/14 10:57:12 rillig Exp $
|
||||
#
|
||||
# Tests for the -dL command line option, which runs additional checks
|
||||
# to catch common mistakes, such as unclosed variable expressions.
|
||||
@ -77,5 +77,19 @@ ${UNDEF}: ${UNDEF}
|
||||
. error
|
||||
.endif
|
||||
|
||||
all:
|
||||
@:;
|
||||
# In lint mode, the whole variable text is evaluated to check for unclosed
|
||||
# expressions and unknown operators. During this check, the subexpression
|
||||
# '${:U2}' is not expanded, instead it is copied verbatim into the regular
|
||||
# expression, leading to '.*=.{1,${:U2}}$'.
|
||||
#
|
||||
# Before var.c 1.856 from 2021-03-14, this regular expression was then
|
||||
# compiled even though that was not necessary for checking the syntax at the
|
||||
# level of variable expressions. The unexpanded '$' then resulted in a wrong
|
||||
# error message.
|
||||
#
|
||||
# This only happened in lint mode since in default mode the early check for
|
||||
# unclosed expressions and unknown modifiers is skipped.
|
||||
#
|
||||
# See VarCheckSyntax, ApplyModifier_Regex.
|
||||
#
|
||||
VARMOD_REGEX= ${:UA=111 B=222 C=33:C/.*=.{1,${:U2}}$//g}
|
||||
|
@ -1,4 +1,4 @@
|
||||
Global:VAR = value
|
||||
Global:.MAKEFLAGS = -r -k -d v -d
|
||||
Global:.MAKEFLAGS = -r -k -d v -d 0
|
||||
Global: VAR = value
|
||||
Global: .MAKEFLAGS = -r -k -d v -d
|
||||
Global: .MAKEFLAGS = -r -k -d v -d 0
|
||||
exit status 0
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: opt-file.mk,v 1.11 2020/12/22 08:57:23 rillig Exp $
|
||||
# $NetBSD: opt-file.mk,v 1.12 2021/04/04 10:13:09 rillig Exp $
|
||||
#
|
||||
# Tests for the -f command line option.
|
||||
|
||||
@ -28,10 +28,10 @@ all: file-containing-null-byte
|
||||
# ParseReadLine (1): 'VAR=value\<A5><A5><A5><A5><A5><A5>'
|
||||
# Global:VAR = value\<A5><A5><A5><A5><A5><A5>value\<A5><A5><A5><A5><A5><A5>
|
||||
# ParseReadLine (2): 'alue\<A5><A5><A5><A5><A5><A5>'
|
||||
# ParseDoDependency(alue\<A5><A5><A5><A5><A5><A5>)
|
||||
# ParseDependency(alue\<A5><A5><A5><A5><A5><A5>)
|
||||
# make-2014.01.01.00.00.00: "(stdin)" line 2: Need an operator
|
||||
# ParseReadLine (3): '<A5><A5><A5>ZZZZZZZZZZZZZZZZ'
|
||||
# ParseDoDependency(<A5><A5><A5>ZZZZZZZZZZZZZZZZ)
|
||||
# ParseDependency(<A5><A5><A5>ZZZZZZZZZZZZZZZZ)
|
||||
#
|
||||
file-ending-in-backslash: .PHONY
|
||||
@printf '%s' 'VAR=value\' \
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: opt-jobs-no-action.mk,v 1.8 2020/12/10 23:54:41 rillig Exp $
|
||||
# $NetBSD: opt-jobs-no-action.mk,v 1.9 2021/04/04 09:58:51 rillig Exp $
|
||||
#
|
||||
# Tests for the combination of the options -j and -n, which prints the
|
||||
# commands instead of actually running them.
|
||||
@ -23,7 +23,7 @@
|
||||
# this is handled by the [0] != '\0' checks in Job_ParseShell.
|
||||
# The '\#' is handled by ParseGetLine.
|
||||
# The '\n' is handled by Str_Words in Job_ParseShell.
|
||||
# The '$$' is handled by Var_Subst in ParseDependency.
|
||||
# The '$$' is handled by Var_Subst in ParseDependencyLine.
|
||||
.SHELL: \
|
||||
name=sh \
|
||||
path=${.SHELL} \
|
||||
|
@ -1,12 +1,12 @@
|
||||
# $NetBSD: recursive.mk,v 1.4 2020/11/09 20:50:56 rillig Exp $
|
||||
# $NetBSD: recursive.mk,v 1.5 2021/03/15 12:15:03 rillig Exp $
|
||||
#
|
||||
# In -dL mode, a variable may get expanded before it makes sense.
|
||||
# This would stop make from doing anything since the "recursive" error
|
||||
# is fatal and exits immediately.
|
||||
#
|
||||
# The purpose of evaluating that variable early was just to detect
|
||||
# whether there are unclosed variables. It might be enough to parse the
|
||||
# variable value without VARE_WANTRES for that purpose.
|
||||
# whether there are unclosed variables. The variable value is therefore
|
||||
# parsed with VARE_PARSE_ONLY for that purpose.
|
||||
#
|
||||
# Seen in pkgsrc/x11/libXfixes, and probably many more package that use
|
||||
# GNU Automake.
|
||||
@ -36,4 +36,3 @@ MISSING_BRACE_INDIRECT:= ${:U\${MISSING_BRACE}
|
||||
UNCLOSED= $(MISSING_PAREN
|
||||
UNCLOSED= ${MISSING_BRACE
|
||||
UNCLOSED= ${MISSING_BRACE_INDIRECT}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: sh-jobs.mk,v 1.3 2020/12/11 01:06:10 rillig Exp $
|
||||
# $NetBSD: sh-jobs.mk,v 1.4 2021/04/16 16:49:27 rillig Exp $
|
||||
#
|
||||
# Tests for the "run in jobs mode" part of the "Shell Commands" section
|
||||
# from the manual page.
|
||||
@ -14,14 +14,14 @@ all: .PHONY comment .WAIT comment-with-followup-line .WAIT no-comment
|
||||
# would lead to a syntax error in the generated shell file, at least for
|
||||
# bash and dash, but not for NetBSD sh and ksh.
|
||||
#
|
||||
# See JobPrintCommand, cmdTemplate, runIgnTmpl
|
||||
# See JobWriteCommand, cmdTemplate, runIgnTmpl
|
||||
comment: .PHONY
|
||||
@# comment
|
||||
|
||||
# If a shell command starts with a comment character after stripping the
|
||||
# leading '@', it is run in ignore-errors mode.
|
||||
#
|
||||
# See JobPrintCommand, cmdTemplate, runIgnTmpl
|
||||
# See JobWriteCommand, cmdTemplate, runIgnTmpl
|
||||
comment-with-followup-line: .PHONY
|
||||
@# comment${.newline}echo '$@: This is printed.'; false
|
||||
@true
|
||||
@ -29,7 +29,7 @@ comment-with-followup-line: .PHONY
|
||||
# Without the comment, the commands are run in the default mode, which checks
|
||||
# the exit status of every makefile line.
|
||||
#
|
||||
# See JobPrintCommand, cmdTemplate, runChkTmpl
|
||||
# See JobWriteCommand, cmdTemplate, runChkTmpl
|
||||
no-comment: .PHONY
|
||||
@echo '$@: This is printed.'; false
|
||||
@true
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: shell-csh.mk,v 1.7 2020/12/13 02:09:55 sjg Exp $
|
||||
# $NetBSD: shell-csh.mk,v 1.8 2021/04/04 09:58:51 rillig Exp $
|
||||
#
|
||||
# Tests for using a C shell for running the commands.
|
||||
|
||||
@ -12,7 +12,7 @@ CSH!= which csh 2> /dev/null || true
|
||||
.endif
|
||||
|
||||
# In parallel mode, the shell->noPrint command is filtered from
|
||||
# the output, rather naively (in JobOutput).
|
||||
# the output, rather naively (in PrintOutput).
|
||||
#
|
||||
# Until 2020-10-03, the output in parallel mode was garbled because
|
||||
# the definition of the csh had been wrong since 1993 at least.
|
||||
|
@ -1,19 +1,19 @@
|
||||
ParseReadLine (9): '.SUFFIXES:'
|
||||
ParseDoDependency(.SUFFIXES:)
|
||||
ParseDependency(.SUFFIXES:)
|
||||
Clearing all suffixes
|
||||
ParseReadLine (11): '.SUFFIXES: .a .b .c'
|
||||
ParseDoDependency(.SUFFIXES: .a .b .c)
|
||||
ParseDependency(.SUFFIXES: .a .b .c)
|
||||
Adding suffix ".a"
|
||||
Adding suffix ".b"
|
||||
Adding suffix ".c"
|
||||
ParseReadLine (17): '.a.b:'
|
||||
ParseDoDependency(.a.b:)
|
||||
ParseDependency(.a.b:)
|
||||
defining transformation from `.a' to `.b'
|
||||
inserting ".a" (1) at end of list
|
||||
inserting ".b" (2) at end of list
|
||||
ParseReadLine (21): '.a.c: ${.PREFIX}.dependency'
|
||||
deleting incomplete transformation from `.a' to `.b'
|
||||
ParseDoDependency(.a.c: ${.PREFIX}.dependency)
|
||||
ParseDependency(.a.c: ${.PREFIX}.dependency)
|
||||
defining transformation from `.a' to `.c'
|
||||
inserting ".a" (1) at end of list
|
||||
inserting ".c" (3) at end of list
|
||||
@ -22,7 +22,7 @@ inserting ".c" (3) at end of list
|
||||
# ${.PREFIX}.dependency, unmade, type none, flags none
|
||||
ParseReadLine (23): '.DEFAULT:'
|
||||
transformation .a.c complete
|
||||
ParseDoDependency(.DEFAULT:)
|
||||
ParseDependency(.DEFAULT:)
|
||||
ParseReadLine (24): ' : Making ${.TARGET} from ${.IMPSRC} all ${.ALLSRC} by default.'
|
||||
transformation .DEFAULT complete
|
||||
Wildcard expanding "all"...
|
||||
|
@ -1,12 +1,12 @@
|
||||
ParseReadLine (8): '.1.2 .1.3 .1.4:'
|
||||
ParseDoDependency(.1.2 .1.3 .1.4:)
|
||||
ParseDependency(.1.2 .1.3 .1.4:)
|
||||
Setting main node to ".1.2"
|
||||
ParseReadLine (9): ' : Making ${.TARGET} from ${.IMPSRC}.'
|
||||
ParseReadLine (14): 'next-main:'
|
||||
ParseDoDependency(next-main:)
|
||||
ParseDependency(next-main:)
|
||||
ParseReadLine (15): ' : Making ${.TARGET}'
|
||||
ParseReadLine (19): '.SUFFIXES: .1 .2 .3 .4'
|
||||
ParseDoDependency(.SUFFIXES: .1 .2 .3 .4)
|
||||
ParseDependency(.SUFFIXES: .1 .2 .3 .4)
|
||||
Adding suffix ".1"
|
||||
Adding suffix ".2"
|
||||
Setting main node from ".1.2" back to null
|
||||
@ -27,42 +27,42 @@ inserting ".1" (1) at end of list
|
||||
inserting ".4" (4) at end of list
|
||||
Setting main node to "next-main"
|
||||
ParseReadLine (24): '.SUFFIXES:'
|
||||
ParseDoDependency(.SUFFIXES:)
|
||||
ParseDependency(.SUFFIXES:)
|
||||
Clearing all suffixes
|
||||
ParseReadLine (32): '.SUFFIXES: .4 .3 .2 .1'
|
||||
ParseDoDependency(.SUFFIXES: .4 .3 .2 .1)
|
||||
ParseDependency(.SUFFIXES: .4 .3 .2 .1)
|
||||
Adding suffix ".4"
|
||||
Adding suffix ".3"
|
||||
Adding suffix ".2"
|
||||
Adding suffix ".1"
|
||||
ParseReadLine (33): '.SUFFIXES:'
|
||||
ParseDoDependency(.SUFFIXES:)
|
||||
ParseDependency(.SUFFIXES:)
|
||||
Clearing all suffixes
|
||||
ParseReadLine (34): '.SUFFIXES: .1 .2 .3 .4'
|
||||
ParseDoDependency(.SUFFIXES: .1 .2 .3 .4)
|
||||
ParseDependency(.SUFFIXES: .1 .2 .3 .4)
|
||||
Adding suffix ".1"
|
||||
Adding suffix ".2"
|
||||
Adding suffix ".3"
|
||||
Adding suffix ".4"
|
||||
ParseReadLine (35): '.SUFFIXES:'
|
||||
ParseDoDependency(.SUFFIXES:)
|
||||
ParseDependency(.SUFFIXES:)
|
||||
Clearing all suffixes
|
||||
ParseReadLine (36): '.SUFFIXES: .4 .3 .2 .1'
|
||||
ParseDoDependency(.SUFFIXES: .4 .3 .2 .1)
|
||||
ParseDependency(.SUFFIXES: .4 .3 .2 .1)
|
||||
Adding suffix ".4"
|
||||
Adding suffix ".3"
|
||||
Adding suffix ".2"
|
||||
Adding suffix ".1"
|
||||
ParseReadLine (38): 'suff-main-several.1:'
|
||||
ParseDoDependency(suff-main-several.1:)
|
||||
ParseDependency(suff-main-several.1:)
|
||||
ParseReadLine (39): ' : Making ${.TARGET} out of nothing.'
|
||||
ParseReadLine (40): 'next-main: suff-main-several.{2,3,4}'
|
||||
ParseDoDependency(next-main: suff-main-several.{2,3,4})
|
||||
ParseDependency(next-main: suff-main-several.{2,3,4})
|
||||
# LinkSource: added child next-main - suff-main-several.{2,3,4}
|
||||
# next-main, unmade, type OP_DEPENDS|OP_HAS_COMMANDS, flags none
|
||||
# suff-main-several.{2,3,4}, unmade, type none, flags none
|
||||
ParseReadLine (42): '.MAKEFLAGS: -d0 -dg1'
|
||||
ParseDoDependency(.MAKEFLAGS: -d0 -dg1)
|
||||
ParseDependency(.MAKEFLAGS: -d0 -dg1)
|
||||
#*** Input graph:
|
||||
# .1.2, unmade, type OP_TRANSFORM, flags none
|
||||
# .1.3, unmade, type OP_TRANSFORM, flags none
|
||||
|
@ -1,38 +1,38 @@
|
||||
ParseReadLine (10): '.SUFFIXES:'
|
||||
ParseDoDependency(.SUFFIXES:)
|
||||
ParseDependency(.SUFFIXES:)
|
||||
Clearing all suffixes
|
||||
ParseReadLine (12): '.SUFFIXES: .a .b .c'
|
||||
ParseDoDependency(.SUFFIXES: .a .b .c)
|
||||
ParseDependency(.SUFFIXES: .a .b .c)
|
||||
Adding suffix ".a"
|
||||
Adding suffix ".b"
|
||||
Adding suffix ".c"
|
||||
ParseReadLine (14): 'suff-rebuild-example.a:'
|
||||
ParseDoDependency(suff-rebuild-example.a:)
|
||||
ParseDependency(suff-rebuild-example.a:)
|
||||
Adding "suff-rebuild-example.a" to all targets.
|
||||
ParseReadLine (15): ' : Making ${.TARGET} out of nothing.'
|
||||
ParseReadLine (17): '.a.b:'
|
||||
ParseDoDependency(.a.b:)
|
||||
ParseDependency(.a.b:)
|
||||
defining transformation from `.a' to `.b'
|
||||
inserting ".a" (1) at end of list
|
||||
inserting ".b" (2) at end of list
|
||||
ParseReadLine (18): ' : Making ${.TARGET} from ${.IMPSRC}.'
|
||||
ParseReadLine (19): '.b.c:'
|
||||
transformation .a.b complete
|
||||
ParseDoDependency(.b.c:)
|
||||
ParseDependency(.b.c:)
|
||||
defining transformation from `.b' to `.c'
|
||||
inserting ".b" (2) at end of list
|
||||
inserting ".c" (3) at end of list
|
||||
ParseReadLine (20): ' : Making ${.TARGET} from ${.IMPSRC}.'
|
||||
ParseReadLine (21): '.c:'
|
||||
transformation .b.c complete
|
||||
ParseDoDependency(.c:)
|
||||
ParseDependency(.c:)
|
||||
defining transformation from `.c' to `'
|
||||
inserting ".c" (3) at end of list
|
||||
inserting "" (0) at end of list
|
||||
ParseReadLine (22): ' : Making ${.TARGET} from ${.IMPSRC}.'
|
||||
ParseReadLine (44): '.SUFFIXES: .c .b .a'
|
||||
transformation .c complete
|
||||
ParseDoDependency(.SUFFIXES: .c .b .a)
|
||||
ParseDependency(.SUFFIXES: .c .b .a)
|
||||
Adding ".END" to all targets.
|
||||
Wildcard expanding "all"...
|
||||
SuffFindDeps "all"
|
||||
|
@ -1 +1,4 @@
|
||||
make: "var-class-cmdline.mk" line 67: global
|
||||
make: "var-class-cmdline.mk" line 76: makeflags
|
||||
makeflags
|
||||
exit status 0
|
||||
|
@ -1,8 +1,80 @@
|
||||
# $NetBSD: var-class-cmdline.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $
|
||||
# $NetBSD: var-class-cmdline.mk,v 1.5 2021/02/23 21:59:31 rillig Exp $
|
||||
#
|
||||
# Tests for variables specified on the command line.
|
||||
#
|
||||
# Variables that are specified on the command line override those from the
|
||||
# global scope.
|
||||
#
|
||||
# For performance reasons, the actual implementation is more complex than the
|
||||
# above single-sentence rule, in order to avoid unnecessary lookups in scopes,
|
||||
# which before var.c 1.586 from 2020-10-25 calculated the hash value of the
|
||||
# variable name once for each lookup. Instead, when looking up the value of
|
||||
# a variable, the search often starts in the global scope since that is where
|
||||
# most of the variables are stored. This conflicts with the statement that
|
||||
# variables from the cmdline scope override global variables, since after the
|
||||
# common case of finding a variable in the global scope, another lookup would
|
||||
# be needed in the cmdline scope to ensure that there is no overriding
|
||||
# variable there.
|
||||
#
|
||||
# Instead of this costly lookup scheme, make implements it in a different
|
||||
# way:
|
||||
#
|
||||
# Whenever a global variable is created, this creation is ignored if
|
||||
# there is a cmdline variable of the same name.
|
||||
#
|
||||
# Whenever a cmdline variable is created, any global variable of the
|
||||
# same name is deleted.
|
||||
#
|
||||
# Whenever a global variable is deleted, nothing special happens.
|
||||
#
|
||||
# Deleting a cmdline variable is not possible.
|
||||
#
|
||||
# These 4 rules provide the guarantee that whenever a global variable exists,
|
||||
# there cannot be a cmdline variable of the same name. Therefore, after
|
||||
# finding a variable in the global scope, no additional lookup is needed in
|
||||
# the cmdline scope.
|
||||
#
|
||||
# The above ruleset provides the same guarantees as the simple rule "cmdline
|
||||
# overrides global". Due to an implementation mistake, the actual behavior
|
||||
# was not entirely equivalent to the simple rule though. The mistake was
|
||||
# that when a cmdline variable with '$$' in its name was added, a global
|
||||
# variable was deleted, but not with the exact same name as the cmdline
|
||||
# variable. Instead, the name of the global variable was expanded one more
|
||||
# time than the name of the cmdline variable. For variable names that didn't
|
||||
# have a '$$' in their name, it was implemented correctly all the time.
|
||||
#
|
||||
# The bug was added in var.c 1.183 on 2013-07-16, when Var_Set called
|
||||
# Var_Delete to delete the global variable. Just two months earlier, in var.c
|
||||
# 1.174 from 2013-05-18, Var_Delete had started to expand the variable name.
|
||||
# Together, these two changes made the variable name be expanded twice in a
|
||||
# row. This bug was fixed in var.c 1.835 from 2021-02-22.
|
||||
#
|
||||
# Another bug was the wrong assumption that "deleting a cmdline variable is
|
||||
# not possible". Deleting such a variable has been possible since var.c 1.204
|
||||
# from 2016-02-19, when the variable modifier ':@' started to delete the
|
||||
# temporary loop variable after finishing the loop. It was probably not
|
||||
# intended back then that a side effect of this seemingly simple change was
|
||||
# that both global and cmdline variables could now be undefined at will as a
|
||||
# side effect of evaluating a variable expression. As of 2021-02-23, this is
|
||||
# still possible.
|
||||
#
|
||||
# Most cmdline variables are set at the very beginning, when parsing the
|
||||
# command line arguments. Using the special target '.MAKEFLAGS', it is
|
||||
# possible to set cmdline variables at any later time.
|
||||
|
||||
# TODO: Implementation
|
||||
# A normal global variable, without any cmdline variable nearby.
|
||||
VAR= global
|
||||
.info ${VAR}
|
||||
|
||||
all:
|
||||
@:;
|
||||
# The global variable is "overridden" by simply deleting it and then
|
||||
# installing the cmdline variable instead. Since there is no obvious way to
|
||||
# undefine a cmdline variable, there is no need to remember the old value
|
||||
# of the global variable could become visible again.
|
||||
#
|
||||
# See varmod-loop.mk for a non-obvious way to undefine a cmdline variable.
|
||||
.MAKEFLAGS: VAR=makeflags
|
||||
.info ${VAR}
|
||||
|
||||
# If Var_SetWithFlags should ever forget to delete the global variable,
|
||||
# the below line would print "global" instead of the current "makeflags".
|
||||
.MAKEFLAGS: -V VAR
|
||||
|
29
unit-tests/var-eval-short.exp
Normal file
29
unit-tests/var-eval-short.exp
Normal file
@ -0,0 +1,29 @@
|
||||
make: "var-eval-short.mk" line 41: In the :@ modifier of "", the variable name "${FAIL}" must not contain a dollar.
|
||||
make: "var-eval-short.mk" line 41: Malformed conditional (0 && ${:Uword:@${FAIL}@expr@})
|
||||
make: "var-eval-short.mk" line 79: Invalid time value: ${FAIL}}
|
||||
make: "var-eval-short.mk" line 79: Malformed conditional (0 && ${:Uword:gmtime=${FAIL}})
|
||||
make: "var-eval-short.mk" line 93: Invalid time value: ${FAIL}}
|
||||
make: "var-eval-short.mk" line 93: Malformed conditional (0 && ${:Uword:localtime=${FAIL}})
|
||||
CondParser_Eval: 0 && ${0:?${FAIL}then:${FAIL}else}
|
||||
Var_Parse: ${0:?${FAIL}then:${FAIL}else} (parse-only)
|
||||
Parsing modifier ${0:?...}
|
||||
Modifier part: "${FAIL}then"
|
||||
Modifier part: "${FAIL}else"
|
||||
Result of ${0:?${FAIL}then:${FAIL}else} is "" (parse-only, defined)
|
||||
ParseReadLine (158): 'DEFINED= defined'
|
||||
Global: DEFINED = defined
|
||||
CondParser_Eval: 0 && ${DEFINED:L:?${FAIL}then:${FAIL}else}
|
||||
Var_Parse: ${DEFINED:L:?${FAIL}then:${FAIL}else} (parse-only)
|
||||
Parsing modifier ${DEFINED:L}
|
||||
Result of ${DEFINED:L} is "defined" (parse-only, regular)
|
||||
Parsing modifier ${DEFINED:?...}
|
||||
Modifier part: "${FAIL}then"
|
||||
Modifier part: "${FAIL}else"
|
||||
Result of ${DEFINED:?${FAIL}then:${FAIL}else} is "defined" (parse-only, regular)
|
||||
ParseReadLine (161): '.MAKEFLAGS: -d0'
|
||||
ParseDependency(.MAKEFLAGS: -d0)
|
||||
Global: .MAKEFLAGS = -r -k -d cpv -d
|
||||
Global: .MAKEFLAGS = -r -k -d cpv -d 0
|
||||
make: Fatal errors encountered -- cannot continue
|
||||
make: stopped in unit-tests
|
||||
exit status 1
|
163
unit-tests/var-eval-short.mk
Normal file
163
unit-tests/var-eval-short.mk
Normal file
@ -0,0 +1,163 @@
|
||||
# $NetBSD: var-eval-short.mk,v 1.5 2021/04/04 13:35:26 rillig Exp $
|
||||
#
|
||||
# Tests for each variable modifier to ensure that they only do the minimum
|
||||
# necessary computations. If the result of the expression is not needed, they
|
||||
# should only parse the modifier but not actually evaluate it.
|
||||
#
|
||||
# See also:
|
||||
# var.c, the comment starting with 'The ApplyModifier functions'
|
||||
# ApplyModifier, for the order of the modifiers
|
||||
# ParseModifierPart, for evaluating nested expressions
|
||||
# cond-short.mk
|
||||
|
||||
FAIL= ${:!echo unexpected 1>&2!}
|
||||
|
||||
# The following tests only ensure that nested expressions are not evaluated.
|
||||
# They cannot ensure that any unexpanded text returned from ParseModifierPart
|
||||
# is ignored as well. To do that, it is necessary to step through the code of
|
||||
# each modifier.
|
||||
|
||||
.if 0 && ${FAIL}
|
||||
.endif
|
||||
|
||||
.if 0 && ${VAR::=${FAIL}}
|
||||
.elif defined(VAR)
|
||||
. error
|
||||
.endif
|
||||
|
||||
.if 0 && ${${FAIL}:?then:else}
|
||||
.endif
|
||||
|
||||
.if 0 && ${1:?${FAIL}:${FAIL}}
|
||||
.endif
|
||||
|
||||
.if 0 && ${0:?${FAIL}:${FAIL}}
|
||||
.endif
|
||||
|
||||
# Before var.c 1.870 from 2021-03-14, the expression ${FAIL} was evaluated
|
||||
# after the loop, when undefining the temporary global loop variable.
|
||||
# Since var.c 1.907 from 2021-04-04, a '$' is no longer allowed in the
|
||||
# variable name.
|
||||
.if 0 && ${:Uword:@${FAIL}@expr@}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:@var@${FAIL}@}
|
||||
.endif
|
||||
|
||||
# Before var.c,v 1.877 from 2021-03-14, the modifier ':[...]' did not expand
|
||||
# the nested expression ${FAIL} and then tried to parse the unexpanded text,
|
||||
# which failed since '$' is not a valid range character.
|
||||
.if 0 && ${:Uword:[${FAIL}]}
|
||||
.endif
|
||||
|
||||
# Before var.c,v 1.867 from 2021-03-14, the modifier ':_' defined the variable
|
||||
# even though the whole expression should have only been parsed, not
|
||||
# evaluated.
|
||||
.if 0 && ${:Uword:_=VAR}
|
||||
.elif defined(VAR)
|
||||
. error
|
||||
.endif
|
||||
|
||||
# Before var.c,v 1.856 from 2021-03-14, the modifier ':C' did not expand the
|
||||
# nested expression ${FAIL} and then tried to compile the unexpanded text as a
|
||||
# regular expression, which failed both because of the '{FAIL}', which is not
|
||||
# a valid repetition, and because of the '****', which are repeated
|
||||
# repetitions as well.
|
||||
# '${FAIL}'
|
||||
.if 0 && ${:Uword:C,${FAIL}****,,}
|
||||
.endif
|
||||
|
||||
DEFINED= # defined
|
||||
.if 0 && ${DEFINED:D${FAIL}}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:E}
|
||||
.endif
|
||||
|
||||
# As of 2021-03-14, the error 'Invalid time value: ${FAIL}}' is ok since
|
||||
# ':gmtime' does not expand its argument.
|
||||
.if 0 && ${:Uword:gmtime=${FAIL}}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:H}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:hash}
|
||||
.endif
|
||||
|
||||
.if 0 && ${value:L}
|
||||
.endif
|
||||
|
||||
# As of 2021-03-14, the error 'Invalid time value: ${FAIL}}' is ok since
|
||||
# ':localtime' does not expand its argument.
|
||||
.if 0 && ${:Uword:localtime=${FAIL}}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:M${FAIL}}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:N${FAIL}}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:O}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:Ox}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:P}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:Q}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:q}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:R}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:range}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:S,${FAIL},${FAIL},}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:sh}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:T}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:ts/}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:U${FAIL}}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:u}
|
||||
.endif
|
||||
|
||||
.if 0 && ${:Uword:word=replacement}
|
||||
.endif
|
||||
|
||||
# Before var.c 1.875 from 2021-03-14, Var_Parse returned "${FAIL}else" for the
|
||||
# irrelevant right-hand side of the condition, even though this was not
|
||||
# necessary. Since the return value from Var_Parse is supposed to be ignored
|
||||
# anyway, and since it is actually ignored in an overly complicated way,
|
||||
# an empty string suffices.
|
||||
.MAKEFLAGS: -dcpv
|
||||
.if 0 && ${0:?${FAIL}then:${FAIL}else}
|
||||
.endif
|
||||
|
||||
# The ':L' is applied before the ':?' modifier, giving the expression a name
|
||||
# and a value, just to see whether this value gets passed through or whether
|
||||
# the parse-only mode results in an empty string (only visible in the debug
|
||||
# log). As of var.c 1.875 from 2021-03-14, the value of the variable gets
|
||||
# through, even though an empty string would suffice.
|
||||
DEFINED= defined
|
||||
.if 0 && ${DEFINED:L:?${FAIL}then:${FAIL}else}
|
||||
.endif
|
||||
.MAKEFLAGS: -d0
|
||||
|
||||
all:
|
@ -1,7 +1,7 @@
|
||||
Var_Parse: ${:U\$\$\$\$\$\$\$\$} with VARE_WANTRES
|
||||
Applying ${:U...} to "" (VARE_WANTRES, none, VES_UNDEF)
|
||||
Result of ${:U\$\$\$\$\$\$\$\$} is "$$$$$$$$" (VARE_WANTRES, none, VES_DEF)
|
||||
Global:VAR.$$$$$$$$ = dollars
|
||||
Global:.MAKEFLAGS = -r -k -d v -d
|
||||
Global:.MAKEFLAGS = -r -k -d v -d 0
|
||||
Var_Parse: ${:U\$\$\$\$\$\$\$\$} (eval)
|
||||
Evaluating modifier ${:U...} on value "" (eval, undefined)
|
||||
Result of ${:U\$\$\$\$\$\$\$\$} is "$$$$$$$$" (eval, defined)
|
||||
Global: VAR.$$$$$$$$ = dollars
|
||||
Global: .MAKEFLAGS = -r -k -d v -d
|
||||
Global: .MAKEFLAGS = -r -k -d v -d 0
|
||||
exit status 0
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: var-op-append.mk,v 1.8 2021/02/03 08:40:47 rillig Exp $
|
||||
# $NetBSD: var-op-append.mk,v 1.9 2021/04/04 10:13:09 rillig Exp $
|
||||
#
|
||||
# Tests for the += variable assignment operator, which appends to a variable,
|
||||
# creating it if necessary.
|
||||
@ -26,7 +26,7 @@ VAR+= # empty
|
||||
# '+=' assignment operator. As far as possible, the '+' is interpreted as
|
||||
# part of the assignment operator.
|
||||
#
|
||||
# See Parse_DoVar
|
||||
# See Parse_Var
|
||||
C++= value
|
||||
.if ${C+} != "value" || defined(C++)
|
||||
. error
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: var-op-assign.mk,v 1.7 2020/11/15 20:20:58 rillig Exp $
|
||||
# $NetBSD: var-op-assign.mk,v 1.8 2021/03/15 19:15:04 rillig Exp $
|
||||
#
|
||||
# Tests for the = variable assignment operator, which overwrites an existing
|
||||
# variable or creates it.
|
||||
@ -42,7 +42,7 @@ VAR= new value and \# some $$ special characters # comment
|
||||
# This alone would not produce any side-effects, therefore the variable has
|
||||
# a :!...! modifier that executes a shell command. The :!...! modifier turns
|
||||
# an undefined expression into a defined one, see ApplyModifier_ShellCommand,
|
||||
# the call to ApplyModifiersState_Define.
|
||||
# the call to Expr_Define.
|
||||
#
|
||||
# Since the right-hand side of a '=' assignment is not expanded at the time
|
||||
# when the variable is defined, the first command is not run at all.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user